*
This commit is contained in:
@@ -76,9 +76,9 @@ public:
|
||||
std::unordered_map<EnumDefContent, std::vector<ResourceId>> Profiles_Lost;
|
||||
|
||||
// Новые или изменённые чанки
|
||||
std::unordered_map<WorldId_t, std::unordered_set<Pos::GlobalChunk>> Chunks_ChangeOrAdd;
|
||||
std::unordered_map<WorldId_t, std::vector<Pos::GlobalChunk>> Chunks_ChangeOrAdd;
|
||||
// Более не отслеживаемые регионы
|
||||
std::unordered_map<WorldId_t, std::unordered_set<Pos::GlobalRegion>> Chunks_Lost;
|
||||
std::unordered_map<WorldId_t, std::vector<Pos::GlobalRegion>> Chunks_Lost;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "ServerSession.hpp"
|
||||
#include "Client/Abstract.hpp"
|
||||
#include "Client/AssetsManager.hpp"
|
||||
#include "Common/Abstract.hpp"
|
||||
#include "Common/Net.hpp"
|
||||
#include "TOSAsync.hpp"
|
||||
@@ -21,7 +22,7 @@
|
||||
namespace LV::Client {
|
||||
|
||||
ServerSession::ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSocket>&& socket)
|
||||
: IAsyncDestructible(ioc), Socket(std::move(socket)), NetInputPackets(1024)
|
||||
: IAsyncDestructible(ioc), Socket(std::move(socket)) //, NetInputPackets(1024)
|
||||
{
|
||||
assert(Socket.get());
|
||||
|
||||
@@ -40,78 +41,6 @@ coro<> ServerSession::asyncDestructor() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ParsedPacket::~ParsedPacket() = default;
|
||||
|
||||
struct PP_Content_ChunkVoxels : public ParsedPacket {
|
||||
WorldId_t Id;
|
||||
Pos::GlobalChunk Pos;
|
||||
std::vector<VoxelCube> Cubes;
|
||||
|
||||
PP_Content_ChunkVoxels(WorldId_t id, Pos::GlobalChunk pos, std::vector<VoxelCube> &&cubes)
|
||||
: ParsedPacket(ToClient::L1::Content, (uint8_t) ToClient::L2Content::ChunkVoxels), Id(id), Pos(pos), Cubes(std::move(cubes))
|
||||
{}
|
||||
};
|
||||
|
||||
struct PP_Content_ChunkNodes : public ParsedPacket {
|
||||
WorldId_t Id;
|
||||
Pos::GlobalChunk Pos;
|
||||
std::array<Node, 16*16*16> Nodes;
|
||||
|
||||
PP_Content_ChunkNodes(WorldId_t id, Pos::GlobalChunk pos)
|
||||
: ParsedPacket(ToClient::L1::Content, (uint8_t) ToClient::L2Content::ChunkNodes), Id(id), Pos(pos)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct PP_Content_RegionRemove : public ParsedPacket {
|
||||
WorldId_t Id;
|
||||
Pos::GlobalRegion Pos;
|
||||
|
||||
PP_Content_RegionRemove(WorldId_t id, Pos::GlobalRegion pos)
|
||||
: ParsedPacket(ToClient::L1::Content, (uint8_t) ToClient::L2Content::RemoveRegion), Id(id), Pos(pos)
|
||||
{}
|
||||
};
|
||||
|
||||
struct PP_Definition_Voxel : public ParsedPacket {
|
||||
DefVoxelId 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 Id;
|
||||
|
||||
PP_Definition_FreeVoxel(DefVoxelId id)
|
||||
: ParsedPacket(ToClient::L1::Definition, (uint8_t) ToClient::L2Definition::FreeVoxel),
|
||||
Id(id)
|
||||
{}
|
||||
};
|
||||
|
||||
struct PP_Definition_Node : public ParsedPacket {
|
||||
DefNodeId 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 Id;
|
||||
|
||||
PP_Definition_FreeNode(DefNodeId id)
|
||||
: ParsedPacket(ToClient::L1::Definition, (uint8_t) ToClient::L2Definition::FreeNode),
|
||||
Id(id)
|
||||
{}
|
||||
};
|
||||
|
||||
using namespace TOS;
|
||||
|
||||
ServerSession::~ServerSession() {
|
||||
@@ -347,7 +276,36 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
||||
AM->pushResources(std::move(resources));
|
||||
}
|
||||
|
||||
// Получить ресурсы с AssetsManager
|
||||
{
|
||||
std::vector<std::pair<AssetsManager::ResourceKey, std::optional<Resource>>> resources = AM->pullReads();
|
||||
std::vector<Hash_t> needRequest;
|
||||
|
||||
for(auto& [key, res] : resources) {
|
||||
if(!res) {
|
||||
// Проверить не был ли уже отправлен запрос на получение этого хеша
|
||||
auto iter = std::lower_bound(AsyncContext.AlreadyLoading.begin(), AsyncContext.AlreadyLoading.end(), res->hash());
|
||||
if(iter == AsyncContext.AlreadyLoading.end()) {
|
||||
AsyncContext.AlreadyLoading.insert(iter, res->hash());
|
||||
needRequest.push_back(res->hash());
|
||||
}
|
||||
} else {
|
||||
AsyncContext.LoadedResources.emplace_back(key, *res);
|
||||
}
|
||||
}
|
||||
|
||||
if(!needRequest.empty()) {
|
||||
assert(needRequest.size() < (1 << 16));
|
||||
|
||||
Net::Packet p;
|
||||
p << (uint8_t) ToServer::L1::System << (uint8_t) ToServer::L2System::ResourceRequest;
|
||||
p << (uint16_t) needRequest.size();
|
||||
for(const Hash_t& hash : needRequest)
|
||||
p.write((const std::byte*) hash.data(), 32);
|
||||
|
||||
Socket->pushPacket(std::move(p));
|
||||
}
|
||||
}
|
||||
|
||||
// Разбираемся с полученными меж тактами привязками ресурсов
|
||||
if(!AsyncContext.AssetsBinds.get_read().empty()) {
|
||||
@@ -436,8 +394,6 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
||||
}
|
||||
}
|
||||
|
||||
// Assets.ExistBinds[(int) bind.Type].insert(bind.Id);
|
||||
|
||||
// Под рукой нет ресурса, отправим на проверку в AssetsManager
|
||||
if(needQuery) {
|
||||
AsyncContext.ResourceWait[(int) bind.Type][bind.Domain].emplace_back(bind.Key, bind.Hash);
|
||||
@@ -448,6 +404,8 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
||||
// Отправляем запрос на получение ресурсов
|
||||
if(!needToLoad.empty())
|
||||
AM->pushReads(std::move(needToLoad));
|
||||
|
||||
AsyncContext.Binds.push_back(std::move(abc));
|
||||
}
|
||||
|
||||
if(!AsyncContext.TickSequence.get_read().empty()) {
|
||||
@@ -456,11 +414,274 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
||||
if(RS)
|
||||
RS->prepareTickSync();
|
||||
|
||||
std::vector<TickData> ticks = std::move(*AsyncContext.TickSequence.lock());
|
||||
|
||||
IRenderSession::TickSyncData result;
|
||||
// Перевариваем данные по тактам
|
||||
|
||||
// Профили
|
||||
std::unordered_map<DefVoxelId, void*> profile_Voxel_AddOrChange;
|
||||
std::vector<DefVoxelId> profile_Voxel_Lost;
|
||||
std::unordered_map<DefNodeId, void*> profile_Node_AddOrChange;
|
||||
std::vector<DefNodeId> profile_Node_Lost;
|
||||
std::unordered_map<DefWorldId, void*> profile_World_AddOrChange;
|
||||
std::vector<DefWorldId> profile_World_Lost;
|
||||
std::unordered_map<DefPortalId, void*> profile_Portal_AddOrChange;
|
||||
std::vector<DefPortalId> profile_Portal_Lost;
|
||||
std::unordered_map<DefEntityId, void*> profile_Entity_AddOrChange;
|
||||
std::vector<DefEntityId> profile_Entity_Lost;
|
||||
std::unordered_map<DefItemId, void*> profile_Item_AddOrChange;
|
||||
std::vector<DefItemId> profile_Item_Lost;
|
||||
|
||||
{
|
||||
for(TickData& data : ticks) {
|
||||
{
|
||||
for(auto& [id, profile] : data.Profile_Voxel_AddOrChange) {
|
||||
auto iter = std::lower_bound(profile_Voxel_Lost.begin(), profile_Voxel_Lost.end(), id);
|
||||
if(iter != profile_Voxel_Lost.end())
|
||||
profile_Voxel_Lost.erase(iter);
|
||||
|
||||
profile_Voxel_AddOrChange[id] = profile;
|
||||
}
|
||||
|
||||
for(DefVoxelId id : data.Profile_Voxel_Lost) {
|
||||
profile_Voxel_AddOrChange.erase(id);
|
||||
}
|
||||
|
||||
profile_Voxel_Lost.insert(profile_Voxel_Lost.end(), data.Profile_Voxel_Lost.begin(), data.Profile_Voxel_Lost.end());
|
||||
std::sort(profile_Voxel_Lost.begin(), profile_Voxel_Lost.end());
|
||||
auto eraseIter = std::unique(profile_Voxel_Lost.begin(), profile_Voxel_Lost.end());
|
||||
profile_Voxel_Lost.erase(eraseIter, profile_Voxel_Lost.end());
|
||||
}
|
||||
|
||||
{
|
||||
for(auto& [id, profile] : data.Profile_Node_AddOrChange) {
|
||||
auto iter = std::lower_bound(profile_Node_Lost.begin(), profile_Node_Lost.end(), id);
|
||||
if(iter != profile_Node_Lost.end())
|
||||
profile_Node_Lost.erase(iter);
|
||||
|
||||
profile_Node_AddOrChange[id] = profile;
|
||||
}
|
||||
|
||||
for(DefNodeId id : data.Profile_Node_Lost) {
|
||||
profile_Node_AddOrChange.erase(id);
|
||||
}
|
||||
|
||||
profile_Node_Lost.insert(profile_Node_Lost.end(), data.Profile_Node_Lost.begin(), data.Profile_Node_Lost.end());
|
||||
std::sort(profile_Node_Lost.begin(), profile_Node_Lost.end());
|
||||
auto eraseIter = std::unique(profile_Node_Lost.begin(), profile_Node_Lost.end());
|
||||
profile_Node_Lost.erase(eraseIter, profile_Node_Lost.end());
|
||||
}
|
||||
|
||||
{
|
||||
for(auto& [id, profile] : data.Profile_World_AddOrChange) {
|
||||
auto iter = std::lower_bound(profile_World_Lost.begin(), profile_World_Lost.end(), id);
|
||||
if(iter != profile_World_Lost.end())
|
||||
profile_World_Lost.erase(iter);
|
||||
|
||||
profile_World_AddOrChange[id] = profile;
|
||||
}
|
||||
|
||||
for(DefWorldId id : data.Profile_World_Lost) {
|
||||
profile_World_AddOrChange.erase(id);
|
||||
}
|
||||
|
||||
profile_World_Lost.insert(profile_World_Lost.end(), data.Profile_World_Lost.begin(), data.Profile_World_Lost.end());
|
||||
std::sort(profile_World_Lost.begin(), profile_World_Lost.end());
|
||||
auto eraseIter = std::unique(profile_World_Lost.begin(), profile_World_Lost.end());
|
||||
profile_World_Lost.erase(eraseIter, profile_World_Lost.end());
|
||||
}
|
||||
|
||||
{
|
||||
for(auto& [id, profile] : data.Profile_Portal_AddOrChange) {
|
||||
auto iter = std::lower_bound(profile_Portal_Lost.begin(), profile_Portal_Lost.end(), id);
|
||||
if(iter != profile_Portal_Lost.end())
|
||||
profile_Portal_Lost.erase(iter);
|
||||
|
||||
profile_Portal_AddOrChange[id] = profile;
|
||||
}
|
||||
|
||||
for(DefPortalId id : data.Profile_Portal_Lost) {
|
||||
profile_Portal_AddOrChange.erase(id);
|
||||
}
|
||||
|
||||
profile_Portal_Lost.insert(profile_Portal_Lost.end(), data.Profile_Portal_Lost.begin(), data.Profile_Portal_Lost.end());
|
||||
std::sort(profile_Portal_Lost.begin(), profile_Portal_Lost.end());
|
||||
auto eraseIter = std::unique(profile_Portal_Lost.begin(), profile_Portal_Lost.end());
|
||||
profile_Portal_Lost.erase(eraseIter, profile_Portal_Lost.end());
|
||||
}
|
||||
|
||||
{
|
||||
for(auto& [id, profile] : data.Profile_Entity_AddOrChange) {
|
||||
auto iter = std::lower_bound(profile_Entity_Lost.begin(), profile_Entity_Lost.end(), id);
|
||||
if(iter != profile_Entity_Lost.end())
|
||||
profile_Entity_Lost.erase(iter);
|
||||
|
||||
profile_Entity_AddOrChange[id] = profile;
|
||||
}
|
||||
|
||||
for(DefEntityId id : data.Profile_Entity_Lost) {
|
||||
profile_Entity_AddOrChange.erase(id);
|
||||
}
|
||||
|
||||
profile_Entity_Lost.insert(profile_Entity_Lost.end(), data.Profile_Entity_Lost.begin(), data.Profile_Entity_Lost.end());
|
||||
std::sort(profile_Entity_Lost.begin(), profile_Entity_Lost.end());
|
||||
auto eraseIter = std::unique(profile_Entity_Lost.begin(), profile_Entity_Lost.end());
|
||||
profile_Entity_Lost.erase(eraseIter, profile_Entity_Lost.end());
|
||||
}
|
||||
|
||||
{
|
||||
for(auto& [id, profile] : data.Profile_Item_AddOrChange) {
|
||||
auto iter = std::lower_bound(profile_Item_Lost.begin(), profile_Item_Lost.end(), id);
|
||||
if(iter != profile_Item_Lost.end())
|
||||
profile_Item_Lost.erase(iter);
|
||||
|
||||
profile_Item_AddOrChange[id] = profile;
|
||||
}
|
||||
|
||||
for(DefItemId id : data.Profile_Item_Lost) {
|
||||
profile_Item_AddOrChange.erase(id);
|
||||
}
|
||||
|
||||
profile_Item_Lost.insert(profile_Item_Lost.end(), data.Profile_Item_Lost.begin(), data.Profile_Item_Lost.end());
|
||||
std::sort(profile_Item_Lost.begin(), profile_Item_Lost.end());
|
||||
auto eraseIter = std::unique(profile_Item_Lost.begin(), profile_Item_Lost.end());
|
||||
profile_Item_Lost.erase(eraseIter, profile_Item_Lost.end());
|
||||
}
|
||||
}
|
||||
|
||||
for(auto& [id, _] : profile_Voxel_AddOrChange)
|
||||
result.Profiles_ChangeOrAdd[EnumDefContent::Voxel].push_back(id);
|
||||
result.Profiles_Lost[EnumDefContent::Voxel] = profile_Voxel_Lost;
|
||||
|
||||
for(auto& [id, _] : profile_Node_AddOrChange)
|
||||
result.Profiles_ChangeOrAdd[EnumDefContent::Node].push_back(id);
|
||||
result.Profiles_Lost[EnumDefContent::Node] = profile_Node_Lost;
|
||||
|
||||
for(auto& [id, _] : profile_World_AddOrChange)
|
||||
result.Profiles_ChangeOrAdd[EnumDefContent::World].push_back(id);
|
||||
result.Profiles_Lost[EnumDefContent::World] = profile_World_Lost;
|
||||
|
||||
for(auto& [id, _] : profile_Portal_AddOrChange)
|
||||
result.Profiles_ChangeOrAdd[EnumDefContent::Portal].push_back(id);
|
||||
result.Profiles_Lost[EnumDefContent::Portal] = profile_Portal_Lost;
|
||||
|
||||
for(auto& [id, _] : profile_Entity_AddOrChange)
|
||||
result.Profiles_ChangeOrAdd[EnumDefContent::Entity].push_back(id);
|
||||
result.Profiles_Lost[EnumDefContent::Entity] = profile_Entity_Lost;
|
||||
|
||||
for(auto& [id, _] : profile_Item_AddOrChange)
|
||||
result.Profiles_ChangeOrAdd[EnumDefContent::Item].push_back(id);
|
||||
result.Profiles_Lost[EnumDefContent::Item] = profile_Item_Lost;
|
||||
}
|
||||
|
||||
// Чанки
|
||||
std::unordered_map<WorldId_t, std::unordered_map<Pos::GlobalChunk, std::vector<VoxelCube>>> chunks_AddOrChange_Voxel_Result;
|
||||
std::unordered_map<WorldId_t, std::unordered_map<Pos::GlobalChunk, std::array<Node, 16*16*16>>> chunks_AddOrChange_Node_Result;
|
||||
std::unordered_map<WorldId_t, std::vector<Pos::GlobalChunk>> chunks_Changed;
|
||||
std::unordered_map<WorldId_t, std::unordered_set<Pos::GlobalRegion>> regions_Lost_Result;
|
||||
|
||||
{
|
||||
std::unordered_map<WorldId_t, std::unordered_map<Pos::GlobalChunk, std::u8string>> chunks_AddOrChange_Voxel;
|
||||
std::unordered_map<WorldId_t, std::unordered_map<Pos::GlobalChunk, std::u8string>> chunks_AddOrChange_Node;
|
||||
std::unordered_map<WorldId_t, std::unordered_set<Pos::GlobalRegion>> regions_Lost;
|
||||
|
||||
for(TickData& data : ticks) {
|
||||
for(auto& [wId, chunks] : data.Chunks_AddOrChange_Voxel) {
|
||||
if(auto iter = regions_Lost.find(wId); iter != regions_Lost.end()) {
|
||||
for(const auto& [pos, value] : chunks) {
|
||||
iter->second.erase(Pos::GlobalRegion(pos >> 2));
|
||||
}
|
||||
}
|
||||
|
||||
chunks_AddOrChange_Voxel[wId].merge(chunks);
|
||||
}
|
||||
|
||||
data.Chunks_AddOrChange_Voxel.clear();
|
||||
|
||||
for(auto& [wId, chunks] : data.Chunks_AddOrChange_Node) {
|
||||
if(auto iter = regions_Lost.find(wId); iter != regions_Lost.end()) {
|
||||
for(const auto& [pos, value] : chunks) {
|
||||
iter->second.erase(Pos::GlobalRegion(pos >> 2));
|
||||
}
|
||||
}
|
||||
|
||||
chunks_AddOrChange_Node[wId].merge(chunks);
|
||||
}
|
||||
|
||||
data.Chunks_AddOrChange_Node.clear();
|
||||
|
||||
for(auto& [wId, regions] : data.Regions_Lost) {
|
||||
std::sort(regions.begin(), regions.end());
|
||||
|
||||
if(auto iter = chunks_AddOrChange_Voxel.find(wId); iter != chunks_AddOrChange_Voxel.end())
|
||||
{
|
||||
std::vector<Pos::GlobalChunk> toDelete;
|
||||
for(auto& [pos, value] : iter->second) {
|
||||
if(std::binary_search(regions.begin(), regions.end(), Pos::GlobalRegion(pos >> 2))) {
|
||||
toDelete.push_back(pos);
|
||||
}
|
||||
}
|
||||
|
||||
for(Pos::GlobalChunk pos : toDelete)
|
||||
iter->second.erase(iter->second.find(pos));
|
||||
}
|
||||
|
||||
if(auto iter = chunks_AddOrChange_Node.find(wId); iter != chunks_AddOrChange_Node.end())
|
||||
{
|
||||
std::vector<Pos::GlobalChunk> toDelete;
|
||||
for(auto& [pos, value] : iter->second) {
|
||||
if(std::binary_search(regions.begin(), regions.end(), Pos::GlobalRegion(pos >> 2))) {
|
||||
toDelete.push_back(pos);
|
||||
}
|
||||
}
|
||||
|
||||
for(Pos::GlobalChunk pos : toDelete)
|
||||
iter->second.erase(iter->second.find(pos));
|
||||
}
|
||||
|
||||
regions_Lost[wId].insert_range(regions);
|
||||
}
|
||||
|
||||
data.Regions_Lost.clear();
|
||||
}
|
||||
|
||||
for(auto& [wId, list] : chunks_AddOrChange_Voxel) {
|
||||
auto& caocvr = chunks_AddOrChange_Voxel_Result[wId];
|
||||
auto& c = chunks_Changed[wId];
|
||||
|
||||
for(auto& [pos, val] : list) {
|
||||
caocvr[pos] = unCompressVoxels(val);
|
||||
c.push_back(pos);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto& [wId, list] : chunks_AddOrChange_Node) {
|
||||
auto& caocvr = chunks_AddOrChange_Node_Result[wId];
|
||||
auto& c = chunks_Changed[wId];
|
||||
|
||||
for(auto& [pos, val] : list) {
|
||||
unCompressNodes(val, caocvr[pos].data());
|
||||
c.push_back(pos);
|
||||
}
|
||||
}
|
||||
|
||||
regions_Lost_Result = std::move(regions_Lost);
|
||||
|
||||
for(auto& [wId, list] : chunks_Changed) {
|
||||
std::sort(list.begin(), list.end());
|
||||
auto eraseIter = std::unique(list.begin(), list.end());
|
||||
list.erase(eraseIter, list.end());
|
||||
}
|
||||
}
|
||||
|
||||
result.Chunks_ChangeOrAdd = std::move(chunks_Changed);
|
||||
|
||||
|
||||
{
|
||||
for(TickData& data : ticks) {
|
||||
}
|
||||
}
|
||||
|
||||
if(RS)
|
||||
RS->pushStageTickSync();
|
||||
@@ -484,58 +705,9 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
||||
std::unordered_map<EnumAssets, std::unordered_set<ResourceId>> lostResources;
|
||||
|
||||
// Обработка полученных ресурсов
|
||||
|
||||
|
||||
// Обработка полученных тактов
|
||||
while(!AsyncContext.TickSequence.get_read().empty()) {
|
||||
TickData tick;
|
||||
|
||||
{
|
||||
auto lock = AsyncContext.TickSequence.lock();
|
||||
tick = lock->front();
|
||||
lock->pop();
|
||||
}
|
||||
|
||||
// Потерянные привязки ресурсов
|
||||
for(int type = 0; type < (int) EnumAssets::MAX_ENUM; type++) {
|
||||
for(ResourceId id : tick.AssetsLost[type]) {
|
||||
Assets.ExistBinds[type].erase(id);
|
||||
changedResources[(EnumAssets) type].erase(id);
|
||||
}
|
||||
// Assets.ExistBinds[type].erase(tick.AssetsLost[type].begin(), tick.AssetsLost[type].end());
|
||||
lostResources[(EnumAssets) type].insert_range(tick.AssetsLost[type]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Получаем ресурсы, загруженные с дискового кеша
|
||||
|
||||
if(RS) {
|
||||
// Уведомляем рендер опотерянных и изменённых ресурсах
|
||||
if(!lostResources.empty()) {
|
||||
std::unordered_map<EnumAssets, std::vector<ResourceId>> lostResources2;
|
||||
|
||||
for(auto& [type, list] : lostResources)
|
||||
lostResources2[type].append_range(list);
|
||||
|
||||
lostResources.clear();
|
||||
RS->onAssetsLost(std::move(lostResources2));
|
||||
}
|
||||
|
||||
if(!changedResources.empty()) {
|
||||
std::unordered_map<EnumAssets, std::vector<AssetEntry>> changedResources2;
|
||||
|
||||
for(auto& [type, list] : changedResources) {
|
||||
auto& a = changedResources2[type];
|
||||
for(auto& [key, val] : list)
|
||||
a.push_back(val);
|
||||
}
|
||||
|
||||
changedResources.clear();
|
||||
RS->onAssetsChanges(std::move(changedResources2));
|
||||
}
|
||||
}
|
||||
|
||||
GTime = gTime;
|
||||
|
||||
Pos += glm::vec3(Speed) * dTime;
|
||||
@@ -556,105 +728,13 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
|
||||
Speed += glm::vec3(0, -1, 0)*float(Keys.SHIFT)*mltpl;
|
||||
Speed += glm::vec3(0, 1, 0)*float(Keys.SPACE)*mltpl;
|
||||
|
||||
{
|
||||
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>> onContentDefinesAdd;
|
||||
std::unordered_map<EnumDefContent, std::vector<ResourceId>> onContentDefinesLost;
|
||||
|
||||
// Пакеты
|
||||
ParsedPacket *pack;
|
||||
while(NetInputPackets.pop(pack)) {
|
||||
if(pack->Level1 == ToClient::L1::Definition) {
|
||||
ToClient::L2Definition l2 = ToClient::L2Definition(pack->Level2);
|
||||
|
||||
if(l2 == ToClient::L2Definition::Voxel) {
|
||||
PP_Definition_Voxel &p = *dynamic_cast<PP_Definition_Voxel*>(pack);
|
||||
Registry.DefVoxel[p.Id] = p.Def;
|
||||
onContentDefinesAdd[EnumDefContent::Voxel].push_back(p.Id);
|
||||
} else if(l2 == ToClient::L2Definition::FreeVoxel) {
|
||||
PP_Definition_FreeVoxel &p = *dynamic_cast<PP_Definition_FreeVoxel*>(pack);
|
||||
{
|
||||
auto iter = Registry.DefVoxel.find(p.Id);
|
||||
if(iter != Registry.DefVoxel.end())
|
||||
Registry.DefVoxel.erase(iter);
|
||||
}
|
||||
onContentDefinesLost[EnumDefContent::Voxel].push_back(p.Id);
|
||||
} else if(l2 == ToClient::L2Definition::Node) {
|
||||
PP_Definition_Node &p = *dynamic_cast<PP_Definition_Node*>(pack);
|
||||
Registry.DefNode[p.Id] = p.Def;
|
||||
onContentDefinesAdd[EnumDefContent::Node].push_back(p.Id);
|
||||
} else if(l2 == ToClient::L2Definition::FreeNode) {
|
||||
PP_Definition_FreeNode &p = *dynamic_cast<PP_Definition_FreeNode*>(pack);
|
||||
{
|
||||
auto iter = Registry.DefNode.find(p.Id);
|
||||
if(iter != Registry.DefNode.end())
|
||||
Registry.DefNode.erase(iter);
|
||||
}
|
||||
onContentDefinesLost[EnumDefContent::Node].push_back(p.Id);
|
||||
}
|
||||
|
||||
} else if(pack->Level1 == ToClient::L1::Content) {
|
||||
ToClient::L2Content l2 = ToClient::L2Content(pack->Level2);
|
||||
if(l2 == ToClient::L2Content::ChunkVoxels) {
|
||||
PP_Content_ChunkVoxels &p = *dynamic_cast<PP_Content_ChunkVoxels*>(pack);
|
||||
Pos::GlobalRegion rPos = p.Pos >> 2;
|
||||
Pos::bvec4u cPos = p.Pos & 0x3;
|
||||
|
||||
Data.Worlds[p.Id].Regions[rPos].Chunks[cPos.pack()].Voxels = std::move(p.Cubes);
|
||||
|
||||
auto &pair = changeOrAddList_removeList[p.Id];
|
||||
std::get<0>(pair).insert(p.Pos);
|
||||
} else if(l2 == ToClient::L2Content::ChunkNodes) {
|
||||
PP_Content_ChunkNodes &p = *dynamic_cast<PP_Content_ChunkNodes*>(pack);
|
||||
Pos::GlobalRegion rPos = p.Pos >> 2;
|
||||
Pos::bvec4u cPos = p.Pos & 0x3;
|
||||
|
||||
Node *nodes = (Node*) Data.Worlds[p.Id].Regions[rPos].Chunks[cPos.pack()].Nodes.data();
|
||||
std::copy(p.Nodes.begin(), p.Nodes.end(), nodes);
|
||||
|
||||
auto &pair = changeOrAddList_removeList[p.Id];
|
||||
std::get<0>(pair).insert(p.Pos);
|
||||
} else if(l2 == ToClient::L2Content::RemoveRegion) {
|
||||
PP_Content_RegionRemove &p = *dynamic_cast<PP_Content_RegionRemove*>(pack);
|
||||
|
||||
auto ®ions = Data.Worlds[p.Id].Regions;
|
||||
auto obj = regions.find(p.Pos);
|
||||
if(obj != regions.end()) {
|
||||
regions.erase(obj);
|
||||
|
||||
auto &pair = changeOrAddList_removeList[p.Id];
|
||||
std::get<1>(pair).insert(p.Pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete pack;
|
||||
}
|
||||
|
||||
if(RS && !changeOrAddList_removeList.empty()) {
|
||||
for(auto &pair : changeOrAddList_removeList) {
|
||||
// Если случится что чанк был изменён и удалён, то исключаем его обновления
|
||||
for(Pos::GlobalRegion removed : std::get<1>(pair.second)) {
|
||||
Pos::GlobalChunk pos = Pos::GlobalChunk(removed) << 2;
|
||||
for(int z = 0; z < 4; z++)
|
||||
for(int y = 0; y < 4; y++)
|
||||
for(int x = 0; x < 4; x++) {
|
||||
std::get<0>(pair.second).erase(pos+Pos::GlobalChunk(x, y, z));
|
||||
}
|
||||
}
|
||||
|
||||
RS->onChunksChange(pair.first, std::get<0>(pair.second), std::get<1>(pair.second));
|
||||
}
|
||||
|
||||
if(!onContentDefinesAdd.empty()) {
|
||||
RS->onContentDefinesAdd(std::move(onContentDefinesAdd));
|
||||
}
|
||||
|
||||
if(!onContentDefinesLost.empty()) {
|
||||
RS->onContentDefinesLost(std::move(onContentDefinesLost));
|
||||
}
|
||||
}
|
||||
}
|
||||
// {
|
||||
// // Пакеты
|
||||
// ParsedPacket *pack;
|
||||
// while(NetInputPackets.pop(pack)) {
|
||||
// delete pack;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Расчёт камеры
|
||||
{
|
||||
@@ -756,7 +836,7 @@ coro<> ServerSession::rP_System(Net::AsyncSocket &sock) {
|
||||
|
||||
co_return;
|
||||
case ToClient::L2System::SyncTick:
|
||||
AsyncContext.TickSequence.lock()->push(std::move(AsyncContext.ThisTickEntry));
|
||||
AsyncContext.TickSequence.lock()->push_back(std::move(AsyncContext.ThisTickEntry));
|
||||
co_return;
|
||||
default:
|
||||
protocolError();
|
||||
@@ -770,7 +850,8 @@ coro<> ServerSession::rP_Resource(Net::AsyncSocket &sock) {
|
||||
case ToClient::L2Resource::Bind:
|
||||
{
|
||||
uint32_t count = co_await sock.read<uint32_t>();
|
||||
AsyncContext.ThisTickEntry.AssetsBinds.reserve(AsyncContext.ThisTickEntry.AssetsBinds.size()+count);
|
||||
std::vector<AssetBindEntry> binds;
|
||||
binds.reserve(count);
|
||||
|
||||
for(size_t iter = 0; iter < count; iter++) {
|
||||
uint8_t type = co_await sock.read<uint8_t>();
|
||||
@@ -781,22 +862,27 @@ coro<> ServerSession::rP_Resource(Net::AsyncSocket &sock) {
|
||||
Hash_t hash;
|
||||
co_await sock.read((std::byte*) hash.data(), hash.size());
|
||||
|
||||
AsyncContext.ThisTickEntry.AssetsBinds.emplace_back(
|
||||
binds.emplace_back(
|
||||
(EnumAssets) type, (ResourceId) id, std::move(domain),
|
||||
std::move(key), hash
|
||||
);
|
||||
}
|
||||
|
||||
AsyncContext.AssetsBinds.lock()->push_back(AssetsBindsChange(binds, {}));
|
||||
}
|
||||
case ToClient::L2Resource::Lost:
|
||||
{
|
||||
uint32_t count = co_await sock.read<uint32_t>();
|
||||
AssetsBindsChange abc;
|
||||
|
||||
for(size_t iter = 0; iter < count; iter++) {
|
||||
uint8_t type = co_await sock.read<uint8_t>();
|
||||
uint32_t id = co_await sock.read<uint32_t>();
|
||||
|
||||
AsyncContext.ThisTickEntry.AssetsLost[(int) type].push_back(id);
|
||||
abc.Lost[(int) type].push_back(id);
|
||||
}
|
||||
|
||||
AsyncContext.AssetsBinds.lock()->emplace_back(std::move(abc));
|
||||
}
|
||||
case ToClient::L2Resource::InitResSend:
|
||||
{
|
||||
@@ -892,11 +978,6 @@ coro<> ServerSession::rP_Definition(Net::AsyncSocket &sock) {
|
||||
{
|
||||
DefNodeId id = co_await sock.read<DefNodeId>();
|
||||
|
||||
PP_Definition_FreeNode *packet = new PP_Definition_FreeNode(
|
||||
id
|
||||
);
|
||||
|
||||
while(!NetInputPackets.push(packet));
|
||||
|
||||
co_return;
|
||||
}
|
||||
@@ -921,12 +1002,16 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||
uint8_t second = co_await sock.read<uint8_t>();
|
||||
|
||||
switch((ToClient::L2Content) second) {
|
||||
case ToClient::L2Content::World:
|
||||
|
||||
case ToClient::L2Content::World: {
|
||||
WorldId_t wId = co_await sock.read<uint32_t>();
|
||||
AsyncContext.ThisTickEntry.Worlds_AddOrChange.emplace_back(wId, nullptr);
|
||||
co_return;
|
||||
case ToClient::L2Content::RemoveWorld:
|
||||
|
||||
}
|
||||
case ToClient::L2Content::RemoveWorld: {
|
||||
WorldId_t wId = co_await sock.read<uint32_t>();
|
||||
AsyncContext.ThisTickEntry.Worlds_Lost.push_back(wId);
|
||||
co_return;
|
||||
}
|
||||
case ToClient::L2Content::Portal:
|
||||
|
||||
co_return;
|
||||
@@ -950,13 +1035,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||
std::u8string compressed(compressedSize, '\0');
|
||||
co_await sock.read((std::byte*) compressed.data(), compressedSize);
|
||||
|
||||
PP_Content_ChunkVoxels *packet = new PP_Content_ChunkVoxels(
|
||||
wcId,
|
||||
pos,
|
||||
unCompressVoxels(compressed) // TODO: вынести в отдельный поток
|
||||
);
|
||||
|
||||
while(!NetInputPackets.push(packet));
|
||||
AsyncContext.ThisTickEntry.Chunks_AddOrChange_Node[wcId].insert({pos, std::move(compressed)});
|
||||
|
||||
co_return;
|
||||
}
|
||||
@@ -972,14 +1051,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||
std::u8string compressed(compressedSize, '\0');
|
||||
co_await sock.read((std::byte*) compressed.data(), compressedSize);
|
||||
|
||||
PP_Content_ChunkNodes *packet = new PP_Content_ChunkNodes(
|
||||
wcId,
|
||||
pos
|
||||
);
|
||||
|
||||
unCompressNodes(compressed, (Node*) packet->Nodes.data()); // TODO: вынести в отдельный поток
|
||||
|
||||
while(!NetInputPackets.push(packet));
|
||||
AsyncContext.ThisTickEntry.Chunks_AddOrChange_Node[wcId].insert({pos, std::move(compressed)});
|
||||
|
||||
co_return;
|
||||
}
|
||||
@@ -991,12 +1063,7 @@ coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||
Pos::GlobalRegion pos;
|
||||
pos.unpack(co_await sock.read<Pos::GlobalRegion::Pack>());
|
||||
|
||||
PP_Content_RegionRemove *packet = new PP_Content_RegionRemove(
|
||||
wcId,
|
||||
pos
|
||||
);
|
||||
|
||||
while(!NetInputPackets.push(packet));
|
||||
AsyncContext.ThisTickEntry.Regions_Lost[wcId].push_back(pos);
|
||||
|
||||
co_return;
|
||||
}
|
||||
|
||||
@@ -19,16 +19,6 @@
|
||||
|
||||
namespace LV::Client {
|
||||
|
||||
struct ParsedPacket {
|
||||
ToClient::L1 Level1;
|
||||
uint8_t Level2;
|
||||
|
||||
ParsedPacket(ToClient::L1 l1, uint8_t l2)
|
||||
: Level1(l1), Level2(l2)
|
||||
{}
|
||||
virtual ~ParsedPacket();
|
||||
};
|
||||
|
||||
class ServerSession : public IAsyncDestructible, public IServerSession, public ISurfaceEventListener {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<ServerSession>;
|
||||
@@ -102,9 +92,25 @@ private:
|
||||
};
|
||||
|
||||
struct TickData {
|
||||
std::vector<WorldId_t> LostWorld;
|
||||
// std::vector<std::pair<WorldId_t, DefWorld>>
|
||||
std::vector<std::pair<DefVoxelId, void*>> Profile_Voxel_AddOrChange;
|
||||
std::vector<DefVoxelId> Profile_Voxel_Lost;
|
||||
std::vector<std::pair<DefNodeId, void*>> Profile_Node_AddOrChange;
|
||||
std::vector<DefNodeId> Profile_Node_Lost;
|
||||
std::vector<std::pair<DefWorldId, void*>> Profile_World_AddOrChange;
|
||||
std::vector<DefWorldId> Profile_World_Lost;
|
||||
std::vector<std::pair<DefPortalId, void*>> Profile_Portal_AddOrChange;
|
||||
std::vector<DefPortalId> Profile_Portal_Lost;
|
||||
std::vector<std::pair<DefEntityId, void*>> Profile_Entity_AddOrChange;
|
||||
std::vector<DefEntityId> Profile_Entity_Lost;
|
||||
std::vector<std::pair<DefItemId, void*>> Profile_Item_AddOrChange;
|
||||
std::vector<DefItemId> Profile_Item_Lost;
|
||||
|
||||
std::vector<std::pair<WorldId_t, void*>> Worlds_AddOrChange;
|
||||
std::vector<WorldId_t> Worlds_Lost;
|
||||
|
||||
std::unordered_map<WorldId_t, std::unordered_map<Pos::GlobalChunk, std::u8string>> Chunks_AddOrChange_Voxel;
|
||||
std::unordered_map<WorldId_t, std::unordered_map<Pos::GlobalChunk, std::u8string>> Chunks_AddOrChange_Node;
|
||||
std::unordered_map<WorldId_t, std::vector<Pos::GlobalRegion>> Regions_Lost;
|
||||
};
|
||||
|
||||
struct AssetsBindsChange {
|
||||
@@ -121,13 +127,15 @@ private:
|
||||
// Накопление данных за такт сервера
|
||||
TickData ThisTickEntry;
|
||||
|
||||
// Сбда обращается ветка обновления IServerSession, накапливая данные до SyncTick
|
||||
// Сюда обращается ветка обновления IServerSession, накапливая данные до SyncTick
|
||||
// Ресурсы, ожидающие ответа от менеджера кеша
|
||||
std::unordered_map<std::string, std::vector<std::pair<std::string, Hash_t>>> ResourceWait[(int) EnumAssets::MAX_ENUM];
|
||||
// Полученные ресурсы в ожидании стадии синхронизации такта
|
||||
std::unordered_map<EnumAssets, std::vector<AssetEntry>> ReceivedResources;
|
||||
// Полученные изменения связок в ожидании стадии синхронизации такта
|
||||
AssetsBindsChange Binds;
|
||||
std::vector<AssetsBindsChange> Binds;
|
||||
// Подгруженные меж тактами ресурсы
|
||||
std::vector<std::pair<AssetsManager::ResourceKey, Resource>> LoadedResources;
|
||||
// Список ресурсов на которые уже был отправлен запрос на загрузку ресурса
|
||||
std::vector<Hash_t> AlreadyLoading;
|
||||
|
||||
@@ -138,15 +146,13 @@ private:
|
||||
// Изменения в наблюдаемых ресурсах
|
||||
TOS::SpinlockObject<std::vector<AssetsBindsChange>> AssetsBinds;
|
||||
// Пакеты обновлений игрового мира
|
||||
TOS::SpinlockObject<std::queue<TickData>> TickSequence;
|
||||
TOS::SpinlockObject<std::vector<TickData>> TickSequence;
|
||||
} AsyncContext;
|
||||
|
||||
|
||||
|
||||
bool IsConnected = true, IsGoingShutdown = false;
|
||||
|
||||
boost::lockfree::spsc_queue<ParsedPacket*> NetInputPackets;
|
||||
|
||||
// PYR - поворот камеры по осям xyz в радианах, PYR_Offset для сглаживание поворота
|
||||
glm::vec3 PYR = glm::vec3(0), PYR_Offset = glm::vec3(0);
|
||||
double PYR_At = 0;
|
||||
|
||||
Reference in New Issue
Block a user