Эта версия компилится
This commit is contained in:
@@ -48,7 +48,7 @@ class Entity {
|
||||
public:
|
||||
// PosQuat
|
||||
WorldId_t WorldId;
|
||||
PortalId_t LastUsedPortal;
|
||||
// PortalId LastUsedPortal;
|
||||
Pos::Object Pos;
|
||||
glm::quat Quat;
|
||||
static constexpr uint16_t HP_BS = 4096, HP_BS_Bit = 12;
|
||||
@@ -66,8 +66,8 @@ public:
|
||||
// Подгрузка двоичных ресурсов
|
||||
virtual void onBinaryResourceAdd(std::vector<Hash_t>) = 0;
|
||||
|
||||
virtual void onContentDefinesAdd(std::unordered_map<EnumDefContent, std::vector<ResourceId_t>>) = 0;
|
||||
virtual void onContentDefinesLost(std::unordered_map<EnumDefContent, std::vector<ResourceId_t>>) = 0;
|
||||
virtual void onContentDefinesAdd(std::unordered_map<EnumDefContent, std::vector<ResourceId>>) = 0;
|
||||
virtual void onContentDefinesLost(std::unordered_map<EnumDefContent, std::vector<ResourceId>>) = 0;
|
||||
|
||||
// Сообщаем об изменившихся чанках
|
||||
virtual void onChunksChange(WorldId_t worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalRegion> &remove) = 0;
|
||||
@@ -149,17 +149,17 @@ public:
|
||||
} Binary;
|
||||
|
||||
struct {
|
||||
std::unordered_map<DefVoxelId_t, DefVoxel_t> DefVoxel;
|
||||
std::unordered_map<DefNodeId_t, DefNode_t> DefNode;
|
||||
std::unordered_map<DefWorldId_t, DefWorldInfo> DefWorld;
|
||||
std::unordered_map<DefPortalId_t, DefPortalInfo> DefPortal;
|
||||
std::unordered_map<DefEntityId_t, DefEntityInfo> DefEntity;
|
||||
std::unordered_map<DefItemId_t, DefItemInfo> DefItem;
|
||||
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;
|
||||
} Registry;
|
||||
|
||||
struct {
|
||||
std::unordered_map<WorldId_t, WorldInfo> Worlds;
|
||||
std::unordered_map<PortalId_t, PortalInfo> Portals;
|
||||
// std::unordered_map<PortalId_t, PortalInfo> Portals;
|
||||
std::unordered_map<EntityId_t, EntityInfo> Entityes;
|
||||
} Data;
|
||||
|
||||
|
||||
@@ -51,38 +51,38 @@ struct PP_Content_RegionRemove : public ParsedPacket {
|
||||
};
|
||||
|
||||
struct PP_Definition_Voxel : public ParsedPacket {
|
||||
DefVoxelId_t Id;
|
||||
DefVoxelId Id;
|
||||
DefVoxel_t Def;
|
||||
|
||||
PP_Definition_Voxel(DefVoxelId_t id, DefVoxel_t def)
|
||||
PP_Definition_Voxel(DefVoxelId id, DefVoxel_t def)
|
||||
: ParsedPacket(ToClient::L1::Definition, (uint8_t) ToClient::L2Definition::Voxel),
|
||||
Id(id), Def(def)
|
||||
{}
|
||||
};
|
||||
|
||||
struct PP_Definition_FreeVoxel : public ParsedPacket {
|
||||
DefVoxelId_t Id;
|
||||
DefVoxelId Id;
|
||||
|
||||
PP_Definition_FreeVoxel(DefVoxelId_t id)
|
||||
PP_Definition_FreeVoxel(DefVoxelId id)
|
||||
: ParsedPacket(ToClient::L1::Definition, (uint8_t) ToClient::L2Definition::FreeVoxel),
|
||||
Id(id)
|
||||
{}
|
||||
};
|
||||
|
||||
struct PP_Definition_Node : public ParsedPacket {
|
||||
DefNodeId_t Id;
|
||||
DefNodeId Id;
|
||||
DefNode_t Def;
|
||||
|
||||
PP_Definition_Node(DefNodeId_t id, DefNode_t def)
|
||||
PP_Definition_Node(DefNodeId id, DefNode_t def)
|
||||
: ParsedPacket(ToClient::L1::Definition, (uint8_t) ToClient::L2Definition::Node),
|
||||
Id(id), Def(def)
|
||||
{}
|
||||
};
|
||||
|
||||
struct PP_Definition_FreeNode : public ParsedPacket {
|
||||
DefNodeId_t Id;
|
||||
DefNodeId Id;
|
||||
|
||||
PP_Definition_FreeNode(DefNodeId_t id)
|
||||
PP_Definition_FreeNode(DefNodeId id)
|
||||
: ParsedPacket(ToClient::L1::Definition, (uint8_t) ToClient::L2Definition::FreeNode),
|
||||
Id(id)
|
||||
{}
|
||||
@@ -331,8 +331,8 @@ void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
||||
|
||||
{
|
||||
std::unordered_map<WorldId_t, std::tuple<std::unordered_set<Pos::GlobalChunk>, std::unordered_set<Pos::GlobalRegion>>> changeOrAddList_removeList;
|
||||
std::unordered_map<EnumDefContent, std::vector<ResourceId_t>> onContentDefinesAdd;
|
||||
std::unordered_map<EnumDefContent, std::vector<ResourceId_t>> onContentDefinesLost;
|
||||
std::unordered_map<EnumDefContent, std::vector<ResourceId>> onContentDefinesAdd;
|
||||
std::unordered_map<EnumDefContent, std::vector<ResourceId>> onContentDefinesLost;
|
||||
|
||||
// Пакеты
|
||||
ParsedPacket *pack;
|
||||
@@ -601,30 +601,30 @@ coro<> ServerSession::rP_Definition(Net::AsyncSocket &sock) {
|
||||
|
||||
switch((ToClient::L2Definition) second) {
|
||||
case ToClient::L2Definition::World: {
|
||||
DefWorldId_t cdId = co_await sock.read<DefWorldId_t>();
|
||||
DefWorldId cdId = co_await sock.read<DefWorldId>();
|
||||
|
||||
co_return;
|
||||
}
|
||||
case ToClient::L2Definition::FreeWorld: {
|
||||
DefWorldId_t cdId = co_await sock.read<DefWorldId_t>();
|
||||
DefWorldId cdId = co_await sock.read<DefWorldId>();
|
||||
|
||||
co_return;
|
||||
}
|
||||
case ToClient::L2Definition::Voxel: {
|
||||
DefVoxelId_t cdId = co_await sock.read<DefVoxelId_t>();
|
||||
DefVoxelId cdId = co_await sock.read<DefVoxelId>();
|
||||
|
||||
co_return;
|
||||
}
|
||||
case ToClient::L2Definition::FreeVoxel: {
|
||||
DefVoxelId_t cdId = co_await sock.read<DefVoxelId_t>();
|
||||
DefVoxelId cdId = co_await sock.read<DefVoxelId>();
|
||||
|
||||
co_return;
|
||||
}
|
||||
case ToClient::L2Definition::Node:
|
||||
{
|
||||
DefNodeId_t id;
|
||||
DefNodeId id;
|
||||
DefNode_t def;
|
||||
id = co_await sock.read<DefNodeId_t>();
|
||||
id = co_await sock.read<DefNodeId>();
|
||||
def.DrawType = (DefNode_t::EnumDrawType) co_await sock.read<uint8_t>();
|
||||
for(int iter = 0; iter < 6; iter++) {
|
||||
auto &pl = def.Texs[iter].Pipeline;
|
||||
@@ -643,7 +643,7 @@ coro<> ServerSession::rP_Definition(Net::AsyncSocket &sock) {
|
||||
}
|
||||
case ToClient::L2Definition::FreeNode:
|
||||
{
|
||||
DefNodeId_t id = co_await sock.read<DefNodeId_t>();
|
||||
DefNodeId id = co_await sock.read<DefNodeId>();
|
||||
|
||||
PP_Definition_FreeNode *packet = new PP_Definition_FreeNode(
|
||||
id
|
||||
|
||||
@@ -24,8 +24,8 @@ void VulkanRenderSession::ThreadVertexObj_t::run() {
|
||||
LOG.debug() << "Старт потока подготовки чанков к рендеру";
|
||||
|
||||
// Контейнеры событий
|
||||
std::vector<DefVoxelId_t> changedDefines_Voxel;
|
||||
std::vector<DefNodeId_t> changedDefines_Node;
|
||||
std::vector<DefVoxelId> changedDefines_Voxel;
|
||||
std::vector<DefNodeId> changedDefines_Node;
|
||||
std::unordered_map<WorldId_t, std::vector<Pos::GlobalChunk>> changedContent_Chunk;
|
||||
std::unordered_map<WorldId_t, std::vector<Pos::GlobalRegion>> changedContent_RegionRemove;
|
||||
|
||||
@@ -991,11 +991,11 @@ void VulkanRenderSession::onBinaryResourceAdd(std::vector<Hash_t>) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onContentDefinesAdd(std::unordered_map<EnumDefContent, std::vector<ResourceId_t>>) {
|
||||
void VulkanRenderSession::onContentDefinesAdd(std::unordered_map<EnumDefContent, std::vector<ResourceId>>) {
|
||||
|
||||
}
|
||||
|
||||
void VulkanRenderSession::onContentDefinesLost(std::unordered_map<EnumDefContent, std::vector<ResourceId_t>>) {
|
||||
void VulkanRenderSession::onContentDefinesLost(std::unordered_map<EnumDefContent, std::vector<ResourceId>>) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -96,9 +96,9 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent {
|
||||
|
||||
struct ChunkObj_t {
|
||||
// Сортированный список уникальных значений
|
||||
std::vector<DefVoxelId_t> VoxelDefines;
|
||||
std::vector<DefVoxelId> VoxelDefines;
|
||||
VertexPool<VoxelVertexPoint>::Pointer VoxelPointer;
|
||||
std::vector<DefNodeId_t> NodeDefines;
|
||||
std::vector<DefNodeId> NodeDefines;
|
||||
VertexPool<NodeVertexStatic>::Pointer NodePointer;
|
||||
};
|
||||
|
||||
@@ -129,7 +129,7 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent {
|
||||
|
||||
// Сюда входят добавленные/изменённые/удалённые определения нод и вокселей
|
||||
// Чтобы перерисовать чанки, связанные с ними
|
||||
void onContentDefinesChange(const std::vector<DefVoxelId_t>& voxels, const std::vector<DefNodeId_t>& nodes) {
|
||||
void onContentDefinesChange(const std::vector<DefVoxelId>& voxels, const std::vector<DefNodeId>& nodes) {
|
||||
ChangedDefines_Voxel.insert(ChangedDefines_Voxel.end(), voxels.begin(), voxels.end());
|
||||
ChangedDefines_Node.insert(ChangedDefines_Node.end(), nodes.begin(), nodes.end());
|
||||
}
|
||||
@@ -239,8 +239,8 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent {
|
||||
VertexPool<VoxelVertexPoint> VertexPool_Voxels;
|
||||
VertexPool<NodeVertexStatic> VertexPool_Nodes;
|
||||
// Списки изменённых определений
|
||||
std::vector<DefVoxelId_t> ChangedDefines_Voxel;
|
||||
std::vector<DefNodeId_t> ChangedDefines_Node;
|
||||
std::vector<DefVoxelId> ChangedDefines_Voxel;
|
||||
std::vector<DefNodeId> ChangedDefines_Node;
|
||||
// Список чанков на перерисовку
|
||||
std::unordered_map<WorldId_t, std::vector<Pos::GlobalChunk>> ChangedContent_Chunk;
|
||||
std::unordered_map<WorldId_t, std::vector<Pos::GlobalRegion>> ChangedContent_RegionRemove;
|
||||
@@ -315,7 +315,7 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent {
|
||||
NodeStaticOpaquePipeline = VK_NULL_HANDLE,
|
||||
NodeStaticTransparentPipeline = VK_NULL_HANDLE;
|
||||
|
||||
std::map<BinTextureId_t, uint16_t> ServerToAtlas;
|
||||
std::map<AssetsTexture, uint16_t> ServerToAtlas;
|
||||
|
||||
struct {
|
||||
} External;
|
||||
@@ -338,8 +338,8 @@ public:
|
||||
}
|
||||
|
||||
virtual void onBinaryResourceAdd(std::vector<Hash_t>) override;
|
||||
virtual void onContentDefinesAdd(std::unordered_map<EnumDefContent, std::vector<ResourceId_t>>) override;
|
||||
virtual void onContentDefinesLost(std::unordered_map<EnumDefContent, std::vector<ResourceId_t>>) override;
|
||||
virtual void onContentDefinesAdd(std::unordered_map<EnumDefContent, std::vector<ResourceId>>) override;
|
||||
virtual void onContentDefinesLost(std::unordered_map<EnumDefContent, std::vector<ResourceId>>) override;
|
||||
virtual void onChunksChange(WorldId_t worldId, const std::unordered_set<Pos::GlobalChunk>& changeOrAddList, const std::unordered_set<Pos::GlobalRegion>& remove) override;
|
||||
virtual void setCameraPos(WorldId_t worldId, Pos::Object pos, glm::quat quat) override;
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace LV {
|
||||
|
||||
CompressedVoxels compressVoxels_byte(const std::vector<VoxelCube>& voxels) {
|
||||
std::u8string compressed;
|
||||
std::vector<DefVoxelId_t> defines;
|
||||
DefVoxelId_t maxValue = 0;
|
||||
std::vector<DefVoxelId> defines;
|
||||
DefVoxelId maxValue = 0;
|
||||
defines.reserve(voxels.size());
|
||||
|
||||
compressed.push_back(1);
|
||||
@@ -55,7 +55,7 @@ CompressedVoxels compressVoxels_byte(const std::vector<VoxelCube>& voxels) {
|
||||
compressed.push_back((defines.size() >> 8) & 0xff);
|
||||
|
||||
// Таблица
|
||||
for(DefVoxelId_t id : defines) {
|
||||
for(DefVoxelId id : defines) {
|
||||
compressed.push_back(id & 0xff);
|
||||
if(bytes_raw > 1)
|
||||
compressed.push_back((id >> 8) & 0xff);
|
||||
@@ -107,11 +107,11 @@ CompressedVoxels compressVoxels_byte(const std::vector<VoxelCube>& voxels) {
|
||||
}
|
||||
|
||||
CompressedVoxels compressVoxels_bit(const std::vector<VoxelCube>& voxels) {
|
||||
std::vector<DefVoxelId_t> profile;
|
||||
std::vector<DefVoxelId_t> one_byte[7];
|
||||
std::vector<DefVoxelId> profile;
|
||||
std::vector<DefVoxelId> one_byte[7];
|
||||
|
||||
DefVoxelId_t maxValueProfile = 0;
|
||||
DefVoxelId_t maxValues[7] = {0};
|
||||
DefVoxelId maxValueProfile = 0;
|
||||
DefVoxelId maxValues[7] = {0};
|
||||
|
||||
profile.reserve(voxels.size());
|
||||
for(int iter = 0; iter < 7; iter++)
|
||||
@@ -195,7 +195,7 @@ CompressedVoxels compressVoxels_bit(const std::vector<VoxelCube>& voxels) {
|
||||
write(bits_raw_profile, 5);
|
||||
write(bits_index_profile, 4);
|
||||
|
||||
for(DefNodeId_t id : profile)
|
||||
for(DefNodeId id : profile)
|
||||
write(id, bits_raw_profile);
|
||||
} else {
|
||||
write(bits_raw_profile, 5);
|
||||
@@ -274,11 +274,11 @@ std::vector<VoxelCube> unCompressVoxels_byte(const std::u8string& compressed) {
|
||||
uint8_t bytes_per_define = (cmd >> 1) & 0x1;
|
||||
uint8_t bytes_raw = (cmd >> 2) & 0x3;
|
||||
|
||||
std::vector<DefVoxelId_t> defines;
|
||||
std::vector<DefVoxelId> defines;
|
||||
defines.resize(read() | (read() << 8));
|
||||
|
||||
for(size_t iter = 0; iter < defines.size(); iter++) {
|
||||
DefVoxelId_t id = read();
|
||||
DefVoxelId id = read();
|
||||
if(bytes_raw > 1)
|
||||
id |= read() << 8;
|
||||
if(bytes_raw > 2)
|
||||
@@ -357,8 +357,8 @@ std::vector<VoxelCube> unCompressVoxels_bit(const std::u8string& compressed) {
|
||||
for(int iter = 0; iter < 7; iter++)
|
||||
indices[iter] = read(1);
|
||||
|
||||
std::vector<DefVoxelId_t> profile;
|
||||
std::vector<DefVoxelId_t> one_byte[7];
|
||||
std::vector<DefVoxelId> profile;
|
||||
std::vector<DefVoxelId> one_byte[7];
|
||||
uint8_t bits_raw_profile;
|
||||
uint8_t bits_index_profile;
|
||||
size_t bits_raw[7];
|
||||
@@ -435,13 +435,13 @@ std::vector<VoxelCube> unCompressVoxels(const std::u8string& compressed) {
|
||||
CompressedNodes compressNodes_byte(const Node* nodes) {
|
||||
std::u8string compressed;
|
||||
|
||||
std::vector<DefNodeId_t> profiles;
|
||||
std::vector<DefNodeId> profiles;
|
||||
|
||||
profiles.reserve(16*16*16);
|
||||
|
||||
compressed.push_back(1);
|
||||
|
||||
DefNodeId_t maxValueProfile = 0;
|
||||
DefNodeId maxValueProfile = 0;
|
||||
|
||||
for(size_t iter = 0; iter < 16*16*16; iter++) {
|
||||
const Node &node = nodes[iter];
|
||||
@@ -477,7 +477,7 @@ CompressedNodes compressNodes_byte(const Node* nodes) {
|
||||
compressed.push_back((profiles.size() >> 8) & 0xff);
|
||||
compressed.push_back((profiles.size() >> 16) & 0xff);
|
||||
|
||||
for(DefNodeId_t id : profiles) {
|
||||
for(DefNodeId id : profiles) {
|
||||
if(bytes_raw_profile > 0)
|
||||
compressed.push_back(id & 0xff);
|
||||
if(bytes_raw_profile > 1)
|
||||
@@ -521,15 +521,15 @@ CompressedNodes compressNodes_byte(const Node* nodes) {
|
||||
CompressedNodes compressNodes_bit(const Node* nodes) {
|
||||
std::u8string compressed;
|
||||
|
||||
std::vector<DefNodeId_t> profiles;
|
||||
std::vector<DefNodeId_t> meta;
|
||||
std::vector<DefNodeId> profiles;
|
||||
std::vector<DefNodeId> meta;
|
||||
|
||||
profiles.reserve(16*16*16);
|
||||
meta.reserve(16*16*16);
|
||||
|
||||
compressed.push_back(1);
|
||||
|
||||
DefNodeId_t maxValueProfile = 0,
|
||||
DefNodeId maxValueProfile = 0,
|
||||
maxValueMeta = 0;
|
||||
|
||||
for(size_t iter = 0; iter < 16*16*16; iter++) {
|
||||
@@ -599,7 +599,7 @@ CompressedNodes compressNodes_bit(const Node* nodes) {
|
||||
if(indices_profile) {
|
||||
write(profiles.size(), 12);
|
||||
|
||||
for(DefNodeId_t id : profiles) {
|
||||
for(DefNodeId id : profiles) {
|
||||
write(id, bits_raw_profile);
|
||||
}
|
||||
}
|
||||
@@ -608,7 +608,7 @@ CompressedNodes compressNodes_bit(const Node* nodes) {
|
||||
if(indices_meta) {
|
||||
write(meta.size(), 8);
|
||||
|
||||
for(DefNodeId_t id : meta) {
|
||||
for(DefNodeId id : meta) {
|
||||
write(id, bits_raw_meta);
|
||||
}
|
||||
}
|
||||
@@ -636,13 +636,12 @@ CompressedNodes compressNodes_bit(const Node* nodes) {
|
||||
return {compressLinear(compressed), profiles};
|
||||
}
|
||||
|
||||
|
||||
CompressedNodes compressNodes(const Node* nodes, bool fast) {
|
||||
std::u8string data(16*16*16*sizeof(Node), '\0');
|
||||
const char8_t *ptr = (const char8_t*) nodes;
|
||||
std::copy(ptr, ptr+16*16*16*4, data.data());
|
||||
|
||||
std::vector<DefNodeId_t> node(16*16*16);
|
||||
std::vector<DefNodeId> node(16*16*16);
|
||||
for(int iter = 0; iter < 16*16*16; iter++) {
|
||||
node[iter] = nodes[iter].NodeId;
|
||||
}
|
||||
@@ -677,11 +676,11 @@ void unCompressNodes_byte(const std::u8string& compressed, Node* ptr) {
|
||||
bool indices_profile = value & 0x1;
|
||||
|
||||
if(indices_profile) {
|
||||
std::vector<DefNodeId_t> profiles;
|
||||
std::vector<DefNodeId> profiles;
|
||||
profiles.resize(read() | (read() << 8) | (read() << 16));
|
||||
|
||||
for(size_t iter = 0; iter < profiles.size(); iter++) {
|
||||
DefNodeId_t id = 0;
|
||||
DefNodeId id = 0;
|
||||
|
||||
if(bytes_raw_profile > 0)
|
||||
id = read();
|
||||
@@ -694,7 +693,7 @@ void unCompressNodes_byte(const std::u8string& compressed, Node* ptr) {
|
||||
for(size_t iter = 0; iter < 16*16*16; iter++) {
|
||||
Node &node = ptr[iter];
|
||||
|
||||
DefNodeId_t index = read();
|
||||
DefNodeId index = read();
|
||||
if(bytes_indices_profile > 1)
|
||||
index |= read() << 8;
|
||||
|
||||
@@ -733,7 +732,7 @@ void unCompressNodes_bit(const std::u8string& compressed, Node* ptr) {
|
||||
return out;
|
||||
};
|
||||
|
||||
std::vector<DefNodeId_t> meta;
|
||||
std::vector<DefNodeId> meta;
|
||||
|
||||
|
||||
bool indices_profile = read(1);
|
||||
@@ -744,7 +743,7 @@ void unCompressNodes_bit(const std::u8string& compressed, Node* ptr) {
|
||||
uint8_t bits_raw_meta = read(3);
|
||||
uint8_t bits_indices_meta = read(3);
|
||||
|
||||
std::vector<DefNodeId_t> profiles;
|
||||
std::vector<DefNodeId> profiles;
|
||||
|
||||
// Таблицы
|
||||
if(indices_profile) {
|
||||
|
||||
@@ -144,6 +144,9 @@ AssetsManager::Out_recheckResources AssetsManager::recheckResources(const Assets
|
||||
}
|
||||
|
||||
for(const fs::path& path : info.Assets) {
|
||||
if(!fs::exists(path))
|
||||
continue;
|
||||
|
||||
for(auto begin = fs::directory_iterator(path), end = fs::directory_iterator(); begin != end; begin++) {
|
||||
if(!begin->is_directory())
|
||||
continue;
|
||||
@@ -264,12 +267,15 @@ AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const
|
||||
result.NewOrChange[type].push_back({id, resource});
|
||||
keyToIdDomain[key] = id;
|
||||
|
||||
data->emplace(lwt, resource);
|
||||
data->emplace(lwt, resource, domain, key);
|
||||
}
|
||||
}
|
||||
|
||||
// Удалённые идентификаторы не считаются удалёнными, если были изменены
|
||||
std::unordered_set<ResourceId> noc(result.NewOrChange[type].begin(), result.NewOrChange[type].end());
|
||||
std::unordered_set<ResourceId> noc;
|
||||
for(auto& [id, _] : result.NewOrChange[type])
|
||||
noc.insert(id);
|
||||
|
||||
std::unordered_set<ResourceId> l(result.Lost[type].begin(), result.Lost[type].end());
|
||||
result.Lost[type].clear();
|
||||
std::set_difference(l.begin(), l.end(), noc.begin(), noc.end(), std::back_inserter(result.Lost[type]));
|
||||
@@ -278,18 +284,4 @@ AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const
|
||||
return result;
|
||||
}
|
||||
|
||||
ResourceId AssetsManager::getId(EnumAssets type, const std::string& domain, const std::string& key) {
|
||||
auto lock = LocalObj.lock();
|
||||
auto& keyToId = lock->KeyToId[(int) type];
|
||||
if(auto iterKTI = keyToId.find(domain); iterKTI != keyToId.end()) {
|
||||
if(auto iterKey = iterKTI->second.find(key); iterKey != iterKTI->second.end()) {
|
||||
return iterKey->second;
|
||||
}
|
||||
}
|
||||
|
||||
auto [id, entry] = lock->nextId(type);
|
||||
keyToId[domain][key] = id;
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <boost/interprocess/file_mapping.hpp>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
@@ -61,6 +62,7 @@ private:
|
||||
// Время последнего изменения файла
|
||||
fs::file_time_type FileChangeTime;
|
||||
Resource Res;
|
||||
std::string Domain, Key;
|
||||
};
|
||||
|
||||
struct TableEntry {
|
||||
@@ -143,7 +145,29 @@ public:
|
||||
Выдаёт идентификатор ресурса, даже если он не существует или был удалён.
|
||||
resource должен содержать домен и путь
|
||||
*/
|
||||
ResourceId getId(EnumAssets type, const std::string& domain, const std::string& key);
|
||||
ResourceId getId(EnumAssets type, const std::string& domain, const std::string& key) {
|
||||
auto lock = LocalObj.lock();
|
||||
auto& keyToId = lock->KeyToId[(int) type];
|
||||
if(auto iterKTI = keyToId.find(domain); iterKTI != keyToId.end()) {
|
||||
if(auto iterKey = iterKTI->second.find(key); iterKey != iterKTI->second.end()) {
|
||||
return iterKey->second;
|
||||
}
|
||||
}
|
||||
|
||||
auto [id, entry] = lock->nextId(type);
|
||||
keyToId[domain][key] = id;
|
||||
return id;
|
||||
}
|
||||
|
||||
std::optional<std::tuple<Resource, const std::string&, const std::string&>> getResource(EnumAssets type, ResourceId id) {
|
||||
auto lock = LocalObj.lock();
|
||||
assert(id < lock->Table[(int) type].size()*TableEntry::ChunkSize);
|
||||
auto& value = lock->Table[(int) type][id / TableEntry::ChunkSize]->Entries[id % TableEntry::ChunkSize];
|
||||
if(value)
|
||||
return {{value->Res, value->Domain, value->Key}};
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -18,56 +18,64 @@ void ContentManager::registerBase_Node(ResourceId id, const sol::table& profile)
|
||||
DefNode& def = *node;
|
||||
|
||||
{
|
||||
std::variant<std::monostate, std::string, sol::table> parent = profile["parent"];
|
||||
if(const sol::table* table = std::get_if<sol::table>(&parent)) {
|
||||
// result = createNodeProfileByLua(*table);
|
||||
} else if(const std::string* key = std::get_if<std::string>(&parent)) {
|
||||
auto regResult = TOS::Str::match(*key, "(?:([\\w\\d_]+):)?([\\w\\d_]+)");
|
||||
if(!regResult)
|
||||
MAKE_ERROR("Недействительный ключ в определении parent");
|
||||
std::optional<std::variant<std::string, sol::table>> parent = profile.get<std::optional<std::variant<std::string, sol::table>>>("parent");
|
||||
if(parent) {
|
||||
if(const sol::table* table = std::get_if<sol::table>(&*parent)) {
|
||||
// result = createNodeProfileByLua(*table);
|
||||
} else if(const std::string* key = std::get_if<std::string>(&*parent)) {
|
||||
auto regResult = TOS::Str::match(*key, "(?:([\\w\\d_]+):)?([\\w\\d_]+)");
|
||||
if(!regResult)
|
||||
MAKE_ERROR("Недействительный ключ в определении parent");
|
||||
|
||||
std::string realKey;
|
||||
std::string realKey;
|
||||
|
||||
if(regResult->at(1)) {
|
||||
realKey = *key;
|
||||
} else {
|
||||
realKey = "core:" + *regResult->at(2);
|
||||
if(regResult->at(1)) {
|
||||
realKey = *key;
|
||||
} else {
|
||||
realKey = "core:" + *regResult->at(2);
|
||||
}
|
||||
|
||||
DefNodeId parentId;
|
||||
|
||||
// {
|
||||
// auto& list = Content.ContentKeyToId[(int) EnumDefContent::Node];
|
||||
// auto iter = list.find(realKey);
|
||||
// if(iter == list.end())
|
||||
// MAKE_ERROR("Идентификатор parent не найден");
|
||||
|
||||
// parentId = iter->second;
|
||||
// }
|
||||
|
||||
// result = Content.ContentIdToDef_Node.at(parentId);
|
||||
}
|
||||
|
||||
DefNodeId_t parentId;
|
||||
|
||||
// {
|
||||
// auto& list = Content.ContentKeyToId[(int) EnumDefContent::Node];
|
||||
// auto iter = list.find(realKey);
|
||||
// if(iter == list.end())
|
||||
// MAKE_ERROR("Идентификатор parent не найден");
|
||||
|
||||
// parentId = iter->second;
|
||||
// }
|
||||
|
||||
// result = Content.ContentIdToDef_Node.at(parentId);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::optional<sol::table> nodestate = profile["nodestate"];
|
||||
std::optional<sol::table> nodestate = profile.get<std::optional<sol::table>>("nodestate");
|
||||
}
|
||||
|
||||
{
|
||||
std::optional<sol::table> render = profile["render"];
|
||||
std::optional<sol::table> render = profile.get<std::optional<sol::table>>("render");
|
||||
}
|
||||
|
||||
{
|
||||
std::optional<sol::table> collision = profile["collision"];
|
||||
std::optional<sol::table> collision = profile.get<std::optional<sol::table>>("collision");
|
||||
}
|
||||
|
||||
{
|
||||
std::optional<sol::table> events = profile["events"];
|
||||
std::optional<sol::table> events = profile.get<std::optional<sol::table>>("events");
|
||||
}
|
||||
|
||||
// result.NodeAdvancementFactory = profile["node_advancement_factory"];
|
||||
}
|
||||
|
||||
void ContentManager::registerBase_World(ResourceId id, const sol::table& profile) {
|
||||
std::optional<DefWorld>& world = getEntry_World(id);
|
||||
if(!world)
|
||||
world.emplace();
|
||||
}
|
||||
|
||||
void ContentManager::registerBase(EnumDefContent type, const std::string& domain, const std::string& key, const sol::table& profile)
|
||||
{
|
||||
ResourceId id = getId(type, domain, key);
|
||||
@@ -75,6 +83,8 @@ void ContentManager::registerBase(EnumDefContent type, const std::string& domain
|
||||
|
||||
if(type == EnumDefContent::Node)
|
||||
registerBase_Node(id, profile);
|
||||
else if(type == EnumDefContent::World)
|
||||
registerBase_World(id, profile);
|
||||
else
|
||||
MAKE_ERROR("Не реализовано");
|
||||
}
|
||||
@@ -107,6 +117,10 @@ ContentManager::Out_buildEndProfiles ContentManager::buildEndProfiles() {
|
||||
keys.erase(iterErase, keys.end());
|
||||
}
|
||||
|
||||
for(ResourceId id : ProfileChanges[(int) EnumDefContent::Voxel]) {
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,12 +24,16 @@ struct DefPortal_Mod { };
|
||||
struct DefEntity_Mod { };
|
||||
struct DefItem_Mod { };
|
||||
|
||||
struct DefVoxel { };
|
||||
struct DefNode { };
|
||||
struct DefWorld { };
|
||||
struct DefPortal { };
|
||||
struct DefEntity { };
|
||||
struct DefItem { };
|
||||
struct ResourceBase {
|
||||
std::string Domain, Key;
|
||||
};
|
||||
|
||||
struct DefVoxel : public ResourceBase { };
|
||||
struct DefNode : public ResourceBase { };
|
||||
struct DefWorld : public ResourceBase { };
|
||||
struct DefPortal : public ResourceBase { };
|
||||
struct DefEntity : public ResourceBase { };
|
||||
struct DefItem : public ResourceBase { };
|
||||
|
||||
class ContentManager {
|
||||
template<typename T>
|
||||
@@ -89,10 +93,41 @@ class ContentManager {
|
||||
|
||||
ResourceId resId = NextId[(int) type]++;
|
||||
ContentKeyToId[(int) type][domain][key] = resId;
|
||||
|
||||
switch(type) {
|
||||
case EnumDefContent::Voxel:
|
||||
if(resId >= Profiles_Voxel.size()*TableEntry<DefVoxel>::ChunkSize)
|
||||
Profiles_Voxel.push_back(std::make_unique<TableEntry<DefVoxel>>());
|
||||
break;
|
||||
case EnumDefContent::Node:
|
||||
if(resId >= Profiles_Node.size()*TableEntry<DefNode>::ChunkSize)
|
||||
Profiles_Node.push_back(std::make_unique<TableEntry<DefNode>>());
|
||||
break;
|
||||
case EnumDefContent::World:
|
||||
if(resId >= Profiles_World.size()*TableEntry<DefWorld>::ChunkSize)
|
||||
Profiles_World.push_back(std::make_unique<TableEntry<DefWorld>>());
|
||||
break;
|
||||
case EnumDefContent::Portal:
|
||||
if(resId >= Profiles_Portal.size()*TableEntry<DefPortal>::ChunkSize)
|
||||
Profiles_Portal.push_back(std::make_unique<TableEntry<DefPortal>>());
|
||||
break;
|
||||
case EnumDefContent::Entity:
|
||||
if(resId >= Profiles_Entity.size()*TableEntry<DefEntity>::ChunkSize)
|
||||
Profiles_Entity.push_back(std::make_unique<TableEntry<DefEntity>>());
|
||||
break;
|
||||
case EnumDefContent::Item:
|
||||
if(resId >= Profiles_Item.size()*TableEntry<DefItem>::ChunkSize)
|
||||
Profiles_Item.push_back(std::make_unique<TableEntry<DefItem>>());
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return resId;
|
||||
}
|
||||
|
||||
void registerBase_Node(ResourceId id, const sol::table& profile);
|
||||
void registerBase_World(ResourceId id, const sol::table& profile);
|
||||
|
||||
public:
|
||||
ContentManager(asio::io_context& ioc);
|
||||
@@ -110,6 +145,60 @@ public:
|
||||
};
|
||||
|
||||
Out_buildEndProfiles buildEndProfiles();
|
||||
|
||||
std::optional<DefVoxel*> getProfile_Voxel(ResourceId id) {
|
||||
assert(id < Profiles_Voxel.size()*TableEntry<DefVoxel>::ChunkSize);
|
||||
auto& value = Profiles_Voxel[id / TableEntry<DefVoxel>::ChunkSize]->Entries[id % TableEntry<DefVoxel>::ChunkSize];
|
||||
if(value)
|
||||
return {&*value};
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<DefNode*> getProfile_Node(ResourceId id) {
|
||||
assert(id < Profiles_Node.size()*TableEntry<DefNode>::ChunkSize);
|
||||
auto& value = Profiles_Node[id / TableEntry<DefNode>::ChunkSize]->Entries[id % TableEntry<DefNode>::ChunkSize];
|
||||
if(value)
|
||||
return {&*value};
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<DefWorld*> getProfile_World(ResourceId id) {
|
||||
assert(id < Profiles_World.size()*TableEntry<DefWorld>::ChunkSize);
|
||||
auto& value = Profiles_World[id / TableEntry<DefWorld>::ChunkSize]->Entries[id % TableEntry<DefWorld>::ChunkSize];
|
||||
if(value)
|
||||
return {&*value};
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<DefPortal*> getProfile_Portal(ResourceId id) {
|
||||
assert(id < Profiles_Portal.size()*TableEntry<DefPortal>::ChunkSize);
|
||||
auto& value = Profiles_Portal[id / TableEntry<DefPortal>::ChunkSize]->Entries[id % TableEntry<DefPortal>::ChunkSize];
|
||||
if(value)
|
||||
return {&*value};
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<DefEntity*> getProfile_Entity(ResourceId id) {
|
||||
assert(id < Profiles_Entity.size()*TableEntry<DefEntity>::ChunkSize);
|
||||
auto& value = Profiles_Entity[id / TableEntry<DefEntity>::ChunkSize]->Entries[id % TableEntry<DefEntity>::ChunkSize];
|
||||
if(value)
|
||||
return {&*value};
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<DefItem*> getProfile_Item(ResourceId id) {
|
||||
assert(id < Profiles_Item.size()*TableEntry<DefItem>::ChunkSize);
|
||||
auto& value = Profiles_Item[id / TableEntry<DefItem>::ChunkSize]->Entries[id % TableEntry<DefItem>::ChunkSize];
|
||||
if(value)
|
||||
return {&*value};
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Common/Packets.hpp"
|
||||
#include "Server/Abstract.hpp"
|
||||
#include "Server/AssetsManager.hpp"
|
||||
#include "Server/ContentManager.hpp"
|
||||
#include "Server/RemoteClient.hpp"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -546,14 +547,14 @@ void GameServer::BackingChunkPressure_t::run(int id) {
|
||||
|
||||
Dump dumpRegion;
|
||||
|
||||
dumpRegion.CECs = regionObj.CECs;
|
||||
dumpRegion.CECs = regionObj.RMs;
|
||||
dumpRegion.IsChunkChanged_Voxels = regionObj.IsChunkChanged_Voxels;
|
||||
regionObj.IsChunkChanged_Voxels = 0;
|
||||
dumpRegion.IsChunkChanged_Nodes = regionObj.IsChunkChanged_Nodes;
|
||||
regionObj.IsChunkChanged_Nodes = 0;
|
||||
|
||||
if(!regionObj.NewCECs.empty()) {
|
||||
dumpRegion.NewCECs = std::move(regionObj.NewCECs);
|
||||
if(!regionObj.NewRMs.empty()) {
|
||||
dumpRegion.NewCECs = std::move(regionObj.NewRMs);
|
||||
dumpRegion.Voxels = regionObj.Voxels;
|
||||
|
||||
for(int z = 0; z < 4; z++)
|
||||
@@ -640,7 +641,7 @@ void GameServer::BackingChunkPressure_t::run(int id) {
|
||||
Pos::GlobalChunk chunkPosR = (Pos::GlobalChunk(regionPos) << 2) + chunkPos;
|
||||
|
||||
for(auto& ptr : region.NewCECs) {
|
||||
bool accepted = ptr->Remote->maybe_prepareChunkUpdate_Voxels(worldId,
|
||||
bool accepted = ptr->maybe_prepareChunkUpdate_Voxels(worldId,
|
||||
chunkPosR, cmp.Compressed, cmp.Defines);
|
||||
if(!accepted) {
|
||||
cecs.push_back(ptr.get());
|
||||
@@ -660,7 +661,7 @@ void GameServer::BackingChunkPressure_t::run(int id) {
|
||||
if(skip)
|
||||
continue;
|
||||
|
||||
bool accepted = ptr->Remote->maybe_prepareChunkUpdate_Voxels(worldId,
|
||||
bool accepted = ptr->maybe_prepareChunkUpdate_Voxels(worldId,
|
||||
chunkPosR, cmp.Compressed, cmp.Defines);
|
||||
if(!accepted) {
|
||||
cecs.push_back(ptr.get());
|
||||
@@ -679,7 +680,7 @@ void GameServer::BackingChunkPressure_t::run(int id) {
|
||||
Pos::GlobalChunk chunkPosR = (Pos::GlobalChunk(regionPos) << 2) + chunkPos;
|
||||
|
||||
for(auto& ptr : region.NewCECs) {
|
||||
bool accepted = ptr->Remote->maybe_prepareChunkUpdate_Nodes(worldId,
|
||||
bool accepted = ptr->maybe_prepareChunkUpdate_Nodes(worldId,
|
||||
chunkPosR, cmp.Compressed, cmp.Defines);
|
||||
if(!accepted) {
|
||||
cecs.push_back(ptr.get());
|
||||
@@ -699,7 +700,7 @@ void GameServer::BackingChunkPressure_t::run(int id) {
|
||||
if(skip)
|
||||
continue;
|
||||
|
||||
bool accepted = ptr->Remote->maybe_prepareChunkUpdate_Nodes(worldId,
|
||||
bool accepted = ptr->maybe_prepareChunkUpdate_Nodes(worldId,
|
||||
chunkPosR, cmp.Compressed, cmp.Defines);
|
||||
if(!accepted) {
|
||||
cecs.push_back(ptr.get());
|
||||
@@ -721,7 +722,7 @@ void GameServer::BackingChunkPressure_t::run(int id) {
|
||||
while(begin != end) {
|
||||
auto& [worldId, chunkPos, cmp] = begin->first;
|
||||
for(RemoteClient* cec : begin->second) {
|
||||
bool accepted = cec->Remote->maybe_prepareChunkUpdate_Voxels(worldId, chunkPos, cmp.Compressed, cmp.Defines);
|
||||
bool accepted = cec->maybe_prepareChunkUpdate_Voxels(worldId, chunkPos, cmp.Compressed, cmp.Defines);
|
||||
if(!accepted)
|
||||
cecs.push_back(cec);
|
||||
}
|
||||
@@ -741,7 +742,7 @@ void GameServer::BackingChunkPressure_t::run(int id) {
|
||||
while(begin != end) {
|
||||
auto& [worldId, chunkPos, cmp] = begin->first;
|
||||
for(RemoteClient* cec : begin->second) {
|
||||
bool accepted = cec->Remote->maybe_prepareChunkUpdate_Nodes(worldId, chunkPos, cmp.Compressed, cmp.Defines);
|
||||
bool accepted = cec->maybe_prepareChunkUpdate_Nodes(worldId, chunkPos, cmp.Compressed, cmp.Defines);
|
||||
if(!accepted)
|
||||
cecs.push_back(cec);
|
||||
}
|
||||
@@ -855,7 +856,7 @@ void GameServer::BackingAsyncLua_t::run(int id) {
|
||||
for(int z = 0; z < 64; z++)
|
||||
for(int y = 0; y < 64; y++)
|
||||
for(int x = 0; x < 64; x++, ptr++) {
|
||||
DefVoxelId_t id = std::clamp(*ptr, 0.f, 1.f) * 3; //> 0.9 ? 1 : 0;
|
||||
DefVoxelId id = std::clamp(*ptr, 0.f, 1.f) * 3; //> 0.9 ? 1 : 0;
|
||||
Pos::bvec64u nodePos(x, y, z);
|
||||
auto &node = out.Nodes[Pos::bvec4u(nodePos >> 4).pack()][Pos::bvec16u(nodePos & 0xf).pack()];
|
||||
node.NodeId = id;
|
||||
@@ -1441,18 +1442,32 @@ void GameServer::init(fs::path worldPath) {
|
||||
|
||||
initLuaAssets();
|
||||
pushEvent("initAssets");
|
||||
for(ssize_t index = mlt.LoadChain.size(); index >= 0; index--) {
|
||||
for(ssize_t index = mlt.LoadChain.size()-1; index >= 0; index--) {
|
||||
AssetsInit.Assets.push_back(mlt.LoadChain[index].Path / "assets");
|
||||
}
|
||||
|
||||
Content.AM.applyResourceChange(Content.AM.recheckResources(AssetsInit));
|
||||
|
||||
LOG.info() << "Пре Инициализация";
|
||||
|
||||
{
|
||||
sol::table t = LuaMainState.create_table();
|
||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test0", t);
|
||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test1", t);
|
||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test2", t);
|
||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test3", t);
|
||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test4", t);
|
||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test5", t);
|
||||
Content.CM.registerBase(EnumDefContent::World, "core", "devel_world", t);
|
||||
}
|
||||
|
||||
initLuaPre();
|
||||
pushEvent("lowPreInit");
|
||||
|
||||
// TODO: регистрация контента из mod/content/*
|
||||
|
||||
Content.CM.buildEndProfiles();
|
||||
|
||||
pushEvent("preInit");
|
||||
pushEvent("highPreInit");
|
||||
|
||||
@@ -1513,15 +1528,15 @@ void GameServer::run() {
|
||||
|
||||
if(IsGoingShutdown) {
|
||||
// Отключить игроков
|
||||
for(std::shared_ptr<RemoteClient> &cec : Game.CECs) {
|
||||
cec->Remote->shutdown(EnumDisconnect::ByInterface, ShutdownReason);
|
||||
for(std::shared_ptr<RemoteClient> &remoteClient : Game.RemoteClients) {
|
||||
remoteClient->shutdown(EnumDisconnect::ByInterface, ShutdownReason);
|
||||
}
|
||||
|
||||
{
|
||||
// Отключить вновь подключившихся
|
||||
auto lock = External.NewConnectedPlayers.lock_write();
|
||||
|
||||
for(std::unique_ptr<RemoteClient> &client : *lock) {
|
||||
for(std::shared_ptr<RemoteClient> &client : *lock) {
|
||||
client->shutdown(EnumDisconnect::ByInterface, ShutdownReason);
|
||||
}
|
||||
|
||||
@@ -1578,7 +1593,7 @@ void GameServer::run() {
|
||||
|
||||
void GameServer::initLuaAssets() {
|
||||
auto &lua = LuaMainState;
|
||||
std::optional<sol::table> core = lua["core"];
|
||||
std::optional<sol::table> core = lua.get<std::optional<sol::table>>("core");
|
||||
if(!core)
|
||||
core = lua.create_named_table("core");
|
||||
|
||||
@@ -1598,13 +1613,13 @@ void GameServer::initLuaAssets() {
|
||||
AssetsInit.Custom[(int) type][CurrentModId][*result[2]] = nullptr;
|
||||
};
|
||||
|
||||
core->set_function("register_nodestate", std::bind(reg, EnumAssets::Nodestate, std::placeholders::_1, std::placeholders::_2));
|
||||
core->set_function("register_particle", std::bind(reg, EnumAssets::Patricle, std::placeholders::_1, std::placeholders::_2));
|
||||
core->set_function("register_animation", std::bind(reg, EnumAssets::Animation, std::placeholders::_1, std::placeholders::_2));
|
||||
core->set_function("register_model", std::bind(reg, EnumAssets::Model, std::placeholders::_1, std::placeholders::_2));
|
||||
core->set_function("register_texture", std::bind(reg, EnumAssets::Texture, std::placeholders::_1, std::placeholders::_2));
|
||||
core->set_function("register_sound", std::bind(reg, EnumAssets::Sound, std::placeholders::_1, std::placeholders::_2));
|
||||
core->set_function("register_font", std::bind(reg, EnumAssets::Font, std::placeholders::_1, std::placeholders::_2));
|
||||
core->set_function("register_nodestate", [&](const std::string& key, const sol::table& profile) { reg(EnumAssets::Nodestate, key, profile); });
|
||||
core->set_function("register_particle", [&](const std::string& key, const sol::table& profile) { reg(EnumAssets::Patricle, key, profile); });
|
||||
core->set_function("register_animation", [&](const std::string& key, const sol::table& profile) { reg(EnumAssets::Animation, key, profile); });
|
||||
core->set_function("register_model", [&](const std::string& key, const sol::table& profile) { reg(EnumAssets::Model, key, profile); });
|
||||
core->set_function("register_texture", [&](const std::string& key, const sol::table& profile) { reg(EnumAssets::Texture, key, profile); });
|
||||
core->set_function("register_sound", [&](const std::string& key, const sol::table& profile) { reg(EnumAssets::Sound, key, profile); });
|
||||
core->set_function("register_font", [&](const std::string& key, const sol::table& profile) { reg(EnumAssets::Font, key, profile); });
|
||||
}
|
||||
|
||||
void GameServer::initLuaPre() {
|
||||
@@ -1635,12 +1650,12 @@ void GameServer::initLuaPre() {
|
||||
Content.CM.registerBase(type, CurrentModId, *result[2], profile);
|
||||
};
|
||||
|
||||
core.set_function("register_voxel", std::bind(reg, EnumDefContent::Voxel, std::placeholders::_1, std::placeholders::_2));
|
||||
core.set_function("register_node", std::bind(reg, EnumDefContent::Node, std::placeholders::_1, std::placeholders::_2));
|
||||
core.set_function("register_world", std::bind(reg, EnumDefContent::World, std::placeholders::_1, std::placeholders::_2));
|
||||
core.set_function("register_portal", std::bind(reg, EnumDefContent::Portal, std::placeholders::_1, std::placeholders::_2));
|
||||
core.set_function("register_entity", std::bind(reg, EnumDefContent::Entity, std::placeholders::_1, std::placeholders::_2));
|
||||
core.set_function("register_item", std::bind(reg, EnumDefContent::Item, std::placeholders::_1, std::placeholders::_2));
|
||||
core.set_function("register_voxel", [&](const std::string& key, const sol::table& profile) { reg(EnumDefContent::Voxel, key, profile); });
|
||||
core.set_function("register_node", [&](const std::string& key, const sol::table& profile) { reg(EnumDefContent::Node, key, profile); });
|
||||
core.set_function("register_world", [&](const std::string& key, const sol::table& profile) { reg(EnumDefContent::World, key, profile); });
|
||||
core.set_function("register_portal", [&](const std::string& key, const sol::table& profile) { reg(EnumDefContent::Portal, key, profile); });
|
||||
core.set_function("register_entity", [&](const std::string& key, const sol::table& profile) { reg(EnumDefContent::Entity, key, profile); });
|
||||
core.set_function("register_item", [&](const std::string& key, const sol::table& profile) { reg(EnumDefContent::Item, key, profile); });
|
||||
}
|
||||
|
||||
void GameServer::initLua() {
|
||||
@@ -1667,9 +1682,9 @@ void GameServer::stepConnections() {
|
||||
if(!External.NewConnectedPlayers.no_lock_readable().empty()) {
|
||||
auto lock = External.NewConnectedPlayers.lock_write();
|
||||
|
||||
for(std::unique_ptr<RemoteClient>& client : *lock) {
|
||||
for(std::shared_ptr<RemoteClient>& client : *lock) {
|
||||
co_spawn(client->run());
|
||||
Game.CECs.push_back(std::make_unique<RemoteClient>(std::move(client)));
|
||||
Game.RemoteClients.push_back(client);
|
||||
}
|
||||
|
||||
lock->clear();
|
||||
@@ -1678,28 +1693,28 @@ void GameServer::stepConnections() {
|
||||
BackingChunkPressure.endCollectChanges();
|
||||
|
||||
// Отключение игроков
|
||||
for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
for(std::shared_ptr<RemoteClient>& cec : Game.RemoteClients) {
|
||||
// Убрать отключившихся
|
||||
if(!cec->Remote->isConnected()) {
|
||||
if(!cec->isConnected()) {
|
||||
// Отписываем наблюдателя от миров
|
||||
for(auto wPair : cec->ContentViewState.Regions) {
|
||||
auto wIter = Expanse.Worlds.find(wPair.first);
|
||||
assert(wIter != Expanse.Worlds.end());
|
||||
|
||||
wIter->second->onCEC_RegionsLost(cec, wPair.second);
|
||||
wIter->second->onRemoteClient_RegionsLost(cec, wPair.second);
|
||||
}
|
||||
|
||||
std::string username = cec->Remote->Username;
|
||||
std::string username = cec->Username;
|
||||
External.ConnectedPlayersSet.lock_write()->erase(username);
|
||||
|
||||
cec.reset();
|
||||
cec = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Вычистить невалидные ссылки на игроков
|
||||
Game.CECs.erase(std::remove_if(Game.CECs.begin(), Game.CECs.end(),
|
||||
Game.RemoteClients.erase(std::remove_if(Game.RemoteClients.begin(), Game.RemoteClients.end(),
|
||||
[](const std::shared_ptr<RemoteClient>& ptr) { return !ptr; }),
|
||||
Game.CECs.end());
|
||||
Game.RemoteClients.end());
|
||||
}
|
||||
|
||||
void GameServer::stepModInitializations() {
|
||||
@@ -1709,44 +1724,56 @@ void GameServer::stepModInitializations() {
|
||||
IWorldSaveBackend::TickSyncInfo_Out GameServer::stepDatabaseSync() {
|
||||
IWorldSaveBackend::TickSyncInfo_In toDB;
|
||||
|
||||
for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
assert(cec);
|
||||
for(std::shared_ptr<RemoteClient>& remoteClient : Game.RemoteClients) {
|
||||
assert(remoteClient);
|
||||
// Пересчитать зоны наблюдения
|
||||
if(cec->CrossedBorder) {
|
||||
cec->CrossedBorder = false;
|
||||
if(remoteClient->CrossedRegion) {
|
||||
remoteClient->CrossedRegion = false;
|
||||
|
||||
// Пересчёт зон наблюдения
|
||||
ServerObjectPos oPos = cec->getPos();
|
||||
std::vector<ContentViewCircle> newCVCs;
|
||||
|
||||
ContentViewCircle cvc;
|
||||
cvc.WorldId = oPos.WorldId;
|
||||
cvc.Pos = Pos::Object_t::asRegionsPos(oPos.ObjectPos);
|
||||
cvc.Range = 2;
|
||||
{
|
||||
std::vector<std::tuple<WorldId_t, Pos::Object, uint8_t>> points = remoteClient->getViewPoints();
|
||||
for(auto& [wId, pos, radius] : points) {
|
||||
assert(radius < 5);
|
||||
ContentViewCircle cvc;
|
||||
cvc.WorldId = wId;
|
||||
cvc.Pos = Pos::Object_t::asRegionsPos(pos);
|
||||
cvc.Range = radius*radius;
|
||||
|
||||
std::vector<ContentViewCircle> list = Expanse.accumulateContentViewCircles(cvc);
|
||||
newCVCs.insert(newCVCs.end(), list.begin(), list.end());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ContentViewCircle> newCVCs = Expanse.accumulateContentViewCircles(cvc);
|
||||
ContentViewInfo newCbg = Expanse_t::makeContentViewInfo(newCVCs);
|
||||
|
||||
ContentViewInfo_Diff diff = newCbg.diffWith(cec->ContentViewState);
|
||||
ContentViewInfo_Diff diff = newCbg.diffWith(remoteClient->ContentViewState);
|
||||
if(!diff.WorldsNew.empty()) {
|
||||
// Сообщить о новых мирах
|
||||
for(const WorldId_t id : diff.WorldsNew) {
|
||||
auto iter = Expanse.Worlds.find(id);
|
||||
assert(iter != Expanse.Worlds.end());
|
||||
|
||||
cec->onWorldUpdate(id, iter->second.get());
|
||||
remoteClient->prepareWorldUpdate(id, iter->second.get());
|
||||
}
|
||||
}
|
||||
|
||||
cec->ContentViewState = newCbg;
|
||||
remoteClient->ContentViewState = newCbg;
|
||||
// Вычистка не наблюдаемых регионов
|
||||
cec->removeUnobservable(diff);
|
||||
for(const auto& [worldId, regions] : diff.RegionsLost)
|
||||
remoteClient->prepareRegionsRemove(worldId, regions);
|
||||
// и миров
|
||||
for(const WorldId_t worldId : diff.WorldsLost)
|
||||
remoteClient->prepareWorldRemove(worldId);
|
||||
|
||||
// Подписываем игрока на наблюдение за регионами
|
||||
for(const auto& [worldId, regions] : diff.RegionsNew) {
|
||||
auto iterWorld = Expanse.Worlds.find(worldId);
|
||||
assert(iterWorld != Expanse.Worlds.end());
|
||||
|
||||
std::vector<Pos::GlobalRegion> notLoaded = iterWorld->second->onCEC_RegionsEnter(cec, regions);
|
||||
std::vector<Pos::GlobalRegion> notLoaded = iterWorld->second->onRemoteClient_RegionsEnter(remoteClient, regions);
|
||||
if(!notLoaded.empty()) {
|
||||
// Добавляем к списку на загрузку
|
||||
std::vector<Pos::GlobalRegion> &tl = toDB.Load[worldId];
|
||||
@@ -1759,7 +1786,7 @@ IWorldSaveBackend::TickSyncInfo_Out GameServer::stepDatabaseSync() {
|
||||
auto iterWorld = Expanse.Worlds.find(worldId);
|
||||
assert(iterWorld != Expanse.Worlds.end());
|
||||
|
||||
iterWorld->second->onCEC_RegionsLost(cec, regions);
|
||||
iterWorld->second->onRemoteClient_RegionsLost(remoteClient, regions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1855,20 +1882,20 @@ void GameServer::stepGeneratorAndLuaAsync(IWorldSaveBackend::TickSyncInfo_Out db
|
||||
|
||||
std::unordered_map<std::shared_ptr<RemoteClient>, std::vector<Pos::GlobalRegion>> toSubscribe;
|
||||
|
||||
for(auto& cec : Game.CECs) {
|
||||
auto iterViewWorld = cec->ContentViewState.Regions.find(worldId);
|
||||
if(iterViewWorld == cec->ContentViewState.Regions.end())
|
||||
for(auto& remoteClient : Game.RemoteClients) {
|
||||
auto iterViewWorld = remoteClient->ContentViewState.Regions.find(worldId);
|
||||
if(iterViewWorld == remoteClient->ContentViewState.Regions.end())
|
||||
continue;
|
||||
|
||||
for(auto& pos : iterViewWorld->second) {
|
||||
if(std::binary_search(newRegions.begin(), newRegions.end(), pos))
|
||||
toSubscribe[cec].push_back(pos);
|
||||
toSubscribe[remoteClient].push_back(pos);
|
||||
}
|
||||
}
|
||||
|
||||
iterWorld->second->pushRegions(std::move(regions));
|
||||
for(auto& [cec, poses] : toSubscribe) {
|
||||
iterWorld->second->onCEC_RegionsEnter(cec, poses);
|
||||
iterWorld->second->onRemoteClient_RegionsEnter(cec, poses);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2324,158 +2351,125 @@ void GameServer::stepGlobalStep() {
|
||||
}
|
||||
|
||||
void GameServer::stepSyncContent() {
|
||||
for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
cec->onUpdate();
|
||||
for(std::shared_ptr<RemoteClient>& remoteClient : Game.RemoteClients) {
|
||||
remoteClient->onUpdate();
|
||||
|
||||
// Это для пробы строительства и ломания нод
|
||||
while(!cec->Build.empty()) {
|
||||
Pos::GlobalNode node = cec->Build.front();
|
||||
cec->Build.pop();
|
||||
// while(!cec->Build.empty()) {
|
||||
// Pos::GlobalNode node = cec->Build.front();
|
||||
// cec->Build.pop();
|
||||
|
||||
Pos::GlobalRegion rPos = node >> 6;
|
||||
Pos::bvec4u cPos = (node >> 4) & 0x3;
|
||||
Pos::bvec16u nPos = node & 0xf;
|
||||
// Pos::GlobalRegion rPos = node >> 6;
|
||||
// Pos::bvec4u cPos = (node >> 4) & 0x3;
|
||||
// Pos::bvec16u nPos = node & 0xf;
|
||||
|
||||
auto ®ion = Expanse.Worlds[0]->Regions[rPos];
|
||||
region->Nodes[cPos.pack()][nPos.pack()].NodeId = 4;
|
||||
region->IsChunkChanged_Nodes |= 1ull << cPos.pack();
|
||||
}
|
||||
// auto ®ion = Expanse.Worlds[0]->Regions[rPos];
|
||||
// region->Nodes[cPos.pack()][nPos.pack()].NodeId = 4;
|
||||
// region->IsChunkChanged_Nodes |= 1ull << cPos.pack();
|
||||
// }
|
||||
|
||||
while(!cec->Break.empty()) {
|
||||
Pos::GlobalNode node = cec->Break.front();
|
||||
cec->Break.pop();
|
||||
// while(!cec->Break.empty()) {
|
||||
// Pos::GlobalNode node = cec->Break.front();
|
||||
// cec->Break.pop();
|
||||
|
||||
Pos::GlobalRegion rPos = node >> 6;
|
||||
Pos::bvec4u cPos = (node >> 4) & 0x3;
|
||||
Pos::bvec16u nPos = node & 0xf;
|
||||
// Pos::GlobalRegion rPos = node >> 6;
|
||||
// Pos::bvec4u cPos = (node >> 4) & 0x3;
|
||||
// Pos::bvec16u nPos = node & 0xf;
|
||||
|
||||
auto ®ion = Expanse.Worlds[0]->Regions[rPos];
|
||||
region->Nodes[cPos.pack()][nPos.pack()].NodeId = 0;
|
||||
region->IsChunkChanged_Nodes |= 1ull << cPos.pack();
|
||||
}
|
||||
// auto ®ion = Expanse.Worlds[0]->Regions[rPos];
|
||||
// region->Nodes[cPos.pack()][nPos.pack()].NodeId = 0;
|
||||
// region->IsChunkChanged_Nodes |= 1ull << cPos.pack();
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// Сбор запросов на ресурсы и профили + отправка пакетов игрокам
|
||||
ResourceRequest full = std::move(Content.OnContentChanges);
|
||||
for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
full.insert(cec->Remote->pushPreparedPackets());
|
||||
for(std::shared_ptr<RemoteClient>& cec : Game.RemoteClients) {
|
||||
full.insert(cec->pushPreparedPackets());
|
||||
}
|
||||
|
||||
|
||||
full.uniq();
|
||||
// Запрашиваем двоичные ресурсы
|
||||
// Content.BRM.needResourceResponse(full);
|
||||
// Content.BRM.update(CurrentTickDuration);
|
||||
// Получаем готовую информацию
|
||||
// {
|
||||
// BinaryResourceManager::OutObj_t out = Content.BRM.takePreparedInformation();
|
||||
// bool hasData = false;
|
||||
// for(int iter = 0; iter < (int) EnumBinResource::MAX_ENUM; iter++)
|
||||
// hasData |= !out.BinToHash[iter].empty();
|
||||
|
||||
// if(hasData) {
|
||||
// for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
// cec->Remote->informateIdToHash(out.BinToHash);
|
||||
// }
|
||||
// }
|
||||
// Информируем о запрошенных ассетах
|
||||
std::vector<std::tuple<EnumAssets, ResourceId, const std::string, const std::string, AssetsManager::Resource>> resources;
|
||||
for(int type = 0; type < (int) EnumAssets::MAX_ENUM; type++) {
|
||||
for(ResourceId resId : full.AssetsInfo[type]) {
|
||||
std::optional<std::tuple<AssetsManager::Resource, const std::string&, const std::string&>> result = Content.AM.getResource((EnumAssets) type, resId);
|
||||
if(!result)
|
||||
continue;
|
||||
|
||||
// if(!out.HashToResource.empty())
|
||||
// for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
// cec->Remote->informateBinary(out.HashToResource);
|
||||
// }
|
||||
// }
|
||||
auto& [resource, domain, key] = *result;
|
||||
resources.emplace_back((EnumAssets) type, resId, domain, key, resource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Оповещаем об игровых профилях
|
||||
// if(!full.Voxel.empty()) {
|
||||
// std::unordered_map<DefVoxelId_t, DefVoxel_t*> defines;
|
||||
// Информируем о запрошенных профилях
|
||||
std::vector<std::pair<DefVoxelId, DefVoxel*>> voxels;
|
||||
for(DefVoxelId id : full.Voxel) {
|
||||
auto value = Content.CM.getProfile_Voxel(id);
|
||||
if(!value)
|
||||
continue;
|
||||
|
||||
// for(DefVoxelId_t id : full.Node) {
|
||||
// auto iter = Content.ContentIdToDef_Voxel.find(id);
|
||||
// if(iter != Content.ContentIdToDef_Voxel.end()) {
|
||||
// defines[id] = &iter->second;
|
||||
// }
|
||||
// }
|
||||
voxels.emplace_back(id, *value);
|
||||
}
|
||||
|
||||
// for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
// cec->Remote->informateDefVoxel(defines);
|
||||
// }
|
||||
// }
|
||||
std::vector<std::pair<DefNodeId, DefNode*>> nodes;
|
||||
for(DefNodeId id : full.Node) {
|
||||
auto value = Content.CM.getProfile_Node(id);
|
||||
if(!value)
|
||||
continue;
|
||||
|
||||
// if(!full.Node.empty()) {
|
||||
// std::unordered_map<DefNodeId_t, DefNode_t*> defines;
|
||||
nodes.emplace_back(id, *value);
|
||||
}
|
||||
|
||||
// for(DefNodeId_t id : full.Node) {
|
||||
// auto iter = Content.ContentIdToDef_Node.find(id);
|
||||
// if(iter != Content.ContentIdToDef_Node.end()) {
|
||||
// defines[id] = &iter->second;
|
||||
// }
|
||||
// }
|
||||
std::vector<std::pair<DefWorldId, DefWorld*>> worlds;
|
||||
for(DefWorldId id : full.World) {
|
||||
auto value = Content.CM.getProfile_World(id);
|
||||
if(!value)
|
||||
continue;
|
||||
|
||||
// for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
// cec->Remote->informateDefNode(defines);
|
||||
// }
|
||||
// }
|
||||
worlds.emplace_back(id, *value);
|
||||
}
|
||||
|
||||
// if(!full.World.empty()) {
|
||||
// std::unordered_map<DefWorldId_t, DefWorld_t*> defines;
|
||||
std::vector<std::pair<DefPortalId, DefPortal*>> portals;
|
||||
for(DefPortalId id : full.Portal) {
|
||||
auto value = Content.CM.getProfile_Portal(id);
|
||||
if(!value)
|
||||
continue;
|
||||
|
||||
// for(DefWorldId_t id : full.Node) {
|
||||
// auto iter = Content.ContentIdToDef_World.find(id);
|
||||
// if(iter != Content.ContentIdToDef_World.end()) {
|
||||
// defines[id] = &iter->second;
|
||||
// }
|
||||
// }
|
||||
portals.emplace_back(id, *value);
|
||||
}
|
||||
|
||||
// for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
// cec->Remote->informateDefWorld(defines);
|
||||
// }
|
||||
// }
|
||||
std::vector<std::pair<DefEntityId, DefEntity*>> entities;
|
||||
for(DefEntityId id : full.Entity) {
|
||||
auto value = Content.CM.getProfile_Entity(id);
|
||||
if(!value)
|
||||
continue;
|
||||
|
||||
// if(!full.Portal.empty()) {
|
||||
// std::unordered_map<DefPortalId_t, DefPortal_t*> defines;
|
||||
entities.emplace_back(id, *value);
|
||||
}
|
||||
|
||||
// for(DefPortalId_t id : full.Node) {
|
||||
// auto iter = Content.ContentIdToDef_Portal.find(id);
|
||||
// if(iter != Content.ContentIdToDef_Portal.end()) {
|
||||
// defines[id] = &iter->second;
|
||||
// }
|
||||
// }
|
||||
std::vector<std::pair<DefItemId, DefItem*>> items;
|
||||
for(DefItemId id : full.Item) {
|
||||
auto value = Content.CM.getProfile_Item(id);
|
||||
if(!value)
|
||||
continue;
|
||||
|
||||
// for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
// cec->Remote->informateDefPortal(defines);
|
||||
// }
|
||||
// }
|
||||
items.emplace_back(id, *value);
|
||||
}
|
||||
|
||||
// if(!full.Entity.empty()) {
|
||||
// std::unordered_map<DefEntityId_t, DefEntity_t*> defines;
|
||||
for(std::shared_ptr<RemoteClient>& remoteClient : Game.RemoteClients) {
|
||||
remoteClient->informateAssets(resources);
|
||||
remoteClient->informateDefVoxel(voxels);
|
||||
remoteClient->informateDefNode(nodes);
|
||||
remoteClient->informateDefWorld(worlds);
|
||||
remoteClient->informateDefPortal(portals);
|
||||
remoteClient->informateDefEntity(entities);
|
||||
remoteClient->informateDefItem(items);
|
||||
}
|
||||
|
||||
// for(DefEntityId_t id : full.Node) {
|
||||
// auto iter = Content.ContentIdToDef_Entity.find(id);
|
||||
// if(iter != Content.ContentIdToDef_Entity.end()) {
|
||||
// defines[id] = &iter->second;
|
||||
// }
|
||||
// }
|
||||
|
||||
// for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
// cec->Remote->informateDefEntity(defines);
|
||||
// }
|
||||
// }
|
||||
|
||||
// if(!full.Item.empty()) {
|
||||
// std::unordered_map<DefItemId_t, DefItem_t*> defines;
|
||||
|
||||
// for(DefItemId_t id : full.Node) {
|
||||
// auto iter = Content.ContentIdToDef_Item.find(id);
|
||||
// if(iter != Content.ContentIdToDef_Item.end()) {
|
||||
// defines[id] = &iter->second;
|
||||
// }
|
||||
// }
|
||||
|
||||
// for(std::shared_ptr<RemoteClient>& cec : Game.CECs) {
|
||||
// cec->Remote->informateDefItem(defines);
|
||||
// }
|
||||
// }
|
||||
|
||||
BackingChunkPressure.startCollectChanges();
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ class GameServer : public AsyncObject {
|
||||
|
||||
struct {
|
||||
Lockable<std::set<std::string>> ConnectedPlayersSet;
|
||||
Lockable<std::list<std::unique_ptr<RemoteClient>>> NewConnectedPlayers;
|
||||
Lockable<std::list<std::shared_ptr<RemoteClient>>> NewConnectedPlayers;
|
||||
} External;
|
||||
|
||||
struct ContentObj {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Common/Abstract.hpp"
|
||||
#include "Common/Net.hpp"
|
||||
#include "Server/Abstract.hpp"
|
||||
#include "Server/World.hpp"
|
||||
#include <algorithm>
|
||||
#include <boost/asio/error.hpp>
|
||||
#include <boost/system/system_error.hpp>
|
||||
@@ -49,7 +50,8 @@ void RemoteClient::shutdown(EnumDisconnect type, const std::string reason) {
|
||||
|
||||
IsGoingShutdown = true;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::System
|
||||
Net::Packet packet;
|
||||
packet << (uint8_t) ToClient::L1::System
|
||||
<< (uint8_t) ToClient::L2System::Disconnect
|
||||
<< (uint8_t) type << reason;
|
||||
|
||||
@@ -61,10 +63,12 @@ void RemoteClient::shutdown(EnumDisconnect type, const std::string reason) {
|
||||
else if(type == EnumDisconnect::ProtocolError)
|
||||
info = "ошибка протокола (сервер) " + reason;
|
||||
|
||||
Socket.pushPacket(std::move(packet));
|
||||
|
||||
LOG.info() << "Игрок '" << Username << "' отключился " << info;
|
||||
}
|
||||
|
||||
void RemoteClient::murky_prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::u8string& compressed_voxels,
|
||||
void RemoteClient::NetworkAndResource_t::prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::u8string& compressed_voxels,
|
||||
const std::vector<DefVoxelId>& uniq_sorted_defines)
|
||||
{
|
||||
Pos::bvec4u localChunk = chunkPos & 0x3;
|
||||
@@ -129,7 +133,7 @@ void RemoteClient::murky_prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::Globa
|
||||
for(const DefVoxelId& id : lostTypes) {
|
||||
auto iter = ResUses.RefDefVoxel.find(id);
|
||||
assert(iter != ResUses.RefDefVoxel.end()); // Должны быть описаны зависимости вокселя
|
||||
decrementBinary(std::move(iter->second));
|
||||
decrementAssets(std::move(iter->second));
|
||||
ResUses.RefDefVoxel.erase(iter);
|
||||
|
||||
checkPacketBorder(16);
|
||||
@@ -139,14 +143,14 @@ void RemoteClient::murky_prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::Globa
|
||||
}
|
||||
}
|
||||
|
||||
murkyCheckPacketBorder(4+4+8+2+4+compressed_voxels.size());
|
||||
MurkyNextPacket << (uint8_t) ToClient::L1::Content
|
||||
checkPacketBorder(4+4+8+2+4+compressed_voxels.size());
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::ChunkVoxels
|
||||
<< worldId << chunkPos.pack() << uint32_t(compressed_voxels.size());
|
||||
MurkyNextPacket.write((const std::byte*) compressed_voxels.data(), compressed_voxels.size());
|
||||
NextPacket.write((const std::byte*) compressed_voxels.data(), compressed_voxels.size());
|
||||
}
|
||||
|
||||
void RemoteClient::maybe_prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::u8string& compressed_nodes,
|
||||
void RemoteClient::NetworkAndResource_t::prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::u8string& compressed_nodes,
|
||||
const std::vector<DefNodeId>& uniq_sorted_defines)
|
||||
{
|
||||
Pos::bvec4u localChunk = chunkPos & 0x3;
|
||||
@@ -205,29 +209,31 @@ void RemoteClient::maybe_prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::Global
|
||||
for(const DefNodeId& id : lostTypes) {
|
||||
auto iter = ResUses.RefDefNode.find(id);
|
||||
assert(iter != ResUses.RefDefNode.end()); // Должны быть описаны зависимости ноды
|
||||
decrementBinary(std::move(iter->second));
|
||||
decrementAssets(std::move(iter->second));
|
||||
ResUses.RefDefNode.erase(iter);
|
||||
|
||||
checkPacketBorder(16);
|
||||
MurkyNextPacket << (uint8_t) ToClient::L1::Definition
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::FreeNode
|
||||
<< id;
|
||||
}
|
||||
}
|
||||
|
||||
checkPacketBorder(4+4+8+4+compressed_nodes.size());
|
||||
MurkyNextPacket << (uint8_t) ToClient::L1::Content
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::ChunkNodes
|
||||
<< worldId << chunkPos.pack() << uint32_t(compressed_nodes.size());
|
||||
MurkyNextPacket.write((const std::byte*) compressed_nodes.data(), compressed_nodes.size());
|
||||
NextPacket.write((const std::byte*) compressed_nodes.data(), compressed_nodes.size());
|
||||
}
|
||||
|
||||
void RemoteClient::prepareRegionRemove(WorldId_t worldId, Pos::GlobalRegion regionPos) {
|
||||
void RemoteClient::NetworkAndResource_t::prepareRegionsRemove(WorldId_t worldId, std::vector<Pos::GlobalRegion> regionPoses)
|
||||
{
|
||||
std::vector<DefVoxelId>
|
||||
lostTypesV /* Потерянные типы вокселей */;
|
||||
std::vector<DefNodeId>
|
||||
lostTypesN /* Потерянные типы нод */;
|
||||
|
||||
for(Pos::GlobalRegion regionPos : regionPoses)
|
||||
// Уменьшаем зависимости вокселей и нод
|
||||
{
|
||||
auto iterWorld = ResUses.RefChunk.find(worldId);
|
||||
@@ -267,7 +273,7 @@ void RemoteClient::prepareRegionRemove(WorldId_t worldId, Pos::GlobalRegion regi
|
||||
for(const DefVoxelId& id : lostTypesV) {
|
||||
auto iter = ResUses.RefDefVoxel.find(id);
|
||||
assert(iter != ResUses.RefDefVoxel.end()); // Должны быть описаны зависимости вокселя
|
||||
decrementBinary(std::move(iter->second));
|
||||
decrementAssets(std::move(iter->second));
|
||||
ResUses.RefDefVoxel.erase(iter);
|
||||
|
||||
checkPacketBorder(16);
|
||||
@@ -281,7 +287,7 @@ void RemoteClient::prepareRegionRemove(WorldId_t worldId, Pos::GlobalRegion regi
|
||||
for(const DefNodeId& id : lostTypesN) {
|
||||
auto iter = ResUses.RefDefNode.find(id);
|
||||
assert(iter != ResUses.RefDefNode.end()); // Должны быть описаны зависимости ноды
|
||||
decrementBinary(std::move(iter->second));
|
||||
decrementAssets(std::move(iter->second));
|
||||
ResUses.RefDefNode.erase(iter);
|
||||
|
||||
checkPacketBorder(16);
|
||||
@@ -291,100 +297,107 @@ void RemoteClient::prepareRegionRemove(WorldId_t worldId, Pos::GlobalRegion regi
|
||||
}
|
||||
}
|
||||
|
||||
checkPacketBorder(16);
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::RemoveRegion
|
||||
<< worldId << regionPos.pack();
|
||||
|
||||
for(Pos::GlobalRegion regionPos : regionPoses) {
|
||||
checkPacketBorder(16);
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::RemoveRegion
|
||||
<< worldId << regionPos.pack();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::prepareEntityUpdate(ServerEntityId_t entityId, const Entity *entity)
|
||||
void RemoteClient::NetworkAndResource_t::prepareEntitiesUpdate(const std::vector<std::tuple<ServerEntityId_t, const Entity*>>& entities)
|
||||
{
|
||||
// Сопоставим с идентификатором клиента
|
||||
ClientEntityId_t ceId = ResRemap.Entityes.toClient(entityId);
|
||||
for(auto& [entityId, entity] : entities) {
|
||||
// Сопоставим с идентификатором клиента
|
||||
ClientEntityId_t ceId = ReMapEntities.toClient(entityId);
|
||||
|
||||
// Профиль новый
|
||||
{
|
||||
DefEntityId_t profile = entity->getDefId();
|
||||
auto iter = ResUses.DefEntity.find(profile);
|
||||
if(iter == ResUses.DefEntity.end()) {
|
||||
// Клиенту неизвестен профиль
|
||||
NextRequest.Entity.push_back(profile);
|
||||
ResUses.DefEntity[profile] = 1;
|
||||
} else
|
||||
iter->second++;
|
||||
// Профиль новый
|
||||
{
|
||||
DefEntityId profile = entity->getDefId();
|
||||
auto iter = ResUses.DefEntity.find(profile);
|
||||
if(iter == ResUses.DefEntity.end()) {
|
||||
// Клиенту неизвестен профиль
|
||||
NextRequest.Entity.push_back(profile);
|
||||
ResUses.DefEntity[profile] = 1;
|
||||
} else
|
||||
iter->second++;
|
||||
}
|
||||
|
||||
// Добавление модификационных зависимостей
|
||||
// incrementBinary({}, {}, {}, {}, {});
|
||||
|
||||
// Старые данные
|
||||
{
|
||||
auto iterEntity = ResUses.RefEntity.find(entityId);
|
||||
if(iterEntity != ResUses.RefEntity.end()) {
|
||||
// Убавляем зависимость к старому профилю
|
||||
auto iterProfile = ResUses.DefEntity.find(iterEntity->second.Profile);
|
||||
assert(iterProfile != ResUses.DefEntity.end()); // Старый профиль должен быть
|
||||
if(--iterProfile->second == 0) {
|
||||
// Старый профиль больше не нужен
|
||||
auto iterProfileRef = ResUses.RefDefEntity.find(iterEntity->second.Profile);
|
||||
decrementAssets(std::move(iterProfileRef->second));
|
||||
ResUses.DefEntity.erase(iterProfile);
|
||||
}
|
||||
|
||||
// Убавляем зависимость к модификационным данным
|
||||
// iterEntity->second.
|
||||
// decrementBinary({}, {}, {}, {}, {});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: отправить клиенту
|
||||
}
|
||||
}
|
||||
|
||||
// Добавление модификационных зависимостей
|
||||
// incrementBinary({}, {}, {}, {}, {});
|
||||
void RemoteClient::NetworkAndResource_t::prepareEntitySwap(ServerEntityId_t prev, ServerEntityId_t next)
|
||||
{
|
||||
ReMapEntities.rebindClientKey(prev, next);
|
||||
}
|
||||
|
||||
// Старые данные
|
||||
{
|
||||
auto iterEntity = ResUses.RefEntity.find(entityId);
|
||||
if(iterEntity != ResUses.RefEntity.end()) {
|
||||
// Убавляем зависимость к старому профилю
|
||||
void RemoteClient::NetworkAndResource_t::prepareEntitiesRemove(const std::vector<ServerEntityId_t>& entityIds)
|
||||
{
|
||||
for(ServerEntityId_t entityId : entityIds) {
|
||||
ClientEntityId_t cId = ReMapEntities.erase(entityId);
|
||||
|
||||
// Убавляем старые данные
|
||||
{
|
||||
auto iterEntity = ResUses.RefEntity.find(entityId);
|
||||
assert(iterEntity != ResUses.RefEntity.end()); // Зависимости должны быть
|
||||
|
||||
// Убавляем модификационные заависимости
|
||||
//decrementBinary(std::vector<BinTextureId_t> &&textures, std::vector<BinAnimationId_t> &&animation, std::vector<BinSoundId_t> &&sounds, std::vector<BinModelId_t> &&models, std::vector<BinFontId_t> &&fonts)
|
||||
|
||||
// Убавляем зависимость к профилю
|
||||
auto iterProfile = ResUses.DefEntity.find(iterEntity->second.Profile);
|
||||
assert(iterProfile != ResUses.DefEntity.end()); // Старый профиль должен быть
|
||||
assert(iterProfile != ResUses.DefEntity.end()); // Профиль должен быть
|
||||
if(--iterProfile->second == 0) {
|
||||
// Старый профиль больше не нужен
|
||||
// Профиль больше не используется
|
||||
auto iterProfileRef = ResUses.RefDefEntity.find(iterEntity->second.Profile);
|
||||
decrementBinary(std::move(iterProfileRef->second));
|
||||
|
||||
decrementAssets(std::move(iterProfileRef->second));
|
||||
|
||||
ResUses.RefDefEntity.erase(iterProfileRef);
|
||||
ResUses.DefEntity.erase(iterProfile);
|
||||
}
|
||||
|
||||
// Убавляем зависимость к модификационным данным
|
||||
// iterEntity->second.
|
||||
// decrementBinary({}, {}, {}, {}, {});
|
||||
}
|
||||
|
||||
checkPacketBorder(16);
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::RemoveEntity
|
||||
<< cId;
|
||||
}
|
||||
|
||||
// TODO: отправить клиенту
|
||||
}
|
||||
|
||||
void RemoteClient::prepareEntitySwap(ServerEntityId_t prev, ServerEntityId_t next)
|
||||
{
|
||||
ResRemap.Entityes.rebindClientKey(prev, next);
|
||||
}
|
||||
|
||||
void RemoteClient::prepareEntityRemove(ServerEntityId_t entityId)
|
||||
{
|
||||
ClientEntityId_t cId = ResRemap.Entityes.erase(entityId);
|
||||
|
||||
// Убавляем старые данные
|
||||
{
|
||||
auto iterEntity = ResUses.RefEntity.find(entityId);
|
||||
assert(iterEntity != ResUses.RefEntity.end()); // Зависимости должны быть
|
||||
|
||||
// Убавляем модификационные заависимости
|
||||
//decrementBinary(std::vector<BinTextureId_t> &&textures, std::vector<BinAnimationId_t> &&animation, std::vector<BinSoundId_t> &&sounds, std::vector<BinModelId_t> &&models, std::vector<BinFontId_t> &&fonts)
|
||||
|
||||
// Убавляем зависимость к профилю
|
||||
auto iterProfile = ResUses.DefEntity.find(iterEntity->second.Profile);
|
||||
assert(iterProfile != ResUses.DefEntity.end()); // Профиль должен быть
|
||||
if(--iterProfile->second == 0) {
|
||||
// Профиль больше не используется
|
||||
auto iterProfileRef = ResUses.RefDefEntity.find(iterEntity->second.Profile);
|
||||
|
||||
decrementBinary(std::move(iterProfileRef->second));
|
||||
|
||||
ResUses.RefDefEntity.erase(iterProfileRef);
|
||||
ResUses.DefEntity.erase(iterProfile);
|
||||
}
|
||||
}
|
||||
|
||||
checkPacketBorder(16);
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::RemoveEntity
|
||||
<< cId;
|
||||
}
|
||||
|
||||
void RemoteClient::prepareWorldUpdate(WorldId_t worldId, World* world)
|
||||
void RemoteClient::NetworkAndResource_t::prepareWorldUpdate(WorldId_t worldId, World* world)
|
||||
{
|
||||
// Добавление зависимостей
|
||||
ResUses.RefChunk[worldId];
|
||||
|
||||
// Профиль
|
||||
{
|
||||
DefWorldId_t defWorld = world->getDefId();
|
||||
DefWorldId defWorld = world->getDefId();
|
||||
auto iterWorldProf = ResUses.DefWorld.find(defWorld);
|
||||
if(iterWorldProf == ResUses.DefWorld.end()) {
|
||||
// Профиль мира неизвестен клиенту
|
||||
@@ -412,7 +425,7 @@ void RemoteClient::prepareWorldUpdate(WorldId_t worldId, World* world)
|
||||
ResUses.DefWorld.erase(iterWorldProf);
|
||||
auto iterWorldProfRef = ResUses.RefDefWorld.find(iterWorld->second.Profile);
|
||||
assert(iterWorldProfRef != ResUses.RefDefWorld.end()); // Зависимости предыдущего профиля также должны быть
|
||||
decrementBinary(std::move(iterWorldProfRef->second));
|
||||
decrementAssets(std::move(iterWorldProfRef->second));
|
||||
ResUses.RefDefWorld.erase(iterWorldProfRef);
|
||||
}
|
||||
}
|
||||
@@ -424,7 +437,7 @@ void RemoteClient::prepareWorldUpdate(WorldId_t worldId, World* world)
|
||||
// TODO: отправить мир
|
||||
}
|
||||
|
||||
void RemoteClient::prepareWorldRemove(WorldId_t worldId)
|
||||
void RemoteClient::NetworkAndResource_t::prepareWorldRemove(WorldId_t worldId)
|
||||
{
|
||||
// Чанки уже удалены prepareChunkRemove
|
||||
// Обновление зависимостей
|
||||
@@ -442,7 +455,7 @@ void RemoteClient::prepareWorldRemove(WorldId_t worldId)
|
||||
// Убавляем зависимости профиля
|
||||
auto iterWorldProfDef = ResUses.RefDefWorld.find(iterWorld->second.Profile);
|
||||
assert(iterWorldProfDef != ResUses.RefDefWorld.end()); // Зависимости профиля должны быть
|
||||
decrementBinary(std::move(iterWorldProfDef->second));
|
||||
decrementAssets(std::move(iterWorldProfDef->second));
|
||||
ResUses.RefDefWorld.erase(iterWorldProfDef);
|
||||
}
|
||||
|
||||
@@ -453,80 +466,67 @@ void RemoteClient::prepareWorldRemove(WorldId_t worldId)
|
||||
ResUses.RefChunk.erase(iter);
|
||||
}
|
||||
|
||||
void RemoteClient::preparePortalUpdate(PortalId_t portalId, void* portal) {}
|
||||
void RemoteClient::preparePortalRemove(PortalId_t portalId) {}
|
||||
// void RemoteClient::NetworkAndResource_t::preparePortalUpdate(PortalId portalId, void* portal) {}
|
||||
// void RemoteClient::NetworkAndResource_t::preparePortalRemove(PortalId portalId) {}
|
||||
|
||||
void RemoteClient::prepareCameraSetEntity(ServerEntityId_t entityId) {
|
||||
|
||||
}
|
||||
|
||||
ResourceRequest RemoteClient::pushPreparedPackets() {
|
||||
if(NextPacket.size())
|
||||
SimplePackets.push_back(std::move(NextPacket));
|
||||
std::vector<Net::Packet> toSend;
|
||||
ResourceRequest nextRequest;
|
||||
|
||||
Socket.pushPackets(&SimplePackets);
|
||||
SimplePackets.clear();
|
||||
{
|
||||
auto lock = NetworkAndResource.lock();
|
||||
|
||||
NextRequest.uniq();
|
||||
if(lock->NextPacket.size())
|
||||
lock->SimplePackets.push_back(std::move(lock->NextPacket));
|
||||
|
||||
return std::move(NextRequest);
|
||||
}
|
||||
|
||||
void RemoteClient::informateBinary(const std::vector<std::shared_ptr<ResourceFile>>& resources) {
|
||||
for(auto& resource : resources) {
|
||||
auto &hash = resource->Hash;
|
||||
|
||||
auto iter = std::find(NeedToSend.begin(), NeedToSend.end(), hash);
|
||||
if(iter == NeedToSend.end())
|
||||
continue; // Клиенту не требуется этот ресурс
|
||||
|
||||
{
|
||||
auto it = std::lower_bound(ClientBinaryCache.begin(), ClientBinaryCache.end(), hash);
|
||||
|
||||
if(it == ClientBinaryCache.end() || *it != hash)
|
||||
ClientBinaryCache.insert(it, hash);
|
||||
}
|
||||
|
||||
// Полная отправка ресурса
|
||||
checkPacketBorder(2+4+32+4);
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource // Принудительная полная отправка
|
||||
<< (uint8_t) ToClient::L2Resource::InitResSend
|
||||
<< uint32_t(resource->Data.size());
|
||||
NextPacket.write((const std::byte*) hash.data(), hash.size());
|
||||
|
||||
NextPacket << uint32_t(resource->Data.size());
|
||||
|
||||
size_t pos = 0;
|
||||
while(pos < resource->Data.size()) {
|
||||
checkPacketBorder(0);
|
||||
size_t need = std::min(resource->Data.size()-pos, std::min<size_t>(NextPacket.size(), 64000));
|
||||
NextPacket.write((const std::byte*) resource->Data.data()+pos, need);
|
||||
pos += need;
|
||||
}
|
||||
|
||||
toSend = std::move(lock->SimplePackets);
|
||||
nextRequest = std::move(lock->NextRequest);
|
||||
}
|
||||
|
||||
Socket.pushPackets(&toSend);
|
||||
toSend.clear();
|
||||
|
||||
nextRequest.uniq();
|
||||
|
||||
return std::move(nextRequest);
|
||||
}
|
||||
|
||||
void RemoteClient::informateIdToHash(const std::unordered_map<ResourceId_t, ResourceFile::Hash_t>* resourcesLink) {
|
||||
std::vector<std::tuple<EnumBinResource, ResourceId_t, Hash_t>> newForClient;
|
||||
void RemoteClient::informateAssets(const std::vector<std::tuple<EnumAssets, ResourceId, const std::string, const std::string, AssetsManager::Resource>>& resources)
|
||||
{
|
||||
std::vector<std::tuple<EnumAssets, ResourceId, const std::string, const std::string, Hash_t>> newForClient;
|
||||
|
||||
for(int type = 0; type < (int) EnumBinResource::MAX_ENUM; type++) {
|
||||
for(auto& [id, hash] : resourcesLink[type]) {
|
||||
for(auto& [type, resId, domain, key, resource] : resources) {
|
||||
auto hash = resource.hash();
|
||||
|
||||
// Проверка запрашиваемых клиентом ресурсов
|
||||
{
|
||||
auto iter = std::find(AssetsInWork.ClientRequested.begin(), AssetsInWork.ClientRequested.end(), hash);
|
||||
if(iter != AssetsInWork.ClientRequested.end())
|
||||
{
|
||||
auto it = std::lower_bound(AssetsInWork.OnClient.begin(), AssetsInWork.OnClient.end(), hash);
|
||||
|
||||
if(it == AssetsInWork.OnClient.end() || *it != hash)
|
||||
AssetsInWork.OnClient.insert(it, hash);
|
||||
|
||||
AssetsInWork.ToSend.emplace_back(type, domain, key, resId, resource, 0);
|
||||
}
|
||||
}
|
||||
|
||||
auto lock = NetworkAndResource.lock();
|
||||
// Информирование клиента о привязках ресурсов к идентификатору
|
||||
{
|
||||
// Посмотрим что известно клиенту
|
||||
auto iter = ResUses.BinUse[uint8_t(type)].find(id);
|
||||
if(iter != ResUses.BinUse[uint8_t(type)].end()) {
|
||||
if(std::get<1>(iter->second) != hash) {
|
||||
// Требуется перепривязать идентификатор к новому хешу
|
||||
newForClient.push_back({(EnumBinResource) type, id, hash});
|
||||
std::get<1>(iter->second) = hash;
|
||||
// Проверить есть ли хеш на стороне клиента
|
||||
if(!std::binary_search(ClientBinaryCache.begin(), ClientBinaryCache.end(), hash)) {
|
||||
NeedToSend.push_back(hash);
|
||||
NextRequest.Hashes.push_back(hash);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Ресурс не отслеживается клиентом
|
||||
if(auto iter = lock->ResUses.AssetsUse[(int) type].find(resId);
|
||||
iter != lock->ResUses.AssetsUse[(int) type].end()
|
||||
&& std::get<Hash_t>(iter->second) != hash
|
||||
) {
|
||||
// Требуется перепривязать идентификатор к новому хешу
|
||||
newForClient.push_back({(EnumAssets) type, resId, domain, key, hash});
|
||||
std::get<Hash_t>(iter->second) = hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -534,19 +534,21 @@ void RemoteClient::informateIdToHash(const std::unordered_map<ResourceId_t, Reso
|
||||
// Отправляем новые привязки ресурсов
|
||||
if(!newForClient.empty()) {
|
||||
assert(newForClient.size() < 65535*4);
|
||||
auto lock = NetworkAndResource.lock();
|
||||
|
||||
checkPacketBorder(2+4+newForClient.size()*(1+4+32));
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource // Оповещение
|
||||
lock->checkPacketBorder(2+4+newForClient.size()*(1+4+32));
|
||||
lock->NextPacket << (uint8_t) ToClient::L1::Resource // Оповещение
|
||||
<< ((uint8_t) ToClient::L2Resource::Bind) << uint32_t(newForClient.size());
|
||||
|
||||
for(auto& [type, id, hash] : newForClient) {
|
||||
NextPacket << uint8_t(type) << uint32_t(id);
|
||||
NextPacket.write((const std::byte*) hash.data(), hash.size());
|
||||
for(auto& [type, resId, domain, key, hash] : newForClient) {
|
||||
// TODO: может внести ограничение на длину домена и ключа?
|
||||
lock->NextPacket << uint8_t(type) << uint32_t(resId) << domain << key;
|
||||
lock->NextPacket.write((const std::byte*) hash.data(), hash.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefVoxel(const std::unordered_map<DefVoxelId, DefVoxel_t*> &voxels)
|
||||
void RemoteClient::NetworkAndResource_t::informateDefVoxel(const std::vector<std::pair<DefVoxelId, DefVoxel*>>& voxels)
|
||||
{
|
||||
for(auto pair : voxels) {
|
||||
DefVoxelId id = pair.first;
|
||||
@@ -559,110 +561,104 @@ void RemoteClient::informateDefVoxel(const std::unordered_map<DefVoxelId, DefVox
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefNode(const std::unordered_map<DefNodeId, DefNode_t*> &nodes)
|
||||
void RemoteClient::NetworkAndResource_t::informateDefNode(const std::vector<std::pair<DefNodeId, DefNode*>>& nodes)
|
||||
{
|
||||
for(auto& [id, def] : nodes) {
|
||||
if(!ResUses.DefNode.contains(id))
|
||||
continue;
|
||||
// for(auto& [id, def] : nodes) {
|
||||
// if(!ResUses.DefNode.contains(id))
|
||||
// continue;
|
||||
|
||||
size_t reserve = 0;
|
||||
for(int iter = 0; iter < 6; iter++)
|
||||
reserve += def->Texs[iter].Pipeline.size();
|
||||
// size_t reserve = 0;
|
||||
// for(int iter = 0; iter < 6; iter++)
|
||||
// reserve += def->Texs[iter].Pipeline.size();
|
||||
|
||||
checkPacketBorder(1+1+4+1+2*6+reserve);
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::Node
|
||||
<< id << (uint8_t) def->DrawType;
|
||||
// checkPacketBorder(1+1+4+1+2*6+reserve);
|
||||
// NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
// << (uint8_t) ToClient::L2Definition::Node
|
||||
// << id << (uint8_t) def->DrawType;
|
||||
|
||||
for(int iter = 0; iter < 6; iter++) {
|
||||
NextPacket << (uint16_t) def->Texs[iter].Pipeline.size();
|
||||
NextPacket.write((const std::byte*) def->Texs[iter].Pipeline.data(), def->Texs[iter].Pipeline.size());
|
||||
}
|
||||
// for(int iter = 0; iter < 6; iter++) {
|
||||
// NextPacket << (uint16_t) def->Texs[iter].Pipeline.size();
|
||||
// NextPacket.write((const std::byte*) def->Texs[iter].Pipeline.data(), def->Texs[iter].Pipeline.size());
|
||||
// }
|
||||
|
||||
ResUsesObj::RefDefBin_t refs;
|
||||
{
|
||||
auto &array = refs.Resources[(uint8_t) EnumBinResource::Texture];
|
||||
for(int iter = 0; iter < 6; iter++) {
|
||||
array.insert(array.end(), def->Texs[iter].BinTextures.begin(), def->Texs[iter].BinTextures.end());
|
||||
}
|
||||
// ResUsesObj::RefDefBin_t refs;
|
||||
// {
|
||||
// auto &array = refs.Resources[(uint8_t) EnumBinResource::Texture];
|
||||
// for(int iter = 0; iter < 6; iter++) {
|
||||
// array.insert(array.end(), def->Texs[iter].BinTextures.begin(), def->Texs[iter].BinTextures.end());
|
||||
// }
|
||||
|
||||
std::sort(array.begin(), array.end());
|
||||
auto eraseLast = std::unique(array.begin(), array.end());
|
||||
array.erase(eraseLast, array.end());
|
||||
// std::sort(array.begin(), array.end());
|
||||
// auto eraseLast = std::unique(array.begin(), array.end());
|
||||
// array.erase(eraseLast, array.end());
|
||||
|
||||
incrementBinary(refs);
|
||||
}
|
||||
// incrementBinary(refs);
|
||||
// }
|
||||
|
||||
|
||||
{
|
||||
auto iterDefRef = ResUses.RefDefNode.find(id);
|
||||
if(iterDefRef != ResUses.RefDefNode.end()) {
|
||||
decrementBinary(std::move(iterDefRef->second));
|
||||
iterDefRef->second = std::move(refs);
|
||||
} else {
|
||||
ResUses.RefDefNode[id] = std::move(refs);
|
||||
}
|
||||
}
|
||||
// {
|
||||
// auto iterDefRef = ResUses.RefDefNode.find(id);
|
||||
// if(iterDefRef != ResUses.RefDefNode.end()) {
|
||||
// decrementBinary(std::move(iterDefRef->second));
|
||||
// iterDefRef->second = std::move(refs);
|
||||
// } else {
|
||||
// ResUses.RefDefNode[id] = std::move(refs);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefWorld(const std::unordered_map<DefWorldId_t, DefWorld_t*> &worlds)
|
||||
void RemoteClient::NetworkAndResource_t::informateDefWorld(const std::vector<std::pair<DefWorldId, DefWorld*>>& worlds)
|
||||
{
|
||||
for(auto pair : worlds) {
|
||||
DefWorldId_t id = pair.first;
|
||||
if(!ResUses.DefWorld.contains(id))
|
||||
continue;
|
||||
// for(auto pair : worlds) {
|
||||
// DefWorldId_t id = pair.first;
|
||||
// if(!ResUses.DefWorld.contains(id))
|
||||
// continue;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::World
|
||||
<< id;
|
||||
}
|
||||
// NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
// << (uint8_t) ToClient::L2Definition::World
|
||||
// << id;
|
||||
// }
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefPortal(const std::unordered_map<DefPortalId_t, DefPortal_t*> &portals)
|
||||
void RemoteClient::NetworkAndResource_t::informateDefPortal(const std::vector<std::pair<DefPortalId, DefPortal*>>& portals)
|
||||
{
|
||||
for(auto pair : portals) {
|
||||
DefPortalId_t id = pair.first;
|
||||
if(!ResUses.DefPortal.contains(id))
|
||||
continue;
|
||||
// for(auto pair : portals) {
|
||||
// DefPortalId_t id = pair.first;
|
||||
// if(!ResUses.DefPortal.contains(id))
|
||||
// continue;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::Portal
|
||||
<< id;
|
||||
}
|
||||
// NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
// << (uint8_t) ToClient::L2Definition::Portal
|
||||
// << id;
|
||||
// }
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefEntity(const std::unordered_map<DefEntityId_t, DefEntity_t*> &entityes)
|
||||
void RemoteClient::NetworkAndResource_t::informateDefEntity(const std::vector<std::pair<DefEntityId, DefEntity*>>& entityes)
|
||||
{
|
||||
for(auto pair : entityes) {
|
||||
DefEntityId_t id = pair.first;
|
||||
if(!ResUses.DefEntity.contains(id))
|
||||
continue;
|
||||
// for(auto pair : entityes) {
|
||||
// DefEntityId_t id = pair.first;
|
||||
// if(!ResUses.DefEntity.contains(id))
|
||||
// continue;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::Entity
|
||||
<< id;
|
||||
}
|
||||
// NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
// << (uint8_t) ToClient::L2Definition::Entity
|
||||
// << id;
|
||||
// }
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefItem(const std::unordered_map<DefItemId_t, DefItem_t*> &items)
|
||||
void RemoteClient::NetworkAndResource_t::informateDefItem(const std::vector<std::pair<DefItemId, DefItem*>>& items)
|
||||
{
|
||||
for(auto pair : items) {
|
||||
DefItemId_t id = pair.first;
|
||||
if(!ResUses.DefNode.contains(id))
|
||||
continue;
|
||||
// for(auto pair : items) {
|
||||
// DefItemId_t id = pair.first;
|
||||
// if(!ResUses.DefNode.contains(id))
|
||||
// continue;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::FuncEntity
|
||||
<< id;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::checkPacketBorder(uint16_t size) {
|
||||
if(64000-NextPacket.size() < size || (NextPacket.size() != 0 && size == 0)) {
|
||||
SimplePackets.push_back(std::move(NextPacket));
|
||||
}
|
||||
// NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
// << (uint8_t) ToClient::L2Definition::FuncEntity
|
||||
// << id;
|
||||
// }
|
||||
}
|
||||
|
||||
void RemoteClient::protocolError() {
|
||||
@@ -725,31 +721,31 @@ coro<> RemoteClient::rP_System(Net::AsyncSocket &sock) {
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::incrementBinary(const ResUsesObj::RefDefBin_t& bin) {
|
||||
void RemoteClient::NetworkAndResource_t::incrementAssets(const ResUses_t::RefAssets_t& bin) {
|
||||
for(int iter = 0; iter < 5; iter++) {
|
||||
auto &use = ResUses.BinUse[iter];
|
||||
auto &use = ResUses.AssetsUse[iter];
|
||||
|
||||
for(ResourceId_t id : bin.Resources[iter]) {
|
||||
for(ResourceId id : bin.Resources[iter]) {
|
||||
if(++std::get<0>(use[id]) == 1) {
|
||||
NextRequest.BinToHash[iter].push_back(id);
|
||||
LOG.debug() << "Новое определение (тип " << iter << ") -> " << id;
|
||||
NextRequest.AssetsInfo[iter].push_back(id);
|
||||
// LOG.debug() << "Новое определение (тип " << iter << ") -> " << id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::decrementBinary(ResUsesObj::RefDefBin_t&& bin) {
|
||||
std::vector<std::tuple<EnumBinResource, ResourceId_t>> lost;
|
||||
void RemoteClient::NetworkAndResource_t::decrementAssets(ResUses_t::RefAssets_t&& bin) {
|
||||
std::vector<std::tuple<EnumAssets, ResourceId>> lost;
|
||||
|
||||
for(int iter = 0; iter < 5; iter++) {
|
||||
auto &use = ResUses.BinUse[iter];
|
||||
for(int iter = 0; iter < (int) EnumAssets::MAX_ENUM; iter++) {
|
||||
auto &use = ResUses.AssetsUse[iter];
|
||||
|
||||
for(ResourceId_t id : bin.Resources[iter]) {
|
||||
for(ResourceId id : bin.Resources[iter]) {
|
||||
if(--std::get<0>(use[id]) == 0) {
|
||||
use.erase(use.find(id));
|
||||
|
||||
lost.push_back({(EnumBinResource) iter, id});
|
||||
LOG.debug() << "Потеряно определение (тип " << iter << ") -> " << id;
|
||||
lost.push_back({(EnumAssets) iter, id});
|
||||
// LOG.debug() << "Потеряно определение (тип " << iter << ") -> " << id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -767,4 +763,12 @@ void RemoteClient::decrementBinary(ResUsesObj::RefDefBin_t&& bin) {
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::onUpdate() {
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::tuple<WorldId_t, Pos::Object, uint8_t>> RemoteClient::getViewPoints() {
|
||||
return {{0, CameraPos, 2}};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -210,7 +210,8 @@ class RemoteClient {
|
||||
struct NetworkAndResource_t {
|
||||
struct ResUses_t {
|
||||
// Счётчики использования двоичных кэшируемых ресурсов + хэш привязанный к идентификатору
|
||||
std::map<ResourceId, uint32_t> AssetsUse[(int) EnumAssets::MAX_ENUM];
|
||||
// Хэш используется для того, чтобы исключить повторные объявления неизменившихся ресурсов
|
||||
std::map<ResourceId, std::pair<uint32_t, Hash_t>> AssetsUse[(int) EnumAssets::MAX_ENUM];
|
||||
|
||||
// Зависимость профилей контента от профилей ресурсов
|
||||
// Нужно чтобы пересчитать зависимости к профилям ресурсов
|
||||
@@ -260,9 +261,6 @@ class RemoteClient {
|
||||
RefAssets_t Assets;
|
||||
};
|
||||
std::map<ServerEntityId_t, RefEntity_t> RefEntity;
|
||||
|
||||
void incrementBinary(const RefAssets_t& bin);
|
||||
void decrementBinary(RefAssets_t&& bin);
|
||||
} ResUses;
|
||||
|
||||
// Смена идентификаторов сервера на клиентские
|
||||
@@ -271,8 +269,34 @@ class RemoteClient {
|
||||
// Запрос информации об ассетах и профилях контента
|
||||
ResourceRequest NextRequest;
|
||||
|
||||
void incrementAssets(const ResUses_t::RefAssets_t& bin);
|
||||
void decrementAssets(ResUses_t::RefAssets_t&& bin);
|
||||
|
||||
Net::Packet NextPacket;
|
||||
std::vector<Net::Packet> SimplePackets;
|
||||
void checkPacketBorder(uint16_t size) {
|
||||
if(64000-NextPacket.size() < size || (NextPacket.size() != 0 && size == 0)) {
|
||||
SimplePackets.push_back(std::move(NextPacket));
|
||||
}
|
||||
}
|
||||
|
||||
void prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::u8string& compressed_voxels,
|
||||
const std::vector<DefVoxelId>& uniq_sorted_defines);
|
||||
void prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::u8string& compressed_nodes,
|
||||
const std::vector<DefNodeId>& uniq_sorted_defines);
|
||||
void prepareEntitiesRemove(const std::vector<ServerEntityId_t>& entityId);
|
||||
void prepareRegionsRemove(WorldId_t worldId, std::vector<Pos::GlobalRegion> regionPoses);
|
||||
void prepareWorldRemove(WorldId_t worldId);
|
||||
void prepareEntitiesUpdate(const std::vector<std::tuple<ServerEntityId_t, const Entity*>>& entities);
|
||||
void prepareEntitiesUpdate_Dynamic(const std::vector<std::tuple<ServerEntityId_t, const Entity*>>& entities);
|
||||
void prepareEntitySwap(ServerEntityId_t prevEntityId, ServerEntityId_t nextEntityId);
|
||||
void prepareWorldUpdate(WorldId_t worldId, World* world);
|
||||
void informateDefVoxel(const std::vector<std::pair<DefVoxelId, DefVoxel*>>& voxels);
|
||||
void informateDefNode(const std::vector<std::pair<DefNodeId, DefNode*>>& nodes);
|
||||
void informateDefWorld(const std::vector<std::pair<DefWorldId, DefWorld*>>& worlds);
|
||||
void informateDefPortal(const std::vector<std::pair<DefPortalId, DefPortal*>>& portals);
|
||||
void informateDefEntity(const std::vector<std::pair<DefEntityId, DefEntity*>>& entityes);
|
||||
void informateDefItem(const std::vector<std::pair<DefItemId, DefItem*>>& items);
|
||||
};
|
||||
|
||||
struct {
|
||||
@@ -284,9 +308,11 @@ class RemoteClient {
|
||||
*/
|
||||
|
||||
// Ресурсы, отправленные на клиент в этой сессии и запрошенные клиентом
|
||||
/// TODO: ClientRequested здесь может быть засор
|
||||
std::vector<Hash_t> OnClient, ClientRequested;
|
||||
// Отправляемые на клиент ресурсы (в конце текущее смещение по отправке)
|
||||
std::vector<std::tuple<EnumAssets, ResourceId, AssetsManager::Resource, size_t>> ToSend;
|
||||
// Отправляемые на клиент ресурсы
|
||||
// Тип, домен, ключ, идентификатор, ресурс, количество отправленных байт
|
||||
std::vector<std::tuple<EnumAssets, std::string, std::string, ResourceId, AssetsManager::Resource, size_t>> ToSend;
|
||||
} AssetsInWork;
|
||||
|
||||
TOS::SpinlockObject<NetworkAndResource_t> NetworkAndResource;
|
||||
@@ -335,26 +361,43 @@ public:
|
||||
|
||||
// В зоне видимости добавился чанк или изменились его воксели
|
||||
bool maybe_prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::u8string& compressed_voxels,
|
||||
const std::vector<DefVoxelId>& uniq_sorted_defines);
|
||||
const std::vector<DefVoxelId>& uniq_sorted_defines)
|
||||
{
|
||||
auto lock = NetworkAndResource.tryLock();
|
||||
if(!lock)
|
||||
return false;
|
||||
|
||||
lock->prepareChunkUpdate_Voxels(worldId, chunkPos, compressed_voxels, uniq_sorted_defines);
|
||||
return true;
|
||||
}
|
||||
|
||||
// В зоне видимости добавился чанк или изменились его ноды
|
||||
bool maybe_prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::GlobalChunk chunkPos, const std::u8string& compressed_nodes,
|
||||
const std::vector<DefNodeId>& uniq_sorted_defines);
|
||||
const std::vector<DefNodeId>& uniq_sorted_defines)
|
||||
{
|
||||
auto lock = NetworkAndResource.tryLock();
|
||||
if(!lock)
|
||||
return false;
|
||||
|
||||
lock->prepareChunkUpdate_Nodes(worldId, chunkPos, compressed_nodes, uniq_sorted_defines);
|
||||
return true;
|
||||
}
|
||||
// void prepareChunkUpdate_LightPrism(WorldId_t worldId, Pos::GlobalChunk chunkPos, const LightPrism *lights);
|
||||
|
||||
// Клиент перестал наблюдать за сущностью
|
||||
void prepareEntitiesRemove(const std::vector<ServerEntityId_t>& entityId);
|
||||
void prepareEntitiesRemove(const std::vector<ServerEntityId_t>& entityId) { NetworkAndResource.lock()->prepareEntitiesRemove(entityId); }
|
||||
// Регион удалён из зоны видимости
|
||||
void prepareRegionRemove(WorldId_t worldId, std::vector<Pos::GlobalRegion> regionPoses);
|
||||
void prepareRegionsRemove(WorldId_t worldId, std::vector<Pos::GlobalRegion> regionPoses) { NetworkAndResource.lock()->prepareRegionsRemove(worldId, regionPoses); }
|
||||
// Мир удалён из зоны видимости
|
||||
void prepareWorldRemove(WorldId_t worldId);
|
||||
void prepareWorldRemove(WorldId_t worldId) { NetworkAndResource.lock()->prepareWorldRemove(worldId); }
|
||||
|
||||
// В зоне видимости добавилась новая сущность или она изменилась
|
||||
void prepareEntityUpdate(const std::vector<std::tuple<ServerEntityId_t, const Entity*>>& entities);
|
||||
void prepareEntityUpdate_Dynamic(const std::vector<std::tuple<ServerEntityId_t, const Entity*>>& entities);
|
||||
void prepareEntitiesUpdate(const std::vector<std::tuple<ServerEntityId_t, const Entity*>>& entities) { NetworkAndResource.lock()->prepareEntitiesUpdate(entities); }
|
||||
void prepareEntitiesUpdate_Dynamic(const std::vector<std::tuple<ServerEntityId_t, const Entity*>>& entities) { NetworkAndResource.lock()->prepareEntitiesUpdate_Dynamic(entities); }
|
||||
// Наблюдаемая сущность пересекла границы региона, у неё изменился серверный идентификатор
|
||||
void prepareEntitySwap(ServerEntityId_t prevEntityId, ServerEntityId_t nextEntityId);
|
||||
void prepareEntitySwap(ServerEntityId_t prevEntityId, ServerEntityId_t nextEntityId) { NetworkAndResource.lock()->prepareEntitySwap(prevEntityId, nextEntityId); }
|
||||
// Мир появился в зоне видимости или изменился
|
||||
void prepareWorldUpdate(WorldId_t worldId, World* world);
|
||||
void prepareWorldUpdate(WorldId_t worldId, World* world) { NetworkAndResource.lock()->prepareWorldUpdate(worldId, world); }
|
||||
|
||||
// В зоне видимости добавился порта или он изменился
|
||||
// void preparePortalUpdate(PortalId_t portalId, void* portal);
|
||||
@@ -375,15 +418,16 @@ public:
|
||||
void informateAssets(const std::vector<std::tuple<EnumAssets, ResourceId, const std::string, const std::string, AssetsManager::Resource>>& resources);
|
||||
|
||||
// Игровые определения
|
||||
void informateDefVoxel(const std::unordered_map<DefVoxelId, DefVoxel*> &voxels);
|
||||
void informateDefNode(const std::unordered_map<DefNodeId, DefNode*> &nodes);
|
||||
void informateDefWorld(const std::unordered_map<DefWorldId, DefWorld*> &worlds);
|
||||
void informateDefPortal(const std::unordered_map<DefPortalId, DefPortal*> &portals);
|
||||
void informateDefEntity(const std::unordered_map<DefEntityId, DefEntity*> &entityes);
|
||||
void informateDefItem(const std::unordered_map<DefItemId, DefItem_t*> &items);
|
||||
void informateDefVoxel(const std::vector<std::pair<DefVoxelId, DefVoxel*>>& voxels) { NetworkAndResource.lock()->informateDefVoxel(voxels); }
|
||||
void informateDefNode(const std::vector<std::pair<DefNodeId, DefNode*>>& nodes) { NetworkAndResource.lock()->informateDefNode(nodes); }
|
||||
void informateDefWorld(const std::vector<std::pair<DefWorldId, DefWorld*>>& worlds) { NetworkAndResource.lock()->informateDefWorld(worlds); }
|
||||
void informateDefPortal(const std::vector<std::pair<DefPortalId, DefPortal*>>& portals) { NetworkAndResource.lock()->informateDefPortal(portals); }
|
||||
void informateDefEntity(const std::vector<std::pair<DefEntityId, DefEntity*>>& entityes) { NetworkAndResource.lock()->informateDefEntity(entityes); }
|
||||
void informateDefItem(const std::vector<std::pair<DefItemId, DefItem*>>& items) { NetworkAndResource.lock()->informateDefItem(items); }
|
||||
|
||||
void onUpdate();
|
||||
|
||||
private:
|
||||
void checkPacketBorder(uint16_t size);
|
||||
void protocolError();
|
||||
coro<> readPacket(Net::AsyncSocket &sock);
|
||||
coro<> rP_System(Net::AsyncSocket &sock);
|
||||
|
||||
@@ -18,15 +18,15 @@ struct SB_Region_In {
|
||||
// Список вокселей всех чанков
|
||||
std::unordered_map<Pos::bvec4u, VoxelCube> Voxels;
|
||||
// Привязка вокселей к ключу профиля
|
||||
std::vector<std::pair<DefVoxelId_t, std::string>> VoxelsMap;
|
||||
std::vector<std::pair<DefVoxelId, std::string>> VoxelsMap;
|
||||
// Ноды всех чанков
|
||||
std::array<std::array<Node, 16*16*16>, 4*4*4> Nodes;
|
||||
// Привязка нод к ключу профиля
|
||||
std::vector<std::pair<DefNodeId_t, std::string>> NodeMap;
|
||||
std::vector<std::pair<DefNodeId, std::string>> NodeMap;
|
||||
// Сущности
|
||||
std::vector<Entity> Entityes;
|
||||
// Привязка идентификатора к ключу профиля
|
||||
std::vector<std::pair<DefEntityId_t, std::string>> EntityMap;
|
||||
std::vector<std::pair<DefEntityId, std::string>> EntityMap;
|
||||
};
|
||||
|
||||
struct DB_Region_Out {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
namespace LV::Server {
|
||||
|
||||
|
||||
World::World(DefWorldId_t defId)
|
||||
World::World(DefWorldId defId)
|
||||
: DefId(defId)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ World::~World() {
|
||||
|
||||
}
|
||||
|
||||
std::vector<Pos::GlobalRegion> World::onCEC_RegionsEnter(std::shared_ptr<ContentEventController> cec, const std::vector<Pos::GlobalRegion>& enter) {
|
||||
std::vector<Pos::GlobalRegion> World::onRemoteClient_RegionsEnter(std::shared_ptr<RemoteClient> cec, const std::vector<Pos::GlobalRegion>& enter) {
|
||||
std::vector<Pos::GlobalRegion> out;
|
||||
|
||||
for(const Pos::GlobalRegion &pos : enter) {
|
||||
@@ -27,8 +27,8 @@ std::vector<Pos::GlobalRegion> World::onCEC_RegionsEnter(std::shared_ptr<Content
|
||||
}
|
||||
|
||||
auto ®ion = *iterRegion->second;
|
||||
region.CECs.push_back(cec);
|
||||
region.NewCECs.push_back(cec);
|
||||
region.RMs.push_back(cec);
|
||||
region.NewRMs.push_back(cec);
|
||||
// Отправить клиенту информацию о чанках и сущностях
|
||||
std::unordered_map<Pos::bvec4u, const std::vector<VoxelCube>*> voxels;
|
||||
std::unordered_map<Pos::bvec4u, const Node*> nodes;
|
||||
@@ -49,13 +49,13 @@ std::vector<Pos::GlobalRegion> World::onCEC_RegionsEnter(std::shared_ptr<Content
|
||||
return out;
|
||||
}
|
||||
|
||||
void World::onCEC_RegionsLost(std::shared_ptr<ContentEventController> cec, const std::vector<Pos::GlobalRegion> &lost) {
|
||||
void World::onRemoteClient_RegionsLost(std::shared_ptr<RemoteClient> cec, const std::vector<Pos::GlobalRegion> &lost) {
|
||||
for(const Pos::GlobalRegion &pos : lost) {
|
||||
auto region = Regions.find(pos);
|
||||
if(region == Regions.end())
|
||||
continue;
|
||||
|
||||
std::vector<std::shared_ptr<ContentEventController>> &CECs = region->second->CECs;
|
||||
std::vector<std::shared_ptr<RemoteClient>> &CECs = region->second->RMs;
|
||||
for(size_t iter = 0; iter < CECs.size(); iter++) {
|
||||
if(CECs[iter] == cec) {
|
||||
CECs.erase(CECs.begin()+iter);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Common/Abstract.hpp"
|
||||
#include "Server/Abstract.hpp"
|
||||
#include "Server/RemoteClient.hpp"
|
||||
#include "Server/SaveBackend.hpp"
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
@@ -24,10 +25,7 @@ public:
|
||||
std::array<std::array<Node, 16*16*16>, 4*4*4> Nodes;
|
||||
|
||||
std::vector<Entity> Entityes;
|
||||
std::vector<std::shared_ptr<ContentEventController>> CECs, NewCECs;
|
||||
// Используется для прорежения количества проверок на наблюдаемые чанки и сущности
|
||||
// В одно обновление региона - проверка одного наблюдателя
|
||||
uint16_t CEC_NextChunkAndEntityesViewCheck = 0;
|
||||
std::vector<std::shared_ptr<RemoteClient>> RMs, NewRMs;
|
||||
|
||||
float LastSaveTime = 0;
|
||||
|
||||
@@ -134,13 +132,13 @@ public:
|
||||
};
|
||||
|
||||
class World {
|
||||
DefWorldId_t DefId;
|
||||
DefWorldId DefId;
|
||||
|
||||
public:
|
||||
std::unordered_map<Pos::GlobalRegion, std::unique_ptr<Region>> Regions;
|
||||
|
||||
public:
|
||||
World(DefWorldId_t defId);
|
||||
World(DefWorldId defId);
|
||||
~World();
|
||||
|
||||
/*
|
||||
@@ -148,8 +146,8 @@ public:
|
||||
Возвращает список не загруженных регионов, на которые соответственно игрока не получилось подписать
|
||||
При подписи происходит отправка всех чанков и сущностей региона
|
||||
*/
|
||||
std::vector<Pos::GlobalRegion> onCEC_RegionsEnter(std::shared_ptr<ContentEventController> cec, const std::vector<Pos::GlobalRegion> &enter);
|
||||
void onCEC_RegionsLost(std::shared_ptr<ContentEventController> cec, const std::vector<Pos::GlobalRegion>& lost);
|
||||
std::vector<Pos::GlobalRegion> onRemoteClient_RegionsEnter(std::shared_ptr<RemoteClient> cec, const std::vector<Pos::GlobalRegion> &enter);
|
||||
void onRemoteClient_RegionsLost(std::shared_ptr<RemoteClient> cec, const std::vector<Pos::GlobalRegion>& lost);
|
||||
struct SaveUnloadInfo {
|
||||
std::vector<Pos::GlobalRegion> ToUnload;
|
||||
std::vector<std::pair<Pos::GlobalRegion, SB_Region_In>> ToSave;
|
||||
@@ -173,7 +171,7 @@ public:
|
||||
|
||||
*/
|
||||
|
||||
DefWorldId_t getDefId() const { return DefId; }
|
||||
DefWorldId getDefId() const { return DefId; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -149,6 +149,10 @@ public:
|
||||
T* operator->() const { assert(Obj); return &Obj->Value; }
|
||||
T& operator*() const { assert(Obj); return Obj->Value; }
|
||||
|
||||
operator bool() const {
|
||||
return Obj;
|
||||
}
|
||||
|
||||
void unlock() { assert(Obj); Obj = nullptr; Flag->clear(std::memory_order_release);}
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user