From 90f18ea651f8ffcfdf9ae5d43bbc537418326b17 Mon Sep 17 00:00:00 2001 From: milek7 Date: Sun, 27 Jan 2019 20:38:03 +0100 Subject: [PATCH] work --- CMakeLists.txt | 1 - Globals.cpp | 6 ---- application.cpp | 15 ++++----- application.h | 5 ++- command.cpp | 1 + command.h | 1 + network/backend/asio.cpp | 54 +++++++++++++++++++------------- network/backend/asio.h | 9 +++--- network/backend/file.cpp | 0 network/backend/file.h | 22 -------------- network/manager.cpp | 24 ++++++++++++++- network/manager.h | 4 +++ network/message.cpp | 2 ++ network/message.h | 1 + network/network.cpp | 66 +++++++++++++++++++++++++++++++++++----- network/network.h | 22 ++++++++++++-- simulation.cpp | 7 +++++ 17 files changed, 168 insertions(+), 72 deletions(-) delete mode 100644 network/backend/file.cpp delete mode 100644 network/backend/file.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 76882d8c..15cb97ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,7 +119,6 @@ set(SOURCES "network/message.cpp" "network/manager.cpp" "network/backend/asio.cpp" -"network/backend/file.cpp" "widgets/vehiclelist.cpp" diff --git a/Globals.cpp b/Globals.cpp index ae58e209..7fd722e3 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -813,12 +813,6 @@ global_settings::ConfigParse(cParser &Parser) { bEnableTraction = false; // false = pantograf się nie połamie bLiveTraction = false; // false = pantografy zawsze zbierają 95% MaxVoltage } - if (iMultiplayer > 0) - { - bInactivePause = false; // okno "w tle" nie może pauzować, jeśli włączona komunikacja - // pauzowanie jest zablokowane dla (iMultiplayer&2)>0, więc iMultiplayer=1 da się zapauzować - // (tryb instruktora) - } /* fFpsMin = fFpsAverage - fFpsDeviation; // dolna granica FPS, przy której promień scenerii będzie zmniejszany diff --git a/application.cpp b/application.cpp index 1daa0b58..4cbc1fe4 100644 --- a/application.cpp +++ b/application.cpp @@ -57,12 +57,7 @@ extern WNDPROC BaseWindowProc; // user input callbacks void focus_callback( GLFWwindow *window, int focus ) { - if( Global.bInactivePause ) {// jeśli ma być pauzowanie okna w tle - if( focus ) - Global.iPause &= ~4; // odpauzowanie, gdy jest na pierwszym planie - else - Global.iPause |= 4; // włączenie pauzy, gdy nieaktywy - } + Application.on_focus_change(focus != 0); } void window_resize_callback( GLFWwindow *window, int w, int h ) { @@ -329,7 +324,6 @@ eu07_application::render_ui() { bool eu07_application::pop_mode() { - if( m_modestack.empty() ) { return false; } m_modes[ m_modestack.top() ]->exit(); @@ -434,6 +428,13 @@ void eu07_application::on_char(unsigned int c) { return; } +void eu07_application::on_focus_change(bool focus) { + if( Global.bInactivePause && !m_network->client) {// jeśli ma być pauzowanie okna w tle + command_relay relay; + relay.post(user_command::focuspauseset, focus ? 1.0 : 0.0, 0.0, GLFW_PRESS, 0); + } +} + GLFWwindow * eu07_application::window( int const Windowindex ) { diff --git a/application.h b/application.h index 2da6655a..e3f43507 100644 --- a/application.h +++ b/application.h @@ -71,7 +71,10 @@ public: on_mouse_button( int const Button, int const Action, int const Mods ); void on_scroll( double const Xoffset, double const Yoffset ); - void on_char(unsigned int c); + void + on_char(unsigned int c); + void + on_focus_change(bool focus); // gives access to specified window, creates a new window if index == -1 GLFWwindow * window( int const Windowindex = 0 ); diff --git a/command.cpp b/command.cpp index 1d9e9802..a24dcd49 100644 --- a/command.cpp +++ b/command.cpp @@ -227,6 +227,7 @@ commanddescription_sequence Commands_descriptions = { { "vehiclemovebackwards", command_target::vehicle, command_mode::oneoff }, { "vehicleboost", command_target::vehicle, command_mode::oneoff }, { "debugtoggle", command_target::simulation, command_mode::oneoff }, + { "focuspauseset", command_target::simulation, command_mode::oneoff }, { "pausetoggle", command_target::simulation, command_mode::oneoff }, { "entervehicle", command_target::simulation, command_mode::oneoff }, { "queueevent", command_target::simulation, command_mode::oneoff }, diff --git a/command.h b/command.h index b20f0d26..37e03f09 100644 --- a/command.h +++ b/command.h @@ -221,6 +221,7 @@ enum class user_command { vehiclemovebackwards, vehicleboost, debugtoggle, + focuspauseset, pausetoggle, entervehicle, queueevent, diff --git a/network/backend/asio.cpp b/network/backend/asio.cpp index 5f46f52c..4a7bb5be 100644 --- a/network/backend/asio.cpp +++ b/network/backend/asio.cpp @@ -2,8 +2,8 @@ #include "sn_utils.h" #include "Logs.h" -network::tcp::connection::connection(asio::io_context &io_ctx, bool client) - : network::connection(client), m_socket(io_ctx) +network::tcp::connection::connection(asio::io_context &io_ctx, bool client, size_t counter) + : network::connection(client, counter), m_socket(io_ctx) { m_header_buffer.resize(8); } @@ -16,9 +16,7 @@ void network::tcp::connection::disconnect() void network::tcp::connection::send_data(std::shared_ptr buffer) { - asio::async_write(m_socket, asio::buffer(*buffer.get()), std::bind(&connection::handle_send, this, buffer, - std::placeholders::_1, - std::placeholders::_2)); + asio::async_write(m_socket, asio::buffer(*buffer.get()), std::bind(&connection::send_complete, this, buffer)); } void network::tcp::connection::connected() @@ -34,12 +32,6 @@ void network::tcp::connection::read_header() std::placeholders::_1, std::placeholders::_2)); } -void network::tcp::connection::handle_send( - std::shared_ptr buf, const asio::error_code &err, size_t bytes_transferred) -{ - -} - void network::tcp::connection::handle_header(const asio::error_code &err, size_t bytes_transferred) { std::istringstream header(m_header_buffer); @@ -80,32 +72,52 @@ void network::tcp::connection::handle_data(const asio::error_code &err, size_t b read_header(); } -void network::tcp::connection::send_message(const message &msg) +void network::tcp::connection::write_message(const message &msg, std::ostream &stream) { - std::ostringstream stream; + size_t beg = (size_t)stream.tellp(); + sn_utils::ls_uint32(stream, NETWORK_MAGIC); sn_utils::ls_uint32(stream, 0); serialize_message(msg, stream); - size_t size = (size_t)stream.tellp() - 8; + size_t size = (size_t)stream.tellp() - beg - 8; if (size > MAX_MSG_SIZE) { ErrorLog("net: message too big", logtype::net); return; } - stream.seekp(4, std::ios_base::beg); + stream.seekp(beg + 4, std::ios_base::beg); sn_utils::ls_uint32(stream, size); - stream.flush(); + stream.seekp(0, std::ios_base::end); +} - std::shared_ptr buf = std::make_shared(stream.str()); - send_data(buf); +void network::tcp::connection::send_messages(const std::vector > &messages) +{ + if (messages.size() == 0) + return; + + std::ostringstream stream; + for (auto const &msg : messages) + write_message(*msg.get(), stream); + + stream.flush(); + send_data(std::make_shared(stream.str())); +} + +void network::tcp::connection::send_message(const message &msg) +{ + std::ostringstream stream; + write_message(msg, stream); + + stream.flush(); + send_data(std::make_shared(stream.str())); } // ----------------- -network::tcp::server::server(asio::io_context &io_ctx, const std::string &host, uint32_t port) - : m_acceptor(io_ctx) +network::tcp::server::server(std::shared_ptr buf, asio::io_context &io_ctx, const std::string &host, uint32_t port) + : network::server(buf), m_acceptor(io_ctx) { auto endpoint = asio::ip::tcp::endpoint(asio::ip::address::from_string(host), port); m_acceptor.open(endpoint.protocol()); @@ -144,7 +156,7 @@ void network::tcp::server::handle_accept(std::shared_ptr conn, const network::tcp::client::client(asio::io_context &io_ctx, const std::string &host, uint32_t port) { - std::shared_ptr conn = std::make_shared(io_ctx, true); + std::shared_ptr conn = std::make_shared(io_ctx, true, messages_counter); conn->set_handler(std::bind(&client::handle_message, this, std::ref(*conn.get()), std::placeholders::_1)); asio::ip::tcp::endpoint endpoint( diff --git a/network/backend/asio.h b/network/backend/asio.h index bbe0858e..a505da03 100644 --- a/network/backend/asio.h +++ b/network/backend/asio.h @@ -12,11 +12,11 @@ namespace network::tcp friend class client; public: - connection(asio::io_context &io_ctx, bool client = false); + connection(asio::io_context &io_ctx, bool client = false, size_t counter = 0); virtual void connected() override; virtual void disconnect() override; - virtual void send_data(std::shared_ptr buffer) override; + virtual void send_messages(const std::vector > &messages) override; virtual void send_message(const message &msg) override; asio::ip::tcp::socket m_socket; @@ -25,8 +25,9 @@ namespace network::tcp std::string m_header_buffer; std::string m_body_buffer; + void write_message(const message &msg, std::ostream &stream); + void send_data(std::shared_ptr buffer); void read_header(); - void handle_send(std::shared_ptr buf, const asio::error_code &err, size_t bytes_transferred); void handle_header(const asio::error_code &err, size_t bytes_transferred); void handle_data(const asio::error_code &err, size_t bytes_transferred); }; @@ -40,7 +41,7 @@ namespace network::tcp asio::ip::tcp::acceptor m_acceptor; public: - server(asio::io_context &io_ctx, const std::string &host, uint32_t port); + server(std::shared_ptr buf, asio::io_context &io_ctx, const std::string &host, uint32_t port); }; class client : public network::client diff --git a/network/backend/file.cpp b/network/backend/file.cpp deleted file mode 100644 index e69de29b..00000000 diff --git a/network/backend/file.h b/network/backend/file.h deleted file mode 100644 index 3737c53f..00000000 --- a/network/backend/file.h +++ /dev/null @@ -1,22 +0,0 @@ -#include "network/network.h" - -namespace network::file -{ - class server : public network::server - { - private: - std::fstream stream; - - public: - server(); - }; - - class client : public network::client - { - private: - std::fstream stream; - - public: - client(); - }; -} diff --git a/network/manager.cpp b/network/manager.cpp index 9d727374..4b311c4f 100644 --- a/network/manager.cpp +++ b/network/manager.cpp @@ -2,6 +2,11 @@ #include "simulation.h" #include "network/backend/asio.h" +network::server_manager::server_manager() +{ + backbuffer = std::make_shared("backbuffer.bin", std::ios::out | std::ios::in | std::ios::trunc | std::ios::binary); +} + command_queue::commands_map network::server_manager::pop_commands() { command_queue::commands_map map; @@ -14,13 +19,29 @@ command_queue::commands_map network::server_manager::pop_commands() void network::server_manager::push_delta(double dt, double sync, const command_queue::commands_map &commands) { + if (dt == 0.0 && commands.empty()) + return; + for (auto srv : servers) srv->push_delta(dt, sync, commands); + + frame_info msg; + msg.dt = dt; + msg.sync = sync; + msg.commands = commands; + + serialize_message(msg, *backbuffer.get()); +} + +void network::server_manager::update() +{ + for (auto srv : servers) + srv->update(); } void network::server_manager::create_server(asio::io_context &ctx, const std::string &host, uint32_t port) { - servers.emplace_back(std::make_shared(ctx, host, port)); + servers.emplace_back(std::make_shared(backbuffer, ctx, host, port)); } network::manager::manager() @@ -30,6 +51,7 @@ network::manager::manager() void network::manager::poll() { io_context.poll(); + servers->update(); } void network::manager::create_server(const std::string &host, uint32_t port) diff --git a/network/manager.h b/network/manager.h index da6ed8ab..09feeb24 100644 --- a/network/manager.h +++ b/network/manager.h @@ -10,11 +10,15 @@ namespace network { private: std::vector> servers; + std::shared_ptr backbuffer; public: + server_manager(); + void push_delta(double dt, double sync, const command_queue::commands_map &commands); command_queue::commands_map pop_commands(); void create_server(asio::io_context &ctx, const std::string &host, uint32_t port); + void update(); }; class manager diff --git a/network/message.cpp b/network/message.cpp index 972ae603..7e275733 100644 --- a/network/message.cpp +++ b/network/message.cpp @@ -4,11 +4,13 @@ void network::client_hello::serialize(std::ostream &stream) const { sn_utils::ls_int32(stream, version); + sn_utils::ls_uint32(stream, start_packet); } void network::client_hello::deserialize(std::istream &stream) { version = sn_utils::ld_int32(stream); + start_packet = sn_utils::ld_uint32(stream); } void network::server_hello::serialize(std::ostream &stream) const diff --git a/network/message.h b/network/message.h index 95991166..9b08c8d7 100644 --- a/network/message.h +++ b/network/message.h @@ -31,6 +31,7 @@ struct client_hello : public message virtual void deserialize(std::istream &stream) override; int32_t version; + uint32_t start_packet; }; struct server_hello : public message diff --git a/network/network.cpp b/network/network.cpp index 7b98f9fd..aedd00f2 100644 --- a/network/network.cpp +++ b/network/network.cpp @@ -16,7 +16,8 @@ void network::connection::set_handler(std::function hand message_handler = handler; } -network::connection::connection(bool client) { +network::connection::connection(bool client, size_t counter) { + packet_counter = counter; is_client = client; state = AWAITING_HELLO; } @@ -28,10 +29,47 @@ void network::connection::connected() if (is_client) { client_hello msg; msg.version = 1; + msg.start_packet = packet_counter; send_message(msg); } } +void network::connection::catch_up() +{ + backbuffer->seekg(backbuffer_pos); + + std::vector> messages; + + for (size_t i = 0; i < CATCHUP_PACKETS; i++) { + if (backbuffer->peek() == EOF) { + send_messages(messages); + backbuffer->seekg(0, std::ios_base::end); + state = ACTIVE; + return; + } + + if (packet_counter) { + packet_counter--; + continue; + } + + messages.push_back(deserialize_message(*backbuffer.get())); + } + + send_messages(messages); + + backbuffer_pos = backbuffer->tellg(); + + backbuffer->seekg(0, std::ios_base::end); +} + +void network::connection::send_complete(std::shared_ptr buf) +{ + if (!is_client && state == CATCHING_UP) { + catch_up(); + } +} + /* if (msg->type == message::TYPE_MAX) { @@ -113,11 +151,13 @@ command_queue::commands_map network::connection::pop_commands() // server +network::server::server(std::shared_ptr buf) : backbuffer(buf) +{ + +} + void network::server::push_delta(double dt, double sync, const command_queue::commands_map &commands) { - if (dt == 0.0 && commands.empty()) - return; - frame_info msg; msg.dt = dt; msg.sync = sync; @@ -128,6 +168,11 @@ void network::server::push_delta(double dt, double sync, const command_queue::co c->send_message(msg); } +void network::server::update() +{ + +} + command_queue::commands_map network::server::pop_commands() { command_queue::commands_map map(client_commands_queue); @@ -144,9 +189,14 @@ void network::server::handle_message(connection &conn, const message &msg) } if (msg.type == message::CLIENT_HELLO) { + auto cmd = dynamic_cast(msg); + server_hello reply; reply.seed = Global.random_seed; - conn.state = connection::ACTIVE; + conn.state = connection::CATCHING_UP; + conn.backbuffer = backbuffer; + conn.backbuffer_pos = 0; + conn.packet_counter = cmd.start_packet; conn.send_message(reply); @@ -190,16 +240,18 @@ void network::client::send_commands(command_queue::commands_map commands) void network::client::handle_message(connection &conn, const message &msg) { - if (msg.type == message::TYPE_MAX) + if (msg.type >= message::TYPE_MAX) { conn.disconnect(); return; } + messages_counter++; + if (msg.type == message::SERVER_HELLO) { auto cmd = dynamic_cast(msg); - conn.state = connection::ACTIVE; + Global.random_seed = cmd.seed; Global.random_engine.seed(Global.random_seed); diff --git a/network/network.h b/network/network.h index 9bcdb1f4..0e766b0f 100644 --- a/network/network.h +++ b/network/network.h @@ -9,9 +9,15 @@ namespace network { + //m7todo: separate client/server connection class? class connection { + friend class server; + friend class client; + private: + const size_t CATCHUP_PACKETS = 100; + /* std::queue< std::pair backbuffer; + size_t backbuffer_pos; + size_t packet_counter; + + void send_complete(std::shared_ptr buf); + void catch_up(); public: std::function message_handler; virtual void connected() = 0; virtual void send_message(const message &msg) = 0; + virtual void send_messages(const std::vector> &messages) = 0; - connection(bool client = false); + connection(bool client = false, size_t counter = 0); void set_handler(std::function handler); virtual void disconnect() = 0; - virtual void send_data(std::shared_ptr buffer) = 0; enum peer_state { AWAITING_HELLO, @@ -50,6 +62,9 @@ namespace network class server { + private: + std::shared_ptr backbuffer; + protected: void handle_message(connection &conn, const message &msg); @@ -58,8 +73,10 @@ namespace network command_queue::commands_map client_commands_queue; public: + server(std::shared_ptr buf); void push_delta(double dt, double sync, const command_queue::commands_map &commands); command_queue::commands_map pop_commands(); + void update(); }; class client @@ -67,6 +84,7 @@ namespace network protected: void handle_message(connection &conn, const message &msg); std::shared_ptr conn; + size_t messages_counter = 0; std::queue< std::pair