From 76aeb8e4df41f6d98294fcbb254d20d49ea8f0c8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 29 Dec 2023 14:17:26 +0300 Subject: [PATCH] Content packs indices auto build + WorldGenerator fix --- src/coders/json.cpp | 4 +++ src/coders/json.h | 2 ++ src/content/ContentLoader.cpp | 61 ++++++++++++++++++++++++++++++++++- src/content/ContentLoader.h | 1 + src/content/ContentPack.cpp | 1 + src/content/ContentPack.h | 2 ++ src/util/listutil.h | 13 ++++++++ src/voxels/WorldGenerator.cpp | 12 ++++--- 8 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 src/util/listutil.h diff --git a/src/coders/json.cpp b/src/coders/json.cpp index 94d5d620..955854c8 100644 --- a/src/coders/json.cpp +++ b/src/coders/json.cpp @@ -238,6 +238,10 @@ JObject& JArray::putObj() { return *obj; } +void JArray::remove(size_t index) { + values.erase(values.begin() + index); +} + JObject::~JObject() { for (auto entry : map) { delete entry.second; diff --git a/src/coders/json.h b/src/coders/json.h index 94d8b5a9..dd170864 100644 --- a/src/coders/json.h +++ b/src/coders/json.h @@ -68,6 +68,8 @@ namespace json { JArray& putArray(); JObject& putObj(); + + void remove(size_t index); }; class JObject { diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 5a10b4c4..93adae1a 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -3,9 +3,11 @@ #include #include #include +#include #include #include "Content.h" +#include "../util/listutil.h" #include "../voxels/Block.h" #include "../files/files.h" #include "../coders/json.h" @@ -19,6 +21,61 @@ namespace fs = std::filesystem; ContentLoader::ContentLoader(ContentPack* pack) : pack(pack) { } +void ContentLoader::fixPackIndices() { + auto folder = pack->folder; + auto indexFile = pack->getContentFile(); + auto blocksFolder = folder/ContentPack::BLOCKS_FOLDER; + std::unique_ptr root; + if (fs::is_regular_file(indexFile)) { + root.reset(files::read_json(indexFile)); + } else { + root.reset(new json::JObject()); + } + + std::vector detectedBlocks; + std::vector indexedBlocks; + if (fs::is_directory(blocksFolder)) { + for (auto entry : fs::directory_iterator(blocksFolder)) { + fs::path file = entry.path(); + if (fs::is_regular_file(file) && file.extension() == ".json") { + std::string name = file.stem(); + if (name[0] == '_') + continue; + detectedBlocks.push_back(name); + } + } + } + + bool modified = false; + if (!root->has("blocks")) { + root->putArray("blocks"); + } + json::JArray* blocksarr = root->arr("blocks"); + if (blocksarr) { + for (uint i = 0; i < blocksarr->size(); i++) { + std::string name = blocksarr->str(i); + if (!util::contains(detectedBlocks, name)) { + blocksarr->remove(i); + i--; + modified = true; + continue; + } + indexedBlocks.push_back(name); + } + } + for (auto name : detectedBlocks) { + if (!util::contains(indexedBlocks, name)) { + blocksarr->put(name); + modified = true; + } + } + if (modified){ + // rewrite modified json + std::cout << indexFile << std::endl; + files::write_string(indexFile, json::stringify(root.get(), true, " ")); + } +} + // TODO: add basic validation and logging Block* ContentLoader::loadBlock(std::string name, fs::path file) { std::unique_ptr root(files::read_json(file)); @@ -95,8 +152,10 @@ Block* ContentLoader::loadBlock(std::string name, fs::path file) { void ContentLoader::load(ContentBuilder* builder) { std::cout << "-- loading pack [" << pack->id << "]" << std::endl; + fixPackIndices(); + auto folder = pack->folder; - auto root = files::read_json(pack->getContentFile()); + std::unique_ptr root (files::read_json(pack->getContentFile())); json::JArray* blocksarr = root->arr("blocks"); if (blocksarr) { diff --git a/src/content/ContentLoader.h b/src/content/ContentLoader.h index 14e42d06..7961da86 100644 --- a/src/content/ContentLoader.h +++ b/src/content/ContentLoader.h @@ -13,6 +13,7 @@ class ContentLoader { public: ContentLoader(ContentPack* pack); + void fixPackIndices(); Block* loadBlock(std::string name, std::filesystem::path file); void load(ContentBuilder* builder); }; diff --git a/src/content/ContentPack.cpp b/src/content/ContentPack.cpp index 7a39dfbe..c1fbacdd 100644 --- a/src/content/ContentPack.cpp +++ b/src/content/ContentPack.cpp @@ -10,6 +10,7 @@ namespace fs = std::filesystem; const std::string ContentPack::PACKAGE_FILENAME = "package.json"; const std::string ContentPack::CONTENT_FILENAME = "content.json"; +const fs::path ContentPack::BLOCKS_FOLDER = "blocks"; contentpack_error::contentpack_error( std::string packId, diff --git a/src/content/ContentPack.h b/src/content/ContentPack.h index 4ae38cba..3e920879 100644 --- a/src/content/ContentPack.h +++ b/src/content/ContentPack.h @@ -30,6 +30,8 @@ struct ContentPack { static const std::string PACKAGE_FILENAME; static const std::string CONTENT_FILENAME; + static const std::filesystem::path BLOCKS_FOLDER; + static bool is_pack(std::filesystem::path folder); static ContentPack read(std::filesystem::path folder); static void scan(std::filesystem::path folder, diff --git a/src/util/listutil.h b/src/util/listutil.h new file mode 100644 index 00000000..1ed07d2f --- /dev/null +++ b/src/util/listutil.h @@ -0,0 +1,13 @@ +#ifndef UTIL_LISTUTIL_H_ +#define UTIL_LISTUTIL_H_ + +#include + +namespace util { + template + bool contains(std::vector vec, const T& value) { + return std::find(vec.begin(), vec.end(), value) != vec.end(); + } +} + +#endif // UTIL_LISTUTIL_H_ diff --git a/src/voxels/WorldGenerator.cpp b/src/voxels/WorldGenerator.cpp index 5a38da81..43dc6bbc 100644 --- a/src/voxels/WorldGenerator.cpp +++ b/src/voxels/WorldGenerator.cpp @@ -128,7 +128,9 @@ int generate_tree(fnl_state *noise, int cur_x, int cur_y, int cur_z, - int tileSize){ + int tileSize, + blockid_t idWood, + blockid_t idLeaves){ const int tileX = floordiv(cur_x, tileSize); const int tileZ = floordiv(cur_z, tileSize); @@ -152,9 +154,9 @@ int generate_tree(fnl_state *noise, int ly = cur_y - height - 3 * radius; int lz = cur_z - centerZ; if (lx == 0 && lz == 0 && cur_y - height < (3*radius + radius/2)) - return 6; + return idWood; if (lx*lx+ly*ly/2+lz*lz < radius*radius) - return 7; + return idLeaves; return 0; } @@ -210,7 +212,7 @@ void WorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){ } else if (cur_y < height){ id = idDirt; } else { - int tree = generate_tree(&noise, &randomtree, heights, cur_x, cur_y, cur_z, treesTile); + int tree = generate_tree(&noise, &randomtree, heights, cur_x, cur_y, cur_z, treesTile, idWood, idLeaves); if (tree) { id = tree; states = BLOCK_DIR_UP; @@ -220,7 +222,7 @@ void WorldGenerator::generate(voxel* voxels, int cx, int cz, int seed){ if ( ((height - (1.1 - 0.2 * pow(height - 54, 4)) + - (5*send)) < cur_y + (height - 0.01- (int)height)) + (5*send)) < cur_y + (height - 0.01- (int)height)) && (cur_y < height)){ id = idSand; }