Сеть, со стороны сервера
This commit is contained in:
@@ -7,6 +7,8 @@
|
||||
#include <exception>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include "World.hpp"
|
||||
#include <Common/Packets.hpp>
|
||||
|
||||
|
||||
namespace LV::Server {
|
||||
@@ -43,77 +45,81 @@ void RemoteClient::shutdown(const std::string reason) {
|
||||
return;
|
||||
|
||||
IsGoingShutdown = true;
|
||||
// Отправить пакет о завершении работы
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::System
|
||||
<< (uint8_t) ToClient::L2System::Disconnect
|
||||
<< reason;
|
||||
}
|
||||
|
||||
void RemoteClient::prepareDefWorld(WorldId_t worldId, void* world) {
|
||||
|
||||
}
|
||||
|
||||
void RemoteClient::prepareDefVoxel(VoxelId_t voxelId, void* voxel) {
|
||||
|
||||
}
|
||||
|
||||
void RemoteClient::prepareDefNode(NodeId_t worldId, void* node) {
|
||||
|
||||
}
|
||||
|
||||
void RemoteClient::prepareDefMediaStream(MediaStreamId_t modelId, void* mediaStream) {
|
||||
|
||||
}
|
||||
|
||||
// Может прийти событие на чанк, про который ещё ничего не знаем
|
||||
void RemoteClient::prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk chunkPos,
|
||||
const std::vector<VoxelCube> &voxels)
|
||||
{
|
||||
WorldId_c wcId = rentWorldRemapId(worldId);
|
||||
if(wcId == WorldId_c(-1))
|
||||
return;
|
||||
WorldId_c wcId = ResRemap.Worlds.toClient(worldId);
|
||||
assert(wcId != WorldId_c(-1));
|
||||
|
||||
// Перебиндить идентификаторы вокселей
|
||||
std::vector<VoxelId_t> NeedVoxels;
|
||||
std::vector<DefVoxelId_t> NeedVoxels;
|
||||
NeedVoxels.reserve(voxels.size());
|
||||
|
||||
for(const VoxelCube &cube : voxels) {
|
||||
NeedVoxels.push_back(cube.Material);
|
||||
NeedVoxels.push_back(cube.VoxelId);
|
||||
}
|
||||
|
||||
std::unordered_set<VoxelId_t> NeedVoxelsSet(NeedVoxels.begin(), NeedVoxels.end());
|
||||
std::unordered_set<DefVoxelId_t> NeedVoxelsSet(NeedVoxels.begin(), NeedVoxels.end());
|
||||
|
||||
// Собираем информацию о конвертации идентификаторов
|
||||
std::unordered_map<VoxelId_t, VoxelId_c> LocalRemapper;
|
||||
for(VoxelId_t vId : NeedVoxelsSet) {
|
||||
auto cvId = Remap.STC_Voxels.find(vId);
|
||||
if(cvId == Remap.STC_Voxels.end()) {
|
||||
// Нужно забронировать идентификатор
|
||||
VoxelId_c cvnId = Remap.UsedVoxelIdC._Find_first();
|
||||
if(cvnId == VoxelId_c(-1))
|
||||
// Нет свободных идентификаторов
|
||||
LocalRemapper[vId] = 0;
|
||||
else {
|
||||
NextRequest.NewVoxels.push_back(vId);
|
||||
Remap.UsedVoxelIdC.reset(cvnId);
|
||||
Remap.STC_Voxels[vId] = cvnId;
|
||||
LocalRemapper[vId] = cvnId;
|
||||
std::unordered_map<DefVoxelId_t, VoxelId_c> LocalRemapper;
|
||||
for(DefVoxelId_t vId : NeedVoxelsSet) {
|
||||
LocalRemapper[vId] = ResRemap.DefVoxels.toClient(vId);
|
||||
}
|
||||
|
||||
// Проверить новые и забытые определения вокселей
|
||||
{
|
||||
std::unordered_set<DefVoxelId_t> &prevSet = ResUses.ChunkVoxels[{worldId, chunkPos}];
|
||||
std::unordered_set<DefVoxelId_t> &nextSet = NeedVoxelsSet;
|
||||
|
||||
std::vector<DefVoxelId_t> newVoxels, lostVoxels;
|
||||
for(DefVoxelId_t id : prevSet) {
|
||||
if(!nextSet.contains(id)) {
|
||||
if(--ResUses.DefVoxel[id] == 0) {
|
||||
// Определение больше не используется
|
||||
|
||||
ResUses.DefVoxel.erase(ResUses.DefVoxel.find(id));
|
||||
VoxelId_c cId = ResRemap.DefVoxels.erase(id);
|
||||
// TODO: отправить пакет потери идентификатора
|
||||
LOG.debug() << "Определение вокселя потеряно: " << id << " -> " << cId;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LocalRemapper[vId] = cvId->second;
|
||||
}
|
||||
|
||||
for(DefVoxelId_t id : nextSet) {
|
||||
if(!prevSet.contains(id)) {
|
||||
if(++ResUses.DefVoxel[id] == 1) {
|
||||
// Определение только появилось
|
||||
NextRequest.NewVoxels.push_back(id);
|
||||
VoxelId_c cId = ResRemap.DefVoxels.toClient(id);
|
||||
LOG.debug() << "Новое определение вокселя: " << id << " -> " << cId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prevSet = std::move(nextSet);
|
||||
}
|
||||
|
||||
Net::Packet packet;
|
||||
// TODO: отправить новую информацию о расположении вокселей
|
||||
LOG.debug() << "Новый чанк: " << worldId << " / " << chunkPos.X << ":" << chunkPos.Y << ":" << chunkPos.Z;
|
||||
// Packet Id
|
||||
packet << uint16_t(0);
|
||||
packet << wcId << Pos::GlobalChunk::Key(chunkPos);
|
||||
packet << uint16_t(voxels.size());
|
||||
// NextPacket << uint16_t(0);
|
||||
// NextPacket << wcId << Pos::GlobalChunk::Key(chunkPos);
|
||||
// NextPacket << uint16_t(voxels.size());
|
||||
|
||||
for(const VoxelCube &cube : voxels) {
|
||||
packet << LocalRemapper[cube.Material]
|
||||
<< cube.Left.X << cube.Left.Y << cube.Left.Z
|
||||
<< cube.Right.X << cube.Right.Y << cube.Right.Z;
|
||||
}
|
||||
|
||||
SimplePackets.push_back(std::move(packet));
|
||||
// for(const VoxelCube &cube : voxels) {
|
||||
// NextPacket << LocalRemapper[cube.VoxelId]
|
||||
// << cube.Left.X << cube.Left.Y << cube.Left.Z
|
||||
// << cube.Right.X << cube.Right.Y << cube.Right.Z;
|
||||
// }
|
||||
}
|
||||
|
||||
void RemoteClient::prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::GlobalChunk chunkPos,
|
||||
@@ -131,144 +137,456 @@ void RemoteClient::prepareChunkUpdate_LightPrism(WorldId_t worldId, Pos::GlobalC
|
||||
|
||||
void RemoteClient::prepareChunkRemove(WorldId_t worldId, Pos::GlobalChunk chunkPos)
|
||||
{
|
||||
// Понизим зависимости ресурсов
|
||||
std::unordered_set<DefVoxelId_t> &prevSet = ResUses.ChunkVoxels[{worldId, chunkPos}];
|
||||
for(DefVoxelId_t id : prevSet) {
|
||||
if(--ResUses.DefVoxel[id] == 0) {
|
||||
// Определение больше не используется
|
||||
|
||||
ResUses.DefVoxel.erase(ResUses.DefVoxel.find(id));
|
||||
VoxelId_c cId = ResRemap.DefVoxels.erase(id);
|
||||
// TODO: отправить пакет потери идентификатора
|
||||
LOG.debug() << "Определение вокселя потеряно: " << id << " -> " << cId;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.debug() << "Чанк потерян: " << worldId << " / " << chunkPos.X << ":" << chunkPos.Y << ":" << chunkPos.Z;
|
||||
WorldId_c cwId = ResRemap.Worlds.toClient(worldId);
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::RemoveChunk
|
||||
<< cwId << chunkPos.X << chunkPos.Y << chunkPos.Z;
|
||||
}
|
||||
|
||||
void RemoteClient::prepareWorldNew(WorldId_t worldId, World* world)
|
||||
{
|
||||
ResUsesObj::WorldResourceUse &res = ResUses.Worlds[worldId];
|
||||
res.DefId = world->getDefId();
|
||||
if(++ResUses.DefWorld[res.DefId] == 1) {
|
||||
// Новое определение мира
|
||||
DefWorldId_c cdId = ResRemap.DefWorlds.toClient(res.DefId);
|
||||
NextRequest.NewWorlds.push_back(res.DefId);
|
||||
|
||||
LOG.debug() << "Новое определение мира: " << res.DefId << " -> " << cdId;
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::World
|
||||
<< cdId;
|
||||
}
|
||||
|
||||
incrementBinary(res.Textures, res.Sounds, res.Models);
|
||||
|
||||
WorldId_c cId = ResRemap.Worlds.toClient(worldId);
|
||||
LOG.debug() << "Новый мир: " << worldId << " -> " << int(cId);
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::World
|
||||
<< cId;
|
||||
}
|
||||
|
||||
void RemoteClient::prepareWorldUpdate(WorldId_t worldId, World* world)
|
||||
{
|
||||
ResUsesObj::WorldResourceUse &res = ResUses.Worlds[worldId];
|
||||
|
||||
if(res.DefId != world->getDefId()) {
|
||||
DefWorldId_t newDef = world->getDefId();
|
||||
|
||||
if(--ResUses.DefWorld[res.DefId] == 0) {
|
||||
// Определение больше не используется
|
||||
ResUses.DefWorld.erase(ResUses.DefWorld.find(res.DefId));
|
||||
DefWorldId_c cdId = ResRemap.DefWorlds.erase(res.DefId);
|
||||
|
||||
// TODO: отправить пакет потери идентификатора
|
||||
LOG.debug() << "Определение мира потеряно: " << res.DefId << " -> " << cdId;
|
||||
}
|
||||
|
||||
if(++ResUses.DefWorld[newDef] == 1) {
|
||||
// Новое определение мира
|
||||
DefWorldId_c cdId = ResRemap.DefWorlds.toClient(newDef);
|
||||
NextRequest.NewWorlds.push_back(newDef);
|
||||
|
||||
// incrementBinary(Textures, Sounds, Models);
|
||||
// TODO: отправить пакет о новом определении мира
|
||||
LOG.debug() << "Новое определение мира: " << newDef << " -> " << cdId;
|
||||
}
|
||||
|
||||
res.DefId = newDef;
|
||||
}
|
||||
|
||||
// TODO: определить различия между переопределением поверх определений
|
||||
std::unordered_set<BinTextureId_t> lostTextures, newTextures;
|
||||
std::unordered_set<BinSoundId_t> lostSounds, newSounds;
|
||||
std::unordered_set<BinModelId_t> lostModels, newModels;
|
||||
|
||||
decrementBinary(lostTextures, lostSounds, lostModels);
|
||||
decrementBinary(newTextures, newSounds, newModels);
|
||||
|
||||
WorldId_c cId = ResRemap.Worlds.toClient(worldId);
|
||||
// TODO: отправить пакет об изменении мира
|
||||
LOG.debug() << "Изменение мира: " << worldId << " -> " << cId;
|
||||
}
|
||||
|
||||
void RemoteClient::prepareWorldRemove(WorldId_t worldId)
|
||||
{
|
||||
|
||||
// Чанки уже удалены prepareChunkRemove
|
||||
// Понизим зависимости ресурсов
|
||||
ResUsesObj::WorldResourceUse &res = ResUses.Worlds[worldId];
|
||||
|
||||
WorldId_c cWorld = ResUses.Worlds.erase(worldId);
|
||||
LOG.debug() << "Мир потерян: " << worldId << " -> " << cWorld;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::RemoveWorld
|
||||
<< cWorld;
|
||||
|
||||
if(--ResUses.DefWorld[res.DefId] == 0) {
|
||||
// Определение мира потеряно
|
||||
ResUses.DefWorld.erase(ResUses.DefWorld.find(res.DefId));
|
||||
DefWorldId_c cdWorld = ResRemap.DefWorlds.erase(res.DefId);
|
||||
|
||||
// TODO: отправить пакет о потере определения мира
|
||||
LOG.debug() << "Определение мира потеряно: " << res.DefId << " -> " << cdWorld;
|
||||
}
|
||||
|
||||
decrementBinary(res.Textures, res.Sounds, res.Models);
|
||||
}
|
||||
|
||||
void RemoteClient::prepareEntitySwap(WorldId_t prevWorldId, Pos::GlobalRegion prevRegionPos, EntityId_t prevEntityId,
|
||||
WorldId_t newWorldId, Pos::GlobalRegion newRegionPos, EntityId_t newEntityId)
|
||||
void RemoteClient::prepareEntitySwap(GlobalEntityId_t prev, GlobalEntityId_t next)
|
||||
{
|
||||
|
||||
ResRemap.Entityes.rebindClientKey(prev, next);
|
||||
LOG.debug() << "Ребинд сущности: " << std::get<0>(prev) << " / " << std::get<1>(prev).X << ":"
|
||||
<< std::get<1>(prev).Y << ":" << std::get<1>(prev).Z << " / " << std::get<2>(prev)
|
||||
<< " -> " << std::get<0>(next) << " / " << std::get<1>(next).X << ":"
|
||||
<< std::get<1>(next).Y << ":" << std::get<1>(next).Z << " / " << std::get<2>(next);
|
||||
}
|
||||
|
||||
void RemoteClient::prepareEntityUpdate(WorldId_t worldId, Pos::GlobalRegion regionPos,
|
||||
EntityId_t entityId, const Entity *entity)
|
||||
void RemoteClient::prepareEntityUpdate(GlobalEntityId_t entityId, const Entity *entity)
|
||||
{
|
||||
// Может прийти событие на сущность, про которую ещё ничего не знаем
|
||||
|
||||
// Сопоставим с идентификатором клиента
|
||||
EntityId_c ceId = -1;
|
||||
EntityId_c ceId = ResRemap.Entityes.toClient(entityId);
|
||||
|
||||
auto pWorld = Remap.STC_Entityes.find(worldId);
|
||||
if(pWorld != Remap.STC_Entityes.end()) {
|
||||
auto pRegion = pWorld->second.find(regionPos);
|
||||
if(pRegion != pWorld->second.end()) {
|
||||
auto pId = pRegion->second.find(entityId);
|
||||
if(pId != pRegion->second.end()) {
|
||||
ceId = pId->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto iter = ResUses.Entity.find(entityId);
|
||||
if(iter == ResUses.Entity.end()) {
|
||||
// Новая сущность
|
||||
|
||||
if(ceId == EntityId_c(-1)) {
|
||||
// Клиент ещё не знает о сущности
|
||||
// Выделяем идентификатор на стороне клиента для сущностей
|
||||
ceId = Remap.UsedEntityIdC._Find_first();
|
||||
if(ceId != EntityId_c(-1)) {
|
||||
Remap.UsedEntityIdC.reset(ceId);
|
||||
Remap.CTS_Entityes[ceId] = {worldId, regionPos, entityId};
|
||||
Remap.STC_Entityes[worldId][regionPos][entityId] = ceId;
|
||||
// WorldId_c cwId = ResRemap.Worlds.toClient(std::get<0>(entityId));
|
||||
|
||||
ResUsesObj::EntityResourceUse &res = ResUses.Entity[entityId];
|
||||
res.DefId = entity->getDefId();
|
||||
|
||||
if(++ResUses.DefEntity[res.DefId] == 1) {
|
||||
// Новое определение
|
||||
NextRequest.NewEntityes.push_back(res.DefId);
|
||||
DefEntityId_c cId = ResRemap.DefEntityes.toClient(res.DefId);
|
||||
LOG.debug() << "Новое определение сущности: " << res.DefId << " -> " << cId;
|
||||
// TODO: Отправить пакет о новом определении
|
||||
|
||||
// incrementBinary(Textures, Sounds, Models);
|
||||
}
|
||||
|
||||
incrementBinary(res.Textures, res.Sounds, res.Models);
|
||||
|
||||
LOG.debug() << "Новая сущность: " << std::get<0>(entityId) << " / " << std::get<1>(entityId).X << ":"
|
||||
<< std::get<1>(entityId).Y << ":" << std::get<1>(entityId).Z << " / " << std::get<2>(entityId)
|
||||
<< " -> " << ceId;
|
||||
|
||||
} else {
|
||||
ResUsesObj::EntityResourceUse &res = iter->second;
|
||||
LOG.debug() << "Обновление сущности: " << ceId;
|
||||
}
|
||||
|
||||
if(ceId == EntityId_c(-1))
|
||||
return; // У клиента закончились идентификаторы
|
||||
|
||||
// Перебиндить ресурсы скомпилированных конвейеров
|
||||
// Отправить информацию о сущности
|
||||
// entity ceId
|
||||
}
|
||||
|
||||
void RemoteClient::prepareEntityRemove(WorldId_t worldId, Pos::GlobalRegion regionPos, EntityId_t entityId)
|
||||
void RemoteClient::prepareEntityRemove(GlobalEntityId_t entityId)
|
||||
{
|
||||
// Освобождаем идентификатор на стороне клиента
|
||||
auto pWorld = Remap.STC_Entityes.find(worldId);
|
||||
if(pWorld == Remap.STC_Entityes.end())
|
||||
return;
|
||||
EntityId_c cId = ResRemap.Entityes.erase(entityId);
|
||||
ResUsesObj::EntityResourceUse &res = ResUses.Entity[entityId];
|
||||
|
||||
auto pRegion = pWorld->second.find(regionPos);
|
||||
if(pRegion == pWorld->second.end())
|
||||
return;
|
||||
if(--ResUses.DefEntity[res.DefId] == 0) {
|
||||
LOG.debug() << "Потеряли определение сущности: " << res.DefId << " -> " << cId;
|
||||
ResUses.DefEntity.erase(ResUses.DefEntity.find(res.DefId));
|
||||
ResRemap.DefEntityes.erase(res.DefId);
|
||||
|
||||
auto pId = pRegion->second.find(entityId);
|
||||
if(pId == pRegion->second.end())
|
||||
return;
|
||||
|
||||
EntityId_c ceId = pId->second;
|
||||
Remap.UsedEntityIdC.set(ceId);
|
||||
|
||||
{
|
||||
auto pceid = Remap.CTS_Entityes.find(ceId);
|
||||
if(pceid != Remap.CTS_Entityes.end())
|
||||
Remap.CTS_Entityes.erase(pceid);
|
||||
// decrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds, std::unordered_set<BinModelId_t> &models)
|
||||
}
|
||||
|
||||
pRegion->second.erase(pId);
|
||||
LOG.debug() << "Сущность потеряна: " << cId;
|
||||
|
||||
if(pRegion->second.empty()) {
|
||||
pWorld->second.erase(pRegion);
|
||||
|
||||
if(pWorld->second.empty())
|
||||
Remap.STC_Entityes.erase(pWorld);
|
||||
}
|
||||
|
||||
// Пакет об удалении сущности
|
||||
// ceId
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::RemoveEntity
|
||||
<< cId;
|
||||
}
|
||||
|
||||
void RemoteClient::preparePortalNew(PortalId_t portalId, void* portal) {}
|
||||
void RemoteClient::preparePortalUpdate(PortalId_t portalId, void* portal) {}
|
||||
void RemoteClient::preparePortalRemove(PortalId_t portalId) {}
|
||||
|
||||
void RemoteClient::prepareCameraSetEntity(WorldId_t worldId, Pos::GlobalChunk chunkPos, EntityId_t entityId) {}
|
||||
void RemoteClient::prepareCameraSetEntity(GlobalEntityId_t entityId) {
|
||||
|
||||
}
|
||||
|
||||
ResourceRequest RemoteClient::pushPreparedPackets() {
|
||||
if(NextPacket.size())
|
||||
SimplePackets.push_back(std::move(NextPacket));
|
||||
|
||||
Socket.pushPackets(&SimplePackets);
|
||||
SimplePackets.clear();
|
||||
|
||||
NextRequest.uniq();
|
||||
|
||||
return std::move(NextRequest);
|
||||
return std::move(NextRequest);
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefTexture(const std::unordered_map<TextureId_t, std::shared_ptr<ResourceFile>> &textures) {
|
||||
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefModel(const std::unordered_map<ModelId_t, std::shared_ptr<ResourceFile>> &models) {
|
||||
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefSound(const std::unordered_map<SoundId_t, std::shared_ptr<ResourceFile>> &sounds) {
|
||||
|
||||
}
|
||||
|
||||
WorldId_c RemoteClient::rentWorldRemapId(WorldId_t wId)
|
||||
void RemoteClient::informateDefTexture(const std::unordered_map<BinTextureId_t, std::shared_ptr<ResourceFile>> &textures)
|
||||
{
|
||||
WorldId_c wcId;
|
||||
for(auto pair : textures) {
|
||||
BinTextureId_t sId = pair.first;
|
||||
if(!ResUses.BinTexture.contains(sId))
|
||||
continue;
|
||||
|
||||
auto cwId = Remap.STC_Worlds.find(wId);
|
||||
if(cwId == Remap.STC_Worlds.end()) {
|
||||
// Нужно забронировать идентификатор
|
||||
wcId = Remap.UsedWorldIdC._Find_first();
|
||||
if(wcId == WorldId_c(-1))
|
||||
// Нет свободных идентификаторов
|
||||
return wcId;
|
||||
else {
|
||||
NextRequest.NewWorlds.push_back(wId);
|
||||
Remap.UsedWorldIdC.reset(wcId);
|
||||
Remap.STC_Worlds[wId] = wcId;
|
||||
TextureId_c cId = ResRemap.BinTextures.toClient(sId);
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource // Оповещение
|
||||
<< (uint8_t) ToClient::L2Resource::Texture << cId;
|
||||
for(auto part : pair.second->Hash)
|
||||
NextPacket << part;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource // Принудительная отправка
|
||||
<< (uint8_t) ToClient::L2Resource::InitResSend
|
||||
<< uint8_t(0) << uint8_t(0) << cId
|
||||
<< uint32_t(pair.second->Data.size());
|
||||
for(auto part : pair.second->Hash)
|
||||
NextPacket << part;
|
||||
|
||||
NextPacket << uint8_t(0) << uint32_t(pair.second->Data.size());
|
||||
|
||||
size_t pos = 0;
|
||||
while(pos < pair.second->Data.size()) {
|
||||
if(NextPacket.size() > 64000) {
|
||||
SimplePackets.push_back(std::move(NextPacket));
|
||||
}
|
||||
|
||||
size_t need = std::min(pair.second->Data.size()-pos, std::min<size_t>(NextPacket.size(), 64000));
|
||||
NextPacket.write(pair.second->Data.data()+pos, need);
|
||||
pos += need;
|
||||
}
|
||||
} else {
|
||||
wcId = cwId->second;
|
||||
}
|
||||
|
||||
return wcId;
|
||||
if(NextPacket.size())
|
||||
SimplePackets.push_back(std::move(NextPacket));
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefSound(const std::unordered_map<BinSoundId_t, std::shared_ptr<ResourceFile>> &sounds)
|
||||
{
|
||||
for(auto pair : sounds) {
|
||||
BinSoundId_t sId = pair.first;
|
||||
if(!ResUses.BinSound.contains(sId))
|
||||
continue;
|
||||
|
||||
SoundId_c cId = ResRemap.BinSounds.toClient(sId);
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource // Оповещение
|
||||
<< (uint8_t) ToClient::L2Resource::Sound << cId;
|
||||
for(auto part : pair.second->Hash)
|
||||
NextPacket << part;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource // Принудительная отправка
|
||||
<< (uint8_t) ToClient::L2Resource::InitResSend
|
||||
<< uint8_t(0) << uint8_t(1) << cId
|
||||
<< uint32_t(pair.second->Data.size());
|
||||
for(auto part : pair.second->Hash)
|
||||
NextPacket << part;
|
||||
|
||||
NextPacket << uint8_t(0) << uint32_t(pair.second->Data.size());
|
||||
|
||||
size_t pos = 0;
|
||||
while(pos < pair.second->Data.size()) {
|
||||
if(NextPacket.size() >= 64000) {
|
||||
SimplePackets.push_back(std::move(NextPacket));
|
||||
}
|
||||
|
||||
size_t need = std::min(pair.second->Data.size()-pos, std::min<size_t>(NextPacket.size(), 64000));
|
||||
NextPacket.write(pair.second->Data.data()+pos, need);
|
||||
pos += need;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefModel(const std::unordered_map<BinModelId_t, std::shared_ptr<ResourceFile>> &models)
|
||||
{
|
||||
for(auto pair : models) {
|
||||
BinModelId_t sId = pair.first;
|
||||
if(!ResUses.BinModel.contains(sId))
|
||||
continue;
|
||||
|
||||
ModelId_c cId = ResRemap.BinModels.toClient(sId);
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource // Оповещение
|
||||
<< (uint8_t) ToClient::L2Resource::Model << cId;
|
||||
for(auto part : pair.second->Hash)
|
||||
NextPacket << part;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource // Принудительная отправка
|
||||
<< (uint8_t) ToClient::L2Resource::InitResSend
|
||||
<< uint8_t(0) << uint8_t(2) << cId
|
||||
<< uint32_t(pair.second->Data.size());
|
||||
for(auto part : pair.second->Hash)
|
||||
NextPacket << part;
|
||||
|
||||
NextPacket << uint8_t(0) << uint32_t(pair.second->Data.size());
|
||||
|
||||
size_t pos = 0;
|
||||
while(pos < pair.second->Data.size()) {
|
||||
if(NextPacket.size() >= 64000) {
|
||||
SimplePackets.push_back(std::move(NextPacket));
|
||||
}
|
||||
|
||||
size_t need = std::min(pair.second->Data.size()-pos, std::min<size_t>(NextPacket.size(), 64000));
|
||||
NextPacket.write(pair.second->Data.data()+pos, need);
|
||||
pos += need;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefWorld(const std::unordered_map<DefWorldId_t, World*> &worlds)
|
||||
{
|
||||
for(auto pair : worlds) {
|
||||
DefWorldId_t sId = pair.first;
|
||||
if(!ResUses.DefWorld.contains(sId))
|
||||
continue;
|
||||
|
||||
DefWorldId_c cId = ResRemap.DefWorlds.toClient(sId);
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::World
|
||||
<< cId;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefVoxel(const std::unordered_map<DefVoxelId_t, void*> &voxels)
|
||||
{
|
||||
for(auto pair : voxels) {
|
||||
DefVoxelId_t sId = pair.first;
|
||||
if(!ResUses.DefWorld.contains(sId))
|
||||
continue;
|
||||
|
||||
VoxelId_c cId = ResRemap.DefVoxels.toClient(sId);
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::Voxel
|
||||
<< cId;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefNode(const std::unordered_map<DefNodeId_t, void*> &nodes)
|
||||
{
|
||||
for(auto pair : nodes) {
|
||||
DefNodeId_t sId = pair.first;
|
||||
if(!ResUses.DefNode.contains(sId))
|
||||
continue;
|
||||
|
||||
NodeId_c cId = ResRemap.DefNodes.toClient(sId);
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::Node
|
||||
<< cId;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefEntityes(const std::unordered_map<DefEntityId_t, void*> &entityes)
|
||||
{
|
||||
for(auto pair : entityes) {
|
||||
DefEntityId_t sId = pair.first;
|
||||
if(!ResUses.DefNode.contains(sId))
|
||||
continue;
|
||||
|
||||
DefEntityId_c cId = ResRemap.DefEntityes.toClient(sId);
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::Entity
|
||||
<< cId;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::informateDefPortals(const std::unordered_map<DefPortalId_t, void*> &portals)
|
||||
{
|
||||
for(auto pair : portals) {
|
||||
DefPortalId_t sId = pair.first;
|
||||
if(!ResUses.DefNode.contains(sId))
|
||||
continue;
|
||||
|
||||
DefPortalId_c cId = ResRemap.DefPortals.toClient(sId);
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::Portal
|
||||
<< cId;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::incrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
||||
std::unordered_set<BinModelId_t> &models)
|
||||
{
|
||||
for(BinTextureId_t id : textures) {
|
||||
if(++ResUses.BinTexture[id] == 1) {
|
||||
TextureId_c cId = ResRemap.BinTextures.toClient(id);
|
||||
NextRequest.NewTextures.push_back(id);
|
||||
LOG.debug() << "Новое определение текстуры: " << id << " -> " << cId;
|
||||
}
|
||||
}
|
||||
|
||||
for(BinSoundId_t id : sounds) {
|
||||
if(++ResUses.BinSound[id] == 1) {
|
||||
SoundId_c cId = ResRemap.BinSounds.toClient(id);
|
||||
NextRequest.NewSounds.push_back(id);
|
||||
LOG.debug() << "Новое определение звука: " << id << " -> " << cId;
|
||||
}
|
||||
}
|
||||
|
||||
for(BinModelId_t id : sounds) {
|
||||
if(++ResUses.BinModel[id] == 1) {
|
||||
ModelId_c cId = ResRemap.BinModels.toClient(id);
|
||||
NextRequest.NewModels.push_back(id);
|
||||
LOG.debug() << "Новое определение модели: " << id << " -> " << cId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::decrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
||||
std::unordered_set<BinModelId_t> &models)
|
||||
{
|
||||
for(BinTextureId_t id : textures) {
|
||||
if(--ResUses.BinTexture[id] == 0) {
|
||||
ResUses.BinTexture.erase(ResUses.BinTexture.find(id));
|
||||
TextureId_c cId = ResRemap.BinTextures.erase(id);
|
||||
LOG.debug() << "Потеряно определение текстуры: " << id << " -> " << cId;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource
|
||||
<< (uint8_t) ToClient::L2Resource::FreeTexture
|
||||
<< cId;
|
||||
}
|
||||
}
|
||||
|
||||
for(BinSoundId_t id : sounds) {
|
||||
if(--ResUses.BinSound[id] == 0) {
|
||||
ResUses.BinSound.erase(ResUses.BinSound.find(id));
|
||||
SoundId_c cId = ResRemap.BinSounds.erase(id);
|
||||
LOG.debug() << "Потеряно определение звука: " << id << " -> " << cId;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource
|
||||
<< (uint8_t) ToClient::L2Resource::FreeSound
|
||||
<< cId;
|
||||
}
|
||||
}
|
||||
|
||||
for(BinModelId_t id : sounds) {
|
||||
if(--ResUses.BinModel[id] == 0) {
|
||||
ResUses.BinModel.erase(ResUses.BinModel.find(id));
|
||||
ModelId_c cId = ResRemap.BinModels.erase(id);
|
||||
LOG.debug() << "Потеряно определение модели: " << id << " -> " << cId;
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Resource
|
||||
<< (uint8_t) ToClient::L2Resource::FreeModel
|
||||
<< cId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user