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

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

View File

@@ -1,9 +1,13 @@
#pragma once
#include "Common/Net.hpp"
#include <cstdint>
#include <functional>
#include <string>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <variant>
#include <vector>
#include <Common/Abstract.hpp>
@@ -149,14 +153,6 @@ struct WorldInfo {
std::unordered_map<Pos::GlobalRegion, Region> Regions;
};
struct VoxelInfo {
};
struct NodeInfo {
};
struct PortalInfo {
};
@@ -168,19 +164,77 @@ struct EntityInfo {
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 DefNode_t {
AssetsNodestate NodestateId = 0;
AssetsTexture TexId = 0;
struct DefWorld {
DefWorld() = default;
DefWorld(const std::u8string_view view) {
}
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 {
@@ -217,12 +271,12 @@ public:
// Используемые профили контента
struct {
std::unordered_map<DefVoxelId, DefVoxel_t> DefVoxel;
std::unordered_map<DefNodeId, DefNode_t> DefNode;
std::unordered_map<DefWorldId, DefWorldInfo> DefWorld;
std::unordered_map<DefPortalId, DefPortalInfo> DefPortal;
std::unordered_map<DefEntityId, DefEntityInfo> DefEntity;
std::unordered_map<DefItemId, DefItemInfo> DefItem;
std::unordered_map<DefVoxelId, DefVoxel> DefVoxels;
std::unordered_map<DefNodeId, DefNode> DefNodes;
std::unordered_map<DefWorldId, DefWorld> DefWorlds;
std::unordered_map<DefPortalId, DefPortal> DefPortals;
std::unordered_map<DefEntityId, DefEntity> DefEntitys;
std::unordered_map<DefItemId, DefItem> DefItems;
} Profiles;
// Видимый контент

View File

@@ -46,7 +46,11 @@ public:
public:
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();
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) {
LOG.info() << "\t" << domains[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);
}
ResourceId reBind(EnumAssets type, ResourceId server) {
return ServerToClientMap[static_cast<size_t>(type)].at(server);
}
void tick() {
// Проверим кеш
std::vector<std::pair<Hash_t, std::optional<Resource>>> resources = Cache->pullReads();

View File

@@ -17,6 +17,7 @@
#include <Common/Packets.hpp>
#include <glm/ext.hpp>
#include <optional>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
@@ -65,12 +66,6 @@ ServerSession::ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSo
{
assert(Socket.get());
Profiles.DefNode[0] = {0};
Profiles.DefNode[1] = {1};
Profiles.DefNode[2] = {2};
Profiles.DefNode[3] = {3};
Profiles.DefNode[4] = {4};
try {
asio::co_spawn(ioc, run(AUC.use()), asio::detached);
// 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::unordered_map<DefNodeId, DefNode_t> profile_Node_AddOrChange;
std::unordered_map<DefNodeId, DefNode> profile_Node_AddOrChange;
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::unordered_map<DefPortalId, void*> profile_Portal_AddOrChange;
std::unordered_map<DefPortalId, DefPortal> profile_Portal_AddOrChange;
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::unordered_map<DefItemId, void*> profile_Item_AddOrChange;
std::unordered_map<DefItemId, DefItem> profile_Item_AddOrChange;
std::vector<DefItemId> profile_Item_Lost;
std::unordered_map<EntityId_t, EntityInfo> entity_AddOrChange;
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)
profile_Voxel_Lost.erase(iter);
profile.reBind(
[&](EnumAssets type, ResourceId server) {
return AM.reBind(type, server);
}
);
profile_Voxel_AddOrChange[id] = profile;
}
@@ -401,6 +403,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
if(iter != profile_Node_Lost.end() && *iter == id)
profile_Node_Lost.erase(iter);
profile.reBind(
[&](EnumAssets type, ResourceId server) {
return AM.reBind(type, server);
}
);
profile_Node_AddOrChange[id] = profile;
}
@@ -420,6 +428,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
if(iter != profile_World_Lost.end() && *iter == id)
profile_World_Lost.erase(iter);
profile.reBind(
[&](EnumAssets type, ResourceId server) {
return AM.reBind(type, server);
}
);
profile_World_AddOrChange[id] = profile;
}
@@ -439,6 +453,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
if(iter != profile_Portal_Lost.end() && *iter == id)
profile_Portal_Lost.erase(iter);
profile.reBind(
[&](EnumAssets type, ResourceId server) {
return AM.reBind(type, server);
}
);
profile_Portal_AddOrChange[id] = profile;
}
@@ -458,6 +478,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
if(iter != profile_Entity_Lost.end() && *iter == id)
profile_Entity_Lost.erase(iter);
profile.reBind(
[&](EnumAssets type, ResourceId server) {
return AM.reBind(type, server);
}
);
profile_Entity_AddOrChange[id] = profile;
}
@@ -477,6 +503,12 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
if(iter != profile_Item_Lost.end() && *iter == id)
profile_Item_Lost.erase(iter);
profile.reBind(
[&](EnumAssets type, ResourceId server) {
return AM.reBind(type, server);
}
);
profile_Item_AddOrChange[id] = profile;
}
@@ -491,10 +523,10 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
}
{
for(auto& [id, info] : data.Entity_AddOrChange) {
auto iter = std::lower_bound(entity_Lost.begin(), entity_Lost.end(), id);
if(iter != entity_Lost.end() && *iter == id)
entity_Lost.erase(iter);
for(auto& [id, info] : data.Entity_AddOrChange) {
auto iter = std::lower_bound(entity_Lost.begin(), entity_Lost.end(), id);
if(iter != entity_Lost.end() && *iter == id)
entity_Lost.erase(iter);
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());
std::sort(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();
result.AssetsNodestates = std::move(updates.Nodestates);
result.AssetsModels = std::move(updates.Models);
result.AssetsTextures = std::move(updates.Textures);
}
{
AssetsManager::ResourceUpdates updates = AM.pullResourceUpdates();
result.AssetsNodestates = std::move(updates.Nodestates);
result.AssetsModels = std::move(updates.Models);
result.AssetsTextures = std::move(updates.Textures);
}
for(auto& [id, _] : profile_Voxel_AddOrChange)
result.Profiles_ChangeOrAdd[EnumDefContent::Voxel].push_back(id);
result.Profiles_Lost[EnumDefContent::Voxel] = profile_Voxel_Lost;
for(auto& [id, _] : profile_Voxel_AddOrChange)
result.Profiles_ChangeOrAdd[EnumDefContent::Voxel].push_back(id);
result.Profiles_Lost[EnumDefContent::Voxel] = profile_Voxel_Lost;
for(auto& [id, _] : profile_Node_AddOrChange)
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)
result.Chunks_Lost[wId] = std::vector<Pos::GlobalRegion>(regions.begin(), regions.end());
{
for(TickData& data : ticks) {
}
@@ -669,12 +700,23 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
// Применяем изменения по ресурсам, профилям и контенту
// Определения
{
for(auto& [resId, def] : profile_Node_AddOrChange) {
Profiles.DefNode[resId] = def;
}
for(auto& [resId, def] : profile_Entity_AddOrChange) {
Profiles.DefEntity[resId] = def;
}
for(auto& [resId, def] : profile_Voxel_AddOrChange)
Profiles.DefVoxels[resId] = def;
for(auto& [resId, def] : profile_Node_AddOrChange)
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);
}
}
}
// Сущности
@@ -904,6 +945,9 @@ coro<> ServerSession::readPacket(Net::AsyncSocket &sock) {
case ToClient::AssetsNextSend:
co_await rP_AssetsNextSend(sock);
co_return;
case ToClient::DefinitionsFull:
co_await rP_DefinitionsFull(sock);
co_return;
case ToClient::DefinitionsUpdate:
co_await rP_DefinitionsUpdate(sock);
co_return;
@@ -1035,55 +1079,281 @@ coro<> ServerSession::rP_AssetsNextSend(Net::AsyncSocket &sock) {
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) {
static std::atomic<uint32_t> debugDefLogCount = 0;
uint32_t typeCount = co_await sock.read<uint32_t>();
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>();
for(uint32_t i = 0; i < count; ++i) {
ResourceId id = co_await sock.read<ResourceId>();
std::string dataStr = co_await sock.read<std::string>();
(void)dataStr;
if(type == static_cast<uint32_t>(EnumDefContent::Node)) {
DefNode_t def;
def.NodestateId = 0;
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 size;
{
size = 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) {
uint32_t id = co_await sock.read<uint32_t>();
std::string data = co_await sock.read<std::string>();
AsyncContext.ThisTickEntry.Profile_Voxel_AddOrChange.emplace_back(
id,
DefVoxel{
std::u8string_view((const char8_t*) data.data(), data.size())
}
}
);
}
}
{
size = 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) {
uint32_t id = co_await sock.read<uint32_t>();
std::string data = co_await sock.read<std::string>();
AsyncContext.ThisTickEntry.Profile_Node_AddOrChange.emplace_back(
id,
DefNode{
std::u8string_view((const char8_t*) data.data(), data.size())
}
);
}
}
{
size = 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) {
uint32_t id = co_await sock.read<uint32_t>();
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())
}
);
}
}
uint32_t lostCount = co_await sock.read<uint32_t>();
lostCount = std::min<uint32_t>(lostCount, static_cast<uint32_t>(EnumDefContent::MAX_ENUM));
for(uint32_t type = 0; type < lostCount; ++type) {
uint32_t count = co_await sock.read<uint32_t>();
for(uint32_t i = 0; i < count; ++i) {
ResourceId id = co_await sock.read<ResourceId>();
if(type == static_cast<uint32_t>(EnumDefContent::Node))
AsyncContext.ThisTickEntry.Profile_Node_Lost.push_back(id);
}
{
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>());
}
uint32_t dkCount = co_await sock.read<uint32_t>();
dkCount = std::min<uint32_t>(dkCount, static_cast<uint32_t>(EnumDefContent::MAX_ENUM));
for(uint32_t type = 0; type < dkCount; ++type) {
uint32_t count = co_await sock.read<uint32_t>();
for(uint32_t i = 0; i < count; ++i) {
std::string key = co_await sock.read<std::string>();
{
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>();
(void)key;
(void)domain;
std::string key = co_await sock.read<std::string>();
(void) domain;
(void) key;
}
}

View File

@@ -122,17 +122,17 @@ private:
// Полученные с сервера ресурсы
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<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<std::pair<DefWorldId, void*>> Profile_World_AddOrChange;
std::vector<std::pair<DefWorldId, DefWorld>> Profile_World_AddOrChange;
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<std::pair<DefEntityId, DefEntityInfo>> Profile_Entity_AddOrChange;
std::vector<std::pair<DefEntityId, DefEntity>> Profile_Entity_AddOrChange;
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<std::pair<WorldId_t, void*>> Worlds_AddOrChange;
@@ -197,6 +197,7 @@ private:
coro<> rP_AssetsBindHH(Net::AsyncSocket &sock);
coro<> rP_AssetsInitSend(Net::AsyncSocket &sock);
coro<> rP_AssetsNextSend(Net::AsyncSocket &sock);
coro<> rP_DefinitionsFull(Net::AsyncSocket &sock);
coro<> rP_DefinitionsUpdate(Net::AsyncSocket &sock);
coro<> rP_ChunkVoxels(Net::AsyncSocket &sock);
coro<> rP_ChunkNodes(Net::AsyncSocket &sock);

View File

@@ -121,15 +121,15 @@ void ChunkMeshGenerator::run(uint8_t id) {
uint8_t fullNodes[18][18][18];
// Профиль, который используется если на стороне клиента отсутствует нужных профиль
DefNode_t defaultProfileNode;
DefNode defaultProfileNode;
// Кеш запросов профилей нод
std::unordered_map<DefNodeId, const DefNode_t*> profilesNodeCache;
auto getNodeProfile = [&](DefNodeId id) -> const DefNode_t* {
std::unordered_map<DefNodeId, const DefNode*> profilesNodeCache;
auto getNodeProfile = [&](DefNodeId id) -> const DefNode* {
auto iterCache = profilesNodeCache.find(id);
if(iterCache == profilesNodeCache.end()) {
// Промах кеша
auto iterSS = SS->Profiles.DefNode.find(id);
if(iterSS != SS->Profiles.DefNode.end()) {
auto iterSS = SS->Profiles.DefNodes.find(id);
if(iterSS != SS->Profiles.DefNodes.end()) {
return (profilesNodeCache[id] = &iterSS->second);
} else {
// Профиль отсутствует на клиенте
@@ -189,46 +189,50 @@ void ChunkMeshGenerator::run(uint8_t id) {
std::unordered_map<DefNodeId, bool> nodeFullCuboidCache;
auto nodeIsFull = [&](Node node) -> bool {
if(node.NodeId == 0)
return false;
auto iterCache = nodeFullCuboidCache.find(node.Data);
if(iterCache == nodeFullCuboidCache.end()) {
const DefNode_t* profile = getNodeProfile(node.NodeId);
if(profile->TexId != 0) {
return (nodeFullCuboidCache[node.Data] = true);
}
if(NSP && profile->NodestateId != 0 && NSP->hasNodestate(profile->NodestateId)) {
std::unordered_map<std::string, int32_t> states;
int32_t meta = node.Meta;
states.emplace("meta", meta);
const auto routes = NSP->getModelsForNode(profile->NodestateId, metaStatesInfo, states);
bool isFull = !routes.empty();
if(isFull) {
for(const auto& variants : routes) {
for(const auto& [weight, faces] : variants) {
(void)weight;
auto hasFace = [&](EnumFace face) -> bool {
auto iterFace = faces.find(face);
return iterFace != faces.end() && !iterFace->second.empty();
};
if(!hasFace(EnumFace::Up)
|| !hasFace(EnumFace::Down)
|| !hasFace(EnumFace::East)
|| !hasFace(EnumFace::West)
|| !hasFace(EnumFace::South)
|| !hasFace(EnumFace::North))
{
isFull = false;
break;
const DefNode* profile = getNodeProfile(node.NodeId);
if(NSP) {
if(const AssetsNodestate* ptr = std::get_if<AssetsNodestate>(&profile->RenderStates)) {
if(NSP->hasNodestate(*ptr)) {
std::unordered_map<std::string, int32_t> states;
int32_t meta = node.Meta;
states.emplace("meta", meta);
const auto routes = NSP->getModelsForNode(*ptr, metaStatesInfo, states);
bool isFull = !routes.empty();
if(isFull) {
for(const auto& variants : routes) {
for(const auto& [weight, faces] : variants) {
(void)weight;
auto hasFace = [&](EnumFace face) -> bool {
auto iterFace = faces.find(face);
return iterFace != faces.end() && !iterFace->second.empty();
};
if(!hasFace(EnumFace::Up)
|| !hasFace(EnumFace::Down)
|| !hasFace(EnumFace::East)
|| !hasFace(EnumFace::West)
|| !hasFace(EnumFace::South)
|| !hasFace(EnumFace::North))
{
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 {
return iterCache->second;
}
@@ -420,6 +424,10 @@ void ChunkMeshGenerator::run(uint8_t id) {
for(int z = 0; z < 16; z++)
for(int y = 0; y < 16; y++)
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();
int fullCovered = 0;
@@ -433,66 +441,46 @@ void ChunkMeshGenerator::run(uint8_t id) {
if(fullCovered == 0b111111)
continue;
const Node& nodeData = (*chunk)[x+y*16+z*16*16];
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;
}
}
const DefNode* node = getNodeProfile(nodeData.NodeId);
bool usedModel = false;
if(NSP && (node->NodestateId != 0 || NSP->hasNodestate(node->NodestateId))) {
auto iterCache = modelCache.find(nodeData.Data);
if(iterCache == modelCache.end()) {
std::unordered_map<std::string, int32_t> states;
states.emplace("meta", nodeData.Meta);
if(NSP) {
if(const AssetsNodestate* ptr = std::get_if<AssetsNodestate>(&node->RenderStates)) {
if(NSP->hasNodestate(*ptr)) {
auto iterCache = modelCache.find(nodeData.Data);
if(iterCache == modelCache.end()) {
std::unordered_map<std::string, int32_t> states;
states.emplace("meta", nodeData.Meta);
ModelCacheEntry entry;
entry.Routes = NSP->getModelsForNode(node->NodestateId, metaStatesInfo, states);
iterCache = modelCache.emplace(nodeData.Data, std::move(entry)).first;
}
ModelCacheEntry entry;
entry.Routes = NSP->getModelsForNode(*ptr, metaStatesInfo, states);
iterCache = modelCache.emplace(nodeData.Data, std::move(entry)).first;
}
if(!iterCache->second.Routes.empty()) {
uint32_t seed = uint32_t(nodeData.Data) * 2654435761u;
seed ^= uint32_t(x) * 73856093u;
seed ^= uint32_t(y) * 19349663u;
seed ^= uint32_t(z) * 83492791u;
if(!iterCache->second.Routes.empty()) {
uint32_t seed = uint32_t(nodeData.Data) * 2654435761u;
seed ^= uint32_t(x) * 73856093u;
seed ^= uint32_t(y) * 19349663u;
seed ^= uint32_t(z) * 83492791u;
for(size_t routeIndex = 0; routeIndex < iterCache->second.Routes.size(); routeIndex++) {
const auto& variants = iterCache->second.Routes[routeIndex];
const auto* faces = pickVariant(variants, seed + uint32_t(routeIndex) * 374761393u);
if(faces)
appendModel(*faces, fullCovered, x, y, z);
for(size_t routeIndex = 0; routeIndex < iterCache->second.Routes.size(); routeIndex++) {
const auto& variants = iterCache->second.Routes[routeIndex];
const auto* faces = pickVariant(variants, seed + uint32_t(routeIndex) * 374761393u);
if(faces)
appendModel(*faces, fullCovered, x, y, z);
}
usedModel = true;
}
}
usedModel = true;
}
}
if(usedModel)
goto node_done;
if(NSP && node->TexId != 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;
v.Tex = 0;
// Рендерим обычный кубоид
// XZ+Y
@@ -700,58 +688,6 @@ void ChunkMeshGenerator::run(uint8_t id) {
}
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)
changed.insert(id);
for(const auto& [nodeId, def] : ServerSession->Profiles.DefNode) {
if(changed.contains(def.NodestateId))
mcpData.ChangedNodes.push_back(nodeId);
for(const auto& [nodeId, def] : ServerSession->Profiles.DefNodes) {
if(const AssetsNodestate* ptr = std::get_if<AssetsNodestate>(&def.RenderStates))
if(changed.contains(*ptr))
mcpData.ChangedNodes.push_back(nodeId);
}
}

View File

@@ -254,26 +254,13 @@ public:
}
{
static std::atomic<uint32_t> debugModelLogCount = 0;
uint32_t idx = debugModelLogCount.fetch_add(1);
if(idx < 128) {
size_t vertexCount = 0;
for(const auto& [_, verts] : model.Vertecies)
vertexCount += verts.size();
LOG.debug() << "Model loaded id=" << key
<< " 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();
}
size_t vertexCount = 0;
for(const auto& [_, verts] : model.Vertecies)
vertexCount += verts.size();
LOG.debug() << "Model loaded id=" << key
<< " verts=" << vertexCount
<< " texKeys=" << model.TextureKeys.size()
<< " pipelines=" << header.TexturePipelines.size();
}
Models.insert_or_assign(key, std::move(model));