mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
feat(gameplay): add task ID to chunk requests to discard stale responses
This commit is contained in:
@@ -573,6 +573,7 @@ void DevPanel::show_client_world_table_bar() {
|
||||
if (ImGui::Button("Spawn Point")) {
|
||||
m_player->set_player_pos({0.0f, 255.0f, 0.0f});
|
||||
}
|
||||
ImGui::Text("Chunk Task Id %d", m_app.client_world().get_chunk_task_id());
|
||||
}
|
||||
|
||||
void DevPanel::show_player_tab_item() {
|
||||
|
||||
@@ -416,8 +416,10 @@ void ClientWorld::request_chunk() {
|
||||
}
|
||||
auto uuid = m_player.get_uuid();
|
||||
Arena arena;
|
||||
++m_chunk_task_id;
|
||||
auto* req = Arena::Create<ChunkDataReq>(&arena);
|
||||
for (const auto& pos : need_send_pos) {
|
||||
req->set_task_id(m_chunk_task_id.load());
|
||||
req->set_uuid(uuid);
|
||||
auto* p = req->mutable_pos();
|
||||
p->set_x(pos.x);
|
||||
@@ -429,6 +431,9 @@ void ClientWorld::request_chunk() {
|
||||
}
|
||||
|
||||
void ClientWorld::receive_chunk(ChunkDataRsp data) {
|
||||
if (data.task_id() < m_chunk_task_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard lock(m_chunks_mutex);
|
||||
@@ -573,6 +578,9 @@ void ClientWorld::rendering_distance(int rendering_distance) {
|
||||
m_rendering_distance.load());
|
||||
request_chunk();
|
||||
}
|
||||
|
||||
int ClientWorld::get_chunk_task_id() const { return m_chunk_task_id.load(); }
|
||||
|
||||
const std::vector<ChunkRenderSnapshot>& ClientWorld::render_snapshots() const {
|
||||
return m_render_snapshots;
|
||||
};
|
||||
|
||||
@@ -31,4 +31,7 @@ bool ServerPlayer::is_disconnect(TickType current_gametick) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
int ServerPlayer::task_id() const { return m_chunk_task_id.load(); }
|
||||
void ServerPlayer::task_id(int id) { m_chunk_task_id = id; }
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -524,10 +524,32 @@ glm::vec3 ServerWorld::get_player_pos(const std::string& uuid) const {
|
||||
return it->second.get_pos();
|
||||
}
|
||||
|
||||
void ServerWorld::handle_chunk_req(const std::string& uuid, ChunkPos pos) {
|
||||
|
||||
void ServerWorld::handle_chunk_req(int task_id, const std::string& uuid,
|
||||
ChunkPos pos) {
|
||||
{
|
||||
std::shared_lock lock(m_player_mutex);
|
||||
auto it = m_players.find(uuid);
|
||||
if (it == m_players.end()) {
|
||||
return;
|
||||
}
|
||||
if (it->second.task_id() < task_id) {
|
||||
// task_id is an atomic variable, can be operated on directly
|
||||
it->second.task_id(task_id);
|
||||
}
|
||||
}
|
||||
auto pool = m_gen_thread_pool.load();
|
||||
pool->enqueue([uuid, pos, this]() {
|
||||
pool->enqueue([task_id, uuid, pos, this]() {
|
||||
{
|
||||
std::shared_lock lock(m_player_mutex);
|
||||
auto it = m_players.find(uuid);
|
||||
if (it == m_players.end()) {
|
||||
return;
|
||||
}
|
||||
if (task_id < it->second.task_id()) {
|
||||
// Old chunk requests are simply discarded
|
||||
return;
|
||||
}
|
||||
}
|
||||
Arena arean;
|
||||
ChunkDataRsp* rsp = Arena::Create<ChunkDataRsp>(&arean);
|
||||
auto* rsq_pos = rsp->mutable_pos();
|
||||
@@ -578,7 +600,7 @@ void ServerWorld::handle_chunk_req(const std::string& uuid, ChunkPos pos) {
|
||||
Logger::error("Player {} session not exist", uuid);
|
||||
return;
|
||||
}
|
||||
|
||||
rsp->set_task_id(task_id);
|
||||
s->send(make_packet(*rsp));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -77,7 +77,8 @@ asio::awaitable<void> Session::read_loop() {
|
||||
// Logger::info("Session: Receive Chunk Data req");
|
||||
if (decode_packet(*req, body_data, header)) {
|
||||
m_server_world.handle_chunk_req(
|
||||
req->uuid(), ChunkPos(req->pos().x(), req->pos().z()));
|
||||
req->task_id(), req->uuid(),
|
||||
ChunkPos(req->pos().x(), req->pos().z()));
|
||||
}
|
||||
}
|
||||
if (cmd_id == to_num(PacketEnum::BLOCK_CHANGE_REQ)) {
|
||||
|
||||
@@ -3,19 +3,21 @@ syntax = "proto3";
|
||||
import "common/chunk_pos.proto";
|
||||
|
||||
message ChunkDataReq {
|
||||
string uuid = 1;
|
||||
ChunkPosNet pos = 2;
|
||||
int32 task_id = 1;
|
||||
string uuid = 2;
|
||||
ChunkPosNet pos = 3;
|
||||
}
|
||||
|
||||
message ChunkDataRsp {
|
||||
ChunkPosNet pos = 1;
|
||||
uint32 chunk_seed = 2;
|
||||
int32 biome_type = 3;
|
||||
repeated uint32 chunk_blocks = 4 [packed=true];
|
||||
repeated uint32 neighbor_blocks_1 = 5 [packed=true];
|
||||
repeated uint32 neighbor_blocks_2 = 6 [packed=true];
|
||||
repeated uint32 neighbor_blocks_3 = 7 [packed=true];
|
||||
repeated uint32 neighbor_blocks_4 = 8 [packed=true];
|
||||
int32 task_id = 1;
|
||||
ChunkPosNet pos = 2;
|
||||
uint32 chunk_seed = 3;
|
||||
int32 biome_type = 4;
|
||||
repeated uint32 chunk_blocks = 5 [packed=true];
|
||||
repeated uint32 neighbor_blocks_1 = 6 [packed=true];
|
||||
repeated uint32 neighbor_blocks_2 = 7 [packed=true];
|
||||
repeated uint32 neighbor_blocks_3 = 8 [packed=true];
|
||||
repeated uint32 neighbor_blocks_4 = 9 [packed=true];
|
||||
}
|
||||
|
||||
message S2C_ClearAllChunks {
|
||||
|
||||
Reference in New Issue
Block a user