#pragma once #include #include #include #include #include #include #include #include "content_fwd.hpp" #include "data/dv.hpp" using DrawGroups = std::set; template using UptrsMap = std::unordered_map>; class Block; struct BlockMaterial; struct ItemDef; struct EntityDef; struct GeneratorDef; namespace rigging { class SkeletonConfig; } constexpr const char* ContentType_name(ContentType type) { switch (type) { case ContentType::NONE: return "none"; case ContentType::BLOCK: return "block"; case ContentType::ITEM: return "item"; case ContentType::ENTITY: return "entity"; case ContentType::GENERATOR: return "generator"; default: return "unknown"; } } class namereuse_error : public std::runtime_error { ContentType type; public: namereuse_error(const std::string& msg, ContentType type) : std::runtime_error(msg), type(type) { } inline ContentType getType() const { return type; } }; template class ContentUnitIndices { std::vector defs; public: ContentUnitIndices(std::vector defs) : defs(std::move(defs)) { } inline const T* get(blockid_t id) const { if (id >= defs.size()) { return nullptr; } return defs[id]; } inline const T& require(blockid_t id) const { return *defs.at(id); } inline size_t count() const { return defs.size(); } inline const auto& getIterable() const { return defs; } inline const T* const* getDefs() const { return defs.data(); } }; /// @brief Runtime defs cache: indices class ContentIndices { public: ContentUnitIndices blocks; ContentUnitIndices items; ContentUnitIndices entities; ContentIndices( ContentUnitIndices blocks, ContentUnitIndices items, ContentUnitIndices entities ); }; template class ContentUnitDefs { UptrsMap defs; public: ContentUnitDefs(UptrsMap defs) : defs(std::move(defs)) { } const T* find(const std::string& id) const { const auto& found = defs.find(id); if (found == defs.end()) { return nullptr; } return found->second.get(); } const 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; } const auto& getDefs() const { return defs; } }; class ResourceIndices { std::vector names; std::unordered_map indices; std::unique_ptr> savedData; public: ResourceIndices() : savedData(std::make_unique>()) { } static constexpr size_t MISSING = SIZE_MAX; void add(const std::string& name, dv::value map) { indices[name] = names.size(); names.push_back(name); savedData->push_back(std::move(map)); } void addAlias(const std::string& name, const std::string& alias) { size_t index = indexOf(name); if (index == MISSING) { throw std::runtime_error( "resource does not exists: "+name); } indices[alias] = index; } const std::string& getName(size_t index) const { return names.at(index); } size_t indexOf(const std::string& name) const { const auto& found = indices.find(name); if (found != indices.end()) { return found->second; } return MISSING; } const dv::value& getSavedData(size_t index) const { return savedData->at(index); } void saveData(size_t index, dv::value map) const { savedData->at(index) = std::move(map); } size_t size() const { return names.size(); } }; constexpr const char* to_string(ResourceType type) { switch (type) { case ResourceType::CAMERA: return "camera"; default: return "unknown"; } } inline std::optional ResourceType_from(std::string_view str) { if (str == "camera") { return ResourceType::CAMERA; } return std::nullopt; } using ResourceIndicesSet = ResourceIndices[RESOURCE_TYPES_COUNT]; /// @brief Content is a definitions repository class Content { std::unique_ptr indices; UptrsMap packs; UptrsMap blockMaterials; UptrsMap skeletons; public: ContentUnitDefs blocks; ContentUnitDefs items; ContentUnitDefs entities; ContentUnitDefs generators; std::unique_ptr const drawGroups; ResourceIndicesSet resourceIndices {}; Content( std::unique_ptr indices, std::unique_ptr drawGroups, ContentUnitDefs blocks, ContentUnitDefs items, ContentUnitDefs entities, ContentUnitDefs generators, UptrsMap packs, UptrsMap blockMaterials, UptrsMap skeletons, ResourceIndicesSet resourceIndices ); ~Content(); inline ContentIndices* getIndices() const { return indices.get(); } inline const ResourceIndices& getIndices(ResourceType type) const { return resourceIndices[static_cast(type)]; } const rigging::SkeletonConfig* getSkeleton(const std::string& id) const; const BlockMaterial* findBlockMaterial(const std::string& id) const; const ContentPackRuntime* getPackRuntime(const std::string& id) const; const UptrsMap& getBlockMaterials() const; const UptrsMap& getPacks() const; const UptrsMap& getSkeletons() const; };