/* =========================================================================== Copyright (C) 1999 - 2005, Id Software, Inc. Copyright (C) 2000 - 2013, Raven Software, Inc. Copyright (C) 2001 - 2013, Activision, Inc. Copyright (C) 2013 - 2015, OpenJK contributors This file is part of the OpenJK source code. OpenJK is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . =========================================================================== */ #include "client.h" // This is for compatibility of old servercache only // Remove when 64-bit int cls_nummplayerservers; serverInfo_t cls_mplayerServers[MAX_OTHER_SERVERS]; /* ==================== LAN_LoadCachedServers ==================== */ void LAN_LoadCachedServers( ) { int size; fileHandle_t fileIn; cls.numglobalservers = cls_nummplayerservers = cls.numfavoriteservers = 0; cls.numGlobalServerAddresses = 0; if (FS_SV_FOpenFileRead("servercache.dat", &fileIn)) { FS_Read(&cls.numglobalservers, sizeof(int), fileIn); FS_Read(&cls_nummplayerservers, sizeof(int), fileIn); FS_Read(&cls.numfavoriteservers, sizeof(int), fileIn); FS_Read(&size, sizeof(int), fileIn); if (size == sizeof(cls.globalServers) + sizeof(cls.favoriteServers) + sizeof(cls_mplayerServers)) { FS_Read(&cls.globalServers, sizeof(cls.globalServers), fileIn); FS_Read(&cls_mplayerServers, sizeof(cls_mplayerServers), fileIn); FS_Read(&cls.favoriteServers, sizeof(cls.favoriteServers), fileIn); } else { cls.numglobalservers = cls_nummplayerservers = cls.numfavoriteservers = 0; cls.numGlobalServerAddresses = 0; } FS_FCloseFile(fileIn); } } /* ==================== LAN_SaveServersToCache ==================== */ void LAN_SaveServersToCache( ) { int size; fileHandle_t fileOut = FS_SV_FOpenFileWrite("servercache.dat"); FS_Write(&cls.numglobalservers, sizeof(int), fileOut); FS_Write(&cls_nummplayerservers, sizeof(int), fileOut); FS_Write(&cls.numfavoriteservers, sizeof(int), fileOut); size = sizeof(cls.globalServers) + sizeof(cls.favoriteServers) + sizeof(cls_mplayerServers); FS_Write(&size, sizeof(int), fileOut); FS_Write(&cls.globalServers, sizeof(cls.globalServers), fileOut); FS_Write(&cls_mplayerServers, sizeof(cls_mplayerServers), fileOut); FS_Write(&cls.favoriteServers, sizeof(cls.favoriteServers), fileOut); FS_FCloseFile(fileOut); } /* ==================== LAN_ResetPings ==================== */ void LAN_ResetPings(int source) { int count,i; serverInfo_t *servers = NULL; count = 0; switch (source) { case AS_LOCAL : servers = &cls.localServers[0]; count = MAX_OTHER_SERVERS; break; case AS_MPLAYER: case AS_GLOBAL : servers = &cls.globalServers[0]; count = MAX_GLOBAL_SERVERS; break; case AS_FAVORITES : servers = &cls.favoriteServers[0]; count = MAX_OTHER_SERVERS; break; } if (servers) { for (i = 0; i < count; i++) { servers[i].ping = -1; } } } /* ==================== LAN_AddServer ==================== */ int LAN_AddServer(int source, const char *name, const char *address) { int max, *count, i; netadr_t adr; serverInfo_t *servers = NULL; max = MAX_OTHER_SERVERS; count = NULL; switch (source) { case AS_LOCAL : count = &cls.numlocalservers; servers = &cls.localServers[0]; break; case AS_MPLAYER: case AS_GLOBAL : max = MAX_GLOBAL_SERVERS; count = &cls.numglobalservers; servers = &cls.globalServers[0]; break; case AS_FAVORITES : count = &cls.numfavoriteservers; servers = &cls.favoriteServers[0]; break; } if (servers && *count < max) { NET_StringToAdr( address, &adr ); for ( i = 0; i < *count; i++ ) { if (NET_CompareAdr(servers[i].adr, adr)) { break; } } if (i >= *count) { servers[*count].adr = adr; Q_strncpyz(servers[*count].hostName, name, sizeof(servers[*count].hostName)); servers[*count].visible = qtrue; (*count)++; return 1; } return 0; } return -1; } int LAN_AddFavAddr( const char *address ) { if ( cls.numfavoriteservers < MAX_OTHER_SERVERS ) { netadr_t adr; if ( !NET_StringToAdr( address, &adr ) ) { return 2; } if ( adr.type == NA_BAD ) { return 3; } for ( int i = 0; i < cls.numfavoriteservers; i++ ) { if ( NET_CompareAdr( cls.favoriteServers[i].adr, adr ) ) { return 0; } } cls.favoriteServers[cls.numfavoriteservers].adr = adr; Q_strncpyz( cls.favoriteServers[cls.numfavoriteservers].hostName, address, sizeof(cls.favoriteServers[cls.numfavoriteservers].hostName) ); cls.favoriteServers[cls.numfavoriteservers].visible = qtrue; cls.numfavoriteservers++; return 1; } return -1; } /* ==================== LAN_RemoveServer ==================== */ void LAN_RemoveServer(int source, const char *addr) { int *count, i; serverInfo_t *servers = NULL; count = NULL; switch (source) { case AS_LOCAL : count = &cls.numlocalservers; servers = &cls.localServers[0]; break; case AS_MPLAYER: case AS_GLOBAL : count = &cls.numglobalservers; servers = &cls.globalServers[0]; break; case AS_FAVORITES : count = &cls.numfavoriteservers; servers = &cls.favoriteServers[0]; break; } if (servers) { netadr_t comp; NET_StringToAdr( addr, &comp ); for (i = 0; i < *count; i++) { if (NET_CompareAdr( comp, servers[i].adr)) { int j = i; while (j < *count - 1) { Com_Memcpy(&servers[j], &servers[j+1], sizeof(servers[j])); j++; } (*count)--; break; } } } } /* ==================== LAN_GetServerCount ==================== */ int LAN_GetServerCount( int source ) { switch (source) { case AS_LOCAL : return cls.numlocalservers; break; case AS_MPLAYER: case AS_GLOBAL : return cls.numglobalservers; break; case AS_FAVORITES : return cls.numfavoriteservers; break; } return 0; } /* ==================== LAN_GetLocalServerAddressString ==================== */ void LAN_GetServerAddressString( int source, int n, char *buf, int buflen ) { switch (source) { case AS_LOCAL : if (n >= 0 && n < MAX_OTHER_SERVERS) { Q_strncpyz(buf, NET_AdrToString( cls.localServers[n].adr) , buflen ); return; } break; case AS_MPLAYER: case AS_GLOBAL : if (n >= 0 && n < MAX_GLOBAL_SERVERS) { Q_strncpyz(buf, NET_AdrToString( cls.globalServers[n].adr) , buflen ); return; } break; case AS_FAVORITES : if (n >= 0 && n < MAX_OTHER_SERVERS) { Q_strncpyz(buf, NET_AdrToString( cls.favoriteServers[n].adr) , buflen ); return; } break; } buf[0] = '\0'; } /* ==================== LAN_GetServerInfo ==================== */ void LAN_GetServerInfo( int source, int n, char *buf, int buflen ) { char info[MAX_STRING_CHARS]; serverInfo_t *server = NULL; info[0] = '\0'; switch (source) { case AS_LOCAL : if (n >= 0 && n < MAX_OTHER_SERVERS) { server = &cls.localServers[n]; } break; case AS_MPLAYER: case AS_GLOBAL : if (n >= 0 && n < MAX_GLOBAL_SERVERS) { server = &cls.globalServers[n]; } break; case AS_FAVORITES : if (n >= 0 && n < MAX_OTHER_SERVERS) { server = &cls.favoriteServers[n]; } break; } if (server && buf) { buf[0] = '\0'; Info_SetValueForKey( info, "hostname", server->hostName); Info_SetValueForKey( info, "mapname", server->mapName); Info_SetValueForKey( info, "clients", va("%i",server->clients)); Info_SetValueForKey( info, "sv_maxclients", va("%i",server->maxClients)); Info_SetValueForKey( info, "ping", va("%i",server->ping)); Info_SetValueForKey( info, "minping", va("%i",server->minPing)); Info_SetValueForKey( info, "maxping", va("%i",server->maxPing)); Info_SetValueForKey( info, "nettype", va("%i",server->netType)); Info_SetValueForKey( info, "needpass", va("%i", server->needPassword ) ); Info_SetValueForKey( info, "truejedi", va("%i", server->trueJedi ) ); Info_SetValueForKey( info, "wdisable", va("%i", server->weaponDisable ) ); Info_SetValueForKey( info, "fdisable", va("%i", server->forceDisable ) ); Info_SetValueForKey( info, "game", server->game); Info_SetValueForKey( info, "gametype", va("%i",server->gameType)); Info_SetValueForKey( info, "addr", NET_AdrToString(server->adr)); Info_SetValueForKey( info, "g_humanplayers", va( "%i", server->humans ) ); Info_SetValueForKey( info, "bots", va( "%i", server->bots ) ); // Info_SetValueForKey( info, "sv_allowAnonymous", va("%i", server->allowAnonymous)); // Info_SetValueForKey( info, "pure", va("%i", server->pure ) ); Q_strncpyz(buf, info, buflen); } else { if (buf) { buf[0] = '\0'; } } } /* ==================== LAN_GetServerPing ==================== */ int LAN_GetServerPing( int source, int n ) { serverInfo_t *server = NULL; switch (source) { case AS_LOCAL : if (n >= 0 && n < MAX_OTHER_SERVERS) { server = &cls.localServers[n]; } break; case AS_MPLAYER: case AS_GLOBAL : if (n >= 0 && n < MAX_GLOBAL_SERVERS) { server = &cls.globalServers[n]; } break; case AS_FAVORITES : if (n >= 0 && n < MAX_OTHER_SERVERS) { server = &cls.favoriteServers[n]; } break; } if (server) { return server->ping; } return -1; } /* ==================== LAN_GetServerPtr ==================== */ static serverInfo_t *LAN_GetServerPtr( int source, int n ) { switch (source) { case AS_LOCAL : if (n >= 0 && n < MAX_OTHER_SERVERS) { return &cls.localServers[n]; } break; case AS_MPLAYER: case AS_GLOBAL : if (n >= 0 && n < MAX_GLOBAL_SERVERS) { return &cls.globalServers[n]; } break; case AS_FAVORITES : if (n >= 0 && n < MAX_OTHER_SERVERS) { return &cls.favoriteServers[n]; } break; } return NULL; } /* ==================== LAN_CompareServers ==================== */ int LAN_CompareServers( int source, int sortKey, int sortDir, int s1, int s2 ) { int res; serverInfo_t *server1, *server2; server1 = LAN_GetServerPtr(source, s1); server2 = LAN_GetServerPtr(source, s2); if (!server1 || !server2) { return 0; } res = 0; switch( sortKey ) { case SORT_HOST: res = Q_stricmp( server1->hostName, server2->hostName ); break; case SORT_MAP: res = Q_stricmp( server1->mapName, server2->mapName ); break; case SORT_CLIENTS: if (server1->clients < server2->clients) { res = -1; } else if (server1->clients > server2->clients) { res = 1; } else { res = 0; } break; case SORT_GAME: if (server1->gameType < server2->gameType) { res = -1; } else if (server1->gameType > server2->gameType) { res = 1; } else { res = 0; } break; case SORT_PING: if (server1->ping < server2->ping) { res = -1; } else if (server1->ping > server2->ping) { res = 1; } else { res = 0; } break; } if (sortDir) { if (res < 0) return 1; if (res > 0) return -1; return 0; } return res; } /* ==================== LAN_GetPingQueueCount ==================== */ int LAN_GetPingQueueCount( void ) { return (CL_GetPingQueueCount()); } /* ==================== LAN_ClearPing ==================== */ void LAN_ClearPing( int n ) { CL_ClearPing( n ); } /* ==================== LAN_GetPing ==================== */ void LAN_GetPing( int n, char *buf, int buflen, int *pingtime ) { CL_GetPing( n, buf, buflen, pingtime ); } /* ==================== LAN_GetPingInfo ==================== */ void LAN_GetPingInfo( int n, char *buf, int buflen ) { CL_GetPingInfo( n, buf, buflen ); } /* ==================== LAN_MarkServerVisible ==================== */ void LAN_MarkServerVisible(int source, int n, qboolean visible ) { if (n == -1) { int count = MAX_OTHER_SERVERS; serverInfo_t *server = NULL; switch (source) { case AS_LOCAL : server = &cls.localServers[0]; break; case AS_MPLAYER: case AS_GLOBAL : server = &cls.globalServers[0]; count = MAX_GLOBAL_SERVERS; break; case AS_FAVORITES : server = &cls.favoriteServers[0]; break; } if (server) { for (n = 0; n < count; n++) { server[n].visible = visible; } } } else { switch (source) { case AS_LOCAL : if (n >= 0 && n < MAX_OTHER_SERVERS) { cls.localServers[n].visible = visible; } break; case AS_MPLAYER: case AS_GLOBAL : if (n >= 0 && n < MAX_GLOBAL_SERVERS) { cls.globalServers[n].visible = visible; } break; case AS_FAVORITES : if (n >= 0 && n < MAX_OTHER_SERVERS) { cls.favoriteServers[n].visible = visible; } break; } } } /* ======================= LAN_ServerIsVisible ======================= */ int LAN_ServerIsVisible(int source, int n ) { switch (source) { case AS_LOCAL : if (n >= 0 && n < MAX_OTHER_SERVERS) { return cls.localServers[n].visible; } break; case AS_MPLAYER: case AS_GLOBAL : if (n >= 0 && n < MAX_GLOBAL_SERVERS) { return cls.globalServers[n].visible; } break; case AS_FAVORITES : if (n >= 0 && n < MAX_OTHER_SERVERS) { return cls.favoriteServers[n].visible; } break; } return qfalse; } /* ======================= LAN_UpdateVisiblePings ======================= */ qboolean LAN_UpdateVisiblePings(int source ) { return CL_UpdateVisiblePings_f(source); } /* ==================== LAN_GetServerStatus ==================== */ int LAN_GetServerStatus( const char *serverAddress, char *serverStatus, int maxLen ) { return CL_ServerStatus( serverAddress, serverStatus, maxLen ); }