-
Notifications
You must be signed in to change notification settings - Fork 151
feat(network): Send product information to distinguish clients (with a colored name and different status) #1404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
f066518
c4e3f1d
f0b8460
fedb4a6
87193b6
eb84ebf
f4177d4
8caeda6
abf9f4e
900a24c
982021d
3d3bd29
5555883
10a4c7d
81609c0
c07857d
8feddcd
f91a058
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -140,6 +140,155 @@ class LANAPIInterface : public SubsystemInterface | |
| }; | ||
|
|
||
|
|
||
| /** | ||
| * LAN message class | ||
| */ | ||
| #pragma pack(push, 1) | ||
| struct LANMessage | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You moved this whole struct up so you can use it further down below, which is fine. Can you make a separate Pull Request moving it, so that the diff of this change is cleaner? |
||
| { | ||
| enum Type ///< What kind of message are we? | ||
| { | ||
| // Locating everybody | ||
| MSG_REQUEST_LOCATIONS, ///< Hey, where is everybody? | ||
| MSG_GAME_ANNOUNCE, ///< Here I am, and here's my game info! | ||
| MSG_LOBBY_ANNOUNCE, ///< Hey, I'm in the lobby! | ||
|
|
||
| // Joining games | ||
| MSG_REQUEST_JOIN, ///< Let me in! Let me in! | ||
| MSG_JOIN_ACCEPT, ///< Okay, you can join. | ||
| MSG_JOIN_DENY, ///< Go away! We don't want any! | ||
|
|
||
| // Leaving games | ||
| MSG_REQUEST_GAME_LEAVE, ///< I want to leave the game | ||
| MSG_REQUEST_LOBBY_LEAVE,///< I'm leaving the lobby | ||
|
|
||
| // Game options, chat, etc | ||
| MSG_SET_ACCEPT, ///< I'm cool with everything as is. | ||
| MSG_MAP_AVAILABILITY, ///< I do (not) have the map. | ||
| MSG_CHAT, ///< Just spouting my mouth off. | ||
| MSG_GAME_START, ///< Hold on; we're starting! | ||
| MSG_GAME_START_TIMER, ///< The game will start in N seconds | ||
| MSG_GAME_OPTIONS, ///< Here's some info about the game. | ||
| MSG_INACTIVE, ///< I've alt-tabbed out. Unaccept me cause I'm a poo-flinging monkey. | ||
|
|
||
| MSG_REQUEST_GAME_INFO, ///< For direct connect, get the game info from a specific IP Address | ||
|
|
||
| // Community Product | ||
| MSG_GAME_REQUEST_PRODUCT_INFO = 1000, | ||
| MSG_GAME_RESPONSE_PRODUCT_INFO, | ||
| MSG_LOBBY_REQUEST_PRODUCT_INFO, | ||
| MSG_LOBBY_RESPONSE_PRODUCT_INFO, | ||
| MSG_MATCH_REQUEST_PRODUCT_INFO, | ||
| MSG_MATCH_RESPONSE_PRODUCT_INFO, | ||
| } messageType; | ||
|
|
||
| WideChar name[g_lanPlayerNameLength+1]; ///< My name, for convenience | ||
| char userName[g_lanLoginNameLength+1]; ///< login name, for convenience | ||
| char hostName[g_lanHostNameLength+1]; ///< machine name, for convenience | ||
|
|
||
| // No additional data is required for REQUEST_LOCATIONS, LOBBY_ANNOUNCE, | ||
| // REQUEST_LOBBY_LEAVE, GAME_START. | ||
| union | ||
| { | ||
| // StartTimer is sent with GAME_START_TIMER | ||
| struct | ||
| { | ||
| Int seconds; | ||
| } StartTimer; | ||
|
|
||
| // GameJoined is sent with REQUEST_GAME_LEAVE | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| } GameToLeave; | ||
|
|
||
| // GameInfo if sent with GAME_ANNOUNCE | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| Bool inProgress; | ||
| char options[m_lanMaxOptionsLength+1]; | ||
| Bool isDirectConnect; | ||
| } GameInfo; | ||
|
|
||
| // PlayerInfo is sent with REQUEST_GAME_INFO for direct connect games. | ||
| struct | ||
| { | ||
| UnsignedInt ip; | ||
| WideChar playerName[g_lanPlayerNameLength+1]; | ||
| } PlayerInfo; | ||
|
|
||
| // GameToJoin is sent with REQUEST_JOIN | ||
| struct | ||
| { | ||
| UnsignedInt gameIP; | ||
| UnsignedInt exeCRC; | ||
| UnsignedInt iniCRC; | ||
| char serial[g_maxSerialLength]; | ||
| } GameToJoin; | ||
|
|
||
| // GameJoined is sent with JOIN_ACCEPT | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| UnsignedInt gameIP; | ||
| UnsignedInt playerIP; | ||
| Int slotPosition; | ||
| } GameJoined; | ||
|
|
||
| // GameNotJoined is sent with JOIN_DENY | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| UnsignedInt gameIP; | ||
| UnsignedInt playerIP; | ||
| LANAPIInterface::ReturnType reason; | ||
| } GameNotJoined; | ||
|
|
||
| // Accept is sent with SET_ACCEPT | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| Bool isAccepted; | ||
| } Accept; | ||
|
|
||
| // Accept is sent with MAP_AVAILABILITY | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| UnsignedInt mapCRC; // to make sure we're talking about the same map | ||
| Bool hasMap; | ||
| } MapStatus; | ||
|
|
||
| // Chat is sent with CHAT | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| LANAPIInterface::ChatType chatType; | ||
| WideChar message[g_lanMaxChatLength+1]; | ||
| } Chat; | ||
|
|
||
| // GameOptions is sent with GAME_OPTIONS | ||
| struct | ||
| { | ||
| char options[m_lanMaxOptionsLength+1]; | ||
| } GameOptions; | ||
|
|
||
| // ProductInfo is sent with REQUEST_PRODUCT_INFO and RESPONSE_PRODUCT_INFO | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps also explain how this is different from the original On that note, does |
||
| struct | ||
| { | ||
| UnsignedInt flags; | ||
| UnsignedInt exeCRC; | ||
| UnsignedInt iniCRC; | ||
| WideChar data[201]; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would be the absolute max possible length for this? I suspect MAX_PACKET_SIZE-12 ? |
||
| } ProductInfo; | ||
xezon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }; | ||
| }; | ||
| #pragma pack(pop) | ||
|
|
||
| static_assert(sizeof(LANMessage) <= MAX_PACKET_SIZE, "LANMessage struct cannot be larger than the max packet size"); | ||
|
|
||
|
|
||
| /** | ||
| * The LANAPI class is used to instantiate a singleton which | ||
| * implements the interface to all LAN broadcast communications. | ||
|
|
@@ -198,6 +347,7 @@ class LANAPI : public LANAPIInterface | |
| // Misc utility functions | ||
| virtual LANGameInfo * LookupGame( UnicodeString gameName ); ///< return a pointer to a game we know about | ||
| virtual LANGameInfo * LookupGameByListOffset( Int offset ); ///< return a pointer to a game we know about | ||
| virtual LANGameInfo * LookupGameByHost( UnsignedInt hostIP ); ///< return a pointer to a game we know about | ||
| virtual LANPlayer * LookupPlayer( UnsignedInt playerIP ); ///< return a pointer to a player we know about | ||
| virtual Bool SetLocalIP( UnsignedInt localIP ); ///< For multiple NIC machines | ||
| virtual void SetLocalIP( AsciiString localIP ); ///< For multiple NIC machines | ||
|
|
@@ -259,6 +409,11 @@ class LANAPI : public LANAPIInterface | |
| void addGame(LANGameInfo *game); | ||
| AsciiString createSlotString( void ); | ||
|
|
||
| static void setProductInfoFromLocalData(GameSlot *slot); | ||
| static void setProductInfoFromMessage(LANMessage *msg, GameSlot *slot); | ||
| static Bool setProductInfoStrings(const UnicodeString(&input)[4], WideChar(&output)[201]); | ||
| static Bool getProductInfoStrings(const WideChar(&input)[201], UnicodeString*(&output)[4]); | ||
|
|
||
| // Functions to handle incoming messages ----------------------------------- | ||
| void handleRequestLocations( LANMessage *msg, UnsignedInt senderIP ); | ||
| void handleGameAnnounce( LANMessage *msg, UnsignedInt senderIP ); | ||
|
|
@@ -277,136 +432,11 @@ class LANAPI : public LANAPIInterface | |
| void handleGameOptions( LANMessage *msg, UnsignedInt senderIP ); | ||
| void handleInActive( LANMessage *msg, UnsignedInt senderIP ); | ||
|
|
||
| void sendProductInfoMessage(LANMessage::Type messageType, UnsignedInt senderIP); | ||
| void handleGameProductInfoRequest(LANMessage *msg, UnsignedInt senderIP); | ||
| void handleGameProductInfoResponse(LANMessage *msg, UnsignedInt senderIP); | ||
| void handleLobbyProductInfoRequest(LANMessage *msg, UnsignedInt senderIP); | ||
| void handleLobbyProductInfoResponse(LANMessage *msg, UnsignedInt senderIP); | ||
| void handleMatchProductInfoRequest(LANMessage *msg, UnsignedInt senderIP); | ||
| void handleMatchProductInfoResponse(LANMessage *msg, UnsignedInt senderIP); | ||
| }; | ||
|
|
||
|
|
||
|
|
||
| /** | ||
| * LAN message class | ||
| */ | ||
| #pragma pack(push, 1) | ||
| struct LANMessage | ||
| { | ||
| enum Type ///< What kind of message are we? | ||
| { | ||
| // Locating everybody | ||
| MSG_REQUEST_LOCATIONS, ///< Hey, where is everybody? | ||
| MSG_GAME_ANNOUNCE, ///< Here I am, and here's my game info! | ||
| MSG_LOBBY_ANNOUNCE, ///< Hey, I'm in the lobby! | ||
|
|
||
| // Joining games | ||
| MSG_REQUEST_JOIN, ///< Let me in! Let me in! | ||
| MSG_JOIN_ACCEPT, ///< Okay, you can join. | ||
| MSG_JOIN_DENY, ///< Go away! We don't want any! | ||
|
|
||
| // Leaving games | ||
| MSG_REQUEST_GAME_LEAVE, ///< I want to leave the game | ||
| MSG_REQUEST_LOBBY_LEAVE,///< I'm leaving the lobby | ||
|
|
||
| // Game options, chat, etc | ||
| MSG_SET_ACCEPT, ///< I'm cool with everything as is. | ||
| MSG_MAP_AVAILABILITY, ///< I do (not) have the map. | ||
| MSG_CHAT, ///< Just spouting my mouth off. | ||
| MSG_GAME_START, ///< Hold on; we're starting! | ||
| MSG_GAME_START_TIMER, ///< The game will start in N seconds | ||
| MSG_GAME_OPTIONS, ///< Here's some info about the game. | ||
| MSG_INACTIVE, ///< I've alt-tabbed out. Unaccept me cause I'm a poo-flinging monkey. | ||
|
|
||
| MSG_REQUEST_GAME_INFO, ///< For direct connect, get the game info from a specific IP Address | ||
| } messageType; | ||
|
|
||
| WideChar name[g_lanPlayerNameLength+1]; ///< My name, for convenience | ||
| char userName[g_lanLoginNameLength+1]; ///< login name, for convenience | ||
| char hostName[g_lanHostNameLength+1]; ///< machine name, for convenience | ||
|
|
||
| // No additional data is required for REQUEST_LOCATIONS, LOBBY_ANNOUNCE, | ||
| // REQUEST_LOBBY_LEAVE, GAME_START. | ||
| union | ||
| { | ||
| // StartTimer is sent with GAME_START_TIMER | ||
| struct | ||
| { | ||
| Int seconds; | ||
| } StartTimer; | ||
|
|
||
| // GameJoined is sent with REQUEST_GAME_LEAVE | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| } GameToLeave; | ||
|
|
||
| // GameInfo if sent with GAME_ANNOUNCE | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| Bool inProgress; | ||
| char options[m_lanMaxOptionsLength+1]; | ||
| Bool isDirectConnect; | ||
| } GameInfo; | ||
|
|
||
| // PlayerInfo is sent with REQUEST_GAME_INFO for direct connect games. | ||
| struct | ||
| { | ||
| UnsignedInt ip; | ||
| WideChar playerName[g_lanPlayerNameLength+1]; | ||
| } PlayerInfo; | ||
|
|
||
| // GameToJoin is sent with REQUEST_JOIN | ||
| struct | ||
| { | ||
| UnsignedInt gameIP; | ||
| UnsignedInt exeCRC; | ||
| UnsignedInt iniCRC; | ||
| char serial[g_maxSerialLength]; | ||
| } GameToJoin; | ||
|
|
||
| // GameJoined is sent with JOIN_ACCEPT | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| UnsignedInt gameIP; | ||
| UnsignedInt playerIP; | ||
| Int slotPosition; | ||
| } GameJoined; | ||
|
|
||
| // GameNotJoined is sent with JOIN_DENY | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| UnsignedInt gameIP; | ||
| UnsignedInt playerIP; | ||
| LANAPIInterface::ReturnType reason; | ||
| } GameNotJoined; | ||
|
|
||
| // Accept is sent with SET_ACCEPT | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| Bool isAccepted; | ||
| } Accept; | ||
|
|
||
| // Accept is sent with MAP_AVAILABILITY | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| UnsignedInt mapCRC; // to make sure we're talking about the same map | ||
| Bool hasMap; | ||
| } MapStatus; | ||
|
|
||
| // Chat is sent with CHAT | ||
| struct | ||
| { | ||
| WideChar gameName[g_lanGameNameLength+1]; | ||
| LANAPIInterface::ChatType chatType; | ||
| WideChar message[g_lanMaxChatLength+1]; | ||
| } Chat; | ||
|
|
||
| // GameOptions is sent with GAME_OPTIONS | ||
| struct | ||
| { | ||
| char options[m_lanMaxOptionsLength+1]; | ||
| } GameOptions; | ||
|
|
||
| }; | ||
| }; | ||
| #pragma pack(pop) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of this flag? It seems oddly specific. Now every product that derives from this will deliver this flag. If all this is needed for is seeing if the remote player has any non retail patch, then simply check if
productTitle(orexeCRC?) is set, because the retail game will not serve this information.