diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/NextGenTransport.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/NextGenTransport.h index 35998abb8ce..ecebdd581d0 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/NextGenTransport.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/NextGenTransport.h @@ -7,9 +7,8 @@ #include "../../Transport.h" #include "../NGMP_include.h" - -#pragma comment(lib, "ENet/enet.lib") #include "GameNetwork/GeneralsOnline/Vendor/ValveNetworkingSockets/steam/isteamnetworkingmessages.h" + #pragma comment(lib, "ValveNetworkingSockets/GameNetworkingSockets.lib") #pragma comment(lib, "ValveNetworkingSockets/abseil_dll.lib") #pragma comment(lib, "ValveNetworkingSockets/libcrypto.lib") diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_Init.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_Init.h index db8b9884b72..e14b10f687b 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_Init.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_Init.h @@ -36,7 +36,7 @@ enum EWebSocketMessageID NETWORK_ROOM_MARK_READY = 5, LOBBY_CURRENT_LOBBY_UPDATE = 6, NETWORK_ROOM_LOBBY_LIST_UPDATE = 7, - PLAYER_CONNECTION_RELAY_UPGRADE = 8, + UNUSED_PLACEHOLDER = 8, // this was relay upgrade, was removed. We can re-use it later, but service needs this placeholder PLAYER_NAME_CHANGE = 9, LOBBY_ROOM_CHAT_FROM_CLIENT = 10, LOBBY_CHAT_FROM_SERVER = 11, @@ -48,6 +48,9 @@ enum EWebSocketMessageID NETWORK_CONNECTION_START_SIGNALLING = 17, NETWORK_CONNECTION_DISCONNECT_PLAYER = 18, NETWORK_CONNECTION_CLIENT_REQUEST_SIGNALLING = 19, + MATCHMAKING_ACTION_JOIN_PREARRANGED_LOBBY = 20, + MATCHMAKING_ACTION_START_GAME = 21, + MATCHMAKING_MESSAGE = 22 }; enum class EQoSRegions @@ -159,7 +162,6 @@ class WebSocket void SendData_JoinNetworkRoom(int roomID); void SendData_LeaveNetworkRoom(); void SendData_MarkReady(bool bReady); - void SendData_ConnectionRelayUpgrade(int64_t userID); void SendData_RequestSignalling(int64_t targetUserID); void SendData_Signalling(int64_t targetUserID, std::vector vecPayload); diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.h index 5aea588c6fe..d5dea07171a 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.h @@ -79,6 +79,33 @@ class NGMP_OnlineServices_LobbyInterface void SearchForLobbies(std::function onStartCallback, std::function)> onCompleteCallback); + std::function m_fnCallbackMatchmakingMessage = nullptr; + void RegisterForMatchmakingMessageCallback(std::function cb) + { + m_fnCallbackMatchmakingMessage = cb; + } + void InvokeMatchmakingMessageCallback(std::string str) + { + if (m_fnCallbackMatchmakingMessage != nullptr) + { + m_fnCallbackMatchmakingMessage(str); + } + } + + void InvokeMatchmakingStartGameCallback() + { + if (m_fnCallbackMatchmakingStartGame != nullptr) + { + m_fnCallbackMatchmakingStartGame(); + } + } + + std::function m_fnCallbackMatchmakingStartGame = nullptr; + void RegisterForMatchmakingStartGameCallback(std::function cb) + { + m_fnCallbackMatchmakingStartGame = cb; + } + // updates void UpdateCurrentLobby_Map(AsciiString strMap, AsciiString strMapPath, bool bIsOfficial, int newMaxPlayers); void UpdateCurrentLobby_LimitSuperweapons(bool bLimitSuperweapons); @@ -373,6 +400,7 @@ class NGMP_OnlineServices_LobbyInterface void LeaveCurrentLobby(); + LobbyEntry GetLobbyFromID(int64_t lobbyID); LobbyEntry GetLobbyFromIndex(int index); std::vector m_vecLobbies; diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_RoomsInterface.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_RoomsInterface.h index 9983d0a6137..3dee20766ba 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_RoomsInterface.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_RoomsInterface.h @@ -83,7 +83,8 @@ struct NGMP_RoomInfo class NetworkRoomMember : public NetworkMemberBase { - +public: + bool IsValid() const { return user_id != -1; } }; class NGMP_OnlineServices_RoomsInterface @@ -149,6 +150,20 @@ class NGMP_OnlineServices_RoomsInterface return nullptr; } + NetworkRoomMember GetRoomMemberFromName(const char* szTargetName) + { + // TODO_NGMP: Migrate away from this, it's slow. This game relies on names too much. + for (auto kvPair : m_mapMembers) + { + if (strcmp(kvPair.second.display_name.c_str(), szTargetName) == 0) + { + return kvPair.second; + } + } + + return NetworkRoomMember(); + } + std::map& GetMembersListForCurrentRoom(); // Chat diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_StatsInterface.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_StatsInterface.h index 56e0a99054d..e26e98f282e 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_StatsInterface.h +++ b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/OnlineServices_StatsInterface.h @@ -438,6 +438,7 @@ class NGMP_OnlineServices_StatsInterface { public: NGMP_OnlineServices_StatsInterface(); + ~NGMP_OnlineServices_StatsInterface(); void GetGlobalStats(std::function cb); diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/callbacks.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/callbacks.h deleted file mode 100644 index 340a4a9896b..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/callbacks.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - @file callbacks.h - @brief ENet callbacks -*/ -#ifndef __ENET_CALLBACKS_H__ -#define __ENET_CALLBACKS_H__ - -#include - -typedef struct _ENetCallbacks -{ - void * (ENET_CALLBACK * malloc) (size_t size); - void (ENET_CALLBACK * free) (void * memory); - void (ENET_CALLBACK * no_memory) (void); -} ENetCallbacks; - -/** @defgroup callbacks ENet internal callbacks - @{ - @ingroup private -*/ -extern void * enet_malloc (size_t); -extern void enet_free (void *); - -/** @} */ - -#endif /* __ENET_CALLBACKS_H__ */ - diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/enet.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/enet.h deleted file mode 100644 index 30010187633..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/enet.h +++ /dev/null @@ -1,616 +0,0 @@ -/** - @file enet.h - @brief ENet public header file -*/ -#ifndef __ENET_ENET_H__ -#define __ENET_ENET_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include - -#ifdef _WIN32 -#include "enet/win32.h" -#else -#include "enet/unix.h" -#endif - -#include "enet/types.h" -#include "enet/protocol.h" -#include "enet/list.h" -#include "enet/callbacks.h" - -#define ENET_VERSION_MAJOR 1 -#define ENET_VERSION_MINOR 3 -#define ENET_VERSION_PATCH 18 -#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) -#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF) -#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF) -#define ENET_VERSION_GET_PATCH(version) ((version)&0xFF) -#define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH) - -typedef enet_uint32 ENetVersion; - -struct _ENetHost; -struct _ENetEvent; -struct _ENetPacket; - -typedef enum _ENetSocketType -{ - ENET_SOCKET_TYPE_STREAM = 1, - ENET_SOCKET_TYPE_DATAGRAM = 2 -} ENetSocketType; - -typedef enum _ENetSocketWait -{ - ENET_SOCKET_WAIT_NONE = 0, - ENET_SOCKET_WAIT_SEND = (1 << 0), - ENET_SOCKET_WAIT_RECEIVE = (1 << 1), - ENET_SOCKET_WAIT_INTERRUPT = (1 << 2) -} ENetSocketWait; - -typedef enum _ENetSocketOption -{ - ENET_SOCKOPT_NONBLOCK = 1, - ENET_SOCKOPT_BROADCAST = 2, - ENET_SOCKOPT_RCVBUF = 3, - ENET_SOCKOPT_SNDBUF = 4, - ENET_SOCKOPT_REUSEADDR = 5, - ENET_SOCKOPT_RCVTIMEO = 6, - ENET_SOCKOPT_SNDTIMEO = 7, - ENET_SOCKOPT_ERROR = 8, - ENET_SOCKOPT_NODELAY = 9, - ENET_SOCKOPT_TTL = 10 -} ENetSocketOption; - -typedef enum _ENetSocketShutdown -{ - ENET_SOCKET_SHUTDOWN_READ = 0, - ENET_SOCKET_SHUTDOWN_WRITE = 1, - ENET_SOCKET_SHUTDOWN_READ_WRITE = 2 -} ENetSocketShutdown; - -#define ENET_HOST_ANY 0 -#define ENET_HOST_BROADCAST 0xFFFFFFFFU -#define ENET_PORT_ANY 0 - -/** - * Portable internet address structure. - * - * The host must be specified in network byte-order, and the port must be in host - * byte-order. The constant ENET_HOST_ANY may be used to specify the default - * server host. The constant ENET_HOST_BROADCAST may be used to specify the - * broadcast address (255.255.255.255). This makes sense for enet_host_connect, - * but not for enet_host_create. Once a server responds to a broadcast, the - * address is updated from ENET_HOST_BROADCAST to the server's actual IP address. - */ -typedef struct _ENetAddress -{ - enet_uint32 host; - enet_uint16 port; -} ENetAddress; - -/** - * Packet flag bit constants. - * - * The host must be specified in network byte-order, and the port must be in - * host byte-order. The constant ENET_HOST_ANY may be used to specify the - * default server host. - - @sa ENetPacket -*/ -typedef enum _ENetPacketFlag -{ - /** packet must be received by the target peer and resend attempts should be - * made until the packet is delivered */ - ENET_PACKET_FLAG_RELIABLE = (1 << 0), - /** packet will not be sequenced with other packets - * not supported for reliable packets - */ - ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1), - /** packet will not allocate data, and user must supply it instead */ - ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2), - /** packet will be fragmented using unreliable (instead of reliable) sends - * if it exceeds the MTU */ - ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3), - - /** whether the packet has been sent from all queues it has been entered into */ - ENET_PACKET_FLAG_SENT = (1<<8) -} ENetPacketFlag; - -typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *); - -/** - * ENet packet structure. - * - * An ENet data packet that may be sent to or received from a peer. The shown - * fields should only be read and never modified. The data field contains the - * allocated data for the packet. The dataLength fields specifies the length - * of the allocated data. The flags field is either 0 (specifying no flags), - * or a bitwise-or of any combination of the following flags: - * - * ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer - * and resend attempts should be made until the packet is delivered - * - * ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets - * (not supported for reliable packets) - * - * ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead - * - * ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable - * (instead of reliable) sends if it exceeds the MTU - * - * ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into - @sa ENetPacketFlag - */ -typedef struct _ENetPacket -{ - size_t referenceCount; /**< internal use only */ - enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */ - enet_uint8 * data; /**< allocated data for packet */ - size_t dataLength; /**< length of data */ - ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */ - void * userData; /**< application private data, may be freely modified */ -} ENetPacket; - -typedef struct _ENetAcknowledgement -{ - ENetListNode acknowledgementList; - enet_uint32 sentTime; - ENetProtocol command; -} ENetAcknowledgement; - -typedef struct _ENetOutgoingCommand -{ - ENetListNode outgoingCommandList; - enet_uint16 reliableSequenceNumber; - enet_uint16 unreliableSequenceNumber; - enet_uint32 sentTime; - enet_uint32 roundTripTimeout; - enet_uint32 queueTime; - enet_uint32 fragmentOffset; - enet_uint16 fragmentLength; - enet_uint16 sendAttempts; - ENetProtocol command; - ENetPacket * packet; -} ENetOutgoingCommand; - -typedef struct _ENetIncomingCommand -{ - ENetListNode incomingCommandList; - enet_uint16 reliableSequenceNumber; - enet_uint16 unreliableSequenceNumber; - ENetProtocol command; - enet_uint32 fragmentCount; - enet_uint32 fragmentsRemaining; - enet_uint32 * fragments; - ENetPacket * packet; -} ENetIncomingCommand; - -typedef enum _ENetPeerState -{ - ENET_PEER_STATE_DISCONNECTED = 0, - ENET_PEER_STATE_CONNECTING = 1, - ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2, - ENET_PEER_STATE_CONNECTION_PENDING = 3, - ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4, - ENET_PEER_STATE_CONNECTED = 5, - ENET_PEER_STATE_DISCONNECT_LATER = 6, - ENET_PEER_STATE_DISCONNECTING = 7, - ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8, - ENET_PEER_STATE_ZOMBIE = 9 -} ENetPeerState; - -#ifndef ENET_BUFFER_MAXIMUM -#define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS) -#endif - -enum -{ - ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024, - ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, - ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, - ENET_HOST_DEFAULT_MTU = 1392, - ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, - ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, - - ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500, - ENET_PEER_DEFAULT_PACKET_THROTTLE = 32, - ENET_PEER_PACKET_THROTTLE_SCALE = 32, - ENET_PEER_PACKET_THROTTLE_COUNTER = 7, - ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2, - ENET_PEER_PACKET_THROTTLE_DECELERATION = 2, - ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000, - ENET_PEER_PACKET_LOSS_SCALE = (1 << 16), - ENET_PEER_PACKET_LOSS_INTERVAL = 10000, - ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024, - ENET_PEER_TIMEOUT_LIMIT = 32, - ENET_PEER_TIMEOUT_MINIMUM = 5000, - ENET_PEER_TIMEOUT_MAXIMUM = 30000, - ENET_PEER_PING_INTERVAL = 500, - ENET_PEER_UNSEQUENCED_WINDOWS = 64, - ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024, - ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32, - ENET_PEER_RELIABLE_WINDOWS = 16, - ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000, - ENET_PEER_FREE_RELIABLE_WINDOWS = 8 -}; - -typedef struct _ENetChannel -{ - enet_uint16 outgoingReliableSequenceNumber; - enet_uint16 outgoingUnreliableSequenceNumber; - enet_uint16 usedReliableWindows; - enet_uint16 reliableWindows [ENET_PEER_RELIABLE_WINDOWS]; - enet_uint16 incomingReliableSequenceNumber; - enet_uint16 incomingUnreliableSequenceNumber; - ENetList incomingReliableCommands; - ENetList incomingUnreliableCommands; -} ENetChannel; - -typedef enum _ENetPeerFlag -{ - ENET_PEER_FLAG_NEEDS_DISPATCH = (1 << 0), - ENET_PEER_FLAG_CONTINUE_SENDING = (1 << 1) -} ENetPeerFlag; - -/** - * An ENet peer which data packets may be sent or received from. - * - * No fields should be modified unless otherwise specified. - */ -typedef struct _ENetPeer -{ - ENetListNode dispatchList; - struct _ENetHost * host; - enet_uint16 outgoingPeerID; - enet_uint16 incomingPeerID; - enet_uint32 connectID; - enet_uint8 outgoingSessionID; - enet_uint8 incomingSessionID; - ENetAddress address; /**< Internet address of the peer */ - void * data; /**< Application private data, may be freely modified */ - ENetPeerState state; - ENetChannel * channels; - size_t channelCount; /**< Number of channels allocated for communication with peer */ - enet_uint32 incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */ - enet_uint32 outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */ - enet_uint32 incomingBandwidthThrottleEpoch; - enet_uint32 outgoingBandwidthThrottleEpoch; - enet_uint32 incomingDataTotal; - enet_uint32 outgoingDataTotal; - enet_uint32 lastSendTime; - enet_uint32 lastReceiveTime; - enet_uint32 nextTimeout; - enet_uint32 earliestTimeout; - enet_uint32 packetLossEpoch; - enet_uint32 packetsSent; - enet_uint32 packetsLost; - enet_uint32 packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */ - enet_uint32 packetLossVariance; - enet_uint32 packetThrottle; - enet_uint32 packetThrottleLimit; - enet_uint32 packetThrottleCounter; - enet_uint32 packetThrottleEpoch; - enet_uint32 packetThrottleAcceleration; - enet_uint32 packetThrottleDeceleration; - enet_uint32 packetThrottleInterval; - enet_uint32 pingInterval; - enet_uint32 timeoutLimit; - enet_uint32 timeoutMinimum; - enet_uint32 timeoutMaximum; - enet_uint32 lastRoundTripTime; - enet_uint32 lowestRoundTripTime; - enet_uint32 lastRoundTripTimeVariance; - enet_uint32 highestRoundTripTimeVariance; - enet_uint32 roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */ - enet_uint32 roundTripTimeVariance; - enet_uint32 mtu; - enet_uint32 windowSize; - enet_uint32 reliableDataInTransit; - enet_uint16 outgoingReliableSequenceNumber; - ENetList acknowledgements; - ENetList sentReliableCommands; - ENetList outgoingSendReliableCommands; - ENetList outgoingCommands; - ENetList dispatchedCommands; - enet_uint16 flags; - enet_uint16 reserved; - enet_uint16 incomingUnsequencedGroup; - enet_uint16 outgoingUnsequencedGroup; - enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; - enet_uint32 eventData; - size_t totalWaitingData; -} ENetPeer; - -/** An ENet packet compressor for compressing UDP packets before socket sends or receives. - */ -typedef struct _ENetCompressor -{ - /** Context data for the compressor. Must be non-NULL. */ - void * context; - /** Compresses from inBuffers[0:inBufferCount-1], containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */ - size_t (ENET_CALLBACK * compress) (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit); - /** Decompresses from inData, containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */ - size_t (ENET_CALLBACK * decompress) (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit); - /** Destroys the context when compression is disabled or the host is destroyed. May be NULL. */ - void (ENET_CALLBACK * destroy) (void * context); -} ENetCompressor; - -/** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */ -typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * buffers, size_t bufferCount); - -/** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */ -typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, struct _ENetEvent * event); - -/** An ENet host for communicating with peers. - * - * No fields should be modified unless otherwise stated. - - @sa enet_host_create() - @sa enet_host_destroy() - @sa enet_host_connect() - @sa enet_host_service() - @sa enet_host_flush() - @sa enet_host_broadcast() - @sa enet_host_compress() - @sa enet_host_compress_with_range_coder() - @sa enet_host_channel_limit() - @sa enet_host_bandwidth_limit() - @sa enet_host_bandwidth_throttle() - */ -typedef struct _ENetHost -{ - ENetSocket socket; - ENetAddress address; /**< Internet address of the host */ - enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */ - enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */ - enet_uint32 bandwidthThrottleEpoch; - enet_uint32 mtu; - enet_uint32 randomSeed; - int recalculateBandwidthLimits; - ENetPeer * peers; /**< array of peers allocated for this host */ - size_t peerCount; /**< number of peers allocated for this host */ - size_t channelLimit; /**< maximum number of channels allowed for connected peers */ - enet_uint32 serviceTime; - ENetList dispatchQueue; - enet_uint32 totalQueued; - size_t packetSize; - enet_uint16 headerFlags; - ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS]; - size_t commandCount; - ENetBuffer buffers [ENET_BUFFER_MAXIMUM]; - size_t bufferCount; - ENetChecksumCallback checksum; /**< callback the user can set to enable packet checksums for this host */ - ENetCompressor compressor; - enet_uint8 packetData [2][ENET_PROTOCOL_MAXIMUM_MTU]; - ENetAddress receivedAddress; - enet_uint8 * receivedData; - size_t receivedDataLength; - enet_uint32 totalSentData; /**< total data sent, user should reset to 0 as needed to prevent overflow */ - enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */ - enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */ - enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */ - ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */ - size_t connectedPeers; - size_t bandwidthLimitedPeers; - size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */ - size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */ - size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */ -} ENetHost; - -/** - * An ENet event type, as specified in @ref ENetEvent. - */ -typedef enum _ENetEventType -{ - /** no event occurred within the specified time limit */ - ENET_EVENT_TYPE_NONE = 0, - - /** a connection request initiated by enet_host_connect has completed. - * The peer field contains the peer which successfully connected. - */ - ENET_EVENT_TYPE_CONNECT = 1, - - /** a peer has disconnected. This event is generated on a successful - * completion of a disconnect initiated by enet_peer_disconnect, if - * a peer has timed out, or if a connection request intialized by - * enet_host_connect has timed out. The peer field contains the peer - * which disconnected. The data field contains user supplied data - * describing the disconnection, or 0, if none is available. - */ - ENET_EVENT_TYPE_DISCONNECT = 2, - - /** a packet has been received from a peer. The peer field specifies the - * peer which sent the packet. The channelID field specifies the channel - * number upon which the packet was received. The packet field contains - * the packet that was received; this packet must be destroyed with - * enet_packet_destroy after use. - */ - ENET_EVENT_TYPE_RECEIVE = 3 -} ENetEventType; - -/** - * An ENet event as returned by enet_host_service(). - - @sa enet_host_service - */ -typedef struct _ENetEvent -{ - ENetEventType type; /**< type of the event */ - ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */ - enet_uint8 channelID; /**< channel on the peer that generated the event, if appropriate */ - enet_uint32 data; /**< data associated with the event, if appropriate */ - ENetPacket * packet; /**< packet associated with the event, if appropriate */ -} ENetEvent; - -/** @defgroup global ENet global functions - @{ -*/ - -/** - Initializes ENet globally. Must be called prior to using any functions in - ENet. - @returns 0 on success, < 0 on failure -*/ -ENET_API int enet_initialize (void); - -/** - Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored. - - @param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use - @param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults - @returns 0 on success, < 0 on failure -*/ -ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits); - -/** - Shuts down ENet globally. Should be called when a program that has - initialized ENet exits. -*/ -ENET_API void enet_deinitialize (void); - -/** - Gives the linked version of the ENet library. - @returns the version number -*/ -ENET_API ENetVersion enet_linked_version (void); - -/** @} */ - -/** @defgroup private ENet private implementation functions */ - -/** - Returns the wall-time in milliseconds. Its initial value is unspecified - unless otherwise set. - */ -ENET_API enet_uint32 enet_time_get (void); -/** - Sets the current wall-time in milliseconds. - */ -ENET_API void enet_time_set (enet_uint32); - -/** @defgroup socket ENet socket functions - @{ -*/ -ENET_API ENetSocket enet_socket_create (ENetSocketType); -ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *); -ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *); -ENET_API int enet_socket_listen (ENetSocket, int); -ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *); -ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *); -ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t); -ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t); -ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32); -ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int); -ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *); -ENET_API int enet_socket_shutdown (ENetSocket, ENetSocketShutdown); -ENET_API void enet_socket_destroy (ENetSocket); -ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32); - -/** @} */ - -/** @defgroup Address ENet address functions - @{ -*/ - -/** Attempts to parse the printable form of the IP address in the parameter hostName - and sets the host field in the address parameter if successful. - @param address destination to store the parsed IP address - @param hostName IP address to parse - @retval 0 on success - @retval < 0 on failure - @returns the address of the given hostName in address on success -*/ -ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostName); - -/** Attempts to resolve the host named by the parameter hostName and sets - the host field in the address parameter if successful. - @param address destination to store resolved address - @param hostName host name to lookup - @retval 0 on success - @retval < 0 on failure - @returns the address of the given hostName in address on success -*/ -ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName); - -/** Gives the printable form of the IP address specified in the address parameter. - @param address address printed - @param hostName destination for name, must not be NULL - @param nameLength maximum length of hostName. - @returns the null-terminated name of the host in hostName on success - @retval 0 on success - @retval < 0 on failure -*/ -ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength); - -/** Attempts to do a reverse lookup of the host field in the address parameter. - @param address address used for reverse lookup - @param hostName destination for name, must not be NULL - @param nameLength maximum length of hostName. - @returns the null-terminated name of the host in hostName on success - @retval 0 on success - @retval < 0 on failure -*/ -ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength); - -/** @} */ - -ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32); -ENET_API void enet_packet_destroy (ENetPacket *); -ENET_API int enet_packet_resize (ENetPacket *, size_t); -ENET_API enet_uint32 enet_crc32 (const ENetBuffer *, size_t); - -ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32); -ENET_API void enet_host_destroy (ENetHost *); -ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32); -ENET_API int enet_host_check_events (ENetHost *, ENetEvent *); -ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32); -ENET_API void enet_host_flush (ENetHost *); -ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *); -ENET_API void enet_host_compress (ENetHost *, const ENetCompressor *); -ENET_API int enet_host_compress_with_range_coder (ENetHost * host); -ENET_API void enet_host_channel_limit (ENetHost *, size_t); -ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32); -extern void enet_host_bandwidth_throttle (ENetHost *); -extern enet_uint32 enet_host_random_seed (void); -extern enet_uint32 enet_host_random (ENetHost *); - -ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *); -ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID); -ENET_API void enet_peer_ping (ENetPeer *); -ENET_API void enet_peer_ping_interval (ENetPeer *, enet_uint32); -ENET_API void enet_peer_timeout (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); -ENET_API void enet_peer_reset (ENetPeer *); -ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32); -ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32); -ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32); -ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32); -extern int enet_peer_throttle (ENetPeer *, enet_uint32); -extern void enet_peer_reset_queues (ENetPeer *); -extern int enet_peer_has_outgoing_commands (ENetPeer *); -extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *); -extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16); -extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32); -extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16); -extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *); -extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *); -extern void enet_peer_on_connect (ENetPeer *); -extern void enet_peer_on_disconnect (ENetPeer *); - -ENET_API void * enet_range_coder_create (void); -ENET_API void enet_range_coder_destroy (void *); -ENET_API size_t enet_range_coder_compress (void *, const ENetBuffer *, size_t, size_t, enet_uint8 *, size_t); -ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, enet_uint8 *, size_t); - -extern size_t enet_protocol_command_size (enet_uint8); - -#ifdef __cplusplus -} -#endif - -#endif /* __ENET_ENET_H__ */ - diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/list.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/list.h deleted file mode 100644 index d7b2600848f..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/list.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - @file list.h - @brief ENet list management -*/ -#ifndef __ENET_LIST_H__ -#define __ENET_LIST_H__ - -#include - -typedef struct _ENetListNode -{ - struct _ENetListNode * next; - struct _ENetListNode * previous; -} ENetListNode; - -typedef ENetListNode * ENetListIterator; - -typedef struct _ENetList -{ - ENetListNode sentinel; -} ENetList; - -extern void enet_list_clear (ENetList *); - -extern ENetListIterator enet_list_insert (ENetListIterator, void *); -extern void * enet_list_remove (ENetListIterator); -extern ENetListIterator enet_list_move (ENetListIterator, void *, void *); - -extern size_t enet_list_size (ENetList *); - -#define enet_list_begin(list) ((list) -> sentinel.next) -#define enet_list_end(list) (& (list) -> sentinel) - -#define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list)) - -#define enet_list_next(iterator) ((iterator) -> next) -#define enet_list_previous(iterator) ((iterator) -> previous) - -#define enet_list_front(list) ((void *) (list) -> sentinel.next) -#define enet_list_back(list) ((void *) (list) -> sentinel.previous) - -#endif /* __ENET_LIST_H__ */ - diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/protocol.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/protocol.h deleted file mode 100644 index f8c73d8a668..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/protocol.h +++ /dev/null @@ -1,198 +0,0 @@ -/** - @file protocol.h - @brief ENet protocol -*/ -#ifndef __ENET_PROTOCOL_H__ -#define __ENET_PROTOCOL_H__ - -#include "enet/types.h" - -enum -{ - ENET_PROTOCOL_MINIMUM_MTU = 576, - ENET_PROTOCOL_MAXIMUM_MTU = 4096, - ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32, - ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096, - ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536, - ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1, - ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255, - ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF, - ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024 -}; - -typedef enum _ENetProtocolCommand -{ - ENET_PROTOCOL_COMMAND_NONE = 0, - ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1, - ENET_PROTOCOL_COMMAND_CONNECT = 2, - ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3, - ENET_PROTOCOL_COMMAND_DISCONNECT = 4, - ENET_PROTOCOL_COMMAND_PING = 5, - ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6, - ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7, - ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8, - ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9, - ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10, - ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11, - ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12, - ENET_PROTOCOL_COMMAND_COUNT = 13, - - ENET_PROTOCOL_COMMAND_MASK = 0x0F -} ENetProtocolCommand; - -typedef enum _ENetProtocolFlag -{ - ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7), - ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6), - - ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14), - ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15), - ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME, - - ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12), - ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12 -} ENetProtocolFlag; - -#ifdef _MSC_VER -#pragma pack(push, 1) -#define ENET_PACKED -#elif defined(__GNUC__) || defined(__clang__) -#define ENET_PACKED __attribute__ ((packed)) -#else -#define ENET_PACKED -#endif - -typedef struct _ENetProtocolHeader -{ - enet_uint16 peerID; - enet_uint16 sentTime; -} ENET_PACKED ENetProtocolHeader; - -typedef struct _ENetProtocolCommandHeader -{ - enet_uint8 command; - enet_uint8 channelID; - enet_uint16 reliableSequenceNumber; -} ENET_PACKED ENetProtocolCommandHeader; - -typedef struct _ENetProtocolAcknowledge -{ - ENetProtocolCommandHeader header; - enet_uint16 receivedReliableSequenceNumber; - enet_uint16 receivedSentTime; -} ENET_PACKED ENetProtocolAcknowledge; - -typedef struct _ENetProtocolConnect -{ - ENetProtocolCommandHeader header; - enet_uint16 outgoingPeerID; - enet_uint8 incomingSessionID; - enet_uint8 outgoingSessionID; - enet_uint32 mtu; - enet_uint32 windowSize; - enet_uint32 channelCount; - enet_uint32 incomingBandwidth; - enet_uint32 outgoingBandwidth; - enet_uint32 packetThrottleInterval; - enet_uint32 packetThrottleAcceleration; - enet_uint32 packetThrottleDeceleration; - enet_uint32 connectID; - enet_uint32 data; -} ENET_PACKED ENetProtocolConnect; - -typedef struct _ENetProtocolVerifyConnect -{ - ENetProtocolCommandHeader header; - enet_uint16 outgoingPeerID; - enet_uint8 incomingSessionID; - enet_uint8 outgoingSessionID; - enet_uint32 mtu; - enet_uint32 windowSize; - enet_uint32 channelCount; - enet_uint32 incomingBandwidth; - enet_uint32 outgoingBandwidth; - enet_uint32 packetThrottleInterval; - enet_uint32 packetThrottleAcceleration; - enet_uint32 packetThrottleDeceleration; - enet_uint32 connectID; -} ENET_PACKED ENetProtocolVerifyConnect; - -typedef struct _ENetProtocolBandwidthLimit -{ - ENetProtocolCommandHeader header; - enet_uint32 incomingBandwidth; - enet_uint32 outgoingBandwidth; -} ENET_PACKED ENetProtocolBandwidthLimit; - -typedef struct _ENetProtocolThrottleConfigure -{ - ENetProtocolCommandHeader header; - enet_uint32 packetThrottleInterval; - enet_uint32 packetThrottleAcceleration; - enet_uint32 packetThrottleDeceleration; -} ENET_PACKED ENetProtocolThrottleConfigure; - -typedef struct _ENetProtocolDisconnect -{ - ENetProtocolCommandHeader header; - enet_uint32 data; -} ENET_PACKED ENetProtocolDisconnect; - -typedef struct _ENetProtocolPing -{ - ENetProtocolCommandHeader header; -} ENET_PACKED ENetProtocolPing; - -typedef struct _ENetProtocolSendReliable -{ - ENetProtocolCommandHeader header; - enet_uint16 dataLength; -} ENET_PACKED ENetProtocolSendReliable; - -typedef struct _ENetProtocolSendUnreliable -{ - ENetProtocolCommandHeader header; - enet_uint16 unreliableSequenceNumber; - enet_uint16 dataLength; -} ENET_PACKED ENetProtocolSendUnreliable; - -typedef struct _ENetProtocolSendUnsequenced -{ - ENetProtocolCommandHeader header; - enet_uint16 unsequencedGroup; - enet_uint16 dataLength; -} ENET_PACKED ENetProtocolSendUnsequenced; - -typedef struct _ENetProtocolSendFragment -{ - ENetProtocolCommandHeader header; - enet_uint16 startSequenceNumber; - enet_uint16 dataLength; - enet_uint32 fragmentCount; - enet_uint32 fragmentNumber; - enet_uint32 totalLength; - enet_uint32 fragmentOffset; -} ENET_PACKED ENetProtocolSendFragment; - -typedef union _ENetProtocol -{ - ENetProtocolCommandHeader header; - ENetProtocolAcknowledge acknowledge; - ENetProtocolConnect connect; - ENetProtocolVerifyConnect verifyConnect; - ENetProtocolDisconnect disconnect; - ENetProtocolPing ping; - ENetProtocolSendReliable sendReliable; - ENetProtocolSendUnreliable sendUnreliable; - ENetProtocolSendUnsequenced sendUnsequenced; - ENetProtocolSendFragment sendFragment; - ENetProtocolBandwidthLimit bandwidthLimit; - ENetProtocolThrottleConfigure throttleConfigure; -} ENET_PACKED ENetProtocol; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif - -#endif /* __ENET_PROTOCOL_H__ */ - diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/time.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/time.h deleted file mode 100644 index c82a5460351..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/time.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - @file time.h - @brief ENet time constants and macros -*/ -#ifndef __ENET_TIME_H__ -#define __ENET_TIME_H__ - -#define ENET_TIME_OVERFLOW 86400000 - -#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW) -#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW) -#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b)) -#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b)) - -#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b)) - -#endif /* __ENET_TIME_H__ */ - diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/types.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/types.h deleted file mode 100644 index ab010a4b13d..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/types.h +++ /dev/null @@ -1,13 +0,0 @@ -/** - @file types.h - @brief type definitions for ENet -*/ -#ifndef __ENET_TYPES_H__ -#define __ENET_TYPES_H__ - -typedef unsigned char enet_uint8; /**< unsigned 8-bit type */ -typedef unsigned short enet_uint16; /**< unsigned 16-bit type */ -typedef unsigned int enet_uint32; /**< unsigned 32-bit type */ - -#endif /* __ENET_TYPES_H__ */ - diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/unix.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/unix.h deleted file mode 100644 index b55be33103d..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/unix.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - @file unix.h - @brief ENet Unix header -*/ -#ifndef __ENET_UNIX_H__ -#define __ENET_UNIX_H__ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef MSG_MAXIOVLEN -#define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN -#endif - -typedef int ENetSocket; - -#define ENET_SOCKET_NULL -1 - -#define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */ -#define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */ - -#define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */ -#define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */ - -typedef struct -{ - void * data; - size_t dataLength; -} ENetBuffer; - -#define ENET_CALLBACK - -#define ENET_API extern - -typedef fd_set ENetSocketSet; - -#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) -#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) -#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) -#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) - -#endif /* __ENET_UNIX_H__ */ - diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/utility.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/utility.h deleted file mode 100644 index b04bb7a5b35..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/utility.h +++ /dev/null @@ -1,13 +0,0 @@ -/** - @file utility.h - @brief ENet utility header -*/ -#ifndef __ENET_UTILITY_H__ -#define __ENET_UTILITY_H__ - -#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y)) -#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) -#define ENET_DIFFERENCE(x, y) ((x) < (y) ? (y) - (x) : (x) - (y)) - -#endif /* __ENET_UTILITY_H__ */ - diff --git a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/win32.h b/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/win32.h deleted file mode 100644 index 6fcf4c811c2..00000000000 --- a/GeneralsMD/Code/GameEngine/Include/GameNetwork/GeneralsOnline/Vendor/ENet/win32.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - @file win32.h - @brief ENet Win32 header -*/ -#ifndef __ENET_WIN32_H__ -#define __ENET_WIN32_H__ - -#ifdef _MSC_VER -#ifdef ENET_BUILDING_LIB -#pragma warning (disable: 4267) // size_t to int conversion -#pragma warning (disable: 4244) // 64bit to 32bit int -#pragma warning (disable: 4018) // signed/unsigned mismatch -#pragma warning (disable: 4146) // unary minus operator applied to unsigned type -#define _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_WARNINGS -#endif -#endif - -#include - -#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H)) -#include -#endif - -typedef SOCKET ENetSocket; - -#define ENET_SOCKET_NULL INVALID_SOCKET - -#define ENET_HOST_TO_NET_16(value) (htons (value)) -#define ENET_HOST_TO_NET_32(value) (htonl (value)) - -#define ENET_NET_TO_HOST_16(value) (ntohs (value)) -#define ENET_NET_TO_HOST_32(value) (ntohl (value)) - -typedef struct -{ - size_t dataLength; - void * data; -} ENetBuffer; - -#define ENET_CALLBACK __cdecl - -#ifdef ENET_DLL -#ifdef ENET_BUILDING_LIB -#define ENET_API __declspec( dllexport ) -#else -#define ENET_API __declspec( dllimport ) -#endif /* ENET_BUILDING_LIB */ -#else /* !ENET_DLL */ -#define ENET_API extern -#endif /* ENET_DLL */ - -typedef fd_set ENetSocketSet; - -#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset)) -#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset)) -#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset)) -#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset)) - -#endif /* __ENET_WIN32_H__ */ - - diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupPlayerInfo.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupPlayerInfo.cpp index c63806e5678..617d031f8c7 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupPlayerInfo.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupPlayerInfo.cpp @@ -246,22 +246,6 @@ void GetAdditionalDisconnectsFromUserFile(PSPlayerStats *stats) // default values RankPoints::RankPoints(void) { - NGMP_OnlineServices_StatsInterface* statsInterface = NGMP_OnlineServicesManager::GetInterface(); - - if (statsInterface != nullptr) - { - m_ranks[RANK_PRIVATE] = 0; - m_ranks[RANK_CORPORAL] = statsInterface->getPointsForRank(RANK_CORPORAL); // 5 - m_ranks[RANK_SERGEANT] = statsInterface->getPointsForRank(RANK_SERGEANT); // 10 - m_ranks[RANK_LIEUTENANT] = statsInterface->getPointsForRank(RANK_LIEUTENANT); // 20 - m_ranks[RANK_CAPTAIN] = statsInterface->getPointsForRank(RANK_CAPTAIN); // 50 - m_ranks[RANK_MAJOR] = statsInterface->getPointsForRank(RANK_MAJOR); // 100 - m_ranks[RANK_COLONEL] = statsInterface->getPointsForRank(RANK_COLONEL); // 200 - m_ranks[RANK_BRIGADIER_GENERAL] = statsInterface->getPointsForRank(RANK_BRIGADIER_GENERAL); // 500 - m_ranks[RANK_GENERAL] = statsInterface->getPointsForRank(RANK_GENERAL); // 1000 - m_ranks[RANK_COMMANDER_IN_CHIEF] = statsInterface->getPointsForRank(RANK_COMMANDER_IN_CHIEF); // 2000 - } - m_winMultiplier = 3.0f; m_lostMultiplier = 0.0f; m_hourSpentOnlineMultiplier = 1.0f; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLobbyMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLobbyMenu.cpp index 7ddf8a36233..3b30a398c5f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLobbyMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLLobbyMenu.cpp @@ -296,22 +296,140 @@ static void playerTooltip(GameWindow *window, } UnicodeString uName = GadgetListBoxGetText(window, row, COLUMN_PLAYERNAME); - AsciiString aName; - aName.translate(uName); + // TODO_NGMP: This causes issues with duplicate names. We should have better ways of looking this up + perhaps only allow unique names NGMP_OnlineServices_RoomsInterface* pRoomsInterface = NGMP_OnlineServicesManager::GetInterface(); - if (pRoomsInterface != nullptr) + NGMP_OnlineServices_AuthInterface* pAuthInterface = NGMP_OnlineServicesManager::GetInterface(); + NGMP_OnlineServices_StatsInterface* pStatsInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pRoomsInterface != nullptr && pAuthInterface != nullptr && pStatsInterface != nullptr) { - NetworkRoomMember* pRoomMember = pRoomsInterface->GetRoomMemberFromIndex(row); + int profileID = (int)GadgetListBoxGetItemData(listboxLobbyPlayers, row, 0); + NetworkRoomMember* roomMember = pRoomsInterface->GetRoomMemberFromID(profileID); + // TODO_NGMP: This is an async call, we should block future popups until it returns to avoid weirdness if (col > 0) { - if (pRoomMember != nullptr) + if (roomMember != nullptr) { - UnicodeString ucTooltip; - ucTooltip.format(L"Display Name: %s\nUser ID: %lld", from_utf8(pRoomMember->display_name).c_str(), pRoomMember->user_id); + // new + pStatsInterface->findPlayerStatsByID(roomMember->user_id, [=](bool bSuccess, PSPlayerStats stats) + { + if (!bSuccess) + { + TheMouse->setCursorTooltip(UnicodeString(L"Error: 1"), -1, NULL, 1.5f); + } + else + { + UnicodeString tooltip = UnicodeString::TheEmptyString; + if (roomMember->user_id == pAuthInterface->GetUserID()) + { + tooltip.format(TheGameText->fetch("TOOLTIP:LocalPlayer"), uName.str()); } + else + { + // not us + // TODO_SOCIAL + bool bIsFriend = false; + if (bIsFriend) + { + // buddy + tooltip.format(TheGameText->fetch("TOOLTIP:BuddyPlayer"), uName.str()); + } + else + { + // non-buddy profiled player + tooltip.format(TheGameText->fetch("TOOLTIP:ProfiledPlayer"), uName.str()); + + // NOTE: Removed non-profiled generic player, this doesn't exist on Generals Online, everyone has a profile + } + } + + // add user ID + UnicodeString tmp; + tmp.format(L"\nUser ID: %lld", roomMember->user_id); + tooltip.concat(tmp); - TheMouse->setCursorTooltip(ucTooltip, -1, NULL, 1.5f); // the text and width are the only params used. the others are the default values. + // TODO_SOCIAL + bool bIgnored = false; + if (bIgnored) + { + tooltip.concat(TheGameText->fetch("TOOLTIP:IgnoredModifier")); + } + + Int rankPoints = CalculateRank(stats); + Int rank = 0; + Int i = 0; + while (rankPoints >= TheRankPointValues->m_ranks[i + 1]) + ++i; + rank = i; + + // determine favorite side + Int mostGames = 0; + Int favorite = 0; + for (auto it = stats.games.begin(); it != stats.games.end(); ++it) + { + if (it->second >= mostGames) + { + mostGames = it->second; + favorite = it->first; + } + } + + AsciiString sideName = "GUI:RandomSide"; + if (mostGames > 0) + { + const PlayerTemplate* fac = ThePlayerTemplateStore->getNthPlayerTemplate(favorite); + if (fac) + { + sideName.format("SIDE:%s", fac->getSide().str()); + } + } + AsciiString rankName; + rankName.format("GUI:GSRank%d", rank); + + tmp.clear(); + tmp.format(L"\n\nFavorite Side: %ls\nRank: %ls", TheGameText->fetch(sideName).str(), TheGameText->fetch(rankName).str()); + tooltip.concat(tmp); + + int totalWins = 0; + int totalLosses = 0; + int totalDC = 0; + int totalWinsInRow = 0; + int totalLossesInRow = 0; + int totalDCInRow = 0; + int maxWinsInRow = 0; + int maxLossesInRow = 0; + int maxDCInRow = 0; + + for (int i = 0; i < stats.wins.size(); ++i) + { + totalWins += stats.wins[i]; + totalLosses += stats.losses[i]; + totalDC += stats.discons[i]; + totalWinsInRow = stats.winsInARow; + totalLossesInRow = stats.lossesInARow; + totalDCInRow = stats.disconsInARow; + + maxWinsInRow = stats.maxWinsInARow; + maxLossesInRow = stats.maxLossesInARow; + maxDCInRow = stats.maxDisconsInARow; + } + + tmp.clear(); + tmp.format(L"\n\nTotal Wins: %d\nTotal Losses: %d\nTotal Disconnects: %d\n\nCurrent Win Streak: %d\nCurrent Loss Streak: %d\nCurrent Disconnect Streak: %d\n\nLongest Win Streak: %d\nLongest Loss Streak: %d\nLongest Disconnect Streak: %d", + totalWins, + totalLosses, + totalDC, + totalWinsInRow, + totalLossesInRow, + totalDCInRow, + maxWinsInRow, + maxLossesInRow, + maxDCInRow); + tooltip.concat(tmp); + + TheMouse->setCursorTooltip(tooltip, -1, NULL, 1.5f); // the text and width are the only params used. the others are the default values. + } + }, EStatsRequestPolicy::RESPECT_CACHE_ALLOW_REQUEST); } else { @@ -594,6 +712,9 @@ static Int insertPlayerInListbox(const PlayerInfo& info, Color color) Int index = GadgetListBoxAddEntryImage(listboxLobbyPlayers, rankImg, -1, 0, w, h); GadgetListBoxAddEntryText(listboxLobbyPlayers, uStr, color, index, 1); #endif + + // attach data + GadgetListBoxSetItemData(listboxLobbyPlayers, (void*)info.m_profileID, index); return index; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp index 3b6bb9e7f15..4b9799684fd 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp @@ -84,6 +84,7 @@ static Bool s_inQM = FALSE; extern NGMPGame* TheNGMPGame; #endif #include "../OnlineServices_MatchmakingInterface.h" +#include "../OnlineServices_LobbyInterface.h" // PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// // window ids ------------------------------------------------------------------------------ @@ -636,6 +637,11 @@ static void populateQuickMatchMapSelectListbox( QuickMatchPreferences& pref ) static void saveQuickMatchOptions( void ) { + // TODO_QUICKMATCH +#if defined(GENERALS_ONLINE) + return; +#endif + if(isInInit) return; QuickMatchPreferences pref; @@ -718,6 +724,224 @@ static void saveQuickMatchOptions( void ) //------------------------------------------------------------------------------------------------- void WOLQuickMatchMenuInit( WindowLayout *layout, void *userData ) { +#if defined(GENERALS_ONLINE) + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + + // cannot connect to the lobby we joined + pLobbyInterface->RegisterForCannotConnectToLobbyCallback([](void) + { + // TODO_QUICKMATCH: Show error message + stop matchmaking + enable buttons again + }); +#endif + + + if (pLobbyInterface != nullptr) + { + // TODO_QUICKMATCH: Deregister when leaving QM + pLobbyInterface->RegisterForMatchmakingMessageCallback([](std::string strMsg) + { + UnicodeString uMsg; + uMsg.format(L"%hs", strMsg.c_str()); + + Int index = GadgetListBoxAddEntryText(quickmatchTextWindow, uMsg, GameSpyColor[GSCOLOR_DEFAULT], -1, -1); + GadgetListBoxSetItemData(quickmatchTextWindow, (void*)-1, index); + }); + + pLobbyInterface->RegisterForMatchmakingStartGameCallback([]() + { + buttonWiden->winEnable(FALSE); + + ////TheNGMPGame->enterGame(); + //TheNGMPGame->setSeed(12356); + + // TODO_QUICKMATCH + //TheGameSpyGame->markGameAsQM(); + + // TODO_QUICKMATCH + //const LadderInfo* info = getLadderInfo(); + + Int i; + Int numPlayers = 0; + for (i = 0; i < MAX_SLOTS; ++i) + { + //TheNGMPGame->getSlot(i); + // TODO_QUICKMATCH + //if (!resp.stagingRoomPlayerNames[i].empty()) + // ++numPlayers; + } + + // TODO_QUICKMATCH + // TODO_QUICKMATCH + //std::list maps = TheGameSpyConfig->getQMMaps(); + std::list maps; + maps.push_back(AsciiString("Maps\\Homeland Alliance\\Homeland Alliance.map")); + + for (std::list::const_iterator it = maps.begin(); it != maps.end(); ++it) + { + AsciiString theMap = *it; + theMap.toLower(); + const MapMetaData* md = TheMapCache->findMap(theMap); + if (md && md->m_numPlayers >= numPlayers) + { + TheNGMPGame->setMap(*it); + + // TODO_QUICKMATCH + //if (resp.qmStatus.mapIdx-- == 0) + // break; + } + } + + // TODO_QUICKMATCH: Create and join a lobby instead + // create our mesh + //if (pLobbyInterface != nullptr) + { + //pLobbyInterface->CreateMesh(); + } + + + Int numPlayersPerTeam = numPlayers / 2; + DEBUG_ASSERTCRASH(numPlayersPerTeam, ("0 players per team???")); + if (!numPlayersPerTeam) + numPlayersPerTeam = 1; + + for (i = 0; i < MAX_SLOTS; ++i) + { + NGMPGameSlot* slot = (NGMPGameSlot*)TheNGMPGame->getSlot(i); + + ////slot->setMapAvailability(TRUE); + + // TODO_QUICKMATCH + //if (resp.stagingRoomPlayerNames[i].empty()) + if (false) + { + //slot->setState(SLOT_CLOSED); + } + else if (slot->getState() == SLOT_PLAYER) + { + // TODO_QUICKMATCH + //AsciiString aName = resp.stagingRoomPlayerNames[i].c_str(); + //AsciiString aName; + //aName.format("QM User %d", i); + //UnicodeString uName; + //uName.translate(aName); + //slot->setState(SLOT_PLAYER, uName, 0); + + // TODO_QUICKMATCH + slot->setColor(i); + + // TODO_QUICKMATCH + slot->setStartPos(i); + slot->setPlayerTemplate(5+i); + //slot->setProfileID(0); + slot->setNATBehavior((FirewallHelperClass::FirewallBehaviorType)0); + //slot->setLocale(""); + slot->setTeamNumber(i / numPlayersPerTeam); + + slot->setMapAvailability(true); + + // TODO_QUICKMATCH + if (i == 0) + TheNGMPGame->setGameName(UnicodeString(L"Quickmatch")); + } + } + + //DEBUG_LOG(("Starting a QM game: options=[%s]", GameInfoToAsciiString(TheGameSpyGame).str())); + //SendStatsToOtherPlayers(TheNGMPGame); + TheNGMPGame->startGame(0); + GameWindow* buttonBuddies = TheWindowManager->winGetWindowFromId(NULL, buttonBuddiesID); + if (buttonBuddies) + buttonBuddies->winEnable(FALSE); + GameSpyCloseOverlay(GSOVERLAY_BUDDY); + }); + + pLobbyInterface->RegisterForJoinLobbyCallback([](EJoinLobbyResult result) + { + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + + if (!pLobbyInterface->IsInLobby()) + { + return; + } + + if (TheNGMPGame == nullptr) + { + TheNGMPGame = new NGMPGame(); + } + pLobbyInterface->UpdateRoomDataCache([]() + { + + }); + + // connection events (for debug really) + NetworkMesh* pMesh = NGMP_OnlineServicesManager::GetNetworkMesh(); + if (pMesh != nullptr) + { + pMesh->RegisterForConnectionEvents([](int64_t userID, std::wstring strDisplayName, PlayerConnection* connection) + { + std::string strState = "Unknown"; + + EConnectionState connState = connection->GetState(); + std::string strConnectionType = connection->GetConnectionType(); + + switch (connState) + { + case EConnectionState::NOT_CONNECTED: + strState = "Not Connected"; + break; + + case EConnectionState::CONNECTING_DIRECT: + strState = "Connecting"; + break; + case EConnectionState::FINDING_ROUTE: + strState = "Connecting (Finding Route)"; + break; + + case EConnectionState::CONNECTED_DIRECT: + strState = "Connected"; + break; + + case EConnectionState::CONNECTION_FAILED: + strState = "Connection Failed"; + break; + + case EConnectionState::CONNECTION_DISCONNECTED: + strState = "Disconnected (Was Connected Previously)"; + break; + + default: + strState = "Unknown"; + break; + } + + UnicodeString strConnectionMessage; + if (connState == EConnectionState::CONNECTING_DIRECT || connState == EConnectionState::FINDING_ROUTE) + { + strConnectionMessage.format(L"Connecting to %s", strDisplayName.c_str()); + + Int index = GadgetListBoxAddEntryText(quickmatchTextWindow, strConnectionMessage, GameMakeColor(255, 194, 15, 255), -1, -1); + GadgetListBoxSetItemData(quickmatchTextWindow, (void*)-1, index); + } + else if (connState == EConnectionState::CONNECTED_DIRECT) + { + strConnectionMessage.format(L"Connected to %s", strDisplayName.c_str()); + + Int index = GadgetListBoxAddEntryText(quickmatchTextWindow, strConnectionMessage, GameMakeColor(255, 194, 15, 255), -1, -1); + GadgetListBoxSetItemData(quickmatchTextWindow, (void*)-1, index); + } + else + { + if (connState == EConnectionState::CONNECTION_FAILED || connState == EConnectionState::CONNECTION_DISCONNECTED) + { + strConnectionMessage.format(L"Connection failed to %s", strDisplayName.c_str()); + Int index = GadgetListBoxAddEntryText(quickmatchTextWindow, strConnectionMessage, GameMakeColor(255, 194, 15, 255), -1, -1); + GadgetListBoxSetItemData(quickmatchTextWindow, (void*)-1, index); + } + } + }); + } + + }); + } isInInit = TRUE; if (TheGameSpyGame && TheGameSpyGame->isGameInProgress()) { @@ -972,7 +1196,9 @@ static void shutdownComplete( WindowLayout *layout ) //------------------------------------------------------------------------------------------------- void WOLQuickMatchMenuShutdown( WindowLayout *layout, void *userData ) { +#if !defined(GENERALS_ONLINE) TheGameSpyInfo->unregisterTextWindow(quickmatchTextWindow); +#endif if (!TheGameEngine->getQuitting()) saveQuickMatchOptions(); @@ -1068,7 +1294,7 @@ void WOLQuickMatchMenuUpdate( WindowLayout * layout, void *userData) RaiseGSMessageBox(); raiseMessageBoxes = false; } - + /// @todo: MDC handle disconnects in-game the same way as Custom Match! if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue) @@ -1734,8 +1960,6 @@ WindowMsgHandledType WOLQuickMatchMenuSystem( GameWindow *window, UnsignedInt ms // TODO_QUICKMATCH: Chat has a sound effect in TheGameSpyInfo, re-eanble it if (bSuccess) { - Int index = GadgetListBoxAddEntryText(quickmatchTextWindow, UnicodeString(L"Started matchmaking... searching for players"), GameSpyColor[GSCOLOR_DEFAULT], -1, -1); - GadgetListBoxSetItemData(quickmatchTextWindow, (void*)-1, index); // buttons buttonWiden->winEnable(FALSE); @@ -1938,8 +2162,10 @@ WindowMsgHandledType WOLQuickMatchMenuSystem( GameWindow *window, UnsignedInt ms } else if ( controlID == buttonBackID ) { - buttonPushed = true; +#if !defined(GENERALS_ONLINE) TheGameSpyInfo->leaveGroupRoom(); +#endif + buttonPushed = true; nextScreen = "Menus/WOLWelcomeMenu.wnd"; TheShell->pop(); } //if ( controlID == buttonBack ) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index 5cfc1e2f2ef..5bc52ea2c8c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -2097,7 +2097,7 @@ void GameLogic::startNewGame( Bool loadingSaveGame ) // update the loadscreen updateLoadProgress(LOAD_PROGRESS_POST_PRELOAD_ASSETS); - TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f); + TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f, false); TheTacticalView->setAngleAndPitchToDefault(); TheTacticalView->setZoomToDefault(); @@ -2682,7 +2682,7 @@ void GameLogic::processCommandList( CommandList *list ) #if defined(GENERALS_ONLINE) // provide more details UnicodeString strMismatchDetails; - strMismatchDetails.format(L"GameLogic frame %d, latest frame %d, GetGameLogicRandomSeedCRC was %d\nHad %d CRCs from %d players\nNum RNG Calls %llu\nAll Player CRCs:\n", + strMismatchDetails.format(L"GameLogic frame %d, latest frame %d, GetGameLogicRandomSeedCRC was %d\nHad %d CRCs from %d players\nNum RNG Calls %llu\nMismatched Players:\n", TheGameLogic->getFrame(), TheGameLogic->getFrame() - TheNetwork->getRunAhead() - 1, GetGameLogicRandomSeedCRC(), @@ -2721,12 +2721,15 @@ void GameLogic::processCommandList( CommandList *list ) // show all players for (std::map::const_iterator crcIt = m_cachedCRCs.begin(); crcIt != m_cachedCRCs.end(); ++crcIt) { - Player* player = ThePlayerList->getNthPlayer(crcIt->first); - UnicodeString strPlayerInfo; - strPlayerInfo.format(L"player %d (%s) = %X [%s]\n", crcIt->first, player ? player->getPlayerDisplayName().str() : L"", crcIt->second, - crcIt->second == biggestCRC ? L"OK" : L"MISMATCH"); + // only show users who arent OK, UI isn't huge + if (crcIt->second != biggestCRC) + { + Player* player = ThePlayerList->getNthPlayer(crcIt->first); + UnicodeString strPlayerInfo; + strPlayerInfo.format(L"player %d (%s) = %X [MISMATCH]\n", crcIt->first, player ? player->getPlayerDisplayName().str() : L"", crcIt->second); - strMismatchDetails.concat(strPlayerInfo); + strMismatchDetails.concat(strPlayerInfo); + } } // TODO_NGMP: Handle missing CRCs, although that doesnt seem common diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp index 2f587a22a6d..1344fa9872c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GameSpy/LobbyUtils.cpp @@ -212,11 +212,6 @@ static void gameTooltip(GameWindow* window, WinInstanceData* instData, UnsignedInt mouse) { - // TODO_NGMP -#if defined(GENERALS_ONLINE) - return; -#endif - Int x, y, row, col; x = LOLONGTOSHORT(mouse); y = HILONGTOSHORT(mouse); @@ -230,12 +225,26 @@ static void gameTooltip(GameWindow* window, } Int gameID = (Int)GadgetListBoxGetItemData(window, row, 0); +#if defined(GENERALS_ONLINE) + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pLobbyInterface == nullptr) + { + return; + } + + LobbyEntry lobbyEntry = pLobbyInterface->GetLobbyFromID(gameID); + if (lobbyEntry.lobbyID == -1) + { + return; + } +#else GameSpyStagingRoom *room = TheGameSpyInfo->findStagingRoomByID(gameID); if (!room) { TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:UnknownGame") ); return; } +#endif if (col == COLUMN_PING) { @@ -258,7 +267,11 @@ static void gameTooltip(GameWindow* window, } if (col == COLUMN_PASSWORD) { +#if defined(GENERALS_ONLINE) + if (lobbyEntry.passworded) +#else if (room->getHasPassword()) +#endif { UnicodeString checkTooltip =TheGameText->fetch("TOOTIP:Password"); if(!checkTooltip.compare(L"Password required to joing game")) @@ -271,7 +284,11 @@ static void gameTooltip(GameWindow* window, } if (col == COLUMN_USE_STATS) { - if ( room->getUseStats() ) +#if defined(GENERALS_ONLINE) + if (lobbyEntry.track_stats) +#else + if (room->getUseStats()) +#endif { TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:UseStatsOn") ); } @@ -285,6 +302,11 @@ static void gameTooltip(GameWindow* window, UnicodeString tooltip; UnicodeString mapName; + +#if defined(GENERALS_ONLINE) + // GO already has the full map info, don't need the cache + mapName.translate(lobbyEntry.map_name.c_str()); +#else const MapMetaData *md = TheMapCache->findMap(room->getMap()); if (md) { @@ -303,9 +325,23 @@ static void gameTooltip(GameWindow* window, } mapName.translate( start ); } +#endif UnicodeString tmp; + +#if defined(GENERALS_ONLINE) + UnicodeString gameName; + gameName.format(L"%s", from_utf8(lobbyEntry.name).c_str()); + tooltip.format(TheGameText->fetch("TOOLTIP:GameInfoGameName"), gameName.str()); +#else tooltip.format(TheGameText->fetch("TOOLTIP:GameInfoGameName"), room->getGameName().str()); +#endif + +#if defined(GENERALS_ONLINE) + // TODO_QUICKMATCH + if (false) +#else if (room->getLadderPort() != 0) + { const LadderInfo *linfo = TheLadderList->findLadder(room->getLadderIP(), room->getLadderPort()); if (linfo) @@ -314,7 +350,12 @@ static void gameTooltip(GameWindow* window, tooltip.concat(tmp); } } +#endif +#if defined(GENERALS_ONLINE) + if (lobbyEntry.exe_crc != TheGlobalData->m_exeCRC || lobbyEntry.ini_crc != TheGlobalData->m_iniCRC) +#else if (room->getExeCRC() != TheGlobalData->m_exeCRC || room->getIniCRC() != TheGlobalData->m_iniCRC) +#endif { tmp.format(TheGameText->fetch("TOOLTIP:InvalidGameVersion"), mapName.str()); tooltip.concat(tmp); @@ -322,6 +363,39 @@ static void gameTooltip(GameWindow* window, tmp.format(TheGameText->fetch("TOOLTIP:GameInfoMap"), mapName.str()); tooltip.concat(tmp); +#if defined(GENERALS_ONLINE) + for (LobbyMemberEntry& member : lobbyEntry.members) + { + if (member.IsHuman()) + { + UnicodeString plrName; + plrName.format(L"%s", from_utf8(member.display_name).c_str()); + + // TODO_NGMP: We don't have stats info + //tmp.format(TheGameText->fetch("TOOLTIP:GameInfoPlayer"), plrName.str(), slot->getWins(), slot->getLosses()); + tooltip.concat(L'\n'); + tooltip.concat(plrName); + } + else + { + switch (member.m_SlotState) + { + case SLOT_EASY_AI: + tooltip.concat(L'\n'); + tooltip.concat(TheGameText->fetch("GUI:EasyAI")); + break; + case SLOT_MED_AI: + tooltip.concat(L'\n'); + tooltip.concat(TheGameText->fetch("GUI:MediumAI")); + break; + case SLOT_BRUTAL_AI: + tooltip.concat(L'\n'); + tooltip.concat(TheGameText->fetch("GUI:HardAI")); + break; + } + } + } +#else AsciiString aPlayer; UnicodeString player; Int numPlayers = 0; @@ -359,6 +433,7 @@ static void gameTooltip(GameWindow* window, } } DEBUG_ASSERTCRASH(numPlayers, ("Tooltipping a 0-player game!")); +#endif TheMouse->setCursorTooltip( tooltip, 10, NULL, 2.0f ); // the text and width are the only params used. the others are the default values. } @@ -570,7 +645,7 @@ static Int insertGame(GameWindow* win, LobbyEntry& lobbyInfo, Bool showMap) } UnicodeString gameName; - gameName.format(L"%s (%s)", UnicodeString(from_utf8(lobbyInfo.name).c_str()), strOwnerName.c_str()); + gameName.format(L"%s (%s)", from_utf8(lobbyInfo.name).c_str(), strOwnerName.c_str()); int numPlayers = lobbyInfo.current_players; int maxPlayers = lobbyInfo.max_players; @@ -578,7 +653,7 @@ static Int insertGame(GameWindow* win, LobbyEntry& lobbyInfo, Bool showMap) AsciiString lobbyMapName = AsciiString(lobbyInfo.map_name.c_str()); AsciiString ladder = AsciiString("TODO_NGMP"); USHORT ladderPort = 1; - int gameID = 0; + int gameID = lobbyInfo.lobbyID; // TODO_NGMP: Downcast. We should use int64 everywhere, although its unlikely we actually need int64 for lobby since its reset regularly. bool bHasPassword = lobbyInfo.passworded; @@ -932,6 +1007,7 @@ void RefreshGameListBox( GameWindow *win, Bool showMap ) { win->winEnable(false); GadgetListBoxAddEntryText(win, UnicodeString(L"No lobbies were found"), GameMakeColor(255, 194, 15, 255), -1, -1); + } else { diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_Init.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_Init.cpp index 97a575f1881..3f3bd8ecfc1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_Init.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_Init.cpp @@ -365,6 +365,7 @@ void NGMP_OnlineServicesManager::Init() m_pLobbyInterface = new NGMP_OnlineServices_LobbyInterface(); m_pRoomInterface = new NGMP_OnlineServices_RoomsInterface(); m_pStatsInterface = new NGMP_OnlineServices_StatsInterface(); + m_pMatchmakingInterface = new NGMP_OnlineServices_MatchmakingInterface(); m_pHTTPManager = new HTTPManager(); m_pHTTPManager->Initialize(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.cpp index c9d787b074e..95216c1dbd4 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_LobbyInterface.cpp @@ -1024,6 +1024,21 @@ void NGMP_OnlineServices_LobbyInterface::LeaveCurrentLobby() ResetCachedRoomData(); } + +LobbyEntry NGMP_OnlineServices_LobbyInterface::GetLobbyFromID(int64_t lobbyID) +{ + // TODO_NGMP: Optimize for lookup + for (LobbyEntry& lobbyEntry : m_vecLobbies) + { + if (lobbyEntry.lobbyID == lobbyID) + { + return lobbyEntry; + } + } + + return LobbyEntry(); +} + LobbyEntry NGMP_OnlineServices_LobbyInterface::GetLobbyFromIndex(int index) { // TODO_NGMP: safety diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_RoomsInterface.cpp b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_RoomsInterface.cpp index ae18ae999dd..17ff4a84df4 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_RoomsInterface.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/OnlineServices_RoomsInterface.cpp @@ -22,7 +22,7 @@ int WebSocket::Ping() { size_t sent; CURLcode result = curl_ws_send(m_pCurl, "wsping", strlen("wsping"), &sent, 0, - CURLWS_PING); + CURLWS_PING); nlohmann::json j; j["msg_id"] = EWebSocketMessageID::PING; @@ -109,17 +109,6 @@ void WebSocket::SendData_RoomChatMessage(UnicodeString& msg, bool bIsAction) Send(strBody.c_str()); } -void WebSocket::SendData_ConnectionRelayUpgrade(int64_t userID) -{ - nlohmann::json j; - j["msg_id"] = EWebSocketMessageID::PLAYER_CONNECTION_RELAY_UPGRADE; - j["target_user_id"] = userID; - - std::string strBody = j.dump(); - - Send(strBody.c_str()); -} - void WebSocket::SendData_MarkReady(bool bReady) { nlohmann::json j; @@ -173,7 +162,7 @@ void WebSocket::Send(const char* send_payload) size_t sent; CURLcode result = curl_ws_send(m_pCurl, send_payload, strlen(send_payload), &sent, 0, - CURLWS_BINARY); + CURLWS_BINARY); if (result != CURLE_OK) { @@ -208,6 +197,14 @@ class WebSocketMessage_NetworkDisconnectPlayer : public WebSocketMessageBase NLOHMANN_DEFINE_TYPE_INTRUSIVE(WebSocketMessage_NetworkDisconnectPlayer, msg_id, lobby_id, user_id) }; +class WebSocketMessage_MatchmakingAction_JoinPrearrangedLobby : public WebSocketMessageBase +{ +public: + int64_t lobby_id; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(WebSocketMessage_MatchmakingAction_JoinPrearrangedLobby, msg_id, lobby_id) +}; + class WebSocketMessage_RoomChatIncoming : public WebSocketMessageBase { @@ -239,12 +236,12 @@ class WebSocketMessage_LobbyChatIncoming : public WebSocketMessageBase NLOHMANN_DEFINE_TYPE_INTRUSIVE(WebSocketMessage_LobbyChatIncoming, msg_id, message, action, announcement, show_announcement_to_host, user_id) }; -class WebSocketMessage_RelayUpgrade : public WebSocketMessageBase +class WebSocketMessage_MatchmakingMessage : public WebSocketMessageBase { public: - int64_t target_user_id = -1; + std::string message; - NLOHMANN_DEFINE_TYPE_INTRUSIVE(WebSocketMessage_RelayUpgrade, msg_id, target_user_id) + NLOHMANN_DEFINE_TYPE_INTRUSIVE(WebSocketMessage_MatchmakingMessage, msg_id, message) }; class WebSocketMessage_NetworkRoomMemberListUpdate : public WebSocketMessageBase @@ -256,6 +253,52 @@ class WebSocketMessage_NetworkRoomMemberListUpdate : public WebSocketMessageBase NLOHMANN_DEFINE_TYPE_INTRUSIVE(WebSocketMessage_NetworkRoomMemberListUpdate, names, ids) }; +static bool JSONDeserialize(const char* szBuffer, nlohmann::json* jsonObject) +{ + try + { + *jsonObject = nlohmann::json::parse(szBuffer); + return true; + } + catch (nlohmann::json::exception& jsonException) + { + NetworkLog(ELogVerbosity::LOG_RELEASE, "JSONDeserialize: Unparsable JSON: %s (%s)", szBuffer, jsonException.what()); + return false; + } + catch (...) + { + NetworkLog(ELogVerbosity::LOG_RELEASE, "JSONDeserialize: Unparsable JSON: %s", szBuffer); + return false; + } + + return false; +} + +template +static bool JSONGetAsObject(nlohmann::json& jsonObject, T* outMsg) +{ + try + { + *outMsg = jsonObject.get(); + + return true; + } + catch (nlohmann::json::exception& jsonException) + { + std::string targetTypeName = typeid(T).name(); + NetworkLog(ELogVerbosity::LOG_RELEASE, "JSONGetAsObject: Unparsable JSON: Target Type is %s (%s)", targetTypeName.c_str(), jsonException.what()); + return false; + } + catch (...) + { + std::string targetTypeName = typeid(T).name(); + NetworkLog(ELogVerbosity::LOG_RELEASE, "JSONGetAsObject: Unparsable JSON: Target Type is %s", targetTypeName.c_str()); + return false; + } + + return false; +} + //static std::string strSignal = "str:1 "; void WebSocket::Tick() { @@ -300,9 +343,8 @@ void WebSocket::Tick() char bufferThisRecv[8196 * 4] = { 0 }; CURLcode ret = CURL_LAST; - ret = curl_ws_recv(m_pCurl, bufferThisRecv, sizeof(bufferThisRecv) - 1, &rlen, &meta); - bufferThisRecv[rlen] = 0; // Ensure null-termination - + ret = curl_ws_recv(m_pCurl, bufferThisRecv, sizeof(bufferThisRecv), &rlen, &meta); + if (ret != CURLE_RECV_ERROR && ret != CURL_LAST && ret != CURLE_AGAIN && ret != CURLE_GOT_NOTHING) { NetworkLog(ELogVerbosity::LOG_DEBUG, "Got websocket msg: %s", bufferThisRecv); @@ -318,8 +360,6 @@ void WebSocket::Tick() } else if (meta->flags & CURLWS_TEXT) { - NetworkLog(ELogVerbosity::LOG_DEBUG, "websocket recv buffer is: %s", bufferThisRecv); - bool bMessageComplete = false; m_vecWSPartialBuffer.resize(m_vecWSPartialBuffer.size() + rlen); @@ -346,210 +386,291 @@ void WebSocket::Tick() { try { + // null terminate buffer + m_vecWSPartialBuffer.push_back('\0'); + // process it - nlohmann::json jsonObject = nlohmann::json::parse(m_vecWSPartialBuffer); + nlohmann::json jsonObject; + bool bDeserializedOK = JSONDeserialize(m_vecWSPartialBuffer.data(), &jsonObject); // clear buffer and resize m_vecWSPartialBuffer.clear(); m_vecWSPartialBuffer.resize(0); - - if (jsonObject.contains("msg_id")) + if (bDeserializedOK) { - WebSocketMessageBase msgDetails = jsonObject.get(); - EWebSocketMessageID msgID = msgDetails.msg_id; - - switch (msgID) - { - - case EWebSocketMessageID::PONG: - { - int64_t currTime = std::chrono::duration_cast(std::chrono::utc_clock::now().time_since_epoch()).count(); - m_lastPong = currTime; - } - break; - - case EWebSocketMessageID::NETWORK_ROOM_CHAT_FROM_SERVER: + if (jsonObject.contains("msg_id")) { - WebSocketMessage_RoomChatIncoming chatData = jsonObject.get(); + WebSocketMessageBase msgDetails; + bool bParsedBase = JSONGetAsObject(jsonObject, &msgDetails); - UnicodeString unicodeStr(from_utf8(chatData.message).c_str()); + if (bParsedBase) + { + EWebSocketMessageID msgID = msgDetails.msg_id; - Color color = DetermineColorForChatMessage(EChatMessageType::CHAT_MESSAGE_TYPE_NETWORK_ROOM, true, chatData.action); + switch (msgID) + { - NGMP_OnlineServices_RoomsInterface* pRoomsInterface = NGMP_OnlineServicesManager::GetInterface(); - if (pRoomsInterface != nullptr && pRoomsInterface->m_OnChatCallback != nullptr) - { - pRoomsInterface->m_OnChatCallback(unicodeStr, color); - } - } - break; + case EWebSocketMessageID::PONG: + { + int64_t currTime = std::chrono::duration_cast(std::chrono::utc_clock::now().time_since_epoch()).count(); + m_lastPong = currTime; + } + break; - case EWebSocketMessageID::START_GAME: - { - NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); - if (pLobbyInterface != nullptr && pLobbyInterface->m_callbackStartGamePacket != nullptr) - { - pLobbyInterface->m_callbackStartGamePacket(); - } - } - break; + case EWebSocketMessageID::NETWORK_ROOM_CHAT_FROM_SERVER: + { + WebSocketMessage_RoomChatIncoming chatData; + bool bParsed = JSONGetAsObject(jsonObject, &chatData); + if (bParsed) + { + UnicodeString unicodeStr(from_utf8(chatData.message).c_str()); - case EWebSocketMessageID::NETWORK_CONNECTION_START_SIGNALLING: - { - WebSocketMessage_NetworkStartSignalling startSignallingData = jsonObject.get(); + Color color = DetermineColorForChatMessage(EChatMessageType::CHAT_MESSAGE_TYPE_NETWORK_ROOM, true, chatData.action); - NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); - if (pLobbyInterface != nullptr) - { - NetworkMesh* pMesh = pLobbyInterface->GetNetworkMeshForLobby(); + NGMP_OnlineServices_RoomsInterface* pRoomsInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pRoomsInterface != nullptr && pRoomsInterface->m_OnChatCallback != nullptr) + { + pRoomsInterface->m_OnChatCallback(unicodeStr, color); + } + } + } + break; - if (pMesh != nullptr) + case EWebSocketMessageID::START_GAME: { - pMesh->StartConnectionSignalling(startSignallingData.user_id, startSignallingData.preferred_port); + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pLobbyInterface != nullptr && pLobbyInterface->m_callbackStartGamePacket != nullptr) + { + pLobbyInterface->m_callbackStartGamePacket(); + } } - else + break; + + + case EWebSocketMessageID::NETWORK_CONNECTION_START_SIGNALLING: { - NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_START_SIGNALLING] Network mesh is null"); - break; + WebSocketMessage_NetworkStartSignalling startSignallingData; + bool bParsed = JSONGetAsObject(jsonObject, &startSignallingData); + + if (bParsed) + { + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pLobbyInterface != nullptr) + { + NetworkMesh* pMesh = pLobbyInterface->GetNetworkMeshForLobby(); + + if (pMesh != nullptr) + { + pMesh->StartConnectionSignalling(startSignallingData.user_id, startSignallingData.preferred_port); + } + else + { + NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_START_SIGNALLING] Network mesh is null"); + break; + } + } + else + { + NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_START_SIGNALLING] Lobby interface is null"); + break; + } + } } - } - else - { - NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_START_SIGNALLING] Lobby interface is null"); break; - } - } - break; - case EWebSocketMessageID::NETWORK_CONNECTION_DISCONNECT_PLAYER: - { - WebSocketMessage_NetworkDisconnectPlayer disconnectPlayerData = jsonObject.get(); + case EWebSocketMessageID::NETWORK_CONNECTION_DISCONNECT_PLAYER: + { + WebSocketMessage_NetworkDisconnectPlayer disconnectPlayerData; + bool bParsed = JSONGetAsObject(jsonObject, &disconnectPlayerData); - NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); - if (pLobbyInterface != nullptr) - { - int64_t currentLobbyID = pLobbyInterface->GetCurrentLobby().lobbyID; + if (bParsed) + { + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pLobbyInterface != nullptr) + { + int64_t currentLobbyID = pLobbyInterface->GetCurrentLobby().lobbyID; + + if (currentLobbyID == -1 || currentLobbyID != disconnectPlayerData.lobby_id) + { + NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_DISCONNECT_PLAYER] Lobby ID mismatch! Expected %lld, got %lld", currentLobbyID, disconnectPlayerData.lobby_id); + break; + } + + NetworkMesh* pMesh = pLobbyInterface->GetNetworkMeshForLobby(); + + if (pMesh != nullptr) + { + pMesh->DisconnectUser(disconnectPlayerData.user_id); + } + else + { + NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_DISCONNECT_PLAYER] Network mesh is null"); + break; + } + } + else + { + NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_DISCONNECT_PLAYER] Lobby interface is null"); + break; + } + } + } + break; - if (currentLobbyID == -1 || currentLobbyID != disconnectPlayerData.lobby_id) + case EWebSocketMessageID::NETWORK_SIGNAL: { - NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_DISCONNECT_PLAYER] Lobby ID mismatch! Expected %lld, got %lld", currentLobbyID, disconnectPlayerData.lobby_id); - break; - } + NetworkLog(ELogVerbosity::LOG_RELEASE, "[SIGNAL] GOT SIGNAL!"); - NetworkMesh* pMesh = pLobbyInterface->GetNetworkMeshForLobby(); + WebSocketMessage_NetworkSignal signalData; + bool bParsed = JSONGetAsObject(jsonObject, &signalData); - if (pMesh != nullptr) - { - pMesh->DisconnectUser(disconnectPlayerData.user_id); + if (bParsed) + { + NetworkLog(ELogVerbosity::LOG_RELEASE, "[SIGNAL] Signal User: %lld!", signalData.target_user_id); + NetworkLog(ELogVerbosity::LOG_RELEASE, "[SIGNAL] Signal Payload Size: %d!", (int)signalData.payload.size()); + m_pendingSignals.push(signalData.payload); + } } - else + break; + + case EWebSocketMessageID::LOBBY_CHAT_FROM_SERVER: { - NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_DISCONNECT_PLAYER] Network mesh is null"); - break; + WebSocketMessage_LobbyChatIncoming chatData; + bool bParsed = JSONGetAsObject(jsonObject, &chatData); + + if (bParsed) + { + UnicodeString unicodeStr(from_utf8(chatData.message).c_str()); + + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pLobbyInterface != nullptr) + { + int lobbySlot = -1; + auto lobbyMembers = pLobbyInterface->GetMembersListForCurrentRoom(); + for (const auto& lobbyMember : lobbyMembers) + { + if (lobbyMember.user_id == chatData.user_id) + { + lobbySlot = lobbyMember.m_SlotIndex; + break; + } + } + + Color color = DetermineColorForChatMessage(EChatMessageType::CHAT_MESSAGE_TYPE_LOBBY, true, chatData.action, lobbySlot); + + if (pLobbyInterface->m_OnChatCallback != nullptr) + { + pLobbyInterface->m_OnChatCallback(unicodeStr, color); + } + } + } } - } - else - { - NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_DISCONNECT_PLAYER] Lobby interface is null"); break; - } - } - break; - - case EWebSocketMessageID::NETWORK_SIGNAL: - { - NetworkLog(ELogVerbosity::LOG_RELEASE, "[SIGNAL] GOT SIGNAL!"); - WebSocketMessage_NetworkSignal signalData = jsonObject.get(); - NetworkLog(ELogVerbosity::LOG_RELEASE, "[SIGNAL] Signal User: %lld!", signalData.target_user_id); - NetworkLog(ELogVerbosity::LOG_RELEASE, "[SIGNAL] Signal Payload Size: %d!", (int)signalData.payload.size()); - m_pendingSignals.push(signalData.payload); - } - break; + case EWebSocketMessageID::NETWORK_ROOM_MEMBER_LIST_UPDATE: + { + WebSocketMessage_NetworkRoomMemberListUpdate memberList; + bool bParsed = JSONGetAsObject(jsonObject, &memberList); - case EWebSocketMessageID::LOBBY_CHAT_FROM_SERVER: - { - WebSocketMessage_LobbyChatIncoming chatData = jsonObject.get(); + if (bParsed) + { + NGMP_OnlineServices_RoomsInterface* pRoomsInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pRoomsInterface != nullptr) + { + pRoomsInterface->OnRosterUpdated(memberList.names, memberList.ids); + } + } + } + break; - UnicodeString unicodeStr(from_utf8(chatData.message).c_str()); + case EWebSocketMessageID::LOBBY_CURRENT_LOBBY_UPDATE: + { + // re-get the room info as it is stale + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pLobbyInterface != nullptr) + { + pLobbyInterface->UpdateRoomDataCache(nullptr); + } + } + break; - NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); - if (pLobbyInterface != nullptr) - { - int lobbySlot = -1; - auto lobbyMembers = pLobbyInterface->GetMembersListForCurrentRoom(); - for (const auto& lobbyMember : lobbyMembers) + case EWebSocketMessageID::NETWORK_ROOM_LOBBY_LIST_UPDATE: { - if (lobbyMember.user_id == chatData.user_id) + // re-get the room info as it is stale + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pLobbyInterface != nullptr) { - lobbySlot = lobbyMember.m_SlotIndex; - break; + pLobbyInterface->SetLobbyListDirty(); } } + break; + + case EWebSocketMessageID::MATCHMAKING_ACTION_JOIN_PREARRANGED_LOBBY: + { + WebSocketMessage_MatchmakingAction_JoinPrearrangedLobby mmEvent; + bool bParsed = JSONGetAsObject(jsonObject, &mmEvent); - Color color = DetermineColorForChatMessage(EChatMessageType::CHAT_MESSAGE_TYPE_LOBBY, true, chatData.action, lobbySlot); + if (bParsed) + { + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pLobbyInterface != nullptr) + { + // TODO_QUICKMATCH: Only if really in quickmatch + + // basic info needed to join + LobbyEntry lobbyEntry; + lobbyEntry.lobbyID = mmEvent.lobby_id; + lobbyEntry.map_path = "Maps\\Homeland Alliance\\Homeland Alliance.map"; + + pLobbyInterface->JoinLobby(lobbyEntry, std::string()); + } + else + { + NetworkLog(ELogVerbosity::LOG_RELEASE, "[NETWORK_CONNECTION_DISCONNECT_PLAYER] Lobby interface is null"); + break; + } + } + } + break; - if (pLobbyInterface->m_OnChatCallback != nullptr) + case EWebSocketMessageID::MATCHMAKING_ACTION_START_GAME: { - pLobbyInterface->m_OnChatCallback(unicodeStr, color); + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pLobbyInterface != nullptr) + { + pLobbyInterface->InvokeMatchmakingStartGameCallback(); + } } - } - } - break; + break; - // TODO_STEAM: remove relay upgrade path from everything - case EWebSocketMessageID::PLAYER_CONNECTION_RELAY_UPGRADE: - { - WebSocketMessage_RelayUpgrade relayUpgrade = jsonObject.get(); - NetworkLog(ELogVerbosity::LOG_RELEASE, "Got relay upgrade for user %lld", relayUpgrade.target_user_id); - NetworkMesh* pMesh = NGMP_OnlineServicesManager::GetNetworkMesh(); - if (pMesh != nullptr) - { - // TODO_STEAM - //pMesh->OnRelayUpgrade(relayUpgrade.target_user_id); - } - } - break; + case EWebSocketMessageID::MATCHMAKING_MESSAGE: + { + WebSocketMessage_MatchmakingMessage matchmakingMsg; + bool bParsed = JSONGetAsObject(jsonObject, &matchmakingMsg); - case EWebSocketMessageID::NETWORK_ROOM_MEMBER_LIST_UPDATE: - { - WebSocketMessage_NetworkRoomMemberListUpdate memberList = jsonObject.get(); - NGMP_OnlineServices_RoomsInterface* pRoomsInterface = NGMP_OnlineServicesManager::GetInterface(); - if (pRoomsInterface != nullptr) - { - pRoomsInterface->OnRosterUpdated(memberList.names, memberList.ids); - } - } - break; + if (bParsed) + { + NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); + if (pLobbyInterface != nullptr) + { + pLobbyInterface->InvokeMatchmakingMessageCallback(matchmakingMsg.message); + } + } + } + break; - case EWebSocketMessageID::LOBBY_CURRENT_LOBBY_UPDATE: - { - // re-get the room info as it is stale - NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); - if (pLobbyInterface != nullptr) - { - pLobbyInterface->UpdateRoomDataCache(nullptr); + default: + NetworkLog(ELogVerbosity::LOG_RELEASE, "Unhandled WebSocketMessage: %d", (int)msgID); + break; + } } - } - break; - - case EWebSocketMessageID::NETWORK_ROOM_LOBBY_LIST_UPDATE: - { - // re-get the room info as it is stale - NGMP_OnlineServices_LobbyInterface* pLobbyInterface = NGMP_OnlineServicesManager::GetInterface(); - if (pLobbyInterface != nullptr) + else { - pLobbyInterface->SetLobbyListDirty(); + NetworkLog(ELogVerbosity::LOG_RELEASE, "Malformed WebSocketMessage: couldn't parse as WebSocketMessageBase"); } } - break; - - default: - NetworkLog(ELogVerbosity::LOG_RELEASE, "Unhandled WebSocketMessage: %d", (int)msgID); - break; - } } else { @@ -631,7 +752,7 @@ void WebSocket::Tick() NGMP_OnlineServices_RoomsInterface::NGMP_OnlineServices_RoomsInterface() { - + } void NGMP_OnlineServices_RoomsInterface::GetRoomList(std::function cb) @@ -653,7 +774,7 @@ void NGMP_OnlineServices_RoomsInterface::GetRoomList(std::function c std::string strName; ERoomFlags flags; - + roomEntryIter["id"].get_to(id); roomEntryIter["name"].get_to(strName); roomEntryIter["flags"].get_to(flags); @@ -706,7 +827,7 @@ void NGMP_OnlineServices_RoomsInterface::JoinRoom(int roomIndex, std::functionm_ranks[RANK_PRIVATE] = 0; + TheRankPointValues->m_ranks[RANK_CORPORAL] = getPointsForRank(RANK_CORPORAL); // 5 + TheRankPointValues->m_ranks[RANK_SERGEANT] = getPointsForRank(RANK_SERGEANT); // 10 + TheRankPointValues->m_ranks[RANK_LIEUTENANT] = getPointsForRank(RANK_LIEUTENANT); // 20 + TheRankPointValues->m_ranks[RANK_CAPTAIN] = getPointsForRank(RANK_CAPTAIN); // 50 + TheRankPointValues->m_ranks[RANK_MAJOR] = getPointsForRank(RANK_MAJOR); // 100 + TheRankPointValues->m_ranks[RANK_COLONEL] = getPointsForRank(RANK_COLONEL); // 200 + TheRankPointValues->m_ranks[RANK_BRIGADIER_GENERAL] = getPointsForRank(RANK_BRIGADIER_GENERAL); // 500 + TheRankPointValues->m_ranks[RANK_GENERAL] = getPointsForRank(RANK_GENERAL); // 1000 + TheRankPointValues->m_ranks[RANK_COMMANDER_IN_CHIEF] = getPointsForRank(RANK_COMMANDER_IN_CHIEF); // 2000 + // TODO_NGMP: Better location TheLadderList = NEW LadderList; } +NGMP_OnlineServices_StatsInterface::~NGMP_OnlineServices_StatsInterface() +{ + if (TheRankPointValues != nullptr) + { + delete TheRankPointValues; + TheRankPointValues = nullptr; + } + + if (TheLadderList != nullptr) + { + delete TheLadderList; + TheLadderList = nullptr; + } +} + void NGMP_OnlineServices_StatsInterface::GetGlobalStats(std::function cb) { std::string strURI = NGMP_OnlineServicesManager::GetAPIEndpoint("GlobalStats"); @@ -169,9 +197,14 @@ void NGMP_OnlineServices_StatsInterface::findPlayerStatsByID(int64_t userID, std // cb cb(true, stats); } + catch (nlohmann::json::exception& jsonException) + { + NetworkLog(ELogVerbosity::LOG_RELEASE, "Stats: Unparsable JSON 1: %s (%s)", strBody.c_str(), jsonException.what()); + cb(false, stats); + } catch (...) { - // cb + NetworkLog(ELogVerbosity::LOG_RELEASE, "Stats: Unparsable JSON 2: %s", strBody.c_str()); cb(false, stats); } }); diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/Vendor/ENet/enet.lib b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/Vendor/ENet/enet.lib deleted file mode 100644 index 3d133bb184e..00000000000 Binary files a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/Vendor/ENet/enet.lib and /dev/null differ diff --git a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/Vendor/ENet/enet64.lib b/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/Vendor/ENet/enet64.lib deleted file mode 100644 index 0c73c3d1bcf..00000000000 Binary files a/GeneralsMD/Code/GameEngine/Source/GameNetwork/GeneralsOnline/Vendor/ENet/enet64.lib and /dev/null differ