Синхронизация профилей контента
This commit is contained in:
@@ -46,6 +46,28 @@ public:
|
||||
Out_applyResourcesUpdate applyResourcesUpdate(Out_checkAndPrepareResourcesUpdate& orr) {
|
||||
Out_applyResourcesUpdate result = AssetsPreloader::applyResourcesUpdate(orr);
|
||||
|
||||
{
|
||||
static TOS::Logger LOG = "Server>AssetsManager";
|
||||
|
||||
for(size_t type = 0; type < static_cast<size_t>(EnumAssets::MAX_ENUM); ++type) {
|
||||
if(result.NewOrUpdates[type].empty())
|
||||
continue;
|
||||
|
||||
EnumAssets typeEnum = static_cast<EnumAssets>(type);
|
||||
const char* typeName = ::EnumAssetsToDirectory(typeEnum);
|
||||
|
||||
for(const auto& bind : result.NewOrUpdates[type]) {
|
||||
auto dk = getDK(typeEnum, bind.Id);
|
||||
if(!dk)
|
||||
continue;
|
||||
|
||||
LOG.debug()
|
||||
<< typeName << ": "
|
||||
<< dk->Domain << '+' << dk->Key << " -> " << bind.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(auto& [hash, data] : orr.NewHeadless) {
|
||||
Resources.emplace(hash, ResourceHashData{0, std::make_shared<std::u8string>(std::move(data))});
|
||||
}
|
||||
@@ -104,4 +126,4 @@ private:
|
||||
> Resources;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,20 +3,62 @@
|
||||
#include "Common/Abstract.hpp"
|
||||
#include "AssetsManager.hpp"
|
||||
#include "Common/IdProvider.hpp"
|
||||
#include "Common/Net.hpp"
|
||||
#include "TOSLib.hpp"
|
||||
#include <array>
|
||||
#include <mutex>
|
||||
#include <sol/table.hpp>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
namespace LV::Server {
|
||||
|
||||
struct DefVoxel_Base { };
|
||||
struct DefNode_Base { };
|
||||
struct DefWorld_Base { };
|
||||
struct DefPortal_Base { };
|
||||
struct DefEntity_Base { };
|
||||
struct DefItem_Base { };
|
||||
struct ResourceBase {
|
||||
std::string Domain, Key;
|
||||
};
|
||||
|
||||
class ContentManager;
|
||||
|
||||
struct DefVoxel : public ResourceBase {
|
||||
std::u8string dumpToClient() const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
struct DefNode : public ResourceBase {
|
||||
AssetsNodestate NodestateId;
|
||||
|
||||
std::u8string dumpToClient() const {
|
||||
auto wr = TOS::ByteBuffer::Writer();
|
||||
wr << uint32_t(NodestateId);
|
||||
auto buff = wr.complite();
|
||||
return (std::u8string) std::u8string_view((const char8_t*) buff.data(), buff.size());
|
||||
}
|
||||
};
|
||||
struct DefWorld : public ResourceBase {
|
||||
std::u8string dumpToClient() const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
struct DefPortal : public ResourceBase {
|
||||
std::u8string dumpToClient() const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
struct DefEntity : public ResourceBase {
|
||||
std::u8string dumpToClient() const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
struct DefItem : public ResourceBase {
|
||||
std::u8string dumpToClient() const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
struct DefVoxel_Mod { };
|
||||
struct DefNode_Mod { };
|
||||
@@ -25,20 +67,57 @@ struct DefPortal_Mod { };
|
||||
struct DefEntity_Mod { };
|
||||
struct DefItem_Mod { };
|
||||
|
||||
struct ResourceBase {
|
||||
std::string Domain, Key;
|
||||
struct DefVoxel_Base {
|
||||
private:
|
||||
friend ContentManager;
|
||||
DefVoxel compile(AssetsManager& am, ContentManager& cm, const std::string_view domain, const std::string_view key, const std::vector<std::tuple<std::string, DefVoxel_Mod>>& mods) const {
|
||||
return DefVoxel();
|
||||
}
|
||||
};
|
||||
|
||||
struct DefVoxel : public ResourceBase { };
|
||||
struct DefNode : public ResourceBase {
|
||||
AssetsNodestate NodestateId;
|
||||
std::vector<AssetsModel> ModelDeps;
|
||||
std::vector<AssetsTexture> TextureDeps;
|
||||
struct DefNode_Base {
|
||||
private:
|
||||
friend ContentManager;
|
||||
DefNode compile(AssetsManager& am, ContentManager& cm, const std::string_view domain, const std::string_view key, const std::vector<std::tuple<std::string, DefNode_Mod>>& mods) const {
|
||||
DefNode profile;
|
||||
std::string jsonKey = std::string(key)+".json";
|
||||
profile.NodestateId = am.getId(EnumAssets::Nodestate, domain, jsonKey);
|
||||
TOS::Logger("Compile").info() << domain << ' ' << key << " -> " << profile.NodestateId;
|
||||
return profile;
|
||||
}
|
||||
};
|
||||
|
||||
struct DefWorld_Base {
|
||||
private:
|
||||
friend ContentManager;
|
||||
DefWorld compile(AssetsManager& am, ContentManager& cm, const std::string_view domain, const std::string_view key, const std::vector<std::tuple<std::string, DefWorld_Mod>>& mods) const {
|
||||
return DefWorld();
|
||||
}
|
||||
};
|
||||
|
||||
struct DefPortal_Base {
|
||||
private:
|
||||
friend ContentManager;
|
||||
DefPortal compile(AssetsManager& am, ContentManager& cm, const std::string_view domain, const std::string_view key, const std::vector<std::tuple<std::string, DefPortal_Mod>>& mods) const {
|
||||
return DefPortal();
|
||||
}
|
||||
};
|
||||
|
||||
struct DefEntity_Base {
|
||||
private:
|
||||
friend ContentManager;
|
||||
DefEntity compile(AssetsManager& am, ContentManager& cm, const std::string_view domain, const std::string_view key, const std::vector<std::tuple<std::string, DefEntity_Mod>>& mods) const {
|
||||
return DefEntity();
|
||||
}
|
||||
};
|
||||
|
||||
struct DefItem_Base {
|
||||
private:
|
||||
friend ContentManager;
|
||||
DefItem compile(AssetsManager& am, ContentManager& cm, const std::string_view domain, const std::string_view key, const std::vector<std::tuple<std::string, DefItem_Mod>>& mods) const {
|
||||
return DefItem();
|
||||
}
|
||||
};
|
||||
struct DefWorld : public ResourceBase { };
|
||||
struct DefPortal : public ResourceBase { };
|
||||
struct DefEntity : public ResourceBase { };
|
||||
struct DefItem : public ResourceBase { };
|
||||
|
||||
/*
|
||||
DK to id
|
||||
@@ -114,7 +193,7 @@ public:
|
||||
MAX_ENUM
|
||||
> DKToId;
|
||||
|
||||
std::unordered_map<DefVoxelId, std::optional<DefItem>*> Profiles_Voxel;
|
||||
std::unordered_map<DefVoxelId, std::optional<DefVoxel>*> Profiles_Voxel;
|
||||
std::unordered_map<DefNodeId, std::optional<DefNode>*> Profiles_Node;
|
||||
std::unordered_map<DefWorldId, std::optional<DefWorld>*> Profiles_World;
|
||||
std::unordered_map<DefPortalId, std::optional<DefPortal>*> Profiles_Portal;
|
||||
@@ -133,15 +212,76 @@ public:
|
||||
void registerModifier(EnumDefContent type, const std::string& mod, const std::string& domain, const std::string& key, const sol::table& profile);
|
||||
void unRegisterModifier(EnumDefContent type, const std::string& mod, const std::string& domain, const std::string& key);
|
||||
// Пометить все профили типа как изменённые (например, после перезагрузки ассетов)
|
||||
void markAllProfilesDirty(EnumDefContent type);
|
||||
// void markAllProfilesDirty(EnumDefContent type);
|
||||
// Список всех зарегистрированных профилей выбранного типа
|
||||
std::vector<ResourceId> collectProfileIds(EnumDefContent type) const;
|
||||
// Компилирует изменённые профили
|
||||
struct Out_buildEndProfiles {
|
||||
std::vector<ResourceId> ChangedProfiles[MAX_ENUM];
|
||||
std::vector<
|
||||
std::tuple<DefVoxelId, const DefVoxel*>
|
||||
> ChangedProfiles_Voxel;
|
||||
|
||||
std::vector<
|
||||
std::tuple<DefNodeId, const DefNode*>
|
||||
> ChangedProfiles_Node;
|
||||
|
||||
std::vector<
|
||||
std::tuple<DefWorldId, const DefWorld*>
|
||||
> ChangedProfiles_World;
|
||||
|
||||
std::vector<
|
||||
std::tuple<DefPortalId, const DefPortal*>
|
||||
> ChangedProfiles_Portal;
|
||||
|
||||
std::vector<
|
||||
std::tuple<DefEntityId, const DefEntity*>
|
||||
> ChangedProfiles_Entity;
|
||||
|
||||
std::vector<
|
||||
std::tuple<DefItemId, const DefItem*>
|
||||
> ChangedProfiles_Item;
|
||||
|
||||
std::array<
|
||||
std::vector<ResourceId>,
|
||||
MAX_ENUM
|
||||
> LostProfiles;
|
||||
|
||||
std::array<
|
||||
std::vector<BindDomainKeyInfo>,
|
||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
||||
> IdToDK;
|
||||
};
|
||||
|
||||
// Компилирует конечные профили по базе и модификаторам (предоставляет клиентам изменённые и потерянные)
|
||||
Out_buildEndProfiles buildEndProfiles();
|
||||
|
||||
struct Out_getAllProfiles {
|
||||
std::vector<DefVoxelId> ProfilesIds_Voxel;
|
||||
std::vector<const DefVoxel*> Profiles_Voxel;
|
||||
|
||||
std::vector<DefNodeId> ProfilesIds_Node;
|
||||
std::vector<const DefNode*> Profiles_Node;
|
||||
|
||||
std::vector<DefWorldId> ProfilesIds_World;
|
||||
std::vector<const DefWorld*> Profiles_World;
|
||||
|
||||
std::vector<DefPortalId> ProfilesIds_Portal;
|
||||
std::vector<const DefPortal*> Profiles_Portal;
|
||||
|
||||
std::vector<DefEntityId> ProfilesIds_Entity;
|
||||
std::vector<const DefEntity*> Profiles_Entity;
|
||||
|
||||
std::vector<DefItemId> ProfilesIds_Item;
|
||||
std::vector<const DefItem*> Profiles_Item;
|
||||
|
||||
std::array<
|
||||
std::vector<BindDomainKeyInfo>,
|
||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
||||
> IdToDK;
|
||||
};
|
||||
|
||||
// Выдаёт все профили (для новых клиентов)
|
||||
Out_getAllProfiles getAllProfiles();
|
||||
|
||||
|
||||
std::optional<DefVoxel>& getEntry_Voxel(ResourceId resId) {
|
||||
@@ -278,17 +418,19 @@ private:
|
||||
void registerBase_World(ResourceId id, const std::string& domain, const std::string& key, const sol::table& profile);
|
||||
void registerBase_Entity(ResourceId id, const std::string& domain, const std::string& key, const sol::table& profile);
|
||||
|
||||
template<class type, class modType>
|
||||
void buildEndProfilesByType(auto& profiles, auto enumType, auto& base, auto& keys, auto& result, auto& mods);
|
||||
|
||||
TOS::Logger LOG = "Server>ContentManager";
|
||||
AssetsManager& AM;
|
||||
|
||||
// Профили зарегистрированные модами
|
||||
std::vector<std::unique_ptr<TableEntry<DefVoxel>>> Profiles_Base_Voxel;
|
||||
std::vector<std::unique_ptr<TableEntry<DefNode>>> Profiles_Base_Node;
|
||||
std::vector<std::unique_ptr<TableEntry<DefWorld>>> Profiles_Base_World;
|
||||
std::vector<std::unique_ptr<TableEntry<DefPortal>>> Profiles_Base_Portal;
|
||||
std::vector<std::unique_ptr<TableEntry<DefEntity>>> Profiles_Base_Entity;
|
||||
std::vector<std::unique_ptr<TableEntry<DefItem>>> Profiles_Base_Item;
|
||||
std::vector<std::unique_ptr<TableEntry<DefVoxel_Base>>> Profiles_Base_Voxel;
|
||||
std::vector<std::unique_ptr<TableEntry<DefNode_Base>>> Profiles_Base_Node;
|
||||
std::vector<std::unique_ptr<TableEntry<DefWorld_Base>>> Profiles_Base_World;
|
||||
std::vector<std::unique_ptr<TableEntry<DefPortal_Base>>> Profiles_Base_Portal;
|
||||
std::vector<std::unique_ptr<TableEntry<DefEntity_Base>>> Profiles_Base_Entity;
|
||||
std::vector<std::unique_ptr<TableEntry<DefItem_Base>>> Profiles_Base_Item;
|
||||
|
||||
// Изменения, накладываемые на профили
|
||||
// Идентификатор [домен мода модификатора, модификатор]
|
||||
|
||||
@@ -786,7 +786,7 @@ void GameServer::BackingAsyncLua_t::run(int id) {
|
||||
uint8_t kMetaGrass = 1;
|
||||
DefNodeId kNodeDirt = lru.getIdNode("test", "dirt");
|
||||
DefNodeId kNodeStone = lru.getIdNode("test", "stone");
|
||||
DefNodeId kNodeWood = lru.getIdNode("test", "wood");
|
||||
DefNodeId kNodeWood = lru.getIdNode("test", "log");
|
||||
DefNodeId kNodeLeaves = lru.getIdNode("test", "leaves");
|
||||
DefNodeId kNodeLava = lru.getIdNode("test", "lava");
|
||||
DefNodeId kNodeWater = lru.getIdNode("test", "water");
|
||||
@@ -1370,7 +1370,6 @@ void GameServer::init(fs::path worldPath) {
|
||||
|
||||
Content.CM.buildEndProfiles();
|
||||
|
||||
|
||||
LOG.info() << "Инициализация";
|
||||
initLua();
|
||||
pushEvent("init");
|
||||
@@ -1615,6 +1614,7 @@ void GameServer::stepConnections() {
|
||||
std::vector<Net::Packet> packets;
|
||||
packets.push_back(RemoteClient::makePacket_informateAssets_DK(Content.AM.idToDK()));
|
||||
packets.push_back(RemoteClient::makePacket_informateAssets_HH(Content.AM.collectHashBindings(), lost));
|
||||
packets.append_range(RemoteClient::makePackets_informateDefContent_Full(Content.CM.getAllProfiles()));
|
||||
|
||||
for(const std::shared_ptr<RemoteClient>& client : newClients) {
|
||||
if(!packets.empty()) {
|
||||
@@ -1685,7 +1685,8 @@ void GameServer::reloadMods() {
|
||||
{
|
||||
// TODO: перезагрузка модов
|
||||
|
||||
Content.CM.buildEndProfiles();
|
||||
ContentManager::Out_buildEndProfiles out = Content.CM.buildEndProfiles();
|
||||
packetsToSend.append_range(RemoteClient::makePackets_informateDefContentUpdate(out));
|
||||
}
|
||||
|
||||
LOG.info() << "Перезагрузка ассетов";
|
||||
|
||||
@@ -94,24 +94,122 @@ Net::Packet RemoteClient::makePacket_informateAssets_HH(
|
||||
return pack;
|
||||
}
|
||||
|
||||
std::vector<Net::Packet> RemoteClient::makePackets_sendDefContentUpdate(
|
||||
std::array<
|
||||
std::vector<
|
||||
std::pair<
|
||||
ResourceId, // Идентификатор профиля
|
||||
std::u8string // Двоичный формат профиля
|
||||
>
|
||||
>,
|
||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
||||
> newOrUpdate, // Новые или изменённые
|
||||
std::array<
|
||||
std::vector<ResourceId>,
|
||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
||||
> lost, // Потерянные профили
|
||||
std::array<
|
||||
std::vector<std::pair<std::string, std::string>>,
|
||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
||||
> idToDK // Новые привязки
|
||||
std::vector<Net::Packet> RemoteClient::makePackets_informateDefContent_Full(
|
||||
const ContentManager::Out_getAllProfiles& profiles
|
||||
) {
|
||||
std::vector<Net::Packet> packets;
|
||||
Net::Packet pack;
|
||||
|
||||
auto check = [&](size_t needSize) {
|
||||
if(pack.size()+needSize > 65500) {
|
||||
packets.emplace_back(std::move(pack));
|
||||
pack.clear();
|
||||
}
|
||||
};
|
||||
|
||||
pack << (uint8_t) ToClient::DefinitionsFull;
|
||||
|
||||
{
|
||||
pack << (uint32_t) profiles.ProfilesIds_Voxel.size();
|
||||
for(uint32_t id : profiles.ProfilesIds_Voxel) {
|
||||
check(4);
|
||||
pack << id;
|
||||
}
|
||||
|
||||
for(const auto& profile : profiles.Profiles_Voxel) {
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
pack << (uint32_t) profiles.ProfilesIds_Node.size();
|
||||
for(uint32_t id : profiles.ProfilesIds_Node) {
|
||||
check(4);
|
||||
pack << id;
|
||||
}
|
||||
|
||||
for(const auto& profile : profiles.Profiles_Node) {
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
pack << (uint32_t) profiles.ProfilesIds_World.size();
|
||||
for(uint32_t id : profiles.ProfilesIds_World) {
|
||||
check(4);
|
||||
pack << id;
|
||||
}
|
||||
|
||||
for(const auto& profile : profiles.Profiles_World) {
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
pack << (uint32_t) profiles.ProfilesIds_Portal.size();
|
||||
for(uint32_t id : profiles.ProfilesIds_Portal) {
|
||||
check(4);
|
||||
pack << id;
|
||||
}
|
||||
|
||||
for(const auto& profile : profiles.Profiles_Portal) {
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
pack << (uint32_t) profiles.ProfilesIds_Entity.size();
|
||||
for(uint32_t id : profiles.ProfilesIds_Entity) {
|
||||
check(4);
|
||||
pack << id;
|
||||
}
|
||||
|
||||
for(const auto& profile : profiles.Profiles_Entity) {
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
pack << (uint32_t) profiles.ProfilesIds_Item.size();
|
||||
for(uint32_t id : profiles.ProfilesIds_Item) {
|
||||
check(4);
|
||||
pack << id;
|
||||
}
|
||||
|
||||
for(const auto& profile : profiles.Profiles_Item) {
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t type = 0; type < static_cast<size_t>(EnumDefContent::MAX_ENUM); type++) {
|
||||
pack << uint32_t(profiles.IdToDK[type].size());
|
||||
|
||||
for(const auto& [domain, key] : profiles.IdToDK[type]) {
|
||||
check(domain.size() + key.size() + 8);
|
||||
pack << domain << key;
|
||||
}
|
||||
}
|
||||
|
||||
if(pack.size())
|
||||
packets.emplace_back(std::move(pack));
|
||||
|
||||
return packets;
|
||||
}
|
||||
|
||||
std::vector<Net::Packet> RemoteClient::makePackets_informateDefContentUpdate(
|
||||
const ContentManager::Out_buildEndProfiles& profiles
|
||||
) {
|
||||
std::vector<Net::Packet> packets;
|
||||
Net::Packet pack;
|
||||
@@ -124,33 +222,86 @@ std::vector<Net::Packet> RemoteClient::makePackets_sendDefContentUpdate(
|
||||
};
|
||||
|
||||
pack << (uint8_t) ToClient::DefinitionsUpdate;
|
||||
pack << uint32_t(newOrUpdate.size());
|
||||
for(size_t type = 0; type < static_cast<size_t>(EnumDefContent::MAX_ENUM); type++) {
|
||||
pack << uint32_t(newOrUpdate[type].size());
|
||||
|
||||
for(const auto& [id, data] : newOrUpdate[type]) {
|
||||
check(data.size());
|
||||
pack << id << (const std::string&) data;
|
||||
}
|
||||
}
|
||||
|
||||
pack << uint32_t(lost.size());
|
||||
for(size_t type = 0; type < static_cast<size_t>(EnumDefContent::MAX_ENUM); type++) {
|
||||
pack << uint32_t(lost[type].size());
|
||||
|
||||
for(ResourceId id : lost[type]) {
|
||||
check(4);
|
||||
{
|
||||
pack << uint32_t(profiles.ChangedProfiles_Voxel.size());
|
||||
for(const auto& [id, profile] : profiles.ChangedProfiles_Voxel) {
|
||||
pack << id;
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
pack << uint32_t(idToDK.size());
|
||||
for(size_t type = 0; type < static_cast<size_t>(EnumDefContent::MAX_ENUM); type++) {
|
||||
pack << uint32_t(idToDK[type].size());
|
||||
|
||||
for(const auto& [domain, key] : idToDK[type]) {
|
||||
check(domain.size() + key.size() + 8);
|
||||
pack << key << domain;
|
||||
{
|
||||
pack << uint32_t(profiles.ChangedProfiles_Node.size());
|
||||
for(const auto& [id, profile] : profiles.ChangedProfiles_Node) {
|
||||
pack << id;
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
pack << uint32_t(profiles.ChangedProfiles_World.size());
|
||||
for(const auto& [id, profile] : profiles.ChangedProfiles_World) {
|
||||
pack << id;
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
pack << uint32_t(profiles.ChangedProfiles_Portal.size());
|
||||
for(const auto& [id, profile] : profiles.ChangedProfiles_Portal) {
|
||||
pack << id;
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
pack << uint32_t(profiles.ChangedProfiles_Entity.size());
|
||||
for(const auto& [id, profile] : profiles.ChangedProfiles_Entity) {
|
||||
pack << id;
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
pack << uint32_t(profiles.ChangedProfiles_Item.size());
|
||||
for(const auto& [id, profile] : profiles.ChangedProfiles_Item) {
|
||||
pack << id;
|
||||
std::u8string data = profile->dumpToClient();
|
||||
check(data.size());
|
||||
pack << std::string_view((const char*) data.data(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
for(size_t type = 0; type < static_cast<size_t>(EnumDefContent::MAX_ENUM); type++) {
|
||||
pack << uint32_t(profiles.LostProfiles[type].size());
|
||||
|
||||
for(const ResourceId id : profiles.LostProfiles[type]) {
|
||||
check(sizeof(ResourceId));
|
||||
pack << id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
for(size_t type = 0; type < static_cast<size_t>(EnumDefContent::MAX_ENUM); type++) {
|
||||
pack << uint32_t(profiles.IdToDK[type].size());
|
||||
|
||||
for(const auto& [domain, key] : profiles.IdToDK[type]) {
|
||||
check(domain.size() + key.size() + 8);
|
||||
pack << key << domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -388,25 +388,15 @@ public:
|
||||
const std::vector<std::tuple<ResourceFile::Hash_t, std::shared_ptr<const std::u8string>>>& resources
|
||||
);
|
||||
|
||||
|
||||
// Создаёт пакет со всеми данными об игровых профилях
|
||||
static std::vector<Net::Packet> makePackets_informateDefContent_Full(
|
||||
const ContentManager::Out_getAllProfiles& profiles
|
||||
);
|
||||
|
||||
// Создаёт пакет об обновлении игровых профилей
|
||||
static std::vector<Net::Packet> makePackets_sendDefContentUpdate(
|
||||
std::array<
|
||||
std::vector<
|
||||
std::pair<
|
||||
ResourceId, // Идентификатор профиля
|
||||
std::u8string // Двоичный формат профиля
|
||||
>
|
||||
>,
|
||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
||||
> newOrUpdate, // Новые или изменённые
|
||||
std::array<
|
||||
std::vector<ResourceId>,
|
||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
||||
> lost, // Потерянные профили
|
||||
std::array<
|
||||
std::vector<std::pair<std::string, std::string>>,
|
||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
||||
> idToDK // Новые привязки
|
||||
static std::vector<Net::Packet> makePackets_informateDefContentUpdate(
|
||||
const ContentManager::Out_buildEndProfiles& profiles
|
||||
);
|
||||
|
||||
void onUpdate();
|
||||
|
||||
Reference in New Issue
Block a user