1 /* 2 * metaserver_messages.h - TCPMess message types for metaserver client 3 4 Copyright (C) 2004 and beyond by Woody Zenfell, III 5 and the "Aleph One" developers. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 This license is contained in the file "COPYING", 18 which is included with this source code; it is available online at 19 http://www.gnu.org/licenses/gpl.html 20 21 April 15, 2004 (Woody Zenfell): 22 Created. 23 */ 24 25 #ifndef METASERVER_MESSAGES_H 26 #define METASERVER_MESSAGES_H 27 28 #include "Message.h" 29 30 #include "AStream.h" 31 #include "SDL_net.h" 32 #include "Scenario.h" // for scenario name and ID 33 #include "network.h" // for network protocol ID 34 35 #include <string> 36 #include <vector> 37 #include <boost/algorithm/string/case_conv.hpp> 38 39 using boost::algorithm::to_lower_copy; 40 41 enum 42 { 43 // Message types sent from servers to clients 44 kSERVER_ROOMLIST = 0, 45 kSERVER_PLAYERLIST = 1, 46 kSERVER_GAMELIST = 2, 47 kSERVER_DENY = 3, 48 kSERVER_SALT = 6, 49 kSERVER_LOGINSUCCESS = 7, 50 kSERVER_SETPLAYERDATA = 8, 51 kSERVER_LIMIT = 9, 52 kSERVER_BROADCAST = 10, 53 kSERVER_ACCEPT = 12, 54 kSERVER_FIND = 14, 55 kSERVER_STATS = 17, 56 57 // Messages sent from clients to servers 58 kCLIENT_LOGIN = 100, 59 kCLIENT_ROOM_LOGIN = 101, 60 kCLIENT_LOGOUT = 102, 61 kCLIENT_NAME_TEAM = 103, 62 kCLIENT_CREATEGAME = 104, 63 kCLIENT_REMOVEGAME = 105, 64 kCLIENT_PLAYERMODE = 107, 65 kCLIENT_KEY = 109, 66 kCLIENT_SYNCGAMES = 110, 67 kCLIENT_GAMEPLAYERLIST = 111, 68 kCLIENT_GAMESCORE = 112, 69 kCLIENT_RESETGAME = 113, 70 kCLIENT_STARTGAME = 114, 71 kCLIENT_LOCALIZE = 115, 72 kCLIENT_FIND = 117, 73 kCLIENT_STATS = 121, 74 75 // Message types sent in both directions 76 kBOTH_CHAT = 200, 77 kBOTH_PRIVATE_MESSAGE = 201, 78 kBOTH_KEEP_ALIVE = 202, 79 }; 80 81 82 83 typedef uint8 HandoffToken[32]; 84 85 AIStream& operator >>(AIStream& stream, HandoffToken& token); 86 // Damned if I can convince the linker this operator exists . . . 87 //AOStream& operator <<(AOStream& stream, const HandoffToken& token); 88 89 90 91 struct GameDescription 92 { 93 uint16 m_type; 94 int32 m_timeLimit; 95 uint32 m_mapChecksum; 96 uint16 m_difficulty; 97 uint16 m_maxPlayers; 98 bool m_teamsAllowed; 99 bool m_closed; 100 bool m_running; 101 uint8 m_numPlayers; 102 std::string m_name; 103 std::string m_mapName; 104 105 // future versions will take action on these: 106 std::string m_scenarioID; 107 std::string m_networkSetupProtocolID; 108 109 // while these are purely for display purposes 110 std::string m_scenarioName; 111 std::string m_scenarioVersion; 112 std::string m_alephoneBuildString; 113 std::string m_netScript; 114 115 // more stuff 116 bool m_hasGameOptions; 117 int16 m_gameOptions; 118 int16 m_cheatFlags; 119 int16 m_killLimit; 120 std::string m_mapFileName; 121 std::string m_physicsName; 122 GameDescriptionGameDescription123 GameDescription() 124 : m_type(0) 125 , m_timeLimit(0) 126 , m_mapChecksum(0) 127 , m_difficulty(0) 128 , m_maxPlayers(8) 129 , m_teamsAllowed(false) 130 , m_closed(false) 131 , m_running(false) 132 , m_numPlayers(1) 133 , m_name("Untitled Game") 134 , m_mapName("Unspecified Map") 135 , m_scenarioID(Scenario::instance()->GetID()) 136 , m_networkSetupProtocolID(kNetworkSetupProtocolID) 137 , m_scenarioName(Scenario::instance()->GetName()) 138 , m_scenarioVersion(Scenario::instance()->GetVersion()) 139 , m_hasGameOptions(false) 140 , m_gameOptions(0) 141 , m_cheatFlags(0) 142 , m_killLimit(0) 143 {} 144 145 }; 146 147 AIStream& operator >>(AIStream& stream, GameDescription& desc); 148 AOStream& operator <<(AOStream& stream, const GameDescription& desc); 149 std::ostream& operator <<(std::ostream& stream, const GameDescription& desc); 150 151 152 153 class LoginAndPlayerInfoMessage : public SmallMessageHelper 154 { 155 public: LoginAndPlayerInfoMessage(const std::string & userName,const std::string & playerName,const std::string & teamName)156 LoginAndPlayerInfoMessage(const std::string& userName, const std::string& playerName, const std::string& teamName) 157 : m_userName(userName), m_playerName(playerName), m_teamName(teamName) {} 158 159 enum { kType = kCLIENT_LOGIN }; 160 type()161 MessageTypeID type() const { return kType; } 162 clone()163 LoginAndPlayerInfoMessage* clone() const 164 { return new LoginAndPlayerInfoMessage(*this); } 165 166 protected: 167 void reallyDeflateTo(AOStream& thePacket) const; 168 reallyInflateFrom(AIStream & inStream)169 bool reallyInflateFrom(AIStream& inStream) 170 { 171 // no support for receiving this type of message 172 return false; 173 } 174 175 private: 176 std::string m_userName; 177 std::string m_playerName; 178 std::string m_teamName; 179 }; 180 181 typedef DatalessMessage<kCLIENT_LOGOUT> LogoutMessage; 182 183 class SetPlayerModeMessage : public SmallMessageHelper 184 { 185 public: 186 enum { kType = kCLIENT_PLAYERMODE }; 187 type()188 MessageTypeID type() const { return kType; } 189 clone()190 SetPlayerModeMessage* clone() const 191 { return new SetPlayerModeMessage(*this); } 192 SetPlayerModeMessage(uint16 mode,const std::string & session_id)193 SetPlayerModeMessage(uint16 mode, const std::string& session_id) : m_mode(mode), m_session_id(session_id) { } 194 195 protected: reallyDeflateTo(AOStream & thePacket)196 void reallyDeflateTo(AOStream& thePacket) const 197 { 198 thePacket << m_mode; 199 thePacket.write(const_cast<char*>(m_session_id.c_str()), m_session_id.size()); 200 } 201 reallyInflateFrom(AIStream & inStream)202 bool reallyInflateFrom(AIStream& inStream) 203 { assert(false); } 204 205 private: 206 uint16 m_mode; 207 std::string m_session_id; 208 }; 209 210 class SaltMessage : public SmallMessageHelper 211 { 212 public: 213 enum { kType = kSERVER_SALT, kKeyLength = 16 }; 214 215 enum { kPlaintextEncryption, kBraindeadSimpleEncryption, kHTTPSEncryption = 4 }; 216 encryptionType()217 uint16 encryptionType() const { return m_encryptionType; } salt()218 const uint8* salt() const { return &(m_salt[0]); } 219 type()220 MessageTypeID type() const { return kType; } 221 clone()222 SaltMessage* clone() const 223 { return new SaltMessage(*this); } 224 225 protected: reallyDeflateTo(AOStream & thePacket)226 void reallyDeflateTo(AOStream& thePacket) const 227 { 228 // no need for deflation 229 assert(false); 230 } 231 232 bool reallyInflateFrom(AIStream& inStream); 233 234 private: 235 uint16 m_encryptionType; 236 uint8 m_salt[kKeyLength]; 237 }; 238 239 240 241 typedef DatalessMessage<kSERVER_ACCEPT> AcceptMessage; 242 243 244 245 class LocalizationMessage : public SmallMessageHelper 246 { 247 public: 248 enum { kType = kCLIENT_LOCALIZE }; 249 type()250 MessageTypeID type() const { return kType; } 251 clone()252 LocalizationMessage* clone() const 253 { return new LocalizationMessage(*this); } 254 255 protected: 256 void reallyDeflateTo(AOStream& thePacket) const; 257 reallyInflateFrom(AIStream & inStream)258 bool reallyInflateFrom(AIStream& inStream) 259 { 260 // no need for inflation 261 return false; 262 } 263 }; 264 265 266 267 class RoomDescription 268 { 269 public: 270 enum 271 { 272 kNormalRoomType = 0, 273 kRankedRoomType, 274 kTournamentRoomType 275 }; 276 277 void read(AIStream& inStream); 278 279 const std::string roomName() const; playerCount()280 int playerCount() const { return m_playerCount; } gameCount()281 int gameCount() const { return m_gameCount; } roomType()282 int roomType() const { return m_type; } roomServerAddress()283 const IPaddress roomServerAddress() const { return m_address; } 284 285 private: 286 uint16 m_id; 287 uint16 m_playerCount; 288 uint16 m_gameCount; 289 uint16 m_type; 290 IPaddress m_address; 291 }; 292 293 std::ostream& operator <<(std::ostream& out, const RoomDescription& roomDesc); 294 295 class RoomListMessage : public SmallMessageHelper 296 { 297 public: 298 enum { kType = kSERVER_ROOMLIST }; 299 type()300 MessageTypeID type() const { return kType; } 301 clone()302 RoomListMessage* clone() const 303 { return new RoomListMessage(*this); } 304 rooms()305 const std::vector<RoomDescription>& rooms() const { return m_rooms; } 306 307 protected: reallyDeflateTo(AOStream & thePacket)308 void reallyDeflateTo(AOStream& thePacket) const 309 { 310 // no need for deflation 311 assert(false); 312 } 313 314 bool reallyInflateFrom(AIStream& inStream); 315 316 private: 317 std::vector<RoomDescription> m_rooms; 318 }; 319 320 std::ostream& operator <<(std::ostream& out, const RoomListMessage& message); 321 322 323 324 class RoomLoginMessage : public SmallMessageHelper 325 { 326 public: 327 enum { kType = kCLIENT_ROOM_LOGIN, kKeyLength = 16 }; 328 type()329 MessageTypeID type() const { return kType; } 330 clone()331 RoomLoginMessage* clone() const 332 { return new RoomLoginMessage(*this); } 333 RoomLoginMessage(const std::string & login,const HandoffToken & token)334 RoomLoginMessage(const std::string& login, const HandoffToken& token) : m_loginName(login) 335 { 336 memcpy(m_token, token, sizeof(m_token)); 337 } 338 339 protected: 340 void reallyDeflateTo(AOStream& out) const; 341 reallyInflateFrom(AIStream &)342 bool reallyInflateFrom(AIStream&) 343 { 344 // don't need to be able to receive these 345 return false; 346 } 347 348 private: 349 HandoffToken m_token; 350 std::string m_loginName; 351 }; 352 353 354 355 class NameAndTeamMessage : public SmallMessageHelper 356 { 357 public: 358 enum { kType = kCLIENT_NAME_TEAM }; 359 type()360 MessageTypeID type() const { return kType; } 361 clone()362 NameAndTeamMessage* clone() const 363 { return new NameAndTeamMessage(*this); } 364 NameAndTeamMessage(const std::string & name,const std::string & team)365 NameAndTeamMessage(const std::string& name, const std::string& team) : m_name(name), m_team(team), m_away(false), m_away_message("") {} 366 NameAndTeamMessage(const std::string & name,const std::string & team,bool away,const std::string & away_message)367 NameAndTeamMessage(const std::string& name, const std::string& team, bool away, const std::string& away_message) : m_name(name), m_team(team), m_away(away), m_away_message(away_message) { } 368 369 protected: 370 void reallyDeflateTo(AOStream& out) const; 371 reallyInflateFrom(AIStream &)372 bool reallyInflateFrom(AIStream&) 373 { 374 // don't need to be able to receive these 375 return false; 376 } 377 378 private: 379 std::string m_name; 380 std::string m_team; 381 382 bool m_away; 383 std::string m_away_message; 384 }; 385 386 class IDAndLimitMessage : public SmallMessageHelper 387 { 388 public: 389 enum { kType = kSERVER_LIMIT }; 390 playerID()391 uint32 playerID() const { return m_playerID; } playerLimit()392 uint16 playerLimit() const { return m_playerLimit; } 393 type()394 MessageTypeID type() const { return kType; } 395 clone()396 IDAndLimitMessage* clone() const 397 { return new IDAndLimitMessage(*this); } 398 399 protected: reallyDeflateTo(AOStream & thePacket)400 void reallyDeflateTo(AOStream& thePacket) const 401 { 402 // no need for deflation 403 assert(false); 404 } 405 406 bool reallyInflateFrom(AIStream& inStream); 407 408 private: 409 uint32 m_playerID; 410 uint16 m_playerLimit; 411 }; 412 413 414 415 class DenialMessage : public SmallMessageHelper 416 { 417 public: 418 enum { kType = kSERVER_DENY }; 419 type()420 MessageTypeID type() const { return kType; } 421 code()422 uint32 code() const { return m_code; } message()423 const std::string message() const { return m_message; } 424 clone()425 DenialMessage* clone() const 426 { return new DenialMessage(*this); } 427 428 protected: reallyDeflateTo(AOStream & thePacket)429 void reallyDeflateTo(AOStream& thePacket) const 430 { 431 // no need for deflation 432 assert(false); 433 } 434 435 bool reallyInflateFrom(AIStream& inStream); 436 437 private: 438 uint32 m_code; 439 std::string m_message; 440 }; 441 442 443 444 class BroadcastMessage : public SmallMessageHelper 445 { 446 public: 447 enum { kType = kSERVER_BROADCAST }; 448 type()449 MessageTypeID type() const { return kType; } 450 message()451 const std::string message() const { return m_message; } 452 clone()453 BroadcastMessage* clone() const 454 { return new BroadcastMessage(*this); } 455 456 protected: reallyDeflateTo(AOStream & thePacket)457 void reallyDeflateTo(AOStream& thePacket) const 458 { 459 // no need for deflation 460 assert(false); 461 } 462 463 bool reallyInflateFrom(AIStream& inStream); 464 465 private: 466 std::string m_message; 467 }; 468 469 class PrivateMessage : public SmallMessageHelper 470 { 471 public: 472 enum { kType = kBOTH_PRIVATE_MESSAGE }; 473 static const int kDirectedBit = 0x1; 474 type()475 MessageTypeID type() const { return kType; } 476 PrivateMessage()477 PrivateMessage() {} 478 479 PrivateMessage(uint32 inSenderID, const std::string& inSenderName, uint32 inSelectedID, const std::string& inMessage); 480 senderID()481 const uint32 senderID() const { return m_senderID; } selectedID()482 const uint32 selectedID() const { return m_selectedID; } internalType()483 const uint16 internalType() const { return m_internalType; } senderName()484 const std::string senderName() const { return m_senderName; } message()485 const std::string message() const { return m_message; } directed()486 const bool directed() const { return m_flags & kDirectedBit; } 487 clone()488 PrivateMessage* clone() const 489 { return new PrivateMessage(*this); } 490 491 protected: 492 void reallyDeflateTo(AOStream& thePacket) const; 493 bool reallyInflateFrom(AIStream& inStream); 494 495 private: 496 uint16 m_color[3] = {}; 497 uint32 m_senderID = 0; 498 uint32 m_selectedID = 0; 499 uint16 m_internalType = 0; 500 uint16 m_flags = 0; 501 std::string m_senderName; 502 std::string m_message; 503 }; 504 505 506 class ChatMessage : public SmallMessageHelper 507 { 508 public: 509 enum { kType = kBOTH_CHAT }; 510 511 static const int kDirectedBit = 0x1; 512 type()513 MessageTypeID type() const { return kType; } 514 ChatMessage()515 ChatMessage() {} 516 517 ChatMessage(uint32 inSenderID, const std::string& inSenderName, const std::string& inMessage); 518 senderID()519 const uint32 senderID() const { return m_senderID; } internalType()520 const uint16 internalType() const { return m_internalType; } senderName()521 const std::string senderName() const { return m_senderName; } message()522 const std::string message() const { return m_message; } directed()523 const bool directed() const { return m_flags & kDirectedBit; } 524 clone()525 ChatMessage* clone() const 526 { return new ChatMessage(*this); } 527 528 protected: 529 void reallyDeflateTo(AOStream& thePacket) const; 530 bool reallyInflateFrom(AIStream& inStream); 531 532 private: 533 uint16 m_color[3] = {}; 534 uint32 m_senderID = 0; 535 uint16 m_internalType = 0; 536 uint16 m_flags = 0; 537 std::string m_senderName; 538 std::string m_message; 539 }; 540 541 542 543 typedef DatalessMessage<kBOTH_KEEP_ALIVE> KeepAliveMessage; 544 545 546 547 class MetaserverPlayerInfo 548 { 549 public: 550 // Flags for adminFlags 551 static const uint16 kNotAdmin = 0x0; 552 static const uint16 kBungie = 0x1; 553 static const uint16 kAdmin = 0x4; 554 555 MetaserverPlayerInfo(AIStream& fromStream); 556 verb()557 uint16 verb() const { return m_verb; } playerID()558 uint32 playerID() const { return m_playerID; } name()559 const std::string& name() const { return m_name; } 560 color()561 const uint16 *color() const { return m_primaryColor; } team_color()562 const uint16 *team_color() const { return m_secondaryColor; } 563 sort(const MetaserverPlayerInfo & a,const MetaserverPlayerInfo & b)564 static bool sort(const MetaserverPlayerInfo& a, const MetaserverPlayerInfo& b) { 565 return (a.m_adminFlags == b.m_adminFlags) ? ( (a.m_status == b.m_status) ? a.playerID() < b.playerID() : a.m_status < b.m_status) : a.m_adminFlags > b.m_adminFlags; 566 } 567 568 friend std::ostream& operator <<(std::ostream& out, const MetaserverPlayerInfo& info); 569 away()570 bool away() const { return m_status & 0x1; } 571 572 // Conformance to metaserver-maintained-list interface 573 typedef uint32 IDType; 574 static const IDType IdNone = 0xffffffff; 575 id()576 IDType id() const { return playerID(); } 577 target()578 bool target() const { return m_target; } target(bool _target)579 void target(bool _target) { m_target = _target; } 580 581 private: 582 MetaserverPlayerInfo(); 583 584 uint16 m_verb; 585 uint16 m_adminFlags; 586 uint32 m_ranking; 587 uint32 m_playerID; 588 uint32 m_roomID; 589 uint16 m_rank; 590 uint16 m_playerDataSize; 591 uint8 m_icon; 592 uint8 m_status; 593 uint16 m_primaryColor[3]; 594 uint16 m_secondaryColor[3]; 595 std::string m_name; 596 std::string m_team; 597 598 bool m_target; 599 }; 600 601 class PlayerListMessage : public SmallMessageHelper 602 { 603 public: 604 enum { kType = kSERVER_PLAYERLIST }; 605 type()606 MessageTypeID type() const { return kType; } 607 PlayerListMessage()608 PlayerListMessage() {} 609 clone()610 PlayerListMessage* clone() const 611 { return new PlayerListMessage(*this); } 612 players()613 const std::vector<MetaserverPlayerInfo>& players() const { return m_players; } 614 615 616 protected: reallyDeflateTo(AOStream & thePacket)617 void reallyDeflateTo(AOStream& thePacket) const 618 { 619 // no need for deflation 620 assert(false); 621 } 622 623 bool reallyInflateFrom(AIStream& inStream); 624 625 private: 626 std::vector<MetaserverPlayerInfo> m_players; 627 }; 628 629 std::ostream& operator <<(std::ostream& out, const PlayerListMessage& info); 630 631 632 633 class CreateGameMessage : public SmallMessageHelper 634 { 635 public: 636 enum { kType = kCLIENT_CREATEGAME }; 637 type()638 MessageTypeID type() const { return kType; } 639 CreateGameMessage(uint16 gamePort,const GameDescription & description)640 CreateGameMessage(uint16 gamePort, const GameDescription& description) 641 : m_gamePort(gamePort) 642 , m_description(description) 643 {} 644 clone()645 CreateGameMessage* clone() const 646 { return new CreateGameMessage(*this); } 647 648 649 protected: 650 void reallyDeflateTo(AOStream& thePacket) const; 651 reallyInflateFrom(AIStream & inStream)652 bool reallyInflateFrom(AIStream& inStream) 653 { 654 // no need for inflation 655 assert(false); 656 return false; 657 } 658 659 660 private: 661 uint16 m_gamePort; 662 GameDescription m_description; 663 }; 664 665 666 667 typedef DatalessMessage<kCLIENT_SYNCGAMES> SyncGamesMessage; 668 669 670 671 class LoginSuccessfulMessage : public SmallMessageHelper 672 { 673 public: 674 enum { kType = kSERVER_LOGINSUCCESS }; 675 type()676 MessageTypeID type() const { return kType; } 677 clone()678 LoginSuccessfulMessage* clone() const 679 { return new LoginSuccessfulMessage(*this); } 680 userID()681 uint32 userID() const { return m_userID; } token()682 const HandoffToken& token() const { return m_token; } 683 684 protected: reallyDeflateTo(AOStream & thePacket)685 void reallyDeflateTo(AOStream& thePacket) const 686 { 687 // no need for deflation 688 assert(false); 689 } 690 691 bool reallyInflateFrom(AIStream& inStream); 692 693 private: 694 uint32 m_userID; 695 uint16 m_order; 696 HandoffToken m_token; 697 }; 698 699 700 701 class SetPlayerDataMessage : public SmallMessageHelper 702 { 703 public: 704 enum { kType = kSERVER_SETPLAYERDATA }; 705 type()706 MessageTypeID type() const { return kType; } 707 clone()708 SetPlayerDataMessage* clone() const 709 { return new SetPlayerDataMessage(*this); } 710 711 712 protected: reallyDeflateTo(AOStream & thePacket)713 void reallyDeflateTo(AOStream& thePacket) const 714 { 715 // no need for deflation 716 assert(false); 717 } 718 719 bool reallyInflateFrom(AIStream& inStream); 720 721 private: 722 }; 723 724 725 726 class GameListMessage : public SmallMessageHelper 727 { 728 public: 729 struct GameListEntry 730 { 731 // Conformance to MetaserverMaintainedList's Element interface 732 typedef uint32 IDType; 733 static const IDType IdNone = 0xffffffff; idGameListEntry734 IDType id() const { return m_gameID; } verbGameListEntry735 uint8 verb() const { return m_verb; } 736 targetGameListEntry737 bool target() const { return m_target; } targetGameListEntry738 void target(bool _target) { m_target = _target; } 739 runningGameListEntry740 bool running() const { return m_description.m_running; } compatibleGameListEntry741 bool compatible() const { return Scenario::instance()->IsCompatible(m_description.m_scenarioID); } 742 sortGameListEntry743 static bool sort(const GameListEntry& a, const GameListEntry& b) { 744 // sort compatible/not running, then compatible/running 745 // then not compatible 746 // in those groups, sort by ID 747 if (a.compatible() && b.compatible()) 748 { 749 if (a.running() == b.running()) 750 { 751 return a.id() < b.id(); 752 } 753 else 754 { 755 return !a.running(); 756 } 757 } 758 else if (a.compatible() == b.compatible()) 759 { 760 return a.id() < b.id(); 761 } 762 else 763 return a.compatible(); 764 } 765 minutes_remainingGameListEntry766 int minutes_remaining() const { 767 if (m_timeRemaining == -1) return -1; 768 int remaining = m_timeRemaining / 60 - (SDL_GetTicks() - m_ticks) / 1000 / 60; 769 if (remaining < 0) remaining = 0; 770 return remaining; 771 } 772 773 std::string format_for_chat(const std::string& player_name) const; 774 std::string game_string() const; 775 776 // Conformance to w_items_in_game<>'s Element interface nameGameListEntry777 const std::string& name() const { return m_description.m_name; } 778 779 uint32 m_gameID; 780 uint8 m_ipAddress[4]; 781 uint16 m_port; 782 uint8 m_verb; 783 uint8 m_gameEnable; 784 uint32 m_timeRemaining; 785 uint32 m_hostPlayerID; 786 uint16 m_len; 787 GameDescription m_description; 788 789 uint32 m_ticks; // SDL ticks at last update 790 std::string m_hostPlayerName; 791 GameListEntryGameListEntry792 GameListEntry() : m_target(false) { } 793 bool m_target; 794 }; 795 796 enum { kType = kSERVER_GAMELIST }; 797 type()798 MessageTypeID type() const { return kType; } 799 clone()800 GameListMessage* clone() const 801 { return new GameListMessage(*this); } 802 entries()803 const std::vector<GameListEntry>& entries() const { return m_entries; } 804 805 protected: reallyDeflateTo(AOStream & thePacket)806 void reallyDeflateTo(AOStream& thePacket) const 807 { 808 // no need for deflation 809 assert(false); 810 } 811 812 bool reallyInflateFrom(AIStream& inStream); 813 814 private: 815 std::vector<GameListEntry> m_entries; 816 }; 817 818 AIStream& operator >>(AIStream& stream, GameListMessage::GameListEntry& entry); 819 std::ostream& operator <<(std::ostream& stream, const GameListMessage::GameListEntry& entry); 820 821 822 823 typedef DatalessMessage<kCLIENT_RESETGAME> ResetGameMessage; 824 typedef DatalessMessage<kCLIENT_REMOVEGAME> RemoveGameMessage; 825 826 827 828 class StartGameMessage : public SmallMessageHelper 829 { 830 public: 831 enum { kType = kCLIENT_STARTGAME }; 832 type()833 MessageTypeID type() const { return kType; } 834 clone()835 StartGameMessage* clone() const 836 { return new StartGameMessage(*this); } 837 StartGameMessage(int32 gameTimeInSeconds)838 StartGameMessage(int32 gameTimeInSeconds) : m_gameTimeInSeconds(gameTimeInSeconds) {} 839 840 protected: 841 void reallyDeflateTo(AOStream& thePacket) const; 842 reallyInflateFrom(AIStream & inStream)843 bool reallyInflateFrom(AIStream& inStream) 844 { 845 // no need for inflation 846 assert(false); 847 return false; 848 } 849 850 private: 851 int32 m_gameTimeInSeconds; 852 }; 853 854 #endif // METASERVER_MESSAGES_H 855