diff --git a/include/Cubed/gameplay/server_world.hpp b/include/Cubed/gameplay/server_world.hpp index 5531bd2..1fd9eea 100644 --- a/include/Cubed/gameplay/server_world.hpp +++ b/include/Cubed/gameplay/server_world.hpp @@ -11,7 +11,6 @@ #include "world/block_change.pb.h" #include -#include #include #include #include @@ -101,10 +100,6 @@ private: ChunkPos pos; }; struct PendingChunk { - std::unique_ptr chunk; - std::future future; - }; - struct FinishedChunk { ChunkPos pos; std::unique_ptr chunk; }; @@ -112,8 +107,7 @@ private: using ChunkHashMap = tbb::concurrent_hash_map; using PlayerHashMap = std::unordered_map; - using PendingChunkHashMap = - std::unordered_map; + using NewChunkVector = std::vector; using ChunkPosSet = absl::flat_hash_set; using PlayerUUIDMap = tbb::concurrent_hash_map; @@ -125,8 +119,7 @@ private: // key = uuid PlayerHashMap m_players; ChunkHashMap m_chunks; - PendingChunkHashMap m_new_chunks; - std::vector m_new_finished_chunk; + NewChunkVector m_new_chunks; CaveCarver m_cave_carcer; RiverWorm m_river_worm; @@ -167,6 +160,7 @@ private: tbb::concurrent_unordered_map m_timers; tbb::concurrent_queue m_waiting_chunk_requests; + tbb::concurrent_queue> m_finished_queue; void init_chunks(); @@ -177,8 +171,7 @@ private: void sync_and_collect_missing_chunks(std::vector&, const ChunkPosSet&); void submit_new_chunks(const std::string& uuid); - void poll_finished_chunks(); - void wait_all_chunk_tasks(); + // void wait_all_chunk_tasks(); void update_ref_count(const ChunkPosSet& old, const ChunkPosSet& now); diff --git a/src/gameplay/server_world.cpp b/src/gameplay/server_world.cpp index 82c5e7e..639074b 100644 --- a/src/gameplay/server_world.cpp +++ b/src/gameplay/server_world.cpp @@ -28,28 +28,13 @@ void ServerWorld::stop() { send_server_stop(); stop_gen_thread(); stop_server_thread(); - wait_all_chunk_tasks(); + // wait_all_chunk_tasks(); stop_thread_pool(); + m_finished_queue.clear(); m_chunks.clear(); } -void ServerWorld::wait_all_chunk_tasks() { - std::lock_guard lock(m_new_chunk_mutex); - for (auto& [pos, task] : m_new_chunks) { - if (task.future.valid()) { - try { - task.future.get(); - } catch (const std::exception& e) { - Logger::error("Chunk generation failed: {}", e.what()); - continue; - } - } else { - Logger::error("Chunk {} {} not started gen task", pos.x, pos.z); - } - } -} - void ServerWorld::update_ref_count(const ChunkPosSet& old, const ChunkPosSet& now) { @@ -265,7 +250,7 @@ void ServerWorld::gen_chunks_internal(const std::string& uuid) { // Create new chunk std::lock_guard lock(m_new_chunk_mutex); for (auto& pos : need_gen_chunks_pos) { - m_new_chunks.emplace( + m_new_chunks.emplace_back( pos, std::make_unique(ServerChunk(*this, pos))); } } @@ -321,25 +306,24 @@ void ServerWorld::submit_new_chunks(const std::string& uuid) { switch (m_chunk_load_style) { case RANDOM: // Enqueue directly in random order - for (auto& [pos, task] : m_new_chunks) { - if (!task.future.valid()) { - task.future = - pool_ptr->enqueue([&task]() { task.chunk->gen_chunk(); }); - } + for (auto& task : m_new_chunks) { + + pool_ptr->enqueue([&task, this]() { + std::unique_ptr chunk{std::move(task.chunk)}; + chunk->gen_chunk(); + m_finished_queue.push(std::move(chunk)); + }); } break; case CENTER: { std::vector> tasks; - for (auto& [pos, task] : m_new_chunks) { - if (!task.future.valid()) { - tasks.emplace_back(pos, &task); - } + for (auto& task : m_new_chunks) { + + tasks.emplace_back(task.pos, &task); } glm::vec3 player_pos = get_player_pos(uuid); - - auto dist2 = [player_pos](ChunkPos chunk_pos) { - ChunkPos player_chunk_pos = - get_chunk_pos(player_pos.x, player_pos.z); + ChunkPos player_chunk_pos = get_chunk_pos(player_pos.x, player_pos.z); + auto dist2 = [player_chunk_pos](ChunkPos chunk_pos) { float dx = player_chunk_pos.x - chunk_pos.x; float dz = player_chunk_pos.z - chunk_pos.z; return dx * dx + dz * dz; @@ -350,39 +334,16 @@ void ServerWorld::submit_new_chunks(const std::string& uuid) { return dist2(a.first) < dist2(b.first); }); for (auto& [pos, task] : tasks) { - if (!task->future.valid()) { - task->future = - pool_ptr->enqueue([task]() { task->chunk->gen_chunk(); }); - } + + pool_ptr->enqueue([this, chunk = std::move(task->chunk)]() mutable { + chunk->gen_chunk(); + m_finished_queue.push(std::move(chunk)); + }); } + } break; } - } -} -void ServerWorld::poll_finished_chunks() { - m_new_finished_chunk.clear(); - std::lock_guard lock(m_new_chunk_mutex); - std::erase_if( - m_new_chunks, [&](std::pair& pair) { - auto& pending = pair.second; - if (!pending.future.valid()) { - return false; - } - if (pending.future.wait_for(0ms) != std::future_status::ready) { - return false; - } - try { - pending.future.get(); - } catch (const std::exception& e) { - Logger::error("Chunk generation failed: {}", e.what()); - return true; - } - // Spawn complete, move away - m_new_finished_chunk.emplace_back(pair.first, - std::move(pending.chunk)); - - return true; - }); + m_new_chunks.clear(); } void ServerWorld::start_gen_thread() { @@ -554,7 +515,6 @@ void ServerWorld::rebuild_world() { m_river_worm.reload(ChunkGenerator::seed()); m_chunks.clear(); - m_new_finished_chunk.clear(); { std::lock_guard lock(m_new_chunk_mutex); @@ -579,19 +539,24 @@ void ServerWorld::rebuild_world() { } void ServerWorld::update() { - poll_finished_chunks(); + // poll_finished_chunks(); { bool consumed = false; - - for (auto& x : m_new_finished_chunk) { + std::unique_ptr chunk; + while (m_finished_queue.try_pop(chunk)) { + if (!chunk) { + Logger::error("Finished Queue has nullptr Chunk"); + return; + } chunk_acc acc; - if (!m_chunks.find(acc, x.pos)) { + auto pos = chunk->get_chunk_pos(); + if (!m_chunks.find(acc, pos)) { Logger::error( - "New Chunk {} {} not Find, don't move to m_chunks", x.pos.x, - x.pos.z); + "New Chunk {} {} not Find, don't move to m_chunks", pos.x, + pos.z); continue; } - acc->second.chunk = std::move(x.chunk); + acc->second.chunk = std::move(chunk); acc->second.state = ChunkState::READY; consumed = true; }