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 "../items/ItemDef.hpp"
#include "../objects/EntityDef.hpp"
#include "ContentPack.hpp"
#include "../logic/scripting/scripting.hpp"
ContentIndices::ContentIndices(
std::vector<Block*> blocks,
std::vector<ItemDef*> items
ContentUnitIndices<Block> blocks,
ContentUnitIndices<ItemDef> items,
ContentUnitIndices<EntityDef> 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> drawGroups,
ContentUnitDefs<Block> blocks,
ContentUnitDefs<ItemDef> items,
ContentUnitDefs<EntityDef> entities,
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs,
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> 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))
{}

View File

@ -14,12 +14,13 @@ using DrawGroups = std::set<ubyte>;
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<Block> blocks;
ContentUnitIndices<ItemDef> items;
ContentUnitIndices<EntityDef> entities;
ContentIndices(
std::vector<Block*> blockDefs,
std::vector<ItemDef*> itemDefs
ContentUnitIndices<Block> blocks,
ContentUnitIndices<ItemDef> items,
ContentUnitIndices<EntityDef> entities
);
};
@ -109,6 +113,7 @@ class Content {
public:
ContentUnitDefs<Block> blocks;
ContentUnitDefs<ItemDef> items;
ContentUnitDefs<EntityDef> entities;
std::unique_ptr<DrawGroups> const drawGroups;
Content(
@ -116,6 +121,7 @@ public:
std::unique_ptr<DrawGroups> drawGroups,
ContentUnitDefs<Block> blocks,
ContentUnitDefs<ItemDef> items,
ContentUnitDefs<EntityDef> entities,
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs,
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);
}
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) {
blockMaterials[id] = std::make_unique<BlockMaterial>();
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<Content> ContentBuilder::build() {
std::vector<Block*> blockDefsIndices;
auto groups = std::make_unique<DrawGroups>();
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<Content> ContentBuilder::build() {
}
std::vector<ItemDef*> 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<Content> ContentBuilder::build() {
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>(
std::make_unique<ContentIndices>(blockDefsIndices, itemDefsIndices),
std::move(groups),
std::move(blockDefs),
std::move(itemDefs),
std::move(packs),
std::make_unique<ContentIndices>(
blockDefsIndices,
itemDefsIndices,
entityDefsIndices),
std::move(groups),
blocks.build(),
items.build(),
entities.build(),
std::move(packs),
std::move(blockMaterials)
);

View File

@ -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 <vector>
#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 {
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<ContentPackRuntime>> packs;
std::unordered_map<std::string, contenttype> allNames;
public:
ContentUnitBuilder<Block> blocks {allNames, contenttype::block};
ContentUnitBuilder<ItemDef> items {allNames, contenttype::item};
ContentUnitBuilder<EntityDef> entities {allNames, contenttype::entity};
~ContentBuilder();
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);
void checkIdentifier(const std::string& id);
contenttype checkContentType(const std::string& id);
std::unique_ptr<Content> build();
};

View File

@ -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++;

View File

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

View File

@ -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");

View File

@ -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;

View File

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