/* * ML_GetFilename * Returns the filename for the map with the corresponding fullname */ const char *ML_GetFilenameExt( const char *fullname, bool recursive ) { mapinfo_t *map; trie_error_t err; char *fullname2; if( !ml_initialized ) return MLIST_NULL; if( !ML_ValidateFullname( fullname ) ) return MLIST_NULL; fullname2 = ( char* )Mem_TempMalloc( strlen( fullname ) + 1 ); strcpy( fullname2, fullname ); Q_strlwr( fullname2 ); err = Trie_Find( mlist_fullnames_trie, fullname2, TRIE_EXACT_MATCH, (void **)&map ); Mem_Free( fullname2 ); if( err == TRIE_OK ) return map->filename; // we should technically never get here, but // maybe the mapper has changed the fullname of the map // or the user has tampered with the mapcache // we need to reload the whole cache from file if we get here /* if( !recursive ) { ML_Restart( true ); return ML_GetFilenameExt( fullname, true ); } */ return MLIST_NULL; }
/* * ML_AddMap * Handles assigning memory for map and adding it to the list * in alphabetical order */ static void ML_AddMap( const char *filename, const char *fullname ) { mapinfo_t *map; char *buffer; char fullname_[MAX_CONFIGSTRING_CHARS]; if( !ML_ValidateFilename( filename ) ) return; if( !strcmp(filename, "ui") ) return; if( !fullname ) { ML_GetFullnameFromMap( filename, fullname_, sizeof( fullname_ ) ); fullname = fullname_; } if( !ML_ValidateFullname( fullname ) && *fullname ) // allow empty fullnames return; if( !strcmp(fullname, "ui") ) return; ml_flush = true; // tell everyone that maplist has changed buffer = ( char* )Mem_ZoneMalloc( sizeof( mapinfo_t ) + strlen( filename ) + 1 + strlen( fullname ) + 1 ); map = ( mapinfo_t * )buffer; buffer += sizeof( mapinfo_t ); map->filename = buffer; strcpy( map->filename, filename ); COM_StripExtension( map->filename ); buffer += strlen( filename ) + 1; map->fullname = buffer; strcpy( map->fullname, fullname ); COM_RemoveColorTokens( map->fullname ); Q_strlwr( map->fullname ); Trie_Insert( mlist_filenames_trie, map->filename, map ); Trie_Insert( mlist_fullnames_trie, map->fullname, map ); map->next = maplist; maplist = map; }
/* * SV_Map_f * * User command to change the map * map: restart game, and start map * devmap: restart game, enable cheats, and start map * gamemap: just start the map */ static void SV_Map_f( void ) { char *map; char mapname[MAX_CONFIGSTRING_CHARS]; qboolean found = qfalse; if( Cmd_Argc() < 2 ) { Com_Printf( "Usage: %s <map>\n", Cmd_Argv( 0 ) ); return; } // if map "<map>" is used Cmd_Args() will return the "" as well. if( Cmd_Argc() == 2 ) map = Cmd_Argv( 1 ); else map = Cmd_Args(); Com_DPrintf( "SV_GameMap(%s)\n", map ); // applies to fullnames and filenames (whereas + strlen( "maps/" ) wouldnt) if( strlen( map ) >= MAX_CONFIGSTRING_CHARS ) { Com_Printf( "Map name too long.\n" ); return; } Q_strncpyz( mapname, map, sizeof( mapname ) ); if( ML_ValidateFilename( mapname ) ) { COM_StripExtension( mapname ); if( ML_FilenameExists( mapname ) ) { found = qtrue; } else { ML_Update(); if( ML_FilenameExists( mapname ) ) found = qtrue; } } if( !found ) { if( ML_ValidateFullname( map ) ) { Q_strncpyz( mapname, ML_GetFilename( map ), sizeof( mapname ) ); if( *mapname ) found = qtrue; } if( !found ) { Com_Printf( "Couldn't find map: %s\n", map ); return; } } if( FS_GetNotifications() & FS_NOTIFT_NEWPAKS ) { FS_RemoveNotifications( FS_NOTIFT_NEWPAKS ); sv.state = ss_dead; // don't save current level when changing } else if( !Q_stricmp( Cmd_Argv( 0 ), "map" ) || !Q_stricmp( Cmd_Argv( 0 ), "devmap" ) ) { sv.state = ss_dead; // don't save current level when changing } // start up the next map SV_Map( mapname, !Q_stricmp( Cmd_Argv( 0 ), "devmap" ) ); // archive server state Q_strncpyz( svs.mapcmd, mapname, sizeof( svs.mapcmd ) ); }