From 66a1240fbc2441a9c6a0d16bd02ee6faf23a20c6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 26 Jun 2024 03:40:14 +0300 Subject: [PATCH] refactor ContentBuilder and add entities support --- src/content/Content.cpp | 11 +++-- src/content/Content.hpp | 14 +++++-- src/content/ContentBuilder.cpp | 69 ++++++++++--------------------- src/content/ContentBuilder.hpp | 54 +++++++++++++++++++----- src/content/ContentLoader.cpp | 6 +-- src/content/ContentLoader.hpp | 2 +- src/core_defs.cpp | 4 +- src/items/ItemDef.hpp | 3 +- src/logic/scripting/scripting.hpp | 2 +- 9 files changed, 90 insertions(+), 75 deletions(-) diff --git a/src/content/Content.cpp b/src/content/Content.cpp index fbd5af85..cb8d11a6 100644 --- a/src/content/Content.cpp +++ b/src/content/Content.cpp @@ -7,15 +7,18 @@ #include "../voxels/Block.hpp" #include "../items/ItemDef.hpp" +#include "../objects/EntityDef.hpp" #include "ContentPack.hpp" #include "../logic/scripting/scripting.hpp" ContentIndices::ContentIndices( - std::vector blocks, - std::vector items + ContentUnitIndices blocks, + ContentUnitIndices items, + ContentUnitIndices entities ) : blocks(std::move(blocks)), - items(std::move(items)) + items(std::move(items)), + entities(std::move(entities)) {} Content::Content( @@ -23,6 +26,7 @@ Content::Content( std::unique_ptr drawGroups, ContentUnitDefs blocks, ContentUnitDefs items, + ContentUnitDefs entities, std::unordered_map> packs, std::unordered_map> blockMaterials ) : indices(std::move(indices)), @@ -30,6 +34,7 @@ Content::Content( blockMaterials(std::move(blockMaterials)), blocks(std::move(blocks)), items(std::move(items)), + entities(std::move(entities)), drawGroups(std::move(drawGroups)) {} diff --git a/src/content/Content.hpp b/src/content/Content.hpp index 455bedf1..1fd21a71 100644 --- a/src/content/Content.hpp +++ b/src/content/Content.hpp @@ -14,12 +14,13 @@ using DrawGroups = std::set; class Block; struct BlockMaterial; -class ItemDef; +struct ItemDef; +struct EntityDef; class Content; class ContentPackRuntime; enum class contenttype { - none, block, item + none, block, item, entity }; inline const char* contenttype_name(contenttype type) { @@ -27,6 +28,7 @@ inline const char* contenttype_name(contenttype type) { case contenttype::none: return "none"; case contenttype::block: return "block"; case contenttype::item: return "item"; + case contenttype::entity: return "entity"; default: return "unknown"; } @@ -70,10 +72,12 @@ class ContentIndices { public: ContentUnitIndices blocks; ContentUnitIndices items; + ContentUnitIndices entities; ContentIndices( - std::vector blockDefs, - std::vector itemDefs + ContentUnitIndices blocks, + ContentUnitIndices items, + ContentUnitIndices entities ); }; @@ -109,6 +113,7 @@ class Content { public: ContentUnitDefs blocks; ContentUnitDefs items; + ContentUnitDefs entities; std::unique_ptr const drawGroups; Content( @@ -116,6 +121,7 @@ public: std::unique_ptr drawGroups, ContentUnitDefs blocks, ContentUnitDefs items, + ContentUnitDefs entities, std::unordered_map> packs, std::unordered_map> blockMaterials ); diff --git a/src/content/ContentBuilder.cpp b/src/content/ContentBuilder.cpp index d292e863..adbe6425 100644 --- a/src/content/ContentBuilder.cpp +++ b/src/content/ContentBuilder.cpp @@ -6,28 +6,6 @@ void ContentBuilder::add(std::unique_ptr pack) { packs[pack->getId()] = std::move(pack); } -Block& ContentBuilder::createBlock(const std::string& id) { - auto found = blockDefs.find(id); - if (found != blockDefs.end()) { - return *found->second; - } - checkIdentifier(id); - blockIds.push_back(id); - blockDefs[id] = std::make_unique(id); - return *blockDefs[id]; -} - -ItemDef& ContentBuilder::createItem(const std::string& id) { - auto found = itemDefs.find(id); - if (found != itemDefs.end()) { - return *found->second; - } - checkIdentifier(id); - itemIds.push_back(id); - itemDefs[id] = std::make_unique(id); - return *itemDefs[id]; -} - BlockMaterial& ContentBuilder::createBlockMaterial(const std::string& id) { blockMaterials[id] = std::make_unique(); auto& material = *blockMaterials[id]; @@ -35,28 +13,11 @@ BlockMaterial& ContentBuilder::createBlockMaterial(const std::string& id) { return material; } -void ContentBuilder::checkIdentifier(const std::string& id) { - contenttype result; - if (((result = checkContentType(id)) != contenttype::none)) { - throw namereuse_error("name "+id+" is already used", result); - } -} - -contenttype ContentBuilder::checkContentType(const std::string& id) { - if (blockDefs.find(id) != blockDefs.end()) { - return contenttype::block; - } - if (itemDefs.find(id) != itemDefs.end()) { - return contenttype::item; - } - return contenttype::none; -} - std::unique_ptr ContentBuilder::build() { std::vector blockDefsIndices; auto groups = std::make_unique(); - for (const std::string& name : blockIds) { - Block& def = *blockDefs[name]; + for (const std::string& name : blocks.names) { + Block& def = *blocks.defs[name]; // Generating runtime info def.rt.id = blockDefsIndices.size(); @@ -79,8 +40,8 @@ std::unique_ptr ContentBuilder::build() { } std::vector itemDefsIndices; - for (const std::string& name : itemIds) { - ItemDef& def = *itemDefs[name]; + for (const std::string& name : items.names) { + ItemDef& def = *items.defs[name]; // Generating runtime info def.rt.id = itemDefsIndices.size(); @@ -88,12 +49,24 @@ std::unique_ptr ContentBuilder::build() { itemDefsIndices.push_back(&def); } + std::vector entityDefsIndices; + for (const std::string& name : entities.names) { + EntityDef& def = *entities.defs[name]; + + // Generating runtime info + entityDefsIndices.push_back(&def); + } + auto content = std::make_unique( - std::make_unique(blockDefsIndices, itemDefsIndices), - std::move(groups), - std::move(blockDefs), - std::move(itemDefs), - std::move(packs), + std::make_unique( + blockDefsIndices, + itemDefsIndices, + entityDefsIndices), + std::move(groups), + blocks.build(), + items.build(), + entities.build(), + std::move(packs), std::move(blockMaterials) ); diff --git a/src/content/ContentBuilder.hpp b/src/content/ContentBuilder.hpp index 0c7a6d31..33e85e6e 100644 --- a/src/content/ContentBuilder.hpp +++ b/src/content/ContentBuilder.hpp @@ -3,6 +3,7 @@ #include "../items/ItemDef.hpp" #include "../voxels/Block.hpp" +#include "../objects/EntityDef.hpp" #include "../content/Content.hpp" #include "../content/ContentPack.hpp" @@ -10,27 +11,58 @@ #include #include +template +class ContentUnitBuilder { + std::unordered_map& allNames; + contenttype type; + + void checkIdentifier(const std::string& id) { + const auto& found = allNames.find(id); + if (found != allNames.end()) { + throw namereuse_error("name "+id+" is already used", found->second); + } + } +public: + std::unordered_map> defs; + std::vector names; + + ContentUnitBuilder( + std::unordered_map& allNames, + contenttype type + ) : allNames(allNames), type(type) {} + + T& create(const std::string& id) { + auto found = defs.find(id); + if (found != defs.end()) { + return *found->second; + } + checkIdentifier(id); + allNames[id] = type; + names.push_back(id); + defs[id] = std::make_unique(id); + return *defs[id]; + } + + auto build() { + return std::move(defs); + } +}; + class ContentBuilder { - std::unordered_map> blockDefs; - std::vector blockIds; - - std::unordered_map> itemDefs; - std::vector itemIds; - std::unordered_map> blockMaterials; std::unordered_map> packs; + std::unordered_map allNames; public: + ContentUnitBuilder blocks {allNames, contenttype::block}; + ContentUnitBuilder items {allNames, contenttype::item}; + ContentUnitBuilder entities {allNames, contenttype::entity}; + ~ContentBuilder(); void add(std::unique_ptr pack); - Block& createBlock(const std::string& id); - ItemDef& createItem(const std::string& id); BlockMaterial& createBlockMaterial(const std::string& id); - void checkIdentifier(const std::string& id); - contenttype checkContentType(const std::string& id); - std::unique_ptr build(); }; diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 73d8b3a3..265c93b7 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -363,14 +363,14 @@ void ContentLoader::load(ContentBuilder& builder) { auto colon = name.find(':'); std::string full = colon == std::string::npos ? pack->id + ":" + name : name; if (colon != std::string::npos) name[colon] = '/'; - auto& def = builder.createBlock(full); + auto& def = builder.blocks.create(full); if (colon != std::string::npos) { def.scriptName = name.substr(0, colon) + '/' + def.scriptName; } loadBlock(def, full, name); stats.totalBlocks++; if (!def.hidden) { - auto& item = builder.createItem(full+BLOCK_ITEM_SUFFIX); + auto& item = builder.items.create(full+BLOCK_ITEM_SUFFIX); item.generated = true; item.caption = def.caption; item.iconType = item_icon_type::block; @@ -392,7 +392,7 @@ void ContentLoader::load(ContentBuilder& builder) { auto colon = name.find(':'); std::string full = colon == std::string::npos ? pack->id + ":" + name : name; if (colon != std::string::npos) name[colon] = '/'; - auto& def = builder.createItem(full); + auto& def = builder.items.create(full); if (colon != std::string::npos) def.scriptName = name.substr(0, colon) + '/' + def.scriptName; loadItem(def, full, name); stats.totalItems++; diff --git a/src/content/ContentLoader.hpp b/src/content/ContentLoader.hpp index fa1c4b61..7a5068eb 100644 --- a/src/content/ContentLoader.hpp +++ b/src/content/ContentLoader.hpp @@ -10,7 +10,7 @@ namespace fs = std::filesystem; class Block; struct BlockMaterial; -class ItemDef; +struct ItemDef; struct ContentPack; class ContentBuilder; diff --git a/src/core_defs.cpp b/src/core_defs.cpp index 57c85bbc..549988d0 100644 --- a/src/core_defs.cpp +++ b/src/core_defs.cpp @@ -12,7 +12,7 @@ // All in-game definitions (blocks, items, etc..) void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) { - Block& block = builder->createBlock("core:air"); + Block& block = builder->blocks.create("core:air"); block.replaceable = true; block.drawGroup = 1; block.lightPassing = true; @@ -22,7 +22,7 @@ void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) { block.model = BlockModel::none; block.pickingItem = "core:empty"; - ItemDef& item = builder->createItem("core:empty"); + ItemDef& item = builder->items.create("core:empty"); item.iconType = item_icon_type::none; auto bindsFile = paths->getResources()/fs::path("bindings.toml"); diff --git a/src/items/ItemDef.hpp b/src/items/ItemDef.hpp index 5abb2e32..015cfb21 100644 --- a/src/items/ItemDef.hpp +++ b/src/items/ItemDef.hpp @@ -19,8 +19,7 @@ enum class item_icon_type { block, // block preview: icon is string block id }; -class ItemDef { -public: +struct ItemDef { /// @brief Item string id (with prefix included) std::string const name; diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index 6ac25e7b..3082420c 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -22,7 +22,7 @@ class ContentIndices; class Level; class Block; class Player; -class ItemDef; +struct ItemDef; class Inventory; class UiDocument; struct block_funcs_set;