Первый коммит

This commit is contained in:
2025-02-03 15:16:12 +06:00
commit d40c3bad86
287 changed files with 124575 additions and 0 deletions

275
Src/Server/RemoteClient.cpp Normal file
View File

@@ -0,0 +1,275 @@
#include <TOSLib.hpp>
#include "RemoteClient.hpp"
#include "Common/Net.hpp"
#include "Server/Abstract.hpp"
#include <boost/asio/error.hpp>
#include <boost/system/system_error.hpp>
#include <exception>
#include <unordered_map>
#include <unordered_set>
namespace AL::Server {
RemoteClient::~RemoteClient() {
shutdown("~RemoteClient()");
UseLock.wait_no_use();
}
coro<> RemoteClient::run() {
auto useLock = UseLock.lock();
try {
while(!IsGoingShutdown && IsConnected) {
co_await Socket.read<uint8_t>();
}
} catch(const std::exception &exc) {
if(const auto *errc = dynamic_cast<const boost::system::system_error*>(&exc);
errc && errc->code() == boost::asio::error::operation_aborted)
{
co_return;
}
TOS::Logger("PlayerSocket").warn() << Username << ": " << exc.what();
}
IsConnected = false;
co_return;
}
void RemoteClient::shutdown(const std::string reason) {
if(IsGoingShutdown)
return;
IsGoingShutdown = true;
// Отправить пакет о завершении работы
}
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;
// Перебиндить идентификаторы вокселей
std::vector<VoxelId_t> NeedVoxels;
NeedVoxels.reserve(voxels.size());
for(const VoxelCube &cube : voxels) {
NeedVoxels.push_back(cube.Material);
}
std::unordered_set<VoxelId_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;
}
} else {
LocalRemapper[vId] = cvId->second;
}
}
Net::Packet packet;
// Packet Id
packet << uint16_t(0);
packet << wcId << Pos::GlobalChunk::Key(chunkPos);
packet << 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));
}
void RemoteClient::prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::GlobalChunk chunkPos,
const std::unordered_map<Pos::Local16_u, Node> &nodes)
{
// Перебиндить идентификаторы нод
}
void RemoteClient::prepareChunkUpdate_LightPrism(WorldId_t worldId, Pos::GlobalChunk chunkPos,
const LightPrism *lights)
{
}
void RemoteClient::prepareChunkRemove(WorldId_t worldId, Pos::GlobalChunk chunkPos)
{
}
void RemoteClient::prepareWorldRemove(WorldId_t worldId)
{
}
void RemoteClient::prepareEntitySwap(WorldId_t prevWorldId, Pos::GlobalRegion prevRegionPos, EntityId_t prevEntityId,
WorldId_t newWorldId, Pos::GlobalRegion newRegionPos, EntityId_t newEntityId)
{
}
void RemoteClient::prepareEntityUpdate(WorldId_t worldId, Pos::GlobalRegion regionPos,
EntityId_t entityId, const Entity *entity)
{
// Может прийти событие на сущность, про которую ещё ничего не знаем
// Сопоставим с идентификатором клиента
EntityId_c ceId = -1;
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;
}
}
}
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;
}
}
if(ceId == EntityId_c(-1))
return; // У клиента закончились идентификаторы
// Перебиндить ресурсы скомпилированных конвейеров
// Отправить информацию о сущности
// entity ceId
}
void RemoteClient::prepareEntityRemove(WorldId_t worldId, Pos::GlobalRegion regionPos, EntityId_t entityId)
{
// Освобождаем идентификатор на стороне клиента
auto pWorld = Remap.STC_Entityes.find(worldId);
if(pWorld == Remap.STC_Entityes.end())
return;
auto pRegion = pWorld->second.find(regionPos);
if(pRegion == pWorld->second.end())
return;
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);
}
pRegion->second.erase(pId);
if(pRegion->second.empty()) {
pWorld->second.erase(pRegion);
if(pWorld->second.empty())
Remap.STC_Entityes.erase(pWorld);
}
// Пакет об удалении сущности
// ceId
}
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) {}
ResourceRequest RemoteClient::pushPreparedPackets() {
Socket.pushPackets(&SimplePackets);
SimplePackets.clear();
NextRequest.uniq();
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)
{
WorldId_c wcId;
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;
}
} else {
wcId = cwId->second;
}
return wcId;
}
}