#include #include #include #include #include #include #include #include #include #include #define _USE_MATH_DEFINES #include #include "../src/network/ClientState.h" // Вспомогательный split std::vector split(const std::string& s, char delimiter) { std::vector tokens; std::string token; std::istringstream tokenStream(s); while (std::getline(tokenStream, token, delimiter)) { tokens.push_back(token); } return tokens; } namespace beast = boost::beast; namespace http = beast::http; namespace websocket = beast::websocket; namespace net = boost::asio; using tcp = net::ip::tcp; class Session; std::vector> g_sessions; std::mutex g_sessions_mutex; class Session : public std::enable_shared_from_this { websocket::stream ws_; beast::flat_buffer buffer_; int id_; ClientStateInterval timedClientStates; void process_message(const std::string& msg) { auto now_server = std::chrono::system_clock::now(); auto parts = split(msg, ':'); if (parts.size() < 16) { throw std::runtime_error("Unknown message type received, too small"); } uint64_t clientTimestamp = std::stoull(parts[1]); ClientState receivedState; receivedState.id = id_; std::chrono::system_clock::time_point uptime_timepoint{ std::chrono::duration_cast(std::chrono::milliseconds(clientTimestamp)) }; receivedState.lastUpdateServerTime = uptime_timepoint; if (parts[0] == "UPD") { receivedState.handle_full_sync(parts, 2); retranslateMessage(msg); } else { throw std::runtime_error("Unknown message type received: " + parts[0]); } timedClientStates.add_state(receivedState); } void retranslateMessage(const std::string& msg) { std::string event_msg = "EVENT:" + std::to_string(id_) + ":" + msg; std::lock_guard lock(g_sessions_mutex); for (auto& session : g_sessions) { if (session->get_id() != id_) { // Не шлем отправителю session->send_message(event_msg); } } } public: explicit Session(tcp::socket&& socket, int id) : ws_(std::move(socket)), id_(id) { } void init() { } void run() { { std::lock_guard lock(g_sessions_mutex); g_sessions.push_back(shared_from_this()); } ws_.async_accept([self = shared_from_this()](beast::error_code ec) { if (ec) return; std::cout << "Client " << self->id_ << " connected\n"; self->init(); self->send_message("ID:" + std::to_string(self->id_)); self->do_read(); }); } void send_message(std::string msg) { auto ss = std::make_shared(std::move(msg)); ws_.async_write(net::buffer(*ss), [ss](beast::error_code, std::size_t) {}); } int get_id() const { return id_; } private: void do_read() { ws_.async_read(buffer_, [self = shared_from_this()](beast::error_code ec, std::size_t) { if (ec) { std::lock_guard lock(g_sessions_mutex); g_sessions.erase(std::remove_if(g_sessions.begin(), g_sessions.end(), [self](const std::shared_ptr& session) { return session.get() == self.get(); }), g_sessions.end()); return; } std::string msg = beast::buffers_to_string(self->buffer_.data()); self->process_message(msg); self->buffer_.consume(self->buffer_.size()); self->do_read(); }); } }; void update_world(net::steady_timer& timer, net::io_context& ioc) { // TODO: Renew game state timer.expires_after(std::chrono::milliseconds(50)); timer.async_wait([&](const boost::system::error_code& ec) { if (!ec) update_world(timer, ioc); }); } 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(std::move(socket), next_id++)->run(); } self_fn(self_fn); }); }; net::steady_timer timer(ioc); update_world(timer, ioc); do_accept(do_accept); ioc.run(); } catch (std::exception const& e) { std::cerr << "Error: " << e.what() << std::endl; } return 0; }