*
This commit is contained in:
@@ -60,26 +60,35 @@ public:
|
|||||||
// states
|
// states
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AssetEntry {
|
|
||||||
EnumAssets Type;
|
|
||||||
ResourceId Id;
|
|
||||||
std::string Domain, Key;
|
|
||||||
Resource Res;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Интерфейс рендера текущего подключения к серверу */
|
/* Интерфейс рендера текущего подключения к серверу */
|
||||||
class IRenderSession {
|
class IRenderSession {
|
||||||
public:
|
public:
|
||||||
// Изменённые ресурсы (кроме звуков)
|
// Объект уведомления об изменениях
|
||||||
virtual void onAssetsChanges(std::unordered_map<EnumAssets, std::vector<AssetEntry>> resources) = 0;
|
struct TickSyncData {
|
||||||
// Потерянные ресурсы
|
// Новые или изменённые используемые теперь двоичные ресурсы
|
||||||
virtual void onAssetsLost(std::unordered_map<EnumAssets, std::vector<ResourceId>> resources) = 0;
|
std::unordered_map<EnumAssets, std::vector<ResourceId>> Assets_ChangeOrAdd;
|
||||||
|
// Более не используемые ресурсы
|
||||||
|
std::unordered_map<EnumAssets, std::vector<ResourceId>> Assets_Lost;
|
||||||
|
|
||||||
virtual void onContentDefinesAdd(std::unordered_map<EnumDefContent, std::vector<ResourceId>>) = 0;
|
// Новые или изменённые профили контента
|
||||||
virtual void onContentDefinesLost(std::unordered_map<EnumDefContent, std::vector<ResourceId>>) = 0;
|
std::unordered_map<EnumDefContent, std::vector<ResourceId>> Profiles_ChangeOrAdd;
|
||||||
|
// Более не используемые профили
|
||||||
|
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::unordered_set<Pos::GlobalRegion>> Chunks_Lost;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Серверная сессия собирается обработать данные такток сервера (изменение профилей, ресурсов, прочих игровых данных)
|
||||||
|
virtual void prepareTickSync() = 0;
|
||||||
|
// Началась стадия изменения данных IServerSession, все должны приостановить работу
|
||||||
|
virtual void pushStageTickSync() = 0;
|
||||||
|
// После изменения внутренних данных IServerSession, IRenderSession уведомляется об изменениях
|
||||||
|
virtual void tickSync(TickSyncData& data) = 0;
|
||||||
|
|
||||||
// Сообщаем об изменившихся чанках
|
|
||||||
virtual void onChunksChange(WorldId_t worldId, const std::unordered_set<Pos::GlobalChunk> &changeOrAddList, const std::unordered_set<Pos::GlobalRegion> &remove) = 0;
|
|
||||||
// Установить позицию для камеры
|
// Установить позицию для камеры
|
||||||
virtual void setCameraPos(WorldId_t worldId, Pos::Object pos, glm::quat quat) = 0;
|
virtual void setCameraPos(WorldId_t worldId, Pos::Object pos, glm::quat quat) = 0;
|
||||||
|
|
||||||
@@ -143,19 +152,27 @@ struct DefItemInfo {
|
|||||||
struct DefVoxel_t {};
|
struct DefVoxel_t {};
|
||||||
struct DefNode_t {};
|
struct DefNode_t {};
|
||||||
|
|
||||||
/* Интерфейс обработчика сессии с сервером */
|
struct AssetEntry {
|
||||||
class IServerSession {
|
EnumAssets Type;
|
||||||
// struct ArrayHasher {
|
ResourceId Id;
|
||||||
// std::size_t operator()(const Hash_t& a) const {
|
std::string Domain, Key;
|
||||||
// std::size_t h = 0;
|
Resource Res;
|
||||||
// for (auto e : a)
|
};
|
||||||
// h ^= std::hash<int>{}(e) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
|
||||||
|
|
||||||
// return h;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Интерфейс обработчика сессии с сервером.
|
||||||
|
|
||||||
|
Данный здесь меняются только меж вызовами
|
||||||
|
IRenderSession::pushStageTickSync
|
||||||
|
и
|
||||||
|
IRenderSession::tickSync
|
||||||
|
*/
|
||||||
|
class IServerSession {
|
||||||
public:
|
public:
|
||||||
|
// Используемые двоичные ресурсы
|
||||||
|
std::unordered_map<EnumAssets, std::unordered_map<ResourceId, AssetEntry>> Assets;
|
||||||
|
|
||||||
|
// Используемые профили контента
|
||||||
struct {
|
struct {
|
||||||
std::unordered_map<DefVoxelId, DefVoxel_t> DefVoxel;
|
std::unordered_map<DefVoxelId, DefVoxel_t> DefVoxel;
|
||||||
std::unordered_map<DefNodeId, DefNode_t> DefNode;
|
std::unordered_map<DefNodeId, DefNode_t> DefNode;
|
||||||
@@ -163,17 +180,19 @@ public:
|
|||||||
std::unordered_map<DefPortalId, DefPortalInfo> DefPortal;
|
std::unordered_map<DefPortalId, DefPortalInfo> DefPortal;
|
||||||
std::unordered_map<DefEntityId, DefEntityInfo> DefEntity;
|
std::unordered_map<DefEntityId, DefEntityInfo> DefEntity;
|
||||||
std::unordered_map<DefItemId, DefItemInfo> DefItem;
|
std::unordered_map<DefItemId, DefItemInfo> DefItem;
|
||||||
} Registry;
|
} Profiles;
|
||||||
|
|
||||||
|
// Видимый контент
|
||||||
struct {
|
struct {
|
||||||
std::unordered_map<WorldId_t, WorldInfo> Worlds;
|
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;
|
std::unordered_map<EntityId_t, EntityInfo> Entityes;
|
||||||
} Data;
|
} Content;
|
||||||
|
|
||||||
virtual ~IServerSession();
|
virtual ~IServerSession();
|
||||||
|
|
||||||
virtual void atFreeDrawTime(GlobalTime gTime, float dTime) = 0;
|
// Обновление сессии с сервером, может начатся стадия IRenderSession::tickSync
|
||||||
|
virtual void update(GlobalTime gTime, float dTime) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "TOSLib.hpp"
|
#include "TOSLib.hpp"
|
||||||
#include "glm/ext/quaternion_geometric.hpp"
|
#include "glm/ext/quaternion_geometric.hpp"
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <boost/asio/deadline_timer.hpp>
|
#include <boost/asio/deadline_timer.hpp>
|
||||||
#include <boost/asio/this_coro.hpp>
|
#include <boost/asio/this_coro.hpp>
|
||||||
#include <boost/date_time/posix_time/posix_time_duration.hpp>
|
#include <boost/date_time/posix_time/posix_time_duration.hpp>
|
||||||
@@ -320,37 +321,170 @@ void ServerSession::onJoystick() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
void ServerSession::update(GlobalTime gTime, float dTime) {
|
||||||
|
// Если были получены ресурсы, отправим их на запись в кеш
|
||||||
|
if(!AsyncContext.LoadedAssets.get_read().empty()) {
|
||||||
|
std::vector<AssetEntry> assets = std::move(*AsyncContext.LoadedAssets.lock());
|
||||||
|
std::vector<Resource> resources;
|
||||||
|
resources.reserve(assets.size());
|
||||||
|
|
||||||
|
for(AssetEntry& entry : assets) {
|
||||||
|
resources.push_back(entry.Res);
|
||||||
|
AsyncContext.ReceivedResources[entry.Type].push_back(entry);
|
||||||
|
|
||||||
|
// // Проверяем используется ли сейчас ресурс
|
||||||
|
// auto iter = Assets.ExistBinds[(int) entry.Type].find(entry.Id);
|
||||||
|
// if(iter == Assets.ExistBinds[(int) entry.Type].end()) {
|
||||||
|
// // Не используется
|
||||||
|
// Assets.NotInUse[(int) entry.Type][entry.Domain + ':' + entry.Key] = {entry, TIME_BEFORE_UNLOAD_RESOURCE+time(nullptr)};
|
||||||
|
// } else {
|
||||||
|
// // Используется
|
||||||
|
// Assets.InUse[(int) entry.Type][entry.Id] = entry;
|
||||||
|
// changedResources[entry.Type].insert({entry.Id, entry});
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
AM->pushResources(std::move(resources));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Разбираемся с полученными меж тактами привязками ресурсов
|
||||||
|
if(!AsyncContext.AssetsBinds.get_read().empty()) {
|
||||||
|
AssetsBindsChange abc;
|
||||||
|
|
||||||
|
// Нужно объеденить изменения в один AssetsBindsChange (abc)
|
||||||
|
{
|
||||||
|
std::vector<AssetsBindsChange> list = std::move(*AsyncContext.AssetsBinds.lock());
|
||||||
|
|
||||||
|
for(AssetsBindsChange entry : list) {
|
||||||
|
for(int type = 0; type < (int) EnumAssets::MAX_ENUM; type++)
|
||||||
|
std::sort(entry.Lost[type].begin(), entry.Lost[type].end());
|
||||||
|
|
||||||
|
// Если до этого была объявлена привязка, а теперь она потеряна, то просто сокращаем значения.
|
||||||
|
// Иначе дописываем в lost
|
||||||
|
for(ssize_t iter = abc.Binds.size()-1; iter >= 0; iter--) {
|
||||||
|
const AssetBindEntry& abe = abc.Binds[iter];
|
||||||
|
auto& lost = entry.Lost[(int) abe.Type];
|
||||||
|
auto iterator = std::lower_bound(lost.begin(), lost.end(), abe.Id);
|
||||||
|
if(iterator != lost.end()) {
|
||||||
|
// Привязка будет удалена
|
||||||
|
lost.erase(iterator);
|
||||||
|
abc.Binds.erase(abc.Binds.begin()+iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int type = 0; type < (int) EnumAssets::MAX_ENUM; type++) {
|
||||||
|
abc.Lost[type].append_range(entry.Lost[type]);
|
||||||
|
entry.Lost[type].clear();
|
||||||
|
std::sort(abc.Lost[type].begin(), abc.Lost[type].end());
|
||||||
|
}
|
||||||
|
|
||||||
|
for(AssetBindEntry& abe : entry.Binds) {
|
||||||
|
auto iterator = std::lower_bound(entry.Lost[(int) abe.Type].begin(), entry.Lost[(int) abe.Type].end(), abe.Id);
|
||||||
|
if(iterator != entry.Lost[(int) abe.Type].end()) {
|
||||||
|
// Получили новую привязку, которая была удалена в предыдущем такте
|
||||||
|
entry.Lost[(int) abe.Type].erase(iterator);
|
||||||
|
} else {
|
||||||
|
// Данная привязка не удалялась, может она была изменена?
|
||||||
|
bool hasChanged = false;
|
||||||
|
for(AssetBindEntry& abe2 : abc.Binds) {
|
||||||
|
if(abe2.Type == abe.Type && abe2.Id == abe.Id) {
|
||||||
|
// Привязка была изменена
|
||||||
|
abe2 = std::move(abe);
|
||||||
|
hasChanged = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!hasChanged)
|
||||||
|
// Изменения не было, это просто новая привязка
|
||||||
|
abc.Binds.emplace_back(std::move(abe));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.Binds.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Запрос к дисковому кешу новых ресурсов
|
||||||
|
std::vector<AssetsManager::ResourceKey> needToLoad;
|
||||||
|
for(const AssetBindEntry& bind : abc.Binds) {
|
||||||
|
bool needQuery = false;
|
||||||
|
// Проверить in memory кеш по домену+ключу
|
||||||
|
{
|
||||||
|
std::string dk = bind.Domain + ':' + bind.Key;
|
||||||
|
auto &niubdk = Assets.NotInUse[(int) bind.Type];
|
||||||
|
auto iter = niubdk.find(dk);
|
||||||
|
if(iter != niubdk.end()) {
|
||||||
|
// Есть ресурс
|
||||||
|
needQuery = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверить если такой запрос уже был отправлен в AssetsManager и ожидает ответа
|
||||||
|
if(!needQuery) {
|
||||||
|
auto& list = AsyncContext.ResourceWait[(int) bind.Type];
|
||||||
|
auto iterDomain = list.find(bind.Domain);
|
||||||
|
if(iterDomain != list.end()) {
|
||||||
|
for(const auto& [key, hash] : iterDomain->second) {
|
||||||
|
if(key == bind.Key && hash == bind.Hash) {
|
||||||
|
needQuery = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assets.ExistBinds[(int) bind.Type].insert(bind.Id);
|
||||||
|
|
||||||
|
// Под рукой нет ресурса, отправим на проверку в AssetsManager
|
||||||
|
if(needQuery) {
|
||||||
|
AsyncContext.ResourceWait[(int) bind.Type][bind.Domain].emplace_back(bind.Key, bind.Hash);
|
||||||
|
needToLoad.emplace_back(bind.Hash, bind.Type, bind.Domain, bind.Key, bind.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Отправляем запрос на получение ресурсов
|
||||||
|
if(!needToLoad.empty())
|
||||||
|
AM->pushReads(std::move(needToLoad));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!AsyncContext.TickSequence.get_read().empty()) {
|
||||||
|
// Есть такты с сервера
|
||||||
|
// Оповещаем о подготовке к обработке тактов
|
||||||
|
if(RS)
|
||||||
|
RS->prepareTickSync();
|
||||||
|
|
||||||
|
IRenderSession::TickSyncData result;
|
||||||
|
// Перевариваем данные по тактам
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(RS)
|
||||||
|
RS->pushStageTickSync();
|
||||||
|
|
||||||
|
// Применяем изменения по ресурсам, профилям и контенту
|
||||||
|
|
||||||
|
if(RS)
|
||||||
|
RS->tickSync(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Здесь нужно обработать управляющие пакеты
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Оповещение модуля рендера об изменениях ресурсов
|
// Оповещение модуля рендера об изменениях ресурсов
|
||||||
std::unordered_map<EnumAssets, std::unordered_map<ResourceId, AssetEntry>> changedResources;
|
std::unordered_map<EnumAssets, std::unordered_map<ResourceId, AssetEntry>> changedResources;
|
||||||
std::unordered_map<EnumAssets, std::unordered_set<ResourceId>> lostResources;
|
std::unordered_map<EnumAssets, std::unordered_set<ResourceId>> lostResources;
|
||||||
|
|
||||||
// Обработка полученных ресурсов
|
// Обработка полученных ресурсов
|
||||||
if(!AsyncContext.LoadedAssets.get_read().empty()) {
|
|
||||||
std::vector<AssetEntry> assets = std::move(*AsyncContext.LoadedAssets.lock());
|
|
||||||
// Для сохранения ресурсов в кеше
|
|
||||||
std::vector<Resource> resources;
|
|
||||||
resources.reserve(assets.size());
|
|
||||||
|
|
||||||
|
|
||||||
for(AssetEntry& entry : assets) {
|
|
||||||
resources.push_back(entry.Res);
|
|
||||||
|
|
||||||
// Проверяем используется ли сейчас ресурс
|
|
||||||
auto iter = Assets.ExistBinds[(int) entry.Type].find(entry.Id);
|
|
||||||
if(iter == Assets.ExistBinds[(int) entry.Type].end()) {
|
|
||||||
// Не используется
|
|
||||||
Assets.NotInUse[(int) entry.Type][entry.Domain + ':' + entry.Key] = {entry, TIME_BEFORE_UNLOAD_RESOURCE+time(nullptr)};
|
|
||||||
} else {
|
|
||||||
// Используется
|
|
||||||
Assets.InUse[(int) entry.Type][entry.Id] = entry;
|
|
||||||
changedResources[entry.Type].insert({entry.Id, entry});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сохраняем в кеш
|
|
||||||
AM->pushResources(std::move(resources));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обработка полученных тактов
|
// Обработка полученных тактов
|
||||||
while(!AsyncContext.TickSequence.get_read().empty()) {
|
while(!AsyncContext.TickSequence.get_read().empty()) {
|
||||||
@@ -372,69 +506,9 @@ void ServerSession::atFreeDrawTime(GlobalTime gTime, float dTime) {
|
|||||||
lostResources[(EnumAssets) type].insert_range(tick.AssetsLost[type]);
|
lostResources[(EnumAssets) type].insert_range(tick.AssetsLost[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запрос к дисковому кешу
|
|
||||||
std::vector<AssetsManager::ResourceKey> needToLoad;
|
|
||||||
// Новые привязки ресурсов
|
|
||||||
for(const AssetBindEntry& bind : tick.AssetsBinds) {
|
|
||||||
Assets.ExistBinds[(int) bind.Type].insert(bind.Id);
|
|
||||||
|
|
||||||
// Проверить in memory кеш по домену+ключу
|
|
||||||
{
|
|
||||||
std::string dk = bind.Domain + ':' + bind.Key;
|
|
||||||
auto &niubdk = Assets.NotInUse[(int) bind.Type];
|
|
||||||
auto iter = niubdk.find(dk);
|
|
||||||
if(iter != niubdk.end()) {
|
|
||||||
// Есть ресурс
|
|
||||||
Assets.InUse[(int) bind.Type][bind.Id] = std::get<0>(iter->second);
|
|
||||||
changedResources[bind.Type].insert({bind.Id, std::get<0>(iter->second)});
|
|
||||||
lostResources[bind.Type].erase(bind.Id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Под рукой нет ресурса, отправим на проверку в AssetsManager
|
|
||||||
needToLoad.emplace_back(bind.Hash, bind.Type, bind.Domain, bind.Key, bind.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!needToLoad.empty())
|
|
||||||
AM->pushReads(std::move(needToLoad));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Получаем ресурсы, загруженные с дискового кеша
|
// Получаем ресурсы, загруженные с дискового кеша
|
||||||
{
|
|
||||||
std::vector<Hash_t> request;
|
|
||||||
std::vector<std::pair<AssetsManager::ResourceKey, std::optional<Resource>>> resources = AM->pullReads();
|
|
||||||
for(auto& [key, res] : resources) {
|
|
||||||
if(!res) {
|
|
||||||
// Нужно запросить ресурс с сервера
|
|
||||||
request.push_back(key.Hash);
|
|
||||||
} else {
|
|
||||||
auto& a = Assets.ExistBinds[(int) key.Type];
|
|
||||||
AssetEntry entry = {key.Type, key.Id, key.Domain, key.Key, *res};
|
|
||||||
|
|
||||||
if(a.contains(key.Id)) {
|
|
||||||
// Ресурс ещё нужен
|
|
||||||
Assets.InUse[(int) key.Type][key.Id] = entry;
|
|
||||||
changedResources[key.Type].insert({key.Id, entry});
|
|
||||||
} else {
|
|
||||||
// Ресурс уже не нужен
|
|
||||||
Assets.NotInUse[(int) key.Type][key.Domain + ':' + key.Key] = {entry, TIME_BEFORE_UNLOAD_RESOURCE+time(nullptr)};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!request.empty()) {
|
|
||||||
assert(request.size() < (1 << 16));
|
|
||||||
Net::Packet p;
|
|
||||||
p << (uint8_t) ToServer::L1::System << (uint8_t) ToServer::L2System::ResourceRequest
|
|
||||||
<< uint16_t(request.size());
|
|
||||||
|
|
||||||
for(Hash_t& hash : request)
|
|
||||||
p.write((const std::byte*) hash.data(), 32);
|
|
||||||
|
|
||||||
Socket->pushPacket(std::move(p));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(RS) {
|
if(RS) {
|
||||||
// Уведомляем рендер опотерянных и изменённых ресурсах
|
// Уведомляем рендер опотерянных и изменённых ресурсах
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
|
|
||||||
// IServerSession
|
// IServerSession
|
||||||
|
|
||||||
virtual void atFreeDrawTime(GlobalTime gTime, float dTime) override;
|
virtual void update(GlobalTime gTime, float dTime) override;
|
||||||
void setRenderSession(IRenderSession* session);
|
void setRenderSession(IRenderSession* session);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -105,24 +105,38 @@ private:
|
|||||||
std::vector<WorldId_t> LostWorld;
|
std::vector<WorldId_t> LostWorld;
|
||||||
// std::vector<std::pair<WorldId_t, DefWorld>>
|
// std::vector<std::pair<WorldId_t, DefWorld>>
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AssetsBindsChange {
|
||||||
// Новые привязки ресурсов
|
// Новые привязки ресурсов
|
||||||
std::vector<AssetBindEntry> AssetsBinds;
|
std::vector<AssetBindEntry> Binds;
|
||||||
// Потерянные из видимости ресурсы
|
// Потерянные из видимости ресурсы
|
||||||
std::vector<ResourceId> AssetsLost[(int) EnumAssets::MAX_ENUM];
|
std::vector<ResourceId> Lost[(int) EnumAssets::MAX_ENUM];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
// Сюда обращается ветка, обрабатывающая сокет; run()
|
// Сюда обращается ветка, обрабатывающая сокет; run()
|
||||||
// Получение ресурсов с сервера
|
// Получение ресурсов с сервера
|
||||||
std::unordered_map<Hash_t, AssetLoading> AssetsLoading;
|
std::unordered_map<Hash_t, AssetLoading> AssetsLoading;
|
||||||
// Получение привязок
|
|
||||||
|
|
||||||
// Накопление данных за такт сервера
|
// Накопление данных за такт сервера
|
||||||
TickData ThisTickEntry;
|
TickData ThisTickEntry;
|
||||||
|
|
||||||
|
// Сбда обращается ветка обновления 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<Hash_t> AlreadyLoading;
|
||||||
|
|
||||||
|
|
||||||
// Обменный пункт
|
// Обменный пункт
|
||||||
// Полученные ресурсы с сервера
|
// Полученные ресурсы с сервера
|
||||||
TOS::SpinlockObject<std::vector<AssetEntry>> LoadedAssets;
|
TOS::SpinlockObject<std::vector<AssetEntry>> LoadedAssets;
|
||||||
|
// Изменения в наблюдаемых ресурсах
|
||||||
|
TOS::SpinlockObject<std::vector<AssetsBindsChange>> AssetsBinds;
|
||||||
// Пакеты обновлений игрового мира
|
// Пакеты обновлений игрового мира
|
||||||
TOS::SpinlockObject<std::queue<TickData>> TickSequence;
|
TOS::SpinlockObject<std::queue<TickData>> TickSequence;
|
||||||
} AsyncContext;
|
} AsyncContext;
|
||||||
|
|||||||
@@ -611,7 +611,7 @@ void Vulkan::run()
|
|||||||
if(Game.RSession)
|
if(Game.RSession)
|
||||||
Game.RSession->pushStage(EnumRenderStage::WorldUpdate);
|
Game.RSession->pushStage(EnumRenderStage::WorldUpdate);
|
||||||
|
|
||||||
Game.Session->atFreeDrawTime(gTime, dTime);
|
Game.Session->update(gTime, dTime);
|
||||||
}
|
}
|
||||||
Screen.State = DrawState::End;
|
Screen.State = DrawState::End;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user