685 lines
18 KiB
C++
685 lines
18 KiB
C++
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//===========================================================================//
|
||
|
|
||
|
#include <vgui/ILocalize.h>
|
||
|
#include <vgui/IScheme.h>
|
||
|
#include <vgui/ISurface.h>
|
||
|
#include <vgui/IVGui.h>
|
||
|
#include <vgui/IInput.h>
|
||
|
#include <vgui/isystem.h>
|
||
|
|
||
|
#include <vgui_controls/MessageBox.h>
|
||
|
#include <vgui_controls/Controls.h>
|
||
|
#include <vgui_controls/Panel.h>
|
||
|
|
||
|
#include "SDKLauncherDialog.h"
|
||
|
#include "appframework/tier3app.h"
|
||
|
#include "tier0/icommandline.h"
|
||
|
#include "filesystem_tools.h"
|
||
|
#include "sdklauncher_main.h"
|
||
|
#include "configs.h"
|
||
|
#include "min_footprint_files.h"
|
||
|
#include "CreateModWizard.h"
|
||
|
#include "inputsystem/iinputsystem.h"
|
||
|
|
||
|
#include <io.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
// Since windows redefines MessageBox.
|
||
|
typedef vgui::MessageBox vguiMessageBox;
|
||
|
|
||
|
#include <winsock2.h>
|
||
|
#include "steam/steam_api.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include <tier0/memdbgon.h>
|
||
|
|
||
|
HANDLE g_dwChangeHandle = NULL;
|
||
|
|
||
|
#define DEFAULTGAMEDIR_KEYNAME "DefaultGameDir"
|
||
|
|
||
|
// Dummy window
|
||
|
static WNDCLASS staticWndclass = { NULL };
|
||
|
static ATOM staticWndclassAtom = 0;
|
||
|
static HWND staticHwnd = 0;
|
||
|
CSteamAPIContext g_SteamAPIContext;
|
||
|
CSteamAPIContext *steamapicontext = &g_SteamAPIContext;
|
||
|
|
||
|
// This is the base engine + mod-specific game dir (e.g. "c:\tf2\mytfmod\")
|
||
|
char gamedir[1024];
|
||
|
extern char g_engineDir[50];
|
||
|
CSDKLauncherDialog *g_pMainFrame = 0;
|
||
|
|
||
|
|
||
|
bool g_bAutoHL2Mod = false;
|
||
|
bool g_bModWizard_CmdLineFields = false;
|
||
|
char g_ModWizard_CmdLine_ModDir[MAX_PATH];
|
||
|
char g_ModWizard_CmdLine_ModName[256];
|
||
|
bool g_bAppQuit = false;
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Message handler for dummy app
|
||
|
//-----------------------------------------------------------------------------
|
||
|
static LRESULT CALLBACK messageProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
||
|
{
|
||
|
// See if we've gotten a VPROJECT change
|
||
|
if ( msg == WM_SETTINGCHANGE )
|
||
|
{
|
||
|
if ( g_pMainFrame != NULL )
|
||
|
{
|
||
|
char szCurrentGame[MAX_PATH];
|
||
|
|
||
|
// Get VCONFIG from the registry
|
||
|
GetVConfigRegistrySetting( GAMEDIR_TOKEN, szCurrentGame, sizeof( szCurrentGame ) );
|
||
|
|
||
|
g_pMainFrame->SetCurrentGame( szCurrentGame );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ::DefWindowProc(hwnd,msg,wparam,lparam);
|
||
|
}
|
||
|
|
||
|
const char* GetLastWindowsErrorString()
|
||
|
{
|
||
|
static char err[2048];
|
||
|
|
||
|
LPVOID lpMsgBuf;
|
||
|
FormatMessage(
|
||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||
|
NULL,
|
||
|
GetLastError(),
|
||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||
|
(LPTSTR) &lpMsgBuf,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
strncpy( err, (char*)lpMsgBuf, sizeof( err ) );
|
||
|
LocalFree( lpMsgBuf );
|
||
|
|
||
|
err[ sizeof( err ) - 1 ] = 0;
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Creates a dummy window that handles windows messages
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CreateMessageWindow( void )
|
||
|
{
|
||
|
// Make and register a very simple window class
|
||
|
memset(&staticWndclass, 0, sizeof(staticWndclass));
|
||
|
staticWndclass.style = 0;
|
||
|
staticWndclass.lpfnWndProc = messageProc;
|
||
|
staticWndclass.hInstance = GetModuleHandle(NULL);
|
||
|
staticWndclass.lpszClassName = "SDKLauncher_Window";
|
||
|
staticWndclassAtom = ::RegisterClass( &staticWndclass );
|
||
|
|
||
|
// Create an empty window just for message handling
|
||
|
staticHwnd = CreateWindowEx(0, "SDKLauncher_Window", "Hidden Window", 0, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL);
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose:
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void ShutdownMessageWindow( void )
|
||
|
{
|
||
|
// Kill our windows instance
|
||
|
::DestroyWindow( staticHwnd );
|
||
|
::UnregisterClass("VConfig_Window", ::GetModuleHandle(NULL));
|
||
|
}
|
||
|
|
||
|
SpewRetval_t SDKLauncherSpewOutputFunc( SpewType_t spewType, char const *pMsg )
|
||
|
{
|
||
|
#ifdef _WIN32
|
||
|
OutputDebugString( pMsg );
|
||
|
#endif
|
||
|
|
||
|
if (spewType == SPEW_ERROR)
|
||
|
{
|
||
|
// In Windows vgui mode, make a message box or they won't ever see the error.
|
||
|
#ifdef _WIN32
|
||
|
MessageBox( NULL, pMsg, "Error", MB_OK | MB_TASKMODAL );
|
||
|
TerminateProcess( GetCurrentProcess(), 1 );
|
||
|
#elif _LINUX
|
||
|
_exit(1);
|
||
|
#else
|
||
|
#error "Implement me"
|
||
|
#endif
|
||
|
|
||
|
return SPEW_ABORT;
|
||
|
}
|
||
|
if (spewType == SPEW_ASSERT)
|
||
|
{
|
||
|
if ( CommandLine()->FindParm( "-noassert" ) == 0 )
|
||
|
return SPEW_DEBUGGER;
|
||
|
else
|
||
|
return SPEW_CONTINUE;
|
||
|
}
|
||
|
return SPEW_CONTINUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char* GetSDKLauncherBinDirectory()
|
||
|
{
|
||
|
static char path[MAX_PATH] = {0};
|
||
|
if ( path[0] == 0 )
|
||
|
{
|
||
|
GetModuleFileName( (HMODULE)GetAppInstance(), path, sizeof( path ) );
|
||
|
Q_StripLastDir( path, sizeof( path ) ); // Get rid of the filename.
|
||
|
Q_StripTrailingSlash( path );
|
||
|
}
|
||
|
return path;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char* GetSDKToolsBinDirectory( )
|
||
|
{
|
||
|
static char path[MAX_PATH] = {0};
|
||
|
if ( path[0] == 0 )
|
||
|
{
|
||
|
GetModuleFileName( (HMODULE)GetAppInstance(), path, sizeof( path ) );
|
||
|
Q_StripLastDir( path, sizeof( path ) ); // Get rid of the filename.
|
||
|
V_strncat( path, g_engineDir, sizeof( path ) );
|
||
|
V_strncat( path, "\\bin", sizeof( path ) );
|
||
|
}
|
||
|
return path;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char* GetSDKLauncherBaseDirectory()
|
||
|
{
|
||
|
static char basedir[512] = {0};
|
||
|
if ( basedir[0] == 0 )
|
||
|
{
|
||
|
Q_strncpy( basedir, GetSDKLauncherBinDirectory(), sizeof( basedir ) );
|
||
|
Q_StripLastDir( basedir, sizeof( basedir ) ); // Get rid of the bin directory.
|
||
|
Q_StripTrailingSlash( basedir );
|
||
|
}
|
||
|
return basedir;
|
||
|
}
|
||
|
|
||
|
|
||
|
void SubstituteBaseDir( const char *pIn, char *pOut, int outLen )
|
||
|
{
|
||
|
Q_StrSubst( pIn, "%basedir%", GetSDKLauncherBaseDirectory(), pOut, outLen );
|
||
|
}
|
||
|
|
||
|
|
||
|
CUtlVector<char> g_FileData;
|
||
|
CUtlVector<char> g_ReplacementData[2];
|
||
|
|
||
|
CUtlVector<char>* GetFileStringWithReplacements(
|
||
|
const char *pInputFilename,
|
||
|
const char **ppReplacements, int nReplacements,
|
||
|
int &dataWriteLen )
|
||
|
{
|
||
|
Assert( nReplacements % 2 == 0 );
|
||
|
|
||
|
// Read in the file data.
|
||
|
FileHandle_t hFile = g_pFullFileSystem->Open( pInputFilename, "rb" );
|
||
|
if ( !hFile )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
g_FileData.SetSize( g_pFullFileSystem->Size( hFile ) );
|
||
|
g_pFullFileSystem->Read( g_FileData.Base(), g_FileData.Count(), hFile );
|
||
|
g_pFullFileSystem->Close( hFile );
|
||
|
|
||
|
CUtlVector<char> *pCurData = &g_FileData;
|
||
|
dataWriteLen = g_FileData.Count();
|
||
|
if ( nReplacements )
|
||
|
{
|
||
|
// Null-terminate it.
|
||
|
g_FileData.AddToTail( 0 );
|
||
|
|
||
|
// Apply all the string substitutions.
|
||
|
int iCurCount = g_FileData.Count() * 2;
|
||
|
g_ReplacementData[0].EnsureCount( iCurCount );
|
||
|
g_ReplacementData[1].EnsureCount( iCurCount );
|
||
|
for ( int i=0; i < nReplacements/2; i++ )
|
||
|
{
|
||
|
for ( int iTestCount=0; iTestCount < 64; iTestCount++ )
|
||
|
{
|
||
|
if ( Q_StrSubst( pCurData->Base(), ppReplacements[i*2], ppReplacements[i*2+1], g_ReplacementData[i&1].Base(), g_ReplacementData[i&1].Count() ) )
|
||
|
break;
|
||
|
|
||
|
// Ok, we would overflow the string.. add more space to do the string substitution into.
|
||
|
iCurCount += 2048;
|
||
|
g_ReplacementData[0].EnsureCount( iCurCount );
|
||
|
g_ReplacementData[1].EnsureCount( iCurCount );
|
||
|
}
|
||
|
pCurData = &g_ReplacementData[i&1];
|
||
|
dataWriteLen = strlen( pCurData->Base() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return pCurData;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool CopyWithReplacements(
|
||
|
const char *pInputFilename,
|
||
|
const char **ppReplacements, int nReplacements,
|
||
|
const char *pOutputFilenameFormat, ... )
|
||
|
{
|
||
|
int dataWriteLen;
|
||
|
CUtlVector<char> *pCurData = GetFileStringWithReplacements( pInputFilename, ppReplacements, nReplacements, dataWriteLen );
|
||
|
if ( !pCurData )
|
||
|
{
|
||
|
char msg[512];
|
||
|
Q_snprintf( msg, sizeof( msg ), "Can't open %s for reading.", pInputFilename );
|
||
|
::MessageBox( NULL, msg, "Error", MB_OK );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Get the output filename.
|
||
|
char outFilename[MAX_PATH];
|
||
|
va_list marker;
|
||
|
va_start( marker, pOutputFilenameFormat );
|
||
|
Q_vsnprintf( outFilename, sizeof( outFilename ), pOutputFilenameFormat, marker );
|
||
|
va_end( marker );
|
||
|
|
||
|
// Write it out. I'd like to use IFileSystem, but Steam lowercases all filenames, which screws case-sensitive linux
|
||
|
// (since the linux makefiles are tuned to the casing in Perforce).
|
||
|
FILE *hFile = fopen( outFilename, "wb" );
|
||
|
if ( !hFile )
|
||
|
{
|
||
|
char msg[512];
|
||
|
Q_snprintf( msg, sizeof( msg ), "Can't open %s for writing.", outFilename );
|
||
|
::MessageBox( NULL, msg, "Error", MB_OK );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
fwrite( pCurData->Base(), 1, dataWriteLen, hFile );
|
||
|
fclose( hFile );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
int InitializeVGui()
|
||
|
{
|
||
|
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
|
||
|
vgui::Panel *pPanel = new vgui::Panel(NULL, "TopPanel");
|
||
|
pPanel->SetVisible(true);
|
||
|
|
||
|
vgui::surface()->SetEmbeddedPanel(pPanel->GetVPanel());
|
||
|
|
||
|
// load the scheme
|
||
|
vgui::scheme()->LoadSchemeFromFile("Resource/sdklauncher_scheme.res", NULL);
|
||
|
|
||
|
// localization
|
||
|
g_pVGuiLocalize->AddFile( "resource/platform_english.txt" );
|
||
|
g_pVGuiLocalize->AddFile( "vgui/resource/vgui_english.txt" );
|
||
|
g_pVGuiLocalize->AddFile( "sdklauncher_english.txt" );
|
||
|
|
||
|
// Start vgui
|
||
|
vgui::ivgui()->Start();
|
||
|
|
||
|
// add our main window
|
||
|
g_pMainFrame = new CSDKLauncherDialog(pPanel, "SDKLauncherDialog");
|
||
|
|
||
|
// show main window
|
||
|
g_pMainFrame->MoveToCenterOfScreen();
|
||
|
g_pMainFrame->Activate();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void ShutdownVGui()
|
||
|
{
|
||
|
delete g_pMainFrame;
|
||
|
}
|
||
|
|
||
|
|
||
|
KeyValues* LoadGameDirsFile()
|
||
|
{
|
||
|
char filename[MAX_PATH];
|
||
|
Q_snprintf( filename, sizeof( filename ), "%ssdklauncher_gamedirs.txt", gamedir );
|
||
|
|
||
|
KeyValues *dataFile = new KeyValues("gamedirs");
|
||
|
dataFile->UsesEscapeSequences( true );
|
||
|
dataFile->LoadFromFile( g_pFullFileSystem, filename, NULL );
|
||
|
return dataFile;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool SaveGameDirsFile( KeyValues *pFile )
|
||
|
{
|
||
|
char filename[MAX_PATH];
|
||
|
Q_snprintf( filename, sizeof( filename ), "%ssdklauncher_gamedirs.txt", gamedir );
|
||
|
return pFile->SaveToFile( g_pFullFileSystem, filename );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
class CModalPreserveMessageBox : public vguiMessageBox
|
||
|
{
|
||
|
public:
|
||
|
CModalPreserveMessageBox(const char *title, const char *text, vgui::Panel *parent)
|
||
|
: vguiMessageBox( title, text, parent )
|
||
|
{
|
||
|
m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface();
|
||
|
}
|
||
|
|
||
|
~CModalPreserveMessageBox()
|
||
|
{
|
||
|
vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel );
|
||
|
}
|
||
|
|
||
|
|
||
|
public:
|
||
|
vgui::VPANEL m_PrevAppFocusPanel;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
void VGUIMessageBox( vgui::Panel *pParent, const char *pTitle, const char *pMsg, ... )
|
||
|
{
|
||
|
char msg[4096];
|
||
|
va_list marker;
|
||
|
va_start( marker, pMsg );
|
||
|
Q_vsnprintf( msg, sizeof( msg ), pMsg, marker );
|
||
|
va_end( marker );
|
||
|
|
||
|
vguiMessageBox *dlg = new CModalPreserveMessageBox( pTitle, msg, pParent );
|
||
|
dlg->DoModal();
|
||
|
dlg->RequestFocus();
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Startup our file watch
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void UpdateConfigsStatus_Init( void )
|
||
|
{
|
||
|
// Watch our config file for changes
|
||
|
if ( g_dwChangeHandle == NULL)
|
||
|
{
|
||
|
char szConfigDir[MAX_PATH];
|
||
|
Q_strncpy( szConfigDir, GetSDKLauncherBinDirectory(), sizeof( szConfigDir ) );
|
||
|
Q_strncat ( szConfigDir, "\\", MAX_PATH );
|
||
|
Q_strncat ( szConfigDir, g_engineDir, MAX_PATH );
|
||
|
Q_strncat ( szConfigDir, "\\bin", MAX_PATH );
|
||
|
|
||
|
g_dwChangeHandle = FindFirstChangeNotification(
|
||
|
szConfigDir, // directory to watch
|
||
|
false, // watch the subtree
|
||
|
(FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_LAST_WRITE|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_ATTRIBUTES)); // watch file and dir name changes
|
||
|
|
||
|
if ( g_dwChangeHandle == INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
// FIXME: Unable to watch the file
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Update our status
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void UpdateConfigsStatus( void )
|
||
|
{
|
||
|
// Wait for notification.
|
||
|
DWORD dwWaitStatus = WaitForSingleObject( g_dwChangeHandle, 0 );
|
||
|
|
||
|
if ( dwWaitStatus == WAIT_OBJECT_0 )
|
||
|
{
|
||
|
// Something in the watched folder changed!
|
||
|
if ( g_pMainFrame != NULL )
|
||
|
{
|
||
|
g_pMainFrame->RefreshConfigs();
|
||
|
}
|
||
|
|
||
|
// Start the next update
|
||
|
if ( FindNextChangeNotification( g_dwChangeHandle ) == FALSE )
|
||
|
{
|
||
|
// This means that something unknown happened to our search handle!
|
||
|
Assert( 0 );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Stop watching the file
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void UpdateConfigsStatus_Shutdown( void )
|
||
|
{
|
||
|
FindCloseChangeNotification( g_dwChangeHandle );
|
||
|
}
|
||
|
|
||
|
void QuickLaunchCommandLine( char *pCommandLine )
|
||
|
{
|
||
|
STARTUPINFO si;
|
||
|
memset( &si, 0, sizeof( si ) );
|
||
|
si.cb = sizeof( si );
|
||
|
|
||
|
PROCESS_INFORMATION pi;
|
||
|
memset( &pi, 0, sizeof( pi ) );
|
||
|
|
||
|
DWORD dwFlags = 0;
|
||
|
|
||
|
if ( !CreateProcess(
|
||
|
0,
|
||
|
pCommandLine,
|
||
|
NULL, // security
|
||
|
NULL,
|
||
|
TRUE,
|
||
|
dwFlags, // flags
|
||
|
NULL, // environment
|
||
|
GetSDKLauncherBaseDirectory(), // current directory
|
||
|
&si,
|
||
|
&pi ) )
|
||
|
{
|
||
|
::MessageBoxA( NULL, GetLastWindowsErrorString(), "Error", MB_OK | MB_ICONINFORMATION | MB_APPLMODAL );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool RunQuickLaunch()
|
||
|
{
|
||
|
char cmdLine[512];
|
||
|
|
||
|
if ( CommandLine()->FindParm( "-runhammer" ) )
|
||
|
{
|
||
|
Q_snprintf( cmdLine, sizeof( cmdLine ), "\"%s\\%s\\bin\\hammer.exe\"", GetSDKLauncherBinDirectory(), g_engineDir );
|
||
|
QuickLaunchCommandLine( cmdLine );
|
||
|
return true;
|
||
|
}
|
||
|
else if ( CommandLine()->FindParm( "-runmodelviewer" ) )
|
||
|
{
|
||
|
Q_snprintf( cmdLine, sizeof( cmdLine ), "\"%s\\%s\\bin\\hlmv.exe\"", GetSDKLauncherBinDirectory(), g_engineDir );
|
||
|
QuickLaunchCommandLine( cmdLine );
|
||
|
return true;
|
||
|
}
|
||
|
else if ( CommandLine()->FindParm( "-runfaceposer" ) )
|
||
|
{
|
||
|
Q_snprintf( cmdLine, sizeof( cmdLine ), "\"%s\\%s\\bin\\hlfaceposer.exe\"", GetSDKLauncherBinDirectory(), g_engineDir );
|
||
|
QuickLaunchCommandLine( cmdLine );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CheckCreateModParameters()
|
||
|
{
|
||
|
if ( CommandLine()->FindParm( "-AutoHL2Mod" ) )
|
||
|
g_bAutoHL2Mod = true;
|
||
|
|
||
|
int iParm = CommandLine()->FindParm( "-CreateMod" );
|
||
|
if ( iParm == 0 )
|
||
|
return;
|
||
|
|
||
|
if ( (iParm + 2) < CommandLine()->ParmCount() )
|
||
|
{
|
||
|
// Set it up so the mod wizard can skip the mod dir/mod name panel.
|
||
|
g_bModWizard_CmdLineFields = true;
|
||
|
Q_strncpy( g_ModWizard_CmdLine_ModDir, CommandLine()->GetParm( iParm + 1 ), sizeof( g_ModWizard_CmdLine_ModDir ) );
|
||
|
Q_strncpy( g_ModWizard_CmdLine_ModName, CommandLine()->GetParm( iParm + 2 ), sizeof( g_ModWizard_CmdLine_ModName ) );
|
||
|
|
||
|
RunCreateModWizard( true );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// The application object
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CSDKLauncherApp : public CVguiSteamApp
|
||
|
{
|
||
|
typedef CVguiSteamApp BaseClass;
|
||
|
|
||
|
public:
|
||
|
// Methods of IApplication
|
||
|
virtual bool Create();
|
||
|
virtual bool PreInit();
|
||
|
virtual int Main();
|
||
|
virtual void PostShutdown();
|
||
|
virtual void Destroy() {}
|
||
|
};
|
||
|
|
||
|
DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT( CSDKLauncherApp );
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// The application object
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CSDKLauncherApp::Create()
|
||
|
{
|
||
|
SpewOutputFunc( SDKLauncherSpewOutputFunc );
|
||
|
|
||
|
AppSystemInfo_t appSystems[] =
|
||
|
{
|
||
|
{ "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
|
||
|
{ "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION },
|
||
|
{ "", "" } // Required to terminate the list
|
||
|
};
|
||
|
|
||
|
return AddSystems( appSystems );
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Entry point
|
||
|
//-----------------------------------------------------------------------------
|
||
|
bool CSDKLauncherApp::PreInit()
|
||
|
{
|
||
|
if ( !BaseClass::PreInit() )
|
||
|
return false;
|
||
|
|
||
|
// Make sure we're using the proper environment variable
|
||
|
ConvertObsoleteVConfigRegistrySetting( GAMEDIR_TOKEN );
|
||
|
|
||
|
if ( !CommandLine()->ParmValue( "-game" ) )
|
||
|
{
|
||
|
Error( "SDKLauncher requires -game on the command line." );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// winsock aware
|
||
|
WSAData wsaData;
|
||
|
WSAStartup( MAKEWORD(2,0), &wsaData );
|
||
|
|
||
|
// Create a window to capture messages
|
||
|
CreateMessageWindow();
|
||
|
|
||
|
FileSystem_SetErrorMode( FS_ERRORMODE_AUTO );
|
||
|
|
||
|
if ( !BaseClass::SetupSearchPaths( NULL, false, true ) )
|
||
|
{
|
||
|
::MessageBox( NULL, "Error", "Unable to initialize file system\n", MB_OK );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Set gamedir.
|
||
|
Q_MakeAbsolutePath( gamedir, sizeof( gamedir ), GetGameInfoPath() );
|
||
|
Q_AppendSlash( gamedir, sizeof( gamedir ) );
|
||
|
|
||
|
// the "base dir" so we can scan mod name
|
||
|
g_pFullFileSystem->AddSearchPath(GetSDKLauncherBaseDirectory(), SDKLAUNCHER_MAIN_PATH_ID);
|
||
|
// the main platform dir
|
||
|
g_pFullFileSystem->AddSearchPath("platform","PLATFORM", PATH_ADD_TO_HEAD);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void CSDKLauncherApp::PostShutdown()
|
||
|
{
|
||
|
// Stop our message window
|
||
|
ShutdownMessageWindow();
|
||
|
::WSACleanup();
|
||
|
|
||
|
BaseClass::PostShutdown();
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Purpose: Entry point
|
||
|
//-----------------------------------------------------------------------------
|
||
|
int CSDKLauncherApp::Main()
|
||
|
{
|
||
|
SetVConfigRegistrySetting( "sourcesdk", GetSDKLauncherBaseDirectory() );
|
||
|
|
||
|
// If they just want to run Hammer or hlmv, just do that and exit.
|
||
|
if ( RunQuickLaunch() )
|
||
|
return 1;
|
||
|
|
||
|
// Run app frame loop
|
||
|
int ret = InitializeVGui();
|
||
|
if ( ret != 0 )
|
||
|
return ret;
|
||
|
|
||
|
DumpMinFootprintFiles( false );
|
||
|
|
||
|
SteamAPI_InitSafe();
|
||
|
SteamAPI_SetTryCatchCallbacks( false ); // We don't use exceptions, so tell steam not to use try/catch in callback handlers
|
||
|
g_SteamAPIContext.Init();
|
||
|
|
||
|
// Start looking for file updates
|
||
|
// UpdateConfigsStatus_Init();
|
||
|
|
||
|
// Check if they want to run the Create Mod wizard right off the bat.
|
||
|
CheckCreateModParameters();
|
||
|
|
||
|
while ( vgui::ivgui()->IsRunning() && !g_bAppQuit )
|
||
|
{
|
||
|
Sleep( 10 );
|
||
|
// UpdateConfigsStatus();
|
||
|
vgui::ivgui()->RunFrame();
|
||
|
}
|
||
|
|
||
|
ShutdownVGui();
|
||
|
|
||
|
// UpdateConfigsStatus_Shutdown();
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|