first version

This commit is contained in:
Vladislav Khorev 2026-01-14 23:17:52 +03:00
parent dca38c986d
commit 483757f8ca
6 changed files with 172 additions and 0 deletions

View File

@ -50,6 +50,9 @@ add_executable(space-game001
../src/UiManager.h ../src/UiManager.h
../src/Projectile.h ../src/Projectile.h
../src/Projectile.cpp ../src/Projectile.cpp
../src/network/NetworkInterface.h
../src/network/WebSocketClient.h
../src/network/WebSocketClient.cpp
) )
# Установка проекта по умолчанию для Visual Studio # Установка проекта по умолчанию для Visual Studio
@ -71,6 +74,7 @@ target_compile_definitions(space-game001 PRIVATE
WIN32_LEAN_AND_MEAN WIN32_LEAN_AND_MEAN
PNG_ENABLED PNG_ENABLED
SDL_MAIN_HANDLED SDL_MAIN_HANDLED
NETWORK
# SIMPLIFIED # SIMPLIFIED
) )

44
server/CMakeLists.txt Normal file
View File

@ -0,0 +1,44 @@
cmake_minimum_required(VERSION 3.15)
project(SpaceGameServer)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Подключаем зависимости нашего движка
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/ThirdParty.cmake)
# Настройка флагов для тяжелых шаблонов Boost
if (MSVC)
add_compile_options(/bigobj)
endif()
# Добавляем скомпилированные компоненты Boost через относительные пути
# CMake сам создаст цели boost_system и др.
add_subdirectory("${BOOST_SRC_DIR}/libs/system" boost-system-build EXCLUDE_FROM_ALL)
add_subdirectory("${BOOST_SRC_DIR}/libs/assert" boost-assert-build EXCLUDE_FROM_ALL)
add_subdirectory("${BOOST_SRC_DIR}/libs/config" boost-config-build EXCLUDE_FROM_ALL)
add_subdirectory("${BOOST_SRC_DIR}/libs/throw_exception" boost-throw_exception-build EXCLUDE_FROM_ALL)
add_subdirectory("${BOOST_SRC_DIR}/libs/variant2" boost-variant2-build EXCLUDE_FROM_ALL)
add_subdirectory("${BOOST_SRC_DIR}/libs/mp11" boost-mp11-build EXCLUDE_FROM_ALL)
add_subdirectory("${BOOST_SRC_DIR}/libs/winapi" boost-winapi-build EXCLUDE_FROM_ALL)
add_subdirectory("${BOOST_SRC_DIR}/libs/predef" boost-predef-build EXCLUDE_FROM_ALL)
# EXCLUDE_FROM_ALL гарантирует, что мы собираем только то, что линкуем
# Исполняемый файл сервера
add_executable(Server main.cpp)
target_include_directories(Server PRIVATE ${BOOST_SRC_DIR})
# Линковка
target_link_libraries(Server
PRIVATE
boost_system # Скомпилированная часть для error_code
eigen_external_lib # Если планируешь использовать математику на сервере
)
if(WIN32)
target_link_libraries(Server PRIVATE ws2_32 mswsock)
endif()
# Дополнительный макрос, чтобы Asio знал, что мы работаем без устаревших функций
target_compile_definitions(Server PRIVATE BOOST_ASIO_NO_DEPRECATED)

81
server/main.cpp Normal file
View File

@ -0,0 +1,81 @@
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <mutex>
namespace beast = boost::beast;
namespace http = beast::http;
namespace websocket = beast::websocket;
namespace net = boost::asio;
using tcp = net::ip::tcp;
class Session : public std::enable_shared_from_this<Session> {
websocket::stream<beast::tcp_stream> ws_;
beast::flat_buffer buffer_;
int id_;
public:
explicit Session(tcp::socket&& socket, int id)
: ws_(std::move(socket)), id_(id) {
}
void run() {
ws_.async_accept([self = shared_from_this()](beast::error_code ec) {
if (ec) return;
std::cout << "Client " << self->id_ << " connected\n";
// Ñðàçó îòïðàâëÿåì ID êëèåíòó
self->send_message("ID:" + std::to_string(self->id_));
self->do_read();
});
}
private:
void do_read() {
ws_.async_read(buffer_, [self = shared_from_this()](beast::error_code ec, std::size_t) {
if (ec) return;
std::string msg = beast::buffers_to_string(self->buffer_.data());
if (msg == "PING") {
self->send_message("PONG");
}
self->buffer_.consume(self->buffer_.size());
self->do_read();
});
}
void send_message(std::string msg) {
auto ss = std::make_shared<std::string>(std::move(msg));
ws_.async_write(net::buffer(*ss), [ss](beast::error_code, std::size_t) {});
}
};
int main() {
try {
net::io_context ioc;
tcp::acceptor acceptor{ ioc, {tcp::v4(), 8080} };
int next_id = 1000;
std::cout << "Server started on port 8080...\n";
auto do_accept = [&](auto& self_fn) -> void {
acceptor.async_accept([&, self_fn](beast::error_code ec, tcp::socket socket) {
if (!ec) {
std::make_shared<Session>(std::move(socket), next_id++)->run();
}
self_fn(self_fn);
});
};
do_accept(do_accept);
ioc.run();
}
catch (std::exception const& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}

View File

@ -0,0 +1,14 @@
#pragma once
#include <string>
// NetworkInterface.h - Èíòåðôåéñ äëÿ ðàçíûõ òèïîâ ñîåäèíåíèé
namespace ZL {
class INetworkClient {
public:
virtual ~INetworkClient() = default;
virtual void Connect(const std::string& host, uint16_t port) = 0;
virtual void Send(const std::string& message) = 0;
virtual bool IsConnected() const = 0;
virtual void Poll() = 0; // Äëÿ îáðàáîòêè âõîäÿùèõ ïàêåòîâ
};
}

View File

View File

@ -0,0 +1,29 @@
#pragma once
// WebSocketClient.h
#include "NetworkInterface.h"
#include <queue>
namespace ZL {
class WebSocketClient : public INetworkClient {
private:
std::queue<std::string> messageQueue;
bool connected = false;
int clientId = -1;
public:
void Connect(const std::string& host, uint16_t port) override {
// Â Emscripten çäåñü áóäåò emscripten_websocket_new
// Â Desktop - boost::beast::websocket::stream
}
void Poll() override {
// ×èòàåì äàííûå èç ñîêåòà.
// Åñëè ïîëó÷èëè ID: clientId = parseId(msg); connected = true;
// Åñëè ïîëó÷èëè "PONG": ëîãèðóåì çàäåðæêó.
}
bool IsConnected() const override { return connected; }
int GetClientId() const { return clientId; }
};
}