Синхронизация профилей контента

This commit is contained in:
2026-01-17 18:59:36 +03:00
parent affdc75ebd
commit 3fb06080db
14 changed files with 1120 additions and 367 deletions

View File

@@ -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;
}
}