Получение пакетов клиентом
This commit is contained in:
@@ -8,20 +8,6 @@
|
||||
|
||||
namespace LV::Server {
|
||||
|
||||
// Идентификаторы на стороне клиента
|
||||
using TextureId_c = uint16_t;
|
||||
using SoundId_c = uint16_t;
|
||||
using ModelId_c = uint16_t;
|
||||
|
||||
using DefWorldId_c = uint8_t;
|
||||
using WorldId_c = uint8_t;
|
||||
using VoxelId_c = uint16_t;
|
||||
using NodeId_c = uint16_t;
|
||||
using DefPortalId_c = uint8_t;
|
||||
using PortalId_c = uint8_t;
|
||||
using DefEntityId_c = uint16_t;
|
||||
using EntityId_c = uint16_t;
|
||||
|
||||
using ResourceId_t = uint32_t;
|
||||
|
||||
// Двоичные данные
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "GameServer.hpp"
|
||||
#include "Common/Abstract.hpp"
|
||||
#include "Common/Net.hpp"
|
||||
#include "Common/Packets.hpp"
|
||||
#include "Server/Abstract.hpp"
|
||||
#include "Server/ContentEventController.hpp"
|
||||
#include <boost/json/parse.hpp>
|
||||
@@ -248,7 +249,7 @@ void GameServer::run() {
|
||||
if(IsGoingShutdown) {
|
||||
// Отключить игроков
|
||||
for(std::unique_ptr<ContentEventController> &cec : Game.CECs) {
|
||||
cec->Remote->shutdown(ShutdownReason);
|
||||
cec->Remote->shutdown(EnumDisconnect::ByInterface, ShutdownReason);
|
||||
}
|
||||
|
||||
// Сохранить данные
|
||||
@@ -259,7 +260,7 @@ void GameServer::run() {
|
||||
auto lock = External.NewConnectedPlayers.lock_write();
|
||||
|
||||
for(std::unique_ptr<RemoteClient> &client : *lock) {
|
||||
client->shutdown(ShutdownReason);
|
||||
client->shutdown(EnumDisconnect::ByInterface, ShutdownReason);
|
||||
}
|
||||
|
||||
bool hasNewConnected = !lock->empty();
|
||||
@@ -361,6 +362,14 @@ void GameServer::stepPlayers() {
|
||||
for(std::unique_ptr<ContentEventController> &cec : Game.CECs) {
|
||||
// Убрать отключившихся
|
||||
if(!cec->Remote->isConnected()) {
|
||||
for(auto wPair : cec->SubscribedRegions) {
|
||||
auto wIter = Expanse.Worlds.find(wPair.first);
|
||||
if(wIter == Expanse.Worlds.end())
|
||||
continue;
|
||||
|
||||
wIter->second->onCEC_RegionsLost(cec.get(), wPair.second);
|
||||
}
|
||||
|
||||
cec.reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,8 @@ public:
|
||||
|
||||
|
||||
void shutdown(const std::string reason) {
|
||||
ShutdownReason = reason;
|
||||
if(ShutdownReason.empty())
|
||||
ShutdownReason = reason;
|
||||
IsGoingShutdown = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
namespace LV::Server {
|
||||
|
||||
RemoteClient::~RemoteClient() {
|
||||
shutdown("~RemoteClient()");
|
||||
shutdown(EnumDisconnect::ByInterface, "~RemoteClient()");
|
||||
if(Socket.isAlive()) {
|
||||
Socket.closeRead();
|
||||
}
|
||||
|
||||
UseLock.wait_no_use();
|
||||
}
|
||||
|
||||
@@ -23,7 +27,7 @@ coro<> RemoteClient::run() {
|
||||
|
||||
try {
|
||||
while(!IsGoingShutdown && IsConnected) {
|
||||
co_await Socket.read<uint8_t>();
|
||||
co_await readPacket(Socket);
|
||||
}
|
||||
} catch(const std::exception &exc) {
|
||||
if(const auto *errc = dynamic_cast<const boost::system::system_error*>(&exc);
|
||||
@@ -40,7 +44,7 @@ coro<> RemoteClient::run() {
|
||||
co_return;
|
||||
}
|
||||
|
||||
void RemoteClient::shutdown(const std::string reason) {
|
||||
void RemoteClient::shutdown(EnumDisconnect type, const std::string reason) {
|
||||
if(IsGoingShutdown)
|
||||
return;
|
||||
|
||||
@@ -48,7 +52,17 @@ void RemoteClient::shutdown(const std::string reason) {
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::System
|
||||
<< (uint8_t) ToClient::L2System::Disconnect
|
||||
<< reason;
|
||||
<< (uint8_t) type << reason;
|
||||
|
||||
std::string info;
|
||||
if(type == EnumDisconnect::ByInterface)
|
||||
info = "по запросу интерфейса " + reason;
|
||||
else if(type == EnumDisconnect::CriticalError)
|
||||
info = "на сервере произошла критическая ошибка " + reason;
|
||||
else if(type == EnumDisconnect::ProtocolError)
|
||||
info = "ошибка протокола (сервер) " + reason;
|
||||
|
||||
LOG.info() << "Игрок '" << Username << "' отключился " << info;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +84,7 @@ void RemoteClient::prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk
|
||||
std::unordered_set<DefVoxelId_t> NeedVoxelsSet(NeedVoxels.begin(), NeedVoxels.end());
|
||||
|
||||
// Собираем информацию о конвертации идентификаторов
|
||||
std::unordered_map<DefVoxelId_t, VoxelId_c> LocalRemapper;
|
||||
std::unordered_map<DefVoxelId_t, DefVoxelId_c> LocalRemapper;
|
||||
for(DefVoxelId_t vId : NeedVoxelsSet) {
|
||||
LocalRemapper[vId] = ResRemap.DefVoxels.toClient(vId);
|
||||
}
|
||||
@@ -87,7 +101,7 @@ void RemoteClient::prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk
|
||||
// Определение больше не используется
|
||||
|
||||
ResUses.DefVoxel.erase(ResUses.DefVoxel.find(id));
|
||||
VoxelId_c cId = ResRemap.DefVoxels.erase(id);
|
||||
DefVoxelId_c cId = ResRemap.DefVoxels.erase(id);
|
||||
// TODO: отправить пакет потери идентификатора
|
||||
LOG.debug() << "Определение вокселя потеряно: " << id << " -> " << cId;
|
||||
}
|
||||
@@ -99,7 +113,7 @@ void RemoteClient::prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk
|
||||
if(++ResUses.DefVoxel[id] == 1) {
|
||||
// Определение только появилось
|
||||
NextRequest.NewVoxels.push_back(id);
|
||||
VoxelId_c cId = ResRemap.DefVoxels.toClient(id);
|
||||
DefVoxelId_c cId = ResRemap.DefVoxels.toClient(id);
|
||||
LOG.debug() << "Новое определение вокселя: " << id << " -> " << cId;
|
||||
}
|
||||
}
|
||||
@@ -108,24 +122,23 @@ void RemoteClient::prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk
|
||||
prevSet = std::move(nextSet);
|
||||
}
|
||||
|
||||
// TODO: отправить новую информацию о расположении вокселей
|
||||
LOG.debug() << "Новый чанк: " << worldId << " / " << chunkPos.X << ":" << chunkPos.Y << ":" << chunkPos.Z;
|
||||
// Packet Id
|
||||
// NextPacket << uint16_t(0);
|
||||
// NextPacket << wcId << Pos::GlobalChunk::Key(chunkPos);
|
||||
// NextPacket << uint16_t(voxels.size());
|
||||
LOG.debug() << "Воксели чанка: " << worldId << " / " << chunkPos.X << ":" << chunkPos.Y << ":" << chunkPos.Z;
|
||||
|
||||
// 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;
|
||||
// }
|
||||
NextPacket << (uint8_t) ToClient::L1::Content
|
||||
<< (uint8_t) ToClient::L2Content::ChunkVoxels << wcId
|
||||
<< Pos::GlobalChunk::Key(chunkPos);
|
||||
NextPacket << uint16_t(voxels.size());
|
||||
// TODO:
|
||||
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,
|
||||
const std::unordered_map<Pos::Local16_u, Node> &nodes)
|
||||
{
|
||||
// Перебиндить идентификаторы нод
|
||||
|
||||
}
|
||||
|
||||
@@ -144,7 +157,7 @@ void RemoteClient::prepareChunkRemove(WorldId_t worldId, Pos::GlobalChunk chunkP
|
||||
// Определение больше не используется
|
||||
|
||||
ResUses.DefVoxel.erase(ResUses.DefVoxel.find(id));
|
||||
VoxelId_c cId = ResRemap.DefVoxels.erase(id);
|
||||
DefVoxelId_c cId = ResRemap.DefVoxels.erase(id);
|
||||
// TODO: отправить пакет потери идентификатора
|
||||
LOG.debug() << "Определение вокселя потеряно: " << id << " -> " << cId;
|
||||
}
|
||||
@@ -154,7 +167,7 @@ void RemoteClient::prepareChunkRemove(WorldId_t worldId, Pos::GlobalChunk chunkP
|
||||
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;
|
||||
<< cwId << Pos::GlobalChunk::Key(chunkPos);
|
||||
}
|
||||
|
||||
void RemoteClient::prepareWorldNew(WorldId_t worldId, World* world)
|
||||
@@ -166,7 +179,7 @@ void RemoteClient::prepareWorldNew(WorldId_t worldId, World* world)
|
||||
DefWorldId_c cdId = ResRemap.DefWorlds.toClient(res.DefId);
|
||||
NextRequest.NewWorlds.push_back(res.DefId);
|
||||
|
||||
LOG.debug() << "Новое определение мира: " << res.DefId << " -> " << cdId;
|
||||
LOG.debug() << "Новое определение мира: " << res.DefId << " -> " << int(cdId);
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::World
|
||||
<< cdId;
|
||||
@@ -468,7 +481,7 @@ void RemoteClient::informateDefVoxel(const std::unordered_map<DefVoxelId_t, void
|
||||
if(!ResUses.DefWorld.contains(sId))
|
||||
continue;
|
||||
|
||||
VoxelId_c cId = ResRemap.DefVoxels.toClient(sId);
|
||||
DefVoxelId_c cId = ResRemap.DefVoxels.toClient(sId);
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::Voxel
|
||||
@@ -483,7 +496,7 @@ void RemoteClient::informateDefNode(const std::unordered_map<DefNodeId_t, void*>
|
||||
if(!ResUses.DefNode.contains(sId))
|
||||
continue;
|
||||
|
||||
NodeId_c cId = ResRemap.DefNodes.toClient(sId);
|
||||
DefNodeId_c cId = ResRemap.DefNodes.toClient(sId);
|
||||
|
||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||
<< (uint8_t) ToClient::L2Definition::Node
|
||||
@@ -521,6 +534,46 @@ void RemoteClient::informateDefPortals(const std::unordered_map<DefPortalId_t, v
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::protocolError() {
|
||||
shutdown(EnumDisconnect::ProtocolError, "Ошибка протокола");
|
||||
}
|
||||
|
||||
coro<> RemoteClient::readPacket(Net::AsyncSocket &sock) {
|
||||
uint8_t first = co_await sock.read<uint8_t>();
|
||||
|
||||
switch((ToServer::L1) first) {
|
||||
case ToServer::L1::System: co_await rP_System(sock); co_return;
|
||||
default:
|
||||
protocolError();
|
||||
}
|
||||
}
|
||||
|
||||
coro<> RemoteClient::rP_System(Net::AsyncSocket &sock) {
|
||||
uint8_t second = co_await sock.read<uint8_t>();
|
||||
|
||||
switch((ToServer::L2System) second) {
|
||||
case ToServer::L2System::InitEnd:
|
||||
|
||||
co_return;
|
||||
case ToServer::L2System::Disconnect:
|
||||
{
|
||||
EnumDisconnect type = (EnumDisconnect) co_await sock.read<uint8_t>();
|
||||
shutdown(EnumDisconnect::ByInterface, "Вы были отключены от игры");
|
||||
std::string reason;
|
||||
if(type == EnumDisconnect::CriticalError)
|
||||
reason = ": Критическая ошибка";
|
||||
else
|
||||
reason = ": Ошибка протокола (клиент)";
|
||||
|
||||
LOG.info() << "Игрок '" << Username << "' отключился" << reason;
|
||||
|
||||
co_return;
|
||||
}
|
||||
default:
|
||||
protocolError();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteClient::incrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
||||
std::unordered_set<BinModelId_t> &models)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <Common/Lockable.hpp>
|
||||
#include <Common/Net.hpp>
|
||||
#include "Abstract.hpp"
|
||||
#include "Common/Packets.hpp"
|
||||
#include "Server/ContentEventController.hpp"
|
||||
#include <Common/Abstract.hpp>
|
||||
#include <bitset>
|
||||
@@ -249,8 +250,8 @@ class RemoteClient {
|
||||
SCSKeyRemapper<BinModelId_t, ModelId_c> BinModels;
|
||||
|
||||
SCSKeyRemapper<DefWorldId_t, DefWorldId_c> DefWorlds;
|
||||
SCSKeyRemapper<DefVoxelId_t, VoxelId_c> DefVoxels;
|
||||
SCSKeyRemapper<DefNodeId_t, NodeId_c> DefNodes;
|
||||
SCSKeyRemapper<DefVoxelId_t, DefVoxelId_c> DefVoxels;
|
||||
SCSKeyRemapper<DefNodeId_t, DefNodeId_c> DefNodes;
|
||||
SCSKeyRemapper<DefPortalId_t, DefPortalId_c> DefPortals;
|
||||
SCSKeyRemapper<DefEntityId_t, DefEntityId_c> DefEntityes;
|
||||
|
||||
@@ -275,7 +276,7 @@ public:
|
||||
~RemoteClient();
|
||||
|
||||
coro<> run();
|
||||
void shutdown(const std::string reason);
|
||||
void shutdown(EnumDisconnect type, const std::string reason);
|
||||
bool isConnected() { return IsConnected; }
|
||||
|
||||
void pushPackets(std::vector<Net::Packet> *simplePackets, std::vector<Net::SmartPacket> *smartPackets = nullptr) {
|
||||
@@ -330,6 +331,10 @@ public:
|
||||
void informateDefPortals(const std::unordered_map<DefPortalId_t, void*> &portals);
|
||||
|
||||
private:
|
||||
void protocolError();
|
||||
coro<> readPacket(Net::AsyncSocket &sock);
|
||||
coro<> rP_System(Net::AsyncSocket &sock);
|
||||
|
||||
void incrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
||||
std::unordered_set<BinModelId_t> &models);
|
||||
void decrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
||||
|
||||
Reference in New Issue
Block a user