1
This commit is contained in:
419
dedicated/console/TextConsoleUnix.cpp
Normal file
419
dedicated/console/TextConsoleUnix.cpp
Normal file
@ -0,0 +1,419 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// CTextConsoleUnix.cpp: Unix implementation of the TextConsole class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "TextConsoleUnix.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "tier1/utllinkedlist.h"
|
||||
#include "filesystem.h"
|
||||
#include "../thirdparty/libedit-3.1/src/histedit.h"
|
||||
#include "tier0/vprof.h"
|
||||
|
||||
#define CONSOLE_LOG_FILE "console.log"
|
||||
|
||||
static pthread_mutex_t g_lock;
|
||||
static pthread_t g_threadid = (pthread_t)-1;
|
||||
CUtlLinkedList< CUtlString > g_Commands;
|
||||
static volatile int g_ProcessingCommands = false;
|
||||
|
||||
#if defined( LINUX )
|
||||
|
||||
// Dynamically load the libtinfo stuff. On servers without a tty attached,
|
||||
// we get to skip all of these dependencies on servers without ttys.
|
||||
#define TINFO_SYM(rc, fn, params, args, ret) \
|
||||
typedef rc (*DYNTINFOFN_##fn) params; \
|
||||
static DYNTINFOFN_##fn g_TINFO_##fn; \
|
||||
extern "C" rc fn params \
|
||||
{ \
|
||||
ret g_TINFO_##fn args; \
|
||||
}
|
||||
|
||||
TINFO_SYM(char *, tgoto, (char *string, int x, int y), (string, x, y), return);
|
||||
TINFO_SYM(int, tputs, (const char *str, int affcnt, int (*putc)(int)), (str, affcnt, putc), return);
|
||||
TINFO_SYM(int, tgetflag, (char *id), (id), return);
|
||||
TINFO_SYM(int, tgetnum, (char *id), (id), return);
|
||||
TINFO_SYM(int, tgetent, (char *bufp, const char *name), (bufp, name), return);
|
||||
TINFO_SYM(char *, tgetstr, (char *id, char **area), (id, area), return);
|
||||
|
||||
#endif // LINUX
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// init_tinfo_functions
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
static bool init_tinfo_functions()
|
||||
{
|
||||
#if !defined( LINUX )
|
||||
return true;
|
||||
#else
|
||||
static void *s_ncurses_handle = NULL;
|
||||
|
||||
if ( !s_ncurses_handle )
|
||||
{
|
||||
// Long time ago, ncurses was two libraries. So if libtinfo fails, try libncurses.
|
||||
static const char *names[] = { "libtinfo.so.5", "libncurses.so.5" };
|
||||
|
||||
for ( int i = 0; !s_ncurses_handle && ( i < ARRAYSIZE( names ) ); i++ )
|
||||
{
|
||||
bool bFailed = true;
|
||||
s_ncurses_handle = dlopen( names[i], RTLD_NOW );
|
||||
|
||||
if ( s_ncurses_handle )
|
||||
{
|
||||
bFailed = false;
|
||||
#define LOADTINFOFUNC(_handle, _func, _failed) \
|
||||
do { \
|
||||
g_TINFO_##_func = ( DYNTINFOFN_##_func )dlsym(_handle, #_func); \
|
||||
if ( !g_TINFO_##_func) \
|
||||
_failed = true; \
|
||||
} while (0)
|
||||
|
||||
LOADTINFOFUNC( s_ncurses_handle, tgoto, bFailed );
|
||||
LOADTINFOFUNC( s_ncurses_handle, tputs, bFailed );
|
||||
LOADTINFOFUNC( s_ncurses_handle, tgetflag, bFailed );
|
||||
LOADTINFOFUNC( s_ncurses_handle, tgetnum, bFailed );
|
||||
LOADTINFOFUNC( s_ncurses_handle, tgetent, bFailed );
|
||||
LOADTINFOFUNC( s_ncurses_handle, tgetstr, bFailed );
|
||||
#undef LOADTINFOFUNC
|
||||
}
|
||||
|
||||
if ( bFailed )
|
||||
s_ncurses_handle = NULL;
|
||||
}
|
||||
|
||||
if ( !s_ncurses_handle )
|
||||
{
|
||||
fprintf( stderr, "\nWARNING: Failed to load 32-bit libtinfo.so.5 or libncurses.so.5.\n"
|
||||
" Please install (lib32tinfo5 / ncurses-libs.i686 / equivalent) to enable readline.\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
return !!s_ncurses_handle;
|
||||
#endif // LINUX
|
||||
}
|
||||
|
||||
static unsigned char editline_complete( EditLine *el, int ch __attribute__((__unused__)) )
|
||||
{
|
||||
static const char *s_cmds[] =
|
||||
{
|
||||
"cvarlist ",
|
||||
"find ",
|
||||
"help ",
|
||||
"maps ",
|
||||
"nextlevel",
|
||||
"quit",
|
||||
"status",
|
||||
"sv_cheats ",
|
||||
"tf_bot_quota ",
|
||||
"toggle ",
|
||||
"sv_dump_edicts",
|
||||
#ifdef STAGING_ONLY
|
||||
"tf_bot_use_items ",
|
||||
#endif
|
||||
};
|
||||
|
||||
const LineInfo *lf = el_line(el);
|
||||
const char *cmd = lf->buffer;
|
||||
size_t len = lf->cursor - cmd;
|
||||
|
||||
if ( len > 0 )
|
||||
{
|
||||
for (int i = 0; i < ARRAYSIZE(s_cmds); i++)
|
||||
{
|
||||
if ( len > strlen( s_cmds[i] ) )
|
||||
continue;
|
||||
|
||||
if ( !Q_strncmp( cmd, s_cmds[i], len ) )
|
||||
{
|
||||
if ( el_insertstr( el, s_cmds[i] + len ) == -1 )
|
||||
return CC_ERROR;
|
||||
else
|
||||
return CC_REFRESH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CC_ERROR;
|
||||
}
|
||||
|
||||
static const char *editline_prompt( EditLine *e )
|
||||
{
|
||||
// Something like: "\1\033[7m\1Srcds$\1\033[0m\1 "
|
||||
static const char *szPrompt = getenv( "SRCDS_PROMPT" );
|
||||
return szPrompt ? szPrompt : "";
|
||||
}
|
||||
|
||||
static void editline_cleanup_handler( void *arg )
|
||||
{
|
||||
if ( arg )
|
||||
{
|
||||
EditLine *el = (EditLine *)arg;
|
||||
el_end( el );
|
||||
}
|
||||
}
|
||||
|
||||
static bool add_command( const char *cmd, int cmd_len )
|
||||
{
|
||||
if ( cmd )
|
||||
{
|
||||
tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
|
||||
|
||||
// Trim trailing whitespace.
|
||||
while ( ( cmd_len > 0 ) && isspace( cmd[ cmd_len - 1 ] ) )
|
||||
cmd_len--;
|
||||
|
||||
if ( cmd_len > 0 )
|
||||
{
|
||||
pthread_mutex_lock( &g_lock );
|
||||
if ( g_Commands.Count() < 32 )
|
||||
{
|
||||
CUtlString szCommand( cmd, cmd_len );
|
||||
g_Commands.AddToTail( szCommand );
|
||||
|
||||
g_ProcessingCommands = true;
|
||||
}
|
||||
pthread_mutex_unlock( &g_lock );
|
||||
|
||||
// Wait a bit until we've processed the command we added.
|
||||
for ( int i = 0; i < 6; i++ )
|
||||
{
|
||||
while ( g_ProcessingCommands )
|
||||
usleep( 500 );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void *editline_threadproc( void *arg )
|
||||
{
|
||||
HistEvent ev;
|
||||
EditLine *el;
|
||||
History *myhistory;
|
||||
FILE *tty = (FILE *)arg;
|
||||
|
||||
ThreadSetDebugName( "libedit" );
|
||||
|
||||
// Set up state
|
||||
el = el_init( "srcds_linux", stdin, tty, stderr );
|
||||
el_set( el, EL_PROMPT, &editline_prompt );
|
||||
el_set( el, EL_EDITOR, "emacs" ); // or "vi"
|
||||
|
||||
// Hitting Ctrl+R will reset prompt.
|
||||
el_set( el, EL_BIND, "^R", "ed-redisplay", NULL );
|
||||
|
||||
/* Add a user-defined function */
|
||||
el_set( el, EL_ADDFN, "ed-complete", "Complete argument", editline_complete );
|
||||
/* Bind tab to it */
|
||||
el_set( el, EL_BIND, "^I", "ed-complete", NULL );
|
||||
|
||||
// Init history.
|
||||
myhistory = history_init();
|
||||
if (myhistory == 0)
|
||||
{
|
||||
fprintf( stderr, "history could not be initialized\n" );
|
||||
g_threadid = (pthread_t)-1;
|
||||
return (void *)-1;
|
||||
}
|
||||
|
||||
// History size.
|
||||
history( myhistory, &ev, H_SETSIZE, 800 );
|
||||
|
||||
// History callback.
|
||||
el_set( el, EL_HIST, history, myhistory );
|
||||
|
||||
// Source user's defaults.
|
||||
el_source( el, NULL );
|
||||
|
||||
pthread_cleanup_push( editline_cleanup_handler, el );
|
||||
|
||||
while ( g_threadid != (pthread_t)-1 )
|
||||
{
|
||||
// count is the number of characters read.
|
||||
// line is a const char* of our command line with the tailing \n
|
||||
int count;
|
||||
const char *line = el_gets( el, &count );
|
||||
|
||||
if ( add_command( line, count ) )
|
||||
{
|
||||
// Add command to history.
|
||||
history( myhistory, &ev, H_ENTER, line );
|
||||
}
|
||||
}
|
||||
|
||||
pthread_cleanup_pop( 0 );
|
||||
|
||||
// Clean up...
|
||||
history_end( myhistory );
|
||||
el_end( el );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *fgets_threadproc( void *arg )
|
||||
{
|
||||
pthread_cleanup_push( editline_cleanup_handler, NULL );
|
||||
|
||||
while ( g_threadid != (pthread_t)-1 )
|
||||
{
|
||||
char cmd[ 512 ];
|
||||
|
||||
if ( fgets( cmd, sizeof( cmd ), stdin ) )
|
||||
{
|
||||
cmd[ sizeof(cmd) - 1 ] = 0;
|
||||
add_command( cmd, strlen( cmd ) );
|
||||
}
|
||||
}
|
||||
|
||||
pthread_cleanup_pop( 0 );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CTextConsoleUnix::Init()
|
||||
{
|
||||
if( g_threadid != (pthread_t)-1 )
|
||||
{
|
||||
Assert( !"CTextConsoleUnix can only handle a single thread!" );
|
||||
return false;
|
||||
}
|
||||
|
||||
pthread_mutex_init( &g_lock, NULL );
|
||||
|
||||
// This code is for echo-ing key presses to the connected tty
|
||||
// (which is != STDOUT)
|
||||
if ( isatty( STDIN_FILENO ) )
|
||||
{
|
||||
const char *termid_str = ctermid( NULL );
|
||||
|
||||
m_tty = fopen( termid_str, "w+" );
|
||||
if ( !m_tty )
|
||||
{
|
||||
fprintf( stderr, "WARNING: Unable to open tty(%s) for output.\n", termid_str );
|
||||
m_tty = stdout;
|
||||
}
|
||||
|
||||
void *(*terminal_threadproc) (void *) = editline_threadproc;
|
||||
if ( !init_tinfo_functions() )
|
||||
terminal_threadproc = fgets_threadproc;
|
||||
|
||||
if ( pthread_create( &g_threadid, NULL, terminal_threadproc, (void *)m_tty ) != 0 )
|
||||
{
|
||||
g_threadid = (pthread_t)-1;
|
||||
fprintf( stderr, "WARNING: pthread_create failed: %s.\n", strerror(errno) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tty = fopen( "/dev/null", "w+" );
|
||||
if ( !m_tty )
|
||||
m_tty = stdout;
|
||||
}
|
||||
|
||||
m_bConDebug = CommandLine()->FindParm( "-condebug" ) != 0;
|
||||
if ( m_bConDebug && CommandLine()->FindParm( "-conclearlog" ) )
|
||||
g_pFullFileSystem->RemoveFile( CONSOLE_LOG_FILE, "GAME" );
|
||||
|
||||
return CTextConsole::Init();
|
||||
}
|
||||
|
||||
void CTextConsoleUnix::ShutDown()
|
||||
{
|
||||
if ( g_threadid != (pthread_t)-1 )
|
||||
{
|
||||
void *status = NULL;
|
||||
pthread_t tid = g_threadid;
|
||||
|
||||
g_threadid = (pthread_t)-1;
|
||||
|
||||
pthread_cancel( tid );
|
||||
pthread_join( tid, &status );
|
||||
}
|
||||
|
||||
pthread_mutex_destroy( &g_lock );
|
||||
}
|
||||
|
||||
void CTextConsoleUnix::Print( char * pszMsg )
|
||||
{
|
||||
int nChars = strlen( pszMsg );
|
||||
|
||||
if ( nChars > 0 )
|
||||
{
|
||||
if ( m_bConDebug )
|
||||
{
|
||||
FileHandle_t fh = g_pFullFileSystem->Open( CONSOLE_LOG_FILE, "a" );
|
||||
if ( fh != FILESYSTEM_INVALID_HANDLE )
|
||||
{
|
||||
g_pFullFileSystem->Write( pszMsg, nChars, fh );
|
||||
g_pFullFileSystem->Close( fh );
|
||||
}
|
||||
}
|
||||
|
||||
fwrite( pszMsg, 1, nChars, m_tty );
|
||||
}
|
||||
}
|
||||
|
||||
void CTextConsoleUnix::SetTitle( char *pszTitle )
|
||||
{
|
||||
}
|
||||
|
||||
void CTextConsoleUnix::SetStatusLine( char *pszStatus )
|
||||
{
|
||||
}
|
||||
|
||||
void CTextConsoleUnix::UpdateStatus()
|
||||
{
|
||||
}
|
||||
|
||||
char *CTextConsoleUnix::GetLine( int index, char *buf, int buflen )
|
||||
{
|
||||
if ( g_threadid != (pthread_t)-1 )
|
||||
{
|
||||
if ( g_Commands.Count() > 0 )
|
||||
{
|
||||
pthread_mutex_lock( &g_lock );
|
||||
|
||||
const CUtlString& psCommand = g_Commands[ g_Commands.Head() ];
|
||||
V_strncpy( buf, psCommand.Get(), buflen );
|
||||
g_Commands.Remove( g_Commands.Head() );
|
||||
|
||||
pthread_mutex_unlock( &g_lock );
|
||||
return buf;
|
||||
}
|
||||
else if ( index == 0 )
|
||||
{
|
||||
// We're being asked for the first command. Must be a new frame.
|
||||
// Reset the processed commands global.
|
||||
g_ProcessingCommands = false;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int CTextConsoleUnix::GetWidth()
|
||||
{
|
||||
int nWidth = 0;
|
||||
struct winsize ws;
|
||||
|
||||
if ( ioctl( STDOUT_FILENO, TIOCGWINSZ, &ws ) == 0 )
|
||||
nWidth = (int)ws.ws_col;
|
||||
|
||||
if ( nWidth <= 1 )
|
||||
nWidth = 80;
|
||||
|
||||
return nWidth;
|
||||
}
|
||||
|
||||
#endif // !_WIN32
|
44
dedicated/console/TextConsoleUnix.h
Normal file
44
dedicated/console/TextConsoleUnix.h
Normal file
@ -0,0 +1,44 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// TextConsoleUnix.h: Unix interface for the TextConsole class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined TEXTCONSOLE_UNIX_H
|
||||
#define TEXTCONSOLE_UNIX_H
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <stdio.h>
|
||||
#include "textconsole.h"
|
||||
|
||||
class CTextConsoleUnix : public CTextConsole
|
||||
{
|
||||
public:
|
||||
virtual ~CTextConsoleUnix() { }
|
||||
|
||||
// CTextConsole
|
||||
bool Init();
|
||||
void ShutDown();
|
||||
void Print( char * pszMsg );
|
||||
|
||||
void SetTitle( char *pszTitle );
|
||||
void SetStatusLine( char *pszStatus );
|
||||
void UpdateStatus();
|
||||
|
||||
char * GetLine( int index, char *buf, int buflen );
|
||||
int GetWidth();
|
||||
|
||||
private:
|
||||
bool m_bConDebug;
|
||||
FILE *m_tty;
|
||||
};
|
||||
|
||||
#endif // _ndef WIN32
|
||||
|
||||
#endif // !defined TEXTCONSOLE_UNIX_H
|
644
dedicated/console/TextConsoleWin32.cpp
Normal file
644
dedicated/console/TextConsoleWin32.cpp
Normal file
@ -0,0 +1,644 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// CTextConsoleWin32.cpp: Win32 implementation of the TextConsole class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "TextConsoleWin32.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "utlvector.h"
|
||||
|
||||
// Could possibly switch all this code over to using readline. This:
|
||||
// http://mingweditline.sourceforge.net/?Description
|
||||
// readline() / add_history(char *)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
BOOL WINAPI ConsoleHandlerRoutine( DWORD CtrlType )
|
||||
{
|
||||
NOTE_UNUSED( CtrlType );
|
||||
/* TODO ?
|
||||
if ( CtrlType != CTRL_C_EVENT && CtrlType != CTRL_BREAK_EVENT )
|
||||
m_System->Stop(); // don't quit on break or ctrl+c
|
||||
*/
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// GetConsoleHwnd() helper function from MSDN Knowledge Base Article Q124103
|
||||
// needed, because HWND GetConsoleWindow(VOID) is not avaliable under Win95/98/ME
|
||||
|
||||
HWND GetConsoleHwnd(void)
|
||||
{
|
||||
typedef HWND (WINAPI *PFNGETCONSOLEWINDOW)( VOID );
|
||||
static PFNGETCONSOLEWINDOW s_pfnGetConsoleWindow = (PFNGETCONSOLEWINDOW) GetProcAddress( GetModuleHandle("kernel32"), "GetConsoleWindow" );
|
||||
if ( s_pfnGetConsoleWindow )
|
||||
return s_pfnGetConsoleWindow();
|
||||
|
||||
HWND hwndFound; // This is what is returned to the caller.
|
||||
char pszNewWindowTitle[1024]; // Contains fabricated WindowTitle
|
||||
char pszOldWindowTitle[1024]; // Contains original WindowTitle
|
||||
|
||||
// Fetch current window title.
|
||||
GetConsoleTitle( pszOldWindowTitle, 1024 );
|
||||
|
||||
// Format a "unique" NewWindowTitle.
|
||||
wsprintf( pszNewWindowTitle,"%d/%d", GetTickCount(), GetCurrentProcessId() );
|
||||
|
||||
// Change current window title.
|
||||
SetConsoleTitle(pszNewWindowTitle);
|
||||
|
||||
// Ensure window title has been updated.
|
||||
Sleep(40);
|
||||
|
||||
// Look for NewWindowTitle.
|
||||
hwndFound = FindWindow( NULL, pszNewWindowTitle );
|
||||
|
||||
// Restore original window title.
|
||||
|
||||
SetConsoleTitle( pszOldWindowTitle );
|
||||
|
||||
return hwndFound;
|
||||
}
|
||||
|
||||
CTextConsoleWin32::CTextConsoleWin32()
|
||||
{
|
||||
hinput = NULL;
|
||||
houtput = NULL;
|
||||
Attrib = 0;
|
||||
statusline[0] = '\0';
|
||||
}
|
||||
|
||||
bool CTextConsoleWin32::Init()
|
||||
{
|
||||
(void) AllocConsole();
|
||||
SetTitle( "SOURCE DEDICATED SERVER" );
|
||||
|
||||
hinput = GetStdHandle ( STD_INPUT_HANDLE );
|
||||
houtput = GetStdHandle ( STD_OUTPUT_HANDLE );
|
||||
|
||||
if ( !SetConsoleCtrlHandler( &ConsoleHandlerRoutine, TRUE) )
|
||||
{
|
||||
Print( "WARNING! TextConsole::Init: Could not attach console hook.\n" );
|
||||
}
|
||||
|
||||
Attrib = FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY ;
|
||||
|
||||
SetWindowPos( GetConsoleHwnd(), HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW );
|
||||
|
||||
memset( m_szConsoleText, 0, sizeof( m_szConsoleText ) );
|
||||
m_nConsoleTextLen = 0;
|
||||
m_nCursorPosition = 0;
|
||||
|
||||
memset( m_szSavedConsoleText, 0, sizeof( m_szSavedConsoleText ) );
|
||||
m_nSavedConsoleTextLen = 0;
|
||||
|
||||
memset( m_aszLineBuffer, 0, sizeof( m_aszLineBuffer ) );
|
||||
m_nTotalLines = 0;
|
||||
m_nInputLine = 0;
|
||||
m_nBrowseLine = 0;
|
||||
|
||||
// these are log messages, not related to console
|
||||
Msg( "\n" );
|
||||
Msg( "Console initialized.\n" );
|
||||
|
||||
return CTextConsole::Init();
|
||||
}
|
||||
|
||||
void CTextConsoleWin32::ShutDown( void )
|
||||
{
|
||||
FreeConsole();
|
||||
}
|
||||
|
||||
void CTextConsoleWin32::SetVisible( bool visible )
|
||||
{
|
||||
ShowWindow ( GetConsoleHwnd(), visible ? SW_SHOW : SW_HIDE );
|
||||
m_ConsoleVisible = visible;
|
||||
}
|
||||
|
||||
char * CTextConsoleWin32::GetLine( int index, char *buf, int buflen )
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
INPUT_RECORD recs[ 1024 ];
|
||||
unsigned long numread;
|
||||
unsigned long numevents;
|
||||
|
||||
if ( !GetNumberOfConsoleInputEvents( hinput, &numevents ) )
|
||||
{
|
||||
Error("CTextConsoleWin32::GetLine: !GetNumberOfConsoleInputEvents");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( numevents <= 0 )
|
||||
break;
|
||||
|
||||
if ( !ReadConsoleInput( hinput, recs, ARRAYSIZE( recs ), &numread ) )
|
||||
{
|
||||
Error("CTextConsoleWin32::GetLine: !ReadConsoleInput");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( numread == 0 )
|
||||
return NULL;
|
||||
|
||||
for ( int i=0; i < (int)numread; i++ )
|
||||
{
|
||||
INPUT_RECORD *pRec = &recs[i];
|
||||
if ( pRec->EventType != KEY_EVENT )
|
||||
continue;
|
||||
|
||||
if ( pRec->Event.KeyEvent.bKeyDown )
|
||||
{
|
||||
// check for cursor keys
|
||||
if ( pRec->Event.KeyEvent.wVirtualKeyCode == VK_UP )
|
||||
{
|
||||
ReceiveUpArrow();
|
||||
}
|
||||
else if ( pRec->Event.KeyEvent.wVirtualKeyCode == VK_DOWN )
|
||||
{
|
||||
ReceiveDownArrow();
|
||||
}
|
||||
else if ( pRec->Event.KeyEvent.wVirtualKeyCode == VK_LEFT )
|
||||
{
|
||||
ReceiveLeftArrow();
|
||||
}
|
||||
else if ( pRec->Event.KeyEvent.wVirtualKeyCode == VK_RIGHT )
|
||||
{
|
||||
ReceiveRightArrow();
|
||||
}
|
||||
else
|
||||
{
|
||||
char ch;
|
||||
int nLen;
|
||||
|
||||
ch = pRec->Event.KeyEvent.uChar.AsciiChar;
|
||||
switch ( ch )
|
||||
{
|
||||
case '\r': // Enter
|
||||
nLen = ReceiveNewline();
|
||||
if ( nLen )
|
||||
{
|
||||
strncpy( buf, m_szConsoleText, buflen );
|
||||
buf[ buflen - 1 ] = 0;
|
||||
return buf;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\b': // Backspace
|
||||
ReceiveBackspace();
|
||||
break;
|
||||
|
||||
case '\t': // TAB
|
||||
ReceiveTab();
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( ( ch >= ' ') && ( ch <= '~' ) ) // dont' accept nonprintable chars
|
||||
{
|
||||
ReceiveStandardChar( ch );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CTextConsoleWin32::Print( char * pszMsg )
|
||||
{
|
||||
if ( m_nConsoleTextLen )
|
||||
{
|
||||
int nLen;
|
||||
|
||||
nLen = m_nConsoleTextLen;
|
||||
|
||||
while ( nLen-- )
|
||||
{
|
||||
PrintRaw( "\b \b" );
|
||||
}
|
||||
}
|
||||
|
||||
PrintRaw( pszMsg );
|
||||
|
||||
if ( m_nConsoleTextLen )
|
||||
{
|
||||
PrintRaw( m_szConsoleText, m_nConsoleTextLen );
|
||||
}
|
||||
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
void CTextConsoleWin32::PrintRaw( const char * pszMsg, int nChars )
|
||||
{
|
||||
unsigned long dummy;
|
||||
|
||||
if ( houtput == NULL )
|
||||
{
|
||||
houtput = GetStdHandle ( STD_OUTPUT_HANDLE );
|
||||
if ( houtput == NULL )
|
||||
return;
|
||||
}
|
||||
|
||||
if ( nChars <= 0 )
|
||||
{
|
||||
nChars = strlen( pszMsg );
|
||||
if ( nChars <= 0 )
|
||||
return;
|
||||
}
|
||||
|
||||
// filter out ASCII BEL characters because windows actually plays a
|
||||
// bell sound, which can be used to lag the server in a DOS attack.
|
||||
char * pTempBuf = NULL;
|
||||
for ( int i = 0; i < nChars; ++i )
|
||||
{
|
||||
if ( pszMsg[i] == 0x07 /*BEL*/ )
|
||||
{
|
||||
if ( !pTempBuf )
|
||||
{
|
||||
pTempBuf = ( char * ) malloc( nChars );
|
||||
memcpy( pTempBuf, pszMsg, nChars );
|
||||
}
|
||||
pTempBuf[i] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
WriteFile( houtput, pTempBuf ? pTempBuf : pszMsg, nChars, &dummy, NULL );
|
||||
|
||||
free( pTempBuf ); // usually NULL
|
||||
}
|
||||
|
||||
int CTextConsoleWin32::GetWidth( void )
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
int nWidth;
|
||||
|
||||
nWidth = 0;
|
||||
|
||||
if ( GetConsoleScreenBufferInfo( houtput, &csbi ) )
|
||||
{
|
||||
nWidth = csbi.dwSize.X;
|
||||
}
|
||||
|
||||
if ( nWidth <= 1 )
|
||||
nWidth = 80;
|
||||
|
||||
return nWidth;
|
||||
}
|
||||
|
||||
void CTextConsoleWin32::SetStatusLine( char * pszStatus )
|
||||
{
|
||||
strncpy( statusline, pszStatus, 80 );
|
||||
statusline[ 79 ] = '\0';
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
void CTextConsoleWin32::UpdateStatus( void )
|
||||
{
|
||||
COORD coord;
|
||||
DWORD dwWritten = 0;
|
||||
WORD wAttrib[ 80 ];
|
||||
|
||||
for ( int i = 0; i < 80; i++ )
|
||||
{
|
||||
wAttrib[i] = Attrib; //FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY ;
|
||||
}
|
||||
|
||||
coord.X = coord.Y = 0;
|
||||
|
||||
WriteConsoleOutputAttribute( houtput, wAttrib, 80, coord, &dwWritten );
|
||||
WriteConsoleOutputCharacter( houtput, statusline, 80, coord, &dwWritten );
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::SetTitle( char * pszTitle )
|
||||
{
|
||||
SetConsoleTitle( pszTitle );
|
||||
}
|
||||
|
||||
void CTextConsoleWin32::SetColor(WORD attrib)
|
||||
{
|
||||
Attrib = attrib;
|
||||
}
|
||||
|
||||
int CTextConsoleWin32::ReceiveNewline( void )
|
||||
{
|
||||
int nLen = 0;
|
||||
|
||||
PrintRaw( "\n" );
|
||||
|
||||
if ( m_nConsoleTextLen )
|
||||
{
|
||||
nLen = m_nConsoleTextLen;
|
||||
|
||||
m_szConsoleText[ m_nConsoleTextLen ] = 0;
|
||||
m_nConsoleTextLen = 0;
|
||||
m_nCursorPosition = 0;
|
||||
|
||||
// cache line in buffer, but only if it's not a duplicate of the previous line
|
||||
if ( ( m_nInputLine == 0 ) || ( strcmp( m_aszLineBuffer[ m_nInputLine - 1 ], m_szConsoleText ) ) )
|
||||
{
|
||||
strncpy( m_aszLineBuffer[ m_nInputLine ], m_szConsoleText, MAX_CONSOLE_TEXTLEN );
|
||||
|
||||
m_nInputLine++;
|
||||
|
||||
if ( m_nInputLine > m_nTotalLines )
|
||||
m_nTotalLines = m_nInputLine;
|
||||
|
||||
if ( m_nInputLine >= MAX_BUFFER_LINES )
|
||||
m_nInputLine = 0;
|
||||
|
||||
}
|
||||
|
||||
m_nBrowseLine = m_nInputLine;
|
||||
}
|
||||
|
||||
return nLen;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::ReceiveBackspace( void )
|
||||
{
|
||||
int nCount;
|
||||
|
||||
if ( m_nCursorPosition == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_nConsoleTextLen--;
|
||||
m_nCursorPosition--;
|
||||
|
||||
PrintRaw( "\b" );
|
||||
|
||||
for ( nCount = m_nCursorPosition; nCount < m_nConsoleTextLen; nCount++ )
|
||||
{
|
||||
m_szConsoleText[ nCount ] = m_szConsoleText[ nCount + 1 ];
|
||||
PrintRaw( m_szConsoleText + nCount, 1 );
|
||||
}
|
||||
|
||||
PrintRaw( " " );
|
||||
|
||||
nCount = m_nConsoleTextLen;
|
||||
while ( nCount >= m_nCursorPosition )
|
||||
{
|
||||
PrintRaw( "\b" );
|
||||
nCount--;
|
||||
}
|
||||
|
||||
m_nBrowseLine = m_nInputLine;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::ReceiveTab( void )
|
||||
{
|
||||
CUtlVector<char *> matches;
|
||||
|
||||
m_szConsoleText[ m_nConsoleTextLen ] = 0;
|
||||
|
||||
if ( matches.Count() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( matches.Count() == 1 )
|
||||
{
|
||||
char * pszCmdName;
|
||||
char * pszRest;
|
||||
|
||||
pszCmdName = matches[0];
|
||||
pszRest = pszCmdName + strlen( m_szConsoleText );
|
||||
|
||||
if ( pszRest )
|
||||
{
|
||||
PrintRaw( pszRest );
|
||||
strcat( m_szConsoleText, pszRest );
|
||||
m_nConsoleTextLen += strlen( pszRest );
|
||||
|
||||
PrintRaw( " " );
|
||||
strcat( m_szConsoleText, " " );
|
||||
m_nConsoleTextLen++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int nLongestCmd;
|
||||
int nTotalColumns;
|
||||
int nCurrentColumn;
|
||||
char * pszCurrentCmd;
|
||||
int i = 0;
|
||||
|
||||
nLongestCmd = 0;
|
||||
|
||||
pszCurrentCmd = matches[0];
|
||||
while ( pszCurrentCmd )
|
||||
{
|
||||
if ( (int)strlen( pszCurrentCmd) > nLongestCmd )
|
||||
{
|
||||
nLongestCmd = strlen( pszCurrentCmd);
|
||||
}
|
||||
|
||||
i++;
|
||||
pszCurrentCmd = (char *)matches[i];
|
||||
}
|
||||
|
||||
nTotalColumns = ( GetWidth() - 1 ) / ( nLongestCmd + 1 );
|
||||
nCurrentColumn = 0;
|
||||
|
||||
PrintRaw( "\n" );
|
||||
|
||||
// Would be nice if these were sorted, but not that big a deal
|
||||
pszCurrentCmd = matches[0];
|
||||
i = 0;
|
||||
while ( pszCurrentCmd )
|
||||
{
|
||||
char szFormatCmd[ 256 ];
|
||||
|
||||
nCurrentColumn++;
|
||||
|
||||
if ( nCurrentColumn > nTotalColumns )
|
||||
{
|
||||
PrintRaw( "\n" );
|
||||
nCurrentColumn = 1;
|
||||
}
|
||||
|
||||
Q_snprintf( szFormatCmd, sizeof(szFormatCmd), "%-*s ", nLongestCmd, pszCurrentCmd );
|
||||
PrintRaw( szFormatCmd );
|
||||
|
||||
i++;
|
||||
pszCurrentCmd = matches[i];
|
||||
}
|
||||
|
||||
PrintRaw( "\n" );
|
||||
PrintRaw( m_szConsoleText );
|
||||
// TODO: Tack on 'common' chars in all the matches, i.e. if I typed 'con' and all the
|
||||
// matches begin with 'connect_' then print the matches but also complete the
|
||||
// command up to that point at least.
|
||||
}
|
||||
|
||||
m_nCursorPosition = m_nConsoleTextLen;
|
||||
m_nBrowseLine = m_nInputLine;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CTextConsoleWin32::ReceiveStandardChar( const char ch )
|
||||
{
|
||||
int nCount;
|
||||
|
||||
// If the line buffer is maxed out, ignore this char
|
||||
if ( m_nConsoleTextLen >= ( sizeof( m_szConsoleText ) - 2 ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nCount = m_nConsoleTextLen;
|
||||
while ( nCount > m_nCursorPosition )
|
||||
{
|
||||
m_szConsoleText[ nCount ] = m_szConsoleText[ nCount - 1 ];
|
||||
nCount--;
|
||||
}
|
||||
|
||||
m_szConsoleText[ m_nCursorPosition ] = ch;
|
||||
|
||||
PrintRaw( m_szConsoleText + m_nCursorPosition, m_nConsoleTextLen - m_nCursorPosition + 1 );
|
||||
|
||||
m_nConsoleTextLen++;
|
||||
m_nCursorPosition++;
|
||||
|
||||
nCount = m_nConsoleTextLen;
|
||||
while ( nCount > m_nCursorPosition )
|
||||
{
|
||||
PrintRaw( "\b" );
|
||||
nCount--;
|
||||
}
|
||||
|
||||
m_nBrowseLine = m_nInputLine;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::ReceiveUpArrow( void )
|
||||
{
|
||||
int nLastCommandInHistory;
|
||||
|
||||
nLastCommandInHistory = m_nInputLine + 1;
|
||||
if ( nLastCommandInHistory > m_nTotalLines )
|
||||
{
|
||||
nLastCommandInHistory = 0;
|
||||
}
|
||||
|
||||
if ( m_nBrowseLine == nLastCommandInHistory )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_nBrowseLine == m_nInputLine )
|
||||
{
|
||||
if ( m_nConsoleTextLen > 0 )
|
||||
{
|
||||
// Save off current text
|
||||
strncpy( m_szSavedConsoleText, m_szConsoleText, m_nConsoleTextLen );
|
||||
// No terminator, it's a raw buffer we always know the length of
|
||||
}
|
||||
|
||||
m_nSavedConsoleTextLen = m_nConsoleTextLen;
|
||||
}
|
||||
|
||||
m_nBrowseLine--;
|
||||
if ( m_nBrowseLine < 0 )
|
||||
{
|
||||
m_nBrowseLine = m_nTotalLines - 1;
|
||||
}
|
||||
|
||||
while ( m_nConsoleTextLen-- ) // delete old line
|
||||
{
|
||||
PrintRaw( "\b \b" );
|
||||
}
|
||||
|
||||
// copy buffered line
|
||||
PrintRaw( m_aszLineBuffer[ m_nBrowseLine ] );
|
||||
|
||||
strncpy( m_szConsoleText, m_aszLineBuffer[ m_nBrowseLine ], MAX_CONSOLE_TEXTLEN );
|
||||
m_nConsoleTextLen = strlen( m_aszLineBuffer[ m_nBrowseLine ] );
|
||||
|
||||
m_nCursorPosition = m_nConsoleTextLen;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::ReceiveDownArrow( void )
|
||||
{
|
||||
if ( m_nBrowseLine == m_nInputLine )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_nBrowseLine++;
|
||||
if ( m_nBrowseLine > m_nTotalLines )
|
||||
{
|
||||
m_nBrowseLine = 0;
|
||||
}
|
||||
|
||||
while ( m_nConsoleTextLen-- ) // delete old line
|
||||
{
|
||||
PrintRaw( "\b \b" );
|
||||
}
|
||||
|
||||
if ( m_nBrowseLine == m_nInputLine )
|
||||
{
|
||||
if ( m_nSavedConsoleTextLen > 0 )
|
||||
{
|
||||
// Restore current text
|
||||
strncpy( m_szConsoleText, m_szSavedConsoleText, m_nSavedConsoleTextLen );
|
||||
// No terminator, it's a raw buffer we always know the length of
|
||||
|
||||
PrintRaw( m_szConsoleText, m_nSavedConsoleTextLen );
|
||||
}
|
||||
|
||||
m_nConsoleTextLen = m_nSavedConsoleTextLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy buffered line
|
||||
PrintRaw( m_aszLineBuffer[ m_nBrowseLine ] );
|
||||
|
||||
strncpy( m_szConsoleText, m_aszLineBuffer[ m_nBrowseLine ], MAX_CONSOLE_TEXTLEN );
|
||||
|
||||
m_nConsoleTextLen = strlen( m_aszLineBuffer[ m_nBrowseLine ] );
|
||||
}
|
||||
|
||||
m_nCursorPosition = m_nConsoleTextLen;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::ReceiveLeftArrow( void )
|
||||
{
|
||||
if ( m_nCursorPosition == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PrintRaw( "\b" );
|
||||
m_nCursorPosition--;
|
||||
}
|
||||
|
||||
|
||||
void CTextConsoleWin32::ReceiveRightArrow( void )
|
||||
{
|
||||
if ( m_nCursorPosition == m_nConsoleTextLen )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PrintRaw( m_szConsoleText + m_nCursorPosition, 1 );
|
||||
m_nCursorPosition++;
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
82
dedicated/console/TextConsoleWin32.h
Normal file
82
dedicated/console/TextConsoleWin32.h
Normal file
@ -0,0 +1,82 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// TextConsoleWin32.h: Win32 interface for the TextConsole class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if !defined TEXTCONSOLE_WIN32_H
|
||||
#define TEXTCONSOLE_WIN32_H
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include "TextConsole.h"
|
||||
|
||||
#define MAX_CONSOLE_TEXTLEN 256
|
||||
#define MAX_BUFFER_LINES 30
|
||||
|
||||
class CTextConsoleWin32 : public CTextConsole
|
||||
{
|
||||
public:
|
||||
CTextConsoleWin32();
|
||||
virtual ~CTextConsoleWin32() { };
|
||||
|
||||
// CTextConsole
|
||||
bool Init();
|
||||
void ShutDown( void );
|
||||
void Print( char *pszMsg );
|
||||
|
||||
void SetTitle( char * pszTitle );
|
||||
void SetStatusLine( char * pszStatus );
|
||||
void UpdateStatus( void );
|
||||
|
||||
char * GetLine( int index, char *buf, int buflen );
|
||||
int GetWidth( void );
|
||||
|
||||
void SetVisible( bool visible );
|
||||
|
||||
protected:
|
||||
// CTextConsoleWin32
|
||||
void SetColor( WORD );
|
||||
void PrintRaw( const char * pszMsg, int nChars = -1 );
|
||||
|
||||
private:
|
||||
char m_szConsoleText[ MAX_CONSOLE_TEXTLEN ]; // console text buffer
|
||||
int m_nConsoleTextLen; // console textbuffer length
|
||||
int m_nCursorPosition; // position in the current input line
|
||||
|
||||
// Saved input data when scrolling back through command history
|
||||
char m_szSavedConsoleText[ MAX_CONSOLE_TEXTLEN ]; // console text buffer
|
||||
int m_nSavedConsoleTextLen; // console textbuffer length
|
||||
|
||||
char m_aszLineBuffer[ MAX_BUFFER_LINES ][ MAX_CONSOLE_TEXTLEN ]; // command buffer last MAX_BUFFER_LINES commands
|
||||
int m_nInputLine; // Current line being entered
|
||||
int m_nBrowseLine; // current buffer line for up/down arrow
|
||||
int m_nTotalLines; // # of nonempty lines in the buffer
|
||||
|
||||
int ReceiveNewline( void );
|
||||
void ReceiveBackspace( void );
|
||||
void ReceiveTab( void );
|
||||
void ReceiveStandardChar( const char ch );
|
||||
void ReceiveUpArrow( void );
|
||||
void ReceiveDownArrow( void );
|
||||
void ReceiveLeftArrow( void );
|
||||
void ReceiveRightArrow( void );
|
||||
|
||||
private:
|
||||
HANDLE hinput; // standard input handle
|
||||
HANDLE houtput; // standard output handle
|
||||
WORD Attrib; // attrib colours for status bar
|
||||
|
||||
char statusline[81]; // first line in console is status line
|
||||
};
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#endif // !defined TEXTCONSOLE_WIN32_H
|
428
dedicated/console/conproc.cpp
Normal file
428
dedicated/console/conproc.cpp
Normal file
@ -0,0 +1,428 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#ifdef _WIN32
|
||||
// conproc.c -- support for qhost
|
||||
#include <stdio.h>
|
||||
#include <process.h>
|
||||
#include <windows.h>
|
||||
#include "conproc.h"
|
||||
#include "isys.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "tier1/strtools.h"
|
||||
|
||||
static HANDLE heventDone;
|
||||
static HANDLE hfileBuffer;
|
||||
static HANDLE heventChildSend;
|
||||
static HANDLE heventParentSend;
|
||||
static HANDLE hStdout;
|
||||
static HANDLE hStdin;
|
||||
|
||||
/*
|
||||
==============
|
||||
SetConsoleCXCY
|
||||
|
||||
==============
|
||||
*/
|
||||
BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
COORD coordMax;
|
||||
|
||||
coordMax = GetLargestConsoleWindowSize(hStdout);
|
||||
|
||||
if (cy > coordMax.Y)
|
||||
cy = coordMax.Y;
|
||||
|
||||
if (cx > coordMax.X)
|
||||
cx = coordMax.X;
|
||||
|
||||
if (!GetConsoleScreenBufferInfo(hStdout, &info))
|
||||
return FALSE;
|
||||
|
||||
// height
|
||||
info.srWindow.Left = 0;
|
||||
info.srWindow.Right = info.dwSize.X - 1;
|
||||
info.srWindow.Top = 0;
|
||||
info.srWindow.Bottom = cy - 1;
|
||||
|
||||
if (cy < info.dwSize.Y)
|
||||
{
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
|
||||
info.dwSize.Y = cy;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
}
|
||||
else if (cy > info.dwSize.Y)
|
||||
{
|
||||
info.dwSize.Y = cy;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!GetConsoleScreenBufferInfo(hStdout, &info))
|
||||
return FALSE;
|
||||
|
||||
// width
|
||||
info.srWindow.Left = 0;
|
||||
info.srWindow.Right = cx - 1;
|
||||
info.srWindow.Top = 0;
|
||||
info.srWindow.Bottom = info.dwSize.Y - 1;
|
||||
|
||||
if (cx < info.dwSize.X)
|
||||
{
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
|
||||
info.dwSize.X = cx;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
}
|
||||
else if (cx > info.dwSize.X)
|
||||
{
|
||||
info.dwSize.X = cx;
|
||||
|
||||
if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
|
||||
return FALSE;
|
||||
|
||||
if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
GetMappedBuffer
|
||||
|
||||
==============
|
||||
*/
|
||||
LPVOID GetMappedBuffer (HANDLE hfileBuffer)
|
||||
{
|
||||
LPVOID pBuffer;
|
||||
|
||||
pBuffer = MapViewOfFile (hfileBuffer,
|
||||
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ReleaseMappedBuffer
|
||||
|
||||
==============
|
||||
*/
|
||||
void ReleaseMappedBuffer (LPVOID pBuffer)
|
||||
{
|
||||
UnmapViewOfFile (pBuffer);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
GetScreenBufferLines
|
||||
|
||||
==============
|
||||
*/
|
||||
BOOL GetScreenBufferLines (int *piLines)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
BOOL bRet;
|
||||
|
||||
bRet = GetConsoleScreenBufferInfo (hStdout, &info);
|
||||
|
||||
if (bRet)
|
||||
*piLines = info.dwSize.Y;
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SetScreenBufferLines
|
||||
|
||||
==============
|
||||
*/
|
||||
BOOL SetScreenBufferLines (int iLines)
|
||||
{
|
||||
return SetConsoleCXCY (hStdout, 80, iLines);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ReadText
|
||||
|
||||
==============
|
||||
*/
|
||||
BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
|
||||
{
|
||||
COORD coord;
|
||||
DWORD dwRead;
|
||||
BOOL bRet;
|
||||
|
||||
coord.X = 0;
|
||||
coord.Y = iBeginLine;
|
||||
|
||||
bRet = ReadConsoleOutputCharacter(
|
||||
hStdout,
|
||||
pszText,
|
||||
80 * (iEndLine - iBeginLine + 1),
|
||||
coord,
|
||||
&dwRead);
|
||||
|
||||
// Make sure it's null terminated.
|
||||
if (bRet)
|
||||
pszText[dwRead] = '\0';
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CharToCode
|
||||
|
||||
==============
|
||||
*/
|
||||
int CharToCode (char c)
|
||||
{
|
||||
char upper;
|
||||
|
||||
upper = toupper(c);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 13:
|
||||
return 28;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (V_isalpha(c))
|
||||
return (30 + upper - 65);
|
||||
|
||||
if (V_isdigit(c))
|
||||
return (1 + upper - 47);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
WriteText
|
||||
|
||||
==============
|
||||
*/
|
||||
BOOL WriteText (LPCTSTR szText)
|
||||
{
|
||||
DWORD dwWritten;
|
||||
INPUT_RECORD rec;
|
||||
char upper, *sz;
|
||||
|
||||
sz = (LPTSTR) szText;
|
||||
|
||||
while (*sz)
|
||||
{
|
||||
// 13 is the code for a carriage return (\n) instead of 10.
|
||||
if (*sz == 10)
|
||||
*sz = 13;
|
||||
|
||||
upper = toupper(*sz);
|
||||
|
||||
rec.EventType = KEY_EVENT;
|
||||
rec.Event.KeyEvent.bKeyDown = TRUE;
|
||||
rec.Event.KeyEvent.wRepeatCount = 1;
|
||||
rec.Event.KeyEvent.wVirtualKeyCode = upper;
|
||||
rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
|
||||
rec.Event.KeyEvent.uChar.AsciiChar = *sz;
|
||||
rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
|
||||
rec.Event.KeyEvent.dwControlKeyState = V_isupper(*sz) ? 0x80 : 0x0;
|
||||
|
||||
WriteConsoleInput(
|
||||
hStdin,
|
||||
&rec,
|
||||
1,
|
||||
&dwWritten);
|
||||
|
||||
rec.Event.KeyEvent.bKeyDown = FALSE;
|
||||
|
||||
WriteConsoleInput(
|
||||
hStdin,
|
||||
&rec,
|
||||
1,
|
||||
&dwWritten);
|
||||
|
||||
sz++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
RequestProc
|
||||
|
||||
==============
|
||||
*/
|
||||
unsigned _stdcall RequestProc (void *arg)
|
||||
{
|
||||
int *pBuffer;
|
||||
DWORD dwRet;
|
||||
HANDLE heventWait[2];
|
||||
int iBeginLine, iEndLine;
|
||||
|
||||
heventWait[0] = heventParentSend;
|
||||
heventWait[1] = heventDone;
|
||||
|
||||
while (1)
|
||||
{
|
||||
dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE);
|
||||
|
||||
// heventDone fired, so we're exiting.
|
||||
if (dwRet == WAIT_OBJECT_0 + 1)
|
||||
break;
|
||||
|
||||
pBuffer = (int *) GetMappedBuffer (hfileBuffer);
|
||||
|
||||
// hfileBuffer is invalid. Just leave.
|
||||
if (!pBuffer)
|
||||
{
|
||||
sys->Printf ("Request Proc: Invalid -HFILE handle\n");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pBuffer[0])
|
||||
{
|
||||
case CCOM_WRITE_TEXT:
|
||||
// Param1 : Text
|
||||
pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
|
||||
break;
|
||||
|
||||
case CCOM_GET_TEXT:
|
||||
// Param1 : Begin line
|
||||
// Param2 : End line
|
||||
iBeginLine = pBuffer[1];
|
||||
iEndLine = pBuffer[2];
|
||||
pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine,
|
||||
iEndLine);
|
||||
break;
|
||||
|
||||
case CCOM_GET_SCR_LINES:
|
||||
// No params
|
||||
pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
|
||||
break;
|
||||
|
||||
case CCOM_SET_SCR_LINES:
|
||||
// Param1 : Number of lines
|
||||
pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
ReleaseMappedBuffer (pBuffer);
|
||||
SetEvent (heventChildSend);
|
||||
}
|
||||
|
||||
_endthreadex (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
DeinitConProc
|
||||
|
||||
==============
|
||||
*/
|
||||
void DeinitConProc (void)
|
||||
{
|
||||
if ( heventDone )
|
||||
{
|
||||
SetEvent ( heventDone );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
InitConProc
|
||||
|
||||
==============
|
||||
*/
|
||||
void InitConProc ( void )
|
||||
{
|
||||
unsigned threadAddr;
|
||||
HANDLE hFile = (HANDLE)0;
|
||||
HANDLE heventParent = (HANDLE)0;
|
||||
HANDLE heventChild = (HANDLE)0;
|
||||
int WantHeight = 50;
|
||||
const char *p;
|
||||
|
||||
// give external front ends a chance to hook into the console
|
||||
if ( CommandLine()->CheckParm ( "-HFILE", &p ) && p )
|
||||
{
|
||||
hFile = (HANDLE)atoi ( p );
|
||||
}
|
||||
|
||||
if ( CommandLine()->CheckParm ( "-HPARENT", &p ) && p )
|
||||
{
|
||||
heventParent = (HANDLE)atoi ( p );
|
||||
}
|
||||
|
||||
if ( CommandLine()->CheckParm ( "-HCHILD", &p ) && p )
|
||||
{
|
||||
heventChild = (HANDLE)atoi ( p );
|
||||
}
|
||||
|
||||
// ignore if we don't have all the events.
|
||||
if ( !hFile || !heventParent || !heventChild )
|
||||
{
|
||||
//sys->Printf ("\n\nNo external front end present.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
sys->Printf( "\n\nInitConProc: Setting up external control.\n" );
|
||||
|
||||
hfileBuffer = hFile;
|
||||
heventParentSend = heventParent;
|
||||
heventChildSend = heventChild;
|
||||
|
||||
// So we'll know when to go away.
|
||||
heventDone = CreateEvent (NULL, FALSE, FALSE, NULL);
|
||||
if (!heventDone)
|
||||
{
|
||||
sys->Printf ("InitConProc: Couldn't create heventDone\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_beginthreadex (NULL, 0, RequestProc, NULL, 0, &threadAddr))
|
||||
{
|
||||
CloseHandle (heventDone);
|
||||
sys->Printf ("InitConProc: Couldn't create third party thread\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// save off the input/output handles.
|
||||
hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
hStdin = GetStdHandle (STD_INPUT_HANDLE);
|
||||
|
||||
if ( CommandLine()->CheckParm( "-conheight", &p ) && p )
|
||||
{
|
||||
WantHeight = atoi( p );
|
||||
}
|
||||
|
||||
// Force 80 character width, at least 25 character height
|
||||
SetConsoleCXCY( hStdout, 80, WantHeight );
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
30
dedicated/console/conproc.h
Normal file
30
dedicated/console/conproc.h
Normal file
@ -0,0 +1,30 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// conproc.h -- support for external server monitoring programs
|
||||
#ifndef INC_CONPROCH
|
||||
#define INC_CONPROCH
|
||||
|
||||
#define CCOM_WRITE_TEXT 0x2
|
||||
// Param1 : Text
|
||||
|
||||
#define CCOM_GET_TEXT 0x3
|
||||
// Param1 : Begin line
|
||||
// Param2 : End line
|
||||
|
||||
#define CCOM_GET_SCR_LINES 0x4
|
||||
// No params
|
||||
|
||||
#define CCOM_SET_SCR_LINES 0x5
|
||||
// Param1 : Number of lines
|
||||
|
||||
void InitConProc ( void );
|
||||
void DeinitConProc ( void );
|
||||
|
||||
void WriteStatusText( char *psz );
|
||||
|
||||
#endif // !INC_CONPROCH
|
22
dedicated/console/textconsole.cpp
Normal file
22
dedicated/console/textconsole.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
// TextConsole.cpp: implementation of the TextConsole class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "textconsole.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool CTextConsole::Init()
|
||||
{
|
||||
m_ConsoleVisible = true;
|
||||
return true;
|
||||
}
|
38
dedicated/console/textconsole.h
Normal file
38
dedicated/console/textconsole.h
Normal file
@ -0,0 +1,38 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#if !defined TEXTCONSOLE_H
|
||||
#define TEXTCONSOLE_H
|
||||
#pragma once
|
||||
|
||||
class CTextConsole
|
||||
{
|
||||
public:
|
||||
CTextConsole() : m_ConsoleVisible( true ) {}
|
||||
virtual ~CTextConsole() {};
|
||||
|
||||
virtual bool Init ();
|
||||
virtual void ShutDown() = 0;
|
||||
virtual void Print( char * pszMsg ) = 0;
|
||||
|
||||
virtual void SetTitle( char * pszTitle ) = 0;
|
||||
virtual void SetStatusLine( char * pszStatus ) = 0;
|
||||
virtual void UpdateStatus() = 0;
|
||||
|
||||
// Must be provided by children
|
||||
virtual char * GetLine( int index, char *buf, int buflen ) = 0;
|
||||
virtual int GetWidth() = 0;
|
||||
|
||||
virtual void SetVisible( bool visible ) { m_ConsoleVisible = visible; }
|
||||
virtual bool IsVisible() { return m_ConsoleVisible; }
|
||||
|
||||
protected:
|
||||
bool m_ConsoleVisible;
|
||||
};
|
||||
|
||||
#endif // !defined TEXTCONSOLE_H
|
78
dedicated/dedicated.h
Normal file
78
dedicated/dedicated.h
Normal file
@ -0,0 +1,78 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// Purpose: Defines a group of app systems that all have the same lifetime
|
||||
// that need to be connected/initialized, etc. in a well-defined order
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef DEDICATED_H
|
||||
#define DEDICATED_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "appframework/tier3app.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward declarations
|
||||
//-----------------------------------------------------------------------------
|
||||
class IDedicatedServerAPI;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Singleton interfaces
|
||||
//-----------------------------------------------------------------------------
|
||||
extern IDedicatedServerAPI *engine;
|
||||
|
||||
|
||||
extern char g_szEXEName[ MAX_PATH ];
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Inner loop: initialize, shutdown main systems, load steam to
|
||||
//-----------------------------------------------------------------------------
|
||||
#ifdef POSIX
|
||||
#define DEDICATED_BASECLASS CTier2SteamApp
|
||||
#else
|
||||
#define DEDICATED_BASECLASS CVguiSteamApp
|
||||
#endif
|
||||
|
||||
class CDedicatedAppSystemGroup : public DEDICATED_BASECLASS
|
||||
{
|
||||
typedef DEDICATED_BASECLASS BaseClass;
|
||||
|
||||
public:
|
||||
// Methods of IApplication
|
||||
virtual bool Create( );
|
||||
virtual bool PreInit( );
|
||||
virtual int Main( );
|
||||
virtual void PostShutdown();
|
||||
virtual void Destroy();
|
||||
|
||||
// Used to chain to base class
|
||||
AppModule_t LoadModule( CreateInterfaceFn factory )
|
||||
{
|
||||
return CSteamAppSystemGroup::LoadModule( factory );
|
||||
}
|
||||
|
||||
// Method to add various global singleton systems
|
||||
bool AddSystems( AppSystemInfo_t *pSystems )
|
||||
{
|
||||
return CSteamAppSystemGroup::AddSystems( pSystems );
|
||||
}
|
||||
|
||||
void *FindSystem( const char *pInterfaceName )
|
||||
{
|
||||
return CSteamAppSystemGroup::FindSystem( pInterfaceName );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // DEDICATED_H
|
72
dedicated/dedicated.rc
Normal file
72
dedicated/dedicated.rc
Normal file
@ -0,0 +1,72 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_HALFLIFE ICON DISCARDABLE "..\\launcher\\res\\launcher.ico"
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
149
dedicated/dedicated.vpc
Normal file
149
dedicated/dedicated.vpc
Normal file
@ -0,0 +1,149 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEDICATED.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR ".."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
|
||||
$include "$SRCDIR\vpc_scripts\source_cryptlib_include.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE,.\,$SRCDIR\engine"
|
||||
$PreprocessorDefinitions "$BASE;DEDICATED;LAUNCHERONLY;SUPPORT_PACKED_STORE"
|
||||
}
|
||||
|
||||
$Linker
|
||||
{
|
||||
$AdditionalDependencies "$BASE wsock32.lib odbc32.lib odbccp32.lib winmm.lib"
|
||||
$SystemLibraries "iconv;edit;curses" [$OSXALL]
|
||||
$SystemFrameworks "AppKit" [$OSXALL]
|
||||
}
|
||||
}
|
||||
|
||||
$Project "Dedicated"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "dedicated.rc"
|
||||
$File "sys_linux.cpp"
|
||||
{
|
||||
$Configuration
|
||||
{
|
||||
$ExcludedFromBuild "Yes"
|
||||
}
|
||||
}
|
||||
$File "filesystem.cpp"
|
||||
$File "$SRCDIR\public\filesystem_init.cpp"
|
||||
$File "$SRCDIR\common\netapi.cpp"
|
||||
$File "$SRCDIR\common\SteamAppStartup.cpp"
|
||||
$File "sys_common.cpp"
|
||||
$File "sys_ded.cpp"
|
||||
$File "sys_windows.cpp" [$WINDOWS]
|
||||
$File "sys_linux.cpp" [$POSIX]
|
||||
{
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalOptions "/EHa"
|
||||
$EnableC++Exceptions "Yes (/EHsc)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$Folder "Console"
|
||||
{
|
||||
$File "console\conproc.cpp"
|
||||
$File "console\textconsole.cpp"
|
||||
$File "console\TextConsoleUnix.cpp" [$POSIX]
|
||||
$File "console\TextConsoleWin32.cpp" [$WINDOWS]
|
||||
}
|
||||
|
||||
$Folder "VGUI" [$WINDOWS]
|
||||
{
|
||||
$File "vgui\CreateMultiplayerGameServerPage.cpp"
|
||||
$File "vgui\MainPanel.cpp"
|
||||
$File "$SRCDIR\public\vgui_controls\vgui_controls.cpp"
|
||||
$File "vgui\vguihelpers.cpp"
|
||||
}
|
||||
|
||||
$Folder "FileSystem"
|
||||
{
|
||||
$File "$SRCDIR\filesystem\filetracker.cpp"
|
||||
$File "$SRCDIR\filesystem\basefilesystem.cpp"
|
||||
$File "$SRCDIR\filesystem\packfile.cpp"
|
||||
$File "$SRCDIR\filesystem\filesystem_async.cpp"
|
||||
$File "$SRCDIR\filesystem\filesystem_stdio.cpp"
|
||||
$File "$SRCDIR\filesystem\QueuedLoader.cpp"
|
||||
$File "$SRCDIR\public\zip_utils.cpp"
|
||||
$File "$SRCDIR\filesystem\linux_support.cpp" [$POSIX]
|
||||
}
|
||||
}
|
||||
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$File "$SRCDIR\filesystem\filetracker.h"
|
||||
$File "$SRCDIR\filesystem\threadsaferefcountedobject.h"
|
||||
$File "$SRCDIR\public\ifilelist.h"
|
||||
$File "$SRCDIR\public\tier0\basetypes.h"
|
||||
$File "$SRCDIR\public\tier0\commonmacros.h"
|
||||
$File "$SRCDIR\public\tier0\dbg.h"
|
||||
$File "dedicated.h"
|
||||
$File "$SRCDIR\public\engine_hlds_api.h"
|
||||
$File "$SRCDIR\public\tier0\fasttimer.h"
|
||||
$File "$SRCDIR\public\filesystem.h"
|
||||
$File "$SRCDIR\common\IAdminServer.h"
|
||||
$File "$SRCDIR\public\appframework\IAppSystem.h"
|
||||
$File "$SRCDIR\public\tier0\icommandline.h"
|
||||
$File "$SRCDIR\public\idedicatedexports.h"
|
||||
$File "$SRCDIR\common\IManageServer.h"
|
||||
$File "$SRCDIR\public\tier1\interface.h"
|
||||
$File "isys.h"
|
||||
$File "$SRCDIR\public\mathlib\mathlib.h"
|
||||
$File "$SRCDIR\common\netapi.h"
|
||||
$File "$SRCDIR\common\GameUI\ObjectList.h"
|
||||
$File "$SRCDIR\public\tier0\platform.h"
|
||||
$File "$SRCDIR\public\tier0\protected_things.h"
|
||||
$File "$SRCDIR\common\SteamAppStartup.h"
|
||||
$File "$SRCDIR\public\string_t.h"
|
||||
$File "$SRCDIR\public\tier1\strtools.h"
|
||||
$File "$SRCDIR\public\tier0\vcr_shared.h"
|
||||
$File "$SRCDIR\public\tier0\vcrmode.h"
|
||||
$File "$SRCDIR\public\mathlib\vector.h"
|
||||
$File "$SRCDIR\public\mathlib\vector2d.h"
|
||||
$File "$SRCDIR\public\vstdlib\vstdlib.h"
|
||||
|
||||
$Folder "Console Headers"
|
||||
{
|
||||
$File "console\conproc.h"
|
||||
$File "$SRCDIR\common\IObjectContainer.h"
|
||||
$File "console\textconsole.h"
|
||||
$File "console\TextConsoleWin32.h"
|
||||
}
|
||||
|
||||
$Folder "VGUI Headers"
|
||||
{
|
||||
$File "vgui\CreateMultiplayerGameServerPage.h"
|
||||
$File "vgui\MainPanel.h"
|
||||
$File "vgui\vguihelpers.h"
|
||||
}
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$Lib appframework
|
||||
$Lib mathlib
|
||||
$Lib tier2
|
||||
$Lib tier3
|
||||
$Lib vgui_controls [$WIN32]
|
||||
$LibExternal "$SRCDIR/thirdparty/libedit-3.1/src/.libs/libedit" [$LINUXALL]
|
||||
$ImpLibExternal steam_api
|
||||
$ImpLib SDL2 [$SDL]
|
||||
}
|
||||
}
|
56
dedicated/filesystem.cpp
Normal file
56
dedicated/filesystem.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $Workfile: $
|
||||
// $Date: $
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
|
||||
#include "filesystem.h"
|
||||
#include "dedicated.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "interface.h"
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "../filesystem/basefilesystem.h"
|
||||
#include "appframework/AppFramework.h"
|
||||
#include "tier2/tier2.h"
|
||||
|
||||
|
||||
extern IFileSystem *g_pFileSystem;
|
||||
extern IBaseFileSystem *g_pBaseFileSystem;
|
||||
|
||||
// implement our own special factory that we don't export outside of the DLL, to stop
|
||||
// people being able to get a pointer to a FILESYSTEM_INTERFACE_VERSION stdio interface
|
||||
void* FileSystemFactory(const char *pName, int *pReturnCode)
|
||||
{
|
||||
{
|
||||
if ( !Q_stricmp(pName, FILESYSTEM_INTERFACE_VERSION ) )
|
||||
{
|
||||
if ( pReturnCode )
|
||||
{
|
||||
*pReturnCode = IFACE_OK;
|
||||
}
|
||||
return g_pFileSystem;
|
||||
}
|
||||
if ( !Q_stricmp(pName, BASEFILESYSTEM_INTERFACE_VERSION ) )
|
||||
{
|
||||
if ( pReturnCode )
|
||||
{
|
||||
*pReturnCode = IFACE_OK;
|
||||
}
|
||||
return g_pBaseFileSystem;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pReturnCode )
|
||||
{
|
||||
*pReturnCode = IFACE_FAILED;
|
||||
}
|
||||
return NULL;
|
||||
}
|
45
dedicated/isys.h
Normal file
45
dedicated/isys.h
Normal file
@ -0,0 +1,45 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
#if !defined( ISYS_H )
|
||||
#define ISYS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
class CDedicatedAppSystemGroup;
|
||||
|
||||
|
||||
abstract_class ISys
|
||||
{
|
||||
public:
|
||||
virtual ~ISys( void ) { }
|
||||
|
||||
virtual bool LoadModules( CDedicatedAppSystemGroup *pAppSystemGroup ) = 0;
|
||||
|
||||
virtual void Sleep( int msec ) = 0;
|
||||
virtual bool GetExecutableName( char *out ) = 0;
|
||||
virtual void ErrorMessage( int level, const char *msg ) = 0;
|
||||
|
||||
virtual void WriteStatusText( char *szText ) = 0;
|
||||
virtual void UpdateStatus( int force ) = 0;
|
||||
|
||||
virtual long LoadLibrary( char *lib ) = 0;
|
||||
virtual void FreeLibrary( long library ) = 0;
|
||||
|
||||
virtual bool CreateConsoleWindow( void ) = 0;
|
||||
virtual void DestroyConsoleWindow( void ) = 0;
|
||||
|
||||
virtual void ConsoleOutput ( char *string ) = 0;
|
||||
virtual char *ConsoleInput ( int index, char *buf, int buflen ) = 0;
|
||||
virtual void Printf( PRINTF_FORMAT_STRING const char *fmt, ...) FMTFUNCTION( 2, 3 ) = 0;
|
||||
};
|
||||
|
||||
extern ISys *sys;
|
||||
|
||||
#endif // ISYS_H
|
25
dedicated/resource.h
Normal file
25
dedicated/resource.h
Normal file
@ -0,0 +1,25 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by Dedicated.rc
|
||||
//
|
||||
#define IDI_HALFLIFE 101
|
||||
#define IDD_CDKEY 102
|
||||
#define IDC_KEY 1000
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 105
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
300
dedicated/sys_common.cpp
Normal file
300
dedicated/sys_common.cpp
Normal file
@ -0,0 +1,300 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//===========================================================================//
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif POSIX
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "isys.h"
|
||||
#include "dedicated.h"
|
||||
#include "engine_hlds_api.h"
|
||||
#include "filesystem.h"
|
||||
#include "tier0/vcrmode.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "idedicatedexports.h"
|
||||
#include "vgui/vguihelpers.h"
|
||||
|
||||
static long hDLLThirdParty = 0L;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Modules...
|
||||
//-----------------------------------------------------------------------------
|
||||
CSysModule *s_hMatSystemModule = NULL;
|
||||
CSysModule *s_hEngineModule = NULL;
|
||||
CSysModule *s_hSoundEmitterModule = NULL;
|
||||
|
||||
CreateInterfaceFn s_MaterialSystemFactory;
|
||||
CreateInterfaceFn s_EngineFactory;
|
||||
CreateInterfaceFn s_SoundEmitterFactory;
|
||||
|
||||
/*
|
||||
==============
|
||||
Load3rdParty
|
||||
|
||||
Load support for third party .dlls ( gamehost )
|
||||
==============
|
||||
*/
|
||||
void Load3rdParty( void )
|
||||
{
|
||||
// Only do this if the server operator wants the support.
|
||||
// ( In case of malicious code, too )
|
||||
if ( CommandLine()->CheckParm( "-usegh" ) )
|
||||
{
|
||||
hDLLThirdParty = sys->LoadLibrary( "ghostinj.dll" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
EF_VID_ForceUnlockedAndReturnState
|
||||
|
||||
Dummy funcion called by engine
|
||||
==============
|
||||
*/
|
||||
int EF_VID_ForceUnlockedAndReturnState(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
EF_VID_ForceLockState
|
||||
|
||||
Dummy funcion called by engine
|
||||
==============
|
||||
*/
|
||||
void EF_VID_ForceLockState(int)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
InitInstance
|
||||
|
||||
==============
|
||||
*/
|
||||
bool InitInstance( )
|
||||
{
|
||||
Load3rdParty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ProcessConsoleInput
|
||||
|
||||
==============
|
||||
*/
|
||||
int ProcessConsoleInput(void)
|
||||
{
|
||||
char *s;
|
||||
int count = 0;
|
||||
|
||||
if ( engine )
|
||||
{
|
||||
do
|
||||
{
|
||||
char szBuf[ 256 ];
|
||||
s = sys->ConsoleInput( count++, szBuf, sizeof( szBuf ) );
|
||||
if (s && s[0] )
|
||||
{
|
||||
V_strcat_safe( szBuf, "\n" );
|
||||
engine->AddConsoleText ( szBuf );
|
||||
}
|
||||
} while (s);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void RunServer( void );
|
||||
|
||||
class CDedicatedExports : public CBaseAppSystem<IDedicatedExports>
|
||||
{
|
||||
public:
|
||||
virtual void Sys_Printf( char *text )
|
||||
{
|
||||
if ( sys )
|
||||
{
|
||||
sys->Printf( "%s", text );
|
||||
}
|
||||
}
|
||||
|
||||
virtual void RunServer()
|
||||
{
|
||||
void RunServer( void );
|
||||
::RunServer();
|
||||
}
|
||||
};
|
||||
|
||||
EXPOSE_SINGLE_INTERFACE( CDedicatedExports, IDedicatedExports, VENGINE_DEDICATEDEXPORTS_API_VERSION );
|
||||
|
||||
static const char *get_consolelog_filename()
|
||||
{
|
||||
static bool s_bInited = false;
|
||||
static char s_consolelog[ MAX_PATH ];
|
||||
|
||||
if ( !s_bInited )
|
||||
{
|
||||
s_bInited = true;
|
||||
|
||||
// Don't do the -consolelog thing if -consoledebug is present.
|
||||
// CTextConsoleUnix::Print() looks for -consoledebug.
|
||||
const char *filename = NULL;
|
||||
if ( !CommandLine()->FindParm( "-consoledebug" ) &&
|
||||
CommandLine()->CheckParm( "-consolelog", &filename ) &&
|
||||
filename )
|
||||
{
|
||||
V_strcpy_safe( s_consolelog, filename );
|
||||
}
|
||||
}
|
||||
|
||||
return s_consolelog;
|
||||
}
|
||||
|
||||
SpewRetval_t DedicatedSpewOutputFunc( SpewType_t spewType, char const *pMsg )
|
||||
{
|
||||
if ( sys )
|
||||
{
|
||||
sys->Printf( "%s", pMsg );
|
||||
|
||||
// If they have specified -consolelog, log this message there. Otherwise these
|
||||
// wind up being lost because Sys_InitGame hasn't been called yet, and
|
||||
// Sys_SpewFunc is the thing that logs stuff to -consolelog, etc.
|
||||
const char *filename = get_consolelog_filename();
|
||||
if ( filename[ 0 ] && pMsg[ 0 ] )
|
||||
{
|
||||
FileHandle_t fh = g_pFullFileSystem->Open( filename, "a" );
|
||||
if ( fh != FILESYSTEM_INVALID_HANDLE )
|
||||
{
|
||||
g_pFullFileSystem->Write( pMsg, V_strlen( pMsg ), fh );
|
||||
g_pFullFileSystem->Close( fh );
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
Plat_DebugString( pMsg );
|
||||
#endif
|
||||
|
||||
if (spewType == SPEW_ERROR)
|
||||
{
|
||||
// In Windows vgui mode, make a message box or they won't ever see the error.
|
||||
#ifdef _WIN32
|
||||
extern bool g_bVGui;
|
||||
if ( g_bVGui )
|
||||
{
|
||||
MessageBox( NULL, pMsg, "Error", MB_OK | MB_TASKMODAL );
|
||||
}
|
||||
TerminateProcess( GetCurrentProcess(), 1 );
|
||||
#elif POSIX
|
||||
fflush(stdout);
|
||||
_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;
|
||||
}
|
||||
|
||||
int Sys_GetExecutableName( char *out )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if ( !::GetModuleFileName( ( HINSTANCE )GetModuleHandle( NULL ), out, 256 ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
strcpy( out, g_szEXEName );
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return the directory where this .exe is running from
|
||||
// Output : char
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *UTIL_GetExecutableDir( )
|
||||
{
|
||||
static char exedir[ MAX_PATH ];
|
||||
|
||||
exedir[ 0 ] = 0;
|
||||
if ( !Sys_GetExecutableName(exedir) )
|
||||
return NULL;
|
||||
|
||||
char *pSlash;
|
||||
char *pSlash2;
|
||||
pSlash = strrchr( exedir,'\\' );
|
||||
pSlash2 = strrchr( exedir,'/' );
|
||||
if ( pSlash2 > pSlash )
|
||||
{
|
||||
pSlash = pSlash2;
|
||||
}
|
||||
if (pSlash)
|
||||
{
|
||||
*pSlash = 0;
|
||||
}
|
||||
|
||||
// Return the bin directory as the executable dir if it's not in there
|
||||
// because that's really where we're running from...
|
||||
int exeLen = strlen(exedir);
|
||||
if ( exedir[exeLen-4] != CORRECT_PATH_SEPARATOR ||
|
||||
exedir[exeLen-3] != 'b' ||
|
||||
exedir[exeLen-2] != 'i' ||
|
||||
exedir[exeLen-1] != 'n' )
|
||||
{
|
||||
Q_strncat( exedir, "\\bin", sizeof( exedir ), COPY_ALL_CHARACTERS );
|
||||
Q_FixSlashes( exedir );
|
||||
}
|
||||
|
||||
return exedir;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return the directory where this .exe is running from
|
||||
// Output : char
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *UTIL_GetBaseDir( void )
|
||||
{
|
||||
static char basedir[ MAX_PATH ];
|
||||
|
||||
char const *pOverrideDir = CommandLine()->CheckParm( "-basedir" );
|
||||
if ( pOverrideDir )
|
||||
return pOverrideDir;
|
||||
|
||||
basedir[ 0 ] = 0;
|
||||
const char *pExeDir = UTIL_GetExecutableDir( );
|
||||
if ( pExeDir )
|
||||
{
|
||||
strcpy( basedir, pExeDir );
|
||||
int dirlen = strlen( basedir );
|
||||
if ( basedir[ dirlen - 3 ] == 'b' &&
|
||||
basedir[ dirlen - 2 ] == 'i' &&
|
||||
basedir[ dirlen - 1 ] == 'n' )
|
||||
{
|
||||
basedir[ dirlen - 4 ] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return basedir;
|
||||
}
|
530
dedicated/sys_ded.cpp
Normal file
530
dedicated/sys_ded.cpp
Normal file
@ -0,0 +1,530 @@
|
||||
//========= 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( );
|
||||
}
|
298
dedicated/sys_linux.cpp
Normal file
298
dedicated/sys_linux.cpp
Normal file
@ -0,0 +1,298 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include "isys.h"
|
||||
#include "console/conproc.h"
|
||||
#include "dedicated.h"
|
||||
#include "engine_hlds_api.h"
|
||||
#include "checksum_md5.h"
|
||||
#include "idedicatedexports.h"
|
||||
#include "tier0/vcrmode.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "mathlib/mathlib.h"
|
||||
#include "interface.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "materialsystem/imaterialsystem.h"
|
||||
#include "istudiorender.h"
|
||||
#include "SoundEmitterSystem/isoundemittersystembase.h"
|
||||
#include "datacache/idatacache.h"
|
||||
#include "datacache/imdlcache.h"
|
||||
#include "vphysics_interface.h"
|
||||
#include "icvar.h"
|
||||
#include "filesystem/IQueuedLoader.h"
|
||||
#include "console/TextConsoleUnix.h"
|
||||
|
||||
bool InitInstance( );
|
||||
|
||||
char g_szEXEName[ MAX_PATH ];
|
||||
|
||||
extern CTextConsoleUnix console;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Implements OS Specific layer ( loosely )
|
||||
//-----------------------------------------------------------------------------
|
||||
class CSys : public ISys
|
||||
{
|
||||
public:
|
||||
virtual ~CSys();
|
||||
|
||||
virtual bool LoadModules( CDedicatedAppSystemGroup *pAppSystemGroup );
|
||||
|
||||
void Sleep( int msec );
|
||||
bool GetExecutableName( char *out );
|
||||
void ErrorMessage( int level, const char *msg );
|
||||
|
||||
void WriteStatusText( char *szText );
|
||||
void UpdateStatus( int force );
|
||||
|
||||
long LoadLibrary( char *lib );
|
||||
void FreeLibrary( long library );
|
||||
void *GetProcAddress( long library, const char *name );
|
||||
|
||||
bool CreateConsoleWindow( void );
|
||||
void DestroyConsoleWindow( void );
|
||||
|
||||
void ConsoleOutput ( char *string );
|
||||
char *ConsoleInput ( int index, char *buf, int buflen );
|
||||
void Printf( const char *fmt, ...);
|
||||
};
|
||||
|
||||
static CSys g_Sys;
|
||||
ISys *sys = &g_Sys;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CSys::~CSys()
|
||||
{
|
||||
sys = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : msec
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSys::Sleep( int msec )
|
||||
{
|
||||
usleep(msec * 1000);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : handle, function name-
|
||||
// Output : void *
|
||||
//-----------------------------------------------------------------------------
|
||||
void *CSys::GetProcAddress( long library, const char *name )
|
||||
{
|
||||
return dlsym( library, name );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *lib -
|
||||
// Output : long
|
||||
//-----------------------------------------------------------------------------
|
||||
long CSys::LoadLibrary( char *lib )
|
||||
{
|
||||
void *hDll = NULL;
|
||||
|
||||
char cwd[1024];
|
||||
char absolute_lib[1024];
|
||||
|
||||
if (!getcwd(cwd, sizeof(cwd)))
|
||||
ErrorMessage(1, "Sys_LoadLibrary: Couldn't determine current directory.");
|
||||
|
||||
if (cwd[strlen(cwd)-1] == '/')
|
||||
cwd[strlen(cwd)-1] = 0;
|
||||
|
||||
Q_snprintf(absolute_lib, sizeof( absolute_lib ), "%s/%s", cwd, lib);
|
||||
|
||||
hDll = dlopen( absolute_lib, RTLD_NOW );
|
||||
if ( !hDll )
|
||||
{
|
||||
ErrorMessage( 1, dlerror() );
|
||||
}
|
||||
return (long)hDll;
|
||||
}
|
||||
|
||||
void CSys::FreeLibrary( long library )
|
||||
{
|
||||
if ( !library )
|
||||
return;
|
||||
|
||||
dlclose( (void *)library );
|
||||
}
|
||||
|
||||
bool CSys::GetExecutableName( char *out )
|
||||
{
|
||||
char *name = strrchr(g_szEXEName, '/' );
|
||||
if ( name )
|
||||
{
|
||||
strcpy( out, name + 1);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ErrorMessage
|
||||
|
||||
Engine is erroring out, display error in message box
|
||||
==============
|
||||
*/
|
||||
void CSys::ErrorMessage( int level, const char *msg )
|
||||
{
|
||||
Error( "%s\n", msg );
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
void CSys::UpdateStatus( int force )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
ConsoleOutput
|
||||
|
||||
Print text to the dedicated console
|
||||
================
|
||||
*/
|
||||
void CSys::ConsoleOutput (char *string)
|
||||
{
|
||||
console.Print(string);
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Printf
|
||||
|
||||
Engine is printing to console
|
||||
==============
|
||||
*/
|
||||
void CSys::Printf( const char *fmt, ...)
|
||||
{
|
||||
// Dump text to debugging console.
|
||||
va_list argptr;
|
||||
char szText[1024];
|
||||
|
||||
va_start (argptr, fmt);
|
||||
Q_vsnprintf (szText, sizeof( szText ), fmt, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
// Get Current text and append it.
|
||||
ConsoleOutput( szText );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
ConsoleInput
|
||||
|
||||
================
|
||||
*/
|
||||
char *CSys::ConsoleInput( int index, char *buf, int buflen )
|
||||
{
|
||||
return console.GetLine( index, buf, buflen );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
WriteStatusText
|
||||
|
||||
==============
|
||||
*/
|
||||
void CSys::WriteStatusText( char *szText )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CreateConsoleWindow
|
||||
|
||||
Create console window ( overridable? )
|
||||
==============
|
||||
*/
|
||||
bool CSys::CreateConsoleWindow( void )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
DestroyConsoleWindow
|
||||
|
||||
==============
|
||||
*/
|
||||
void CSys::DestroyConsoleWindow( void )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
GameInit
|
||||
================
|
||||
*/
|
||||
bool CSys::LoadModules( CDedicatedAppSystemGroup *pAppSystemGroup )
|
||||
{
|
||||
AppSystemInfo_t appSystems[] =
|
||||
{
|
||||
{ "engine" DLL_EXT_STRING, CVAR_QUERY_INTERFACE_VERSION },
|
||||
{ "soundemittersystem" DLL_EXT_STRING, SOUNDEMITTERSYSTEM_INTERFACE_VERSION }, // loaded for backwards compatability, prevents crash on exit for old game dlls
|
||||
{ "materialsystem" DLL_EXT_STRING, MATERIAL_SYSTEM_INTERFACE_VERSION },
|
||||
{ "studiorender" DLL_EXT_STRING, STUDIO_RENDER_INTERFACE_VERSION },
|
||||
{ "vphysics" DLL_EXT_STRING, VPHYSICS_INTERFACE_VERSION },
|
||||
{ "datacache" DLL_EXT_STRING, DATACACHE_INTERFACE_VERSION },
|
||||
{ "datacache" DLL_EXT_STRING, MDLCACHE_INTERFACE_VERSION },
|
||||
{ "datacache" DLL_EXT_STRING, STUDIO_DATA_CACHE_INTERFACE_VERSION },
|
||||
{ "dedicated" DLL_EXT_STRING, QUEUEDLOADER_INTERFACE_VERSION },
|
||||
{ "engine" DLL_EXT_STRING, VENGINE_HLDS_API_VERSION },
|
||||
{ "", "" } // Required to terminate the list
|
||||
};
|
||||
|
||||
if ( !pAppSystemGroup->AddSystems( appSystems ) )
|
||||
return false;
|
||||
|
||||
engine = (IDedicatedServerAPI *)pAppSystemGroup->FindSystem( VENGINE_HLDS_API_VERSION );
|
||||
// obsolete i think SetCVarIF( (ICvar*)pAppSystemGroup->FindSystem( VENGINE_CVAR_INTERFACE_VERSION ) );
|
||||
|
||||
IMaterialSystem* pMaterialSystem = (IMaterialSystem*)pAppSystemGroup->FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION );
|
||||
pMaterialSystem->SetShaderAPI( "shaderapiempty" DLL_EXT_STRING );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NET_Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void NET_Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
extern int main(int argc, char *argv[]);
|
||||
DLL_EXPORT int DedicatedMain( int argc, char *argv[] );
|
||||
|
||||
int DedicatedMain( int argc, char *argv[] )
|
||||
{
|
||||
return main(argc,argv);
|
||||
}
|
411
dedicated/sys_windows.cpp
Normal file
411
dedicated/sys_windows.cpp
Normal file
@ -0,0 +1,411 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <eh.h>
|
||||
#include "isys.h"
|
||||
#include "console/conproc.h"
|
||||
#include "dedicated.h"
|
||||
#include "engine_hlds_api.h"
|
||||
#include "checksum_md5.h"
|
||||
#include "tier0/vcrmode.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "inputsystem/iinputsystem.h"
|
||||
#include "SteamAppStartup.h"
|
||||
#include "console/textconsole.h"
|
||||
#include "vgui/vguihelpers.h"
|
||||
#include "appframework/appframework.h"
|
||||
#include "materialsystem/imaterialsystem.h"
|
||||
#include "istudiorender.h"
|
||||
#include "vgui/ivgui.h"
|
||||
#include "console/TextConsoleWin32.h"
|
||||
#include "icvar.h"
|
||||
#include "datacache/idatacache.h"
|
||||
#include "datacache/imdlcache.h"
|
||||
#include "vphysics_interface.h"
|
||||
#include "filesystem.h"
|
||||
#include "steam/steam_api.h"
|
||||
#include "filesystem/IQueuedLoader.h"
|
||||
|
||||
extern CTextConsoleWin32 console;
|
||||
extern bool g_bVGui;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Implements OS Specific layer ( loosely )
|
||||
//-----------------------------------------------------------------------------
|
||||
class CSys : public ISys
|
||||
{
|
||||
public:
|
||||
virtual ~CSys( void );
|
||||
|
||||
virtual bool LoadModules( CDedicatedAppSystemGroup *pAppSystemGroup );
|
||||
|
||||
void Sleep( int msec );
|
||||
bool GetExecutableName( char *out );
|
||||
void ErrorMessage( int level, const char *msg );
|
||||
|
||||
void WriteStatusText( char *szText );
|
||||
void UpdateStatus( int force );
|
||||
|
||||
long LoadLibrary( char *lib );
|
||||
void FreeLibrary( long library );
|
||||
|
||||
bool CreateConsoleWindow( void );
|
||||
void DestroyConsoleWindow( void );
|
||||
|
||||
void ConsoleOutput ( char *string );
|
||||
char *ConsoleInput ( int index, char *buf, int buflen );
|
||||
void Printf( PRINTF_FORMAT_STRING const char *fmt, ... );
|
||||
};
|
||||
|
||||
static CSys g_Sys;
|
||||
ISys *sys = &g_Sys;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CSys::~CSys()
|
||||
{
|
||||
sys = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : msec -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSys::Sleep( int msec )
|
||||
{
|
||||
// Call ThreadSleep because it has the necessary magic to set the system
|
||||
// timer resolution so that Sleep( 1 ) will sleep for one millisecond
|
||||
// instead of for 10-16 ms.
|
||||
ThreadSleep( msec );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *lib -
|
||||
// Output : long
|
||||
//-----------------------------------------------------------------------------
|
||||
long CSys::LoadLibrary( char *lib )
|
||||
{
|
||||
void *hDll = ::LoadLibrary( lib );
|
||||
return (long)hDll;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : library -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSys::FreeLibrary( long library )
|
||||
{
|
||||
if ( !library )
|
||||
return;
|
||||
|
||||
::FreeLibrary( (HMODULE)library );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *out -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CSys::GetExecutableName( char *out )
|
||||
{
|
||||
if ( !::GetModuleFileName( ( HINSTANCE )GetModuleHandle( NULL ), out, 256 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : level -
|
||||
// *msg -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSys::ErrorMessage( int level, const char *msg )
|
||||
{
|
||||
MessageBox( NULL, msg, "Half-Life", MB_OK );
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : force -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSys::UpdateStatus( int force )
|
||||
{
|
||||
static double tLast = 0.0;
|
||||
double tCurrent;
|
||||
char szPrompt[256];
|
||||
int n, nMax;
|
||||
char szMap[64];
|
||||
char szHostname[128];
|
||||
float fps;
|
||||
|
||||
if ( !engine )
|
||||
return;
|
||||
|
||||
tCurrent = Sys_FloatTime();
|
||||
|
||||
if ( !force )
|
||||
{
|
||||
if ( ( tCurrent - tLast ) < 0.5f )
|
||||
return;
|
||||
}
|
||||
|
||||
tLast = tCurrent;
|
||||
|
||||
engine->UpdateStatus( &fps, &n, &nMax, szMap, sizeof( szMap ) );
|
||||
engine->UpdateHostname( szHostname, sizeof( szHostname ) );
|
||||
|
||||
console.SetTitle( szHostname );
|
||||
|
||||
Q_snprintf( szPrompt, sizeof( szPrompt ), "%.1f fps %2i/%2i on map %16s", (float)fps, n, nMax, szMap);
|
||||
|
||||
console.SetStatusLine(szPrompt);
|
||||
console.UpdateStatus();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *string -
|
||||
// Output : void CSys::ConsoleOutput
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSys::ConsoleOutput (char *string)
|
||||
{
|
||||
if ( g_bVGui )
|
||||
{
|
||||
VGUIPrintf( string );
|
||||
}
|
||||
else
|
||||
{
|
||||
console.Print(string);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *fmt -
|
||||
// ... -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSys::Printf( PRINTF_FORMAT_STRING const char *fmt, ... )
|
||||
{
|
||||
// Dump text to debugging console.
|
||||
va_list argptr;
|
||||
char szText[1024];
|
||||
|
||||
va_start (argptr, fmt);
|
||||
Q_vsnprintf (szText, sizeof( szText ), fmt, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
// Get Current text and append it.
|
||||
ConsoleOutput( szText );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : char *
|
||||
//-----------------------------------------------------------------------------
|
||||
char *CSys::ConsoleInput ( int index, char *buf, int buflen )
|
||||
{
|
||||
return console.GetLine( index, buf, buflen );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *szText -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSys::WriteStatusText( char *szText )
|
||||
{
|
||||
SetConsoleTitle( szText );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CSys::CreateConsoleWindow( void )
|
||||
{
|
||||
if ( !AllocConsole () )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
InitConProc();
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CSys::DestroyConsoleWindow( void )
|
||||
{
|
||||
FreeConsole ();
|
||||
|
||||
// shut down QHOST hooks if necessary
|
||||
DeinitConProc ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Loading modules used by the dedicated server.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CSys::LoadModules( CDedicatedAppSystemGroup *pAppSystemGroup )
|
||||
{
|
||||
AppSystemInfo_t appSystems[] =
|
||||
{
|
||||
{ "engine.dll", CVAR_QUERY_INTERFACE_VERSION }, // NOTE: This one must be first!!
|
||||
{ "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
|
||||
{ "materialsystem.dll", MATERIAL_SYSTEM_INTERFACE_VERSION },
|
||||
{ "studiorender.dll", STUDIO_RENDER_INTERFACE_VERSION },
|
||||
{ "vphysics.dll", VPHYSICS_INTERFACE_VERSION },
|
||||
{ "datacache.dll", DATACACHE_INTERFACE_VERSION },
|
||||
{ "datacache.dll", MDLCACHE_INTERFACE_VERSION },
|
||||
{ "datacache.dll", STUDIO_DATA_CACHE_INTERFACE_VERSION },
|
||||
{ "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION },
|
||||
{ "engine.dll", VENGINE_HLDS_API_VERSION },
|
||||
{ "dedicated.dll", QUEUEDLOADER_INTERFACE_VERSION },
|
||||
{ "", "" } // Required to terminate the list
|
||||
};
|
||||
|
||||
if ( !pAppSystemGroup->AddSystems( appSystems ) )
|
||||
return false;
|
||||
|
||||
engine = (IDedicatedServerAPI *)pAppSystemGroup->FindSystem( VENGINE_HLDS_API_VERSION );
|
||||
|
||||
IMaterialSystem* pMaterialSystem = (IMaterialSystem*)pAppSystemGroup->FindSystem( MATERIAL_SYSTEM_INTERFACE_VERSION );
|
||||
pMaterialSystem->SetShaderAPI( "shaderapiempty.dll" );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool NET_Init( void )
|
||||
{
|
||||
// Startup winock
|
||||
WORD version = MAKEWORD( 1, 1 );
|
||||
WSADATA wsaData;
|
||||
|
||||
int err = WSAStartup( version, &wsaData );
|
||||
if ( err != 0 )
|
||||
{
|
||||
char msg[ 256 ];
|
||||
Q_snprintf( msg, sizeof( msg ), "Winsock 1.1 unavailable...\n" );
|
||||
sys->Printf( "%s", msg );
|
||||
Plat_DebugString( msg );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void NET_Shutdown( void )
|
||||
{
|
||||
// Kill winsock
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : hInstance -
|
||||
// hPrevInstance -
|
||||
// lpszCmdLine -
|
||||
// nCmdShow -
|
||||
// Output : int PASCAL
|
||||
//-----------------------------------------------------------------------------
|
||||
int main(int argc, char **argv); // in sys_ded.cpp
|
||||
static char *GetBaseDir( const char *pszBuffer )
|
||||
{
|
||||
static char basedir[ MAX_PATH ];
|
||||
char szBuffer[ MAX_PATH ];
|
||||
int j;
|
||||
char *pBuffer = NULL;
|
||||
|
||||
V_strcpy_safe( szBuffer, pszBuffer );
|
||||
|
||||
pBuffer = strrchr( szBuffer,'\\' );
|
||||
if ( pBuffer )
|
||||
{
|
||||
*(pBuffer+1) = '\0';
|
||||
}
|
||||
|
||||
strcpy( basedir, szBuffer );
|
||||
|
||||
j = strlen( basedir );
|
||||
if (j > 0)
|
||||
{
|
||||
if ( ( basedir[ j-1 ] == '\\' ) ||
|
||||
( basedir[ j-1 ] == '/' ) )
|
||||
{
|
||||
basedir[ j-1 ] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return basedir;
|
||||
}
|
||||
|
||||
void MiniDumpFunction( unsigned int nExceptionCode, EXCEPTION_POINTERS *pException )
|
||||
{
|
||||
SteamAPI_WriteMiniDump( nExceptionCode, pException, 0 );
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) int DedicatedMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
|
||||
{
|
||||
SetAppInstance( hInstance );
|
||||
|
||||
// Check that we are running on Win32
|
||||
OSVERSIONINFO vinfo;
|
||||
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
|
||||
|
||||
if ( !GetVersionEx ( &vinfo ) )
|
||||
return -1;
|
||||
|
||||
if ( vinfo.dwPlatformId == VER_PLATFORM_WIN32s )
|
||||
return -1;
|
||||
|
||||
int argc, iret = -1;
|
||||
LPWSTR * argv= CommandLineToArgvW(GetCommandLineW(),&argc);
|
||||
CommandLine()->CreateCmdLine( VCRHook_GetCommandLine() );
|
||||
|
||||
if ( !Plat_IsInDebugSession() && !CommandLine()->FindParm( "-nominidumps") )
|
||||
{
|
||||
// This warning only applies if you want to catch structured exceptions (crashes)
|
||||
// using C++ exceptions. We do not want to do that so we can build with C++ exceptions
|
||||
// completely disabled, and just suppress this warning.
|
||||
// warning C4535: calling _set_se_translator() requires /EHa
|
||||
#pragma warning( suppress : 4535 )
|
||||
_set_se_translator( MiniDumpFunction );
|
||||
|
||||
try // this try block allows the SE translator to work
|
||||
{
|
||||
iret = main(argc,(char **)argv);
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iret = main(argc,(char **)argv);
|
||||
}
|
||||
|
||||
GlobalFree( argv );
|
||||
return iret;
|
||||
}
|
||||
|
872
dedicated/vgui/CreateMultiplayerGameServerPage.cpp
Normal file
872
dedicated/vgui/CreateMultiplayerGameServerPage.cpp
Normal file
@ -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
|
||||
|
126
dedicated/vgui/CreateMultiplayerGameServerPage.h
Normal file
126
dedicated/vgui/CreateMultiplayerGameServerPage.h
Normal file
@ -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
|
274
dedicated/vgui/MainPanel.cpp
Normal file
274
dedicated/vgui/MainPanel.cpp
Normal file
@ -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
|
89
dedicated/vgui/MainPanel.h
Normal file
89
dedicated/vgui/MainPanel.h
Normal file
@ -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
|
187
dedicated/vgui/vguihelpers.cpp
Normal file
187
dedicated/vgui/vguihelpers.cpp
Normal file
@ -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
|
||||
|
26
dedicated/vgui/vguihelpers.h
Normal file
26
dedicated/vgui/vguihelpers.h
Normal file
@ -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
|
||||
|
39
dedicated/vgui/vguihelpers_linux.cpp
Normal file
39
dedicated/vgui/vguihelpers_linux.cpp
Normal file
@ -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()
|
||||
{
|
||||
}
|
||||
|
Reference in New Issue
Block a user