net_connection.cpp

main 220 lines · 5.6 KB Raw
Alex Alex Commit Map Editor 18/10/2026 23:40
1//////////////////////////////////////////////////////////////////////
2// This file is part of Remere's Map Editor
3//////////////////////////////////////////////////////////////////////
4// Remere's Map Editor is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Remere's Map Editor is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//////////////////////////////////////////////////////////////////////
17
18#include "main.h"
19#include "net_connection.h"
20
21/*
22RME Server-Client Split Roadmap:
23
241. Server Project (New Linux-based project)
25 - Core Components:
26 * OTBM file loader (port from RME)
27 * SPR/DAT loaders
28 * items.otb handler
29 * Network message handler
30 * Live editing protocol
31 * Client session management
32 * Map change broadcasting
33 * Undo/Redo synchronization
34
35 - Required Features:
36 * Headless operation (no GUI)
37 * Multi-client support
38 * File change monitoring
39 * Backup system
40 * Change validation
41 * Permission system
42 * Map locking mechanism
43 * Auto-save functionality
44
452. RME Client Modifications:
46 - Remove:
47 * LiveServer class
48 * Server-side packet handlers
49 * Host/server creation UI
50 * Local map saving (server handles this)
51
52 - Modify:
53 * NetworkMessage class (client-only packets)
54 * LiveClient to handle all server communication
55 * Editor class to work in client-only mode
56 * GUI to reflect client-only status
57 * ActionQueue to forward all changes to server
58
593. Protocol Updates:
60 - New Packets:
61 * Client authentication
62 * Map region requests
63 * Change proposals
64 * Lock requests
65 * Client synchronization
66 * Server commands
67
68 - Security:
69 * Implement proper encryption
70 * Add checksum validation
71 * Session management
72 * Anti-tampering measures
73
744. Data Flow:
75 Server: Client:
76 [OTBM] <-> [Server] <---> [RME Client] <-> [GUI]
77 [items.otb] ^ ^
78 [spr/dat] | |
79 +----------------+
80 Network Protocol
81
82Implementation Priority:
831. Create basic server project structure
842. Port core file handlers to server
853. Implement basic client-server protocol
864. Remove server code from RME
875. Add security features
886. Implement advanced features
897. Testing and optimization
90
91Note: This requires significant restructuring of the RME codebase
92and careful handling of backwards compatibility for offline editing.
93*/
94
95NetworkMessage::NetworkMessage() {
96 clear();
97}
98
99void NetworkMessage::clear() {
100 buffer.resize(4);
101 position = 4;
102 size = 0;
103}
104
105void NetworkMessage::expand(const size_t length) {
106 if (position + length >= buffer.size()) {
107 buffer.resize(position + length + 1);
108 }
109 size += length;
110}
111
112template <>
113std::string NetworkMessage::read<std::string>() {
114 const uint16_t length = read<uint16_t>();
115
116 // Check if we have enough data for the string
117 if (position + length > buffer.size()) {
118 throw std::runtime_error("Buffer underflow - string length exceeds remaining buffer size");
119 }
120
121 char* strBuffer = reinterpret_cast<char*>(&buffer[position]);
122 position += length;
123 return std::string(strBuffer, length);
124}
125
126template <>
127Position NetworkMessage::read<Position>() {
128 Position position;
129 position.x = read<uint16_t>();
130 position.y = read<uint16_t>();
131 position.z = read<uint8_t>();
132 return position;
133}
134
135template <>
136void NetworkMessage::write<std::string>(const std::string& value) {
137 const size_t length = value.length();
138 write<uint16_t>(length);
139
140 expand(length);
141 memcpy(&buffer[position], &value[0], length);
142 position += length;
143}
144
145template <>
146void NetworkMessage::write<Position>(const Position& value) {
147 write<uint16_t>(value.x);
148 write<uint16_t>(value.y);
149 write<uint8_t>(value.z);
150}
151
152// NetworkConnection
153NetworkConnection::NetworkConnection() :
154 service(nullptr), thread(), stopped(false) {
155 //
156}
157
158NetworkConnection::~NetworkConnection() {
159 stop();
160}
161
162NetworkConnection& NetworkConnection::getInstance() {
163 static NetworkConnection connection;
164 return connection;
165}
166
167bool NetworkConnection::start() {
168 if (thread.joinable()) {
169 if (stopped) {
170 return false;
171 }
172 return true;
173 }
174
175 stopped = false;
176 if (!service) {
177 service = new boost::asio::io_context;
178 }
179
180 thread = std::thread([this]() -> void {
181 boost::asio::io_context& serviceRef = *service;
182 // Create a work guard to keep the context alive even when there are no pending handlers
183 boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work =
184 boost::asio::make_work_guard(serviceRef);
185
186 try {
187 while (!stopped) {
188 // Run one handler at a time
189 serviceRef.run_one();
190
191 // Instead of reset, just check if we should continue
192 if (serviceRef.stopped() && !stopped) {
193 // If the service stopped but we didn't request it, restart it
194 serviceRef.restart();
195 }
196 }
197 } catch (std::exception& e) {
198 std::cout << e.what() << std::endl;
199 }
200 });
201 return true;
202}
203
204void NetworkConnection::stop() {
205 if (!service) {
206 return;
207 }
208
209 service->stop();
210 stopped = true;
211 thread.join();
212
213 delete service;
214 service = nullptr;
215}
216
217boost::asio::io_context& NetworkConnection::get_service() {
218 return *service;
219}
220
Top