2004-08-23 00:15:46 +00:00
/*
Copyright ( C ) 1996 - 1997 Id Software , Inc .
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 .
*/
// cl_main.c -- client main loop
# include "quakedef.h"
# include "winquake.h"
2005-04-18 03:21:16 +00:00
# include <sys/types.h>
2004-08-23 00:15:46 +00:00
# ifdef _WIN32
# include "winsock.h"
# else
# include <netinet/in.h>
# endif
# if defined(_WIN32) && !defined(MINGW) && defined(RGLQUAKE)
# define WINAVI
# endif
# include <ctype.h>
// we need to declare some mouse variables here, because the menu system
// references them even when on a unix system.
qboolean noclip_anglehack ; // remnant from old quake
cvar_t rcon_password = { " rcon_password " , " " } ;
cvar_t rcon_address = { " rcon_address " , " " } ;
cvar_t cl_timeout = { " cl_timeout " , " 60 " } ;
cvar_t cl_shownet = { " cl_shownet " , " 0 " } ; // can be 0, 1, or 2
cvar_t cl_sbar = { " cl_sbar " , " 0 " , NULL , CVAR_ARCHIVE } ;
cvar_t cl_hudswap = { " cl_hudswap " , " 0 " , NULL , CVAR_ARCHIVE } ;
2005-05-08 05:56:03 +00:00
cvar_t cl_maxfps = { " cl_maxfps " , " 1000 " , NULL , CVAR_ARCHIVE } ;
2004-08-23 00:15:46 +00:00
cvar_t cl_nopext = { " cl_nopext " , " 0 " , NULL , CVAR_ARCHIVE } ;
2005-04-26 16:04:12 +00:00
cvar_t cl_nolerp = { " cl_nolerp " , " 1 " } ;
2004-08-23 00:15:46 +00:00
2004-10-13 07:24:59 +00:00
cvar_t cfg_save_name = { " cfg_save_name " , " fte " , NULL , CVAR_ARCHIVE } ;
2004-08-23 00:15:46 +00:00
cvar_t cl_splitscreen = { " cl_splitscreen " , " 0 " } ;
cvar_t lookspring = { " lookspring " , " 0 " , NULL , CVAR_ARCHIVE } ;
cvar_t lookstrafe = { " lookstrafe " , " 0 " , NULL , CVAR_ARCHIVE } ;
cvar_t sensitivity = { " sensitivity " , " 3 " , NULL , CVAR_ARCHIVE } ;
2005-01-13 16:29:20 +00:00
cvar_t cl_staticsounds = { " cl_staticsounds " , " 1 " } ;
2004-08-23 00:15:46 +00:00
cvar_t m_pitch = { " m_pitch " , " 0.022 " , NULL , CVAR_ARCHIVE } ;
cvar_t m_yaw = { " m_yaw " , " 0.022 " } ;
cvar_t m_forward = { " m_forward " , " 1 " } ;
cvar_t m_side = { " m_side " , " 0.8 " } ;
cvar_t entlatency = { " entlatency " , " 20 " } ;
cvar_t cl_predict_players = { " cl_predict_players " , " 1 " } ;
cvar_t cl_predict_players2 = { " cl_predict_players2 " , " 1 " } ;
cvar_t cl_solid_players = { " cl_solid_players " , " 1 " } ;
2004-12-24 08:45:56 +00:00
cvar_t cl_demospeed = { " cl_demospeed " , " 0 " } ;
2005-03-12 23:40:42 +00:00
cvar_t cl_indepphysics = { " cl_indepphysics " , " 0 " } ;
2004-08-23 00:15:46 +00:00
cvar_t localid = { " localid " , " " } ;
static qboolean allowremotecmd = true ;
//
// info mirrors
//
cvar_t password = { " password " , " " , NULL , CVAR_USERINFO } ; //this is parhaps slightly dodgy...
cvar_t spectator = { " spectator " , " " , NULL , CVAR_USERINFO } ;
cvar_t name = { " name " , " unnamed " , NULL , CVAR_ARCHIVE | CVAR_USERINFO } ;
cvar_t team = { " team " , " " , NULL , CVAR_ARCHIVE | CVAR_USERINFO } ;
cvar_t skin = { " skin " , " " , NULL , CVAR_ARCHIVE | CVAR_USERINFO } ;
2004-12-24 08:45:56 +00:00
cvar_t model = { " model " , " " , NULL , CVAR_ARCHIVE | CVAR_USERINFO } ;
2004-08-23 00:15:46 +00:00
cvar_t topcolor = { " topcolor " , " " , NULL , CVAR_ARCHIVE | CVAR_USERINFO } ;
cvar_t bottomcolor = { " bottomcolor " , " " , NULL , CVAR_ARCHIVE | CVAR_USERINFO } ;
cvar_t rate = { " rate " , " 2500 " , NULL , CVAR_ARCHIVE | CVAR_USERINFO } ;
2005-01-16 02:25:35 +00:00
cvar_t drate = { " drate " , " 100000 " , NULL , CVAR_ARCHIVE | CVAR_USERINFO } ; // :)
2004-08-23 00:15:46 +00:00
cvar_t noaim = { " noaim " , " " , NULL , CVAR_ARCHIVE | CVAR_USERINFO } ;
cvar_t msg = { " msg " , " 1 " , NULL , CVAR_ARCHIVE | CVAR_USERINFO } ;
2004-09-30 22:42:34 +00:00
cvar_t cl_nofake = { " cl_nofake " , " 2 " } ;
cvar_t cl_chatsound = { " cl_chatsound " , " 1 " } ;
2004-08-23 00:15:46 +00:00
2005-01-17 17:40:37 +00:00
cvar_t r_rocketlight = { " r_rocketlight " , " 1 " } ;
cvar_t r_lightflicker = { " r_lightflicker " , " 1 " } ;
cvar_t cl_r2g = { " cl_r2g " , " 0 " } ;
cvar_t r_powerupglow = { " r_powerupglow " , " 1 " } ;
2005-04-16 16:21:27 +00:00
cvar_t v_powerupshell = { " v_powerupshell " , " 0 " } ;
2005-01-18 20:15:20 +00:00
cvar_t cl_gibfilter = { " cl_gibfilter " , " 0 " } ;
cvar_t cl_deadbodyfilter = { " cl_deadbodyfilter " , " 0 " } ;
2005-01-17 17:40:37 +00:00
2005-01-13 16:29:20 +00:00
cvar_t cl_muzzleflash = { " cl_muzzleflash " , " 1 " } ;
2004-08-23 00:15:46 +00:00
cvar_t cl_item_bobbing = { " cl_model_bobbing " , " 0 " } ;
cvar_t requiredownloads = { " requiredownloads " , " 1 " , NULL , CVAR_ARCHIVE } ;
cvar_t cl_standardchat = { " cl_standardchat " , " 0 " } ;
cvar_t host_mapname = { " host_mapname " , " " } ;
extern cvar_t cl_hightrack ;
char cl_screengroup [ ] = " Screen options " ;
char cl_controlgroup [ ] = " client operation options " ;
char cl_inputgroup [ ] = " client input controls " ;
char cl_predictiongroup [ ] = " Client side prediction " ;
client_static_t cls ;
client_state_t cl ;
entity_state_t cl_baselines [ MAX_EDICTS ] ;
efrag_t cl_efrags [ MAX_EFRAGS ] ;
entity_t cl_static_entities [ MAX_STATIC_ENTITIES ] ;
lightstyle_t cl_lightstyle [ MAX_LIGHTSTYLES ] ;
//lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES];
dlight_t cl_dlights [ MAX_DLIGHTS ] ;
// refresh list
// this is double buffered so the last frame
// can be scanned for oldorigins of trailing objects
int cl_numvisedicts , cl_oldnumvisedicts ;
entity_t * cl_visedicts , * cl_oldvisedicts ;
entity_t cl_visedicts_list [ 2 ] [ MAX_VISEDICTS ] ;
double connect_time = - 1 ; // for connection retransmits
int connect_type = 0 ;
quakeparms_t host_parms ;
qboolean host_initialized ; // true if into command execution
qboolean nomaster ;
double host_frametime ;
double realtime ; // without any filtering or bounding
double oldrealtime ; // last frame run
int host_framecount ;
int host_hunklevel ;
qbyte * host_basepal ;
qbyte * host_colormap ;
2005-01-23 17:49:42 +00:00
cvar_t host_speeds = { " host_speeds " , " 0 " } ; // set for running times
2004-10-10 06:32:29 +00:00
# ifdef CRAZYDEBUGGING
cvar_t developer = { " developer " , " 1 " } ;
# else
2004-08-23 00:15:46 +00:00
cvar_t developer = { " developer " , " 0 " } ;
2004-10-10 06:32:29 +00:00
# endif
2004-08-23 00:15:46 +00:00
int fps_count ;
jmp_buf host_abort ;
void Master_Connect_f ( void ) ;
float server_version = 0 ; // version of server we connected to
char emodel_name [ ] =
{ ' e ' ^ 0xff , ' m ' ^ 0xff , ' o ' ^ 0xff , ' d ' ^ 0xff , ' e ' ^ 0xff , ' l ' ^ 0xff , 0 } ;
char pmodel_name [ ] =
{ ' p ' ^ 0xff , ' m ' ^ 0xff , ' o ' ^ 0xff , ' d ' ^ 0xff , ' e ' ^ 0xff , ' l ' ^ 0xff , 0 } ;
char prespawn_name [ ] =
{ ' p ' ^ 0xff , ' r ' ^ 0xff , ' e ' ^ 0xff , ' s ' ^ 0xff , ' p ' ^ 0xff , ' a ' ^ 0xff , ' w ' ^ 0xff , ' n ' ^ 0xff ,
' ' ^ 0xff , ' % ' ^ 0xff , ' i ' ^ 0xff , ' ' ^ 0xff , ' 0 ' ^ 0xff , ' ' ^ 0xff , ' % ' ^ 0xff , ' i ' ^ 0xff , 0 } ;
char modellist_name [ ] =
{ ' m ' ^ 0xff , ' o ' ^ 0xff , ' d ' ^ 0xff , ' e ' ^ 0xff , ' l ' ^ 0xff , ' l ' ^ 0xff , ' i ' ^ 0xff , ' s ' ^ 0xff , ' t ' ^ 0xff ,
' ' ^ 0xff , ' % ' ^ 0xff , ' i ' ^ 0xff , ' ' ^ 0xff , ' % ' ^ 0xff , ' i ' ^ 0xff , 0 } ;
char soundlist_name [ ] =
{ ' s ' ^ 0xff , ' o ' ^ 0xff , ' u ' ^ 0xff , ' n ' ^ 0xff , ' d ' ^ 0xff , ' l ' ^ 0xff , ' i ' ^ 0xff , ' s ' ^ 0xff , ' t ' ^ 0xff ,
' ' ^ 0xff , ' % ' ^ 0xff , ' i ' ^ 0xff , ' ' ^ 0xff , ' % ' ^ 0xff , ' i ' ^ 0xff , 0 } ;
/*
= = = = = = = = = = = = = = = = = =
CL_Quit_f
= = = = = = = = = = = = = = = = = =
*/
void CL_Quit_f ( void )
{
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-23 00:15:46 +00:00
if ( ! isDedicated )
2004-11-29 01:21:00 +00:00
# endif
2004-08-23 00:15:46 +00:00
{
M_Menu_Quit_f ( ) ;
return ;
}
CL_Disconnect ( ) ;
Sys_Quit ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = =
CL_Version_f
= = = = = = = = = = = = = = = = = = = = = =
*/
void CL_Version_f ( void )
{
# ifdef VERSION3PART
# ifdef DISTRIBUTION
Con_TPrintf ( TLC_VERSIONST3 , DISTRIBUTION , VERSION , build_number ( ) ) ;
# else
Con_TPrintf ( TCL_VERSION3 , VERSION , build_number ( ) ) ;
# endif
# else
# ifdef DISTRIBUTION
Con_TPrintf ( TLC_VERSIONST2 , DISTRIBUTION , VERSION , build_number ( ) ) ;
# else
Con_TPrintf ( TLC_VERSION2 , VERSION , build_number ( ) ) ;
# endif
# endif
Con_TPrintf ( TL_EXEDATETIME , __DATE__ , __TIME__ ) ;
}
2004-11-20 01:12:02 +00:00
void CL_ConnectToDarkPlaces ( char * challenge , netadr_t adr )
{
char data [ 2048 ] ;
cls . fteprotocolextensions = 0 ;
cls . resendinfo = false ;
connect_time = realtime ; // for retransmit requests
sprintf ( data , " %c%c%c%cconnect \\ protocol \\ darkplaces 3 \\ challenge \\ %s " , 255 , 255 , 255 , 255 , challenge ) ;
NET_SendPacket ( NS_CLIENT , strlen ( data ) , data , adr ) ;
cl . splitclients = 0 ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = =
CL_SendConnectPacket
called by CL_Connect_f and CL_CheckResend
= = = = = = = = = = = = = = = = = = = = = =
*/
void CL_SendConnectPacket (
# ifdef PROTOCOL_VERSION_FTE
int ftepext ,
# endif
int compressioncrc
/*, ...*/ ) //dmw new parms
{
netadr_t adr ;
char data [ 2048 ] ;
char playerinfo2 [ MAX_INFO_STRING ] ;
double t1 , t2 ;
# ifdef PROTOCOL_VERSION_FTE
int fteprotextsupported = 0 ;
# endif
int clients ;
int c ;
// JACK: Fixed bug where DNS lookups would cause two connects real fast
// Now, adds lookup time to the connect time.
// Should I add it to realtime instead?!?!
if ( cls . state ! = ca_disconnected )
return ;
if ( cl_nopext . value ) //imagine it's an unenhanced server
{
ftepext = 0 ;
compressioncrc = 0 ;
}
# ifdef PROTOCOL_VERSION_FTE
# ifdef PEXT_SCALE //dmw - protocol extensions
fteprotextsupported | = PEXT_SCALE ;
# endif
# ifdef PEXT_LIGHTSTYLECOL
fteprotextsupported | = PEXT_LIGHTSTYLECOL ;
# endif
# ifdef PEXT_TRANS
fteprotextsupported | = PEXT_TRANS ;
# endif
# ifdef PEXT_VIEW2
fteprotextsupported | = PEXT_VIEW2 ;
# endif
# ifdef PEXT_BULLETENS
fteprotextsupported | = PEXT_BULLETENS ;
# endif
# ifdef PEXT_ZLIBDL
fteprotextsupported | = PEXT_ZLIBDL ;
# endif
# ifdef PEXT_LIGHTUPDATES
fteprotextsupported | = PEXT_LIGHTUPDATES ;
# endif
# ifdef PEXT_FATNESS
fteprotextsupported | = PEXT_FATNESS ;
# endif
# ifdef PEXT_HLBSP
fteprotextsupported | = PEXT_HLBSP ;
# endif
# ifdef PEXT_Q2BSP
fteprotextsupported | = PEXT_Q2BSP ;
# endif
# ifdef PEXT_Q3BSP
fteprotextsupported | = PEXT_Q3BSP ;
# endif
# ifdef PEXT_TE_BULLET
fteprotextsupported | = PEXT_TE_BULLET ;
# endif
# ifdef PEXT_HULLSIZE
fteprotextsupported | = PEXT_HULLSIZE ;
# endif
# ifdef PEXT_SETVIEW
fteprotextsupported | = PEXT_SETVIEW ;
# endif
# ifdef PEXT_MODELDBL
fteprotextsupported | = PEXT_MODELDBL ;
# endif
# ifdef PEXT_VWEAP
fteprotextsupported | = PEXT_VWEAP ;
# endif
2004-11-17 17:56:27 +00:00
# ifdef PEXT_FLOATCOORDS
fteprotextsupported | = PEXT_FLOATCOORDS ;
2004-08-23 00:15:46 +00:00
# endif
fteprotextsupported | = PEXT_SPAWNSTATIC2 ;
2005-02-09 19:32:09 +00:00
# ifdef PEXT_SEEF1
2004-08-23 00:15:46 +00:00
fteprotextsupported | = PEXT_SEEF1 ;
2005-02-09 19:32:09 +00:00
# endif
2004-08-23 00:15:46 +00:00
fteprotextsupported | = PEXT_SPLITSCREEN ;
fteprotextsupported | = PEXT_HEXEN2 ;
fteprotextsupported | = PEXT_CUSTOMTEMPEFFECTS ;
fteprotextsupported | = PEXT_256PACKETENTITIES ;
2004-09-01 00:01:08 +00:00
// fteprotextsupported |= PEXT_64PLAYERS;
fteprotextsupported | = PEXT_SHOWPIC ;
2004-10-10 06:32:29 +00:00
fteprotextsupported | = PEXT_SETATTACHMENT ;
2005-01-16 02:25:35 +00:00
# ifdef PEXT_CHUNKEDDOWNLOADS
fteprotextsupported | = PEXT_CHUNKEDDOWNLOADS ;
# endif
2005-02-28 07:16:19 +00:00
# ifdef PEXT_CSQC
fteprotextsupported | = PEXT_CSQC ;
# endif
2004-08-23 00:15:46 +00:00
fteprotextsupported & = ftepext ;
2005-04-16 16:21:27 +00:00
# ifdef Q2CLIENT
2005-03-18 06:14:07 +00:00
if ( cls . q2server )
fteprotextsupported = 0 ;
2005-04-16 16:21:27 +00:00
# endif
2005-03-18 06:14:07 +00:00
2004-08-23 00:15:46 +00:00
cls . fteprotocolextensions = fteprotextsupported ;
# endif
t1 = Sys_DoubleTime ( ) ;
if (
# ifdef NQPROT
! cls . netcon & &
# endif
! NET_StringToAdr ( cls . servername , & adr ) )
{
Con_TPrintf ( TLC_BADSERVERADDRESS ) ;
connect_time = - 1 ;
return ;
}
if ( ! NET_IsClientLegal ( & adr ) )
{
Con_TPrintf ( TLC_ILLEGALSERVERADDRESS ) ;
connect_time = - 1 ;
return ;
}
if ( adr . port = = 0 )
adr . port = BigShort ( 27500 ) ;
t2 = Sys_DoubleTime ( ) ;
cls . resendinfo = false ;
connect_time = realtime + t2 - t1 ; // for retransmit requests
cls . qport = Cvar_VariableValue ( " qport " ) ;
// Info_SetValueForStarKey (cls.userinfo, "*ip", NET_AdrToString(adr), MAX_INFO_STRING);
Q_strncpyz ( playerinfo2 , cls . userinfo , sizeof ( playerinfo2 ) - 1 ) ;
Info_SetValueForStarKey ( playerinfo2 , " name " , " Second player " , MAX_INFO_STRING ) ;
clients = 1 ;
if ( cl_splitscreen . value )
{
if ( adr . type = = NA_LOOPBACK )
clients = cl_splitscreen . value + 1 ;
else
Con_Printf ( " Split screens are still under development \n " ) ;
}
if ( clients < 1 )
clients = 1 ;
if ( clients > MAX_SPLITS )
clients = MAX_SPLITS ;
# ifdef Q2CLIENT
if ( cls . q2server ) //sorry - too lazy.
clients = 1 ;
# endif
2004-12-24 08:45:56 +00:00
# ifdef Q3CLIENT
if ( cls . q2server = = 2 )
{ //q3 requires some very strange things.
CLQ3_SendConnectPacket ( adr ) ;
return ;
}
# endif
2004-08-23 00:15:46 +00:00
sprintf ( data , " %c%c%c%cconnect " , 255 , 255 , 255 , 255 ) ;
2004-12-24 08:45:56 +00:00
2004-08-23 00:15:46 +00:00
if ( clients > 1 ) //splitscreen 'connect' command specifies the number of userinfos sent.
strcat ( data , va ( " %i " , clients ) ) ;
# ifdef Q2CLIENT
if ( cls . q2server )
strcat ( data , va ( " %i " , PROTOCOL_VERSION_Q2 ) ) ;
else
# endif
strcat ( data , va ( " %i " , PROTOCOL_VERSION ) ) ;
strcat ( data , va ( " %i %i " , cls . qport , cls . challenge ) ) ;
//userinfo 0 + zquake extension info.
2005-01-16 02:25:35 +00:00
strcat ( data , va ( " \" %s \\ *z_ext \\ %i \" " , cls . userinfo , SUPPORTED_Z_EXTENSIONS ) ) ;
2004-08-23 00:15:46 +00:00
for ( c = 1 ; c < clients ; c + + )
{
Info_SetValueForStarKey ( playerinfo2 , " name " , va ( " %s%i " , name . string , c + 1 ) , MAX_INFO_STRING ) ;
2005-01-16 02:25:35 +00:00
strcat ( data , va ( " \" %s \" " , playerinfo2 , SUPPORTED_Z_EXTENSIONS ) ) ;
2004-08-23 00:15:46 +00:00
}
strcat ( data , " \n " ) ;
# ifdef PROTOCOL_VERSION_FTE
if ( ftepext )
strcat ( data , va ( " 0x%x 0x%x \n " , PROTOCOL_VERSION_FTE , fteprotextsupported ) ) ;
# endif
# ifdef HUFFNETWORK
if ( compressioncrc & & Huff_CompressionCRC ( compressioncrc ) )
{
strcat ( data , va ( " 0x%x 0x%x \n " , ( ( ' H ' < < 0 ) + ( ' U ' < < 8 ) + ( ' F ' < < 16 ) + ( ' F ' < < 24 ) ) , compressioncrc ) ) ;
cls . netchan . compress = true ;
}
else
# endif
cls . netchan . compress = false ;
# ifdef NQPROT
if ( cls . netcon )
{
sizebuf_t msg ;
msg . allowoverflow = false ;
msg . cursize = strlen ( data ) ;
msg . data = data ;
msg . maxsize = sizeof ( data ) ;
msg . overflowed = false ;
NET_SendMessage ( cls . netcon , & msg ) ;
}
else
# endif
NET_SendPacket ( NS_CLIENT , strlen ( data ) , data , adr ) ;
cl . splitclients = 0 ;
2005-05-13 10:42:48 +00:00
CL_RegisterSplitCommands ( ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = =
CL_CheckForResend
Resend a connect message if the last one has timed out
= = = = = = = = = = = = = = = = =
*/
void CL_CheckForResend ( void )
{
netadr_t adr ;
char data [ 2048 ] ;
double t1 , t2 ;
# ifndef CLIENTONLY
if ( ! cls . state & & sv . state )
{
Q_strncpyz ( cls . servername , " internalserver " , sizeof ( cls . servername ) ) ;
cls . state = ca_disconnected ;
2005-03-12 23:40:42 +00:00
switch ( svs . gametype )
{
# ifdef Q3CLIENT
case GT_QUAKE3 :
cls . q2server = 2 ;
break ;
# endif
2004-08-23 00:15:46 +00:00
# ifdef Q2CLIENT
2005-03-12 23:40:42 +00:00
case GT_QUAKE2 :
2004-08-23 00:15:46 +00:00
cls . q2server = true ;
2005-03-12 23:40:42 +00:00
break ;
2004-08-23 00:15:46 +00:00
# endif
2005-03-12 23:40:42 +00:00
default :
cls . q2server = false ;
break ;
}
2004-08-23 00:15:46 +00:00
CL_SendConnectPacket ( svs . fteprotocolextensions , false ) ;
return ;
}
# endif
if ( connect_time = = - 1 )
return ;
if ( cls . state ! = ca_disconnected )
return ;
# ifdef NQPROT
if ( connect_type )
{
if ( ! connect_time | | ! ( realtime - connect_time < 5.0 ) )
{
connect_time = realtime ;
NQ_BeginConnect ( cls . servername ) ;
NQ_ContinueConnect ( cls . servername ) ;
}
else
NQ_ContinueConnect ( cls . servername ) ;
return ;
}
# endif
if ( connect_time & & realtime - connect_time < 5.0 )
return ;
t1 = Sys_DoubleTime ( ) ;
if ( ! NET_StringToAdr ( cls . servername , & adr ) )
{
Con_TPrintf ( TLC_BADSERVERADDRESS ) ;
connect_time = - 1 ;
return ;
}
if ( ! NET_IsClientLegal ( & adr ) )
{
Con_TPrintf ( TLC_ILLEGALSERVERADDRESS ) ;
connect_time = - 1 ;
return ;
}
if ( adr . port = = 0 )
adr . port = BigShort ( 27500 ) ;
t2 = Sys_DoubleTime ( ) ;
connect_time = realtime + t2 - t1 ; // for retransmit requests
Con_TPrintf ( TLC_CONNECTINGTO , cls . servername ) ;
sprintf ( data , " %c%c%c%cgetchallenge \n " , 255 , 255 , 255 , 255 ) ;
NET_SendPacket ( NS_CLIENT , strlen ( data ) , data , adr ) ;
}
void CL_BeginServerConnect ( void )
{
# ifdef NQPROT
if ( cls . netcon )
{
NET_Close ( cls . netcon ) ;
cls . netcon = cls . netchan . qsocket = NULL ;
}
# endif
connect_time = 0 ;
connect_type = 0 ;
CL_CheckForResend ( ) ;
}
# ifdef NQPROT
void CLNQ_BeginServerConnect ( void )
{
if ( cls . netcon )
{
NET_Close ( cls . netcon ) ;
cls . netcon = NULL ;
}
connect_time = 0 ;
connect_type = 1 ;
CL_CheckForResend ( ) ;
}
# endif
void CL_BeginServerReconnect ( void )
{
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-23 00:15:46 +00:00
if ( isDedicated )
2004-11-29 01:21:00 +00:00
# endif
2004-08-23 00:15:46 +00:00
{
Con_TPrintf ( TLC_DEDICATEDCANNOTCONNECT ) ;
return ;
}
connect_time = 0 ;
CL_CheckForResend ( ) ;
}
/*
= = = = = = = = = = = = = = = =
CL_Connect_f
= = = = = = = = = = = = = = = =
*/
void CL_Connect_f ( void )
{
char * server ;
if ( Cmd_Argc ( ) ! = 2 )
{
Con_TPrintf ( TLC_SYNTAX_CONNECT ) ;
return ;
}
server = Cmd_Argv ( 1 ) ;
CL_Disconnect_f ( ) ;
Q_strncpyz ( cls . servername , server , sizeof ( cls . servername ) ) ;
CL_BeginServerConnect ( ) ;
}
2005-01-13 23:33:00 +00:00
void CL_Join_f ( void )
{
char * server ;
if ( Cmd_Argc ( ) ! = 2 )
{
if ( cls . state )
{ //Hmm. This server sucks.
if ( cls . z_ext & Z_EXT_JOIN_OBSERVE )
Cmd_ForwardToServer ( ) ;
else
Cbuf_AddText ( " \n spectator 0;reconnect \n " , RESTRICT_LOCAL ) ;
return ;
}
Con_Printf ( " join requires a connection or servername/ip \n " ) ;
return ;
}
server = Cmd_Argv ( 1 ) ;
CL_Disconnect_f ( ) ;
Cvar_Set ( & spectator , " 0 " ) ;
Q_strncpyz ( cls . servername , server , sizeof ( cls . servername ) ) ;
CL_BeginServerConnect ( ) ;
}
void CL_Observe_f ( void )
{
char * server ;
if ( Cmd_Argc ( ) ! = 2 )
{
if ( cls . state )
{ //Hmm. This server sucks.
if ( cls . z_ext & Z_EXT_JOIN_OBSERVE )
Cmd_ForwardToServer ( ) ;
else
Cbuf_AddText ( " \n spectator 1;reconnect \n " , RESTRICT_LOCAL ) ;
return ;
}
Con_Printf ( " observe requires a connection or servername/ip \n " ) ;
return ;
}
server = Cmd_Argv ( 1 ) ;
CL_Disconnect_f ( ) ;
Cvar_Set ( & spectator , " 1 " ) ;
Q_strncpyz ( cls . servername , server , sizeof ( cls . servername ) ) ;
CL_BeginServerConnect ( ) ;
}
2004-08-23 00:15:46 +00:00
# ifdef NQPROT
void CLNQ_Connect_f ( void )
{
char * server ;
if ( Cmd_Argc ( ) ! = 2 )
{
Con_TPrintf ( TLC_SYNTAX_CONNECT ) ;
return ;
}
server = Cmd_Argv ( 1 ) ;
CL_Disconnect_f ( ) ;
Q_strncpyz ( cls . servername , server , sizeof ( cls . servername ) ) ;
CLNQ_BeginServerConnect ( ) ;
}
# endif
/*
= = = = = = = = = = = = = = = = = = = = =
CL_Rcon_f
Send the rest of the command line over as
an unconnected command .
= = = = = = = = = = = = = = = = = = = = =
*/
void CL_Rcon_f ( void )
{
char message [ 1024 ] ;
int i ;
netadr_t to ;
if ( ! rcon_password . string ) //FIXME: this is strange...
{
Con_TPrintf ( TLC_NORCONPASSWORD ) ;
return ;
}
message [ 0 ] = 255 ;
message [ 1 ] = 255 ;
message [ 2 ] = 255 ;
message [ 3 ] = 255 ;
message [ 4 ] = 0 ;
strcat ( message , " rcon " ) ;
strcat ( message , rcon_password . string ) ;
strcat ( message , " " ) ;
for ( i = 1 ; i < Cmd_Argc ( ) ; i + + )
{
strcat ( message , Cmd_Argv ( i ) ) ;
strcat ( message , " " ) ;
}
if ( cls . state > = ca_connected )
to = cls . netchan . remote_address ;
else
{
if ( ! strlen ( rcon_address . string ) )
{
Con_TPrintf ( TLC_NORCONDEST ) ;
return ;
}
NET_StringToAdr ( rcon_address . string , & to ) ;
}
NET_SendPacket ( NS_CLIENT , strlen ( message ) + 1 , message
, to ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
CL_ClearState
= = = = = = = = = = = = = = = = = = = = =
*/
void CL_ClearState ( void )
{
int i ;
# ifndef CLIENTONLY
# define serverrunning (sv.state != ss_dead)
# define tolocalserver NET_IsLoopBackAddress(cls.netchan.remote_address)
# else
# define serverrunning false
# define tolocalserver false
# define SV_UnspawnServer()
# endif
2005-02-28 07:16:19 +00:00
CL_AllowIndependantSendCmd ( false ) ; //model stuff could be a problem.
2004-08-23 00:15:46 +00:00
S_StopAllSounds ( true ) ;
Cvar_ApplyLatches ( CVAR_SERVEROVERRIDE ) ;
Con_DPrintf ( " Clearing memory \n " ) ;
# ifdef PEXT_BULLETENS
WipeBulletenTextures ( ) ;
# endif
if ( ! serverrunning | | ! tolocalserver )
{
if ( serverrunning )
SV_UnspawnServer ( ) ;
D_FlushCaches ( ) ;
Mod_ClearAll ( ) ;
if ( host_hunklevel ) // FIXME: check this...
Hunk_FreeToLowMark ( host_hunklevel ) ;
Cvar_ApplyLatches ( CVAR_LATCH ) ;
}
CL_ClearTEnts ( ) ;
CL_ClearCustomTEnts ( ) ;
2004-09-01 00:01:08 +00:00
SCR_ShowPic_Clear ( ) ;
2004-08-23 00:15:46 +00:00
if ( cl . playernum [ 0 ] = = - 1 )
{ //left over from q2 connect.
Media_PlayFilm ( " " ) ;
}
// wipe the entire cl structure
memset ( & cl , 0 , sizeof ( cl ) ) ;
SZ_Clear ( & cls . netchan . message ) ;
// clear other arrays
memset ( cl_efrags , 0 , sizeof ( cl_efrags ) ) ;
memset ( cl_dlights , 0 , sizeof ( cl_dlights ) ) ;
memset ( cl_lightstyle , 0 , sizeof ( cl_lightstyle ) ) ;
memset ( cl_baselines , 0 , sizeof ( cl_baselines ) ) ;
//
// allocate the efrags and chain together into a free list
//
cl . free_efrags = cl_efrags ;
for ( i = 0 ; i < MAX_EFRAGS - 1 ; i + + )
cl . free_efrags [ i ] . entnext = & cl . free_efrags [ i + 1 ] ;
cl . free_efrags [ i ] . entnext = NULL ;
for ( i = 0 ; i < MAX_SPLITS ; i + + )
cl . viewheight [ i ] = DEFAULT_VIEWHEIGHT ;
cl . minpitch = - 70 ;
cl . maxpitch = 80 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
CL_Disconnect
Sends a disconnect message to the server
This is also called on Host_Error , so it shouldn ' t cause any errors
= = = = = = = = = = = = = = = = = = = = =
*/
void CL_Disconnect ( void )
{
qbyte final [ 10 ] ;
connect_time = - 1 ;
Cvar_ApplyLatches ( CVAR_SERVEROVERRIDE ) ;
2004-12-09 23:31:48 +00:00
if ( VID_SetWindowCaption )
VID_SetWindowCaption ( " FTE QuakeWorld: disconnected " ) ;
2004-08-23 00:15:46 +00:00
// stop sounds (especially looping!)
S_StopAllSounds ( true ) ;
2004-12-29 03:24:21 +00:00
# ifdef VM_CG
2004-12-24 08:45:56 +00:00
CG_Stop ( ) ;
# endif
2005-02-09 19:32:09 +00:00
# ifdef CSQC_DAT
CSQC_Shutdown ( ) ;
# endif
// if running a local server, shut it down
2004-08-23 00:15:46 +00:00
if ( cls . demoplayback ! = DPB_NONE )
CL_StopPlayback ( ) ;
else if ( cls . state ! = ca_disconnected )
{
if ( cls . demorecording )
CL_Stop_f ( ) ;
# ifdef NQPROT
if ( cls . netcon )
{
sizebuf_t msg ;
final [ 0 ] = clc_disconnect ;
msg . data = final ;
msg . cursize = 1 ;
msg . maxsize = 10 ;
NET_SendMessage ( cls . netcon , & msg ) ;
NET_SendMessage ( cls . netcon , & msg ) ;
NET_SendMessage ( cls . netcon , & msg ) ;
}
else
# endif
{
# ifdef Q2CLIENT
if ( cls . q2server )
{
final [ 0 ] = clcq2_stringcmd ;
strcpy ( final + 1 , " disconnect " ) ;
}
else
# endif
{
final [ 0 ] = clc_stringcmd ;
strcpy ( final + 1 , " drop " ) ;
}
2004-10-19 16:10:14 +00:00
Netchan_Transmit ( & cls . netchan , strlen ( final ) + 1 , final , 2500 ) ;
Netchan_Transmit ( & cls . netchan , strlen ( final ) + 1 , final , 2500 ) ;
Netchan_Transmit ( & cls . netchan , strlen ( final ) + 1 , final , 2500 ) ;
2004-08-23 00:15:46 +00:00
}
cls . state = ca_disconnected ;
cls . demoplayback = DPB_NONE ;
cls . demorecording = cls . timedemo = false ;
# ifndef CLIENTONLY
//running a server, and it's our own
if ( serverrunning & & ! tolocalserver ) SV_UnspawnServer ( ) ;
# endif
}
Cam_Reset ( ) ;
if ( cl . worldmodel )
{
# if defined(RUNTIMELIGHTING) && defined(RGLQUAKE)
extern model_t * lightmodel ;
lightmodel = NULL ;
# endif
cl . worldmodel - > needload = true ;
cl . worldmodel = NULL ;
}
2005-01-13 23:33:00 +00:00
if ( cls . downloadmethod < = DL_QWPENDING )
cls . downloadmethod = DL_NONE ;
2004-08-23 00:15:46 +00:00
if ( cls . downloadqw )
{
fclose ( cls . downloadqw ) ;
cls . downloadqw = NULL ;
}
if ( ! cls . downloadmethod )
* cls . downloadname = ' \0 ' ;
{
downloadlist_t * next ;
while ( cl . downloadlist )
{
next = cl . downloadlist - > next ;
Z_Free ( cl . downloadlist ) ;
cl . downloadlist = next ;
}
while ( cl . faileddownloads )
{
next = cl . faileddownloads - > next ;
Z_Free ( cl . faileddownloads ) ;
cl . faileddownloads = next ;
}
}
COM_FlushTempoaryPacks ( ) ;
2005-04-16 16:21:27 +00:00
cl . spectator = 0 ;
2004-08-23 00:15:46 +00:00
# ifdef NQPROT
cls . signon = 0 ;
NET_Close ( cls . netcon ) ;
cls . netcon = NULL ;
# endif
CL_StopUpload ( ) ;
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-23 00:15:46 +00:00
if ( ! isDedicated )
2004-11-29 01:21:00 +00:00
# endif
2004-08-23 00:15:46 +00:00
SCR_EndLoadingPlaque ( ) ;
2004-12-24 08:45:56 +00:00
2004-12-24 09:10:39 +00:00
# ifdef Q2CLIENT
2004-12-24 08:45:56 +00:00
cls . q2server = 0 ;
2004-12-24 09:10:39 +00:00
# endif
2004-08-23 00:15:46 +00:00
}
# undef serverrunning
# undef tolocalserver
void CL_Disconnect_f ( void )
{
CL_Disconnect ( ) ;
# ifndef CLIENTONLY
if ( sv . state )
SV_UnspawnServer ( ) ;
# endif
Alias_WipeStuffedAliaes ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = =
CL_User_f
user < name or userid >
Dump userdata / masterdata for a user
= = = = = = = = = = = = = = = = = = = =
*/
void CL_User_f ( void )
{
int uid ;
int i ;
# ifndef CLIENTONLY
if ( isDedicated )
{
SV_User_f ( ) ;
return ;
}
# endif
if ( Cmd_Argc ( ) ! = 2 )
{
Con_TPrintf ( TLC_SYNTAX_USER ) ;
return ;
}
uid = atoi ( Cmd_Argv ( 1 ) ) ;
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( ! cl . players [ i ] . name [ 0 ] )
continue ;
if ( cl . players [ i ] . userid = = uid
| | ! strcmp ( cl . players [ i ] . name , Cmd_Argv ( 1 ) ) )
{
Info_Print ( cl . players [ i ] . userinfo ) ;
return ;
}
}
Con_TPrintf ( TLC_USER_NOUSER ) ;
}
/*
= = = = = = = = = = = = = = = = = = = =
CL_Users_f
Dump userids for all current players
= = = = = = = = = = = = = = = = = = = =
*/
void CL_Users_f ( void )
{
int i ;
int c ;
c = 0 ;
Con_TPrintf ( TLC_USERBANNER ) ;
Con_TPrintf ( TLC_USERBANNER2 ) ;
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{
if ( cl . players [ i ] . name [ 0 ] )
{
Con_TPrintf ( TLC_USERLINE , cl . players [ i ] . userid , cl . players [ i ] . frags , cl . players [ i ] . name ) ;
c + + ;
}
}
Con_TPrintf ( TLC_USERTOTAL , c ) ;
}
void CL_Color_f ( void )
{
// just for quake compatability...
int top , bottom ;
char num [ 16 ] ;
qboolean server_owns_colour ;
if ( Cmd_Argc ( ) = = 1 )
{
Con_TPrintf ( TLC_COLOURCURRENT ,
Info_ValueForKey ( cls . userinfo , " topcolor " ) ,
Info_ValueForKey ( cls . userinfo , " bottomcolor " ) ) ;
Con_TPrintf ( TLC_SYNTAX_COLOUR ) ;
return ;
}
2005-04-16 16:21:27 +00:00
if ( Cmd_FromGamecode ( ) )
2004-08-23 00:15:46 +00:00
server_owns_colour = true ;
else
server_owns_colour = false ;
if ( Cmd_Argc ( ) = = 2 )
top = bottom = atoi ( Cmd_Argv ( 1 ) ) ;
else
{
top = atoi ( Cmd_Argv ( 1 ) ) ;
bottom = atoi ( Cmd_Argv ( 2 ) ) ;
}
top & = 15 ;
if ( top > 13 )
top = 13 ;
bottom & = 15 ;
if ( bottom > 13 )
bottom = 13 ;
sprintf ( num , " %i " , top ) ;
if ( top = = 0 )
* num = ' \0 ' ;
if ( Cmd_ExecLevel > RESTRICT_SERVER ) //colour command came from server for a split client
Cbuf_AddText ( va ( " cmd %i setinfo topcolor %i \n " , Cmd_ExecLevel - RESTRICT_SERVER - 1 , top ) , Cmd_ExecLevel ) ;
// else if (server_owns_colour)
// Cvar_LockFromServer(&topcolor, num);
else
Cvar_Set ( & topcolor , num ) ;
sprintf ( num , " %i " , bottom ) ;
if ( bottom = = 0 )
* num = ' \0 ' ;
if ( Cmd_ExecLevel > RESTRICT_SERVER ) //colour command came from server for a split client
Cbuf_AddText ( va ( " cmd %i setinfo bottomcolor %i \n " , Cmd_ExecLevel - RESTRICT_SERVER - 1 , bottom ) , Cmd_ExecLevel ) ;
else if ( server_owns_colour )
Cvar_LockFromServer ( & bottomcolor , num ) ;
else
Cvar_Set ( & bottomcolor , num ) ;
# ifdef NQPROT
if ( cls . netcon )
Cmd_ForwardToServer ( ) ;
# endif
}
void CL_CheckServerInfo ( void )
{
char * s ;
unsigned int allowed ;
cl . teamplay = atoi ( Info_ValueForKey ( cl . serverinfo , " teamplay " ) ) ;
cl . deathmatch = atoi ( Info_ValueForKey ( cl . serverinfo , " deathmatch " ) ) ;
cls . allow_cheats = false ;
cls . allow_semicheats = true ;
cls . allow_rearview = false ;
cls . allow_watervis = false ;
cls . allow_skyboxes = false ;
cls . allow_mirrors = false ;
cls . allow_shaders = false ;
cls . allow_luma = true ;
cls . allow_bump = false ;
# ifdef FISH
cls . allow_fish = false ;
# endif
2005-01-05 08:01:19 +00:00
// cls.allow_fbskins = 0;
2004-08-23 00:15:46 +00:00
// cls.allow_overbrightlight;
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | atoi ( Info_ValueForKey ( cl . serverinfo , " rearview " ) ) )
2004-08-23 00:15:46 +00:00
cls . allow_rearview = true ;
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | atoi ( Info_ValueForKey ( cl . serverinfo , " watervis " ) ) )
2004-08-23 00:15:46 +00:00
cls . allow_watervis = true ;
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | atoi ( Info_ValueForKey ( cl . serverinfo , " allow_skybox " ) ) | | atoi ( Info_ValueForKey ( cl . serverinfo , " allow_skyboxes " ) ) )
2004-08-23 00:15:46 +00:00
cls . allow_skyboxes = true ;
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | atoi ( Info_ValueForKey ( cl . serverinfo , " mirrors " ) ) )
2004-08-23 00:15:46 +00:00
cls . allow_mirrors = true ;
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | atoi ( Info_ValueForKey ( cl . serverinfo , " allow_shaders " ) ) )
2004-08-23 00:15:46 +00:00
cls . allow_shaders = true ;
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | ! atoi ( Info_ValueForKey ( cl . serverinfo , " allow_luma " ) ) )
2004-08-23 00:15:46 +00:00
cls . allow_luma = false ;
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | atoi ( Info_ValueForKey ( cl . serverinfo , " allow_lmgamma " ) ) )
2004-08-23 00:15:46 +00:00
cls . allow_lightmapgamma = true ;
s = Info_ValueForKey ( cl . serverinfo , " allow_bump " ) ;
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | atoi ( s ) | | ! * s ) //admin doesn't care.
2004-08-23 00:15:46 +00:00
cls . allow_bump = true ;
# ifdef FISH
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | atoi ( Info_ValueForKey ( cl . serverinfo , " allow_fish " ) ) )
2004-08-23 00:15:46 +00:00
cls . allow_fish = true ;
# endif
s = Info_ValueForKey ( cl . serverinfo , " fbskins " ) ;
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | * s )
2004-08-23 00:15:46 +00:00
cls . allow_fbskins = atof ( s ) ;
else
2005-01-05 08:01:19 +00:00
cls . allow_fbskins = 1 ;
2004-08-23 00:15:46 +00:00
s = Info_ValueForKey ( cl . serverinfo , " *cheats " ) ;
2004-10-13 07:24:59 +00:00
if ( cls . demoplayback | | ! stricmp ( s , " on " ) )
2004-08-23 00:15:46 +00:00
cls . allow_cheats = true ;
s = Info_ValueForKey ( cl . serverinfo , " strict " ) ;
2004-10-13 07:24:59 +00:00
if ( ! cls . demoplayback & & * s & & strcmp ( s , " 0 " ) )
2004-08-23 00:15:46 +00:00
{
cls . allow_semicheats = false ;
cls . allow_cheats = false ;
}
cls . maxfps = atof ( Info_ValueForKey ( cl . serverinfo , " maxfps " ) ) ;
2005-04-16 16:21:27 +00:00
if ( cls . maxfps < 20 )
cls . maxfps = 72 ;
2004-08-23 00:15:46 +00:00
if ( ! atoi ( Info_ValueForKey ( cl . serverinfo , " deathmatch " ) ) )
cls . gamemode = GAME_COOP ;
else
cls . gamemode = GAME_DEATHMATCH ;
cls . z_ext = atoi ( Info_ValueForKey ( cl . serverinfo , " *z_ext " ) ) ;
// movement vars for prediction
cl . bunnyspeedcap = Q_atof ( Info_ValueForKey ( cl . serverinfo , " pm_bunnyspeedcap " ) ) ;
movevars . slidefix = ( Q_atof ( Info_ValueForKey ( cl . serverinfo , " pm_slidefix " ) ) ! = 0 ) ;
movevars . airstep = ( Q_atof ( Info_ValueForKey ( cl . serverinfo , " pm_airstep " ) ) ! = 0 ) ;
2005-01-13 16:29:20 +00:00
movevars . walljump = ( Q_atof ( Info_ValueForKey ( cl . serverinfo , " pm_walljump " ) ) ) ;
2004-08-23 00:15:46 +00:00
movevars . ktjump = Q_atof ( Info_ValueForKey ( cl . serverinfo , " pm_ktjump " ) ) ;
// Initialize cl.maxpitch & cl.minpitch
s = ( cls . z_ext & Z_EXT_PITCHLIMITS ) ? Info_ValueForKey ( cl . serverinfo , " maxpitch " ) : " " ;
cl . maxpitch = * s ? Q_atof ( s ) : 80.0f ;
s = ( cls . z_ext & Z_EXT_PITCHLIMITS ) ? Info_ValueForKey ( cl . serverinfo , " minpitch " ) : " " ;
cl . minpitch = * s ? Q_atof ( s ) : - 70.0f ;
allowed = atoi ( Info_ValueForKey ( cl . serverinfo , " allow " ) ) ;
if ( allowed & 1 )
cls . allow_watervis = true ;
if ( allowed & 2 )
cls . allow_rearview = true ;
if ( allowed & 4 )
cls . allow_skyboxes = true ;
if ( allowed & 8 )
cls . allow_mirrors = true ;
if ( allowed & 16 )
cls . allow_shaders = true ;
if ( allowed & 32 )
cls . allow_luma = true ;
if ( allowed & 64 )
cls . allow_bump = true ;
# ifdef FISH
if ( allowed & 128 )
cls . allow_fish = true ;
# endif
if ( allowed & 256 )
cls . allow_lightmapgamma = true ;
if ( allowed & 512 )
cls . allow_cheats = true ;
if ( cls . allow_semicheats )
cls . allow_anyparticles = true ;
else
cls . allow_anyparticles = false ;
Cvar_ForceCheatVars ( cls . allow_semicheats , cls . allow_cheats ) ;
}
/*
= = = = = = = = = = = = = = = = = =
CL_FullServerinfo_f
2005-03-10 03:55:18 +00:00
Sent by server just after the svc_serverdata
2004-08-23 00:15:46 +00:00
= = = = = = = = = = = = = = = = = =
*/
void CL_FullServerinfo_f ( void )
{
char * p ;
float v ;
2005-04-16 16:21:27 +00:00
if ( ! Cmd_FromGamecode ( ) )
2005-01-07 02:44:12 +00:00
{
Con_Printf ( " Hey! fullserverinfo is meant to come from the server! \n " ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( Cmd_Argc ( ) ! = 2 )
{
Con_TPrintf ( TLC_SYNTAX_FULLSERVERINFO ) ;
return ;
}
2005-03-07 08:55:30 +00:00
Q_strncpyz ( cl . serverinfo , Cmd_Argv ( 1 ) , sizeof ( cl . serverinfo ) ) ;
2004-08-23 00:15:46 +00:00
if ( ( p = Info_ValueForKey ( cl . serverinfo , " *version " ) ) & & * p ) {
v = Q_atof ( p ) ;
if ( v ) {
if ( ! server_version )
Con_TPrintf ( TLC_SERVER_VERSION , v ) ;
server_version = v ;
}
}
CL_CheckServerInfo ( ) ;
2005-03-10 03:55:18 +00:00
2005-03-20 02:57:11 +00:00
cl . gamespeed = atof ( Info_ValueForKey ( cl . serverinfo , " *gamespeed " ) ) / 100.f ;
if ( cl . gamespeed < 0.1 )
cl . gamespeed = 1 ;
cl . csqcdebug = atoi ( Info_ValueForKey ( cl . serverinfo , " *csqcdebug " ) ) ;
2005-03-10 03:55:18 +00:00
# ifdef CSQC_DAT
p = Info_ValueForKey ( cl . serverinfo , " *csprogs " ) ;
2005-05-19 02:53:03 +00:00
if ( * p | | cls . demoplayback ) //only allow csqc if the server says so, and the 'checksum' matches.
2005-03-10 03:55:18 +00:00
{
unsigned int chksum = strtoul ( p , NULL , 0 ) ;
if ( CSQC_Init ( chksum ) )
2005-03-23 22:14:08 +00:00
CL_SendClientCommand ( true , " enablecsqc " ) ;
2005-03-10 03:55:18 +00:00
}
# endif
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
CL_FullInfo_f
Allow clients to change userinfo
= = = = = = = = = = = = = = = = = =
*/
void CL_FullInfo_f ( void )
{
char key [ 512 ] ;
char value [ 512 ] ;
char * o ;
char * s ;
if ( Cmd_Argc ( ) ! = 2 )
{
Con_TPrintf ( TLC_SYNTAX_FULLINFO ) ;
return ;
}
s = Cmd_Argv ( 1 ) ;
if ( * s = = ' \\ ' )
s + + ;
while ( * s )
{
o = key ;
while ( * s & & * s ! = ' \\ ' )
* o + + = * s + + ;
* o = 0 ;
if ( ! * s )
{
Con_TPrintf ( TL_KEYHASNOVALUE ) ;
return ;
}
o = value ;
s + + ;
while ( * s & & * s ! = ' \\ ' )
* o + + = * s + + ;
* o = 0 ;
if ( * s )
s + + ;
if ( ! stricmp ( key , pmodel_name ) | | ! stricmp ( key , emodel_name ) )
continue ;
Info_SetValueForKey ( cls . userinfo , key , value , MAX_INFO_STRING ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
CL_SetInfo_f
Allow clients to change userinfo
= = = = = = = = = = = = = = = = = =
*/
void CL_SetInfo_f ( void )
{
cvar_t * var ;
if ( Cmd_Argc ( ) = = 1 )
{
Info_Print ( cls . userinfo ) ;
return ;
}
if ( Cmd_Argc ( ) ! = 3 )
{
Con_TPrintf ( TLC_SYNTAX_SETINFO ) ;
return ;
}
if ( ! stricmp ( Cmd_Argv ( 1 ) , pmodel_name ) | | ! strcmp ( Cmd_Argv ( 1 ) , emodel_name ) )
return ;
var = Cvar_FindVar ( Cmd_Argv ( 1 ) ) ;
if ( var & & ( var - > flags & CVAR_USERINFO ) )
{ //get the cvar code to set it. the server might have locked it.
Cvar_Set ( var , Cmd_Argv ( 2 ) ) ;
return ;
}
Info_SetValueForKey ( cls . userinfo , Cmd_Argv ( 1 ) , Cmd_Argv ( 2 ) , MAX_INFO_STRING ) ;
if ( cls . state > = ca_connected )
{
# ifdef Q2CLIENT
if ( cls . q2server )
2004-12-24 08:45:56 +00:00
cls . resendinfo = true ;
2004-08-23 00:15:46 +00:00
else
# endif
Cmd_ForwardToServer ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = =
CL_Packet_f
packet < destination > < contents >
Contents allows \ n escape character
= = = = = = = = = = = = = = = = = = = =
*/
void CL_Packet_f ( void )
{
char send [ 2048 ] ;
int i , l ;
char * in , * out ;
netadr_t adr ;
2004-12-15 19:54:09 +00:00
2004-08-23 00:15:46 +00:00
if ( Cmd_Argc ( ) ! = 3 )
{
Con_TPrintf ( TLC_PACKET_SYNTAX ) ;
return ;
}
if ( ! NET_StringToAdr ( Cmd_Argv ( 1 ) , & adr ) )
{
Con_TPrintf ( TLC_BADADDRESS ) ;
return ;
}
2005-04-16 16:21:27 +00:00
if ( Cmd_FromGamecode ( ) ) //some mvd servers stuffcmd a packet command which lets them know which ip the client is from.
2004-12-08 04:14:52 +00:00
{ //unfortunatly, 50% of servers are badly configured.
2004-09-14 21:39:18 +00:00
if ( adr . type = = NA_IP )
if ( adr . ip [ 0 ] = = 127 )
if ( adr . ip [ 1 ] = = 0 )
if ( adr . ip [ 2 ] = = 0 )
if ( adr . ip [ 3 ] = = 1 )
{
2005-02-28 07:16:19 +00:00
adr . ip [ 0 ] = cls . netchan . remote_address . ip [ 0 ] ;
adr . ip [ 1 ] = cls . netchan . remote_address . ip [ 1 ] ;
adr . ip [ 2 ] = cls . netchan . remote_address . ip [ 2 ] ;
adr . ip [ 3 ] = cls . netchan . remote_address . ip [ 3 ] ;
adr . port = cls . netchan . remote_address . port ;
2005-04-16 16:21:27 +00:00
Con_Printf ( " ^b^1Server is broken. Trying to send to server instead. \n " ) ;
2005-02-28 07:16:19 +00:00
2004-09-14 21:39:18 +00:00
}
2004-12-08 04:14:52 +00:00
2005-01-29 02:22:43 +00:00
Con_DPrintf ( " Sending realip packet \n " ) ;
2004-09-14 21:39:18 +00:00
}
2004-12-15 19:54:09 +00:00
cls . lastarbiatarypackettime = Sys_DoubleTime ( ) ; //prevent the packet command from causing a reconnect on badly configured mvdsv servers.
2004-09-14 21:39:18 +00:00
2004-08-23 00:15:46 +00:00
in = Cmd_Argv ( 2 ) ;
out = send + 4 ;
send [ 0 ] = send [ 1 ] = send [ 2 ] = send [ 3 ] = 0xff ;
l = strlen ( in ) ;
for ( i = 0 ; i < l ; i + + )
{
if ( in [ i ] = = ' \\ ' & & in [ i + 1 ] = = ' n ' )
{
* out + + = ' \n ' ;
i + + ;
}
else
* out + + = in [ i ] ;
}
* out = 0 ;
NET_SendPacket ( NS_CLIENT , out - send , send , adr ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
CL_NextDemo
Called to play the next demo in the demo loop
= = = = = = = = = = = = = = = = = = = = =
*/
void CL_NextDemo ( void )
{
char str [ 1024 ] ;
if ( cls . demonum = = - 1 )
return ; // don't play demos
if ( ! cls . demos [ cls . demonum ] [ 0 ] | | cls . demonum = = MAX_DEMOS )
{
cls . demonum = 0 ;
if ( ! cls . demos [ cls . demonum ] [ 0 ] )
{
// Con_Printf ("No demos listed with startdemos\n");
cls . demonum = - 1 ;
return ;
}
}
sprintf ( str , " playdemo %s \n " , cls . demos [ cls . demonum ] ) ;
Cbuf_InsertText ( str , RESTRICT_LOCAL ) ;
cls . demonum + + ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
DEMO LOOP CONTROL
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
CL_Startdemos_f
= = = = = = = = = = = = = = = = = =
*/
void CL_Startdemos_f ( void )
{
int i , c ;
c = Cmd_Argc ( ) - 1 ;
if ( c > MAX_DEMOS )
{
Con_Printf ( " Max %i demos in demoloop \n " , MAX_DEMOS ) ;
c = MAX_DEMOS ;
}
Con_Printf ( " %i demo(s) in loop \n " , c ) ;
for ( i = 1 ; i < c + 1 ; i + + )
Q_strncpyz ( cls . demos [ i - 1 ] , Cmd_Argv ( i ) , sizeof ( cls . demos [ 0 ] ) ) ;
2004-11-29 01:21:00 +00:00
if (
# ifndef CLIENTONLY
! sv . state & &
# endif
cls . demonum ! = - 1 & & cls . demoplayback = = DPB_NONE & & ! media_filmtype & & COM_CheckParm ( " -demos " ) )
2004-08-23 00:15:46 +00:00
{
cls . demonum = 0 ;
CL_NextDemo ( ) ;
}
else
cls . demonum = - 1 ;
}
/*
= = = = = = = = = = = = = = = = = =
CL_Demos_f
Return to looping demos
= = = = = = = = = = = = = = = = = =
*/
void CL_Demos_f ( void )
{
if ( cls . demonum = = - 1 )
cls . demonum = 1 ;
CL_Disconnect_f ( ) ;
CL_NextDemo ( ) ;
}
/*
= = = = = = = = = = = = = = = = = =
CL_Stopdemo_f
stop demo
= = = = = = = = = = = = = = = = = =
*/
void CL_Stopdemo_f ( void )
{
if ( cls . demoplayback = = DPB_NONE )
return ;
CL_StopPlayback ( ) ;
CL_Disconnect ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
CL_Changing_f
Just sent as a hint to the client that they should
drop to full console
= = = = = = = = = = = = = = = = =
*/
void CL_Changing_f ( void )
{
if ( cls . downloadqw ) // don't change when downloading
return ;
SCR_BeginLoadingPlaque ( ) ;
S_StopAllSounds ( true ) ;
cl . intermission = 0 ;
cls . state = ca_connected ; // not active anymore, but not disconnected
Con_TPrintf ( TLC_CHANGINGMAP ) ;
# ifdef NQPROT
cls . signon = 0 ;
# endif
}
/*
= = = = = = = = = = = = = = = = =
CL_Reconnect_f
The server is changing levels
= = = = = = = = = = = = = = = = =
*/
void CL_Reconnect_f ( void )
{
if ( cls . downloadqw ) // don't change when downloading
return ;
# ifdef NQPROT
if ( cls . netcon )
{
CL_Changing_f ( ) ;
return ;
}
# endif
S_StopAllSounds ( true ) ;
if ( cls . state = = ca_connected )
{
Con_TPrintf ( TLC_RECONNECTING ) ;
2005-03-23 22:14:08 +00:00
CL_SendClientCommand ( true , " new " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
if ( ! * cls . servername )
{
Con_TPrintf ( TLC_RECONNECT_NOSERVER ) ;
return ;
}
CL_Disconnect ( ) ;
CL_BeginServerReconnect ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
CL_ConnectionlessPacket
Responses to broadcasts , etc
= = = = = = = = = = = = = = = = =
*/
void CL_ConnectionlessPacket ( void )
{
char * s ;
int c ;
MSG_BeginReading ( ) ;
MSG_ReadLong ( ) ; // skip the -1
c = MSG_ReadByte ( ) ;
if ( cls . demoplayback = = DPB_NONE )
Con_TPrintf ( TL_ST_COLON , NET_AdrToString ( net_from ) ) ;
2004-12-24 08:45:56 +00:00
// Con_DPrintf ("%s", net_message.data + 4);
2004-08-23 00:15:46 +00:00
2004-12-24 08:45:56 +00:00
if ( c = = S2C_CHALLENGE )
{
2004-08-23 00:15:46 +00:00
unsigned long pext = 0 , huffcrc = 0 ;
Con_TPrintf ( TLC_S2C_CHALLENGE ) ;
s = MSG_ReadString ( ) ;
COM_Parse ( s ) ;
2004-12-24 08:45:56 +00:00
if ( ! strcmp ( com_token , " hallengeResponse " ) )
{
# ifdef Q3CLIENT
cls . q2server = 2 ;
cls . challenge = atoi ( s + 17 ) ;
CL_SendConnectPacket ( 0 , 0 /*, ...*/ ) ;
return ;
# else
Con_Printf ( " \n Unable to connect to Quake3 \n " ) ;
return ;
# endif
}
else if ( ! strcmp ( com_token , " hallenge " ) )
2004-08-23 00:15:46 +00:00
{
2004-11-20 01:12:02 +00:00
char * s2 ;
2004-12-24 08:45:56 +00:00
for ( s2 = s + 9 ; * s2 ; s2 + + )
2004-11-20 01:12:02 +00:00
{
2004-12-24 08:45:56 +00:00
if ( ( * s2 < ' 0 ' | | * s2 > ' 9 ' ) & & * s2 ! = ' - ' )
2004-11-20 01:12:02 +00:00
break ;
}
2004-12-24 08:45:56 +00:00
if ( * s2 )
2004-11-20 01:12:02 +00:00
{ //and if it's not, we're unlikly to be compatable with whatever it is that's talking at us.
# ifdef NQPROT
CL_ConnectToDarkPlaces ( s + 9 , net_from ) ;
# else
2004-12-24 08:45:56 +00:00
Con_Printf ( " \n Unable connect to DarkPlaces \n " ) ;
2004-11-20 01:12:02 +00:00
# endif
return ;
}
# ifdef Q2CLIENT
2004-08-23 00:15:46 +00:00
cls . q2server = true ;
2004-12-24 08:45:56 +00:00
# else
Con_Printf ( " \n Unable to connect to Quake2 \n " ) ;
2004-11-20 01:12:02 +00:00
# endif
2004-08-23 00:15:46 +00:00
s + = 9 ;
}
2004-12-24 08:45:56 +00:00
# ifdef Q3CLIENT
else if ( ! strcmp ( com_token , " onnectResponse " ) )
{
goto client_connect ;
}
# endif
2004-11-20 01:12:02 +00:00
# ifdef Q2CLIENT
2004-08-23 00:15:46 +00:00
else if ( ! strcmp ( com_token , " lient_connect " ) )
{
goto client_connect ;
}
else
cls . q2server = false ;
# endif
cls . challenge = atoi ( s ) ;
for ( ; ; )
{
c = MSG_ReadLong ( ) ;
if ( msg_badread )
break ;
if ( c = = PROTOCOL_VERSION_FTE )
pext = MSG_ReadLong ( ) ;
# ifdef HUFFNETWORK
else if ( c = = ( ( ' H ' < < 0 ) + ( ' U ' < < 8 ) + ( ' F ' < < 16 ) + ( ' F ' < < 24 ) ) )
huffcrc = MSG_ReadLong ( ) ;
# endif
//else if (c == PROTOCOL_VERSION_...)
else
MSG_ReadLong ( ) ;
}
CL_SendConnectPacket ( pext , huffcrc /*, ...*/ ) ;
return ;
}
# ifdef Q2CLIENT
if ( cls . q2server )
{
char * nl ;
msg_readcount - - ;
c = msg_readcount ;
s = MSG_ReadString ( ) ;
nl = strchr ( s , ' \n ' ) ;
if ( nl )
{
msg_readcount = c + nl - s + 1 ;
* nl = ' \0 ' ;
}
if ( ! strcmp ( s , " print " ) )
{
Con_TPrintf ( TLC_A2C_PRINT ) ;
s = MSG_ReadString ( ) ;
Con_Print ( s ) ;
return ;
}
else if ( ! strcmp ( s , " client_connect " ) )
{
goto client_connect ;
}
2004-12-24 08:45:56 +00:00
else if ( ! strcmp ( s , " disconnect " ) )
{
if ( NET_CompareAdr ( net_from , cls . netchan . remote_address ) )
{
Con_Printf ( " disconnect \n " ) ;
CL_Disconnect_f ( ) ;
return ;
}
else
{
Con_Printf ( " Ignoring random disconnect command \n " ) ;
return ;
}
}
2004-08-23 00:15:46 +00:00
else
{
Con_TPrintf ( TLC_Q2CONLESSPACKET_UNKNOWN , s ) ;
msg_readcount = c ;
c = MSG_ReadByte ( ) ;
}
}
# endif
2004-11-20 01:12:02 +00:00
# ifdef NQPROT
if ( c = = ' a ' )
{
s = MSG_ReadString ( ) ;
COM_Parse ( s ) ;
if ( ! strcmp ( com_token , " ccept " ) )
{
cls . netcon = Datagram_ConnectToDarkPlacesServer ( & net_from ) ;
SockadrToNetadr ( & cls . netcon - > addr , & net_from ) ;
Netchan_Setup ( cls . netcon - > socket , & cls . netchan , net_from , cls . qport ) ;
cls . netchan . qsocket = cls . netcon ;
Con_DPrintf ( " CL_EstablishConnection: connected to %s \n " , cls . servername ) ;
cls . netchan . qsocket = cls . netcon ;
cls . netchan . isnqprotocol = true ;
cls . demonum = - 1 ; // not in the demo loop now
cls . state = ca_connected ;
SCR_BeginLoadingPlaque ( ) ;
return ;
}
}
# endif
2004-12-24 08:45:56 +00:00
if ( c = = ' d ' ) //note - this conflicts with qw masters, our browser uses a different socket.
{
Con_Printf ( " Disconnect \n " ) ;
CL_Disconnect_f ( ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( c = = S2C_CONNECTION )
{
int compress ;
# ifdef Q2CLIENT
client_connect : //fixme: make function
# endif
Con_TPrintf ( TLC_GOTCONNECTION ) ;
if ( cls . state > = ca_connected )
{
if ( cls . demoplayback = = DPB_NONE )
Con_TPrintf ( TLC_DUPCONNECTION ) ;
return ;
}
compress = cls . netchan . compress ;
Netchan_Setup ( NS_CLIENT , & cls . netchan , net_from , cls . qport ) ;
cls . netchan . compress = compress ;
# ifdef NQPROT
cls . netchan . qsocket = cls . netcon ;
# endif
2005-04-16 16:21:27 +00:00
# ifdef Q3CLIENT
2005-03-12 23:40:42 +00:00
if ( cls . q2server < 2 )
2005-04-16 16:21:27 +00:00
# endif
2005-03-23 22:14:08 +00:00
CL_SendClientCommand ( true , " new " ) ;
2004-08-23 00:15:46 +00:00
cls . state = ca_connected ;
Con_TPrintf ( TLC_CONNECTED ) ;
allowremotecmd = false ; // localid required now for remote cmds
return ;
}
// remote command from gui front end
2004-12-25 02:06:27 +00:00
if ( c = = A2C_CLIENT_COMMAND ) //man I hate this.
2004-08-23 00:15:46 +00:00
{
char cmdtext [ 2048 ] ;
Con_TPrintf ( TLC_CONLESS_CONCMD ) ;
if ( net_from . type ! = net_local_ipadr . type
| | ( ( * ( unsigned * ) net_from . ip ! = * ( unsigned * ) net_local_ipadr . ip ) & & ( * ( unsigned * ) net_from . ip ! = htonl ( INADDR_LOOPBACK ) ) ) )
{
Con_TPrintf ( TLC_CMDFROMREMOTE ) ;
return ;
}
# ifdef _WIN32
ShowWindow ( mainwindow , SW_RESTORE ) ;
SetForegroundWindow ( mainwindow ) ;
# endif
s = MSG_ReadString ( ) ;
Q_strncpyz ( cmdtext , s , sizeof ( cmdtext ) ) ;
s = MSG_ReadString ( ) ;
while ( * s & & isspace ( * s ) )
s + + ;
while ( * s & & isspace ( s [ strlen ( s ) - 1 ] ) )
s [ strlen ( s ) - 1 ] = 0 ;
if ( ! allowremotecmd & & ( ! * localid . string | | strcmp ( localid . string , s ) ) ) {
if ( ! * localid . string ) {
Con_TPrintf ( TL_LINEBREAK_EQUALS ) ;
Con_TPrintf ( TLC_LOCALID_NOTSET ) ;
Con_TPrintf ( TL_LINEBREAK_EQUALS ) ;
return ;
}
Con_TPrintf ( TL_LINEBREAK_EQUALS ) ;
Con_TPrintf ( TLC_LOCALID_BAD ,
s , localid . string ) ;
Con_TPrintf ( TL_LINEBREAK_EQUALS ) ;
Cvar_Set ( & localid , " " ) ;
return ;
}
2004-12-25 02:06:27 +00:00
Cbuf_AddText ( cmdtext , RESTRICT_SERVER ) ;
2004-08-23 00:15:46 +00:00
allowremotecmd = false ;
return ;
}
// print command from somewhere
2004-12-24 08:45:56 +00:00
if ( c = = ' p ' )
{
if ( ! strncmp ( net_message . data + 4 , " print \n " , 6 ) )
{
Con_TPrintf ( TLC_A2C_PRINT ) ;
Con_Print ( net_message . data + 10 ) ;
return ;
}
}
2004-08-23 00:15:46 +00:00
if ( c = = A2C_PRINT )
{
Con_TPrintf ( TLC_A2C_PRINT ) ;
s = MSG_ReadString ( ) ;
Con_Print ( s ) ;
return ;
}
// ping from somewhere
if ( c = = A2A_PING )
{
char data [ 6 ] ;
Con_TPrintf ( TLC_A2A_PING ) ;
data [ 0 ] = 0xff ;
data [ 1 ] = 0xff ;
data [ 2 ] = 0xff ;
data [ 3 ] = 0xff ;
data [ 4 ] = A2A_ACK ;
data [ 5 ] = 0 ;
NET_SendPacket ( NS_CLIENT , 6 , & data , net_from ) ;
return ;
}
//happens in demos
if ( c = = svc_disconnect & & cls . demoplayback ! = DPB_NONE )
{
Host_EndGame ( " End of Demo " ) ;
return ;
}
Con_TPrintf ( TLC_CONLESSPACKET_UNKNOWN , c ) ;
}
/*
= = = = = = = = = = = = = = = = =
CL_ReadPackets
= = = = = = = = = = = = = = = = =
*/
void CL_ReadPackets ( void )
{
// while (NET_GetPacket ())
while ( CL_GetMessage ( ) )
{
# ifdef NQPROT
if ( cls . demoplayback = = DPB_NETQUAKE )
{
cls . netchan . last_received = realtime ;
CLNQ_ParseServerMessage ( ) ;
continue ;
}
# endif
# ifdef Q2CLIENT
if ( cls . demoplayback = = DPB_QUAKE2 )
{
MSG_BeginReading ( ) ;
cls . netchan . last_received = realtime ;
CLQ2_ParseServerMessage ( ) ;
continue ;
}
# endif
//
// remote command packet
//
if ( * ( int * ) net_message . data = = - 1 )
{
CL_ConnectionlessPacket ( ) ;
continue ;
}
if ( net_message . cursize < 8 & & cls . demoplayback ! = DPB_MVD ) //MVDs don't have the whole sequence header thing going on
{
Con_TPrintf ( TL_RUNTPACKET , NET_AdrToString ( net_from ) ) ;
continue ;
}
//
// packet from server
//
if ( ! cls . demoplayback & &
! NET_CompareAdr ( net_from , cls . netchan . remote_address ) )
{
Con_DPrintf ( " %s:sequenced packet without connection \n "
, NET_AdrToString ( net_from ) ) ;
continue ;
}
if ( cls . state = = ca_disconnected )
continue ; //ignore it. We arn't connected.
2004-12-24 08:45:56 +00:00
# ifdef Q3CLIENT
if ( cls . q2server = = 2 )
{
CLQ3_ParseServerMessage ( ) ;
continue ;
}
# endif
2004-08-23 00:15:46 +00:00
if ( cls . demoplayback = = DPB_MVD )
MSG_BeginReading ( ) ;
else if ( ! Netchan_Process ( & cls . netchan ) )
continue ; // wasn't accepted for some reason
# ifdef Q2CLIENT
if ( cls . q2server )
CLQ2_ParseServerMessage ( ) ;
else
# endif
CL_ParseServerMessage ( ) ;
// if (cls.demoplayback && cls.state >= ca_active && !CL_DemoBehind())
// return;
}
# ifdef NQPROT
while ( CLNQ_GetMessage ( ) > 0 )
{
//allow qw protocol over nq transports
if ( cls . netcon - > qwprotocol )
{
if ( * ( int * ) net_message . data = = - 1 )
{
CL_ConnectionlessPacket ( ) ;
continue ;
}
if ( net_message . cursize < 8 )
{
Con_TPrintf ( TL_RUNTPACKET , NET_AdrToString ( net_from ) ) ;
continue ;
}
if ( cls . state = = ca_disconnected )
continue ; //ignore it. We arn't connected.
memcpy ( & cls . netchan . remote_address , & net_from , sizeof ( net_from ) ) ;
if ( ! Netchan_Process ( & cls . netchan ) )
continue ; // wasn't accepted for some reason
// MSG_BeginReading();
// MSG_ReadLong();
// MSG_ReadLong();
# ifdef Q2CLIENT
2004-12-24 08:45:56 +00:00
if ( cls . q2server )
2004-08-23 00:15:46 +00:00
CLQ2_ParseServerMessage ( ) ;
else
# endif
CL_ParseServerMessage ( ) ;
}
else
{
cls . netchan . last_received = realtime ;
CLNQ_ParseServerMessage ( ) ;
}
}
# endif
//
// check timeout
//
if ( cls . state > = ca_connected
& & realtime - cls . netchan . last_received > cl_timeout . value )
{
Con_TPrintf ( TLC_SERVERTIMEOUT ) ;
CL_Disconnect ( ) ;
return ;
}
if ( cls . demoplayback = = DPB_MVD )
MVD_Interpolate ( ) ;
}
//=============================================================================
/*
= = = = = = = = = = = = = = = = = = = = =
CL_Download_f
= = = = = = = = = = = = = = = = = = = = =
*/
void CL_Download_f ( void )
{
2005-01-17 17:40:37 +00:00
// char *p, *q;
char * url ;
2004-08-23 00:15:46 +00:00
url = Cmd_Argv ( 1 ) ;
# ifdef WEBCLIENT
if ( ! strnicmp ( url , " http:// " , 7 ) | | ! strnicmp ( url , " ftp:// " , 6 ) )
{
2005-04-16 16:21:27 +00:00
if ( Cmd_IsInsecure ( ) )
2004-08-23 00:15:46 +00:00
return ;
HTTP_CL_Get ( url , Cmd_Argv ( 2 ) ) ; //"test.txt");
return ;
}
# endif
if ( ! strnicmp ( url , " qw:// " , 5 ) | | ! strnicmp ( url , " q2:// " , 5 ) )
{
url + = 5 ;
}
if ( cls . state = = ca_disconnected | | cls . demoplayback )
{
Con_TPrintf ( TLC_CONNECTFIRST ) ;
return ;
}
if ( cls . netchan . remote_address . type = = NA_LOOPBACK )
{
Con_TPrintf ( TLC_CONNECTFIRST ) ;
return ;
}
if ( Cmd_Argc ( ) ! = 2 )
{
Con_TPrintf ( TLC_SYNTAX_DOWNLOAD ) ;
return ;
}
2005-04-16 16:21:27 +00:00
if ( Cmd_IsInsecure ( ) ) //mark server specified downloads.
2004-08-23 00:15:46 +00:00
{
2004-11-26 06:05:18 +00:00
if ( ! strncmp ( url , " game " , 4 ) | | ! strcmp ( url , " progs.dat " ) | | ! strcmp ( url , " menu.dat " ) | | ! strcmp ( url , " csqc.dat " ) | | ! strcmp ( url , " qwprogs.dat " ) | | strstr ( url , " .. " ) | | strstr ( url , " .dll " ) | | strstr ( url , " .so " ) )
2004-08-23 00:15:46 +00:00
{ //yes, I know the user can use a different progs from the one that is specified. If you leave it blank there will be no problem. (server isn't allowed to stuff progs cvar)
Con_Printf ( " Ignoring stuffed download of \" %s \" due to possible security risk \n " , url ) ;
return ;
}
cls . downloadtype = dl_singlestuffed ;
CL_CheckOrDownloadFile ( url , false ) ;
return ;
}
else
{
cls . downloadtype = dl_single ;
}
2005-01-16 02:25:35 +00:00
CL_EnqueDownload ( url , true , false ) ;
/*
strcpy ( cls . downloadname , url ) ;
2004-08-23 00:15:46 +00:00
_snprintf ( cls . downloadname , sizeof ( cls . downloadname ) , " %s/%s " , com_gamedir , url ) ;
p = cls . downloadname ;
for ( ; ; )
{
if ( ( q = strchr ( p , ' / ' ) ) ! = NULL )
{
* q = 0 ;
Sys_mkdir ( cls . downloadname ) ;
* q = ' / ' ;
p = q + 1 ;
} else
break ;
}
2005-01-16 02:25:35 +00:00
COM_StripExtension ( cls . downloadname , cls . downloadtempname ) ;
COM_DefaultExtension ( cls . downloadtempname , " .tmp " ) ;
if ( cls . down
2004-09-20 23:25:38 +00:00
// cls.downloadqw = fopen (cls.downloadname, "wb");
2005-01-16 02:25:35 +00:00
cls . downloadmethod = DL_QWPENDING ;
2004-08-23 00:15:46 +00:00
2005-02-28 07:16:19 +00:00
CL_SendClientCommand ( " download %s \n " , url ) ; */
2004-08-23 00:15:46 +00:00
}
# ifdef _WINDOWS
# include <windows.h>
/*
= = = = = = = = = = = = = = = = =
CL_Minimize_f
= = = = = = = = = = = = = = = = =
*/
2004-12-09 23:31:48 +00:00
void CL_Windows_f ( void )
{
if ( ! mainwindow )
{
Con_Printf ( " Cannot comply \n " ) ;
return ;
}
2004-08-23 00:15:46 +00:00
// if (modestate == MS_WINDOWED)
// ShowWindow(mainwindow, SW_MINIMIZE);
// else
SendMessage ( mainwindow , WM_SYSKEYUP , VK_TAB , 1 | ( 0x0F < < 16 ) | ( 1 < < 29 ) ) ;
}
# endif
# ifndef CLIENTONLY
void CL_ServerInfo_f ( void )
{
if ( ! sv . state & & cls . state )
Cmd_ForwardToServer ( ) ;
else
{
SV_Serverinfo_f ( ) ; //allow it to be set... (whoops)
}
}
# endif
# ifdef WEBCLIENT
void CL_FTP_f ( void )
{
FTP_Client_Command ( Cmd_Args ( ) ) ;
}
2004-09-24 02:45:41 +00:00
# endif
# ifdef IRCCLIENT
2004-08-23 00:15:46 +00:00
void CL_IRC_f ( void )
{
IRC_Command ( Cmd_Args ( ) ) ;
}
# endif
2005-01-13 16:29:20 +00:00
void SCR_ShowPic_Script_f ( void ) ;
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = =
CL_Init
= = = = = = = = = = = = = = = = =
*/
void CL_Init ( void )
{
extern void CL_Say_f ( void ) ;
2004-11-17 17:56:27 +00:00
extern void CL_SayMe_f ( void ) ;
2004-11-13 17:27:34 +00:00
extern void CL_SayTeam_f ( void ) ;
2004-08-23 00:15:46 +00:00
extern cvar_t baseskin ;
extern cvar_t noskins ;
char st [ 80 ] ;
cls . state = ca_disconnected ;
# ifdef VERSION3PART
sprintf ( st , " %s %4.3f-%04d " , DISTRIBUTION , VERSION , build_number ( ) ) ;
# else
sprintf ( st , " %s %4.2f-%04d " , DISTRIBUTION , VERSION , build_number ( ) ) ;
# endif
sprintf ( st , " %s " , DISTRIBUTION ) ;
Info_SetValueForStarKey ( cls . userinfo , " *ver " , st , MAX_INFO_STRING ) ;
InitValidation ( ) ;
CL_InitInput ( ) ;
CL_InitTEnts ( ) ;
CL_InitPrediction ( ) ;
CL_InitCam ( ) ;
PM_Init ( ) ;
TP_Init ( ) ;
//
// register our commands
//
2005-01-23 17:49:42 +00:00
CLSCR_Init ( ) ;
2005-03-20 02:57:11 +00:00
# ifdef CSQC_DAT
CSQC_RegisterCvarsAndThings ( ) ;
# endif
2004-08-23 00:15:46 +00:00
Cvar_Register ( & host_speeds , cl_controlgroup ) ;
Cvar_Register ( & developer , cl_controlgroup ) ;
2004-09-22 15:25:58 +00:00
Cvar_Register ( & cfg_save_name , cl_controlgroup ) ;
2004-12-24 08:45:56 +00:00
Cvar_Register ( & cl_demospeed , " Demo playback " ) ;
2004-08-23 00:15:46 +00:00
Cvar_Register ( & cl_warncmd , " Warnings " ) ;
Cvar_Register ( & cl_upspeed , cl_inputgroup ) ;
Cvar_Register ( & cl_forwardspeed , cl_inputgroup ) ;
Cvar_Register ( & cl_backspeed , cl_inputgroup ) ;
Cvar_Register ( & cl_sidespeed , cl_inputgroup ) ;
Cvar_Register ( & cl_movespeedkey , cl_inputgroup ) ;
Cvar_Register ( & cl_yawspeed , cl_inputgroup ) ;
Cvar_Register ( & cl_pitchspeed , cl_inputgroup ) ;
Cvar_Register ( & cl_anglespeedkey , cl_inputgroup ) ;
Cvar_Register ( & cl_shownet , cl_screengroup ) ;
Cvar_Register ( & cl_sbar , cl_screengroup ) ;
Cvar_Register ( & cl_hudswap , cl_screengroup ) ;
Cvar_Register ( & cl_maxfps , cl_screengroup ) ;
Cvar_Register ( & cl_timeout , cl_controlgroup ) ;
Cvar_Register ( & lookspring , cl_inputgroup ) ;
Cvar_Register ( & lookstrafe , cl_inputgroup ) ;
Cvar_Register ( & sensitivity , cl_inputgroup ) ;
Cvar_Register ( & m_pitch , cl_inputgroup ) ;
Cvar_Register ( & m_yaw , cl_inputgroup ) ;
Cvar_Register ( & m_forward , cl_inputgroup ) ;
Cvar_Register ( & m_side , cl_inputgroup ) ;
Cvar_Register ( & rcon_password , cl_controlgroup ) ;
Cvar_Register ( & rcon_address , cl_controlgroup ) ;
Cvar_Register ( & entlatency , cl_predictiongroup ) ;
Cvar_Register ( & cl_predict_players2 , cl_predictiongroup ) ;
Cvar_Register ( & cl_predict_players , cl_predictiongroup ) ;
Cvar_Register ( & cl_solid_players , cl_predictiongroup ) ;
Cvar_Register ( & localid , cl_controlgroup ) ;
2005-01-13 16:29:20 +00:00
Cvar_Register ( & cl_muzzleflash , cl_controlgroup ) ;
2004-08-23 00:15:46 +00:00
Cvar_Register ( & baseskin , " Teamplay " ) ;
Cvar_Register ( & noskins , " Teamplay " ) ;
Cvar_Register ( & cl_item_bobbing , " Item effects " ) ;
2005-01-13 16:29:20 +00:00
Cvar_Register ( & cl_staticsounds , " Item effects " ) ;
2005-01-17 17:40:37 +00:00
Cvar_Register ( & r_rocketlight , " Item effects " ) ;
Cvar_Register ( & r_lightflicker , " Item effects " ) ;
Cvar_Register ( & cl_r2g , " Item effects " ) ;
Cvar_Register ( & r_powerupglow , " Item effects " ) ;
2005-04-26 16:04:12 +00:00
Cvar_Register ( & v_powerupshell , " Item effects " ) ;
2005-01-17 17:40:37 +00:00
2005-01-18 20:15:20 +00:00
Cvar_Register ( & cl_gibfilter , " Item effects " ) ;
Cvar_Register ( & cl_deadbodyfilter , " Item effects " ) ;
2005-04-26 16:04:12 +00:00
Cvar_Register ( & cl_nolerp , " Item effects " ) ;
2004-08-23 00:15:46 +00:00
//
// info mirrors
//
Cvar_Register ( & name , cl_controlgroup ) ;
Cvar_Register ( & password , cl_controlgroup ) ;
Cvar_Register ( & spectator , cl_controlgroup ) ;
Cvar_Register ( & skin , cl_controlgroup ) ;
2004-12-24 08:45:56 +00:00
Cvar_Register ( & model , cl_controlgroup ) ;
2004-08-23 00:15:46 +00:00
Cvar_Register ( & team , cl_controlgroup ) ;
Cvar_Register ( & topcolor , cl_controlgroup ) ;
Cvar_Register ( & bottomcolor , cl_controlgroup ) ;
Cvar_Register ( & rate , cl_controlgroup ) ;
2005-01-16 02:25:35 +00:00
Cvar_Register ( & drate , cl_controlgroup ) ;
2004-08-23 00:15:46 +00:00
Cvar_Register ( & msg , cl_controlgroup ) ;
Cvar_Register ( & noaim , cl_controlgroup ) ;
2004-09-30 22:42:34 +00:00
Cvar_Register ( & cl_nofake , cl_controlgroup ) ;
Cvar_Register ( & cl_chatsound , cl_controlgroup ) ;
2004-08-23 00:15:46 +00:00
Cvar_Register ( & requiredownloads , cl_controlgroup ) ;
Cvar_Register ( & cl_standardchat , cl_controlgroup ) ;
Cvar_Register ( & cl_nopext , cl_controlgroup ) ;
Cvar_Register ( & cl_splitscreen , cl_controlgroup ) ;
Cvar_Register ( & host_mapname , " Scripting " ) ;
# ifdef IRCCLIENT
Cmd_AddCommand ( " irc " , CL_IRC_f ) ;
# endif
# ifdef WEBCLIENT
Cmd_AddCommand ( " ftp " , CL_FTP_f ) ;
# endif
Cmd_AddCommand ( " version " , CL_Version_f ) ;
Cmd_AddCommand ( " changing " , CL_Changing_f ) ;
Cmd_AddCommand ( " disconnect " , CL_Disconnect_f ) ;
Cmd_AddCommand ( " record " , CL_Record_f ) ;
Cmd_AddCommand ( " rerecord " , CL_ReRecord_f ) ;
Cmd_AddCommand ( " stop " , CL_Stop_f ) ;
Cmd_AddCommand ( " playdemo " , CL_PlayDemo_f ) ;
Cmd_AddCommand ( " timedemo " , CL_TimeDemo_f ) ;
2005-01-13 16:29:20 +00:00
Cmd_AddCommand ( " showpic " , SCR_ShowPic_Script_f ) ;
2004-08-23 00:15:46 +00:00
Cmd_AddCommand ( " startdemos " , CL_Startdemos_f ) ;
Cmd_AddCommand ( " demos " , CL_Demos_f ) ;
Cmd_AddCommand ( " stopdemo " , CL_Stopdemo_f ) ;
Cmd_AddCommand ( " skins " , Skin_Skins_f ) ;
Cmd_AddCommand ( " allskins " , Skin_AllSkins_f ) ;
Cmd_AddCommand ( " quit " , CL_Quit_f ) ;
Cmd_AddCommand ( " connect " , CL_Connect_f ) ;
# ifdef NQPROT
Cmd_AddCommand ( " nqconnect " , CLNQ_Connect_f ) ;
# endif
Cmd_AddCommand ( " reconnect " , CL_Reconnect_f ) ;
2005-01-13 23:33:00 +00:00
Cmd_AddCommand ( " join " , CL_Join_f ) ;
Cmd_AddCommand ( " observe " , CL_Observe_f ) ;
2004-08-23 00:15:46 +00:00
Cmd_AddCommand ( " rcon " , CL_Rcon_f ) ;
Cmd_AddCommand ( " packet " , CL_Packet_f ) ;
Cmd_AddCommand ( " user " , CL_User_f ) ;
Cmd_AddCommand ( " users " , CL_Users_f ) ;
Cmd_AddCommand ( " setinfo " , CL_SetInfo_f ) ;
Cmd_AddCommand ( " fullinfo " , CL_FullInfo_f ) ;
Cmd_AddCommand ( " fullserverinfo " , CL_FullServerinfo_f ) ;
Cmd_AddCommand ( " color " , CL_Color_f ) ;
Cmd_AddCommand ( " download " , CL_Download_f ) ;
Cmd_AddCommand ( " nextul " , CL_NextUpload ) ;
Cmd_AddCommand ( " stopul " , CL_StopUpload ) ;
//
// forward to server commands
//
Cmd_AddCommand ( " god " , NULL ) ; //cheats
Cmd_AddCommand ( " give " , NULL ) ;
Cmd_AddCommand ( " noclip " , NULL ) ;
Cmd_AddCommand ( " fly " , NULL ) ;
Cmd_AddCommand ( " setpos " , NULL ) ;
Cmd_AddCommand ( " topten " , NULL ) ;
Cmd_AddCommand ( " kill " , NULL ) ;
Cmd_AddCommand ( " pause " , NULL ) ;
Cmd_AddCommand ( " say " , CL_Say_f ) ;
2004-11-17 17:56:27 +00:00
Cmd_AddCommand ( " me " , CL_SayMe_f ) ;
2004-08-23 00:15:46 +00:00
Cmd_AddCommand ( " sayone " , CL_Say_f ) ;
2004-11-13 17:27:34 +00:00
Cmd_AddCommand ( " say_team " , CL_SayTeam_f ) ;
2004-08-23 00:15:46 +00:00
# ifdef CLIENTONLY
Cmd_AddCommand ( " serverinfo " , NULL ) ;
# else
Cmd_AddCommand ( " serverinfo " , CL_ServerInfo_f ) ;
# endif
//
// Windows commands
//
# ifdef _WINDOWS
Cmd_AddCommand ( " windows " , CL_Windows_f ) ;
# endif
2005-04-26 16:04:12 +00:00
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = =
Host_EndGame
Call this to drop to a console without exiting the qwcl
= = = = = = = = = = = = = = = =
*/
void VARGS Host_EndGame ( char * message , . . . )
{
va_list argptr ;
char string [ 1024 ] ;
SCR_EndLoadingPlaque ( ) ;
va_start ( argptr , message ) ;
_vsnprintf ( string , sizeof ( string ) - 1 , message , argptr ) ;
va_end ( argptr ) ;
Con_TPrintf ( TL_NL ) ;
Con_TPrintf ( TL_LINEBREAK_EQUALS ) ;
Con_TPrintf ( TLC_CLIENTCON_ERROR_ENDGAME , string ) ;
Con_TPrintf ( TL_LINEBREAK_EQUALS ) ;
Con_TPrintf ( TL_NL ) ;
SCR_EndLoadingPlaque ( ) ;
CL_Disconnect ( ) ;
Cvar_Set ( & cl_shownet , " 0 " ) ;
longjmp ( host_abort , 1 ) ;
}
/*
= = = = = = = = = = = = = = = =
Host_Error
This shuts down the client and exits qwcl
= = = = = = = = = = = = = = = =
*/
void VARGS Host_Error ( char * error , . . . )
{
va_list argptr ;
char string [ 1024 ] ;
static qboolean inerror = false ;
if ( inerror )
Sys_Error ( " Host_Error: recursively entered " ) ;
inerror = true ;
va_start ( argptr , error ) ;
_vsnprintf ( string , sizeof ( string ) - 1 , error , argptr ) ;
va_end ( argptr ) ;
Con_TPrintf ( TLC_HOSTFATALERROR , string ) ;
CL_Disconnect ( ) ;
cls . demonum = - 1 ;
inerror = false ;
// FIXME
Sys_Error ( " Host_Error: %s \n " , string ) ;
}
/*
= = = = = = = = = = = = = = =
Host_WriteConfiguration
Writes key bindings and archived cvars to config . cfg
= = = = = = = = = = = = = = =
*/
void Host_WriteConfiguration ( void )
{
FILE * f ;
if ( host_initialized & & cfg_save_name . string & & * cfg_save_name . string )
{
if ( strchr ( cfg_save_name . string , ' . ' ) )
{
Con_TPrintf ( TLC_CONFIGCFG_WRITEFAILED ) ;
return ;
}
f = fopen ( va ( " %s/%s.cfg " , com_gamedir , cfg_save_name . string ) , " w " ) ;
if ( ! f )
{
Con_TPrintf ( TLC_CONFIGCFG_WRITEFAILED ) ;
return ;
}
Key_WriteBindings ( f ) ;
Cvar_WriteVariables ( f , false ) ;
fclose ( f ) ;
}
}
//============================================================================
#if 0
/*
= = = = = = = = = = = = = = = = = =
Host_SimulationTime
This determines if enough time has passed to run a simulation frame
= = = = = = = = = = = = = = = = = =
*/
qboolean Host_SimulationTime ( float time )
{
float fps ;
if ( oldrealtime > realtime )
oldrealtime = 0 ;
if ( cl_maxfps . value )
fps = max ( 30.0 , min ( cl_maxfps . value , 72.0 ) ) ;
else
fps = max ( 30.0 , min ( rate . value / 80.0 , 72.0 ) ) ;
if ( ! cls . timedemo & & ( realtime + time ) - oldrealtime < 1.0 / fps )
return false ; // framerate is too high
return true ;
}
# endif
/*
= = = = = = = = = = = = = = = = = =
Host_Frame
Runs all active servers
= = = = = = = = = = = = = = = = = =
*/
# if defined(WINAVI) && !defined(NOMEDIA)
extern float recordavi_frametime ;
extern qboolean recordingdemo ;
# endif
2005-02-28 07:16:19 +00:00
extern cvar_t cl_netfps ;
2004-08-23 00:15:46 +00:00
int nopacketcount ;
void SNDDMA_SetUnderWater ( qboolean underwater ) ;
2005-04-16 16:21:27 +00:00
float CL_FilterTime ( double time , float wantfps ) ;
2004-08-23 00:15:46 +00:00
void Host_Frame ( float time )
{
static double time1 = 0 ;
static double time2 = 0 ;
static double time3 = 0 ;
int pass1 , pass2 , pass3 ;
// float fps;
2005-03-20 02:57:11 +00:00
float realframetime ;
2005-04-16 16:21:27 +00:00
static float spare ;
2004-12-15 19:54:09 +00:00
RSpeedLocals ( ) ;
2004-08-23 00:15:46 +00:00
if ( setjmp ( host_abort ) )
return ; // something bad happened, or the server disconnected
2005-03-20 02:57:11 +00:00
realframetime = time ;
2004-08-23 00:15:46 +00:00
# if defined(WINAVI) && !defined(NOMEDIA)
2005-02-28 07:16:19 +00:00
if ( cls . demoplayback & & recordingdemo & & recordavi_frametime > 0.01 )
2004-08-23 00:15:46 +00:00
time = recordavi_frametime ;
# endif
2004-12-24 08:45:56 +00:00
if ( cls . demoplayback & & cl_demospeed . value > 0 )
time * = cl_demospeed . value ;
2004-08-23 00:15:46 +00:00
# ifndef CLIENTONLY
2004-12-15 19:54:09 +00:00
RSpeedRemark ( ) ;
2004-08-23 00:15:46 +00:00
SV_Frame ( time ) ;
2004-12-15 19:54:09 +00:00
RSpeedEnd ( RSPEED_SERVER ) ;
2004-08-23 00:15:46 +00:00
# endif
2005-03-20 02:57:11 +00:00
if ( cl . gamespeed < 0.1 )
cl . gamespeed = 1 ;
time * = cl . gamespeed ;
2004-08-23 00:15:46 +00:00
# ifdef WEBCLIENT
FTP_ClientThink ( ) ;
HTTP_CL_Think ( ) ;
# endif
# ifdef IRCCLIENT
IRC_Frame ( ) ;
# endif
2004-09-30 22:42:34 +00:00
# ifdef PLUGINS
2004-09-24 02:45:41 +00:00
Plug_Tick ( ) ;
2004-09-30 22:42:34 +00:00
# endif
2004-09-24 02:45:41 +00:00
2004-08-23 00:15:46 +00:00
// decide the simulation time
2005-03-22 02:08:01 +00:00
realtime + = realframetime ;
2004-08-23 00:15:46 +00:00
if ( oldrealtime > realtime )
oldrealtime = 0 ;
2004-10-03 10:16:15 +00:00
if ( cl . paused )
cl . gametimemark + = time ;
2004-08-23 00:15:46 +00:00
# ifdef VOICECHAT
CLVC_Poll ( ) ;
# endif
/*
if ( cl_maxfps . value )
fps = cl_maxfps . value ; //max(30.0, min(cl_maxfps.value, 72.0));
else
fps = max ( 30.0 , min ( rate . value / 80.0 , 72.0 ) ) ;
if ( ! cls . timedemo & & realtime - oldrealtime < 1.0 / fps )
return ; // framerate is too high
*/
2004-12-29 03:24:21 +00:00
Mod_Think ( ) ; //think even on idle (which means small walls and a fast cpu can get more surfaces done.
2005-02-28 07:16:19 +00:00
if ( cl_maxfps . value > 0 & & cl_netfps . value > 0 )
{ //limit the fps freely, and expect the netfps to cope.
if ( ( realtime - oldrealtime ) < 1 / cl_maxfps . value )
return ;
}
else
{
2005-04-16 16:21:27 +00:00
realtime + = spare / 1000 ; //don't use it all!
spare = CL_FilterTime ( ( realtime - oldrealtime ) * 1000 , cl_maxfps . value > 0 ? cl_maxfps . value : cl_netfps . value ) ;
if ( ! spare )
2005-02-28 07:16:19 +00:00
return ;
2005-04-16 16:21:27 +00:00
if ( spare < 0 | | cls . state < ca_onserver )
spare = 0 ; //uncapped.
if ( spare > 10 )
spare = 10 ;
realtime - = spare / 1000 ; //don't use it all!
2005-02-28 07:16:19 +00:00
}
2004-08-23 00:15:46 +00:00
2005-03-22 02:08:01 +00:00
host_frametime = ( realtime - oldrealtime ) * cl . gamespeed ;
2004-08-23 00:15:46 +00:00
oldrealtime = realtime ;
2005-04-16 16:21:27 +00:00
# if defined(NQPROT) || defined(Q2CLIENT)
# if defined(NQPROT) && defined(Q2CLIENT)
if ( cls . q2server | | cls . demoplayback = = DPB_NETQUAKE )
# elif defined(NQPROT)
if ( cls . demoplayback = = DPB_NETQUAKE )
# elif defined(Q2CLIENT)
if ( cls . q2server )
# endif
cl . time + = host_frametime ;
# endif
2004-08-23 00:15:46 +00:00
// if (host_frametime > 0.2)
// host_frametime = 0.2;
// get new key events
Sys_SendKeyEvents ( ) ;
// allow mice or other external controllers to add commands
IN_Commands ( ) ;
// process console commands
Cbuf_Execute ( ) ;
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-23 00:15:46 +00:00
if ( isDedicated ) //someone changed it.
return ;
2004-11-29 01:21:00 +00:00
# endif
2004-08-23 00:15:46 +00:00
2004-12-29 03:24:21 +00:00
cls . framecount + + ;
2005-05-08 05:56:03 +00:00
RSpeedRemark ( ) ;
2004-08-23 00:15:46 +00:00
# ifdef NQPROT
NET_Poll ( ) ;
# endif
2004-12-29 03:24:21 +00:00
2005-03-12 23:40:42 +00:00
CL_UseIndepPhysics ( ! ! cl_indepphysics . value ) ;
2005-02-28 07:16:19 +00:00
CL_AllowIndependantSendCmd ( false ) ;
2004-08-23 00:15:46 +00:00
if ( cls . downloadtype = = dl_none & & ! * cls . downloadname & & cl . downloadlist )
2005-02-28 07:16:19 +00:00
CL_RequestNextDownload ( ) ;
2004-08-23 00:15:46 +00:00
// fetch results from server
CL_ReadPackets ( ) ;
2005-02-28 07:16:19 +00:00
CL_AllowIndependantSendCmd ( true ) ;
2004-08-23 00:15:46 +00:00
// send intentions now
// resend a connection request if necessary
if ( cls . state = = ca_disconnected )
{
IN_Move ( NULL , 0 ) ;
CL_CheckForResend ( ) ;
}
else
{
2005-03-12 23:40:42 +00:00
extern qboolean runningindepphys ;
if ( ! runningindepphys )
2005-03-22 02:08:01 +00:00
CL_SendCmd ( host_frametime / cl . gamespeed ) ;
2004-08-23 00:15:46 +00:00
2005-02-12 18:56:04 +00:00
if ( cls . state = = ca_onserver & & cl . validsequence & & cl . worldmodel )
{ // first update is the final signon stage
cls . state = ca_active ;
if ( VID_SetWindowCaption )
VID_SetWindowCaption ( va ( " FTE QuakeWorld: %s " , cls . servername ) ) ;
2004-08-23 00:15:46 +00:00
2005-02-12 18:56:04 +00:00
SCR_EndLoadingPlaque ( ) ;
2004-08-23 00:15:46 +00:00
}
}
2005-05-08 05:56:03 +00:00
TP_CheckVars ( ) ;
2005-04-16 16:21:27 +00:00
RSpeedEnd ( RSPEED_PROTOCOL ) ;
2004-12-15 19:54:09 +00:00
2004-08-23 00:15:46 +00:00
// update video
if ( host_speeds . value )
time1 = Sys_DoubleTime ( ) ;
if ( SCR_UpdateScreen )
{
extern mleaf_t * r_viewleaf ;
2005-04-16 16:21:27 +00:00
extern cvar_t scr_chatmodecvar ;
if ( scr_chatmodecvar . value & & ! cl . intermission )
scr_chatmode = ( cl . spectator & & cl . splitclients < 2 & & cls . state = = ca_active ) ? 2 : 1 ;
else
scr_chatmode = 0 ;
2004-08-23 00:15:46 +00:00
SCR_UpdateScreen ( ) ;
if ( cls . state > = ca_active & & r_viewleaf )
SNDDMA_SetUnderWater ( r_viewleaf - > contents < = Q1CONTENTS_WATER ) ;
else
SNDDMA_SetUnderWater ( false ) ;
}
if ( host_speeds . value )
time2 = Sys_DoubleTime ( ) ;
// update audio
if ( cls . state = = ca_active )
{
S_Update ( r_origin , vpn , vright , vup ) ;
}
else
S_Update ( vec3_origin , vec3_origin , vec3_origin , vec3_origin ) ;
CDAudio_Update ( ) ;
if ( host_speeds . value )
{
pass1 = ( time1 - time3 ) * 1000 ;
time3 = Sys_DoubleTime ( ) ;
pass2 = ( time2 - time1 ) * 1000 ;
pass3 = ( time3 - time2 ) * 1000 ;
Con_TPrintf ( TLC_HOSTSPEEDSOUTPUT ,
pass1 + pass2 + pass3 , pass1 , pass2 , pass3 ) ;
}
host_framecount + + ;
fps_count + + ;
IN_Commands ( ) ;
// process console commands
Cbuf_Execute ( ) ;
# ifdef NQPROT
NET_Poll ( ) ;
# endif
if ( cls . downloadtype = = dl_none & & ! * cls . downloadname & & cl . downloadlist )
{
CL_RequestNextDownload ( ) ;
}
}
static void simple_crypt ( char * buf , int len )
{
while ( len - - )
* buf + + ^ = 0xff ;
}
void Host_FixupModelNames ( void )
{
simple_crypt ( emodel_name , sizeof ( emodel_name ) - 1 ) ;
simple_crypt ( pmodel_name , sizeof ( pmodel_name ) - 1 ) ;
simple_crypt ( prespawn_name , sizeof ( prespawn_name ) - 1 ) ;
simple_crypt ( modellist_name , sizeof ( modellist_name ) - 1 ) ;
simple_crypt ( soundlist_name , sizeof ( soundlist_name ) - 1 ) ;
}
//============================================================================
/*
= = = = = = = = = = = = = = = = = = = =
Host_Init
= = = = = = = = = = = = = = = = = = = =
*/
void Host_Init ( quakeparms_t * parms )
{
2005-02-06 02:47:36 +00:00
int i ;
2005-01-05 08:01:19 +00:00
int qrc , hrc , def ;
2004-08-23 00:15:46 +00:00
extern cvar_t vid_renderer ;
COM_InitArgv ( parms - > argc , parms - > argv ) ;
2004-11-23 01:10:10 +00:00
if ( setjmp ( host_abort ) )
Sys_Error ( " Host_Init: An error occured. Try the -condebug commandline parameter \n " ) ;
2004-08-23 00:15:46 +00:00
Sys_mkdir ( " qw " ) ;
if ( COM_CheckParm ( " -minmemory " ) )
parms - > memsize = MINIMUM_MEMORY ;
host_parms = * parms ;
if ( parms - > memsize < MINIMUM_MEMORY )
Sys_Error ( " Only %4.1f megs of memory reported, can't execute game " , parms - > memsize / ( float ) 0x100000 ) ;
Memory_Init ( parms - > membase , parms - > memsize ) ;
2005-01-07 02:44:12 +00:00
COM_ParsePlusSets ( ) ;
2004-08-23 00:15:46 +00:00
Cbuf_Init ( ) ;
Cmd_Init ( ) ;
V_Init ( ) ;
COM_Init ( ) ;
# ifdef Q2BSPS
CM_Init ( ) ;
# endif
Host_FixupModelNames ( ) ;
NET_Init ( ) ;
NET_InitClient ( ) ;
Netchan_Init ( ) ;
Renderer_Init ( ) ;
// W_LoadWadFile ("gfx.wad");
Key_Init ( ) ;
Con_Init ( ) ;
M_Init ( ) ;
2005-04-18 17:12:18 +00:00
# ifndef _WIN32
2004-08-23 00:15:46 +00:00
IN_Init ( ) ;
CDAudio_Init ( ) ;
// VID_Init (host_basepal);
// Draw_Init ();
// SCR_Init ();
// R_Init ();
S_Init ( ) ;
cls . state = ca_disconnected ;
Sbar_Init ( ) ;
CL_Init ( ) ;
# else
S_Init ( ) ;
cls . state = ca_disconnected ;
CDAudio_Init ( ) ;
Sbar_Init ( ) ;
CL_Init ( ) ;
IN_Init ( ) ;
# endif
TranslateInit ( ) ;
# ifndef CLIENTONLY
SV_Init ( parms ) ;
# endif
# ifdef TEXTEDITOR
Editor_Init ( ) ;
# endif
2005-01-15 17:37:11 +00:00
# ifdef PLUGINS
Plug_Init ( ) ;
# endif
2004-08-23 00:15:46 +00:00
// Con_Printf ("Exe: "__TIME__" "__DATE__"\n");
Con_TPrintf ( TL_HEAPSIZE , parms - > memsize / ( 1024 * 1024.0 ) ) ;
2005-04-26 16:04:12 +00:00
Cbuf_AddText ( " cl_warncmd 0 \n " , RESTRICT_LOCAL ) ;
2004-08-23 00:15:46 +00:00
Cbuf_AddText ( " +mlook \n " , RESTRICT_LOCAL ) ; //fixme: this is bulky, only exec one of these.
2005-01-05 08:01:19 +00:00
2005-02-06 02:47:36 +00:00
//who should we imitate?
qrc = COM_FDepthFile ( " quake.rc " , true ) ; //q1
hrc = COM_FDepthFile ( " hexen.rc " , true ) ; //h2
def = COM_FDepthFile ( " default.cfg " , true ) ; //q2/q3
2005-01-05 08:01:19 +00:00
2005-01-07 02:44:12 +00:00
if ( qrc > = def & & qrc > = hrc & & qrc ! = 0x7fffffff )
Cbuf_AddText ( " exec quake.rc \n " , RESTRICT_LOCAL ) ;
else if ( hrc > = def & & hrc ! = 0x7fffffff )
Cbuf_AddText ( " exec hexen.rc \n " , RESTRICT_LOCAL ) ;
else
2005-01-05 08:01:19 +00:00
{ //they didn't give us an rc file!
Cbuf_AddText ( " exec default.cfg \n " , RESTRICT_LOCAL ) ;
Cbuf_AddText ( " exec config.cfg \n " , RESTRICT_LOCAL ) ;
Cbuf_AddText ( " exec autoexec.cfg \n " , RESTRICT_LOCAL ) ;
}
2004-08-23 00:15:46 +00:00
Cbuf_AddText ( " exec fte.cfg \n " , RESTRICT_LOCAL ) ;
2005-01-05 08:01:19 +00:00
Cbuf_AddText ( " cl_warncmd 1 \n " , RESTRICT_LOCAL ) ; //and then it's allowed to start moaning.
2004-08-23 00:15:46 +00:00
Hunk_AllocName ( 0 , " -HOST_HUNKLEVEL- " ) ;
host_hunklevel = Hunk_LowMark ( ) ;
2005-03-20 02:57:11 +00:00
2004-11-23 01:10:10 +00:00
R_SetRenderer ( 0 ) ; //set the renderer stuff to 'none'...
2004-08-23 00:15:46 +00:00
host_initialized = true ;
2005-01-07 02:44:12 +00:00
Cmd_StuffCmds ( ) ;
2005-03-20 02:57:11 +00:00
2005-01-07 02:44:12 +00:00
Cbuf_Execute ( ) ; //if the server initialisation causes a problem, give it a place to abort to
2005-03-20 02:57:11 +00:00
2005-02-06 02:47:36 +00:00
//assuming they didn't use any waits in thier config (fools)
//the configs should be fully loaded.
//so convert the backwards compable commandline parameters in cvar sets.
if ( COM_CheckParm ( " -window " ) | | COM_CheckParm ( " -startwindowed " ) )
Cvar_Set ( Cvar_FindVar ( " vid_fullscreen " ) , " 0 " ) ;
if ( COM_CheckParm ( " -fullscreen " ) )
Cvar_Set ( Cvar_FindVar ( " vid_fullscreen " ) , " 1 " ) ;
2005-03-20 02:57:11 +00:00
2005-02-06 02:47:36 +00:00
if ( ( i = COM_CheckParm ( " -width " ) ) ) //width on it's own also sets height
2004-08-23 00:15:46 +00:00
{
2005-02-06 02:47:36 +00:00
Cvar_Set ( Cvar_FindVar ( " vid_width " ) , com_argv [ i + 1 ] ) ;
Cvar_SetValue ( Cvar_FindVar ( " vid_height " ) , ( atoi ( com_argv [ i + 1 ] ) / 3 ) * 4 ) ;
2004-08-23 00:15:46 +00:00
}
2005-02-06 02:47:36 +00:00
if ( ( i = COM_CheckParm ( " -height " ) ) )
Cvar_Set ( Cvar_FindVar ( " vid_height " ) , com_argv [ i + 1 ] ) ;
if ( ( i = COM_CheckParm ( " -conwidth " ) ) ) //width on it's own also sets height
{
Cvar_Set ( Cvar_FindVar ( " vid_conwidth " ) , com_argv [ i + 1 ] ) ;
Cvar_SetValue ( Cvar_FindVar ( " vid_conheight " ) , ( atoi ( com_argv [ i + 1 ] ) / 3 ) * 4 ) ;
}
if ( ( i = COM_CheckParm ( " -conheight " ) ) )
Cvar_Set ( Cvar_FindVar ( " vid_conheight " ) , com_argv [ i + 1 ] ) ;
if ( ( i = COM_CheckParm ( " -bpp " ) ) )
Cvar_Set ( Cvar_FindVar ( " vid_bpp " ) , com_argv [ i + 1 ] ) ;
2004-08-23 00:15:46 +00:00
if ( ! qrenderer & & * vid_renderer . string )
{
Cmd_ExecuteString ( " vid_restart \n " , RESTRICT_LOCAL ) ;
}
if ( ! qrenderer )
{
Cmd_ExecuteString ( " vid_restart \n " , RESTRICT_LOCAL ) ;
}
UI_Init ( ) ;
2005-02-06 02:47:36 +00:00
# ifndef NOMEDIA
if ( ! cls . demofile & & ! cls . state & & ! media_filmtype )
{
2005-04-26 16:04:12 +00:00
int ol_depth ;
int idcin_depth ;
int idroq_depth ;
idcin_depth = COM_FDepthFile ( " video/idlog.cin " , true ) ; //q2
idroq_depth = COM_FDepthFile ( " video/idlogo.roq " , true ) ; //q2
ol_depth = COM_FDepthFile ( " video/openinglogos.roq " , true ) ; //jk2
if ( ol_depth < = idroq_depth | | ol_depth < = idcin_depth )
Media_PlayFilm ( " video/openinglogos.roq " ) ;
else if ( idroq_depth < = idcin_depth )
2005-02-06 02:47:36 +00:00
Media_PlayFilm ( " video/idlogo.roq " ) ;
2005-04-26 16:04:12 +00:00
else if ( idcin_depth )
Media_PlayFilm ( " video/idlog.cin " ) ;
2005-02-06 02:47:36 +00:00
}
# endif
2004-08-23 00:15:46 +00:00
Con_TPrintf ( TL_NL ) ;
# ifdef VERSION3PART
Con_TPrintf ( TCL_VERSION3 , VERSION , build_number ( ) ) ;
# else
Con_TPrintf ( TLC_VERSION2 , VERSION , build_number ( ) ) ;
# endif
Con_TPrintf ( TL_NL ) ;
Con_TPrintf ( TLC_QUAKEWORLD_INITED ) ;
2005-01-05 08:01:19 +00:00
Con_DPrintf ( " This program is free software; you can redistribute it and/or "
2004-08-23 00:15:46 +00:00
" 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. "
" \n "
" 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. "
" \n "
" See the GNU General Public License for more details. \n " ) ;
}
/*
= = = = = = = = = = = = = = =
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 )
{
Sys_Printf ( " recursive shutdown \n " ) ;
return ;
}
isdown = true ;
UI_Stop ( ) ;
Host_WriteConfiguration ( ) ;
CDAudio_Shutdown ( ) ;
S_Shutdown ( ) ;
IN_Shutdown ( ) ;
if ( VID_DeInit )
VID_DeInit ( ) ;
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-23 00:15:46 +00:00
SV_Shutdown ( ) ;
# else
NET_Shutdown ( ) ;
# endif
Cvar_Shutdown ( ) ;
Validation_FlushFileList ( ) ;
}
2004-11-29 01:21:00 +00:00
# ifdef CLIENTONLY
void SV_EndRedirect ( void )
{
}
2004-12-09 23:31:48 +00:00
# endif