From 51ffb93230a0e150669aaea3bc8081497c3145d4 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 26 Jan 2024 15:35:23 +0300 Subject: [PATCH] inventory reindexing --- src/constants.h | 2 ++ src/content/ContentLUT.cpp | 36 ++++++++++++++++++++++++---- src/content/ContentLUT.h | 35 ++++++++++++++++++++++++--- src/data/dynamic.cpp | 14 +++++------ src/files/WorldConverter.cpp | 46 +++++++++++++++++++++++++++--------- src/files/WorldConverter.h | 14 ++++++++++- src/files/WorldFiles.cpp | 24 +------------------ src/files/WorldFiles.h | 2 +- src/items/Inventory.cpp | 11 +++++++++ src/items/Inventory.h | 3 +++ src/objects/Player.cpp | 32 +++++++++++++++++++++++++ src/objects/Player.h | 6 +++++ 12 files changed, 174 insertions(+), 51 deletions(-) diff --git a/src/constants.h b/src/constants.h index f9cc1d4b..c67a5f7c 100644 --- a/src/constants.h +++ b/src/constants.h @@ -24,6 +24,8 @@ constexpr int CHUNK_VOL = (CHUNK_W * CHUNK_H * CHUNK_D); /* BLOCK_VOID is block id used to mark non-existing voxel (voxel of missing chunk) */ const blockid_t BLOCK_VOID = std::numeric_limits::max(); +const itemid_t ITEM_VOID = std::numeric_limits::max(); + const blockid_t MAX_BLOCKS = BLOCK_VOID; inline uint vox_index(int x, int y, int z, int w=CHUNK_W, int d=CHUNK_D) { diff --git a/src/content/ContentLUT.cpp b/src/content/ContentLUT.cpp index 11e7b5e8..3adf398c 100644 --- a/src/content/ContentLUT.cpp +++ b/src/content/ContentLUT.cpp @@ -7,10 +7,11 @@ #include "../files/files.h" #include "../coders/json.h" #include "../voxels/Block.h" +#include "../items/ItemDef.h" #include "../data/dynamic.h" -ContentLUT::ContentLUT(size_t blocksCount, const Content* content) { +ContentLUT::ContentLUT(const Content* content, size_t blocksCount, size_t itemsCount) { auto* indices = content->getIndices(); for (size_t i = 0; i < blocksCount; i++) { blocks.push_back(i); @@ -18,23 +19,37 @@ ContentLUT::ContentLUT(size_t blocksCount, const Content* content) { for (size_t i = 0; i < indices->countBlockDefs(); i++) { blockNames.push_back(indices->getBlockDef(i)->name); } - for (size_t i = indices->countBlockDefs(); i < blocksCount; i++) { blockNames.push_back(""); } + + for (size_t i = 0; i < itemsCount; i++) { + items.push_back(i); + } + for (size_t i = 0; i < indices->countItemDefs(); i++) { + itemNames.push_back(indices->getItemDef(i)->name); + } + for (size_t i = indices->countItemDefs(); i < itemsCount; i++) { + itemNames.push_back(""); + } } ContentLUT* ContentLUT::create(const fs::path& filename, const Content* content) { auto root = files::read_json(filename); auto blocklist = root->list("blocks"); + auto itemlist = root->list("items"); auto* indices = content->getIndices(); size_t blocks_c = blocklist ? std::max(blocklist->size(), indices->countBlockDefs()) : indices->countBlockDefs(); - - auto lut = std::make_unique(blocks_c, content); + size_t items_c = itemlist + ? std::max(itemlist->size(), indices->countItemDefs()) + : indices->countItemDefs(); + + auto lut = std::make_unique(content, blocks_c, items_c); + if (blocklist) { for (size_t i = 0; i < blocklist->size(); i++) { std::string name = blocklist->str(i); @@ -46,6 +61,19 @@ ContentLUT* ContentLUT::create(const fs::path& filename, } } } + + if (itemlist) { + for (size_t i = 0; i < itemlist->size(); i++) { + std::string name = itemlist->str(i); + ItemDef* def = content->findItem(name); + if (def) { + lut->setItem(i, name, def->rt.id); + } else { + lut->setItem(i, name, ITEM_VOID); + } + } + } + if (lut->hasContentReorder() || lut->hasMissingContent()) { return lut.release(); } else { diff --git a/src/content/ContentLUT.h b/src/content/ContentLUT.h index 458d4bfb..f97d87f6 100644 --- a/src/content/ContentLUT.h +++ b/src/content/ContentLUT.h @@ -12,6 +12,8 @@ namespace fs = std::filesystem; class Content; +// TODO: make it unified for all types of content + /* Content indices lookup table or report used to convert world with different indices Building with indices.json */ @@ -19,10 +21,13 @@ class ContentLUT { std::vector blocks; std::vector blockNames; + std::vector items; + std::vector itemNames; + bool reorderContent = false; bool missingContent = false; public: - ContentLUT(size_t blocks, const Content* content); + ContentLUT(const Content* content, size_t blocks, size_t items); inline const std::string& getBlockName(blockid_t index) const { return blockNames[index]; @@ -42,8 +47,28 @@ public: } } - static ContentLUT* create(const fs::path& filename, - const Content* content); + inline const std::string& getItemName(blockid_t index) const { + return itemNames[index]; + } + + inline itemid_t getItemId(itemid_t index) const { + return items[index]; + } + + inline void setItem(itemid_t index, std::string name, itemid_t id) { + items[index] = id; + itemNames[index] = name; + if (id == ITEM_VOID) { + missingContent = true; + } else if (index != id) { + reorderContent = true; + } + } + + static ContentLUT* create( + const fs::path& filename, + const Content* content + ); inline bool hasContentReorder() const { return reorderContent; @@ -55,6 +80,10 @@ public: inline size_t countBlocks() const { return blocks.size(); } + + inline size_t countItems() const { + return items.size(); + } }; #endif // CONTENT_CONTENT_LUT_H_ diff --git a/src/data/dynamic.cpp b/src/data/dynamic.cpp index 30fa53ca..ca08472f 100644 --- a/src/data/dynamic.cpp +++ b/src/data/dynamic.cpp @@ -246,11 +246,9 @@ Map& Map::put(std::string key, int value) { } Map& Map::put(std::string key, int64_t value) { - auto found = values.find(key); - if (found != values.end()) found->second; valvalue val; val.integer = value; - values.insert(std::make_pair(key, new Value(valtype::integer, val))); + values[key] = std::make_unique(valtype::integer, val); return *this; } @@ -265,14 +263,14 @@ Map& Map::put(std::string key, float value) { Map& Map::put(std::string key, double value) { valvalue val; val.decimal = value; - values.insert(std::make_pair(key, new Value(valtype::number, val))); + values[key] = std::make_unique(valtype::number, val); return *this; } Map& Map::put(std::string key, std::string value){ valvalue val; val.str = new std::string(value); - values.insert(std::make_pair(key, new Value(valtype::string, val))); + values[key] = std::make_unique(valtype::string, val); return *this; } @@ -283,21 +281,21 @@ Map& Map::put(std::string key, const char* value) { Map& Map::put(std::string key, Map* value){ valvalue val; val.map = value; - values.insert(std::make_pair(key, new Value(valtype::map, val))); + values[key] = std::make_unique(valtype::map, val); return *this; } Map& Map::put(std::string key, List* value){ valvalue val; val.list = value; - values.insert(std::make_pair(key, new Value(valtype::list, val))); + values[key] = std::make_unique(valtype::list, val); return *this; } Map& Map::put(std::string key, bool value){ valvalue val; val.boolean = value; - values.insert(std::make_pair(key, new Value(valtype::boolean, val))); + values[key] = std::make_unique(valtype::boolean, val); return *this; } diff --git a/src/files/WorldConverter.cpp b/src/files/WorldConverter.cpp index f3e9b319..ddf2e993 100644 --- a/src/files/WorldConverter.cpp +++ b/src/files/WorldConverter.cpp @@ -4,8 +4,12 @@ #include #include #include "WorldFiles.h" + +#include "../data/dynamic.h" +#include "../files/files.h" #include "../voxels/Chunk.h" #include "../content/ContentLUT.h" +#include "../objects/Player.h" namespace fs = std::filesystem; @@ -21,8 +25,9 @@ WorldConverter::WorldConverter(fs::path folder, std::cerr << "nothing to convert" << std::endl; return; } + tasks.push(convert_task {convert_task_type::player, wfile->getPlayerFile()}); for (auto file : fs::directory_iterator(regionsFolder)) { - regions.push(file.path()); + tasks.push(convert_task {convert_task_type::region, file.path()}); } } @@ -31,19 +36,12 @@ WorldConverter::~WorldConverter() { } bool WorldConverter::hasNext() const { - return !regions.empty(); + return !tasks.empty(); } -void WorldConverter::convertNext() { - if (!hasNext()) { - throw std::runtime_error("no more regions to convert"); - } - fs::path regfile = regions.front(); - regions.pop(); - if (!fs::is_regular_file(regfile)) - return; +void WorldConverter::convertRegion(fs::path file) { int x, z; - std::string name = regfile.stem().string(); + std::string name = file.stem().string(); if (!WorldFiles::parseRegionFilename(name, x, z)) { std::cerr << "could not parse name " << name << std::endl; return; @@ -64,6 +62,32 @@ void WorldConverter::convertNext() { } } +void WorldConverter::convertPlayer(fs::path file) { + std::cout << "converting player " << file.u8string() << std::endl; + auto map = files::read_json(file); + Player::convert(map.get(), lut.get()); + files::write_json(file, map.get()); +} + +void WorldConverter::convertNext() { + if (!hasNext()) { + throw std::runtime_error("no more regions to convert"); + } + convert_task task = tasks.front(); + tasks.pop(); + + if (!fs::is_regular_file(task.file)) + return; + switch (task.type) { + case convert_task_type::region: + convertRegion(task.file); + break; + case convert_task_type::player: + convertPlayer(task.file); + break; + } +} + void WorldConverter::write() { std::cout << "writing world" << std::endl; wfile->write(nullptr, content); diff --git a/src/files/WorldConverter.h b/src/files/WorldConverter.h index 99b52754..180a78d0 100644 --- a/src/files/WorldConverter.h +++ b/src/files/WorldConverter.h @@ -11,11 +11,23 @@ class Content; class ContentLUT; class WorldFiles; +enum class convert_task_type { + region, player +}; + +struct convert_task { + convert_task_type type; + fs::path file; +}; + class WorldConverter { WorldFiles* wfile; std::shared_ptr const lut; const Content* const content; - std::queue regions; + std::queue tasks; + + void convertPlayer(fs::path file); + void convertRegion(fs::path file); public: WorldConverter(fs::path folder, const Content* content, std::shared_ptr lut); diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index 44c8af76..95449b46 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -531,29 +531,7 @@ bool WorldFiles::readWorldInfo(World* world) { } void WorldFiles::writePlayer(Player* player) { - glm::vec3 position = player->hitbox->position; - dynamic::Map root; - auto& posarr = root.putList("position"); - posarr.put(position.x); - posarr.put(position.y); - posarr.put(position.z); - - auto& rotarr = root.putList("rotation"); - rotarr.put(player->cam.x); - rotarr.put(player->cam.y); - - auto& sparr = root.putList("spawnpoint"); - glm::vec3 spawnpoint = player->getSpawnPoint(); - sparr.put(spawnpoint.x); - sparr.put(spawnpoint.y); - sparr.put(spawnpoint.z); - - root.put("flight", player->flight); - root.put("noclip", player->noclip); - root.put("chosen-slot", player->getChosenSlot()); - root.put("inventory", player->getInventory()->write().release()); - - files::write_json(getPlayerFile(), &root); + files::write_json(getPlayerFile(), player->write().release()); } bool WorldFiles::readPlayer(Player* player) { diff --git a/src/files/WorldFiles.h b/src/files/WorldFiles.h index ef23c024..3b76bf7b 100644 --- a/src/files/WorldFiles.h +++ b/src/files/WorldFiles.h @@ -76,7 +76,6 @@ class WorldFiles { void writeWorldInfo(const World* world); fs::path getLightsFolder() const; fs::path getRegionFilename(int x, int y) const; - fs::path getPlayerFile() const; fs::path getWorldFile() const; fs::path getIndicesFile() const; fs::path getPacksFile() const; @@ -114,6 +113,7 @@ class WorldFiles { public: static bool parseRegionFilename(const std::string& name, int& x, int& y); fs::path getRegionsFolder() const; + fs::path getPlayerFile() const; regionsmap regions; regionsmap lights; diff --git a/src/items/Inventory.cpp b/src/items/Inventory.cpp index cc4b1a2c..3a0f7318 100644 --- a/src/items/Inventory.cpp +++ b/src/items/Inventory.cpp @@ -1,5 +1,7 @@ #include "Inventory.h" +#include "../content/ContentLUT.h" + Inventory::Inventory(size_t size) : slots(size) { } @@ -71,4 +73,13 @@ std::unique_ptr Inventory::write() const { return map; } +void Inventory::convert(dynamic::Map* data, const ContentLUT* lut) { + auto slotsarr = data->list("slots"); + for (size_t i = 0; i < slotsarr->size(); i++) { + auto item = slotsarr->map(i); + itemid_t id = item->getInt("id", ITEM_EMPTY); + item->put("id", lut->getItemId(id)); + } +} + const size_t Inventory::npos = -1; diff --git a/src/items/Inventory.h b/src/items/Inventory.h index 6cde29a7..99193cde 100644 --- a/src/items/Inventory.h +++ b/src/items/Inventory.h @@ -9,6 +9,7 @@ #include "../typedefs.h" #include "../data/dynamic.h" +class ContentLUT; class ContentIndices; // TODO: items indices fix @@ -36,6 +37,8 @@ public: /* serializing inventory */ std::unique_ptr write() const; + static void convert(dynamic::Map* data, const ContentLUT* lut); + static const size_t npos; }; diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 3fccf14b..195d8619 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -1,4 +1,5 @@ #include "Player.h" +#include "../content/ContentLUT.h" #include "../physics/Hitbox.h" #include "../physics/PhysicsSolver.h" #include "../voxels/Chunks.h" @@ -167,3 +168,34 @@ void Player::setSpawnPoint(glm::vec3 spawnpoint) { glm::vec3 Player::getSpawnPoint() const { return spawnpoint; } + +std::unique_ptr Player::write() const { + glm::vec3 position = hitbox->position; + auto root = std::make_unique(); + auto& posarr = root->putList("position"); + posarr.put(position.x); + posarr.put(position.y); + posarr.put(position.z); + + auto& rotarr = root->putList("rotation"); + rotarr.put(cam.x); + rotarr.put(cam.y); + + auto& sparr = root->putList("spawnpoint"); + sparr.put(spawnpoint.x); + sparr.put(spawnpoint.y); + sparr.put(spawnpoint.z); + + root->put("flight", flight); + root->put("noclip", noclip); + root->put("chosen-slot", chosenSlot); + root->put("inventory", inventory->write().release()); + return root; +} + +void Player::convert(dynamic::Map* data, const ContentLUT* lut) { + auto inventory = data->map("inventory"); + if (inventory) { + Inventory::convert(inventory, lut); + } +} diff --git a/src/objects/Player.h b/src/objects/Player.h index 9c5e600f..cbe510ec 100644 --- a/src/objects/Player.h +++ b/src/objects/Player.h @@ -4,12 +4,14 @@ #include #include +#include "../data/dynamic.h" #include "../voxels/voxel.h" #include "../settings.h" class Camera; class Hitbox; class Inventory; +class ContentLUT; class PhysicsSolver; class Chunks; class Level; @@ -62,6 +64,10 @@ public: void setSpawnPoint(glm::vec3 point); glm::vec3 getSpawnPoint() const; + + std::unique_ptr write() const; + + static void convert(dynamic::Map* data, const ContentLUT* lut); }; #endif /* SRC_OBJECTS_PLAYER_H_ */