На этом коммите всё компилируется, дальше разработка профилей нод

This commit is contained in:
2025-07-24 17:44:05 +06:00
parent cfec93957d
commit bd31b57d7d
9 changed files with 337 additions and 243 deletions

Binary file not shown.

View File

@@ -512,24 +512,24 @@ coro<> ServerSession::rP_Resource(Net::AsyncSocket &sock) {
uint8_t second = co_await sock.read<uint8_t>();
switch((ToClient::L2Resource) second) {
case ToClient::L2Resource::Texture:
co_return;
case ToClient::L2Resource::FreeTexture:
co_return;
case ToClient::L2Resource::Sound:
co_return;
case ToClient::L2Resource::FreeSound:
co_return;
case ToClient::L2Resource::Model:
co_return;
case ToClient::L2Resource::FreeModel:
co_return;
case ToClient::L2Resource::Bind:
{
uint32_t count = co_await sock.read<uint32_t>();
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>();
Hash_t hash;
co_await sock.read((std::byte*) hash.data(), hash.size());
}
}
case ToClient::L2Resource::Lost:
{
uint32_t count = co_await sock.read<uint32_t>();
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>();
}
}
case ToClient::L2Resource::InitResSend:
{
uint32_t size = co_await sock.read<uint32_t>();
@@ -537,6 +537,8 @@ coro<> ServerSession::rP_Resource(Net::AsyncSocket &sock) {
co_await sock.read((std::byte*) hash.data(), hash.size());
uint32_t chunkSize = co_await sock.read<uint32_t>();
assert(chunkSize < std::pow(2, 26));
std::u8string data(size, '\0');
co_await sock.read((std::byte*) data.data(), data.size());

View File

@@ -389,7 +389,7 @@ using ResourceId_t = uint32_t;
*/
enum class EnumBinResource {
Texture, Animation, Model, Sound, Font
Texture, Animation, Model, Sound, Font, MAX_ENUM
};
using BinaryResource = std::shared_ptr<const std::u8string>;
@@ -401,14 +401,8 @@ using BinModelId_t = ResourceId_t;
using BinSoundId_t = ResourceId_t;
using BinFontId_t = ResourceId_t;
// Шаблоны использования бинарных ресурсов
// using DefTextureId_t = ResourceId_t;
// using DefModelId_t = ResourceId_t;
// using DefSoundId_t = ResourceId_t;
// using DefFontId_t = ResourceId_t;
enum class EnumDefContent {
Voxel, Node, Generator, World, Portal, Entity, FuncEntitry
Voxel, Node, Generator, World, Portal, Entity, Item, MAX_ENUM
};
// Игровые определения
@@ -496,6 +490,10 @@ struct TexturePipeline {
std::u8string Pipeline;
};
struct DefVoxel_t {
};
struct DefNode_t {
enum struct EnumDrawType : uint8_t {
NoDraw, // Не рисуется
@@ -505,6 +503,22 @@ struct DefNode_t {
TexturePipeline Texs[6];
};
struct DefWorld_t {
};
struct DefPortal_t {
};
struct DefEntity_t {
};
struct DefItem_t {
};
using Hash_t = std::array<uint8_t, 32>;
}

View File

@@ -20,99 +20,67 @@ BinaryResourceManager::~BinaryResourceManager() {
}
void BinaryResourceManager::recheckResources() {
void BinaryResourceManager::recheckResources(std::vector<fs::path> assets /* Пути до активных папок assets */) {
}
ResourceId_t BinaryResourceManager::mapUriToId(const std::string &uri) {
UriParse parse = parseUri(uri);
if(parse.Protocol != "assets")
MAKE_ERROR("Неизвестный протокол ресурса '" << parse.Protocol << "'. Полный путь: " << parse.Orig);
void BinaryResourceManager::needResourceResponse(const ResourceRequest& resources) {
auto lock = Local.lock();
for(int iter = 0; iter < (int) EnumBinResource::MAX_ENUM; iter++) {
lock->BinToHash[iter].insert(lock->BinToHash[iter].end(), resources.BinToHash[iter].begin(), resources.BinToHash[iter].end());
}
return getResource_Assets(parse.Path);
}
void BinaryResourceManager::needResourceResponse(const std::vector<ResourceId_t> &resources) {
UpdatedResources.lock_write()->insert(resources.end(), resources.begin(), resources.end());
lock->Hashes.insert(lock->Hashes.end(), resources.Hashes.begin(), resources.Hashes.end());
}
void BinaryResourceManager::update(float dtime) {
if(UpdatedResources.no_lock_readable().empty())
return;
// if(UpdatedResources.no_lock_readable().empty())
// return;
auto lock = UpdatedResources.lock_write();
for(ResourceId_t resId : *lock) {
auto iterPI = PreparedInformation.find(resId);
if(iterPI != PreparedInformation.end())
continue;
// auto lock = UpdatedResources.lock_write();
// for(ResourceId_t resId : *lock) {
// auto iterPI = PreparedInformation.find(resId);
// if(iterPI != PreparedInformation.end())
// continue;
auto iterRI = ResourcesInfo.find(resId);
if(iterRI != ResourcesInfo.end()) {
PreparedInformation[resId] = iterRI->second->Loaded;
}
}
// auto iterRI = ResourcesInfo.find(resId);
// if(iterRI != ResourcesInfo.end()) {
// PreparedInformation[resId] = iterRI->second->Loaded;
// }
// }
}
BinaryResourceManager::UriParse BinaryResourceManager::parseUri(const std::string &uri) {
size_t pos = uri.find("://");
if(pos == std::string::npos)
return {uri, "assets", uri};
return {"assets", uri};
else
return {uri, uri.substr(0, pos), uri.substr(pos+3)};
return {uri.substr(0, pos), uri.substr(pos+3)};
}
ResourceId_t BinaryResourceManager::getResource_Assets(std::string path) {
size_t pos = path.find("/");
// coro<> BinaryResourceManager::checkResource_Assets(ResourceId_t id, fs::path path, std::shared_ptr<Resource> res) {
// try {
// asio::stream_file fd(IOC, path, asio::stream_file::flags::read_only);
if(pos == std::string::npos)
MAKE_ERROR("Не действительный путь assets: '" << path << "'");
std::string domain = path.substr(0, pos);
std::string inDomainPath = path.substr(pos+1);
// if(fd.size() > 1024*1024*16)
// MAKE_ERROR("Превышен лимит размера файла: " << fd.size() << " > " << 1024*1024*16);
ResourceId_t &resId = KnownResource[path];
if(!resId)
resId = NextId++;
// std::shared_ptr<ResourceFile> file = std::make_shared<ResourceFile>();
// file->Data.resize(fd.size());
// co_await asio::async_read(fd, asio::mutable_buffer(file->Data.data(), file->Data.size()));
// file->calcHash();
// res->LastError.clear();
// } catch(const std::exception &exc) {
// res->LastError = exc.what();
// res->IsLoading = false;
std::shared_ptr<Resource> &res = ResourcesInfo[resId];
if(!res) {
res = std::make_shared<Resource>();
// if(const boost::system::system_error *errc = dynamic_cast<const boost::system::system_error*>(&exc); errc && errc->code() == asio::error::operation_aborted)
// co_return;
// }
auto iter = Domains.find("domain");
if(iter == Domains.end()) {
UpdatedResources.lock_write()->push_back(resId);
} else {
res->IsLoading = true;
co_spawn(checkResource_Assets(resId, iter->second / inDomainPath, res));
}
}
return resId;
}
coro<> BinaryResourceManager::checkResource_Assets(ResourceId_t id, fs::path path, std::shared_ptr<Resource> res) {
try {
asio::stream_file fd(IOC, path, asio::stream_file::flags::read_only);
if(fd.size() > 1024*1024*16)
MAKE_ERROR("Превышен лимит размера файла: " << fd.size() << " > " << 1024*1024*16);
std::shared_ptr<ResourceFile> file = std::make_shared<ResourceFile>();
file->Data.resize(fd.size());
co_await asio::async_read(fd, asio::mutable_buffer(file->Data.data(), file->Data.size()));
file->calcHash();
res->LastError.clear();
} catch(const std::exception &exc) {
res->LastError = exc.what();
res->IsLoading = false;
if(const boost::system::system_error *errc = dynamic_cast<const boost::system::system_error*>(&exc); errc && errc->code() == asio::error::operation_aborted)
co_return;
}
res->IsLoading = false;
UpdatedResources.lock_write()->push_back(id);
}
// res->IsLoading = false;
// UpdatedResources.lock_write()->push_back(id);
// }
}

View File

@@ -26,7 +26,6 @@ namespace fs = std::filesystem;
тогда обычным оповещениям клиентам дойдёт новая версия
Подержать какое-то время ресурс в памяти
*/
class BinaryResourceManager : public AsyncObject {
@@ -34,34 +33,52 @@ public:
private:
struct Resource {
// Файл загруженный на диск
// Файл загруженный с диска
std::shared_ptr<ResourceFile> Loaded;
// Источник
std::string Uri;
bool IsLoading = false;
size_t LastUsedTime = 0;
std::string LastError;
};
struct UriParse {
std::string Orig, Protocol, Path;
std::string Protocol, Path;
std::string getFull() const {
return Protocol + "://" + Path;
}
};
// Последовательная регистрация ресурсов
BinTextureId_t NextIdTexture = 0, NextIdAnimation = 0, NextIdModel = 0,
NextIdSound = 0, NextIdFont = 0;
// Ресурсы - кешированные в оперативную память или в процессе загрузки
std::map<BinTextureId_t, std::shared_ptr<Resource>>
// Известные ресурсы
std::map<std::string, ResourceId_t> KnownResource;
std::map<ResourceId_t, std::shared_ptr<Resource>> ResourcesInfo;
// Сюда
TOS::SpinlockObject<std::vector<ResourceId_t>> UpdatedResources;
// Подготовленая таблица оповещения об изменениях ресурсов
// Должна забираться сервером и отчищаться
std::unordered_map<ResourceId_t, std::shared_ptr<ResourceFile>> PreparedInformation;
// Поток сервера
// Последовательная регистрация ресурсов
ResourceId_t NextId[(int) EnumBinResource::MAX_ENUM] = {0};
// Известные ресурсы, им присвоен идентификатор
std::unordered_map<std::string, ResourceId_t> KnownResource[(int) EnumBinResource::MAX_ENUM];
std::unordered_map<ResourceId_t, std::shared_ptr<Resource>> ResourcesInfo[(int) EnumBinResource::MAX_ENUM];
// Местные потоки
struct LocalObj_t {
// Ресурсы - кешированные в оперативную память или в процессе загрузки
std::map<BinTextureId_t, std::shared_ptr<Resource>> InMemory[(int) EnumBinResource::MAX_ENUM];
// Кому-то нужно сопоставить идентификаторы с хэшами
std::vector<ResourceId_t> BinToHash[(int) EnumBinResource::MAX_ENUM];
// Запрос ресурсов, по которым потоки загружают ресурсы с диска
std::vector<Hash_t> Hashes;
};
TOS::SpinlockObject<LocalObj_t> Local;
public:
// Подготовленные оповещения о ресурсах
struct OutObj_t {
std::unordered_map<ResourceId_t, ResourceFile::Hash_t> BinToHash[(int) EnumBinResource::MAX_ENUM];
std::vector<std::shared_ptr<ResourceFile>> HashToResource;
};
private:
TOS::SpinlockObject<OutObj_t> Out;
public:
// Если ресурс будет обновлён или загружен будет вызвано onResourceUpdate
@@ -71,17 +88,48 @@ public:
// Перепроверка изменений ресурсов
void recheckResources(std::vector<fs::path> assets /* Пути до активных папок assets */);
// Выдаёт или назначает идентификатор для ресурса
BinTextureId_t getTexture (const std::string& uri);
BinAnimationId_t getAnimation(const std::string& uri);
BinModelId_t getModel (const std::string& uri);
BinSoundId_t getSound (const std::string& uri);
BinFontId_t getFont (const std::string& uri);
ResourceId_t getResource(const std::string& uri, EnumBinResource bin) {
std::string fullUri = parseUri(uri).getFull();
int index = (int) bin;
auto &container = KnownResource[index];
auto iter = container.find(fullUri);
if(iter == container.end()) {
assert(NextId[index] != ResourceId_t(-1));
ResourceId_t nextId = NextId[index]++;
container.insert(iter, {fullUri, nextId});
return nextId;
}
return iter->second;
}
BinTextureId_t getTexture(const std::string& uri) {
return getResource(uri, EnumBinResource::Texture);
}
BinAnimationId_t getAnimation(const std::string& uri) {
return getResource(uri, EnumBinResource::Animation);
}
BinModelId_t getModel(const std::string& uri) {
return getResource(uri, EnumBinResource::Model);
}
BinSoundId_t getSound(const std::string& uri) {
return getResource(uri, EnumBinResource::Sound);
}
BinFontId_t getFont(const std::string& uri) {
return getResource(uri, EnumBinResource::Font);
}
// Запросить ресурсы через pushPreparedPackets
void needResourceResponse(const ResourceRequest& resources);
// Запросить ресурсы через onResourceUpdate
void needResourceResponse(const ResourceRequest &&resources);
// Получение обновлений или оповещений ресурсов
std::unordered_map<ResourceId_t, std::shared_ptr<ResourceFile>> takePreparedInformation() {
return std::move(PreparedInformation);
OutObj_t takePreparedInformation() {
return std::move(*Out.lock());
}
// Серверный такт
@@ -89,8 +137,6 @@ public:
protected:
UriParse parseUri(const std::string &uri);
ResourceId_t getResource_Assets(std::string path);
coro<> checkResource_Assets(ResourceId_t id, fs::path path, std::shared_ptr<Resource> res);
};

View File

@@ -33,7 +33,7 @@ namespace LV::Server {
GameServer::GameServer(asio::io_context &ioc, fs::path worldPath)
: AsyncObject(ioc),
Content(ioc, nullptr, nullptr, nullptr, nullptr, nullptr)
Content(ioc)
{
BackingChunkPressure.Threads.resize(4);
BackingNoiseGenerator.Threads.resize(4);
@@ -745,6 +745,8 @@ TexturePipeline GameServer::buildTexturePipeline(const std::string& pl) {
cmd_name += pl[pos];
}
}
MAKE_ERROR("Ожидался конец команды объявленной на " << startPos << ", наткнулись на конец потока");
};
parse_obj = [&](size_t pos) -> std::pair<size_t, std::u8string> {
@@ -1652,6 +1654,7 @@ void GameServer::stepSyncContent() {
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->onUpdate();
// Это для пробы строительства и ломания нод
while(!cec->Build.empty()) {
Pos::GlobalNode node = cec->Build.front();
cec->Build.pop();
@@ -1679,86 +1682,129 @@ void GameServer::stepSyncContent() {
}
}
// Оповещения о ресурсах и профилях
Content.Texture.update(CurrentTickDuration);
if(Content.Texture.hasPreparedInformation()) {
auto table = Content.Texture.takePreparedInformation();
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateBinTexture(table);
}
}
Content.Animation.update(CurrentTickDuration);
if(Content.Animation.hasPreparedInformation()) {
auto table = Content.Animation.takePreparedInformation();
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateBinAnimation(table);
}
}
Content.Model.update(CurrentTickDuration);
if(Content.Model.hasPreparedInformation()) {
auto table = Content.Model.takePreparedInformation();
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateBinModel(table);
}
}
Content.Sound.update(CurrentTickDuration);
if(Content.Sound.hasPreparedInformation()) {
auto table = Content.Sound.takePreparedInformation();
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateBinSound(table);
}
}
Content.Font.update(CurrentTickDuration);
if(Content.Font.hasPreparedInformation()) {
auto table = Content.Font.takePreparedInformation();
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateBinFont(table);
}
}
// Сбор запросов на ресурсы и профили + отправка пакетов игрокам
ResourceRequest full;
ResourceRequest full = std::move(Content.OnContentChanges);
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
full.insert(cec->Remote->pushPreparedPackets());
}
BackingChunkPressure.startCollectChanges();
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(!full.BinTexture.empty())
Content.Texture.needResourceResponse(full.BinTexture);
if(hasData) {
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateIdToHash(out.BinToHash);
}
}
if(!full.BinAnimation.empty())
Content.Animation.needResourceResponse(full.BinAnimation);
if(!out.HashToResource.empty())
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateBinary(out.HashToResource);
}
}
if(!full.BinModel.empty())
Content.Model.needResourceResponse(full.BinModel);
// Оповещаем об игровых профилях
if(!full.Voxel.empty()) {
std::unordered_map<DefVoxelId_t, DefVoxel_t*> defines;
if(!full.BinSound.empty())
Content.Sound.needResourceResponse(full.BinSound);
if(!full.BinFont.empty())
Content.Font.needResourceResponse(full.BinFont);
if(!full.Node.empty()) {
std::unordered_map<DefNodeId_t, DefNode_t*> nodeDefines;
for(DefNodeId_t id : full.Node) {
auto iter = Content.NodeDefines.find(id);
if(iter != Content.NodeDefines.end()) {
nodeDefines[id] = &iter->second;
for(DefVoxelId_t id : full.Node) {
auto iter = Content.ContentIdToDef_Voxel.find(id);
if(iter != Content.ContentIdToDef_Voxel.end()) {
defines[id] = &iter->second;
}
}
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateDefNode(nodeDefines);
cec->Remote->informateDefVoxel(defines);
}
}
if(!full.Node.empty()) {
std::unordered_map<DefNodeId_t, DefNode_t*> defines;
for(DefNodeId_t id : full.Node) {
auto iter = Content.ContentIdToDef_Node.find(id);
if(iter != Content.ContentIdToDef_Node.end()) {
defines[id] = &iter->second;
}
}
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateDefNode(defines);
}
}
if(!full.World.empty()) {
std::unordered_map<DefWorldId_t, DefWorld_t*> defines;
for(DefWorldId_t id : full.Node) {
auto iter = Content.ContentIdToDef_World.find(id);
if(iter != Content.ContentIdToDef_World.end()) {
defines[id] = &iter->second;
}
}
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateDefWorld(defines);
}
}
if(!full.Portal.empty()) {
std::unordered_map<DefPortalId_t, DefPortal_t*> defines;
for(DefPortalId_t id : full.Node) {
auto iter = Content.ContentIdToDef_Portal.find(id);
if(iter != Content.ContentIdToDef_Portal.end()) {
defines[id] = &iter->second;
}
}
for(std::shared_ptr<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateDefPortal(defines);
}
}
if(!full.Entity.empty()) {
std::unordered_map<DefEntityId_t, DefEntity_t*> defines;
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<ContentEventController>& 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<ContentEventController>& cec : Game.CECs) {
cec->Remote->informateDefItem(defines);
}
}
BackingChunkPressure.startCollectChanges();
}

View File

@@ -50,32 +50,42 @@ class GameServer : public AsyncObject {
struct ContentObj {
public:
// WorldDefManager WorldDM;
// VoxelDefManager VoxelDM;
// NodeDefManager NodeDM;
BinaryResourceManager Texture;
BinaryResourceManager Animation;
BinaryResourceManager Model;
BinaryResourceManager Sound;
BinaryResourceManager Font;
BinaryResourceManager BRM;
ContentObj(asio::io_context &ioc,
std::shared_ptr<ResourceFile> zeroTexture,
std::shared_ptr<ResourceFile> zeroAnimation,
std::shared_ptr<ResourceFile> zeroModel,
std::shared_ptr<ResourceFile> zeroSound,
std::shared_ptr<ResourceFile> zeroFont)
: Texture(ioc, zeroTexture),
Animation(ioc, zeroAnimation),
Model(ioc, zeroModel),
Sound(ioc, zeroSound),
Font(ioc, zeroFont)
ResourceId_t NextId[(int) EnumDefContent::MAX_ENUM] = {0};
std::unordered_map<std::string, ResourceId_t> ContentKeyToId[(int) EnumDefContent::MAX_ENUM]; // EnumDefContent
std::unordered_map<DefVoxelId_t, DefVoxel_t> ContentIdToDef_Voxel;
std::unordered_map<DefNodeId_t, DefNode_t> ContentIdToDef_Node;
std::unordered_map<DefWorldId_t, DefWorld_t> ContentIdToDef_World;
std::unordered_map<DefPortalId_t, DefPortal_t> ContentIdToDef_Portal;
std::unordered_map<DefEntityId_t, DefEntity_t> ContentIdToDef_Entity;
std::unordered_map<DefItemId_t, DefItem_t> ContentIdToDef_Item;
ResourceId_t getContentDefId(const std::string& key, EnumDefContent def) {
int index = int(def);
assert(index < (int) EnumDefContent::MAX_ENUM);
auto &container = ContentKeyToId[index];
auto iter = container.find(key);
if(iter == container.end()) {
assert(NextId[index] != ResourceId_t(-1));
ResourceId_t nextId = NextId[index]++;
container.insert(iter, {key, nextId});
return nextId;
}
return iter->second;
}
// Если контент был перерегистрирован (исключая двоичные ресурсы), то профили будут повторно разосланы
ResourceRequest OnContentChanges;
ContentObj(asio::io_context& ioc)
: BRM(ioc)
{}
std::map<DefNodeId_t, DefNode_t> NodeDefines;
std::map<std::string, DefNodeId_t> NodeKeys;
} Content;
struct {

View File

@@ -510,8 +510,7 @@ void RemoteClient::informateBinary(const std::vector<std::shared_ptr<ResourceFil
NextPacket << (uint8_t) ToClient::L1::Resource // Принудительная полная отправка
<< (uint8_t) ToClient::L2Resource::InitResSend
<< uint32_t(resource->Data.size());
for(auto part : hash)
NextPacket << part;
NextPacket.write((const std::byte*) hash.data(), hash.size());
NextPacket << uint32_t(resource->Data.size());
@@ -526,25 +525,27 @@ void RemoteClient::informateBinary(const std::vector<std::shared_ptr<ResourceFil
}
}
void RemoteClient::informateIdToHash(const std::vector<std::tuple<EnumBinResource, ResourceId_t, Hash_t>>& resourcesLink) {
void RemoteClient::informateIdToHash(const std::unordered_map<ResourceId_t, ResourceFile::Hash_t>* resourcesLink) {
std::vector<std::tuple<EnumBinResource, ResourceId_t, Hash_t>> newForClient;
for(auto& [type, id, hash] : resourcesLink) {
// Посмотрим что известно клиенту
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({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);
for(int type = 0; type < (int) EnumBinResource::MAX_ENUM; type++) {
for(auto& [id, hash] : resourcesLink[type]) {
// Посмотрим что известно клиенту
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 {
// Ресурс не отслеживается клиентом
}
} else {
// Ресурс не отслеживается клиентом
}
}
@@ -563,7 +564,7 @@ void RemoteClient::informateIdToHash(const std::vector<std::tuple<EnumBinResourc
}
}
void RemoteClient::informateDefVoxel(const std::unordered_map<DefVoxelId_t, void*> &voxels)
void RemoteClient::informateDefVoxel(const std::unordered_map<DefVoxelId_t, DefVoxel_t*> &voxels)
{
for(auto pair : voxels) {
DefVoxelId_t id = pair.first;
@@ -624,7 +625,7 @@ void RemoteClient::informateDefNode(const std::unordered_map<DefNodeId_t, DefNod
}
}
void RemoteClient::informateDefWorld(const std::unordered_map<DefWorldId_t, void*> &worlds)
void RemoteClient::informateDefWorld(const std::unordered_map<DefWorldId_t, DefWorld_t*> &worlds)
{
for(auto pair : worlds) {
DefWorldId_t id = pair.first;
@@ -637,7 +638,7 @@ void RemoteClient::informateDefWorld(const std::unordered_map<DefWorldId_t, void
}
}
void RemoteClient::informateDefPortal(const std::unordered_map<DefPortalId_t, void*> &portals)
void RemoteClient::informateDefPortal(const std::unordered_map<DefPortalId_t, DefPortal_t*> &portals)
{
for(auto pair : portals) {
DefPortalId_t id = pair.first;
@@ -650,7 +651,7 @@ void RemoteClient::informateDefPortal(const std::unordered_map<DefPortalId_t, vo
}
}
void RemoteClient::informateDefEntity(const std::unordered_map<DefEntityId_t, void*> &entityes)
void RemoteClient::informateDefEntity(const std::unordered_map<DefEntityId_t, DefEntity_t*> &entityes)
{
for(auto pair : entityes) {
DefEntityId_t id = pair.first;
@@ -663,7 +664,7 @@ void RemoteClient::informateDefEntity(const std::unordered_map<DefEntityId_t, vo
}
}
void RemoteClient::informateDefItem(const std::unordered_map<DefItemId_t, void*> &items)
void RemoteClient::informateDefItem(const std::unordered_map<DefItemId_t, DefItem_t*> &items)
{
for(auto pair : items) {
DefItemId_t id = pair.first;

View File

@@ -140,7 +140,7 @@ public:
*/
struct ResourceRequest {
std::vector<Hash_t> Hashes;
std::vector<ResourceId_t> BinToHash[5];
std::vector<ResourceId_t> BinToHash[5 /*EnumBinResource*/];
std::vector<DefVoxelId_t> Voxel;
std::vector<DefNodeId_t> Node;
@@ -163,7 +163,7 @@ struct ResourceRequest {
}
void uniq() {
for(std::vector<ResourceId_t> *vec : {&BinToHash, &Voxel, &Node, &World,
for(std::vector<ResourceId_t> *vec : {&Voxel, &Node, &World,
&Portal, &Entity, &Item
})
{
@@ -172,6 +172,13 @@ struct ResourceRequest {
vec->erase(last, vec->end());
}
for(int type = 0; type < (int) EnumBinResource::MAX_ENUM; type++)
{
std::sort(BinToHash[type].begin(), BinToHash[type].end());
auto last = std::unique(BinToHash[type].begin(), BinToHash[type].end());
BinToHash[type].erase(last, BinToHash[type].end());
}
std::sort(Hashes.begin(), Hashes.end());
auto last = std::unique(Hashes.begin(), Hashes.end());
Hashes.erase(last, Hashes.end());
@@ -343,15 +350,15 @@ public:
// Привязывает локальный идентификатор с хешем. Если его нет у клиента,
// то делается запрос на получение ресурсы для последующей отправки клиенту
void informateIdToHash(const std::vector<std::tuple<EnumBinResource, ResourceId_t, Hash_t>>& resourcesLink);
void informateIdToHash(const std::unordered_map<ResourceId_t, ResourceFile::Hash_t>* resourcesLink);
// Игровые определения
void informateDefVoxel(const std::unordered_map<DefVoxelId_t, void*> &voxels);
void informateDefVoxel(const std::unordered_map<DefVoxelId_t, DefVoxel_t*> &voxels);
void informateDefNode(const std::unordered_map<DefNodeId_t, DefNode_t*> &nodes);
void informateDefWorld(const std::unordered_map<DefWorldId_t, void*> &worlds);
void informateDefPortal(const std::unordered_map<DefPortalId_t, void*> &portals);
void informateDefEntity(const std::unordered_map<DefEntityId_t, void*> &entityes);
void informateDefItem(const std::unordered_map<DefItemId_t, void*> &items);
void informateDefWorld(const std::unordered_map<DefWorldId_t, DefWorld_t*> &worlds);
void informateDefPortal(const std::unordered_map<DefPortalId_t, DefPortal_t*> &portals);
void informateDefEntity(const std::unordered_map<DefEntityId_t, DefEntity_t*> &entityes);
void informateDefItem(const std::unordered_map<DefItemId_t, DefItem_t*> &items);
private:
void checkPacketBorder(uint16_t size);