Синхронизация профилей контента
This commit is contained in:
@@ -1,9 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Common/Net.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <Common/Abstract.hpp>
|
#include <Common/Abstract.hpp>
|
||||||
|
|
||||||
@@ -149,14 +153,6 @@ struct WorldInfo {
|
|||||||
std::unordered_map<Pos::GlobalRegion, Region> Regions;
|
std::unordered_map<Pos::GlobalRegion, Region> Regions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VoxelInfo {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NodeInfo {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PortalInfo {
|
struct PortalInfo {
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -168,19 +164,77 @@ struct EntityInfo {
|
|||||||
glm::quat Quat = glm::quat(1.f, 0.f, 0.f, 0.f);
|
glm::quat Quat = glm::quat(1.f, 0.f, 0.f, 0.f);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FuncEntityInfo {
|
/*
|
||||||
|
Конструируются с серверными идентификаторами
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct DefVoxel {
|
||||||
|
DefVoxel() = default;
|
||||||
|
DefVoxel(const std::u8string_view view) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void reBind(const std::function<ResourceId(EnumAssets, ResourceId)>& am) {
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DefItemInfo {
|
struct DefNode {
|
||||||
|
std::variant<AssetsNodestate> RenderStates;
|
||||||
|
|
||||||
|
DefNode() = default;
|
||||||
|
DefNode(const std::u8string_view view) {
|
||||||
|
Net::LinearReader lr(view);
|
||||||
|
RenderStates = lr.read<uint32_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reBind(const std::function<ResourceId(EnumAssets, ResourceId)>& am) {
|
||||||
|
RenderStates = am(EnumAssets::Nodestate, std::get<AssetsNodestate>(RenderStates));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DefVoxel_t {};
|
struct DefWorld {
|
||||||
struct DefNode_t {
|
DefWorld() = default;
|
||||||
AssetsNodestate NodestateId = 0;
|
DefWorld(const std::u8string_view view) {
|
||||||
AssetsTexture TexId = 0;
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void reBind(const std::function<ResourceId(EnumAssets, ResourceId)>& am) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DefPortal {
|
||||||
|
DefPortal() = default;
|
||||||
|
DefPortal(const std::u8string_view view) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void reBind(const std::function<ResourceId(EnumAssets, ResourceId)>& am) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DefEntity {
|
||||||
|
DefEntity() = default;
|
||||||
|
DefEntity(const std::u8string_view view) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void reBind(const std::function<ResourceId(EnumAssets, ResourceId)>& am) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DefItem {
|
||||||
|
DefItem() = default;
|
||||||
|
DefItem(const std::u8string_view view) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void reBind(const std::function<ResourceId(EnumAssets, ResourceId)>& am) {
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AssetEntry {
|
struct AssetEntry {
|
||||||
@@ -217,12 +271,12 @@ public:
|
|||||||
|
|
||||||
// Используемые профили контента
|
// Используемые профили контента
|
||||||
struct {
|
struct {
|
||||||
std::unordered_map<DefVoxelId, DefVoxel_t> DefVoxel;
|
std::unordered_map<DefVoxelId, DefVoxel> DefVoxels;
|
||||||
std::unordered_map<DefNodeId, DefNode_t> DefNode;
|
std::unordered_map<DefNodeId, DefNode> DefNodes;
|
||||||
std::unordered_map<DefWorldId, DefWorldInfo> DefWorld;
|
std::unordered_map<DefWorldId, DefWorld> DefWorlds;
|
||||||
std::unordered_map<DefPortalId, DefPortalInfo> DefPortal;
|
std::unordered_map<DefPortalId, DefPortal> DefPortals;
|
||||||
std::unordered_map<DefEntityId, DefEntityInfo> DefEntity;
|
std::unordered_map<DefEntityId, DefEntity> DefEntitys;
|
||||||
std::unordered_map<DefItemId, DefItemInfo> DefItem;
|
std::unordered_map<DefItemId, DefItem> DefItems;
|
||||||
} Profiles;
|
} Profiles;
|
||||||
|
|
||||||
// Видимый контент
|
// Видимый контент
|
||||||
|
|||||||
@@ -46,7 +46,11 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
AssetsManager(asio::io_context& ioc, fs::path cachePath)
|
AssetsManager(asio::io_context& ioc, fs::path cachePath)
|
||||||
: Cache(AssetsCacheManager::Create(ioc, cachePath)) {
|
: Cache(AssetsCacheManager::Create(ioc, cachePath))
|
||||||
|
{
|
||||||
|
for(size_t type = 0; type < static_cast<size_t>(EnumAssets::MAX_ENUM); type++) {
|
||||||
|
ServerToClientMap[type].push_back(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ручные обновления
|
// Ручные обновления
|
||||||
@@ -179,9 +183,13 @@ public:
|
|||||||
) {
|
) {
|
||||||
LOG.debug() << "BindDK domains=" << domains.size();
|
LOG.debug() << "BindDK domains=" << domains.size();
|
||||||
for(size_t type = 0; type < static_cast<size_t>(EnumAssets::MAX_ENUM); ++type) {
|
for(size_t type = 0; type < static_cast<size_t>(EnumAssets::MAX_ENUM); ++type) {
|
||||||
|
LOG.info() << type;
|
||||||
for(size_t forDomainIter = 0; forDomainIter < keys[type].size(); ++forDomainIter) {
|
for(size_t forDomainIter = 0; forDomainIter < keys[type].size(); ++forDomainIter) {
|
||||||
|
LOG.info() << "\t" << domains[forDomainIter];
|
||||||
for(const std::string& key : keys[type][forDomainIter]) {
|
for(const std::string& key : keys[type][forDomainIter]) {
|
||||||
ServerToClientMap[type].push_back(getId((EnumAssets) type, domains[forDomainIter], key));
|
uint32_t id = getId((EnumAssets) type, domains[forDomainIter], key);
|
||||||
|
LOG.info() << "\t\t" << key << " -> " << id;
|
||||||
|
ServerToClientMap[type].push_back(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,6 +307,10 @@ public:
|
|||||||
return std::move(RU);
|
return std::move(RU);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResourceId reBind(EnumAssets type, ResourceId server) {
|
||||||
|
return ServerToClientMap[static_cast<size_t>(type)].at(server);
|
||||||
|
}
|
||||||
|
|
||||||
void tick() {
|
void tick() {
|
||||||
// Проверим кеш
|
// Проверим кеш
|
||||||
std::vector<std::pair<Hash_t, std::optional<Resource>>> resources = Cache->pullReads();
|
std::vector<std::pair<Hash_t, std::optional<Resource>>> resources = Cache->pullReads();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <Common/Packets.hpp>
|
#include <Common/Packets.hpp>
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
@@ -65,12 +66,6 @@ ServerSession::ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSo
|
|||||||
{
|
{
|
||||||
assert(Socket.get());
|
assert(Socket.get());
|
||||||
|
|
||||||
Profiles.DefNode[0] = {0};
|
|
||||||
Profiles.DefNode[1] = {1};
|
|
||||||
Profiles.DefNode[2] = {2};
|
|
||||||
Profiles.DefNode[3] = {3};
|
|
||||||
Profiles.DefNode[4] = {4};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
asio::co_spawn(ioc, run(AUC.use()), asio::detached);
|
asio::co_spawn(ioc, run(AUC.use()), asio::detached);
|
||||||
// TODO: добавить оптимизацию для подключения клиента к внутреннему серверу
|
// TODO: добавить оптимизацию для подключения клиента к внутреннему серверу
|
||||||
@@ -345,18 +340,19 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
// Перевариваем данные по тактам
|
// Перевариваем данные по тактам
|
||||||
|
|
||||||
// Профили
|
// Профили
|
||||||
std::unordered_map<DefVoxelId, void*> profile_Voxel_AddOrChange;
|
std::unordered_map<DefVoxelId, DefVoxel> profile_Voxel_AddOrChange;
|
||||||
std::vector<DefVoxelId> profile_Voxel_Lost;
|
std::vector<DefVoxelId> profile_Voxel_Lost;
|
||||||
std::unordered_map<DefNodeId, DefNode_t> profile_Node_AddOrChange;
|
std::unordered_map<DefNodeId, DefNode> profile_Node_AddOrChange;
|
||||||
std::vector<DefNodeId> profile_Node_Lost;
|
std::vector<DefNodeId> profile_Node_Lost;
|
||||||
std::unordered_map<DefWorldId, void*> profile_World_AddOrChange;
|
std::unordered_map<DefWorldId, DefWorld> profile_World_AddOrChange;
|
||||||
std::vector<DefWorldId> profile_World_Lost;
|
std::vector<DefWorldId> profile_World_Lost;
|
||||||
std::unordered_map<DefPortalId, void*> profile_Portal_AddOrChange;
|
std::unordered_map<DefPortalId, DefPortal> profile_Portal_AddOrChange;
|
||||||
std::vector<DefPortalId> profile_Portal_Lost;
|
std::vector<DefPortalId> profile_Portal_Lost;
|
||||||
std::unordered_map<DefEntityId, DefEntityInfo> profile_Entity_AddOrChange;
|
std::unordered_map<DefEntityId, DefEntity> profile_Entity_AddOrChange;
|
||||||
std::vector<DefEntityId> profile_Entity_Lost;
|
std::vector<DefEntityId> profile_Entity_Lost;
|
||||||
std::unordered_map<DefItemId, void*> profile_Item_AddOrChange;
|
std::unordered_map<DefItemId, DefItem> profile_Item_AddOrChange;
|
||||||
std::vector<DefItemId> profile_Item_Lost;
|
std::vector<DefItemId> profile_Item_Lost;
|
||||||
|
|
||||||
std::unordered_map<EntityId_t, EntityInfo> entity_AddOrChange;
|
std::unordered_map<EntityId_t, EntityInfo> entity_AddOrChange;
|
||||||
std::vector<EntityId_t> entity_Lost;
|
std::vector<EntityId_t> entity_Lost;
|
||||||
|
|
||||||
@@ -382,6 +378,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
if(iter != profile_Voxel_Lost.end() && *iter == id)
|
if(iter != profile_Voxel_Lost.end() && *iter == id)
|
||||||
profile_Voxel_Lost.erase(iter);
|
profile_Voxel_Lost.erase(iter);
|
||||||
|
|
||||||
|
profile.reBind(
|
||||||
|
[&](EnumAssets type, ResourceId server) {
|
||||||
|
return AM.reBind(type, server);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
profile_Voxel_AddOrChange[id] = profile;
|
profile_Voxel_AddOrChange[id] = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,6 +403,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
if(iter != profile_Node_Lost.end() && *iter == id)
|
if(iter != profile_Node_Lost.end() && *iter == id)
|
||||||
profile_Node_Lost.erase(iter);
|
profile_Node_Lost.erase(iter);
|
||||||
|
|
||||||
|
profile.reBind(
|
||||||
|
[&](EnumAssets type, ResourceId server) {
|
||||||
|
return AM.reBind(type, server);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
profile_Node_AddOrChange[id] = profile;
|
profile_Node_AddOrChange[id] = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,6 +428,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
if(iter != profile_World_Lost.end() && *iter == id)
|
if(iter != profile_World_Lost.end() && *iter == id)
|
||||||
profile_World_Lost.erase(iter);
|
profile_World_Lost.erase(iter);
|
||||||
|
|
||||||
|
profile.reBind(
|
||||||
|
[&](EnumAssets type, ResourceId server) {
|
||||||
|
return AM.reBind(type, server);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
profile_World_AddOrChange[id] = profile;
|
profile_World_AddOrChange[id] = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,6 +453,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
if(iter != profile_Portal_Lost.end() && *iter == id)
|
if(iter != profile_Portal_Lost.end() && *iter == id)
|
||||||
profile_Portal_Lost.erase(iter);
|
profile_Portal_Lost.erase(iter);
|
||||||
|
|
||||||
|
profile.reBind(
|
||||||
|
[&](EnumAssets type, ResourceId server) {
|
||||||
|
return AM.reBind(type, server);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
profile_Portal_AddOrChange[id] = profile;
|
profile_Portal_AddOrChange[id] = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,6 +478,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
if(iter != profile_Entity_Lost.end() && *iter == id)
|
if(iter != profile_Entity_Lost.end() && *iter == id)
|
||||||
profile_Entity_Lost.erase(iter);
|
profile_Entity_Lost.erase(iter);
|
||||||
|
|
||||||
|
profile.reBind(
|
||||||
|
[&](EnumAssets type, ResourceId server) {
|
||||||
|
return AM.reBind(type, server);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
profile_Entity_AddOrChange[id] = profile;
|
profile_Entity_AddOrChange[id] = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,6 +503,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
if(iter != profile_Item_Lost.end() && *iter == id)
|
if(iter != profile_Item_Lost.end() && *iter == id)
|
||||||
profile_Item_Lost.erase(iter);
|
profile_Item_Lost.erase(iter);
|
||||||
|
|
||||||
|
profile.reBind(
|
||||||
|
[&](EnumAssets type, ResourceId server) {
|
||||||
|
return AM.reBind(type, server);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
profile_Item_AddOrChange[id] = profile;
|
profile_Item_AddOrChange[id] = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,10 +523,10 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
for(auto& [id, info] : data.Entity_AddOrChange) {
|
for(auto& [id, info] : data.Entity_AddOrChange) {
|
||||||
auto iter = std::lower_bound(entity_Lost.begin(), entity_Lost.end(), id);
|
auto iter = std::lower_bound(entity_Lost.begin(), entity_Lost.end(), id);
|
||||||
if(iter != entity_Lost.end() && *iter == id)
|
if(iter != entity_Lost.end() && *iter == id)
|
||||||
entity_Lost.erase(iter);
|
entity_Lost.erase(iter);
|
||||||
|
|
||||||
entity_AddOrChange[id] = info;
|
entity_AddOrChange[id] = info;
|
||||||
}
|
}
|
||||||
@@ -506,20 +538,20 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
entity_Lost.insert(entity_Lost.end(), data.Entity_Lost.begin(), data.Entity_Lost.end());
|
entity_Lost.insert(entity_Lost.end(), data.Entity_Lost.begin(), data.Entity_Lost.end());
|
||||||
std::sort(entity_Lost.begin(), entity_Lost.end());
|
std::sort(entity_Lost.begin(), entity_Lost.end());
|
||||||
auto eraseIter = std::unique(entity_Lost.begin(), entity_Lost.end());
|
auto eraseIter = std::unique(entity_Lost.begin(), entity_Lost.end());
|
||||||
entity_Lost.erase(eraseIter, entity_Lost.end());
|
entity_Lost.erase(eraseIter, entity_Lost.end());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
AssetsManager::ResourceUpdates updates = AM.pullResourceUpdates();
|
AssetsManager::ResourceUpdates updates = AM.pullResourceUpdates();
|
||||||
result.AssetsNodestates = std::move(updates.Nodestates);
|
result.AssetsNodestates = std::move(updates.Nodestates);
|
||||||
result.AssetsModels = std::move(updates.Models);
|
result.AssetsModels = std::move(updates.Models);
|
||||||
result.AssetsTextures = std::move(updates.Textures);
|
result.AssetsTextures = std::move(updates.Textures);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& [id, _] : profile_Voxel_AddOrChange)
|
for(auto& [id, _] : profile_Voxel_AddOrChange)
|
||||||
result.Profiles_ChangeOrAdd[EnumDefContent::Voxel].push_back(id);
|
result.Profiles_ChangeOrAdd[EnumDefContent::Voxel].push_back(id);
|
||||||
result.Profiles_Lost[EnumDefContent::Voxel] = profile_Voxel_Lost;
|
result.Profiles_Lost[EnumDefContent::Voxel] = profile_Voxel_Lost;
|
||||||
|
|
||||||
for(auto& [id, _] : profile_Node_AddOrChange)
|
for(auto& [id, _] : profile_Node_AddOrChange)
|
||||||
result.Profiles_ChangeOrAdd[EnumDefContent::Node].push_back(id);
|
result.Profiles_ChangeOrAdd[EnumDefContent::Node].push_back(id);
|
||||||
@@ -657,7 +689,6 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
for(auto& [wId, regions] : regions_Lost_Result)
|
for(auto& [wId, regions] : regions_Lost_Result)
|
||||||
result.Chunks_Lost[wId] = std::vector<Pos::GlobalRegion>(regions.begin(), regions.end());
|
result.Chunks_Lost[wId] = std::vector<Pos::GlobalRegion>(regions.begin(), regions.end());
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
for(TickData& data : ticks) {
|
for(TickData& data : ticks) {
|
||||||
}
|
}
|
||||||
@@ -669,12 +700,23 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
// Применяем изменения по ресурсам, профилям и контенту
|
// Применяем изменения по ресурсам, профилям и контенту
|
||||||
// Определения
|
// Определения
|
||||||
{
|
{
|
||||||
for(auto& [resId, def] : profile_Node_AddOrChange) {
|
for(auto& [resId, def] : profile_Voxel_AddOrChange)
|
||||||
Profiles.DefNode[resId] = def;
|
Profiles.DefVoxels[resId] = def;
|
||||||
}
|
|
||||||
for(auto& [resId, def] : profile_Entity_AddOrChange) {
|
for(auto& [resId, def] : profile_Node_AddOrChange)
|
||||||
Profiles.DefEntity[resId] = def;
|
Profiles.DefNodes[resId] = def;
|
||||||
}
|
|
||||||
|
for(auto& [resId, def] : profile_World_AddOrChange)
|
||||||
|
Profiles.DefWorlds[resId] = def;
|
||||||
|
|
||||||
|
for(auto& [resId, def] : profile_Portal_AddOrChange)
|
||||||
|
Profiles.DefPortals[resId] = def;
|
||||||
|
|
||||||
|
for(auto& [resId, def] : profile_Entity_AddOrChange)
|
||||||
|
Profiles.DefEntitys[resId] = def;
|
||||||
|
|
||||||
|
for(auto& [resId, def] : profile_Item_AddOrChange)
|
||||||
|
Profiles.DefItems[resId] = def;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Чанки
|
// Чанки
|
||||||
@@ -724,7 +766,6 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
|||||||
regions[pos >> 2].Chunks[Pos::bvec4u(pos & 0x3).pack()].Nodes = std::move(data);
|
regions[pos >> 2].Chunks[Pos::bvec4u(pos & 0x3).pack()].Nodes = std::move(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сущности
|
// Сущности
|
||||||
@@ -904,6 +945,9 @@ coro<> ServerSession::readPacket(Net::AsyncSocket &sock) {
|
|||||||
case ToClient::AssetsNextSend:
|
case ToClient::AssetsNextSend:
|
||||||
co_await rP_AssetsNextSend(sock);
|
co_await rP_AssetsNextSend(sock);
|
||||||
co_return;
|
co_return;
|
||||||
|
case ToClient::DefinitionsFull:
|
||||||
|
co_await rP_DefinitionsFull(sock);
|
||||||
|
co_return;
|
||||||
case ToClient::DefinitionsUpdate:
|
case ToClient::DefinitionsUpdate:
|
||||||
co_await rP_DefinitionsUpdate(sock);
|
co_await rP_DefinitionsUpdate(sock);
|
||||||
co_return;
|
co_return;
|
||||||
@@ -1035,55 +1079,281 @@ coro<> ServerSession::rP_AssetsNextSend(Net::AsyncSocket &sock) {
|
|||||||
AsyncContext.AssetsLoading.erase(AsyncContext.AssetsLoading.find(hash));
|
AsyncContext.AssetsLoading.erase(AsyncContext.AssetsLoading.find(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
coro<> ServerSession::rP_DefinitionsFull(Net::AsyncSocket &sock) {
|
||||||
|
std::vector<ResourceId> ids;
|
||||||
|
uint32_t size = 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
ids.clear();
|
||||||
|
ids.reserve(size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
ids.push_back(co_await sock.read<uint32_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Voxel_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_Voxel_AddOrChange.size()+size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Voxel_AddOrChange.emplace_back(
|
||||||
|
ids[iter],
|
||||||
|
DefVoxel{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
ids.clear();
|
||||||
|
ids.reserve(size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
ids.push_back(co_await sock.read<uint32_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Node_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_Node_AddOrChange.size()+size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Node_AddOrChange.emplace_back(
|
||||||
|
ids[iter],
|
||||||
|
DefNode{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
ids.clear();
|
||||||
|
ids.reserve(size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
ids.push_back(co_await sock.read<uint32_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncContext.ThisTickEntry.Profile_World_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_World_AddOrChange.size()+size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_World_AddOrChange.emplace_back(
|
||||||
|
ids[iter],
|
||||||
|
DefWorld{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
ids.clear();
|
||||||
|
ids.reserve(size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
ids.push_back(co_await sock.read<uint32_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Portal_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_Portal_AddOrChange.size()+size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Portal_AddOrChange.emplace_back(
|
||||||
|
ids[iter],
|
||||||
|
DefPortal{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
ids.clear();
|
||||||
|
ids.reserve(size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
ids.push_back(co_await sock.read<uint32_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Entity_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_Entity_AddOrChange.size()+size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Entity_AddOrChange.emplace_back(
|
||||||
|
ids[iter],
|
||||||
|
DefEntity{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
ids.clear();
|
||||||
|
ids.reserve(size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
ids.push_back(co_await sock.read<uint32_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Item_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_Item_AddOrChange.size()+size);
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Item_AddOrChange.emplace_back(
|
||||||
|
ids[iter],
|
||||||
|
DefItem{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t type = 0; type < static_cast<size_t>(EnumDefContent::MAX_ENUM); type++) {
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
|
std::string domain = co_await sock.read<std::string>();
|
||||||
|
std::string key = co_await sock.read<std::string>();
|
||||||
|
|
||||||
|
(void) domain;
|
||||||
|
(void) key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
coro<> ServerSession::rP_DefinitionsUpdate(Net::AsyncSocket &sock) {
|
coro<> ServerSession::rP_DefinitionsUpdate(Net::AsyncSocket &sock) {
|
||||||
static std::atomic<uint32_t> debugDefLogCount = 0;
|
static std::atomic<uint32_t> debugDefLogCount = 0;
|
||||||
uint32_t typeCount = co_await sock.read<uint32_t>();
|
uint32_t size;
|
||||||
typeCount = std::min<uint32_t>(typeCount, static_cast<uint32_t>(EnumDefContent::MAX_ENUM));
|
|
||||||
|
|
||||||
for(uint32_t type = 0; type < typeCount; ++type) {
|
{
|
||||||
uint32_t count = co_await sock.read<uint32_t>();
|
size = co_await sock.read<uint32_t>();
|
||||||
for(uint32_t i = 0; i < count; ++i) {
|
AsyncContext.ThisTickEntry.Profile_Voxel_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_Voxel_AddOrChange.size()+size);
|
||||||
ResourceId id = co_await sock.read<ResourceId>();
|
for(size_t iter = 0; iter < size; ++iter) {
|
||||||
std::string dataStr = co_await sock.read<std::string>();
|
uint32_t id = co_await sock.read<uint32_t>();
|
||||||
(void)dataStr;
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Voxel_AddOrChange.emplace_back(
|
||||||
if(type == static_cast<uint32_t>(EnumDefContent::Node)) {
|
id,
|
||||||
DefNode_t def;
|
DefVoxel{
|
||||||
def.NodestateId = 0;
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
def.TexId = id;
|
|
||||||
AsyncContext.ThisTickEntry.Profile_Node_AddOrChange.emplace_back(id, def);
|
|
||||||
if(id < 32) {
|
|
||||||
uint32_t idx = debugDefLogCount.fetch_add(1);
|
|
||||||
if(idx < 64) {
|
|
||||||
LOG.debug() << "DefNode id=" << id
|
|
||||||
<< " nodestate=" << def.NodestateId
|
|
||||||
<< " tex=" << def.TexId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t lostCount = co_await sock.read<uint32_t>();
|
{
|
||||||
lostCount = std::min<uint32_t>(lostCount, static_cast<uint32_t>(EnumDefContent::MAX_ENUM));
|
size = co_await sock.read<uint32_t>();
|
||||||
for(uint32_t type = 0; type < lostCount; ++type) {
|
AsyncContext.ThisTickEntry.Profile_Node_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_Node_AddOrChange.size()+size);
|
||||||
uint32_t count = co_await sock.read<uint32_t>();
|
for(size_t iter = 0; iter < size; ++iter) {
|
||||||
for(uint32_t i = 0; i < count; ++i) {
|
uint32_t id = co_await sock.read<uint32_t>();
|
||||||
ResourceId id = co_await sock.read<ResourceId>();
|
std::string data = co_await sock.read<std::string>();
|
||||||
if(type == static_cast<uint32_t>(EnumDefContent::Node))
|
AsyncContext.ThisTickEntry.Profile_Node_AddOrChange.emplace_back(
|
||||||
AsyncContext.ThisTickEntry.Profile_Node_Lost.push_back(id);
|
id,
|
||||||
|
DefNode{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t dkCount = co_await sock.read<uint32_t>();
|
{
|
||||||
dkCount = std::min<uint32_t>(dkCount, static_cast<uint32_t>(EnumDefContent::MAX_ENUM));
|
size = co_await sock.read<uint32_t>();
|
||||||
for(uint32_t type = 0; type < dkCount; ++type) {
|
AsyncContext.ThisTickEntry.Profile_World_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_World_AddOrChange.size()+size);
|
||||||
uint32_t count = co_await sock.read<uint32_t>();
|
for(size_t iter = 0; iter < size; ++iter) {
|
||||||
for(uint32_t i = 0; i < count; ++i) {
|
uint32_t id = co_await sock.read<uint32_t>();
|
||||||
std::string key = co_await sock.read<std::string>();
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_World_AddOrChange.emplace_back(
|
||||||
|
id,
|
||||||
|
DefWorld{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Portal_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_Portal_AddOrChange.size()+size);
|
||||||
|
for(size_t iter = 0; iter < size; ++iter) {
|
||||||
|
uint32_t id = co_await sock.read<uint32_t>();
|
||||||
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Portal_AddOrChange.emplace_back(
|
||||||
|
id,
|
||||||
|
DefPortal{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Entity_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_Entity_AddOrChange.size()+size);
|
||||||
|
for(size_t iter = 0; iter < size; ++iter) {
|
||||||
|
uint32_t id = co_await sock.read<uint32_t>();
|
||||||
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Entity_AddOrChange.emplace_back(
|
||||||
|
id,
|
||||||
|
DefEntity{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Item_AddOrChange.reserve(AsyncContext.ThisTickEntry.Profile_Item_AddOrChange.size()+size);
|
||||||
|
for(size_t iter = 0; iter < size; ++iter) {
|
||||||
|
uint32_t id = co_await sock.read<uint32_t>();
|
||||||
|
std::string data = co_await sock.read<std::string>();
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Item_AddOrChange.emplace_back(
|
||||||
|
id,
|
||||||
|
DefItem{
|
||||||
|
std::u8string_view((const char8_t*) data.data(), data.size())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
for(uint32_t iter = 0; iter < size; ++iter)
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Voxel_Lost.push_back(co_await sock.read<ResourceId>());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
for(uint32_t iter = 0; iter < size; ++iter)
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Node_Lost.push_back(co_await sock.read<ResourceId>());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
for(uint32_t iter = 0; iter < size; ++iter)
|
||||||
|
AsyncContext.ThisTickEntry.Profile_World_Lost.push_back(co_await sock.read<ResourceId>());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
for(uint32_t iter = 0; iter < size; ++iter)
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Portal_Lost.push_back(co_await sock.read<ResourceId>());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
for(uint32_t iter = 0; iter < size; ++iter)
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Entity_Lost.push_back(co_await sock.read<ResourceId>());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
for(uint32_t iter = 0; iter < size; ++iter)
|
||||||
|
AsyncContext.ThisTickEntry.Profile_Item_Lost.push_back(co_await sock.read<ResourceId>());
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t type = 0; type < static_cast<size_t>(EnumDefContent::MAX_ENUM); type++) {
|
||||||
|
size = co_await sock.read<uint32_t>();
|
||||||
|
|
||||||
|
for(size_t iter = 0; iter < size; iter++) {
|
||||||
std::string domain = co_await sock.read<std::string>();
|
std::string domain = co_await sock.read<std::string>();
|
||||||
(void)key;
|
std::string key = co_await sock.read<std::string>();
|
||||||
(void)domain;
|
|
||||||
|
(void) domain;
|
||||||
|
(void) key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,17 +122,17 @@ private:
|
|||||||
// Полученные с сервера ресурсы
|
// Полученные с сервера ресурсы
|
||||||
std::vector<std::tuple<ResourceFile::Hash_t, std::u8string>> ReceivedAssets;
|
std::vector<std::tuple<ResourceFile::Hash_t, std::u8string>> ReceivedAssets;
|
||||||
|
|
||||||
std::vector<std::pair<DefVoxelId, void*>> Profile_Voxel_AddOrChange;
|
std::vector<std::pair<DefVoxelId, DefVoxel>> Profile_Voxel_AddOrChange;
|
||||||
std::vector<DefVoxelId> Profile_Voxel_Lost;
|
std::vector<DefVoxelId> Profile_Voxel_Lost;
|
||||||
std::vector<std::pair<DefNodeId, DefNode_t>> Profile_Node_AddOrChange;
|
std::vector<std::pair<DefNodeId, DefNode>> Profile_Node_AddOrChange;
|
||||||
std::vector<DefNodeId> Profile_Node_Lost;
|
std::vector<DefNodeId> Profile_Node_Lost;
|
||||||
std::vector<std::pair<DefWorldId, void*>> Profile_World_AddOrChange;
|
std::vector<std::pair<DefWorldId, DefWorld>> Profile_World_AddOrChange;
|
||||||
std::vector<DefWorldId> Profile_World_Lost;
|
std::vector<DefWorldId> Profile_World_Lost;
|
||||||
std::vector<std::pair<DefPortalId, void*>> Profile_Portal_AddOrChange;
|
std::vector<std::pair<DefPortalId, DefPortal>> Profile_Portal_AddOrChange;
|
||||||
std::vector<DefPortalId> Profile_Portal_Lost;
|
std::vector<DefPortalId> Profile_Portal_Lost;
|
||||||
std::vector<std::pair<DefEntityId, DefEntityInfo>> Profile_Entity_AddOrChange;
|
std::vector<std::pair<DefEntityId, DefEntity>> Profile_Entity_AddOrChange;
|
||||||
std::vector<DefEntityId> Profile_Entity_Lost;
|
std::vector<DefEntityId> Profile_Entity_Lost;
|
||||||
std::vector<std::pair<DefItemId, void*>> Profile_Item_AddOrChange;
|
std::vector<std::pair<DefItemId, DefItem>> Profile_Item_AddOrChange;
|
||||||
std::vector<DefItemId> Profile_Item_Lost;
|
std::vector<DefItemId> Profile_Item_Lost;
|
||||||
|
|
||||||
std::vector<std::pair<WorldId_t, void*>> Worlds_AddOrChange;
|
std::vector<std::pair<WorldId_t, void*>> Worlds_AddOrChange;
|
||||||
@@ -197,6 +197,7 @@ private:
|
|||||||
coro<> rP_AssetsBindHH(Net::AsyncSocket &sock);
|
coro<> rP_AssetsBindHH(Net::AsyncSocket &sock);
|
||||||
coro<> rP_AssetsInitSend(Net::AsyncSocket &sock);
|
coro<> rP_AssetsInitSend(Net::AsyncSocket &sock);
|
||||||
coro<> rP_AssetsNextSend(Net::AsyncSocket &sock);
|
coro<> rP_AssetsNextSend(Net::AsyncSocket &sock);
|
||||||
|
coro<> rP_DefinitionsFull(Net::AsyncSocket &sock);
|
||||||
coro<> rP_DefinitionsUpdate(Net::AsyncSocket &sock);
|
coro<> rP_DefinitionsUpdate(Net::AsyncSocket &sock);
|
||||||
coro<> rP_ChunkVoxels(Net::AsyncSocket &sock);
|
coro<> rP_ChunkVoxels(Net::AsyncSocket &sock);
|
||||||
coro<> rP_ChunkNodes(Net::AsyncSocket &sock);
|
coro<> rP_ChunkNodes(Net::AsyncSocket &sock);
|
||||||
|
|||||||
@@ -121,15 +121,15 @@ void ChunkMeshGenerator::run(uint8_t id) {
|
|||||||
uint8_t fullNodes[18][18][18];
|
uint8_t fullNodes[18][18][18];
|
||||||
|
|
||||||
// Профиль, который используется если на стороне клиента отсутствует нужных профиль
|
// Профиль, который используется если на стороне клиента отсутствует нужных профиль
|
||||||
DefNode_t defaultProfileNode;
|
DefNode defaultProfileNode;
|
||||||
// Кеш запросов профилей нод
|
// Кеш запросов профилей нод
|
||||||
std::unordered_map<DefNodeId, const DefNode_t*> profilesNodeCache;
|
std::unordered_map<DefNodeId, const DefNode*> profilesNodeCache;
|
||||||
auto getNodeProfile = [&](DefNodeId id) -> const DefNode_t* {
|
auto getNodeProfile = [&](DefNodeId id) -> const DefNode* {
|
||||||
auto iterCache = profilesNodeCache.find(id);
|
auto iterCache = profilesNodeCache.find(id);
|
||||||
if(iterCache == profilesNodeCache.end()) {
|
if(iterCache == profilesNodeCache.end()) {
|
||||||
// Промах кеша
|
// Промах кеша
|
||||||
auto iterSS = SS->Profiles.DefNode.find(id);
|
auto iterSS = SS->Profiles.DefNodes.find(id);
|
||||||
if(iterSS != SS->Profiles.DefNode.end()) {
|
if(iterSS != SS->Profiles.DefNodes.end()) {
|
||||||
return (profilesNodeCache[id] = &iterSS->second);
|
return (profilesNodeCache[id] = &iterSS->second);
|
||||||
} else {
|
} else {
|
||||||
// Профиль отсутствует на клиенте
|
// Профиль отсутствует на клиенте
|
||||||
@@ -189,46 +189,50 @@ void ChunkMeshGenerator::run(uint8_t id) {
|
|||||||
|
|
||||||
std::unordered_map<DefNodeId, bool> nodeFullCuboidCache;
|
std::unordered_map<DefNodeId, bool> nodeFullCuboidCache;
|
||||||
auto nodeIsFull = [&](Node node) -> bool {
|
auto nodeIsFull = [&](Node node) -> bool {
|
||||||
|
if(node.NodeId == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
auto iterCache = nodeFullCuboidCache.find(node.Data);
|
auto iterCache = nodeFullCuboidCache.find(node.Data);
|
||||||
if(iterCache == nodeFullCuboidCache.end()) {
|
if(iterCache == nodeFullCuboidCache.end()) {
|
||||||
const DefNode_t* profile = getNodeProfile(node.NodeId);
|
const DefNode* profile = getNodeProfile(node.NodeId);
|
||||||
if(profile->TexId != 0) {
|
if(NSP) {
|
||||||
return (nodeFullCuboidCache[node.Data] = true);
|
if(const AssetsNodestate* ptr = std::get_if<AssetsNodestate>(&profile->RenderStates)) {
|
||||||
}
|
if(NSP->hasNodestate(*ptr)) {
|
||||||
|
std::unordered_map<std::string, int32_t> states;
|
||||||
if(NSP && profile->NodestateId != 0 && NSP->hasNodestate(profile->NodestateId)) {
|
int32_t meta = node.Meta;
|
||||||
std::unordered_map<std::string, int32_t> states;
|
states.emplace("meta", meta);
|
||||||
int32_t meta = node.Meta;
|
const auto routes = NSP->getModelsForNode(*ptr, metaStatesInfo, states);
|
||||||
states.emplace("meta", meta);
|
bool isFull = !routes.empty();
|
||||||
const auto routes = NSP->getModelsForNode(profile->NodestateId, metaStatesInfo, states);
|
if(isFull) {
|
||||||
bool isFull = !routes.empty();
|
for(const auto& variants : routes) {
|
||||||
if(isFull) {
|
for(const auto& [weight, faces] : variants) {
|
||||||
for(const auto& variants : routes) {
|
(void)weight;
|
||||||
for(const auto& [weight, faces] : variants) {
|
auto hasFace = [&](EnumFace face) -> bool {
|
||||||
(void)weight;
|
auto iterFace = faces.find(face);
|
||||||
auto hasFace = [&](EnumFace face) -> bool {
|
return iterFace != faces.end() && !iterFace->second.empty();
|
||||||
auto iterFace = faces.find(face);
|
};
|
||||||
return iterFace != faces.end() && !iterFace->second.empty();
|
if(!hasFace(EnumFace::Up)
|
||||||
};
|
|| !hasFace(EnumFace::Down)
|
||||||
if(!hasFace(EnumFace::Up)
|
|| !hasFace(EnumFace::East)
|
||||||
|| !hasFace(EnumFace::Down)
|
|| !hasFace(EnumFace::West)
|
||||||
|| !hasFace(EnumFace::East)
|
|| !hasFace(EnumFace::South)
|
||||||
|| !hasFace(EnumFace::West)
|
|| !hasFace(EnumFace::North))
|
||||||
|| !hasFace(EnumFace::South)
|
{
|
||||||
|| !hasFace(EnumFace::North))
|
isFull = false;
|
||||||
{
|
break;
|
||||||
isFull = false;
|
}
|
||||||
break;
|
}
|
||||||
|
if(!isFull)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!isFull)
|
|
||||||
break;
|
return (nodeFullCuboidCache[node.Data] = isFull);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (nodeFullCuboidCache[node.Data] = isFull);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (nodeFullCuboidCache[node.Data] = false);
|
return (nodeFullCuboidCache[node.Data] = true);
|
||||||
} else {
|
} else {
|
||||||
return iterCache->second;
|
return iterCache->second;
|
||||||
}
|
}
|
||||||
@@ -420,6 +424,10 @@ void ChunkMeshGenerator::run(uint8_t id) {
|
|||||||
for(int z = 0; z < 16; z++)
|
for(int z = 0; z < 16; z++)
|
||||||
for(int y = 0; y < 16; y++)
|
for(int y = 0; y < 16; y++)
|
||||||
for(int x = 0; x < 16; x++) {
|
for(int x = 0; x < 16; x++) {
|
||||||
|
const Node& nodeData = (*chunk)[x+y*16+z*16*16];
|
||||||
|
if(nodeData.NodeId == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
const size_t vertexStart = result.NodeVertexs.size();
|
const size_t vertexStart = result.NodeVertexs.size();
|
||||||
int fullCovered = 0;
|
int fullCovered = 0;
|
||||||
|
|
||||||
@@ -433,66 +441,46 @@ void ChunkMeshGenerator::run(uint8_t id) {
|
|||||||
if(fullCovered == 0b111111)
|
if(fullCovered == 0b111111)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Node& nodeData = (*chunk)[x+y*16+z*16*16];
|
const DefNode* node = getNodeProfile(nodeData.NodeId);
|
||||||
const DefNode_t* node = getNodeProfile(nodeData.NodeId);
|
|
||||||
|
|
||||||
if(debugMeshEnabled) {
|
|
||||||
const bool hasRenderable = (node->NodestateId != 0) || (node->TexId != 0);
|
|
||||||
if(hasRenderable && fullCovered != 0b111111) {
|
|
||||||
expectedColumnX[x] = 1;
|
|
||||||
expectedColumnY[y] = 1;
|
|
||||||
expectedColumnZ[z] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool usedModel = false;
|
bool usedModel = false;
|
||||||
|
|
||||||
if(NSP && (node->NodestateId != 0 || NSP->hasNodestate(node->NodestateId))) {
|
if(NSP) {
|
||||||
auto iterCache = modelCache.find(nodeData.Data);
|
if(const AssetsNodestate* ptr = std::get_if<AssetsNodestate>(&node->RenderStates)) {
|
||||||
if(iterCache == modelCache.end()) {
|
if(NSP->hasNodestate(*ptr)) {
|
||||||
std::unordered_map<std::string, int32_t> states;
|
auto iterCache = modelCache.find(nodeData.Data);
|
||||||
states.emplace("meta", nodeData.Meta);
|
if(iterCache == modelCache.end()) {
|
||||||
|
std::unordered_map<std::string, int32_t> states;
|
||||||
|
states.emplace("meta", nodeData.Meta);
|
||||||
|
|
||||||
ModelCacheEntry entry;
|
ModelCacheEntry entry;
|
||||||
entry.Routes = NSP->getModelsForNode(node->NodestateId, metaStatesInfo, states);
|
entry.Routes = NSP->getModelsForNode(*ptr, metaStatesInfo, states);
|
||||||
iterCache = modelCache.emplace(nodeData.Data, std::move(entry)).first;
|
iterCache = modelCache.emplace(nodeData.Data, std::move(entry)).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!iterCache->second.Routes.empty()) {
|
if(!iterCache->second.Routes.empty()) {
|
||||||
uint32_t seed = uint32_t(nodeData.Data) * 2654435761u;
|
uint32_t seed = uint32_t(nodeData.Data) * 2654435761u;
|
||||||
seed ^= uint32_t(x) * 73856093u;
|
seed ^= uint32_t(x) * 73856093u;
|
||||||
seed ^= uint32_t(y) * 19349663u;
|
seed ^= uint32_t(y) * 19349663u;
|
||||||
seed ^= uint32_t(z) * 83492791u;
|
seed ^= uint32_t(z) * 83492791u;
|
||||||
|
|
||||||
for(size_t routeIndex = 0; routeIndex < iterCache->second.Routes.size(); routeIndex++) {
|
for(size_t routeIndex = 0; routeIndex < iterCache->second.Routes.size(); routeIndex++) {
|
||||||
const auto& variants = iterCache->second.Routes[routeIndex];
|
const auto& variants = iterCache->second.Routes[routeIndex];
|
||||||
const auto* faces = pickVariant(variants, seed + uint32_t(routeIndex) * 374761393u);
|
const auto* faces = pickVariant(variants, seed + uint32_t(routeIndex) * 374761393u);
|
||||||
if(faces)
|
if(faces)
|
||||||
appendModel(*faces, fullCovered, x, y, z);
|
appendModel(*faces, fullCovered, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
usedModel = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usedModel = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(usedModel)
|
if(usedModel)
|
||||||
goto node_done;
|
goto node_done;
|
||||||
|
|
||||||
if(NSP && node->TexId != 0) {
|
v.Tex = 0;
|
||||||
auto iterTex = baseTextureCache.find(node->TexId);
|
|
||||||
if(iterTex != baseTextureCache.end()) {
|
|
||||||
v.Tex = iterTex->second;
|
|
||||||
} else {
|
|
||||||
uint32_t resolvedTex = NSP->getTextureId(node->TexId);
|
|
||||||
v.Tex = resolvedTex;
|
|
||||||
baseTextureCache.emplace(node->TexId, resolvedTex);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
v.Tex = node->TexId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(v.Tex == 0)
|
|
||||||
goto node_done;
|
|
||||||
|
|
||||||
// Рендерим обычный кубоид
|
// Рендерим обычный кубоид
|
||||||
// XZ+Y
|
// XZ+Y
|
||||||
@@ -700,58 +688,6 @@ void ChunkMeshGenerator::run(uint8_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
node_done:
|
node_done:
|
||||||
if(debugMeshEnabled) {
|
|
||||||
const bool emitted = result.NodeVertexs.size() > vertexStart;
|
|
||||||
if(emitted) {
|
|
||||||
generatedColumnX[x] = 1;
|
|
||||||
generatedColumnY[y] = 1;
|
|
||||||
generatedColumnZ[z] = 1;
|
|
||||||
} else {
|
|
||||||
const bool hasRenderable = (node->NodestateId != 0) || (node->TexId != 0);
|
|
||||||
if(hasRenderable && fullCovered != 0b111111) {
|
|
||||||
uint32_t warnIndex = debugMeshWarnCount.fetch_add(1);
|
|
||||||
if(warnIndex < 16) {
|
|
||||||
LOG.warn() << "Missing node geometry at chunk " << int(pos[0]) << ','
|
|
||||||
<< int(pos[1]) << ',' << int(pos[2])
|
|
||||||
<< " local " << x << ',' << y << ',' << z
|
|
||||||
<< " nodeId " << nodeData.NodeId
|
|
||||||
<< " meta " << int(nodeData.Meta)
|
|
||||||
<< " covered " << fullCovered
|
|
||||||
<< " tex " << node->TexId
|
|
||||||
<< " nodestate " << node->NodestateId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(debugMeshEnabled) {
|
|
||||||
auto collectMissing = [](const std::array<uint8_t, 16>& expected,
|
|
||||||
const std::array<uint8_t, 16>& generated) {
|
|
||||||
std::string res;
|
|
||||||
for(int i = 0; i < 16; i++) {
|
|
||||||
if(expected[i] && !generated[i]) {
|
|
||||||
if(!res.empty())
|
|
||||||
res += ',';
|
|
||||||
res += std::to_string(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string missingX = collectMissing(expectedColumnX, generatedColumnX);
|
|
||||||
std::string missingY = collectMissing(expectedColumnY, generatedColumnY);
|
|
||||||
std::string missingZ = collectMissing(expectedColumnZ, generatedColumnZ);
|
|
||||||
if(!missingX.empty() || !missingY.empty() || !missingZ.empty()) {
|
|
||||||
uint32_t warnIndex = debugMeshWarnCount.fetch_add(1);
|
|
||||||
if(warnIndex < 16) {
|
|
||||||
LOG.warn() << "Missing mesh columns at chunk " << int(pos[0]) << ','
|
|
||||||
<< int(pos[1]) << ',' << int(pos[2])
|
|
||||||
<< " missingX[" << missingX << "]"
|
|
||||||
<< " missingY[" << missingY << "]"
|
|
||||||
<< " missingZ[" << missingZ << "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Вычислить индексы и сократить вершины
|
// Вычислить индексы и сократить вершины
|
||||||
@@ -1700,9 +1636,10 @@ void VulkanRenderSession::tickSync(TickSyncData& data) {
|
|||||||
for(AssetsNodestate id : changedNodestates)
|
for(AssetsNodestate id : changedNodestates)
|
||||||
changed.insert(id);
|
changed.insert(id);
|
||||||
|
|
||||||
for(const auto& [nodeId, def] : ServerSession->Profiles.DefNode) {
|
for(const auto& [nodeId, def] : ServerSession->Profiles.DefNodes) {
|
||||||
if(changed.contains(def.NodestateId))
|
if(const AssetsNodestate* ptr = std::get_if<AssetsNodestate>(&def.RenderStates))
|
||||||
mcpData.ChangedNodes.push_back(nodeId);
|
if(changed.contains(*ptr))
|
||||||
|
mcpData.ChangedNodes.push_back(nodeId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -254,26 +254,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
static std::atomic<uint32_t> debugModelLogCount = 0;
|
size_t vertexCount = 0;
|
||||||
uint32_t idx = debugModelLogCount.fetch_add(1);
|
for(const auto& [_, verts] : model.Vertecies)
|
||||||
if(idx < 128) {
|
vertexCount += verts.size();
|
||||||
size_t vertexCount = 0;
|
LOG.debug() << "Model loaded id=" << key
|
||||||
for(const auto& [_, verts] : model.Vertecies)
|
<< " verts=" << vertexCount
|
||||||
vertexCount += verts.size();
|
<< " texKeys=" << model.TextureKeys.size()
|
||||||
LOG.debug() << "Model loaded id=" << key
|
<< " pipelines=" << header.TexturePipelines.size();
|
||||||
<< " verts=" << vertexCount
|
|
||||||
<< " texKeys=" << model.TextureKeys.size()
|
|
||||||
<< " pipelines=" << header.TexturePipelines.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(model.Vertecies.empty()) {
|
|
||||||
static std::atomic<uint32_t> debugEmptyModelLogCount = 0;
|
|
||||||
uint32_t idx = debugEmptyModelLogCount.fetch_add(1);
|
|
||||||
if(idx < 128) {
|
|
||||||
LOG.warn() << "Model has empty geometry id=" << key
|
|
||||||
<< " pipelines=" << header.TexturePipelines.size();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Models.insert_or_assign(key, std::move(model));
|
Models.insert_or_assign(key, std::move(model));
|
||||||
|
|||||||
@@ -161,8 +161,7 @@ public:
|
|||||||
// reverse читаем под shared lock
|
// reverse читаем под shared lock
|
||||||
std::shared_lock rlk(_ReverseMutex[t]);
|
std::shared_lock rlk(_ReverseMutex[t]);
|
||||||
for(ResourceId id : new_ids) {
|
for(ResourceId id : new_ids) {
|
||||||
// id=0 не бывает в newlyInserted
|
const std::size_t idx = static_cast<std::size_t>(id);
|
||||||
const std::size_t idx = static_cast<std::size_t>(id - 1);
|
|
||||||
if(idx >= _Reverse[t].size()) {
|
if(idx >= _Reverse[t].size()) {
|
||||||
// теоретически не должно случаться (мы пишем reverse до push в log)
|
// теоретически не должно случаться (мы пишем reverse до push в log)
|
||||||
continue;
|
continue;
|
||||||
@@ -175,8 +174,7 @@ public:
|
|||||||
rlk.unlock();
|
rlk.unlock();
|
||||||
|
|
||||||
// 3) дописать в IdToDK (для новых клиентов)
|
// 3) дописать в IdToDK (для новых клиентов)
|
||||||
// Важно: IdToDK[0] уже содержит "core/none" как элемент 0.
|
IdToDK[t].append_range(result[t]);
|
||||||
IdToDK[t].append_range(result[t]); // C++23
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ enum struct ToClient : uint8_t {
|
|||||||
AssetsInitSend, // Начало отправки запрошенного клиентом ресурса
|
AssetsInitSend, // Начало отправки запрошенного клиентом ресурса
|
||||||
AssetsNextSend, // Продолжение отправки ресурса
|
AssetsNextSend, // Продолжение отправки ресурса
|
||||||
|
|
||||||
|
DefinitionsFull, // Полная информация о профилях контента
|
||||||
DefinitionsUpdate, // Обновление и потеря профилей контента (воксели, ноды, сущности, миры, ...)
|
DefinitionsUpdate, // Обновление и потеря профилей контента (воксели, ноды, сущности, миры, ...)
|
||||||
|
|
||||||
ChunkVoxels, // Обновление вокселей чанка
|
ChunkVoxels, // Обновление вокселей чанка
|
||||||
|
|||||||
@@ -46,6 +46,28 @@ public:
|
|||||||
Out_applyResourcesUpdate applyResourcesUpdate(Out_checkAndPrepareResourcesUpdate& orr) {
|
Out_applyResourcesUpdate applyResourcesUpdate(Out_checkAndPrepareResourcesUpdate& orr) {
|
||||||
Out_applyResourcesUpdate result = AssetsPreloader::applyResourcesUpdate(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) {
|
for(auto& [hash, data] : orr.NewHeadless) {
|
||||||
Resources.emplace(hash, ResourceHashData{0, std::make_shared<std::u8string>(std::move(data))});
|
Resources.emplace(hash, ResourceHashData{0, std::make_shared<std::u8string>(std::move(data))});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "ContentManager.hpp"
|
#include "ContentManager.hpp"
|
||||||
#include "Common/Abstract.hpp"
|
#include "Common/Abstract.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <optional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace LV::Server {
|
namespace LV::Server {
|
||||||
|
|
||||||
@@ -12,13 +14,22 @@ ContentManager::ContentManager(AssetsManager& am)
|
|||||||
ContentManager::~ContentManager() = default;
|
ContentManager::~ContentManager() = default;
|
||||||
|
|
||||||
void ContentManager::registerBase_Node(ResourceId id, const std::string& domain, const std::string& key, const sol::table& profile) {
|
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);
|
std::optional<DefNode_Base>* basePtr;
|
||||||
if(!node)
|
|
||||||
node.emplace();
|
|
||||||
|
|
||||||
DefNode& def = *node;
|
{
|
||||||
def.Domain = domain;
|
size_t entryIndex = id / TableEntry<DefNode_Base>::ChunkSize;
|
||||||
def.Key = key;
|
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");
|
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)
|
void ContentManager::registerBase(EnumDefContent type, const std::string& domain, const std::string& key, const sol::table& profile)
|
||||||
{
|
{
|
||||||
ResourceId id = getId(type, domain, key);
|
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)
|
if(type == EnumDefContent::Node)
|
||||||
registerBase_Node(id, domain, key, profile);
|
registerBase_Node(id, domain, key, profile);
|
||||||
@@ -122,11 +133,54 @@ void ContentManager::unRegisterModifier(EnumDefContent type, const std::string&
|
|||||||
ProfileChanges[(int) type].push_back(id);
|
ProfileChanges[(int) type].push_back(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentManager::markAllProfilesDirty(EnumDefContent type) {
|
// void ContentManager::markAllProfilesDirty(EnumDefContent type) {
|
||||||
const auto &table = this->idToDK()[(int) type];
|
// const auto &table = this->idToDK()[(int) type];
|
||||||
size_t counter = 0;
|
// size_t counter = 0;
|
||||||
for(const auto& [domain, key] : table) {
|
// for(const auto& [domain, key] : table) {
|
||||||
ProfileChanges[static_cast<size_t>(type)].push_back(counter++);
|
// 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;
|
Out_buildEndProfiles result;
|
||||||
|
|
||||||
for(int type = 0; type < (int) EnumDefContent::MAX_ENUM; type++) {
|
for(int type = 0; type < (int) EnumDefContent::MAX_ENUM; type++) {
|
||||||
|
std::shared_lock lock(Profiles_Mtx[type]);
|
||||||
auto& keys = ProfileChanges[type];
|
auto& keys = ProfileChanges[type];
|
||||||
std::sort(keys.begin(), keys.end());
|
std::sort(keys.begin(), keys.end());
|
||||||
auto iterErase = std::unique(keys.begin(), keys.end());
|
auto iterErase = std::unique(keys.begin(), keys.end());
|
||||||
keys.erase(iterErase, 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;
|
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 "Common/Abstract.hpp"
|
||||||
#include "AssetsManager.hpp"
|
#include "AssetsManager.hpp"
|
||||||
#include "Common/IdProvider.hpp"
|
#include "Common/IdProvider.hpp"
|
||||||
|
#include "Common/Net.hpp"
|
||||||
|
#include "TOSLib.hpp"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <sol/table.hpp>
|
#include <sol/table.hpp>
|
||||||
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
||||||
namespace LV::Server {
|
namespace LV::Server {
|
||||||
|
|
||||||
struct DefVoxel_Base { };
|
struct ResourceBase {
|
||||||
struct DefNode_Base { };
|
std::string Domain, Key;
|
||||||
struct DefWorld_Base { };
|
};
|
||||||
struct DefPortal_Base { };
|
|
||||||
struct DefEntity_Base { };
|
class ContentManager;
|
||||||
struct DefItem_Base { };
|
|
||||||
|
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 DefVoxel_Mod { };
|
||||||
struct DefNode_Mod { };
|
struct DefNode_Mod { };
|
||||||
@@ -25,20 +67,57 @@ struct DefPortal_Mod { };
|
|||||||
struct DefEntity_Mod { };
|
struct DefEntity_Mod { };
|
||||||
struct DefItem_Mod { };
|
struct DefItem_Mod { };
|
||||||
|
|
||||||
struct ResourceBase {
|
struct DefVoxel_Base {
|
||||||
std::string Domain, Key;
|
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_Base {
|
||||||
struct DefNode : public ResourceBase {
|
private:
|
||||||
AssetsNodestate NodestateId;
|
friend ContentManager;
|
||||||
std::vector<AssetsModel> ModelDeps;
|
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 {
|
||||||
std::vector<AssetsTexture> TextureDeps;
|
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
|
DK to id
|
||||||
@@ -114,7 +193,7 @@ public:
|
|||||||
MAX_ENUM
|
MAX_ENUM
|
||||||
> DKToId;
|
> 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<DefNodeId, std::optional<DefNode>*> Profiles_Node;
|
||||||
std::unordered_map<DefWorldId, std::optional<DefWorld>*> Profiles_World;
|
std::unordered_map<DefWorldId, std::optional<DefWorld>*> Profiles_World;
|
||||||
std::unordered_map<DefPortalId, std::optional<DefPortal>*> Profiles_Portal;
|
std::unordered_map<DefPortalId, std::optional<DefPortal>*> Profiles_Portal;
|
||||||
@@ -133,16 +212,77 @@ public:
|
|||||||
void registerModifier(EnumDefContent type, const std::string& mod, const std::string& domain, const std::string& key, const sol::table& profile);
|
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 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;
|
std::vector<ResourceId> collectProfileIds(EnumDefContent type) const;
|
||||||
// Компилирует изменённые профили
|
// Компилирует изменённые профили
|
||||||
struct Out_buildEndProfiles {
|
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();
|
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) {
|
std::optional<DefVoxel>& getEntry_Voxel(ResourceId resId) {
|
||||||
std::shared_lock mtx(Profiles_Mtx[static_cast<size_t>(EnumDefContent::Voxel)]);
|
std::shared_lock mtx(Profiles_Mtx[static_cast<size_t>(EnumDefContent::Voxel)]);
|
||||||
@@ -278,17 +418,19 @@ private:
|
|||||||
void registerBase_World(ResourceId id, const std::string& domain, const std::string& key, const sol::table& profile);
|
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);
|
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";
|
TOS::Logger LOG = "Server>ContentManager";
|
||||||
AssetsManager& AM;
|
AssetsManager& AM;
|
||||||
|
|
||||||
// Профили зарегистрированные модами
|
// Профили зарегистрированные модами
|
||||||
std::vector<std::unique_ptr<TableEntry<DefVoxel>>> Profiles_Base_Voxel;
|
std::vector<std::unique_ptr<TableEntry<DefVoxel_Base>>> Profiles_Base_Voxel;
|
||||||
std::vector<std::unique_ptr<TableEntry<DefNode>>> Profiles_Base_Node;
|
std::vector<std::unique_ptr<TableEntry<DefNode_Base>>> Profiles_Base_Node;
|
||||||
std::vector<std::unique_ptr<TableEntry<DefWorld>>> Profiles_Base_World;
|
std::vector<std::unique_ptr<TableEntry<DefWorld_Base>>> Profiles_Base_World;
|
||||||
std::vector<std::unique_ptr<TableEntry<DefPortal>>> Profiles_Base_Portal;
|
std::vector<std::unique_ptr<TableEntry<DefPortal_Base>>> Profiles_Base_Portal;
|
||||||
std::vector<std::unique_ptr<TableEntry<DefEntity>>> Profiles_Base_Entity;
|
std::vector<std::unique_ptr<TableEntry<DefEntity_Base>>> Profiles_Base_Entity;
|
||||||
std::vector<std::unique_ptr<TableEntry<DefItem>>> Profiles_Base_Item;
|
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;
|
uint8_t kMetaGrass = 1;
|
||||||
DefNodeId kNodeDirt = lru.getIdNode("test", "dirt");
|
DefNodeId kNodeDirt = lru.getIdNode("test", "dirt");
|
||||||
DefNodeId kNodeStone = lru.getIdNode("test", "stone");
|
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 kNodeLeaves = lru.getIdNode("test", "leaves");
|
||||||
DefNodeId kNodeLava = lru.getIdNode("test", "lava");
|
DefNodeId kNodeLava = lru.getIdNode("test", "lava");
|
||||||
DefNodeId kNodeWater = lru.getIdNode("test", "water");
|
DefNodeId kNodeWater = lru.getIdNode("test", "water");
|
||||||
@@ -1370,7 +1370,6 @@ void GameServer::init(fs::path worldPath) {
|
|||||||
|
|
||||||
Content.CM.buildEndProfiles();
|
Content.CM.buildEndProfiles();
|
||||||
|
|
||||||
|
|
||||||
LOG.info() << "Инициализация";
|
LOG.info() << "Инициализация";
|
||||||
initLua();
|
initLua();
|
||||||
pushEvent("init");
|
pushEvent("init");
|
||||||
@@ -1615,6 +1614,7 @@ void GameServer::stepConnections() {
|
|||||||
std::vector<Net::Packet> packets;
|
std::vector<Net::Packet> packets;
|
||||||
packets.push_back(RemoteClient::makePacket_informateAssets_DK(Content.AM.idToDK()));
|
packets.push_back(RemoteClient::makePacket_informateAssets_DK(Content.AM.idToDK()));
|
||||||
packets.push_back(RemoteClient::makePacket_informateAssets_HH(Content.AM.collectHashBindings(), lost));
|
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) {
|
for(const std::shared_ptr<RemoteClient>& client : newClients) {
|
||||||
if(!packets.empty()) {
|
if(!packets.empty()) {
|
||||||
@@ -1685,7 +1685,8 @@ void GameServer::reloadMods() {
|
|||||||
{
|
{
|
||||||
// TODO: перезагрузка модов
|
// TODO: перезагрузка модов
|
||||||
|
|
||||||
Content.CM.buildEndProfiles();
|
ContentManager::Out_buildEndProfiles out = Content.CM.buildEndProfiles();
|
||||||
|
packetsToSend.append_range(RemoteClient::makePackets_informateDefContentUpdate(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.info() << "Перезагрузка ассетов";
|
LOG.info() << "Перезагрузка ассетов";
|
||||||
|
|||||||
@@ -94,24 +94,122 @@ Net::Packet RemoteClient::makePacket_informateAssets_HH(
|
|||||||
return pack;
|
return pack;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Net::Packet> RemoteClient::makePackets_sendDefContentUpdate(
|
std::vector<Net::Packet> RemoteClient::makePackets_informateDefContent_Full(
|
||||||
std::array<
|
const ContentManager::Out_getAllProfiles& profiles
|
||||||
std::vector<
|
) {
|
||||||
std::pair<
|
std::vector<Net::Packet> packets;
|
||||||
ResourceId, // Идентификатор профиля
|
Net::Packet pack;
|
||||||
std::u8string // Двоичный формат профиля
|
|
||||||
>
|
auto check = [&](size_t needSize) {
|
||||||
>,
|
if(pack.size()+needSize > 65500) {
|
||||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
packets.emplace_back(std::move(pack));
|
||||||
> newOrUpdate, // Новые или изменённые
|
pack.clear();
|
||||||
std::array<
|
}
|
||||||
std::vector<ResourceId>,
|
};
|
||||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
|
||||||
> lost, // Потерянные профили
|
pack << (uint8_t) ToClient::DefinitionsFull;
|
||||||
std::array<
|
|
||||||
std::vector<std::pair<std::string, std::string>>,
|
{
|
||||||
static_cast<size_t>(EnumDefContent::MAX_ENUM)
|
pack << (uint32_t) profiles.ProfilesIds_Voxel.size();
|
||||||
> idToDK // Новые привязки
|
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;
|
std::vector<Net::Packet> packets;
|
||||||
Net::Packet pack;
|
Net::Packet pack;
|
||||||
@@ -124,33 +222,86 @@ std::vector<Net::Packet> RemoteClient::makePackets_sendDefContentUpdate(
|
|||||||
};
|
};
|
||||||
|
|
||||||
pack << (uint8_t) ToClient::DefinitionsUpdate;
|
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 << uint32_t(profiles.ChangedProfiles_Voxel.size());
|
||||||
pack << id << (const std::string&) data;
|
for(const auto& [id, profile] : profiles.ChangedProfiles_Voxel) {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 << id;
|
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(profiles.ChangedProfiles_Node.size());
|
||||||
pack << uint32_t(idToDK[type].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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(const auto& [domain, key] : idToDK[type]) {
|
{
|
||||||
check(domain.size() + key.size() + 8);
|
pack << uint32_t(profiles.ChangedProfiles_World.size());
|
||||||
pack << key << domain;
|
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
|
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(
|
static std::vector<Net::Packet> makePackets_informateDefContentUpdate(
|
||||||
std::array<
|
const ContentManager::Out_buildEndProfiles& profiles
|
||||||
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 // Новые привязки
|
|
||||||
);
|
);
|
||||||
|
|
||||||
void onUpdate();
|
void onUpdate();
|
||||||
|
|||||||
Reference in New Issue
Block a user