/* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. Copyright (C) 2000-2009 Darklegion Development This file is part of Tremulous. Tremulous is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Tremulous 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 Tremulous; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ // // gameinfo.c // #include "ui_local.h" // // arena and bot info // int ui_numBots; static char *ui_botInfos[MAX_BOTS]; static int ui_numArenas; static char *ui_arenaInfos[MAX_ARENAS]; /* =============== UI_ParseInfos =============== */ int UI_ParseInfos( char *buf, int max, char *infos[] ) { char * token; int count; char key[MAX_TOKEN_CHARS]; char info[MAX_INFO_STRING]; count = 0; while( 1 ) { token = COM_Parse( &buf ); if( !token[0] ) break; if( strcmp( token, "{" ) ) { Com_Printf( "Missing { in info file\n" ); break; } if( count == max ) { Com_Printf( "Max infos exceeded\n" ); break; } info[0] = '\0'; while( 1 ) { token = COM_ParseExt( &buf, qtrue ); if( !token[0] ) { Com_Printf( "Unexpected end of info file\n" ); break; } if( !strcmp( token, "}" ) ) break; Q_strncpyz( key, token, sizeof( key ) ); token = COM_ParseExt( &buf, qfalse ); if( !token[0] ) strcpy( token, "" ); Info_SetValueForKey( info, key, token ); } //NOTE: extra space for arena number infos[count] = UI_Alloc( strlen( info ) + strlen( "\\num\\" ) + strlen( va( "%d", MAX_ARENAS ) ) + 1 ); if( infos[count] ) { strcpy( infos[count], info ); count++; } } return count; } /* =============== UI_LoadArenasFromFile =============== */ static void UI_LoadArenasFromFile( char *filename ) { int len; fileHandle_t f; char buf[MAX_ARENAS_TEXT]; len = trap_FS_FOpenFile( filename, &f, FS_READ ); if( !f ) { trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) ); return; } if( len >= MAX_ARENAS_TEXT ) { trap_Print( va( S_COLOR_RED "file too large: %s is %i, max allowed is %i", filename, len, MAX_ARENAS_TEXT ) ); trap_FS_FCloseFile( f ); return; } trap_FS_Read( buf, len, f ); buf[len] = 0; trap_FS_FCloseFile( f ); ui_numArenas += UI_ParseInfos( buf, MAX_ARENAS - ui_numArenas, &ui_arenaInfos[ui_numArenas] ); } /* ================= UI_MapNameCompare ================= */ static int UI_MapNameCompare( const void *a, const void *b ) { mapInfo * A = ( mapInfo * )a; mapInfo *B = ( mapInfo * )b; return Q_stricmp( A->mapName, B->mapName ); } /* =============== UI_LoadArenas =============== */ void UI_LoadArenas( void ) { int numdirs; char filename[512]; char dirlist[4048]; char* dirptr; int i, n; int dirlen; char *type; ui_numArenas = 0; uiInfo.mapCount = 0; // get all arenas from .arena files numdirs = trap_FS_GetFileList( "scripts", ".arena", dirlist, 4048 ); dirptr = dirlist; for( i = 0; i < numdirs; i++, dirptr += dirlen + 1 ) { dirlen = strlen( dirptr ); strcpy( filename, "scripts/" ); strcat( filename, dirptr ); UI_LoadArenasFromFile( filename ); } trap_Print( va( "[skipnotify]%i arenas parsed\n", ui_numArenas ) ); if( UI_OutOfMemory() ) trap_Print( S_COLOR_YELLOW"WARNING: not anough memory in pool to load all arenas\n" ); for( n = 0; n < ui_numArenas; n++ ) { // determine type type = Info_ValueForKey( ui_arenaInfos[ n ], "type" ); // if no type specified, it will be treated as "ffa" uiInfo.mapList[uiInfo.mapCount].cinematic = -1; uiInfo.mapList[uiInfo.mapCount].mapLoadName = String_Alloc( Info_ValueForKey( ui_arenaInfos[n], "map" ) ); uiInfo.mapList[uiInfo.mapCount].mapName = String_Alloc( Info_ValueForKey( ui_arenaInfos[n], "longname" ) ); uiInfo.mapList[uiInfo.mapCount].levelShot = -1; uiInfo.mapList[uiInfo.mapCount].imageName = String_Alloc( va( "levelshots/%s", uiInfo.mapList[uiInfo.mapCount].mapLoadName ) ); uiInfo.mapCount++; if( uiInfo.mapCount >= MAX_MAPS ) break; } qsort( uiInfo.mapList, uiInfo.mapCount, sizeof( mapInfo ), UI_MapNameCompare ); } /* =============== UI_LoadBotsFromFile =============== */ static void UI_LoadBotsFromFile( char *filename ) { int len; fileHandle_t f; char buf[MAX_BOTS_TEXT]; len = trap_FS_FOpenFile( filename, &f, FS_READ ); if( !f ) { trap_Print( va( S_COLOR_RED "file not found: %s\n", filename ) ); return; } if( len >= MAX_BOTS_TEXT ) { trap_Print( va( S_COLOR_RED "file too large: %s is %i, max allowed is %i", filename, len, MAX_BOTS_TEXT ) ); trap_FS_FCloseFile( f ); return; } trap_FS_Read( buf, len, f ); buf[len] = 0; trap_FS_FCloseFile( f ); COM_Compress( buf ); ui_numBots += UI_ParseInfos( buf, MAX_BOTS - ui_numBots, &ui_botInfos[ui_numBots] ); } /* =============== UI_LoadBots =============== */ void UI_LoadBots( void ) { vmCvar_t botsFile; int numdirs; char filename[128]; char dirlist[1024]; char* dirptr; int i; int dirlen; ui_numBots = 0; trap_Cvar_Register( &botsFile, "g_botsFile", "", CVAR_INIT | CVAR_ROM ); if( *botsFile.string ) UI_LoadBotsFromFile( botsFile.string ); else UI_LoadBotsFromFile( "scripts/bots.txt" ); // get all bots from .bot files numdirs = trap_FS_GetFileList( "scripts", ".bot", dirlist, 1024 ); dirptr = dirlist; for( i = 0; i < numdirs; i++, dirptr += dirlen + 1 ) { dirlen = strlen( dirptr ); strcpy( filename, "scripts/" ); strcat( filename, dirptr ); UI_LoadBotsFromFile( filename ); } trap_Print( va( "%i bots parsed\n", ui_numBots ) ); } /* =============== UI_GetBotInfoByNumber =============== */ char *UI_GetBotInfoByNumber( int num ) { if( num < 0 || num >= ui_numBots ) { trap_Print( va( S_COLOR_RED "Invalid bot number: %i\n", num ) ); return NULL; } return ui_botInfos[num]; } /* =============== UI_GetBotInfoByName =============== */ char *UI_GetBotInfoByName( const char *name ) { int n; char *value; for( n = 0; n < ui_numBots ; n++ ) { value = Info_ValueForKey( ui_botInfos[n], "name" ); if( !Q_stricmp( value, name ) ) return ui_botInfos[n]; } return NULL; } int UI_GetNumBots( void ) { return ui_numBots; } char *UI_GetBotNameByNumber( int num ) { char * info = UI_GetBotInfoByNumber( num ); if( info ) return Info_ValueForKey( info, "name" ); return ""; } void UI_ServerInfo( void ) { char info[ MAX_INFO_VALUE ]; char hostname[MAX_HOSTNAME_LENGTH]; info[0] = '\0'; if( trap_GetConfigString( CS_SERVERINFO, info, sizeof( info ) ) ) { trap_Cvar_Set( "ui_serverinfo_mapname", Info_ValueForKey( info, "mapname" ) ); trap_Cvar_Set( "ui_serverinfo_timelimit", Info_ValueForKey( info, "timelimit" ) ); trap_Cvar_Set( "ui_serverinfo_sd", Info_ValueForKey( info, "g_suddenDeathTime" ) ); UI_EscapeEmoticons( hostname, Info_ValueForKey( info, "sv_hostname" ), sizeof( hostname ) ); trap_Cvar_Set( "ui_serverinfo_hostname", hostname ); trap_Cvar_Set( "ui_serverinfo_maxclients", Info_ValueForKey( info, "sv_maxclients" ) ); trap_Cvar_Set( "ui_serverinfo_version", Info_ValueForKey( info, "version" ) ); trap_Cvar_Set( "ui_serverinfo_unlagged", Info_ValueForKey( info, "g_unlagged" ) ); trap_Cvar_Set( "ui_serverinfo_friendlyFire", Info_ValueForKey( info, "g_friendlyFire" ) ); trap_Cvar_Set( "ui_serverinfo_friendlyBuildableFire", Info_ValueForKey( info, "g_friendlyBuildableFire" ) ); trap_Cvar_Set( "ui_serverinfo_allowdl", Info_ValueForKey( info, "sv_allowdownload" ) ); } }