#include "ContentManager.hpp" #include "Common/Abstract.hpp" #include #include #include namespace LV::Server { ContentManager::ContentManager(AssetsManager& am) : AM(am) { } ContentManager::~ContentManager() = default; void ContentManager::registerBase_Node(ResourceId id, const std::string& domain, const std::string& key, const sol::table& profile) { std::optional* basePtr; { size_t entryIndex = id / TableEntry::ChunkSize; size_t entryId = id % TableEntry::ChunkSize; size_t need = entryIndex+1-Profiles_Base_Node.size(); for(size_t iter = 0; iter < need; iter++) { Profiles_Base_Node.emplace_back(std::make_unique>()); } basePtr = &Profiles_Base_Node[entryIndex]->Entries[entryId]; *basePtr = DefNode_Base(); } DefNode_Base& def = **basePtr; { std::optional> parent = profile.get>>("parent"); if(parent) { if(const sol::table* table = std::get_if(&*parent)) { // result = createNodeProfileByLua(*table); } else if(const std::string* key = std::get_if(&*parent)) { auto regResult = TOS::Str::match(*key, "(?:([\\w\\d_]+):)?([\\w\\d_]+)"); if(!regResult) MAKE_ERROR("Недействительный ключ в определении parent"); std::string realKey; if(!regResult->at(1)) { realKey = *key; } else { realKey = "core:" + *regResult->at(2); } DefNodeId parentId; // { // auto& list = Content.ContentKeyToId[(int) EnumDefContent::Node]; // auto iter = list.find(realKey); // if(iter == list.end()) // MAKE_ERROR("Идентификатор parent не найден"); // parentId = iter->second; // } // result = Content.ContentIdToDef_Node.at(parentId); } } } { std::optional nodestate = profile.get>("nodestate"); } { std::optional render = profile.get>("render"); } { std::optional collision = profile.get>("collision"); } { std::optional events = profile.get>("events"); } // result.NodeAdvancementFactory = profile["node_advancement_factory"]; } void ContentManager::registerBase_World(ResourceId id, const std::string& domain, const std::string& key, const sol::table& profile) { std::optional& world = getEntry_World(id); if(!world) world.emplace(); } void ContentManager::registerBase_Entity(ResourceId id, const std::string& domain, const std::string& key, const sol::table& profile) { std::optional& entity = getEntry_Entity(id); if(!entity) entity.emplace(); DefEntity& def = *entity; def.Domain = domain; def.Key = key; } void ContentManager::registerBase(EnumDefContent type, const std::string& domain, const std::string& key, const sol::table& profile) { ResourceId id = getId(type, domain, key); ProfileChanges[static_cast(type)].push_back(id); if(type == EnumDefContent::Node) registerBase_Node(id, domain, key, profile); else if(type == EnumDefContent::World) registerBase_World(id, domain, key, profile); else if(type == EnumDefContent::Entity) registerBase_Entity(id, domain, key, profile); else MAKE_ERROR("Не реализовано"); } void ContentManager::unRegisterBase(EnumDefContent type, const std::string& domain, const std::string& key) { ResourceId id = getId(type, domain, key); ProfileChanges[(int) type].push_back(id); } void ContentManager::registerModifier(EnumDefContent type, const std::string& mod, const std::string& domain, const std::string& key, const sol::table& profile) { ResourceId id = getId(type, domain, key); ProfileChanges[(int) type].push_back(id); } void ContentManager::unRegisterModifier(EnumDefContent type, const std::string& mod, const std::string& domain, const std::string& key) { ResourceId id = getId(type, domain, key); ProfileChanges[(int) type].push_back(id); } // void ContentManager::markAllProfilesDirty(EnumDefContent type) { // const auto &table = this->idToDK()[(int) type]; // size_t counter = 0; // for(const auto& [domain, key] : table) { // ProfileChanges[static_cast(type)].push_back(counter++); // } // } template void ContentManager::buildEndProfilesByType(auto& profiles, auto enumType, auto& base, auto& keys, auto& result, auto& modsTable) { // Расширяем таблицу итоговых профилей до нужного количества if(!keys.empty()) { size_t need = keys.back() / TableEntry::ChunkSize; if(need >= profiles.size()) { profiles.reserve(need); for(size_t iter = 0; iter <= need-profiles.size(); ++iter) profiles.emplace_back(std::make_unique>()); } } TOS::Logger("CM").debug() << "type: " << static_cast(enumType); // Пересчитываем профили for(size_t id : keys) { size_t entryIndex = id / TableEntry::ChunkSize; size_t subIndex = id % TableEntry::ChunkSize; if( entryIndex >= base.size() || !base[entryIndex]->Entries[subIndex] ) { // Базовый профиль не существует profiles[entryIndex]->Entries[subIndex] = std::nullopt; // Уведомляем о потере профиля result.LostProfiles[static_cast(enumType)].push_back(id); } else { // Собираем конечный профиль std::vector> mods_default, *mods = &mods_default; auto iter = modsTable.find(id); if(iter != modsTable.end()) mods = &iter->second; std::optional dk = getDK(enumType, id); assert(dk); TOS::Logger("CM").debug() << "\t" << dk->Domain << ":" << dk->Key << " -> " << id; profiles[entryIndex]->Entries[subIndex] = base[entryIndex]->Entries[subIndex]->compile(AM, *this, dk->Domain, dk->Key, *mods); } } } ContentManager::Out_buildEndProfiles ContentManager::buildEndProfiles() { Out_buildEndProfiles result; for(int type = 0; type < (int) EnumDefContent::MAX_ENUM; type++) { std::shared_lock lock(Profiles_Mtx[type]); auto& keys = ProfileChanges[type]; std::sort(keys.begin(), keys.end()); auto iterErase = std::unique(keys.begin(), keys.end()); keys.erase(iterErase, keys.end()); switch(type) { case 0: buildEndProfilesByType (Profiles_Voxel, EnumDefContent::Voxel, Profiles_Base_Voxel, keys, result, Profiles_Mod_Voxel); break; case 1: buildEndProfilesByType (Profiles_Node, EnumDefContent::Node, Profiles_Base_Node, keys, result, Profiles_Mod_Node); break; case 2: buildEndProfilesByType (Profiles_World, EnumDefContent::World, Profiles_Base_World, keys, result, Profiles_Mod_World); break; case 3: buildEndProfilesByType (Profiles_Portal, EnumDefContent::Portal, Profiles_Base_Portal, keys, result, Profiles_Mod_Portal); break; case 4: buildEndProfilesByType (Profiles_Entity, EnumDefContent::Entity, Profiles_Base_Entity, keys, result, Profiles_Mod_Entity); break; case 5: buildEndProfilesByType (Profiles_Item, EnumDefContent::Item, Profiles_Base_Item, keys, result, Profiles_Mod_Item); break; default: std::unreachable(); } } return result; } ContentManager::Out_getAllProfiles ContentManager::getAllProfiles() { Out_getAllProfiles result; size_t counter; { std::shared_lock lock(Profiles_Mtx[static_cast(EnumDefContent::Voxel)]); result.ProfilesIds_Voxel.reserve(Profiles_Voxel.size()*TableEntry::ChunkSize); counter = 0; for(const auto& entry : Profiles_Voxel) for(const auto& item : entry->Entries) { size_t id = counter++; if(item) result.ProfilesIds_Voxel.push_back(id); } result.ProfilesIds_Voxel.shrink_to_fit(); result.Profiles_Voxel.reserve(result.ProfilesIds_Voxel.size()); for(const auto& entry : Profiles_Voxel) for(const auto& item : entry->Entries) if(item) result.Profiles_Voxel.push_back(&item.value()); } { std::shared_lock lock(Profiles_Mtx[static_cast(EnumDefContent::Node)]); result.ProfilesIds_Node.reserve(Profiles_Node.size()*TableEntry::ChunkSize); counter = 0; for(const auto& entry : Profiles_Node) for(const auto& item : entry->Entries) { size_t id = counter++; if(item) result.ProfilesIds_Node.push_back(id); } result.ProfilesIds_Node.shrink_to_fit(); result.Profiles_Node.reserve(result.ProfilesIds_Node.size()); for(const auto& entry : Profiles_Node) for(const auto& item : entry->Entries) if(item) result.Profiles_Node.push_back(&item.value()); } { std::shared_lock lock(Profiles_Mtx[static_cast(EnumDefContent::World)]); result.ProfilesIds_World.reserve(Profiles_World.size()*TableEntry::ChunkSize); counter = 0; for(const auto& entry : Profiles_World) for(const auto& item : entry->Entries) { size_t id = counter++; if(item) result.ProfilesIds_World.push_back(id); } result.ProfilesIds_World.shrink_to_fit(); result.Profiles_World.reserve(result.ProfilesIds_World.size()); for(const auto& entry : Profiles_World) for(const auto& item : entry->Entries) if(item) result.Profiles_World.push_back(&item.value()); } { std::shared_lock lock(Profiles_Mtx[static_cast(EnumDefContent::Portal)]); result.ProfilesIds_Portal.reserve(Profiles_Portal.size()*TableEntry::ChunkSize); counter = 0; for(const auto& entry : Profiles_Portal) for(const auto& item : entry->Entries) { size_t id = counter++; if(item) result.ProfilesIds_Portal.push_back(id); } result.ProfilesIds_Portal.shrink_to_fit(); result.Profiles_Portal.reserve(result.ProfilesIds_Portal.size()); for(const auto& entry : Profiles_Portal) for(const auto& item : entry->Entries) if(item) result.Profiles_Portal.push_back(&item.value()); } { std::shared_lock lock(Profiles_Mtx[static_cast(EnumDefContent::Entity)]); result.ProfilesIds_Entity.reserve(Profiles_Entity.size()*TableEntry::ChunkSize); counter = 0; for(const auto& entry : Profiles_Entity) for(const auto& item : entry->Entries) { size_t id = counter++; if(item) result.ProfilesIds_Entity.push_back(id); } result.ProfilesIds_Entity.shrink_to_fit(); result.Profiles_Entity.reserve(result.ProfilesIds_Entity.size()); for(const auto& entry : Profiles_Entity) for(const auto& item : entry->Entries) if(item) result.Profiles_Entity.push_back(&item.value()); } { std::shared_lock lock(Profiles_Mtx[static_cast(EnumDefContent::Item)]); result.ProfilesIds_Item.reserve(Profiles_Item.size()*TableEntry::ChunkSize); counter = 0; for(const auto& entry : Profiles_Item) for(const auto& item : entry->Entries) { size_t id = counter++; if(item) result.ProfilesIds_Item.push_back(id); } result.ProfilesIds_Item.shrink_to_fit(); result.Profiles_Item.reserve(result.ProfilesIds_Item.size()); for(const auto& entry : Profiles_Item) for(const auto& item : entry->Entries) if(item) result.Profiles_Item.push_back(&item.value()); } result.IdToDK = idToDK(); return result; } }