////////////////////////////////////////////////////////////////////// // This file is part of Remere's Map Editor ////////////////////////////////////////////////////////////////////// // Remere's Map Editor is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Remere's Map Editor is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . ////////////////////////////////////////////////////////////////////// #include "main.h" #include "net_connection.h" /* RME Server-Client Split Roadmap: 1. Server Project (New Linux-based project) - Core Components: * OTBM file loader (port from RME) * SPR/DAT loaders * items.otb handler * Network message handler * Live editing protocol * Client session management * Map change broadcasting * Undo/Redo synchronization - Required Features: * Headless operation (no GUI) * Multi-client support * File change monitoring * Backup system * Change validation * Permission system * Map locking mechanism * Auto-save functionality 2. RME Client Modifications: - Remove: * LiveServer class * Server-side packet handlers * Host/server creation UI * Local map saving (server handles this) - Modify: * NetworkMessage class (client-only packets) * LiveClient to handle all server communication * Editor class to work in client-only mode * GUI to reflect client-only status * ActionQueue to forward all changes to server 3. Protocol Updates: - New Packets: * Client authentication * Map region requests * Change proposals * Lock requests * Client synchronization * Server commands - Security: * Implement proper encryption * Add checksum validation * Session management * Anti-tampering measures 4. Data Flow: Server: Client: [OTBM] <-> [Server] <---> [RME Client] <-> [GUI] [items.otb] ^ ^ [spr/dat] | | +----------------+ Network Protocol Implementation Priority: 1. Create basic server project structure 2. Port core file handlers to server 3. Implement basic client-server protocol 4. Remove server code from RME 5. Add security features 6. Implement advanced features 7. Testing and optimization Note: This requires significant restructuring of the RME codebase and careful handling of backwards compatibility for offline editing. */ NetworkMessage::NetworkMessage() { clear(); } void NetworkMessage::clear() { buffer.resize(4); position = 4; size = 0; } void NetworkMessage::expand(const size_t length) { if (position + length >= buffer.size()) { buffer.resize(position + length + 1); } size += length; } template <> std::string NetworkMessage::read() { const uint16_t length = read(); // Check if we have enough data for the string if (position + length > buffer.size()) { throw std::runtime_error("Buffer underflow - string length exceeds remaining buffer size"); } char* strBuffer = reinterpret_cast(&buffer[position]); position += length; return std::string(strBuffer, length); } template <> Position NetworkMessage::read() { Position position; position.x = read(); position.y = read(); position.z = read(); return position; } template <> void NetworkMessage::write(const std::string& value) { const size_t length = value.length(); write(length); expand(length); memcpy(&buffer[position], &value[0], length); position += length; } template <> void NetworkMessage::write(const Position& value) { write(value.x); write(value.y); write(value.z); } // NetworkConnection NetworkConnection::NetworkConnection() : service(nullptr), thread(), stopped(false) { // } NetworkConnection::~NetworkConnection() { stop(); } NetworkConnection& NetworkConnection::getInstance() { static NetworkConnection connection; return connection; } bool NetworkConnection::start() { if (thread.joinable()) { if (stopped) { return false; } return true; } stopped = false; if (!service) { service = new boost::asio::io_context; } thread = std::thread([this]() -> void { boost::asio::io_context& serviceRef = *service; // Create a work guard to keep the context alive even when there are no pending handlers boost::asio::executor_work_guard work = boost::asio::make_work_guard(serviceRef); try { while (!stopped) { // Run one handler at a time serviceRef.run_one(); // Instead of reset, just check if we should continue if (serviceRef.stopped() && !stopped) { // If the service stopped but we didn't request it, restart it serviceRef.restart(); } } } catch (std::exception& e) { std::cout << e.what() << std::endl; } }); return true; } void NetworkConnection::stop() { if (!service) { return; } service->stop(); stopped = true; thread.join(); delete service; service = nullptr; } boost::asio::io_context& NetworkConnection::get_service() { return *service; }