#pragma once #ifdef __linux__ #include "../../../Minecraft.Server/Linux/PosixNetLayer.h" #else #ifdef _WINDOWS64 #include #include #include #include "../../Common/Network/NetworkPlayerInterface.h" #pragma comment(lib, "Ws2_32.lib") #define WIN64_NET_DEFAULT_PORT 25565 #define WIN64_NET_RECV_BUFFER_SIZE 131072 #define WIN64_NET_MAX_PACKET_SIZE (3 * 1024 * 1024) #define WIN64_LAN_DISCOVERY_PORT 25566 #define WIN64_LAN_BROADCAST_MAGIC 0x4D434C4E #define WIN64_LAN_BROADCAST_PLAYERS 8 #define WIN64_NET_SEND_BUFFER_SIZE 262144 #define WIN64_NET_MAX_SEND_QUEUE (4 * 1024 * 1024) class Socket; #pragma pack(push, 1) struct Win64LANBroadcast { DWORD magic; WORD netVersion; WORD gamePort; wchar_t hostName[32]; BYTE playerCount; BYTE maxPlayers; DWORD gameHostSettings; DWORD texturePackParentId; BYTE subTexturePackId; BYTE isJoinable; BYTE isDedicatedServer; char playerNames[WIN64_LAN_BROADCAST_PLAYERS][XUSER_NAME_SIZE]; }; #pragma pack(pop) struct Win64LANSession { char hostIP[64]; int hostPort; wchar_t hostName[32]; unsigned short netVersion; unsigned char playerCount; unsigned char maxPlayers; unsigned int gameHostSettings; unsigned int texturePackParentId; unsigned char subTexturePackId; bool isJoinable; bool isDedicatedServer; DWORD lastSeenTick; char playerNames[WIN64_LAN_BROADCAST_PLAYERS][XUSER_NAME_SIZE]; }; struct Win64RemoteConnection { SOCKET tcpSocket; BYTE smallId; volatile bool active; CRITICAL_SECTION sendLock; BYTE *recvBuffer; int recvBufferUsed; int recvBufferSize; int currentPacketSize; bool readingHeader; BYTE *sendBuffer; int sendBufferUsed; int sendBufferSize; CRITICAL_SECTION sendBufLock; }; class WinsockNetLayer { public: static bool Initialize(); static void Shutdown(); static bool HostGame(int port); static bool JoinGame(const char *ip, int port); enum JoinResult { JOIN_IN_PROGRESS, JOIN_SUCCESS, JOIN_FAILED }; static bool BeginJoinGame(const char *ip, int port); static JoinResult PollJoinResult(); static void CancelJoinGame(); static bool SendToSmallId(BYTE targetSmallId, const void *data, int dataSize); static bool SendOnSocket(SOCKET sock, const void *data, int dataSize); static bool IsHosting() { return s_isHost; } static bool IsConnected() { return s_connected; } static bool IsActive() { return s_active; } static BYTE GetLocalSmallId() { return s_localSmallId; } static BYTE GetHostSmallId() { return s_hostSmallId; } static SOCKET GetSocketForSmallId(BYTE smallId); static std::string GetIPForSmallId(BYTE smallId); static void HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsigned char *data, unsigned int dataSize); static void FlushPendingData(); static void FlushSendBuffers(); static bool PopDisconnectedSmallId(BYTE *outSmallId); static void PushFreeSmallId(BYTE smallId); static void CloseConnectionBySmallId(BYTE smallId); static bool PopPendingJoinSmallId(BYTE *outSmallId); static bool IsSmallIdConnected(BYTE smallId); static bool StartAdvertising(int gamePort, const wchar_t *hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer); static void StopAdvertising(); static void UpdateAdvertisePlayerCount(BYTE count); static void UpdateAdvertiseJoinable(bool joinable); static void UpdateAdvertisePlayerNames(BYTE count, const char playerNames[][XUSER_NAME_SIZE]); static void UpdateAdvertiseGameHostSettings(unsigned int settings); static bool StartDiscovery(); static void StopDiscovery(); static std::vector GetDiscoveredSessions(); static int GetHostPort() { return s_hostGamePort; } private: static size_t GetConnectionSlotCount(); static DWORD WINAPI AcceptThreadProc(LPVOID param); static DWORD WINAPI IOThreadProc(LPVOID param); static DWORD WINAPI ClientRecvThreadProc(LPVOID param); static DWORD WINAPI AdvertiseThreadProc(LPVOID param); static DWORD WINAPI DiscoveryThreadProc(LPVOID param); static DWORD WINAPI AsyncJoinThreadProc(LPVOID param); static bool ProcessRecvData(Win64RemoteConnection &conn); static SOCKET s_listenSocket; static SOCKET s_hostConnectionSocket; static HANDLE s_acceptThread; static HANDLE s_ioThread; static HANDLE s_clientRecvThread; static bool s_isHost; static bool s_connected; static bool s_active; static bool s_initialized; static BYTE s_localSmallId; static BYTE s_hostSmallId; static BYTE s_nextSmallId; static CRITICAL_SECTION s_sendLock; static CRITICAL_SECTION s_connectionsLock; static std::vector s_connections; static SOCKET s_advertiseSock; static HANDLE s_advertiseThread; static volatile bool s_advertising; static Win64LANBroadcast s_advertiseData; static CRITICAL_SECTION s_advertiseLock; static int s_hostGamePort; static SOCKET s_discoverySock; static SOCKET s_discoveryLegacySock; static HANDLE s_discoveryThread; static volatile bool s_discovering; static CRITICAL_SECTION s_discoveryLock; static std::vector s_discoveredSessions; static CRITICAL_SECTION s_disconnectLock; static std::vector s_disconnectedSmallIds; static CRITICAL_SECTION s_pendingJoinLock; static std::vector s_pendingJoinSmallIds; static CRITICAL_SECTION s_freeSmallIdLock; static std::vector s_freeSmallIds; static CRITICAL_SECTION s_earlyDataLock; static std::vector > s_earlyDataBuffers; static HANDLE s_asyncJoinThread; static volatile JoinResult s_asyncJoinResult; static volatile bool s_asyncJoinActive; static char s_asyncJoinIP[256]; static int s_asyncJoinPort; }; extern bool g_Win64MultiplayerHost; extern bool g_Win64MultiplayerJoin; extern int g_Win64MultiplayerPort; extern char g_Win64MultiplayerIP[256]; #endif #endif