diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /dedicated/vgui/CreateMultiplayerGameServerPage.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'dedicated/vgui/CreateMultiplayerGameServerPage.cpp')
| -rw-r--r-- | dedicated/vgui/CreateMultiplayerGameServerPage.cpp | 872 |
1 files changed, 872 insertions, 0 deletions
diff --git a/dedicated/vgui/CreateMultiplayerGameServerPage.cpp b/dedicated/vgui/CreateMultiplayerGameServerPage.cpp new file mode 100644 index 0000000..d4e6308 --- /dev/null +++ b/dedicated/vgui/CreateMultiplayerGameServerPage.cpp @@ -0,0 +1,872 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifdef _WIN32 +#include <stdio.h> + +#include "CreateMultiplayerGameServerPage.h" +#include <Winsock2.h> + +using namespace vgui; + +#include <vgui_controls/Controls.h> +#include <KeyValues.h> +#include <vgui_controls/ListPanel.h> +#include <vgui_controls/ComboBox.h> +#include <vgui_controls/MessageBox.h> +#include <vgui_controls/CheckButton.h> +#include <vgui/IVGui.h> + +#include <OfflineMode.h> + +#include "filesystem.h" +#include "mainpanel.h" +#include "tier0/icommandline.h" +#include "netapi.h" +// for SRC +#include <vstdlib/random.h> + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + + +//#define ALLOW_OLD_ENGINE_GAMES + + +bool IsEp1EraAppID( int iSteamAppId ) +{ + return iSteamAppId == 211 || iSteamAppId == 215; +} + +// Checks the liblist.gam file for a "fallback_dir" +const char *GetLiblistFallbackDir( const char *pszGameDir ) +{ + static char szFallback[512]; + char szTemp[512]; + + szFallback[0] = 0; + + V_sprintf_safe( szTemp, "%s\\liblist.gam", pszGameDir ); + g_pFullFileSystem->GetLocalCopy( szTemp ); + + FileHandle_t hFile = g_pFullFileSystem->Open( szTemp, "rt" ); + + if ( hFile ) + { + char szLine[512]; + + // look for the line starting with 'fallback_dir' + while ( !g_pFullFileSystem->EndOfFile( hFile ) ) + { + // get a single line + szLine[0] = 0; + g_pFullFileSystem->ReadLine( szLine, sizeof(szLine) - 1, hFile ); + szLine[sizeof(szLine) - 1] = 0; + + if ( !strnicmp( szLine, "fallback_dir", 12 ) ) + { + // we got the line, get the value between the quotes + char *start = strchr( szLine, '\"' ); + + if ( !start ) + { + break; + } + + char *end = strchr( start + 1, '\"' ); + if ( !end ) + { + break; + } + + // copy out between start and end + int bytesToCopy = end - start - 1; + if ( bytesToCopy >= sizeof(szFallback) - 1 ) + { + bytesToCopy = sizeof(szFallback) - 1; + break; + } + + if ( bytesToCopy > 0 ) + { + strncpy( szFallback, start + 1, bytesToCopy ); + szFallback[bytesToCopy] = 0; + } + } + } + + g_pFullFileSystem->Close( hFile ); + } + + return szFallback; +} + + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CCreateMultiplayerGameServerPage::CCreateMultiplayerGameServerPage(vgui::Panel *parent, const char *name) : Frame(parent, name) +{ + memset(&m_iServer,0x0,sizeof(serveritem_t)); + + m_MainPanel = parent; // as we are a popup frame we need to store this seperately + m_pSavedData = NULL; + m_pGameInfo = NULL; + + SetMinimumSize(310, 350); + SetSize(310, 350); + SetSizeable(false); + + + SetTitle("#Start_Server_Title",true); + + m_pMapList = new ComboBox(this, "MapList",10,false); + m_pMapList->SetEnabled(false); // a mod needs to be chosen first to populate the map list + m_pMapList->SetEditable(false); + + m_pNetworkCombo = new ComboBox(this, "NetworkCombo",10,false); + int defaultItem = m_pNetworkCombo->AddItem("#Internet", NULL); + int lanItem = m_pNetworkCombo->AddItem("#LAN", NULL); + if ( CommandLine()->CheckParm("-steam") && IsSteamInOfflineMode() ) + { + defaultItem = lanItem; + } + m_pNetworkCombo->ActivateItem(defaultItem); + + m_pNumPlayers = new ComboBox(this, "NumPlayers",10,false); + char num[3]; + int i; + for( i = 1 ; i <= MAX_PLAYERS ; i++ ) + { + V_sprintf_safe(num, "%i", i); + m_pNumPlayers->AddItem(num, NULL); + } + m_pNumPlayers->ActivateItemByRow(23); // 24 players by default + + m_pGameCombo = new ComboBox(this,"MODCombo", 10, false); + + m_pStartServerButton = new Button(this, "StartButton", "#Start_Server_Button"); + m_pStartServerButton->SetCommand("start"); + + m_pCancelButton = new Button(this, "CancelButton", "#Start_Server_Cancel"); + m_pCancelButton->SetCommand("cancel"); + + m_pSecureCheck = new CheckButton(this, "SecureCheck", "#Start_Server_Secure"); + m_pSecureCheck->SetSelected(true); + + LoadControlSettingsAndUserConfig("Admin/CreateMultiplayerGameServerPage.res"); + + // load some defaults into the controls + SetControlString("ServerNameEdit", "Half-Life dedicated server"); + V_strcpy_safe(m_szGameName, "Half-Life"); + + LoadMODList(); + + m_pGameCombo->RequestFocus(); + + // get default port from commandline if possible + m_iPort = 27015; + const char *portVal = NULL; + if (CommandLine()->CheckParm("-port", &portVal) && portVal && atoi(portVal) > 0) + { + m_iPort = atoi(portVal); + } + SetControlInt("PortEdit", m_iPort); + + LoadConfig(); + + m_szMapName[0] = 0; + m_szHostName[0] = 0; + m_szPassword[0] = 0; + m_iMaxPlayers = 24; + + if ( CommandLine()->CheckParm("-steam") && IsSteamInOfflineMode() ) + { + m_pNetworkCombo->SetEnabled( false ); + } + + SetVisible(true); + + if ( CommandLine()->CheckParm("-steam") && IsSteamInOfflineMode() ) + { + MessageBox *box = new vgui::MessageBox( "#Start_Server_Offline_Title", "#Start_Server_Offline_Warning" ); + box->DoModal(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Destructor +//----------------------------------------------------------------------------- +CCreateMultiplayerGameServerPage::~CCreateMultiplayerGameServerPage() +{ + SaveConfig(); + if (m_pSavedData) + { + m_pSavedData->deleteThis(); + m_pSavedData = NULL; + } + if ( m_pGameInfo ) + { + m_pGameInfo->deleteThis(); + m_pGameInfo = NULL; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCreateMultiplayerGameServerPage::OnResetData() +{ + m_pGameCombo->SetEnabled(true); +} + +//----------------------------------------------------------------------------- +// Purpose: loads settings from a config file +//----------------------------------------------------------------------------- +void CCreateMultiplayerGameServerPage::LoadConfig() +{ + // free any old filters + if (m_pSavedData) + { + m_pSavedData->deleteThis(); + } + m_pSavedData = new KeyValues ("Server"); + + if (!m_pSavedData->LoadFromFile(g_pFullFileSystem, "Server.vdf", "CONFIG")) + { + // file not successfully loaded + } + else + { + if (m_pSavedData->FindKey("RconPassword", false)) + { + const char *password = m_pSavedData->GetString("RconPassword", ""); + if (strlen(password)>0) + { + SetControlString("RCONPasswordEdit", password); + } + } + if (m_pSavedData->FindKey("MaxPlayers", false)) + { + int maxPlayers = m_pSavedData->GetInt("MaxPlayers", -1); + if (maxPlayers > 0 && maxPlayers <= 32) + { + m_pNumPlayers->ActivateItemByRow(maxPlayers - 1); + } + } + if (m_pSavedData->FindKey("MOD", false)) + { + const char *mod = m_pSavedData->GetString("MOD", ""); + if (strlen(mod) > 0) + { + // look for the item in the dropdown + m_szMod[0] = 0; + for (int i = 0; i < m_pGameCombo->GetItemCount(); i++) + { + if (!m_pGameCombo->IsItemIDValid(i)) + continue; + + if (!stricmp(m_pGameCombo->GetItemUserData(i)->GetString("gamedir"), mod)) + { + // item found in list, activate + m_pGameCombo->ActivateItem(i); + break; + } + } + } + } + if (m_pSavedData->FindKey("Map", false)) + { + const char *map = m_pSavedData->GetString("Map", ""); + if (strlen(map) > 0) + { + SetControlString("MapList", map); + } + } + + if (m_pSavedData->FindKey("Network", false)) + { + int nwIndex = m_pSavedData->GetInt("Network"); + if (nwIndex > 0 && nwIndex < 2) + { + m_pNetworkCombo->ActivateItemByRow(nwIndex); + } + } + if (m_pSavedData->FindKey("Secure", false)) + { + int secure = m_pSavedData->GetInt("Secure"); + m_pSecureCheck->SetSelected(secure); + } + if (m_pSavedData->FindKey("ServerName", false)) + { + const char *serverName = m_pSavedData->GetString("ServerName",""); + if (strlen(serverName) > 0) + { + SetControlString("ServerNameEdit", serverName); + } + } + m_iPort = m_pSavedData->GetInt("Port", m_iPort); + SetControlInt("PortEdit", m_iPort); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +void CCreateMultiplayerGameServerPage::SetConfig(const char *serverName, const char *rconPassword, int maxPlayers, const char *mod, const char *map, int network, int secure, int port) +{ + m_pSavedData->SetInt("MaxPlayers", maxPlayers); + m_pSavedData->SetString("RconPassword", rconPassword); + m_pSavedData->SetString("ServerName", serverName); + m_pSavedData->SetString("MOD", mod); + m_pSavedData->SetString("Map", map); + m_pSavedData->SetInt("Secure", secure); + m_pSavedData->SetInt("Network", network); + m_pSavedData->SetInt("Port", port); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CCreateMultiplayerGameServerPage::SaveConfig() +{ + m_pSavedData->SaveToFile(g_pFullFileSystem, "Server.vdf", "CONFIG"); +} + +//----------------------------------------------------------------------------- +// Purpose: returns true if one of the characters in the string is not a valid alpha numeric character +//----------------------------------------------------------------------------- +bool CCreateMultiplayerGameServerPage::BadRconChars(const char *pass) +{ + bool bad = false; + + for(unsigned int i=0;i<strlen(pass);i++) + { + bad |= !( V_isalnum(pass[i]) ? true : false ); + } + return bad; +} + +const char *ToString( int val ) +{ + static char text[256]; + Q_snprintf( text, sizeof(text), "%i", val ); + return text; +} + + +//----------------------------------------------------------------------------- +// Purpose: called to get the info from the dialog +//----------------------------------------------------------------------------- +void CCreateMultiplayerGameServerPage::OnCommand(const char *cmd) +{ + char cvars[1024]; + int secure = GetControlInt("SecureCheck", 1); + m_pNumPlayers->GetText(cvars, 1024); + m_iMaxPlayers = atoi(cvars); + V_strcpy_safe(m_szHostName, GetControlString("ServerNameEdit", "")); + V_strcpy_safe(m_szPassword, GetControlString("RCONPasswordEdit", "")); + m_iPort = GetControlInt("PortEdit", 27015); + + if (!stricmp(cmd, "cancel")) + { + vgui::ivgui()->PostMessage( m_MainPanel->GetVPanel(), new KeyValues("Quit"), NULL); + Close(); + } + else if (!stricmp(cmd, "start")) + { + // save our current settings + SetConfig(m_szHostName, m_szPassword, m_iMaxPlayers, m_szMod, GetMapName(), m_pNetworkCombo->GetActiveItem() != 0, secure, m_iPort); + SaveConfig(); + + // create the command to execute + bool isLanOnly = (m_pNetworkCombo->GetActiveItem() != 0); + CommandLine()->AppendParm("-game", m_szMod); + CommandLine()->AppendParm("-maxplayers", ToString(m_iMaxPlayers)); + CommandLine()->AppendParm("+sv_lan", ToString(isLanOnly)); + CommandLine()->AppendParm("+map", GetMapName()); + CommandLine()->AppendParm("-port", ToString(m_iPort)); + if (!secure) // if they don't want it secure... + { + CommandLine()->AppendParm("-insecure", ""); + } + + + // V_strcpy_safe(m_szPassword, GetControlString("RCONPasswordEdit", "")); + if (strlen(m_szPassword) < 3 || BadRconChars(m_szPassword)) + { + MessageBox *dlg = new MessageBox("#Start_Server_RCON_Error_Title", "#Start_Server_RCON_Error"); + dlg->DoModal(); + } + else + { + V_sprintf_safe(cvars, "rcon_password \"%s\"\nsetmaster enable\nhostname \"%s\"\n", m_szPassword, m_szHostName); + + m_pGameCombo->SetEnabled(false); + m_pNumPlayers->SetEnabled(false); + + netadr_t local; + net->GetLocalIP(&local); + local.port = ::htons(m_iPort); + + for (int i = 0; i < 4; i++) + { + m_iServer.ip[i] = local.ip[i]; + } + m_iServer.port = (local.port & 0xff) << 8 | (local.port & 0xff00) >> 8;; + + V_strcpy_safe(m_iServer.name, m_szHostName); + V_strcpy_safe(m_iServer.map, GetMapName()); + V_strcpy_safe(m_iServer.gameDir, m_szMod); + m_iServer.maxPlayers = m_iMaxPlayers; + + SetVisible(false); + + KeyValues *gameData = m_pGameCombo->GetActiveItemUserData(); + +// // mount the caches +// if (CommandLine()->CheckParm("-steam")) +// { +// if (gameData) +// { +// KeyValues *pFileSystem = gameData->FindKey( "FileSystem" ); +// if ( !pFileSystem ) +// Error( "Game %s missing FileSystem key.", gameData->GetString( "game" ) ); +// +// // Mods just specify their app ID (CS, HL2, HL2MP, etc), and it mounts all the necessary caches. +// int iAppId = pFileSystem->GetInt( "SteamAppId" ); +// if ( iAppId ) +// { +// CUtlVector<unsigned int> depList; +// MountDependencies( iAppId, depList ); +// +// char gameinfoFilename[MAX_PATH]; +// Q_snprintf( gameinfoFilename, sizeof( gameinfoFilename ), "%s\\gameinfo.txt", m_iServer.gameDir ); +// g_pFullFileSystem->GetLocalCopy( gameinfoFilename ); +// } +// } +// } + + // Launch the old dedicated server if necessary. + if ( LaunchOldDedicatedServer( gameData ) ) + { + vgui::ivgui()->PostMessage( m_MainPanel->GetVPanel(), new KeyValues("Quit"), NULL); + Close(); + } + + CMainPanel::GetInstance()->StartServer(cvars); + } + } +} + +bool CCreateMultiplayerGameServerPage::LaunchOldDedicatedServer( KeyValues *pGameInfo ) +{ +#if defined( ALLOW_OLD_ENGINE_GAMES ) + // Validate the gameinfo.txt format.. + KeyValues *pSub = pGameInfo->FindKey( "FileSystem" ); + if ( pSub ) + { + int iSteamAppId = pSub->GetInt( "SteamAppId", -1 ); + if ( iSteamAppId != -1 ) + { + if ( IsEp1EraAppID( iSteamAppId ) ) + { + // Old-skool app. Launch the old dedicated server. + char steamDir[MAX_PATH]; + if ( !system()->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\SteamPath", steamDir, sizeof( steamDir ) ) ) + Error( "LaunchOldDedicatedServer: can't get SteamPath." ); + + V_FixSlashes( steamDir ); + V_AppendSlash( steamDir, sizeof( steamDir ) ); + + char commandLine[1024 * 4]; + commandLine[0] = 0; + V_snprintf( commandLine, sizeof( commandLine ), "\"%ssteam.exe\" -applaunch 205 -HiddenLaunch", steamDir ); + + // Feed it all the parameters chosen in the UI so it doesn't redisplay the UI. + STARTUPINFO si; + memset( &si, 0, sizeof( si ) ); + si.cb = sizeof( si ); + + PROCESS_INFORMATION pi; + if ( !CreateProcess( NULL, commandLine, NULL, NULL, false, 0, NULL, steamDir, &si, &pi ) ) + { + Error( "LaunchOldDedicatedServer: Unable to launch old srcds." ); + } + + return true; + } + } + } +#endif + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: loads the list of available maps into the map list +//----------------------------------------------------------------------------- +void CCreateMultiplayerGameServerPage::LoadMODList() +{ + m_pGameCombo->DeleteAllItems(); + + // add steam games + if (CommandLine()->CheckParm("-steam")) + { + const char *pSteamGamesFilename = "hlds_steamgames.vdf"; + + KeyValues *gamesFile = new KeyValues( pSteamGamesFilename ); + + if ( gamesFile->LoadFromFile( g_pFullFileSystem, pSteamGamesFilename, NULL ) ) + { + for ( KeyValues *kv = gamesFile->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey() ) + { + const char *pGameDir = kv->GetString( "gamedir", NULL ); + if ( !pGameDir ) + Error( "Mod %s in %s missing 'gamedir'.", kv->GetName(), pSteamGamesFilename ); + + AddMod( pGameDir, pSteamGamesFilename, kv ); + } + } + gamesFile->deleteThis(); + gamesFile = NULL; + } + + + // For backward compatibility, check inside the dedicated server's own directory for mods. + LoadModListInDirectory( "." ); + + // Also, check in SourceMods. + char sourceModsDir[MAX_PATH]; + if ( system()->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\SourceModInstallPath", sourceModsDir, sizeof( sourceModsDir ) ) ) + LoadModListInDirectory( sourceModsDir ); + + m_pGameCombo->ActivateItem(0); +} + + +void CCreateMultiplayerGameServerPage::LoadModListInDirectory( const char *pDirectoryName ) +{ + char searchString[MAX_PATH*2]; + V_strcpy_safe( searchString, pDirectoryName ); + Q_AppendSlash( searchString, sizeof( searchString ) ); + Q_strncat( searchString, "*.*", sizeof( searchString ), COPY_ALL_CHARACTERS ); + + FileFindHandle_t findHandle = NULL; + const char *filename = g_pFullFileSystem->FindFirst( searchString, &findHandle ); + while ( filename ) + { + // add to the mod list + if (filename[0] != '.' && g_pFullFileSystem->FindIsDirectory(findHandle)) + { + char fullFilename[MAX_PATH]; + if ( Q_stricmp( pDirectoryName, "." ) == 0 ) + { + // If we don't do this, then the games in hlds_steamgames.vdf will get listed twice + // since their gamedir is listed as "cstrike" and "hl2mp", not ".\cstrike" or ".\hl2mp". + V_strcpy_safe( fullFilename, filename ); + } + else + { + V_strcpy_safe( fullFilename, pDirectoryName ); + Q_AppendSlash( fullFilename, sizeof( fullFilename ) ); + Q_strncat( fullFilename, filename, sizeof( fullFilename ), COPY_ALL_CHARACTERS ); + } + + LoadPossibleMod( fullFilename ); + } + + filename = g_pFullFileSystem->FindNext(findHandle); + } + g_pFullFileSystem->FindClose(findHandle); +} + + +void CCreateMultiplayerGameServerPage::LoadPossibleMod( const char *pGameDirName ) +{ + char gameInfoFilename[1024]; + Q_snprintf(gameInfoFilename, sizeof(gameInfoFilename) - 1, "%s\\gameinfo.txt", pGameDirName); + if ( !g_pFullFileSystem->FileExists(gameInfoFilename) ) + return; + + // don't want to add single player games to the list + KeyValues *pGameInfo = new KeyValues( "GameInfo" ); + bool loadedFile = pGameInfo->LoadFromFile( g_pFullFileSystem, gameInfoFilename ); + if ( !loadedFile ) + return; + + AddMod( pGameDirName, gameInfoFilename, pGameInfo ); + + pGameInfo->deleteThis(); + pGameInfo = NULL; +} + + +void CCreateMultiplayerGameServerPage::AddMod( const char *pGameDirName, const char *pGameInfoFilename, KeyValues *pGameInfo ) +{ + // Don't re-add something with the same gamedir name (this can happen with games listed in hlds_steamgames.vdf, + // since after the first time a game is run, it'll also have a gameinfo.txt that will be found). + for ( int i=0; i < m_pGameCombo->GetItemCount(); i++ ) + { + if ( !m_pGameCombo->IsItemIDValid(i) ) + continue; + + if ( Q_stricmp( m_pGameCombo->GetItemUserData(i)->GetString("gamedir"), pGameDirName ) == 0 ) + return; + } + + // If this mod supports multiplayer, then we'll add it. + const char *gameType = pGameInfo->GetString( "type", "singleplayer_only" ); + if ( Q_stricmp(gameType, "singleplayer_only") != 0 ) + { + // Validate the gameinfo.txt format.. + KeyValues *pSub = pGameInfo->FindKey( "FileSystem" ); + if ( !pSub ) + Error( "%s missing FileSystem key.", pGameInfoFilename ); + + int iSteamAppId = pSub->GetInt( "SteamAppId", -1 ); + if ( iSteamAppId == -1 ) + Error( "%s missing FileSystem\\SteamAppId key.", pGameInfoFilename ); + +#if !defined( ALLOW_OLD_ENGINE_GAMES ) + // If we're not supporting old games in here and its appid is old, forget about it. + if ( IsEp1EraAppID( iSteamAppId ) ) + return; +#endif + + const char *gameName = pGameInfo->GetString( "game", NULL ); + if ( !gameName ) + Error( "%s missing 'game' key.", pGameInfoFilename ); + + + // add to drop-down combo and mod list + KeyValues *kv = pGameInfo->MakeCopy(); + kv->SetString( "gamedir", pGameDirName ); + + m_pGameCombo->AddItem( gameName, kv ); + + kv->deleteThis(); + kv = NULL; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: loads the list of available maps for the given path into the map list +// Returns: number of maps loaded into the list +//----------------------------------------------------------------------------- +int CCreateMultiplayerGameServerPage::LoadMaps( const char *pszMod ) +{ + // iterate the filesystem getting the list of all the files + // UNDONE: steam wants this done in a special way, need to support that + FileFindHandle_t findHandle = NULL; + char szSearch[256]; + sprintf( szSearch, "%s/maps/*.bsp", pszMod ); + + int iMapsFound = 0; + + const char *pszFilename = g_pFullFileSystem->FindFirst( szSearch, &findHandle ); + + KeyValues *hiddenMaps = NULL; + if ( m_pGameInfo ) + { + hiddenMaps = m_pGameInfo->FindKey( "hidden_maps" ); + } + + while ( pszFilename ) + { + // remove the text 'maps/' and '.bsp' from the file name to get the map name + char mapname[256]; + const char *str = strstr( pszFilename, "maps" ); + if ( str ) + { + V_strcpy_safe( mapname, str + 5 ); // maps + \\ = 5 + } + else + { + V_strcpy_safe( mapname, pszFilename ); + } + + char *ext = strstr( mapname, ".bsp" ); + if ( ext ) + { + *ext = 0; + } + + //!! hack: strip out single player HL maps + // this needs to be specified in a seperate file + if ( ( mapname[0] == 'c' || mapname[0] == 't' ) && mapname[2] == 'a' && mapname[1] >= '0' && mapname[1] <= '5' ) + { + goto nextFile; + } + + // strip out maps that shouldn't be displayed + if ( hiddenMaps ) + { + if ( hiddenMaps->GetInt( mapname, 0 ) ) + { + goto nextFile; + } + } + + iMapsFound++; + + // add to the map list + m_pMapList->AddItem( mapname, NULL ); + + // get the next file + nextFile: + pszFilename = g_pFullFileSystem->FindNext( findHandle ); + } + + g_pFullFileSystem->FindClose( findHandle ); + + return iMapsFound; +} + +//----------------------------------------------------------------------------- +// Purpose: loads the list of available maps into the map list +//----------------------------------------------------------------------------- +void CCreateMultiplayerGameServerPage::LoadMapList() +{ + int iMapsFound = 0; + + // clear the current list (if any) + m_pMapList->DeleteAllItems(); + + Assert( strlen(m_szMod ) > 0); + if ( strlen( m_szMod ) < 1) + { + m_pMapList->SetEnabled( false ); + return; + } + + m_pMapList->SetEnabled( true ); + m_pStartServerButton->SetEnabled( true ); + + if ( CommandLine()->CheckParm( "-steam" ) ) + { + KeyValues *userData = m_pGameCombo->GetActiveItemUserData(); + if ( userData && userData->GetString( "DedicatedServerStartMap", NULL ) ) + { + // set only + m_pMapList->AddItem( userData->GetString( "DedicatedServerStartMap" ), NULL ); + m_pMapList->ActivateItemByRow( 0 ); + m_pMapList->SetEnabled( false ); + return; + } + } + + // Load the maps for the GameDir + iMapsFound += LoadMaps( m_szMod ); + + // If we're using a "fallback_dir" in liblist.gam then include those maps... + const char *pszFallback = GetLiblistFallbackDir( m_szMod ); + if ( pszFallback[0] ) + { + iMapsFound += LoadMaps( pszFallback ); + } + + if ( iMapsFound < 1 ) + { + m_pMapList->SetEnabled( false ); + } + + // set the first item to be selected + m_pMapList->ActivateItemByRow( 0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: returns the name of the map selected from the map combo +//----------------------------------------------------------------------------- +const char *CCreateMultiplayerGameServerPage::GetMapName() +{ + m_pMapList->GetText(m_szMapName, DATA_STR_LENGTH); + return m_szMapName; +} + +//----------------------------------------------------------------------------- +// Purpose: data accessor +//----------------------------------------------------------------------------- +const char *CCreateMultiplayerGameServerPage::GetRconPassword() +{ + return m_szPassword; +} + +//----------------------------------------------------------------------------- +// Purpose: updates "s" with the details of the chosen server to run +//----------------------------------------------------------------------------- +void CCreateMultiplayerGameServerPage::GetServer(serveritem_t &s) +{ + s=m_iServer; + V_strcpy_safe(s.name,m_iServer.name); + V_strcpy_safe(s.rconPassword,m_iServer.rconPassword); + memcpy(s.ip,m_iServer.ip,sizeof(m_iServer.ip)); + memcpy(s.pings,m_iServer.pings,3*sizeof(int)); + V_strcpy_safe(s.gameDir,m_iServer.gameDir); + V_strcpy_safe(s.map,m_iServer.map); + V_strcpy_safe(s.gameDescription,m_iServer.gameDescription); +} + +//----------------------------------------------------------------------------- +// Purpose: Handles changes to combo boxes +//----------------------------------------------------------------------------- +void CCreateMultiplayerGameServerPage::OnTextChanged(Panel *panel) +{ + if (panel == m_pGameCombo) + { + // see if we should update the game name + bool updateHostname = false; + char hostname[256]; + GetControlString("ServerNameEdit", m_szHostName, sizeof(m_szHostName)); + V_sprintf_safe(hostname, "%s dedicated server", m_szGameName); + if (!stricmp(m_szHostName, hostname)) + { + updateHostname = true; + } + + // update the game name + m_pGameCombo->GetText( m_szGameName, sizeof(m_szGameName) ); + + + // Copy the gamedir into m_szMod. + KeyValues *gameData = m_pGameCombo->GetActiveItemUserData(); + if ( !gameData ) + Error( "Missing gameData for active item." ); + + const char *pGameDir = gameData->GetString( "gamedir", NULL ); + if ( !pGameDir ) + Error( "Game %s missing 'gamedir' key.", m_szGameName ); + + V_strcpy_safe( m_szMod, pGameDir ); + + + // re-load the GameInfo KeyValues + if ( m_pGameInfo ) + { + m_pGameInfo->deleteThis(); + } + char liblist[1024]; + Q_snprintf(liblist, sizeof(liblist) - 1, "%s\\gameinfo.txt", m_szMod); + m_pGameInfo = new KeyValues( "GameInfo" ); + m_pGameInfo->LoadFromFile( g_pFullFileSystem, liblist ); + + // redo the hostname with the new game name + if (updateHostname) + { + V_sprintf_safe(hostname, "%s dedicated server", m_szGameName); + SetControlString("ServerNameEdit", hostname); + } + + // reload the list of maps we display + LoadMapList(); + } +} + +#endif // _WIN32 + |