From 458e0005690ea9d579588a0a12368fc2c2c9a93a Mon Sep 17 00:00:00 2001 From: untodesu Date: Tue, 1 Jul 2025 03:08:39 +0500 Subject: I hyper-focued on refactoring again - I put a cool-sounding "we are number one" remix on repeat and straight up grinded the entire repository to a better state until 03:09 AM. I guess I have something wrong in my brain that makes me do this shit --- game/server/world/worldgen.cc | 150 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 game/server/world/worldgen.cc (limited to 'game/server/world/worldgen.cc') diff --git a/game/server/world/worldgen.cc b/game/server/world/worldgen.cc new file mode 100644 index 0000000..99e9a78 --- /dev/null +++ b/game/server/world/worldgen.cc @@ -0,0 +1,150 @@ +#include "server/pch.hh" + +#include "server/world/worldgen.hh" + +#include "core/io/cmdline.hh" + +#include "shared/world/chunk.hh" +#include "shared/world/dimension.hh" + +#include "shared/protocol.hh" +#include "shared/threading.hh" + +#include "server/world/inhabited.hh" + +#include "server/globals.hh" +#include "server/sessions.hh" + +static bool aggressive_caching; + +static emhash8::HashMap>> active_tasks; + +class WorldgenTask final : public Task { +public: + explicit WorldgenTask(world::Dimension* dimension, const chunk_pos& cpos); + virtual ~WorldgenTask(void) = default; + virtual void process(void) override; + virtual void finalize(void) override; + +private: + world::Dimension* m_dimension; + world::VoxelStorage m_voxels; + chunk_pos m_cpos; +}; + +WorldgenTask::WorldgenTask(world::Dimension* dimension, const chunk_pos& cpos) +{ + m_dimension = dimension; + m_voxels.fill(rand()); // trolling + m_cpos = cpos; +} + +void WorldgenTask::process(void) +{ + if(!m_dimension->generate(m_cpos, m_voxels)) { + set_status(task_status::CANCELLED); + } +} + +void WorldgenTask::finalize(void) +{ + auto dim_tasks = active_tasks.find(m_dimension); + + if(dim_tasks == active_tasks.cend()) { + // Normally this should never happen but + // one can never be sure about anything + // when that anything is threaded out + return; + } + + auto it = dim_tasks->second.find(m_cpos); + + if(it == dim_tasks->second.cend()) { + // Normally this should never happen but + // one can never be sure about anything + // when that anything is threaded out + return; + } + + auto chunk = m_dimension->create_chunk(m_cpos); + chunk->set_voxels(m_voxels); + + if(aggressive_caching) { + // Marking the chunk with InhabitedComponent makes + // it so that it is saved regardles of whether it was + // modified by players or not. This isn't particularly + // good for server-side disk usage but it might improve performance + m_dimension->chunks.emplace(chunk->get_entity()); + } + + protocol::ChunkVoxels response; + response.voxels = m_voxels; + response.chunk = m_cpos; + + auto packet = protocol::encode(response); + + for(auto session : it->second) { + if(session->peer) { + // Respond with the voxels to every session + // that has requested this specific chunk for this dimension + enet_peer_send(session->peer, protocol::CHANNEL, packet); + } + } + + dim_tasks->second.erase(it); + + if(dim_tasks->second.empty()) { + // There are no more requests + // to generate a chunk for that + // dimension, at least for now + active_tasks.erase(dim_tasks); + } +} + +void world::worldgen::init(void) +{ + aggressive_caching = io::cmdline::contains("aggressive-caching"); +} + +bool world::worldgen::is_generating(Dimension* dimension, const chunk_pos& cpos) +{ + auto dim_tasks = active_tasks.find(dimension); + + if(dim_tasks == active_tasks.cend()) { + // No tasks for this dimension + return false; + } + + auto it = dim_tasks->second.find(cpos); + + if(it == dim_tasks->second.cend()) { + // Not generating this chunk + return false; + } + + return true; +} + +void world::worldgen::request_chunk(Session* session, const chunk_pos& cpos) +{ + if(session->dimension) { + auto dim_tasks = active_tasks.find(session->dimension); + + if(dim_tasks == active_tasks.cend()) { + dim_tasks = active_tasks.emplace(session->dimension, emhash8::HashMap>()).first; + } + + auto it = dim_tasks->second.find(cpos); + + if(it == dim_tasks->second.cend()) { + auto& sessions = dim_tasks->second.insert_or_assign(cpos, std::unordered_set()).first->second; + sessions.insert(session); + + threading::submit(session->dimension, cpos); + + return; + } + + it->second.insert(session); + } +} -- cgit