|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include <stdio.h>
#include <stdlib.h>
#include "isys.h"
#include "console/conproc.h"
#include "dedicated.h"
#include "engine_hlds_api.h"
#include "checksum_md5.h"
#include "mathlib/mathlib.h"
#include "tier0/vcrmode.h"
#include "tier0/dbg.h"
#include "tier1/strtools.h"
#include "tier0/icommandline.h"
#include "idedicatedexports.h"
#include "vgui/vguihelpers.h"
#include "appframework/AppFramework.h"
#include "filesystem_init.h"
#include "tier2/tier2.h"
#include "dedicated.h"
#include "vstdlib/cvar.h"
#include "inputsystem/iinputsystem.h"
#ifdef _WIN32
#include <windows.h>
#include <direct.h>
#include "KeyValues.h"
#else
#define _chdir chdir
#include <unistd.h>
#endif
void* FileSystemFactory( const char *pName, int *pReturnCode ); bool InitInstance( ); int ProcessConsoleInput( void ); bool NET_Init( void ); void NET_Shutdown( void ); const char *UTIL_GetBaseDir( void ); #ifdef _WIN32
bool g_bVGui = false; #endif
#if defined ( _WIN32 )
#include "console/TextConsoleWin32.h"
CTextConsoleWin32 console; #else
#include "console/TextConsoleUnix.h"
CTextConsoleUnix console; #endif
#ifdef _WIN32
extern char *gpszCvars; #endif
IDedicatedServerAPI *engine = NULL;
//-----------------------------------------------------------------------------
// Implementation of IVCRHelpers.
//-----------------------------------------------------------------------------
class CVCRHelpers : public IVCRHelpers { public: virtual void ErrorMessage( const char *pMsg ) { printf( "ERROR: %s\n", pMsg ); }
virtual void* GetMainWindow() { return 0; } }; CVCRHelpers g_VCRHelpers;
SpewRetval_t DedicatedSpewOutputFunc( SpewType_t spewType, char const *pMsg ); // in sys_common.cpp
//-----------------------------------------------------------------------------
// Run a single VGUI frame. if bFinished is true, run VGUIFinishedConfig() first.
//-----------------------------------------------------------------------------
static bool DoRunVGUIFrame( bool bFinished = false ) { #ifdef _WIN32
if ( g_bVGui ) { if ( bFinished ) VGUIFinishedConfig(); RunVGUIFrame(); return true; } #endif
return false; }
//-----------------------------------------------------------------------------
// Handle the VCRHook PeekMessage loop.
// Return true if WM_QUIT received.
//-----------------------------------------------------------------------------
static bool HandleVCRHook() { #if defined ( _WIN32 )
MSG msg;
bool bDone = false; while( VCRHook_PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { //if (!GetMessage( &msg, NULL, 0, 0))
if ( msg.message == WM_QUIT ) { bDone = true; break; }
TranslateMessage( &msg ); DispatchMessage( &msg ); }
if ( IsPC() ) { // NOTE: Under some implementations of Win9x,
// dispatching messages can cause the FPU control word to change
SetupFPUControlWord(); }
if ( bDone /*|| gbAppHasBeenTerminated*/ ) return true; #endif // _WIN32
return false; }
//-----------------------------------------------------------------------------
//
// Server loop
//
//-----------------------------------------------------------------------------
void RunServer( void ) { #ifdef _WIN32
if(gpszCvars) { engine->AddConsoleText(gpszCvars); } #endif
// Run 2 engine frames first to get the engine to load its resources.
for ( int i = 0; i < 2; i++ ) { DoRunVGUIFrame(); if ( !engine->RunFrame() ) return; }
// Run final VGUI frame.
DoRunVGUIFrame( true );
int bDone = false; while ( !bDone ) { // Check on VCRHook_PeekMessage...
if ( HandleVCRHook() ) break;
if ( !DoRunVGUIFrame() ) ProcessConsoleInput();
if ( !engine->RunFrame() ) bDone = true;
sys->UpdateStatus( 0 /* don't force */ ); } }
//-----------------------------------------------------------------------------
//
// initialize the console or wait for vgui to start the server
//
//-----------------------------------------------------------------------------
static bool ConsoleStartup( ) { #ifdef _WIN32
if ( g_bVGui ) { RunVGUIFrame();
// Run the config screen
while (VGUIIsInConfig() && VGUIIsRunning()) RunVGUIFrame();
if ( VGUIIsStopping() ) return false;
return true; } else { if ( !console.Init() ) { return false; } } #endif // _WIN32
return true; }
//-----------------------------------------------------------------------------
// Instantiate all main libraries
//-----------------------------------------------------------------------------
bool CDedicatedAppSystemGroup::Create( ) { #ifndef _WIN32
if ( !console.Init() ) return false; #endif
// Hook the debug output stuff (override the spew func in the appframework)
SpewOutputFunc( DedicatedSpewOutputFunc );
// Added the dedicated exports module for the engine to grab
AppModule_t dedicatedModule = LoadModule( Sys_GetFactoryThis() ); IAppSystem *pSystem = AddSystem( dedicatedModule, VENGINE_DEDICATEDEXPORTS_API_VERSION ); if ( !pSystem ) return false;
if ( sys->LoadModules( this ) ) { // Find the input system and tell it to skip Steam Controller initialization (we have to set this flag before Init gets called on the
// input system). Dedicated server should skip controller initialization to avoid initializing Steam, because we don't want the user to be
// flagged as "playing" the game.
auto inputsystem = ( IInputSystem* )FindSystem( INPUTSYSTEM_INTERFACE_VERSION ); if ( inputsystem ) { inputsystem->SetSkipControllerInitialization( true ); }
return true; } else { return false; } }
bool CDedicatedAppSystemGroup::PreInit( ) { // A little hack needed because dedicated links directly to filesystem .cpp files
g_pFullFileSystem = NULL;
if ( !BaseClass::PreInit() ) return false;
CFSSteamSetupInfo steamInfo; steamInfo.m_pDirectoryName = NULL; steamInfo.m_bOnlyUseDirectoryName = false; steamInfo.m_bToolsMode = false; steamInfo.m_bSetSteamDLLPath = false; steamInfo.m_bSteam = g_pFullFileSystem->IsSteam(); steamInfo.m_bNoGameInfo = steamInfo.m_bSteam; if ( FileSystem_SetupSteamEnvironment( steamInfo ) != FS_OK ) return false;
CFSMountContentInfo fsInfo; fsInfo.m_pFileSystem = g_pFullFileSystem; fsInfo.m_bToolsMode = false; fsInfo.m_pDirectoryName = steamInfo.m_GameInfoPath;
if ( FileSystem_MountContent( fsInfo ) != FS_OK ) return false;
if ( !NET_Init() ) return false;
#ifdef _WIN32
g_bVGui = !CommandLine()->CheckParm( "-console" ); #endif
CreateInterfaceFn factory = GetFactory(); IInputSystem *inputsystem = (IInputSystem *)factory( INPUTSYSTEM_INTERFACE_VERSION, NULL ); if ( inputsystem ) { inputsystem->SetConsoleTextMode( true ); }
#ifdef _WIN32
if ( g_bVGui ) { StartVGUI( GetFactory() ); } else #endif
{ if ( !sys->CreateConsoleWindow() ) return false; }
return true; }
int CDedicatedAppSystemGroup::Main( ) { if ( !ConsoleStartup() ) return -1;
#ifdef _WIN32
if ( g_bVGui ) RunVGUIFrame(); #endif
// Set up mod information
ModInfo_t info; info.m_pInstance = GetAppInstance(); info.m_pBaseDirectory = UTIL_GetBaseDir(); info.m_pInitialMod = CommandLine()->ParmValue( "-game", "hl2" ); info.m_pInitialGame = CommandLine()->ParmValue( "-defaultgamedir", "hl2" ); info.m_pParentAppSystemGroup = this; info.m_bTextMode = CommandLine()->CheckParm( "-textmode" );
if ( engine->ModInit( info ) ) { engine->ModShutdown(); } // if engine->ModInit
return 0; }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDedicatedAppSystemGroup::PostShutdown() { #ifdef _WIN32
if ( g_bVGui ) StopVGUI(); #endif
sys->DestroyConsoleWindow(); console.ShutDown(); NET_Shutdown(); BaseClass::PostShutdown(); }
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDedicatedAppSystemGroup::Destroy() { }
//-----------------------------------------------------------------------------
// Gets the executable name
//-----------------------------------------------------------------------------
bool GetExecutableName( char *out, int nMaxLen ) { #ifdef _WIN32
if ( !::GetModuleFileName( ( HINSTANCE )GetModuleHandle( NULL ), out, nMaxLen ) ) return false; return true; #elif POSIX
Q_strncpy( out, g_szEXEName, nMaxLen ); return true; #endif
}
//-----------------------------------------------------------------------------
// Purpose: Return the directory where this .exe is running from
// Output : char
//-----------------------------------------------------------------------------
void UTIL_ComputeBaseDir( char *pBaseDir, int nMaxLen ) { int j; char *pBuffer = NULL;
pBaseDir[ 0 ] = 0;
if ( GetExecutableName( pBaseDir, nMaxLen ) ) { pBuffer = strrchr( pBaseDir, CORRECT_PATH_SEPARATOR ); if ( pBuffer && *pBuffer ) { *(pBuffer+1) = '\0'; }
j = strlen( pBaseDir ); if (j > 0) { if ( ( pBaseDir[ j-1 ] == '\\' ) || ( pBaseDir[ j-1 ] == '/' ) ) { pBaseDir[ j-1 ] = 0; } } }
char const *pOverrideDir = CommandLine()->CheckParm( "-basedir" ); if ( pOverrideDir ) { strcpy( pBaseDir, pOverrideDir ); }
Q_strlower( pBaseDir ); Q_FixSlashes( pBaseDir ); }
//-----------------------------------------------------------------------------
// This class is a helper class used for steam-based applications.
// It loads up the file system in preparation for using it to load other
// required modules from steam.
//
// I couldn't use the one in appframework because the dedicated server
// inlines all the filesystem code.
//-----------------------------------------------------------------------------
class CDedicatedSteamApplication : public CSteamApplication { public: CDedicatedSteamApplication( CSteamAppSystemGroup *pAppSystemGroup ); virtual bool Create( ); };
//-----------------------------------------------------------------------------
// This class is a helper class used for steam-based applications.
// It loads up the file system in preparation for using it to load other
// required modules from steam.
//
// I couldn't use the one in appframework because the dedicated server
// inlines all the filesystem code.
//-----------------------------------------------------------------------------
CDedicatedSteamApplication::CDedicatedSteamApplication( CSteamAppSystemGroup *pAppSystemGroup ) : CSteamApplication( pAppSystemGroup ) { }
//-----------------------------------------------------------------------------
// Implementation of IAppSystemGroup
//-----------------------------------------------------------------------------
bool CDedicatedSteamApplication::Create( ) { // Add in the cvar factory
AppModule_t cvarModule = LoadModule( VStdLib_GetICVarFactory() ); AddSystem( cvarModule, CVAR_INTERFACE_VERSION );
AppModule_t fileSystemModule = LoadModule( FileSystemFactory ); m_pFileSystem = (IFileSystem*)AddSystem( fileSystemModule, FILESYSTEM_INTERFACE_VERSION );
if ( !m_pFileSystem ) { Warning( "Unable to load the file system!\n" ); return false; }
return true; }
//-----------------------------------------------------------------------------
//
// Main entry point for dedicated server, shared between win32 and linux
//
//-----------------------------------------------------------------------------
int main(int argc, char **argv) { #ifndef POSIX
_asm { fninit } #endif
SetupFPUControlWord();
#ifdef POSIX
Q_strncpy( g_szEXEName, *argv, ARRAYSIZE( g_szEXEName ) ); // Store off command line for argument searching
BuildCmdLine( argc, argv ); #endif
MathLib_Init( 2.2f, 2.2f, 0.0f, 1.0f );
// Store off command line for argument searching
CommandLine()->CreateCmdLine( VCRHook_GetCommandLine() ); #ifndef _WIN32
Plat_SetCommandLine( CommandLine()->GetCmdLine() ); #endif
// Start VCR mode?
const char *filename; if( CommandLine()->CheckParm( "-vcrrecord", &filename ) ) { if ( !VCRStart( filename, true, &g_VCRHelpers ) ) { Error( "-vcrrecord: can't open '%s' for writing.\n", filename ); return -1; } } else if( CommandLine()->CheckParm( "-vcrplayback", &filename ) ) { if ( !VCRStart( filename, false, &g_VCRHelpers ) ) { Error( "-vcrplayback: can't open '%s' for reading.\n", filename ); return -1; } }
// Figure out the directory the executable is running from
// and make that be the current working directory
char pBasedir[ MAX_PATH ]; UTIL_ComputeBaseDir( pBasedir, MAX_PATH ); _chdir( pBasedir );
// Rehook the command line through VCR mode.
CommandLine()->CreateCmdLine( VCRHook_GetCommandLine() );
if ( !InitInstance() ) return -1;
CDedicatedAppSystemGroup dedicatedSystems; CDedicatedSteamApplication steamApplication( &dedicatedSystems ); return steamApplication.Run( ); }
|