summaryrefslogtreecommitdiff
path: root/dedicated/vgui
diff options
context:
space:
mode:
Diffstat (limited to 'dedicated/vgui')
-rw-r--r--dedicated/vgui/CreateMultiplayerGameServerPage.cpp872
-rw-r--r--dedicated/vgui/CreateMultiplayerGameServerPage.h126
-rw-r--r--dedicated/vgui/MainPanel.cpp274
-rw-r--r--dedicated/vgui/MainPanel.h89
-rw-r--r--dedicated/vgui/vguihelpers.cpp187
-rw-r--r--dedicated/vgui/vguihelpers.h26
-rw-r--r--dedicated/vgui/vguihelpers_linux.cpp39
7 files changed, 1613 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
+
diff --git a/dedicated/vgui/CreateMultiplayerGameServerPage.h b/dedicated/vgui/CreateMultiplayerGameServerPage.h
new file mode 100644
index 0000000..6cabef4
--- /dev/null
+++ b/dedicated/vgui/CreateMultiplayerGameServerPage.h
@@ -0,0 +1,126 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef CREATEMULTIPLAYERGAMESERVERPAGE_H
+#define CREATEMULTIPLAYERGAMESERVERPAGE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <vgui_controls/Frame.h>
+#include <vgui_controls/Button.h>
+#include <vgui_controls/ComboBox.h>
+
+//-----------------------------------------------------------------------------
+// Purpose: Data describing a single server
+//-----------------------------------------------------------------------------
+struct serveritem_t
+{
+ serveritem_t()
+ {
+ pings[0] = 0;
+ pings[1] = 0;
+ pings[2] = 0;
+ }
+
+ unsigned char ip[4];
+ int port;
+ int received;
+ float time;
+ int ping; // current ping time, derived from pings[]
+ int pings[3]; // last 3 ping times
+ bool hadSuccessfulResponse; // server has responded successfully in the past
+ bool doNotRefresh; // server is marked as not responding and should no longer be refreshed
+ char gameDir[32]; // current game directory
+ char map[32]; // current map
+ char gameDescription[64]; // game description
+ char name[64]; // server name
+ int players;
+ int maxPlayers;
+ int botPlayers;
+ bool proxy;
+ bool password;
+ bool secure;
+ bool loadedFromFile; // true if this entry was loaded from file rather than comming from the master
+ unsigned int serverID;
+ int listEntryID;
+ char rconPassword[64]; // the rcon password for this server
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: server options page of the create game server dialog
+//-----------------------------------------------------------------------------
+class CCreateMultiplayerGameServerPage : public vgui::Frame
+{
+ DECLARE_CLASS_SIMPLE( CCreateMultiplayerGameServerPage, vgui::Frame );
+public:
+ CCreateMultiplayerGameServerPage(vgui::Panel *parent, const char *name);
+ ~CCreateMultiplayerGameServerPage();
+
+ // returns currently entered information about the server
+ int GetMaxPlayers() { return m_iMaxPlayers; }
+ const char *GetPassword() { return m_szPassword; }
+ const char *GetHostName() { return m_szHostName; }
+ const char *GetMapName();
+ const char *GetModName() { return m_szMod; }
+ const char *GetGameName() { return m_szGameName; }
+ void LoadMapList();
+ int LoadMaps( const char *pszMod );
+
+ virtual void OnCommand(const char *cmd);
+
+ virtual void OnResetData();
+
+ void GetServer(serveritem_t &s);
+ const char *GetRconPassword();
+
+private:
+ enum { MAX_PLAYERS = 32 };
+ enum { DATA_STR_LENGTH = 64 };
+
+ void LoadConfig();
+ void SaveConfig();
+ void SetConfig(const char *serverName, const char *rconPassword, int maxPlayers, const char *map, const char *mod, int network, int secure, int port);
+
+ bool LaunchOldDedicatedServer( KeyValues *pGameInfo );
+
+ //void OnCommand(const char *text);
+ void LoadMODList();
+ void LoadModListInDirectory( const char *pDirectoryName );
+ void LoadPossibleMod( const char *pGameDirName );
+ void AddMod( const char *pGameDirName, const char *pGameInfoFilename, KeyValues *pGameInfo );
+
+ bool BadRconChars(const char *pass);
+
+ vgui::ComboBox *m_pGameCombo;
+ vgui::ComboBox *m_pMapList;
+ vgui::ComboBox *m_pNumPlayers;
+ vgui::ComboBox *m_pNetworkCombo;
+ vgui::Button *m_pStartServerButton;
+ vgui::Button *m_pCancelButton;
+ vgui::CheckButton *m_pSecureCheck;
+
+ MESSAGE_FUNC_PTR( OnTextChanged, "TextChanged", panel );
+
+ serveritem_t m_iServer;
+
+ char m_szHostName[DATA_STR_LENGTH];
+ char m_szPassword[DATA_STR_LENGTH];
+ char m_szMapName[DATA_STR_LENGTH];
+ char m_szMod[DATA_STR_LENGTH];
+ char m_szGameName[DATA_STR_LENGTH];
+ char m_szExtra[DATA_STR_LENGTH*2];
+ int m_iMaxPlayers;
+ int m_iPort;
+
+ vgui::Panel *m_MainPanel;
+ KeyValues *m_pSavedData; // data to save away
+ KeyValues *m_pGameInfo;
+};
+
+
+#endif // CREATEMULTIPLAYERGAMESERVERPAGE_H
diff --git a/dedicated/vgui/MainPanel.cpp b/dedicated/vgui/MainPanel.cpp
new file mode 100644
index 0000000..f7fc51b
--- /dev/null
+++ b/dedicated/vgui/MainPanel.cpp
@@ -0,0 +1,274 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: $
+//
+//-----------------------------------------------------------------------------
+// $Log: $
+//
+// $NoKeywords: $
+//=============================================================================//
+#ifdef _WIN32
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <windows.h>
+// base vgui interfaces
+#include <vgui/vgui.h>
+#include <vgui_controls/Panel.h>
+#include <vgui/IVGui.h>
+#include <vgui/ISurface.h>
+#include <vgui/Cursor.h>
+#include <vgui_controls/ProgressBox.h>
+
+#include "filesystem.h"
+#include "IAdminServer.h"
+
+#include "MainPanel.h"
+#include <imanageserver.h>
+#include "ivguimodule.h"
+#include <vgui/IVGui.h>
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+using namespace vgui;
+
+static CMainPanel *s_InternetDlg = NULL;
+CSysModule *g_hAdminServerModule = NULL;
+extern IAdminServer *g_pAdminServer;
+char *gpszCvars = NULL;
+
+
+void Sys_Sleep_Old( int msec );
+
+extern BOOL gbAppHasBeenTerminated; // used to signal the server thread
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CMainPanel::CMainPanel( ) : Panel(NULL, "CMainPanel")
+{
+ SetPaintBackgroundEnabled( false );
+ SetFgColor( Color( 0,0,0,0 ) );
+ m_bStarting = false;
+ m_flPreviousSteamProgress = 0.0f;
+ m_pGameServer= NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CMainPanel::~CMainPanel()
+{
+ if (gpszCvars)
+ {
+ free(gpszCvars);
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Called once to set up
+//-----------------------------------------------------------------------------
+void CMainPanel::Initialize( )
+{
+ s_InternetDlg = this;
+ m_pGameServer = NULL;
+
+ m_bStarted = false;
+ m_bIsInConfig = true;
+ m_bClosing = false;
+ m_pProgressBox = NULL;
+ m_hShutdown = NULL;
+
+ MoveToFront();
+
+ m_pConfigPage = new CCreateMultiplayerGameServerPage(this, "Config");
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMainPanel::Open( void )
+{
+ m_pConfigPage->SetVisible(true);
+ m_pConfigPage->MoveToFront();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMainPanel::OnClose()
+{
+ DoStop();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns a pointer to a static instance of this dialog
+//-----------------------------------------------------------------------------
+CMainPanel *CMainPanel::GetInstance()
+{
+ return s_InternetDlg;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Changes to the console page and starts up the actual server
+//-----------------------------------------------------------------------------
+void CMainPanel::StartServer(const char *cvars)
+{
+ surface()->SetCursor(dc_hourglass);
+ m_pConfigPage->GetServer(s1);
+
+ // hide the config page and close it
+ m_pConfigPage->SetVisible(false);
+ m_pConfigPage->Close();
+
+ gpszCvars = strdup(cvars);
+
+ // show the basic progress box immediately
+ m_pProgressBox = new ProgressBox("#Start_Server_Loading_Title", "#Server_UpdatingSteamResources", "Starting dedicated server...");
+ m_pProgressBox->SetCancelButtonVisible(true);
+ m_pProgressBox->ShowWindow();
+
+ // make sure we have all the steam content for this mod
+ char reslist[_MAX_PATH];
+ _snprintf(reslist, sizeof(reslist), "reslists/%s/preload.lst", m_pConfigPage->GetGameName());
+ m_hResourceWaitHandle = g_pFullFileSystem->WaitForResources(reslist);
+ if (!m_hResourceWaitHandle)
+ {
+ Assert( 0 );
+ }
+
+ m_pProgressBox->SetCancelButtonEnabled(false);
+
+ m_hShutdown = CreateEvent( NULL, TRUE, FALSE, NULL );
+ ivgui()->AddTickSignal(GetVPanel());
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: lets us delay the loading of the management screen until the server has started
+//-----------------------------------------------------------------------------
+void CMainPanel::OnTick()
+{
+ if (m_hResourceWaitHandle)
+ {
+ // see if we've been cancelled
+ if (!m_pProgressBox.Get() || !m_pProgressBox->IsVisible())
+ {
+ // cancel out
+ g_pFullFileSystem->CancelWaitForResources(m_hResourceWaitHandle);
+ m_hResourceWaitHandle = NULL;
+ DoStop();
+ return;
+ }
+
+ // update resource waiting
+ bool complete;
+ float progress;
+ if (g_pFullFileSystem->GetWaitForResourcesProgress(m_hResourceWaitHandle, &progress, &complete))
+ {
+ vgui::ivgui()->DPrintf2( "progress %.2f %s\n", progress, complete ? "not complete" : "complete" );
+
+ // don't set the progress if we've jumped straight from 0 to 100% complete
+ if (!(progress == 1.0f && m_flPreviousSteamProgress == 0.0f))
+ {
+ m_pProgressBox->SetProgress(progress);
+ m_flPreviousSteamProgress = progress;
+ }
+ }
+
+ // This is here because without it, the dedicated server will consume a lot of CPU and it will slow Steam down
+ // so much that it'll download at 64k instead of 6M.
+ Sleep( 200 );
+
+ // see if we're done
+ if (complete)
+ {
+ m_hResourceWaitHandle = NULL;
+ m_bStarting = true;
+ m_bIsInConfig = false;
+ // at this stage in the process the user can no longer cancel
+ m_pProgressBox->SetCancelButtonEnabled(false);
+ }
+ }
+
+ if (m_bStarting) // if we are actively launching the app
+ {
+ static int count = 0;
+ if (WAIT_OBJECT_0 == WaitForSingleObject(m_hShutdown, 10) || count > 5000)
+ {
+ if (!m_bStarted)
+ {
+ serveritem_t server;
+ m_pConfigPage->GetServer(server);
+ ManageServerUIHandle_t managePage = g_pAdminServer->OpenManageServerDialog(server.name, server.gameDir);
+ m_pGameServer = g_pAdminServer->GetManageServerInterface(managePage);
+ m_bStarted = true;
+
+ if (m_pProgressBox)
+ {
+ m_pProgressBox->Close();
+ m_pProgressBox = NULL;
+ }
+ }
+ else // must be stopping the server
+ {
+ DoStop();
+ }
+
+ surface()->SetCursor(dc_user);
+ m_bStarting = false;
+ ResetEvent(m_hShutdown);
+ }
+ else
+ {
+ count++;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: stops VGUI and kills any progress dialog we may have been displaying
+//-----------------------------------------------------------------------------
+void CMainPanel::DoStop()
+{
+ surface()->SetCursor(dc_user);
+
+ m_bStarted = false;
+ m_bClosing = true;
+
+ if (m_pProgressBox)
+ {
+ m_pProgressBox->Close();
+ m_pProgressBox = NULL;
+ }
+
+ ivgui()->Stop();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Pushes text into the console
+//-----------------------------------------------------------------------------
+void CMainPanel::AddConsoleText(const char *msg)
+{
+ if (m_pGameServer)
+ {
+ m_pGameServer->AddToConsole(msg);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Message map
+//-----------------------------------------------------------------------------
+MessageMapItem_t CMainPanel::m_MessageMap[] =
+{
+ MAP_MESSAGE( CMainPanel, "Quit", OnClose ),
+};
+
+IMPLEMENT_PANELMAP(CMainPanel, BaseClass);
+
+#endif // _WIN32
diff --git a/dedicated/vgui/MainPanel.h b/dedicated/vgui/MainPanel.h
new file mode 100644
index 0000000..04f558e
--- /dev/null
+++ b/dedicated/vgui/MainPanel.h
@@ -0,0 +1,89 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Workfile: $
+// $Date: $
+// $NoKeywords: $
+//===========================================================================//
+#ifndef CMAINPANEL_H
+#define CMAINPANEL_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <vgui_controls/Frame.h>
+#include <vgui_controls/Panel.h>
+#include <vgui_controls/ListPanel.h>
+#include <vgui_controls/PHandle.h>
+#include "utlvector.h"
+
+//#include <GamePanelInfo.h>
+
+#include "imanageserver.h"
+//#include "gameserver.h"
+#include "CreateMultiplayerGameServerPage.h"
+
+class IAdminServer;
+
+//-----------------------------------------------------------------------------
+// Purpose: Root panel for dedicated server GUI
+//-----------------------------------------------------------------------------
+class CMainPanel : public vgui::Panel
+{
+public:
+ // Construction/destruction
+ CMainPanel( );
+ virtual ~CMainPanel();
+
+ virtual void Initialize( );
+
+ // displays the dialog, moves it into focus, updates if it has to
+ virtual void Open( void );
+
+ // returns a pointer to a static instance of this dialog
+ // valid for use only in sort functions
+ static CMainPanel *GetInstance();
+ virtual void StartServer(const char *cvars);
+
+ void ActivateBuildMode();
+
+ void *GetShutdownHandle() { return m_hShutdown; }
+
+ void AddConsoleText(const char *msg);
+
+ bool Stopping() { return m_bClosing; }
+
+ bool IsInConfig() { return m_bIsInConfig; }
+
+private:
+
+ // called when dialog is shut down
+ virtual void OnClose();
+ virtual void OnTick();
+ void DoStop();
+
+ // GUI elements
+ IManageServer *m_pGameServer;
+
+ // the popup menu
+ vgui::DHANDLE<vgui::ProgressBox> m_pProgressBox;
+ CCreateMultiplayerGameServerPage *m_pConfigPage;
+
+ // Event that lets the thread tell the main window it shutdown
+ void *m_hShutdown;
+
+ bool m_bStarting; // whether the server is currently starting
+ bool m_bStarted; // whether the server has been started or not
+ bool m_bClosing; // whether we are shutting down
+ bool m_bIsInConfig;
+ serveritem_t s1;
+ int m_hResourceWaitHandle;
+ float m_flPreviousSteamProgress;
+
+ typedef vgui::Panel BaseClass;
+ DECLARE_PANELMAP();
+
+};
+
+#endif // CMAINPANEL_H \ No newline at end of file
diff --git a/dedicated/vgui/vguihelpers.cpp b/dedicated/vgui/vguihelpers.cpp
new file mode 100644
index 0000000..11cf33e
--- /dev/null
+++ b/dedicated/vgui/vguihelpers.cpp
@@ -0,0 +1,187 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+#ifdef _WIN32
+#include <windows.h>
+#include <direct.h>
+
+// includes for the VGUI version
+#include <vgui_controls/Panel.h>
+#include <vgui_controls/Controls.h>
+#include <vgui/ISystem.h>
+#include <vgui/IVGui.h>
+#include <vgui/IPanel.h>
+#include "filesystem.h"
+#include <vgui/ILocalize.h>
+#include <vgui/IScheme.h>
+#include <vgui/ISurface.h>
+#include <IVGuiModule.h>
+
+#include "vgui/MainPanel.h"
+#include "IAdminServer.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+static CMainPanel *g_pMainPanel = NULL; // the main panel to show
+static CSysModule *g_hAdminServerModule;
+IAdminServer *g_pAdminServer = NULL;
+static IVGuiModule *g_pAdminVGuiModule = NULL;
+
+void* DedicatedFactory(const char *pName, int *pReturnCode);
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Starts up the VGUI system and loads the base panel
+//-----------------------------------------------------------------------------
+int StartVGUI( CreateInterfaceFn dedicatedFactory )
+{
+ // the "base dir" so we can scan mod name
+ g_pFullFileSystem->AddSearchPath(".", "MAIN");
+ // the main platform dir
+ g_pFullFileSystem->AddSearchPath( "platform", "PLATFORM", PATH_ADD_TO_HEAD);
+
+ vgui::ivgui()->SetSleep(false);
+
+ // find our configuration directory
+ char szConfigDir[512];
+ const char *steamPath = getenv("SteamInstallPath");
+ if (steamPath)
+ {
+ // put the config dir directly under steam
+ Q_snprintf(szConfigDir, sizeof(szConfigDir), "%s/config", steamPath);
+ }
+ else
+ {
+ // we're not running steam, so just put the config dir under the platform
+ Q_strncpy( szConfigDir, "platform/config", sizeof(szConfigDir));
+ }
+ g_pFullFileSystem->CreateDirHierarchy("config", "PLATFORM");
+ g_pFullFileSystem->AddSearchPath(szConfigDir, "CONFIG", PATH_ADD_TO_HEAD);
+
+ // initialize the user configuration file
+ vgui::system()->SetUserConfigFile("DedicatedServerDialogConfig.vdf", "CONFIG");
+
+ // Init the surface
+ g_pMainPanel = new CMainPanel( );
+ g_pMainPanel->SetVisible(true);
+
+ vgui::surface()->SetEmbeddedPanel(g_pMainPanel->GetVPanel());
+
+ // load the scheme
+ vgui::scheme()->LoadSchemeFromFile("Resource/SourceScheme.res", NULL);
+
+ // localization
+ g_pVGuiLocalize->AddFile( "Resource/platform_%language%.txt" );
+ g_pVGuiLocalize->AddFile( "Resource/vgui_%language%.txt" );
+ g_pVGuiLocalize->AddFile( "Admin/server_%language%.txt" );
+
+ // Start vgui
+ vgui::ivgui()->Start();
+
+ // load the module
+ g_pFullFileSystem->GetLocalCopy("bin/AdminServer.dll");
+ g_hAdminServerModule = g_pFullFileSystem->LoadModule("AdminServer");
+ Assert(g_hAdminServerModule != NULL);
+ CreateInterfaceFn adminFactory = NULL;
+
+ if (!g_hAdminServerModule)
+ {
+ vgui::ivgui()->DPrintf2("Admin Error: module version (Admin/AdminServer.dll, %s) invalid, not loading\n", IMANAGESERVER_INTERFACE_VERSION );
+ }
+ else
+ {
+ // make sure we get the right version
+ adminFactory = Sys_GetFactory(g_hAdminServerModule);
+ g_pAdminServer = (IAdminServer *)adminFactory(ADMINSERVER_INTERFACE_VERSION, NULL);
+ g_pAdminVGuiModule = (IVGuiModule *)adminFactory("VGuiModuleAdminServer001", NULL);
+ Assert(g_pAdminServer != NULL);
+ Assert(g_pAdminVGuiModule != NULL);
+ if (!g_pAdminServer || !g_pAdminVGuiModule)
+ {
+ vgui::ivgui()->DPrintf2("Admin Error: module version (Admin/AdminServer.dll, %s) invalid, not loading\n", IMANAGESERVER_INTERFACE_VERSION );
+ }
+ }
+
+ // finish initializing admin module
+ g_pAdminVGuiModule->Initialize( &dedicatedFactory, 1 );
+ g_pAdminVGuiModule->PostInitialize(&adminFactory, 1);
+ g_pAdminVGuiModule->SetParent( g_pMainPanel->GetVPanel() );
+
+ // finish setting up main panel
+ g_pMainPanel->Initialize( );
+ g_pMainPanel->Open();
+
+ return 0;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Shuts down the VGUI system
+//-----------------------------------------------------------------------------
+void StopVGUI()
+{
+ SetEvent(g_pMainPanel->GetShutdownHandle());
+
+ delete g_pMainPanel;
+ g_pMainPanel = NULL;
+
+ if (g_hAdminServerModule)
+ {
+ g_pAdminVGuiModule->Shutdown( );
+ Sys_UnloadModule(g_hAdminServerModule);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Run a single VGUI frame
+//-----------------------------------------------------------------------------
+void RunVGUIFrame()
+{
+ vgui::ivgui()->RunFrame();
+}
+
+
+bool VGUIIsStopping()
+{
+ return g_pMainPanel->Stopping();
+}
+
+
+bool VGUIIsRunning()
+{
+ return vgui::ivgui()->IsRunning();
+}
+
+bool VGUIIsInConfig()
+{
+ return g_pMainPanel->IsInConfig();
+}
+
+void VGUIFinishedConfig()
+{
+ Assert( g_pMainPanel );
+ if(g_pMainPanel) // engine is loaded, pass the message on
+ {
+ SetEvent(g_pMainPanel->GetShutdownHandle());
+ }
+}
+
+void VGUIPrintf( const char *msg )
+{
+ if ( !g_pMainPanel || VGUIIsInConfig() || VGUIIsStopping() )
+ {
+ OutputDebugStringA( msg );
+ }
+ else if ( g_pMainPanel )
+ {
+ g_pMainPanel->AddConsoleText( msg );
+ }
+}
+
+#endif // _WIN32
+
diff --git a/dedicated/vgui/vguihelpers.h b/dedicated/vgui/vguihelpers.h
new file mode 100644
index 0000000..e29203e
--- /dev/null
+++ b/dedicated/vgui/vguihelpers.h
@@ -0,0 +1,26 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef VGUIHELPERS_H
+#define VGUIHELPERS_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier1/interface.h"
+
+int StartVGUI( CreateInterfaceFn dedicatedFactory );
+void StopVGUI();
+void RunVGUIFrame();
+bool VGUIIsRunning();
+bool VGUIIsStopping();
+bool VGUIIsInConfig();
+void VGUIFinishedConfig();
+void VGUIPrintf( const char *msg );
+
+#endif // VGUIHELPERS_H
+
diff --git a/dedicated/vgui/vguihelpers_linux.cpp b/dedicated/vgui/vguihelpers_linux.cpp
new file mode 100644
index 0000000..4b8f474
--- /dev/null
+++ b/dedicated/vgui/vguihelpers_linux.cpp
@@ -0,0 +1,39 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+#include "interface.h"
+
+bool InitializeVGui(CreateInterfaceFn *factorylist, int factorycount)
+{
+}
+
+int StartVGUI()
+{
+}
+
+void StopVGUI()
+{
+}
+
+void RunVGUIFrame()
+{
+}
+
+bool VGUIIsRunning()
+{
+}
+
+bool VGUIIsStopping()
+{
+}
+
+bool VGUIIsInConfig()
+{
+}
+
+void VGUIFinishedConfig()
+{
+}
+