refactor Content
This commit is contained in:
+9
-41
@@ -12,62 +12,30 @@
|
||||
#include "../logic/scripting/scripting.hpp"
|
||||
|
||||
ContentIndices::ContentIndices(
|
||||
std::vector<Block*> blockDefs,
|
||||
std::vector<ItemDef*> itemDefs
|
||||
) : blockDefs(std::move(blockDefs)),
|
||||
itemDefs(std::move(itemDefs))
|
||||
std::vector<Block*> blocks,
|
||||
std::vector<ItemDef*> items
|
||||
) : blocks(std::move(blocks)),
|
||||
items(std::move(items))
|
||||
{}
|
||||
|
||||
Content::Content(
|
||||
std::unique_ptr<ContentIndices> indices,
|
||||
std::unique_ptr<DrawGroups> drawGroups,
|
||||
std::unordered_map<std::string, std::unique_ptr<Block>> blockDefs,
|
||||
std::unordered_map<std::string, std::unique_ptr<ItemDef>> itemDefs,
|
||||
ContentUnitDefs<Block> blocks,
|
||||
ContentUnitDefs<ItemDef> items,
|
||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs,
|
||||
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials
|
||||
) : blockDefs(std::move(blockDefs)),
|
||||
itemDefs(std::move(itemDefs)),
|
||||
indices(std::move(indices)),
|
||||
) : indices(std::move(indices)),
|
||||
packs(std::move(packs)),
|
||||
blockMaterials(std::move(blockMaterials)),
|
||||
blocks(std::move(blocks)),
|
||||
items(std::move(items)),
|
||||
drawGroups(std::move(drawGroups))
|
||||
{}
|
||||
|
||||
Content::~Content() {
|
||||
}
|
||||
|
||||
Block* Content::findBlock(const std::string& id) const {
|
||||
auto found = blockDefs.find(id);
|
||||
if (found == blockDefs.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
Block& Content::requireBlock(const std::string& id) const {
|
||||
auto found = blockDefs.find(id);
|
||||
if (found == blockDefs.end()) {
|
||||
throw std::runtime_error("missing block "+id);
|
||||
}
|
||||
return *found->second;
|
||||
}
|
||||
|
||||
ItemDef* Content::findItem(const std::string& id) const {
|
||||
auto found = itemDefs.find(id);
|
||||
if (found == itemDefs.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
ItemDef& Content::requireItem(const std::string& id) const {
|
||||
auto found = itemDefs.find(id);
|
||||
if (found == itemDefs.end()) {
|
||||
throw std::runtime_error("missing item "+id);
|
||||
}
|
||||
return *found->second;
|
||||
}
|
||||
|
||||
const BlockMaterial* Content::findBlockMaterial(const std::string& id) const {
|
||||
auto found = blockMaterials.find(id);
|
||||
if (found == blockMaterials.end()) {
|
||||
|
||||
+50
-39
@@ -43,61 +43,79 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class ContentUnitIndices {
|
||||
std::vector<T*> defs;
|
||||
public:
|
||||
ContentUnitIndices(std::vector<T*> defs) : defs(std::move(defs)) {}
|
||||
|
||||
inline T* get(blockid_t id) const {
|
||||
if (id >= defs.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return defs[id];
|
||||
}
|
||||
|
||||
inline size_t count() const {
|
||||
return defs.size();
|
||||
}
|
||||
|
||||
inline const T* const* getDefs() const {
|
||||
return defs.data();
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Runtime defs cache: indices
|
||||
class ContentIndices {
|
||||
std::vector<Block*> blockDefs;
|
||||
std::vector<ItemDef*> itemDefs;
|
||||
public:
|
||||
ContentUnitIndices<Block> blocks;
|
||||
ContentUnitIndices<ItemDef> items;
|
||||
|
||||
ContentIndices(
|
||||
std::vector<Block*> blockDefs,
|
||||
std::vector<ItemDef*> itemDefs
|
||||
);
|
||||
};
|
||||
|
||||
inline Block* getBlockDef(blockid_t id) const {
|
||||
if (id >= blockDefs.size())
|
||||
template<class T>
|
||||
class ContentUnitDefs {
|
||||
std::unordered_map<std::string, std::unique_ptr<T>> defs;
|
||||
public:
|
||||
ContentUnitDefs(std::unordered_map<std::string, std::unique_ptr<T>> defs)
|
||||
: defs(std::move(defs)) {
|
||||
}
|
||||
|
||||
T* find(const std::string& id) const {
|
||||
const auto& found = defs.find(id);
|
||||
if (found == defs.end()) {
|
||||
return nullptr;
|
||||
return blockDefs[id];
|
||||
}
|
||||
return found->second.get();
|
||||
}
|
||||
|
||||
inline ItemDef* getItemDef(itemid_t id) const {
|
||||
if (id >= itemDefs.size())
|
||||
return nullptr;
|
||||
return itemDefs[id];
|
||||
}
|
||||
|
||||
inline size_t countBlockDefs() const {
|
||||
return blockDefs.size();
|
||||
}
|
||||
|
||||
inline size_t countItemDefs() const {
|
||||
return itemDefs.size();
|
||||
}
|
||||
|
||||
// use this for critical spots to prevent range check overhead
|
||||
const Block* const* getBlockDefs() const {
|
||||
return blockDefs.data();
|
||||
}
|
||||
|
||||
const ItemDef* const* getItemDefs() const {
|
||||
return itemDefs.data();
|
||||
T& require(const std::string& id) const {
|
||||
const auto& found = defs.find(id);
|
||||
if (found == defs.end()) {
|
||||
throw std::runtime_error("missing content unit "+id);
|
||||
}
|
||||
return *found->second;
|
||||
}
|
||||
};
|
||||
|
||||
/* Content is a definitions repository */
|
||||
/// @brief Content is a definitions repository
|
||||
class Content {
|
||||
std::unordered_map<std::string, std::unique_ptr<Block>> blockDefs;
|
||||
std::unordered_map<std::string, std::unique_ptr<ItemDef>> itemDefs;
|
||||
std::unique_ptr<ContentIndices> indices;
|
||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs;
|
||||
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials;
|
||||
public:
|
||||
ContentUnitDefs<Block> blocks;
|
||||
ContentUnitDefs<ItemDef> items;
|
||||
std::unique_ptr<DrawGroups> const drawGroups;
|
||||
|
||||
Content(
|
||||
std::unique_ptr<ContentIndices> indices,
|
||||
std::unique_ptr<DrawGroups> drawGroups,
|
||||
std::unordered_map<std::string, std::unique_ptr<Block>> blockDefs,
|
||||
std::unordered_map<std::string, std::unique_ptr<ItemDef>> itemDefs,
|
||||
ContentUnitDefs<Block> blocks,
|
||||
ContentUnitDefs<ItemDef> items,
|
||||
std::unordered_map<std::string, std::unique_ptr<ContentPackRuntime>> packs,
|
||||
std::unordered_map<std::string, std::unique_ptr<BlockMaterial>> blockMaterials
|
||||
);
|
||||
@@ -106,15 +124,8 @@ public:
|
||||
inline ContentIndices* getIndices() const {
|
||||
return indices.get();
|
||||
}
|
||||
|
||||
Block* findBlock(const std::string& id) const;
|
||||
Block& requireBlock(const std::string& id) const;
|
||||
|
||||
ItemDef* findItem(const std::string& id) const;
|
||||
ItemDef& requireItem(const std::string& id) const;
|
||||
|
||||
const BlockMaterial* findBlockMaterial(const std::string& id) const;
|
||||
|
||||
const ContentPackRuntime* getPackRuntime(const std::string& id) const;
|
||||
|
||||
const std::unordered_map<std::string, std::unique_ptr<BlockMaterial>>& getBlockMaterials() const;
|
||||
|
||||
@@ -99,11 +99,11 @@ std::unique_ptr<Content> ContentBuilder::build() {
|
||||
|
||||
// Now, it's time to resolve foreign keys
|
||||
for (Block* def : blockDefsIndices) {
|
||||
def->rt.pickingItem = content->requireItem(def->pickingItem).rt.id;
|
||||
def->rt.pickingItem = content->items.require(def->pickingItem).rt.id;
|
||||
}
|
||||
|
||||
for (ItemDef* def : itemDefsIndices) {
|
||||
def->rt.placingBlock = content->requireBlock(def->placingBlock).rt.id;
|
||||
def->rt.placingBlock = content->blocks.require(def->placingBlock).rt.id;
|
||||
}
|
||||
|
||||
return content;
|
||||
|
||||
+37
-46
@@ -10,29 +10,45 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
template<typename I, class T>
|
||||
static void init(std::vector<I>& ids, std::vector<std::string>& names,
|
||||
const ContentUnitIndices<T>& indices, size_t count) {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
ids.push_back(i);
|
||||
}
|
||||
for (size_t i = 0; i < indices.count(); i++) {
|
||||
names.push_back(indices.get(i)->name);
|
||||
}
|
||||
for (size_t i = indices.count(); i < count; i++) {
|
||||
names.emplace_back("");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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.emplace_back("");
|
||||
}
|
||||
init(blocks, blockNames, indices->blocks, blocksCount);
|
||||
init(items, itemNames, indices->items, itemsCount);
|
||||
}
|
||||
|
||||
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.emplace_back();
|
||||
template<class T>
|
||||
static void setup_lut(ContentLUT* lut, const ContentUnitDefs<T>& defs, dynamic::List* list) {
|
||||
if (list) {
|
||||
for (size_t i = 0; i < list->size(); i++) {
|
||||
std::string name = list->str(i);
|
||||
if (auto def = defs.find(name)) {
|
||||
lut->setBlock(i, name, def->rt.id);
|
||||
} else {
|
||||
lut->setBlock(i, name, BLOCK_VOID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class T> static constexpr size_t get_entries_count(
|
||||
const ContentUnitIndices<T>& indices, dynamic::List* list) {
|
||||
return list ? std::max(list->size(), indices.count()) : indices.count();
|
||||
}
|
||||
|
||||
std::shared_ptr<ContentLUT> ContentLUT::create(
|
||||
const fs::path& filename,
|
||||
const Content* content
|
||||
@@ -42,38 +58,13 @@ std::shared_ptr<ContentLUT> ContentLUT::create(
|
||||
auto itemlist = root->list("items");
|
||||
|
||||
auto* indices = content->getIndices();
|
||||
size_t blocks_c = blocklist
|
||||
? std::max(blocklist->size(), indices->countBlockDefs())
|
||||
: indices->countBlockDefs();
|
||||
size_t items_c = itemlist
|
||||
? std::max(itemlist->size(), indices->countItemDefs())
|
||||
: indices->countItemDefs();
|
||||
size_t blocks_c = get_entries_count(indices->blocks, blocklist);
|
||||
size_t items_c = get_entries_count(indices->items, itemlist);
|
||||
|
||||
auto lut = std::make_shared<ContentLUT>(content, blocks_c, items_c);
|
||||
|
||||
if (blocklist) {
|
||||
for (size_t i = 0; i < blocklist->size(); i++) {
|
||||
std::string name = blocklist->str(i);
|
||||
Block* def = content->findBlock(name);
|
||||
if (def) {
|
||||
lut->setBlock(i, name, def->rt.id);
|
||||
} else {
|
||||
lut->setBlock(i, name, BLOCK_VOID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
setup_lut(lut.get(), content->blocks, blocklist);
|
||||
setup_lut(lut.get(), content->items, itemlist);
|
||||
|
||||
if (lut->hasContentReorder() || lut->hasMissingContent()) {
|
||||
return lut;
|
||||
|
||||
Reference in New Issue
Block a user