diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 418bf17aa..f2d4cf780 100755 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1601,7 +1601,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } } -void CServer::SendServerInfoConnless(const NETADDR *pAddr, int Token, bool Extended) +void CServer::SendServerInfoConnless(const NETADDR *pAddr, int Token, int Type) { const int MaxRequests = g_Config.m_SvServerInfoPerSecond; int64 Now = Tick(); @@ -1624,14 +1624,16 @@ void CServer::SendServerInfoConnless(const NETADDR *pAddr, int Token, bool Exten str_format(aBuf, sizeof(aBuf), "Too many info requests from %s: %d > %d (Now = %lld, mSIFR = %lld)", aAddrStr, m_ServerInfoNumRequests, MaxRequests, Now, m_ServerInfoFirstRequest); Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "inforequests", aBuf); - } else { - SendServerInfo(pAddr, Token, Extended, true); + return; } + + bool SendClients = m_ServerInfoNumRequests <= MaxRequests && !m_ServerInfoHighLoad; + SendServerInfo(pAddr, Token, Type, SendClients); } -void CServer::SendServerInfo(const NETADDR *pAddr, int Token, bool Extended, bool SendClients, int Offset) +void CServer::SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool SendClients) { - CNetChunk Packet; + // One chance to improve the protocol! CPacker p; char aBuf[256]; @@ -1653,9 +1655,19 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token, bool Extended, boo p.Reset(); - p.AddRaw(Extended?SERVERBROWSE_INFO64:SERVERBROWSE_INFO, sizeof(Extended?SERVERBROWSE_INFO64:SERVERBROWSE_INFO)); - str_format(aBuf, sizeof(aBuf), "%d", Token); - p.AddString(aBuf, 6); + #define ADD_RAW(p, x) (p).AddRaw(x, sizeof(x)) + #define ADD_INT(p, x) do { str_format(aBuf, sizeof(aBuf), "%d", x); (p).AddString(aBuf, 0); } while(0) + + switch(Type) + { + case SERVERINFO_EXTENDED: ADD_RAW(p, SERVERBROWSE_INFO_EXTENDED); break; + case SERVERINFO_64_LEGACY: ADD_RAW(p, SERVERBROWSE_INFO_64_LEGACY); break; + case SERVERINFO_VANILLA: ADD_RAW(p, SERVERBROWSE_INFO); break; + case SERVERINFO_INGAME: ADD_RAW(p, SERVERBROWSE_INFO); break; + default: dbg_assert(false, "unknown serverinfo type"); + } + + ADD_INT(p, Token); p.AddString(GameServer()->Version(), 32); @@ -1736,102 +1748,184 @@ void CServer::SendServerInfo(const NETADDR *pAddr, int Token, bool Extended, boo } } - if (Extended) + if(Type != SERVERINFO_VANILLA) { - p.AddString(aBuf, 256); + p.AddString(aBuf, 256); } else { - if (ClientCount < VANILLA_MAX_CLIENTS) + if(m_NetServer.MaxClients() <= VANILLA_MAX_CLIENTS) + { p.AddString(aBuf, 64); + } else { - char bBuf[64]; - str_format(bBuf, sizeof(bBuf), "%s - %d/%d online", aBuf, ClientCount, m_NetServer.MaxClients()); - p.AddString(bBuf, 64); + str_format(aBuf, sizeof(aBuf), "%s [%d/%d]", aBuf, ClientCount, m_NetServer.MaxClients()); + p.AddString(aBuf, 64); } } - p.AddString(pMapName, 32); + if(Type == SERVERINFO_EXTENDED) + { + ADD_INT(p, m_CurrentMapCrc); + ADD_INT(p, m_CurrentMapSize); + } + // gametype p.AddString(GameServer()->GameType(), 16); // flags - int i = 0; - if(g_Config.m_Password[0]) // password set - i |= SERVER_FLAG_PASSWORD; - str_format(aBuf, sizeof(aBuf), "%d", i); - p.AddString(aBuf, 2); + ADD_INT(p, g_Config.m_Password[0] ? SERVER_FLAG_PASSWORD : 0); int MaxClients = m_NetServer.MaxClients(); - if (!Extended) + if(Type == SERVERINFO_VANILLA || Type == SERVERINFO_INGAME) { - if (ClientCount >= VANILLA_MAX_CLIENTS) + if(ClientCount >= VANILLA_MAX_CLIENTS) { - if (ClientCount < MaxClients) + if(ClientCount < MaxClients) ClientCount = VANILLA_MAX_CLIENTS - 1; else ClientCount = VANILLA_MAX_CLIENTS; } - if (MaxClients > VANILLA_MAX_CLIENTS) MaxClients = VANILLA_MAX_CLIENTS; + if(MaxClients > VANILLA_MAX_CLIENTS) + MaxClients = VANILLA_MAX_CLIENTS; + if(PlayerCount > ClientCount) + PlayerCount = ClientCount; } - if (PlayerCount > ClientCount) - PlayerCount = ClientCount; + ADD_INT(p, PlayerCount); // num players + ADD_INT(p, MaxClients-g_Config.m_SvSpectatorSlots); // max players + ADD_INT(p, ClientCount); // num clients + ADD_INT(p, MaxClients); // max clients - str_format(aBuf, sizeof(aBuf), "%d", PlayerCount); p.AddString(aBuf, 3); // num players - str_format(aBuf, sizeof(aBuf), "%d", MaxClients-g_Config.m_SvSpectatorSlots); p.AddString(aBuf, 3); // max players - str_format(aBuf, sizeof(aBuf), "%d", ClientCount); p.AddString(aBuf, 3); // num clients - str_format(aBuf, sizeof(aBuf), "%d", MaxClients); p.AddString(aBuf, 3); // max clients + if(Type == SERVERINFO_EXTENDED) + p.AddString("", 0); // extra info, reserved - if (Extended) - p.AddInt(Offset); + const void *pPrefix = p.Data(); + int PrefixSize = p.Size(); - int ClientsPerPacket = Extended ? 24 : VANILLA_MAX_CLIENTS; - int Skip = Offset; - int Take = ClientsPerPacket; + CPacker pp; + CNetChunk Packet; + int PacketsSent = 0; + int PlayersSent = 0; + Packet.m_ClientID = -1; + Packet.m_Address = *pAddr; + Packet.m_Flags = NETSENDFLAG_CONNLESS; - if (SendClients) { - for(i = 0; i < MAX_CLIENTS; i++) + #define SEND(size) \ + do \ + { \ + Packet.m_pData = pp.Data(); \ + Packet.m_DataSize = size; \ + m_NetServer.Send(&Packet); \ + PacketsSent++; \ + } while(0) + + #define RESET() \ + do \ + { \ + pp.Reset(); \ + pp.AddRaw(pPrefix, PrefixSize); \ + } while(0) + + RESET(); + + if(Type == SERVERINFO_64_LEGACY) + pp.AddInt(PlayersSent); // offset + + if(!SendClients) + { + SEND(pp.Size()); + return; + } + + if(Type == SERVERINFO_EXTENDED) + { + pPrefix = SERVERBROWSE_INFO_EXTENDED_MORE; + PrefixSize = sizeof(SERVERBROWSE_INFO_EXTENDED_MORE); + } + + int Remaining; + switch(Type) + { + case SERVERINFO_EXTENDED: Remaining = -1; break; + case SERVERINFO_64_LEGACY: Remaining = 24; break; + case SERVERINFO_VANILLA: Remaining = VANILLA_MAX_CLIENTS; break; + case SERVERINFO_INGAME: Remaining = VANILLA_MAX_CLIENTS; break; + default: dbg_assert(0, "caught earlier, unreachable"); return; + } + + // Use the following strategy for sending: + // For vanilla, send the first 16 players. + // For legacy 64p, send 24 players per packet. + // For extended, send as much players as possible. + + for(int i = 0; i < MAX_CLIENTS; i++) + { + if(m_aClients[i].m_State != CClient::STATE_EMPTY) { - if(m_aClients[i].m_State != CClient::STATE_EMPTY) - { - if(GameServer()->IsClientBot(i)) - continue; + if(GameServer()->IsClientBot(i)) + continue; - if(g_Config.m_SvHideInfo) - { - if(ClientCount == 0) - break; + if(g_Config.m_SvHideInfo) + { + if(ClientCount == 0) + break; - --ClientCount; - } + --ClientCount; + } - if (Skip-- > 0) - continue; - if (--Take < 0) + if(Remaining == 0) + { + if(Type == SERVERINFO_VANILLA || Type == SERVERINFO_INGAME) break; - p.AddString(ClientName(i), MAX_NAME_LENGTH); // client name - p.AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan + // Otherwise we're SERVERINFO_64_LEGACY. + SEND(pp.Size()); + RESET(); + pp.AddInt(PlayersSent); // offset + Remaining = 24; + } + if(Remaining > 0) + { + Remaining--; + } + + int PreviousSize = pp.Size(); + + pp.AddString(ClientName(i), MAX_NAME_LENGTH); // client name + pp.AddString(ClientClan(i), MAX_CLAN_LENGTH); // client clan - str_format(aBuf, sizeof(aBuf), "%d", m_aClients[i].m_Country); p.AddString(aBuf, 6); // client country - str_format(aBuf, sizeof(aBuf), "%d", RoundStatistics()->PlayerScore(i)); p.AddString(aBuf, 6); // client score - str_format(aBuf, sizeof(aBuf), "%d", GameServer()->IsClientPlayer(i)?1:0); p.AddString(aBuf, 2); // is player? + ADD_INT(pp, m_aClients[i].m_Country); // client country + ADD_INT(pp, RoundStatistics()->PlayerScore(i)); // client score + ADD_INT(pp, GameServer()->IsClientPlayer(i) ? 1 : 0); // is player? + if(Type == SERVERINFO_EXTENDED) + pp.AddString("", 0); // extra info, reserved + + if(Type == SERVERINFO_EXTENDED) + { + if(pp.Size() >= NET_MAX_PAYLOAD) + { + // Retry current player. + i--; + SEND(PreviousSize); + RESET(); + ADD_INT(pp, Token); + ADD_INT(pp, PacketsSent); + pp.AddString("", 0); // extra info, reserved + continue; + } } + PlayersSent++; } } - Packet.m_ClientID = -1; - Packet.m_Address = *pAddr; - Packet.m_Flags = NETSENDFLAG_CONNLESS; - Packet.m_DataSize = p.Size(); - Packet.m_pData = p.Data(); - m_NetServer.Send(&Packet); - - if (Extended && Take < 0) - SendServerInfo(pAddr, Token, Extended, SendClients, Offset + ClientsPerPacket); + SEND(pp.Size()); + #undef SEND + #undef RESET + #undef ADD_RAW + #undef ADD_INT } void CServer::UpdateServerInfo() @@ -1839,11 +1933,12 @@ void CServer::UpdateServerInfo() for(int i = 0; i < MAX_CLIENTS; ++i) { if(m_aClients[i].m_State != CClient::STATE_EMPTY) - SendServerInfo(m_NetServer.ClientAddr(i), -1); + { + SendServerInfo(m_NetServer.ClientAddr(i), -1, SERVERINFO_INGAME, false); + } } } - void CServer::PumpNetwork() { CNetChunk Packet; @@ -1858,15 +1953,29 @@ void CServer::PumpNetwork() // stateless if(!m_Register.RegisterProcessPacket(&Packet)) { - if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETINFO)+1 && + int ExtraToken = 0; + int Type = -1; + if(Packet.m_DataSize >= (int)sizeof(SERVERBROWSE_GETINFO)+1 && mem_comp(Packet.m_pData, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO)) == 0) { - SendServerInfoConnless(&Packet.m_Address, ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO)]); + if(Packet.m_Flags&NETSENDFLAG_EXTENDED) + { + Type = SERVERINFO_EXTENDED; + ExtraToken = (Packet.m_aExtraData[0] << 8) | Packet.m_aExtraData[1]; + } + else + Type = SERVERINFO_VANILLA; + } + else if(Packet.m_DataSize >= (int)sizeof(SERVERBROWSE_GETINFO_64_LEGACY)+1 && + mem_comp(Packet.m_pData, SERVERBROWSE_GETINFO_64_LEGACY, sizeof(SERVERBROWSE_GETINFO_64_LEGACY)) == 0) + { + Type = SERVERINFO_64_LEGACY; } - else if(Packet.m_DataSize == sizeof(SERVERBROWSE_GETINFO64)+1 && - mem_comp(Packet.m_pData, SERVERBROWSE_GETINFO64, sizeof(SERVERBROWSE_GETINFO64)) == 0) + if(Type != -1) { - SendServerInfoConnless(&Packet.m_Address, ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO64)], true); + int Token = ((unsigned char *)Packet.m_pData)[sizeof(SERVERBROWSE_GETINFO)]; + Token |= ExtraToken << 8; + SendServerInfoConnless(&Packet.m_Address, Token, Type); } } } diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 58b608b39..579228678 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -266,8 +266,8 @@ class CServer : public IServer void ProcessClientPacket(CNetChunk *pPacket); - void SendServerInfoConnless(const NETADDR *pAddr, int Token, bool Extended = false); - void SendServerInfo(const NETADDR *pAddr, int Token, bool Extended=false, bool SendClients = true, int Offset=0); + void SendServerInfo(const NETADDR *pAddr, int Token, int Type, bool SendClients); + void SendServerInfoConnless(const NETADDR *pAddr, int Token, int Type); void UpdateServerInfo(); void PumpNetwork(); diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index 235d77d9e..eab145a9d 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -87,18 +87,24 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk) } } +static const unsigned char NET_HEADER_EXTENDED[] = {'x', 'e'}; // packs the data tight and sends it -void CNetBase::SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize) +void CNetBase::SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize, bool Extended, unsigned char aExtra[4]) { unsigned char aBuffer[NET_MAX_PACKETSIZE]; - aBuffer[0] = 0xff; - aBuffer[1] = 0xff; - aBuffer[2] = 0xff; - aBuffer[3] = 0xff; - aBuffer[4] = 0xff; - aBuffer[5] = 0xff; - mem_copy(&aBuffer[6], pData, DataSize); - net_udp_send(Socket, pAddr, aBuffer, 6+DataSize); + const int DATA_OFFSET = 6; + if(!Extended) + { + for(int i = 0; i < DATA_OFFSET; i++) + aBuffer[i] = 0xff; + } + else + { + mem_copy(aBuffer, NET_HEADER_EXTENDED, sizeof(NET_HEADER_EXTENDED)); + mem_copy(aBuffer + sizeof(NET_HEADER_EXTENDED), aExtra, 4); + } + mem_copy(aBuffer + DATA_OFFSET, pData, DataSize); + net_udp_send(Socket, pAddr, aBuffer, DataSize + DATA_OFFSET); } void CNetBase::SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket, SECURITY_TOKEN SecurityToken) @@ -191,7 +197,8 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct if(pPacket->m_Flags&NET_PACKETFLAG_CONNLESS) { - if(Size < 6) + const int DATA_OFFSET = 6; + if(Size < DATA_OFFSET) { dbg_msg("", "connection less packet too small, %d", Size); return -1; @@ -200,8 +207,14 @@ int CNetBase::UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct pPacket->m_Flags = NET_PACKETFLAG_CONNLESS; pPacket->m_Ack = 0; pPacket->m_NumChunks = 0; - pPacket->m_DataSize = Size - 6; - mem_copy(pPacket->m_aChunkData, &pBuffer[6], pPacket->m_DataSize); + pPacket->m_DataSize = Size - DATA_OFFSET; + mem_copy(pPacket->m_aChunkData, pBuffer + DATA_OFFSET, pPacket->m_DataSize); + + if(mem_comp(pBuffer, NET_HEADER_EXTENDED, sizeof(NET_HEADER_EXTENDED)) == 0) + { + pPacket->m_Flags |= NET_PACKETFLAG_EXTENDED; + mem_copy(pPacket->m_aExtraData, pBuffer + sizeof(NET_HEADER_EXTENDED), sizeof(pPacket->m_aExtraData)); + } } else { diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 4c076279c..3689010e6 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -37,6 +37,7 @@ enum NETSENDFLAG_VITAL=1, NETSENDFLAG_CONNLESS=2, NETSENDFLAG_FLUSH=4, + NETSENDFLAG_EXTENDED=8, NETSTATE_OFFLINE=0, NETSTATE_CONNECTING, @@ -70,6 +71,8 @@ enum NET_PACKETFLAG_CONNLESS=2, NET_PACKETFLAG_RESEND=4, NET_PACKETFLAG_COMPRESSION=8, + // NOT SENT VIA THE NETWORK DIRECTLY: + NET_PACKETFLAG_EXTENDED=16, NET_CHUNKFLAG_VITAL=1, NET_CHUNKFLAG_RESEND=2, @@ -125,6 +128,8 @@ struct CNetChunk int m_Flags; int m_DataSize; const void *m_pData; + // only used if the flags contain NETSENDFLAG_EXTENDED and NETSENDFLAG_CONNLESS + unsigned char m_aExtraData[4]; }; class CNetChunkHeader @@ -158,6 +163,7 @@ class CNetPacketConstruct int m_NumChunks; int m_DataSize; unsigned char m_aChunkData[NET_MAX_PAYLOAD]; + unsigned char m_aExtraData[4]; }; @@ -465,8 +471,9 @@ class CNetBase static int Decompress(const void *pData, int DataSize, void *pOutput, int OutputSize); static void SendControlMsg(NETSOCKET Socket, NETADDR *pAddr, int Ack, int ControlMsg, const void *pExtra, int ExtraSize, SECURITY_TOKEN SecurityToken); - static void SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize); + static void SendPacketConnless(NETSOCKET Socket, NETADDR *pAddr, const void *pData, int DataSize, bool Extended, unsigned char aExtra[4]); static void SendPacket(NETSOCKET Socket, NETADDR *pAddr, CNetPacketConstruct *pPacket, SECURITY_TOKEN SecurityToken); + static int UnpackPacket(unsigned char *pBuffer, int Size, CNetPacketConstruct *pPacket); // The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not diff --git a/src/engine/shared/network_client.cpp b/src/engine/shared/network_client.cpp index e68c05436..207e7400c 100644 --- a/src/engine/shared/network_client.cpp +++ b/src/engine/shared/network_client.cpp @@ -79,6 +79,11 @@ int CNetClient::Recv(CNetChunk *pChunk) pChunk->m_Address = Addr; pChunk->m_DataSize = m_RecvUnpacker.m_Data.m_DataSize; pChunk->m_pData = m_RecvUnpacker.m_Data.m_aChunkData; + if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_EXTENDED) + { + pChunk->m_Flags |= NETSENDFLAG_EXTENDED; + mem_copy(pChunk->m_aExtraData, m_RecvUnpacker.m_Data.m_aExtraData, sizeof(pChunk->m_aExtraData)); + } return 1; } else @@ -102,7 +107,8 @@ int CNetClient::Send(CNetChunk *pChunk) if(pChunk->m_Flags&NETSENDFLAG_CONNLESS) { // send connectionless packet - CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize); + CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize, + pChunk->m_Flags&NETSENDFLAG_EXTENDED, pChunk->m_aExtraData); } else { diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp index f9a8754b2..2913f5a0b 100644 --- a/src/engine/shared/network_server.cpp +++ b/src/engine/shared/network_server.cpp @@ -437,6 +437,11 @@ int CNetServer::Recv(CNetChunk *pChunk) pChunk->m_Address = Addr; pChunk->m_DataSize = m_RecvUnpacker.m_Data.m_DataSize; pChunk->m_pData = m_RecvUnpacker.m_Data.m_aChunkData; + if(m_RecvUnpacker.m_Data.m_Flags&NET_PACKETFLAG_EXTENDED) + { + pChunk->m_Flags |= NETSENDFLAG_EXTENDED; + mem_copy(pChunk->m_aExtraData, m_RecvUnpacker.m_Data.m_aExtraData, sizeof(pChunk->m_aExtraData)); + } return 1; } else @@ -499,7 +504,8 @@ int CNetServer::Send(CNetChunk *pChunk) if(pChunk->m_Flags&NETSENDFLAG_CONNLESS) { // send connectionless packet - CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize); + CNetBase::SendPacketConnless(m_Socket, &pChunk->m_Address, pChunk->m_pData, pChunk->m_DataSize, + pChunk->m_Flags&NETSENDFLAG_EXTENDED, pChunk->m_aExtraData); } else { diff --git a/src/mastersrv/mastersrv.h b/src/mastersrv/mastersrv.h index ae9a0c2af..eb99f1173 100644 --- a/src/mastersrv/mastersrv.h +++ b/src/mastersrv/mastersrv.h @@ -28,8 +28,11 @@ static const unsigned char SERVERBROWSE_COUNT[] = {255, 255, 255, 255, 's', 'i', static const unsigned char SERVERBROWSE_GETINFO[] = {255, 255, 255, 255, 'g', 'i', 'e', '3'}; static const unsigned char SERVERBROWSE_INFO[] = {255, 255, 255, 255, 'i', 'n', 'f', '3'}; -static const unsigned char SERVERBROWSE_GETINFO64[] = {255, 255, 255, 255, 'f', 's', 't', 'd'}; -static const unsigned char SERVERBROWSE_INFO64[] = {255, 255, 255, 255, 'd', 't', 's', 'f'}; +static const unsigned char SERVERBROWSE_GETINFO_64_LEGACY[] = {255, 255, 255, 255, 'f', 's', 't', 'd'}; +static const unsigned char SERVERBROWSE_INFO_64_LEGACY[] = {255, 255, 255, 255, 'd', 't', 's', 'f'}; + +static const unsigned char SERVERBROWSE_INFO_EXTENDED[] = {255, 255, 255, 255, 'i', 'e', 'x', 't'}; +static const unsigned char SERVERBROWSE_INFO_EXTENDED_MORE[] = {255, 255, 255, 255, 'i', 'e', 'x', '+'}; static const unsigned char SERVERBROWSE_FWCHECK[] = {255, 255, 255, 255, 'f', 'w', '?', '?'}; static const unsigned char SERVERBROWSE_FWRESPONSE[] = {255, 255, 255, 255, 'f', 'w', '!', '!'}; @@ -52,4 +55,13 @@ static const unsigned char SERVERBROWSE_LIST_LEGACY[] = {255, 255, 255, 255, 'l' static const unsigned char SERVERBROWSE_GETCOUNT_LEGACY[] = {255, 255, 255, 255, 'c', 'o', 'u', 'n'}; static const unsigned char SERVERBROWSE_COUNT_LEGACY[] = {255, 255, 255, 255, 's', 'i', 'z', 'e'}; + +enum +{ + SERVERINFO_VANILLA=0, + SERVERINFO_64_LEGACY, + SERVERINFO_EXTENDED, + SERVERINFO_EXTENDED_MORE, + SERVERINFO_INGAME, +}; #endif