2010-02-15 23:26:55 +00:00
/*
Copyright ( C ) 1996 - 2001 Id Software , Inc .
Copyright ( C ) 2002 - 2009 John Fitzgibbons and others
Copyright ( C ) 2007 - 2008 Kristian Duske
2014-09-22 08:55:46 +00:00
Copyright ( C ) 2010 - 2014 QuakeSpasm developers
2010-02-15 23:26:55 +00:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
// host.c -- coordinates spawning and killing of local servers
# include "quakedef.h"
Backported external music files support using decoder libraries and the
new raw samples interface from Hammer of Thyrion (uhexen2) :
- bgmusic.c, bgmusic.h: New BGM interface for background music handling.
Handles streaming music as raw sound samples.
- bgmnull.c: BGM source for cases where the engine is configured for no
sound.
- cl_main.c: Include bgmusic.h. Call BGM_Stop() and CDAudio_Stop() in
CL_Disconnect().
- cd_sdl.c: Moved bgmvolume boundary checking to bgmusic.c upon value
changes.
- gl_vidnt.c, gl_vidsdl.c, cl_parse.c: Include bgmusic.h. Add BGM_Pause()
and BGM_Resume() calls along with CDAudio_ counterparts.
- cl_parse.c: Replace CDAudio_Play() call by the new BGM_PlayCDtrack()
which first tries CDAudio_Play() and then streaming music if it fails.
- host.c: Include bgmusic.h. Call BGM_Update() just before S_Update()
in Host_Frame(). In Host_Init(), call BGM_Init() after other audio init
calls. In Host_Shutdown(), call BGM_Shutdown() before all other audio
shutdown calls.
- snd_dma.c: Include snd_codec.h and bgmusic.h. Call S_CodecInit() from
S_Init(). Call S_CodecShutdown() from S_Shutdown().
- snd_codec.c, snd_codec.h: New public codec interface for streaming
music as raw samples. Adapted from quake2 and ioquake3 with changes.
Individual codecs are responsible for handling any necessary byte swap
operations.
- snd_codeci.h: New header for snd_codec internals.
- snd_wave.c, snd_wave.h: Codec for WAV format streaming music. Adapted
from ioquake3 with changes.
- snd_vorbis.c, snd_vorbis.h: Codec for Ogg/Vorbis format streaming music.
- snd_mp3.c, snd_mp3.h: Codec for MP3 format streaming music using libmad.
Adapted from the SoX project with changes.
- Makefile: Adjusted for the new sources. Added switches USE_CODEC_WAVE,
USE_CODEC_MP3, USE_CODEC_VORBIS for enabling and disabling individual
codecs.
- Windows makefiles and project files as well as other CodeBlocks project
files will be updated shortly.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@374 af15c1b1-3010-417e-b628-4374ebc0bcbd
2011-01-05 19:50:43 +00:00
# include "bgmusic.h"
2010-08-14 20:55:39 +00:00
# include <setjmp.h>
2010-02-15 23:26:55 +00:00
/*
A server can allways be started , even if the system started out as a client
to a remote system .
A client can NOT be started if the system started as a dedicated server .
Memory is cleared / released when a server or client begins , not when they end .
*/
2011-04-19 16:41:45 +00:00
quakeparms_t * host_parms ;
2010-02-15 23:26:55 +00:00
qboolean host_initialized ; // true if into command execution
double host_frametime ;
double realtime ; // without any filtering or bounding
double oldrealtime ; // last frame run
2011-12-23 12:03:49 +00:00
int host_framecount ;
2010-02-15 23:26:55 +00:00
2011-12-23 12:03:49 +00:00
int host_hunklevel ;
int minimum_memory ;
2010-02-15 23:26:55 +00:00
client_t * host_client ; // current client
jmp_buf host_abortserver ;
byte * host_colormap ;
2018-05-13 07:00:41 +00:00
float host_netinterval ;
2011-12-28 22:01:33 +00:00
cvar_t host_framerate = { " host_framerate " , " 0 " , CVAR_NONE } ; // set for slow motion
cvar_t host_speeds = { " host_speeds " , " 0 " , CVAR_NONE } ; // set for running times
cvar_t host_maxfps = { " host_maxfps " , " 72 " , CVAR_ARCHIVE } ; //johnfitz
cvar_t host_timescale = { " host_timescale " , " 0 " , CVAR_NONE } ; //johnfitz
2017-09-17 02:12:53 +00:00
cvar_t max_edicts = { " max_edicts " , " 15000 " , CVAR_NONE } ; //johnfitz //ericw -- changed from 2048 to 8192, removed CVAR_ARCHIVE
2018-05-01 00:35:14 +00:00
cvar_t cl_nocsqc = { " cl_nocsqc " , " 0 " , CVAR_NONE } ; //spike -- blocks the loading of any csqc modules
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t sys_ticrate = { " sys_ticrate " , " 0.05 " , CVAR_NONE } ; // dedicated server
cvar_t serverprofile = { " serverprofile " , " 0 " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t fraglimit = { " fraglimit " , " 0 " , CVAR_NOTIFY | CVAR_SERVERINFO } ;
cvar_t timelimit = { " timelimit " , " 0 " , CVAR_NOTIFY | CVAR_SERVERINFO } ;
cvar_t teamplay = { " teamplay " , " 0 " , CVAR_NOTIFY | CVAR_SERVERINFO } ;
2020-09-02 08:43:25 +00:00
cvar_t samelevel = { " samelevel " , " 0 " , CVAR_SERVERINFO } ;
2011-12-28 22:01:33 +00:00
cvar_t noexit = { " noexit " , " 0 " , CVAR_NOTIFY | CVAR_SERVERINFO } ;
2020-09-02 08:43:25 +00:00
cvar_t skill = { " skill " , " 1 " , CVAR_SERVERINFO } ; // 0 - 3
cvar_t deathmatch = { " deathmatch " , " 0 " , CVAR_SERVERINFO } ; // 0, 1, or 2
cvar_t coop = { " coop " , " 0 " , CVAR_SERVERINFO } ; // 0 or 1
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t pausable = { " pausable " , " 1 " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t developer = { " developer " , " 0 " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
2020-07-08 14:46:00 +00:00
static cvar_t pr_engine = { " pr_engine " , ENGINE_NAME_AND_VER , CVAR_NONE } ;
2011-12-28 22:01:33 +00:00
cvar_t temp1 = { " temp1 " , " 0 " , CVAR_NONE } ;
2010-02-15 23:26:55 +00:00
2011-12-28 22:01:33 +00:00
cvar_t devstats = { " devstats " , " 0 " , CVAR_NONE } ; //johnfitz -- track developer statistics that vary every frame
2010-02-15 23:26:55 +00:00
2021-08-22 15:55:02 +00:00
cvar_t campaign = { " campaign " , " 0 " , CVAR_NONE } ; // for the 2021 rerelease
2022-02-12 17:37:03 +00:00
cvar_t horde = { " horde " , " 0 " , CVAR_NONE } ; // for the 2021 rerelease
2021-08-22 15:55:02 +00:00
2010-04-22 19:02:29 +00:00
devstats_t dev_stats , dev_peakstats ;
overflowtimes_t dev_overflows ; //this stores the last time overflow messages were displayed, not the last time overflows occured
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = =
Max_Edicts_f - - johnfitz
= = = = = = = = = = = = = = = =
*/
2011-12-24 14:04:01 +00:00
static void Max_Edicts_f ( cvar_t * var )
2010-02-15 23:26:55 +00:00
{
//TODO: clamp it here?
if ( cls . state = = ca_connected | | sv . active )
Con_Printf ( " Changes to max_edicts will not take effect until the next time a map is loaded. \n " ) ;
}
2017-09-12 23:27:26 +00:00
/*
= = = = = = = = = = = = = = = =
Max_Fps_f - - ericw
= = = = = = = = = = = = = = = =
*/
static void Max_Fps_f ( cvar_t * var )
{
2018-05-13 07:00:41 +00:00
if ( var - > value > 72 | | var - > value < = 0 )
{
if ( ! host_netinterval )
Con_Printf ( " Using renderer/network isolation. \n " ) ;
host_netinterval = 1.0 / 72 ;
}
else
{
if ( host_netinterval )
Con_Printf ( " Disabling renderer/network isolation. \n " ) ;
host_netinterval = 0 ;
if ( var - > value > 72 )
Con_Warning ( " host_maxfps above 72 breaks physics. \n " ) ;
}
2017-09-12 23:27:26 +00:00
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = =
Host_EndGame
= = = = = = = = = = = = = = = =
*/
Constified Con_DebugLog, Con_Print, Con_Printf, Con_Warning, Con_DPrintf,
Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, Con_LogCenterPrint,
Con_NotifyBox, PL_ErrorDialog, PR_RunError, Host_EndGame, Host_Error,
SV_ClientPrintf, SV_BroadcastPrintf, Host_ClientCommands, Sys_DebugLog,
Sys_Error, Sys_Printf, BOPS_Error and va. Added noreturn attribute to
Sys_Error, Sys_Quit, BOPS_Error, PR_RunError, Host_EndGame and Host_Error.
Added format printf attribute to Con_DebugLog, Con_Printf, Con_Warning,
Con_DPrintf, Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, PL_ErrorDialog,
PR_RunError, Host_EndGame, Host_Error, SV_ClientPrintf, SV_BroadcastPrintf,
Host_ClientCommands, Sys_DebugLog, Sys_Error, Sys_Printf and va. Adjusted
Host_Status_f and NET_Ban_f for the new attributes. Fixed broken format
strings in Con_Dump_f, Mod_LoadTexinfo, PR_AllocStringSlots and FloorDivMod.
Defined __attribute__ macros in quakedef.h so that we don't break non-gcc
compilers.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@154 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-04-26 16:30:40 +00:00
void Host_EndGame ( const char * message , . . . )
2010-02-15 23:26:55 +00:00
{
va_list argptr ;
char string [ 1024 ] ;
va_start ( argptr , message ) ;
2010-08-31 16:57:12 +00:00
q_vsnprintf ( string , sizeof ( string ) , message , argptr ) ;
2010-02-15 23:26:55 +00:00
va_end ( argptr ) ;
Con_DPrintf ( " Host_EndGame: %s \n " , string ) ;
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( NULL ) ;
2010-02-15 23:26:55 +00:00
if ( sv . active )
Host_ShutdownServer ( false ) ;
if ( cls . state = = ca_dedicated )
Sys_Error ( " Host_EndGame: %s \n " , string ) ; // dedicated servers exit
2022-04-02 08:50:10 +00:00
if ( cls . demonum ! = - 1 & & ! cls . timedemo )
2010-02-15 23:26:55 +00:00
CL_NextDemo ( ) ;
else
CL_Disconnect ( ) ;
longjmp ( host_abortserver , 1 ) ;
}
/*
= = = = = = = = = = = = = = = =
Host_Error
This shuts down both the client and server
= = = = = = = = = = = = = = = =
*/
Constified Con_DebugLog, Con_Print, Con_Printf, Con_Warning, Con_DPrintf,
Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, Con_LogCenterPrint,
Con_NotifyBox, PL_ErrorDialog, PR_RunError, Host_EndGame, Host_Error,
SV_ClientPrintf, SV_BroadcastPrintf, Host_ClientCommands, Sys_DebugLog,
Sys_Error, Sys_Printf, BOPS_Error and va. Added noreturn attribute to
Sys_Error, Sys_Quit, BOPS_Error, PR_RunError, Host_EndGame and Host_Error.
Added format printf attribute to Con_DebugLog, Con_Printf, Con_Warning,
Con_DPrintf, Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, PL_ErrorDialog,
PR_RunError, Host_EndGame, Host_Error, SV_ClientPrintf, SV_BroadcastPrintf,
Host_ClientCommands, Sys_DebugLog, Sys_Error, Sys_Printf and va. Adjusted
Host_Status_f and NET_Ban_f for the new attributes. Fixed broken format
strings in Con_Dump_f, Mod_LoadTexinfo, PR_AllocStringSlots and FloorDivMod.
Defined __attribute__ macros in quakedef.h so that we don't break non-gcc
compilers.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@154 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-04-26 16:30:40 +00:00
void Host_Error ( const char * error , . . . )
2010-02-15 23:26:55 +00:00
{
va_list argptr ;
char string [ 1024 ] ;
static qboolean inerror = false ;
if ( inerror )
Sys_Error ( " Host_Error: recursively entered " ) ;
inerror = true ;
2018-06-28 04:42:28 +00:00
if ( cl . qcvm . progs )
glDisable ( GL_SCISSOR_TEST ) ; //equivelent to drawresetcliparea, to reset any damage if we crashed in csqc.
2020-07-02 19:05:51 +00:00
if ( qcvm = = & cls . menu_qcvm )
MQC_Shutdown ( ) ;
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( NULL ) ;
2010-02-15 23:26:55 +00:00
SCR_EndLoadingPlaque ( ) ; // reenable screen updates
va_start ( argptr , error ) ;
2010-08-31 16:57:12 +00:00
q_vsnprintf ( string , sizeof ( string ) , error , argptr ) ;
2010-02-15 23:26:55 +00:00
va_end ( argptr ) ;
Con_Printf ( " Host_Error: %s \n " , string ) ;
2017-09-17 02:12:53 +00:00
Con_Redirect ( NULL ) ;
2010-02-15 23:26:55 +00:00
if ( sv . active )
Host_ShutdownServer ( false ) ;
if ( cls . state = = ca_dedicated )
Sys_Error ( " Host_Error: %s \n " , string ) ; // dedicated servers exit
CL_Disconnect ( ) ;
cls . demonum = - 1 ;
cl . intermission = 0 ; //johnfitz -- for errors during intermissions (changelevel with no map found, etc.)
inerror = false ;
longjmp ( host_abortserver , 1 ) ;
}
/*
= = = = = = = = = = = = = = = =
Host_FindMaxClients
= = = = = = = = = = = = = = = =
*/
void Host_FindMaxClients ( void )
{
int i ;
svs . maxclients = 1 ;
i = COM_CheckParm ( " -dedicated " ) ;
if ( i )
{
cls . state = ca_dedicated ;
if ( i ! = ( com_argc - 1 ) )
{
svs . maxclients = Q_atoi ( com_argv [ i + 1 ] ) ;
}
else
svs . maxclients = 8 ;
}
else
cls . state = ca_disconnected ;
i = COM_CheckParm ( " -listen " ) ;
if ( i )
{
if ( cls . state = = ca_dedicated )
Sys_Error ( " Only one of -dedicated or -listen can be specified " ) ;
if ( i ! = ( com_argc - 1 ) )
svs . maxclients = Q_atoi ( com_argv [ i + 1 ] ) ;
else
svs . maxclients = 8 ;
}
if ( svs . maxclients < 1 )
svs . maxclients = 8 ;
else if ( svs . maxclients > MAX_SCOREBOARD )
svs . maxclients = MAX_SCOREBOARD ;
svs . maxclientslimit = svs . maxclients ;
if ( svs . maxclientslimit < 4 )
svs . maxclientslimit = 4 ;
host_cmd.c, console.c, gl_draw.c, image.c, gl_model.c, r_sprite.c, cl_parse.c,
gl_warp.c, host.c, gl_mesh.c, gl_sky.c, gl_texmgr.c, cvar.c, sv_main.c, cvar.h,
gl_screen.c, r_brush.c, gl_vidsdl.c, zone.c, cl_main.c, cmd.c, snd_dma.c,
snd_mem.c, common.c, sv_phys.c: Added explicit casts to eliminate -Wc++-compat
warnings.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@170 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-05-31 07:42:36 +00:00
svs . clients = ( struct client_s * ) Hunk_AllocName ( svs . maxclientslimit * sizeof ( client_t ) , " clients " ) ;
2010-02-15 23:26:55 +00:00
if ( svs . maxclients > 1 )
2011-12-29 21:21:11 +00:00
Cvar_SetQuick ( & deathmatch , " 1 " ) ;
2010-02-15 23:26:55 +00:00
else
2011-12-29 21:21:11 +00:00
Cvar_SetQuick ( & deathmatch , " 0 " ) ;
2010-02-15 23:26:55 +00:00
}
2011-06-27 13:20:52 +00:00
void Host_Version_f ( void )
{
Con_Printf ( " Quake Version %1.2f \n " , VERSION ) ;
2017-05-29 04:17:49 +00:00
Con_Printf ( " QuakeSpasm Version " QUAKESPASM_VER_STRING " \n " ) ;
2019-06-18 13:19:16 +00:00
# ifdef QSS_VERSION
2019-09-10 18:02:39 +00:00
Con_Printf ( " QSS Git Description " QS_STRINGIFY ( QSS_VERSION ) " \n " ) ;
2019-06-18 13:19:16 +00:00
# endif
# ifdef QSS_REVISION
2019-09-10 18:02:39 +00:00
Con_Printf ( " QSS Git Revision " QS_STRINGIFY ( QSS_REVISION ) " \n " ) ;
2019-06-18 13:19:16 +00:00
# endif
2020-10-12 01:45:40 +00:00
# ifdef QSS_DATE
Con_Printf ( " QuakeSpasm-Spiked Build " QS_STRINGIFY ( QSS_DATE ) " \n " ) ;
# else
2016-04-29 20:00:50 +00:00
Con_Printf ( " Exe: " __TIME__ " " __DATE__ " \n " ) ;
2020-10-12 01:45:40 +00:00
# endif
2011-06-27 13:20:52 +00:00
}
2011-12-28 22:01:33 +00:00
/* cvar callback functions : */
void Host_Callback_Notify ( cvar_t * var )
{
if ( sv . active )
SV_BroadcastPrintf ( " \" %s \" changed to \" %s \" \n " , var - > name , var - > string ) ;
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = =
Host_InitLocal
= = = = = = = = = = = = = = = = = = = = = =
*/
void Host_InitLocal ( void )
{
2011-06-27 13:20:52 +00:00
Cmd_AddCommand ( " version " , Host_Version_f ) ;
2010-02-15 23:26:55 +00:00
Host_InitCommands ( ) ;
2020-07-08 14:46:00 +00:00
Cvar_RegisterVariable ( & pr_engine ) ;
2011-12-28 22:01:33 +00:00
Cvar_RegisterVariable ( & host_framerate ) ;
Cvar_RegisterVariable ( & host_speeds ) ;
Cvar_RegisterVariable ( & host_maxfps ) ; //johnfitz
2017-09-12 23:27:26 +00:00
Cvar_SetCallback ( & host_maxfps , Max_Fps_f ) ;
2011-12-28 22:01:33 +00:00
Cvar_RegisterVariable ( & host_timescale ) ; //johnfitz
2018-05-01 00:35:14 +00:00
Cvar_RegisterVariable ( & cl_nocsqc ) ; //spike
2011-12-28 22:01:33 +00:00
Cvar_RegisterVariable ( & max_edicts ) ; //johnfitz
Cvar_SetCallback ( & max_edicts , Max_Edicts_f ) ;
Cvar_RegisterVariable ( & devstats ) ; //johnfitz
Cvar_RegisterVariable ( & sys_ticrate ) ;
Cvar_RegisterVariable ( & sys_throttle ) ;
Cvar_RegisterVariable ( & serverprofile ) ;
Cvar_RegisterVariable ( & fraglimit ) ;
Cvar_RegisterVariable ( & timelimit ) ;
Cvar_RegisterVariable ( & teamplay ) ;
Cvar_SetCallback ( & fraglimit , Host_Callback_Notify ) ;
Cvar_SetCallback ( & timelimit , Host_Callback_Notify ) ;
Cvar_SetCallback ( & teamplay , Host_Callback_Notify ) ;
Cvar_RegisterVariable ( & samelevel ) ;
Cvar_RegisterVariable ( & noexit ) ;
Cvar_SetCallback ( & noexit , Host_Callback_Notify ) ;
Cvar_RegisterVariable ( & skill ) ;
Cvar_RegisterVariable ( & developer ) ;
Cvar_RegisterVariable ( & coop ) ;
Cvar_RegisterVariable ( & deathmatch ) ;
2021-08-22 15:55:02 +00:00
Cvar_RegisterVariable ( & campaign ) ;
2022-02-12 17:37:03 +00:00
Cvar_RegisterVariable ( & horde ) ;
2021-08-22 15:55:02 +00:00
2011-12-28 22:01:33 +00:00
Cvar_RegisterVariable ( & pausable ) ;
Cvar_RegisterVariable ( & temp1 ) ;
2010-02-15 23:26:55 +00:00
Host_FindMaxClients ( ) ;
}
/*
= = = = = = = = = = = = = = =
Host_WriteConfiguration
Writes key bindings and archived cvars to config . cfg
= = = = = = = = = = = = = = =
*/
void Host_WriteConfiguration ( void )
{
FILE * f ;
// dedicated servers initialize the host but don't parse and set the
// config.cfg cvars
2018-02-21 07:33:07 +00:00
if ( host_initialized & & ! isDedicated & & ! host_parms - > errstate )
2010-02-15 23:26:55 +00:00
{
f = fopen ( va ( " %s/config.cfg " , com_gamedir ) , " w " ) ;
if ( ! f )
{
Con_Printf ( " Couldn't write config.cfg. \n " ) ;
return ;
}
2018-02-21 16:25:04 +00:00
//VID_SyncCvars (); //johnfitz -- write actual current mode to config file, in case cvars were messed with
2010-02-15 23:26:55 +00:00
Key_WriteBindings ( f ) ;
Cvar_WriteVariables ( f ) ;
//johnfitz -- extra commands to preserve state
fprintf ( f , " vid_restart \n " ) ;
if ( in_mlook . state & 1 ) fprintf ( f , " +mlook \n " ) ;
//johnfitz
fclose ( f ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
SV_ClientPrintf
Sends text across to be displayed
FIXME : make this just a stuffed echo ?
= = = = = = = = = = = = = = = = =
*/
Constified Con_DebugLog, Con_Print, Con_Printf, Con_Warning, Con_DPrintf,
Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, Con_LogCenterPrint,
Con_NotifyBox, PL_ErrorDialog, PR_RunError, Host_EndGame, Host_Error,
SV_ClientPrintf, SV_BroadcastPrintf, Host_ClientCommands, Sys_DebugLog,
Sys_Error, Sys_Printf, BOPS_Error and va. Added noreturn attribute to
Sys_Error, Sys_Quit, BOPS_Error, PR_RunError, Host_EndGame and Host_Error.
Added format printf attribute to Con_DebugLog, Con_Printf, Con_Warning,
Con_DPrintf, Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, PL_ErrorDialog,
PR_RunError, Host_EndGame, Host_Error, SV_ClientPrintf, SV_BroadcastPrintf,
Host_ClientCommands, Sys_DebugLog, Sys_Error, Sys_Printf and va. Adjusted
Host_Status_f and NET_Ban_f for the new attributes. Fixed broken format
strings in Con_Dump_f, Mod_LoadTexinfo, PR_AllocStringSlots and FloorDivMod.
Defined __attribute__ macros in quakedef.h so that we don't break non-gcc
compilers.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@154 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-04-26 16:30:40 +00:00
void SV_ClientPrintf ( const char * fmt , . . . )
2010-02-15 23:26:55 +00:00
{
va_list argptr ;
char string [ 1024 ] ;
va_start ( argptr , fmt ) ;
2010-08-31 16:57:12 +00:00
q_vsnprintf ( string , sizeof ( string ) , fmt , argptr ) ;
2010-02-15 23:26:55 +00:00
va_end ( argptr ) ;
MSG_WriteByte ( & host_client - > message , svc_print ) ;
MSG_WriteString ( & host_client - > message , string ) ;
}
/*
= = = = = = = = = = = = = = = = =
SV_BroadcastPrintf
Sends text to all active clients
= = = = = = = = = = = = = = = = =
*/
Constified Con_DebugLog, Con_Print, Con_Printf, Con_Warning, Con_DPrintf,
Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, Con_LogCenterPrint,
Con_NotifyBox, PL_ErrorDialog, PR_RunError, Host_EndGame, Host_Error,
SV_ClientPrintf, SV_BroadcastPrintf, Host_ClientCommands, Sys_DebugLog,
Sys_Error, Sys_Printf, BOPS_Error and va. Added noreturn attribute to
Sys_Error, Sys_Quit, BOPS_Error, PR_RunError, Host_EndGame and Host_Error.
Added format printf attribute to Con_DebugLog, Con_Printf, Con_Warning,
Con_DPrintf, Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, PL_ErrorDialog,
PR_RunError, Host_EndGame, Host_Error, SV_ClientPrintf, SV_BroadcastPrintf,
Host_ClientCommands, Sys_DebugLog, Sys_Error, Sys_Printf and va. Adjusted
Host_Status_f and NET_Ban_f for the new attributes. Fixed broken format
strings in Con_Dump_f, Mod_LoadTexinfo, PR_AllocStringSlots and FloorDivMod.
Defined __attribute__ macros in quakedef.h so that we don't break non-gcc
compilers.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@154 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-04-26 16:30:40 +00:00
void SV_BroadcastPrintf ( const char * fmt , . . . )
2010-02-15 23:26:55 +00:00
{
va_list argptr ;
char string [ 1024 ] ;
int i ;
va_start ( argptr , fmt ) ;
2010-08-31 16:57:12 +00:00
q_vsnprintf ( string , sizeof ( string ) , fmt , argptr ) ;
2010-02-15 23:26:55 +00:00
va_end ( argptr ) ;
2012-11-06 08:56:09 +00:00
for ( i = 0 ; i < svs . maxclients ; i + + )
{
2010-02-15 23:26:55 +00:00
if ( svs . clients [ i ] . active & & svs . clients [ i ] . spawned )
{
MSG_WriteByte ( & svs . clients [ i ] . message , svc_print ) ;
MSG_WriteString ( & svs . clients [ i ] . message , string ) ;
}
2012-11-06 08:56:09 +00:00
}
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = =
Host_ClientCommands
Send text over to the client to be executed
= = = = = = = = = = = = = = = = =
*/
Constified Con_DebugLog, Con_Print, Con_Printf, Con_Warning, Con_DPrintf,
Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, Con_LogCenterPrint,
Con_NotifyBox, PL_ErrorDialog, PR_RunError, Host_EndGame, Host_Error,
SV_ClientPrintf, SV_BroadcastPrintf, Host_ClientCommands, Sys_DebugLog,
Sys_Error, Sys_Printf, BOPS_Error and va. Added noreturn attribute to
Sys_Error, Sys_Quit, BOPS_Error, PR_RunError, Host_EndGame and Host_Error.
Added format printf attribute to Con_DebugLog, Con_Printf, Con_Warning,
Con_DPrintf, Con_DPrintf2, Con_SafePrintf, Con_CenterPrintf, PL_ErrorDialog,
PR_RunError, Host_EndGame, Host_Error, SV_ClientPrintf, SV_BroadcastPrintf,
Host_ClientCommands, Sys_DebugLog, Sys_Error, Sys_Printf and va. Adjusted
Host_Status_f and NET_Ban_f for the new attributes. Fixed broken format
strings in Con_Dump_f, Mod_LoadTexinfo, PR_AllocStringSlots and FloorDivMod.
Defined __attribute__ macros in quakedef.h so that we don't break non-gcc
compilers.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@154 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-04-26 16:30:40 +00:00
void Host_ClientCommands ( const char * fmt , . . . )
2010-02-15 23:26:55 +00:00
{
va_list argptr ;
char string [ 1024 ] ;
va_start ( argptr , fmt ) ;
2010-08-31 16:57:12 +00:00
q_vsnprintf ( string , sizeof ( string ) , fmt , argptr ) ;
2010-02-15 23:26:55 +00:00
va_end ( argptr ) ;
MSG_WriteByte ( & host_client - > message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > message , string ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
SV_DropClient
Called when the player is getting totally kicked off the host
if ( crash = true ) , don ' t bother sending signofs
= = = = = = = = = = = = = = = = = = = = =
*/
void SV_DropClient ( qboolean crash )
{
int saveSelf ;
int i ;
client_t * client ;
if ( ! crash )
{
// send any final messages (don't check for errors)
if ( NET_CanSendMessage ( host_client - > netconnection ) )
{
MSG_WriteByte ( & host_client - > message , svc_disconnect ) ;
NET_SendMessage ( host_client - > netconnection , & host_client - > message ) ;
}
if ( host_client - > edict & & host_client - > spawned )
{
// call the prog function for removing a client
// this will set the body to a dead frame, among other things
2020-04-06 22:24:22 +00:00
qcvm_t * oldvm = qcvm ;
PR_SwitchQCVM ( NULL ) ;
PR_SwitchQCVM ( & sv . qcvm ) ;
2010-02-15 23:26:55 +00:00
saveSelf = pr_global_struct - > self ;
pr_global_struct - > self = EDICT_TO_PROG ( host_client - > edict ) ;
PR_ExecuteProgram ( pr_global_struct - > ClientDisconnect ) ;
pr_global_struct - > self = saveSelf ;
2020-04-06 22:24:22 +00:00
PR_SwitchQCVM ( NULL ) ;
PR_SwitchQCVM ( oldvm ) ;
2010-02-15 23:26:55 +00:00
}
Sys_Printf ( " Client %s removed \n " , host_client - > name ) ;
}
// break the net connection
NET_Close ( host_client - > netconnection ) ;
host_client - > netconnection = NULL ;
2017-09-17 02:12:53 +00:00
SVFTE_DestroyFrames ( host_client ) ; //release any delta state
2010-02-15 23:26:55 +00:00
// free the client (the body stays around)
host_client - > active = false ;
host_client - > name [ 0 ] = 0 ;
host_client - > old_frags = - 999999 ;
net_activeconnections - - ;
2017-09-17 02:12:53 +00:00
if ( host_client - > download . file )
fclose ( host_client - > download . file ) ;
memset ( & host_client - > download , 0 , sizeof ( host_client - > download ) ) ;
2010-02-15 23:26:55 +00:00
// send notification to all clients
2012-11-06 08:56:09 +00:00
for ( i = 0 , client = svs . clients ; i < svs . maxclients ; i + + , client + + )
2010-02-15 23:26:55 +00:00
{
2017-09-17 02:12:53 +00:00
if ( ! client - > knowntoqc )
2010-02-15 23:26:55 +00:00
continue ;
2020-09-03 10:39:38 +00:00
if ( ( host_client - > protocol_pext1 & PEXT1_CSQC ) | | ( host_client - > protocol_pext2 & PEXT2_REPLACEMENTDELTAS ) )
2020-09-02 08:43:25 +00:00
{
MSG_WriteByte ( & client - > message , svc_stufftext ) ;
MSG_WriteString ( & client - > message , va ( " //fui %u \" \" \n " , ( unsigned ) ( host_client - svs . clients ) ) ) ;
}
else
{
MSG_WriteByte ( & client - > message , svc_updatename ) ;
MSG_WriteByte ( & client - > message , host_client - svs . clients ) ;
MSG_WriteString ( & client - > message , " " ) ;
MSG_WriteByte ( & client - > message , svc_updatecolors ) ;
MSG_WriteByte ( & client - > message , host_client - svs . clients ) ;
MSG_WriteByte ( & client - > message , 0 ) ;
}
2010-02-15 23:26:55 +00:00
MSG_WriteByte ( & client - > message , svc_updatefrags ) ;
MSG_WriteByte ( & client - > message , host_client - svs . clients ) ;
MSG_WriteShort ( & client - > message , 0 ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
Host_ShutdownServer
This only happens at the end of a game , not between levels
= = = = = = = = = = = = = = = = = =
*/
void Host_ShutdownServer ( qboolean crash )
{
int i ;
int count ;
sizebuf_t buf ;
chase.c, cl_input.c, cl_parse.c, client.h, common.c, common.h, console.h,
cvar.h, draw.h, gl_draw.c, gl_fog.c, gl_mesh.c, gl_model.c, gl_model.h,
gl_rmain.c, gl_rmisc.c, gl_screen.c, gl_sky.c, gl_texmgr.c, glquake.h,
host.c, keys.c, keys.h, main.c, menu.c, menu.h, pr_cmds.c, quakedef.h,
r_alias.c, r_brush.c, r_part.c, r_sprite.c, r_world.c, sbar.c, sbar.h,
screen.h, snd_dma.c, snd_mem.c, snd_mix.c, sv_main.c, sys_sdl.c, vid.h,
view.h, world.c, world.h: Loads of warning fixes about missing function
prototypes, missing parens around &, missing braces leading to ambiguous
else statements and unused and uninitialized variables. There are still a
couple of unitialised variables here and there, but not much. The warnings
about strict aliasing violations need taking care of.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@21 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-02-16 12:01:07 +00:00
byte message [ 4 ] ;
2010-02-15 23:26:55 +00:00
double start ;
if ( ! sv . active )
return ;
sv . active = false ;
// stop all client sounds immediately
if ( cls . state = = ca_connected )
CL_Disconnect ( ) ;
// flush any pending messages - like the score!!!
2011-12-12 16:01:01 +00:00
start = Sys_DoubleTime ( ) ;
2010-02-15 23:26:55 +00:00
do
{
count = 0 ;
2022-04-25 22:33:06 +00:00
NET_GetServerMessage ( ) ; //read packets to make sure we're receiving their acks. we're going to drop them all so we don't actually care to read the data, just the acks so we can flush our outgoing properly.
2010-02-15 23:26:55 +00:00
for ( i = 0 , host_client = svs . clients ; i < svs . maxclients ; i + + , host_client + + )
{
2017-09-17 02:12:53 +00:00
if ( host_client - > active & & host_client - > message . cursize & & host_client - > netconnection )
2010-02-15 23:26:55 +00:00
{
2022-04-25 22:33:06 +00:00
if ( NET_CanSendMessage ( host_client - > netconnection ) ) //also sends pending data too.
2010-02-15 23:26:55 +00:00
{
NET_SendMessage ( host_client - > netconnection , & host_client - > message ) ;
SZ_Clear ( & host_client - > message ) ;
}
else
count + + ;
}
}
2011-12-12 16:01:01 +00:00
if ( ( Sys_DoubleTime ( ) - start ) > 3.0 )
2010-02-15 23:26:55 +00:00
break ;
}
while ( count ) ;
// make sure all the clients know we're disconnecting
buf . data = message ;
buf . maxsize = 4 ;
buf . cursize = 0 ;
MSG_WriteByte ( & buf , svc_disconnect ) ;
2010-06-20 15:00:57 +00:00
count = NET_SendToAll ( & buf , 5.0 ) ;
2010-02-15 23:26:55 +00:00
if ( count )
Con_Printf ( " Host_ShutdownServer: NET_SendToAll failed for %u clients \n " , count ) ;
2018-05-01 00:35:14 +00:00
PR_SwitchQCVM ( & sv . qcvm ) ;
2012-11-06 08:56:09 +00:00
for ( i = 0 , host_client = svs . clients ; i < svs . maxclients ; i + + , host_client + + )
2010-02-15 23:26:55 +00:00
if ( host_client - > active )
SV_DropClient ( crash ) ;
2018-05-01 00:35:14 +00:00
qcvm - > worldmodel = NULL ;
PR_SwitchQCVM ( NULL ) ;
2017-09-17 02:12:53 +00:00
2010-02-15 23:26:55 +00:00
//
// clear structures
//
2012-11-06 08:56:09 +00:00
// memset (&sv, 0, sizeof(sv)); // ServerSpawn already do this by Host_ClearMemory
2010-02-15 23:26:55 +00:00
memset ( svs . clients , 0 , svs . maxclientslimit * sizeof ( client_t ) ) ;
}
/*
= = = = = = = = = = = = = = = =
Host_ClearMemory
This clears all the memory used by both the client and server , but does
not reinitialize anything .
= = = = = = = = = = = = = = = =
*/
void Host_ClearMemory ( void )
{
2020-09-03 10:39:38 +00:00
if ( cl . qcvm . extfuncs . CSQC_Shutdown )
{
PR_SwitchQCVM ( & cl . qcvm ) ;
PR_ExecuteProgram ( qcvm - > extfuncs . CSQC_Shutdown ) ;
qcvm - > extfuncs . CSQC_Shutdown = 0 ;
PR_SwitchQCVM ( NULL ) ;
}
2010-02-15 23:26:55 +00:00
Con_DPrintf ( " Clearing memory \n " ) ;
D_FlushCaches ( ) ;
Mod_ClearAll ( ) ;
2021-08-09 22:00:02 +00:00
Sky_ClearAll ( ) ;
2011-07-05 06:50:23 +00:00
/* host_hunklevel MUST be set at this point */
Hunk_FreeToLowMark ( host_hunklevel ) ;
2010-02-15 23:26:55 +00:00
cls . signon = 0 ;
2018-05-01 00:35:14 +00:00
PR_ClearProgs ( & sv . qcvm ) ;
2017-09-17 02:12:53 +00:00
free ( sv . static_entities ) ; //spike -- this is dynamic too, now
free ( sv . ambientsounds ) ;
2010-02-15 23:26:55 +00:00
memset ( & sv , 0 , sizeof ( sv ) ) ;
2020-06-19 22:19:07 +00:00
CL_FreeState ( ) ;
2010-02-15 23:26:55 +00:00
}
//==============================================================================
//
// Host Frame
//
//==============================================================================
/*
= = = = = = = = = = = = = = = = = = =
Host_FilterTime
Returns false if the time is too short to run a frame
= = = = = = = = = = = = = = = = = = =
*/
qboolean Host_FilterTime ( float time )
{
float maxfps ; //johnfitz
realtime + = time ;
//johnfitz -- max fps cvar
2022-07-15 13:11:03 +00:00
maxfps = CLAMP ( 10.f , host_maxfps . value , 1000.0 ) ;
2017-09-17 02:12:53 +00:00
if ( host_maxfps . value & & ! cls . timedemo & & realtime - oldrealtime < 1.0 / maxfps )
2010-02-15 23:26:55 +00:00
return false ; // framerate is too high
//johnfitz
host_frametime = realtime - oldrealtime ;
oldrealtime = realtime ;
//johnfitz -- host_timescale is more intuitive than host_framerate
if ( host_timescale . value > 0 )
host_frametime * = host_timescale . value ;
//johnfitz
else if ( host_framerate . value > 0 )
host_frametime = host_framerate . value ;
2017-09-17 02:12:53 +00:00
else if ( host_maxfps . value ) // don't allow really long or short frames
2018-05-13 07:00:41 +00:00
host_frametime = CLAMP ( 0.0001 , host_frametime , 0.1 ) ; //johnfitz -- use CLAMP
2010-02-15 23:26:55 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = = = = =
Host_GetConsoleCommands
Add them exactly as if they had been typed at the console
= = = = = = = = = = = = = = = = = = =
*/
void Host_GetConsoleCommands ( void )
{
2011-12-12 12:02:37 +00:00
const char * cmd ;
2010-02-15 23:26:55 +00:00
2011-12-15 15:51:28 +00:00
if ( ! isDedicated )
return ; // no stdin necessary in graphical mode
2010-02-15 23:26:55 +00:00
while ( 1 )
{
cmd = Sys_ConsoleInput ( ) ;
if ( ! cmd )
break ;
Cbuf_AddText ( cmd ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
Host_ServerFrame
= = = = = = = = = = = = = = = = = =
*/
void Host_ServerFrame ( void )
{
int i , active ; //johnfitz
edict_t * ent ; //johnfitz
// run the world state
pr_global_struct - > frametime = host_frametime ;
// set the time and clear the general datagram
SV_ClearDatagram ( ) ;
// check for new clients
SV_CheckForNewClients ( ) ;
// read client messages
SV_RunClients ( ) ;
// move things around and think
// always pause in single player if in console or menus
if ( ! sv . paused & & ( svs . maxclients > 1 | | key_dest = = key_game ) )
2022-07-19 21:36:57 +00:00
SV_Physics ( host_frametime ) ;
2010-02-15 23:26:55 +00:00
//johnfitz -- devstats
if ( cls . signon = = SIGNONS )
{
2018-05-01 00:35:14 +00:00
for ( i = 0 , active = 0 ; i < qcvm - > num_edicts ; i + + )
2010-02-15 23:26:55 +00:00
{
ent = EDICT_NUM ( i ) ;
if ( ! ent - > free )
active + + ;
}
if ( active > 600 & & dev_peakstats . edicts < = 600 )
2018-05-01 00:35:14 +00:00
Con_DWarning ( " %i edicts exceeds standard limit of 600 (max = %d). \n " , active , qcvm - > max_edicts ) ;
2010-02-15 23:26:55 +00:00
dev_stats . edicts = active ;
2011-01-10 10:35:40 +00:00
dev_peakstats . edicts = q_max ( active , dev_peakstats . edicts ) ;
2010-02-15 23:26:55 +00:00
}
//johnfitz
// send all messages to the clients
SV_SendClientMessages ( ) ;
}
2018-05-07 18:32:50 +00:00
//used for cl.qcvm.GetModel (so ssqc+csqc can share builtins)
qmodel_t * CL_ModelForIndex ( int index )
{
if ( index < 0 | | index > = MAX_MODELS )
return NULL ;
return cl . model_precache [ index ] ;
}
2020-09-03 10:39:38 +00:00
static void CL_LoadCSProgs ( void )
{
qboolean fullcsqc = false ;
PR_ClearProgs ( & cl . qcvm ) ;
if ( pr_checkextension . value & & ! cl_nocsqc . value )
{ //only try to use csqc if qc extensions are enabled.
char versionedname [ MAX_QPATH ] ;
unsigned int csqchash ;
size_t csqcsize ;
2021-09-08 00:48:18 +00:00
const char * val ;
2020-09-03 10:39:38 +00:00
PR_SwitchQCVM ( & cl . qcvm ) ;
2021-09-08 00:48:18 +00:00
val = Info_GetKey ( cl . serverinfo , " *csprogs " , versionedname , sizeof ( versionedname ) ) ;
csqchash = ( unsigned int ) strtoul ( val , NULL , 0 ) ;
if ( * val )
snprintf ( versionedname , MAX_QPATH , " csprogsvers/%x.dat " , csqchash ) ;
else
* versionedname = 0 ;
2020-09-03 10:39:38 +00:00
csqcsize = strtoul ( Info_GetKey ( cl . serverinfo , " *csprogssize " , versionedname , sizeof ( versionedname ) ) , NULL , 0 ) ;
//try csprogs.dat first, then fall back on progs.dat in case someone tried merging the two.
//we only care about it if it actually contains a CSQC_DrawHud, otherwise its either just a (misnamed) ssqc progs or a full csqc progs that would just crash us on 3d stuff.
2021-09-08 00:48:18 +00:00
if ( ( * versionedname & & PR_LoadProgs ( versionedname , false , PROGHEADER_CRC , pr_csqcbuiltins , pr_csqcnumbuiltins ) & & ( qcvm - > extfuncs . CSQC_DrawHud | | cl . qcvm . extfuncs . CSQC_UpdateView ) ) | |
2021-08-31 02:36:55 +00:00
( PR_LoadProgs ( " csprogs.dat " , false , PROGHEADER_CRC , pr_csqcbuiltins , pr_csqcnumbuiltins ) & & ( qcvm - > extfuncs . CSQC_DrawHud | | qcvm - > extfuncs . CSQC_DrawScores | | cl . qcvm . extfuncs . CSQC_UpdateView ) ) | |
2020-09-03 10:39:38 +00:00
( PR_LoadProgs ( " progs.dat " , false , PROGHEADER_CRC , pr_csqcbuiltins , pr_csqcnumbuiltins ) & & ( qcvm - > extfuncs . CSQC_DrawHud | | cl . qcvm . extfuncs . CSQC_UpdateView ) ) )
{
qcvm - > max_edicts = CLAMP ( MIN_EDICTS , ( int ) max_edicts . value , MAX_EDICTS ) ;
qcvm - > edicts = ( edict_t * ) malloc ( qcvm - > max_edicts * qcvm - > edict_size ) ;
qcvm - > num_edicts = qcvm - > reserved_edicts = 1 ;
memset ( qcvm - > edicts , 0 , qcvm - > num_edicts * qcvm - > edict_size ) ;
//in terms of exploit protection this is kinda pointless as someone can just strip out this check and compile themselves. oh well.
2021-09-08 00:48:18 +00:00
if ( ( * versionedname & & qcvm - > progshash = = csqchash & & qcvm - > progssize = = csqcsize ) | | cls . demoplayback )
2020-09-03 10:39:38 +00:00
fullcsqc = true ;
else
{ //okay, it doesn't match. full csqc is disallowed to prevent cheats, but we still allow simplecsqc...
if ( ! qcvm - > extfuncs . CSQC_DrawHud )
{ //no simplecsqc entry points... abort entirely!
PR_ClearProgs ( qcvm ) ;
PR_SwitchQCVM ( NULL ) ;
return ;
}
fullcsqc = false ;
qcvm - > nogameaccess = true ;
qcvm - > extfuncs . CSQC_Input_Frame = 0 ; //prevent reading/writing input frames (no wallhacks please).
qcvm - > extfuncs . CSQC_UpdateView = 0 ; //will probably bug out. block it.
qcvm - > extfuncs . CSQC_Ent_Update = 0 ; //don't let the qc know where ents are... the server should prevent this, but make sure the user didn't cheese a 'cmd enablecsqc'
qcvm - > extfuncs . CSQC_Ent_Remove = 0 ;
qcvm - > extfuncs . CSQC_Parse_StuffCmd = 0 ; //don't allow blocking stuffcmds... though we can't prevent cvar queries+sets, so this is probably futile...
qcvm - > extglobals . clientcommandframe = NULL ; //input frames are blocked, so don't bother to connect these either.
qcvm - > extglobals . servercommandframe = NULL ;
}
qcvm - > GetModel = PR_CSQC_GetModel ;
//set a few globals, if they exist
if ( qcvm - > extglobals . maxclients )
* qcvm - > extglobals . maxclients = cl . maxclients ;
2022-07-19 21:36:57 +00:00
pr_global_struct - > time = qcvm - > time = cl . time ;
2020-09-03 10:39:38 +00:00
pr_global_struct - > mapname = PR_SetEngineString ( cl . mapname ) ;
pr_global_struct - > total_monsters = cl . statsf [ STAT_TOTALMONSTERS ] ;
pr_global_struct - > total_secrets = cl . statsf [ STAT_TOTALSECRETS ] ;
pr_global_struct - > deathmatch = cl . gametype ;
pr_global_struct - > coop = ( cl . gametype = = GAME_COOP ) & & cl . maxclients ! = 1 ;
if ( qcvm - > extglobals . player_localnum )
* qcvm - > extglobals . player_localnum = cl . viewentity - 1 ; //this is a guess, but is important for scoreboards.
//set a few worldspawn fields too
qcvm - > edicts - > v . solid = SOLID_BSP ;
qcvm - > edicts - > v . modelindex = 1 ;
qcvm - > edicts - > v . model = PR_SetEngineString ( cl . worldmodel - > name ) ;
VectorCopy ( cl . worldmodel - > mins , qcvm - > edicts - > v . mins ) ;
VectorCopy ( cl . worldmodel - > maxs , qcvm - > edicts - > v . maxs ) ;
qcvm - > edicts - > v . message = PR_SetEngineString ( cl . levelname ) ;
//and call the init function... if it exists.
qcvm - > worldmodel = cl . worldmodel ;
SV_ClearWorld ( ) ;
if ( qcvm - > extfuncs . CSQC_Init )
{
int maj = ( int ) QUAKESPASM_VERSION ;
int min = ( QUAKESPASM_VERSION - maj ) * 100 ;
G_FLOAT ( OFS_PARM0 ) = fullcsqc ;
G_INT ( OFS_PARM1 ) = PR_SetEngineString ( " QuakeSpasm-Spiked " ) ;
G_FLOAT ( OFS_PARM2 ) = 10000 * maj + 100 * ( min ) + QUAKESPASM_VER_PATCH ;
PR_ExecuteProgram ( qcvm - > extfuncs . CSQC_Init ) ;
}
if ( fullcsqc )
{
//let the server know.
MSG_WriteByte ( & cls . message , clc_stringcmd ) ;
MSG_WriteString ( & cls . message , " enablecsqc " ) ;
}
}
else
PR_ClearProgs ( qcvm ) ;
PR_SwitchQCVM ( NULL ) ;
}
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = =
Host_Frame
Runs all active servers
= = = = = = = = = = = = = = = = = =
*/
2018-05-13 07:00:41 +00:00
void _Host_Frame ( double time )
2010-02-15 23:26:55 +00:00
{
2018-05-13 07:00:41 +00:00
static double accumtime = 0 ;
2010-02-15 23:26:55 +00:00
static double time1 = 0 ;
static double time2 = 0 ;
static double time3 = 0 ;
int pass1 , pass2 , pass3 ;
if ( setjmp ( host_abortserver ) )
return ; // something bad happened, or the server disconnected
// keep the random time dependent
rand ( ) ;
// decide the simulation time
2018-05-13 07:00:41 +00:00
accumtime + = host_netinterval ? CLAMP ( 0 , time , 0.2 ) : 0 ; //for renderer/server isolation
2010-02-15 23:26:55 +00:00
if ( ! Host_FilterTime ( time ) )
return ; // don't run too fast, or packets will flood out
// get new key events
2012-10-23 08:44:20 +00:00
Key_UpdateForDest ( ) ;
2014-09-23 19:10:02 +00:00
IN_UpdateInputMode ( ) ;
2011-12-16 14:11:37 +00:00
Sys_SendKeyEvents ( ) ;
2010-02-15 23:26:55 +00:00
// allow mice or other external controllers to add commands
IN_Commands ( ) ;
2018-05-13 07:00:41 +00:00
//check the stdin for commands (dedicated servers)
Host_GetConsoleCommands ( ) ;
2010-02-15 23:26:55 +00:00
// process console commands
Cbuf_Execute ( ) ;
NET_Poll ( ) ;
2017-09-17 02:12:53 +00:00
if ( cl . sendprespawn )
{
if ( CL_CheckDownloads ( ) )
{
2020-09-03 10:39:38 +00:00
CL_LoadCSProgs ( ) ;
2018-05-01 00:35:14 +00:00
2017-09-17 02:12:53 +00:00
cl . sendprespawn = false ;
MSG_WriteByte ( & cls . message , clc_stringcmd ) ;
MSG_WriteString ( & cls . message , " prespawn " ) ;
2019-02-06 00:06:40 +00:00
vid . recalc_refdef = true ;
2017-09-17 02:12:53 +00:00
}
else if ( ! cls . message . cursize )
MSG_WriteByte ( & cls . message , clc_nop ) ;
}
2018-05-13 07:00:41 +00:00
CL_AccumulateCmd ( ) ;
2010-02-15 23:26:55 +00:00
2020-06-19 22:19:07 +00:00
//Run the server+networking (client->server->client), at a different rate from everything else
2018-05-13 07:00:41 +00:00
if ( accumtime > = host_netinterval )
2018-05-01 00:35:14 +00:00
{
2018-05-13 07:00:41 +00:00
float realframetime = host_frametime ;
if ( host_netinterval )
{
2018-07-19 21:03:42 +00:00
host_frametime = q_max ( accumtime , host_netinterval ) ;
accumtime - = host_frametime ;
2018-05-13 07:00:41 +00:00
if ( host_timescale . value > 0 )
host_frametime * = host_timescale . value ;
else if ( host_framerate . value )
host_frametime = host_framerate . value ;
}
2018-07-19 21:03:42 +00:00
else
accumtime - = host_netinterval ;
2010-02-15 23:26:55 +00:00
CL_SendCmd ( ) ;
2018-05-13 07:00:41 +00:00
if ( sv . active )
{
PR_SwitchQCVM ( & sv . qcvm ) ;
Host_ServerFrame ( ) ;
PR_SwitchQCVM ( NULL ) ;
}
host_frametime = realframetime ;
Cbuf_Waited ( ) ;
}
2010-02-15 23:26:55 +00:00
2020-09-04 11:22:26 +00:00
if ( cl . qcvm . progs )
{
PR_SwitchQCVM ( & cl . qcvm ) ;
2022-07-19 21:36:57 +00:00
SV_Physics ( cl . time - qcvm - > time ) ;
pr_global_struct - > time = cl . time ;
2020-09-04 11:22:26 +00:00
PR_SwitchQCVM ( NULL ) ;
}
2010-02-15 23:26:55 +00:00
// fetch results from server
if ( cls . state = = ca_connected )
CL_ReadFromServer ( ) ;
// update video
if ( host_speeds . value )
2011-12-12 16:01:01 +00:00
time1 = Sys_DoubleTime ( ) ;
2010-02-15 23:26:55 +00:00
SCR_UpdateScreen ( ) ;
CL_RunParticles ( ) ; //johnfitz -- seperated from rendering
if ( host_speeds . value )
2011-12-12 16:01:01 +00:00
time2 = Sys_DoubleTime ( ) ;
2010-02-15 23:26:55 +00:00
// update audio
Backported external music files support using decoder libraries and the
new raw samples interface from Hammer of Thyrion (uhexen2) :
- bgmusic.c, bgmusic.h: New BGM interface for background music handling.
Handles streaming music as raw sound samples.
- bgmnull.c: BGM source for cases where the engine is configured for no
sound.
- cl_main.c: Include bgmusic.h. Call BGM_Stop() and CDAudio_Stop() in
CL_Disconnect().
- cd_sdl.c: Moved bgmvolume boundary checking to bgmusic.c upon value
changes.
- gl_vidnt.c, gl_vidsdl.c, cl_parse.c: Include bgmusic.h. Add BGM_Pause()
and BGM_Resume() calls along with CDAudio_ counterparts.
- cl_parse.c: Replace CDAudio_Play() call by the new BGM_PlayCDtrack()
which first tries CDAudio_Play() and then streaming music if it fails.
- host.c: Include bgmusic.h. Call BGM_Update() just before S_Update()
in Host_Frame(). In Host_Init(), call BGM_Init() after other audio init
calls. In Host_Shutdown(), call BGM_Shutdown() before all other audio
shutdown calls.
- snd_dma.c: Include snd_codec.h and bgmusic.h. Call S_CodecInit() from
S_Init(). Call S_CodecShutdown() from S_Shutdown().
- snd_codec.c, snd_codec.h: New public codec interface for streaming
music as raw samples. Adapted from quake2 and ioquake3 with changes.
Individual codecs are responsible for handling any necessary byte swap
operations.
- snd_codeci.h: New header for snd_codec internals.
- snd_wave.c, snd_wave.h: Codec for WAV format streaming music. Adapted
from ioquake3 with changes.
- snd_vorbis.c, snd_vorbis.h: Codec for Ogg/Vorbis format streaming music.
- snd_mp3.c, snd_mp3.h: Codec for MP3 format streaming music using libmad.
Adapted from the SoX project with changes.
- Makefile: Adjusted for the new sources. Added switches USE_CODEC_WAVE,
USE_CODEC_MP3, USE_CODEC_VORBIS for enabling and disabling individual
codecs.
- Windows makefiles and project files as well as other CodeBlocks project
files will be updated shortly.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@374 af15c1b1-3010-417e-b628-4374ebc0bcbd
2011-01-05 19:50:43 +00:00
BGM_Update ( ) ; // adds music raw samples and/or advances midi driver
2020-09-04 11:07:05 +00:00
if ( cl . listener_defined )
2010-02-15 23:26:55 +00:00
{
2020-09-04 11:07:05 +00:00
cl . listener_defined = false ;
S_Update ( cl . listener_origin , cl . listener_axis [ 0 ] , cl . listener_axis [ 1 ] , cl . listener_axis [ 2 ] ) ;
2010-02-15 23:26:55 +00:00
}
2020-09-04 11:07:05 +00:00
else if ( cls . signon = = SIGNONS )
S_Update ( r_origin , vpn , vright , vup ) ;
2010-02-15 23:26:55 +00:00
else
S_Update ( vec3_origin , vec3_origin , vec3_origin , vec3_origin ) ;
2020-09-04 11:01:03 +00:00
CL_DecayLights ( ) ;
2010-02-15 23:26:55 +00:00
CDAudio_Update ( ) ;
if ( host_speeds . value )
{
pass1 = ( time1 - time3 ) * 1000 ;
2011-12-12 16:01:01 +00:00
time3 = Sys_DoubleTime ( ) ;
2010-02-15 23:26:55 +00:00
pass2 = ( time2 - time1 ) * 1000 ;
pass3 = ( time3 - time2 ) * 1000 ;
Con_Printf ( " %3i tot %3i server %3i gfx %3i snd \n " ,
pass1 + pass2 + pass3 , pass1 , pass2 , pass3 ) ;
}
host_framecount + + ;
}
2018-05-13 07:00:41 +00:00
void Host_Frame ( double time )
2010-02-15 23:26:55 +00:00
{
double time1 , time2 ;
static double timetotal ;
static int timecount ;
int i , c , m ;
if ( ! serverprofile . value )
{
_Host_Frame ( time ) ;
return ;
}
2011-12-12 16:01:01 +00:00
time1 = Sys_DoubleTime ( ) ;
2010-02-15 23:26:55 +00:00
_Host_Frame ( time ) ;
2011-12-12 16:01:01 +00:00
time2 = Sys_DoubleTime ( ) ;
2010-02-15 23:26:55 +00:00
timetotal + = time2 - time1 ;
timecount + + ;
if ( timecount < 1000 )
return ;
m = timetotal * 1000 / timecount ;
timecount = 0 ;
timetotal = 0 ;
c = 0 ;
2012-11-06 08:56:09 +00:00
for ( i = 0 ; i < svs . maxclients ; i + + )
2010-02-15 23:26:55 +00:00
{
if ( svs . clients [ i ] . active )
c + + ;
}
Con_Printf ( " serverprofile: %2i clients %2i msec \n " , c , m ) ;
}
/*
= = = = = = = = = = = = = = = = = = = =
Host_Init
= = = = = = = = = = = = = = = = = = = =
*/
2011-04-19 16:41:45 +00:00
void Host_Init ( void )
2010-02-15 23:26:55 +00:00
{
if ( standard_quake )
minimum_memory = MINIMUM_MEMORY ;
2012-11-06 08:56:09 +00:00
else minimum_memory = MINIMUM_MEMORY_LEVELPAK ;
2010-02-15 23:26:55 +00:00
if ( COM_CheckParm ( " -minmemory " ) )
2011-04-19 16:41:45 +00:00
host_parms - > memsize = minimum_memory ;
2010-02-15 23:26:55 +00:00
2011-04-19 16:41:45 +00:00
if ( host_parms - > memsize < minimum_memory )
Sys_Error ( " Only %4.1f megs of memory available, can't execute game " , host_parms - > memsize / ( float ) 0x100000 ) ;
2010-02-15 23:26:55 +00:00
2011-04-19 16:41:45 +00:00
com_argc = host_parms - > argc ;
com_argv = host_parms - > argv ;
2010-02-15 23:26:55 +00:00
2011-04-19 16:41:45 +00:00
Memory_Init ( host_parms - > membase , host_parms - > memsize ) ;
2010-02-15 23:26:55 +00:00
Cbuf_Init ( ) ;
Cmd_Init ( ) ;
2011-04-19 16:41:45 +00:00
LOG_Init ( host_parms ) ;
2010-02-15 23:26:55 +00:00
Cvar_Init ( ) ; //johnfitz
2011-04-19 16:41:45 +00:00
COM_Init ( ) ;
2011-12-29 15:10:18 +00:00
COM_InitFilesystem ( ) ;
2010-02-15 23:26:55 +00:00
Host_InitLocal ( ) ;
W_LoadWadFile ( ) ; //johnfitz -- filename is now hard-coded for honesty
2010-06-26 08:16:58 +00:00
if ( cls . state ! = ca_dedicated )
{
Key_Init ( ) ;
Con_Init ( ) ;
}
2010-02-15 23:26:55 +00:00
PR_Init ( ) ;
Mod_Init ( ) ;
NET_Init ( ) ;
SV_Init ( ) ;
2021-06-29 11:17:17 +00:00
# ifdef QSS_DATE //avoid non-determinism.
Con_Printf ( " Exe: " ENGINE_NAME_AND_VER " \n " ) ;
# else
2016-04-29 20:00:50 +00:00
Con_Printf ( " Exe: " __TIME__ " " __DATE__ " \n " ) ;
2021-06-29 11:17:17 +00:00
# endif
2011-04-19 16:41:45 +00:00
Con_Printf ( " %4.1f megabyte heap \n " , host_parms - > memsize / ( 1024 * 1024.0 ) ) ;
2010-02-15 23:26:55 +00:00
if ( cls . state ! = ca_dedicated )
{
2011-01-02 21:45:16 +00:00
host_colormap = ( byte * ) COM_LoadHunkFile ( " gfx/colormap.lmp " , NULL ) ;
2010-02-15 23:26:55 +00:00
if ( ! host_colormap )
Sys_Error ( " Couldn't load gfx/colormap.lmp " ) ;
2010-06-26 08:16:58 +00:00
V_Init ( ) ;
Chase_Init ( ) ;
ExtraMaps_Init ( ) ; //johnfitz
Modlist_Init ( ) ; //johnfitz
2015-05-30 02:28:58 +00:00
DemoList_Init ( ) ; //ericw
2010-02-15 23:26:55 +00:00
VID_Init ( ) ;
2012-11-06 08:56:09 +00:00
IN_Init ( ) ;
2010-02-15 23:26:55 +00:00
TexMgr_Init ( ) ; //johnfitz
Draw_Init ( ) ;
SCR_Init ( ) ;
R_Init ( ) ;
S_Init ( ) ;
CDAudio_Init ( ) ;
Backported external music files support using decoder libraries and the
new raw samples interface from Hammer of Thyrion (uhexen2) :
- bgmusic.c, bgmusic.h: New BGM interface for background music handling.
Handles streaming music as raw sound samples.
- bgmnull.c: BGM source for cases where the engine is configured for no
sound.
- cl_main.c: Include bgmusic.h. Call BGM_Stop() and CDAudio_Stop() in
CL_Disconnect().
- cd_sdl.c: Moved bgmvolume boundary checking to bgmusic.c upon value
changes.
- gl_vidnt.c, gl_vidsdl.c, cl_parse.c: Include bgmusic.h. Add BGM_Pause()
and BGM_Resume() calls along with CDAudio_ counterparts.
- cl_parse.c: Replace CDAudio_Play() call by the new BGM_PlayCDtrack()
which first tries CDAudio_Play() and then streaming music if it fails.
- host.c: Include bgmusic.h. Call BGM_Update() just before S_Update()
in Host_Frame(). In Host_Init(), call BGM_Init() after other audio init
calls. In Host_Shutdown(), call BGM_Shutdown() before all other audio
shutdown calls.
- snd_dma.c: Include snd_codec.h and bgmusic.h. Call S_CodecInit() from
S_Init(). Call S_CodecShutdown() from S_Shutdown().
- snd_codec.c, snd_codec.h: New public codec interface for streaming
music as raw samples. Adapted from quake2 and ioquake3 with changes.
Individual codecs are responsible for handling any necessary byte swap
operations.
- snd_codeci.h: New header for snd_codec internals.
- snd_wave.c, snd_wave.h: Codec for WAV format streaming music. Adapted
from ioquake3 with changes.
- snd_vorbis.c, snd_vorbis.h: Codec for Ogg/Vorbis format streaming music.
- snd_mp3.c, snd_mp3.h: Codec for MP3 format streaming music using libmad.
Adapted from the SoX project with changes.
- Makefile: Adjusted for the new sources. Added switches USE_CODEC_WAVE,
USE_CODEC_MP3, USE_CODEC_VORBIS for enabling and disabling individual
codecs.
- Windows makefiles and project files as well as other CodeBlocks project
files will be updated shortly.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@374 af15c1b1-3010-417e-b628-4374ebc0bcbd
2011-01-05 19:50:43 +00:00
BGM_Init ( ) ;
2010-02-15 23:26:55 +00:00
Sbar_Init ( ) ;
CL_Init ( ) ;
2010-06-26 08:45:40 +00:00
}
2010-02-15 23:26:55 +00:00
2021-08-29 14:11:28 +00:00
LOC_Init ( ) ; // for 2021 rerelease support.
2010-02-15 23:26:55 +00:00
Hunk_AllocName ( 0 , " -HOST_HUNKLEVEL- " ) ;
host_hunklevel = Hunk_LowMark ( ) ;
host_initialized = true ;
2011-07-05 06:45:31 +00:00
Con_Printf ( " \n ========= Quake Initialized ========= \n \n " ) ;
2010-02-15 23:26:55 +00:00
2020-07-02 19:05:51 +00:00
if ( setjmp ( host_abortserver ) )
2020-10-17 02:35:32 +00:00
return ; // something bad happened
//okay... now we can do stuff that's allowed to Host_Error
2020-07-02 19:05:51 +00:00
2017-09-17 02:12:53 +00:00
//spike -- create these aliases, because they're useful.
Cbuf_AddText ( " alias startmap_sp \" map start \" \n " ) ;
Cbuf_AddText ( " alias startmap_dm \" map start \" \n " ) ;
2020-10-17 02:35:32 +00:00
if ( cls . state ! = ca_dedicated )
M_Init ( ) ;
if ( setjmp ( host_abortserver ) )
return ; // don't do the above twice if the following Cbuf_Execute does bad things.
2011-07-05 06:45:31 +00:00
if ( cls . state ! = ca_dedicated )
{
2017-09-17 02:12:53 +00:00
Cbuf_AddText ( " cl_warncmd 0 \n " ) ;
2011-07-05 06:45:31 +00:00
Cbuf_InsertText ( " exec quake.rc \n " ) ;
2020-09-13 15:14:59 +00:00
Cbuf_AddText ( " cl_warncmd 1 \n " ) ;
2011-07-05 06:45:31 +00:00
// johnfitz -- in case the vid mode was locked during vid_init, we can unlock it now.
// note: two leading newlines because the command buffer swallows one of them.
Cbuf_AddText ( " \n \n vid_unlock \n " ) ;
}
2010-06-26 08:45:40 +00:00
if ( cls . state = = ca_dedicated )
{
2017-09-17 02:12:53 +00:00
Cbuf_AddText ( " cl_warncmd 0 \n " ) ;
Cbuf_AddText ( " exec default.cfg \n " ) ; //spike -- someone decided that quake.rc shouldn't be execed on dedicated servers, but that means you'll get bad defaults
Cbuf_AddText ( " cl_warncmd 1 \n " ) ;
Cbuf_AddText ( " exec server.cfg \n " ) ; //spike -- for people who want things explicit.
2010-06-26 08:45:40 +00:00
Cbuf_AddText ( " exec autoexec.cfg \n " ) ;
2020-10-17 02:35:32 +00:00
Cbuf_AddText ( " stuffcmds \n " ) ;
2010-06-26 08:45:40 +00:00
Cbuf_Execute ( ) ;
if ( ! sv . active )
2017-09-17 02:12:53 +00:00
Cbuf_AddText ( " startmap_dm \n " ) ;
2010-06-26 08:45:40 +00:00
}
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = =
Host_Shutdown
FIXME : this is a callback from Sys_Quit and Sys_Error . It would be better
to run quit through here before the final handoff to the sys code .
= = = = = = = = = = = = = = =
*/
void Host_Shutdown ( void )
{
static qboolean isdown = false ;
if ( isdown )
{
printf ( " recursive shutdown \n " ) ;
return ;
}
isdown = true ;
// keep Con_Printf from trying to update the screen
scr_disabled_for_loading = true ;
Host_WriteConfiguration ( ) ;
NET_Shutdown ( ) ;
if ( cls . state ! = ca_dedicated )
{
2010-06-26 00:31:12 +00:00
if ( con_initialized )
History_Shutdown ( ) ;
Backported external music files support using decoder libraries and the
new raw samples interface from Hammer of Thyrion (uhexen2) :
- bgmusic.c, bgmusic.h: New BGM interface for background music handling.
Handles streaming music as raw sound samples.
- bgmnull.c: BGM source for cases where the engine is configured for no
sound.
- cl_main.c: Include bgmusic.h. Call BGM_Stop() and CDAudio_Stop() in
CL_Disconnect().
- cd_sdl.c: Moved bgmvolume boundary checking to bgmusic.c upon value
changes.
- gl_vidnt.c, gl_vidsdl.c, cl_parse.c: Include bgmusic.h. Add BGM_Pause()
and BGM_Resume() calls along with CDAudio_ counterparts.
- cl_parse.c: Replace CDAudio_Play() call by the new BGM_PlayCDtrack()
which first tries CDAudio_Play() and then streaming music if it fails.
- host.c: Include bgmusic.h. Call BGM_Update() just before S_Update()
in Host_Frame(). In Host_Init(), call BGM_Init() after other audio init
calls. In Host_Shutdown(), call BGM_Shutdown() before all other audio
shutdown calls.
- snd_dma.c: Include snd_codec.h and bgmusic.h. Call S_CodecInit() from
S_Init(). Call S_CodecShutdown() from S_Shutdown().
- snd_codec.c, snd_codec.h: New public codec interface for streaming
music as raw samples. Adapted from quake2 and ioquake3 with changes.
Individual codecs are responsible for handling any necessary byte swap
operations.
- snd_codeci.h: New header for snd_codec internals.
- snd_wave.c, snd_wave.h: Codec for WAV format streaming music. Adapted
from ioquake3 with changes.
- snd_vorbis.c, snd_vorbis.h: Codec for Ogg/Vorbis format streaming music.
- snd_mp3.c, snd_mp3.h: Codec for MP3 format streaming music using libmad.
Adapted from the SoX project with changes.
- Makefile: Adjusted for the new sources. Added switches USE_CODEC_WAVE,
USE_CODEC_MP3, USE_CODEC_VORBIS for enabling and disabling individual
codecs.
- Windows makefiles and project files as well as other CodeBlocks project
files will be updated shortly.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@374 af15c1b1-3010-417e-b628-4374ebc0bcbd
2011-01-05 19:50:43 +00:00
BGM_Shutdown ( ) ;
2010-06-26 00:31:12 +00:00
CDAudio_Shutdown ( ) ;
S_Shutdown ( ) ;
2012-11-06 08:56:09 +00:00
IN_Shutdown ( ) ;
2010-02-15 23:26:55 +00:00
VID_Shutdown ( ) ;
}
2010-08-23 09:49:03 +00:00
2010-04-27 08:24:13 +00:00
LOG_Close ( ) ;
2021-08-29 14:11:28 +00:00
LOC_Shutdown ( ) ;
2010-02-15 23:26:55 +00:00
}