refactor ContentBuilder and add entities support

This commit is contained in:
MihailRis 2024-06-26 03:40:14 +03:00
parent 1acced4475
commit 66a1240fbc
9 changed files with 90 additions and 75 deletions

View File

@ -7,15 +7,18 @@
#include "../voxels/Block.hpp" #include "../voxels/Block.hpp"
#include "../items/ItemDef.hpp" #include "../items/ItemDef.hpp"
#include "../objects/EntityDef.hpp"
#include "ContentPack.hpp" #include "ContentPack.hpp"
#include "../logic/scripting/scripting.hpp" #include "../logic/scripting/scripting.hpp"
ContentIndices::ContentIndices( ContentIndices::ContentIndices(
std::vector<Block*> blocks, ContentUnitIndices<Block> blocks,
std::vector<ItemDef*> items ContentUnitIndices<ItemDef> items,
ContentUnitIndices<EntityDef> entities
) : blocks(std::move(blocks)), ) : blocks(std::move(blocks)),
items(std::move(items)) items(std::move(items)),
entities(std::move(entities))
{} {}
Content::Content( Content::Content(
@ -23,6 +26,7 @@ Content::Content(
std::unique_ptr<DrawGroups> drawGroups, std::unique_ptr<DrawGroups> drawGroups,
ContentUnitDefs<Block> blocks, ContentUnitDefs<Block> blocks,
ContentUnitDefs<ItemDef> items, ContentUnitDefs<ItemDef> items,
ContentUnitDefs<EntityDef> entities,
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs, std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs,
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials
) : indices(std::move(indices)), ) : indices(std::move(indices)),
@ -30,6 +34,7 @@ Content::Content(
blockMaterials(std::move(blockMaterials)), blockMaterials(std::move(blockMaterials)),
blocks(std::move(blocks)), blocks(std::move(blocks)),
items(std::move(items)), items(std::move(items)),
entities(std::move(entities)),
drawGroups(std::move(drawGroups)) drawGroups(std::move(drawGroups))
{} {}

View File

@ -14,12 +14,13 @@ using DrawGroups = std::set<ubyte>;
class Block; class Block;
struct BlockMaterial; struct BlockMaterial;
class ItemDef; struct ItemDef;
struct EntityDef;
class Content; class Content;
class ContentPackRuntime; class ContentPackRuntime;
enum class contenttype { enum class contenttype {
none, block, item none, block, item, entity
}; };
inline const char* contenttype_name(contenttype type) { 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::none: return "none";
case contenttype::block: return "block"; case contenttype::block: return "block";
case contenttype::item: return "item"; case contenttype::item: return "item";
case contenttype::entity: return "entity";
default: default:
return "unknown"; return "unknown";
} }
@ -70,10 +72,12 @@ class ContentIndices {
public: public:
ContentUnitIndices<Block> blocks; ContentUnitIndices<Block> blocks;
ContentUnitIndices<ItemDef> items; ContentUnitIndices<ItemDef> items;
ContentUnitIndices<EntityDef> entities;
ContentIndices( ContentIndices(
std::vector<Block*> blockDefs, ContentUnitIndices<Block> blocks,
std::vector<ItemDef*> itemDefs ContentUnitIndices<ItemDef> items,
ContentUnitIndices<EntityDef> entities
); );
}; };
@ -109,6 +113,7 @@ class Content {
public: public:
ContentUnitDefs<Block> blocks; ContentUnitDefs<Block> blocks;
ContentUnitDefs<ItemDef> items; ContentUnitDefs<ItemDef> items;
ContentUnitDefs<EntityDef> entities;
std::unique_ptr<DrawGroups> const drawGroups; std::unique_ptr<DrawGroups> const drawGroups;
Content( Content(
@ -116,6 +121,7 @@ public:
std::unique_ptr<DrawGroups> drawGroups, std::unique_ptr<DrawGroups> drawGroups,
ContentUnitDefs<Block> blocks, ContentUnitDefs<Block> blocks,
ContentUnitDefs<ItemDef> items, ContentUnitDefs<ItemDef> items,
ContentUnitDefs<EntityDef> entities,
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs, std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs,
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials
); );

View File

@ -6,28 +6,6 @@ void ContentBuilder::add(std::unique_ptr<ContentPackRuntime> pack) {
packs[pack->getId()] = std::move(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<Block>(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<ItemDef>(id);
return *itemDefs[id];
}
BlockMaterial& ContentBuilder::createBlockMaterial(const std::string& id) { BlockMaterial& ContentBuilder::createBlockMaterial(const std::string& id) {
blockMaterials[id] = std::make_unique<BlockMaterial>(); blockMaterials[id] = std::make_unique<BlockMaterial>();
auto& material = *blockMaterials[id]; auto& material = *blockMaterials[id];
@ -35,28 +13,11 @@ BlockMaterial& ContentBuilder::createBlockMaterial(const std::string& id) {
return material; 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<Content> ContentBuilder::build() { std::unique_ptr<Content> ContentBuilder::build() {
std::vector<Block*> blockDefsIndices; std::vector<Block*> blockDefsIndices;
auto groups = std::make_unique<DrawGroups>(); auto groups = std::make_unique<DrawGroups>();
for (const std::string& name : blockIds) { for (const std::string& name : blocks.names) {
Block& def = *blockDefs[name]; Block& def = *blocks.defs[name];
// Generating runtime info // Generating runtime info
def.rt.id = blockDefsIndices.size(); def.rt.id = blockDefsIndices.size();
@ -79,8 +40,8 @@ std::unique_ptr<Content> ContentBuilder::build() {
} }
std::vector<ItemDef*> itemDefsIndices; std::vector<ItemDef*> itemDefsIndices;
for (const std::string& name : itemIds) { for (const std::string& name : items.names) {
ItemDef& def = *itemDefs[name]; ItemDef& def = *items.defs[name];
// Generating runtime info // Generating runtime info
def.rt.id = itemDefsIndices.size(); def.rt.id = itemDefsIndices.size();
@ -88,12 +49,24 @@ std::unique_ptr<Content> ContentBuilder::build() {
itemDefsIndices.push_back(&def); itemDefsIndices.push_back(&def);
} }
std::vector<EntityDef*> 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<Content>( auto content = std::make_unique<Content>(
std::make_unique<ContentIndices>(blockDefsIndices, itemDefsIndices), std::make_unique<ContentIndices>(
std::move(groups), blockDefsIndices,
std::move(blockDefs), itemDefsIndices,
std::move(itemDefs), entityDefsIndices),
std::move(packs), std::move(groups),
blocks.build(),
items.build(),
entities.build(),
std::move(packs),
std::move(blockMaterials) std::move(blockMaterials)
); );

View File

@ -3,6 +3,7 @@
#include "../items/ItemDef.hpp" #include "../items/ItemDef.hpp"
#include "../voxels/Block.hpp" #include "../voxels/Block.hpp"
#include "../objects/EntityDef.hpp"
#include "../content/Content.hpp" #include "../content/Content.hpp"
#include "../content/ContentPack.hpp" #include "../content/ContentPack.hpp"
@ -10,27 +11,58 @@
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
template<class T>
class ContentUnitBuilder {
std::unordered_map<std::string, contenttype>& 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<std::string, std::unique_ptr<T>> defs;
std::vector<std::string> names;
ContentUnitBuilder(
std::unordered_map<std::string, contenttype>& 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<T>(id);
return *defs[id];
}
auto build() {
return std::move(defs);
}
};
class ContentBuilder { class ContentBuilder {
std::unordered_map<std::string, std::unique_ptr<Block>> blockDefs;
std::vector<std::string> blockIds;
std::unordered_map<std::string, std::unique_ptr<ItemDef>> itemDefs;
std::vector<std::string> itemIds;
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials; std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials;
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs; std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs;
std::unordered_map<std::string, contenttype> allNames;
public: public:
ContentUnitBuilder<Block> blocks {allNames, contenttype::block};
ContentUnitBuilder<ItemDef> items {allNames, contenttype::item};
ContentUnitBuilder<EntityDef> entities {allNames, contenttype::entity};
~ContentBuilder(); ~ContentBuilder();
void add(std::unique_ptr<ContentPackRuntime> pack); void add(std::unique_ptr<ContentPackRuntime> pack);
Block& createBlock(const std::string& id);
ItemDef& createItem(const std::string& id);
BlockMaterial& createBlockMaterial(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<Content> build(); std::unique_ptr<Content> build();
}; };

View File

@ -363,14 +363,14 @@ void ContentLoader::load(ContentBuilder& builder) {
auto colon = name.find(':'); auto colon = name.find(':');
std::string full = colon == std::string::npos ? pack->id + ":" + name : name; std::string full = colon == std::string::npos ? pack->id + ":" + name : name;
if (colon != std::string::npos) name[colon] = '/'; if (colon != std::string::npos) name[colon] = '/';
auto& def = builder.createBlock(full); auto& def = builder.blocks.create(full);
if (colon != std::string::npos) { if (colon != std::string::npos) {
def.scriptName = name.substr(0, colon) + '/' + def.scriptName; def.scriptName = name.substr(0, colon) + '/' + def.scriptName;
} }
loadBlock(def, full, name); loadBlock(def, full, name);
stats.totalBlocks++; stats.totalBlocks++;
if (!def.hidden) { if (!def.hidden) {
auto& item = builder.createItem(full+BLOCK_ITEM_SUFFIX); auto& item = builder.items.create(full+BLOCK_ITEM_SUFFIX);
item.generated = true; item.generated = true;
item.caption = def.caption; item.caption = def.caption;
item.iconType = item_icon_type::block; item.iconType = item_icon_type::block;
@ -392,7 +392,7 @@ void ContentLoader::load(ContentBuilder& builder) {
auto colon = name.find(':'); auto colon = name.find(':');
std::string full = colon == std::string::npos ? pack->id + ":" + name : name; std::string full = colon == std::string::npos ? pack->id + ":" + name : name;
if (colon != std::string::npos) name[colon] = '/'; 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; if (colon != std::string::npos) def.scriptName = name.substr(0, colon) + '/' + def.scriptName;
loadItem(def, full, name); loadItem(def, full, name);
stats.totalItems++; stats.totalItems++;

View File

@ -10,7 +10,7 @@ namespace fs = std::filesystem;
class Block; class Block;
struct BlockMaterial; struct BlockMaterial;
class ItemDef; struct ItemDef;
struct ContentPack; struct ContentPack;
class ContentBuilder; class ContentBuilder;

View File

@ -12,7 +12,7 @@
// All in-game definitions (blocks, items, etc..) // All in-game definitions (blocks, items, etc..)
void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) { void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) {
Block& block = builder->createBlock("core:air"); Block& block = builder->blocks.create("core:air");
block.replaceable = true; block.replaceable = true;
block.drawGroup = 1; block.drawGroup = 1;
block.lightPassing = true; block.lightPassing = true;
@ -22,7 +22,7 @@ void corecontent::setup(EnginePaths* paths, ContentBuilder* builder) {
block.model = BlockModel::none; block.model = BlockModel::none;
block.pickingItem = "core:empty"; block.pickingItem = "core:empty";
ItemDef& item = builder->createItem("core:empty"); ItemDef& item = builder->items.create("core:empty");
item.iconType = item_icon_type::none; item.iconType = item_icon_type::none;
auto bindsFile = paths->getResources()/fs::path("bindings.toml"); auto bindsFile = paths->getResources()/fs::path("bindings.toml");

View File

@ -19,8 +19,7 @@ enum class item_icon_type {
block, // block preview: icon is string block id block, // block preview: icon is string block id
}; };
class ItemDef { struct ItemDef {
public:
/// @brief Item string id (with prefix included) /// @brief Item string id (with prefix included)
std::string const name; std::string const name;

View File

@ -22,7 +22,7 @@ class ContentIndices;
class Level; class Level;
class Block; class Block;
class Player; class Player;
class ItemDef; struct ItemDef;
class Inventory; class Inventory;
class UiDocument; class UiDocument;
struct block_funcs_set; struct block_funcs_set;