VoxelEngine/src/content/ContentBuilder.hpp
2024-09-02 09:31:53 +03:00

81 lines
2.2 KiB
C++

#pragma once
#include <memory>
#include <unordered_map>
#include <vector>
#include "Content.hpp"
#include "ContentPack.hpp"
#include "items/ItemDef.hpp"
#include "objects/EntityDef.hpp"
#include "voxels/Block.hpp"
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:
UptrsMap<std::string, 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];
}
// Only fetch existing definition, return null otherwise.
T* get(const std::string& id) {
auto found = defs.find(id);
if (found != defs.end()) {
return &*found->second;
}
return nullptr;
}
auto build() {
return std::move(defs);
}
};
class ContentBuilder {
UptrsMap<std::string, BlockMaterial> blockMaterials;
UptrsMap<std::string, rigging::SkeletonConfig> skeletons;
UptrsMap<std::string, 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};
ResourceIndicesSet resourceIndices {};
~ContentBuilder();
void add(std::unique_ptr<ContentPackRuntime> pack);
void add(std::unique_ptr<rigging::SkeletonConfig> skeleton);
BlockMaterial& createBlockMaterial(const std::string& id);
std::unique_ptr<Content> build();
};