This commit is contained in:
FluorescentCIAAfricanAmerican
2020-04-22 12:56:21 -04:00
commit 3bf9df6b27
15370 changed files with 5489726 additions and 0 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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;
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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()
{
}