Получение пакетов клиентом
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -rdynamic")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") # -rdynamic
|
||||||
|
|
||||||
project (LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description")
|
project (LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description")
|
||||||
add_executable(${PROJECT_NAME})
|
add_executable(${PROJECT_NAME})
|
||||||
@@ -65,8 +65,8 @@ add_custom_command(OUTPUT assets.o resources.cpp INPUT ${ASSETS}
|
|||||||
COMMAND cd "${CMAKE_CURRENT_SOURCE_DIR}/Work/assets" && ld -r -b binary -o '${CMAKE_CURRENT_BINARY_DIR}/assets.o' ${ASSETS}
|
COMMAND cd "${CMAKE_CURRENT_SOURCE_DIR}/Work/assets" && ld -r -b binary -o '${CMAKE_CURRENT_BINARY_DIR}/assets.o' ${ASSETS}
|
||||||
COMMAND objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents ${CMAKE_CURRENT_BINARY_DIR}/assets.o ${CMAKE_CURRENT_BINARY_DIR}/assets.o)
|
COMMAND objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents ${CMAKE_CURRENT_BINARY_DIR}/assets.o ${CMAKE_CURRENT_BINARY_DIR}/assets.o)
|
||||||
|
|
||||||
add_library(assets STATIC resources.cpp assets.o)
|
|
||||||
SET_SOURCE_FILES_PROPERTIES(assets.o PROPERTIES EXTERNAL_OBJECT true GENERATED true)
|
SET_SOURCE_FILES_PROPERTIES(assets.o PROPERTIES EXTERNAL_OBJECT true GENERATED true)
|
||||||
|
add_library(assets STATIC resources.cpp assets.o)
|
||||||
SET_TARGET_PROPERTIES(assets PROPERTIES LINKER_LANGUAGE C)
|
SET_TARGET_PROPERTIES(assets PROPERTIES LINKER_LANGUAGE C)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC assets uring)
|
target_link_libraries(${PROJECT_NAME} PUBLIC assets uring)
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,10 @@
|
|||||||
#include "Abstract.hpp"
|
#include "Abstract.hpp"
|
||||||
|
#include "Common/Abstract.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace LV::Client {
|
namespace LV::Client {
|
||||||
|
|
||||||
void IRenderSession::onChunksChange(WorldId_t worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) {}
|
|
||||||
void IRenderSession::attachCameraToEntity(EntityId_t id) {}
|
|
||||||
void IRenderSession::onWorldAdd(WorldId_t id) {}
|
|
||||||
void IRenderSession::onWorldRemove(WorldId_t id) {}
|
|
||||||
void IRenderSession::onWorldChange(WorldId_t id) {}
|
|
||||||
void IRenderSession::onEntitysAdd(const std::vector<EntityId_t> &list) {}
|
|
||||||
void IRenderSession::onEntitysRemove(const std::vector<EntityId_t> &list) {}
|
|
||||||
void IRenderSession::onEntitysPosQuatChanges(const std::vector<EntityId_t> &list) {}
|
|
||||||
void IRenderSession::onEntitysStateChanges(const std::vector<EntityId_t> &list) {}
|
|
||||||
TextureId_t IRenderSession::allocateTexture() { return 0; }
|
|
||||||
void IRenderSession::freeTexture(TextureId_t id) {}
|
|
||||||
void IRenderSession::setTexture(TextureId_t id, TextureInfo info) {}
|
|
||||||
ModelId_t IRenderSession::allocateModel() { return 0; }
|
|
||||||
void IRenderSession::freeModel(ModelId_t id) {}
|
|
||||||
void IRenderSession::setModel(ModelId_t id, ModelInfo info) {}
|
|
||||||
IRenderSession::~IRenderSession() = default;
|
IRenderSession::~IRenderSession() = default;
|
||||||
|
|
||||||
IServerSession::~IServerSession() = default;
|
IServerSession::~IServerSession() = default;
|
||||||
|
|
||||||
void ISurfaceEventListener::onResize(uint32_t width, uint32_t height) {}
|
void ISurfaceEventListener::onResize(uint32_t width, uint32_t height) {}
|
||||||
|
|||||||
@@ -9,17 +9,13 @@
|
|||||||
|
|
||||||
namespace LV::Client {
|
namespace LV::Client {
|
||||||
|
|
||||||
using VoxelId_t = uint16_t;
|
|
||||||
|
|
||||||
struct VoxelCube {
|
struct VoxelCube {
|
||||||
|
DefVoxelId_c VoxelId;
|
||||||
Pos::Local256 Left, Right;
|
Pos::Local256 Left, Right;
|
||||||
VoxelId_t Material;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using NodeId_t = uint16_t;
|
|
||||||
|
|
||||||
struct Node {
|
struct Node {
|
||||||
NodeId_t NodeId;
|
DefNodeId_c NodeId;
|
||||||
uint8_t Rotate : 6;
|
uint8_t Rotate : 6;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -34,15 +30,11 @@ struct Chunk {
|
|||||||
LightPrism Lights[16][16];
|
LightPrism Lights[16][16];
|
||||||
};
|
};
|
||||||
|
|
||||||
using WorldId_t = uint8_t;
|
|
||||||
using PortalId_t = uint16_t;
|
|
||||||
using EntityId_t = uint16_t;
|
|
||||||
|
|
||||||
class Entity {
|
class Entity {
|
||||||
public:
|
public:
|
||||||
// PosQuat
|
// PosQuat
|
||||||
WorldId_t WorldId;
|
DefWorldId_c WorldId;
|
||||||
PortalId_t LastUsedPortal;
|
DefPortalId_c LastUsedPortal;
|
||||||
Pos::Object Pos;
|
Pos::Object Pos;
|
||||||
glm::quat Quat;
|
glm::quat Quat;
|
||||||
static constexpr uint16_t HP_BS = 4096, HP_BS_Bit = 12;
|
static constexpr uint16_t HP_BS = 4096, HP_BS_Bit = 12;
|
||||||
@@ -54,51 +46,24 @@ public:
|
|||||||
// states
|
// states
|
||||||
};
|
};
|
||||||
|
|
||||||
using TextureId_t = uint16_t;
|
|
||||||
|
|
||||||
struct TextureInfo {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
using ModelId_t = uint16_t;
|
|
||||||
|
|
||||||
struct ModelInfo {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Интерфейс рендера текущего подключения к серверу */
|
/* Интерфейс рендера текущего подключения к серверу */
|
||||||
class IRenderSession {
|
class IRenderSession {
|
||||||
public:
|
public:
|
||||||
|
virtual void onDefTexture(TextureId_c id, std::vector<std::byte> &&info) = 0;
|
||||||
|
virtual void onDefTextureLost(const std::vector<TextureId_c> &&lost) = 0;
|
||||||
|
virtual void onDefModel(ModelId_c id, std::vector<std::byte> &&info) = 0;
|
||||||
|
virtual void onDefModelLost(const std::vector<ModelId_c> &&lost) = 0;
|
||||||
|
|
||||||
|
virtual void onDefWorldUpdates(const std::vector<DefWorldId_c> &updates) = 0;
|
||||||
|
virtual void onDefVoxelUpdates(const std::vector<DefVoxelId_c> &updates) = 0;
|
||||||
|
virtual void onDefNodeUpdates(const std::vector<DefNodeId_c> &updates) = 0;
|
||||||
|
virtual void onDefPortalUpdates(const std::vector<DefPortalId_c> &updates) = 0;
|
||||||
|
virtual void onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) = 0;
|
||||||
|
|
||||||
// Сообщаем об изменившихся чанках
|
// Сообщаем об изменившихся чанках
|
||||||
virtual void onChunksChange(WorldId_t worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove);
|
virtual void onChunksChange(WorldId_c worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) = 0;
|
||||||
// Подключаем камеру к сущности
|
// Установить позицию для камеры
|
||||||
virtual void attachCameraToEntity(EntityId_t id);
|
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) = 0;
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
// Мир уже есть в глобальном списке
|
|
||||||
virtual void onWorldAdd(WorldId_t id);
|
|
||||||
// Мира уже нет в списке
|
|
||||||
virtual void onWorldRemove(WorldId_t id);
|
|
||||||
// Изменение состояния мира
|
|
||||||
virtual void onWorldChange(WorldId_t id);
|
|
||||||
|
|
||||||
// Сущности уже есть в глобальном списке
|
|
||||||
virtual void onEntitysAdd(const std::vector<EntityId_t> &list);
|
|
||||||
//
|
|
||||||
virtual void onEntitysRemove(const std::vector<EntityId_t> &list);
|
|
||||||
//
|
|
||||||
virtual void onEntitysPosQuatChanges(const std::vector<EntityId_t> &list);
|
|
||||||
//
|
|
||||||
virtual void onEntitysStateChanges(const std::vector<EntityId_t> &list);
|
|
||||||
|
|
||||||
virtual TextureId_t allocateTexture();
|
|
||||||
virtual void freeTexture(TextureId_t id);
|
|
||||||
virtual void setTexture(TextureId_t id, TextureInfo info);
|
|
||||||
|
|
||||||
virtual ModelId_t allocateModel();
|
|
||||||
virtual void freeModel(ModelId_t id);
|
|
||||||
virtual void setModel(ModelId_t id, ModelInfo info);
|
|
||||||
|
|
||||||
virtual ~IRenderSession();
|
virtual ~IRenderSession();
|
||||||
};
|
};
|
||||||
@@ -110,13 +75,25 @@ struct Region {
|
|||||||
|
|
||||||
|
|
||||||
struct World {
|
struct World {
|
||||||
std::vector<EntityId_t> Entitys;
|
std::vector<EntityId_c> Entitys;
|
||||||
std::unordered_map<Pos::GlobalRegion::Key, Region> Regions;
|
std::unordered_map<Pos::GlobalRegion::Key, Region> Regions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ChunksIterator {
|
struct DefWorldInfo {
|
||||||
public:
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DefPortalInfo {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DefEntityInfo {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WorldInfo {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VoxelInfo {
|
struct VoxelInfo {
|
||||||
@@ -127,13 +104,28 @@ struct NodeInfo {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PortalInfo {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EntityInfo {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/* Интерфейс обработчика сессии с сервером */
|
/* Интерфейс обработчика сессии с сервером */
|
||||||
class IServerSession {
|
class IServerSession {
|
||||||
public:
|
public:
|
||||||
std::unordered_map<EntityId_t, Entity> Entitys;
|
struct {
|
||||||
std::unordered_map<WorldId_t, World> Worlds;
|
std::unordered_map<DefWorldId_c, DefWorldInfo> DefWorlds;
|
||||||
std::unordered_map<VoxelId_t, VoxelInfo> VoxelRegistry;
|
std::unordered_map<DefVoxelId_c, VoxelInfo> DefVoxels;
|
||||||
std::unordered_map<NodeId_t, NodeInfo> NodeRegistry;
|
std::unordered_map<DefNodeId_c, NodeInfo> DefNodes;
|
||||||
|
std::unordered_map<DefPortalId_c, DefPortalInfo> DefPortals;
|
||||||
|
std::unordered_map<DefEntityId_c, DefEntityInfo> DefEntityes;
|
||||||
|
|
||||||
|
std::unordered_map<WorldId_c, WorldInfo> Worlds;
|
||||||
|
std::unordered_map<PortalId_c, PortalInfo> Portals;
|
||||||
|
std::unordered_map<EntityId_c, EntityInfo> Entityes;
|
||||||
|
} Registry;
|
||||||
|
|
||||||
virtual ~IServerSession();
|
virtual ~IServerSession();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,24 @@
|
|||||||
#include "ServerSession.hpp"
|
#include "ServerSession.hpp"
|
||||||
|
#include "Client/Abstract.hpp"
|
||||||
#include "Common/Net.hpp"
|
#include "Common/Net.hpp"
|
||||||
#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>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <Common/Packets.hpp>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <glm/ext.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace LV::Client {
|
namespace LV::Client {
|
||||||
|
|
||||||
using namespace TOS;
|
using namespace TOS;
|
||||||
|
|
||||||
ServerSession::~ServerSession() = default;
|
ServerSession::~ServerSession() {
|
||||||
|
WorkDeadline.cancel();
|
||||||
|
UseLock.wait_no_use();
|
||||||
|
}
|
||||||
|
|
||||||
coro<> ServerSession::asyncAuthorizeWithServer(tcp::socket &socket, const std::string username, const std::string token, int a_ar_r, std::function<void(const std::string&)> onProgress) {
|
coro<> ServerSession::asyncAuthorizeWithServer(tcp::socket &socket, const std::string username, const std::string token, int a_ar_r, std::function<void(const std::string&)> onProgress) {
|
||||||
assert(a_ar_r >= 0 && a_ar_r <= 2);
|
assert(a_ar_r >= 0 && a_ar_r <= 2);
|
||||||
@@ -109,4 +116,270 @@ coro<std::unique_ptr<Net::AsyncSocket>> ServerSession::asyncInitGameProtocol(asi
|
|||||||
co_return std::make_unique<Net::AsyncSocket>(ioc, std::move(socket));
|
co_return std::make_unique<Net::AsyncSocket>(ioc, std::move(socket));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ServerSession::shutdown(EnumDisconnect type) {
|
||||||
|
IsGoingShutdown = true;
|
||||||
|
Net::Packet packet;
|
||||||
|
packet << (uint8_t) ToServer::L1::System
|
||||||
|
<< (uint8_t) ToServer::L2System::Disconnect
|
||||||
|
<< (uint8_t) type;
|
||||||
|
|
||||||
|
Socket->pushPacket(std::move(packet));
|
||||||
|
|
||||||
|
std::string reason;
|
||||||
|
if(type == EnumDisconnect::ByInterface)
|
||||||
|
reason = "по запросу интерфейса";
|
||||||
|
else if(type == EnumDisconnect::CriticalError)
|
||||||
|
reason = "на сервере произошла критическая ошибка";
|
||||||
|
else if(type == EnumDisconnect::ProtocolError)
|
||||||
|
reason = "ошибка протокола (клиент)";
|
||||||
|
|
||||||
|
LOG.info() << "Отключение от сервера: " << reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSession::onResize(uint32_t width, uint32_t height) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSession::onChangeFocusState(bool isFocused) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSession::onCursorPosChange(int32_t width, int32_t height) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSession::onCursorMove(float xMove, float yMove) {
|
||||||
|
glm::vec3 front = Camera.Quat*glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSession::onFrameRendering() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSession::onFrameRenderEnd() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSession::onCursorBtn(ISurfaceEventListener::EnumCursorBtn btn, bool state) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSession::onKeyboardBtn(int btn, int state) {
|
||||||
|
if(btn == GLFW_KEY_TAB && !state) {
|
||||||
|
CursorMode = CursorMode == EnumCursorMoveMode::Default ? EnumCursorMoveMode::MoveAndHidden : EnumCursorMoveMode::Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSession::onJoystick() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
coro<> ServerSession::run() {
|
||||||
|
auto useLock = UseLock.lock();
|
||||||
|
|
||||||
|
try {
|
||||||
|
while(!IsGoingShutdown && IsConnected) {
|
||||||
|
co_await readPacket(*Socket);
|
||||||
|
}
|
||||||
|
} 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("ServerSession").warn() << exc.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
IsConnected = false;
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerSession::protocolError() {
|
||||||
|
shutdown(EnumDisconnect::ProtocolError);
|
||||||
|
}
|
||||||
|
|
||||||
|
coro<> ServerSession::readPacket(Net::AsyncSocket &sock) {
|
||||||
|
uint8_t first = co_await sock.read<uint8_t>();
|
||||||
|
|
||||||
|
switch((ToClient::L1) first) {
|
||||||
|
case ToClient::L1::System: co_await rP_System(sock); co_return;
|
||||||
|
case ToClient::L1::Resource: co_await rP_Resource(sock); co_return;
|
||||||
|
case ToClient::L1::Definition: co_await rP_Definition(sock); co_return;
|
||||||
|
case ToClient::L1::Content: co_await rP_Content(sock); co_return;
|
||||||
|
default:
|
||||||
|
protocolError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coro<> ServerSession::rP_System(Net::AsyncSocket &sock) {
|
||||||
|
uint8_t second = co_await sock.read<uint8_t>();
|
||||||
|
|
||||||
|
switch((ToClient::L2System) second) {
|
||||||
|
case ToClient::L2System::Init:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2System::Disconnect:
|
||||||
|
{
|
||||||
|
EnumDisconnect type = (EnumDisconnect) co_await sock.read<uint8_t>();
|
||||||
|
std::string reason = co_await sock.read<std::string>();
|
||||||
|
|
||||||
|
if(type == EnumDisconnect::ByInterface)
|
||||||
|
reason = "по запросу интерфейса " + reason;
|
||||||
|
else if(type == EnumDisconnect::CriticalError)
|
||||||
|
reason = "на сервере произошла критическая ошибка " + reason;
|
||||||
|
else if(type == EnumDisconnect::ProtocolError)
|
||||||
|
reason = "ошибка протокола (сервер) " + reason;
|
||||||
|
|
||||||
|
LOG.info() << "Отключение от сервера: " << reason;
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
case ToClient::L2System::LinkCameraToEntity:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2System::UnlinkCamera:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
default:
|
||||||
|
protocolError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::InitResSend:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Resource::ChunkSend:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Resource::SendCanceled:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
default:
|
||||||
|
protocolError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coro<> ServerSession::rP_Definition(Net::AsyncSocket &sock) {
|
||||||
|
uint8_t second = co_await sock.read<uint8_t>();
|
||||||
|
|
||||||
|
switch((ToClient::L2Definition) second) {
|
||||||
|
case ToClient::L2Definition::World:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Definition::FreeWorld:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Definition::Voxel:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Definition::FreeVoxel:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Definition::Node:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Definition::FreeNode:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Definition::Portal:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Definition::FreePortal:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Definition::Entity:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Definition::FreeEntity:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
default:
|
||||||
|
protocolError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
|
||||||
|
uint8_t second = co_await sock.read<uint8_t>();
|
||||||
|
|
||||||
|
switch((ToClient::L2Content) second) {
|
||||||
|
case ToClient::L2Content::World:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Content::RemoveWorld:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Content::Portal:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Content::RemovePortal:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Content::Entity:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Content::RemoveEntity:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Content::ChunkVoxels:
|
||||||
|
{
|
||||||
|
WorldId_c wcId = co_await sock.read<uint8_t>();
|
||||||
|
Pos::GlobalChunk::Key posKey = co_await sock.read<Pos::GlobalChunk::Key>();
|
||||||
|
Pos::GlobalChunk pos = *(Pos::GlobalChunk*) &posKey;
|
||||||
|
|
||||||
|
std::vector<VoxelCube> cubes(co_await sock.read<uint16_t>());
|
||||||
|
|
||||||
|
for(size_t iter = 0; iter < cubes.size(); iter++) {
|
||||||
|
VoxelCube &cube = cubes[iter];
|
||||||
|
cube.VoxelId = co_await sock.read<uint16_t>();
|
||||||
|
cube.Left.X = co_await sock.read<uint8_t>();
|
||||||
|
cube.Left.Y = co_await sock.read<uint8_t>();
|
||||||
|
cube.Left.Z = co_await sock.read<uint8_t>();
|
||||||
|
cube.Right.X = co_await sock.read<uint8_t>();
|
||||||
|
cube.Right.Y = co_await sock.read<uint8_t>();
|
||||||
|
cube.Right.Z = co_await sock.read<uint8_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.info() << "Приняты воксели чанка " << int(wcId) << " / " << pos.X << ":" << pos.Y << ":" << pos.Z << " Вокселей " << cubes.size();
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ToClient::L2Content::ChunkNodes:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Content::ChunkLightPrism:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
case ToClient::L2Content::RemoveChunk:
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
default:
|
||||||
|
protocolError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Abstract.hpp"
|
#include "Abstract.hpp"
|
||||||
|
#include "Common/Async.hpp"
|
||||||
|
#include "Common/Lockable.hpp"
|
||||||
#include "Common/Net.hpp"
|
#include "Common/Net.hpp"
|
||||||
|
#include "Common/Packets.hpp"
|
||||||
#include <TOSLib.hpp>
|
#include <TOSLib.hpp>
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
|
|
||||||
@@ -9,16 +12,23 @@
|
|||||||
namespace LV::Client {
|
namespace LV::Client {
|
||||||
|
|
||||||
class ServerSession : public AsyncObject, public IServerSession, public ISurfaceEventListener {
|
class ServerSession : public AsyncObject, public IServerSession, public ISurfaceEventListener {
|
||||||
std::unique_ptr<Net::AsyncSocket> _Socket;
|
std::unique_ptr<Net::AsyncSocket> Socket;
|
||||||
Net::AsyncSocket &Socket;
|
|
||||||
IRenderSession *RS = nullptr;
|
IRenderSession *RS = nullptr;
|
||||||
|
DestroyLock UseLock;
|
||||||
|
bool IsConnected = true, IsGoingShutdown = false;
|
||||||
|
|
||||||
|
TOS::Logger LOG = "ServerSession";
|
||||||
|
|
||||||
|
struct {
|
||||||
|
glm::quat Quat;
|
||||||
|
} Camera;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Нужен сокет, на котором только что был согласован игровой протокол (asyncInitGameProtocol)
|
// Нужен сокет, на котором только что был согласован игровой протокол (asyncInitGameProtocol)
|
||||||
ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSocket> &&socket, IRenderSession *rs = nullptr)
|
ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSocket> &&socket, IRenderSession *rs = nullptr)
|
||||||
: AsyncObject(ioc), _Socket(std::move(socket)), Socket(*socket), RS(rs)
|
: AsyncObject(ioc), Socket(std::move(socket)), RS(rs)
|
||||||
{
|
{
|
||||||
assert(socket.get());
|
assert(Socket.get());
|
||||||
co_spawn(run());
|
co_spawn(run());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,23 +39,38 @@ public:
|
|||||||
// Начать игровой протокол в авторизированном сокете
|
// Начать игровой протокол в авторизированном сокете
|
||||||
static coro<std::unique_ptr<Net::AsyncSocket>> asyncInitGameProtocol(asio::io_context &ioc, tcp::socket &&socket, std::function<void(const std::string&)> onProgress = nullptr);
|
static coro<std::unique_ptr<Net::AsyncSocket>> asyncInitGameProtocol(asio::io_context &ioc, tcp::socket &&socket, std::function<void(const std::string&)> onProgress = nullptr);
|
||||||
|
|
||||||
|
void shutdown(EnumDisconnect type);
|
||||||
|
|
||||||
|
bool isConnected() {
|
||||||
|
return IsConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void waitShutdown() {
|
||||||
|
UseLock.wait_no_use();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ISurfaceEventListener
|
// ISurfaceEventListener
|
||||||
|
|
||||||
// virtual void onResize(uint32_t width, uint32_t height) override;
|
virtual void onResize(uint32_t width, uint32_t height) override;
|
||||||
// virtual void onChangeFocusState(bool isFocused) override;
|
virtual void onChangeFocusState(bool isFocused) override;
|
||||||
// virtual void onCursorPosChange(int32_t width, int32_t height) override;
|
virtual void onCursorPosChange(int32_t width, int32_t height) override;
|
||||||
// virtual void onCursorMove(float xMove, float yMove) override;
|
virtual void onCursorMove(float xMove, float yMove) override;
|
||||||
// virtual void onFrameRendering() override;
|
virtual void onFrameRendering() override;
|
||||||
// virtual void onFrameRenderEnd() override;
|
virtual void onFrameRenderEnd() override;
|
||||||
|
|
||||||
// virtual void onCursorBtn(EnumCursorBtn btn, bool state) override;
|
virtual void onCursorBtn(EnumCursorBtn btn, bool state) override;
|
||||||
// virtual void onKeyboardBtn(int btn, int state) override;
|
virtual void onKeyboardBtn(int btn, int state) override;
|
||||||
// virtual void onJoystick() override;
|
virtual void onJoystick() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
coro<> run();
|
coro<> run();
|
||||||
|
void protocolError();
|
||||||
|
coro<> readPacket(Net::AsyncSocket &sock);
|
||||||
|
coro<> rP_System(Net::AsyncSocket &sock);
|
||||||
|
coro<> rP_Resource(Net::AsyncSocket &sock);
|
||||||
|
coro<> rP_Definition(Net::AsyncSocket &sock);
|
||||||
|
coro<> rP_Content(Net::AsyncSocket &sock);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include "Vulkan.hpp"
|
#include "Vulkan.hpp"
|
||||||
|
#include "Client/ServerSession.hpp"
|
||||||
|
#include "Common/Async.hpp"
|
||||||
|
#include "Common/Net.hpp"
|
||||||
|
#include "assets.hpp"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
#ifdef HAS_IMGUI
|
#ifdef HAS_IMGUI
|
||||||
@@ -20,10 +25,22 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <png++/png.hpp>
|
#include <png++/png.hpp>
|
||||||
|
#include "VulkanRenderSession.hpp"
|
||||||
|
#include <Server/GameServer.hpp>
|
||||||
|
|
||||||
extern void LoadSymbolsVulkan(TOS::DynamicLibrary &library);
|
extern void LoadSymbolsVulkan(TOS::DynamicLibrary &library);
|
||||||
|
|
||||||
namespace TOS::VK {
|
namespace LV::Client::VK {
|
||||||
|
|
||||||
|
struct ServerObj {
|
||||||
|
Server::GameServer GS;
|
||||||
|
Net::Server LS;
|
||||||
|
|
||||||
|
ServerObj(asio::io_context &ioc)
|
||||||
|
: GS(ioc, ""), LS(ioc, [&](tcp::socket sock) -> coro<> { co_await GS.pushSocketConnect(std::move(sock)); }, 7890)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ByteBuffer loadPNG(std::ifstream &&read, int &width, int &height, bool &hasAlpha, bool flipOver)
|
ByteBuffer loadPNG(std::ifstream &&read, int &width, int &height, bool &hasAlpha, bool flipOver)
|
||||||
{
|
{
|
||||||
@@ -55,35 +72,38 @@ ByteBuffer loadPNG(std::istream &&read, int &width, int &height, bool &hasAlpha,
|
|||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
IWindowCallbackListener::~IWindowCallbackListener() = default;
|
Vulkan::Vulkan(asio::io_context &ioc)
|
||||||
|
: AsyncObject(ioc), GuardLock(ioc.get_executor())
|
||||||
void IWindowCallbackListener::onFrameBufferResize(uint32_t width, uint32_t height) {}
|
|
||||||
void IWindowCallbackListener::onScale(float x, float y) {}
|
|
||||||
void IWindowCallbackListener::onMouseClick(int btn, int state, int mods) {}
|
|
||||||
void IWindowCallbackListener::onMousePos(double x, double y) {}
|
|
||||||
void IWindowCallbackListener::onKeyboardClick(int key, int scancode, int action, int mods) {}
|
|
||||||
void IWindowCallbackListener::onFocus(int focused) {}
|
|
||||||
|
|
||||||
Vulkan::Vulkan(uint16_t width, uint16_t height)
|
|
||||||
{
|
{
|
||||||
if(width)
|
Screen.Width = 1920/2;
|
||||||
Screen.Width = width;
|
Screen.Height = 1080/2;
|
||||||
if(height)
|
|
||||||
Screen.Height = height;
|
|
||||||
getSettingsNext() = getBestSettings();
|
getSettingsNext() = getBestSettings();
|
||||||
|
reInit();
|
||||||
|
|
||||||
|
addImGUIFont(LV::getResource("default.ttf")->makeView());
|
||||||
|
Game.ImGuiInterfaces.push_back(&Vulkan::gui_MainMenu);
|
||||||
|
|
||||||
|
Game.MainThread = std::thread([&]() {
|
||||||
|
auto useLock = Game.UseLock.lock();
|
||||||
|
run();
|
||||||
|
GuardLock.reset();
|
||||||
|
|
||||||
|
if(Game.Session) {
|
||||||
|
Game.Session->shutdown(EnumDisconnect::ByInterface);
|
||||||
|
Game.Session = nullptr;
|
||||||
|
Game.RSession = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Game.Server) {
|
||||||
|
Game.Server->GS.shutdown("Завершение работы из-за остановки клиента");
|
||||||
|
Game.Server = nullptr;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Vulkan::~Vulkan()
|
Vulkan::~Vulkan()
|
||||||
{
|
{
|
||||||
WindowEventListener = nullptr;
|
Game.UseLock.wait_no_use();
|
||||||
for(size_t watchdog = 0; watchdog < 100 && isAlive(); watchdog++)
|
|
||||||
{
|
|
||||||
glfwSetWindowShouldClose(Graphics.Window, 1);
|
|
||||||
Time::sleep3(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isAlive())
|
|
||||||
LOGGER.error() << "WatchDog: Не дождались завершения потока рендера в течении 10 секунд";
|
|
||||||
|
|
||||||
for(std::shared_ptr<IVulkanDependent> dependent : ROS_Dependents)
|
for(std::shared_ptr<IVulkanDependent> dependent : ROS_Dependents)
|
||||||
dependent->free(this);
|
dependent->free(this);
|
||||||
@@ -96,6 +116,8 @@ Vulkan::~Vulkan()
|
|||||||
glfwDestroyWindow(Graphics.Window);
|
glfwDestroyWindow(Graphics.Window);
|
||||||
Graphics.Window = nullptr;
|
Graphics.Window = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Game.MainThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan::run()
|
void Vulkan::run()
|
||||||
@@ -122,8 +144,29 @@ void Vulkan::run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CallBeforeDraw)
|
if(glfwWindowShouldClose(Graphics.Window)) {
|
||||||
CallBeforeDraw(this);
|
NeedShutdown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Game.Session) {
|
||||||
|
ServerSession &sobj = *Game.Session;
|
||||||
|
|
||||||
|
// Спрятать или показать курсор
|
||||||
|
{
|
||||||
|
int mode = glfwGetInputMode(Graphics.Window, GLFW_CURSOR);
|
||||||
|
if(mode == GLFW_CURSOR_HIDDEN && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::MoveAndHidden)
|
||||||
|
glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
|
else if(mode == GLFW_CURSOR_NORMAL && sobj.CursorMode != ISurfaceEventListener::EnumCursorMoveMode::Default) {
|
||||||
|
glfwSetInputMode(Graphics.Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||||
|
glfwSetCursorPos(Graphics.Window, Screen.Width/2., Screen.Height/2.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(CallBeforeDraw)
|
||||||
|
// CallBeforeDraw(this);
|
||||||
|
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
@@ -208,8 +251,8 @@ void Vulkan::run()
|
|||||||
vkCmdSetScissor(Graphics.CommandBufferRender, 0, 1, &scissor);
|
vkCmdSetScissor(Graphics.CommandBufferRender, 0, 1, &scissor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(CallOnDraw)
|
// if(CallOnDraw)
|
||||||
CallOnDraw(this, 0, Graphics.CommandBufferRender);
|
// CallOnDraw(this, 0, Graphics.CommandBufferRender);
|
||||||
|
|
||||||
vkCmdEndRenderPass(Graphics.CommandBufferRender);
|
vkCmdEndRenderPass(Graphics.CommandBufferRender);
|
||||||
|
|
||||||
@@ -254,7 +297,7 @@ void Vulkan::run()
|
|||||||
{
|
{
|
||||||
const VkClearValue clear_values[2] =
|
const VkClearValue clear_values[2] =
|
||||||
{
|
{
|
||||||
[0] = { .color = { .float32 = { 0.2f, 0.2f, 0.4f, 1.2f }}},
|
[0] = { .color = { .float32 = { 0.1f, 0.1f, 0.1f, 1.0f }}},
|
||||||
[1] = { .depthStencil = { 1, 0 } },
|
[1] = { .depthStencil = { 1, 0 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -279,12 +322,13 @@ void Vulkan::run()
|
|||||||
ImGui_ImplVulkan_NewFrame();
|
ImGui_ImplVulkan_NewFrame();
|
||||||
ImGui_ImplGlfw_NewFrame();
|
ImGui_ImplGlfw_NewFrame();
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
#endif
|
|
||||||
|
|
||||||
if(CallOnDraw)
|
ImGui::SetNextWindowPos({0, 0});
|
||||||
CallOnDraw(this, 1, Graphics.CommandBufferRender);
|
ImGui::SetNextWindowSize({(float) Screen.Width, (float) Screen.Height});
|
||||||
|
|
||||||
|
assert(Game.ImGuiInterfaces.size());
|
||||||
|
(this->*Game.ImGuiInterfaces.back())();
|
||||||
|
|
||||||
#ifdef HAS_IMGUI
|
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), Graphics.CommandBufferRender);
|
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), Graphics.CommandBufferRender);
|
||||||
#endif
|
#endif
|
||||||
@@ -819,45 +863,52 @@ void Vulkan::glfwCallbackOnResize(GLFWwindow *window, int width, int height)
|
|||||||
handler->freeSwapchains();
|
handler->freeSwapchains();
|
||||||
handler->buildSwapchains();
|
handler->buildSwapchains();
|
||||||
|
|
||||||
if(handler->WindowEventListener)
|
if(handler->Game.Session)
|
||||||
handler->WindowEventListener->onFrameBufferResize(width, height);
|
handler->Game.Session->onResize(width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan::glfwCallbackOnMouseButton(GLFWwindow* window, int button, int action, int mods)
|
void Vulkan::glfwCallbackOnMouseButton(GLFWwindow* window, int button, int action, int mods)
|
||||||
{
|
{
|
||||||
Vulkan *handler = (Vulkan*) glfwGetWindowUserPointer(window);
|
Vulkan *handler = (Vulkan*) glfwGetWindowUserPointer(window);
|
||||||
if(handler && handler->WindowEventListener)
|
|
||||||
handler->WindowEventListener->onMouseClick(button, action, mods);
|
if(handler->Game.Session)
|
||||||
|
handler->Game.Session->onCursorBtn((ISurfaceEventListener::EnumCursorBtn) button, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan::glfwCallbackOnCursorPos(GLFWwindow* window, double xpos, double ypos)
|
void Vulkan::glfwCallbackOnCursorPos(GLFWwindow* window, double xpos, double ypos)
|
||||||
{
|
{
|
||||||
Vulkan *handler = (Vulkan*) glfwGetWindowUserPointer(window);
|
Vulkan *handler = (Vulkan*) glfwGetWindowUserPointer(window);
|
||||||
if(handler && handler->WindowEventListener)
|
|
||||||
handler->WindowEventListener->onMousePos(xpos, ypos);
|
if(handler->Game.Session) {
|
||||||
|
ServerSession &sobj = *handler->Game.Session;
|
||||||
|
if(sobj.CursorMode == ISurfaceEventListener::EnumCursorMoveMode::Default) {
|
||||||
|
sobj.onCursorPosChange((int32_t) xpos, (int32_t) ypos);
|
||||||
|
} else {
|
||||||
|
glfwSetCursorPos(handler->Graphics.Window, handler->Screen.Width/2., handler->Screen.Height/2.);
|
||||||
|
sobj.onCursorMove(xpos-handler->Screen.Width/2., handler->Screen.Height/2.-ypos);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan::glfwCallbackOnScale(GLFWwindow* window, float xscale, float yscale)
|
void Vulkan::glfwCallbackOnScale(GLFWwindow* window, float xscale, float yscale)
|
||||||
{
|
{
|
||||||
Vulkan *handler = (Vulkan*) glfwGetWindowUserPointer(window);
|
Vulkan *handler = (Vulkan*) glfwGetWindowUserPointer(window);
|
||||||
if(handler && handler->WindowEventListener)
|
|
||||||
handler->WindowEventListener->onScale(xscale, yscale);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan::glfwCallbackOnKey(GLFWwindow* window, int key, int scancode, int action, int mods)
|
void Vulkan::glfwCallbackOnKey(GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||||
{
|
{
|
||||||
Vulkan *handler = (Vulkan*) glfwGetWindowUserPointer(window);
|
Vulkan *handler = (Vulkan*) glfwGetWindowUserPointer(window);
|
||||||
if(handler && handler->WindowEventListener)
|
if(handler->Game.Session)
|
||||||
handler->WindowEventListener->onKeyboardClick(key, scancode, action, mods);
|
handler->Game.Session->onKeyboardBtn(key, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan::glfwCallbackOnFocus(GLFWwindow* window, int focused)
|
void Vulkan::glfwCallbackOnFocus(GLFWwindow* window, int focused)
|
||||||
{
|
{
|
||||||
Vulkan *handler = (Vulkan*) glfwGetWindowUserPointer(window);
|
Vulkan *handler = (Vulkan*) glfwGetWindowUserPointer(window);
|
||||||
if(handler && handler->WindowEventListener)
|
if(handler->Game.Session)
|
||||||
handler->WindowEventListener->onFocus(focused);
|
handler->Game.Session->onChangeFocusState(focused);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan::checkLibrary()
|
void Vulkan::checkLibrary()
|
||||||
@@ -1066,7 +1117,7 @@ void Vulkan::checkLibrary()
|
|||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
//glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
//glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||||
|
|
||||||
Graphics.Window = glfwCreateWindow(Screen.Width, Screen.Height, "Duckout", nullptr, nullptr);
|
Graphics.Window = glfwCreateWindow(Screen.Width, Screen.Height, "LuaVox", nullptr, nullptr);
|
||||||
if (!Graphics.Window)
|
if (!Graphics.Window)
|
||||||
{
|
{
|
||||||
const char *error_msg;
|
const char *error_msg;
|
||||||
@@ -1716,12 +1767,10 @@ void Vulkan::deInitVulkan()
|
|||||||
if(Graphics.ImGuiDescPool)
|
if(Graphics.ImGuiDescPool)
|
||||||
vkDestroyDescriptorPool(Graphics.Device, Graphics.ImGuiDescPool, nullptr);
|
vkDestroyDescriptorPool(Graphics.Device, Graphics.ImGuiDescPool, nullptr);
|
||||||
|
|
||||||
|
|
||||||
// Удаляем SwapChain
|
// Удаляем SwapChain
|
||||||
if(Graphics.Swapchain)
|
if(Graphics.Swapchain)
|
||||||
vkDestroySwapchainKHR(Graphics.Device, Graphics.Swapchain, nullptr);
|
vkDestroySwapchainKHR(Graphics.Device, Graphics.Swapchain, nullptr);
|
||||||
|
|
||||||
|
|
||||||
// Очистка буферов команд
|
// Очистка буферов команд
|
||||||
if(Graphics.CommandBufferData)
|
if(Graphics.CommandBufferData)
|
||||||
vkFreeCommandBuffers(Graphics.Device, Graphics.Pool, 1, &Graphics.CommandBufferData);
|
vkFreeCommandBuffers(Graphics.Device, Graphics.Pool, 1, &Graphics.CommandBufferData);
|
||||||
@@ -1729,7 +1778,6 @@ void Vulkan::deInitVulkan()
|
|||||||
if(Graphics.CommandBufferRender)
|
if(Graphics.CommandBufferRender)
|
||||||
vkFreeCommandBuffers(Graphics.Device, Graphics.Pool, 1, &Graphics.CommandBufferRender);
|
vkFreeCommandBuffers(Graphics.Device, Graphics.Pool, 1, &Graphics.CommandBufferRender);
|
||||||
|
|
||||||
|
|
||||||
// Освобождение пула команд
|
// Освобождение пула команд
|
||||||
if(Graphics.Pool)
|
if(Graphics.Pool)
|
||||||
vkDestroyCommandPool(Graphics.Device, Graphics.Pool, nullptr);
|
vkDestroyCommandPool(Graphics.Device, Graphics.Pool, nullptr);
|
||||||
@@ -1739,8 +1787,8 @@ void Vulkan::deInitVulkan()
|
|||||||
vkDestroyRenderPass(Graphics.Device, Graphics.RenderPass, nullptr);
|
vkDestroyRenderPass(Graphics.Device, Graphics.RenderPass, nullptr);
|
||||||
|
|
||||||
// Освобождение виртуального устройства
|
// Освобождение виртуального устройства
|
||||||
if(Graphics.Device)
|
//if(Graphics.Device)
|
||||||
vkDestroyDevice(Graphics.Device, nullptr);
|
// vkDestroyDevice(Graphics.Device, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Graphics.Surface)
|
if(Graphics.Surface)
|
||||||
@@ -1837,7 +1885,7 @@ Vulkan& Vulkan::operator<<(std::shared_ptr<IVulkanDependent> dependent)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan::addImGUIFont(const ByteBuffer &font) {
|
void Vulkan::addImGUIFont(std::string_view view) {
|
||||||
ImFontConfig fontConfig;
|
ImFontConfig fontConfig;
|
||||||
fontConfig.MergeMode = false;
|
fontConfig.MergeMode = false;
|
||||||
fontConfig.PixelSnapH = true;
|
fontConfig.PixelSnapH = true;
|
||||||
@@ -1845,16 +1893,121 @@ void Vulkan::addImGUIFont(const ByteBuffer &font) {
|
|||||||
fontConfig.OversampleV = 1;
|
fontConfig.OversampleV = 1;
|
||||||
|
|
||||||
auto &io = ImGui::GetIO();
|
auto &io = ImGui::GetIO();
|
||||||
uint8_t *fontPtr = new uint8_t[font.size()];
|
uint8_t *fontPtr = new uint8_t[view.size()];
|
||||||
std::copy(font.begin(), font.end(), fontPtr);
|
std::copy(view.begin(), view.end(), fontPtr);
|
||||||
try{
|
try{
|
||||||
io.Fonts->AddFontFromMemoryTTF(fontPtr, font.size(), 16.0f, &fontConfig, io.Fonts->GetGlyphRangesCyrillic());
|
io.Fonts->AddFontFromMemoryTTF(fontPtr, view.size(), 16.0f, &fontConfig, io.Fonts->GetGlyphRangesCyrillic());
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
delete[] fontPtr;
|
delete[] fontPtr;
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Vulkan::gui_MainMenu() {
|
||||||
|
if(!ImGui::Begin("MainMenu", nullptr, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove))
|
||||||
|
return;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char Address[256] = "localhost", Username[256], Password[256];
|
||||||
|
bool Cancel = false, InProgress = false;
|
||||||
|
std::string Progress;
|
||||||
|
|
||||||
|
std::unique_ptr<Net::AsyncSocket> Socket;
|
||||||
|
|
||||||
|
coro<> connect(asio::io_context &ioc) {
|
||||||
|
try {
|
||||||
|
std::string a(Address, strlen(Address));
|
||||||
|
std::string u(Username, strlen(Username));
|
||||||
|
std::string p(Password, strlen(Password));
|
||||||
|
|
||||||
|
tcp::socket sock = co_await Net::asyncConnectTo(a, [&](const std::string &text) {
|
||||||
|
Progress += text;
|
||||||
|
});
|
||||||
|
|
||||||
|
co_await Client::ServerSession::asyncAuthorizeWithServer(sock, u, p, 1, [&](const std::string &text) {
|
||||||
|
Progress += text;
|
||||||
|
});
|
||||||
|
|
||||||
|
Socket = co_await Client::ServerSession::asyncInitGameProtocol(ioc, std::move(sock), [&](const std::string &text) {
|
||||||
|
Progress += text;
|
||||||
|
});
|
||||||
|
} catch(const std::exception &exc) {
|
||||||
|
Progress += "\n-> ";
|
||||||
|
Progress += exc.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
InProgress = false;
|
||||||
|
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
} ConnectionProgress;
|
||||||
|
|
||||||
|
ImGui::InputText("Address", ConnectionProgress.Address, sizeof(ConnectionProgress.Address));
|
||||||
|
ImGui::InputText("Username", ConnectionProgress.Username, sizeof(ConnectionProgress.Username));
|
||||||
|
ImGui::InputText("Password", ConnectionProgress.Password, sizeof(ConnectionProgress.Password), ImGuiInputTextFlags_Password);
|
||||||
|
|
||||||
|
if(!ConnectionProgress.InProgress && !ConnectionProgress.Socket) {
|
||||||
|
if(ImGui::Button("Подключиться")) {
|
||||||
|
ConnectionProgress.InProgress = true;
|
||||||
|
ConnectionProgress.Cancel = false;
|
||||||
|
ConnectionProgress.Progress.clear();
|
||||||
|
co_spawn(ConnectionProgress.connect(IOC));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Game.Server) {
|
||||||
|
if(ImGui::Button("Запустить сервер")) {
|
||||||
|
try {
|
||||||
|
Game.Server = std::make_unique<ServerObj>(IOC);
|
||||||
|
ConnectionProgress.Progress = "Сервер запущен на порту " + std::to_string(Game.Server->LS.getPort());
|
||||||
|
} catch(const std::exception &exc) {
|
||||||
|
ConnectionProgress.Progress = "Не удалось запустить внутренний сервер: " + std::string(exc.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(!Game.Server->GS.isAlive())
|
||||||
|
Game.Server = nullptr;
|
||||||
|
else if(ImGui::Button("Остановить сервер")) {
|
||||||
|
Game.Server->GS.shutdown("Сервер останавливается по запросу интерфейса");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ConnectionProgress.InProgress) {
|
||||||
|
if(ImGui::Button("Отмена"))
|
||||||
|
ConnectionProgress.Cancel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ConnectionProgress.Progress.empty()) {
|
||||||
|
if(ImGui::BeginChild("Прогресс", {0, 0}, ImGuiChildFlags_Borders, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||||
|
ImGui::Text("Прогресс:\n%s", ConnectionProgress.Progress.c_str());
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ConnectionProgress.Socket) {
|
||||||
|
std::unique_ptr<Net::AsyncSocket> sock = std::move(ConnectionProgress.Socket);
|
||||||
|
Game.RSession = std::make_unique<VulkanRenderSession>(this);
|
||||||
|
Game.Session = std::make_unique<ServerSession>(IOC, std::move(sock), Game.RSession.get());
|
||||||
|
Game.RSession->setServerSession(Game.Session.get());
|
||||||
|
Game.ImGuiInterfaces.push_back(&Vulkan::gui_ConnectedToServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vulkan::gui_ConnectedToServer() {
|
||||||
|
if(Game.Session) {
|
||||||
|
if(Game.Session->isConnected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Game.RSession = nullptr;
|
||||||
|
Game.Session = nullptr;
|
||||||
|
Game.ImGuiInterfaces.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
EnumRebuildType IVulkanDependent::needRebuild() { return EnumRebuildType::None; }
|
EnumRebuildType IVulkanDependent::needRebuild() { return EnumRebuildType::None; }
|
||||||
IVulkanDependent::~IVulkanDependent() = default;
|
IVulkanDependent::~IVulkanDependent() = default;
|
||||||
|
|
||||||
@@ -1947,7 +2100,7 @@ Vulkan::vkInstance::~vkInstance()
|
|||||||
if(!Instance)
|
if(!Instance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vkDestroyInstance(Instance, nullptr);
|
//vkDestroyInstance(Instance, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Client/ServerSession.hpp"
|
||||||
|
#include "Common/Async.hpp"
|
||||||
#include <TOSLib.hpp>
|
#include <TOSLib.hpp>
|
||||||
|
#include <boost/asio/executor_work_guard.hpp>
|
||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -26,7 +30,10 @@
|
|||||||
|
|
||||||
#define IMGUI_ENABLE_STB_TEXTEDIT_UNICODE
|
#define IMGUI_ENABLE_STB_TEXTEDIT_UNICODE
|
||||||
|
|
||||||
namespace TOS::VK {
|
namespace LV::Client::VK {
|
||||||
|
|
||||||
|
class VulkanRenderSession;
|
||||||
|
using namespace TOS;
|
||||||
|
|
||||||
ByteBuffer loadPNG(std::ifstream &&file, int &width, int &height, bool &hasAlpha, bool flipOver = true);
|
ByteBuffer loadPNG(std::ifstream &&file, int &width, int &height, bool &hasAlpha, bool flipOver = true);
|
||||||
ByteBuffer loadPNG(std::istream &&file, int &width, int &height, bool &hasAlpha, bool flipOver = true);
|
ByteBuffer loadPNG(std::istream &&file, int &width, int &height, bool &hasAlpha, bool flipOver = true);
|
||||||
@@ -49,21 +56,7 @@ struct Settings {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ServerObj;
|
||||||
class IWindowCallbackListener {
|
|
||||||
public:
|
|
||||||
IWindowCallbackListener() = default;
|
|
||||||
virtual ~IWindowCallbackListener();
|
|
||||||
|
|
||||||
virtual void onFrameBufferResize(uint32_t width, uint32_t height);
|
|
||||||
virtual void onScale(float x, float y);
|
|
||||||
virtual void onMouseClick(int btn, int state, int mods);
|
|
||||||
virtual void onMousePos(double x, double y);
|
|
||||||
virtual void onKeyboardClick(int key, int scancode, int action, int mods);
|
|
||||||
virtual void onFocus(int focused);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class DescriptorLayout;
|
class DescriptorLayout;
|
||||||
class Pipeline;
|
class Pipeline;
|
||||||
class DescriptorPool;
|
class DescriptorPool;
|
||||||
@@ -76,7 +69,7 @@ class Buffer;
|
|||||||
Vulkan.reInit();
|
Vulkan.reInit();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Vulkan {
|
class Vulkan : public AsyncObject {
|
||||||
private:
|
private:
|
||||||
struct vkInstanceLayer {
|
struct vkInstanceLayer {
|
||||||
std::string LayerName = "nullptr", Description = "nullptr";
|
std::string LayerName = "nullptr", Description = "nullptr";
|
||||||
@@ -174,9 +167,8 @@ private:
|
|||||||
VkFramebuffer FrameBuffer = nullptr;
|
VkFramebuffer FrameBuffer = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::function<void(Vulkan*, int subpass, VkCommandBuffer&)> CallOnDraw;
|
|
||||||
std::function<void(Vulkan*)> CallBeforeDraw;
|
|
||||||
bool NeedShutdown = false;
|
bool NeedShutdown = false;
|
||||||
|
asio::executor_work_guard<asio::io_context::executor_type> GuardLock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct {
|
struct {
|
||||||
@@ -243,6 +235,16 @@ public:
|
|||||||
DrawState State = DrawState::Begin;
|
DrawState State = DrawState::Begin;
|
||||||
} Screen;
|
} Screen;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
DestroyLock UseLock;
|
||||||
|
std::thread MainThread;
|
||||||
|
std::unique_ptr<VulkanRenderSession> RSession;
|
||||||
|
std::unique_ptr<ServerSession> Session;
|
||||||
|
|
||||||
|
std::list<void (Vulkan::*)()> ImGuiInterfaces;
|
||||||
|
std::unique_ptr<ServerObj> Server;
|
||||||
|
} Game;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logger LOGGER = "Vulkan";
|
Logger LOGGER = "Vulkan";
|
||||||
Settings
|
Settings
|
||||||
@@ -256,7 +258,6 @@ private:
|
|||||||
std::optional<DynamicLibrary> LibraryVulkan;
|
std::optional<DynamicLibrary> LibraryVulkan;
|
||||||
|
|
||||||
std::queue<std::function<void(Vulkan&)>> VulkanContext;
|
std::queue<std::function<void(Vulkan&)>> VulkanContext;
|
||||||
std::shared_ptr<IWindowCallbackListener> WindowEventListener;
|
|
||||||
|
|
||||||
// Объекты рисовки
|
// Объекты рисовки
|
||||||
std::unordered_set<std::shared_ptr<IVulkanDependent>> ROS_Dependents;
|
std::unordered_set<std::shared_ptr<IVulkanDependent>> ROS_Dependents;
|
||||||
@@ -298,7 +299,7 @@ private:
|
|||||||
void buildSwapchains();
|
void buildSwapchains();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Vulkan(uint16_t width = 0, uint16_t height = 0);
|
Vulkan(asio::io_context &ioc);
|
||||||
~Vulkan();
|
~Vulkan();
|
||||||
|
|
||||||
Vulkan(const Vulkan&) = delete;
|
Vulkan(const Vulkan&) = delete;
|
||||||
@@ -339,12 +340,6 @@ public:
|
|||||||
Settings& getSettingsNext() { return SettingsNext; }
|
Settings& getSettingsNext() { return SettingsNext; }
|
||||||
|
|
||||||
bool isAlive() { return false; }
|
bool isAlive() { return false; }
|
||||||
void start(std::function<void(Vulkan*, int subpass, VkCommandBuffer&)> &&onDraw, std::function<void(Vulkan*)> &&beforeDraw = {})
|
|
||||||
{
|
|
||||||
CallOnDraw = std::move(onDraw);
|
|
||||||
CallBeforeDraw = std::move(beforeDraw);
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Добавить обработчик перед началом рисовки кадра
|
// Добавить обработчик перед началом рисовки кадра
|
||||||
void beforeDraw(std::function<void(Vulkan*)> &&callback) {
|
void beforeDraw(std::function<void(Vulkan*)> &&callback) {
|
||||||
@@ -356,10 +351,11 @@ public:
|
|||||||
return std::this_thread::get_id() == Graphics.ThisThread;
|
return std::this_thread::get_id() == Graphics.ThisThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setWindowEventListener(std::shared_ptr<IWindowCallbackListener> listener) { WindowEventListener = listener; }
|
|
||||||
void shutdown() { NeedShutdown = true; }
|
void shutdown() { NeedShutdown = true; }
|
||||||
|
void addImGUIFont(std::string_view view);
|
||||||
|
|
||||||
void addImGUIFont(const ByteBuffer &font);
|
void gui_MainMenu();
|
||||||
|
void gui_ConnectedToServer();
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EnumRebuildType {
|
enum class EnumRebuildType {
|
||||||
|
|||||||
63
Src/Client/Vulkan/VulkanRenderSession.cpp
Normal file
63
Src/Client/Vulkan/VulkanRenderSession.cpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#include "VulkanRenderSession.hpp"
|
||||||
|
|
||||||
|
namespace LV::Client::VK {
|
||||||
|
|
||||||
|
|
||||||
|
VulkanRenderSession::VulkanRenderSession(VK::Vulkan *vkInst)
|
||||||
|
: VkInst(vkInst),
|
||||||
|
MainAtlas(vkInst)
|
||||||
|
{
|
||||||
|
assert(VkInst);
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanRenderSession::~VulkanRenderSession() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::onDefTexture(TextureId_c id, std::vector<std::byte> &&info) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::onDefTextureLost(const std::vector<TextureId_c> &&lost) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::onDefModel(ModelId_c id, std::vector<std::byte> &&info) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::onDefModelLost(const std::vector<ModelId_c> &&lost) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::onDefWorldUpdates(const std::vector<DefWorldId_c> &updates) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::onDefVoxelUpdates(const std::vector<DefVoxelId_c> &updates) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::onDefNodeUpdates(const std::vector<DefNodeId_c> &updates) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::onDefPortalUpdates(const std::vector<DefPortalId_c> &updates) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::onChunksChange(WorldId_c worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanRenderSession::setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) {
|
||||||
|
WorldId = worldId;
|
||||||
|
Pos = pos;
|
||||||
|
Quat = quat;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
43
Src/Client/Vulkan/VulkanRenderSession.hpp
Normal file
43
Src/Client/Vulkan/VulkanRenderSession.hpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Client/Abstract.hpp"
|
||||||
|
#include <Client/Vulkan/Vulkan.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
namespace LV::Client::VK {
|
||||||
|
|
||||||
|
class VulkanRenderSession : public IRenderSession {
|
||||||
|
VK::Vulkan *VkInst;
|
||||||
|
IServerSession *ServerSession = nullptr;
|
||||||
|
|
||||||
|
WorldId_c WorldId;
|
||||||
|
Pos::Object Pos;
|
||||||
|
glm::quat Quat;
|
||||||
|
|
||||||
|
VK::AtlasImage MainAtlas;
|
||||||
|
std::map<TextureId_c, uint16_t> ServerToAtlas;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VulkanRenderSession(VK::Vulkan *vkInst);
|
||||||
|
virtual ~VulkanRenderSession();
|
||||||
|
|
||||||
|
void setServerSession(IServerSession *serverSession) {
|
||||||
|
ServerSession = serverSession;
|
||||||
|
assert(serverSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void onDefTexture(TextureId_c id, std::vector<std::byte> &&info) override;
|
||||||
|
virtual void onDefTextureLost(const std::vector<TextureId_c> &&lost) override;
|
||||||
|
virtual void onDefModel(ModelId_c id, std::vector<std::byte> &&info) override;
|
||||||
|
virtual void onDefModelLost(const std::vector<ModelId_c> &&lost) override;
|
||||||
|
|
||||||
|
virtual void onDefWorldUpdates(const std::vector<DefWorldId_c> &updates) override;
|
||||||
|
virtual void onDefVoxelUpdates(const std::vector<DefVoxelId_c> &updates) override;
|
||||||
|
virtual void onDefNodeUpdates(const std::vector<DefNodeId_c> &updates) override;
|
||||||
|
virtual void onDefPortalUpdates(const std::vector<DefPortalId_c> &updates) override;
|
||||||
|
virtual void onDefEntityUpdates(const std::vector<DefEntityId_c> &updates) override;
|
||||||
|
|
||||||
|
virtual void onChunksChange(WorldId_c worldId, const std::vector<Pos::GlobalChunk> &changeOrAddList, const std::vector<Pos::GlobalChunk> &remove) override;
|
||||||
|
virtual void setCameraPos(WorldId_c worldId, Pos::Object pos, glm::quat quat) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -32,7 +32,7 @@ struct Local16 {
|
|||||||
|
|
||||||
using Key = uint16_t;
|
using Key = uint16_t;
|
||||||
operator Key() const {
|
operator Key() const {
|
||||||
return Key(X) | (Key(Y) << 4) | (Key(Z) << 8);
|
return Key(uint8_t(X)) | (Key(uint8_t(Y) << 4)) | (Key(uint8_t(Z)) << 8);
|
||||||
};
|
};
|
||||||
|
|
||||||
Local4_u left() const { return Local4_u{uint8_t(uint16_t(X) >> 2), uint8_t(uint16_t(Y) >> 2), uint8_t(uint16_t(Z) >> 2)}; }
|
Local4_u left() const { return Local4_u{uint8_t(uint16_t(X) >> 2), uint8_t(uint16_t(Y) >> 2), uint8_t(uint16_t(Z) >> 2)}; }
|
||||||
@@ -74,18 +74,18 @@ struct GlobalNode {
|
|||||||
|
|
||||||
using Key = uint64_t;
|
using Key = uint64_t;
|
||||||
operator Key() const {
|
operator Key() const {
|
||||||
return Key(X) | (Key(Y) << 20) | (Key(Z) << 40);
|
return Key(uint32_t(X)) | (Key(uint32_t(Y) << 20)) | (Key(uint32_t(Z)) << 40);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto operator<=>(const GlobalNode&) const = default;
|
auto operator<=>(const GlobalNode&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GlobalChunk {
|
struct GlobalChunk {
|
||||||
int16_t X : 16, Y : 16, Z : 16;
|
int16_t X, Y, Z;
|
||||||
|
|
||||||
using Key = uint64_t;
|
using Key = uint64_t;
|
||||||
operator Key() const {
|
operator Key() const {
|
||||||
return Key(X) | (Key(Y) << 16) | (Key(Z) << 32);
|
return Key(uint16_t(X)) | (Key(uint16_t(Y)) << 16) | (Key(uint16_t(Z)) << 32);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto operator<=>(const GlobalChunk&) const = default;
|
auto operator<=>(const GlobalChunk&) const = default;
|
||||||
@@ -96,7 +96,7 @@ struct GlobalRegion {
|
|||||||
|
|
||||||
using Key = uint64_t;
|
using Key = uint64_t;
|
||||||
operator Key() const {
|
operator Key() const {
|
||||||
return Key(X) | (Key(Y) << 12) | (Key(Z) << 24);
|
return Key(uint16_t(X)) | (Key(uint16_t(Y) << 12)) | (Key(uint16_t(Z)) << 24);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto operator<=>(const GlobalRegion&) const = default;
|
auto operator<=>(const GlobalRegion&) const = default;
|
||||||
@@ -118,6 +118,20 @@ struct LightPrism {
|
|||||||
uint8_t R : 2, G : 2, B : 2;
|
uint8_t R : 2, G : 2, B : 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Идентификаторы на стороне клиента
|
||||||
|
using TextureId_c = uint16_t;
|
||||||
|
using SoundId_c = uint16_t;
|
||||||
|
using ModelId_c = uint16_t;
|
||||||
|
|
||||||
|
using DefWorldId_c = uint8_t;
|
||||||
|
using DefVoxelId_c = uint16_t;
|
||||||
|
using DefNodeId_c = uint16_t;
|
||||||
|
using DefPortalId_c = uint8_t;
|
||||||
|
using WorldId_c = uint8_t;
|
||||||
|
using PortalId_c = uint8_t;
|
||||||
|
using DefEntityId_c = uint16_t;
|
||||||
|
using EntityId_c = uint16_t;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
std::atomic_bool flag = false;
|
std::atomic_bool flag = false;
|
||||||
Deadline.async_wait([&](boost::system::error_code errc) { flag.store(true); });
|
Deadline.async_wait([&](boost::system::error_code errc) { flag.store(true); flag.notify_all(); });
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
flag.wait(false);
|
flag.wait(false);
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
std::atomic_bool flag = false;
|
std::atomic_bool flag = false;
|
||||||
Deadline.async_wait([&](boost::system::error_code errc) { flag.store(true); });
|
Deadline.async_wait([&](boost::system::error_code errc) { flag.store(true); flag.notify_all(); });
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
flag.wait(false);
|
flag.wait(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,10 +110,12 @@ public:
|
|||||||
: Lock(lock)
|
: Lock(lock)
|
||||||
{
|
{
|
||||||
lock.UseCount++;
|
lock.UseCount++;
|
||||||
|
lock.UseCount.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
~Guard() {
|
~Guard() {
|
||||||
Lock.UseCount--;
|
Lock.UseCount--;
|
||||||
|
Lock.UseCount.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "Net.hpp"
|
#include "Net.hpp"
|
||||||
#include <TOSLib.hpp>
|
#include <TOSLib.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <boost/asio/socket_base.hpp>
|
||||||
|
|
||||||
namespace LV::Net {
|
namespace LV::Net {
|
||||||
|
|
||||||
@@ -17,15 +18,14 @@ bool Server::isStopped() {
|
|||||||
|
|
||||||
void Server::stop() {
|
void Server::stop() {
|
||||||
NeedClose = true;
|
NeedClose = true;
|
||||||
|
NeedClose.notify_all();
|
||||||
if(Acceptor.is_open())
|
if(Acceptor.is_open())
|
||||||
Acceptor.close();
|
Acceptor.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::wait() {
|
void Server::wait() {
|
||||||
if(!IsAlive)
|
while(bool val = IsAlive)
|
||||||
return;
|
IsAlive.wait(val);
|
||||||
|
|
||||||
Lock.wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
coro<void> Server::async_wait() {
|
coro<void> Server::async_wait() {
|
||||||
@@ -45,6 +45,7 @@ coro<void> Server::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IsAlive.store(false);
|
IsAlive.store(false);
|
||||||
|
IsAlive.notify_all();
|
||||||
Lock.cancel();
|
Lock.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ AsyncSocket::~AsyncSocket() {
|
|||||||
SendPackets.Context->NeedShutdown = true;
|
SendPackets.Context->NeedShutdown = true;
|
||||||
|
|
||||||
SendPackets.SenderGuard.cancel();
|
SendPackets.SenderGuard.cancel();
|
||||||
|
WorkDeadline.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncSocket::pushPackets(std::vector<Packet> *simplePackets, std::vector<SmartPacket> *smartPackets) {
|
void AsyncSocket::pushPackets(std::vector<Packet> *simplePackets, std::vector<SmartPacket> *smartPackets) {
|
||||||
@@ -135,6 +137,10 @@ coro<> AsyncSocket::read(std::byte *data, uint32_t size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AsyncSocket::closeRead() {
|
||||||
|
Socket.shutdown(boost::asio::socket_base::shutdown_receive);
|
||||||
|
}
|
||||||
|
|
||||||
coro<> AsyncSocket::waitForSend() {
|
coro<> AsyncSocket::waitForSend() {
|
||||||
asio::deadline_timer waiter(IOC);
|
asio::deadline_timer waiter(IOC);
|
||||||
|
|
||||||
@@ -249,8 +255,7 @@ coro<tcp::socket> asyncConnectTo(const std::string address, std::function<void(c
|
|||||||
if(!re) {
|
if(!re) {
|
||||||
re = Str::match(address, "([-_\\.\\w\\d]+)(?:\\:(\\d+))?");
|
re = Str::match(address, "([-_\\.\\w\\d]+)(?:\\:(\\d+))?");
|
||||||
if(!re) {
|
if(!re) {
|
||||||
addLog("Не удалось разобрать адрес");
|
MAKE_ERROR("Не удалось разобрать адрес");
|
||||||
co_return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tcp::resolver resv{ioc};
|
tcp::resolver resv{ioc};
|
||||||
@@ -288,8 +293,7 @@ coro<tcp::socket> asyncConnectTo(const std::string address, std::function<void(c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addLog("Не удалось подключится к серверу");
|
MAKE_ERROR("Не удалось подключится к серверу");
|
||||||
MAKE_ERROR(progress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -27,6 +27,7 @@ public:
|
|||||||
|
|
||||||
co_spawn(run());
|
co_spawn(run());
|
||||||
IsAlive.store(true);
|
IsAlive.store(true);
|
||||||
|
IsAlive.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
~Server();
|
~Server();
|
||||||
@@ -78,9 +79,24 @@ protected:
|
|||||||
public:
|
public:
|
||||||
Packet() = default;
|
Packet() = default;
|
||||||
Packet(const Packet&) = default;
|
Packet(const Packet&) = default;
|
||||||
Packet(Packet&&) = default;
|
Packet(Packet &&obj)
|
||||||
|
: Size(obj.Size), Pages(std::move(obj.Pages))
|
||||||
|
{
|
||||||
|
obj.Size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Packet& operator=(const Packet&) = default;
|
Packet& operator=(const Packet&) = default;
|
||||||
Packet& operator=(Packet&&) = default;
|
|
||||||
|
Packet& operator=(Packet &&obj) {
|
||||||
|
if(&obj == this)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
Size = obj.Size;
|
||||||
|
Pages = std::move(obj.Pages);
|
||||||
|
obj.Size = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline Packet& write(const std::byte *data, uint16_t size) {
|
inline Packet& write(const std::byte *data, uint16_t size) {
|
||||||
assert(Size+size < MAX_PACKET_SIZE);
|
assert(Size+size < MAX_PACKET_SIZE);
|
||||||
@@ -213,17 +229,24 @@ protected:
|
|||||||
boost::asio::ip::tcp::no_delay optionNoDelay(true); // Отключает попытки объёденить данные в крупные пакеты
|
boost::asio::ip::tcp::no_delay optionNoDelay(true); // Отключает попытки объёденить данные в крупные пакеты
|
||||||
Socket.set_option(optionNoDelay);
|
Socket.set_option(optionNoDelay);
|
||||||
|
|
||||||
asio::co_spawn(ioc, runSender(SendPackets.Context), asio::detached);
|
co_spawn(runSender(SendPackets.Context));
|
||||||
}
|
}
|
||||||
|
|
||||||
~AsyncSocket();
|
~AsyncSocket();
|
||||||
|
|
||||||
void pushPackets(std::vector<Packet> *simplePackets, std::vector<SmartPacket> *smartPackets = nullptr);
|
void pushPackets(std::vector<Packet> *simplePackets, std::vector<SmartPacket> *smartPackets = nullptr);
|
||||||
|
|
||||||
|
void pushPacket(Packet &&simplePacket) {
|
||||||
|
std::vector<Packet> out(1);
|
||||||
|
out[0] = std::move(simplePacket);
|
||||||
|
pushPackets(&out);
|
||||||
|
}
|
||||||
|
|
||||||
std::string getError() const;
|
std::string getError() const;
|
||||||
bool isAlive() const;
|
bool isAlive() const;
|
||||||
|
|
||||||
coro<> read(std::byte *data, uint32_t size);
|
coro<> read(std::byte *data, uint32_t size);
|
||||||
|
void closeRead();
|
||||||
|
|
||||||
template<typename T, std::enable_if_t<std::is_integral_v<T> or std::is_same_v<T, std::string>, int> = 0>
|
template<typename T, std::enable_if_t<std::is_integral_v<T> or std::is_same_v<T, std::string>, int> = 0>
|
||||||
coro<T> read() {
|
coro<T> read() {
|
||||||
|
|||||||
@@ -6,6 +6,12 @@
|
|||||||
|
|
||||||
namespace LV {
|
namespace LV {
|
||||||
|
|
||||||
|
enum struct EnumDisconnect {
|
||||||
|
ByInterface,
|
||||||
|
CriticalError,
|
||||||
|
ProtocolError
|
||||||
|
};
|
||||||
|
|
||||||
namespace ToServer {
|
namespace ToServer {
|
||||||
|
|
||||||
struct PacketQuat {
|
struct PacketQuat {
|
||||||
@@ -51,6 +57,17 @@ struct PacketQuat {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Первый уровень
|
||||||
|
enum struct L1 : uint8_t {
|
||||||
|
System,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Второй уровень
|
||||||
|
enum struct L2System : uint8_t {
|
||||||
|
InitEnd,
|
||||||
|
Disconnect
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ToClient {
|
namespace ToClient {
|
||||||
|
|||||||
@@ -8,20 +8,6 @@
|
|||||||
|
|
||||||
namespace LV::Server {
|
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;
|
using ResourceId_t = uint32_t;
|
||||||
|
|
||||||
// Двоичные данные
|
// Двоичные данные
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "GameServer.hpp"
|
#include "GameServer.hpp"
|
||||||
#include "Common/Abstract.hpp"
|
#include "Common/Abstract.hpp"
|
||||||
#include "Common/Net.hpp"
|
#include "Common/Net.hpp"
|
||||||
|
#include "Common/Packets.hpp"
|
||||||
#include "Server/Abstract.hpp"
|
#include "Server/Abstract.hpp"
|
||||||
#include "Server/ContentEventController.hpp"
|
#include "Server/ContentEventController.hpp"
|
||||||
#include <boost/json/parse.hpp>
|
#include <boost/json/parse.hpp>
|
||||||
@@ -248,7 +249,7 @@ void GameServer::run() {
|
|||||||
if(IsGoingShutdown) {
|
if(IsGoingShutdown) {
|
||||||
// Отключить игроков
|
// Отключить игроков
|
||||||
for(std::unique_ptr<ContentEventController> &cec : Game.CECs) {
|
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();
|
auto lock = External.NewConnectedPlayers.lock_write();
|
||||||
|
|
||||||
for(std::unique_ptr<RemoteClient> &client : *lock) {
|
for(std::unique_ptr<RemoteClient> &client : *lock) {
|
||||||
client->shutdown(ShutdownReason);
|
client->shutdown(EnumDisconnect::ByInterface, ShutdownReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNewConnected = !lock->empty();
|
bool hasNewConnected = !lock->empty();
|
||||||
@@ -361,6 +362,14 @@ void GameServer::stepPlayers() {
|
|||||||
for(std::unique_ptr<ContentEventController> &cec : Game.CECs) {
|
for(std::unique_ptr<ContentEventController> &cec : Game.CECs) {
|
||||||
// Убрать отключившихся
|
// Убрать отключившихся
|
||||||
if(!cec->Remote->isConnected()) {
|
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();
|
cec.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
void shutdown(const std::string reason) {
|
void shutdown(const std::string reason) {
|
||||||
|
if(ShutdownReason.empty())
|
||||||
ShutdownReason = reason;
|
ShutdownReason = reason;
|
||||||
IsGoingShutdown = true;
|
IsGoingShutdown = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,11 @@
|
|||||||
namespace LV::Server {
|
namespace LV::Server {
|
||||||
|
|
||||||
RemoteClient::~RemoteClient() {
|
RemoteClient::~RemoteClient() {
|
||||||
shutdown("~RemoteClient()");
|
shutdown(EnumDisconnect::ByInterface, "~RemoteClient()");
|
||||||
|
if(Socket.isAlive()) {
|
||||||
|
Socket.closeRead();
|
||||||
|
}
|
||||||
|
|
||||||
UseLock.wait_no_use();
|
UseLock.wait_no_use();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,7 +27,7 @@ coro<> RemoteClient::run() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
while(!IsGoingShutdown && IsConnected) {
|
while(!IsGoingShutdown && IsConnected) {
|
||||||
co_await Socket.read<uint8_t>();
|
co_await readPacket(Socket);
|
||||||
}
|
}
|
||||||
} catch(const std::exception &exc) {
|
} catch(const std::exception &exc) {
|
||||||
if(const auto *errc = dynamic_cast<const boost::system::system_error*>(&exc);
|
if(const auto *errc = dynamic_cast<const boost::system::system_error*>(&exc);
|
||||||
@@ -40,7 +44,7 @@ coro<> RemoteClient::run() {
|
|||||||
co_return;
|
co_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteClient::shutdown(const std::string reason) {
|
void RemoteClient::shutdown(EnumDisconnect type, const std::string reason) {
|
||||||
if(IsGoingShutdown)
|
if(IsGoingShutdown)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -48,7 +52,17 @@ void RemoteClient::shutdown(const std::string reason) {
|
|||||||
|
|
||||||
NextPacket << (uint8_t) ToClient::L1::System
|
NextPacket << (uint8_t) ToClient::L1::System
|
||||||
<< (uint8_t) ToClient::L2System::Disconnect
|
<< (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_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) {
|
for(DefVoxelId_t vId : NeedVoxelsSet) {
|
||||||
LocalRemapper[vId] = ResRemap.DefVoxels.toClient(vId);
|
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));
|
ResUses.DefVoxel.erase(ResUses.DefVoxel.find(id));
|
||||||
VoxelId_c cId = ResRemap.DefVoxels.erase(id);
|
DefVoxelId_c cId = ResRemap.DefVoxels.erase(id);
|
||||||
// TODO: отправить пакет потери идентификатора
|
// TODO: отправить пакет потери идентификатора
|
||||||
LOG.debug() << "Определение вокселя потеряно: " << id << " -> " << cId;
|
LOG.debug() << "Определение вокселя потеряно: " << id << " -> " << cId;
|
||||||
}
|
}
|
||||||
@@ -99,7 +113,7 @@ void RemoteClient::prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk
|
|||||||
if(++ResUses.DefVoxel[id] == 1) {
|
if(++ResUses.DefVoxel[id] == 1) {
|
||||||
// Определение только появилось
|
// Определение только появилось
|
||||||
NextRequest.NewVoxels.push_back(id);
|
NextRequest.NewVoxels.push_back(id);
|
||||||
VoxelId_c cId = ResRemap.DefVoxels.toClient(id);
|
DefVoxelId_c cId = ResRemap.DefVoxels.toClient(id);
|
||||||
LOG.debug() << "Новое определение вокселя: " << id << " -> " << cId;
|
LOG.debug() << "Новое определение вокселя: " << id << " -> " << cId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,24 +122,23 @@ void RemoteClient::prepareChunkUpdate_Voxels(WorldId_t worldId, Pos::GlobalChunk
|
|||||||
prevSet = std::move(nextSet);
|
prevSet = std::move(nextSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: отправить новую информацию о расположении вокселей
|
LOG.debug() << "Воксели чанка: " << worldId << " / " << chunkPos.X << ":" << chunkPos.Y << ":" << chunkPos.Z;
|
||||||
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());
|
|
||||||
|
|
||||||
// for(const VoxelCube &cube : voxels) {
|
NextPacket << (uint8_t) ToClient::L1::Content
|
||||||
// NextPacket << LocalRemapper[cube.VoxelId]
|
<< (uint8_t) ToClient::L2Content::ChunkVoxels << wcId
|
||||||
// << cube.Left.X << cube.Left.Y << cube.Left.Z
|
<< Pos::GlobalChunk::Key(chunkPos);
|
||||||
// << cube.Right.X << cube.Right.Y << cube.Right.Z;
|
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,
|
void RemoteClient::prepareChunkUpdate_Nodes(WorldId_t worldId, Pos::GlobalChunk chunkPos,
|
||||||
const std::unordered_map<Pos::Local16_u, Node> &nodes)
|
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));
|
ResUses.DefVoxel.erase(ResUses.DefVoxel.find(id));
|
||||||
VoxelId_c cId = ResRemap.DefVoxels.erase(id);
|
DefVoxelId_c cId = ResRemap.DefVoxels.erase(id);
|
||||||
// TODO: отправить пакет потери идентификатора
|
// TODO: отправить пакет потери идентификатора
|
||||||
LOG.debug() << "Определение вокселя потеряно: " << id << " -> " << cId;
|
LOG.debug() << "Определение вокселя потеряно: " << id << " -> " << cId;
|
||||||
}
|
}
|
||||||
@@ -154,7 +167,7 @@ void RemoteClient::prepareChunkRemove(WorldId_t worldId, Pos::GlobalChunk chunkP
|
|||||||
WorldId_c cwId = ResRemap.Worlds.toClient(worldId);
|
WorldId_c cwId = ResRemap.Worlds.toClient(worldId);
|
||||||
NextPacket << (uint8_t) ToClient::L1::Content
|
NextPacket << (uint8_t) ToClient::L1::Content
|
||||||
<< (uint8_t) ToClient::L2Content::RemoveChunk
|
<< (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)
|
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);
|
DefWorldId_c cdId = ResRemap.DefWorlds.toClient(res.DefId);
|
||||||
NextRequest.NewWorlds.push_back(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
|
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||||
<< (uint8_t) ToClient::L2Definition::World
|
<< (uint8_t) ToClient::L2Definition::World
|
||||||
<< cdId;
|
<< cdId;
|
||||||
@@ -468,7 +481,7 @@ void RemoteClient::informateDefVoxel(const std::unordered_map<DefVoxelId_t, void
|
|||||||
if(!ResUses.DefWorld.contains(sId))
|
if(!ResUses.DefWorld.contains(sId))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
VoxelId_c cId = ResRemap.DefVoxels.toClient(sId);
|
DefVoxelId_c cId = ResRemap.DefVoxels.toClient(sId);
|
||||||
|
|
||||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||||
<< (uint8_t) ToClient::L2Definition::Voxel
|
<< (uint8_t) ToClient::L2Definition::Voxel
|
||||||
@@ -483,7 +496,7 @@ void RemoteClient::informateDefNode(const std::unordered_map<DefNodeId_t, void*>
|
|||||||
if(!ResUses.DefNode.contains(sId))
|
if(!ResUses.DefNode.contains(sId))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
NodeId_c cId = ResRemap.DefNodes.toClient(sId);
|
DefNodeId_c cId = ResRemap.DefNodes.toClient(sId);
|
||||||
|
|
||||||
NextPacket << (uint8_t) ToClient::L1::Definition
|
NextPacket << (uint8_t) ToClient::L1::Definition
|
||||||
<< (uint8_t) ToClient::L2Definition::Node
|
<< (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,
|
void RemoteClient::incrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
||||||
std::unordered_set<BinModelId_t> &models)
|
std::unordered_set<BinModelId_t> &models)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <Common/Lockable.hpp>
|
#include <Common/Lockable.hpp>
|
||||||
#include <Common/Net.hpp>
|
#include <Common/Net.hpp>
|
||||||
#include "Abstract.hpp"
|
#include "Abstract.hpp"
|
||||||
|
#include "Common/Packets.hpp"
|
||||||
#include "Server/ContentEventController.hpp"
|
#include "Server/ContentEventController.hpp"
|
||||||
#include <Common/Abstract.hpp>
|
#include <Common/Abstract.hpp>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
@@ -249,8 +250,8 @@ class RemoteClient {
|
|||||||
SCSKeyRemapper<BinModelId_t, ModelId_c> BinModels;
|
SCSKeyRemapper<BinModelId_t, ModelId_c> BinModels;
|
||||||
|
|
||||||
SCSKeyRemapper<DefWorldId_t, DefWorldId_c> DefWorlds;
|
SCSKeyRemapper<DefWorldId_t, DefWorldId_c> DefWorlds;
|
||||||
SCSKeyRemapper<DefVoxelId_t, VoxelId_c> DefVoxels;
|
SCSKeyRemapper<DefVoxelId_t, DefVoxelId_c> DefVoxels;
|
||||||
SCSKeyRemapper<DefNodeId_t, NodeId_c> DefNodes;
|
SCSKeyRemapper<DefNodeId_t, DefNodeId_c> DefNodes;
|
||||||
SCSKeyRemapper<DefPortalId_t, DefPortalId_c> DefPortals;
|
SCSKeyRemapper<DefPortalId_t, DefPortalId_c> DefPortals;
|
||||||
SCSKeyRemapper<DefEntityId_t, DefEntityId_c> DefEntityes;
|
SCSKeyRemapper<DefEntityId_t, DefEntityId_c> DefEntityes;
|
||||||
|
|
||||||
@@ -275,7 +276,7 @@ public:
|
|||||||
~RemoteClient();
|
~RemoteClient();
|
||||||
|
|
||||||
coro<> run();
|
coro<> run();
|
||||||
void shutdown(const std::string reason);
|
void shutdown(EnumDisconnect type, const std::string reason);
|
||||||
bool isConnected() { return IsConnected; }
|
bool isConnected() { return IsConnected; }
|
||||||
|
|
||||||
void pushPackets(std::vector<Net::Packet> *simplePackets, std::vector<Net::SmartPacket> *smartPackets = nullptr) {
|
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);
|
void informateDefPortals(const std::unordered_map<DefPortalId_t, void*> &portals);
|
||||||
|
|
||||||
private:
|
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,
|
void incrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
||||||
std::unordered_set<BinModelId_t> &models);
|
std::unordered_set<BinModelId_t> &models);
|
||||||
void decrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
void decrementBinary(std::unordered_set<BinTextureId_t> &textures, std::unordered_set<BinSoundId_t> &sounds,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
extern std::unordered_map<std::string, std::tuple<const char*, const char*>> _binary_assets_symbols;
|
extern std::unordered_map<std::string, std::tuple<const char*, const char*>> _binary_assets_symbols;
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
namespace AL {
|
namespace LV {
|
||||||
|
|
||||||
Resource::Resource() = default;
|
Resource::Resource() = default;
|
||||||
Resource::~Resource() = default;
|
Resource::~Resource() = default;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <istream>
|
#include <istream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace AL {
|
namespace LV {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct membuf : std::streambuf {
|
struct membuf : std::streambuf {
|
||||||
|
|||||||
60
Src/main.cpp
60
Src/main.cpp
@@ -1,3 +1,4 @@
|
|||||||
|
#include <GLFW/glfw3.h>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/asio/deadline_timer.hpp>
|
#include <boost/asio/deadline_timer.hpp>
|
||||||
#include <boost/asio/detached.hpp>
|
#include <boost/asio/detached.hpp>
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "Client/ServerSession.hpp"
|
#include "Client/ServerSession.hpp"
|
||||||
#include "Common/Net.hpp"
|
#include "Common/Net.hpp"
|
||||||
|
#include "Common/Packets.hpp"
|
||||||
#include "Server/GameServer.hpp"
|
#include "Server/GameServer.hpp"
|
||||||
#include <Client/Vulkan/Vulkan.hpp>
|
#include <Client/Vulkan/Vulkan.hpp>
|
||||||
|
|
||||||
@@ -16,14 +18,14 @@ namespace LV {
|
|||||||
|
|
||||||
using namespace TOS;
|
using namespace TOS;
|
||||||
|
|
||||||
|
std::unique_ptr<Client::ServerSession> session;
|
||||||
|
|
||||||
coro<> runClient(asio::io_context &ioc, uint16_t port) {
|
coro<> runClient(asio::io_context &ioc, uint16_t port) {
|
||||||
try {
|
try {
|
||||||
tcp::socket sock = co_await Net::asyncConnectTo("localhost:"+std::to_string(port));
|
tcp::socket sock = co_await Net::asyncConnectTo("localhost:"+std::to_string(port));
|
||||||
co_await Client::ServerSession::asyncAuthorizeWithServer(sock, "DrSocalkwe3n", "1password2", 1);
|
co_await Client::ServerSession::asyncAuthorizeWithServer(sock, "DrSocalkwe3n", "1password2", 1);
|
||||||
std::unique_ptr<Net::AsyncSocket> asock = co_await Client::ServerSession::asyncInitGameProtocol(ioc, std::move(sock));
|
std::unique_ptr<Net::AsyncSocket> asock = co_await Client::ServerSession::asyncInitGameProtocol(ioc, std::move(sock));
|
||||||
asio::deadline_timer timer(ioc);
|
session = std::make_unique<Client::ServerSession>(ioc, std::move(asock), nullptr);
|
||||||
timer.expires_from_now(boost::posix_time::seconds(1));
|
|
||||||
co_await timer.async_wait();
|
|
||||||
} catch(const std::exception &exc) {
|
} catch(const std::exception &exc) {
|
||||||
std::cout << exc.what() << std::endl;
|
std::cout << exc.what() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -31,33 +33,41 @@ coro<> runClient(asio::io_context &ioc, uint16_t port) {
|
|||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
|
||||||
VK::Vulkan VkInst;
|
|
||||||
VkInst.getSettingsNext() = VkInst.getBestSettings();
|
|
||||||
VkInst.reInit();
|
|
||||||
|
|
||||||
auto ot = std::async([&](){
|
|
||||||
VkInst.start([&](VK::Vulkan *instance, int subpass, VkCommandBuffer &renderCmd)
|
|
||||||
{
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// LuaVox
|
// LuaVox
|
||||||
|
|
||||||
asio::io_context ioc;
|
asio::io_context ioc;
|
||||||
|
|
||||||
Server::GameServer gs(ioc, "");
|
LV::Client::VK::Vulkan vkInst(ioc);
|
||||||
|
|
||||||
Net::Server server(ioc, [&](tcp::socket sock) -> coro<> {
|
|
||||||
server.stop();
|
|
||||||
co_await gs.pushSocketConnect(std::move(sock));
|
|
||||||
}, 6666);
|
|
||||||
|
|
||||||
std::cout << server.getPort() << std::endl;
|
|
||||||
|
|
||||||
asio::co_spawn(ioc, runClient(ioc, server.getPort()), asio::detached);
|
|
||||||
|
|
||||||
ioc.run();
|
ioc.run();
|
||||||
VkInst.shutdown();
|
|
||||||
|
// Server::GameServer gs(ioc, "");
|
||||||
|
|
||||||
|
// Net::Server server(ioc, [&](tcp::socket sock) -> coro<> {
|
||||||
|
// server.stop();
|
||||||
|
// co_await gs.pushSocketConnect(std::move(sock));
|
||||||
|
// }, 6666);
|
||||||
|
|
||||||
|
// std::cout << server.getPort() << std::endl;
|
||||||
|
|
||||||
|
// asio::co_spawn(ioc, runClient(ioc, server.getPort()), asio::detached);
|
||||||
|
|
||||||
|
|
||||||
|
// auto ot = std::async([&](){
|
||||||
|
// VkInst.start([&](VK::Vulkan *instance, int subpass, VkCommandBuffer &renderCmd)
|
||||||
|
// {
|
||||||
|
// if(glfwWindowShouldClose(VkInst.Graphics.Window) || (session && !session->isConnected())) {
|
||||||
|
// VkInst.shutdown();
|
||||||
|
|
||||||
|
// if(glfwWindowShouldClose(VkInst.Graphics.Window) && session)
|
||||||
|
// session->shutdown(EnumDisconnect::ByInterface);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// session = nullptr;
|
||||||
|
// });
|
||||||
|
|
||||||
|
// ioc.run();
|
||||||
|
// VkInst.shutdown();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
Work/assets/default.ttf
Normal file
BIN
Work/assets/default.ttf
Normal file
Binary file not shown.
BIN
Work/assets/default2.ttf
Normal file
BIN
Work/assets/default2.ttf
Normal file
Binary file not shown.
@@ -1,4 +1,8 @@
|
|||||||
[Window][Debug##Default]
|
[Window][Debug##Default]
|
||||||
Pos=60,60
|
Pos=0,0
|
||||||
Size=400,400
|
Size=400,400
|
||||||
|
|
||||||
|
[Window][MainMenu]
|
||||||
|
Pos=0,0
|
||||||
|
Size=960,540
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user