Синхронизация профилей контента
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
#include "ContentManager.hpp"
|
||||
#include "Common/Abstract.hpp"
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
namespace LV::Server {
|
||||
|
||||
@@ -12,13 +14,22 @@ ContentManager::ContentManager(AssetsManager& am)
|
||||
ContentManager::~ContentManager() = default;
|
||||
|
||||
void ContentManager::registerBase_Node(ResourceId id, const std::string& domain, const std::string& key, const sol::table& profile) {
|
||||
std::optional<DefNode>& node = getEntry_Node(id);
|
||||
if(!node)
|
||||
node.emplace();
|
||||
std::optional<DefNode_Base>* basePtr;
|
||||
|
||||
DefNode& def = *node;
|
||||
def.Domain = domain;
|
||||
def.Key = key;
|
||||
{
|
||||
size_t entryIndex = id / TableEntry<DefNode_Base>::ChunkSize;
|
||||
size_t entryId = id % TableEntry<DefNode_Base>::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<TableEntry<DefNode_Base>>());
|
||||
}
|
||||
|
||||
basePtr = &Profiles_Base_Node[entryIndex]->Entries[entryId];
|
||||
*basePtr = DefNode_Base();
|
||||
}
|
||||
|
||||
DefNode_Base& def = **basePtr;
|
||||
|
||||
{
|
||||
std::optional<std::variant<std::string, sol::table>> parent = profile.get<std::optional<std::variant<std::string, sol::table>>>("parent");
|
||||
@@ -92,7 +103,7 @@ void ContentManager::registerBase_Entity(ResourceId id, const std::string& domai
|
||||
void ContentManager::registerBase(EnumDefContent type, const std::string& domain, const std::string& key, const sol::table& profile)
|
||||
{
|
||||
ResourceId id = getId(type, domain, key);
|
||||
ProfileChanges[(int) type].push_back(id);
|
||||
ProfileChanges[static_cast<size_t>(type)].push_back(id);
|
||||
|
||||
if(type == EnumDefContent::Node)
|
||||
registerBase_Node(id, domain, key, profile);
|
||||
@@ -122,11 +133,54 @@ void ContentManager::unRegisterModifier(EnumDefContent type, const std::string&
|
||||
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<size_t>(type)].push_back(counter++);
|
||||
// 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<size_t>(type)].push_back(counter++);
|
||||
// }
|
||||
// }
|
||||
|
||||
template<class type, class modType>
|
||||
void ContentManager::buildEndProfilesByType(auto& profiles, auto enumType, auto& base, auto& keys, auto& result, auto& modsTable) {
|
||||
// Расширяем таблицу итоговых профилей до нужного количества
|
||||
if(!keys.empty()) {
|
||||
size_t need = keys.back() / TableEntry<type>::ChunkSize;
|
||||
if(need >= profiles.size()) {
|
||||
profiles.reserve(need);
|
||||
|
||||
for(size_t iter = 0; iter <= need-profiles.size(); ++iter)
|
||||
profiles.emplace_back(std::make_unique<TableEntry<type>>());
|
||||
}
|
||||
}
|
||||
|
||||
TOS::Logger("CM").debug() << "type: " << static_cast<size_t>(enumType);
|
||||
|
||||
// Пересчитываем профили
|
||||
for(size_t id : keys) {
|
||||
size_t entryIndex = id / TableEntry<type>::ChunkSize;
|
||||
size_t subIndex = id % TableEntry<type>::ChunkSize;
|
||||
|
||||
if(
|
||||
entryIndex >= base.size()
|
||||
|| !base[entryIndex]->Entries[subIndex]
|
||||
) {
|
||||
// Базовый профиль не существует
|
||||
profiles[entryIndex]->Entries[subIndex] = std::nullopt;
|
||||
// Уведомляем о потере профиля
|
||||
result.LostProfiles[static_cast<size_t>(enumType)].push_back(id);
|
||||
} else {
|
||||
// Собираем конечный профиль
|
||||
std::vector<std::tuple<std::string, modType>> mods_default, *mods = &mods_default;
|
||||
auto iter = modsTable.find(id);
|
||||
if(iter != modsTable.end())
|
||||
mods = &iter->second;
|
||||
|
||||
std::optional<BindDomainKeyInfo> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,15 +188,148 @@ 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<DefVoxel, DefVoxel_Mod> (Profiles_Voxel, EnumDefContent::Voxel, Profiles_Base_Voxel, keys, result, Profiles_Mod_Voxel); break;
|
||||
case 1: buildEndProfilesByType<DefNode, DefNode_Mod> (Profiles_Node, EnumDefContent::Node, Profiles_Base_Node, keys, result, Profiles_Mod_Node); break;
|
||||
case 2: buildEndProfilesByType<DefWorld, DefWorld_Mod> (Profiles_World, EnumDefContent::World, Profiles_Base_World, keys, result, Profiles_Mod_World); break;
|
||||
case 3: buildEndProfilesByType<DefPortal, DefPortal_Mod> (Profiles_Portal, EnumDefContent::Portal, Profiles_Base_Portal, keys, result, Profiles_Mod_Portal); break;
|
||||
case 4: buildEndProfilesByType<DefEntity, DefEntity_Mod> (Profiles_Entity, EnumDefContent::Entity, Profiles_Base_Entity, keys, result, Profiles_Mod_Entity); break;
|
||||
case 5: buildEndProfilesByType<DefItem, DefItem_Mod> (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<size_t>(EnumDefContent::Voxel)]);
|
||||
result.ProfilesIds_Voxel.reserve(Profiles_Voxel.size()*TableEntry<DefVoxel>::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<size_t>(EnumDefContent::Node)]);
|
||||
result.ProfilesIds_Node.reserve(Profiles_Node.size()*TableEntry<DefNode>::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<size_t>(EnumDefContent::World)]);
|
||||
result.ProfilesIds_World.reserve(Profiles_World.size()*TableEntry<DefWorld>::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<size_t>(EnumDefContent::Portal)]);
|
||||
result.ProfilesIds_Portal.reserve(Profiles_Portal.size()*TableEntry<DefPortal>::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<size_t>(EnumDefContent::Entity)]);
|
||||
result.ProfilesIds_Entity.reserve(Profiles_Entity.size()*TableEntry<DefEntity>::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<size_t>(EnumDefContent::Item)]);
|
||||
result.ProfilesIds_Item.reserve(Profiles_Item.size()*TableEntry<DefItem>::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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user