From fd87fbe7f0971aab5e8cd184612644b787114662 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 28 May 2024 03:52:13 +0300 Subject: [PATCH 1/4] memory-related refactor --- src/files/WorldRegions.cpp | 28 +++++++++++----------------- src/files/WorldRegions.hpp | 6 +++--- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/files/WorldRegions.cpp b/src/files/WorldRegions.cpp index 55f3b3d2..3d2af8c4 100644 --- a/src/files/WorldRegions.cpp +++ b/src/files/WorldRegions.cpp @@ -50,16 +50,11 @@ std::unique_ptr regfile::read(int index, uint32_t& length) { } WorldRegion::WorldRegion() { - chunksData = new ubyte*[REGION_CHUNKS_COUNT]{}; - sizes = new uint32_t[REGION_CHUNKS_COUNT]{}; + chunksData = std::make_unique[]>(REGION_CHUNKS_COUNT); + sizes = std::make_unique(REGION_CHUNKS_COUNT); } WorldRegion::~WorldRegion() { - for (uint i = 0; i < REGION_CHUNKS_COUNT; i++) { - delete[] chunksData[i]; - } - delete[] sizes; - delete[] chunksData; } void WorldRegion::setUnsaved(bool unsaved) { @@ -69,23 +64,22 @@ bool WorldRegion::isUnsaved() const { return unsaved; } -ubyte** WorldRegion::getChunks() const { - return chunksData; +std::unique_ptr* WorldRegion::getChunks() const { + return chunksData.get(); } uint32_t* WorldRegion::getSizes() const { - return sizes; + return sizes.get(); } void WorldRegion::put(uint x, uint z, ubyte* data, uint32_t size) { size_t chunk_index = z * REGION_SIZE + x; - delete[] chunksData[chunk_index]; - chunksData[chunk_index] = data; + chunksData[chunk_index].reset(data); sizes[chunk_index] = size; } ubyte* WorldRegion::getChunkData(uint x, uint z) { - return chunksData[z * REGION_SIZE + x]; + return chunksData[z * REGION_SIZE + x].get(); } uint WorldRegion::getChunkDataSize(uint x, uint z) { @@ -165,14 +159,14 @@ std::unique_ptr WorldRegions::readChunkData( /// @brief Read missing chunks data (null pointers) from region file void WorldRegions::fetchChunks(WorldRegion* region, int x, int z, regfile* file) { - ubyte** chunks = region->getChunks(); + auto* chunks = region->getChunks(); uint32_t* sizes = region->getSizes(); for (size_t i = 0; i < REGION_CHUNKS_COUNT; i++) { int chunk_x = (i % REGION_SIZE) + x * REGION_SIZE; int chunk_z = (i / REGION_SIZE) + z * REGION_SIZE; if (chunks[i] == nullptr) { - chunks[i] = readChunkData(chunk_x, chunk_z, sizes[i], file).release(); + chunks[i] = readChunkData(chunk_x, chunk_z, sizes[i], file); } } } @@ -294,11 +288,11 @@ void WorldRegions::writeRegion(int x, int z, int layer, WorldRegion* entry){ char intbuf[4]{}; uint offsets[REGION_CHUNKS_COUNT]{}; - ubyte** region = entry->getChunks(); + auto* region = entry->getChunks(); uint32_t* sizes = entry->getSizes(); for (size_t i = 0; i < REGION_CHUNKS_COUNT; i++) { - ubyte* chunk = region[i]; + ubyte* chunk = region[i].get(); if (chunk == nullptr){ offsets[i] = 0; } else { diff --git a/src/files/WorldRegions.hpp b/src/files/WorldRegions.hpp index ae727c09..ffab6373 100644 --- a/src/files/WorldRegions.hpp +++ b/src/files/WorldRegions.hpp @@ -38,8 +38,8 @@ public: }; class WorldRegion { - ubyte** chunksData; - uint32_t* sizes; + std::unique_ptr[]> chunksData; + std::unique_ptr sizes; bool unsaved = false; public: WorldRegion(); @@ -52,7 +52,7 @@ public: void setUnsaved(bool unsaved); bool isUnsaved() const; - ubyte** getChunks() const; + std::unique_ptr* getChunks() const; uint32_t* getSizes() const; }; From db071982c94068ed3f0cd278e0d633c0a7f051a5 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 28 May 2024 05:17:56 +0300 Subject: [PATCH 2/4] memory-related refactor --- src/files/WorldRegions.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/files/WorldRegions.cpp b/src/files/WorldRegions.cpp index 3d2af8c4..ebfcacc5 100644 --- a/src/files/WorldRegions.cpp +++ b/src/files/WorldRegions.cpp @@ -49,10 +49,10 @@ std::unique_ptr regfile::read(int index, uint32_t& length) { return data; } -WorldRegion::WorldRegion() { - chunksData = std::make_unique[]>(REGION_CHUNKS_COUNT); - sizes = std::make_unique(REGION_CHUNKS_COUNT); -} +WorldRegion::WorldRegion() + : chunksData(std::make_unique[]>(REGION_CHUNKS_COUNT)), + sizes(std::make_unique(REGION_CHUNKS_COUNT)) +{} WorldRegion::~WorldRegion() { } @@ -108,13 +108,14 @@ WorldRegion* WorldRegions::getRegion(int x, int z, int layer) { } WorldRegion* WorldRegions::getOrCreateRegion(int x, int z, int layer) { - WorldRegion* region = getRegion(x, z, layer); - if (region == nullptr) { - RegionsLayer& regions = layers[layer]; - std::lock_guard lock(regions.mutex); - region = new WorldRegion(); - regions.regions[glm::ivec2(x, z)].reset(region); + if (auto region = getRegion(x, z, layer)) { + return region; } + RegionsLayer& regions = layers[layer]; + std::lock_guard lock(regions.mutex); + auto region_ptr = std::make_unique(); + auto region = region_ptr.get(); + regions.regions[{x, z}] = std::move(region_ptr); return region; } @@ -299,7 +300,7 @@ void WorldRegions::writeRegion(int x, int z, int layer, WorldRegion* entry){ offsets[i] = offset; size_t compressedSize = sizes[i]; - dataio::write_int32_big(compressedSize, (ubyte*)intbuf, 0); + dataio::write_int32_big(compressedSize, reinterpret_cast(intbuf), 0); offset += 4 + compressedSize; file.write(intbuf, 4); @@ -307,7 +308,7 @@ void WorldRegions::writeRegion(int x, int z, int layer, WorldRegion* entry){ } } for (size_t i = 0; i < REGION_CHUNKS_COUNT; i++) { - dataio::write_int32_big(offsets[i], (ubyte*)intbuf, 0); + dataio::write_int32_big(offsets[i], reinterpret_cast(intbuf), 0); file.write(intbuf, 4); } } @@ -357,7 +358,7 @@ static std::unique_ptr write_inventories(Chunk* chunk, uint& datasize) return data; } -/// @brief Store chunk (voxels and lights) in region (existing or new) +/// @brief Store chunk data (voxels and lights) in region (existing or new) void WorldRegions::put(Chunk* chunk){ assert(chunk != nullptr); From 96593bdb5d00d3180aaa55a2f437c7f73c18b09a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 28 May 2024 18:49:03 +0300 Subject: [PATCH 3/4] minor refactor --- src/files/WorldRegions.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/files/WorldRegions.cpp b/src/files/WorldRegions.cpp index ebfcacc5..ffc51e8c 100644 --- a/src/files/WorldRegions.cpp +++ b/src/files/WorldRegions.cpp @@ -147,10 +147,7 @@ inline void calc_reg_coords( } std::unique_ptr WorldRegions::readChunkData( - int x, - int z, - uint32_t& length, - regfile* rfile + int x, int z, uint32_t& length, regfile* rfile ){ int regionX, regionZ, localX, localZ; calc_reg_coords(x, z, regionX, regionZ, localX, localZ); @@ -352,9 +349,7 @@ static std::unique_ptr write_inventories(Chunk* chunk, uint& datasize) auto datavec = builder.data(); datasize = builder.size(); auto data = std::make_unique(datasize); - for (uint i = 0; i < datasize; i++) { - data[i] = datavec[i]; - } + std::memcpy(data.get(), datavec, datasize); return data; } From c67e4b04bb3b28424d62b88f26b72b92182f44f9 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 7 Jun 2024 14:04:25 +0300 Subject: [PATCH 4/4] refactor: WorldRegions and chunks saving --- src/files/WorldRegions.cpp | 24 +++++++++++++++++------- src/files/WorldRegions.hpp | 2 +- src/voxels/Chunk.cpp | 11 +++++++---- src/voxels/Chunk.hpp | 24 ++++++++++++++---------- src/voxels/Chunks.cpp | 11 +++-------- src/voxels/ChunksStorage.cpp | 2 ++ src/world/World.cpp | 20 ++++++-------------- src/world/World.hpp | 1 - 8 files changed, 50 insertions(+), 45 deletions(-) diff --git a/src/files/WorldRegions.cpp b/src/files/WorldRegions.cpp index 7c9f0f5b..24aaa694 100644 --- a/src/files/WorldRegions.cpp +++ b/src/files/WorldRegions.cpp @@ -103,8 +103,9 @@ WorldRegion* WorldRegions::getRegion(int x, int z, int layer) { RegionsLayer& regions = layers[layer]; std::lock_guard lock(regions.mutex); auto found = regions.regions.find(glm::ivec2(x, z)); - if (found == regions.regions.end()) + if (found == regions.regions.end()) { return nullptr; + } return found->second.get(); } @@ -357,6 +358,13 @@ static std::unique_ptr write_inventories(Chunk* chunk, uint& datasize) /// @brief Store chunk data (voxels and lights) in region (existing or new) void WorldRegions::put(Chunk* chunk){ assert(chunk != nullptr); + if (!chunk->flags.lighted) { + return; + } + bool lightsUnsaved = !chunk->flags.loadedLights && doWriteLights; + if (!chunk->flags.unsaved && !lightsUnsaved) { + return; + } int regionX, regionZ, localX, localZ; calc_reg_coords(chunk->x, chunk->z, regionX, regionZ, localX, localZ); @@ -399,11 +407,12 @@ std::unique_ptr WorldRegions::getLights(int x, int z) { } chunk_inventories_map WorldRegions::fetchInventories(int x, int z) { - chunk_inventories_map inventories; + chunk_inventories_map meta; uint32_t bytesSize; const ubyte* data = getData(x, z, REGION_LAYER_INVENTORIES, bytesSize); - if (data == nullptr) - return inventories; + if (data == nullptr) { + return meta; + } ByteReader reader(data, bytesSize); int count = reader.getInt32(); for (int i = 0; i < count; i++) { @@ -413,9 +422,9 @@ chunk_inventories_map WorldRegions::fetchInventories(int x, int z) { reader.skip(size); auto inv = std::make_shared(0, 0); inv->deserialize(map.get()); - inventories[index] = inv; + meta[index] = inv; } - return inventories; + return meta; } void WorldRegions::processRegionVoxels(int x, int z, const regionproc& func) { @@ -456,8 +465,9 @@ void WorldRegions::write() { bool WorldRegions::parseRegionFilename(const std::string& name, int& x, int& z) { size_t sep = name.find('_'); - if (sep == std::string::npos || sep == 0 || sep == name.length()-1) + if (sep == std::string::npos || sep == 0 || sep == name.length()-1) { return false; + } try { x = std::stoi(name.substr(0, sep)); z = std::stoi(name.substr(sep+1)); diff --git a/src/files/WorldRegions.hpp b/src/files/WorldRegions.hpp index b12ceb11..39a2a6b3 100644 --- a/src/files/WorldRegions.hpp +++ b/src/files/WorldRegions.hpp @@ -128,7 +128,7 @@ public: bool generatorTestMode = false; bool doWriteLights = true; - WorldRegions(const fs::path &directory); + WorldRegions(const fs::path& directory); WorldRegions(const WorldRegions&) = delete; ~WorldRegions(); diff --git a/src/voxels/Chunk.cpp b/src/voxels/Chunk.cpp index b437b8a2..be8238c6 100644 --- a/src/voxels/Chunk.cpp +++ b/src/voxels/Chunk.cpp @@ -113,8 +113,11 @@ bool Chunk::decode(const ubyte* data) { ubyte bst1 = data[CHUNK_VOL*2 + i]; ubyte bst2 = data[CHUNK_VOL*3 + i]; - vox.id = (blockid_t(bid1) << 8) | (blockid_t(bid2)); - vox.state = int2blockstate((blockstate_t(bst1) << 8) | (blockstate_t(bst2))); + vox.id = (static_cast(bid1) << 8) | + static_cast(bid2); + vox.state = int2blockstate( + (static_cast(bst1) << 8) | + static_cast(bst2)); } return true; } @@ -122,8 +125,8 @@ bool Chunk::decode(const ubyte* data) { void Chunk::convert(ubyte* data, const ContentLUT* lut) { for (uint i = 0; i < CHUNK_VOL; i++) { // see encode method to understand what the hell is going on here - blockid_t id = ((blockid_t(data[i]) << 8) | - blockid_t(data[CHUNK_VOL+i])); + blockid_t id = ((static_cast(data[i]) << 8) | + static_cast(data[CHUNK_VOL+i])); blockid_t replacement = lut->getBlockId(id); data[i] = replacement >> 8; data[CHUNK_VOL+i] = replacement & 0xFF; diff --git a/src/voxels/Chunk.hpp b/src/voxels/Chunk.hpp index 535b6125..a0157763 100644 --- a/src/voxels/Chunk.hpp +++ b/src/voxels/Chunk.hpp @@ -5,8 +5,9 @@ #include #include -#include "../constants.hpp" #include "voxel.hpp" + +#include "../constants.hpp" #include "../lighting/Lightmap.hpp" inline constexpr int CHUNK_DATA_LEN = CHUNK_VOL*4; @@ -15,6 +16,10 @@ class Lightmap; class ContentLUT; class Inventory; +namespace dynamic { + class Map; +} + using chunk_inventories_map = std::unordered_map>; class Chunk { @@ -32,7 +37,7 @@ public: bool loadedLights: 1; } flags {}; - /* Block inventories map where key is index of block in voxels array */ + /// @brief Block inventories map where key is index of block in voxels array chunk_inventories_map inventories; Chunk(int x, int z); @@ -44,14 +49,15 @@ public: // unused std::unique_ptr clone() const; - /* Creates new block inventory given size - @return inventory id or 0 if block does not exists */ - void addBlockInventory(std::shared_ptr inventory, - uint x, uint y, uint z); + /// @brief Creates new block inventory given size + /// @return inventory id or 0 if block does not exists + void addBlockInventory( + std::shared_ptr inventory, uint x, uint y, uint z + ); void removeBlockInventory(uint x, uint y, uint z); void setBlockInventories(chunk_inventories_map map); - /* @return inventory bound to the given block or nullptr */ + /// @return inventory bound to the given block or nullptr std::shared_ptr getBlockInventory(uint x, uint y, uint z) const; inline void setModifiedAndUnsaved() { @@ -61,9 +67,7 @@ public: std::unique_ptr encode() const; - /** - * @return true if all is fine - **/ + /// @return true if all is fine bool decode(const ubyte* data); static void convert(ubyte* data, const ContentLUT* lut); diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index b2386455..2805c94b 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -497,14 +497,9 @@ void Chunks::saveAndClear(){ for (size_t i = 0; i < volume; i++){ Chunk* chunk = chunks[i].get(); chunks[i] = nullptr; - if (chunk == nullptr || !chunk->flags.lighted) - continue; - - bool lightsUnsaved = !chunk->flags.loadedLights && - worldFiles->doesWriteLights(); - if (!chunk->flags.unsaved && !lightsUnsaved) - continue; - regions.put(chunk); + if (chunk) { + regions.put(chunk); + } } chunksCount = 0; } diff --git a/src/voxels/ChunksStorage.cpp b/src/voxels/ChunksStorage.cpp index ab6f9714..1ffb2b03 100644 --- a/src/voxels/ChunksStorage.cpp +++ b/src/voxels/ChunksStorage.cpp @@ -59,8 +59,10 @@ std::shared_ptr ChunksStorage::create(int x, int z) { auto data = regions.getChunk(chunk->x, chunk->z); if (data) { chunk->decode(data.get()); + auto invs = regions.fetchInventories(chunk->x, chunk->z); chunk->setBlockInventories(std::move(invs)); + chunk->flags.loaded = true; for(auto& entry : chunk->inventories) { level->inventories->store(entry.second); diff --git a/src/world/World.cpp b/src/world/World.cpp index fe9a8eba..3e92ccb6 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -35,12 +35,10 @@ World::World( ) : name(std::move(name)), generator(std::move(generator)), seed(seed), - settings(settings), content(content), - packs(packs) -{ - wfile = std::make_unique(directory, settings.debug); -} + packs(packs), + wfile(std::make_unique(directory, settings.debug)) +{} World::~World(){ } @@ -57,16 +55,10 @@ void World::write(Level* level) { auto& regions = wfile->getRegions(); for (size_t i = 0; i < chunks->volume; i++) { - auto chunk = chunks->chunks[i]; - if (chunk == nullptr || !chunk->flags.lighted) - continue; - bool lightsUnsaved = !chunk->flags.loadedLights && - settings.debug.doWriteLights.get(); - if (!chunk->flags.unsaved && !lightsUnsaved) - continue; - regions.put(chunk.get()); + if (auto chunk = chunks->chunks[i]) { + regions.put(chunk.get()); + } } - wfile->write(this, content); auto playerFile = dynamic::Map(); diff --git a/src/world/World.hpp b/src/world/World.hpp index fdde86e2..904ed027 100644 --- a/src/world/World.hpp +++ b/src/world/World.hpp @@ -30,7 +30,6 @@ class World : Serializable { std::string name; std::string generator; uint64_t seed; - EngineSettings& settings; const Content* const content; std::vector packs;