From b02b45457322e1ce8f6b9735caeb5b58b1e2ffb4 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 13 Jul 2025 15:36:09 +0300 Subject: [PATCH 1/2] fix: missing pack.has_indices if content is not loaded --- src/content/ContentPack.cpp | 21 +++++++++++++++++++++ src/content/ContentPack.hpp | 23 +++++++++++++---------- src/logic/scripting/lua/libs/libpack.cpp | 7 ++++++- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/content/ContentPack.cpp b/src/content/ContentPack.cpp index 9114aacd..ac8c8d59 100644 --- a/src/content/ContentPack.cpp +++ b/src/content/ContentPack.cpp @@ -9,7 +9,10 @@ #include "data/dv.hpp" #include "io/engine_paths.hpp" #include "io/io.hpp" +#include "coders/commons.hpp" +#include "debug/Logger.hpp" +static debug::Logger logger("content-pack"); namespace fs = std::filesystem; @@ -47,6 +50,24 @@ bool ContentPack::is_pack(const io::path& folder) { return io::is_regular_file(folder / PACKAGE_FILENAME); } +std::optional ContentPack::loadStats() const { + auto contentFile = getContentFile(); + if (!io::exists(contentFile)) { + return std::nullopt; + } + dv::value object; + try { + object = io::read_object(contentFile); + } catch (const parsing_error& err) { + logger.error() << err.errorLog(); + } + ContentPackStats stats {}; + stats.totalBlocks = object.has("blocks") ? object["blocks"].size() : 0; + stats.totalItems = object.has("items") ? object["items"].size() : 0; + stats.totalEntities = object.has("entities") ? object["entities"].size() : 0; + return stats; +} + static void checkContentPackId(const std::string& id, const io::path& folder) { if (id.length() < 2 || id.length() > 24) throw contentpack_error( diff --git a/src/content/ContentPack.hpp b/src/content/ContentPack.hpp index d434268a..f4e44801 100644 --- a/src/content/ContentPack.hpp +++ b/src/content/ContentPack.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "typedefs.hpp" #include "content_fwd.hpp" @@ -36,6 +37,16 @@ struct DependencyPack { std::string id; }; +struct ContentPackStats { + size_t totalBlocks; + size_t totalItems; + size_t totalEntities; + + inline bool hasSavingContent() const { + return totalBlocks + totalItems + totalEntities > 0; + } +}; + struct ContentPack { std::string id = "none"; std::string title = "untitled"; @@ -48,6 +59,8 @@ struct ContentPack { io::path getContentFile() const; + std::optional loadStats() const; + static inline const std::string PACKAGE_FILENAME = "package.json"; static inline const std::string CONTENT_FILENAME = "content.json"; static inline const io::path BLOCKS_FOLDER = "blocks"; @@ -87,16 +100,6 @@ struct ContentPack { } }; -struct ContentPackStats { - size_t totalBlocks; - size_t totalItems; - size_t totalEntities; - - inline bool hasSavingContent() const { - return totalBlocks + totalItems + totalEntities > 0; - } -}; - struct WorldFuncsSet { bool onblockplaced; bool onblockreplaced; diff --git a/src/logic/scripting/lua/libs/libpack.cpp b/src/logic/scripting/lua/libs/libpack.cpp index e95cf2ba..adc45096 100644 --- a/src/logic/scripting/lua/libs/libpack.cpp +++ b/src/logic/scripting/lua/libs/libpack.cpp @@ -123,8 +123,13 @@ static int l_pack_get_info( auto runtime = content ? content->getPackRuntime(pack.id) : nullptr; if (runtime) { lua::pushboolean(L, runtime->getStats().hasSavingContent()); - lua::setfield(L, "has_indices"); + } else { + auto stats = pack.loadStats(); + lua::pushboolean( + L, stats.has_value() ? stats->hasSavingContent() : false + ); } + lua::setfield(L, "has_indices"); return 1; } From 15a778299c6981556c2d5e64edffad024e8dec54 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 13 Jul 2025 15:57:57 +0300 Subject: [PATCH 2/2] limit chunks non-unloading zone to a circle --- src/frontend/hud.cpp | 12 ++++++++-- src/logic/ChunksController.cpp | 43 ++++++++++++++++++++++++++++++---- src/logic/ChunksController.hpp | 2 ++ src/util/AreaMap2D.hpp | 11 +++++++++ src/voxels/Chunks.cpp | 4 ++++ src/voxels/Chunks.hpp | 2 ++ 6 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 74003b2b..60cee6c4 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -270,6 +270,7 @@ void Hud::updateHotbarControl() { void Hud::updateWorldGenDebug() { auto& level = frontend.getLevel(); const auto& chunks = *player.chunks; + uint padding = engine.getSettings().chunks.padding.get(); auto generator = frontend.getController()->getChunksController()->getGenerator(); auto debugInfo = generator->createDebugInfo(); @@ -291,8 +292,15 @@ void Hud::updateWorldGenDebug() { int ax = x - (width - areaWidth) / 2; int az = z - (height - areaHeight) / 2; - data[(flippedZ * width + x) * 4 + 1] = - chunks.getChunk(ax + ox, az + oz) ? 255 : 0; + bool isInLoadingZone = + frontend.getController() + ->getChunksController() + ->isInLoadingZone(player, padding, ax + ox, az + oz); + + data[(flippedZ * width + x) * 4 + 1] = + chunks.getChunk(ax + ox, az + oz) + ? (isInLoadingZone ? 255 : 128) + : 0; data[(flippedZ * width + x) * 4 + 0] = level.chunks->fetch(ax + ox, az + oz) ? 255 : 0; diff --git a/src/logic/ChunksController.cpp b/src/logic/ChunksController.cpp index 1c90b122..97bbdf99 100644 --- a/src/logic/ChunksController.cpp +++ b/src/logic/ChunksController.cpp @@ -60,18 +60,55 @@ void ChunksController::update( } } -bool ChunksController::loadVisible(const Player& player, uint padding) const { +bool ChunksController::isInLoadingZone( + const Player& player, uint padding, int x, int z +) const { const auto& chunks = *player.chunks; int sizeX = chunks.getWidth(); int sizeY = chunks.getHeight(); + int minDistance = ((sizeX - padding * 2) / 2) * ((sizeY - padding * 2) / 2); + + int lx = (x - chunks.getOffsetX()) - sizeX / 2; + int lz = (z - chunks.getOffsetY()) - sizeY / 2; + int distance = (lx * lx + lz * lz); + + return distance < minDistance; +} + +bool ChunksController::loadVisible(const Player& player, uint padding) const { + auto& chunks = *player.chunks; + int sizeX = chunks.getWidth(); + int sizeY = chunks.getHeight(); + int nearX = 0; int nearZ = 0; bool assigned = false; int minDistance = ((sizeX - padding * 2) / 2) * ((sizeY - padding * 2) / 2); + int maxDistance = ((sizeX) / 2) * ((sizeY) / 2); + for (uint z = 0; z < sizeY; z++) { + for (uint x = 0; x < sizeX; x++) { + int index = z * sizeX + x; + int lx = x - sizeX / 2; + int lz = z - sizeY / 2; + int distance = (lx * lx + lz * lz); + auto& chunk = chunks.getChunks()[index]; + if (chunk != nullptr) { + if (distance >= maxDistance) { + chunks.remove( + x + chunks.getOffsetX(), z + chunks.getOffsetY() + ); + } + continue; + } + } + } for (uint z = padding; z < sizeY - padding; z++) { for (uint x = padding; x < sizeX - padding; x++) { int index = z * sizeX + x; + int lx = x - sizeX / 2; + int lz = z - sizeY / 2; + int distance = (lx * lx + lz * lz); auto& chunk = chunks.getChunks()[index]; if (chunk != nullptr) { if (chunk->flags.loaded && !chunk->flags.lighted) { @@ -81,9 +118,7 @@ bool ChunksController::loadVisible(const Player& player, uint padding) const { } continue; } - int lx = x - sizeX / 2; - int lz = z - sizeY / 2; - int distance = (lx * lx + lz * lz); + if (distance < minDistance) { minDistance = distance; nearX = x; diff --git a/src/logic/ChunksController.hpp b/src/logic/ChunksController.hpp index 80901bff..e9f367da 100644 --- a/src/logic/ChunksController.hpp +++ b/src/logic/ChunksController.hpp @@ -32,6 +32,8 @@ public: int64_t maxDuration, int loadDistance, uint padding, Player& player ) const; + bool isInLoadingZone(const Player& player, uint padding, int x, int z) const; + const WorldGenerator* getGenerator() const { return generator.get(); } diff --git a/src/util/AreaMap2D.hpp b/src/util/AreaMap2D.hpp index b7eda1fb..9ec0e439 100644 --- a/src/util/AreaMap2D.hpp +++ b/src/util/AreaMap2D.hpp @@ -114,6 +114,17 @@ namespace util { return true; } + void remove(TCoord x, TCoord y) { + auto lx = x - offsetX; + auto ly = y - offsetY; + if (lx < 0 || ly < 0 || lx >= sizeX || ly >= sizeY) { + return; + } + if (outCallback) + outCallback(x, y, firstBuffer[ly * sizeX + lx]); + firstBuffer[ly * sizeX + lx] = T{}; + } + void setOutCallback(const OutCallback& callback) { outCallback = callback; } diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 60422c60..b9650b99 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -419,3 +419,7 @@ void Chunks::getVoxels(VoxelsVolume& volume, bool backlight) const { void Chunks::saveAndClear() { areaMap.clear(); } + +void Chunks::remove(int32_t x, int32_t z) { + areaMap.remove(x, z); +} diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index 172cc329..2b2183f5 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -133,6 +133,8 @@ public: void saveAndClear(); + void remove(int32_t x, int32_t z); + const std::vector>& getChunks() const { return areaMap.getBuffer(); }