initial
This commit is contained in:
148
dedicated/_vpc_/manifest_dedicated/win32/manifest.txt
Normal file
148
dedicated/_vpc_/manifest_dedicated/win32/manifest.txt
Normal 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
425
dedicated/conproc.cpp
Normal 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
30
dedicated/conproc.h
Normal 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
|
||||
360
dedicated/console/TextConsoleUnix.cpp
Normal file
360
dedicated/console/TextConsoleUnix.cpp
Normal 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
|
||||
59
dedicated/console/TextConsoleUnix.h
Normal file
59
dedicated/console/TextConsoleUnix.h
Normal 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
|
||||
277
dedicated/console/TextConsoleWin32.cpp
Normal file
277
dedicated/console/TextConsoleWin32.cpp
Normal 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
|
||||
55
dedicated/console/TextConsoleWin32.h
Normal file
55
dedicated/console/TextConsoleWin32.h
Normal 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
|
||||
427
dedicated/console/conproc.cpp
Normal file
427
dedicated/console/conproc.cpp
Normal 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
|
||||
|
||||
30
dedicated/console/conproc.h
Normal file
30
dedicated/console/conproc.h
Normal 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
|
||||
406
dedicated/console/textconsole.cpp
Normal file
406
dedicated/console/textconsole.cpp
Normal 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++;
|
||||
}
|
||||
76
dedicated/console/textconsole.h
Normal file
76
dedicated/console/textconsole.h
Normal 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
88
dedicated/dedicated.h
Normal 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
72
dedicated/dedicated.rc
Normal file
@@ -0,0 +1,72 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_HALFLIFE ICON DISCARDABLE "..\\launcher\\res\\launcher.ico"
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
127
dedicated/dedicated.vpc
Normal file
127
dedicated/dedicated.vpc
Normal 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]
|
||||
}
|
||||
}
|
||||
13
dedicated/dedicated.vpc.vpc_cache
Normal file
13
dedicated/dedicated.vpc.vpc_cache
Normal 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
97
dedicated/filesystem.cpp
Normal 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
45
dedicated/isys.h
Normal 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
25
dedicated/resource.h
Normal 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
303
dedicated/sys_common.cpp
Normal 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
667
dedicated/sys_ded.cpp
Normal 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
313
dedicated/sys_linux.cpp
Normal 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
845
dedicated/sys_subproc.cpp
Normal 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
413
dedicated/sys_windows.cpp
Normal 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;
|
||||
}
|
||||
|
||||
876
dedicated/vgui/CreateMultiplayerGameServerPage.cpp
Normal file
876
dedicated/vgui/CreateMultiplayerGameServerPage.cpp
Normal 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
|
||||
|
||||
126
dedicated/vgui/CreateMultiplayerGameServerPage.h
Normal file
126
dedicated/vgui/CreateMultiplayerGameServerPage.h
Normal 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
|
||||
274
dedicated/vgui/MainPanel.cpp
Normal file
274
dedicated/vgui/MainPanel.cpp
Normal 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
|
||||
89
dedicated/vgui/MainPanel.h
Normal file
89
dedicated/vgui/MainPanel.h
Normal 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
|
||||
187
dedicated/vgui/vguihelpers.cpp
Normal file
187
dedicated/vgui/vguihelpers.cpp
Normal 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
|
||||
|
||||
26
dedicated/vgui/vguihelpers.h
Normal file
26
dedicated/vgui/vguihelpers.h
Normal 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
|
||||
|
||||
39
dedicated/vgui/vguihelpers_linux.cpp
Normal file
39
dedicated/vgui/vguihelpers_linux.cpp
Normal 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()
|
||||
{
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user