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
2005-07-03 15:16:20 +00:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
2004-08-23 00:15:46 +00:00
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 .
*/
// sv_user.c -- server code for moving users
# include "qwsvdef.h"
2004-11-29 01:21:00 +00:00
# ifndef CLIENTONLY
2004-08-23 00:15:46 +00:00
# include <ctype.h>
# define Q2EDICT_NUM(i) (q2edict_t*)((char *)ge->edicts+i*ge->edict_size)
# define Q2NUM_FOR_EDICT(ent) (((char *)ent - (char *)ge->edicts) / ge->edict_size)
hull_t * SV_HullForEntity ( edict_t * ent , int hullnum , vec3_t mins , vec3_t maxs , vec3_t offset ) ;
edict_t * sv_player ;
usercmd_t cmd ;
# ifdef SERVERONLY
2006-02-11 02:09:43 +00:00
cvar_t cl_rollspeed = SCVAR ( " cl_rollspeed " , " 200 " ) ;
cvar_t cl_rollangle = SCVAR ( " cl_rollangle " , " 2.0 " ) ;
2004-08-23 00:15:46 +00:00
# else
extern cvar_t cl_rollspeed ;
extern cvar_t cl_rollangle ;
# endif
2006-02-11 02:09:43 +00:00
cvar_t sv_spectalk = SCVAR ( " sv_spectalk " , " 1 " ) ;
2004-08-23 00:15:46 +00:00
2006-02-11 02:09:43 +00:00
cvar_t sv_mapcheck = SCVAR ( " sv_mapcheck " , " 1 " ) ;
2004-08-23 00:15:46 +00:00
2006-02-11 02:09:43 +00:00
cvar_t sv_cheatpc = SCVAR ( " sv_cheatpc " , " 125 " ) ;
cvar_t sv_cheatspeedchecktime = SCVAR ( " sv_cheatspeedchecktime " , " 30 " ) ;
cvar_t sv_playermodelchecks = SCVAR ( " sv_playermodelchecks " , " 1 " ) ;
2004-08-23 00:15:46 +00:00
2006-02-11 02:09:43 +00:00
cvar_t sv_cmdlikercon = SCVAR ( " sv_cmdlikercon " , " 0 " ) ; //set to 1 to allow a password of username:password instead of the correct rcon password.
cvar_t cmd_allowaccess = SCVAR ( " cmd_allowaccess " , " 0 " ) ; //set to 1 to allow cmd to execute console commands on the server.
cvar_t cmd_gamecodelevel = SCVAR ( " cmd_gamecodelevel " , " 50 " ) ; //execution level which gamecode is told about (for unrecognised commands)
2004-08-23 00:15:46 +00:00
2006-02-11 02:09:43 +00:00
cvar_t sv_nomsec = SCVAR ( " sv_nomsec " , " 0 " ) ;
2008-12-06 02:06:00 +00:00
cvar_t sv_edgefriction = FCVAR ( " sv_edgefriction " , " edgefriction " , " 2 " , 0 ) ;
2004-08-23 00:15:46 +00:00
2006-02-11 02:09:43 +00:00
cvar_t sv_brokenmovetypes = SCVAR ( " sv_brokenmovetypes " , " 0 " ) ;
2004-08-23 00:15:46 +00:00
2006-02-11 02:09:43 +00:00
cvar_t sv_chatfilter = SCVAR ( " sv_chatfilter " , " 0 " ) ;
2004-08-23 00:15:46 +00:00
2006-05-29 06:12:12 +00:00
cvar_t sv_floodprotect = SCVAR ( " sv_floodprotect " , " 1 " ) ;
cvar_t sv_floodprotect_messages = SCVAR ( " sv_floodprotect_messages " , " 4 " ) ;
cvar_t sv_floodprotect_interval = SCVAR ( " sv_floodprotect_interval " , " 4 " ) ;
cvar_t sv_floodprotect_silencetime = SCVAR ( " sv_floodprotect_silencetime " , " 10 " ) ;
2006-05-30 04:00:24 +00:00
cvar_t sv_floodprotect_suicide = SCVAR ( " sv_floodprotect_suicide " , " 1 " ) ;
cvar_t sv_floodprotect_sendmessage = FCVAR ( " sv_floodprotect_sendmessage " , " floodprotmsg " , " " , 0 ) ;
2006-05-29 05:35:07 +00:00
2006-02-11 02:09:43 +00:00
cvar_t votelevel = SCVAR ( " votelevel " , " 0 " ) ;
cvar_t voteminimum = SCVAR ( " voteminimum " , " 4 " ) ;
cvar_t votepercent = SCVAR ( " votepercent " , " -1 " ) ;
cvar_t votetime = SCVAR ( " votetime " , " 10 " ) ;
2004-08-23 00:15:46 +00:00
2006-02-11 02:09:43 +00:00
cvar_t pr_allowbutton1 = SCVARF ( " pr_allowbutton1 " , " 1 " , CVAR_LATCH ) ;
2007-08-30 20:45:01 +00:00
extern cvar_t sv_minping ;
2004-08-23 00:15:46 +00:00
2004-08-31 23:58:18 +00:00
2004-08-23 00:15:46 +00:00
extern cvar_t pm_bunnyspeedcap ;
extern cvar_t pm_ktjump ;
extern cvar_t pm_slidefix ;
2005-05-17 02:36:54 +00:00
extern cvar_t pm_slidyslopes ;
2004-08-23 00:15:46 +00:00
extern cvar_t pm_airstep ;
2005-01-04 08:04:42 +00:00
extern cvar_t pm_walljump ;
2006-02-11 02:09:43 +00:00
cvar_t sv_pushplayers = SCVAR ( " sv_pushplayers " , " 0 " ) ;
2004-08-23 00:15:46 +00:00
2008-05-25 22:23:43 +00:00
//yes, realip cvars need to be fully initialised or realip will be disabled
cvar_t sv_getrealip = SCVAR ( " sv_getrealip " , " 0 " ) ;
2008-05-27 18:59:07 +00:00
cvar_t sv_realip_kick = SCVAR ( " sv_realip_kick " , " 0 " ) ;
2008-05-25 22:23:43 +00:00
cvar_t sv_realiphostname_ipv4 = SCVAR ( " sv_realiphostname_ipv4 " , " " ) ;
2008-05-26 19:34:03 +00:00
cvar_t sv_realiphostname_ipv6 = SCVAR ( " sv_realiphostname_ipv6 " , " " ) ;
2008-05-25 22:23:43 +00:00
cvar_t sv_realip_timeout = SCVAR ( " sv_realip_timeout " , " 10 " ) ;
2004-08-23 00:15:46 +00:00
char sv_votinggroup [ ] = " server voting " ;
extern char cvargroup_serverpermissions [ ] ;
extern char cvargroup_serverinfo [ ] ;
extern char cvargroup_serverphysics [ ] ;
extern char cvargroup_servercontrol [ ] ;
extern vec3_t player_mins , player_maxs ;
extern cvar_t pausable ;
void SV_PreRunCmd ( void ) ;
void SV_RunCmd ( usercmd_t * ucmd , qboolean recurse ) ;
void SV_PostRunCmd ( void ) ;
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
USER STRINGCMD EXECUTION
host_client and sv_player will be valid .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2008-05-25 22:23:43 +00:00
qboolean SV_CheckRealIP ( client_t * client , qboolean force )
2006-09-17 00:59:22 +00:00
{
//returns true if they have a real ip
char * serverip ;
char * msg ;
2008-05-30 21:38:02 +00:00
if ( sv_getrealip . value < = client - > realip_status | | sv_getrealip . value > 3 )
2006-09-17 00:59:22 +00:00
return true ;
if ( client - > netchan . remote_address . type = = NA_LOOPBACK )
return true ; //the loopback client doesn't have to pass realip checks
if ( client - > realip_status = = 3 )
return true ; //we know that the ip is authentic
if ( client - > realip_status = = 2 )
{
ClientReliableWrite_Begin ( client , svc_print , 256 ) ;
ClientReliableWrite_Byte ( client , PRINT_HIGH ) ;
ClientReliableWrite_String ( client , " Couldn't verify your real ip \n " ) ;
return true ; //client doesn't support certainty.
}
if ( client - > realip_status = = - 1 )
2008-05-27 18:59:07 +00:00
return true ; //this client timed out.
2006-09-17 00:59:22 +00:00
2008-05-27 18:59:07 +00:00
if ( realtime - client - > connection_started > sv_realip_timeout . value )
2006-09-17 00:59:22 +00:00
{
ClientReliableWrite_Begin ( client , svc_print , 256 ) ;
ClientReliableWrite_Byte ( client , PRINT_HIGH ) ;
2008-05-27 18:59:07 +00:00
if ( client - > realip_status > 0 )
ClientReliableWrite_String ( client , " Couldn't verify your real ip \n " ) ;
else
ClientReliableWrite_String ( client , " Couldn't determine your real ip \n " ) ;
if ( sv_realip_kick . value > host_client - > realip_status )
2008-05-25 22:23:43 +00:00
{
SV_DropClient ( client ) ;
return false ;
}
2008-05-27 20:08:21 +00:00
if ( ! client - > realip_status )
client - > realip_status = - 1 ;
2006-09-17 00:59:22 +00:00
return true ;
}
if ( client - > realip_status = = 1 )
{
msg = va ( " \xff \xff \xff \xff %c %i " , A2A_PING , client - > realip_ping ) ;
NET_SendPacket ( NS_SERVER , strlen ( msg ) , msg , client - > realip ) ;
}
else
{
2008-05-25 22:23:43 +00:00
if ( client - > netchan . remote_address . type = = NA_IPV6 )
{
serverip = sv_realiphostname_ipv6 . string ;
// serverip = NET_AdrToString (net_local_sv_ip6adr);
}
else
{
serverip = sv_realiphostname_ipv4 . string ;
// serverip = NET_AdrToString (net_local_sv_ipadr);
}
if ( ! * serverip )
{
Con_Printf ( " realip not fully configured \n " ) ;
2008-05-27 18:59:07 +00:00
client - > realip_status = - 1 ;
2008-05-25 22:23:43 +00:00
return true ;
}
2006-09-17 00:59:22 +00:00
2008-05-25 22:23:43 +00:00
ClientReliableWrite_Begin ( client , svc_stufftext , 256 ) ;
2006-09-17 00:59:22 +00:00
ClientReliableWrite_String ( client , va ( " packet %s \" realip %i %i \" \n " , serverip , client - svs . clients , client - > realip_num ) ) ;
}
return false ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = =
SV_New_f
Sends the first message from the server to a connected client .
This will be sent on the initial connection and upon each server load .
= = = = = = = = = = = = = = = =
*/
void SV_New_f ( void )
{
char * gamedir ;
int playernum ;
2004-12-08 04:14:52 +00:00
int splitnum ;
2004-08-23 00:15:46 +00:00
client_t * split ;
if ( host_client - > state = = cs_spawned )
return ;
2005-05-26 12:55:34 +00:00
2004-08-23 00:15:46 +00:00
/* splitt delay
host_client - > state = cs_connected ;
host_client - > connection_started = realtime ;
# ifdef SVRANKING
host_client - > stats_started = realtime ;
# endif* /
// send the info about the new client to all connected clients
// SV_FullClientUpdate (host_client, &sv.reliable_datagram);
// host_client->sendinfo = true;
gamedir = Info_ValueForKey ( svs . info , " *gamedir " ) ;
2005-11-30 01:20:53 +00:00
if ( ! gamedir [ 0 ] | | ! strcmp ( gamedir , " fte " ) )
2004-08-23 00:15:46 +00:00
gamedir = " qw " ;
//NOTE: This doesn't go through ClientReliableWrite since it's before the user
//spawns. These functions are written to not overflow
2005-06-22 17:10:13 +00:00
/* if (host_client->num_backbuf)
2004-08-23 00:15:46 +00:00
{
2005-07-03 15:16:20 +00:00
Con_TPrintf ( STL_BACKBUFSET , host_client - > name , host_client - > netchan . message . cursize ) ;
2004-08-23 00:15:46 +00:00
host_client - > num_backbuf = 0 ;
SZ_Clear ( & host_client - > netchan . message ) ;
}
2005-06-22 17:10:13 +00:00
*/
2004-11-17 17:38:49 +00:00
if ( sizeofcoord > 2 & & ! ( host_client - > fteprotocolextensions & PEXT_FLOATCOORDS ) )
{
SV_ClientPrintf ( host_client , 2 , " \n \n \n \n Sorry, but your client does not appear to support FTE's bigcoords \n FTE users will need to set cl_nopext to 0 and then reconnect, or to upgrade \n " ) ;
Con_Printf ( " %s does not support bigcoords \n " , host_client - > name ) ;
return ;
}
2005-06-22 17:10:13 +00:00
ClientReliableCheckBlock ( host_client , 800 ) ; //okay, so it might be longer, but I'm too lazy to work out the real size.
2004-11-17 17:38:49 +00:00
2004-08-23 00:15:46 +00:00
// send the serverdata
2005-06-22 17:10:13 +00:00
ClientReliableWrite_Byte ( host_client , ISQ2CLIENT ( host_client ) ? svcq2_serverdata : svc_serverdata ) ;
2004-08-23 00:15:46 +00:00
# ifdef PROTOCOL_VERSION_FTE
if ( host_client - > fteprotocolextensions ) //let the client know
{
2009-01-29 01:41:28 +00:00
ClientReliableWrite_Long ( host_client , PROTOCOL_VERSION_FTE ) ;
2004-11-17 17:38:49 +00:00
if ( sizeofcoord = = 2 ) //we're not using float orgs on this level.
2009-01-29 01:41:28 +00:00
ClientReliableWrite_Long ( host_client , host_client - > fteprotocolextensions & ~ PEXT_FLOATCOORDS ) ;
2004-11-17 17:38:49 +00:00
else
2009-01-29 01:41:28 +00:00
ClientReliableWrite_Long ( host_client , host_client - > fteprotocolextensions ) ;
2004-08-23 00:15:46 +00:00
}
# endif
2008-04-12 23:24:19 +00:00
ClientReliableWrite_Long ( host_client , ISQ2CLIENT ( host_client ) ? PROTOCOL_VERSION_Q2 : PROTOCOL_VERSION_QW ) ;
2005-06-22 17:10:13 +00:00
ClientReliableWrite_Long ( host_client , svs . spawncount ) ;
2005-05-26 12:55:34 +00:00
if ( ISQ2CLIENT ( host_client ) )
2005-06-22 17:10:13 +00:00
ClientReliableWrite_Byte ( host_client , 0 ) ;
ClientReliableWrite_String ( host_client , gamedir ) ;
2004-08-23 00:15:46 +00:00
2004-12-08 04:14:52 +00:00
splitnum = 0 ;
2004-08-23 00:15:46 +00:00
for ( split = host_client ; split ; split = split - > controlled )
{
2009-03-03 01:52:30 +00:00
switch ( svs . gametype )
{
# ifdef HLSERVER
case GT_HALFLIFE :
playernum = split - svs . clients ;
break ;
# endif
2004-08-23 00:15:46 +00:00
# ifdef Q2SERVER
2009-03-03 01:52:30 +00:00
case GT_QUAKE2 :
2004-08-23 00:15:46 +00:00
playernum = Q2NUM_FOR_EDICT ( split - > q2edict ) - 1 ;
2009-03-03 01:52:30 +00:00
break ;
2004-08-23 00:15:46 +00:00
# endif
2009-03-03 01:52:30 +00:00
default :
2004-08-23 00:15:46 +00:00
playernum = NUM_FOR_EDICT ( svprogfuncs , split - > edict ) - 1 ;
2009-03-03 01:52:30 +00:00
}
2004-08-23 00:15:46 +00:00
if ( sv . demostate )
2004-12-08 04:14:52 +00:00
{
playernum = ( MAX_CLIENTS - 1 - splitnum ) | 128 ;
}
2004-08-23 00:15:46 +00:00
else if ( split - > spectator )
playernum | = 128 ;
if ( sv . state = = ss_cinematic )
playernum = - 1 ;
2005-05-26 12:55:34 +00:00
if ( ISQ2CLIENT ( host_client ) )
2005-06-22 17:10:13 +00:00
ClientReliableWrite_Short ( host_client , playernum ) ;
2004-08-23 00:15:46 +00:00
else
2005-06-22 17:10:13 +00:00
ClientReliableWrite_Byte ( host_client , playernum ) ;
2004-08-23 00:15:46 +00:00
split - > state = cs_connected ;
split - > connection_started = realtime ;
# ifdef SVRANKING
split - > stats_started = realtime ;
# endif
2004-12-08 04:14:52 +00:00
splitnum + + ;
2004-08-23 00:15:46 +00:00
}
2008-05-25 22:23:43 +00:00
2004-08-23 00:15:46 +00:00
if ( host_client - > fteprotocolextensions & PEXT_SPLITSCREEN )
2005-06-22 17:10:13 +00:00
ClientReliableWrite_Byte ( host_client , 128 ) ;
2004-08-23 00:15:46 +00:00
// send full levelname
2004-12-10 03:04:42 +00:00
if ( sv . demostatevalid )
2005-06-22 17:10:13 +00:00
ClientReliableWrite_String ( host_client , sv . demfullmapname ) ;
2004-12-10 03:04:42 +00:00
else
2005-06-22 17:10:13 +00:00
ClientReliableWrite_String ( host_client , sv . mapname ) ;
2004-08-23 00:15:46 +00:00
//
// game server
2005-07-03 15:16:20 +00:00
//
2004-08-23 00:15:46 +00:00
# ifdef Q2SERVER
2005-05-26 12:55:34 +00:00
if ( ISQ2CLIENT ( host_client ) )
2004-08-23 00:15:46 +00:00
{
if ( sv . state ! = ss_cinematic )
{
// host_client->q2edict = Q2NUM_FOR_EDICT(split->q2edict)-1;
memset ( & host_client - > lastcmd , 0 , sizeof ( host_client - > lastcmd ) ) ;
// begin fetching configstrings
2005-06-22 17:10:13 +00:00
ClientReliableWrite_Byte ( host_client , svcq2_stufftext ) ;
ClientReliableWrite_String ( host_client , va ( " cmd configstrings %i 0 \n " , svs . spawncount ) ) ;
2004-08-23 00:15:46 +00:00
}
return ;
}
# endif
// send the movevars
2005-06-22 17:10:13 +00:00
ClientReliableWrite_Float ( host_client , movevars . gravity ) ;
ClientReliableWrite_Float ( host_client , movevars . stopspeed ) ;
ClientReliableWrite_Float ( host_client , movevars . maxspeed ) ;
ClientReliableWrite_Float ( host_client , movevars . spectatormaxspeed ) ;
ClientReliableWrite_Float ( host_client , movevars . accelerate ) ;
ClientReliableWrite_Float ( host_client , movevars . airaccelerate ) ;
ClientReliableWrite_Float ( host_client , movevars . wateraccelerate ) ;
ClientReliableWrite_Float ( host_client , movevars . friction ) ;
ClientReliableWrite_Float ( host_client , movevars . waterfriction ) ;
ClientReliableWrite_Float ( host_client , movevars . entgravity ) ;
2004-08-23 00:15:46 +00:00
// send server info string
2005-01-25 20:46:24 +00:00
if ( sv . demostatevalid )
2005-06-22 17:10:13 +00:00
{
ClientReliableCheckBlock ( host_client , 20 + strlen ( sv . demoinfo ) ) ;
ClientReliableWrite_Byte ( host_client , svc_stufftext ) ;
ClientReliableWrite_String ( host_client , va ( " fullserverinfo \" %s \" \n " , sv . demoinfo ) ) ;
}
2005-01-25 05:01:30 +00:00
else
2005-06-22 17:10:13 +00:00
{
ClientReliableCheckBlock ( host_client , 20 + strlen ( svs . info ) ) ;
ClientReliableWrite_Byte ( host_client , svc_stufftext ) ;
ClientReliableWrite_String ( host_client , va ( " fullserverinfo \" %s \" \n " , svs . info ) ) ;
}
2004-08-23 00:15:46 +00:00
2005-03-10 03:55:18 +00:00
host_client - > csqcactive = false ;
2008-05-25 22:23:43 +00:00
host_client - > realip_num = rand ( ) + ( host_client - > challenge < < 16 ) ;
SV_CheckRealIP ( host_client , false ) ;
2004-08-23 00:15:46 +00:00
// send music
2005-06-22 17:10:13 +00:00
ClientReliableCheckBlock ( host_client , 2 ) ;
ClientReliableWrite_Byte ( host_client , svc_cdtrack ) ;
2004-08-23 00:15:46 +00:00
if ( svprogfuncs )
2005-06-22 17:10:13 +00:00
ClientReliableWrite_Byte ( host_client , sv . edicts - > v - > sounds ) ;
2004-08-23 00:15:46 +00:00
else
2005-06-22 17:10:13 +00:00
ClientReliableWrite_Byte ( host_client , 0 ) ;
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " new (QW) " ) ;
2004-08-23 00:15:46 +00:00
}
# define GAME_DEATHMATCH 0
# define GAME_COOP 1
void SVNQ_New_f ( void )
{
extern cvar_t coop ;
char message [ 2048 ] ;
int i ;
2005-05-26 12:55:34 +00:00
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svc_print ) ;
# ifdef DISTRIBUTION
2005-10-04 21:08:06 +00:00
sprintf ( message , " %c \n " DISTRIBUTION " QuakeWorld build %i server \n " , 2 , build_number ( ) ) ;
2004-08-23 00:15:46 +00:00
# else
2005-10-04 21:08:06 +00:00
sprintf ( message , " %c \n QUAKEWORLD BUILD %i SERVER \n " , 2 , build_number ( ) ) ;
2004-08-23 00:15:46 +00:00
# endif
MSG_WriteString ( & host_client - > netchan . message , message ) ;
2008-11-09 22:29:28 +00:00
if ( host_client - > protocol = = SCP_DARKPLACES6 | | host_client - > protocol = = SCP_DARKPLACES7 )
2007-06-10 05:14:38 +00:00
{
2007-06-20 00:02:54 +00:00
extern cvar_t allow_download ;
2007-06-10 05:14:38 +00:00
char * f ;
2007-06-10 21:33:24 +00:00
2007-06-20 00:02:54 +00:00
if ( allow_download . value )
{
MSG_WriteByte ( & host_client - > netchan . message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , " cl_serverextension_download 1 \n " ) ;
}
2007-06-10 21:33:24 +00:00
2007-06-10 05:14:38 +00:00
f = COM_LoadTempFile ( " csprogs.dat " ) ;
if ( f )
{
MSG_WriteByte ( & host_client - > netchan . message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " csqc_progname %s \n " , " csprogs.dat " ) ) ;
MSG_WriteByte ( & host_client - > netchan . message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " csqc_progsize %i \n " , com_filesize ) ) ;
MSG_WriteByte ( & host_client - > netchan . message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " csqc_progcrc %i \n " , QCRC_Block ( f , com_filesize ) ) ) ;
host_client - > csqcactive = true ;
}
}
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svc_serverdata ) ;
2005-05-27 05:41:07 +00:00
switch ( host_client - > protocol )
{
2005-07-03 15:16:20 +00:00
# ifdef NQPROT
2005-05-27 05:41:07 +00:00
case SCP_NETQUAKE :
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " new (NQ) " ) ;
2005-05-27 05:41:07 +00:00
MSG_WriteLong ( & host_client - > netchan . message , NQ_PROTOCOL_VERSION ) ;
MSG_WriteByte ( & host_client - > netchan . message , 16 ) ;
break ;
case SCP_DARKPLACES6 :
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " new (DP6) " ) ;
2005-05-27 05:41:07 +00:00
MSG_WriteLong ( & host_client - > netchan . message , DP6_PROTOCOL_VERSION ) ;
MSG_WriteByte ( & host_client - > netchan . message , sv . allocated_client_slots ) ;
break ;
case SCP_DARKPLACES7 :
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " new (DP7) " ) ;
2005-05-27 05:41:07 +00:00
MSG_WriteLong ( & host_client - > netchan . message , DP7_PROTOCOL_VERSION ) ;
MSG_WriteByte ( & host_client - > netchan . message , sv . allocated_client_slots ) ;
break ;
2005-07-03 15:16:20 +00:00
# endif
2005-05-27 05:41:07 +00:00
default :
host_client - > drop = true ;
break ;
}
2004-08-23 00:15:46 +00:00
if ( ! coop . value & & deathmatch . value )
MSG_WriteByte ( & host_client - > netchan . message , GAME_DEATHMATCH ) ;
else
MSG_WriteByte ( & host_client - > netchan . message , GAME_COOP ) ;
strcpy ( message , sv . mapname ) ;
MSG_WriteString ( & host_client - > netchan . message , message ) ;
2006-02-17 02:51:59 +00:00
for ( i = 1 ; sv . strings . model_precache [ i ] ; i + + )
MSG_WriteString ( & host_client - > netchan . message , sv . strings . model_precache [ i ] ) ;
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
2006-02-17 02:51:59 +00:00
for ( i = 1 ; * sv . strings . sound_precache [ i ] ; i + + )
MSG_WriteString ( & host_client - > netchan . message , sv . strings . sound_precache [ i ] ) ;
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
// send music
MSG_WriteByte ( & host_client - > netchan . message , svc_cdtrack ) ;
2005-03-28 00:11:59 +00:00
MSG_WriteByte ( & host_client - > netchan . message , sv . edicts - > v - > sounds ) ;
MSG_WriteByte ( & host_client - > netchan . message , sv . edicts - > v - > sounds ) ;
2004-08-23 00:15:46 +00:00
2005-07-03 15:16:20 +00:00
// set view
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svc_setview ) ;
MSG_WriteShort ( & host_client - > netchan . message , NUM_FOR_EDICT ( svprogfuncs , host_client - > edict ) ) ;
MSG_WriteByte ( & host_client - > netchan . message , svc_signonnum ) ;
MSG_WriteByte ( & host_client - > netchan . message , 1 ) ;
MSG_WriteByte ( & host_client - > netchan . message , svc_setpause ) ;
MSG_WriteByte ( & host_client - > netchan . message , sv . paused ) ;
// host_client->sendsignon = true;
// host_client->spawned = false; // need prespawn, spawn, etc
}
# ifdef Q2SERVER
void SVQ2_ConfigStrings_f ( void )
{
int start ;
2005-03-20 02:57:11 +00:00
char * str ;
2004-08-23 00:15:46 +00:00
Con_DPrintf ( " Configstrings() from %s \n " , host_client - > name ) ;
if ( host_client - > state ! = cs_connected )
{
Con_DPrintf ( " configstrings not valid -- already spawned \n " ) ;
return ;
}
// handle the case of a level changing while a client was connecting
if ( atoi ( Cmd_Argv ( 1 ) ) ! = svs . spawncount )
{
Con_DPrintf ( " SV_Configstrings_f from different level \n " ) ;
SV_New_f ( ) ;
return ;
}
start = atoi ( Cmd_Argv ( 2 ) ) ;
2004-10-28 21:13:52 +00:00
if ( start < 0 )
{
Con_Printf ( " SV_Configstrings_f: %s tried crashing us \n " , host_client - > name ) ;
host_client - > drop = true ;
return ;
}
2004-08-23 00:15:46 +00:00
// write a packet full of data
2005-07-03 15:16:20 +00:00
while ( host_client - > netchan . message . cursize < MAX_QWMSGLEN / 2
2004-08-23 00:15:46 +00:00
& & start < Q2MAX_CONFIGSTRINGS )
{
2006-02-17 02:51:59 +00:00
str = sv . strings . configstring [ start ] ;
2005-03-20 02:57:11 +00:00
if ( * str )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , str ) ;
}
/*
2004-08-23 00:15:46 +00:00
//choose range to grab from.
if ( start < Q2CS_CDTRACK )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , sv . name ) ;
2005-03-20 02:57:11 +00:00
}
2004-08-23 00:15:46 +00:00
else if ( start < Q2CS_SKY )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
if ( svprogfuncs )
2005-03-28 00:11:59 +00:00
MSG_WriteString ( & host_client - > netchan . message , va ( " %i " , sv . edicts - > v - > sounds ) ) ;
2004-08-23 00:15:46 +00:00
else
MSG_WriteString ( & host_client - > netchan . message , " 0 " ) ;
}
else if ( start < Q2CS_SKYAXIS )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , " unit1_ " ) ;
}
else if ( start < Q2CS_SKYROTATE )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , " 0 " ) ;
}
else if ( start < Q2CS_STATUSBAR )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , " 0 " ) ;
}
else if ( start < Q2CS_AIRACCEL )
{ //show status bar
if ( start = = Q2CS_STATUSBAR )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , sv . statusbar ) ;
}
}
else if ( start < Q2CS_MAXCLIENTS )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " %i " , ( int ) 1 ) ) ;
}
else if ( start < Q2CS_MAPCHECKSUM )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " %i " , ( int ) 32 ) ) ;
}
else if ( start < Q2CS_MODELS )
{
2006-02-17 19:54:47 +00:00
extern int map_checksum ;
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " %i " , map_checksum ) ) ;
}
else if ( start < Q2CS_SOUNDS )
{
if ( * sv . model_precache [ start - Q2CS_MODELS ] )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , sv . model_precache [ start - Q2CS_MODELS ] ) ;
}
}
else if ( start < Q2CS_IMAGES )
{
if ( * sv . sound_precache [ start - Q2CS_SOUNDS ] )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , sv . sound_precache [ start - Q2CS_SOUNDS ] ) ;
}
}
else if ( start < Q2CS_LIGHTS )
{
if ( * sv . image_precache [ start - Q2CS_IMAGES ] )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , sv . image_precache [ start - Q2CS_IMAGES ] ) ;
}
}
else if ( start < Q2CS_ITEMS )
{
if ( start - Q2CS_LIGHTS < MAX_LIGHTSTYLES & & sv . lightstyles [ start - Q2CS_LIGHTS ] )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_configstring ) ;
MSG_WriteShort ( & host_client - > netchan . message , start ) ;
MSG_WriteString ( & host_client - > netchan . message , sv . lightstyles [ start - Q2CS_LIGHTS ] ) ;
}
}
else if ( start < Q2CS_PLAYERSKINS )
{
// MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
// MSG_WriteShort (&host_client->netchan.message, start);
// MSG_WriteString (&host_client->netchan.message, sv.configstrings[start-Q2CS_ITEMS]);
}
else if ( start < Q2CS_GENERAL )
{
// MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
// MSG_WriteShort (&host_client->netchan.message, start);
// MSG_WriteString (&host_client->netchan.message, sv.configstrings[start]);
}
else
{
// MSG_WriteByte (&host_client->netchan.message, svcq2_configstring);
// MSG_WriteShort (&host_client->netchan.message, start);
// MSG_WriteString (&host_client->netchan.message, sv.configstrings[start]);
}
2005-03-20 02:57:11 +00:00
*/
2004-08-23 00:15:46 +00:00
start + + ;
}
// send next command
if ( start = = Q2MAX_CONFIGSTRINGS )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " cmd baselines %i 0 \n " , svs . spawncount ) ) ;
}
else
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " cmd configstrings %i %i \n " , svs . spawncount , start ) ) ;
}
}
# endif
# ifdef Q2SERVER
void SVQ2_BaseLines_f ( void )
{
int start ;
q2entity_state_t nullstate ;
q2entity_state_t * base ;
extern q2entity_state_t sv_baselines [ Q2MAX_EDICTS ] ;
Con_DPrintf ( " Baselines() from %s \n " , host_client - > name ) ;
if ( host_client - > state ! = cs_connected )
{
Con_Printf ( " baselines not valid -- already spawned \n " ) ;
return ;
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// handle the case of a level changing while a client was connecting
if ( atoi ( Cmd_Argv ( 1 ) ) ! = svs . spawncount )
{
Con_Printf ( " SV_Baselines_f from different level \n " ) ;
SV_New_f ( ) ;
return ;
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
start = atoi ( Cmd_Argv ( 2 ) ) ;
memset ( & nullstate , 0 , sizeof ( nullstate ) ) ;
// write a packet full of data
while ( host_client - > netchan . message . cursize < MAX_QWMSGLEN / 2
& & start < Q2MAX_EDICTS )
{
base = & sv_baselines [ start ] ;
if ( base - > modelindex | | base - > sound | | base - > effects )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_spawnbaseline ) ;
MSGQ2_WriteDeltaEntity ( & nullstate , base , & host_client - > netchan . message , true , true ) ;
}
start + + ;
}
// send next command
if ( start = = Q2MAX_EDICTS )
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " precache %i \n " , svs . spawncount ) ) ;
}
else
{
MSG_WriteByte ( & host_client - > netchan . message , svcq2_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " cmd baselines %i %i \n " , svs . spawncount , start ) ) ;
}
}
2004-08-27 00:45:34 +00:00
void SVQ2_NextServer_f ( void )
{
if ( ! * sv . modelname & & atoi ( Cmd_Argv ( 1 ) ) = = svs . spawncount )
{
cvar_t * nsv = Cvar_FindVar ( " nextserver " ) ;
if ( ! nsv | | ! * nsv - > string )
return ;
svs . spawncount + + ; // make sure another doesn't sneak in
Cbuf_AddText ( nsv - > string , RESTRICT_LOCAL ) ;
Cbuf_AddText ( " \n " , RESTRICT_LOCAL ) ;
Cvar_Set ( nsv , " " ) ;
}
}
2004-08-23 00:15:46 +00:00
# endif
2004-11-17 17:38:49 +00:00
void SV_PK3List_f ( void )
{
2005-01-24 23:47:32 +00:00
# ifndef PEXT_PK3DOWNLOADS
Con_Printf ( " pk3list not valid -- It's not implemented! \n " ) ;
return ;
# else
2004-11-17 17:38:49 +00:00
int crc ;
char * name ;
2004-11-23 00:36:33 +00:00
int i ;
2005-07-03 15:16:20 +00:00
2004-11-17 17:38:49 +00:00
if ( host_client - > state ! = cs_connected )
{ //fixme: send prints instead
2005-07-28 15:22:15 +00:00
Con_Printf ( " pk3list not valid -- already spawned \n " ) ;
2004-11-17 17:38:49 +00:00
return ;
}
// handle the case of a level changing while a client was connecting
if ( atoi ( Cmd_Argv ( 1 ) ) ! = svs . spawncount & & ! sv . msgfromdemo )
{
Con_Printf ( " SV_PK3List_f from different level \n " ) ;
SV_New_f ( ) ;
return ;
}
i = atoi ( Cmd_Argv ( 2 ) ) ;
2005-07-03 15:16:20 +00:00
2004-11-17 17:38:49 +00:00
//NOTE: This doesn't go through ClientReliableWrite since it's before the user
//spawns. These functions are written to not overflow
2005-01-24 23:47:32 +00:00
if ( host_client - > num_backbuf )
{
2008-11-09 22:29:28 +00:00
char * msg = va ( " cmd pk3list %s %s \n " , Cmd_Argv ( 1 ) , Cmd_Argv ( 2 ) ) ;
Con_TPrintf ( STL_BACKBUFSET , host_client - > name , host_client - > netchan . message . cursize ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 2 + strlen ( msg ) ) ;
ClientReliableWrite_String ( & host_client - > netchan . message , msg ) ;
return ;
2004-11-17 17:38:49 +00:00
}
if ( i < 0 )
{
Con_Printf ( " SV_PK3List_f: %s tried to crash us \n " , host_client - > name ) ;
SV_DropClient ( host_client ) ;
return ;
}
2005-01-24 23:47:32 +00:00
for ( ; ; i + + )
2004-11-17 17:38:49 +00:00
{
if ( host_client - > netchan . message . cursize < ( MAX_QWMSGLEN / 2 ) )
{ //user's buffer was too small
MSG_WriteByte ( & host_client - > netchan . message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " cmd pk3list %i %i \n " , svs . spawncount , 0 ) ) ;
return ; //and stop before we flood them
}
name = COM_GetPathInfo ( i , & crc ) ;
if ( name & & * name )
{
MSG_WriteByte ( & host_client - > netchan . message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " echo packfile %s \n " , name ) ) ;
2005-01-24 23:47:32 +00:00
continue ; //try the next.
2004-11-17 17:38:49 +00:00
}
2005-01-24 23:47:32 +00:00
//that's all folks, move on to sound.
2004-11-17 17:38:49 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " soundlist %i 0 \n " , svs . spawncount ) ) ;
return ;
}
2005-01-24 23:47:32 +00:00
# endif
2004-11-17 17:38:49 +00:00
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = =
SV_Soundlist_f
= = = = = = = = = = = = = = = = = =
*/
void SV_Soundlist_f ( void )
{
2008-11-28 20:34:51 +00:00
unsigned int i ;
2004-08-23 00:15:46 +00:00
//char **s;
2008-11-28 20:34:51 +00:00
unsigned int n ;
unsigned int maxclientsupportedsounds ;
2004-08-23 00:15:46 +00:00
if ( host_client - > state ! = cs_connected )
{
2005-07-28 15:22:15 +00:00
Con_Printf ( " soundlist not valid -- already spawned \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
// handle the case of a level changing while a client was connecting
if ( atoi ( Cmd_Argv ( 1 ) ) ! = svs . spawncount & & ! sv . msgfromdemo )
{
Con_Printf ( " SV_Soundlist_f from different level \n " ) ;
SV_New_f ( ) ;
return ;
}
n = atoi ( Cmd_Argv ( 2 ) ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
//NOTE: This doesn't go through ClientReliableWrite since it's before the user
//spawns. These functions are written to not overflow
2008-11-09 22:29:28 +00:00
if ( host_client - > num_backbuf )
{
char * msg = va ( " cmd soundlist %s %s \n " , Cmd_Argv ( 1 ) , Cmd_Argv ( 2 ) ) ;
Con_TPrintf ( STL_BACKBUFSET , host_client - > name , host_client - > netchan . message . cursize ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 1 + strlen ( msg ) ) ;
ClientReliableWrite_String ( host_client , msg ) ;
return ;
2004-08-23 00:15:46 +00:00
}
2004-12-08 04:14:52 +00:00
if ( n > = MAX_SOUNDS )
2004-11-17 17:38:49 +00:00
{
2004-12-08 04:14:52 +00:00
SV_EndRedirect ( ) ;
Con_Printf ( " SV_Soundlist_f: %s send an invalid index \n " , host_client - > name ) ;
2004-11-17 17:38:49 +00:00
SV_DropClient ( host_client ) ;
return ;
}
2008-11-28 20:34:51 +00:00
# ifdef PEXT_SOUNDDBL
if ( n > 255 )
{
MSG_WriteByte ( & host_client - > netchan . message , svcfte_soundlistshort ) ;
MSG_WriteShort ( & host_client - > netchan . message , n ) ;
}
else
# endif
{
MSG_WriteByte ( & host_client - > netchan . message , svc_soundlist ) ;
MSG_WriteByte ( & host_client - > netchan . message , n ) ;
}
maxclientsupportedsounds = 256 ;
# ifdef PEXT_SOUNDDBL
if ( host_client - > fteprotocolextensions & PEXT_SOUNDDBL )
maxclientsupportedsounds * = 2 ;
# endif
2004-08-23 00:15:46 +00:00
if ( sv . democausesreconnect ) //read the list from somewhere else
{
for ( i = 1 + n ;
2005-07-03 15:16:20 +00:00
* sv . demsound_precache [ i ] & & host_client - > netchan . message . cursize < ( MAX_QWMSGLEN / 2 ) ;
2004-08-23 00:15:46 +00:00
i + + , n + + )
MSG_WriteString ( & host_client - > netchan . message , sv . demsound_precache [ i ] ) ;
2004-12-05 15:19:11 +00:00
2005-07-03 15:16:20 +00:00
2004-12-05 15:19:11 +00:00
if ( ! * sv . demsound_precache [ i ] )
n = 0 ;
2004-08-23 00:15:46 +00:00
}
else
{
for ( i = 1 + n ;
2008-11-28 20:34:51 +00:00
i < maxclientsupportedsounds & & * sv . strings . sound_precache [ i ] & & host_client - > netchan . message . cursize < ( MAX_QWMSGLEN / 2 ) ;
2004-08-23 00:15:46 +00:00
i + + , n + + )
2008-11-28 20:34:51 +00:00
{
2006-02-17 02:51:59 +00:00
MSG_WriteString ( & host_client - > netchan . message , sv . strings . sound_precache [ i ] ) ;
2008-11-28 20:34:51 +00:00
if ( ( ( n & 255 ) = = 255 ) & & n ! = i - 1 )
break ;
}
2004-12-05 15:19:11 +00:00
2006-02-17 02:51:59 +00:00
if ( ! * sv . strings . sound_precache [ i ] )
2004-12-05 15:19:11 +00:00
n = 0 ;
2004-08-23 00:15:46 +00:00
}
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
// next msg
2004-12-05 15:19:11 +00:00
MSG_WriteByte ( & host_client - > netchan . message , n ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
SV_Modellist_f
= = = = = = = = = = = = = = = = = =
*/
void SV_Modellist_f ( void )
{
2008-11-28 20:34:51 +00:00
unsigned int i ;
unsigned int n ;
unsigned int maxclientsupportedmodels ;
2004-08-23 00:15:46 +00:00
if ( host_client - > state ! = cs_connected )
{
2005-07-28 15:22:15 +00:00
Con_Printf ( " modellist not valid -- already spawned \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// handle the case of a level changing while a client was connecting
if ( atoi ( Cmd_Argv ( 1 ) ) ! = svs . spawncount & & ! sv . msgfromdemo )
{
Con_Printf ( " SV_Modellist_f from different level \n " ) ;
SV_New_f ( ) ;
return ;
}
n = atoi ( Cmd_Argv ( 2 ) ) ;
2009-06-21 17:45:33 +00:00
if ( n > = MAX_MODELS )
{
SV_EndRedirect ( ) ;
Con_Printf ( " SV_Modellist_f: %s send an invalid index \n " , host_client - > name ) ;
SV_DropClient ( host_client ) ;
return ;
}
if ( n = = 0 & & ( host_client - > zquake_extensions & Z_EXT_VWEP ) )
{
char mname [ MAX_QPATH ] ;
2009-07-06 01:20:20 +00:00
char vweaplist [ 1024 ] = " //vwep " ;
2009-06-21 17:45:33 +00:00
int pos = strlen ( vweaplist ) ;
for ( i = 0 ; sv . strings . vw_model_precache [ i ] ; i + + )
{
//grab the model name... without a progs/ prefix if it has one
if ( ! strncmp ( sv . strings . vw_model_precache [ i ] , " progs/ " , 6 ) )
Q_strncpy ( mname , sv . strings . vw_model_precache [ i ] + 6 , sizeof ( mname ) ) ;
else
Q_strncpy ( mname , sv . strings . vw_model_precache [ i ] , sizeof ( mname ) ) ;
//strip .mdl extensions
if ( ! strcmp ( COM_FileExtension ( mname ) , " .mdl " ) )
COM_StripExtension ( mname , mname , sizeof ( mname ) ) ;
//add it to the vweap command, taking care of any remaining spaces in names.
if ( strchr ( mname , ' ' ) )
Q_strncatz ( vweaplist , va ( " \" %s \" " , mname ) , sizeof ( vweaplist ) ) ;
else
Q_strncatz ( vweaplist , va ( " %s " , mname ) , sizeof ( vweaplist ) ) ;
}
if ( strlen ( vweaplist ) < = sizeof ( vweaplist ) - 2 )
{
Q_strncatz ( vweaplist , " \n " , sizeof ( vweaplist ) ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 2 + strlen ( vweaplist ) ) ;
ClientReliableWrite_String ( host_client , vweaplist ) ;
}
}
2004-08-23 00:15:46 +00:00
//NOTE: This doesn't go through ClientReliableWrite since it's before the user
//spawns. These functions are written to not overflow
2008-11-09 22:29:28 +00:00
if ( host_client - > num_backbuf )
{
char * msg = va ( " cmd modellist %s %s \n " , Cmd_Argv ( 1 ) , Cmd_Argv ( 2 ) ) ;
Con_TPrintf ( STL_BACKBUFSET , host_client - > name , host_client - > netchan . message . cursize ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 1 + strlen ( msg ) ) ;
ClientReliableWrite_String ( host_client , msg ) ;
return ;
2004-08-23 00:15:46 +00:00
}
2008-11-28 20:34:51 +00:00
# ifdef PEXT_MODELDBL
if ( n > 255 )
2004-08-23 00:15:46 +00:00
{
2008-05-25 22:23:43 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svcfte_modellistshort ) ;
2004-08-23 00:15:46 +00:00
MSG_WriteShort ( & host_client - > netchan . message , n ) ;
}
else
2008-11-28 20:34:51 +00:00
# endif
2004-08-23 00:15:46 +00:00
{
MSG_WriteByte ( & host_client - > netchan . message , svc_modellist ) ;
MSG_WriteByte ( & host_client - > netchan . message , n ) ;
}
2005-10-19 19:37:16 +00:00
maxclientsupportedmodels = 256 ;
2008-11-28 20:34:51 +00:00
# ifdef PEXT_MODELDBL
2005-10-19 19:37:16 +00:00
if ( host_client - > fteprotocolextensions & PEXT_MODELDBL )
maxclientsupportedmodels * = 2 ;
2008-11-28 20:34:51 +00:00
# endif
2005-10-19 19:37:16 +00:00
2004-08-23 00:15:46 +00:00
if ( sv . democausesreconnect ) //read the list from somewhere else
{
for ( i = 1 + n ;
* sv . demmodel_precache [ i ] & & ( ( n & 255 ) = = 0 | | host_client - > netchan . message . cursize < ( MAX_QWMSGLEN / 2 ) ) ;
i + + , n + + )
MSG_WriteString ( & host_client - > netchan . message , sv . demmodel_precache [ i ] ) ;
2004-12-05 15:19:11 +00:00
if ( ! * sv . demmodel_precache [ i ] )
n = 0 ;
2004-08-23 00:15:46 +00:00
}
else
{
for ( i = 1 + n ;
2006-02-17 02:51:59 +00:00
i < maxclientsupportedmodels & & sv . strings . model_precache [ i ] & & host_client - > netchan . message . cursize < ( MAX_QWMSGLEN / 2 ) ; //make sure we don't send a 0 next...
2005-10-19 19:37:16 +00:00
i + + )
{
2006-02-17 02:51:59 +00:00
MSG_WriteString ( & host_client - > netchan . message , sv . strings . model_precache [ i ] ) ;
2005-10-19 19:37:16 +00:00
if ( ( ( n & 255 ) = = 255 ) & & n ! = i - 1 )
break ;
}
n = i - 1 ;
2004-12-05 15:19:11 +00:00
2006-02-17 02:51:59 +00:00
if ( ! sv . strings . model_precache [ i ] )
2004-12-05 15:19:11 +00:00
n = 0 ;
2004-08-23 00:15:46 +00:00
}
2005-10-19 19:37:16 +00:00
if ( i = = maxclientsupportedmodels )
n = 0 ; //doh!
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
// next msg
2004-12-05 15:19:11 +00:00
MSG_WriteByte ( & host_client - > netchan . message , n ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
SV_PreSpawn_f
= = = = = = = = = = = = = = = = = =
*/
void SV_PreSpawn_f ( void )
{
unsigned buf , bufs ;
unsigned check ;
unsigned statics ;
if ( host_client - > state ! = cs_connected )
{
2005-07-28 15:22:15 +00:00
Con_Printf ( " prespawn not valid -- already spawned \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// handle the case of a level changing while a client was connecting
if ( atoi ( Cmd_Argv ( 1 ) ) ! = svs . spawncount & & ! sv . msgfromdemo )
{
Con_Printf ( " SV_PreSpawn_f from different level \n " ) ;
SV_New_f ( ) ;
return ;
}
if ( sv . democausesreconnect )
bufs = sv . num_demosignon_buffers ;
else
bufs = sv . num_signon_buffers ;
statics = sv . numextrastatics ;
buf = atoi ( Cmd_Argv ( 2 ) ) ;
if ( buf > = bufs + statics + sv . num_edicts + 255 )
2004-12-08 04:14:52 +00:00
{
SV_EndRedirect ( ) ;
Con_Printf ( " SV_Modellist_f: %s send an invalid index \n " , host_client - > name ) ;
SV_DropClient ( host_client ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( ! buf )
{
// should be three numbers following containing checksums
check = atoi ( Cmd_Argv ( 3 ) ) ;
// Con_DPrintf("Client check = %d\n", check);
if ( sv_mapcheck . value & & check ! = sv . worldmodel - > checksum & &
2005-05-19 01:40:14 +00:00
check ! = LittleLong ( sv . worldmodel - > checksum2 ) )
2004-08-23 00:15:46 +00:00
if ( ! sv . demofile | | ( sv . demofile & & ! sv . democausesreconnect ) ) //demo playing causes no check. If it's the return level, check anyway to avoid that loophole.
{
2005-07-03 15:16:20 +00:00
SV_ClientTPrintf ( host_client , PRINT_HIGH ,
2004-08-23 00:15:46 +00:00
STL_MAPCHEAT ,
sv . modelname , check , sv . worldmodel - > checksum , sv . worldmodel - > checksum2 ) ;
2005-07-03 15:16:20 +00:00
SV_DropClient ( host_client ) ;
2004-08-23 00:15:46 +00:00
return ;
}
host_client - > checksum = check ;
}
//NOTE: This doesn't go through ClientReliableWrite since it's before the user
//spawns. These functions are written to not overflow
2008-11-09 22:29:28 +00:00
if ( host_client - > num_backbuf )
{
char * msg = va ( " cmd prespawn %s %s %s \n " , Cmd_Argv ( 1 ) , Cmd_Argv ( 2 ) , Cmd_Argv ( 3 ) ) ;
Con_TPrintf ( STL_BACKBUFSET , host_client - > name , host_client - > netchan . message . cursize ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 1 + strlen ( msg ) ) ;
ClientReliableWrite_String ( host_client , msg ) ;
return ;
2004-08-23 00:15:46 +00:00
}
2004-12-05 15:38:57 +00:00
if ( buf > = bufs & & ! sv . democausesreconnect )
2004-08-23 00:15:46 +00:00
{
int i ;
entity_state_t from ;
entity_state_t * state ;
edict_t * ent ;
svcustomtents_t * ctent ;
memset ( & from , 0 , sizeof ( from ) ) ;
while ( host_client - > netchan . message . cursize < ( host_client - > netchan . message . maxsize / 2 ) ) //static entities
{
if ( buf - bufs > = sv . numextrastatics )
break ;
state = & sv . extendedstatics [ buf - bufs ] ;
if ( host_client - > fteprotocolextensions & PEXT_SPAWNSTATIC2 )
{
MSG_WriteByte ( & host_client - > netchan . message , svc_spawnstatic2 ) ;
SV_WriteDelta ( & from , state , & host_client - > netchan . message , true , host_client - > fteprotocolextensions ) ;
}
2005-10-19 19:37:16 +00:00
else if ( state - > modelindex < 256 )
2004-08-23 00:15:46 +00:00
{
MSG_WriteByte ( & host_client - > netchan . message , svc_spawnstatic ) ;
MSG_WriteByte ( & host_client - > netchan . message , state - > modelindex & 255 ) ;
MSG_WriteByte ( & host_client - > netchan . message , state - > frame ) ;
MSG_WriteByte ( & host_client - > netchan . message , ( int ) state - > colormap ) ;
MSG_WriteByte ( & host_client - > netchan . message , ( int ) state - > skinnum ) ;
for ( i = 0 ; i < 3 ; i + + )
{
MSG_WriteCoord ( & host_client - > netchan . message , state - > origin [ i ] ) ;
MSG_WriteAngle ( & host_client - > netchan . message , state - > angles [ i ] ) ;
}
}
buf + + ;
}
while ( host_client - > netchan . message . cursize < ( host_client - > netchan . message . maxsize / 2 ) ) //baselines
{
if ( buf - bufs - sv . numextrastatics > = sv . num_edicts )
break ;
ent = EDICT_NUM ( svprogfuncs , buf - bufs - sv . numextrastatics ) ;
2004-10-10 06:32:29 +00:00
state = & ent - > baseline ;
2004-08-23 00:15:46 +00:00
if ( ! state - > number | | ! state - > modelindex )
{ //ent doesn't have a baseline
buf + + ;
continue ;
}
if ( ! ent )
{
MSG_WriteByte ( & host_client - > netchan . message , svc_spawnbaseline ) ;
MSG_WriteShort ( & host_client - > netchan . message , buf - bufs - sv . numextrastatics ) ;
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
for ( i = 0 ; i < 3 ; i + + )
{
MSG_WriteCoord ( & host_client - > netchan . message , 0 ) ;
MSG_WriteAngle ( & host_client - > netchan . message , 0 ) ;
}
}
else if ( host_client - > fteprotocolextensions & PEXT_SPAWNSTATIC2 )
{
2008-05-25 22:23:43 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svcfte_spawnbaseline2 ) ;
2004-08-23 00:15:46 +00:00
SV_WriteDelta ( & from , state , & host_client - > netchan . message , true , host_client - > fteprotocolextensions ) ;
}
2005-10-19 19:37:16 +00:00
else if ( state - > modelindex < 256 )
2004-08-23 00:15:46 +00:00
{
MSG_WriteByte ( & host_client - > netchan . message , svc_spawnbaseline ) ;
MSG_WriteShort ( & host_client - > netchan . message , buf - bufs - sv . numextrastatics ) ;
2005-10-19 19:37:16 +00:00
MSG_WriteByte ( & host_client - > netchan . message , state - > modelindex ) ;
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , state - > frame ) ;
MSG_WriteByte ( & host_client - > netchan . message , ( int ) state - > colormap ) ;
MSG_WriteByte ( & host_client - > netchan . message , ( int ) state - > skinnum ) ;
for ( i = 0 ; i < 3 ; i + + )
{
MSG_WriteCoord ( & host_client - > netchan . message , state - > origin [ i ] ) ;
MSG_WriteAngle ( & host_client - > netchan . message , state - > angles [ i ] ) ;
}
}
buf + + ;
}
while ( host_client - > netchan . message . cursize < ( host_client - > netchan . message . maxsize / 2 ) )
{
i = buf - bufs - sv . numextrastatics - sv . num_edicts ;
if ( i > = 255 )
break ;
ctent = & sv . customtents [ i ] ;
buf + + ;
if ( ! * ctent - > particleeffecttype )
{ //effect isn't registered.
continue ;
}
if ( host_client - > fteprotocolextensions & PEXT_CUSTOMTEMPEFFECTS )
{
2008-05-25 22:23:43 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svcfte_customtempent ) ;
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , 255 ) ;
MSG_WriteByte ( & host_client - > netchan . message , i ) ;
MSG_WriteByte ( & host_client - > netchan . message , ctent - > netstyle ) ;
MSG_WriteString ( & host_client - > netchan . message , ctent - > particleeffecttype ) ;
if ( ctent - > netstyle & CTE_STAINS )
{
MSG_WriteChar ( & host_client - > netchan . message , ctent - > stain [ 0 ] ) ;
MSG_WriteChar ( & host_client - > netchan . message , ctent - > stain [ 0 ] ) ;
MSG_WriteChar ( & host_client - > netchan . message , ctent - > stain [ 0 ] ) ;
MSG_WriteByte ( & host_client - > netchan . message , ctent - > radius ) ;
}
if ( ctent - > netstyle & CTE_GLOWS )
{
MSG_WriteByte ( & host_client - > netchan . message , ctent - > dlightrgb [ 0 ] ) ;
MSG_WriteByte ( & host_client - > netchan . message , ctent - > dlightrgb [ 1 ] ) ;
MSG_WriteByte ( & host_client - > netchan . message , ctent - > dlightrgb [ 2 ] ) ;
MSG_WriteByte ( & host_client - > netchan . message , ctent - > dlightradius ) ;
MSG_WriteByte ( & host_client - > netchan . message , ctent - > dlighttime ) ;
}
}
}
}
2004-12-05 15:38:57 +00:00
else if ( buf > = bufs )
{
buf = bufs + sv . numextrastatics + sv . num_edicts + 255 ;
}
else
2004-08-23 00:15:46 +00:00
{
if ( sv . democausesreconnect )
2005-05-13 10:42:48 +00:00
{
2005-05-15 18:49:04 +00:00
if ( host_client - > netchan . message . cursize + sv . signon_buffer_size [ buf ] + 30 < host_client - > netchan . message . maxsize )
2005-05-13 10:42:48 +00:00
{
2005-07-03 15:16:20 +00:00
SZ_Write ( & host_client - > netchan . message ,
2005-05-13 10:42:48 +00:00
sv . demosignon_buffers [ buf ] ,
sv . demosignon_buffer_size [ buf ] ) ;
buf + + ;
}
}
2004-08-23 00:15:46 +00:00
else
2005-05-13 10:42:48 +00:00
{
2005-05-15 18:49:04 +00:00
if ( host_client - > netchan . message . cursize + sv . signon_buffer_size [ buf ] + 30 < host_client - > netchan . message . maxsize )
2005-05-13 10:42:48 +00:00
{
2005-07-03 15:16:20 +00:00
SZ_Write ( & host_client - > netchan . message ,
2005-05-13 10:42:48 +00:00
sv . signon_buffers [ buf ] ,
sv . signon_buffer_size [ buf ] ) ;
buf + + ;
}
}
2004-08-23 00:15:46 +00:00
}
if ( buf = = bufs + sv . numextrastatics + sv . num_edicts + 255 )
{ // all done prespawning
MSG_WriteByte ( & host_client - > netchan . message , svc_stufftext ) ;
MSG_WriteString ( & host_client - > netchan . message , va ( " cmd spawn %i \n " , svs . spawncount ) ) ;
}
else
{ // need to prespawn more
MSG_WriteByte ( & host_client - > netchan . message , svc_stufftext ) ;
2005-07-03 15:16:20 +00:00
MSG_WriteString ( & host_client - > netchan . message ,
2004-08-23 00:15:46 +00:00
va ( " cmd prespawn %i %i \n " , svs . spawncount , buf ) ) ;
}
}
/*
= = = = = = = = = = = = = = = = = =
SV_Spawn_f
= = = = = = = = = = = = = = = = = =
*/
void SV_Spawn_f ( void )
{
int i ;
client_t * client , * split ;
edict_t * ent ;
2009-03-03 01:52:30 +00:00
int secret_total , secret_found , monsters_total , monsters_found ;
2004-08-23 00:15:46 +00:00
if ( host_client - > state ! = cs_connected )
{
2005-07-28 15:22:15 +00:00
Con_Printf ( " Spawn not valid -- already spawned \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
// handle the case of a level changing while a client was connecting
if ( atoi ( Cmd_Argv ( 1 ) ) ! = svs . spawncount & & ! sv . msgfromdemo )
{
Con_Printf ( " SV_Spawn_f from different level \n " ) ;
SV_New_f ( ) ;
return ;
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// send all current names, colors, and frag counts
// FIXME: is this a good thing?
SZ_Clear ( & host_client - > netchan . message ) ;
// send current status of all other players
// normally this could overflow, but no need to check due to backbuf
for ( i = 0 , client = svs . clients ; i < MAX_CLIENTS ; i + + , client + + )
SV_FullClientUpdateToClient ( client , host_client ) ;
// send all current light styles
for ( i = 0 ; i < MAX_LIGHTSTYLES ; i + + )
{
if ( sv . democausesreconnect )
{
2005-10-01 03:09:17 +00:00
if ( i > = MAX_STANDARDLIGHTSTYLES )
continue ;
2005-07-03 15:16:20 +00:00
ClientReliableWrite_Begin ( host_client , svc_lightstyle ,
2004-08-23 00:15:46 +00:00
3 + ( sv . demolightstyles [ i ] ? strlen ( sv . demolightstyles [ i ] ) : 1 ) ) ;
ClientReliableWrite_Byte ( host_client , ( char ) i ) ;
ClientReliableWrite_String ( host_client , sv . demolightstyles [ i ] ) ;
}
else
{
2005-10-01 03:09:17 +00:00
if ( i > = MAX_STANDARDLIGHTSTYLES )
2006-02-17 02:51:59 +00:00
if ( ! sv . strings . lightstyles [ i ] )
2005-10-01 03:09:17 +00:00
continue ;
# ifdef PEXT_LIGHTSTYLECOL
2006-03-06 01:41:09 +00:00
if ( ( host_client - > fteprotocolextensions & PEXT_LIGHTSTYLECOL ) & & sv . strings . lightstylecolours [ i ] ! = 7 )
2005-10-01 03:09:17 +00:00
{
2008-05-25 22:23:43 +00:00
ClientReliableWrite_Begin ( host_client , svcfte_lightstylecol ,
2006-02-17 02:51:59 +00:00
3 + ( sv . strings . lightstyles [ i ] ? strlen ( sv . strings . lightstyles [ i ] ) : 1 ) ) ;
2005-10-01 03:09:17 +00:00
ClientReliableWrite_Byte ( host_client , ( char ) i ) ;
2006-02-17 02:51:59 +00:00
ClientReliableWrite_Char ( host_client , sv . strings . lightstylecolours [ i ] ) ;
ClientReliableWrite_String ( host_client , sv . strings . lightstyles [ i ] ) ;
2005-10-01 03:09:17 +00:00
}
else
2004-08-23 00:15:46 +00:00
# endif
2005-10-01 03:09:17 +00:00
{
ClientReliableWrite_Begin ( host_client , svc_lightstyle ,
2006-02-17 02:51:59 +00:00
3 + ( sv . strings . lightstyles [ i ] ? strlen ( sv . strings . lightstyles [ i ] ) : 1 ) ) ;
2005-10-01 03:09:17 +00:00
ClientReliableWrite_Byte ( host_client , ( char ) i ) ;
2006-02-17 02:51:59 +00:00
ClientReliableWrite_String ( host_client , sv . strings . lightstyles [ i ] ) ;
2005-10-01 03:09:17 +00:00
}
2004-08-23 00:15:46 +00:00
}
}
2009-03-03 01:52:30 +00:00
# ifdef HLSERVER
if ( svs . gametype = = GT_HALFLIFE )
2004-08-23 00:15:46 +00:00
{
2009-03-03 01:52:30 +00:00
for ( split = host_client ; split ; split = split - > controlled )
2004-08-23 00:15:46 +00:00
{
2009-03-03 01:52:30 +00:00
split - > entgravity = 1 ;
split - > maxspeed = 320 ;
2009-04-01 22:03:56 +00:00
SVHL_PutClientInServer ( split ) ;
2004-08-23 00:15:46 +00:00
}
2009-03-03 01:52:30 +00:00
secret_total = 0 ;
secret_found = 0 ;
monsters_total = 0 ;
monsters_found = 0 ;
}
else
# endif
{
// set up the edict
for ( split = host_client ; split ; split = split - > controlled )
2004-08-23 00:15:46 +00:00
{
2009-03-03 01:52:30 +00:00
ent = split - > edict ;
if ( split - > istobeloaded ) //minimal setup
{
split - > entgravity = ent - > xv - > gravity ;
split - > maxspeed = ent - > xv - > maxspeed ;
}
else
{
SV_SetUpClientEdict ( split , ent ) ;
}
//
// force stats to be updated
//
memset ( host_client - > statsi , 0 , sizeof ( host_client - > statsi ) ) ;
memset ( host_client - > statsf , 0 , sizeof ( host_client - > statsf ) ) ;
memset ( host_client - > statss , 0 , sizeof ( host_client - > statss ) ) ;
2004-08-23 00:15:46 +00:00
}
2009-03-03 01:52:30 +00:00
secret_total = pr_global_struct - > total_secrets ;
secret_found = pr_global_struct - > found_secrets ;
monsters_total = pr_global_struct - > total_monsters ;
monsters_found = pr_global_struct - > killed_monsters ;
2004-08-23 00:15:46 +00:00
}
ClientReliableWrite_Begin ( host_client , svc_updatestatlong , 6 ) ;
ClientReliableWrite_Byte ( host_client , STAT_TOTALSECRETS ) ;
2009-03-03 01:52:30 +00:00
ClientReliableWrite_Long ( host_client , secret_total ) ;
2004-08-23 00:15:46 +00:00
ClientReliableWrite_Begin ( host_client , svc_updatestatlong , 6 ) ;
ClientReliableWrite_Byte ( host_client , STAT_TOTALMONSTERS ) ;
2009-03-03 01:52:30 +00:00
ClientReliableWrite_Long ( host_client , monsters_total ) ;
2004-08-23 00:15:46 +00:00
ClientReliableWrite_Begin ( host_client , svc_updatestatlong , 6 ) ;
ClientReliableWrite_Byte ( host_client , STAT_SECRETS ) ;
2009-03-03 01:52:30 +00:00
ClientReliableWrite_Long ( host_client , secret_found ) ;
2004-08-23 00:15:46 +00:00
ClientReliableWrite_Begin ( host_client , svc_updatestatlong , 6 ) ;
ClientReliableWrite_Byte ( host_client , STAT_MONSTERS ) ;
2009-03-03 01:52:30 +00:00
ClientReliableWrite_Long ( host_client , monsters_found ) ;
2004-08-23 00:15:46 +00:00
// get the client to check and download skins
// when that is completed, a begin command will be issued
ClientReliableWrite_Begin ( host_client , svc_stufftext , 8 ) ;
ClientReliableWrite_String ( host_client , " skins \n " ) ;
}
/*
= = = = = = = = = = = = = = = = = =
SV_SpawnSpectator
= = = = = = = = = = = = = = = = = =
*/
void SV_SpawnSpectator ( void )
{
int i ;
edict_t * e ;
2006-05-29 04:50:24 +00:00
VectorClear ( sv_player - > v - > origin ) ;
VectorClear ( sv_player - > v - > view_ofs ) ;
2005-03-28 00:11:59 +00:00
sv_player - > v - > view_ofs [ 2 ] = DEFAULT_VIEWHEIGHT ;
sv_player - > v - > movetype = MOVETYPE_NOCLIP ;
2004-08-23 00:15:46 +00:00
// search for an info_playerstart to spawn the spectator at
2005-01-17 17:48:13 +00:00
//this is only useful when a mod doesn't nativly support spectators. old qw on nq mods.
2004-10-26 15:33:33 +00:00
for ( i = MAX_CLIENTS + 1 ; i < sv . num_edicts ; i + + )
2004-08-23 00:15:46 +00:00
{
e = EDICT_NUM ( svprogfuncs , i ) ;
2005-03-28 00:11:59 +00:00
if ( ! strcmp ( PR_GetString ( svprogfuncs , e - > v - > classname ) , " info_player_start " ) )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
VectorCopy ( e - > v - > origin , sv_player - > v - > origin ) ;
2004-08-23 00:15:46 +00:00
return ;
}
}
}
2008-11-09 22:29:28 +00:00
void SV_Begin_Core ( client_t * split )
{ //this is the client-protocol-independant core, for q1/q2 gamecode
2004-08-23 00:15:46 +00:00
2008-11-09 22:29:28 +00:00
client_t * oh ;
int i ;
2009-04-19 00:50:42 +00:00
if ( progstype = = PROG_H2 & & split - > playerclass )
split - > edict - > xv - > playerclass = host_client - > playerclass ; //make sure it's set the same as the userinfo
2009-03-03 01:52:30 +00:00
2005-03-18 06:13:11 +00:00
# ifdef Q2SERVER
2009-03-03 01:52:30 +00:00
if ( ge )
{
2009-04-01 22:03:56 +00:00
ge - > ClientUserinfoChanged ( split - > q2edict , split - > userinfo ) ; //tell the gamecode
SV_ExtractFromUserinfo ( split ) ; //let the server routines know
2009-03-03 01:52:30 +00:00
ge - > ClientBegin ( split - > q2edict ) ;
split - > istobeloaded = false ;
}
else
# endif
if ( split - > istobeloaded )
{
func_t f ;
split - > istobeloaded = false ;
f = PR_FindFunction ( svprogfuncs , " RestoreGame " , PR_ANY ) ;
if ( f )
2005-03-18 06:13:11 +00:00
{
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , split - > edict ) ;
PR_ExecuteProgram ( svprogfuncs , f ) ;
2005-03-18 06:13:11 +00:00
}
2009-03-03 01:52:30 +00:00
}
else
{
if ( split - > spectator )
2004-08-23 00:15:46 +00:00
{
2009-03-03 01:52:30 +00:00
SV_SpawnSpectator ( ) ;
2006-01-21 00:06:49 +00:00
2009-03-03 01:52:30 +00:00
if ( SpectatorConnect )
2006-01-21 00:06:49 +00:00
{
2009-03-03 01:52:30 +00:00
//keep the spectator tracking the player from the previous map
if ( split - > spec_track > 0 )
split - > edict - > v - > goalentity = EDICT_TO_PROG ( svprogfuncs , svs . clients [ split - > spec_track - 1 ] . edict ) ;
else
split - > edict - > v - > goalentity = 0 ;
// copy spawn parms out of the client_t
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
{
if ( spawnparamglobals [ i ] )
* spawnparamglobals [ i ] = split - > spawn_parms [ i ] ;
}
// call the spawn function
pr_global_struct - > time = sv . physicstime ;
2006-01-21 00:06:49 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , split - > edict ) ;
2009-03-03 01:52:30 +00:00
PR_ExecuteProgram ( svprogfuncs , SpectatorConnect ) ;
2006-01-21 00:06:49 +00:00
}
2004-08-23 00:15:46 +00:00
}
else
{
2009-03-03 01:52:30 +00:00
if ( svprogfuncs )
{
eval_t * eval , * eval2 ;
eval = PR_FindGlobal ( svprogfuncs , " ClientReEnter " , 0 ) ;
if ( eval & & split - > spawninfo )
{
globalvars_t * pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
int j ;
edict_t * ent ;
ent = split - > edict ;
j = strlen ( split - > spawninfo ) ;
SV_UnlinkEdict ( ent ) ;
svprogfuncs - > restoreent ( svprogfuncs , split - > spawninfo , & j , ent ) ;
eval2 = svprogfuncs - > GetEdictFieldValue ( svprogfuncs , ent , " stats_restored " , NULL ) ;
if ( eval2 )
eval2 - > _float = 1 ;
for ( j = 0 ; j < NUM_SPAWN_PARMS ; j + + )
{
if ( spawnparamglobals [ j ] )
* spawnparamglobals [ j ] = split - > spawn_parms [ j ] ;
}
pr_global_struct - > time = sv . physicstime ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , ent ) ;
G_FLOAT ( OFS_PARM0 ) = sv . time - split - > spawninfotime ;
PR_ExecuteProgram ( svprogfuncs , eval - > function ) ;
}
else
2004-08-23 00:15:46 +00:00
{
// copy spawn parms out of the client_t
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
2005-06-22 17:10:13 +00:00
{
if ( spawnparamglobals [ i ] )
* spawnparamglobals [ i ] = split - > spawn_parms [ i ] ;
}
2004-08-23 00:15:46 +00:00
// call the spawn function
2007-09-02 19:55:17 +00:00
# ifdef VM_Q1
2009-03-03 01:52:30 +00:00
if ( svs . gametype = = GT_Q1QVM )
Q1QVM_ClientConnect ( split ) ;
else
2007-09-02 19:55:17 +00:00
# endif
2009-03-03 01:52:30 +00:00
{
2009-04-19 00:50:42 +00:00
globalvars_t * pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , split - > edict ) ;
2009-04-19 00:50:42 +00:00
G_FLOAT ( OFS_PARM0 ) = split - > csqcactive ; //this arg is part of EXT_CSQC_1, but doesn't have to be supported by the mod
2009-03-03 01:52:30 +00:00
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > ClientConnect ) ;
// actually spawn the player
pr_global_struct - > time = sv . physicstime ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , split - > edict ) ;
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > PutClientInServer ) ;
}
2004-08-23 00:15:46 +00:00
2009-03-03 01:52:30 +00:00
oh = host_client ;
host_client = split ;
sv_player = host_client - > edict ;
SV_PreRunCmd ( ) ;
{
usercmd_t cmd ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
cmd . msec = 0 ;
2004-08-23 00:15:46 +00:00
# define ANGLE2SHORT(x) (x) * (65536 / 360.0)
2009-03-03 01:52:30 +00:00
cmd . angles [ 0 ] = ANGLE2SHORT ( split - > edict - > v - > v_angle [ 0 ] ) ;
cmd . angles [ 1 ] = ANGLE2SHORT ( split - > edict - > v - > v_angle [ 1 ] ) ;
cmd . angles [ 2 ] = ANGLE2SHORT ( split - > edict - > v - > v_angle [ 2 ] ) ;
SV_RunCmd ( & cmd , false ) ;
2004-08-23 00:15:46 +00:00
}
2009-03-03 01:52:30 +00:00
SV_PostRunCmd ( ) ;
host_client = oh ;
sv_player = host_client - > edict ;
2004-08-23 00:15:46 +00:00
}
}
}
}
2009-03-03 01:52:30 +00:00
}
2004-08-23 00:15:46 +00:00
2008-11-09 22:29:28 +00:00
/*
= = = = = = = = = = = = = = = = = =
SV_Begin_f
= = = = = = = = = = = = = = = = = =
*/
void SV_Begin_f ( void )
{
client_t * split ;
unsigned pmodel = 0 , emodel = 0 ;
qboolean sendangles = false ;
if ( ! SV_CheckRealIP ( host_client , true ) )
{
if ( host_client - > protocol = = SCP_QUAKE2 )
ClientReliableWrite_Begin ( host_client , svcq2_stufftext , 13 + strlen ( Cmd_Args ( ) ) ) ;
else
ClientReliableWrite_Begin ( host_client , svc_stufftext , 13 + strlen ( Cmd_Args ( ) ) ) ;
ClientReliableWrite_String ( host_client , va ( " cmd begin %s \n " , Cmd_Args ( ) ) ) ;
return ;
}
if ( host_client - > state = = cs_spawned )
return ; // don't begin again
for ( split = host_client ; split ; split = split - > controlled )
split - > state = cs_spawned ;
// handle the case of a level changing while a client was connecting
if ( atoi ( Cmd_Argv ( 1 ) ) ! = svs . spawncount & & ! sv . msgfromdemo )
{
Con_Printf ( " SV_Begin_f from different level \n " ) ;
SV_New_f ( ) ;
return ;
}
if ( host_client - > istobeloaded )
sendangles = true ;
for ( split = host_client ; split ; split = split - > controlled )
{ //tell the gamecode they're ready
SV_Begin_Core ( split ) ;
}
2004-08-23 00:15:46 +00:00
// clear the net statistics, because connecting gives a bogus picture
host_client - > netchan . frame_latency = 0 ;
host_client - > netchan . frame_rate = 0 ;
host_client - > netchan . drop_count = 0 ;
host_client - > netchan . good_count = 0 ;
//check he's not cheating
if ( progstype = = PROG_QW )
{
pmodel = atoi ( Info_ValueForKey ( host_client - > userinfo , " pmodel " ) ) ;
emodel = atoi ( Info_ValueForKey ( host_client - > userinfo , " emodel " ) ) ;
if ( pmodel ! = sv . model_player_checksum | |
emodel ! = sv . eyes_player_checksum )
SV_BroadcastTPrintf ( PRINT_HIGH , STL_POSSIBLEMODELCHEAT , host_client - > name ) ;
}
// if we are paused, tell the client
if ( sv . paused )
{
2005-05-26 12:55:34 +00:00
if ( ! ISQ2CLIENT ( host_client ) )
2004-08-23 00:15:46 +00:00
{
ClientReliableWrite_Begin ( host_client , svc_setpause , 2 ) ;
ClientReliableWrite_Byte ( host_client , sv . paused ) ;
}
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_SERVERPAUSED ) ;
}
if ( sendangles )
{
//
// send a fixangle over the reliable channel to make sure it gets there
// Never send a roll angle, because savegames can catch the server
// in a state where it is expecting the client to correct the angle
// and it won't happen if the game was just loaded, so you wind up
2005-07-03 15:16:20 +00:00
// with a permanent head tilt
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svc_setangle ) ;
MSG_WriteAngle ( & host_client - > netchan . message , 0 ) ;
2005-03-28 00:11:59 +00:00
MSG_WriteAngle ( & host_client - > netchan . message , host_client - > edict - > v - > angles [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
MSG_WriteAngle ( & host_client - > netchan . message , 0 ) ;
}
}
//=============================================================================
2007-06-20 00:02:54 +00:00
//dp downloads are a 2-stream system
//the server->client stream is as you'd expect. except that its unreliable rather than reliable
//the client->server stream contains no actual data.
//when c2s has a hole, the s2c stream is reset to the last-known 'good' position.
//eventually the client is left acking packets with no data in them, the server then tells the client that the download is complete.
//the client does no checks to see if there's a hole, other than the crc
//so any single lost packet (even client->server) means that the entire stream will be set back by your ping time
void SV_DarkPlacesDownloadChunk ( client_t * cl , sizebuf_t * msg )
2007-06-10 21:33:24 +00:00
{
# define MAXDPDOWNLOADCHUNK 1024
char buffer [ MAXDPDOWNLOADCHUNK ] ;
int size , start ;
2007-06-20 00:02:54 +00:00
if ( ! ISNQCLIENT ( cl ) )
return ;
if ( ! cl - > download )
return ;
if ( ! cl - > downloadstarted )
return ;
2007-06-10 21:33:24 +00:00
if ( cl - > num_backbuf )
2007-06-20 00:02:54 +00:00
return ;
size = 1024 ; //fixme
if ( size > cl - > datagram . maxsize - cl - > datagram . cursize )
size = cl - > datagram . maxsize - cl - > datagram . cursize - 16 ;
2007-06-10 21:33:24 +00:00
if ( size > MAXDPDOWNLOADCHUNK ) //don't clog it too much
size = MAXDPDOWNLOADCHUNK ;
start = VFS_TELL ( cl - > download ) ;
if ( start + size > cl - > downloadsize ) //clamp to the size of the file.
size = cl - > downloadsize - start ;
2007-06-20 00:02:54 +00:00
size = VFS_READ ( cl - > download , buffer , size ) ;
if ( size < 0 )
size = 0 ;
2007-06-10 21:33:24 +00:00
2007-06-20 00:02:54 +00:00
MSG_WriteByte ( msg , svcdp_downloaddata ) ;
MSG_WriteLong ( msg , start ) ;
MSG_WriteShort ( msg , size ) ;
SZ_Write ( msg , buffer , size ) ;
2007-06-10 21:33:24 +00:00
}
2007-06-20 00:02:54 +00:00
void SVDP_StartDownload_f ( void )
2007-06-10 21:33:24 +00:00
{
if ( host_client - > protocol ! = SCP_DARKPLACES7 )
return ;
2007-06-20 00:02:54 +00:00
if ( ! host_client - > download )
return ;
host_client - > downloadstarted = true ;
2007-06-10 21:33:24 +00:00
}
void SV_DarkPlacesDownloadAck ( client_t * cl )
{
int start = MSG_ReadLong ( ) ;
int size = ( unsigned short ) MSG_ReadShort ( ) ;
2007-06-20 00:02:54 +00:00
if ( ! cl - > download )
return ;
if ( start ! = cl - > downloadacked )
{
//packetloss
VFS_SEEK ( cl - > download , cl - > downloadacked ) ;
}
else if ( size ! = 0 )
{
cl - > downloadacked + = size ; //successful packet
cl - > downloadcount = cl - > downloadacked ;
}
else
2007-06-10 21:33:24 +00:00
{
char * s ;
unsigned short crc ;
int pos = 0 , csize ;
qbyte chunk [ 1024 ] ;
QCRC_Init ( & crc ) ;
VFS_SEEK ( host_client - > download , 0 ) ;
while ( pos < host_client - > downloadsize )
{
csize = sizeof ( chunk ) ;
if ( pos + csize > host_client - > downloadsize )
csize = host_client - > downloadsize - pos ;
VFS_READ ( host_client - > download , chunk , csize ) ;
QCRC_AddBlock ( & crc , chunk , csize ) ;
pos + = csize ;
}
s = va ( " \n cl_downloadfinished %i %i \" \" \n " , host_client - > downloadsize , crc ) ;
ClientReliableWrite_Begin ( cl , svc_stufftext , 2 + strlen ( s ) ) ;
ClientReliableWrite_String ( cl , s ) ;
2007-06-20 00:02:54 +00:00
VFS_CLOSE ( host_client - > download ) ;
host_client - > download = NULL ;
host_client - > downloadsize = 0 ;
2007-06-10 21:33:24 +00:00
}
}
2009-04-06 00:34:32 +00:00
void SV_NextChunkedDownload ( unsigned int chunknum , int ezpercent , int ezfilenum )
2005-01-16 02:24:05 +00:00
{
# define CHUNKSIZE 1024
2006-10-18 23:27:39 +00:00
char buffer [ CHUNKSIZE ] ;
2008-11-09 22:29:28 +00:00
qbyte oobdata [ 1 + ( sizeof ( " \\ chunk " ) - 1 ) + 4 + 1 + 4 + CHUNKSIZE ] ;
sizebuf_t * msg , msg_oob ;
2006-10-15 19:31:24 +00:00
int i ;
2008-11-09 22:29:28 +00:00
qboolean error = false ;
msg = & host_client - > datagram ;
2009-04-06 00:34:32 +00:00
if ( chunknum * CHUNKSIZE > host_client - > downloadsize )
2008-11-09 22:29:28 +00:00
{
2009-04-06 00:34:32 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " Invalid file chunk requested %u to %u of %u. \n " , chunknum * CHUNKSIZE , ( chunknum + 1 ) * CHUNKSIZE , host_client - > downloadsize ) ;
2008-11-09 22:29:28 +00:00
error = true ;
}
if ( ! error & & VFS_SEEK ( host_client - > download , chunknum * CHUNKSIZE ) = = false )
error = true ;
else
{
if ( host_client - > downloadcount < chunknum * CHUNKSIZE )
host_client - > downloadcount = chunknum * CHUNKSIZE ;
}
2006-10-15 19:31:24 +00:00
2005-03-10 03:55:18 +00:00
if ( host_client - > datagram . cursize + CHUNKSIZE + 5 + 50 > host_client - > datagram . maxsize )
2008-11-09 22:29:28 +00:00
{
//would overflow the packet.
msg = & msg_oob ;
2006-10-15 19:45:33 +00:00
2008-11-09 22:29:28 +00:00
if ( ! ezfilenum )
return ;
2009-05-24 10:11:17 +00:00
if ( host_client - > waschoked )
return ; //don't let chunked downloads flood out the standard packets.
2008-11-09 22:29:28 +00:00
if ( ! Netchan_CanPacket ( & host_client - > netchan , SV_RateForClient ( host_client ) ) )
return ;
}
2006-10-15 19:45:33 +00:00
2008-11-09 22:29:28 +00:00
if ( error )
i = 0 ;
else
i = VFS_READ ( host_client - > download , buffer , CHUNKSIZE ) ;
2005-01-16 02:24:05 +00:00
2006-10-15 19:31:24 +00:00
if ( i > 0 )
{
2009-04-06 00:34:32 +00:00
if ( msg = = & msg_oob )
2008-11-09 22:29:28 +00:00
{
msg = & msg_oob ;
msg - > cursize = 0 ;
msg - > maxsize = sizeof ( oobdata ) ;
msg - > currentbit = 0 ;
msg - > packing = SZ_RAWBYTES ;
msg - > allowoverflow = 0 ;
msg - > overflowed = 0 ;
msg - > data = oobdata ;
MSG_WriteByte ( msg , A2C_PRINT ) ;
SZ_Write ( msg , " \\ chunk " , 6 ) ;
2009-04-06 00:34:32 +00:00
MSG_WriteLong ( msg , ezfilenum ) ; //echoing the file num is used so the packets don't go out of sync.
2008-11-09 22:29:28 +00:00
}
2006-10-15 19:31:24 +00:00
if ( i ! = CHUNKSIZE )
2006-10-18 23:27:39 +00:00
memset ( buffer + i , 0 , CHUNKSIZE - i ) ;
2006-10-15 19:31:24 +00:00
2008-11-09 22:29:28 +00:00
MSG_WriteByte ( msg , svc_download ) ;
MSG_WriteLong ( msg , chunknum ) ;
SZ_Write ( msg , buffer , CHUNKSIZE ) ;
if ( msg = = & msg_oob )
{
Netchan_OutOfBand ( NS_SERVER , host_client - > netchan . remote_address , msg_oob . cursize , msg_oob . data ) ;
Netchan_Block ( & host_client - > netchan , msg_oob . cursize , SV_RateForClient ( host_client ) ) ;
}
}
else if ( i < 0 )
error = true ;
if ( error )
{
VFS_CLOSE ( host_client - > download ) ;
host_client - > download = NULL ;
ClientReliableWrite_Begin ( host_client , svc_download , 10 + strlen ( host_client - > downloadfn ) ) ;
ClientReliableWrite_Long ( host_client , - 1 ) ;
ClientReliableWrite_Long ( host_client , - 3 ) ;
ClientReliableWrite_String ( host_client , host_client - > downloadfn ) ;
host_client - > downloadstarted = false ;
2006-10-15 19:31:24 +00:00
}
2005-01-16 02:24:05 +00:00
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = =
SV_NextDownload_f
= = = = = = = = = = = = = = = = = =
*/
void SV_NextDownload_f ( void )
{
qbyte buffer [ 1024 ] ;
int r ;
int percent ;
int size ;
if ( ! host_client - > download )
return ;
2005-01-16 19:55:35 +00:00
# ifdef PEXT_CHUNKEDDOWNLOADS
2005-01-16 02:24:05 +00:00
if ( host_client - > fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS )
{
2009-04-06 00:34:32 +00:00
if ( Cmd_Argc ( ) < 2 )
SV_NextChunkedDownload ( atoi ( Cmd_Argv ( 1 ) ) , atoi ( Cmd_Argv ( 2 ) ) , atoi ( Cmd_Argv ( 3 ) ) ) ;
else
SV_NextChunkedDownload ( atoi ( Cmd_Argv ( 1 ) ) , atoi ( Cmd_Argv ( 2 ) ) , atoi ( Cmd_Argv ( 3 ) ) ) ;
2005-01-16 02:24:05 +00:00
return ;
}
2005-01-16 19:55:35 +00:00
# endif
2005-01-16 02:24:05 +00:00
2004-08-23 00:15:46 +00:00
r = host_client - > downloadsize - host_client - > downloadcount ;
/*
# ifdef PEXT_ZLIBDL
if ( host_client - > protocolextensions & PEXT_ZLIBDL )
{
if ( r > 1024 ) //expect a little more.
r = 1024 ;
}
else
# endif
*/
if ( r > 768 )
r = 768 ;
2005-12-21 03:07:33 +00:00
r = VFS_READ ( host_client - > download , buffer , r ) ;
2005-05-26 12:55:34 +00:00
ClientReliableWrite_Begin ( host_client , ISQ2CLIENT ( host_client ) ? svcq2_download : svc_download , 6 + r ) ;
2004-08-23 00:15:46 +00:00
ClientReliableWrite_Short ( host_client , r ) ;
host_client - > downloadcount + = r ;
size = host_client - > downloadsize ;
2006-08-02 05:34:17 +00:00
if ( host_client - > downloadcount < size )
{
if ( ! size )
size = 1 ;
percent = ( double ) host_client - > downloadcount * 100.0 / size ;
percent = bound ( 0 , percent , 99 ) ;
}
else
percent = 100 ;
2004-08-23 00:15:46 +00:00
# ifdef PEXT_ZLIBDL
if ( host_client - > fteprotocolextensions & PEXT_ZLIBDL )
{
ClientReliableWrite_Byte ( host_client , percent + 101 ) ;
ClientReliableWrite_ZLib ( host_client , buffer , r ) ;
}
else
# endif
{
ClientReliableWrite_Byte ( host_client , percent ) ;
ClientReliableWrite_SZ ( host_client , buffer , r ) ;
}
2006-08-02 05:34:17 +00:00
if ( host_client - > downloadcount < host_client - > downloadsize )
2004-08-23 00:15:46 +00:00
return ;
2005-12-21 03:07:33 +00:00
VFS_CLOSE ( host_client - > download ) ;
2004-08-23 00:15:46 +00:00
host_client - > download = NULL ;
}
void VARGS OutofBandPrintf ( netadr_t where , char * fmt , . . . )
{
va_list argptr ;
char send [ 1024 ] ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
send [ 0 ] = 0xff ;
send [ 1 ] = 0xff ;
send [ 2 ] = 0xff ;
send [ 3 ] = 0xff ;
send [ 4 ] = A2C_PRINT ;
va_start ( argptr , fmt ) ;
vsprintf ( send + 5 , fmt , argptr ) ;
va_end ( argptr ) ;
NET_SendPacket ( NS_SERVER , strlen ( send ) + 1 , send , where ) ;
}
/*
= = = = = = = = = = = = = = = = = =
SV_NextUpload
= = = = = = = = = = = = = = = = = =
*/
void SV_NextUpload ( void )
{
int percent ;
int size ;
if ( ! * host_client - > uploadfn )
{
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_UPLOADDENIED ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 8 ) ;
ClientReliableWrite_String ( host_client , " stopul " ) ;
// suck out rest of packet
size = MSG_ReadShort ( ) ; MSG_ReadByte ( ) ;
msg_readcount + = size ;
return ;
}
size = MSG_ReadShort ( ) ;
percent = MSG_ReadByte ( ) ;
if ( ! host_client - > upload )
{
2005-12-21 03:07:33 +00:00
host_client - > upload = FS_OpenVFS ( host_client - > uploadfn , " wb " , FS_GAME ) ;
2004-08-23 00:15:46 +00:00
if ( ! host_client - > upload )
{
Sys_Printf ( " Can't create %s \n " , host_client - > uploadfn ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 8 ) ;
ClientReliableWrite_String ( host_client , " stopul " ) ;
* host_client - > uploadfn = 0 ;
return ;
}
Con_Printf ( " Receiving %s from %d... \n " , host_client - > uploadfn , host_client - > userid ) ;
if ( host_client - > remote_snap )
OutofBandPrintf ( host_client - > snap_from , " Server receiving %s from %d... \n " , host_client - > uploadfn , host_client - > userid ) ;
}
2005-12-21 03:07:33 +00:00
VFS_WRITE ( host_client - > upload , net_message . data + msg_readcount , size ) ;
2004-08-23 00:15:46 +00:00
msg_readcount + = size ;
if ( percent ! = 100 )
{
ClientReliableWrite_Begin ( host_client , svc_stufftext , 8 ) ;
ClientReliableWrite_String ( host_client , " nextul \n " ) ;
}
else
{
2005-12-21 03:07:33 +00:00
VFS_CLOSE ( host_client - > upload ) ;
2004-08-23 00:15:46 +00:00
host_client - > upload = NULL ;
Con_Printf ( " %s upload completed. \n " , host_client - > uploadfn ) ;
if ( host_client - > remote_snap )
{
char * p ;
if ( ( p = strchr ( host_client - > uploadfn , ' / ' ) ) ! = NULL )
p + + ;
else
p = host_client - > uploadfn ;
2005-07-03 15:16:20 +00:00
OutofBandPrintf ( host_client - > snap_from , " %s upload completed. \n To download, enter: \n download %s \n " ,
2004-08-23 00:15:46 +00:00
host_client - > uploadfn , p ) ;
}
}
}
2004-09-20 23:25:38 +00:00
//Use of this function is on name only.
//Be aware that the maps directory should be restricted based on weather the file was from a pack file
//this is to preserve copyright - please do not breach due to a bug.
2009-04-01 22:03:56 +00:00
qboolean SV_AllowDownload ( const char * name )
2004-08-23 00:15:46 +00:00
{
extern cvar_t allow_download ;
extern cvar_t allow_download_skins ;
extern cvar_t allow_download_models ;
extern cvar_t allow_download_sounds ;
extern cvar_t allow_download_demos ;
2004-09-20 23:25:38 +00:00
extern cvar_t allow_download_maps ;
extern cvar_t allow_download_textures ;
extern cvar_t allow_download_pk3s ;
extern cvar_t allow_download_wads ;
2004-08-23 00:15:46 +00:00
extern cvar_t allow_download_root ;
2005-12-21 03:07:33 +00:00
extern cvar_t allow_download_configs ;
2004-09-20 23:25:38 +00:00
//allowed at all?
if ( ! allow_download . value )
return false ;
2004-08-23 00:15:46 +00:00
2004-09-20 23:25:38 +00:00
//no subdirs?
if ( strstr ( name , " .. " ) ) //no under paths.
return false ;
if ( * name = = ' . ' ) //relative is pointless
return false ;
if ( * name = = ' / ' ) //no absolute.
2004-08-23 00:15:46 +00:00
return false ;
2004-09-20 23:25:38 +00:00
if ( strchr ( name , ' \\ ' ) ) //no windows paths - grow up lame windows users.
return false ;
2005-10-19 19:37:16 +00:00
if ( strncmp ( name , " maps/ " , 5 ) = = 0 )
return ! ! allow_download_maps . value ;
2004-09-20 23:25:38 +00:00
//skins?
2005-10-19 19:37:16 +00:00
if ( strncmp ( name , " skins/ " , 6 ) = = 0 )
return ! ! allow_download_skins . value ;
2004-09-20 23:25:38 +00:00
//models
2007-08-31 23:35:28 +00:00
if ( ( strncmp ( name , " progs/ " , 6 ) = = 0 ) | |
( strncmp ( name , " models/ " , 7 ) = = 0 ) )
2005-10-19 19:37:16 +00:00
return ! ! allow_download_models . value ;
2004-09-20 23:25:38 +00:00
//sound
2005-10-19 19:37:16 +00:00
if ( strncmp ( name , " sound/ " , 6 ) = = 0 )
return ! ! allow_download_sounds . value ;
2004-09-20 23:25:38 +00:00
//demos
2005-10-19 19:37:16 +00:00
if ( strncmp ( name , " demos/ " , 6 ) = = 0 )
return ! ! allow_download_demos . value ;
2004-09-20 23:25:38 +00:00
//textures
2007-08-31 23:35:28 +00:00
if ( strncmp ( name , " textures/ " , 9 ) = = 0 )
2005-10-19 19:37:16 +00:00
return ! ! allow_download_textures . value ;
2004-09-20 23:25:38 +00:00
//wads
2005-10-19 19:37:16 +00:00
if ( strncmp ( name , " wads/ " , 5 ) = = 0 )
return ! ! allow_download_wads . value ;
2007-08-31 17:06:29 +00:00
if ( ! strcmp ( " wad " , COM_FileExtension ( name ) ) )
2005-10-19 19:37:16 +00:00
return ! ! allow_download_wads . value ;
2004-09-20 23:25:38 +00:00
//pk3s.
2007-08-31 17:06:29 +00:00
if ( ! strcmp ( " pk3 " , COM_FileExtension ( name ) ) | | ! strcmp ( " pak " , COM_FileExtension ( name ) ) )
2004-09-20 23:25:38 +00:00
if ( strnicmp ( name , " pak " , 3 ) ) //don't give out q3 pk3 files.
2005-10-19 19:37:16 +00:00
return ! ! allow_download_pk3s . value ;
2004-09-20 23:25:38 +00:00
2007-08-31 17:06:29 +00:00
if ( ! strcmp ( " cfg " , COM_FileExtension ( name ) ) )
2005-12-21 03:07:33 +00:00
return ! ! allow_download_configs . value ;
2004-09-20 23:25:38 +00:00
//root of gamedir
2004-12-05 08:22:06 +00:00
if ( ! strchr ( name , ' / ' ) & & ! allow_download_root . value )
2005-08-11 04:14:33 +00:00
{
2008-11-09 22:29:28 +00:00
if ( strcmp ( name , " csprogs.dat " ) ) //we always allow csprogs.dat to be downloaded (if downloads are permitted).
2005-08-11 04:14:33 +00:00
return false ;
}
2004-09-20 23:25:38 +00:00
//any other subdirs are allowed
2004-08-23 00:15:46 +00:00
return true ;
}
2008-11-09 22:29:28 +00:00
static int SV_LocateDownload ( char * name , flocation_t * loc , char * * replacementname , qboolean redirectpaks )
2004-08-23 00:15:46 +00:00
{
2005-03-24 18:32:44 +00:00
extern cvar_t allow_download_anymap , allow_download_pakcontents ;
2007-09-01 04:36:17 +00:00
extern cvar_t sv_demoDir ;
2008-11-09 22:29:28 +00:00
qboolean protectedpak ;
qboolean found ;
2005-03-07 08:58:26 +00:00
2008-11-09 22:29:28 +00:00
if ( replacementname )
* replacementname = NULL ;
//mangle the name by making it lower case.
2007-08-31 23:35:28 +00:00
{
2008-11-09 22:29:28 +00:00
char * p ;
for ( p = name ; * p ; p + + )
* p = ( char ) tolower ( * p ) ;
2007-08-31 23:35:28 +00:00
}
2008-11-09 22:29:28 +00:00
if ( ! SV_AllowDownload ( name ) )
return - 2 ; //not permitted (even if it exists).
//mvdsv demo downloading support demonum/ -> demos/XXXX (sets up the client paths)
2005-03-07 08:58:26 +00:00
if ( ! strncmp ( name , " demonum/ " , 8 ) )
2007-06-10 21:33:24 +00:00
{
2008-11-09 22:29:28 +00:00
if ( replacementname )
2007-09-10 18:22:33 +00:00
{
2008-11-09 22:29:28 +00:00
char mvdnamebuffer [ MAX_QPATH ] ;
char * mvdname = SV_MVDNum ( mvdnamebuffer , sizeof ( mvdnamebuffer ) , atoi ( name + 8 ) ) ;
if ( ! mvdname )
{
SV_ClientPrintf ( host_client , PRINT_HIGH , " %s is an invalid MVD demonum. \n " , name + 8 ) ;
Sys_Printf ( " %s requested invalid demonum %s \n " , host_client - > name , name + 8 ) ;
return - 1 ; //not found
}
* replacementname = va ( " demos/%s \n " , mvdname ) ;
return - 4 ; //redirect
2007-09-01 04:36:17 +00:00
}
2008-11-09 22:29:28 +00:00
}
2007-09-01 04:36:17 +00:00
2008-11-09 22:29:28 +00:00
//mvdsv demo downloading support. demos/ -> demodir (sets up the server paths)
if ( ! strncmp ( name , " demos/ " , 6 ) )
name = va ( " %s/%s " , sv_demoDir . string , name + 6 ) ;
found = FS_FLocateFile ( name , FSLFRT_IFFOUND , loc ) ;
//nexuiz names certain files as .wav but they're really .ogg on disk.
if ( ! found & & replacementname )
{
if ( ! strcmp ( COM_FileExtension ( name ) , " wav " ) )
2007-09-01 04:36:17 +00:00
{
2008-11-09 22:29:28 +00:00
char tryogg [ MAX_QPATH ] ;
COM_StripExtension ( name , tryogg , sizeof ( tryogg ) ) ;
COM_DefaultExtension ( tryogg , " .ogg " , sizeof ( tryogg ) ) ;
found = FS_FLocateFile ( tryogg , FSLFRT_IFFOUND , loc ) ;
if ( found )
{
name = * replacementname = va ( " %s " , tryogg ) ;
}
2007-09-01 04:36:17 +00:00
}
2008-11-09 22:29:28 +00:00
}
//nexuiz also names files with absolute paths (yet sounds are meant to have an extra prefix)
//this results in clients asking for sound/sound/blah.wav (or sound/sound/blah.ogg for nexuiz)
if ( ! found & & replacementname )
{
if ( ! strncmp ( name , " sound/ " , 6 ) )
2007-09-01 04:36:17 +00:00
{
2008-11-09 22:29:28 +00:00
int result ;
result = SV_LocateDownload ( name + 6 , loc , replacementname , redirectpaks ) ;
if ( ! result )
{ //if that was successful... redirect to it.
result = - 4 ;
* replacementname = name + 6 ;
}
return result ;
2007-09-01 04:36:17 +00:00
}
2008-11-09 22:29:28 +00:00
}
if ( found )
{
protectedpak = com_file_copyprotected ;
// special check for maps, if it came from a pak file, don't allow download
if ( protectedpak )
2007-09-01 04:36:17 +00:00
{
2008-11-09 22:29:28 +00:00
if ( ! allow_download_anymap . value & & ! strncmp ( name , " maps/ " , 5 ) )
return - 2 ;
2007-08-31 23:35:28 +00:00
}
2007-09-01 01:38:18 +00:00
2008-11-09 22:29:28 +00:00
if ( replacementname )
2007-09-01 04:36:17 +00:00
{
2008-11-09 22:29:28 +00:00
char * pakname = FS_WhichPackForLocation ( loc ) ;
if ( pakname & & SV_AllowDownload ( pakname ) )
{
//return loc of the pak instead.
if ( FS_FLocateFile ( name , FSLFRT_IFFOUND , loc ) )
{
//its inside a pak file, return the name of this file instead
* replacementname = pakname ;
return - 4 ; //redirect
}
else
Con_Printf ( " Failed to read %s \n " , pakname ) ;
}
2007-09-01 04:36:17 +00:00
}
2008-11-09 22:29:28 +00:00
if ( protectedpak )
{ //if its in a pak file, don't allow downloads if we don't allow the contents of paks to be sent.
if ( ! allow_download_pakcontents . value )
return - 2 ;
}
if ( replacementname & & * replacementname )
return - 4 ;
return 0 ;
2007-06-10 21:33:24 +00:00
}
2008-11-09 22:29:28 +00:00
return - 1 ; //not found
}
2007-06-10 21:33:24 +00:00
2008-11-09 22:29:28 +00:00
//this function is only meaningful for nq/qw
void SV_DownloadSize_f ( void )
{
flocation_t loc ;
char * name = Cmd_Argv ( 1 ) ;
char * redirected = " " ;
2007-06-20 00:02:54 +00:00
2008-11-09 22:29:28 +00:00
switch ( SV_LocateDownload ( name , & loc , & redirected , true ) )
{
case - 4 :
name = va ( " dlsize \" %s \" r \" %s \" \n " , name , redirected ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 2 + strlen ( name ) ) ;
ClientReliableWrite_String ( host_client , name ) ;
break ;
default :
case - 1 :
name = va ( " dlsize \" %s \" e \n " , name ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 2 + strlen ( name ) ) ;
ClientReliableWrite_String ( host_client , name ) ;
break ;
case - 2 :
name = va ( " dlsize \" %s \" p \n " , name ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 2 + strlen ( name ) ) ;
ClientReliableWrite_String ( host_client , name ) ;
break ;
case 0 :
name = va ( " dlsize \" %s \" %u \n " , name , loc . len ) ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 2 + strlen ( name ) ) ;
ClientReliableWrite_String ( host_client , name ) ;
break ;
}
}
/*
= = = = = = = = = = = = = = = = = =
SV_BeginDownload_f
= = = = = = = = = = = = = = = = = =
*/
void SV_BeginDownload_f ( void )
{
char * name = Cmd_Argv ( 1 ) ;
char * redirection = NULL ;
extern cvar_t allow_download_anymap , allow_download_pakcontents ;
extern cvar_t sv_demoDir ;
flocation_t loc ;
int result ;
if ( ISNQCLIENT ( host_client ) & & host_client - > protocol ! = SCP_DARKPLACES7 )
{
SV_PrintToClient ( host_client , PRINT_HIGH , " Your client isn't meant to support downloads \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2008-11-09 22:29:28 +00:00
result = SV_LocateDownload ( name , & loc , & redirection , false ) ;
* host_client - > downloadfn = 0 ;
2004-08-23 00:15:46 +00:00
if ( host_client - > download )
{
2005-12-21 03:07:33 +00:00
VFS_CLOSE ( host_client - > download ) ;
2004-08-23 00:15:46 +00:00
host_client - > download = NULL ;
}
2008-11-09 22:29:28 +00:00
//redirection protocol-specific code goes here.
if ( result = = - 4 )
2004-08-23 00:15:46 +00:00
{
}
2008-11-09 22:29:28 +00:00
if ( result = = 0 )
{ //if we are allowed and could find it
host_client - > download = FS_OpenReadLocation ( & loc ) ;
if ( ! host_client - > download )
result = - 1 ; //this isn't likely, but hey.
}
2004-08-23 00:15:46 +00:00
2008-11-09 22:29:28 +00:00
//handle errors
if ( result ! = 0 )
{ // don't allow anything with .. path
char * error ;
switch ( result )
2004-08-23 00:15:46 +00:00
{
2008-11-09 22:29:28 +00:00
default :
error = " Download could not be found \n " ;
break ;
case - 2 :
error = " Download permission denied \n " ;
break ;
case - 4 :
result = - 1 ;
error = " " ;
break ;
2004-08-23 00:15:46 +00:00
}
2007-06-10 21:33:24 +00:00
if ( ISNQCLIENT ( host_client ) )
{
2008-11-09 22:29:28 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , error ) ;
2007-09-01 05:18:20 +00:00
ClientReliableWrite_Begin ( host_client , svc_stufftext , 2 + 12 ) ;
2007-06-10 21:33:24 +00:00
ClientReliableWrite_String ( host_client , " \n stopdownload \n " ) ;
}
2005-01-16 19:55:35 +00:00
# ifdef PEXT_CHUNKEDDOWNLOADS
2008-11-09 22:29:28 +00:00
else if ( host_client - > fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS )
2005-01-16 02:24:05 +00:00
{
ClientReliableWrite_Begin ( host_client , svc_download , 10 + strlen ( name ) ) ;
ClientReliableWrite_Long ( host_client , - 1 ) ;
2008-11-09 22:29:28 +00:00
ClientReliableWrite_Long ( host_client , result ) ;
2005-01-16 02:24:05 +00:00
ClientReliableWrite_String ( host_client , name ) ;
}
else
2005-01-16 19:55:35 +00:00
# endif
2005-01-16 02:24:05 +00:00
{
2008-11-09 22:29:28 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , error ) ;
2005-05-26 12:55:34 +00:00
ClientReliableWrite_Begin ( host_client , ISQ2CLIENT ( host_client ) ? svcq2_download : svc_download , 4 ) ;
2005-01-16 02:24:05 +00:00
ClientReliableWrite_Short ( host_client , - 1 ) ;
ClientReliableWrite_Byte ( host_client , 0 ) ;
}
2008-11-09 22:29:28 +00:00
//it errored because it was a redirection.
//ask the client to grab the alternate file instead.
if ( redirection )
{
//tell the client to download the new one.
ClientReliableWrite_Begin ( host_client , ISQ2CLIENT ( host_client ) ? svcq2_stufftext : svc_stufftext , 2 + strlen ( redirection ) ) ;
ClientReliableWrite_String ( host_client , va ( " \n download \" %s \" \n " , redirection ) ) ;
}
2004-08-23 00:15:46 +00:00
return ;
}
2008-11-09 22:29:28 +00:00
Q_strncpyz ( host_client - > downloadfn , name , sizeof ( host_client - > downloadfn ) ) ;
host_client - > downloadcount = 0 ;
2005-12-21 03:07:33 +00:00
host_client - > downloadsize = VFS_GETLEN ( host_client - > download ) ;
2005-01-16 19:55:35 +00:00
# ifdef PEXT_CHUNKEDDOWNLOADS
2005-01-16 02:24:05 +00:00
if ( host_client - > fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS )
{
2006-02-11 02:09:43 +00:00
if ( host_client - > download - > seekingisabadplan )
{ //if seeking is a bad plan (for whatever reason - usually because of zip files)
//create a temp file instead
int i , len ;
char buffer [ 8192 ] ;
vfsfile_t * tmp ;
tmp = FS_OpenTemp ( ) ;
for ( i = 0 ; ; i + = len )
{
len = sizeof ( buffer ) ;
if ( len > host_client - > downloadsize - i )
len = host_client - > downloadsize - i ;
if ( len = = 0 )
break ;
VFS_READ ( host_client - > download , buffer , len ) ;
VFS_WRITE ( tmp , buffer , len ) ;
}
VFS_CLOSE ( host_client - > download ) ;
host_client - > download = tmp ;
}
2008-11-09 22:29:28 +00:00
ClientReliableWrite_Begin ( host_client , svc_download , 10 + strlen ( host_client - > downloadfn ) ) ;
2005-01-16 02:24:05 +00:00
ClientReliableWrite_Long ( host_client , - 1 ) ;
ClientReliableWrite_Long ( host_client , host_client - > downloadsize ) ;
2008-11-09 22:29:28 +00:00
ClientReliableWrite_String ( host_client , host_client - > downloadfn ) ;
2005-01-16 02:24:05 +00:00
}
2008-11-09 22:29:28 +00:00
else
2005-01-16 19:55:35 +00:00
# endif
2005-01-16 02:24:05 +00:00
2007-06-10 21:33:24 +00:00
if ( ISNQCLIENT ( host_client ) )
{
2008-11-09 22:29:28 +00:00
char * s = va ( " \n cl_downloadbegin %i %s \n " , host_client - > downloadsize , host_client - > downloadfn ) ;
2007-06-10 21:33:24 +00:00
ClientReliableWrite_Begin ( host_client , svc_stufftext , 2 + strlen ( s ) ) ;
ClientReliableWrite_String ( host_client , s ) ;
}
else
SV_NextDownload_f ( ) ;
2004-08-23 00:15:46 +00:00
SV_EndRedirect ( ) ;
2008-11-09 22:29:28 +00:00
Con_Printf ( " Downloading %s to %s \n " , host_client - > downloadfn , host_client - > name ) ;
2004-08-23 00:15:46 +00:00
}
2007-06-20 00:02:54 +00:00
void SV_StopDownload_f ( void )
{
//this doesn't mean the download failed or was canceled.
if ( host_client - > download )
{
VFS_CLOSE ( host_client - > download ) ;
host_client - > download = NULL ;
}
else
2009-04-06 00:34:32 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " But you're not downloading anything \n " ) ;
2007-06-20 00:02:54 +00:00
host_client - > downloadstarted = false ;
}
2004-08-23 00:15:46 +00:00
//=============================================================================
/*
= = = = = = = = = = = = = = = = = =
SV_SayOne_f
= = = = = = = = = = = = = = = = = =
*/
void SV_SayOne_f ( void )
{
char text [ 1024 ] ;
client_t * to ;
int i ;
char * s , * s2 ;
int clnum = - 1 ;
if ( Cmd_Argc ( ) < 3 )
return ;
while ( ( to = SV_GetClientForString ( Cmd_Argv ( 1 ) , & clnum ) ) )
{
if ( host_client - > spectator )
{
if ( ! sv_spectalk . value | | to - > spectator )
sprintf ( text , " [SPEC] {%s}: " , host_client - > name ) ;
else
continue ;
}
else
sprintf ( text , " {%s}: " , host_client - > name ) ;
if ( host_client - > ismuted )
{
SV_ClientTPrintf ( host_client , PRINT_CHAT ,
STL_YOUAREMUTED ) ;
return ;
2005-07-03 15:16:20 +00:00
}
2004-08-23 00:15:46 +00:00
for ( i = 2 ; ; i + + )
{
s = Cmd_Argv ( i ) ;
if ( ! * s )
break ;
if ( strlen ( text ) + strlen ( s ) + 2 > = sizeof ( text ) - 1 )
break ;
strcat ( text , " " ) ;
strcat ( text , s ) ;
}
//filter out '\n' and '\r'
s = text ;
s2 = text ;
while ( * s2 )
{
if ( * s2 = = ' \r ' | | * s2 = = ' \n ' )
{
s2 + + ;
continue ;
}
* s = * s2 ;
s + + ;
s2 + + ;
}
* s = ' \0 ' ;
strcat ( text , " \n " ) ;
SV_ClientPrintf ( to , PRINT_CHAT , " %s " , text ) ;
}
if ( clnum = = - 1 ) //none found
{
SV_ClientTPrintf ( host_client , PRINT_CHAT , STL_NAMEDCLIENTDOESNTEXIST ) ;
return ;
}
}
2005-12-16 17:14:06 +00:00
float SV_CheckFloodProt ( client_t * client )
{
2006-05-29 05:35:07 +00:00
if ( ! sv_floodprotect . value )
return 0 ;
2006-05-30 04:00:24 +00:00
if ( sv_floodprotect_messages . value < = 0 | | sv_floodprotect_interval . value < = 0 )
2006-05-29 06:12:12 +00:00
return 0 ;
if ( sv . paused )
return 0 ;
if ( realtime < client - > lockedtill )
return client - > lockedtill - realtime ;
if ( client - > floodprotmessage > sv_floodprotect_messages . value )
2005-12-16 17:14:06 +00:00
{
2006-05-29 06:12:12 +00:00
client - > lockedtill = realtime + sv_floodprotect_silencetime . value ;
client - > floodprotmessage = 0.0 ;
client - > lastspoke = 0.0 ;
2006-05-30 04:00:24 +00:00
if ( sv_floodprotect_sendmessage . string [ 0 ] )
SV_ClientPrintf ( client , PRINT_CHAT , " FloodProt: %s \n " , sv_floodprotect_sendmessage . string ) ;
2006-05-29 06:12:12 +00:00
return sv_floodprotect_silencetime . value ;
2005-12-16 17:14:06 +00:00
}
2006-05-29 06:12:12 +00:00
2005-12-16 17:14:06 +00:00
return 0 ;
}
void SV_PushFloodProt ( client_t * client )
{
2006-05-29 06:12:12 +00:00
if ( ! sv_floodprotect . value )
return ;
2006-05-30 04:00:24 +00:00
if ( sv_floodprotect_messages . value < = 0 | | sv_floodprotect_interval . value < = 0 )
2006-05-29 06:12:12 +00:00
return ;
if ( sv . paused )
return ;
if ( client - > lastspoke )
2005-12-16 17:14:06 +00:00
{
2006-05-29 06:12:12 +00:00
client - > floodprotmessage - = ( realtime - client - > lastspoke )
* sv_floodprotect_messages . value
/ sv_floodprotect_interval . value ;
client - > floodprotmessage = max ( 0 , client - > floodprotmessage ) ;
client - > floodprotmessage + + ;
2005-12-16 17:14:06 +00:00
}
2006-05-29 06:12:12 +00:00
else
client - > floodprotmessage = 1.0 ;
client - > lastspoke = realtime ;
2005-12-16 17:14:06 +00:00
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = =
SV_Say
= = = = = = = = = = = = = = = = = =
*/
void SV_Say ( qboolean team )
{
client_t * client ;
2006-01-27 08:06:48 +00:00
int j ;
2004-08-23 00:15:46 +00:00
char * p ;
char text [ 1024 ] ;
char t1 [ 32 ] , * t2 ;
int cls = 0 ;
2005-12-16 17:14:06 +00:00
float floodtime ;
2004-08-23 00:15:46 +00:00
qboolean sent [ MAX_CLIENTS ] ; //so we don't send to the same splitscreen connection twice. (it's ugly)
int cln ;
2005-09-08 01:43:29 +00:00
qboolean mvdrecording ;
2004-08-23 00:15:46 +00:00
char * s , * s2 ;
if ( Cmd_Argc ( ) < 2 )
return ;
Sys_ServerActivity ( ) ;
memset ( sent , 0 , sizeof ( sent ) ) ;
if ( team )
{
Q_strncpyz ( t1 , Info_ValueForKey ( host_client - > userinfo , " team " ) , sizeof ( t1 ) ) ;
}
if ( host_client - > spectator & & ( ! sv_spectalk . value | | team ) )
sprintf ( text , " [SPEC] %s: " , host_client - > name ) ;
else if ( team )
sprintf ( text , " (%s): " , host_client - > name ) ;
else
sprintf ( text , " %s: " , host_client - > name ) ;
if ( host_client - > ismuted )
{
SV_ClientTPrintf ( host_client , PRINT_CHAT ,
STL_MUTEDCHAT ) ;
return ;
}
2007-09-03 22:37:13 +00:00
# ifdef VM_Q1
if ( Q1QVM_ClientSay ( sv_player , team ) )
return ;
# endif
2005-12-16 17:14:06 +00:00
if ( ( floodtime = SV_CheckFloodProt ( host_client ) ) )
2004-08-23 00:15:46 +00:00
{
2005-12-16 17:14:06 +00:00
SV_ClientTPrintf ( host_client , PRINT_CHAT ,
2005-07-03 15:16:20 +00:00
STL_FLOODPROTTIME ,
2005-12-16 17:14:06 +00:00
( int ) ( floodtime ) ) ;
return ;
2004-08-23 00:15:46 +00:00
}
2005-12-16 17:14:06 +00:00
SV_PushFloodProt ( host_client ) ;
2004-08-23 00:15:46 +00:00
p = Cmd_Args ( ) ;
if ( * p = = ' " ' )
{
p + + ;
p [ Q_strlen ( p ) - 1 ] = 0 ;
}
if ( strlen ( text ) + strlen ( p ) + 2 > = sizeof ( text ) - 10 )
{
SV_ClientTPrintf ( host_client , PRINT_CHAT , STL_BUFFERPROTECTION ) ;
return ;
}
if ( svprogfuncs )
if ( PR_QCChat ( p , team ) ) //true if handled.
return ;
Q_strcat ( text , p ) ;
//filter out '\n' and '\r'
if ( sv_chatfilter . value )
{
s = text ;
s2 = text ;
while ( * s2 )
{
if ( * s2 = = ' \r ' | | * s2 = = ' \n ' )
{
s2 + + ;
continue ;
}
* s = * s2 ;
s + + ;
s2 + + ;
}
* s = ' \0 ' ;
}
Q_strcat ( text , " \n " ) ;
Sys_Printf ( " %s " , text ) ;
2005-09-08 01:43:29 +00:00
mvdrecording = sv . mvdrecording ;
sv . mvdrecording = false ; //so that the SV_ClientPrintf doesn't send to all players.
2004-08-23 00:15:46 +00:00
for ( j = 0 , client = svs . clients ; j < MAX_CLIENTS ; j + + , client + + )
{
if ( client - > state ! = cs_spawned & & client - > state ! = cs_connected )
continue ;
if ( host_client - > spectator & & ! sv_spectalk . value )
if ( ! client - > spectator )
continue ;
if ( team )
{
// the spectator team
if ( host_client - > spectator ) {
if ( ! client - > spectator )
continue ;
} else {
t2 = Info_ValueForKey ( client - > userinfo , " team " ) ;
if ( strcmp ( t1 , t2 ) | | client - > spectator )
continue ; // on different teams
}
}
cls | = 1 < < j ;
//make sure we don't send the say to the same client 20 times due to splitscreen
if ( client - > controller )
cln = client - > controller - svs . clients ;
else
cln = client - svs . clients ;
if ( sent [ cln ] )
continue ;
else
sent [ cln ] = true ;
SV_ClientPrintf ( client , PRINT_CHAT , " %s " , text ) ;
}
2005-09-08 01:43:29 +00:00
sv . mvdrecording = mvdrecording ;
2004-08-23 00:15:46 +00:00
if ( ! sv . mvdrecording | | ! cls )
return ;
2005-07-28 15:33:27 +00:00
// non-team messages should be seen always, even if not tracking any player
2004-08-23 00:15:46 +00:00
if ( ! team & & ( ( host_client - > spectator & & sv_spectalk . value ) | | ! host_client - > spectator ) )
{
MVDWrite_Begin ( dem_all , 0 , strlen ( text ) + 3 ) ;
}
2005-07-03 15:16:20 +00:00
else
2004-08-23 00:15:46 +00:00
MVDWrite_Begin ( dem_multiple , cls , strlen ( text ) + 3 ) ;
MSG_WriteByte ( ( sizebuf_t * ) demo . dbuf , svc_print ) ;
MSG_WriteByte ( ( sizebuf_t * ) demo . dbuf , PRINT_CHAT ) ;
MSG_WriteString ( ( sizebuf_t * ) demo . dbuf , text ) ;
}
/*
= = = = = = = = = = = = = = = = = =
SV_Say_f
= = = = = = = = = = = = = = = = = =
*/
void SV_Say_f ( void )
{
SV_Say ( false ) ;
}
/*
= = = = = = = = = = = = = = = = = =
SV_Say_Team_f
= = = = = = = = = = = = = = = = = =
*/
void SV_Say_Team_f ( void )
{
SV_Say ( true ) ;
}
//============================================================================
/*
= = = = = = = = = = = = = = = = =
SV_Pings_f
The client is showing the scoreboard , so send new ping times for all
clients
= = = = = = = = = = = = = = = = =
*/
void SV_Pings_f ( void )
{
client_t * client ;
int j ;
if ( sv . demofile )
{
for ( j = 0 , client = svs . clients ; j < MAX_CLIENTS ; j + + , client + + )
{
if ( ! * sv . recordedplayer [ j ] . userinfo )
continue ;
ClientReliableWrite_Begin ( host_client , svc_updateping , 4 ) ;
ClientReliableWrite_Byte ( host_client , j ) ;
ClientReliableWrite_Short ( host_client , sv . recordedplayer [ j ] . ping ) ;
ClientReliableWrite_Begin ( host_client , svc_updatepl , 4 ) ;
ClientReliableWrite_Byte ( host_client , j ) ;
ClientReliableWrite_Byte ( host_client , sv . recordedplayer [ j ] . pl ) ;
}
return ;
}
2007-06-20 00:02:54 +00:00
if ( ISNQCLIENT ( host_client ) )
2004-08-23 00:15:46 +00:00
{
2007-06-20 00:02:54 +00:00
char * s ;
ClientReliableWrite_Begin ( host_client , svc_stufftext , 15 + 10 * MAX_CLIENTS ) ;
ClientReliableWrite_SZ ( host_client , " pingplreport " , 12 ) ;
for ( j = 0 , client = svs . clients ; j < MAX_CLIENTS ; j + + , client + + )
{
s = va ( " %i %i " , SV_CalcPing ( client ) , client - > lossage ) ;
ClientReliableWrite_SZ ( host_client , s , strlen ( s ) ) ;
}
ClientReliableWrite_Byte ( host_client , ' \n ' ) ;
ClientReliableWrite_Byte ( host_client , ' \0 ' ) ;
2004-08-23 00:15:46 +00:00
2007-06-20 00:02:54 +00:00
}
else
{
for ( j = 0 , client = svs . clients ; j < MAX_CLIENTS ; j + + , client + + )
{
if ( client - > state ! = cs_spawned )
continue ;
ClientReliableWrite_Begin ( host_client , svc_updateping , 4 ) ;
ClientReliableWrite_Byte ( host_client , j ) ;
ClientReliableWrite_Short ( host_client , SV_CalcPing ( client ) ) ;
ClientReliableWrite_Begin ( host_client , svc_updatepl , 4 ) ;
ClientReliableWrite_Byte ( host_client , j ) ;
ClientReliableWrite_Byte ( host_client , client - > lossage ) ;
}
2004-08-23 00:15:46 +00:00
}
}
/*
= = = = = = = = = = = = = = = = = =
SV_Kill_f
= = = = = = = = = = = = = = = = = =
*/
void SV_Kill_f ( void )
{
2005-12-16 17:14:06 +00:00
float floodtime ;
2009-03-03 01:52:30 +00:00
# ifdef HLSERVER
if ( svs . gametype = = GT_HALFLIFE )
{
HLSV_ClientCommand ( host_client ) ;
return ;
}
# endif
2007-09-02 19:55:17 +00:00
# ifdef VM_Q1
if ( svs . gametype = = GT_Q1QVM )
{
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
2007-09-02 19:55:17 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
Q1QVM_ClientCommand ( ) ;
return ;
}
# endif
2009-03-03 01:52:30 +00:00
if ( svs . gametype ! = GT_PROGS )
return ;
2007-09-02 19:55:17 +00:00
2005-03-28 00:11:59 +00:00
if ( sv_player - > v - > health < = 0 )
2004-08-23 00:15:46 +00:00
{
2006-05-29 06:12:12 +00:00
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_NOSUICIDEWHENDEAD ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2005-07-03 15:16:20 +00:00
2006-05-30 04:00:24 +00:00
if ( sv_floodprotect_suicide . value )
2005-12-16 17:14:06 +00:00
{
2006-05-30 04:00:24 +00:00
if ( ( floodtime = SV_CheckFloodProt ( host_client ) ) )
{
SV_ClientPrintf ( host_client , PRINT_HIGH , " You can't suicide for %i seconds \n " , ( int ) floodtime ) ;
return ;
}
SV_PushFloodProt ( host_client ) ;
2005-12-16 17:14:06 +00:00
}
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > ClientKill ) ;
}
/*
= = = = = = = = = = = = = = = = = =
SV_TogglePause
= = = = = = = = = = = = = = = = = =
*/
2006-01-21 00:06:49 +00:00
qboolean SV_TogglePause ( client_t * initiator )
2004-08-23 00:15:46 +00:00
{
int i ;
client_t * cl ;
2006-01-21 00:06:49 +00:00
int newv ;
newv = sv . paused ^ 1 ;
if ( ! PR_ShouldTogglePause ( initiator , newv ) )
return false ;
sv . paused = newv ;
2004-08-23 00:15:46 +00:00
2006-01-21 00:06:49 +00:00
sv . pausedstart = Sys_DoubleTime ( ) ;
2004-08-23 00:15:46 +00:00
// send notification to all clients
for ( i = 0 , cl = svs . clients ; i < MAX_CLIENTS ; i + + , cl + + )
{
if ( ! cl - > state )
continue ;
2006-01-21 00:06:49 +00:00
if ( ! ISQ2CLIENT ( cl ) & & ! cl - > controller )
2004-08-23 00:15:46 +00:00
{
ClientReliableWrite_Begin ( cl , svc_setpause , 2 ) ;
ClientReliableWrite_Byte ( cl , sv . paused ) ;
}
}
2006-01-21 00:06:49 +00:00
return true ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
SV_Pause_f
= = = = = = = = = = = = = = = = = =
*/
void SV_Pause_f ( void )
{
if ( ! pausable . value )
{
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_CANTPAUSE ) ;
return ;
}
if ( host_client - > spectator & & ! svs . demoplayback )
{
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_CANTPAUSESPEC ) ;
return ;
}
2006-01-21 00:06:49 +00:00
if ( SV_TogglePause ( host_client ) )
{
if ( sv . paused )
SV_BroadcastTPrintf ( PRINT_HIGH , STL_CLIENTPAUSED , host_client - > name ) ;
else
SV_BroadcastTPrintf ( PRINT_HIGH , STL_CLIENTUNPAUSED , host_client - > name ) ;
}
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = =
SV_Drop_f
The client is going to disconnect , so remove the connection immediately
= = = = = = = = = = = = = = = = =
*/
void SV_Drop_f ( void )
{
SV_EndRedirect ( ) ;
if ( ! host_client - > spectator )
SV_BroadcastTPrintf ( PRINT_HIGH , STL_CLIENTDROPPED , host_client - > name ) ;
2005-07-03 15:16:20 +00:00
SV_DropClient ( host_client ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = =
SV_PTrack_f
Change the bandwidth estimate for a client
= = = = = = = = = = = = = = = = =
*/
void SV_PTrack_f ( void )
{
int i ;
edict_t * ent , * tent ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
if ( ! host_client - > spectator & & ! sv . demofile )
return ;
if ( Cmd_Argc ( ) ! = 2 )
{
// turn off tracking
host_client - > spec_track = 0 ;
ent = EDICT_NUM ( svprogfuncs , host_client - svs . clients + 1 ) ;
tent = EDICT_NUM ( svprogfuncs , 0 ) ;
2005-03-28 00:11:59 +00:00
ent - > v - > goalentity = EDICT_TO_PROG ( svprogfuncs , tent ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
i = atoi ( Cmd_Argv ( 1 ) ) ;
if ( * sv . recordedplayer [ i ] . userinfo )
{
host_client - > spec_track = i + 1 ;
return ;
}
if ( i < 0 | | i > = MAX_CLIENTS | | svs . clients [ i ] . state ! = cs_spawned | |
svs . clients [ i ] . spectator )
{
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_INVALIDTRACKCLIENT ) ;
host_client - > spec_track = 0 ;
ent = EDICT_NUM ( svprogfuncs , host_client - svs . clients + 1 ) ;
tent = EDICT_NUM ( svprogfuncs , 0 ) ;
2005-03-28 00:11:59 +00:00
ent - > v - > goalentity = EDICT_TO_PROG ( svprogfuncs , tent ) ;
2004-08-23 00:15:46 +00:00
return ;
}
host_client - > spec_track = i + 1 ; // now tracking
ent = EDICT_NUM ( svprogfuncs , host_client - svs . clients + 1 ) ;
tent = EDICT_NUM ( svprogfuncs , i + 1 ) ;
2005-03-28 00:11:59 +00:00
ent - > v - > goalentity = EDICT_TO_PROG ( svprogfuncs , tent ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = =
SV_Rate_f
Change the bandwidth estimate for a client
= = = = = = = = = = = = = = = = =
*/
void SV_Rate_f ( void )
2005-07-03 15:16:20 +00:00
{
2004-08-23 00:15:46 +00:00
if ( Cmd_Argc ( ) ! = 2 )
{
2005-03-20 02:57:11 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " Effective rate %i \n " , SV_RateForClient ( host_client ) ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2005-03-20 02:57:11 +00:00
host_client - > rate = atoi ( Cmd_Argv ( 1 ) ) ;
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_RATESETTO , SV_RateForClient ( host_client ) ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = =
SV_Msg_f
Change the message level for a client
= = = = = = = = = = = = = = = = =
*/
void SV_Msg_f ( void )
2005-07-03 15:16:20 +00:00
{
2004-08-23 00:15:46 +00:00
if ( Cmd_Argc ( ) ! = 2 )
{
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_CURRENTMSGLEVEL ,
host_client - > messagelevel ) ;
return ;
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
host_client - > messagelevel = atoi ( Cmd_Argv ( 1 ) ) ;
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_MSGLEVELSET , host_client - > messagelevel ) ;
}
2005-12-15 19:15:39 +00:00
qboolean SV_UserInfoIsBasic ( char * infoname )
{
int i ;
char * basicinfos [ ] = {
" name " ,
" team " ,
" skin " ,
" topcolor " ,
" bottomcolor " ,
NULL } ;
for ( i = 0 ; basicinfos [ i ] ; i + + )
{
2006-02-22 23:29:59 +00:00
if ( * infoname = = ' * ' | | ! strcmp ( infoname , basicinfos [ i ] ) )
2005-12-15 19:15:39 +00:00
return true ;
}
return false ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = =
SV_SetInfo_f
Allow clients to change userinfo
= = = = = = = = = = = = = = = = = =
*/
void SV_SetInfo_f ( void )
{
2005-12-15 19:15:39 +00:00
int i , j ;
2004-08-23 00:15:46 +00:00
char oldval [ MAX_INFO_STRING ] ;
2005-12-06 02:17:27 +00:00
char * key , * val ;
2005-12-15 19:15:39 +00:00
qboolean basic ; //infos that we send to any old qw client.
client_t * client ;
2004-08-23 00:15:46 +00:00
if ( Cmd_Argc ( ) = = 1 )
{
2009-04-06 00:34:32 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " User info settings: \n " ) ;
2004-08-23 00:15:46 +00:00
Info_Print ( host_client - > userinfo ) ;
return ;
}
if ( Cmd_Argc ( ) ! = 3 )
{
2009-04-06 00:34:32 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " usage: setinfo [ <key> <value> ] \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
if ( Cmd_Argv ( 1 ) [ 0 ] = = ' * ' )
return ; // don't set priveledged values
2005-12-15 19:15:39 +00:00
if ( strstr ( Cmd_Argv ( 1 ) , " \\ " ) | | strstr ( Cmd_Argv ( 2 ) , " \\ " ) )
return ; // illegal char
2007-09-03 22:37:13 +00:00
Q_strncpyz ( oldval , Info_ValueForKey ( host_client - > userinfo , Cmd_Argv ( 1 ) ) , MAX_INFO_STRING ) ;
# ifdef VM_Q1
if ( Q1QVM_UserInfoChanged ( sv_player ) )
return ;
# endif
2004-08-23 00:15:46 +00:00
2005-03-07 08:58:26 +00:00
Info_SetValueForKey ( host_client - > userinfo , Cmd_Argv ( 1 ) , Cmd_Argv ( 2 ) , sizeof ( host_client - > userinfo ) ) ;
2004-08-23 00:15:46 +00:00
// name is extracted below in ExtractFromUserInfo
// strncpy (host_client->name, Info_ValueForKey (host_client->userinfo, "name")
2005-07-03 15:16:20 +00:00
// , sizeof(host_client->name)-1);
2004-08-23 00:15:46 +00:00
// SV_FullClientUpdate (host_client, &sv.reliable_datagram);
// host_client->sendinfo = true;
if ( ! strcmp ( Info_ValueForKey ( host_client - > userinfo , Cmd_Argv ( 1 ) ) , oldval ) )
return ; // key hasn't changed
// process any changed values
SV_ExtractFromUserinfo ( host_client ) ;
if ( progstype ! = PROG_QW & & ! strcmp ( Cmd_Argv ( 1 ) , " bottomcolor " ) )
2007-09-03 22:37:13 +00:00
{ //team fortress has a nasty habit of booting people without this
2005-03-28 00:11:59 +00:00
sv_player - > v - > team = atoi ( Cmd_Argv ( 2 ) ) + 1 ;
2004-08-23 00:15:46 +00:00
}
2005-07-01 19:23:00 +00:00
if ( * Cmd_Argv ( 1 ) ! = ' _ ' )
{
i = host_client - svs . clients ;
2005-12-06 02:17:27 +00:00
key = Cmd_Argv ( 1 ) ;
val = Info_ValueForKey ( host_client - > userinfo , key ) ;
2005-12-15 19:15:39 +00:00
basic = SV_UserInfoIsBasic ( key ) ;
if ( basic )
Info_SetValueForKey ( host_client - > userinfobasic , key , val , sizeof ( host_client - > userinfobasic ) ) ;
for ( j = 0 ; j < MAX_CLIENTS ; j + + )
{
client = svs . clients + j ;
if ( client - > state < cs_connected )
continue ; // reliables go to all connected or spawned
if ( client - > controller )
continue ; //splitscreen
if ( client - > protocol = = SCP_BAD )
continue ; //botclient
if ( ISQWCLIENT ( client ) )
{
2006-01-13 20:29:34 +00:00
if ( basic | | ( client - > fteprotocolextensions & PEXT_BIGUSERINFOS ) )
2005-12-15 19:15:39 +00:00
{
2009-01-22 04:08:45 +00:00
ClientReliableWrite_Begin ( client , svc_setinfo , 1 + 1 + strlen ( key ) + 1 + strlen ( val ) + 1 ) ;
ClientReliableWrite_Char ( client , i ) ;
ClientReliableWrite_String ( client , key ) ;
ClientReliableWrite_String ( client , val ) ;
2005-12-15 19:15:39 +00:00
}
}
}
2005-12-06 02:17:27 +00:00
if ( sv . mvdrecording )
{
MVDWrite_Begin ( dem_all , 0 , strlen ( key ) + strlen ( val ) + 4 ) ;
MSG_WriteByte ( ( sizebuf_t * ) demo . dbuf , svc_setinfo ) ;
MSG_WriteByte ( ( sizebuf_t * ) demo . dbuf , i ) ;
MSG_WriteString ( ( sizebuf_t * ) demo . dbuf , key ) ;
MSG_WriteString ( ( sizebuf_t * ) demo . dbuf , val ) ;
}
2005-07-01 19:23:00 +00:00
}
2004-08-23 00:15:46 +00:00
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " userinfo changed " ) ;
2005-07-01 19:23:00 +00:00
PR_ClientUserInfoChanged ( Cmd_Argv ( 1 ) , oldval , Info_ValueForKey ( host_client - > userinfo , Cmd_Argv ( 1 ) ) ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
SV_ShowServerinfo_f
Dumps the serverinfo info string
= = = = = = = = = = = = = = = = = =
*/
void SV_ShowServerinfo_f ( void )
{
2009-04-06 00:34:32 +00:00
SV_BeginRedirect ( RD_CLIENT , host_client - > language ) ;
2004-08-23 00:15:46 +00:00
Info_Print ( svs . info ) ;
2009-04-06 00:34:32 +00:00
SV_EndRedirect ( ) ;
2004-08-23 00:15:46 +00:00
}
void SV_NoSnap_f ( void )
{
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " refused snap " ) ;
2004-08-23 00:15:46 +00:00
if ( * host_client - > uploadfn ) {
* host_client - > uploadfn = 0 ;
SV_BroadcastTPrintf ( PRINT_HIGH , STL_SNAPREFUSED , host_client - > name ) ;
}
}
//3 votes per player.
typedef struct voteinfo_s {
struct voteinfo_s * next ;
float timeout ;
int clientid ;
char command [ 1 ] ;
} voteinfo_t ;
voteinfo_t * voteinfo ;
void VoteAdd ( char * cmd , int id )
{
voteinfo_t * vote ;
vote = Z_Malloc ( sizeof ( voteinfo_t ) + strlen ( cmd ) ) ; //null term is part of voteinfo_t
strcpy ( vote - > command , cmd ) ;
vote - > clientid = id ;
vote - > timeout = realtime + votetime . value * 60 ;
vote - > next = voteinfo ;
voteinfo = vote ;
}
void VoteRemoveCommands ( char * command , int id ) //all of one command
{
voteinfo_t * vote , * prev ;
prev = NULL ;
for ( vote = voteinfo ; vote ; vote = vote - > next )
{
if ( ( ! command | | ! strcmp ( vote - > command , command ) ) & & ( vote - > clientid = = id | | id = = - 1 ) )
{
if ( prev )
prev - > next = vote - > next ;
else
voteinfo = vote - > next ;
Z_Free ( vote ) ;
VoteRemoveCommands ( command , id ) ;
return ;
}
else
prev = vote ;
}
}
void VoteFlushAll ( void )
{
VoteRemoveCommands ( NULL , - 1 ) ;
}
int VoteCount ( char * command , int id ) //all of one command
{
voteinfo_t * vote ;
int num = 0 ;
for ( vote = voteinfo ; vote ; vote = vote - > next )
{
if ( ! command | | ! strcmp ( vote - > command , command ) )
{
if ( vote - > clientid = = id | | id = = - 1 )
num + + ;
}
}
return num ;
}
void VoteCheckTimes ( void )
{
voteinfo_t * vote , * prev ;
prev = NULL ;
2008-05-26 21:50:11 +00:00
for ( vote = voteinfo ; vote ; )
2004-08-23 00:15:46 +00:00
{
if ( vote - > timeout < realtime )
{
if ( prev )
prev - > next = vote - > next ;
else
voteinfo = vote - > next ;
Z_Free ( vote ) ;
2008-05-26 21:50:11 +00:00
if ( prev )
vote = prev ;
else
vote = voteinfo ;
2004-08-23 00:15:46 +00:00
}
else
prev = vote ;
2008-05-26 21:50:11 +00:00
vote = vote - > next ;
2004-08-23 00:15:46 +00:00
}
}
void SV_Vote_f ( void )
{
char * command = Cmd_Args ( ) ;
char * base ;
int id = host_client - > userid ;
int num ;
int totalusers = 0 ;
qboolean passes ;
if ( ! votelevel . value )
{
2009-04-06 00:34:32 +00:00
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_NOVOTING ) ;
2004-08-23 00:15:46 +00:00
return ;
}
if ( host_client - > ismuted )
{
2009-04-06 00:34:32 +00:00
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_MUTEDVOTE ) ;
2004-08-23 00:15:46 +00:00
return ;
}
Cmd_ExecLevel = votelevel . value ;
base = command ;
while ( * base > ' ' )
base + + ;
2005-07-03 15:16:20 +00:00
if ( * base )
2004-08-23 00:15:46 +00:00
* base = ' \0 ' ;
else
base = NULL ;
if ( strchr ( command , ' ; ' ) | | ! strcmp ( command , " if " ) )
{
2009-04-06 00:34:32 +00:00
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_BADVOTE ) ;
2004-08-23 00:15:46 +00:00
return ;
}
num = Cmd_Level ( command ) ;
if ( base )
* base = ' ' ;
if ( num ! = Cmd_ExecLevel )
{
2009-04-06 00:34:32 +00:00
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_BADVOTE ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2005-07-03 15:16:20 +00:00
VoteCheckTimes ( ) ;
2004-08-23 00:15:46 +00:00
for ( num = 0 ; num < sv . allocated_client_slots ; num + + )
if ( svs . clients [ num ] . state = = cs_spawned )
totalusers + + ;
if ( VoteCount ( command , id ) )
{
VoteRemoveCommands ( command , id ) ;
2009-04-06 00:34:32 +00:00
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_OLDVOTEREMOVED ) ;
2004-08-23 00:15:46 +00:00
return ;
}
if ( VoteCount ( NULL , id ) > = 3 )
{
VoteRemoveCommands ( NULL , id ) ;
2009-04-06 00:34:32 +00:00
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_VOTESREMOVED ) ;
2004-08-23 00:15:46 +00:00
}
num = VoteCount ( command , - 1 ) + 1 ;
passes = true ;
if ( votepercent . value < 0 & & ( float ) ( totalusers - num ) > = 0.5 * totalusers )
passes = false ;
if ( votepercent . value > = 0 & & num < = totalusers * votepercent . value / 100 )
passes = false ;
if ( num < voteminimum . value )
passes = false ;
if ( passes ) //>min number of votes, and meets the percent required
{
SV_BroadcastTPrintf ( PRINT_HIGH , STL_FINALVOTE , host_client - > name , command ) ;
VoteRemoveCommands ( command , - 1 ) ;
Cbuf_AddText ( command , votelevel . value ) ;
2005-09-07 14:55:25 +00:00
Cbuf_AddText ( " \n " , votelevel . value ) ;
2004-08-23 00:15:46 +00:00
//Cmd_ExecuteString (command, votelevel.value);
return ;
}
else //otherwise, try later.
{
SV_BroadcastTPrintf ( PRINT_HIGH , STL_VOTE , host_client - > name , command ) ;
VoteAdd ( command , id ) ;
}
}
extern qboolean sv_allow_cheats ;
2005-01-07 02:36:13 +00:00
void Cmd_Notarget_f ( void )
2004-08-23 00:15:46 +00:00
{
2005-01-07 02:36:13 +00:00
if ( ! sv_allow_cheats )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Cheats are not allowed on this server \n " ) ;
2005-01-07 02:36:13 +00:00
return ;
}
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " notarget cheat " ) ;
2005-03-28 00:11:59 +00:00
if ( ( int ) ( sv_player - > v - > flags = ( int ) sv_player - > v - > flags ^ FL_NOTARGET ) & FL_NOTARGET )
2004-08-23 00:15:46 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " notarget ON \n " ) ;
else
SV_ClientPrintf ( host_client , PRINT_HIGH , " notarget OFF \n " ) ;
2005-01-07 02:36:13 +00:00
}
2004-08-23 00:15:46 +00:00
2005-01-07 02:36:13 +00:00
//Sets client to godmode
void Cmd_God_f ( void )
{
2004-08-23 00:15:46 +00:00
if ( ! sv_allow_cheats )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Cheats are not allowed on this server \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " god cheat " ) ;
2005-03-28 00:11:59 +00:00
if ( ( int ) ( sv_player - > v - > flags = ( int ) sv_player - > v - > flags ^ FL_GODMODE ) & FL_GODMODE )
2004-08-23 00:15:46 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " godmode ON \n " ) ;
else
SV_ClientPrintf ( host_client , PRINT_HIGH , " godmode OFF \n " ) ;
}
void Cmd_Give_f ( void )
{
char * t ;
int v ;
2009-04-01 22:03:56 +00:00
# ifdef HLSERVER
if ( svs . gametype = = GT_HALFLIFE )
{
HLSV_ClientCommand ( host_client ) ;
return ;
}
# endif
2004-08-23 00:15:46 +00:00
if ( ! sv_allow_cheats )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Cheats are not allowed on this server \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
t = Cmd_Argv ( 1 ) ;
v = atoi ( Cmd_Argv ( 2 ) ) ;
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " give cheat " ) ;
2004-08-23 00:15:46 +00:00
if ( strlen ( t ) = = 1 & & ( Cmd_Argc ( ) = = 3 | | ( * t > = ' 0 ' & & * t < = ' 9 ' ) ) )
{
switch ( t [ 0 ] )
{
case ' 2 ' :
case ' 3 ' :
case ' 4 ' :
case ' 5 ' :
case ' 6 ' :
case ' 7 ' :
case ' 8 ' :
case ' 9 ' :
2005-03-28 00:11:59 +00:00
sv_player - > v - > items = ( int ) sv_player - > v - > items | IT_SHOTGUN < < ( t [ 0 ] - ' 2 ' ) ;
2004-08-23 00:15:46 +00:00
break ;
case ' s ' :
2005-03-28 00:11:59 +00:00
sv_player - > v - > ammo_shells = v ;
2005-07-03 15:16:20 +00:00
break ;
2004-08-23 00:15:46 +00:00
case ' n ' :
2005-03-28 00:11:59 +00:00
sv_player - > v - > ammo_nails = v ;
2005-07-03 15:16:20 +00:00
break ;
2004-08-23 00:15:46 +00:00
case ' r ' :
2005-03-28 00:11:59 +00:00
sv_player - > v - > ammo_rockets = v ;
2005-07-03 15:16:20 +00:00
break ;
2004-08-23 00:15:46 +00:00
case ' h ' :
2005-03-28 00:11:59 +00:00
sv_player - > v - > health = v ;
2005-07-03 15:16:20 +00:00
break ;
2004-08-23 00:15:46 +00:00
case ' c ' :
2005-03-28 00:11:59 +00:00
sv_player - > v - > ammo_cells = v ;
2005-07-03 15:16:20 +00:00
break ;
2004-08-23 00:15:46 +00:00
}
}
2008-11-09 22:29:28 +00:00
else if ( developer . value | | host_client - > netchan . remote_address . type = = NA_LOOPBACK ) //we don't want clients doing nasty things... like setting movetype 3123
2004-08-23 00:15:46 +00:00
{
int oldself ;
oldself = pr_global_struct - > self ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
2008-11-09 22:29:28 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " Result: %s \n " , svprogfuncs - > EvaluateDebugString ( svprogfuncs , Cmd_Args ( ) ) ) ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > self = oldself ;
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
}
void Cmd_Noclip_f ( void )
{
if ( ! sv_allow_cheats )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Cheats are not allowed on this server \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " noclip cheat " ) ;
2005-03-28 00:11:59 +00:00
if ( sv_player - > v - > movetype ! = MOVETYPE_NOCLIP )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > movetype = MOVETYPE_NOCLIP ;
sv_player - > v - > solid = SOLID_TRIGGER ;
2004-08-23 00:15:46 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " noclip ON \n " ) ;
}
else
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > movetype = MOVETYPE_WALK ;
if ( sv_player - > v - > health > 0 )
sv_player - > v - > solid = SOLID_SLIDEBOX ;
2004-08-23 00:15:46 +00:00
else
2005-03-28 00:11:59 +00:00
sv_player - > v - > solid = SOLID_NOT ;
2004-08-23 00:15:46 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " noclip OFF \n " ) ;
}
}
2005-01-07 02:36:13 +00:00
void Cmd_Fly_f ( void )
{
if ( ! sv_allow_cheats )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Cheats are not allowed on this server \n " ) ;
2005-01-07 02:36:13 +00:00
return ;
}
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " fly cheat " ) ;
2005-03-28 00:11:59 +00:00
if ( sv_player - > v - > movetype ! = MOVETYPE_FLY )
2005-01-07 02:36:13 +00:00
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > movetype = MOVETYPE_FLY ;
2005-01-07 02:36:13 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " flymode ON \n " ) ;
}
else
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > movetype = MOVETYPE_WALK ;
if ( sv_player - > v - > health > 0 )
sv_player - > v - > solid = SOLID_SLIDEBOX ;
2005-01-07 02:36:13 +00:00
else
2005-03-28 00:11:59 +00:00
sv_player - > v - > solid = SOLID_NOT ;
2005-01-07 02:36:13 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " flymode OFF \n " ) ;
}
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = =
Host_SetPos_f UDC
2005-07-01 19:23:00 +00:00
By Alex Shadowalker ( and added to fte because he kept winging )
2004-08-23 00:15:46 +00:00
= = = = = = = = = = = = = = = = = = = =
*/
void Cmd_SetPos_f ( void )
2005-07-03 15:16:20 +00:00
{
2004-08-23 00:15:46 +00:00
if ( ! sv_allow_cheats )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Cheats are not allowed on this server \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
if ( Cmd_Argc ( ) ! = 4 )
{
2009-04-06 00:34:32 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " setpos %f %f %f \n " , sv_player - > v - > origin [ 0 ] , sv_player - > v - > origin [ 1 ] , sv_player - > v - > origin [ 2 ] ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " setpos cheat " ) ;
2005-03-28 00:11:59 +00:00
if ( sv_player - > v - > movetype ! = MOVETYPE_NOCLIP )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > movetype = MOVETYPE_NOCLIP ;
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " noclip on \n " ) ;
2004-08-23 00:15:46 +00:00
}
2005-03-28 00:11:59 +00:00
sv_player - > v - > origin [ 0 ] = atof ( Cmd_Argv ( 1 ) ) ;
sv_player - > v - > origin [ 1 ] = atof ( Cmd_Argv ( 2 ) ) ;
sv_player - > v - > origin [ 2 ] = atof ( Cmd_Argv ( 3 ) ) ;
2004-08-23 00:15:46 +00:00
SV_LinkEdict ( sv_player , false ) ;
}
void ED_ClearEdict ( progfuncs_t * progfuncs , edict_t * e ) ;
2005-10-07 16:27:20 +00:00
void SV_SetUpClientEdict ( client_t * cl , edict_t * ent )
2004-08-23 00:15:46 +00:00
{
2004-10-29 06:11:33 +00:00
extern int pr_teamfield ;
2007-09-02 19:55:17 +00:00
# ifdef VM_Q1
if ( svs . gametype = = GT_Q1QVM )
{
string_t preserve ;
preserve = ent - > v - > netname ;
Q1QVMED_ClearEdict ( ent , true ) ;
ent - > v - > netname = preserve ;
}
else
# endif
{
if ( progstype ! = PROG_NQ ) //allow frikbots to work in NQ mods (but not qw!)
ED_ClearEdict ( svprogfuncs , ent ) ;
2007-09-03 22:37:13 +00:00
ent - > v - > netname = PR_SetString ( svprogfuncs , cl - > name ) ;
2007-09-02 19:55:17 +00:00
}
2008-06-01 22:06:22 +00:00
ED_Spawned ( ent , false ) ;
2004-08-23 00:15:46 +00:00
ent - > isfree = false ;
2005-07-03 15:16:20 +00:00
2005-03-28 00:11:59 +00:00
ent - > v - > colormap = NUM_FOR_EDICT ( svprogfuncs , ent ) ;
2004-08-23 00:15:46 +00:00
2004-10-29 06:11:33 +00:00
if ( pr_teamfield )
2005-12-06 23:33:59 +00:00
( ( string_t * ) ent - > v ) [ pr_teamfield ] = ( string_t ) ( cl - > team - svprogfuncs - > stringtable ) ;
2004-10-29 06:11:33 +00:00
2005-10-12 23:04:25 +00:00
{
2005-10-20 00:03:50 +00:00
int tc = atoi ( Info_ValueForKey ( cl - > userinfo , " topcolor " ) ) ;
int bc = atoi ( Info_ValueForKey ( cl - > userinfo , " bottomcolor " ) ) ;
2005-10-12 23:04:25 +00:00
if ( tc < 0 | | tc > 13 )
tc = 0 ;
if ( bc < 0 | | bc > 13 )
bc = 0 ;
2007-09-02 19:55:17 +00:00
ent - > xv - > clientcolors = 16 * tc + bc ;
2005-10-12 23:04:25 +00:00
}
2004-10-29 06:11:33 +00:00
2007-09-02 19:55:17 +00:00
ent - > xv - > gravity = cl - > entgravity = 1.0 ;
ent - > xv - > maxspeed = cl - > maxspeed = sv_maxspeed . value ;
2005-03-28 00:11:59 +00:00
ent - > v - > movetype = MOVETYPE_NOCLIP ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Join_f
Set client to player mode without reconnecting
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Join_f ( void )
{
int i ;
client_t * cl ;
int numclients ;
extern cvar_t maxclients ;
if ( host_client - > state ! = cs_spawned )
return ;
if ( ! host_client - > spectator )
return ; // already a player
2007-09-03 22:37:13 +00:00
if ( svs . gametype ! = GT_PROGS )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Sorry, not implemented in this gamecode type. Try moaning at the dev team \n " ) ;
2007-09-03 22:37:13 +00:00
return ;
}
2005-01-04 08:04:42 +00:00
if ( ! ( host_client - > zquake_extensions & Z_EXT_JOIN_OBSERVE ) )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Your QW client doesn't support this command \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2005-01-04 08:04:42 +00:00
if ( password . string [ 0 ] & & stricmp ( password . string , " none " ) )
{
2009-04-06 00:34:32 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " This server requires a %s password. Please disconnect, set the password and reconnect as %s. \n " , " player " , " player " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
// count players already on server
numclients = 0 ;
2005-01-04 08:04:42 +00:00
for ( i = 0 , cl = svs . clients ; i < sv . allocated_client_slots ; i + + , cl + + )
{
2004-08-23 00:15:46 +00:00
if ( cl - > state ! = cs_free & & ! cl - > spectator )
numclients + + ;
}
2005-01-04 08:04:42 +00:00
if ( numclients > = maxclients . value )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Can't join, all player slots full \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
// call the prog function for removing a client
// this will set the body to a dead frame, among other things
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
if ( SpectatorDisconnect )
PR_ExecuteProgram ( svprogfuncs , SpectatorDisconnect ) ;
host_client - > old_frags = 0 ;
2005-10-07 16:27:20 +00:00
SV_SetUpClientEdict ( host_client , host_client - > edict ) ;
2004-08-23 00:15:46 +00:00
// turn the spectator into a player
host_client - > spectator = false ;
Info_RemoveKey ( host_client - > userinfo , " *spectator " ) ;
2006-02-22 23:29:59 +00:00
Info_RemoveKey ( host_client - > userinfobasic , " *spectator " ) ;
2004-08-23 00:15:46 +00:00
// FIXME, bump the client's userid?
// call the progs to get default spawn parms for the new client
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > SetNewParms ) ;
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
2005-06-22 17:10:13 +00:00
{
if ( spawnparamglobals [ i ] )
host_client - > spawn_parms [ i ] = * spawnparamglobals [ i ] ;
else
host_client - > spawn_parms [ i ] = 0 ;
}
2004-08-23 00:15:46 +00:00
// call the spawn function
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > ClientConnect ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// actually spawn the player
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
2005-07-03 15:16:20 +00:00
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > PutClientInServer ) ;
2004-08-23 00:15:46 +00:00
// send notification to all clients
host_client - > sendinfo = true ;
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " joined " ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
Cmd_Observe_f
Set client to spectator mode without reconnecting
= = = = = = = = = = = = = = = = = =
*/
void Cmd_Observe_f ( void )
{
int i ;
client_t * cl ;
int numspectators ;
extern cvar_t maxspectators , spectator_password ;
if ( host_client - > state ! = cs_spawned )
return ;
if ( host_client - > spectator )
return ; // already a spectator
2007-09-03 22:37:13 +00:00
if ( svs . gametype ! = GT_PROGS )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Sorry, not implemented in this gamecode type. Try moaning at the dev team \n " ) ;
2007-09-03 22:37:13 +00:00
return ;
}
2004-08-23 00:15:46 +00:00
2005-01-17 17:48:13 +00:00
if ( ! ( host_client - > zquake_extensions & Z_EXT_JOIN_OBSERVE ) )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Your QW client doesn't support this command \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
2005-01-17 17:48:13 +00:00
if ( spectator_password . string [ 0 ] & & stricmp ( spectator_password . string , " none " ) )
{
2009-04-06 00:34:32 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " This server requires a %s password. Please disconnect, set the password and reconnect as %s. \n " , " spectator " , " spectator " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
// count spectators already on server
numspectators = 0 ;
for ( i = 0 , cl = svs . clients ; i < sv . allocated_client_slots ; i + + , cl + + ) {
if ( cl - > state ! = cs_free & & cl - > spectator )
numspectators + + ;
}
2005-01-17 17:48:13 +00:00
if ( numspectators > = maxspectators . value )
{
2009-04-06 00:34:32 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Can't join, all spectator slots full \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
// call the prog function for removing a client
// this will set the body to a dead frame, among other things
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > ClientDisconnect ) ;
host_client - > old_frags = 0 ;
2005-10-07 16:27:20 +00:00
SV_SetUpClientEdict ( host_client , host_client - > edict ) ;
2004-08-23 00:15:46 +00:00
// turn the player into a spectator
host_client - > spectator = true ;
2005-03-07 08:58:26 +00:00
Info_SetValueForStarKey ( host_client - > userinfo , " *spectator " , " 1 " , sizeof ( host_client - > userinfo ) ) ;
2006-02-22 23:29:59 +00:00
Info_SetValueForStarKey ( host_client - > userinfobasic , " *spectator " , " 1 " , sizeof ( host_client - > userinfobasic ) ) ;
2004-08-23 00:15:46 +00:00
// FIXME, bump the client's userid?
// call the progs to get default spawn parms for the new client
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > SetNewParms ) ;
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
2005-06-22 17:10:13 +00:00
{
if ( spawnparamglobals [ i ] )
host_client - > spawn_parms [ i ] = * spawnparamglobals [ i ] ;
else
host_client - > spawn_parms [ i ] = 0 ;
}
2004-08-23 00:15:46 +00:00
SV_SpawnSpectator ( ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// call the spawn function
2005-01-17 17:48:13 +00:00
if ( SpectatorConnect )
{
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
PR_ExecuteProgram ( svprogfuncs , SpectatorConnect ) ;
}
2005-08-26 22:56:51 +00:00
else
sv_player - > v - > movetype = MOVETYPE_NOCLIP ;
2004-08-23 00:15:46 +00:00
// send notification to all clients
host_client - > sendinfo = true ;
2007-07-27 21:24:31 +00:00
SV_LogPlayer ( host_client , " observing " ) ;
2004-08-23 00:15:46 +00:00
}
2007-07-23 11:44:45 +00:00
void Cmd_FPSList_f ( void )
{
client_t * cl ;
int c ;
int f ;
2009-05-24 10:11:17 +00:00
double minf = 1000 , maxf = 0 , this ;
2007-07-23 11:44:45 +00:00
double ftime ;
int frames ;
2009-06-23 21:49:44 +00:00
int inbytes ;
int outbytes ;
int msecs ;
2007-07-23 11:44:45 +00:00
for ( c = 0 ; c < sv . allocated_client_slots ; c + + )
{
cl = & svs . clients [ c ] ;
ftime = 0 ;
frames = 0 ;
2009-06-23 21:49:44 +00:00
inbytes = 0 ;
outbytes = 0 ;
2009-07-05 18:45:53 +00:00
msecs = 0 ;
2007-07-23 11:44:45 +00:00
if ( ! cl - > state )
continue ;
2009-06-23 21:49:44 +00:00
if ( cl - > protocol ! = SCP_QUAKEWORLD )
continue ;
2007-07-23 11:44:45 +00:00
if ( cl - > frameunion . frames )
{
for ( f = 0 ; f < UPDATE_BACKUP ; f + + )
{
if ( cl - > frameunion . frames [ f ] . move_msecs > = 0 )
{
2009-05-24 10:11:17 +00:00
if ( ! cl - > frameunion . frames [ f ] . move_msecs )
2009-06-23 21:49:44 +00:00
{
2009-05-24 10:11:17 +00:00
this = 1001 ;
2009-06-23 21:49:44 +00:00
msecs + = 1 ;
}
2009-05-24 10:11:17 +00:00
else
2009-06-23 21:49:44 +00:00
{
2009-05-24 10:11:17 +00:00
this = 1000.0f / cl - > frameunion . frames [ f ] . move_msecs ;
2009-06-23 21:49:44 +00:00
msecs + = cl - > frameunion . frames [ f ] . move_msecs ;
}
2007-07-23 11:44:45 +00:00
ftime + = this ;
2009-05-24 10:11:17 +00:00
if ( minf > this )
2007-07-23 11:44:45 +00:00
minf = this ;
2009-05-24 10:11:17 +00:00
if ( maxf < this )
2007-07-23 11:44:45 +00:00
maxf = this ;
frames + + ;
2009-06-23 21:49:44 +00:00
inbytes + = cl - > frameunion . frames [ f ] . packetsizein ;
outbytes + = cl - > frameunion . frames [ f ] . packetsizeout ;
2007-07-23 11:44:45 +00:00
}
}
}
if ( frames )
2009-06-23 21:49:44 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " %s: %ffps (min%f max %f), in: %fbps, out: %fbps \n " , cl - > name , ftime / frames , minf , maxf , ( 1000.0f * inbytes ) / msecs , ( 1000.0f * outbytes ) / msecs ) ;
2007-07-23 11:44:45 +00:00
else
2009-04-06 00:34:32 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " %s: no information available \n " , cl - > name ) ;
2007-07-23 11:44:45 +00:00
}
}
2005-03-10 03:55:18 +00:00
void SV_EnableClientsCSQC ( void )
{
2005-11-03 23:40:51 +00:00
# ifdef PEXT_CSQC
2007-06-20 00:02:54 +00:00
if ( host_client - > fteprotocolextensions & PEXT_CSQC | | atoi ( Cmd_Argv ( 1 ) ) )
2005-10-04 20:37:23 +00:00
host_client - > csqcactive = true ;
else
2009-04-06 00:34:32 +00:00
SV_ClientPrintf ( host_client , PRINT_HIGH , " CSQC entities not enabled - no support from network protocol \n " ) ;
2005-11-03 23:40:51 +00:00
# endif
2005-03-10 03:55:18 +00:00
}
2006-01-11 22:21:35 +00:00
void SV_DisableClientsCSQC ( void )
{
# ifdef PEXT_CSQC
2007-06-20 00:02:54 +00:00
host_client - > csqcactive = false ;
2006-01-11 22:21:35 +00:00
# endif
}
2005-03-10 03:55:18 +00:00
2010-01-11 17:39:56 +00:00
void SV_UserCmdMVDList_f ( void ) ;
2004-08-23 00:15:46 +00:00
void SV_MVDInfo_f ( void ) ;
typedef struct
{
char * name ;
void ( * func ) ( void ) ;
2004-12-05 11:51:44 +00:00
qboolean noqchandling ;
2004-08-23 00:15:46 +00:00
} ucmd_t ;
ucmd_t ucmds [ ] =
{
2004-12-05 11:51:44 +00:00
{ " new " , SV_New_f , true } ,
{ " pk3list " , SV_PK3List_f , true } ,
{ " modellist " , SV_Modellist_f , true } ,
{ " soundlist " , SV_Soundlist_f , true } ,
{ " prespawn " , SV_PreSpawn_f , true } ,
{ " spawn " , SV_Spawn_f , true } ,
{ " begin " , SV_Begin_f , true } ,
2004-08-23 00:15:46 +00:00
{ " join " , Cmd_Join_f } ,
{ " observe " , Cmd_Observe_f } ,
{ " drop " , SV_Drop_f } ,
{ " disconnect " , SV_Drop_f } ,
{ " pings " , SV_Pings_f } ,
2005-07-03 15:16:20 +00:00
// issued by hand at client consoles
2004-08-23 00:15:46 +00:00
{ " rate " , SV_Rate_f } ,
{ " kill " , SV_Kill_f } ,
{ " pause " , SV_Pause_f } ,
{ " msg " , SV_Msg_f } ,
{ " sayone " , SV_SayOne_f } ,
{ " say " , SV_Say_f } ,
{ " say_team " , SV_Say_Team_f } ,
{ " setinfo " , SV_SetInfo_f } ,
{ " serverinfo " , SV_ShowServerinfo_f } ,
2008-11-09 22:29:28 +00:00
{ " dlsize " , SV_DownloadSize_f } ,
2004-08-23 00:15:46 +00:00
{ " download " , SV_BeginDownload_f } ,
{ " nextdl " , SV_NextDownload_f } ,
{ " ptrack " , SV_PTrack_f } , //ZOID - used with autocam
2005-03-10 03:55:18 +00:00
{ " enablecsqc " , SV_EnableClientsCSQC } ,
2006-01-11 22:21:35 +00:00
{ " disablecsqc " , SV_DisableClientsCSQC } ,
2004-08-23 00:15:46 +00:00
{ " snap " , SV_NoSnap_f } ,
{ " vote " , SV_Vote_f } ,
# ifdef SVRANKING
{ " topten " , Rank_ListTop10_f } ,
# endif
2007-07-23 11:44:45 +00:00
{ " efpslist " , Cmd_FPSList_f } , //don't conflict with the ktpro one
2004-08-23 00:15:46 +00:00
{ " god " , Cmd_God_f } ,
{ " give " , Cmd_Give_f } ,
{ " noclip " , Cmd_Noclip_f } ,
2005-01-07 02:36:13 +00:00
{ " fly " , Cmd_Fly_f } ,
{ " notarget " , Cmd_Notarget_f } ,
2004-08-23 00:15:46 +00:00
{ " setpos " , Cmd_SetPos_f } ,
2007-06-20 00:02:54 +00:00
{ " stopdownload " , SV_StopDownload_f } ,
2010-01-11 17:39:56 +00:00
{ " demolist " , SV_UserCmdMVDList_f } ,
2004-08-23 00:15:46 +00:00
{ " demoinfo " , SV_MVDInfo_f } ,
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
{ NULL , NULL }
} ;
# ifdef Q2SERVER
ucmd_t ucmdsq2 [ ] = {
2004-12-05 11:51:44 +00:00
{ " new " , SV_New_f , true } ,
{ " configstrings " , SVQ2_ConfigStrings_f , true } ,
{ " baselines " , SVQ2_BaseLines_f , true } ,
{ " begin " , SV_Begin_f , true } ,
2004-08-23 00:15:46 +00:00
2005-03-20 02:57:11 +00:00
// {"setinfo", SV_SetInfo_f, true},
2004-08-23 00:15:46 +00:00
2004-12-05 11:51:44 +00:00
{ " serverinfo " , SV_ShowServerinfo_f , true } ,
2005-03-20 02:57:11 +00:00
{ " info " , SV_ShowServerinfo_f , true } ,
2004-08-23 00:15:46 +00:00
2004-12-05 11:51:44 +00:00
{ " download " , SV_BeginDownload_f , true } ,
{ " nextdl " , SV_NextDownload_f , true } ,
2004-08-23 00:15:46 +00:00
2004-12-05 11:51:44 +00:00
{ " nextserver " , SVQ2_NextServer_f , true } ,
2004-08-27 00:45:34 +00:00
2004-12-05 11:51:44 +00:00
{ " vote " , SV_Vote_f , true } ,
2004-08-23 00:15:46 +00:00
2005-03-20 02:57:11 +00:00
//#ifdef SVRANKING
// {"topten", Rank_ListTop10_f, true},
//#endif
2004-08-23 00:15:46 +00:00
2004-12-05 11:51:44 +00:00
{ " drop " , SV_Drop_f , true } ,
{ " disconnect " , SV_Drop_f , true } ,
2004-08-23 00:15:46 +00:00
{ NULL , NULL }
} ;
# endif
2005-10-23 17:57:20 +00:00
extern ucmd_t nqucmds [ ] ;
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = =
SV_ExecuteUserCommand
= = = = = = = = = = = = = = = = = =
*/
void SV_ExecuteUserCommand ( char * s , qboolean fromQC )
{
ucmd_t * u ;
client_t * oldhost = host_client ;
2008-06-08 14:37:57 +00:00
char adr [ MAX_ADR_SIZE ] ;
2004-12-05 15:19:11 +00:00
Con_DPrintf ( " Client command: %s \n " , s ) ;
2005-07-03 15:16:20 +00:00
2004-12-08 04:14:52 +00:00
Cmd_TokenizeString ( s , false , false ) ;
2004-08-23 00:15:46 +00:00
sv_player = host_client - > edict ;
Cmd_ExecLevel = 1 ;
2007-01-30 08:44:34 +00:00
if ( host_client - > controlled & & atoi ( Cmd_Argv ( 0 ) ) > 0 ) //now see if it's meant to be from a slave client
2004-08-23 00:15:46 +00:00
{
int pnum = atoi ( Cmd_Argv ( 0 ) ) ;
client_t * s ;
for ( s = host_client ; s ; s = s - > controlled )
{
if ( ! - - pnum )
{
host_client = s ;
break ;
}
}
sv_player = host_client - > edict ;
2004-12-08 04:14:52 +00:00
Cmd_ShiftArgs ( 1 , false ) ;
2004-08-23 00:15:46 +00:00
}
# ifdef Q2SERVER
2005-05-26 12:55:34 +00:00
if ( ISQ2CLIENT ( host_client ) )
2004-08-23 00:15:46 +00:00
u = ucmdsq2 ;
else
# endif
2005-11-03 23:40:51 +00:00
# ifdef NQPROT
2005-10-23 17:57:20 +00:00
if ( ISNQCLIENT ( host_client ) )
u = nqucmds ;
else
2005-11-03 23:40:51 +00:00
# endif
2004-08-23 00:15:46 +00:00
u = ucmds ;
for ( ; u - > name ; u + + )
if ( ! strcmp ( Cmd_Argv ( 0 ) , u - > name ) )
{
2004-12-05 11:51:44 +00:00
if ( ! fromQC & & ! u - > noqchandling )
2004-12-15 19:58:07 +00:00
if ( PR_KrimzonParseCommand ( s ) ) //KRIMZON_SV_PARSECLIENTCOMMAND has the opertunity to parse out certain commands.
2004-12-05 11:51:44 +00:00
{
host_client = oldhost ;
return ;
}
2008-11-09 22:29:28 +00:00
// SV_BeginRedirect (RD_CLIENT, host_client->language);
2005-11-26 21:14:47 +00:00
if ( u - > func )
u - > func ( ) ;
2004-12-05 11:51:44 +00:00
host_client = oldhost ;
2008-11-09 22:29:28 +00:00
// SV_EndRedirect ();
2004-12-05 11:51:44 +00:00
return ;
2004-08-23 00:15:46 +00:00
}
if ( ! u - > name )
{
2009-03-03 01:52:30 +00:00
# ifdef HLSERVER
if ( HLSV_ClientCommand ( host_client ) )
{
host_client = oldhost ;
return ;
}
# endif
2004-08-23 00:15:46 +00:00
if ( ! fromQC )
2004-12-15 19:58:07 +00:00
if ( PR_UserCmd ( s ) ) //Q2 and MVDSV command handling only happens if the engine didn't recognise it.
2004-08-27 00:45:34 +00:00
{
host_client = oldhost ;
2004-08-23 00:15:46 +00:00
return ;
2004-08-27 00:45:34 +00:00
}
2005-11-03 23:40:51 +00:00
# ifdef SVRANKING
2004-08-23 00:15:46 +00:00
if ( sv_cmdlikercon . value & & host_client - > rankid )
{
char remaining [ 1024 ] ;
int i ;
rankstats_t stats ;
if ( ! Rank_GetPlayerStats ( host_client - > rankid , & stats ) )
{
host_client = oldhost ;
return ;
}
Con_Printf ( " cmd from %s: \n %s \n "
, host_client - > name , net_message . data + 4 ) ;
2005-01-16 00:59:48 +00:00
SV_BeginRedirect ( RD_CLIENT , host_client - > language ) ;
2004-08-23 00:15:46 +00:00
remaining [ 0 ] = 0 ;
for ( i = 0 ; i < Cmd_Argc ( ) ; i + + )
{
if ( strlen ( remaining ) + strlen ( Cmd_Argv ( i ) ) > = sizeof ( remaining ) - 1 )
{
Con_Printf ( " cmd was too long \n " ) ;
host_client = oldhost ;
SV_EndRedirect ( ) ;
Con_Printf ( " cmd from %s: \n %s \n "
2008-06-08 14:37:57 +00:00
, NET_AdrToString ( adr , sizeof ( adr ) , net_from ) , " Was too long - possible buffer overflow attempt " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
strcat ( remaining , Cmd_Argv ( i ) ) ;
strcat ( remaining , " " ) ;
}
Cmd_ExecuteString ( remaining , stats . trustlevel ) ;
host_client = oldhost ;
SV_EndRedirect ( ) ;
return ;
}
2005-11-03 23:40:51 +00:00
# endif
2004-08-23 00:15:46 +00:00
Con_Printf ( " Bad user command: %s \n " , Cmd_Argv ( 0 ) ) ;
}
host_client = oldhost ;
SV_EndRedirect ( ) ;
}
# ifdef NQPROT
void SVNQ_Spawn_f ( void )
{
2005-02-12 18:56:04 +00:00
extern cvar_t sv_gravity ;
2004-08-23 00:15:46 +00:00
int i ;
client_t * client ;
edict_t * ent ;
if ( host_client - > state ! = cs_connected )
{
2005-07-28 15:22:15 +00:00
Con_Printf ( " spawn not valid -- already spawned \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
// send all current names, colors, and frag counts
// FIXME: is this a good thing?
SZ_Clear ( & host_client - > netchan . message ) ;
// send current status of all other players
// normally this could overflow, but no need to check due to backbuf
for ( i = 0 , client = svs . clients ; i < sv . allocated_client_slots ; i + + , client + + )
SV_FullClientUpdateToClient ( client , host_client ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// send all current light styles
for ( i = 0 ; i < MAX_LIGHTSTYLES ; i + + )
{
2005-10-23 17:57:20 +00:00
if ( i > = MAX_STANDARDLIGHTSTYLES & & host_client - > protocol ! = SCP_DARKPLACES7 )
break ; //dp7 clients support more lightstyles.
2005-07-03 15:16:20 +00:00
ClientReliableWrite_Begin ( host_client , svc_lightstyle ,
2006-02-17 02:51:59 +00:00
3 + ( sv . strings . lightstyles [ i ] ? strlen ( sv . strings . lightstyles [ i ] ) : 1 ) ) ;
2004-08-23 00:15:46 +00:00
ClientReliableWrite_Byte ( host_client , ( char ) i ) ;
2006-02-17 02:51:59 +00:00
ClientReliableWrite_String ( host_client , sv . strings . lightstyles [ i ] ) ;
2004-08-23 00:15:46 +00:00
}
// set up the edict
ent = host_client - > edict ;
if ( host_client - > istobeloaded ) //minimal setup
{
2007-09-02 19:55:17 +00:00
host_client - > entgravity = ent - > xv - > gravity * sv_gravity . value ;
host_client - > maxspeed = ent - > xv - > maxspeed ;
2004-08-23 00:15:46 +00:00
}
else
{
2005-05-17 02:36:54 +00:00
memset ( ent - > v , 0 , pr_edict_size ) ;
2008-06-01 22:06:22 +00:00
ED_Spawned ( ent , false ) ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
ent - > v - > colormap = NUM_FOR_EDICT ( svprogfuncs , ent ) ;
ent - > v - > team = 0 ; // FIXME
ent - > v - > netname = PR_SetString ( svprogfuncs , host_client - > name ) ;
2004-08-23 00:15:46 +00:00
2007-09-02 19:55:17 +00:00
host_client - > entgravity = ent - > xv - > gravity = 1.0 ;
2005-02-12 18:56:04 +00:00
host_client - > entgravity * = sv_gravity . value ;
2007-09-02 19:55:17 +00:00
host_client - > maxspeed = ent - > xv - > maxspeed = sv_maxspeed . value ;
2004-08-23 00:15:46 +00:00
}
//
// force stats to be updated
//
2008-05-25 22:23:43 +00:00
memset ( host_client - > statsi , 0 , sizeof ( host_client - > statsi ) ) ;
memset ( host_client - > statsf , 0 , sizeof ( host_client - > statsf ) ) ;
memset ( host_client - > statss , 0 , sizeof ( host_client - > statss ) ) ;
2004-08-23 00:15:46 +00:00
ClientReliableWrite_Begin ( host_client , svc_updatestat , 6 ) ;
ClientReliableWrite_Byte ( host_client , STAT_TOTALSECRETS ) ;
ClientReliableWrite_Long ( host_client , pr_global_struct - > total_secrets ) ;
ClientReliableWrite_Begin ( host_client , svc_updatestat , 6 ) ;
ClientReliableWrite_Byte ( host_client , STAT_TOTALMONSTERS ) ;
ClientReliableWrite_Long ( host_client , pr_global_struct - > total_monsters ) ;
ClientReliableWrite_Begin ( host_client , svc_updatestat , 6 ) ;
ClientReliableWrite_Byte ( host_client , STAT_SECRETS ) ;
ClientReliableWrite_Long ( host_client , pr_global_struct - > found_secrets ) ;
ClientReliableWrite_Begin ( host_client , svc_updatestat , 6 ) ;
ClientReliableWrite_Byte ( host_client , STAT_MONSTERS ) ;
ClientReliableWrite_Long ( host_client , pr_global_struct - > killed_monsters ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
SZ_Write ( & host_client - > netchan . message , sv . signon . data , sv . signon . cursize ) ;
MSG_WriteByte ( & host_client - > netchan . message , svc_signonnum ) ;
MSG_WriteByte ( & host_client - > netchan . message , 3 ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
host_client - > send_message = true ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
}
void SVNQ_Begin_f ( void )
{
unsigned pmodel = 0 , emodel = 0 ;
int i ;
qboolean sendangles = false ;
if ( host_client - > state = = cs_spawned )
return ; // don't begin again
host_client - > state = cs_spawned ;
if ( host_client - > istobeloaded )
{
sendangles = true ;
host_client - > istobeloaded = false ;
}
else
{
if ( host_client - > spectator )
{
SV_SpawnSpectator ( ) ;
if ( SpectatorConnect )
{
// copy spawn parms out of the client_t
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
2005-06-22 17:10:13 +00:00
{
if ( spawnparamglobals [ i ] )
* spawnparamglobals [ i ] = host_client - > spawn_parms [ i ] ;
}
2004-08-23 00:15:46 +00:00
// call the spawn function
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
PR_ExecuteProgram ( svprogfuncs , SpectatorConnect ) ;
}
}
else
{
// copy spawn parms out of the client_t
for ( i = 0 ; i < NUM_SPAWN_PARMS ; i + + )
2005-06-22 17:10:13 +00:00
{
if ( spawnparamglobals [ i ] )
* spawnparamglobals [ i ] = host_client - > spawn_parms [ i ] ;
}
2004-08-23 00:15:46 +00:00
// call the spawn function
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > ClientConnect ) ;
// actually spawn the player
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
2005-07-03 15:16:20 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > PutClientInServer ) ;
2004-08-23 00:15:46 +00:00
}
}
// clear the net statistics, because connecting gives a bogus picture
host_client - > netchan . frame_latency = 0 ;
host_client - > netchan . frame_rate = 0 ;
host_client - > netchan . drop_count = 0 ;
host_client - > netchan . good_count = 0 ;
//check he's not cheating
if ( sv_playermodelchecks . value )
{
pmodel = atoi ( Info_ValueForKey ( host_client - > userinfo , " pmodel " ) ) ;
emodel = atoi ( Info_ValueForKey ( host_client - > userinfo , " emodel " ) ) ;
if ( pmodel ! = sv . model_player_checksum | |
emodel ! = sv . eyes_player_checksum )
SV_BroadcastTPrintf ( PRINT_HIGH , STL_POSSIBLEMODELCHEAT , host_client - > name ) ;
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// if we are paused, tell the client
if ( sv . paused )
{
2005-05-26 12:55:34 +00:00
if ( ! ISQ2CLIENT ( host_client ) )
2004-08-23 00:15:46 +00:00
{
ClientReliableWrite_Begin ( host_client , svc_setpause , 2 ) ;
ClientReliableWrite_Byte ( host_client , sv . paused ) ;
}
SV_ClientTPrintf ( host_client , PRINT_HIGH , STL_SERVERPAUSED ) ;
}
if ( sendangles )
{
//
// send a fixangle over the reliable channel to make sure it gets there
// Never send a roll angle, because savegames can catch the server
// in a state where it is expecting the client to correct the angle
// and it won't happen if the game was just loaded, so you wind up
2005-07-03 15:16:20 +00:00
// with a permanent head tilt
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svc_setangle ) ;
MSG_WriteAngle ( & host_client - > netchan . message , 0 ) ;
2005-03-28 00:11:59 +00:00
MSG_WriteAngle ( & host_client - > netchan . message , host_client - > edict - > v - > angles [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
MSG_WriteAngle ( & host_client - > netchan . message , 0 ) ;
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
SZ_Write ( & host_client - > netchan . message , sv . signon . data , sv . signon . cursize ) ;
2005-05-26 12:55:34 +00:00
// MSG_WriteByte (&host_client->netchan.message, svc_signonnum);
// MSG_WriteByte (&host_client->netchan.message, 4);
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
host_client - > send_message = true ;
}
void SVNQ_PreSpawn_f ( void )
{
edict_t * ent ;
entity_state_t * state ;
int i , e ;
if ( host_client - > state ! = cs_connected )
{
2005-07-28 15:22:15 +00:00
Con_Printf ( " prespawn not valid -- already spawned \n " ) ;
2004-08-23 00:15:46 +00:00
return ;
}
for ( e = 1 ; e < sv . num_edicts ; e + + )
{
ent = EDICT_NUM ( svprogfuncs , e ) ;
state = & ent - > baseline ;
if ( ! state - > number | | ! state - > modelindex )
{ //ent doesn't have a baseline
continue ;
}
if ( ! ent )
{
MSG_WriteByte ( & host_client - > netchan . message , svc_spawnbaseline ) ;
MSG_WriteShort ( & host_client - > netchan . message , e ) ;
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
MSG_WriteByte ( & host_client - > netchan . message , 0 ) ;
for ( i = 0 ; i < 3 ; i + + )
{
MSG_WriteCoord ( & host_client - > netchan . message , 0 ) ;
MSG_WriteAngle ( & host_client - > netchan . message , 0 ) ;
}
}
else
{
2005-06-14 04:52:10 +00:00
if ( host_client - > protocol ! = SCP_NETQUAKE & & ( state - > modelindex > 255 | | state - > frame > 255 ) )
{
MSG_WriteByte ( & host_client - > netchan . message , svcdp_spawnbaseline2 ) ;
2004-08-23 00:15:46 +00:00
2005-06-14 04:52:10 +00:00
MSG_WriteShort ( & host_client - > netchan . message , e ) ;
MSG_WriteShort ( & host_client - > netchan . message , state - > modelindex ) ;
MSG_WriteShort ( & host_client - > netchan . message , state - > frame ) ;
}
else
{
MSG_WriteByte ( & host_client - > netchan . message , svc_spawnbaseline ) ;
2004-08-23 00:15:46 +00:00
2005-06-14 04:52:10 +00:00
MSG_WriteShort ( & host_client - > netchan . message , e ) ;
MSG_WriteByte ( & host_client - > netchan . message , state - > modelindex & 255 ) ;
MSG_WriteByte ( & host_client - > netchan . message , state - > frame & 255 ) ;
}
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , ( int ) state - > colormap ) ;
MSG_WriteByte ( & host_client - > netchan . message , ( int ) state - > skinnum ) ;
for ( i = 0 ; i < 3 ; i + + )
{
MSG_WriteCoord ( & host_client - > netchan . message , state - > origin [ i ] ) ;
MSG_WriteAngle ( & host_client - > netchan . message , state - > angles [ i ] ) ;
}
}
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < sv . num_signon_buffers ; i + + )
SZ_Write ( & host_client - > netchan . message , sv . signon_buffers [ i ] , sv . signon_buffer_size [ i ] ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & host_client - > netchan . message , svc_signonnum ) ;
MSG_WriteByte ( & host_client - > netchan . message , 2 ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
host_client - > send_message = true ;
}
void SVNQ_NQInfo_f ( void )
{
2004-12-08 04:14:52 +00:00
Cmd_TokenizeString ( va ( " setinfo \" %s \" \" %s \" \n " , Cmd_Argv ( 0 ) , Cmd_Argv ( 1 ) ) , false , false ) ;
2005-07-03 15:16:20 +00:00
SV_SetInfo_f ( ) ;
2004-08-23 00:15:46 +00:00
}
void SVNQ_NQColour_f ( void )
{
int top ;
int bottom ;
int playercolor ;
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 ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
playercolor = top * 16 + bottom ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
if ( progstype ! = PROG_QW )
2005-03-28 00:11:59 +00:00
host_client - > edict - > v - > team = bottom + 1 ;
2004-08-23 00:15:46 +00:00
2005-03-07 08:58:26 +00:00
Info_SetValueForKey ( host_client - > userinfo , " topcolor " , va ( " %i " , top ) , sizeof ( host_client - > userinfo ) ) ;
Info_SetValueForKey ( host_client - > userinfo , " bottomcolor " , va ( " %i " , bottom ) , sizeof ( host_client - > userinfo ) ) ;
2004-08-23 00:15:46 +00:00
switch ( bottom )
{
case 4 :
2005-03-07 08:58:26 +00:00
Info_SetValueForKey ( host_client - > userinfo , " team " , " red " , sizeof ( host_client - > userinfo ) ) ;
2004-08-23 00:15:46 +00:00
break ;
case 14 :
2005-03-07 08:58:26 +00:00
Info_SetValueForKey ( host_client - > userinfo , " team " , " blue " , sizeof ( host_client - > userinfo ) ) ;
2004-08-23 00:15:46 +00:00
break ;
default :
2005-03-07 08:58:26 +00:00
Info_SetValueForKey ( host_client - > userinfo , " team " , va ( " t%i " , bottom + 1 ) , sizeof ( host_client - > userinfo ) ) ;
2004-08-23 00:15:46 +00:00
break ;
}
SV_ExtractFromUserinfo ( host_client ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
MSG_WriteByte ( & sv . reliable_datagram , svc_setinfo ) ;
MSG_WriteByte ( & sv . reliable_datagram , host_client - svs . clients ) ;
MSG_WriteString ( & sv . reliable_datagram , " topcolor " ) ;
MSG_WriteString ( & sv . reliable_datagram , Info_ValueForKey ( host_client - > userinfo , " topcolor " ) ) ;
MSG_WriteByte ( & sv . reliable_datagram , svc_setinfo ) ;
MSG_WriteByte ( & sv . reliable_datagram , host_client - svs . clients ) ;
MSG_WriteString ( & sv . reliable_datagram , " bottomcolor " ) ;
MSG_WriteString ( & sv . reliable_datagram , Info_ValueForKey ( host_client - > userinfo , " bottomcolor " ) ) ;
MSG_WriteByte ( & sv . reliable_datagram , svc_setinfo ) ;
MSG_WriteByte ( & sv . reliable_datagram , host_client - svs . clients ) ;
MSG_WriteString ( & sv . reliable_datagram , " team " ) ;
MSG_WriteString ( & sv . reliable_datagram , Info_ValueForKey ( host_client - > userinfo , " team " ) ) ;
MSG_WriteByte ( & sv . nqreliable_datagram , svc_updatecolors ) ;
MSG_WriteByte ( & sv . nqreliable_datagram , host_client - svs . clients ) ;
MSG_WriteByte ( & sv . nqreliable_datagram , playercolor ) ;
}
2005-05-26 12:55:34 +00:00
void SVNQ_Ping_f ( void )
{
int i ;
client_t * cl ;
2008-11-09 22:29:28 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , " Client ping times: \n " ) ;
2005-05-26 12:55:34 +00:00
for ( i = 0 , cl = svs . clients ; i < MAX_CLIENTS ; i + + , cl + + )
{
if ( ! cl - > state )
continue ;
2008-11-09 22:29:28 +00:00
SV_PrintToClient ( host_client , PRINT_HIGH , va ( " %3i %s \n " , SV_CalcPing ( cl ) , cl - > name ) ) ;
2005-05-26 12:55:34 +00:00
}
}
2004-08-23 00:15:46 +00:00
ucmd_t nqucmds [ ] =
{
2007-06-20 00:02:54 +00:00
{ " new " , SVNQ_New_f , true } ,
2004-08-23 00:15:46 +00:00
{ " status " , NULL } ,
{ " god " , Cmd_God_f } ,
{ " give " , Cmd_Give_f } ,
2005-01-07 02:36:13 +00:00
{ " notarget " , Cmd_Notarget_f } ,
2004-08-23 00:15:46 +00:00
{ " fly " , NULL } ,
{ " noclip " , Cmd_Noclip_f } ,
2007-06-20 00:02:54 +00:00
{ " pings " , SV_Pings_f } ,
2004-08-23 00:15:46 +00:00
{ " name " , SVNQ_NQInfo_f } ,
{ " say " , SV_Say_f } ,
{ " say_team " , SV_Say_Team_f } ,
{ " tell " , SV_SayOne_f } ,
{ " color " , SVNQ_NQColour_f } ,
{ " kill " , SV_Kill_f } ,
{ " pause " , SV_Pause_f } ,
2004-12-05 11:51:44 +00:00
{ " spawn " , SVNQ_Spawn_f , true } ,
{ " begin " , SVNQ_Begin_f , true } ,
{ " prespawn " , SVNQ_PreSpawn_f , true } ,
2004-08-23 00:15:46 +00:00
{ " kick " , NULL } ,
2005-05-26 12:55:34 +00:00
{ " ping " , SVNQ_Ping_f } ,
2004-08-23 00:15:46 +00:00
{ " ban " , NULL } ,
{ " vote " , SV_Vote_f } ,
2007-06-10 21:33:24 +00:00
{ " download " , SV_BeginDownload_f } ,
2007-06-20 00:02:54 +00:00
{ " sv_startdownload " , SVDP_StartDownload_f } ,
2007-06-10 21:33:24 +00:00
2005-10-23 17:57:20 +00:00
{ " setinfo " , SV_SetInfo_f } ,
2005-05-19 02:53:03 +00:00
{ " playermodel " , NULL } ,
{ " playerskin " , NULL } ,
2005-07-01 19:23:00 +00:00
{ " rate " , SV_Rate_f } ,
2005-05-19 02:53:03 +00:00
2004-08-23 00:15:46 +00:00
# ifdef SVRANKING
{ " topten " , Rank_ListTop10_f } ,
# endif
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
{ NULL , NULL }
} ;
2005-10-23 17:57:20 +00:00
/*
2004-08-23 00:15:46 +00:00
void SVNQ_ExecuteUserCommand ( char * s )
{
2004-12-05 11:51:44 +00:00
client_t * oldhost = host_client ;
2004-08-23 00:15:46 +00:00
ucmd_t * u ;
2005-07-03 15:16:20 +00:00
2004-12-08 04:14:52 +00:00
Cmd_TokenizeString ( s , false , false ) ;
2004-08-23 00:15:46 +00:00
sv_player = host_client - > edict ;
Cmd_ExecLevel = 1 ;
for ( u = nqucmds ; u - > name ; u + + )
{
if ( ! strcmp ( Cmd_Argv ( 0 ) , u - > name ) )
{
2005-10-23 17:57:20 +00:00
if ( / * ! fromQC & & * / ! u - > noqchandling )
2004-12-05 11:51:44 +00:00
if ( PR_UserCmd ( s ) )
{
host_client = oldhost ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( ! u - > func )
{
2005-01-16 00:59:48 +00:00
SV_BeginRedirect ( RD_CLIENT , host_client - > language ) ;
2004-12-05 11:51:44 +00:00
Con_Printf ( " Command was disabled \n " ) ;
SV_EndRedirect ( ) ;
2004-08-23 00:15:46 +00:00
}
else
2004-12-05 11:51:44 +00:00
{
2005-01-16 00:59:48 +00:00
SV_BeginRedirect ( RD_CLIENT , host_client - > language ) ;
2004-08-23 00:15:46 +00:00
u - > func ( ) ;
2004-12-05 11:51:44 +00:00
SV_EndRedirect ( ) ;
}
host_client = oldhost ;
return ;
2004-08-23 00:15:46 +00:00
}
}
if ( ! u - > name )
Con_Printf ( " %s tried to \" %s \" \n " , host_client - > name , s ) ;
}
2005-10-23 17:57:20 +00:00
*/
2004-08-23 00:15:46 +00:00
# endif
int implevels [ 256 ] ;
qboolean SV_FiltureImpulse ( int imp , int level )
{
if ( imp < 0 | | imp > 255 )
return true ; //erm
if ( implevels [ imp ] > level )
return false ;
return true ;
}
void SV_FilterImpulseInit ( void )
{
char buffer [ 1024 ] ;
char * s ;
int lev ;
int imp ;
memset ( implevels , 0 , sizeof ( implevels ) ) ;
s = COM_LoadStackFile ( " impfiltr.cfg " , buffer , sizeof ( buffer ) ) ;
if ( ! s )
2005-12-21 07:00:33 +00:00
Con_DPrintf ( " impfiltr.cfg not found. Impulse filters are disabled \n " ) ;
2004-08-23 00:15:46 +00:00
while ( s )
{
s = COM_Parse ( s ) ;
if ( ! s )
return ;
imp = atoi ( com_token ) ;
s = COM_Parse ( s ) ;
if ( ! s )
{
Con_Printf ( " Unexpected eof in impfiltr.cfg \n " ) ;
return ;
}
lev = atoi ( com_token ) ;
if ( imp > 255 | | imp < 0 | | lev < 0 | | lev > RESTRICT_MAX )
Con_Printf ( " impfiltr.cfg - bad paramters \n " ) ;
else
implevels [ imp ] = lev ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
USER CMD EXECUTION
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# ifdef SERVERONLY
/*
= = = = = = = = = = = = = = =
V_CalcRoll
Used by view and sv_user
= = = = = = = = = = = = = = =
*/
float V_CalcRoll ( vec3_t angles , vec3_t velocity )
{
vec3_t forward , right , up ;
float sign ;
float side ;
float value ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
AngleVectors ( angles , forward , right , up ) ;
side = DotProduct ( velocity , right ) ;
sign = side < 0 ? - 1 : 1 ;
side = fabs ( side ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
value = cl_rollangle . value ;
if ( side < cl_rollspeed . value )
side = side * value / cl_rollspeed . value ;
else
side = value ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
return side * sign ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
}
# endif
//============================================================================
vec3_t pmove_mins , pmove_maxs ;
/*
= = = = = = = = = = = = = = = = = = = =
AddLinksToPmove
= = = = = = = = = = = = = = = = = = = =
*/
2008-11-09 22:29:28 +00:00
void AddLinksToPmove ( edict_t * player , areanode_t * node )
2004-08-23 00:15:46 +00:00
{
int Q1_HullPointContents ( hull_t * hull , int num , vec3_t p ) ;
link_t * l , * next ;
edict_t * check ;
int pl ;
int i ;
physent_t * pe ;
2005-07-16 00:53:08 +00:00
model_t * model ;
2008-11-09 22:29:28 +00:00
pl = EDICT_TO_PROG ( svprogfuncs , player ) ;
2004-08-23 00:15:46 +00:00
// touch linked edicts
for ( l = node - > solid_edicts . next ; l ! = & node - > solid_edicts ; l = next )
{
next = l - > next ;
check = EDICT_FROM_AREA ( l ) ;
2005-03-28 00:11:59 +00:00
if ( check - > v - > owner = = pl )
2004-08-23 00:15:46 +00:00
continue ; // player's own missile
2005-07-03 15:16:20 +00:00
if ( check - > v - > solid = = SOLID_BSP
| | check - > v - > solid = = SOLID_BBOX
2005-03-28 00:11:59 +00:00
| | check - > v - > solid = = SOLID_SLIDEBOX )
2004-08-23 00:15:46 +00:00
{
2008-11-09 22:29:28 +00:00
if ( check = = player )
2004-08-23 00:15:46 +00:00
continue ;
for ( i = 0 ; i < 3 ; i + + )
2005-03-28 00:11:59 +00:00
if ( check - > v - > absmin [ i ] > pmove_maxs [ i ]
| | check - > v - > absmax [ i ] < pmove_mins [ i ] )
2004-08-23 00:15:46 +00:00
break ;
if ( i ! = 3 )
continue ;
2004-09-04 18:01:53 +00:00
2004-08-23 00:15:46 +00:00
if ( pmove . numphysent = = MAX_PHYSENTS )
break ;
pe = & pmove . physents [ pmove . numphysent ] ;
2008-11-09 22:29:28 +00:00
pe - > notouch = ! ( ( int ) player - > xv - > dimension_solid & ( int ) check - > xv - > dimension_hit ) ;
if ( ! ( ( int ) player - > xv - > dimension_hit & ( int ) check - > xv - > dimension_solid ) )
2004-09-04 18:01:53 +00:00
continue ;
2004-08-23 00:15:46 +00:00
pmove . numphysent + + ;
2005-03-28 00:11:59 +00:00
VectorCopy ( check - > v - > origin , pe - > origin ) ;
2004-08-23 00:15:46 +00:00
pe - > info = NUM_FOR_EDICT ( svprogfuncs , check ) ;
2005-03-28 00:11:59 +00:00
if ( check - > v - > solid = = SOLID_BSP )
2004-11-17 17:38:49 +00:00
{
if ( progstype ! = PROG_H2 )
pe - > angles [ 0 ] * = - 1 ; //quake is wierd. I guess someone fixed it hexen2... or my code is buggy or something...
2005-03-28 00:11:59 +00:00
pe - > model = sv . models [ ( int ) ( check - > v - > modelindex ) ] ;
2005-10-07 02:11:35 +00:00
VectorCopy ( check - > v - > angles , pe - > angles ) ;
2004-11-17 17:38:49 +00:00
}
2004-08-23 00:15:46 +00:00
else
{
pe - > model = NULL ;
2005-03-28 00:11:59 +00:00
VectorCopy ( check - > v - > mins , pe - > mins ) ;
VectorCopy ( check - > v - > maxs , pe - > maxs ) ;
2005-10-07 02:11:35 +00:00
VectorClear ( pe - > angles ) ;
2004-08-23 00:15:46 +00:00
}
}
}
2008-11-09 22:29:28 +00:00
if ( player - > v - > mins [ 2 ] ! = 24 ) //crouching/dead
2004-08-23 00:15:46 +00:00
for ( l = node - > trigger_edicts . next ; l ! = & node - > trigger_edicts ; l = next )
{
next = l - > next ;
check = EDICT_FROM_AREA ( l ) ;
2005-03-28 00:11:59 +00:00
if ( check - > v - > owner = = pl )
2004-08-23 00:15:46 +00:00
continue ; // player's own missile
2005-03-28 00:11:59 +00:00
if ( check - > v - > solid = = SOLID_LADDER )
2004-08-23 00:15:46 +00:00
{
for ( i = 0 ; i < 3 ; i + + )
2005-03-28 00:11:59 +00:00
if ( check - > v - > absmin [ i ] > pmove_maxs [ i ]
| | check - > v - > absmax [ i ] < pmove_mins [ i ] )
2004-08-23 00:15:46 +00:00
break ;
if ( i ! = 3 )
continue ;
2008-11-09 22:29:28 +00:00
if ( ! ( ( int ) player - > xv - > dimension_hit & ( int ) check - > xv - > dimension_solid ) )
2004-08-31 23:58:18 +00:00
continue ;
2005-07-16 00:53:08 +00:00
model = sv . models [ ( int ) check - > v - > modelindex ] ;
if ( model )
2004-08-23 00:15:46 +00:00
// test the point
2008-11-09 22:29:28 +00:00
if ( model - > funcs . PointContents ( model , player - > v - > origin ) = = FTECONTENTS_SOLID )
2009-04-19 00:50:42 +00:00
player - > xv - > pmove_flags = ( int ) player - > xv - > pmove_flags | PMF_LADDER ; //touch that ladder!
2004-08-23 00:15:46 +00:00
}
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// recurse down both sides
if ( node - > axis = = - 1 )
return ;
2008-11-09 22:29:28 +00:00
if ( pmove_maxs [ node - > axis ] > node - > dist )
AddLinksToPmove ( player , node - > children [ 0 ] ) ;
if ( pmove_mins [ node - > axis ] < node - > dist )
AddLinksToPmove ( player , node - > children [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = =
AddAllEntsToPmove
For debugging
= = = = = = = = = = = = = = = =
*/
void AddAllEntsToPmove ( void )
{
int e ;
edict_t * check ;
int i ;
physent_t * pe ;
int pl ;
pl = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
for ( e = 1 ; e < sv . num_edicts ; e + + )
{
check = EDICT_NUM ( svprogfuncs , e ) ;
if ( check - > isfree )
continue ;
2005-03-28 00:11:59 +00:00
if ( check - > v - > owner = = pl )
2004-08-23 00:15:46 +00:00
continue ;
2005-07-03 15:16:20 +00:00
if ( check - > v - > solid = = SOLID_BSP
| | check - > v - > solid = = SOLID_BBOX
2005-03-28 00:11:59 +00:00
| | check - > v - > solid = = SOLID_SLIDEBOX )
2004-08-23 00:15:46 +00:00
{
if ( check = = sv_player )
continue ;
for ( i = 0 ; i < 3 ; i + + )
2005-03-28 00:11:59 +00:00
if ( check - > v - > absmin [ i ] > pmove_maxs [ i ]
| | check - > v - > absmax [ i ] < pmove_mins [ i ] )
2004-08-23 00:15:46 +00:00
break ;
if ( i ! = 3 )
continue ;
pe = & pmove . physents [ pmove . numphysent ] ;
2005-03-28 00:11:59 +00:00
VectorCopy ( check - > v - > origin , pe - > origin ) ;
2004-08-23 00:15:46 +00:00
pmove . physents [ pmove . numphysent ] . info = e ;
2005-03-28 00:11:59 +00:00
if ( check - > v - > solid = = SOLID_BSP )
2005-10-07 02:11:35 +00:00
{
VectorCopy ( check - > v - > angles , pe - > angles ) ;
2005-03-28 00:11:59 +00:00
pe - > model = sv . models [ ( int ) ( check - > v - > modelindex ) ] ;
2005-10-07 02:11:35 +00:00
}
2004-08-23 00:15:46 +00:00
else
{
pe - > angles [ 0 ] = pe - > angles [ 1 ] = pe - > angles [ 2 ] = 0 ;
pe - > model = NULL ;
2005-03-28 00:11:59 +00:00
VectorCopy ( check - > v - > mins , pe - > mins ) ;
VectorCopy ( check - > v - > maxs , pe - > maxs ) ;
2004-08-23 00:15:46 +00:00
}
if ( + + pmove . numphysent = = MAX_PHYSENTS )
break ;
}
}
}
int SV_PMTypeForClient ( client_t * cl )
{
2004-12-06 01:57:07 +00:00
if ( sv . demostatevalid )
{ //force noclip... This does create problems for closing demos.
if ( cl - > zquake_extensions & Z_EXT_PM_TYPE_NEW )
return PM_SPECTATOR ;
return PM_OLD_SPECTATOR ;
}
2005-05-26 12:55:34 +00:00
if ( sv_brokenmovetypes . value ) //this is to mimic standard qw servers, which don't support movetypes other than MOVETYPE_FLY.
{ //it prevents bugs from being visible in unsuspecting mods.
if ( cl - > spectator )
{
if ( cl - > zquake_extensions & Z_EXT_PM_TYPE_NEW )
return PM_SPECTATOR ;
return PM_OLD_SPECTATOR ;
}
if ( cl - > edict - > v - > health < = 0 )
return PM_DEAD ;
return PM_NORMAL ;
}
2005-03-28 00:11:59 +00:00
if ( cl - > edict - > v - > movetype = = MOVETYPE_NOCLIP )
2004-08-23 00:15:46 +00:00
{
if ( cl - > zquake_extensions & Z_EXT_PM_TYPE_NEW )
return PM_SPECTATOR ;
return PM_OLD_SPECTATOR ;
}
2005-03-28 00:11:59 +00:00
if ( cl - > edict - > v - > movetype = = MOVETYPE_FLY )
2004-08-23 00:15:46 +00:00
return PM_FLY ;
2005-03-28 00:11:59 +00:00
if ( cl - > edict - > v - > movetype = = MOVETYPE_NONE )
2004-08-23 00:15:46 +00:00
return PM_NONE ;
2005-03-28 00:11:59 +00:00
if ( cl - > edict - > v - > health < = 0 )
2004-08-23 00:15:46 +00:00
return PM_DEAD ;
return PM_NORMAL ;
}
2005-06-22 17:10:13 +00:00
//called for common csqc/server code (supposedly)
void SV_RunEntity ( edict_t * ent ) ;
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = =
SV_PreRunCmd
= = = = = = = = = = =
Done before running a player command . Clears the touch array
*/
qbyte playertouch [ ( MAX_EDICTS + 7 ) / 8 ] ;
void SV_PreRunCmd ( void )
{
memset ( playertouch , 0 , sizeof ( playertouch ) ) ;
}
/*
= = = = = = = = = = =
SV_RunCmd
= = = = = = = = = = =
*/
void SV_RunCmd ( usercmd_t * ucmd , qboolean recurse )
{
edict_t * ent ;
int i , n ;
int oldmsec ;
double tmp_time ;
qboolean jumpable ;
2008-06-08 14:37:57 +00:00
char adr [ MAX_ADR_SIZE ] ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// DMW copied this KK hack copied from QuakeForge anti-cheat
2005-07-03 15:16:20 +00:00
// (also extra inside parm on all SV_RunCmds that follow)
2004-08-23 00:15:46 +00:00
// To prevent a infinite loop
2006-10-05 22:10:09 +00:00
if ( ! recurse )
{
2004-08-23 00:15:46 +00:00
host_client - > msecs + = ucmd - > msec ;
2006-10-05 22:10:09 +00:00
if ( ( tmp_time = realtime - host_client - > last_check ) > = sv_cheatspeedchecktime . value )
{
2004-08-23 00:15:46 +00:00
tmp_time = tmp_time * 1000.0 * sv_cheatpc . value / 100.0 ;
2006-10-05 22:10:09 +00:00
if ( host_client - > msecs > tmp_time )
{
2004-08-23 00:15:46 +00:00
host_client - > msec_cheating + + ;
2005-07-03 15:16:20 +00:00
SV_BroadcastTPrintf ( PRINT_HIGH ,
2004-08-23 00:15:46 +00:00
STL_SPEEDCHEATPOSSIBLE ,
host_client - > msecs , tmp_time ,
host_client - > msec_cheating , host_client - > name ) ;
2006-10-05 22:10:09 +00:00
if ( host_client - > msec_cheating > = 2 )
{
2005-07-03 15:16:20 +00:00
SV_BroadcastTPrintf ( PRINT_HIGH ,
STL_SPEEDCHEATKICKED ,
2008-06-08 14:37:57 +00:00
host_client - > name , NET_AdrToString ( adr , sizeof ( adr ) , host_client - > netchan . remote_address ) ) ;
2006-10-05 22:10:09 +00:00
host_client - > drop = true ; //drop later
2004-08-23 00:15:46 +00:00
}
}
host_client - > msecs = 0 ;
host_client - > last_check = realtime ;
}
}
// end KK hack copied from QuakeForge anti-cheat
//it's amazing how code get's copied around...
2009-04-19 00:50:42 +00:00
if ( SV_RunFullQCMovement ( host_client , ucmd ) )
{
return ;
}
2004-08-23 00:15:46 +00:00
cmd = * ucmd ;
// chop up very long commands
if ( cmd . msec > 50 )
{
oldmsec = ucmd - > msec ;
cmd . msec = oldmsec / 2 ;
SV_RunCmd ( & cmd , true ) ;
2007-10-05 17:43:26 +00:00
cmd . msec = oldmsec / 2 + ( oldmsec & 1 ) ; //give them back their msec.
2004-08-23 00:15:46 +00:00
cmd . impulse = 0 ;
SV_RunCmd ( & cmd , true ) ;
return ;
}
host_frametime = ucmd - > msec * 0.001 ;
2005-03-20 02:57:11 +00:00
host_frametime * = sv . gamespeed ;
2004-08-23 00:15:46 +00:00
if ( host_frametime > 0.1 )
host_frametime = 0.1 ;
2005-07-03 15:16:20 +00:00
2005-01-26 03:39:47 +00:00
if ( sv . demostatevalid )
{ //spectators watching MVDs do not affect the running progs.
player_mins [ 0 ] = - 16 ;
player_mins [ 1 ] = - 16 ;
player_mins [ 2 ] = - 24 ;
player_maxs [ 0 ] = 16 ;
player_maxs [ 1 ] = 16 ;
player_maxs [ 2 ] = 32 ;
pmove . angles [ 0 ] = SHORT2ANGLE ( ucmd - > angles [ 0 ] ) ;
pmove . angles [ 1 ] = SHORT2ANGLE ( ucmd - > angles [ 1 ] ) ;
pmove . angles [ 2 ] = SHORT2ANGLE ( ucmd - > angles [ 2 ] ) ;
2005-07-03 15:16:20 +00:00
2005-01-26 03:39:47 +00:00
VectorCopy ( host_client - > specorigin , pmove . origin ) ;
VectorCopy ( host_client - > specvelocity , pmove . velocity ) ;
if ( host_client - > zquake_extensions & Z_EXT_PM_TYPE_NEW )
pmove . pm_type = PM_SPECTATOR ;
else
pmove . pm_type = PM_OLD_SPECTATOR ;
pmove . jump_held = host_client - > jump_held ;
pmove . jump_msec = 0 ;
pmove . waterjumptime = 0 ;
pmove . numphysent = 1 ;
pmove . physents [ 0 ] . model = sv . worldmodel ;
pmove . cmd = * ucmd ;
pmove . hullnum = SV_HullNumForPlayer ( 0 , player_mins , player_maxs ) ;
movevars . entgravity = 0 ;
movevars . maxspeed = 0 ;
movevars . bunnyspeedcap = pm_bunnyspeedcap . value ;
movevars . ktjump = pm_ktjump . value ;
movevars . slidefix = ( pm_slidefix . value ! = 0 ) ;
movevars . airstep = ( pm_airstep . value ! = 0 ) ;
movevars . walljump = ( pm_walljump . value ) ;
2005-05-17 02:36:54 +00:00
movevars . slidyslopes = ( pm_slidyslopes . value ! = 0 ) ;
2005-01-26 03:39:47 +00:00
for ( i = 0 ; i < 3 ; i + + )
{
pmove_mins [ i ] = pmove . origin [ i ] - 256 ;
pmove_maxs [ i ] = pmove . origin [ i ] + 256 ;
}
2005-03-20 03:07:24 +00:00
PM_PlayerMove ( sv . gamespeed ) ;
2005-07-03 15:16:20 +00:00
2005-01-26 03:39:47 +00:00
VectorCopy ( pmove . origin , host_client - > specorigin ) ;
VectorCopy ( pmove . velocity , host_client - > specvelocity ) ;
return ;
}
2004-08-23 00:15:46 +00:00
# ifdef SVCHAT
if ( SV_ChatMove ( ucmd - > impulse ) )
{
ucmd - > buttons = 0 ;
ucmd - > impulse = 0 ;
ucmd - > forwardmove = ucmd - > sidemove = ucmd - > upmove = 0 ;
}
# endif
2005-03-28 00:11:59 +00:00
if ( ! sv_player - > v - > fixangle )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > v_angle [ 0 ] = SHORT2ANGLE ( ucmd - > angles [ 0 ] ) ;
sv_player - > v - > v_angle [ 1 ] = SHORT2ANGLE ( ucmd - > angles [ 1 ] ) ;
sv_player - > v - > v_angle [ 2 ] = SHORT2ANGLE ( ucmd - > angles [ 2 ] ) ;
2004-08-23 00:15:46 +00:00
}
if ( progstype = = PROG_H2 )
2007-09-02 19:55:17 +00:00
sv_player - > xv - > light_level = 128 ; //hmm... HACK!!!
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
sv_player - > v - > button0 = ucmd - > buttons & 1 ;
sv_player - > v - > button2 = ( ucmd - > buttons > > 1 ) & 1 ;
2004-08-31 09:05:42 +00:00
if ( pr_allowbutton1 . value ) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows.
2005-03-28 00:11:59 +00:00
sv_player - > v - > button1 = ( ( ucmd - > buttons > > 2 ) & 1 ) ;
2004-09-04 18:01:53 +00:00
// DP_INPUTBUTTONS
2007-09-02 19:55:17 +00:00
sv_player - > xv - > button3 = ( ( ucmd - > buttons > > 2 ) & 1 ) ;
sv_player - > xv - > button4 = ( ( ucmd - > buttons > > 3 ) & 1 ) ;
sv_player - > xv - > button5 = ( ( ucmd - > buttons > > 4 ) & 1 ) ;
sv_player - > xv - > button6 = ( ( ucmd - > buttons > > 5 ) & 1 ) ;
sv_player - > xv - > button7 = ( ( ucmd - > buttons > > 6 ) & 1 ) ;
sv_player - > xv - > button8 = ( ( ucmd - > buttons > > 7 ) & 1 ) ;
2004-08-23 00:15:46 +00:00
if ( ucmd - > impulse & & SV_FiltureImpulse ( ucmd - > impulse , host_client - > trustlevel ) )
2005-03-28 00:11:59 +00:00
sv_player - > v - > impulse = ucmd - > impulse ;
2004-08-23 00:15:46 +00:00
if ( host_client - > iscuffed )
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > impulse = 0 ;
sv_player - > v - > button0 = 0 ;
2004-08-23 00:15:46 +00:00
}
2007-10-08 12:23:55 +00:00
if ( host_client - > state & & host_client - > protocol ! = SCP_BAD )
{
sv_player - > xv - > movement [ 0 ] = ucmd - > forwardmove * host_frametime ;
sv_player - > xv - > movement [ 1 ] = ucmd - > sidemove * host_frametime ;
sv_player - > xv - > movement [ 2 ] = ucmd - > upmove * host_frametime ;
}
2004-08-23 00:15:46 +00:00
SV_CheckVelocity ( sv_player ) ;
//
// angles
2005-07-03 15:16:20 +00:00
// show 1/3 the pitch angle and all the roll angle
2005-03-28 00:11:59 +00:00
if ( sv_player - > v - > health > 0 )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
if ( ! sv_player - > v - > fixangle )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > angles [ PITCH ] = - sv_player - > v - > v_angle [ PITCH ] / 3 ;
sv_player - > v - > angles [ YAW ] = sv_player - > v - > v_angle [ YAW ] ;
2004-08-23 00:15:46 +00:00
}
2005-07-03 15:16:20 +00:00
sv_player - > v - > angles [ ROLL ] =
2005-03-28 00:11:59 +00:00
V_CalcRoll ( sv_player - > v - > angles , sv_player - > v - > velocity ) * 4 ;
2004-08-23 00:15:46 +00:00
}
2005-06-22 17:10:13 +00:00
if ( SV_PlayerPhysicsQC )
{ //csqc independant physics support
pr_global_struct - > frametime = host_frametime ;
pr_global_struct - > time = sv . time ;
SV_RunEntity ( sv_player ) ;
return ;
}
2004-08-23 00:15:46 +00:00
if ( ! host_client - > spectator )
{
vec_t oldvz ;
pr_global_struct - > frametime = host_frametime ;
pr_global_struct - > time = sv . time ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
2005-03-28 00:11:59 +00:00
oldvz = sv_player - > v - > velocity [ 2 ] ;
2004-08-23 00:15:46 +00:00
if ( progstype ! = PROG_QW )
{
# define FL_JUMPRELEASED 4096
2005-03-28 00:11:59 +00:00
jumpable = ( int ) sv_player - > v - > flags & FL_JUMPRELEASED ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
pmove . waterjumptime = sv_player - > v - > teleport_time ;
2004-08-23 00:15:46 +00:00
if ( pmove . waterjumptime > sv . time )
2005-03-28 00:11:59 +00:00
sv_player - > v - > flags = ( int ) sv_player - > v - > flags | FL_WATERJUMP ;
sv_player - > v - > teleport_time = sv . time + pmove . waterjumptime ;
2004-08-23 00:15:46 +00:00
}
else
jumpable = false ;
2007-09-02 19:55:17 +00:00
# ifdef VM_Q1
if ( svs . gametype = = GT_Q1QVM )
Q1QVM_PlayerPreThink ( ) ;
else
# endif
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > PlayerPreThink ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
if ( progstype ! = PROG_QW )
{
2005-03-28 00:11:59 +00:00
if ( sv_player - > v - > velocity [ 2 ] = = 225 & & sv_player - > v - > teleport_time > sv . time )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > velocity [ 2 ] = oldvz ;
2004-08-23 00:15:46 +00:00
// Con_Printf("Waterjump detected\n");
}
2005-03-28 00:11:59 +00:00
sv_player - > v - > flags = ( int ) sv_player - > v - > flags & ~ FL_WATERJUMP ;
sv_player - > v - > teleport_time = pmove . waterjumptime ;
if ( jumpable & & ! ( ( int ) sv_player - > v - > flags & FL_JUMPRELEASED ) ) //hmm... a jump was hit.
sv_player - > v - > velocity [ 2 ] - = 270 ;
2004-08-23 00:15:46 +00:00
}
SV_RunThink ( sv_player ) ;
}
// memset(&pmove, 0, sizeof(pmove));
// memset(&movevars, 0, sizeof(movevars));
2005-03-28 00:11:59 +00:00
player_mins [ 0 ] = sv_player - > v - > mins [ 0 ] ;
player_mins [ 1 ] = sv_player - > v - > mins [ 1 ] ;
player_mins [ 2 ] = sv_player - > v - > mins [ 2 ] ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
player_maxs [ 0 ] = sv_player - > v - > maxs [ 0 ] ;
player_maxs [ 1 ] = sv_player - > v - > maxs [ 1 ] ;
player_maxs [ 2 ] = sv_player - > v - > maxs [ 2 ] ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
2005-03-28 00:11:59 +00:00
pmove . origin [ i ] = sv_player - > v - > origin [ i ] ; // + (sv_player->v->mins[i] - player_mins[i]);
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
VectorCopy ( sv_player - > v - > velocity , pmove . velocity ) ;
VectorCopy ( sv_player - > v - > v_angle , pmove . angles ) ;
2004-08-23 00:15:46 +00:00
pmove . pm_type = SV_PMTypeForClient ( host_client ) ;
pmove . jump_held = host_client - > jump_held ;
pmove . jump_msec = 0 ;
if ( progstype ! = PROG_QW ) //this is just annoying.
2005-03-28 00:11:59 +00:00
pmove . waterjumptime = sv_player - > v - > teleport_time - sv . time ;
2004-08-23 00:15:46 +00:00
else
2005-03-28 00:11:59 +00:00
pmove . waterjumptime = sv_player - > v - > teleport_time ;
2004-08-23 00:15:46 +00:00
pmove . numphysent = 1 ;
pmove . physents [ 0 ] . model = sv . worldmodel ;
pmove . cmd = * ucmd ;
2009-04-19 00:50:42 +00:00
pmove . hullnum = SV_HullNumForPlayer ( sv_player - > xv - > hull , sv_player - > v - > mins , sv_player - > v - > maxs ) ;
2004-08-23 00:15:46 +00:00
2005-02-12 18:56:04 +00:00
movevars . entgravity = host_client - > entgravity / movevars . gravity ;
2004-08-23 00:15:46 +00:00
movevars . maxspeed = host_client - > maxspeed ;
movevars . bunnyspeedcap = pm_bunnyspeedcap . value ;
movevars . ktjump = pm_ktjump . value ;
movevars . slidefix = ( pm_slidefix . value ! = 0 ) ;
movevars . airstep = ( pm_airstep . value ! = 0 ) ;
2005-01-16 00:59:48 +00:00
movevars . walljump = ( pm_walljump . value ) ;
2005-05-17 02:36:54 +00:00
movevars . slidyslopes = ( pm_slidyslopes . value ! = 0 ) ;
2004-08-23 00:15:46 +00:00
2007-09-02 19:55:17 +00:00
if ( sv_player - > xv - > hasted )
movevars . maxspeed * = sv_player - > xv - > hasted ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
{
pmove_mins [ i ] = pmove . origin [ i ] - 256 ;
pmove_maxs [ i ] = pmove . origin [ i ] + 256 ;
}
2009-04-19 00:50:42 +00:00
sv_player - > xv - > pmove_flags = ( int ) sv_player - > xv - > pmove_flags & ~ PMF_LADDER ; //assume not touching ladder trigger
2004-08-23 00:15:46 +00:00
# if 1
2008-11-09 22:29:28 +00:00
AddLinksToPmove ( sv_player , sv_areanodes ) ;
2004-08-23 00:15:46 +00:00
# else
AddAllEntsToPmove ( ) ;
# endif
2009-04-19 00:50:42 +00:00
if ( ( int ) sv_player - > xv - > pmove_flags & PMF_LADDER )
2004-08-23 00:15:46 +00:00
pmove . onladder = true ;
else
pmove . onladder = false ;
#if 0
{
int before , after ;
before = PM_TestPlayerPosition ( pmove . origin ) ;
PlayerMove ( ) ;
after = PM_TestPlayerPosition ( pmove . origin ) ;
2005-03-28 00:11:59 +00:00
if ( sv_player - > v - > health > 0 & & before & & ! after )
2004-08-23 00:15:46 +00:00
Con_Printf ( " player %s got stuck in playermove!!!! \n " , host_client - > name ) ;
}
# else
2005-03-20 02:57:11 +00:00
PM_PlayerMove ( sv . gamespeed ) ;
2004-08-23 00:15:46 +00:00
# endif
host_client - > jump_held = pmove . jump_held ;
if ( progstype ! = PROG_QW ) //this is just annoying.
2005-03-28 00:11:59 +00:00
sv_player - > v - > teleport_time = pmove . waterjumptime + sv . time ;
2004-08-23 00:15:46 +00:00
else
2005-03-28 00:11:59 +00:00
sv_player - > v - > teleport_time = pmove . waterjumptime ;
sv_player - > v - > waterlevel = pmove . waterlevel ;
2004-08-23 00:15:46 +00:00
if ( pmove . watertype & FTECONTENTS_SOLID )
2005-03-28 00:11:59 +00:00
sv_player - > v - > watertype = Q1CONTENTS_SOLID ;
2004-08-23 00:15:46 +00:00
else if ( pmove . watertype & FTECONTENTS_SKY )
2005-03-28 00:11:59 +00:00
sv_player - > v - > watertype = Q1CONTENTS_SKY ;
2004-08-23 00:15:46 +00:00
else if ( pmove . watertype & FTECONTENTS_LAVA )
2005-03-28 00:11:59 +00:00
sv_player - > v - > watertype = Q1CONTENTS_LAVA ;
2004-08-23 00:15:46 +00:00
else if ( pmove . watertype & FTECONTENTS_SLIME )
2005-03-28 00:11:59 +00:00
sv_player - > v - > watertype = Q1CONTENTS_SLIME ;
2004-08-23 00:15:46 +00:00
else if ( pmove . watertype & FTECONTENTS_WATER )
2005-03-28 00:11:59 +00:00
sv_player - > v - > watertype = Q1CONTENTS_WATER ;
2004-08-23 00:15:46 +00:00
else
2005-03-28 00:11:59 +00:00
sv_player - > v - > watertype = Q1CONTENTS_EMPTY ;
2004-08-23 00:15:46 +00:00
if ( pmove . onground )
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > flags = ( int ) sv_player - > v - > flags | FL_ONGROUND ;
sv_player - > v - > groundentity = EDICT_TO_PROG ( svprogfuncs , EDICT_NUM ( svprogfuncs , pmove . physents [ pmove . groundent ] . info ) ) ;
2004-08-23 00:15:46 +00:00
}
else
2005-03-28 00:11:59 +00:00
sv_player - > v - > flags = ( int ) sv_player - > v - > flags & ~ FL_ONGROUND ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
2005-03-28 00:11:59 +00:00
sv_player - > v - > origin [ i ] = pmove . origin [ i ] ; // - (sv_player->v->mins[i] - player_mins[i]);
2004-08-23 00:15:46 +00:00
#if 0
// truncate velocity the same way the net protocol will
for ( i = 0 ; i < 3 ; i + + )
2005-03-28 00:11:59 +00:00
sv_player - > v - > velocity [ i ] = ( int ) pmove . velocity [ i ] ;
2004-08-23 00:15:46 +00:00
# else
2005-03-28 00:11:59 +00:00
VectorCopy ( pmove . velocity , sv_player - > v - > velocity ) ;
2004-08-23 00:15:46 +00:00
# endif
2005-03-28 00:11:59 +00:00
VectorCopy ( pmove . angles , sv_player - > v - > v_angle ) ;
2004-08-23 00:15:46 +00:00
player_mins [ 0 ] = - 16 ;
player_mins [ 1 ] = - 16 ;
player_mins [ 2 ] = - 24 ;
player_maxs [ 0 ] = 16 ;
player_maxs [ 1 ] = 16 ;
player_maxs [ 2 ] = 32 ;
if ( ! host_client - > spectator )
{
// link into place and touch triggers
SV_LinkEdict ( sv_player , true ) ;
2004-09-04 18:01:53 +00:00
/* for (i = 0; i < pmove.numphysent; i++)
{
}
*/
2004-08-23 00:15:46 +00:00
// touch other objects
for ( i = 0 ; i < pmove . numtouch ; i + + )
{
2005-07-05 23:46:10 +00:00
if ( sv_pushplayers . value )
{
n = pmove . physents [ pmove . touchindex [ i ] ] . info ;
if ( n & & n < = sv . allocated_client_slots )
{
float vel ;
vec3_t dir ;
vec3_t svel ;
ent = EDICT_NUM ( svprogfuncs , n ) ;
VectorSubtract ( ent - > v - > origin , sv_player - > v - > origin , dir ) ;
VectorNormalize ( dir ) ;
VectorCopy ( sv_player - > v - > velocity , svel ) ;
VectorNormalize ( svel ) ;
vel = DotProduct ( svel , dir ) ;
VectorMA ( ent - > v - > velocity , sv_pushplayers . value * vel , dir , ent - > v - > velocity ) ;
}
}
2004-09-04 18:01:53 +00:00
if ( pmove . physents [ pmove . touchindex [ i ] ] . notouch )
continue ;
2004-08-23 00:15:46 +00:00
n = pmove . physents [ pmove . touchindex [ i ] ] . info ;
ent = EDICT_NUM ( svprogfuncs , n ) ;
2005-03-28 00:11:59 +00:00
if ( ! ent - > v - > touch | | ( playertouch [ n / 8 ] & ( 1 < < ( n % 8 ) ) ) )
2004-08-23 00:15:46 +00:00
continue ;
2004-09-04 18:01:53 +00:00
2004-08-23 00:15:46 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , ent ) ;
pr_global_struct - > other = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
2005-01-18 21:11:55 +00:00
pr_global_struct - > time = sv . time ;
2007-09-02 19:55:17 +00:00
# ifdef VM_Q1
if ( svs . gametype = = GT_Q1QVM )
Q1QVM_Touch ( ) ;
else
# endif
PR_ExecuteProgram ( svprogfuncs , ent - > v - > touch ) ;
2004-08-23 00:15:46 +00:00
playertouch [ n / 8 ] | = 1 < < ( n % 8 ) ;
}
}
}
/*
= = = = = = = = = = =
SV_PostRunCmd
= = = = = = = = = = =
Done after running a player command .
*/
void SV_PostRunCmd ( void )
{
// run post-think
if ( ! svprogfuncs )
return ;
2007-09-02 19:55:17 +00:00
# ifdef VM_Q1
if ( svs . gametype = = GT_Q1QVM )
{
2004-08-23 00:15:46 +00:00
pr_global_struct - > time = sv . time ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
2007-09-02 19:55:17 +00:00
Q1QVM_PostThink ( ) ;
}
else
# endif
{
if ( ! host_client - > spectator )
{
pr_global_struct - > time = sv . time ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
2004-08-23 00:15:46 +00:00
2007-09-02 19:55:17 +00:00
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > PlayerPostThink ) ;
2004-08-23 00:15:46 +00:00
2007-09-02 19:55:17 +00:00
SV_RunNewmis ( ) ;
}
else if ( SpectatorThink )
{
pr_global_struct - > time = sv . time ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
PR_ExecuteProgram ( svprogfuncs , SpectatorThink ) ;
}
2004-08-23 00:15:46 +00:00
}
}
2009-05-24 10:11:17 +00:00
void SV_ReadPrydonCursor ( void )
{
float f ;
int entnum ;
eval_t * cursor_screen , * cursor_start , * cursor_impact , * cursor_entitynumber ;
if ( svprogfuncs )
{
cursor_screen = svprogfuncs - > GetEdictFieldValue ( svprogfuncs , host_client - > edict , " cursor_screen " , NULL ) ;
2009-08-29 15:08:39 +00:00
cursor_start = svprogfuncs - > GetEdictFieldValue ( svprogfuncs , host_client - > edict , " cursor_trace_start " , NULL ) ;
cursor_impact = svprogfuncs - > GetEdictFieldValue ( svprogfuncs , host_client - > edict , " cursor_trace_endpos " , NULL ) ;
cursor_entitynumber = svprogfuncs - > GetEdictFieldValue ( svprogfuncs , host_client - > edict , " cursor_trace_ent " , NULL ) ;
2009-05-24 10:11:17 +00:00
}
else
{
cursor_screen = NULL ;
cursor_start = NULL ;
cursor_impact = NULL ;
cursor_entitynumber = NULL ;
}
f = MSG_ReadShort ( ) * ( 1.0f / 32767.0f ) ;
if ( cursor_screen ) cursor_screen - > _vector [ 0 ] = f ;
f = MSG_ReadShort ( ) * ( 1.0f / 32767.0f ) ;
if ( cursor_screen ) cursor_screen - > _vector [ 1 ] = f ;
f = MSG_ReadFloat ( ) ;
if ( cursor_start ) cursor_start - > _vector [ 0 ] = f ;
f = MSG_ReadFloat ( ) ;
if ( cursor_start ) cursor_start - > _vector [ 1 ] = f ;
f = MSG_ReadFloat ( ) ;
if ( cursor_start ) cursor_start - > _vector [ 2 ] = f ;
f = MSG_ReadFloat ( ) ;
if ( cursor_impact ) cursor_impact - > _vector [ 0 ] = f ;
f = MSG_ReadFloat ( ) ;
if ( cursor_impact ) cursor_impact - > _vector [ 1 ] = f ;
f = MSG_ReadFloat ( ) ;
if ( cursor_impact ) cursor_impact - > _vector [ 2 ] = f ;
entnum = ( unsigned short ) MSG_ReadShort ( ) ;
if ( entnum > = sv . max_edicts )
{
Con_DPrintf ( " SV_ReadPrydonCursor: client send bad cursor_entitynumber \n " ) ;
entnum = 0 ;
}
// as requested by FrikaC, cursor_trace_ent is reset to world if the
// entity is free at time of receipt
if ( ! svprogfuncs | | EDICT_NUM ( svprogfuncs , entnum ) - > isfree )
entnum = 0 ;
if ( msg_badread ) Con_Printf ( " SV_ReadPrydonCursor: badread at %s:%i \n " , __FILE__ , __LINE__ ) ;
if ( cursor_entitynumber ) cursor_entitynumber - > edict = entnum ;
}
void SV_ReadQCRequest ( void )
{
int e ;
char args [ 9 ] ;
char * rname ;
func_t f ;
int i ;
globalvars_t * pr_globals ;
if ( ! svprogfuncs )
{
msg_badread = true ;
return ;
}
pr_globals = PR_globals ( svprogfuncs , PR_CURRENT ) ;
for ( i = 0 ; ; i + + )
{
if ( i > = sizeof ( args ) )
if ( MSG_ReadByte ( ) ! = ev_void )
{
msg_badread = true ;
return ;
}
switch ( MSG_ReadByte ( ) )
{
case ev_void :
i = 6 ;
break ;
case ev_float :
args [ i ] = ' f ' ;
G_FLOAT ( OFS_PARM0 + i * 3 ) = MSG_ReadFloat ( ) ;
break ;
case ev_vector :
args [ i ] = ' v ' ;
G_FLOAT ( OFS_PARM0 + i * 3 + 0 ) = MSG_ReadFloat ( ) ;
G_FLOAT ( OFS_PARM0 + i * 3 + 1 ) = MSG_ReadFloat ( ) ;
G_FLOAT ( OFS_PARM0 + i * 3 + 2 ) = MSG_ReadFloat ( ) ;
break ;
case ev_integer :
args [ i ] = ' i ' ;
G_INT ( OFS_PARM0 + i * 3 ) = MSG_ReadLong ( ) ;
break ;
case ev_string :
args [ i ] = ' s ' ;
G_INT ( OFS_PARM0 + i * 3 ) = PR_TempString ( svprogfuncs , MSG_ReadString ( ) ) ;
break ;
case ev_entity :
args [ i ] = ' s ' ;
e = MSG_ReadShort ( ) ;
if ( e < 0 | | e > = sv . num_edicts )
e = 0 ;
G_INT ( OFS_PARM0 + i * 3 ) = EDICT_TO_PROG ( svprogfuncs , EDICT_NUM ( svprogfuncs , e ) ) ;
break ;
}
}
rname = MSG_ReadString ( ) ;
f = PR_FindFunc ( svprogfuncs , va ( " Cmd_%s_%s " , rname , args ) , PR_ANY ) ;
if ( f )
PR_ExecuteProgram ( svprogfuncs , f ) ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = =
SV_ExecuteClientMessage
The current net_message is parsed for the given client
= = = = = = = = = = = = = = = = = = =
*/
void SV_ClientThink ( void ) ;
void SV_ExecuteClientMessage ( client_t * cl )
{
client_t * split ;
int c ;
char * s ;
usercmd_t oldest , oldcmd , newcmd ;
client_frame_t * frame ;
vec3_t o ;
qboolean move_issued = false ; //only allow one move command
int checksumIndex ;
qbyte checksum , calculatedChecksum ;
2005-02-28 07:16:19 +00:00
int seq_hash , i ;
2004-08-23 00:15:46 +00:00
// calc ping time
2006-02-17 02:51:59 +00:00
if ( cl - > frameunion . frames )
2004-08-23 00:15:46 +00:00
{ //split screen doesn't always have frames.
2006-02-17 02:51:59 +00:00
frame = & cl - > frameunion . frames [ cl - > netchan . incoming_acknowledged & UPDATE_MASK ] ;
2005-02-28 07:16:19 +00:00
if ( cl - > lastsequence_acknoledged + UPDATE_BACKUP > cl - > netchan . incoming_acknowledged )
2007-08-30 20:45:01 +00:00
{
2005-02-28 07:16:19 +00:00
frame - > ping_time = realtime - frame - > senttime ; //no more phenomanally low pings please
2007-08-30 20:45:01 +00:00
if ( cl - > spectator )
cl - > delay = 0 ;
else
{
if ( frame - > ping_time * 1000 > sv_minping . value + 1 )
{
cl - > delay - = 0.001 ;
if ( cl - > delay < 0 )
cl - > delay = 0 ;
}
if ( frame - > ping_time * 1000 < sv_minping . value )
{
cl - > delay + = 0.001 ;
if ( cl - > delay > 1 )
cl - > delay = 1 ;
}
}
}
2005-03-10 03:55:18 +00:00
# ifdef PEXT_CSQC
2005-12-06 02:17:27 +00:00
if ( cl - > lastsequence_acknoledged + UPDATE_BACKUP > cl - > netchan . incoming_acknowledged )
{
for ( i = cl - > lastsequence_acknoledged + 1 ; i < cl - > netchan . incoming_acknowledged ; i + + )
SV_CSQC_DroppedPacket ( cl , i ) ;
}
else
SV_CSQC_DropAll ( cl ) ;
2005-03-10 03:55:18 +00:00
# endif
2005-02-28 07:16:19 +00:00
cl - > lastsequence_acknoledged = cl - > netchan . incoming_acknowledged ;
2004-08-23 00:15:46 +00:00
}
else
2005-10-16 03:48:24 +00:00
{
Con_Printf ( " Server bug: No frames! \n " ) ;
cl - > send_message = false ;
2004-08-23 00:15:46 +00:00
return ; //shouldn't happen...
2005-10-16 03:48:24 +00:00
}
2004-08-23 00:15:46 +00:00
// make sure the reply sequence number matches the incoming
2005-07-03 15:16:20 +00:00
// sequence number
2004-08-23 00:15:46 +00:00
if ( cl - > netchan . incoming_sequence > = cl - > netchan . outgoing_sequence )
cl - > netchan . outgoing_sequence = cl - > netchan . incoming_sequence ;
else
2005-07-03 15:16:20 +00:00
cl - > send_message = false ; // don't reply, sequences have slipped
2004-08-23 00:15:46 +00:00
// save time for ping calculations
2006-02-17 02:51:59 +00:00
if ( cl - > frameunion . frames )
2004-08-23 00:15:46 +00:00
{ //split screen doesn't always have frames.
2006-02-17 02:51:59 +00:00
cl - > frameunion . frames [ cl - > netchan . outgoing_sequence & UPDATE_MASK ] . senttime = realtime ;
cl - > frameunion . frames [ cl - > netchan . outgoing_sequence & UPDATE_MASK ] . ping_time = - 1 ;
2007-07-23 11:44:45 +00:00
cl - > frameunion . frames [ cl - > netchan . outgoing_sequence & UPDATE_MASK ] . move_msecs = - 1 ;
2009-06-23 21:49:44 +00:00
cl - > frameunion . frames [ cl - > netchan . outgoing_sequence & UPDATE_MASK ] . packetsizein = net_message . cursize ;
cl - > frameunion . frames [ cl - > netchan . outgoing_sequence & UPDATE_MASK ] . packetsizeout = 0 ;
2004-08-23 00:15:46 +00:00
}
host_client = cl ;
sv_player = host_client - > edict ;
seq_hash = cl - > netchan . incoming_sequence ;
// mark time so clients will know how much to predict
// other players
cl - > localtime = sv . time ;
cl - > delta_sequence = - 1 ; // no delta unless requested
while ( 1 )
{
if ( msg_badread )
{
Con_Printf ( " SV_ReadClientMessage: badread \n " ) ;
SV_DropClient ( cl ) ;
return ;
2005-07-03 15:16:20 +00:00
}
2004-08-23 00:15:46 +00:00
c = MSG_ReadByte ( ) ;
2004-09-04 18:01:53 +00:00
haveannothergo :
2004-08-23 00:15:46 +00:00
if ( c = = - 1 )
break ;
switch ( c )
{
default :
Con_Printf ( " SV_ReadClientMessage: unknown command char %i \n " , c ) ;
SV_DropClient ( cl ) ;
return ;
case clc_nop :
break ;
case clc_delta :
cl - > delta_sequence = MSG_ReadByte ( ) ;
break ;
case clc_move :
if ( move_issued )
return ; // someone is trying to cheat...
move_issued = true ;
checksumIndex = MSG_GetReadCount ( ) ;
checksum = ( qbyte ) MSG_ReadByte ( ) ;
// read loss percentage
cl - > lossage = MSG_ReadByte ( ) ;
for ( split = cl ; cl ; cl = cl - > controlled ) //FIXME
{
host_client = cl ;
cl - > localtime = sv . time ;
sv_player = cl - > edict ;
MSG_ReadDeltaUsercmd ( & nullcmd , & oldest ) ;
MSG_ReadDeltaUsercmd ( & oldest , & oldcmd ) ;
MSG_ReadDeltaUsercmd ( & oldcmd , & newcmd ) ;
2007-07-23 11:44:45 +00:00
if ( cl - > frameunion . frames )
cl - > frameunion . frames [ cl - > netchan . outgoing_sequence & UPDATE_MASK ] . move_msecs = newcmd . msec ;
2004-09-04 18:01:53 +00:00
if ( cl - > state = = cs_spawned )
2004-08-23 00:15:46 +00:00
{
2004-09-04 18:01:53 +00:00
if ( split = = cl )
2004-08-23 00:15:46 +00:00
{
2004-09-04 18:01:53 +00:00
// if the checksum fails, ignore the rest of the packet
calculatedChecksum = COM_BlockSequenceCRCByte (
net_message . data + checksumIndex + 1 ,
MSG_GetReadCount ( ) - checksumIndex - 1 ,
seq_hash ) ;
2004-08-23 00:15:46 +00:00
2004-09-04 18:01:53 +00:00
if ( calculatedChecksum ! = checksum )
2004-08-23 00:15:46 +00:00
{
2005-07-03 15:16:20 +00:00
Con_DPrintf ( " Failed command checksum for %s(%d) (%d != %d) \n " ,
2004-09-04 18:01:53 +00:00
cl - > name , cl - > netchan . incoming_sequence , checksum , calculatedChecksum ) ;
2006-02-27 00:42:25 +00:00
for ( cl = cl - > controlled ; cl ; cl = cl - > controlled ) //FIXME
2004-09-04 18:01:53 +00:00
{
MSG_ReadDeltaUsercmd ( & nullcmd , & oldest ) ;
MSG_ReadDeltaUsercmd ( & oldest , & oldcmd ) ;
MSG_ReadDeltaUsercmd ( & oldcmd , & newcmd ) ;
}
2009-04-19 00:50:42 +00:00
break ;
2004-08-23 00:15:46 +00:00
}
}
2004-09-04 18:01:53 +00:00
if ( cl - > iscrippled )
{
cl - > lastcmd . forwardmove = 0 ; //hmmm.... does this work well enough?
oldest . forwardmove = 0 ;
newcmd . forwardmove = 0 ;
2004-08-23 00:15:46 +00:00
2004-09-04 18:01:53 +00:00
cl - > lastcmd . sidemove = 0 ;
oldest . sidemove = 0 ;
newcmd . sidemove = 0 ;
2004-08-23 00:15:46 +00:00
2004-09-04 18:01:53 +00:00
cl - > lastcmd . upmove = 0 ;
oldest . upmove = 0 ;
newcmd . upmove = 0 ;
}
2004-08-23 00:15:46 +00:00
2009-03-03 01:52:30 +00:00
# ifdef HLSERVER
if ( svs . gametype = = GT_HALFLIFE )
{
SVHL_RunPlayerCommand ( cl , & oldest , & oldcmd , & newcmd ) ;
}
else
# endif
2004-09-04 18:01:53 +00:00
if ( ! sv . paused )
2004-08-23 00:15:46 +00:00
{
2005-06-22 17:10:13 +00:00
if ( sv_nomsec . value )
2004-08-23 00:15:46 +00:00
{
2005-06-22 17:10:13 +00:00
cl - > isindependant = false ;
2005-03-28 00:11:59 +00:00
if ( ! sv_player - > v - > fixangle )
2004-09-04 18:01:53 +00:00
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > v_angle [ 0 ] = newcmd . angles [ 0 ] * ( 360.0 / 65536 ) ;
sv_player - > v - > v_angle [ 1 ] = newcmd . angles [ 1 ] * ( 360.0 / 65536 ) ;
sv_player - > v - > v_angle [ 2 ] = newcmd . angles [ 2 ] * ( 360.0 / 65536 ) ;
2004-09-04 18:01:53 +00:00
}
if ( newcmd . impulse ) // && SV_FiltureImpulse(newcmd.impulse, host_client->trustlevel))
2005-03-28 00:11:59 +00:00
sv_player - > v - > impulse = newcmd . impulse ;
2004-10-10 06:32:29 +00:00
2005-03-28 00:11:59 +00:00
sv_player - > v - > button0 = newcmd . buttons & 1 ;
sv_player - > v - > button2 = ( newcmd . buttons > > 1 ) & 1 ;
2004-10-10 06:32:29 +00:00
if ( pr_allowbutton1 . value ) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows.
2005-03-28 00:11:59 +00:00
sv_player - > v - > button1 = ( ( newcmd . buttons > > 2 ) & 1 ) ;
2004-10-10 06:32:29 +00:00
// DP_INPUTBUTTONS
2007-09-02 19:55:17 +00:00
sv_player - > xv - > button3 = ( ( newcmd . buttons > > 2 ) & 1 ) ;
sv_player - > xv - > button4 = ( ( newcmd . buttons > > 3 ) & 1 ) ;
sv_player - > xv - > button5 = ( ( newcmd . buttons > > 4 ) & 1 ) ;
sv_player - > xv - > button6 = ( ( newcmd . buttons > > 5 ) & 1 ) ;
sv_player - > xv - > button7 = ( ( newcmd . buttons > > 6 ) & 1 ) ;
sv_player - > xv - > button8 = ( ( newcmd . buttons > > 7 ) & 1 ) ;
2004-10-10 06:32:29 +00:00
2004-09-04 18:01:53 +00:00
cl - > lastcmd = newcmd ;
cl - > lastcmd . buttons = 0 ; // avoid multiple fires on lag
2005-01-26 03:39:47 +00:00
2004-10-03 22:52:02 +00:00
if ( msg_badread )
{
Con_Printf ( " SV_ReadClientMessage: badread \n " ) ;
SV_DropClient ( cl ) ;
return ;
}
c = MSG_ReadByte ( ) ;
if ( c ! = clc_move )
{
host_client = cl = split ;
sv_player = cl - > edict ;
goto haveannothergo ;
}
2004-09-04 18:01:53 +00:00
continue ;
2004-08-23 00:15:46 +00:00
}
2005-06-22 17:10:13 +00:00
cl - > isindependant = true ;
2004-09-04 18:01:53 +00:00
SV_PreRunCmd ( ) ;
2004-08-23 00:15:46 +00:00
2004-09-04 18:01:53 +00:00
if ( net_drop < 20 )
2004-08-23 00:15:46 +00:00
{
2004-09-04 18:01:53 +00:00
while ( net_drop > 2 )
{
SV_RunCmd ( & cl - > lastcmd , false ) ;
net_drop - - ;
}
if ( net_drop > 1 )
SV_RunCmd ( & oldest , false ) ;
if ( net_drop > 0 )
SV_RunCmd ( & oldcmd , false ) ;
2004-08-23 00:15:46 +00:00
}
2004-09-04 18:01:53 +00:00
SV_RunCmd ( & newcmd , false ) ;
2005-06-22 17:10:13 +00:00
if ( ! SV_PlayerPhysicsQC )
SV_PostRunCmd ( ) ;
2005-01-26 03:39:47 +00:00
2004-08-23 00:15:46 +00:00
}
2004-09-04 18:01:53 +00:00
cl - > lastcmd = newcmd ;
cl - > lastcmd . buttons = 0 ; // avoid multiple fires on lag
2004-08-23 00:15:46 +00:00
}
2004-09-04 18:01:53 +00:00
if ( msg_badread )
{
Con_Printf ( " SV_ReadClientMessage: badread \n " ) ;
SV_DropClient ( cl ) ;
return ;
2005-01-26 03:39:47 +00:00
}
2004-08-23 00:15:46 +00:00
2004-09-04 18:01:53 +00:00
c = MSG_ReadByte ( ) ;
if ( c ! = clc_move )
{
host_client = cl = split ;
sv_player = cl - > edict ;
goto haveannothergo ;
}
2004-08-23 00:15:46 +00:00
}
host_client = cl = split ;
sv_player = cl - > edict ;
break ;
2009-05-24 10:11:17 +00:00
case clc_prydoncursor :
SV_ReadPrydonCursor ( ) ;
break ;
case clc_qcrequest :
SV_ReadQCRequest ( ) ;
break ;
2004-08-23 00:15:46 +00:00
2005-07-03 15:16:20 +00:00
case clc_stringcmd :
2004-08-23 00:15:46 +00:00
s = MSG_ReadString ( ) ;
SV_ExecuteUserCommand ( s , false ) ;
host_client = cl ;
sv_player = cl - > edict ;
break ;
case clc_tmove :
o [ 0 ] = MSG_ReadCoord ( ) ;
o [ 1 ] = MSG_ReadCoord ( ) ;
o [ 2 ] = MSG_ReadCoord ( ) ;
// only allowed by spectators
2005-01-26 03:39:47 +00:00
if ( sv . mvdplayback )
{
VectorCopy ( o , host_client - > specorigin ) ;
}
else if ( host_client - > spectator )
{
2005-03-28 00:11:59 +00:00
VectorCopy ( o , sv_player - > v - > origin ) ;
2004-08-23 00:15:46 +00:00
SV_LinkEdict ( sv_player , false ) ;
}
break ;
case clc_upload :
SV_NextUpload ( ) ;
break ;
}
}
host_client = NULL ;
sv_player = NULL ;
}
# ifdef Q2SERVER
void SVQ2_ExecuteClientMessage ( client_t * cl )
{
enum clcq2_ops_e c ;
char * s ;
usercmd_t oldest , oldcmd , newcmd ;
q2client_frame_t * frame ;
qboolean move_issued = false ; //only allow one move command
int checksumIndex ;
qbyte checksum , calculatedChecksum ;
int seq_hash ;
int lastframe ;
2005-03-18 06:13:11 +00:00
if ( ! ge )
{
Con_Printf ( " Q2 client without Q2 server \n " ) ;
SV_DropClient ( cl ) ;
}
2004-08-23 00:15:46 +00:00
// calc ping time
2006-02-17 02:51:59 +00:00
frame = & cl - > frameunion . q2frames [ cl - > netchan . incoming_acknowledged & Q2UPDATE_MASK ] ;
2004-08-23 00:15:46 +00:00
// make sure the reply sequence number matches the incoming
2005-07-03 15:16:20 +00:00
// sequence number
2004-08-23 00:15:46 +00:00
if ( cl - > netchan . incoming_sequence > = cl - > netchan . outgoing_sequence )
cl - > netchan . outgoing_sequence = cl - > netchan . incoming_sequence ;
else
2005-07-03 15:16:20 +00:00
cl - > send_message = false ; // don't reply, sequences have slipped
2004-08-23 00:15:46 +00:00
// save time for ping calculations
2006-02-17 02:51:59 +00:00
cl - > frameunion . q2frames [ cl - > netchan . outgoing_sequence & Q2UPDATE_MASK ] . senttime = realtime ;
2004-08-23 00:15:46 +00:00
// cl->q2frames[cl->netchan.outgoing_sequence & UPDATE_MASK].ping_time = -1;
host_client = cl ;
sv_player = host_client - > edict ;
seq_hash = cl - > netchan . incoming_sequence ;
// mark time so clients will know how much to predict
// other players
cl - > localtime = sv . time ;
cl - > delta_sequence = - 1 ; // no delta unless requested
while ( 1 )
{
if ( msg_badread )
{
Con_Printf ( " SVQ2_ExecuteClientMessage: badread \n " ) ;
SV_DropClient ( cl ) ;
return ;
2005-07-03 15:16:20 +00:00
}
2004-08-23 00:15:46 +00:00
c = MSG_ReadByte ( ) ;
if ( c = = - 1 )
break ;
switch ( c )
{
default :
Con_Printf ( " SV_ReadClientMessage: unknown command char %i \n " , c ) ;
SV_DropClient ( cl ) ;
return ;
case clcq2_nop :
break ;
case clcq2_move :
if ( move_issued )
return ; // someone is trying to cheat...
move_issued = true ;
checksumIndex = MSG_GetReadCount ( ) ;
checksum = ( qbyte ) MSG_ReadByte ( ) ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
lastframe = MSG_ReadLong ( ) ;
if ( lastframe ! = host_client - > delta_sequence ) {
cl - > delta_sequence = lastframe ;
}
MSGQ2_ReadDeltaUsercmd ( & nullcmd , & oldest ) ;
MSGQ2_ReadDeltaUsercmd ( & oldest , & oldcmd ) ;
MSGQ2_ReadDeltaUsercmd ( & oldcmd , & newcmd ) ;
if ( cl - > state ! = cs_spawned )
break ;
// if the checksum fails, ignore the rest of the packet
calculatedChecksum = Q2COM_BlockSequenceCRCByte (
net_message . data + checksumIndex + 1 ,
MSG_GetReadCount ( ) - checksumIndex - 1 ,
seq_hash ) ;
if ( calculatedChecksum ! = checksum )
{
2005-07-03 15:16:20 +00:00
Con_DPrintf ( " Failed command checksum for %s(%d) (%d != %d) \n " ,
2004-08-23 00:15:46 +00:00
cl - > name , cl - > netchan . incoming_sequence , checksum , calculatedChecksum ) ;
return ;
}
if ( cl - > iscrippled )
{
cl - > lastcmd . forwardmove = 0 ; //hmmm.... does this work well enough?
oldest . forwardmove = 0 ;
newcmd . forwardmove = 0 ;
cl - > lastcmd . sidemove = 0 ;
oldest . sidemove = 0 ;
newcmd . sidemove = 0 ;
cl - > lastcmd . upmove = 0 ;
oldest . upmove = 0 ;
newcmd . upmove = 0 ;
}
if ( ! sv . paused )
{
if ( net_drop < 20 )
{
while ( net_drop > 2 )
{
2005-03-18 06:13:11 +00:00
ge - > ClientThink ( host_client - > q2edict , ( q2usercmd_t * ) & cl - > lastcmd ) ;
2004-08-23 00:15:46 +00:00
net_drop - - ;
}
if ( net_drop > 1 )
2005-03-18 06:13:11 +00:00
ge - > ClientThink ( host_client - > q2edict , ( q2usercmd_t * ) & oldest ) ;
2004-08-23 00:15:46 +00:00
if ( net_drop > 0 )
2005-03-18 06:13:11 +00:00
ge - > ClientThink ( host_client - > q2edict , ( q2usercmd_t * ) & oldcmd ) ;
2004-08-23 00:15:46 +00:00
}
2005-03-18 06:13:11 +00:00
ge - > ClientThink ( host_client - > q2edict , ( q2usercmd_t * ) & newcmd ) ;
2004-08-23 00:15:46 +00:00
}
cl - > lastcmd = newcmd ;
break ;
case clcq2_userinfo :
2005-03-20 02:57:11 +00:00
strncpy ( cl - > userinfo , MSG_ReadString ( ) , sizeof ( cl - > userinfo ) - 1 ) ;
ge - > ClientUserinfoChanged ( cl - > q2edict , cl - > userinfo ) ; //tell the gamecode
SV_ExtractFromUserinfo ( cl ) ; //let the server routines know
2004-08-23 00:15:46 +00:00
break ;
2005-07-03 15:16:20 +00:00
case clcq2_stringcmd :
2004-08-23 00:15:46 +00:00
s = MSG_ReadString ( ) ;
SV_ExecuteUserCommand ( s , false ) ;
2005-10-23 17:57:20 +00:00
host_client = cl ;
sv_player = cl - > edict ;
2004-08-23 00:15:46 +00:00
if ( cl - > state = = cs_zombie )
return ; // disconnect command
break ;
}
}
}
# endif
# ifdef NQPROT
void SVNQ_ReadClientMove ( usercmd_t * move )
{
int i ;
int bits ;
2005-07-03 15:16:20 +00:00
client_frame_t * frame ;
2008-11-09 22:29:28 +00:00
float timesincelast ;
float cltime ;
2005-07-03 15:16:20 +00:00
2006-02-17 02:51:59 +00:00
frame = & host_client - > frameunion . frames [ host_client - > netchan . incoming_acknowledged & UPDATE_MASK ] ;
2005-05-27 05:41:07 +00:00
if ( host_client - > protocol = = SCP_DARKPLACES7 )
2005-06-22 17:10:13 +00:00
host_client - > last_sequence = MSG_ReadLong ( ) ;
else
host_client - > last_sequence = 0 ;
2008-11-09 22:29:28 +00:00
cltime = MSG_ReadFloat ( ) ;
2009-04-19 00:50:42 +00:00
if ( cltime < move - > fservertime )
cltime = move - > fservertime ;
2008-11-09 22:29:28 +00:00
if ( cltime > sv . time )
cltime = sv . time ;
if ( cltime < sv . time - 2 ) //if you do lag more than this, you won't get your free time.
cltime = sv . time - 2 ;
timesincelast = cltime - move - > fservertime ;
move - > fservertime = cltime ;
move - > servertime = move - > fservertime ;
frame - > ping_time = sv . time - cltime ;
2004-08-23 00:15:46 +00:00
2005-07-03 15:16:20 +00:00
// read current angles
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
2004-11-20 00:52:49 +00:00
{
2005-03-28 00:11:59 +00:00
host_client - > edict - > v - > v_angle [ i ] = MSG_ReadAngle ( ) ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
move - > angles [ i ] = ( host_client - > edict - > v - > v_angle [ i ] * 256 * 256 ) / 360 ;
2004-11-20 00:52:49 +00:00
}
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// read movement
move - > forwardmove = MSG_ReadShort ( ) ;
move - > sidemove = MSG_ReadShort ( ) ;
move - > upmove = MSG_ReadShort ( ) ;
2008-11-09 22:29:28 +00:00
move - > msec = timesincelast * 1000 ; //MSG_ReadFloat;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// read buttons
2005-06-14 04:52:10 +00:00
if ( host_client - > protocol = = SCP_DARKPLACES6 | | host_client - > protocol = = SCP_DARKPLACES7 )
bits = MSG_ReadLong ( ) ;
else
bits = MSG_ReadByte ( ) ;
2005-07-03 15:16:20 +00:00
move - > buttons = bits ;
2004-08-23 00:15:46 +00:00
i = MSG_ReadByte ( ) ;
if ( i )
move - > impulse = i ;
2004-11-20 00:52:49 +00:00
2005-06-14 04:52:10 +00:00
if ( host_client - > protocol = = SCP_DARKPLACES6 | | host_client - > protocol = = SCP_DARKPLACES7 )
{
2009-05-24 10:11:17 +00:00
SV_ReadPrydonCursor ( ) ;
2005-09-14 04:41:25 +00:00
}
2004-11-20 00:52:49 +00:00
2009-04-19 00:50:42 +00:00
if ( SV_RunFullQCMovement ( host_client , move ) )
{
pr_global_struct - > time = sv . physicstime ;
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
# ifdef VM_Q1
if ( svs . gametype = = GT_Q1QVM )
Q1QVM_PostThink ( ) ;
else
# endif
{
if ( pr_global_struct - > PlayerPostThink )
PR_ExecuteProgram ( svprogfuncs , pr_global_struct - > PlayerPostThink ) ;
}
host_client - > isindependant = true ;
return ;
}
2004-11-20 00:52:49 +00:00
if ( i & & SV_FiltureImpulse ( i , host_client - > trustlevel ) )
2005-03-28 00:11:59 +00:00
host_client - > edict - > v - > impulse = i ;
2004-11-20 00:52:49 +00:00
2005-03-28 00:11:59 +00:00
host_client - > edict - > v - > button0 = bits & 1 ;
host_client - > edict - > v - > button2 = ( bits > > 1 ) & 1 ;
2004-11-20 00:52:49 +00:00
if ( pr_allowbutton1 . value ) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows.
2005-03-28 00:11:59 +00:00
host_client - > edict - > v - > button1 = ( ( bits > > 2 ) & 1 ) ;
2004-11-20 00:52:49 +00:00
// DP_INPUTBUTTONS
2007-09-02 19:55:17 +00:00
host_client - > edict - > xv - > button3 = ( ( bits > > 2 ) & 1 ) ;
host_client - > edict - > xv - > button4 = ( ( bits > > 3 ) & 1 ) ;
host_client - > edict - > xv - > button5 = ( ( bits > > 4 ) & 1 ) ;
host_client - > edict - > xv - > button6 = ( ( bits > > 5 ) & 1 ) ;
host_client - > edict - > xv - > button7 = ( ( bits > > 6 ) & 1 ) ;
host_client - > edict - > xv - > button8 = ( ( bits > > 7 ) & 1 ) ;
2005-06-22 17:10:13 +00:00
if ( host_client - > last_sequence )
2008-11-09 22:29:28 +00:00
{
host_frametime = timesincelast ;
2005-06-22 17:10:13 +00:00
SV_RunEntity ( host_client - > edict ) ;
2008-11-09 22:29:28 +00:00
host_client - > isindependant = true ;
}
else
host_client - > isindependant = false ;
2004-08-23 00:15:46 +00:00
}
void SVNQ_ExecuteClientMessage ( client_t * cl )
{
int c ;
char * s ;
2005-07-03 15:16:20 +00:00
client_frame_t * frame ;
2004-08-23 00:15:46 +00:00
int seq_hash ;
2005-05-26 12:55:34 +00:00
cl - > netchan . outgoing_sequence + + ;
cl - > netchan . incoming_acknowledged = cl - > netchan . outgoing_sequence - 1 ;
2004-08-23 00:15:46 +00:00
// calc ping time
2006-02-17 02:51:59 +00:00
frame = & cl - > frameunion . frames [ cl - > netchan . incoming_acknowledged & UPDATE_MASK ] ;
2007-06-20 00:02:54 +00:00
frame - > ping_time = - 1 ;
2004-08-23 00:15:46 +00:00
// make sure the reply sequence number matches the incoming
2005-07-03 15:16:20 +00:00
// sequence number
2005-05-26 12:55:34 +00:00
// if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence)
2004-08-23 00:15:46 +00:00
cl - > netchan . outgoing_sequence = cl - > netchan . incoming_sequence ;
2005-05-26 12:55:34 +00:00
// else
2005-07-03 15:16:20 +00:00
// cl->send_message = false; // don't reply, sequences have slipped
2004-08-23 00:15:46 +00:00
// save time for ping calculations
2006-02-17 02:51:59 +00:00
cl - > frameunion . frames [ cl - > netchan . outgoing_sequence & UPDATE_MASK ] . senttime = realtime ;
cl - > frameunion . frames [ cl - > netchan . outgoing_sequence & UPDATE_MASK ] . ping_time = - 1 ;
2004-08-23 00:15:46 +00:00
host_client = cl ;
sv_player = host_client - > edict ;
2005-07-03 15:16:20 +00:00
seq_hash = cl - > netchan . incoming_sequence ;
2004-08-23 00:15:46 +00:00
// mark time so clients will know how much to predict
// other players
cl - > localtime = sv . time ;
while ( 1 )
{
if ( msg_badread )
{
Con_Printf ( " SV_ReadClientMessage: badread \n " ) ;
SV_DropClient ( cl ) ;
return ;
2005-07-03 15:16:20 +00:00
}
2004-08-23 00:15:46 +00:00
c = MSG_ReadByte ( ) ;
if ( c = = - 1 )
break ;
switch ( c )
{
default :
Con_Printf ( " SV_ReadClientMessage: unknown command char %i \n " , c ) ;
SV_DropClient ( cl ) ;
return ;
case clc_disconnect :
SV_DropClient ( cl ) ;
break ;
case clc_nop :
break ;
case clc_delta :
cl - > delta_sequence = MSG_ReadByte ( ) ;
break ;
case clc_move :
SVNQ_ReadClientMove ( & host_client - > lastcmd ) ;
// cmd = host_client->lastcmd;
// SV_ClientThink();
break ;
2005-07-03 15:16:20 +00:00
case clc_stringcmd :
2004-08-23 00:15:46 +00:00
s = MSG_ReadString ( ) ;
2005-10-23 17:57:20 +00:00
SV_ExecuteUserCommand ( s , false ) ;
host_client = cl ;
sv_player = cl - > edict ;
2004-08-23 00:15:46 +00:00
break ;
2008-11-09 22:29:28 +00:00
case 50 :
MSG_ReadLong ( ) ;
break ;
2007-06-10 21:33:24 +00:00
case clcdp_ackdownloaddata :
SV_DarkPlacesDownloadAck ( host_client ) ;
break ;
2004-08-23 00:15:46 +00:00
}
}
}
# endif
/*
= = = = = = = = = = = = = =
SV_UserInit
= = = = = = = = = = = = = =
*/
void SV_UserInit ( void )
2005-07-03 15:16:20 +00:00
{
2004-08-23 00:15:46 +00:00
# ifdef SERVERONLY
Cvar_Register ( & cl_rollspeed , " Prediction stuff " ) ;
Cvar_Register ( & cl_rollangle , " Prediction stuff " ) ;
# endif
Cvar_Register ( & sv_chatfilter , cvargroup_serverpermissions ) ;
Cvar_Register ( & sv_spectalk , cvargroup_servercontrol ) ;
Cvar_Register ( & sv_mapcheck , cvargroup_servercontrol ) ;
Cvar_Register ( & sv_cheatpc , cvargroup_servercontrol ) ;
Cvar_Register ( & sv_cheatspeedchecktime , cvargroup_servercontrol ) ;
Cvar_Register ( & sv_playermodelchecks , cvargroup_servercontrol ) ;
2008-05-25 22:23:43 +00:00
Cvar_Register ( & sv_getrealip , cvargroup_servercontrol ) ;
2008-05-27 18:59:07 +00:00
Cvar_Register ( & sv_realip_kick , cvargroup_servercontrol ) ;
2008-05-25 22:23:43 +00:00
Cvar_Register ( & sv_realiphostname_ipv4 , cvargroup_servercontrol ) ;
Cvar_Register ( & sv_realiphostname_ipv6 , cvargroup_servercontrol ) ;
Cvar_Register ( & sv_realip_timeout , cvargroup_servercontrol ) ;
2005-07-05 23:46:10 +00:00
Cvar_Register ( & sv_pushplayers , cvargroup_servercontrol ) ;
2006-05-29 05:35:07 +00:00
Cvar_Register ( & sv_floodprotect , cvargroup_servercontrol ) ;
2006-05-29 06:12:12 +00:00
Cvar_Register ( & sv_floodprotect_interval , cvargroup_servercontrol ) ;
Cvar_Register ( & sv_floodprotect_messages , cvargroup_servercontrol ) ;
Cvar_Register ( & sv_floodprotect_silencetime , cvargroup_servercontrol ) ;
2006-05-30 04:00:24 +00:00
Cvar_Register ( & sv_floodprotect_suicide , cvargroup_servercontrol ) ;
Cvar_Register ( & sv_floodprotect_sendmessage , cvargroup_servercontrol ) ;
2006-05-29 05:35:07 +00:00
2004-08-23 00:15:46 +00:00
Cvar_Register ( & sv_cmdlikercon , cvargroup_serverpermissions ) ;
2005-03-12 23:40:42 +00:00
Cvar_Register ( & cmd_gamecodelevel , " Access controls " ) ;
Cvar_Register ( & cmd_allowaccess , " Access controls " ) ;
2004-08-23 00:15:46 +00:00
Cvar_Register ( & votelevel , sv_votinggroup ) ;
Cvar_Register ( & voteminimum , sv_votinggroup ) ;
Cvar_Register ( & votepercent , sv_votinggroup ) ;
Cvar_Register ( & votetime , sv_votinggroup ) ;
2005-10-30 23:54:29 +00:00
Cvar_Register ( & sv_brokenmovetypes , " Backwards compatability " ) ;
2004-08-23 00:15:46 +00:00
Cvar_Register ( & sv_edgefriction , " netquake compatability " ) ;
}
static vec3_t forward , right , up , wishdir ;
static float * origin , * velocity , * angles ;
static float wishspeed ;
extern cvar_t sv_accelerate , sv_friction ;
static qboolean onground ;
/*
= = = = = = = = = = = = = = = = = =
SV_UserFriction
= = = = = = = = = = = = = = = = = =
*/
void SV_UserFriction ( void )
{
extern cvar_t sv_stopspeed ;
float * vel ;
float speed , newspeed , control ;
vec3_t start , stop ;
float friction ;
trace_t trace ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
vel = velocity ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
speed = sqrt ( vel [ 0 ] * vel [ 0 ] + vel [ 1 ] * vel [ 1 ] ) ;
if ( ! speed )
return ;
// if the leading edge is over a dropoff, increase friction
start [ 0 ] = stop [ 0 ] = origin [ 0 ] + vel [ 0 ] / speed * 16 ;
start [ 1 ] = stop [ 1 ] = origin [ 1 ] + vel [ 1 ] / speed * 16 ;
2005-03-28 00:11:59 +00:00
start [ 2 ] = origin [ 2 ] + sv_player - > v - > mins [ 2 ] ;
2004-08-23 00:15:46 +00:00
stop [ 2 ] = start [ 2 ] - 34 ;
trace = SV_Move ( start , vec3_origin , vec3_origin , stop , true , sv_player ) ;
if ( trace . fraction = = 1.0 )
friction = sv_friction . value * sv_edgefriction . value ;
else
friction = sv_friction . value ;
// val = GetEdictFieldValue(sv_player, "friction", &frictioncache);
// if (val && val->_float)
// friction *= val->_float;
2005-07-03 15:16:20 +00:00
// apply friction
2004-08-23 00:15:46 +00:00
control = speed < sv_stopspeed . value ? sv_stopspeed . value : speed ;
newspeed = speed - host_frametime * control * friction ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
if ( newspeed < 0 )
newspeed = 0 ;
newspeed / = speed ;
vel [ 0 ] = vel [ 0 ] * newspeed ;
vel [ 1 ] = vel [ 1 ] * newspeed ;
vel [ 2 ] = vel [ 2 ] * newspeed ;
}
void SV_Accelerate ( void )
{
int i ;
float addspeed , accelspeed , currentspeed ;
currentspeed = DotProduct ( velocity , wishdir ) ;
addspeed = wishspeed - currentspeed ;
if ( addspeed < = 0 )
return ;
accelspeed = sv_accelerate . value * host_frametime * wishspeed ;
if ( accelspeed > addspeed )
accelspeed = addspeed ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
2005-07-03 15:16:20 +00:00
velocity [ i ] + = accelspeed * wishdir [ i ] ;
2004-08-23 00:15:46 +00:00
}
void SV_AirAccelerate ( vec3_t wishveloc )
{
int i ;
float addspeed , wishspd , accelspeed , currentspeed ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
wishspd = VectorNormalize ( wishveloc ) ;
if ( wishspd > 30 )
wishspd = 30 ;
currentspeed = DotProduct ( velocity , wishveloc ) ;
addspeed = wishspd - currentspeed ;
if ( addspeed < = 0 )
return ;
// accelspeed = sv_accelerate.value * host_frametime;
accelspeed = sv_accelerate . value * wishspeed * host_frametime ;
if ( accelspeed > addspeed )
accelspeed = addspeed ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
2005-07-03 15:16:20 +00:00
velocity [ i ] + = accelspeed * wishveloc [ i ] ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
SV_AirMove
= = = = = = = = = = = = = = = = = = =
*/
void SV_AirMove ( void )
{
int i ;
vec3_t wishvel ;
float fmove , smove ;
float scale , maxspeed ;
2005-03-28 00:11:59 +00:00
AngleVectors ( sv_player - > v - > angles , forward , right , up ) ;
2004-08-23 00:15:46 +00:00
fmove = cmd . forwardmove ;
smove = cmd . sidemove ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
// hack to not let you back into teleporter
2005-03-28 00:11:59 +00:00
if ( sv . time < sv_player - > v - > teleport_time & & fmove < 0 )
2004-08-23 00:15:46 +00:00
fmove = 0 ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
wishvel [ i ] = forward [ i ] * fmove + right [ i ] * smove ;
2005-03-28 00:11:59 +00:00
if ( ( int ) sv_player - > v - > movetype ! = MOVETYPE_WALK )
2004-08-23 00:15:46 +00:00
wishvel [ 2 ] = cmd . upmove ;
else
wishvel [ 2 ] = 0 ;
VectorCopy ( wishvel , wishdir ) ;
wishspeed = VectorNormalize ( wishdir ) ;
// val = GetEdictFieldValue(sv_player, "scale", &scalecache);
// if (!val || !val->_float)
scale = 1 ;
// else
// scale = val->_float;
2007-10-05 18:08:47 +00:00
maxspeed = sv_player - > xv - > maxspeed ; //FIXME: This isn't fully compatible code...
2007-09-02 19:55:17 +00:00
if ( sv_player - > xv - > hasted )
maxspeed * = sv_player - > xv - > hasted ;
2004-08-23 00:15:46 +00:00
if ( wishspeed > maxspeed * scale )
{
VectorScale ( wishvel , maxspeed / wishspeed , wishvel ) ;
wishspeed = maxspeed * scale ;
}
2005-07-03 15:16:20 +00:00
2005-03-28 00:11:59 +00:00
if ( sv_player - > v - > movetype = = MOVETYPE_NOCLIP )
2004-08-23 00:15:46 +00:00
{ // noclip
VectorCopy ( wishvel , velocity ) ;
}
else if ( onground )
{
SV_UserFriction ( ) ;
SV_Accelerate ( ) ;
}
else
{ // not on ground, so little effect on velocity
SV_AirAccelerate ( wishvel ) ;
2005-07-03 15:16:20 +00:00
}
2004-08-23 00:15:46 +00:00
}
void SV_WaterMove ( void )
{
int i ;
vec3_t wishvel ;
float speed , newspeed , wishspeed , addspeed , accelspeed ;
float scale ;
float maxspeed ;
//
// user intentions
//
2005-03-28 00:11:59 +00:00
AngleVectors ( sv_player - > v - > v_angle , forward , right , up ) ;
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
wishvel [ i ] = forward [ i ] * cmd . forwardmove + right [ i ] * cmd . sidemove ;
if ( ! cmd . forwardmove & & ! cmd . sidemove & & ! cmd . upmove )
wishvel [ 2 ] - = 60 ; // drift towards bottom
else
wishvel [ 2 ] + = cmd . upmove ;
wishspeed = Length ( wishvel ) ;
// val = GetEdictFieldValue(sv_player, "scale", &scalecache);
// if (!val || !val->_float)
scale = 1 ;
// else
// scale = val->_float;
// val = GetEdictFieldValue(sv_player, "maxspeed", &maxspeedcache);
// if (val && val->_float)
// maxspeed = sv_maxspeed.value*val->_float;
// else
maxspeed = host_client - > maxspeed ;
if ( wishspeed > maxspeed * scale )
{
VectorScale ( wishvel , maxspeed / wishspeed , wishvel ) ;
wishspeed = maxspeed * scale ;
}
wishspeed * = 0.7 ;
//
// water friction
//
speed = Length ( velocity ) ;
if ( speed )
{
// val = GetEdictFieldValue(sv_player, "friction", &frictioncache);
// if (val&&val->_float)
// newspeed = speed - host_frametime * speed * sv_friction.value*val->_float;
// else
newspeed = speed - host_frametime * speed * sv_friction . value ;
if ( newspeed < 0 )
2005-07-03 15:16:20 +00:00
newspeed = 0 ;
2004-08-23 00:15:46 +00:00
VectorScale ( velocity , newspeed / speed , velocity ) ;
}
else
newspeed = 0 ;
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
//
// water acceleration
//
if ( ! wishspeed )
return ;
addspeed = wishspeed - newspeed ;
if ( addspeed < = 0 )
return ;
VectorNormalize ( wishvel ) ;
accelspeed = sv_accelerate . value * wishspeed * host_frametime ;
if ( accelspeed > addspeed )
accelspeed = addspeed ;
for ( i = 0 ; i < 3 ; i + + )
velocity [ i ] + = accelspeed * wishvel [ i ] ;
}
void SV_WaterJump ( void )
{
2005-03-28 00:11:59 +00:00
if ( sv . time > sv_player - > v - > teleport_time
| | ! sv_player - > v - > waterlevel )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
sv_player - > v - > flags = ( int ) sv_player - > v - > flags & ~ FL_WATERJUMP ;
sv_player - > v - > teleport_time = 0 ;
2004-08-23 00:15:46 +00:00
}
2005-03-28 00:11:59 +00:00
sv_player - > v - > velocity [ 0 ] = sv_player - > v - > movedir [ 0 ] ;
sv_player - > v - > velocity [ 1 ] = sv_player - > v - > movedir [ 1 ] ;
2004-08-23 00:15:46 +00:00
}
void SV_ClientThink ( void )
{
vec3_t v_angle ;
2004-09-22 15:29:33 +00:00
cmd = host_client - > lastcmd ;
sv_player = host_client - > edict ;
2007-10-08 12:23:55 +00:00
if ( host_client - > state & & host_client - > protocol ! = SCP_BAD )
{
sv_player - > xv - > movement [ 0 ] = cmd . forwardmove ;
sv_player - > xv - > movement [ 1 ] = cmd . sidemove ;
sv_player - > xv - > movement [ 2 ] = cmd . upmove ;
}
2004-08-23 00:15:46 +00:00
2004-09-07 23:12:46 +00:00
if ( SV_PlayerPhysicsQC )
2004-08-23 00:15:46 +00:00
{
2009-03-03 01:52:30 +00:00
pr_global_struct - > time = sv . physicstime ;
2004-08-23 00:15:46 +00:00
pr_global_struct - > self = EDICT_TO_PROG ( svprogfuncs , sv_player ) ;
PR_ExecuteProgram ( svprogfuncs , SV_PlayerPhysicsQC ) ;
return ;
}
2004-09-07 23:12:46 +00:00
2005-03-28 00:11:59 +00:00
if ( sv_player - > v - > movetype = = MOVETYPE_NONE )
2004-08-23 00:15:46 +00:00
return ;
2005-07-03 15:16:20 +00:00
2005-03-28 00:11:59 +00:00
onground = ( int ) sv_player - > v - > flags & FL_ONGROUND ;
2004-08-23 00:15:46 +00:00
2005-03-28 00:11:59 +00:00
origin = sv_player - > v - > origin ;
velocity = sv_player - > v - > velocity ;
2004-08-23 00:15:46 +00:00
// DropPunchAngle ();
2005-07-03 15:16:20 +00:00
2004-08-23 00:15:46 +00:00
//
// if dead, behave differently
//
2005-03-28 00:11:59 +00:00
if ( sv_player - > v - > health < = 0 )
2004-08-23 00:15:46 +00:00
return ;
//
// angles
// show 1/3 the pitch angle and all the roll angle
2005-03-28 00:11:59 +00:00
angles = sv_player - > v - > angles ;
2005-07-03 15:16:20 +00:00
2005-03-28 00:11:59 +00:00
VectorCopy ( sv_player - > v - > v_angle , v_angle ) ;
// VectorAdd (sv_player->v->v_angle, sv_player->v->punchangle, v_angle);
angles [ ROLL ] = V_CalcRoll ( sv_player - > v - > angles , sv_player - > v - > velocity ) * 4 ;
if ( ! sv_player - > v - > fixangle )
2004-08-23 00:15:46 +00:00
{
angles [ PITCH ] = - v_angle [ PITCH ] / 3 ;
angles [ YAW ] = v_angle [ YAW ] ;
}
2005-03-28 00:11:59 +00:00
if ( ( int ) sv_player - > v - > flags & FL_WATERJUMP )
2004-08-23 00:15:46 +00:00
{
SV_WaterJump ( ) ;
return ;
}
//
// walk
//
2005-03-28 00:11:59 +00:00
if ( ( sv_player - > v - > waterlevel > = 2 )
& & ( sv_player - > v - > movetype ! = MOVETYPE_NOCLIP ) )
2004-08-23 00:15:46 +00:00
{
SV_WaterMove ( ) ;
return ;
}
SV_AirMove ( ) ;
}
2004-11-29 01:21:00 +00:00
# endif