1 #include "Message.h"
2
3 #include "../combat/CombatLogManager.h"
4 #include "../Empire/EmpireManager.h"
5 #include "../Empire/Supply.h"
6 #include "../Empire/Diplomacy.h"
7 #include "../util/Logger.h"
8 #include "../util/ModeratorAction.h"
9 #include "../util/SaveGamePreviewUtils.h"
10 #include "../universe/Species.h"
11 #include "../universe/Universe.h"
12 #include "../util/OptionsDB.h"
13 #include "../util/OrderSet.h"
14 #include "../util/Serialize.h"
15 #include "../util/ScopedTimer.h"
16 #include "../util/i18n.h"
17 #include "../util/Version.h"
18 #include <boost/algorithm/string/erase.hpp>
19 #include <boost/algorithm/string/predicate.hpp>
20 #include <boost/serialization/deque.hpp>
21 #include <boost/serialization/list.hpp>
22 #include <boost/serialization/map.hpp>
23 #include <boost/serialization/set.hpp>
24 #include <boost/serialization/vector.hpp>
25 #include <boost/serialization/weak_ptr.hpp>
26 #include <boost/date_time/posix_time/time_serialize.hpp>
27 #include <boost/uuid/uuid_serialize.hpp>
28 #include <boost/uuid/uuid_io.hpp>
29
30 #include <zlib.h>
31
32 #include <iostream>
33 #include <stdexcept>
34 #include <sstream>
35 #include <map>
36
37
38 namespace {
39 const std::string DUMMY_EMPTY_MESSAGE = "Lathanda";
40 }
41
42 ////////////////////////////////////////////////
43 // Free Functions
44 ////////////////////////////////////////////////
operator <<(std::ostream & os,const Message & msg)45 std::ostream& operator<<(std::ostream& os, const Message& msg) {
46 os << "Message: "
47 << msg.Type();
48
49 os << " \"" << msg.Text() << "\"\n";
50
51 return os;
52 }
53
54
55 ////////////////////////////////////////////////
56 // Message
57 ////////////////////////////////////////////////
Message()58 Message::Message() :
59 m_type(UNDEFINED),
60 m_message_size(0),
61 m_message_text()
62 {}
63
Message(MessageType type,const std::string & text)64 Message::Message(MessageType type,
65 const std::string& text) :
66 m_type(type),
67 m_message_size(text.size()),
68 m_message_text(new char[text.size()])
69 { std::copy(text.begin(), text.end(), m_message_text.get()); }
70
Type() const71 Message::MessageType Message::Type() const
72 { return m_type; }
73
Size() const74 std::size_t Message::Size() const
75 { return m_message_size; }
76
Data() const77 const char* Message::Data() const
78 { return m_message_text.get(); }
79
Text() const80 std::string Message::Text() const
81 { return std::string(m_message_text.get(), m_message_size); }
82
Resize(std::size_t size)83 void Message::Resize(std::size_t size) {
84 m_message_size = size;
85 m_message_text.reset(new char[m_message_size]);
86 }
87
Data()88 char* Message::Data()
89 { return m_message_text.get(); }
90
Swap(Message & rhs)91 void Message::Swap(Message& rhs) {
92 std::swap(m_type, rhs.m_type);
93 std::swap(m_message_size, rhs.m_message_size);
94 std::swap(m_message_text, rhs.m_message_text);
95 }
96
operator ==(const Message & lhs,const Message & rhs)97 bool operator==(const Message& lhs, const Message& rhs) {
98 return
99 lhs.Type() == rhs.Type() &&
100 lhs.Text() == rhs.Text();
101 }
102
operator !=(const Message & lhs,const Message & rhs)103 bool operator!=(const Message& lhs, const Message& rhs)
104 { return !(lhs == rhs); }
105
swap(Message & lhs,Message & rhs)106 void swap(Message& lhs, Message& rhs)
107 { lhs.Swap(rhs); }
108
BufferToHeader(const Message::HeaderBuffer & buffer,Message & message)109 void BufferToHeader(const Message::HeaderBuffer& buffer, Message& message) {
110 message.m_type = static_cast<Message::MessageType>(buffer[Message::Parts::TYPE]);
111 message.m_message_size = buffer[Message::Parts::SIZE];
112 }
113
HeaderToBuffer(const Message & message,Message::HeaderBuffer & buffer)114 void HeaderToBuffer(const Message& message, Message::HeaderBuffer& buffer) {
115 buffer[Message::Parts::TYPE] = message.Type();
116 buffer[Message::Parts::SIZE] = message.Size();
117 }
118
119 ////////////////////////////////////////////////
120 // Message named ctors
121 ////////////////////////////////////////////////
ErrorMessage(const std::string & problem,bool fatal,int player_id)122 Message ErrorMessage(const std::string& problem, bool fatal/* = true*/,
123 int player_id/* = Networking::INVALID_PLAYER_ID*/) {
124 std::ostringstream os;
125 {
126 freeorion_xml_oarchive oa(os);
127 oa << BOOST_SERIALIZATION_NVP(problem)
128 << BOOST_SERIALIZATION_NVP(fatal)
129 << BOOST_SERIALIZATION_NVP(player_id);
130 }
131 return Message(Message::ERROR_MSG, os.str());
132 }
133
HostSPGameMessage(const SinglePlayerSetupData & setup_data)134 Message HostSPGameMessage(const SinglePlayerSetupData& setup_data) {
135 std::ostringstream os;
136 {
137 std::string client_version_string = FreeOrionVersionString();
138 freeorion_xml_oarchive oa(os);
139 oa << BOOST_SERIALIZATION_NVP(setup_data)
140 << BOOST_SERIALIZATION_NVP(client_version_string);
141 }
142 return Message(Message::HOST_SP_GAME, os.str());
143 }
144
HostMPGameMessage(const std::string & host_player_name)145 Message HostMPGameMessage(const std::string& host_player_name)
146 {
147 std::ostringstream os;
148 {
149 std::string client_version_string = FreeOrionVersionString();
150 freeorion_xml_oarchive oa(os);
151 oa << BOOST_SERIALIZATION_NVP(host_player_name)
152 << BOOST_SERIALIZATION_NVP(client_version_string);
153 }
154 return Message(Message::HOST_MP_GAME, os.str());
155 }
156
JoinGameMessage(const std::string & player_name,Networking::ClientType client_type,boost::uuids::uuid cookie)157 Message JoinGameMessage(const std::string& player_name,
158 Networking::ClientType client_type,
159 boost::uuids::uuid cookie) {
160 std::ostringstream os;
161 {
162 freeorion_xml_oarchive oa(os);
163 std::string client_version_string = FreeOrionVersionString();
164 oa << BOOST_SERIALIZATION_NVP(player_name)
165 << BOOST_SERIALIZATION_NVP(client_type)
166 << BOOST_SERIALIZATION_NVP(client_version_string)
167 << BOOST_SERIALIZATION_NVP(cookie);
168 }
169 return Message(Message::JOIN_GAME, os.str());
170 }
171
HostIDMessage(int host_player_id)172 Message HostIDMessage(int host_player_id) {
173 return Message(Message::HOST_ID,
174 std::to_string(host_player_id));
175 }
176
GameStartMessage(bool single_player_game,int empire_id,int current_turn,const EmpireManager & empires,const Universe & universe,const SpeciesManager & species,CombatLogManager & combat_logs,const SupplyManager & supply,const std::map<int,PlayerInfo> & players,GalaxySetupData galaxy_setup_data,bool use_binary_serialization)177 Message GameStartMessage(bool single_player_game, int empire_id,
178 int current_turn, const EmpireManager& empires,
179 const Universe& universe, const SpeciesManager& species,
180 CombatLogManager& combat_logs, const SupplyManager& supply,
181 const std::map<int, PlayerInfo>& players,
182 GalaxySetupData galaxy_setup_data,
183 bool use_binary_serialization)
184 {
185 std::ostringstream os;
186 {
187 if (use_binary_serialization) {
188 freeorion_bin_oarchive oa(os);
189 oa << BOOST_SERIALIZATION_NVP(single_player_game)
190 << BOOST_SERIALIZATION_NVP(empire_id)
191 << BOOST_SERIALIZATION_NVP(current_turn);
192 GetUniverse().EncodingEmpire() = empire_id;
193 oa << BOOST_SERIALIZATION_NVP(empires)
194 << BOOST_SERIALIZATION_NVP(species);
195 combat_logs.SerializeIncompleteLogs(oa, 1);
196 oa << BOOST_SERIALIZATION_NVP(supply);
197 Serialize(oa, universe);
198 bool loaded_game_data = false;
199 oa << BOOST_SERIALIZATION_NVP(players)
200 << BOOST_SERIALIZATION_NVP(loaded_game_data);
201 galaxy_setup_data.m_encoding_empire = empire_id;
202 oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
203 } else {
204 freeorion_xml_oarchive oa(os);
205 oa << BOOST_SERIALIZATION_NVP(single_player_game)
206 << BOOST_SERIALIZATION_NVP(empire_id)
207 << BOOST_SERIALIZATION_NVP(current_turn);
208 GetUniverse().EncodingEmpire() = empire_id;
209 oa << BOOST_SERIALIZATION_NVP(empires)
210 << BOOST_SERIALIZATION_NVP(species);
211 combat_logs.SerializeIncompleteLogs(oa, 1);
212 oa << BOOST_SERIALIZATION_NVP(supply);
213 Serialize(oa, universe);
214 bool loaded_game_data = false;
215 oa << BOOST_SERIALIZATION_NVP(players)
216 << BOOST_SERIALIZATION_NVP(loaded_game_data);
217 galaxy_setup_data.m_encoding_empire = empire_id;
218 oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
219 }
220 }
221 return Message(Message::GAME_START, os.str());
222 }
223
GameStartMessage(bool single_player_game,int empire_id,int current_turn,const EmpireManager & empires,const Universe & universe,const SpeciesManager & species,CombatLogManager & combat_logs,const SupplyManager & supply,const std::map<int,PlayerInfo> & players,const OrderSet & orders,const SaveGameUIData * ui_data,GalaxySetupData galaxy_setup_data,bool use_binary_serialization)224 Message GameStartMessage(bool single_player_game, int empire_id,
225 int current_turn, const EmpireManager& empires,
226 const Universe& universe, const SpeciesManager& species,
227 CombatLogManager& combat_logs, const SupplyManager& supply,
228 const std::map<int, PlayerInfo>& players,
229 const OrderSet& orders, const SaveGameUIData* ui_data,
230 GalaxySetupData galaxy_setup_data,
231 bool use_binary_serialization)
232 {
233 std::ostringstream os;
234 {
235 if (use_binary_serialization) {
236 freeorion_bin_oarchive oa(os);
237 oa << BOOST_SERIALIZATION_NVP(single_player_game)
238 << BOOST_SERIALIZATION_NVP(empire_id)
239 << BOOST_SERIALIZATION_NVP(current_turn);
240 GetUniverse().EncodingEmpire() = empire_id;
241 oa << BOOST_SERIALIZATION_NVP(empires)
242 << BOOST_SERIALIZATION_NVP(species);
243 combat_logs.SerializeIncompleteLogs(oa, 1);
244 oa << BOOST_SERIALIZATION_NVP(supply);
245 Serialize(oa, universe);
246 bool loaded_game_data = true;
247 oa << BOOST_SERIALIZATION_NVP(players)
248 << BOOST_SERIALIZATION_NVP(loaded_game_data);
249 Serialize(oa, orders);
250 bool ui_data_available = (ui_data != nullptr);
251 oa << BOOST_SERIALIZATION_NVP(ui_data_available);
252 if (ui_data_available)
253 oa << boost::serialization::make_nvp("ui_data", *ui_data);
254 bool save_state_string_available = false;
255 oa << BOOST_SERIALIZATION_NVP(save_state_string_available);
256 galaxy_setup_data.m_encoding_empire = empire_id;
257 oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
258 } else {
259 freeorion_xml_oarchive oa(os);
260 oa << BOOST_SERIALIZATION_NVP(single_player_game)
261 << BOOST_SERIALIZATION_NVP(empire_id)
262 << BOOST_SERIALIZATION_NVP(current_turn);
263 GetUniverse().EncodingEmpire() = empire_id;
264 oa << BOOST_SERIALIZATION_NVP(empires)
265 << BOOST_SERIALIZATION_NVP(species);
266 combat_logs.SerializeIncompleteLogs(oa, 1);
267 oa << BOOST_SERIALIZATION_NVP(supply);
268 Serialize(oa, universe);
269 bool loaded_game_data = true;
270 oa << BOOST_SERIALIZATION_NVP(players)
271 << BOOST_SERIALIZATION_NVP(loaded_game_data);
272 Serialize(oa, orders);
273 bool ui_data_available = (ui_data != nullptr);
274 oa << BOOST_SERIALIZATION_NVP(ui_data_available);
275 if (ui_data_available) {
276 if (ui_data) {
277 oa << boost::serialization::make_nvp("ui_data", *ui_data);
278 } else {
279 ErrorLogger() << "GameStartMessage expected UI data but it was nullptr";
280 SaveGameUIData temp_UI_data;
281 oa << boost::serialization::make_nvp("ui_data", temp_UI_data);
282 }
283 }
284 bool save_state_string_available = false;
285 oa << BOOST_SERIALIZATION_NVP(save_state_string_available);
286 galaxy_setup_data.m_encoding_empire = empire_id;
287 oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
288 }
289 }
290 return Message(Message::GAME_START, os.str());
291 }
292
GameStartMessage(bool single_player_game,int empire_id,int current_turn,const EmpireManager & empires,const Universe & universe,const SpeciesManager & species,CombatLogManager & combat_logs,const SupplyManager & supply,const std::map<int,PlayerInfo> & players,const OrderSet & orders,const std::string * save_state_string,GalaxySetupData galaxy_setup_data,bool use_binary_serialization)293 Message GameStartMessage(bool single_player_game, int empire_id,
294 int current_turn, const EmpireManager& empires,
295 const Universe& universe, const SpeciesManager& species,
296 CombatLogManager& combat_logs, const SupplyManager& supply,
297 const std::map<int, PlayerInfo>& players,
298 const OrderSet& orders, const std::string* save_state_string,
299 GalaxySetupData galaxy_setup_data,
300 bool use_binary_serialization)
301 {
302 std::ostringstream os;
303 {
304 if (use_binary_serialization) {
305 freeorion_bin_oarchive oa(os);
306 oa << BOOST_SERIALIZATION_NVP(single_player_game)
307 << BOOST_SERIALIZATION_NVP(empire_id)
308 << BOOST_SERIALIZATION_NVP(current_turn);
309 GetUniverse().EncodingEmpire() = empire_id;
310 oa << BOOST_SERIALIZATION_NVP(empires)
311 << BOOST_SERIALIZATION_NVP(species);
312 combat_logs.SerializeIncompleteLogs(oa, 1);
313 oa << BOOST_SERIALIZATION_NVP(supply);
314 Serialize(oa, universe);
315 bool loaded_game_data = true;
316 oa << BOOST_SERIALIZATION_NVP(players)
317 << BOOST_SERIALIZATION_NVP(loaded_game_data);
318 Serialize(oa, orders);
319 bool ui_data_available = false;
320 oa << BOOST_SERIALIZATION_NVP(ui_data_available);
321 bool save_state_string_available = (save_state_string != nullptr);
322 oa << BOOST_SERIALIZATION_NVP(save_state_string_available);
323 if (save_state_string_available)
324 oa << boost::serialization::make_nvp("save_state_string", *save_state_string);
325 galaxy_setup_data.m_encoding_empire = empire_id;
326 oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
327 } else {
328 freeorion_xml_oarchive oa(os);
329 oa << BOOST_SERIALIZATION_NVP(single_player_game)
330 << BOOST_SERIALIZATION_NVP(empire_id)
331 << BOOST_SERIALIZATION_NVP(current_turn);
332 GetUniverse().EncodingEmpire() = empire_id;
333 oa << BOOST_SERIALIZATION_NVP(empires)
334 << BOOST_SERIALIZATION_NVP(species);
335 combat_logs.SerializeIncompleteLogs(oa, 1);
336 oa << BOOST_SERIALIZATION_NVP(supply);
337 Serialize(oa, universe);
338 bool loaded_game_data = true;
339 oa << BOOST_SERIALIZATION_NVP(players)
340 << BOOST_SERIALIZATION_NVP(loaded_game_data);
341 Serialize(oa, orders);
342 bool ui_data_available = false;
343 oa << BOOST_SERIALIZATION_NVP(ui_data_available);
344 bool save_state_string_available = (save_state_string != nullptr);
345 oa << BOOST_SERIALIZATION_NVP(save_state_string_available);
346 if (save_state_string_available) {
347 if (save_state_string) {
348 oa << boost::serialization::make_nvp("save_state_string", *save_state_string);
349 } else {
350 ErrorLogger() << "GameStartMessage expectes save_state_string but it was nullptr";
351 std::string temp_sss;
352 oa << boost::serialization::make_nvp("save_state_string", temp_sss);
353 }
354 }
355 galaxy_setup_data.m_encoding_empire = empire_id;
356 oa << BOOST_SERIALIZATION_NVP(galaxy_setup_data);
357 }
358 }
359 return Message(Message::GAME_START, os.str());
360 }
361
HostSPAckMessage(int player_id)362 Message HostSPAckMessage(int player_id)
363 { return Message(Message::HOST_SP_GAME, std::to_string(player_id)); }
364
HostMPAckMessage(int player_id)365 Message HostMPAckMessage(int player_id)
366 { return Message(Message::HOST_MP_GAME, std::to_string(player_id)); }
367
JoinAckMessage(int player_id,boost::uuids::uuid cookie)368 Message JoinAckMessage(int player_id, boost::uuids::uuid cookie)
369 {
370 std::ostringstream os;
371 {
372 freeorion_xml_oarchive oa(os);
373 oa << BOOST_SERIALIZATION_NVP(player_id)
374 << BOOST_SERIALIZATION_NVP(cookie);
375 }
376 return Message(Message::JOIN_GAME, os.str());
377 }
378
TurnOrdersMessage(const OrderSet & orders,const SaveGameUIData & ui_data)379 Message TurnOrdersMessage(const OrderSet& orders, const SaveGameUIData& ui_data) {
380 std::ostringstream os;
381 {
382 freeorion_xml_oarchive oa(os);
383 Serialize(oa, orders);
384 bool ui_data_available = true;
385 bool save_state_string_available = false;
386 oa << BOOST_SERIALIZATION_NVP(ui_data_available)
387 << BOOST_SERIALIZATION_NVP(ui_data)
388 << BOOST_SERIALIZATION_NVP(save_state_string_available);
389 }
390 return Message(Message::TURN_ORDERS, os.str());
391 }
392
TurnOrdersMessage(const OrderSet & orders,const std::string & save_state_string)393 Message TurnOrdersMessage(const OrderSet& orders, const std::string& save_state_string) {
394 std::ostringstream os;
395 {
396 freeorion_xml_oarchive oa(os);
397 Serialize(oa, orders);
398 bool ui_data_available = false;
399 bool save_state_string_available = true;
400 oa << BOOST_SERIALIZATION_NVP(ui_data_available)
401 << BOOST_SERIALIZATION_NVP(save_state_string_available)
402 << BOOST_SERIALIZATION_NVP(save_state_string);
403 }
404 return Message(Message::TURN_ORDERS, os.str());
405 }
406
TurnPartialOrdersMessage(const std::pair<OrderSet,std::set<int>> & orders_updates)407 Message TurnPartialOrdersMessage(const std::pair<OrderSet, std::set<int>>& orders_updates) {
408 std::ostringstream os;
409 {
410 freeorion_xml_oarchive oa(os);
411 Serialize(oa, orders_updates.first);
412 oa << boost::serialization::make_nvp("deleted", orders_updates.second);
413 }
414 return Message(Message::TURN_PARTIAL_ORDERS, os.str());
415 }
416
TurnTimeoutMessage(int timeout_remaining)417 Message TurnTimeoutMessage(int timeout_remaining)
418 { return Message(Message::TURN_TIMEOUT, std::to_string(timeout_remaining)); }
419
TurnProgressMessage(Message::TurnProgressPhase phase_id)420 Message TurnProgressMessage(Message::TurnProgressPhase phase_id) {
421 std::ostringstream os;
422 {
423 freeorion_xml_oarchive oa(os);
424 oa << BOOST_SERIALIZATION_NVP(phase_id);
425 }
426 return Message(Message::TURN_PROGRESS, os.str());
427 }
428
PlayerStatusMessage(Message::PlayerStatus player_status,int about_empire_id)429 Message PlayerStatusMessage(Message::PlayerStatus player_status,
430 int about_empire_id)
431 {
432 std::ostringstream os;
433 {
434 freeorion_xml_oarchive oa(os);
435 oa << BOOST_SERIALIZATION_NVP(player_status)
436 << BOOST_SERIALIZATION_NVP(about_empire_id);
437 }
438 return Message(Message::PLAYER_STATUS, os.str());
439 }
440
TurnUpdateMessage(int empire_id,int current_turn,const EmpireManager & empires,const Universe & universe,const SpeciesManager & species,CombatLogManager & combat_logs,const SupplyManager & supply,const std::map<int,PlayerInfo> & players,bool use_binary_serialization)441 Message TurnUpdateMessage(int empire_id, int current_turn,
442 const EmpireManager& empires, const Universe& universe,
443 const SpeciesManager& species, CombatLogManager& combat_logs,
444 const SupplyManager& supply,
445 const std::map<int, PlayerInfo>& players,
446 bool use_binary_serialization)
447 {
448 std::ostringstream os;
449 {
450 if (use_binary_serialization) {
451 freeorion_bin_oarchive oa(os);
452 GetUniverse().EncodingEmpire() = empire_id;
453 oa << BOOST_SERIALIZATION_NVP(current_turn);
454 oa << BOOST_SERIALIZATION_NVP(empires);
455 oa << BOOST_SERIALIZATION_NVP(species);
456 combat_logs.SerializeIncompleteLogs(oa, 1);
457 oa << BOOST_SERIALIZATION_NVP(supply);
458 Serialize(oa, universe);
459 oa << BOOST_SERIALIZATION_NVP(players);
460 } else {
461 freeorion_xml_oarchive oa(os);
462 GetUniverse().EncodingEmpire() = empire_id;
463 oa << BOOST_SERIALIZATION_NVP(current_turn)
464 << BOOST_SERIALIZATION_NVP(empires)
465 << BOOST_SERIALIZATION_NVP(species);
466 combat_logs.SerializeIncompleteLogs(oa, 1);
467 oa << BOOST_SERIALIZATION_NVP(supply);
468 Serialize(oa, universe);
469 oa << BOOST_SERIALIZATION_NVP(players);
470 }
471 }
472 return Message(Message::TURN_UPDATE, os.str());
473 }
474
TurnPartialUpdateMessage(int empire_id,const Universe & universe,bool use_binary_serialization)475 Message TurnPartialUpdateMessage(int empire_id, const Universe& universe,
476 bool use_binary_serialization) {
477 std::ostringstream os;
478 {
479 if (use_binary_serialization) {
480 freeorion_bin_oarchive oa(os);
481 GetUniverse().EncodingEmpire() = empire_id;
482 Serialize(oa, universe);
483 } else {
484 freeorion_xml_oarchive oa(os);
485 GetUniverse().EncodingEmpire() = empire_id;
486 Serialize(oa, universe);
487 }
488 }
489 return Message(Message::TURN_PARTIAL_UPDATE, os.str());
490 }
491
HostSaveGameInitiateMessage(const std::string & filename)492 Message HostSaveGameInitiateMessage(const std::string& filename)
493 { return Message(Message::SAVE_GAME_INITIATE, filename); }
494
ServerSaveGameCompleteMessage(const std::string & save_filename,int bytes_written)495 Message ServerSaveGameCompleteMessage(const std::string& save_filename, int bytes_written) {
496 std::ostringstream os;
497 {
498 freeorion_xml_oarchive oa(os);
499 oa << BOOST_SERIALIZATION_NVP(save_filename)
500 << BOOST_SERIALIZATION_NVP(bytes_written);
501 }
502 return Message(Message::SAVE_GAME_COMPLETE, os.str());
503 }
504
DiplomacyMessage(const DiplomaticMessage & diplo_message)505 Message DiplomacyMessage(const DiplomaticMessage& diplo_message) {
506 std::ostringstream os;
507 {
508 freeorion_xml_oarchive oa(os);
509 oa << BOOST_SERIALIZATION_NVP(diplo_message);
510 }
511 return Message(Message::DIPLOMACY, os.str());
512 }
513
DiplomaticStatusMessage(const DiplomaticStatusUpdateInfo & diplo_update)514 Message DiplomaticStatusMessage(const DiplomaticStatusUpdateInfo& diplo_update) {
515 std::ostringstream os;
516 {
517 freeorion_xml_oarchive oa(os);
518 oa << BOOST_SERIALIZATION_NVP(diplo_update.empire1_id)
519 << BOOST_SERIALIZATION_NVP(diplo_update.empire2_id)
520 << BOOST_SERIALIZATION_NVP(diplo_update.diplo_status);
521 }
522 return Message(Message::DIPLOMATIC_STATUS, os.str());
523 }
524
EndGameMessage(Message::EndGameReason reason,const std::string & reason_player_name)525 Message EndGameMessage(Message::EndGameReason reason,
526 const std::string& reason_player_name/* = ""*/)
527 {
528 std::ostringstream os;
529 {
530 freeorion_xml_oarchive oa(os);
531 oa << BOOST_SERIALIZATION_NVP(reason)
532 << BOOST_SERIALIZATION_NVP(reason_player_name);
533 }
534 return Message(Message::END_GAME, os.str());
535 }
536
AIEndGameAcknowledgeMessage()537 Message AIEndGameAcknowledgeMessage()
538 { return Message(Message::AI_END_GAME_ACK, DUMMY_EMPTY_MESSAGE); }
539
ModeratorActionMessage(const Moderator::ModeratorAction & action)540 Message ModeratorActionMessage(const Moderator::ModeratorAction& action) {
541 std::ostringstream os;
542 {
543 const Moderator::ModeratorAction* mod_action = &action;
544 freeorion_xml_oarchive oa(os);
545 oa << BOOST_SERIALIZATION_NVP(mod_action);
546 }
547 return Message(Message::MODERATOR_ACTION, os.str());
548 }
549
ShutdownServerMessage()550 Message ShutdownServerMessage()
551 { return Message(Message::SHUT_DOWN_SERVER, DUMMY_EMPTY_MESSAGE); }
552
553 /** requests previews of savefiles from server synchronously */
RequestSavePreviewsMessage(std::string relative_directory)554 Message RequestSavePreviewsMessage(std::string relative_directory)
555 { return Message(Message::REQUEST_SAVE_PREVIEWS, relative_directory); }
556
557 /** returns the savegame previews to the client */
DispatchSavePreviewsMessage(const PreviewInformation & previews)558 Message DispatchSavePreviewsMessage(const PreviewInformation& previews) {
559 std::ostringstream os;
560 {
561 freeorion_xml_oarchive oa(os);
562 oa << BOOST_SERIALIZATION_NVP(previews);
563 }
564 return Message(Message::DISPATCH_SAVE_PREVIEWS, os.str());
565 }
566
RequestCombatLogsMessage(const std::vector<int> & ids)567 Message RequestCombatLogsMessage(const std::vector<int>& ids) {
568 std::ostringstream os;
569 {
570 freeorion_xml_oarchive oa(os);
571 oa << BOOST_SERIALIZATION_NVP(ids);
572 }
573 return Message(Message::REQUEST_COMBAT_LOGS, os.str());
574 }
575
DispatchCombatLogsMessage(const std::vector<std::pair<int,const CombatLog>> & logs,bool use_binary_serialization)576 Message DispatchCombatLogsMessage(const std::vector<std::pair<int, const CombatLog>>& logs,
577 bool use_binary_serialization)
578 {
579 std::ostringstream os;
580 {
581 try {
582 if (use_binary_serialization) {
583 freeorion_bin_oarchive oa(os);
584 oa << BOOST_SERIALIZATION_NVP(logs);
585 } else {
586 freeorion_xml_oarchive oa(os);
587 oa << BOOST_SERIALIZATION_NVP(logs);
588 }
589 } catch (const std::exception& e) {
590 ErrorLogger() << "Caught exception serializing combat logs: " << e.what();
591 }
592 }
593
594 return Message(Message::DISPATCH_COMBAT_LOGS, os.str());
595 }
596
LoggerConfigMessage(int sender,const std::set<std::tuple<std::string,std::string,LogLevel>> & options)597 Message LoggerConfigMessage(int sender, const std::set<std::tuple<std::string, std::string, LogLevel>>& options) {
598 std::ostringstream os;
599 {
600 freeorion_xml_oarchive oa(os);
601 std::size_t size = options.size();
602 oa << BOOST_SERIALIZATION_NVP(size);
603 for (const auto& option_tuple : options) {
604 auto option = std::get<0>(option_tuple);
605 auto name = std::get<1>(option_tuple);
606 auto value = std::get<2>(option_tuple);
607 oa << BOOST_SERIALIZATION_NVP(option);
608 oa << BOOST_SERIALIZATION_NVP(name);
609 oa << BOOST_SERIALIZATION_NVP(value);
610 }
611 }
612 return Message(Message::LOGGER_CONFIG, os.str());
613 }
614
615 ////////////////////////////////////////////////
616 // Multiplayer Lobby Message named ctors
617 ////////////////////////////////////////////////
LobbyUpdateMessage(const MultiplayerLobbyData & lobby_data)618 Message LobbyUpdateMessage(const MultiplayerLobbyData& lobby_data) {
619 std::ostringstream os;
620 {
621 freeorion_xml_oarchive oa(os);
622 oa << BOOST_SERIALIZATION_NVP(lobby_data);
623 }
624 return Message(Message::LOBBY_UPDATE, os.str());
625 }
626
ServerLobbyUpdateMessage(const MultiplayerLobbyData & lobby_data)627 Message ServerLobbyUpdateMessage(const MultiplayerLobbyData& lobby_data) {
628 std::ostringstream os;
629 {
630 freeorion_xml_oarchive oa(os);
631 oa << BOOST_SERIALIZATION_NVP(lobby_data);
632 }
633 return Message(Message::LOBBY_UPDATE, os.str());
634 }
635
ChatHistoryMessage(const std::vector<std::reference_wrapper<const ChatHistoryEntity>> & chat_history)636 Message ChatHistoryMessage(const std::vector<std::reference_wrapper<const ChatHistoryEntity>>& chat_history) {
637 std::ostringstream os;
638 {
639 freeorion_xml_oarchive oa(os);
640 std::size_t size = chat_history.size();
641 oa << BOOST_SERIALIZATION_NVP(size);
642 for (const auto& elem : chat_history) {
643 oa << boost::serialization::make_nvp(BOOST_PP_STRINGIZE(elem), elem.get());
644 }
645 }
646 return Message(Message::CHAT_HISTORY, os.str());
647 }
648
PlayerChatMessage(const std::string & data,std::set<int> recipients,bool pm)649 Message PlayerChatMessage(const std::string& data, std::set<int> recipients, bool pm) {
650 std::ostringstream os;
651 {
652 freeorion_xml_oarchive oa(os);
653 oa << BOOST_SERIALIZATION_NVP(recipients)
654 << BOOST_SERIALIZATION_NVP(data)
655 << BOOST_SERIALIZATION_NVP(pm);
656 }
657 return Message(Message::PLAYER_CHAT, os.str());
658 }
659
ServerPlayerChatMessage(int sender,const boost::posix_time::ptime & timestamp,const std::string & data,bool pm)660 Message ServerPlayerChatMessage(int sender, const boost::posix_time::ptime& timestamp,
661 const std::string& data, bool pm)
662 {
663 std::ostringstream os;
664 {
665 freeorion_xml_oarchive oa(os);
666 oa << BOOST_SERIALIZATION_NVP(sender)
667 << BOOST_SERIALIZATION_NVP(timestamp)
668 << BOOST_SERIALIZATION_NVP(data)
669 << BOOST_SERIALIZATION_NVP(pm);
670 }
671 return Message(Message::PLAYER_CHAT, os.str());
672 }
673
StartMPGameMessage()674 Message StartMPGameMessage()
675 { return Message(Message::START_MP_GAME, DUMMY_EMPTY_MESSAGE); }
676
ContentCheckSumMessage()677 Message ContentCheckSumMessage() {
678 auto checksums = CheckSumContent();
679
680 std::ostringstream os;
681 {
682 freeorion_xml_oarchive oa(os);
683 oa << BOOST_SERIALIZATION_NVP(checksums);
684 }
685 return Message(Message::CHECKSUM, os.str());
686 }
687
AuthRequestMessage(const std::string & player_name,const std::string & auth)688 Message AuthRequestMessage(const std::string& player_name, const std::string& auth) {
689 std::ostringstream os;
690 {
691 freeorion_xml_oarchive oa(os);
692 oa << BOOST_SERIALIZATION_NVP(player_name)
693 << BOOST_SERIALIZATION_NVP(auth);
694 }
695 return Message(Message::AUTH_REQUEST, os.str());
696 }
697
AuthResponseMessage(const std::string & player_name,const std::string & auth)698 Message AuthResponseMessage(const std::string& player_name, const std::string& auth) {
699 std::ostringstream os;
700 {
701 freeorion_xml_oarchive oa(os);
702 oa << BOOST_SERIALIZATION_NVP(player_name)
703 << BOOST_SERIALIZATION_NVP(auth);
704 }
705 return Message(Message::AUTH_RESPONSE, os.str());
706 }
707
SetAuthorizationRolesMessage(const Networking::AuthRoles & roles)708 Message SetAuthorizationRolesMessage(const Networking::AuthRoles& roles)
709 { return Message(Message::SET_AUTH_ROLES, roles.Text()); }
710
EliminateSelfMessage()711 Message EliminateSelfMessage()
712 { return Message(Message::ELIMINATE_SELF, DUMMY_EMPTY_MESSAGE); }
713
UnreadyMessage()714 Message UnreadyMessage()
715 { return Message(Message::UNREADY, DUMMY_EMPTY_MESSAGE); }
716
PlayerInfoMessage(const std::map<int,PlayerInfo> & players)717 Message PlayerInfoMessage(const std::map<int, PlayerInfo>& players) {
718 std::ostringstream os;
719 {
720 freeorion_xml_oarchive oa(os);
721 oa << BOOST_SERIALIZATION_NVP(players);
722 }
723 return Message(Message::PLAYER_INFO, os.str());
724 }
725
726 ////////////////////////////////////////////////
727 // Message data extractors
728 ////////////////////////////////////////////////
ExtractErrorMessageData(const Message & msg,int & player_id,std::string & problem,bool & fatal)729 void ExtractErrorMessageData(const Message& msg, int& player_id, std::string& problem, bool& fatal) {
730 try {
731 std::istringstream is(msg.Text());
732 freeorion_xml_iarchive ia(is);
733 ia >> BOOST_SERIALIZATION_NVP(problem)
734 >> BOOST_SERIALIZATION_NVP(fatal)
735 >> BOOST_SERIALIZATION_NVP(player_id);
736 } catch (const std::exception& err) {
737 ErrorLogger() << "ExtractErrorMessageData(const Message& msg, std::string& problem, bool& fatal) failed! Message:\n"
738 << msg.Text() << "\n"
739 << "Error: " << err.what();
740 problem = UserStringNop("SERVER_MESSAGE_NOT_UNDERSTOOD");
741 fatal = false;
742 }
743 }
744
ExtractHostMPGameMessageData(const Message & msg,std::string & host_player_name,std::string & client_version_string)745 void ExtractHostMPGameMessageData(const Message& msg, std::string& host_player_name, std::string& client_version_string) {
746 try {
747 std::istringstream is(msg.Text());
748 freeorion_xml_iarchive ia(is);
749 ia >> BOOST_SERIALIZATION_NVP(host_player_name)
750 >> BOOST_SERIALIZATION_NVP(client_version_string);
751
752 } catch (const std::exception& err) {
753 ErrorLogger() << "ExtractHostMPGameMessageData(const Message& msg, std::string& host_player_name, std::string& client_version_string) failed! Message:\n"
754 << msg.Text() << "\n"
755 << "Error: " << err.what();
756 throw err;
757 }
758 }
759
ExtractLobbyUpdateMessageData(const Message & msg,MultiplayerLobbyData & lobby_data)760 void ExtractLobbyUpdateMessageData(const Message& msg, MultiplayerLobbyData& lobby_data) {
761 try {
762 std::istringstream is(msg.Text());
763 freeorion_xml_iarchive ia(is);
764 ia >> BOOST_SERIALIZATION_NVP(lobby_data);
765
766 } catch (const std::exception& err) {
767 ErrorLogger() << "ExtractLobbyUpdateMessageData(const Message& msg, MultiplayerLobbyData& lobby_data) failed! Message:\n"
768 << msg.Text() << "\n"
769 << "Error: " << err.what();
770 throw err;
771 }
772 }
773
ExtractChatHistoryMessage(const Message & msg,std::vector<ChatHistoryEntity> & chat_history)774 void ExtractChatHistoryMessage(const Message& msg, std::vector<ChatHistoryEntity>& chat_history) {
775 try {
776 std::istringstream is(msg.Text());
777 freeorion_xml_iarchive ia(is);
778 std::size_t size;
779 ia >> BOOST_SERIALIZATION_NVP(size);
780 chat_history.clear();
781 chat_history.reserve(size);
782 for (size_t ii = 0; ii < size; ++ii) {
783 ChatHistoryEntity elem;
784 ia >> BOOST_SERIALIZATION_NVP(elem);
785 chat_history.push_back(elem);
786 }
787 } catch (const std::exception& err) {
788 ErrorLogger() << "ExtractChatHistoryMessage(const Message& msg, std::vector<ChatHistoryEntity>& chat_history) failed! Message:]n"
789 << msg.Text() << "\n"
790 << "Error: " << err.what();
791 throw err;
792 }
793 }
794
ExtractPlayerChatMessageData(const Message & msg,std::set<int> & recipients,std::string & data,bool & pm)795 void ExtractPlayerChatMessageData(const Message& msg, std::set<int>& recipients, std::string& data, bool& pm) {
796 try {
797 std::istringstream is(msg.Text());
798 freeorion_xml_iarchive ia(is);
799 ia >> BOOST_SERIALIZATION_NVP(recipients)
800 >> BOOST_SERIALIZATION_NVP(data)
801 >> BOOST_SERIALIZATION_NVP(pm);
802
803 } catch (const std::exception& err) {
804 ErrorLogger() << "ExtractPlayerChatMessageData(const Message& msg, int& receiver, std::string& data) failed! Message:\n"
805 << msg.Text() << "\n"
806 << "Error: " << err.what();
807 throw err;
808 }
809 }
810
ExtractServerPlayerChatMessageData(const Message & msg,int & sender,boost::posix_time::ptime & timestamp,std::string & data,bool & pm)811 void ExtractServerPlayerChatMessageData(const Message& msg,
812 int& sender, boost::posix_time::ptime& timestamp,
813 std::string& data, bool& pm)
814 {
815 try {
816 std::istringstream is(msg.Text());
817 freeorion_xml_iarchive ia(is);
818 ia >> BOOST_SERIALIZATION_NVP(sender)
819 >> BOOST_SERIALIZATION_NVP(timestamp)
820 >> BOOST_SERIALIZATION_NVP(data)
821 >> BOOST_SERIALIZATION_NVP(pm);
822 } catch (const std::exception& err) {
823 ErrorLogger() << "ExtractServerPlayerChatMessageData(const Message& msg, int& sender, std::string& data) failed! Message:\n"
824 << msg.Text() << "\n"
825 << "Error: " << err.what();
826 throw err;
827 }
828 }
829
ExtractGameStartMessageData(const Message & msg,bool & single_player_game,int & empire_id,int & current_turn,EmpireManager & empires,Universe & universe,SpeciesManager & species,CombatLogManager & combat_logs,SupplyManager & supply,std::map<int,PlayerInfo> & players,OrderSet & orders,bool & loaded_game_data,bool & ui_data_available,SaveGameUIData & ui_data,bool & save_state_string_available,std::string & save_state_string,GalaxySetupData & galaxy_setup_data)830 void ExtractGameStartMessageData(const Message& msg, bool& single_player_game, int& empire_id, int& current_turn,
831 EmpireManager& empires, Universe& universe, SpeciesManager& species,
832 CombatLogManager& combat_logs, SupplyManager& supply,
833 std::map<int, PlayerInfo>& players, OrderSet& orders, bool& loaded_game_data,
834 bool& ui_data_available, SaveGameUIData& ui_data, bool& save_state_string_available,
835 std::string& save_state_string, GalaxySetupData& galaxy_setup_data)
836 {
837 try {
838 bool try_xml = false;
839 if (strncmp(msg.Data(), "<?xml", 5)) {
840 try {
841 // first attempt binary deserialziation
842 std::istringstream is(msg.Text());
843
844 freeorion_bin_iarchive ia(is);
845 ia >> BOOST_SERIALIZATION_NVP(single_player_game)
846 >> BOOST_SERIALIZATION_NVP(empire_id)
847 >> BOOST_SERIALIZATION_NVP(current_turn);
848 GetUniverse().EncodingEmpire() = empire_id;
849
850 ScopedTimer deserialize_timer;
851 ia >> BOOST_SERIALIZATION_NVP(empires);
852 DebugLogger() << "ExtractGameStartMessage empire deserialization time " << deserialize_timer.DurationString();
853
854 ia >> BOOST_SERIALIZATION_NVP(species);
855 combat_logs.Clear(); // only needed when loading new game, not when incrementally serializing logs on turn update
856 combat_logs.SerializeIncompleteLogs(ia, 1);
857 ia >> BOOST_SERIALIZATION_NVP(supply);
858
859 deserialize_timer.restart();
860 Deserialize(ia, universe);
861 DebugLogger() << "ExtractGameStartMessage universe deserialization time " << deserialize_timer.DurationString();
862
863
864 ia >> BOOST_SERIALIZATION_NVP(players)
865 >> BOOST_SERIALIZATION_NVP(loaded_game_data);
866 if (loaded_game_data) {
867 Deserialize(ia, orders);
868 ia >> BOOST_SERIALIZATION_NVP(ui_data_available);
869 if (ui_data_available)
870 ia >> BOOST_SERIALIZATION_NVP(ui_data);
871 ia >> BOOST_SERIALIZATION_NVP(save_state_string_available);
872 if (save_state_string_available)
873 ia >> BOOST_SERIALIZATION_NVP(save_state_string);
874 } else {
875 ui_data_available = false;
876 save_state_string_available = false;
877 }
878 ia >> BOOST_SERIALIZATION_NVP(galaxy_setup_data);
879 } catch (...) {
880 try_xml = true;
881 }
882 } else {
883 try_xml = true;
884 }
885 if (try_xml) {
886 // if binary deserialization failed, try more-portable XML deserialization
887 std::istringstream is(msg.Text());
888
889 freeorion_xml_iarchive ia(is);
890 ia >> BOOST_SERIALIZATION_NVP(single_player_game)
891 >> BOOST_SERIALIZATION_NVP(empire_id)
892 >> BOOST_SERIALIZATION_NVP(current_turn);
893 GetUniverse().EncodingEmpire() = empire_id;
894
895 ScopedTimer deserialize_timer;
896 ia >> BOOST_SERIALIZATION_NVP(empires);
897
898 DebugLogger() << "ExtractGameStartMessage empire deserialization time " << deserialize_timer.DurationString();
899
900 ia >> BOOST_SERIALIZATION_NVP(species);
901 combat_logs.Clear(); // only needed when loading new game, not when incrementally serializing logs on turn update
902 combat_logs.SerializeIncompleteLogs(ia, 1);
903 ia >> BOOST_SERIALIZATION_NVP(supply);
904
905 deserialize_timer.restart();
906 Deserialize(ia, universe);
907 DebugLogger() << "ExtractGameStartMessage universe deserialization time " << deserialize_timer.DurationString();;
908
909
910 ia >> BOOST_SERIALIZATION_NVP(players)
911 >> BOOST_SERIALIZATION_NVP(loaded_game_data);
912 TraceLogger() << "ExtractGameStartMessage players and loaded_game_data=" << loaded_game_data << " deserialization time " << deserialize_timer.DurationString();
913 if (loaded_game_data) {
914 Deserialize(ia, orders);
915 TraceLogger() << "ExtractGameStartMessage orders deserialization time " << deserialize_timer.DurationString();
916 ia >> BOOST_SERIALIZATION_NVP(ui_data_available);
917 if (ui_data_available)
918 ia >> BOOST_SERIALIZATION_NVP(ui_data);
919 TraceLogger() << "ExtractGameStartMessage UI data " << ui_data_available << " deserialization time " << deserialize_timer.DurationString();
920 ia >> BOOST_SERIALIZATION_NVP(save_state_string_available);
921 if (save_state_string_available)
922 ia >> BOOST_SERIALIZATION_NVP(save_state_string);
923 TraceLogger() << "ExtractGameStartMessage save state " << save_state_string_available << " deserialization time " << deserialize_timer.DurationString();
924 } else {
925 ui_data_available = false;
926 save_state_string_available = false;
927 }
928 ia >> BOOST_SERIALIZATION_NVP(galaxy_setup_data);
929 TraceLogger() << "ExtractGameStartMessage galaxy setup data deserialization time " << deserialize_timer.DurationString();
930 }
931
932 } catch (const std::exception& err) {
933 ErrorLogger() << "ExtractGameStartMessageData(...) failed! Message probably long, so not outputting to log.\n"
934 << "Error: " << err.what();
935 TraceLogger() << "Message: " << msg.Text();
936 throw err;
937 }
938 }
939
ExtractJoinGameMessageData(const Message & msg,std::string & player_name,Networking::ClientType & client_type,std::string & version_string,boost::uuids::uuid & cookie)940 void ExtractJoinGameMessageData(const Message& msg, std::string& player_name,
941 Networking::ClientType& client_type,
942 std::string& version_string,
943 boost::uuids::uuid& cookie)
944 {
945 DebugLogger() << "ExtractJoinGameMessageData() from " << player_name << " client type " << client_type;
946 try {
947 std::istringstream is(msg.Text());
948 freeorion_xml_iarchive ia(is);
949 ia >> BOOST_SERIALIZATION_NVP(player_name)
950 >> BOOST_SERIALIZATION_NVP(client_type)
951 >> BOOST_SERIALIZATION_NVP(version_string)
952 >> BOOST_SERIALIZATION_NVP(cookie);
953
954 } catch (const std::exception& err) {
955 ErrorLogger() << "ExtractJoinGameMessageData(const Message& msg, std::string& player_name, "
956 << "Networking::ClientType client_type, std::string& version_string) failed! Message:\n"
957 << msg.Text() << "\n"
958 << "Error: " << err.what();
959 throw err;
960 }
961 }
962
ExtractJoinAckMessageData(const Message & msg,int & player_id,boost::uuids::uuid & cookie)963 void ExtractJoinAckMessageData(const Message& msg, int& player_id,
964 boost::uuids::uuid& cookie)
965 {
966 try {
967 std::istringstream is(msg.Text());
968 freeorion_xml_iarchive ia(is);
969 ia >> BOOST_SERIALIZATION_NVP(player_id)
970 >> BOOST_SERIALIZATION_NVP(cookie);
971 } catch (const std::exception& err) {
972 ErrorLogger() << "ExtractJoinAckMessageData(const Message& msg, int& player_id, "
973 << "boost::uuids::uuid& cookie) failed! Message:\n"
974 << msg.Text() << "\n"
975 << "Error: " << err.what();
976 throw err;
977 }
978 }
979
ExtractTurnOrdersMessageData(const Message & msg,OrderSet & orders,bool & ui_data_available,SaveGameUIData & ui_data,bool & save_state_string_available,std::string & save_state_string)980 void ExtractTurnOrdersMessageData(const Message& msg,
981 OrderSet& orders,
982 bool& ui_data_available,
983 SaveGameUIData& ui_data,
984 bool& save_state_string_available,
985 std::string& save_state_string)
986 {
987 try {
988 std::istringstream is(msg.Text());
989 freeorion_xml_iarchive ia(is);
990 DebugLogger() << "deserializing orders";
991 Deserialize(ia, orders);
992 DebugLogger() << "checking for ui data";
993 ia >> BOOST_SERIALIZATION_NVP(ui_data_available);
994 if (ui_data_available) {
995 DebugLogger() << "deserializing UI data";
996 ia >> BOOST_SERIALIZATION_NVP(ui_data);
997 }
998 DebugLogger() << "checking for save state string";
999 ia >> BOOST_SERIALIZATION_NVP(save_state_string_available);
1000 if (save_state_string_available) {
1001 DebugLogger() << "deserializing save state string";
1002 ia >> BOOST_SERIALIZATION_NVP(save_state_string);
1003 }
1004
1005 } catch (const std::exception& err) {
1006 ErrorLogger() << "ExtractTurnOrdersMessageData(const Message& msg, ...) failed! Message probably long, so not outputting to log.\n"
1007 << "Error: " << err.what();
1008 throw err;
1009 }
1010 }
1011
ExtractTurnPartialOrdersMessageData(const Message & msg,OrderSet & added,std::set<int> & deleted)1012 void ExtractTurnPartialOrdersMessageData(const Message& msg, OrderSet& added, std::set<int>& deleted) {
1013 try {
1014 std::istringstream is(msg.Text());
1015 freeorion_xml_iarchive ia(is);
1016 DebugLogger() << "deserializing partial orders";
1017 Deserialize(ia, added);
1018 ia >> BOOST_SERIALIZATION_NVP(deleted);
1019 } catch (const std::exception& err) {
1020 ErrorLogger() << "ExtractTurnPartialOrdersMessageData(const Message& msg) failed! Message probably long, so not outputting to log.\n"
1021 << "Error: " << err.what();
1022 throw err;
1023 }
1024 }
1025
ExtractTurnUpdateMessageData(const Message & msg,int empire_id,int & current_turn,EmpireManager & empires,Universe & universe,SpeciesManager & species,CombatLogManager & combat_logs,SupplyManager & supply,std::map<int,PlayerInfo> & players)1026 void ExtractTurnUpdateMessageData(const Message& msg, int empire_id, int& current_turn, EmpireManager& empires,
1027 Universe& universe, SpeciesManager& species, CombatLogManager& combat_logs,
1028 SupplyManager& supply, std::map<int, PlayerInfo>& players)
1029 {
1030 try {
1031 ScopedTimer timer("Turn Update Unpacking", true);
1032
1033 bool try_xml = false;
1034 if (std::strncmp(msg.Data(), "<?xml", 5)) {
1035 try {
1036 // first attempt binary deserialization
1037 std::istringstream is(msg.Text());
1038 freeorion_bin_iarchive ia(is);
1039 GetUniverse().EncodingEmpire() = empire_id;
1040 ia >> BOOST_SERIALIZATION_NVP(current_turn)
1041 >> BOOST_SERIALIZATION_NVP(empires)
1042 >> BOOST_SERIALIZATION_NVP(species);
1043 combat_logs.SerializeIncompleteLogs(ia, 1);
1044 ia >> BOOST_SERIALIZATION_NVP(supply);
1045 Deserialize(ia, universe);
1046 ia >> BOOST_SERIALIZATION_NVP(players);
1047 } catch (...) {
1048 try_xml = true;
1049 }
1050 } else {
1051 try_xml = true;
1052 }
1053 if (try_xml) {
1054 // try again with more-portable XML deserialization
1055 std::istringstream is(msg.Text());
1056 freeorion_xml_iarchive ia(is);
1057 GetUniverse().EncodingEmpire() = empire_id;
1058 ia >> BOOST_SERIALIZATION_NVP(current_turn)
1059 >> BOOST_SERIALIZATION_NVP(empires)
1060 >> BOOST_SERIALIZATION_NVP(species);
1061 combat_logs.SerializeIncompleteLogs(ia, 1);
1062 ia >> BOOST_SERIALIZATION_NVP(supply);
1063 Deserialize(ia, universe);
1064 ia >> BOOST_SERIALIZATION_NVP(players);
1065 }
1066
1067 } catch (const std::exception& err) {
1068 ErrorLogger() << "ExtractTurnUpdateMessageData(...) failed! Message probably long, so not outputting to log.\n"
1069 << "Error: " << err.what();
1070 throw err;
1071 }
1072 }
1073
ExtractTurnPartialUpdateMessageData(const Message & msg,int empire_id,Universe & universe)1074 void ExtractTurnPartialUpdateMessageData(const Message& msg, int empire_id, Universe& universe) {
1075 try {
1076 ScopedTimer timer("Mid Turn Update Unpacking", true);
1077
1078 bool try_xml = false;
1079 if (std::strncmp(msg.Data(), "<?xml", 5)) {
1080 try {
1081 // first attempt binary deserialization
1082 std::istringstream is(msg.Text());
1083 freeorion_bin_iarchive ia(is);
1084 GetUniverse().EncodingEmpire() = empire_id;
1085 Deserialize(ia, universe);
1086 } catch (...) {
1087 try_xml = true;
1088 }
1089 } else {
1090 try_xml = true;
1091 }
1092 if (try_xml) {
1093 // try again with more-portable XML deserialization
1094 std::istringstream is(msg.Text());
1095 freeorion_xml_iarchive ia(is);
1096 GetUniverse().EncodingEmpire() = empire_id;
1097 Deserialize(ia, universe);
1098 }
1099
1100 } catch (const std::exception& err) {
1101 ErrorLogger() << "ExtracturnPartialUpdateMessageData(...) failed! Message probably long, so not outputting to log.\n"
1102 << "Error: " << err.what();
1103 throw err;
1104 }
1105 }
1106
ExtractTurnProgressMessageData(const Message & msg,Message::TurnProgressPhase & phase_id)1107 void ExtractTurnProgressMessageData(const Message& msg, Message::TurnProgressPhase& phase_id) {
1108 try {
1109 std::istringstream is(msg.Text());
1110 freeorion_xml_iarchive ia(is);
1111 ia >> BOOST_SERIALIZATION_NVP(phase_id);
1112
1113 } catch (const std::exception& err) {
1114 ErrorLogger() << "ExtractTurnProgressMessageData(const Message& msg, Message::TurnProgressPhase& phase_id) failed! Message:\n"
1115 << msg.Text() << "\n"
1116 << "Error: " << err.what();
1117 throw err;
1118 }
1119 }
1120
ExtractPlayerStatusMessageData(const Message & msg,Message::PlayerStatus & status,int & about_empire_id)1121 void ExtractPlayerStatusMessageData(const Message& msg,
1122 Message::PlayerStatus& status,
1123 int& about_empire_id) {
1124 try {
1125 std::istringstream is(msg.Text());
1126 freeorion_xml_iarchive ia(is);
1127 ia >> BOOST_SERIALIZATION_NVP(status)
1128 >> BOOST_SERIALIZATION_NVP(about_empire_id);
1129
1130 } catch (const std::exception& err) {
1131 ErrorLogger() << "ExtractPlayerStatusMessageData(const Message& msg, Message::PlayerStatus&, int& about_empire_id) failed! Message:\n"
1132 << msg.Text() << "\n"
1133 << "Error: " << err.what();
1134 throw err;
1135 }
1136 }
1137
ExtractHostSPGameMessageData(const Message & msg,SinglePlayerSetupData & setup_data,std::string & client_version_string)1138 void ExtractHostSPGameMessageData(const Message& msg, SinglePlayerSetupData& setup_data, std::string& client_version_string) {
1139 try {
1140 std::istringstream is(msg.Text());
1141 freeorion_xml_iarchive ia(is);
1142 ia >> BOOST_SERIALIZATION_NVP(setup_data)
1143 >> BOOST_SERIALIZATION_NVP(client_version_string);
1144
1145 } catch (const std::exception& err) {
1146 ErrorLogger() << "ExtractHostSPGameMessageData(const Message& msg, SinglePlayerSetupData& setup_data, std::string& client_version_string) failed! Message:\n"
1147 << msg.Text() << "\n"
1148 << "Error: " << err.what();
1149 throw err;
1150 }
1151 }
1152
ExtractEndGameMessageData(const Message & msg,Message::EndGameReason & reason,std::string & reason_player_name)1153 void ExtractEndGameMessageData(const Message& msg, Message::EndGameReason& reason, std::string& reason_player_name) {
1154 try {
1155 std::istringstream is(msg.Text());
1156 freeorion_xml_iarchive ia(is);
1157 ia >> BOOST_SERIALIZATION_NVP(reason)
1158 >> BOOST_SERIALIZATION_NVP(reason_player_name);
1159
1160 } catch (const std::exception& err) {
1161 ErrorLogger() << "ExtractEndGameMessageData(const Message& msg, Message::EndGameReason& reason, "
1162 << "std::string& reason_player_name) failed! Message:\n"
1163 << msg.Text() << "\n"
1164 << "Error: " << err.what();
1165 throw err;
1166 }
1167 }
1168
ExtractModeratorActionMessageData(const Message & msg,Moderator::ModeratorAction * & mod_action)1169 void ExtractModeratorActionMessageData(const Message& msg, Moderator::ModeratorAction*& mod_action) {
1170 try {
1171 std::istringstream is(msg.Text());
1172 freeorion_xml_iarchive ia(is);
1173 ia >> BOOST_SERIALIZATION_NVP(mod_action);
1174
1175 } catch (const std::exception& err) {
1176 ErrorLogger() << "ExtractModeratorActionMessageData(const Message& msg, Moderator::ModeratorAction& mod_act) "
1177 << "failed! Message:\n"
1178 << msg.Text() << "\n"
1179 << "Error: " << err.what();
1180 }
1181 }
1182
ExtractDiplomacyMessageData(const Message & msg,DiplomaticMessage & diplo_message)1183 void ExtractDiplomacyMessageData(const Message& msg, DiplomaticMessage& diplo_message) {
1184 try {
1185 std::istringstream is(msg.Text());
1186 freeorion_xml_iarchive ia(is);
1187 ia >> BOOST_SERIALIZATION_NVP(diplo_message);
1188
1189 } catch (const std::exception& err) {
1190 ErrorLogger() << "ExtractDiplomacyMessageData(const Message& msg, DiplomaticMessage& "
1191 << "diplo_message) failed! Message:\n"
1192 << msg.Text() << "\n"
1193 << "Error: " << err.what();
1194 throw err;
1195 }
1196 }
1197
ExtractDiplomaticStatusMessageData(const Message & msg,DiplomaticStatusUpdateInfo & diplo_update)1198 void ExtractDiplomaticStatusMessageData(const Message& msg, DiplomaticStatusUpdateInfo& diplo_update) {
1199 try {
1200 std::istringstream is(msg.Text());
1201 freeorion_xml_iarchive ia(is);
1202 ia >> BOOST_SERIALIZATION_NVP(diplo_update.empire1_id)
1203 >> BOOST_SERIALIZATION_NVP(diplo_update.empire2_id)
1204 >> BOOST_SERIALIZATION_NVP(diplo_update.diplo_status);
1205
1206 } catch (const std::exception& err) {
1207 ErrorLogger() << "ExtractDiplomaticStatusMessageData(const Message& msg, DiplomaticStatusUpdate& diplo_update) failed! Message:\n"
1208 << msg.Text() << "\n"
1209 << "Error: " << err.what();
1210 throw err;
1211 }
1212 }
1213
ExtractRequestSavePreviewsMessageData(const Message & msg,std::string & directory)1214 void ExtractRequestSavePreviewsMessageData(const Message& msg, std::string& directory)
1215 { directory = msg.Text(); }
1216
ExtractDispatchSavePreviewsMessageData(const Message & msg,PreviewInformation & previews)1217 void ExtractDispatchSavePreviewsMessageData(const Message& msg, PreviewInformation& previews) {
1218 try {
1219 std::istringstream is(msg.Text());
1220 freeorion_xml_iarchive ia(is);
1221 ia >> BOOST_SERIALIZATION_NVP(previews);
1222
1223 } catch(const std::exception& err) {
1224 ErrorLogger() << "ExtractDispatchSavePreviewsMessageData(const Message& msg, PreviewInformation& previews) failed! Message:\n"
1225 << msg.Text() << "\n"
1226 << "Error: " << err.what();
1227 throw err;
1228 }
1229 }
1230
ExtractServerSaveGameCompleteMessageData(const Message & msg,std::string & save_filename,int & bytes_written)1231 FO_COMMON_API void ExtractServerSaveGameCompleteMessageData(const Message& msg, std::string& save_filename, int& bytes_written) {
1232 try {
1233 std::istringstream is(msg.Text());
1234 freeorion_xml_iarchive ia(is);
1235 ia >> BOOST_SERIALIZATION_NVP(save_filename)
1236 >> BOOST_SERIALIZATION_NVP(bytes_written);
1237
1238 } catch(const std::exception& err) {
1239 ErrorLogger() << "ExtractServerSaveGameCompleteServerSaveGameCompleteMessageData(const Message& msg, std::string& save_filename, int& bytes_written) failed! Message:\n"
1240 << msg.Text() << "\n"
1241 << "Error: " << err.what();
1242 throw err;
1243 }
1244 }
1245
ExtractRequestCombatLogsMessageData(const Message & msg,std::vector<int> & ids)1246 FO_COMMON_API void ExtractRequestCombatLogsMessageData(const Message& msg, std::vector<int>& ids) {
1247 try {
1248 std::istringstream is(msg.Text());
1249 freeorion_xml_iarchive ia(is);
1250 ia >> BOOST_SERIALIZATION_NVP(ids);
1251 } catch(const std::exception& err) {
1252 ErrorLogger() << "ExtractRequestCombatLogMessageData(const Message& msg, std::vector<int>& ids) failed! Message:\n"
1253 << msg.Text() << "\n"
1254 << "Error: " << err.what();
1255 throw err;
1256 }
1257 }
1258
ExtractDispatchCombatLogsMessageData(const Message & msg,std::vector<std::pair<int,CombatLog>> & logs)1259 FO_COMMON_API void ExtractDispatchCombatLogsMessageData(
1260 const Message& msg, std::vector<std::pair<int, CombatLog>>& logs)
1261 {
1262 try {
1263 bool try_xml = false;
1264 if (std::strncmp(msg.Data(), "<?xml", 5)) {
1265 try {
1266 // first attempt binary deserialization
1267 std::istringstream is(msg.Text());
1268 freeorion_bin_iarchive ia(is);
1269 ia >> BOOST_SERIALIZATION_NVP(logs);
1270 } catch (...) {
1271 try_xml = true;
1272 }
1273 } else {
1274 try_xml = true;
1275 }
1276 if (try_xml) {
1277 // try again with more-portable XML deserialization
1278 std::istringstream is(msg.Text());
1279 freeorion_xml_iarchive ia(is);
1280 ia >> BOOST_SERIALIZATION_NVP(logs);
1281 }
1282
1283 } catch(const std::exception& err) {
1284 ErrorLogger() << "ExtractDispatchCombatLogMessageData(const Message& msg, std::vector<std::pair<int, const CombatLog&>>& logs) failed! Message:\n"
1285 << msg.Text() << "\n"
1286 << "Error: " << err.what();
1287 throw err;
1288 }
1289 }
1290
ExtractLoggerConfigMessageData(const Message & msg,std::set<std::tuple<std::string,std::string,LogLevel>> & options)1291 FO_COMMON_API void ExtractLoggerConfigMessageData(
1292 const Message& msg, std::set<std::tuple<std::string, std::string, LogLevel>>& options)
1293 {
1294 try {
1295 std::istringstream is(msg.Text());
1296 freeorion_xml_iarchive ia(is);
1297 std::size_t size;
1298 ia >> BOOST_SERIALIZATION_NVP(size);
1299 for (size_t ii = 0; ii < size; ++ii) {
1300 std::string option;
1301 std::string name;
1302 LogLevel level;
1303 ia >> BOOST_SERIALIZATION_NVP(option);
1304 ia >> BOOST_SERIALIZATION_NVP(name);
1305 ia >> BOOST_SERIALIZATION_NVP(level);
1306 options.insert(std::make_tuple(option, name, level));
1307 }
1308 } catch (const std::exception& err) {
1309 ErrorLogger() << "ExtractDispatchCombatLogMessageData(const Message& msg, std::vector<std::pair<int, const CombatLog&> >& logs) failed! Message:\n"
1310 << msg.Text() << "\n"
1311 << "Error: " << err.what();
1312 throw err;
1313 }
1314
1315 }
1316
ExtractContentCheckSumMessageData(const Message & msg,std::map<std::string,unsigned int> & checksums)1317 void ExtractContentCheckSumMessageData(
1318 const Message& msg, std::map<std::string, unsigned int>& checksums)
1319 {
1320 checksums.clear();
1321 try {
1322 std::istringstream is(msg.Text());
1323 freeorion_xml_iarchive ia(is);
1324 ia >> BOOST_SERIALIZATION_NVP(checksums);
1325
1326 } catch(const std::exception& err) {
1327 ErrorLogger() << "ExtractContentCheckSumMessageData(const Message& msg, std::string& save_filename, std::map<std::string, unsigned int>) failed! Message:\n"
1328 << msg.Text() << "\n"
1329 << "Error: " << err.what();
1330 throw err;
1331 }
1332 }
1333
ExtractAuthRequestMessageData(const Message & msg,std::string & player_name,std::string & auth)1334 void ExtractAuthRequestMessageData(const Message& msg, std::string& player_name, std::string& auth) {
1335 try {
1336 std::istringstream is(msg.Text());
1337 freeorion_xml_iarchive ia(is);
1338 ia >> BOOST_SERIALIZATION_NVP(player_name)
1339 >> BOOST_SERIALIZATION_NVP(auth);
1340
1341 } catch(const std::exception& err) {
1342 ErrorLogger() << "ExtractAuthRequestMessageData(const Message& msg, std::string& player_name, std::string& auth) failed! Message:\n"
1343 << msg.Text() << "\n"
1344 << "Error: " << err.what();
1345 throw err;
1346 }
1347 }
1348
ExtractAuthResponseMessageData(const Message & msg,std::string & player_name,std::string & auth)1349 void ExtractAuthResponseMessageData(const Message& msg, std::string& player_name, std::string& auth) {
1350 try {
1351 std::istringstream is(msg.Text());
1352 freeorion_xml_iarchive ia(is);
1353 ia >> BOOST_SERIALIZATION_NVP(player_name)
1354 >> BOOST_SERIALIZATION_NVP(auth);
1355
1356 } catch(const std::exception& err) {
1357 ErrorLogger() << "ExtractAuthResponeMessageData(const Message& msg, std::string& player_name, std::string& auth) failed! Message:\n"
1358 << msg.Text() << "\n"
1359 << "Error: " << err.what();
1360 throw err;
1361 }
1362 }
1363
ExtractSetAuthorizationRolesMessage(const Message & msg,Networking::AuthRoles & roles)1364 void ExtractSetAuthorizationRolesMessage(const Message &msg, Networking::AuthRoles& roles)
1365 { roles.SetText(msg.Text()); }
1366
ExtractPlayerInfoMessageData(const Message & msg,std::map<int,PlayerInfo> & players)1367 void ExtractPlayerInfoMessageData(const Message &msg, std::map<int, PlayerInfo>& players) {
1368 try {
1369 std::istringstream is(msg.Text());
1370 freeorion_xml_iarchive ia(is);
1371 ia >> BOOST_SERIALIZATION_NVP(players);
1372 } catch(const std::exception& err) {
1373 ErrorLogger() << "ExtractPlayerInfo(const Message &msg, std::map<int, PlayerInfo>& players) failed! Message:\n"
1374 << msg.Text() << "\n"
1375 << "Error: " << err.what();
1376 }
1377 }
1378