This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@@ -0,0 +1,148 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\common\debug_dll_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_dll_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_dll_check.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\filesystem.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\filesystem.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\filesystem.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\public\filesystem_init.cpp
Debug output file: F:\csgo_64\cstrike15_src\public\filesystem_init.cpp
Release output file: F:\csgo_64\cstrike15_src\public\filesystem_init.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\public\tier0\memoverride.cpp
Debug output file: F:\csgo_64\cstrike15_src\public\tier0\memoverride.cpp
Release output file: F:\csgo_64\cstrike15_src\public\tier0\memoverride.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\netapi.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\netapi.cpp
Release output file: F:\csgo_64\cstrike15_src\common\netapi.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\SteamAppStartup.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\SteamAppStartup.cpp
Release output file: F:\csgo_64\cstrike15_src\common\SteamAppStartup.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\sys_common.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\sys_common.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\sys_common.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\sys_ded.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\sys_ded.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\sys_ded.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\sys_subproc.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\sys_subproc.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\sys_subproc.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\sys_windows.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\sys_windows.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\sys_windows.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\console\conproc.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\console\conproc.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\console\conproc.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\console\textconsole.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\console\textconsole.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\console\textconsole.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\console\TextConsoleWin32.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\console\TextConsoleWin32.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\console\TextConsoleWin32.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\filesystem\basefilesystem.cpp
Debug output file: F:\csgo_64\cstrike15_src\filesystem\basefilesystem.cpp
Release output file: F:\csgo_64\cstrike15_src\filesystem\basefilesystem.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\filesystem\basefilesystemasync.cpp
Debug output file: F:\csgo_64\cstrike15_src\filesystem\basefilesystemasync.cpp
Release output file: F:\csgo_64\cstrike15_src\filesystem\basefilesystemasync.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\filesystem\filesystem_stdio.cpp
Debug output file: F:\csgo_64\cstrike15_src\filesystem\filesystem_stdio.cpp
Release output file: F:\csgo_64\cstrike15_src\filesystem\filesystem_stdio.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\filesystem\filesystem_steam.cpp
Debug output file: F:\csgo_64\cstrike15_src\filesystem\filesystem_steam.cpp
Release output file: F:\csgo_64\cstrike15_src\filesystem\filesystem_steam.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\filesystem\filesystemasync.cpp
Debug output file: F:\csgo_64\cstrike15_src\filesystem\filesystemasync.cpp
Release output file: F:\csgo_64\cstrike15_src\filesystem\filesystemasync.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\filesystem\filetracker.cpp
Debug output file: F:\csgo_64\cstrike15_src\filesystem\filetracker.cpp
Release output file: F:\csgo_64\cstrike15_src\filesystem\filetracker.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\public\zip_utils.cpp
Debug output file: F:\csgo_64\cstrike15_src\public\zip_utils.cpp
Release output file: F:\csgo_64\cstrike15_src\public\zip_utils.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\vgui\CreateMultiplayerGameServerPage.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\vgui\CreateMultiplayerGameServerPage.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\vgui\CreateMultiplayerGameServerPage.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\vgui\MainPanel.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\vgui\MainPanel.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\vgui\MainPanel.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\public\vgui_controls\vgui_controls.cpp
Debug output file: F:\csgo_64\cstrike15_src\public\vgui_controls\vgui_controls.cpp
Release output file: F:\csgo_64\cstrike15_src\public\vgui_controls\vgui_controls.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\dedicated\vgui\vguihelpers.cpp
Debug output file: F:\csgo_64\cstrike15_src\dedicated\vgui\vguihelpers.cpp
Release output file: F:\csgo_64\cstrike15_src\dedicated\vgui\vguihelpers.cpp
Containing unity file:
PCH file:

425
dedicated/conproc.cpp Normal file
View File

@@ -0,0 +1,425 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// conproc.c -- support for qhost
#include "dedicated.h"
#include <stdio.h>
#include <process.h>
#include <windows.h>
#include "conproc.h"
#include "isys.h"
#include "tier0/icommandline.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 (isalpha(c))
return (30 + upper - 65);
if (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 = 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 );
}

30
dedicated/conproc.h Normal file
View File

@@ -0,0 +1,30 @@
//========= Copyright <20> 1996-2005, 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,360 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// CTextConsoleUnix.cpp: Unix implementation of the TextConsole class.
//
//////////////////////////////////////////////////////////////////////
#ifndef _WIN32
#include "TextConsoleUnix.h"
// un-needed include...
//#include "resource.h"
#include "tier0/icommandline.h"
//#include "../ifilesystem.h"
#include "filesystem.h"
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <termios.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <signal.h>
#define CONSOLE_LOG_FILE "console.log"
bool CTextConsoleUnix::Init( )
{
static struct termios termNew;
sigset_t block_ttou;
sigemptyset (&block_ttou);
sigaddset (&block_ttou, SIGTTOU);
sigprocmask (SIG_BLOCK, &block_ttou, NULL);
tty = stdout;
// this code is for echo-ing key presses to the connected tty
// (which is != STDOUT)
if ( isatty(STDIN_FILENO) )
{
tty = fopen( ctermid( NULL ), "w+" );
if ( !tty )
{
printf("Unable to open tty(%s) for output\n", ctermid( NULL ) );
tty = stdout;
}
else
{
setbuf( tty, NULL ); // turn buffering off
}
}
else
{
tty = fopen( "/dev/null", "w+" );
if ( !tty )
{
tty = stdout;
}
}
tcgetattr( STDIN_FILENO, &termStored );
memcpy( &termNew, &termStored, sizeof( struct termios ) );
/* Disable canonical mode, and set buffer size to 1 byte */
termNew.c_lflag &= ( ~ICANON );
termNew.c_cc[ VMIN ] = 1;
termNew.c_cc[ VTIME ] = 0;
/* disable echo */
termNew.c_lflag &= ( ~ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &termNew );
sigprocmask (SIG_UNBLOCK, &block_ttou, NULL);
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( void )
{
sigset_t block_ttou;
sigemptyset (&block_ttou);
sigaddset (&block_ttou, SIGTTOU);
sigprocmask (SIG_BLOCK, &block_ttou, NULL);
tcsetattr( STDIN_FILENO, TCSANOW, &termStored );
sigprocmask (SIG_UNBLOCK, &block_ttou, NULL);
CTextConsole::ShutDown();
}
// return 0 if the kb isn't hit
int CTextConsoleUnix::kbhit( void )
{
fd_set rfds;
struct timeval tv;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO( &rfds );
FD_SET( STDIN_FILENO, &rfds );
/* Return immediately. */
tv.tv_sec = 0;
tv.tv_usec = 0;
/* Must be in raw or cbreak mode for this to work correctly. */
return select( STDIN_FILENO + 1, &rfds, NULL, NULL, &tv )!=-1 && FD_ISSET( STDIN_FILENO, &rfds );
}
char * CTextConsoleUnix::GetLine( void )
{
if ( !kbhit() ) // early return for 99.999% case :)
return NULL;
escape_sequence_t es;
es = ESCAPE_CLEAR;
sigset_t block_ttou;
sigemptyset (&block_ttou);
sigaddset (&block_ttou, SIGTTOU);
sigaddset (&block_ttou, SIGTTIN);
sigprocmask (SIG_BLOCK, &block_ttou, NULL);
while ( 1 )
{
char ch;
int nLen;
if ( !kbhit() )
break;
ch = 0;
int numRead = read( STDIN_FILENO, &ch, 1 );
if ( !numRead )
break;
switch (ch)
{
case '\n': // Enter
es = ESCAPE_CLEAR;
nLen = ReceiveNewline();
if ( nLen )
{
sigprocmask (SIG_UNBLOCK, &block_ttou, NULL);
return m_szConsoleText;
}
break;
case 127: // Backspace
case '\b': // Backspace
es = ESCAPE_CLEAR;
ReceiveBackspace();
break;
case '\t': // TAB
es = ESCAPE_CLEAR;
ReceiveTab();
break;
case 27: // Escape character
es = ESCAPE_RECEIVED;
break;
case '[': // 2nd part of escape sequence
case 'O':
case 'o':
switch( es )
{
case ESCAPE_CLEAR:
case ESCAPE_BRACKET_RECEIVED:
es = ESCAPE_CLEAR;
ReceiveStandardChar( ch );
break;
case ESCAPE_RECEIVED:
es = ESCAPE_BRACKET_RECEIVED;
break;
}
break;
case 'A':
if ( es == ESCAPE_BRACKET_RECEIVED )
{
es = ESCAPE_CLEAR;
ReceiveUpArrow();
}
else
{
es = ESCAPE_CLEAR;
ReceiveStandardChar( ch );
}
break;
case 'B':
if ( es == ESCAPE_BRACKET_RECEIVED )
{
es = ESCAPE_CLEAR;
ReceiveDownArrow();
}
else
{
es = ESCAPE_CLEAR;
ReceiveStandardChar( ch );
}
break;
case 'C':
if ( es == ESCAPE_BRACKET_RECEIVED )
{
es = ESCAPE_CLEAR;
ReceiveRightArrow();
}
else
{
es = ESCAPE_CLEAR;
ReceiveStandardChar( ch );
}
break;
case 'D':
if ( es == ESCAPE_BRACKET_RECEIVED )
{
es = ESCAPE_CLEAR;
ReceiveLeftArrow();
}
else
{
es = ESCAPE_CLEAR;
ReceiveStandardChar( ch );
}
break;
default:
if ( es != ESCAPE_BRACKET_RECEIVED ) // Just eat this char if it's an unsupported escape
{
if ( ( ch >= ' ') && ( ch <= '~' ) ) // dont' accept nonprintable chars
{
es = ESCAPE_CLEAR;
ReceiveStandardChar( ch );
}
}
break;
}
fflush( stdout );
}
sigprocmask (SIG_UNBLOCK, &block_ttou, NULL);
return NULL;
}
void CTextConsoleUnix::PrintRaw( char * pszMsg, int nChars )
{
if ( m_bConDebug )
{
FileHandle_t fh = g_pFullFileSystem->Open( CONSOLE_LOG_FILE, "a" );
if ( fh != FILESYSTEM_INVALID_HANDLE )
{
if ( nChars == 0 )
{
g_pFullFileSystem->Write( pszMsg, strlen( pszMsg ), fh );
}
else
{
g_pFullFileSystem->Write( pszMsg, nChars, fh );
}
g_pFullFileSystem->Close( fh );
}
}
if ( nChars == 0 )
{
printf( "%s", pszMsg );
}
else
{
int nCount;
for ( nCount = 0; nCount < nChars; nCount++ )
{
printf( "%c", pszMsg[ nCount ] );
}
}
}
void CTextConsoleUnix::Echo( char * pszMsg, int nChars )
{
if ( nChars == 0 )
{
fprintf( tty, "%s", pszMsg );
}
else
{
int nCount;
for ( nCount = 0; nCount < nChars; nCount++ )
{
fprintf( tty, "%c", pszMsg[ nCount ] );
}
}
}
int CTextConsoleUnix::GetWidth( void )
{
struct winsize ws;
int nWidth;
nWidth = 0;
if ( ioctl( STDOUT_FILENO, TIOCGWINSZ, &ws ) == 0 )
{
nWidth = (int)ws.ws_col;
}
/* if ( nWidth <= 0 )
{
char * ss;
ss = getenv( "COLUMNS" );
if ( ss )
{
nWidth = atoi( ss );
}
}
*/
if ( nWidth <= 1 )
{
nWidth = 80;
}
return nWidth;
}
#endif // ndef _WIN32

View File

@@ -0,0 +1,59 @@
//========= Copyright <20> 1996-2005, 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 <termios.h>
#include <stdio.h>
#include "textconsole.h"
typedef enum
{
ESCAPE_CLEAR = 0,
ESCAPE_RECEIVED,
ESCAPE_BRACKET_RECEIVED
} escape_sequence_t;
class CTextConsoleUnix : public CTextConsole
{
public:
virtual ~CTextConsoleUnix()
{
};
bool Init();
void ShutDown( void );
void PrintRaw( char * pszMsg, int nChars = 0 );
void Echo( char * pszMsg, int nChars = 0 );
char * GetLine( void );
int GetWidth( void );
private:
int kbhit( void );
bool m_bConDebug;
struct termios termStored;
FILE *tty;
};
#endif // _ndef WIN32
#endif // !defined

View File

@@ -0,0 +1,277 @@
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// CTextConsoleWin32.cpp: Win32 implementation of the TextConsole class.
//
//////////////////////////////////////////////////////////////////////
#pragma warning(disable:4100) //unreferenced formal parameter
#include "TextConsoleWin32.h"
#pragma warning(default:4100) //unreferenced formal parameter
#include "tier0/dbg.h"
#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)
{
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 = houtput = INVALID_HANDLE_VALUE;
}
bool CTextConsoleWin32::Init( /*IBaseSystem * system*/ )
{
if ( !AllocConsole () )
//m_System = system;
//if ( m_System )
// SetTitle( m_System->GetName() );
//else
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_NOREPOSITION | SWP_SHOWWINDOW );
return CTextConsole::Init( /*system */ );
}
void CTextConsoleWin32::ShutDown( void )
{
FreeConsole();
CTextConsole::ShutDown();
}
void CTextConsoleWin32::SetVisible( bool visible )
{
ShowWindow ( GetConsoleHwnd(), visible ? SW_SHOW : SW_HIDE );
m_ConsoleVisible = visible;
}
char * CTextConsoleWin32::GetLine( void )
{
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 )
{
return m_szConsoleText;
}
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::PrintRaw( char * pszMsg, int nChars )
{
unsigned long dummy;
if ( houtput == INVALID_HANDLE_VALUE )
return;
if ( nChars == 0 )
{
WriteFile( houtput, pszMsg, strlen( pszMsg ), &dummy, NULL );
}
else
{
WriteFile( houtput, pszMsg, nChars, &dummy, NULL );
}
}
void CTextConsoleWin32::Echo( char * pszMsg, int nChars )
{
PrintRaw( pszMsg, nChars );
}
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;
}
#endif

View File

@@ -0,0 +1,55 @@
//========= Copyright <20> 1996-2005, 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"
class CTextConsoleWin32 : public CTextConsole
{
public:
CTextConsoleWin32();
virtual ~CTextConsoleWin32()
{
};
bool Init( /*IBaseSystem * system*/ );
void ShutDown( void );
void PrintRaw( char * pszMsz, int nChars = 0 );
void Echo( char * pszMsz, int nChars = 0 );
char * GetLine( void );
int GetWidth( void );
void SetTitle( char * pszTitle );
void SetStatusLine( char * pszStatus );
void UpdateStatus( void );
void SetColor( WORD );
void SetVisible( bool visible );
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

View File

@@ -0,0 +1,427 @@
//========= Copyright <20> 1996-2005, 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"
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 (isalpha(c))
return (30 + upper - 65);
if (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 = 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 <20> 1996-2005, 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,406 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// TextConsole.cpp: implementation of the TextConsole class.
//
//////////////////////////////////////////////////////////////////////
//#include "port.h"
#pragma warning(disable:4100) //unreferenced formal parameter
#include "textconsole.h"
#pragma warning(default:4100) //unreferenced formal parameter
#include "utlvector.h"
#include "tier1/strtools.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
bool CTextConsole::Init( /*IBaseSystem * system*/ )
{
//m_System = system; // NULL or a valid base system interface
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" );
m_ConsoleVisible = true;
return true;
}
void CTextConsole::SetVisible( bool visible )
{
m_ConsoleVisible = visible;
}
bool CTextConsole::IsVisible()
{
return m_ConsoleVisible;
}
void CTextConsole::ShutDown( void )
{
}
void CTextConsole::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();
}
int CTextConsole::ReceiveNewline( void )
{
int nLen = 0;
Echo( "\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 CTextConsole::ReceiveBackspace( void )
{
int nCount;
if ( m_nCursorPosition == 0 )
{
return;
}
m_nConsoleTextLen--;
m_nCursorPosition--;
Echo( "\b" );
for ( nCount = m_nCursorPosition; nCount < m_nConsoleTextLen; nCount++ )
{
m_szConsoleText[ nCount ] = m_szConsoleText[ nCount + 1 ];
Echo( m_szConsoleText + nCount, 1 );
}
Echo( " " );
nCount = m_nConsoleTextLen;
while ( nCount >= m_nCursorPosition )
{
Echo( "\b" );
nCount--;
}
m_nBrowseLine = m_nInputLine;
}
void CTextConsole::ReceiveTab( void )
{
CUtlVector<char *> matches;
//if ( !m_System )
// return;
m_szConsoleText[ m_nConsoleTextLen ] = 0;
//m_System->GetCommandMatches( m_szConsoleText, &matches );
if ( matches.Count() == 0 )
{
return;
}
if ( matches.Count() == 1 )
{
char * pszCmdName;
char * pszRest;
pszCmdName = matches[0];
pszRest = pszCmdName + strlen( m_szConsoleText );
if ( pszRest )
{
Echo( pszRest );
strcat( m_szConsoleText, pszRest );
m_nConsoleTextLen += strlen( pszRest );
Echo( " " );
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;
Echo( "\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 )
{
Echo( "\n" );
nCurrentColumn = 1;
}
Q_snprintf( szFormatCmd, sizeof(szFormatCmd), "%-*s ", nLongestCmd, pszCurrentCmd );
Echo( szFormatCmd );
i++;
pszCurrentCmd = matches[i];
}
Echo( "\n" );
Echo( 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 CTextConsole::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;
Echo( m_szConsoleText + m_nCursorPosition, m_nConsoleTextLen - m_nCursorPosition + 1 );
m_nConsoleTextLen++;
m_nCursorPosition++;
nCount = m_nConsoleTextLen;
while ( nCount > m_nCursorPosition )
{
Echo( "\b" );
nCount--;
}
m_nBrowseLine = m_nInputLine;
}
void CTextConsole::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
{
Echo( "\b \b" );
}
// copy buffered line
Echo( 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 CTextConsole::ReceiveDownArrow( void )
{
if ( m_nBrowseLine == m_nInputLine )
{
return;
}
m_nBrowseLine++;
if ( m_nBrowseLine > m_nTotalLines )
{
m_nBrowseLine = 0;
}
while ( m_nConsoleTextLen-- ) // delete old line
{
Echo( "\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
Echo( m_szConsoleText, m_nSavedConsoleTextLen );
}
m_nConsoleTextLen = m_nSavedConsoleTextLen;
}
else
{
// copy buffered line
Echo( 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 CTextConsole::ReceiveLeftArrow( void )
{
if ( m_nCursorPosition == 0 )
{
return;
}
Echo( "\b" );
m_nCursorPosition--;
}
void CTextConsole::ReceiveRightArrow( void )
{
if ( m_nCursorPosition == m_nConsoleTextLen )
{
return;
}
Echo( m_szConsoleText + m_nCursorPosition, 1 );
m_nCursorPosition++;
}

View File

@@ -0,0 +1,76 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#if !defined TEXTCONSOLE_H
#define TEXTCONSOLE_H
#pragma once
#ifdef _WIN32
#include <windows.h>
#endif // _WIN32
#define MAX_CONSOLE_TEXTLEN 256
#define MAX_BUFFER_LINES 30
//class IBaseSystem;
class CTextConsole
{
public:
virtual ~CTextConsole()
{
};
virtual bool Init ( /*IBaseSystem * system*/ );
virtual void ShutDown( void );
virtual void Print( char * pszMsg );
virtual void SetTitle( char * pszTitle ) { };
virtual void SetStatusLine( char * pszStatus ) { };
virtual void UpdateStatus() { };
// Must be provided by children
virtual void PrintRaw( char * pszMsg, int nChars = 0 ) = 0;
virtual void Echo( char * pszMsg, int nChars = 0 ) = 0;
virtual char * GetLine( void ) = 0;
virtual int GetWidth( void ) = 0;
virtual void SetVisible( bool visible );
virtual bool IsVisible();
protected:
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
bool m_ConsoleVisible;
// IBaseSystem * m_System;
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 );
};
#endif // !defined

88
dedicated/dedicated.h Normal file
View File

@@ -0,0 +1,88 @@
//===== Copyright 1996-2005, 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;
//-----------------------------------------------------------------------------
// 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 );
}
};
// main server entry point after init
void RunServer( bool bSupressStdIOBecauseWeAreAForkedChild );
#ifdef _LINUX
void RunServerSubProcesses( int nNumChildInstances );
#endif
// modify the command line, replacing all occurrences of ## with nIndex
void PerformCommandLineSubstitutions( int nIndex );
// forked subprocess index. 0 for master or not forked mode
extern int g_nSubProcessId;
#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

127
dedicated/dedicated.vpc Normal file
View File

@@ -0,0 +1,127 @@
//-----------------------------------------------------------------------------
// DEDICATED.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR ".."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE,.\,$SRCDIR\engine"
$PreprocessorDefinitions "$BASE;DEDICATED;LAUNCHERONLY"
}
$Linker
{
$AdditionalDependencies "$BASE wsock32.lib odbc32.lib odbccp32.lib winmm.lib" [$WINDOWS]
$SystemFrameworks "AppKit"
$SystemLibraries "iconv" [$OSXALL]
}
}
$Project "Dedicated"
{
$Folder "Source Files"
{
$File "dedicated.rc"
$File "sys_linux.cpp" [$POSIX]
$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_subproc.cpp"
$File "sys_windows.cpp" [$WINDOWS]
$Folder "Console"
{
$File "console\conproc.cpp"
$File "console\textconsole.cpp"
$File "console\TextConsoleUnix.cpp" [$POSIX]
$File "console\TextConsoleWin32.cpp" [$WINDOWS]
}
$Folder "VGUI" [$WINDOWS||$POSIX]
{
$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\basefilesystemasync.cpp"
$File "$SRCDIR\filesystem\filesystem_stdio.cpp"
$File "$SRCDIR\filesystem\filesystem_steam.cpp" [!$POSIX]
$File "$SRCDIR\filesystem\filesystemasync.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\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\public\tier0\platform.h"
$File "$SRCDIR\common\SteamAppStartup.h"
$File "$SRCDIR\public\string_t.h"
$File "$SRCDIR\public\tier1\strtools.h"
$File "$SRCDIR\public\mathlib\vector.h"
$File "$SRCDIR\public\mathlib\vector2d.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" [$WINDOWS || $POSIX]
{
$Lib appframework
$Lib dmxloader
$ImplibExternal steam_api [ ( $WIN32 || $POSIX || $PS3 ) && !$NO_STEAM ]
$ImplibExternal steam_api64 [ $WIN64 && !$NO_STEAM ]
$Lib mathlib
$Lib tier2
$Lib tier3
$Lib vpklib
$Lib vgui_controls [$WINDOWS||$OSXALL]
}
}

View File

@@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "dedicated.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "dedicated.vcxproj"
"1" "dedicated.vcxproj.filters"
}
}
}

97
dedicated/filesystem.cpp Normal file
View File

@@ -0,0 +1,97 @@
//===== Copyright <20> 1996-2005, 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 "Steam.h"
#include "appframework/AppFramework.h"
#include "tier2/tier2.h"
extern IFileSystem *g_pFileSystem;
extern IBaseFileSystem *g_pBaseFileSystem;
extern IFileSystem *g_pFileSystemSteam;
extern IBaseFileSystem *g_pBaseFileSystemSteam;
// We have two CBaseFilesystem objects, stdio and steam, so we have to manage the
// BaseFileSystem() accessor ourselves.
#ifdef _WIN32
CBaseFileSystem *BaseFileSystem_Steam( void );
CBaseFileSystem *BaseFileSystem_Stdio( void );
static CBaseFileSystem *s_pBaseFileSystem = NULL;
CBaseFileSystem *BaseFileSystem( void )
{
return s_pBaseFileSystem;
}
#endif
// 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)
{
#ifdef _WIN32
if ( CommandLine()->FindParm( "-steam" ) )
{
s_pBaseFileSystem = BaseFileSystem_Steam();
if ( !Q_stricmp(pName, FILESYSTEM_INTERFACE_VERSION ) )
{
if ( pReturnCode )
{
*pReturnCode = IFACE_OK;
}
return g_pFileSystemSteam;
}
if ( !Q_stricmp(pName, BASEFILESYSTEM_INTERFACE_VERSION ) )
{
if ( pReturnCode )
{
*pReturnCode = IFACE_OK;
}
return g_pBaseFileSystemSteam;
}
}
else
#endif
{
#ifdef _WIN32
s_pBaseFileSystem = BaseFileSystem_Stdio();
#endif
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 <20> 1996-2005, 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 (void) = 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 <20> 1996-2005, 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

303
dedicated/sys_common.cpp Normal file
View File

@@ -0,0 +1,303 @@
//===== Copyright 1996-2005, 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/dbg.h"
#include "tier1/strtools.h"
#include "tier0/icommandline.h"
#include "idedicatedexports.h"
#include "mathlib/expressioncalculator.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;
#ifdef _WIN32
extern bool g_bVGui;
#endif
/*
==============
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
==============
*/
void ProcessConsoleInput( void )
{
char *s;
if ( !engine )
return;
do
{
s = sys->ConsoleInput();
if (s)
{
char szBuf[ 256 ];
Q_snprintf( szBuf, sizeof( szBuf ), "%s\n", s );
engine->AddConsoleText ( szBuf );
}
} while (s);
}
#ifdef _WIN32
extern bool g_bVGui;
#endif
class CDedicatedExports : public CBaseAppSystem<IDedicatedExports>
{
public:
virtual void Sys_Printf( char *text )
{
if ( sys )
{
sys->Printf( "%s", text );
}
}
virtual void RunServer( void );
virtual bool IsGuiDedicatedServer();
};
void PerformCommandLineSubstitutions( int nIndex )
{
// modify the command line, replacing all occurrences of ## with nIndex
for( int i = 0; i < CommandLine()->ParmCount(); i++ )
{
char newBuf[2048];
char const *ppParm = CommandLine()->GetParm( i );
V_strncpy( newBuf, ppParm, sizeof( newBuf ) );
bool bDidReplace = false;
bool bWasExpression = false;
for(;;)
{
char *pReplace = V_strstr( newBuf, "##" );
if (! pReplace )
break;
pReplace[0] = '0' + ( nIndex / 10 );
pReplace[1] = '0' + ( nIndex % 10 );
bDidReplace = true;
if ( ( pReplace != newBuf ) &&
( strchr( "+-/*", pReplace[-1] ) ) ) // is this an expression involving "##"?
{
bWasExpression = true;
}
}
if ( bDidReplace )
{
if ( bWasExpression )
{
sprintf( newBuf, "%d", ( int ) ( EvaluateExpression( newBuf, -1 ) ) );
}
printf("setparm %d %s\n", i, newBuf );
CommandLine()->SetParm( i, newBuf );
}
}
}
#ifdef _LINUX // linux uses the implementation in sys_subproc
void CDedicatedExports::RunServer( void )
{
// check for forking
char const *pForkParam = CommandLine()->ParmValue( "-fork" );
if ( pForkParam )
{
int nNumChildInstances = atoi( pForkParam );
if ( nNumChildInstances >= 1 )
{
RunServerSubProcesses( nNumChildInstances );
}
}
else
{
::RunServer( false );
}
}
#else
void CDedicatedExports::RunServer( void )
{
PerformCommandLineSubstitutions( 0 );
::RunServer( false );
}
#endif
bool CDedicatedExports::IsGuiDedicatedServer()
{
#ifndef _WIN32
return false;
#else
return g_bVGui;
#endif
}
EXPOSE_SINGLE_INTERFACE( CDedicatedExports, IDedicatedExports, VENGINE_DEDICATEDEXPORTS_API_VERSION );
int Sys_GetExecutableName( char *out )
{
#ifdef _WIN32
if ( !::GetModuleFileName( ( HINSTANCE )GetModuleHandle( NULL ), out, 256 ) )
{
return 0;
}
#else
extern char g_szEXEName[ 256 ];
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;
}

667
dedicated/sys_ded.cpp Normal file
View File

@@ -0,0 +1,667 @@
//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include <stdio.h>
#include <stdlib.h>
#include "isys.h"
#include "conproc.h"
#include "dedicated.h"
#include "engine_hlds_api.h"
#include "checksum_md5.h"
#include "mathlib/mathlib.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"
#ifdef LINUX
#include <mcheck.h>
#endif
#ifdef _WIN32
#include <windows.h>
#include <direct.h>
#include "keyvalues.h"
// filesystem_steam.cpp implements this useful function - mount all the caches for a given app ID.
extern void MountDependencies( int iAppId, CUtlVector<unsigned int> &depList );
#else
#define _chdir chdir
#include <unistd.h>
#endif
void* FileSystemFactory( const char *pName, int *pReturnCode );
bool InitInstance( );
void ProcessConsoleInput( void );
const char *UTIL_GetExecutableDir( );
bool NET_Init( void );
void NET_Shutdown( void );
const char *UTIL_GetBaseDir( void );
bool g_bVGui = false;
#if defined( CSTRIKE15 )
const char *g_gameName = "csgo";
#else
const char *g_gameName = "hl2";
#endif
#if defined ( _WIN32 )
#include "console/TextConsoleWin32.h"
CTextConsoleWin32 console;
#else
#include "console/TextConsoleUnix.h"
CTextConsoleUnix console;
#endif
extern char *gpszCvars;
IDedicatedServerAPI *engine = NULL;
int g_nSubProcessId = 0;
#ifdef POSIX
extern char g_szEXEName[ 256 ];
#endif
class CDedicatedServerLoggingListener : public ILoggingListener
{
public:
virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
{
if ( sys )
{
if ( g_nSubProcessId )
{
sys->Printf( " #%0x2d:%s", g_nSubProcessId, pMessage );
}
else
{
sys->Printf( "#%s", pMessage );
}
}
#ifdef _WIN32
Plat_DebugString( pMessage );
#endif
if ( pContext->m_Severity == LS_ERROR )
{
// In Windows vgui mode, make a message box or they won't ever see the error.
#ifdef _WIN32
if ( g_bVGui )
{
MessageBox( NULL, pMessage, "Error", MB_OK | MB_TASKMODAL );
}
TerminateProcess( GetCurrentProcess(), 1 );
#elif POSIX
fflush(stdout);
_exit(1);
#else
#error "Implement me"
#endif
}
}
};
#if defined(POSIX) && !defined(_PS3)
#define MAX_LINUX_CMDLINE 2048
static char linuxCmdline[ MAX_LINUX_CMDLINE +7 ]; // room for -steam
void BuildCmdLine( int argc, char **argv )
{
int len;
int i;
for (len = 0, i = 0; i < argc; i++)
{
len += strlen(argv[i]);
}
if ( len > MAX_LINUX_CMDLINE )
{
printf( "command line too long, %i max\n", MAX_LINUX_CMDLINE );
exit(-1);
return;
}
linuxCmdline[0] = '\0';
for ( i = 0; i < argc; i++ )
{
if ( i > 0 )
{
strcat( linuxCmdline, " " );
}
strcat( linuxCmdline, argv[ i ] );
}
strcat( linuxCmdline, " -steam" );
}
char *GetCommandLine()
{
return linuxCmdline;
}
#endif
static CNonFatalLoggingResponsePolicy s_NonFatalLoggingResponsePolicy;
static CDedicatedServerLoggingListener s_DedicatedServerLoggingListener;
bool RunServerIteration( bool bSupressStdIOBecauseWeAreAForkedChild )
{
bool bDone = false;
#if defined ( _WIN32 )
MSG msg;
while( 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 bDone;
#endif // _WIN32
if ( g_bVGui )
{
#ifdef _WIN32
RunVGUIFrame();
#endif
}
else
{
if (! bSupressStdIOBecauseWeAreAForkedChild )
{
// Calling ProcessConsoleInput can cost about a tenth of a millisecond.
// We used to call it up to 1,000 times a second. Even calling it once
// a frame is wasteful since the console hardly needs that level of
// responsiveness, and calling it too frequently is a waste of CPU time
// and power.
static int s_nProcessCount;
// Don't set this too high since the users keystrokes are not reflected
// until this ProcessConsoleInput is called.
const int nConsoleInputFrames = 5;
++s_nProcessCount;
if ( s_nProcessCount > nConsoleInputFrames )
{
s_nProcessCount = 0;
ProcessConsoleInput();
}
}
}
if ( !engine->RunFrame() )
{
bDone = true;
}
sys->UpdateStatus( 0 /* don't force */ );
return bDone;
}
//-----------------------------------------------------------------------------
//
// Server loop
//
//-----------------------------------------------------------------------------
void RunServer( bool bSupressStdIOBecauseWeAreAForkedChild )
{
#ifdef _WIN32
if(gpszCvars)
{
engine->AddConsoleText(gpszCvars);
}
#endif
// run 2 engine frames first to get the engine to load its resources
if (g_bVGui)
{
#ifdef _WIN32
RunVGUIFrame();
#endif
}
if ( !engine->RunFrame() )
{
return;
}
if (g_bVGui)
{
#ifdef _WIN32
RunVGUIFrame();
#endif
}
if ( !engine->RunFrame() )
{
return;
}
if (g_bVGui)
{
#ifdef _WIN32
VGUIFinishedConfig();
RunVGUIFrame();
#endif
}
bool bDone = false;
while ( ! bDone )
{
bDone = RunServerIteration( bSupressStdIOBecauseWeAreAForkedChild );
}
}
//-----------------------------------------------------------------------------
//
// initialize the console or wait for vgui to start the server
//
//-----------------------------------------------------------------------------
bool ConsoleStartup( CreateInterfaceFn dedicatedFactory )
{
#ifdef _WIN32
if ( g_bVGui )
{
StartVGUI( dedicatedFactory );
RunVGUIFrame();
// Run the config screen
while (VGUIIsInConfig() && VGUIIsRunning())
{
RunVGUIFrame();
}
if ( VGUIIsStopping() )
{
return false;
}
}
else
#endif // _WIN32
{
if ( !console.Init() )
{
return false;
}
}
return true;
}
//-----------------------------------------------------------------------------
// Instantiate all main libraries
//-----------------------------------------------------------------------------
bool CDedicatedAppSystemGroup::Create( )
{
// Hook the debug output stuff (override the spew func in the appframework)
LoggingSystem_PushLoggingState();
LoggingSystem_SetLoggingResponsePolicy( &s_NonFatalLoggingResponsePolicy );
LoggingSystem_RegisterLoggingListener( &s_DedicatedServerLoggingListener );
// 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;
return sys->LoadModules( this );
}
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;
// Needs to be done prior to init material system config
CFSSearchPathsInit initInfo;
initInfo.m_pFileSystem = g_pFullFileSystem;
initInfo.m_pDirectoryName = CommandLine()->ParmValue( "-game" );
// Load gameinfo.txt and setup all the search paths, just like the tools do.
FileSystem_LoadSearchPaths( initInfo );
#ifdef _WIN32
if ( CommandLine()->CheckParm( "-console" ) )
{
g_bVGui = false;
}
else
{
g_bVGui = true;
}
#else
// no VGUI under linux
g_bVGui = false;
#endif
if ( !g_bVGui )
{
if ( !sys->CreateConsoleWindow() )
return false;
}
return true;
}
int CDedicatedAppSystemGroup::Main( )
{
if ( !ConsoleStartup( GetFactory() ) )
return -1;
#ifdef _WIN32
if ( g_bVGui )
{
RunVGUIFrame();
}
else
{
// mount the caches
if (CommandLine()->CheckParm("-steam"))
{
// Add a search path for the base dir
char fullLocationPath[MAX_PATH];
if ( _getcwd( fullLocationPath, MAX_PATH ) )
{
g_pFullFileSystem->AddSearchPath( fullLocationPath, "MAIN" );
}
// Find the gameinfo.txt for our mod and mount it's caches
char gameInfoFilename[MAX_PATH];
Q_snprintf( gameInfoFilename, sizeof(gameInfoFilename) - 1, "%s\\gameinfo.txt", CommandLine()->ParmValue( "-game", g_gameName ) );
KeyValues *gameData = new KeyValues( "GameInfo" );
if ( gameData->LoadFromFile( g_pFullFileSystem, gameInfoFilename ) )
{
KeyValues *pFileSystem = gameData->FindKey( "FileSystem" );
int iAppId = pFileSystem->GetInt( "SteamAppId" );
if ( iAppId )
{
CUtlVector<unsigned int> depList;
MountDependencies( iAppId, depList );
}
}
gameData->deleteThis();
// remove our base search path
g_pFullFileSystem->RemoveSearchPaths( "MAIN" );
}
}
#endif
// Set up mod information
ModInfo_t info;
info.m_pInstance = GetAppInstance();
info.m_pBaseDirectory = UTIL_GetBaseDir();
info.m_pInitialMod = CommandLine()->ParmValue( "-game", g_gameName );
info.m_pInitialGame = CommandLine()->ParmValue( "-defaultgamedir", g_gameName );
info.m_pParentAppSystemGroup = this;
info.m_bTextMode = CommandLine()->CheckParm( "-textmode" ) ? true : false;
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()
{
LoggingSystem_PopLoggingState();
}
//-----------------------------------------------------------------------------
// 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;
}
static bool s_GameInfoSuggestFN( CFSSteamSetupInfo const *pFsSteamSetupInfo, char *pchPathBuffer, int nBufferLength, bool *pbBubbleDirectories )
{
V_strncpy( pchPathBuffer, "left4dead", nBufferLength );
return true;
}
//-----------------------------------------------------------------------------
//
// Main entry point for dedicated server, shared between win32 and linux
//
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
#if !defined( POSIX ) && !defined( _WIN64 )
_asm
{
fninit
}
#endif
SetupFPUControlWord();
#ifdef POSIX
strcpy(g_szEXEName, *argv);
// Store off command line for argument searching
BuildCmdLine(argc, argv);
#endif
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
// Store off command line for argument searching
CommandLine()->CreateCmdLine( GetCommandLine() );
#ifndef _WIN32
Plat_SetCommandLine( CommandLine()->GetCmdLine() );
#endif
#ifdef LINUX
if ( CommandLine()->CheckParm( "-mtrace" ) )
{
mtrace();
}
#ifndef DEDICATED
if ( CommandLine()->CheckParm( "-logmem" ) )
{
EnableMemoryLogging( true );
}
#endif
#endif
// 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.
CommandLine()->CreateCmdLine( GetCommandLine() );
if ( !InitInstance() )
return -1;
SetSuggestGameInfoDirFn( s_GameInfoSuggestFN );
CDedicatedAppSystemGroup dedicatedSystems;
CDedicatedSteamApplication steamApplication( &dedicatedSystems );
int nRet = steamApplication.Run( );
#ifdef LINUX
#ifndef DEDICATED
EnableMemoryLogging( false );
if ( CommandLine()->CheckParm( "-mtrace" ) )
{
muntrace();
}
#endif
#endif
return nRet;
}

313
dedicated/sys_linux.cpp Normal file
View File

@@ -0,0 +1,313 @@
//========= Copyright (c) 1996-2005, 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 "conproc.h"
#include "dedicated.h"
#include "engine_hlds_api.h"
#include "checksum_md5.h"
#include "idedicatedexports.h"
#include "tier0/dbg.h"
#include "mathlib/mathlib.h"
#include "interface.h"
#include "tier1/strtools.h"
#include "tier0/stacktools.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 "net.h"
#include "vscript/ivscript.h"
bool InitInstance( );
void ProcessConsoleInput( void );
#define stringize(a) #a
#define engine_binary(a,b,c) a stringize(b) c
static const char *g_pszengine = "bin/engine" DLL_EXT_STRING;
static const char *g_pszsoundemitter = "bin/soundemitter" DLL_EXT_STRING;
char g_szEXEName[ 256 ];
#include "console/TextConsoleUnix.h"
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 (void);
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() );
}
else
{
StackToolsNotify_LoadedLibrary( absolute_lib );
}
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( void )
{
return console.GetLine();
}
/*
==============
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[] =
{
{ g_pszengine, CVAR_QUERY_INTERFACE_VERSION },
{ "bin/materialsystem" DLL_EXT_STRING, MATERIAL_SYSTEM_INTERFACE_VERSION },
{ "bin/studiorender" DLL_EXT_STRING, STUDIO_RENDER_INTERFACE_VERSION },
{ "bin/vphysics" DLL_EXT_STRING, VPHYSICS_INTERFACE_VERSION },
{ "bin/datacache" DLL_EXT_STRING, DATACACHE_INTERFACE_VERSION },
{ "bin/datacache" DLL_EXT_STRING, MDLCACHE_INTERFACE_VERSION },
{ "bin/datacache" DLL_EXT_STRING, STUDIO_DATA_CACHE_INTERFACE_VERSION },
{ "bin/vscript" DLL_EXT_STRING, VSCRIPT_INTERFACE_VERSION },
{ g_pszengine, 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( "bin/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);
}

845
dedicated/sys_subproc.cpp Normal file
View File

@@ -0,0 +1,845 @@
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifdef _LINUX
// linux has a multi-processing forked server mode.
#include <stdio.h>
#include <stdlib.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <syscall.h>
#include <unistd.h>
#include <arpa/inet.h>
//#include <linux/tcp.h>
#include <netdb.h>
//#include <sys/param.h>
#include <sys/uio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "isys.h"
#include "dedicated.h"
#include "engine_hlds_api.h"
#include "filesystem.h"
#include "tier0/dbg.h"
#include "tier1/strtools.h"
#include "tier0/icommandline.h"
#include "tier2/socketcreator.h"
#include "idedicatedexports.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include "mathlib/expressioncalculator.h"
#define closesocket close
#define WSAGetLastError() errno
#define ioctlsocket ioctl
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static netadr_t net_local_adr;
unsigned short NET_HostToNetShort( unsigned short us_in )
{
return htons( us_in );
}
unsigned short NET_NetToHostShort( unsigned short us_in )
{
return ntohs( us_in );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *s -
// *sadr -
// Output : bool NET_StringToSockaddr
//-----------------------------------------------------------------------------
bool NET_StringToSockaddr( const char *s, struct sockaddr *sadr )
{
char *colon;
char copy[128];
Q_memset (sadr, 0, sizeof(*sadr));
((struct sockaddr_in *)sadr)->sin_family = AF_INET;
((struct sockaddr_in *)sadr)->sin_port = 0;
Q_strncpy (copy, s, sizeof( copy ) );
// strip off a trailing :port if present
for (colon = copy ; *colon ; colon++)
{
if (*colon == ':')
{
*colon = 0;
((struct sockaddr_in *)sadr)->sin_port = NET_HostToNetShort((short)atoi(colon+1));
}
}
if (copy[0] >= '0' && copy[0] <= '9' && Q_strstr( copy, "." ) )
{
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(copy);
}
else
{
struct hostent *h;
if ( (h = gethostbyname(copy)) == NULL )
return false;
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
}
return true;
}
/*
=============
NET_StringToAdr
localhost
idnewt
idnewt:28000
192.246.40.70
192.246.40.70:28000
=============
*/
bool NET_StringToAdr ( const char *s, netadr_t *a)
{
struct sockaddr saddr;
char address[128];
Q_strncpy( address, s, sizeof(address) );
if ( !Q_strncmp( address, "localhost", 10 ) || !Q_strncmp( address, "localhost:", 10 ) )
{
// subsitute 'localhost' with '127.0.0.1", both have 9 chars
// this way we can resolve 'localhost' without DNS and still keep the port
Q_memcpy( address, "127.0.0.1", 9 );
}
if ( !NET_StringToSockaddr (address, &saddr) )
return false;
a->SetFromSockadr( &saddr );
return true;
}
void NET_GetLocalAddress (void)
{
net_local_adr.Clear();
char buff[512];
gethostname( buff, sizeof(buff) ); // get own IP address
buff[sizeof(buff)-1] = 0; // Ensure that it doesn't overrun the buffer
NET_StringToAdr (buff, &net_local_adr);
}
#define MAX_STATUS_STRING_LENGTH 1024
#define MAX_INPUT_FROM_CHILD 2048
class CConnectedNetConsoleData
{
public:
int m_nCharsInCommandBuffer;
char m_pszInputCommandBuffer[MAX_INPUT_FROM_CHILD];
bool m_bAuthorized; // for password protection
CConnectedNetConsoleData( void )
{
m_nCharsInCommandBuffer = 0;
m_bAuthorized = false;
}
};
class CParentProcessNetConsoleMgr : public ISocketCreatorListener
{
public:
CSocketCreator m_Socket;
netadr_t m_Address;
char m_pPassword[256]; // if set
bool m_bPasswordProtected;
bool m_bActive;
bool ShouldAcceptSocket( SocketHandle_t hSocket, const netadr_t &netAdr )
{
return true;
}
void OnSocketAccepted( SocketHandle_t hSocket, const netadr_t &netAdr, void** ppData )
{
CConnectedNetConsoleData *pData = new CConnectedNetConsoleData;
if ( ! m_bPasswordProtected )
pData->m_bAuthorized = true; // no password, auto-auth
*ppData = pData;
}
void OnSocketClosed( SocketHandle_t hSocket, const netadr_t &netAdr, void* pData )
{
if ( pData )
free( pData );
}
void RunFrame( void );
CParentProcessNetConsoleMgr( void );
void HandleInputChars( char const *pIn, int recvLen, CConnectedNetConsoleData *pData, int idx );
void SendString( char const *pString, int idx = -1 ); // send a string to all sockets or just one
void Execute( CConnectedNetConsoleData *pData, int idx );
};
void CParentProcessNetConsoleMgr::SendString( char const *pString, int nidx )
{
m_Socket.RunFrame();
int nCount = m_Socket.GetAcceptedSocketCount();
if ( nCount )
{
// lets add the lf to any cr's
char *pTmp = (char * ) stackalloc( strlen( pString ) * 2 + 1 );
char *oString = pTmp;
char const *pIn = pString;
while ( *pIn )
{
if ( *pIn == '\n' )
*( oString++ ) = '\r';
*( oString++ ) = *( pIn++ );
}
*( oString++ ) = 0;
for ( int i = 0; i < nCount; i++ )
{
if ( ( nidx == -1 ) || ( i == nidx ) )
{
SocketHandle_t hSocket = m_Socket.GetAcceptedSocketHandle( i );
//const netadr_t& socketAdr = m_Socket.GetAcceptedSocketAddress( i );
CConnectedNetConsoleData *pData = ( CConnectedNetConsoleData * ) m_Socket.GetAcceptedSocketData( i );
if ( pData->m_bAuthorized ) // no output to un-authed net consoles
{
send( hSocket, pTmp, oString - pTmp - 1, MSG_NOSIGNAL );
}
}
}
}
}
CParentProcessNetConsoleMgr::CParentProcessNetConsoleMgr( void ) : m_Socket( this )
{
m_bActive = false;
m_bPasswordProtected = false;
int nPassword = CommandLine()->FindParm( "-netconpassword" );
if ( nPassword )
{
char const *pPassword = CommandLine()->GetParm( nPassword + 1 );
V_strncpy( m_pPassword, pPassword, sizeof( m_pPassword ) );
m_bPasswordProtected = true;
}
int nPort = CommandLine()->FindParm( "-netconport" );
if ( nPort )
{
NET_GetLocalAddress();
char const *pPortNum = CommandLine()->GetParm( nPort + 1 );
char newBuf[256];
V_strncpy( newBuf, pPortNum, sizeof( newBuf ) );
char *pReplace = V_strstr( newBuf, "##" );
if ( pReplace )
{
pReplace[0] = '0';
pReplace[1] = '0';
}
m_Address = net_local_adr;
int nPortNumber = EvaluateExpression( newBuf, -1 );
if ( nPortNumber > 0 )
{
m_Address.SetPort( nPortNumber );
m_bActive = true;
m_Socket.CreateListenSocket( m_Address, true );
}
}
}
void CParentProcessNetConsoleMgr::RunFrame( void )
{
// check for incoming data
if (! m_bActive )
return;
m_Socket.RunFrame();
int nCount = m_Socket.GetAcceptedSocketCount();
for ( int i = nCount - 1; i >= 0; i-- )
{
SocketHandle_t hSocket = m_Socket.GetAcceptedSocketHandle( i );
// const netadr_t& socketAdr = m_Socket.GetAcceptedSocketAddress( i );
CConnectedNetConsoleData *pData = ( CConnectedNetConsoleData * ) m_Socket.GetAcceptedSocketData( i );
char ch;
int pendingLen = recv( hSocket, &ch, sizeof(ch), MSG_PEEK );
if ( pendingLen == -1 && SocketWouldBlock() )
continue;
if ( pendingLen <= 0 ) // eof or error
{
m_Socket.CloseAcceptedSocket( i );
continue;
}
// find out how much we have to read
unsigned long readLen;
ioctlsocket( hSocket, FIONREAD, &readLen );
while( readLen > 0 )
{
char recvBuf[256];
int recvLen = recv( hSocket, recvBuf , MIN( sizeof( recvBuf ) , readLen ), 0 );
if ( recvLen == 0 ) // socket was closed
{
m_Socket.CloseAcceptedSocket( i );
break;
}
if ( recvLen < 0 && !SocketWouldBlock() )
{
break;
}
readLen -= recvLen;
// now, lets write what we've got into the command buffer
HandleInputChars( recvBuf, recvLen, pData, i );
}
}
}
void CParentProcessNetConsoleMgr::HandleInputChars( char const *pIn, int recvLen, CConnectedNetConsoleData *pData, int idx )
{
while( recvLen )
{
switch( *pIn )
{
case '\r':
case '\n':
{
if ( pData->m_nCharsInCommandBuffer )
{
pData->m_pszInputCommandBuffer[pData->m_nCharsInCommandBuffer] = 0;
Execute( pData, idx );
}
pData->m_nCharsInCommandBuffer = 0;
break;
}
default:
{
if ( pData->m_nCharsInCommandBuffer < MAX_INPUT_FROM_CHILD - 1 )
pData->m_pszInputCommandBuffer[pData->m_nCharsInCommandBuffer++] = *pIn;
break;
}
}
pIn++;
recvLen--;
}
}
struct CServerInstance
{
pid_t m_nPid;
int m_nSocketToChild; // "our" side of the socket connection
int m_nNumCharsInInputBuffer;
int m_nNumPlayers;
char m_pszStatus[MAX_STATUS_STRING_LENGTH];
char m_pszMapName[MAX_PATH];
char m_pszInputBuffer[MAX_INPUT_FROM_CHILD];
bool m_bRunning;
void ClearInputBuffer( void )
{
m_nNumCharsInInputBuffer = 0;
}
void ResetStatus( void )
{
m_pszMapName[0] = 0;
m_nNumPlayers = 0;
}
CServerInstance( void )
{
m_pszStatus[0] = 0; // clear status string
m_bRunning = false;
m_nSocketToChild = -1;
ClearInputBuffer();
ResetStatus();
}
void HandleSocketInput( void );
void ProcessInputFromChild( void );
};
#define MAX_CHILD_PROCESSSES 100
CParentProcessNetConsoleMgr *g_pParentProcessNetConsole;
int g_nNumChildInstances;
CServerInstance *g_pChildProcesses;
static bool s_bQuit = false;
static bool s_bDelayedQuit = false;
typedef void (*CMDFN)( char const *pArgs, int nIdx );
struct CommandDescriptor
{
char const *m_pCmdName;
CMDFN m_pCmdFn;
char const *m_pCmdHelp;
};
static char *va( char *format, ... )
{
va_list argptr;
static char string[8][512];
static int curstring = 0;
curstring = ( curstring + 1 ) % 8;
va_start (argptr, format);
Q_vsnprintf( string[curstring], sizeof( string[curstring] ), format, argptr );
va_end (argptr);
return string[curstring];
}
static void s_DoStatusCmd( char const *pArgs, int nConsoleIdx )
{
// print status
g_pParentProcessNetConsole->SendString( "#status\n", nConsoleIdx );
for( int i = 0; i < g_nNumChildInstances; i++ )
{
CServerInstance *pChild = g_pChildProcesses + i;
g_pParentProcessNetConsole->SendString( va( "child %d\n", i ), nConsoleIdx );
if ( pChild && ( pChild->m_nSocketToChild != -1 ) )
{
g_pParentProcessNetConsole->SendString( va( " pid : %d\n", i, pChild->m_nPid ), nConsoleIdx );
g_pParentProcessNetConsole->SendString( va( " map : %s\n", pChild->m_pszMapName ), nConsoleIdx );
g_pParentProcessNetConsole->SendString( va( " numplayers : %d\n", pChild->m_nNumPlayers ), nConsoleIdx );
}
}
g_pParentProcessNetConsole->SendString( "#end\n", nConsoleIdx );
}
static void s_DoQuit( char const *pArgs, int nConsoleIdx )
{
g_pParentProcessNetConsole->SendString( "Killing all children and exiting\n", nConsoleIdx );
for( int i = 0; i < g_nNumChildInstances; i++ )
{
CServerInstance *pChild = g_pChildProcesses + i;
if ( pChild && ( pChild->m_nSocketToChild != -1 ) )
{
g_pParentProcessNetConsole->SendString( va( "killing child %d\n", i ), nConsoleIdx );
kill( pChild->m_nPid, SIGKILL );
}
}
s_bQuit = true;
}
static void s_DoBroadCastCmd( char const *pArgs, int nConsoleIdx )
{
if ( ! pArgs )
{
g_pParentProcessNetConsole->SendString( "Format of command is \"broadcast <concommand>\"\n" );
}
else
{
for( int i = 0; i < g_nNumChildInstances; i++ )
{
CServerInstance *pChild = g_pChildProcesses + i;
if ( pChild && ( pChild->m_nSocketToChild != -1 ) )
{
send( pChild->m_nSocketToChild, pArgs, strlen( pArgs ), MSG_NOSIGNAL );
send( pChild->m_nSocketToChild, "\n", 1, MSG_NOSIGNAL );
}
}
}
}
static void s_DoShutdown( char const *pArgs, int nConsoleIdx )
{
s_bDelayedQuit = ! s_bDelayedQuit;
if ( s_bDelayedQuit )
{
g_pParentProcessNetConsole->SendString( "Server will shutdown when all games are finished and children have exited.\n" );
}
else
{
g_pParentProcessNetConsole->SendString( "Server shutdown cancelled.\n" );
}
for( int i = 0; i < g_nNumChildInstances; i++ )
{
CServerInstance *pChild = g_pChildProcesses + i;
if ( pChild && ( pChild->m_nSocketToChild != -1 ) )
{
if ( pChild->m_nNumPlayers == 0 )
{
kill( pChild->m_nPid, SIGKILL );
}
}
}
}
static void s_DoFind( char const *pArgs, int nConsoleIdx );
static CommandDescriptor s_CmdTable[]={
{ "status", s_DoStatusCmd, "List the status of all subprocesses." },
{ "broadcast", s_DoBroadCastCmd, "Send a command to all subprocesses." },
{ "find", s_DoFind, "find commands containing a string." },
{ "shutdown", s_DoShutdown, "Tell the server shutdown once all players have left. This is a toggle." },
{ "quit", s_DoQuit, "immediately shut down the server and all its child processes." },
};
static void s_DoFind( char const *pArgs, int nConsoleIdx )
{
for( int i = 0; i < ARRAYSIZE( s_CmdTable ); i++ )
{
if ( ( pArgs[0] == 0 ) || ( V_stristr( s_CmdTable[i].m_pCmdName, pArgs ) ) )
{
g_pParentProcessNetConsole->SendString( va( "%s:\t%s\n", s_CmdTable[i].m_pCmdName, s_CmdTable[i].m_pCmdHelp) , nConsoleIdx );
}
}
}
void CParentProcessNetConsoleMgr::Execute( CConnectedNetConsoleData *pData, int idx )
{
if ( memcmp( pData->m_pszInputCommandBuffer, "PASS ", 5 ) == 0 )
{
if ( V_strcmp( pData->m_pszInputCommandBuffer + 5, m_pPassword ) == 0 )
{
pData->m_bAuthorized = true;
}
else
{
// bad password
Warning( "Bad password attempt from net console\n" );
pData->m_bAuthorized = false;
}
}
else
{
if ( pData->m_bAuthorized )
{
char const *pCmd = pData->m_pszInputCommandBuffer;
pCmd += strspn( pCmd, " \t" );
char const *pArgs = strchr( pCmd, ' ' );
int nCmdLen;
if ( pArgs )
{
nCmdLen = pArgs - pCmd;
pArgs += strspn( pArgs, " \t" ); // skip to first char of first word
}
else
{
nCmdLen = strlen( pCmd );
pArgs = pCmd + strlen( pCmd ); // point at trailing 0 bytes
}
for( int i = 0; i < ARRAYSIZE( s_CmdTable ); i++ )
{
char const *pTblCmd = s_CmdTable[i].m_pCmdName;
if ( ( strlen( pTblCmd ) == nCmdLen ) &&
( memcmp( pTblCmd, pCmd, nCmdLen ) == 0 ) )
{
// found it
( *s_CmdTable[i].m_pCmdFn )( pArgs, idx );
break;
}
}
}
else
{
SendString( "This server is password protected. Enter PASS <passwd> for access\n", idx );
}
}
}
static void HandleDeadChildProcesses( void )
{
for(;;)
{
int nStatus;
pid_t nWait = waitpid( -1, &nStatus, WNOHANG );
if ( nWait > 0 )
{
// find the process that exited
CServerInstance *pFound = NULL;
int nFound = -1;
for( int i = 0; i < g_nNumChildInstances; i++ )
{
if ( g_pChildProcesses[i].m_nPid == nWait )
{
pFound = g_pChildProcesses + i;
nFound = i;
break;
}
}
if ( ! pFound )
{
Warning( "unknown child process %d exited?\n", nWait );
}
else
{
if ( WIFEXITED( nStatus ) )
{
Msg( "Child %d exited with status %d\n", nFound, WEXITSTATUS( nStatus ) );
}
if ( WIFSIGNALED( nStatus ) )
{
Msg( "Child %d aborted with signal %d\n", nFound, WTERMSIG( nStatus ) );
}
if ( WCOREDUMP( nStatus ) )
{
Msg( "Child wrote a core dump\n");
}
pFound->m_bRunning = false;
if ( pFound->m_nSocketToChild != -1 )
{
close( pFound->m_nSocketToChild );
pFound->m_nSocketToChild = -1;
}
}
}
else
{
break; // no dead children
}
}
}
#define MAX_ACTIVE_PARENT_NETCONSOLE_SOCKETS 20
static void ServiceChildProcesses( void )
{
// for any children that aren't running (or not running yet), start them
pollfd pollFds[MAX_CHILD_PROCESSSES + 1 + MAX_ACTIVE_PARENT_NETCONSOLE_SOCKETS ];
int nPoll = 0;
int nNumRunning = 0;
for( int i = 0; i < g_nNumChildInstances; i++ )
{
if ( g_pChildProcesses[i].m_bRunning == false )
{
if (! s_bDelayedQuit )
{
int nSockets[2];
int nRslt = socketpair( AF_UNIX, SOCK_STREAM, 0, nSockets );
if ( nRslt != 0 )
{
Error( "socket pair returned error errno = %d\n", errno );
}
pid_t nChild = fork();
if ( nChild == 0 ) // are we the forked child?
{
//ResetBaseTime(); // start plat_float time over at 0 for precision
PerformCommandLineSubstitutions( i + 1 );
close( nSockets[1] );
engine->SetSubProcessID( i + 1, nSockets[0] );
g_nSubProcessId = i + 1;
RunServer( true );
syscall( SYS_exit, 0 ); // we are not going to perform a normal c++ exit. We _dont_ want to run destructors, etc.
}
else
{
g_pChildProcesses[i].m_nPid = nChild;
g_pChildProcesses[i].m_pszStatus[0] = 0;
g_pChildProcesses[i].m_bRunning = true;
close( nSockets[0] );
g_pChildProcesses[i].m_nSocketToChild = nSockets[1];
}
}
}
else
{
nNumRunning++;
}
if ( g_pChildProcesses[i].m_nSocketToChild != -1 )
{
pollFds[nPoll].fd = g_pChildProcesses[i].m_nSocketToChild;
pollFds[nPoll].events = POLLIN | POLLERR | POLLHUP;
pollFds[nPoll].revents = 0;
nPoll++;
}
}
if ( s_bDelayedQuit && ( nNumRunning == 0 ) )
{
_exit( 0 );
}
// now, wait for activity on any of our sockets or stdin
// pollFds[nPoll].fd = STDIN_FILENO;
// pollFds[nPoll].events = POLLIN;
// pollFds[nPoll].revents = 0;
// nPoll++;
if ( g_pParentProcessNetConsole && ( g_pParentProcessNetConsole->m_bActive ) )
{
pollFds[nPoll].fd = g_pParentProcessNetConsole->m_Socket.m_hListenSocket;
pollFds[nPoll].events = POLLIN;
pollFds[nPoll].revents = 0;
nPoll++;
int nCount = g_pParentProcessNetConsole->m_Socket.GetAcceptedSocketCount();
for( int i = 0; ( i < nCount ) && ( nPoll < ARRAYSIZE( pollFds ) ); i++ )
{
SocketHandle_t hSocket = g_pParentProcessNetConsole->m_Socket.GetAcceptedSocketHandle( i );
pollFds[nPoll].fd = hSocket;
pollFds[nPoll].events = POLLIN;
pollFds[nPoll].revents = 0;
nPoll++;
}
}
int nPollResult = poll( pollFds, nPoll, 10 * 1000 ); // wait up to 10 seconds. Could wait forever, really
// check for activity on the sockets from our children
int np = 0;
for( int i = 0; i < g_nNumChildInstances; i++ )
{
if ( g_pChildProcesses[i].m_nSocketToChild != -1 )
{
if ( pollFds[np].revents & POLLIN ) // data ready to read?
{
g_pChildProcesses[i].HandleSocketInput();
}
np++;
}
}
// see if any children have exited
HandleDeadChildProcesses();
g_pParentProcessNetConsole->RunFrame();
}
void RunServerSubProcesses( int nNumChildren )
{
g_nNumChildInstances = nNumChildren;
g_pChildProcesses = new CServerInstance[g_nNumChildInstances];
g_pParentProcessNetConsole = new CParentProcessNetConsoleMgr;
while( ! s_bQuit )
{
ServiceChildProcesses();
}
_exit( 0 );
}
static bool DecodeParam( char const *pParamName, char const *pInput, char const **pOutPtr )
{
// if the left of the string matches pParamName, return the right of the string else return null
int nPLen = strlen( pParamName );
if ( memcmp( pParamName, pInput, nPLen ) == 0 )
{
*pOutPtr= pInput + nPLen;
}
else
{
*pOutPtr = NULL;
}
return ( *pOutPtr );
}
void CServerInstance::ProcessInputFromChild( void )
{
if ( m_pszInputBuffer[0] == '#' ) // spew?
{
puts( m_pszInputBuffer );
}
else
{
char *pSpace = strchr( m_pszInputBuffer, ' ' );
if ( pSpace )
{
*( pSpace++ ) = 0;
pSpace += strspn( pSpace, " \t" );
}
else
{
pSpace = m_pszInputBuffer + strlen( m_pszInputBuffer );
}
if ( !strcmp( m_pszInputBuffer, "status" ) )
{
CUtlStringList statusRecords;
V_SplitString( pSpace, ";", statusRecords );
for( int i = 0; i < statusRecords.Count(); i++ )
{
char const *pRecord = statusRecords[i];
char const *pParm;
if ( DecodeParam( "map=", pRecord, &pParm ) )
{
V_strncpy( m_pszMapName, pParm, sizeof( m_pszMapName ) );
}
else if ( DecodeParam( "players=", pRecord, &pParm ) )
{
m_nNumPlayers = atoi( pParm );
}
}
}
else
{
Warning("got unknown cmd %s args %s\n", m_pszInputBuffer, pSpace );
}
}
}
void CServerInstance::HandleSocketInput( void )
{
char *pDest = m_pszInputBuffer + m_nNumCharsInInputBuffer;
int nRead = recv( m_nSocketToChild, pDest, sizeof( m_pszInputBuffer ) - m_nNumCharsInInputBuffer, MSG_DONTWAIT );
if ( nRead > 0 )
{
m_nNumCharsInInputBuffer += nRead;
if ( m_pszInputBuffer[m_nNumCharsInInputBuffer - 1] == 0 )
{
ProcessInputFromChild();
m_nNumCharsInInputBuffer = 0;
}
if ( m_nNumCharsInInputBuffer == MAX_INPUT_FROM_CHILD )
m_nNumCharsInInputBuffer = 0;
}
}
#endif //linux

413
dedicated/sys_windows.cpp Normal file
View File

@@ -0,0 +1,413 @@
//===== Copyright <20> 1996-2005, 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 "conproc.h"
#include "dedicated.h"
#include "engine_hlds_api.h"
#include "checksum_md5.h"
#include "tier0/dbg.h"
#include "tier0/stacktools.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 "vscript/ivscript.h"
#include "steam/steam_api.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 (void);
void Printf(const char *fmt, ...);
};
static CSys g_Sys;
ISys *sys = &g_Sys;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CSys::~CSys()
{
sys = NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : msec -
//-----------------------------------------------------------------------------
void CSys::Sleep( int msec )
{
::Sleep( msec );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *lib -
// Output : long
//-----------------------------------------------------------------------------
long CSys::LoadLibrary( char *lib )
{
void *hDll = ::LoadLibrary( lib );
if ( hDll )
StackToolsNotify_LoadedLibrary( 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(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 (void)
{
return console.GetLine();
}
//-----------------------------------------------------------------------------
// 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!!
{ "soundemittersystem.dll", SOUNDEMITTERSYSTEM_INTERFACE_VERSION },
{ "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
{ "inputsystem.dll", INPUTSTACKSYSTEM_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 },
#ifndef DOTA_DLL
{ "vscript.dll", VSCRIPT_INTERFACE_VERSION },
#endif
{ "engine.dll", VENGINE_HLDS_API_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;
strcpy( 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( GetCommandLine() );
if ( !Plat_IsInDebugSession() && !CommandLine()->FindParm( "-nominidumps") )
{
// This warning is not actually true in this context.
#pragma warning( suppress : 4535 ) // warning C4535: calling _set_se_translator() requires /EHa
_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,876 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifdef _WIN32
#include <stdio.h>
#include "steam.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
// filesystem_steam.cpp implements this useful function - mount all the caches for a given app ID.
extern void MountDependencies( int iAppId, CUtlVector<unsigned int> &depList );
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;
_snprintf( szTemp, sizeof(szTemp) - 1, "%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++ )
{
_snprintf(num, 3, "%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");
Q_strncpy(m_szGameName, "Half-Life", sizeof(m_szGameName));
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))
{
bool secure = m_pSavedData->GetBool("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", "");
}
// strncpy(m_szPassword, GetControlString("RCONPasswordEdit", ""), DATA_STR_LENGTH);
if (strlen(m_szPassword) < 3 || BadRconChars(m_szPassword))
{
MessageBox *dlg = new MessageBox("#Start_Server_RCON_Error_Title", "#Start_Server_RCON_Error");
dlg->DoModal();
}
else
{
_snprintf(cvars, 1024, "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);
// mount the caches
KeyValues *gameData = m_pGameCombo->GetActiveItemUserData();
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];
Q_strncpy( searchString, pDirectoryName, sizeof( searchString ) );
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".
Q_strncpy( fullFilename, filename, sizeof( fullFilename ) );
}
else
{
Q_strncpy( fullFilename, pDirectoryName, sizeof( fullFilename ) );
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;
strcpy(s.name,m_iServer.name);
strcpy(s.rconPassword,m_iServer.rconPassword);
memcpy(s.ip,m_iServer.ip,sizeof(m_iServer.ip));
memcpy(s.pings,m_iServer.pings,3*sizeof(int));
strcpy(s.gameDir,m_iServer.gameDir);
strcpy(s.map,m_iServer.map);
strcpy(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));
_snprintf(hostname, sizeof(hostname) - 1, "%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 );
Q_strncpy( m_szMod, pGameDir, sizeof( m_szMod ) );
// 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)
{
_snprintf(hostname, sizeof(hostname) - 1, "%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 <20> 1996-2005, 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 <20> 1996-2005, 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 <20> 1996-2005, 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 <20> 1996-2005, 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", "SourceScheme");
// 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() )
{
::MessageBox( NULL, msg, "Dedicated Server Message", MB_OK | MB_TOPMOST );
}
else if ( g_pMainPanel )
{
g_pMainPanel->AddConsoleText( msg );
}
}
#endif // _WIN32

View File

@@ -0,0 +1,26 @@
//===== Copyright <20> 1996-2005, 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 <20> 1996-2005, 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()
{
}