This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/host.c

589 lines
14 KiB
C
Raw Normal View History

2007-06-21 22:00:00 +02:00
//=======================================================================
// Copyright XashXT Group 2007 <20>
// host.c - dedicated and shared host
//=======================================================================
2008-06-09 22:00:00 +02:00
#include "common.h"
2008-08-04 22:00:00 +02:00
#include "input.h"
2007-11-25 22:00:00 +01:00
#include "client.h"
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
#define VID_NUM_MODES ( sizeof( vid_modes ) / sizeof( vid_modes[0] ))
2007-11-24 22:00:00 +01:00
physic_exp_t *pe;
2007-11-17 22:00:00 +01:00
render_exp_t *re;
2008-06-04 22:00:00 +02:00
vprogs_exp_t *vm;
2008-06-12 22:00:00 +02:00
vsound_exp_t *se;
2007-09-03 22:00:00 +02:00
host_parm_t host; // host parms
2007-11-30 22:00:00 +01:00
stdlib_api_t com, newcom;
2007-06-21 22:00:00 +02:00
byte *zonepool;
2007-09-11 22:00:00 +02:00
char *buildstring = __TIME__ " " __DATE__;
2007-09-02 22:00:00 +02:00
2009-09-10 22:00:00 +02:00
dll_info_t physic_dll = { "physic.dll", NULL, "CreateAPI", NULL, NULL, 1, sizeof(physic_exp_t), sizeof(stdlib_api_t) };
dll_info_t render_dll = { "render.dll", NULL, "CreateAPI", NULL, NULL, 0, sizeof(render_exp_t), sizeof(stdlib_api_t) };
dll_info_t vprogs_dll = { "vprogs.dll", NULL, "CreateAPI", NULL, NULL, 1, sizeof(vprogs_exp_t), sizeof(stdlib_api_t) };
dll_info_t vsound_dll = { "vsound.dll", NULL, "CreateAPI", NULL, NULL, 0, sizeof(vsound_exp_t), sizeof(stdlib_api_t) };
2007-06-21 22:00:00 +02:00
cvar_t *timescale;
2007-11-14 22:00:00 +01:00
cvar_t *host_serverstate;
2007-11-25 22:00:00 +01:00
cvar_t *host_cheats;
2008-07-11 22:00:00 +02:00
cvar_t *host_maxfps;
2009-02-03 22:00:00 +01:00
cvar_t *host_minfps;
cvar_t *host_ticrate;
cvar_t *host_framerate;
2008-07-31 22:00:00 +02:00
cvar_t *host_maxclients;
2008-08-01 22:00:00 +02:00
cvar_t *host_registered;
2007-11-17 22:00:00 +01:00
2008-07-31 22:00:00 +02:00
// these cvars will be duplicated on each client across network
int Host_ServerState( void ) { return (int)Cvar_VariableValue( "host_serverstate" ); }
int Host_MaxClients( void ) { return (int)bound( 1, Cvar_VariableValue( "host_maxclients" ), 255 ); }
2008-07-06 22:00:00 +02:00
2007-10-22 22:00:00 +02:00
void Host_InitPhysic( void )
{
static physic_imp_t pi;
2007-11-17 22:00:00 +01:00
launch_t CreatePhysic;
2007-10-22 22:00:00 +02:00
2007-10-27 22:00:00 +02:00
// phys callback
2007-11-11 22:00:00 +01:00
pi.api_size = sizeof(physic_imp_t);
2007-10-27 22:00:00 +02:00
pi.Transform = SV_Transform;
2008-06-03 22:00:00 +02:00
pi.PlaySound = SV_PlaySound;
2008-05-24 22:00:00 +02:00
pi.ClientMove = SV_PlayerMove;
2008-01-12 22:00:00 +01:00
pi.GetModelVerts = SV_GetModelVerts;
2007-10-27 22:00:00 +02:00
2007-10-22 22:00:00 +02:00
Sys_LoadLibrary( &physic_dll );
2007-11-17 22:00:00 +01:00
CreatePhysic = (void *)physic_dll.main;
2007-11-30 22:00:00 +01:00
pe = CreatePhysic( &newcom, &pi );
2007-10-22 22:00:00 +02:00
2007-11-24 22:00:00 +01:00
pe->Init();
2007-10-22 22:00:00 +02:00
}
void Host_FreePhysic( void )
{
if(physic_dll.link)
{
2007-11-24 22:00:00 +01:00
pe->Shutdown();
2008-10-29 22:00:00 +01:00
Mem_Set( &pe, 0, sizeof(pe));
2007-10-22 22:00:00 +02:00
}
Sys_FreeLibrary( &physic_dll );
}
2007-11-17 22:00:00 +01:00
void Host_InitRender( void )
{
static render_imp_t ri;
launch_t CreateRender;
2008-08-04 22:00:00 +02:00
bool result = false;
2007-11-17 22:00:00 +01:00
ri.api_size = sizeof(render_imp_t);
// studio callbacks
2008-11-08 22:00:00 +01:00
ri.UpdateScreen = SCR_UpdateScreen;
2007-11-17 22:00:00 +01:00
ri.StudioEvent = CL_StudioEvent;
2009-09-03 22:00:00 +02:00
ri.StudioFxTransform = CL_StudioFxTransform;
2007-12-11 22:00:00 +01:00
ri.ShowCollision = pe->DrawCollision;
2008-08-05 22:00:00 +02:00
ri.GetClientEdict = CL_GetEdictByIndex;
ri.GetLocalPlayer = CL_GetLocalPlayer;
ri.GetMaxClients = CL_GetMaxClients;
2008-08-04 22:00:00 +02:00
ri.WndProc = IN_WndProc;
2007-11-17 22:00:00 +01:00
Sys_LoadLibrary( &render_dll );
2008-08-04 22:00:00 +02:00
if( render_dll.link )
{
CreateRender = (void *)render_dll.main;
re = CreateRender( &newcom, &ri );
2008-11-15 22:00:00 +01:00
if( re->Init( true )) result = true;
2008-08-04 22:00:00 +02:00
}
// video system not started, run dedicated server
2009-01-31 22:00:00 +01:00
if( !result ) Sys_NewInstance( va("#%s", GI->gamedir ), "Host_InitRender: fallback to dedicated mode\n" );
2007-11-17 22:00:00 +01:00
}
void Host_FreeRender( void )
{
2008-11-15 22:00:00 +01:00
if( render_dll.link )
2007-11-17 22:00:00 +01:00
{
2008-11-15 22:00:00 +01:00
re->Shutdown( true );
Mem_Set( &re, 0, sizeof( re ));
2007-11-17 22:00:00 +01:00
}
Sys_FreeLibrary( &render_dll );
}
2009-08-18 22:00:00 +02:00
void Host_InitVprogs( const int argc, const char **argv )
2008-06-04 22:00:00 +02:00
{
2008-06-12 22:00:00 +02:00
launch_t CreateVprogs;
2008-06-04 22:00:00 +02:00
Sys_LoadLibrary( &vprogs_dll );
CreateVprogs = (void *)vprogs_dll.main;
vm = CreateVprogs( &newcom, NULL ); // second interface not allowed
2008-07-30 22:00:00 +02:00
vm->Init( argc, argv );
2008-06-04 22:00:00 +02:00
}
void Host_FreeVprogs( void )
{
2008-11-15 22:00:00 +01:00
if( vprogs_dll.link )
2008-06-04 22:00:00 +02:00
{
vm->Free();
2008-10-29 22:00:00 +01:00
Mem_Set( &vm, 0, sizeof(vm));
2008-06-04 22:00:00 +02:00
}
Sys_FreeLibrary( &vprogs_dll );
}
2008-12-03 22:00:00 +01:00
void Host_FreeSound( void )
{
if( vsound_dll.link )
{
se->Shutdown();
Mem_Set( &se, 0, sizeof( se ));
}
Sys_FreeLibrary( &vsound_dll );
}
2008-06-12 22:00:00 +02:00
void Host_InitSound( void )
{
static vsound_imp_t si;
launch_t CreateSound;
2008-12-03 22:00:00 +01:00
bool result = false;
2008-06-12 22:00:00 +02:00
// phys callback
si.api_size = sizeof(vsound_imp_t);
si.GetSoundSpatialization = CL_GetEntitySoundSpatialization;
2008-11-16 22:00:00 +01:00
si.PointContents = CL_PointContents;
2008-06-12 22:00:00 +02:00
si.AddLoopingSounds = CL_AddLoopingSounds;
Sys_LoadLibrary( &vsound_dll );
2008-12-03 22:00:00 +01:00
if( vsound_dll.link )
2008-06-12 22:00:00 +02:00
{
2008-12-03 22:00:00 +01:00
CreateSound = (void *)vsound_dll.main;
se = CreateSound( &newcom, &si );
if( se->Init( host.hWnd )) result = true;
2008-06-12 22:00:00 +02:00
}
2008-12-03 22:00:00 +01:00
// audio system not started, shutdown sound subsystem
if( !result ) Host_FreeSound();
2008-06-12 22:00:00 +02:00
}
2007-09-10 22:00:00 +02:00
/*
================
Host_AbortCurrentFrame
aborts the current host frame and goes on with the next one
================
*/
void Host_AbortCurrentFrame( void )
{
2008-05-18 22:00:00 +02:00
longjmp( host.abortframe, 1 );
2007-09-10 22:00:00 +02:00
}
2007-11-14 22:00:00 +01:00
/*
==================
Host_SetServerState
==================
*/
void Host_SetServerState( int state )
{
2008-07-31 22:00:00 +02:00
Cvar_SetValue( "host_serverstate", state );
2007-11-14 22:00:00 +01:00
}
2007-06-21 22:00:00 +02:00
/*
=================
2007-11-17 22:00:00 +01:00
Host_VidRestart_f
Restart the video subsystem
2007-06-21 22:00:00 +02:00
=================
*/
2007-11-17 22:00:00 +01:00
void Host_VidRestart_f( void )
2007-06-21 22:00:00 +02:00
{
2009-02-02 22:00:00 +01:00
host.state = HOST_RESTART;
2007-11-17 22:00:00 +01:00
S_StopAllSounds(); // don't let them loop during the restart
2008-08-03 22:00:00 +02:00
cl.video_prepped = false;
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
Host_FreeRender(); // release render.dll
Host_InitRender(); // load it again
2009-02-02 22:00:00 +01:00
2009-01-25 22:00:00 +01:00
SCR_RegisterShaders(); // reload 2d-shaders
2007-11-17 22:00:00 +01:00
}
2007-06-21 22:00:00 +02:00
2008-06-12 22:00:00 +02:00
/*
=================
Host_SndRestart_f
Restart the audio subsystem
=================
*/
void Host_SndRestart_f( void )
{
2009-02-02 22:00:00 +01:00
host.state = HOST_RESTART;
2008-08-03 22:00:00 +02:00
S_StopAllSounds(); // don't let them loop during the restart
cl.audio_prepped = false;
2008-06-12 22:00:00 +02:00
Host_FreeSound(); // release vsound.dll
Host_InitSound(); // load it again
}
2008-08-04 22:00:00 +02:00
void Host_ChangeGame_f( void )
{
int i;
if( Cmd_Argc() != 2 )
{
2009-09-10 22:00:00 +02:00
Msg( "Usage: game <directory>\n" );
2008-08-04 22:00:00 +02:00
return;
}
// validate gamedir
2009-09-10 22:00:00 +02:00
for( i = 0; i < SI->numgames; i++ )
2008-08-04 22:00:00 +02:00
{
2009-09-10 22:00:00 +02:00
if( !com.stricmp( SI->games[i]->gamefolder, Cmd_Argv( 1 )))
2008-08-04 22:00:00 +02:00
break;
}
2009-09-10 22:00:00 +02:00
if( i == SI->numgames ) Msg( "%s not exist\n", Cmd_Argv( 1 ));
else if( !com.stricmp( GI->gamefolder, Cmd_Argv( 1 )))
Msg( "%s already active\n", Cmd_Argv( 1 ));
else Sys_NewInstance( Cmd_Argv( 1 ), "Host_ChangeGame\n" );
2008-08-04 22:00:00 +02:00
}
2008-08-10 22:00:00 +02:00
void Host_Minimize_f( void )
{
if( host.hWnd ) ShowWindow( host.hWnd, SW_MINIMIZE );
}
2007-11-17 22:00:00 +01:00
/*
============
VID_Init
============
*/
void VID_Init( void )
{
2009-09-10 22:00:00 +02:00
scr_width = Cvar_Get( "width", "640", 0, "screen width" );
scr_height = Cvar_Get( "height", "480", 0, "screen height" );
2008-06-12 22:00:00 +02:00
2008-08-10 22:00:00 +02:00
Cmd_AddCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
2008-08-04 22:00:00 +02:00
Cmd_AddCommand( "vid_restart", Host_VidRestart_f, "restarts video system" );
Cmd_AddCommand( "snd_restart", Host_SndRestart_f, "restarts audio system" );
Cmd_AddCommand( "game", Host_ChangeGame_f, "change game" );
2007-06-21 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
Host_InitRender();
2008-06-12 22:00:00 +02:00
Host_InitSound();
2007-11-17 22:00:00 +01:00
}
2007-06-21 22:00:00 +02:00
2008-07-06 22:00:00 +02:00
/*
=================
Host_EventLoop
Returns last event time
=================
*/
2009-02-03 22:00:00 +01:00
void Host_EventLoop( void )
2008-07-06 22:00:00 +02:00
{
sys_event_t ev;
while( 1 )
{
2009-02-03 22:00:00 +01:00
ev = Sys_GetEvent();
switch( ev.type )
2008-07-06 22:00:00 +02:00
{
case SE_NONE:
2009-06-22 22:00:00 +02:00
// end of events
2009-02-03 22:00:00 +01:00
return;
2008-07-06 22:00:00 +02:00
case SE_KEY:
2009-02-03 22:00:00 +01:00
Key_Event( ev.value[0], ev.value[1] );
2008-07-06 22:00:00 +02:00
break;
case SE_CHAR:
CL_CharEvent( ev.value[0] );
break;
case SE_MOUSE:
2009-02-03 22:00:00 +01:00
CL_MouseEvent( ev.value[0], ev.value[1] );
2008-07-06 22:00:00 +02:00
break;
case SE_CONSOLE:
2009-06-22 22:00:00 +02:00
Cbuf_AddText( va( "%s\n", ev.data ));
2008-07-12 22:00:00 +02:00
break;
2008-07-06 22:00:00 +02:00
default:
Host_Error( "Host_EventLoop: bad event type %i", ev.type );
break;
}
if( ev.data ) Mem_Free( ev.data );
}
}
/*
2009-02-03 22:00:00 +01:00
===================
Host_FilterTime
2008-07-06 22:00:00 +02:00
2009-02-03 22:00:00 +01:00
Returns false if the time is too short to run a frame
===================
2008-07-06 22:00:00 +02:00
*/
2009-02-03 22:00:00 +01:00
bool Host_FilterTime( double time )
2008-07-06 22:00:00 +02:00
{
2009-02-03 22:00:00 +01:00
host.realtime += time;
2008-07-06 22:00:00 +02:00
2009-07-03 22:00:00 +02:00
if( host.realtime - host.oldrealtime < 1.0 / host_maxfps->value )
return false; // framerate is too high
2008-07-06 22:00:00 +02:00
2009-02-03 22:00:00 +01:00
host.realframetime = host.frametime = host.realtime - host.oldrealtime;
host.oldrealtime = host.realtime;
if( host_framerate->value > 0 )
2008-07-06 22:00:00 +02:00
{
2009-02-03 22:00:00 +01:00
host.frametime = host_framerate->value;
2008-07-06 22:00:00 +02:00
}
2009-02-03 22:00:00 +01:00
else
2009-07-03 22:00:00 +02:00
{ // don't allow really long or short frames
if( host.frametime > 0.1f )
host.frametime = 0.1f;
if( host.frametime < 0.001f )
host.frametime = 0.001f;
2008-07-06 22:00:00 +02:00
}
2009-02-03 22:00:00 +01:00
return true;
2008-07-06 22:00:00 +02:00
}
2007-06-21 22:00:00 +02:00
/*
=================
Host_Frame
=================
*/
2009-02-03 22:00:00 +01:00
void Host_Frame( double time )
2008-07-06 22:00:00 +02:00
{
2008-12-20 22:00:00 +01:00
if( setjmp( host.abortframe ))
2008-07-06 22:00:00 +02:00
return;
rand(); // keep the random time dependent
2009-02-03 22:00:00 +01:00
// decide the simulation time
if( !Host_FilterTime( time ))
return;
Host_EventLoop (); // process all system events
2009-07-03 22:00:00 +02:00
Cbuf_Execute (); // execute commands
2008-07-06 22:00:00 +02:00
2009-07-04 22:00:00 +02:00
SV_Frame ( host.frametime ); // server frame
CL_Frame ( host.frametime ); // client frame
VM_Frame ( host.frametime ); // vprogs frame
2008-07-06 22:00:00 +02:00
host.framecount++;
}
2007-11-14 22:00:00 +01:00
/*
================
Host_Print
Handles cursor positioning, line wrapping, etc
All console printing must go through this in order to be logged to disk
If no console is visible, the text will appear at the top of the game window
================
*/
void Host_Print( const char *txt )
{
2008-07-12 22:00:00 +02:00
if( host.rd.target )
2007-11-14 22:00:00 +01:00
{
2008-07-12 22:00:00 +02:00
if((com.strlen (txt) + com.strlen(host.rd.buffer)) > (host.rd.buffersize - 1))
2007-11-14 22:00:00 +01:00
{
2008-07-12 22:00:00 +02:00
if( host.rd.flush )
2007-11-14 22:00:00 +01:00
{
2008-07-12 22:00:00 +02:00
host.rd.flush( host.rd.address, host.rd.target, host.rd.buffer );
2007-11-14 22:00:00 +01:00
*host.rd.buffer = 0;
}
}
2008-07-12 22:00:00 +02:00
com.strcat( host.rd.buffer, txt );
2007-11-14 22:00:00 +01:00
return;
}
Con_Print( txt ); // echo to client console
}
2007-09-10 22:00:00 +02:00
/*
=================
Host_Error
=================
*/
void Host_Error( const char *error, ... )
{
2008-07-23 22:00:00 +02:00
static char hosterror1[MAX_MSGLEN];
static char hosterror2[MAX_MSGLEN];
2007-09-10 22:00:00 +02:00
static bool recursive = false;
va_list argptr;
va_start( argptr, error );
2008-06-09 22:00:00 +02:00
com.vsprintf( hosterror1, error, argptr );
2007-09-10 22:00:00 +02:00
va_end( argptr );
2008-11-05 22:00:00 +01:00
if( host.framecount < 3 || host.state == HOST_SHUTDOWN )
2008-11-04 22:00:00 +01:00
{
2008-12-25 22:00:00 +01:00
Msg( "Host_InitError: " );
2008-08-04 22:00:00 +02:00
com.error( hosterror1 );
2008-11-04 22:00:00 +01:00
}
2008-11-05 22:00:00 +01:00
else if( host.framecount == host.errorframe )
{
com.error( "Host_MultiError: %s", hosterror2 );
return;
}
2008-08-04 22:00:00 +02:00
else Msg( "Host_Error: %s", hosterror1 );
2007-09-10 22:00:00 +02:00
2008-08-04 22:00:00 +02:00
if( recursive )
2007-09-10 22:00:00 +02:00
{
2008-11-06 22:00:00 +01:00
Msg( "Host_RecursiveError: %s", hosterror2 );
2008-08-08 22:00:00 +02:00
com.error( va( "%s", hosterror1 ));
2007-11-21 22:00:00 +01:00
return; // don't multiple executes
2007-09-10 22:00:00 +02:00
}
2007-11-21 22:00:00 +01:00
2007-09-10 22:00:00 +02:00
recursive = true;
2008-11-04 22:00:00 +01:00
com.strncpy( hosterror2, hosterror1, MAX_MSGLEN );
2008-11-06 22:00:00 +01:00
host.errorframe = host.framecount; // to avoid multply calls per frame
2008-05-18 22:00:00 +02:00
com.sprintf( host.finalmsg, "Server crashed: %s\n", hosterror1 );
2007-09-10 22:00:00 +02:00
2007-11-21 22:00:00 +01:00
SV_Shutdown( false );
2007-09-10 22:00:00 +02:00
CL_Drop(); // drop clients
recursive = false;
Host_AbortCurrentFrame();
2007-09-22 22:00:00 +02:00
host.state = HOST_ERROR;
2007-09-10 22:00:00 +02:00
}
void Host_Error_f( void )
{
2008-08-03 22:00:00 +02:00
if( Cmd_Argc() == 1 ) Sys_Break( "\n" );
else Host_Error( "%s\n", Cmd_Argv( 1 ));
2007-11-17 22:00:00 +01:00
}
/*
=================
Host_Crash_f
=================
*/
2008-07-11 22:00:00 +02:00
static void Host_Crash_f (void)
2007-11-17 22:00:00 +01:00
{
*(int *)0 = 0xffffffff;
}
2009-08-18 22:00:00 +02:00
void Host_InitCommon( const int argc, const char **argv )
2008-07-06 22:00:00 +02:00
{
char dev_level[4];
newcom = com;
// overload some funcs
newcom.error = Host_Error;
// check developer mode
2009-02-03 22:00:00 +01:00
if( FS_GetParmFromCmdLine( "-dev", dev_level ))
host.developer = com.atoi( dev_level );
2008-07-06 22:00:00 +02:00
2009-09-10 22:00:00 +02:00
FS_LoadGameInfo();
zonepool = Mem_AllocPool( "Zone Engine" );
2008-07-06 22:00:00 +02:00
IN_Init();
}
void Host_FreeCommon( void )
{
IN_Shutdown();
Mem_FreePool( &zonepool );
}
2007-11-17 22:00:00 +01:00
/*
=================
Host_Init
=================
*/
2009-08-18 22:00:00 +02:00
void Host_Init( const int argc, const char **argv )
2007-11-17 22:00:00 +01:00
{
char *s;
host.state = HOST_INIT; // initialzation started
2009-09-10 22:00:00 +02:00
host.type = g_Instance();
2007-11-17 22:00:00 +01:00
2009-01-11 22:00:00 +01:00
Host_InitCommon( argc, argv );
2007-11-17 22:00:00 +01:00
Key_Init();
2009-09-10 22:00:00 +02:00
// get default configuration (but disable for save default config)
if( FS_FileExists( "config/basekeys.rc" )) Cbuf_AddText( "exec keys.rc\n" );
if( FS_FileExists( "config/basevars.rc" )) Cbuf_AddText( "exec vars.rc\n" );
2007-11-17 22:00:00 +01:00
Cbuf_Execute();
// init commands and vars
2008-07-31 22:00:00 +02:00
if( host.developer )
2007-11-17 22:00:00 +01:00
{
Cmd_AddCommand ("error", Host_Error_f, "just throw a fatal error to test shutdown procedures" );
Cmd_AddCommand ("crash", Host_Crash_f, "a way to force a bus error for development reasons");
}
2008-07-17 22:00:00 +02:00
2009-02-03 22:00:00 +01:00
host_cheats = Cvar_Get( "sv_cheats", "1", CVAR_SYSTEMINFO, "allow cheat variables to enable" );
host_minfps = Cvar_Get( "host_minfps", "10", CVAR_ARCHIVE, "host fps lower limit" );
2008-07-06 22:00:00 +02:00
host_maxfps = Cvar_Get( "host_maxfps", "100", CVAR_ARCHIVE, "host fps upper limit" );
2009-02-03 22:00:00 +01:00
host_ticrate = Cvar_Get( "sys_ticrate", "0.0138889", CVAR_SYSTEMINFO, "how long a server frame is in seconds" );
host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" );
2008-08-01 22:00:00 +02:00
host_maxclients = Cvar_Get("host_maxclients", "1", CVAR_SERVERINFO|CVAR_LATCH, "server maxplayers limit" );
host_serverstate = Cvar_Get("host_serverstate", "0", CVAR_SERVERINFO, "displays current server state" );
host_registered = Cvar_Get( "registered", "1", CVAR_SYSTEMINFO, "indicate shareware version of game" );
2009-02-03 22:00:00 +01:00
timescale = Cvar_Get( "timescale", "1.0", 0, "slow-mo timescale" );
2007-11-17 22:00:00 +01:00
2007-11-27 22:00:00 +01:00
s = va("^1Xash %g ^3%s", GI->version, buildstring );
2008-06-29 22:00:00 +02:00
Cvar_Get( "version", s, CVAR_SERVERINFO|CVAR_INIT, "engine current version" );
2008-07-11 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
NET_Init();
Netchan_Init();
Host_InitPhysic();
2008-06-04 22:00:00 +02:00
Host_InitVprogs( argc, argv );
2008-07-11 22:00:00 +02:00
2008-07-17 22:00:00 +02:00
// per level user limit
2009-01-22 22:00:00 +01:00
host.max_edicts = bound( 8, Cvar_VariableValue( "host_maxedicts" ), MAX_EDICTS - 1 );
2008-07-17 22:00:00 +02:00
2007-11-17 22:00:00 +01:00
SV_Init();
CL_Init();
2008-07-06 22:00:00 +02:00
2009-09-10 22:00:00 +02:00
Host_WriteDefaultConfig ();
2009-07-12 22:00:00 +02:00
if( host.type == HOST_DEDICATED )
{
2009-09-10 22:00:00 +02:00
Cmd_AddCommand( "quit", Sys_Quit, "quit the game" );
Cmd_AddCommand( "exit", Sys_Quit, "quit the game" );
2009-07-12 22:00:00 +02:00
}
2008-11-04 22:00:00 +01:00
host.errorframe = 0;
2007-11-17 22:00:00 +01:00
}
/*
=================
Host_Main
=================
*/
void Host_Main( void )
{
2009-02-03 22:00:00 +01:00
static double oldtime, newtime;
oldtime = Sys_DoubleTime();
2007-11-17 22:00:00 +01:00
// main window message loop
2007-11-21 22:00:00 +01:00
while( host.type != HOST_OFFLINE )
2007-11-17 22:00:00 +01:00
{
2008-07-06 22:00:00 +02:00
IN_Frame();
2009-02-03 22:00:00 +01:00
newtime = Sys_DoubleTime ();
Host_Frame( newtime - oldtime );
oldtime = newtime;
2007-11-17 22:00:00 +01:00
}
}
/*
=================
Host_Shutdown
=================
*/
void Host_Free( void )
{
2008-06-06 22:00:00 +02:00
host.state = HOST_SHUTDOWN; // prepare host to normal shutdown
com.strncpy( host.finalmsg, "Server shutdown\n", MAX_STRING );
2007-11-21 22:00:00 +01:00
SV_Shutdown( false );
2007-11-17 22:00:00 +01:00
CL_Shutdown();
Host_FreeRender();
NET_Shutdown();
2008-06-04 22:00:00 +02:00
Host_FreeVprogs();
2007-11-17 22:00:00 +01:00
Host_FreePhysic();
Host_FreeCommon();
2007-06-21 22:00:00 +02:00
}