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:
@@ -52,6 +52,7 @@ public:
|
||||
void receive_player_logout(const LogoutRsp& rsp);
|
||||
int rendering_distance() const;
|
||||
void rendering_distance(int rendering_distance);
|
||||
int get_chunk_task_id() const;
|
||||
void start_client_thread(std::string_view uuid);
|
||||
void stop_client_thread();
|
||||
|
||||
@@ -108,6 +109,7 @@ private:
|
||||
std::atomic<TickType> m_day_tick{6000};
|
||||
std::atomic<bool> m_requesting_chunk{false};
|
||||
std::atomic<bool> m_is_rebuilding{false};
|
||||
std::atomic<int> m_chunk_task_id{0};
|
||||
std::shared_ptr<NetworkClient> m_client;
|
||||
ChunkLoadStyle m_chunk_load_style{ChunkLoadStyle::CENTER};
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ public:
|
||||
void update_pos(float x, float y, float z);
|
||||
void update_sync_gametick(TickType gametick);
|
||||
bool is_disconnect(TickType current_gametick) const;
|
||||
int task_id() const;
|
||||
void task_id(int id);
|
||||
|
||||
private:
|
||||
static constexpr TickType TIMEOUT = 200;
|
||||
@@ -32,5 +34,6 @@ private:
|
||||
ChunkPos m_last_chunk_pos{0, 0};
|
||||
std::shared_ptr<Session> m_session;
|
||||
std::atomic<TickType> m_last_gametick{0};
|
||||
std::atomic<int> m_chunk_task_id{0};
|
||||
};
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
std::shared_ptr<Session> session);
|
||||
glm::vec3 get_player_pos(const std::string& uuid) const;
|
||||
|
||||
void handle_chunk_req(const std::string& uuid, ChunkPos pos);
|
||||
void handle_chunk_req(int task_id, const std::string& uuid, ChunkPos pos);
|
||||
void handle_block_change(const BlockChangeReq& req);
|
||||
template <typename Fn>
|
||||
void register_timer(std::string_view id, TickType threshold, Fn&& f) {
|
||||
|
||||
@@ -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