#include "shared/pch.hh" #include "shared/world/dimension.hh" #include "shared/world/chunk.hh" #include "shared/world/voxel_registry.hh" #include "shared/coord.hh" #include "shared/globals.hh" Dimension::Dimension(std::string_view name, float gravity) { m_name = name; m_gravity = gravity; } Dimension::~Dimension(void) { for(const auto it : m_chunkmap) delete it.second; entities.clear(); chunks.clear(); } std::string_view Dimension::get_name(void) const { return m_name; } float Dimension::get_gravity(void) const { return m_gravity; } Chunk* Dimension::create_chunk(const chunk_pos& cpos) { auto it = m_chunkmap.find(cpos); if(it != m_chunkmap.cend()) { // Chunk already exists return it->second; } auto entity = chunks.create(); auto chunk = new Chunk(entity, this); auto& component = chunks.emplace(entity); component.chunk = chunk; component.cpos = cpos; ChunkCreateEvent event; event.dimension = this; event.chunk = chunk; event.cpos = cpos; globals::dispatcher.trigger(event); return m_chunkmap.insert_or_assign(cpos, std::move(chunk)).first->second; } Chunk* Dimension::find_chunk(entt::entity entity) const { if(chunks.valid(entity)) { return chunks.get(entity).chunk; } else { return nullptr; } } Chunk* Dimension::find_chunk(const chunk_pos& cpos) const { auto it = m_chunkmap.find(cpos); if(it != m_chunkmap.cend()) { return it->second; } else { return nullptr; } } void Dimension::remove_chunk(entt::entity entity) { if(chunks.valid(entity)) { auto& component = chunks.get(entity); m_chunkmap.erase(component.cpos); chunks.destroy(entity); } } void Dimension::remove_chunk(const chunk_pos& cpos) { auto it = m_chunkmap.find(cpos); if(it != m_chunkmap.cend()) { chunks.destroy(it->second->get_entity()); m_chunkmap.erase(it); } } void Dimension::remove_chunk(Chunk* chunk) { if(chunk) { const auto& component = chunks.get(chunk->get_entity()); m_chunkmap.erase(component.cpos); chunks.destroy(chunk->get_entity()); } } const Voxel* Dimension::get_voxel(const voxel_pos& vpos) const { auto cpos = coord::to_chunk(vpos); auto lpos = coord::to_local(vpos); if(auto chunk = find_chunk(cpos)) { return chunk->get_voxel(lpos); } return nullptr; } const Voxel* Dimension::get_voxel(const chunk_pos& cpos, const local_pos& lpos) const { // This allows accessing get_voxel with negative // local coordinates that usually would result in an // out-of-range values; this is useful for per-voxel update logic return get_voxel(coord::to_voxel(cpos, lpos)); } bool Dimension::set_voxel(const Voxel* voxel, const voxel_pos& vpos) { auto cpos = coord::to_chunk(vpos); auto lpos = coord::to_local(vpos); if(auto chunk = find_chunk(cpos)) { if(auto old_voxel = chunk->get_voxel(lpos)) { if(old_voxel != voxel) { // Notify the old voxel that it is // being replaced with a different voxel old_voxel->on_remove(this, vpos); } } chunk->set_voxel(voxel, lpos); if(voxel) { // If we're not placing air, notify the // new voxel that it has been placed voxel->on_place(this, vpos); } VoxelSetEvent event; event.dimension = this; event.voxel = voxel; event.cpos = cpos; event.lpos = lpos; event.chunk = chunk; globals::dispatcher.trigger(event); return true; } return false; } bool Dimension::set_voxel(const Voxel* voxel, const chunk_pos& cpos, const local_pos& lpos) { // This allows accessing set_voxel with negative // local coordinates that usually would result in an // out-of-range values; this is useful for per-voxel update logic return set_voxel(voxel, coord::to_voxel(cpos, lpos)); } void Dimension::init(ConfigMap& config) { } void Dimension::init_late(std::uint64_t global_seed) { } bool Dimension::generate(const chunk_pos& cpos, VoxelStorage& voxels) { return false; }