2005-09-24 04:48:20 +00:00
/*
Copyright ( C ) 1996 - 1997 Id Software , Inc .
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the included ( GNU . txt ) 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 .
*/
2005-09-06 01:09:36 +00:00
# include "qtv.h"
2007-12-27 15:17:33 +00:00
# include "bsd_string.h"
2005-09-06 01:09:36 +00:00
# define ParseError(m) (m)->cursize = (m)->cursize+1 //
void SendBufferToViewer ( viewer_t * v , const char * buffer , int length , qboolean reliable )
{
if ( reliable )
{
//try and put it in the normal reliable
if ( ! v - > backbuffered & & v - > netchan . message . cursize + length < v - > netchan . message . maxsize )
WriteData ( & v - > netchan . message , buffer , length ) ;
else if ( v - > backbuffered > 0 & & v - > backbuf [ v - > backbuffered - 1 ] . cursize + length < v - > backbuf [ v - > backbuffered - 1 ] . maxsize ) //try and put it in the current backbuffer
WriteData ( & v - > backbuf [ v - > backbuffered - 1 ] , buffer , length ) ;
else if ( v - > backbuffered = = MAX_BACK_BUFFERS )
2007-03-18 05:07:10 +00:00
{
v - > netchan . message . cursize = 0 ;
WriteByte ( & v - > netchan . message , svc_print ) ;
2007-07-23 10:53:59 +00:00
if ( ! v - > netchan . isnqprotocol )
WriteByte ( & v - > netchan . message , PRINT_HIGH ) ;
2007-03-18 05:07:10 +00:00
WriteString ( & v - > netchan . message , " backbuffer overflow \n " ) ;
2007-07-23 10:53:59 +00:00
if ( ! v - > drop )
Sys_Printf ( NULL , " %s backbuffers overflowed \n " , v - > name ) ; //FIXME
2005-09-06 01:09:36 +00:00
v - > drop = true ; //we would need too many backbuffers.
2007-03-18 05:07:10 +00:00
}
2005-09-06 01:09:36 +00:00
else
{
//create a new backbuffer
if ( ! v - > backbuf [ v - > backbuffered ] . data )
{
InitNetMsg ( & v - > backbuf [ v - > backbuffered ] , ( unsigned char * ) malloc ( MAX_BACKBUF_SIZE ) , MAX_BACKBUF_SIZE ) ;
}
v - > backbuf [ v - > backbuffered ] . cursize = 0 ; //make sure it's empty
WriteData ( & v - > backbuf [ v - > backbuffered ] , buffer , length ) ;
v - > backbuffered + + ;
}
}
}
2007-07-23 10:53:59 +00:00
void Multicast ( sv_t * tv , void * buffer , int length , int to , unsigned int playermask , int suitablefor )
2005-09-06 01:09:36 +00:00
{
viewer_t * v ;
switch ( to )
{
case dem_multiple :
case dem_single :
case dem_stats :
//check and send to them only if they're tracking this player(s).
2005-10-07 02:02:15 +00:00
for ( v = tv - > cluster - > viewers ; v ; v = v - > next )
2005-09-06 01:09:36 +00:00
{
2006-09-19 01:48:12 +00:00
if ( v - > thinksitsconnected | | suitablefor & CONNECTING )
if ( v - > server = = tv )
if ( v - > trackplayer > = 0 )
if ( ( 1 < < v - > trackplayer ) & playermask )
{
if ( suitablefor & ( v - > netchan . isnqprotocol ? NQ : QW ) )
SendBufferToViewer ( v , buffer , length , true ) ; //FIXME: change the reliable depending on message type
}
2005-09-06 01:09:36 +00:00
}
break ;
default :
//send to all
2005-10-07 02:02:15 +00:00
for ( v = tv - > cluster - > viewers ; v ; v = v - > next )
2005-09-06 01:09:36 +00:00
{
2006-09-19 01:48:12 +00:00
if ( v - > thinksitsconnected | | suitablefor & CONNECTING )
if ( v - > server = = tv )
if ( suitablefor & ( v - > netchan . isnqprotocol ? NQ : QW ) )
2007-03-18 05:07:10 +00:00
SendBufferToViewer ( v , buffer , length , true ) ; //FIXME: change the reliable depending on message type
2005-09-06 01:09:36 +00:00
}
break ;
}
}
2007-07-23 10:53:59 +00:00
void Broadcast ( cluster_t * cluster , void * buffer , int length , int suitablefor )
2005-10-09 09:40:26 +00:00
{
viewer_t * v ;
for ( v = cluster - > viewers ; v ; v = v - > next )
{
2006-09-17 01:27:32 +00:00
if ( suitablefor & ( v - > netchan . isnqprotocol ? NQ : QW ) )
SendBufferToViewer ( v , buffer , length , true ) ;
2005-10-09 09:40:26 +00:00
}
}
2005-09-06 01:09:36 +00:00
2007-07-23 10:53:59 +00:00
void ConnectionData ( sv_t * tv , void * buffer , int length , int to , unsigned int playermask , int suitablefor )
{
if ( ! tv - > parsingconnectiondata )
Multicast ( tv , buffer , length , to , playermask , suitablefor ) ;
2007-09-08 20:15:59 +00:00
else if ( tv - > controller )
{
if ( suitablefor & ( tv - > controller - > netchan . isnqprotocol ? NQ : QW ) )
SendBufferToViewer ( tv - > controller , buffer , length , true ) ;
}
2007-07-23 10:53:59 +00:00
}
2005-09-06 01:09:36 +00:00
static void ParseServerData ( sv_t * tv , netmsg_t * m , int to , unsigned int playermask )
{
2007-01-05 22:09:56 +00:00
int i ;
2005-09-06 01:09:36 +00:00
int protocol ;
viewer_t * v ;
2005-09-25 20:50:57 +00:00
2005-09-06 01:09:36 +00:00
protocol = ReadLong ( m ) ;
if ( protocol ! = PROTOCOL_VERSION )
{
ParseError ( m ) ;
return ;
}
tv - > parsingconnectiondata = true ;
2006-02-21 19:55:12 +00:00
tv - > clservercount = ReadLong ( m ) ; //we don't care about server's servercount, it's all reliable data anyway.
2005-09-06 01:09:36 +00:00
2006-04-11 22:15:09 +00:00
tv - > trackplayer = - 1 ;
2005-09-06 01:09:36 +00:00
ReadString ( m , tv - > gamedir , sizeof ( tv - > gamedir ) ) ;
2007-07-23 10:53:59 +00:00
if ( tv - > usequakeworldprotocols )
2006-02-21 19:55:12 +00:00
tv - > thisplayer = ReadByte ( m ) & ~ 128 ;
else
{
tv - > thisplayer = MAX_CLIENTS - 1 ;
/*tv->servertime =*/ ReadFloat ( m ) ;
}
2007-09-08 20:15:59 +00:00
if ( tv - > controller )
tv - > controller - > thisplayer = tv - > thisplayer ;
2005-09-06 01:09:36 +00:00
ReadString ( m , tv - > mapname , sizeof ( tv - > mapname ) ) ;
2007-05-28 02:31:48 +00:00
QTV_Printf ( tv , " Gamedir: %s \n " , tv - > gamedir ) ;
QTV_Printf ( tv , " --------------------- \n " ) ;
Sys_Printf ( tv - > cluster , " Stream %i: %s \n " , tv - > streamid , tv - > mapname ) ;
QTV_Printf ( tv , " --------------------- \n " ) ;
2005-09-06 01:09:36 +00:00
// get the movevars
tv - > movevars . gravity = ReadFloat ( m ) ;
tv - > movevars . stopspeed = ReadFloat ( m ) ;
tv - > movevars . maxspeed = ReadFloat ( m ) ;
tv - > movevars . spectatormaxspeed = ReadFloat ( m ) ;
tv - > movevars . accelerate = ReadFloat ( m ) ;
tv - > movevars . airaccelerate = ReadFloat ( m ) ;
tv - > movevars . wateraccelerate = ReadFloat ( m ) ;
tv - > movevars . friction = ReadFloat ( m ) ;
tv - > movevars . waterfriction = ReadFloat ( m ) ;
tv - > movevars . entgrav = ReadFloat ( m ) ;
2005-10-07 02:02:15 +00:00
for ( v = tv - > cluster - > viewers ; v ; v = v - > next )
{
if ( v - > server = = tv )
v - > thinksitsconnected = false ;
}
2005-09-06 01:09:36 +00:00
2006-12-26 21:26:10 +00:00
// tv->maxents = 0; //clear these
2006-09-17 01:27:32 +00:00
tv - > spawnstatic_count = 0 ;
2005-09-06 01:09:36 +00:00
memset ( tv - > modellist , 0 , sizeof ( tv - > modellist ) ) ;
memset ( tv - > soundlist , 0 , sizeof ( tv - > soundlist ) ) ;
memset ( tv - > lightstyle , 0 , sizeof ( tv - > lightstyle ) ) ;
tv - > staticsound_count = 0 ;
2005-09-24 04:48:20 +00:00
memset ( tv - > staticsound , 0 , sizeof ( tv - > staticsound ) ) ;
memset ( tv - > players , 0 , sizeof ( tv - > players ) ) ;
2007-10-08 14:37:08 +00:00
memset ( tv - > entity , 0 , sizeof ( tv - > entity ) ) ; //for the baselines
2006-02-21 19:55:12 +00:00
2007-01-05 22:09:56 +00:00
for ( i = 0 ; i < MAX_ENTITY_FRAMES ; i + + )
{
tv - > frame [ i ] . numents = 0 ;
}
2006-02-21 19:55:12 +00:00
2007-09-08 20:15:59 +00:00
if ( ! tv - > controller & & tv - > usequakeworldprotocols )
2006-02-21 19:55:12 +00:00
{
2006-04-11 22:15:09 +00:00
tv - > netchan . message . cursize = 0 ; //mvdsv sucks
2006-02-21 19:55:12 +00:00
SendClientCommand ( tv , " soundlist %i 0 \n " , tv - > clservercount ) ;
}
2007-09-08 20:15:59 +00:00
else
ConnectionData ( tv , ( void * ) ( ( char * ) m - > data + m - > startpos ) , m - > readpos - m - > startpos , to , dem_read , QW ) ;
2007-09-10 19:27:39 +00:00
if ( tv - > controller )
QW_ClearViewerState ( tv - > controller ) ;
2006-04-11 22:15:09 +00:00
strcpy ( tv - > status , " Receiving soundlist \n " ) ;
2005-09-06 01:09:36 +00:00
}
static void ParseCDTrack ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
2006-09-17 01:27:32 +00:00
char nqversion [ 3 ] ;
2005-09-06 01:09:36 +00:00
tv - > cdtrack = ReadByte ( m ) ;
2007-08-01 14:55:28 +00:00
ConnectionData ( tv , ( void * ) ( ( char * ) m - > data + m - > startpos ) , m - > readpos - m - > startpos , to , mask , QW ) ;
2006-09-17 01:27:32 +00:00
2007-07-23 10:53:59 +00:00
nqversion [ 0 ] = svc_cdtrack ;
nqversion [ 1 ] = tv - > cdtrack ;
nqversion [ 2 ] = tv - > cdtrack ;
ConnectionData ( tv , nqversion , 3 , to , mask , NQ ) ;
2005-09-06 01:09:36 +00:00
}
static void ParseStufftext ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
viewer_t * v ;
char text [ 1024 ] ;
2005-09-24 04:48:20 +00:00
char value [ 256 ] ;
qboolean fromproxy ;
2005-09-06 01:09:36 +00:00
ReadString ( m , text , sizeof ( text ) ) ;
2006-04-11 22:15:09 +00:00
// Sys_Printf(tv->cluster, "stuffcmd: %s", text);
2007-03-18 05:07:10 +00:00
if ( ! strcmp ( text , " say proxy:menu \n " ) )
{ //qizmo's 'previous proxy' message
tv - > proxyisselected = true ;
if ( tv - > controller )
QW_SetMenu ( tv - > controller , MENU_MAIN ) ;
tv - > serverisproxy = true ; //FIXME: Detect this properly on qizmo
}
2007-10-08 14:37:08 +00:00
else if ( ! strncmp ( text , " //I am a proxy " , 14 ) )
tv - > serverisproxy = true ;
2007-03-18 05:07:10 +00:00
else if ( ! strncmp ( text , " //set prox_inmenu " , 18 ) )
{
if ( tv - > controller )
QW_SetMenu ( tv - > controller , atoi ( text + 18 ) ? MENU_FORWARDING : MENU_NONE ) ;
}
else if ( strstr ( text , " screenshot " ) )
2007-07-23 10:53:59 +00:00
{
if ( tv - > controller )
{ //let it through to the controller
2007-08-03 14:10:47 +00:00
SendBufferToViewer ( tv - > controller , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , true ) ;
2007-07-23 10:53:59 +00:00
}
2007-03-18 05:07:10 +00:00
return ; //this was generating far too many screenshots when watching demos
2007-07-23 10:53:59 +00:00
}
2007-03-03 18:46:43 +00:00
else if ( ! strcmp ( text , " skins \n " ) )
2005-09-06 01:09:36 +00:00
{
const char newcmd [ 10 ] = { svc_stufftext , ' c ' , ' m ' , ' d ' , ' ' , ' n ' , ' e ' , ' w ' , ' \n ' , ' \0 ' } ;
tv - > parsingconnectiondata = false ;
2005-09-24 04:48:20 +00:00
2006-04-11 22:15:09 +00:00
strcpy ( tv - > status , " On server \n " ) ;
2005-10-07 02:02:15 +00:00
for ( v = tv - > cluster - > viewers ; v ; v = v - > next )
2005-09-06 01:09:36 +00:00
{
2007-09-08 20:15:59 +00:00
if ( v - > server = = tv & & v ! = tv - > controller )
2005-10-07 02:02:15 +00:00
{
v - > servercount + + ;
SendBufferToViewer ( v , newcmd , sizeof ( newcmd ) , true ) ;
}
2005-09-06 01:09:36 +00:00
}
2006-02-21 19:55:12 +00:00
2007-09-08 20:15:59 +00:00
if ( tv - > controller )
SendBufferToViewer ( tv - > controller , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , true ) ;
else if ( tv - > usequakeworldprotocols )
2006-02-21 19:55:12 +00:00
SendClientCommand ( tv , " begin %i \n " , tv - > clservercount ) ;
2005-09-06 01:09:36 +00:00
return ;
}
else if ( ! strncmp ( text , " fullserverinfo " , 15 ) )
{
2005-09-24 04:48:20 +00:00
text [ strlen ( text ) - 1 ] = ' \0 ' ;
text [ strlen ( text ) - 1 ] = ' \0 ' ;
//copy over the server's serverinfo
2007-12-27 15:17:33 +00:00
strlcpy ( tv - > serverinfo , text + 16 , sizeof ( tv - > serverinfo ) ) ;
2005-09-24 04:48:20 +00:00
2007-10-08 14:37:08 +00:00
Info_ValueForKey ( tv - > serverinfo , " *qtv " , value , sizeof ( value ) ) ;
2005-09-24 04:48:20 +00:00
if ( * value )
2007-10-08 14:37:08 +00:00
{
2005-09-24 04:48:20 +00:00
fromproxy = true ;
2007-10-08 14:37:08 +00:00
tv - > serverisproxy = fromproxy ;
}
2005-09-24 04:48:20 +00:00
else
fromproxy = false ;
//add on our extra infos
Info_SetValueForStarKey ( tv - > serverinfo , " *qtv " , VERSION , sizeof ( tv - > serverinfo ) ) ;
Info_SetValueForStarKey ( tv - > serverinfo , " *z_ext " , Z_EXT_STRING , sizeof ( tv - > serverinfo ) ) ;
2006-10-07 22:29:31 +00:00
Info_ValueForKey ( tv - > serverinfo , " hostname " , tv - > hostname , sizeof ( tv - > hostname ) ) ;
2005-09-24 04:48:20 +00:00
//change the hostname (the qtv's hostname with the server's hostname in brackets)
Info_ValueForKey ( tv - > serverinfo , " hostname " , value , sizeof ( value ) ) ;
if ( fromproxy & & strchr ( value , ' ( ' ) & & value [ strlen ( value ) - 1 ] = = ' ) ' ) //already has brackets
{ //the fromproxy check is because it's fairly common to find a qw server with brackets after it's name.
char * s ;
s = strchr ( value , ' ( ' ) ; //so strip the parent proxy's hostname, and put our hostname first, leaving the origional server's hostname within the brackets
2005-10-07 02:02:15 +00:00
snprintf ( text , sizeof ( text ) , " %s %s " , tv - > cluster - > hostname , s ) ;
2005-09-24 04:48:20 +00:00
}
else
{
2006-10-22 19:18:15 +00:00
if ( tv - > sourcefile )
2005-10-07 02:02:15 +00:00
snprintf ( text , sizeof ( text ) , " %s (recorded from: %s) " , tv - > cluster - > hostname , value ) ;
2005-09-24 04:48:20 +00:00
else
2005-10-07 02:02:15 +00:00
snprintf ( text , sizeof ( text ) , " %s (live: %s) " , tv - > cluster - > hostname , value ) ;
2005-09-24 04:48:20 +00:00
}
Info_SetValueForStarKey ( tv - > serverinfo , " hostname " , text , sizeof ( tv - > serverinfo ) ) ;
2007-10-08 14:48:13 +00:00
if ( tv - > controller & & ( tv - > controller - > netchan . isnqprotocol = = false ) )
2007-10-08 14:37:08 +00:00
SendBufferToViewer ( tv - > controller , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , true ) ;
2005-09-06 01:09:36 +00:00
return ;
}
else if ( ! strncmp ( text , " cmd " , 4 ) )
2006-02-21 19:55:12 +00:00
{
2007-09-08 20:15:59 +00:00
if ( tv - > controller )
SendBufferToViewer ( tv - > controller , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , true ) ;
else if ( tv - > usequakeworldprotocols )
2006-02-21 19:55:12 +00:00
SendClientCommand ( tv , " %s " , text + 4 ) ;
2005-09-06 01:09:36 +00:00
return ; //commands the game server asked for are pointless.
2006-02-21 19:55:12 +00:00
}
2006-02-21 23:25:54 +00:00
else if ( ! strncmp ( text , " reconnect " , 9 ) )
{
2007-09-08 20:15:59 +00:00
if ( tv - > controller )
SendBufferToViewer ( tv - > controller , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , true ) ;
else if ( tv - > usequakeworldprotocols )
2006-02-21 23:25:54 +00:00
SendClientCommand ( tv , " new \n " ) ;
return ;
}
2006-04-11 22:15:09 +00:00
else if ( ! strncmp ( text , " packet " , 7 ) )
{
2007-07-23 10:53:59 +00:00
if ( tv - > controller )
{ //if we're acting as a proxy, forward the realip packets, and ONLY to the controller
2007-08-03 14:10:47 +00:00
SendBufferToViewer ( tv - > controller , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , true ) ;
2007-07-23 10:53:59 +00:00
return ;
}
if ( tv - > usequakeworldprotocols )
{ //eeeevil hack for proxy-spectating
2006-04-11 22:15:09 +00:00
char * ptr ;
char arg [ 3 ] [ ARG_LEN ] ;
netadr_t adr ;
ptr = text ;
ptr = COM_ParseToken ( ptr , arg [ 0 ] , ARG_LEN , " " ) ;
ptr = COM_ParseToken ( ptr , arg [ 1 ] , ARG_LEN , " " ) ;
ptr = COM_ParseToken ( ptr , arg [ 2 ] , ARG_LEN , " " ) ;
2007-07-23 10:53:59 +00:00
NET_StringToAddr ( arg [ 1 ] , & adr , PROX_DEFAULTSERVERPORT ) ;
2006-04-11 22:15:09 +00:00
Netchan_OutOfBand ( tv - > cluster , tv - > sourcesock , adr , strlen ( arg [ 2 ] ) , arg [ 2 ] ) ;
//this is an evil hack
SendClientCommand ( tv , " new \n " ) ;
return ;
}
2007-12-12 11:17:18 +00:00
Sys_Printf ( tv - > cluster , " packet stuffcmd in an mvd \n " ) ; //shouldn't ever happen, try ignoring it.
2006-04-11 22:15:09 +00:00
return ;
}
2007-07-23 10:53:59 +00:00
else if ( tv - > usequakeworldprotocols & & ! strncmp ( text , " setinfo " , 8 ) )
2006-04-11 22:15:09 +00:00
{
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , Q1 ) ;
2007-09-08 20:15:59 +00:00
if ( ! tv - > controller )
SendClientCommand ( tv , text ) ;
2006-04-11 22:15:09 +00:00
}
else
{
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , Q1 ) ;
2006-04-11 22:15:09 +00:00
return ;
}
2005-09-06 01:09:36 +00:00
}
2005-10-07 02:02:15 +00:00
static void ParseSetInfo ( sv_t * tv , netmsg_t * m )
{
int pnum ;
char key [ 64 ] ;
char value [ 256 ] ;
pnum = ReadByte ( m ) ;
ReadString ( m , key , sizeof ( key ) ) ;
ReadString ( m , value , sizeof ( value ) ) ;
if ( pnum < MAX_CLIENTS )
Info_SetValueForStarKey ( tv - > players [ pnum ] . userinfo , key , value , sizeof ( tv - > players [ pnum ] . userinfo ) ) ;
2007-08-03 14:10:47 +00:00
ConnectionData ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , dem_all , ( unsigned ) - 1 , QW ) ;
2005-10-07 02:02:15 +00:00
}
2005-09-06 01:09:36 +00:00
static void ParseServerinfo ( sv_t * tv , netmsg_t * m )
{
char key [ 64 ] ;
2005-09-24 21:31:01 +00:00
char value [ 256 ] ;
2005-09-06 01:09:36 +00:00
ReadString ( m , key , sizeof ( key ) ) ;
ReadString ( m , value , sizeof ( value ) ) ;
2005-09-24 21:31:01 +00:00
if ( strcmp ( key , " hostname " ) ) //don't allow the hostname to change, but allow the server to change other serverinfos.
Info_SetValueForStarKey ( tv - > serverinfo , key , value , sizeof ( tv - > serverinfo ) ) ;
2007-08-03 14:10:47 +00:00
ConnectionData ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , dem_all , ( unsigned ) - 1 , QW ) ;
2005-09-06 01:09:36 +00:00
}
static void ParsePrint ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
char text [ 1024 ] ;
2006-09-17 01:27:32 +00:00
char buffer [ 1024 ] ;
2005-09-06 01:09:36 +00:00
int level ;
2005-09-24 11:44:26 +00:00
2005-09-06 01:09:36 +00:00
level = ReadByte ( m ) ;
2006-09-17 01:27:32 +00:00
ReadString ( m , text , sizeof ( text ) - 2 ) ;
if ( level = = 3 )
{
strcpy ( buffer + 2 , text ) ;
buffer [ 1 ] = 1 ;
}
else
{
strcpy ( buffer + 1 , text ) ;
}
buffer [ 0 ] = svc_print ;
2005-09-06 01:09:36 +00:00
2007-07-23 10:53:59 +00:00
if ( ( to & dem_mask ) = = dem_all | | to = = dem_read )
2005-09-06 01:09:36 +00:00
{
if ( level > 1 )
2005-09-24 11:44:26 +00:00
{
2007-05-28 02:31:48 +00:00
QTV_Printf ( tv , " %s " , text ) ;
2005-09-24 11:44:26 +00:00
}
2005-09-06 01:09:36 +00:00
}
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , QW | CONNECTING ) ;
2006-09-19 01:48:12 +00:00
// Multicast(tv, buffer, strlen(buffer), to, mask, NQ);
2005-09-06 01:09:36 +00:00
}
static void ParseCenterprint ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
2007-03-18 05:07:10 +00:00
viewer_t * v ;
2005-09-06 01:09:36 +00:00
char text [ 1024 ] ;
ReadString ( m , text , sizeof ( text ) ) ;
2007-03-18 05:07:10 +00:00
switch ( to )
{
case dem_multiple :
case dem_single :
case dem_stats :
//check and send to them only if they're tracking this player(s).
for ( v = tv - > cluster - > viewers ; v ; v = v - > next )
{
if ( ! v - > menunum | | v - > menunum = = MENU_FORWARDING )
if ( v - > thinksitsconnected )
if ( v - > server = = tv )
if ( v - > trackplayer > = 0 )
if ( ( 1 < < v - > trackplayer ) & mask )
{
2007-08-03 14:10:47 +00:00
SendBufferToViewer ( v , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , true ) ; //FIXME: change the reliable depending on message type
2007-03-18 05:07:10 +00:00
}
}
break ;
default :
//send to all
for ( v = tv - > cluster - > viewers ; v ; v = v - > next )
{
if ( ! v - > menunum | | v - > menunum = = MENU_FORWARDING )
if ( v - > thinksitsconnected )
if ( v - > server = = tv )
2007-08-03 14:10:47 +00:00
SendBufferToViewer ( v , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , true ) ; //FIXME: change the reliable depending on message type
2007-03-18 05:07:10 +00:00
}
break ;
}
2005-09-06 01:09:36 +00:00
}
2005-09-24 04:48:20 +00:00
static int ParseList ( sv_t * tv , netmsg_t * m , filename_t * list , int to , unsigned int mask )
2005-09-06 01:09:36 +00:00
{
int first ;
first = ReadByte ( m ) + 1 ;
for ( ; first < MAX_LIST ; first + + )
{
ReadString ( m , list [ first ] . name , sizeof ( list [ first ] . name ) ) ;
2005-09-24 04:48:20 +00:00
// printf("read %i: %s\n", first, list[first].name);
2005-09-06 01:09:36 +00:00
if ( ! * list [ first ] . name )
break ;
// printf("%i: %s\n", first, list[first].name);
}
2005-09-24 04:48:20 +00:00
return ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
}
2005-09-24 04:48:20 +00:00
static void ParseEntityState ( entity_state_t * es , netmsg_t * m ) //for baselines/static entities
2005-09-06 01:09:36 +00:00
{
int i ;
2005-09-24 04:48:20 +00:00
es - > modelindex = ReadByte ( m ) ;
es - > frame = ReadByte ( m ) ;
es - > colormap = ReadByte ( m ) ;
es - > skinnum = ReadByte ( m ) ;
for ( i = 0 ; i < 3 ; i + + )
{
es - > origin [ i ] = ReadShort ( m ) ;
es - > angles [ i ] = ReadByte ( m ) ;
}
}
static void ParseBaseline ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
2005-09-06 01:09:36 +00:00
unsigned int entnum ;
entnum = ReadShort ( m ) ;
if ( entnum > = MAX_ENTITIES )
{
ParseError ( m ) ;
return ;
}
2005-09-24 04:48:20 +00:00
ParseEntityState ( & tv - > entity [ entnum ] . baseline , m ) ;
2007-09-08 20:15:59 +00:00
ConnectionData ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , Q1 ) ;
2005-09-06 01:09:36 +00:00
}
static void ParseStaticSound ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
if ( tv - > staticsound_count = = MAX_STATICSOUNDS )
{
2005-09-24 04:48:20 +00:00
tv - > staticsound_count - - ; // don't be fatal.
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " Too many static sounds \n " ) ;
2005-09-06 01:09:36 +00:00
}
tv - > staticsound [ tv - > staticsound_count ] . origin [ 0 ] = ReadShort ( m ) ;
tv - > staticsound [ tv - > staticsound_count ] . origin [ 1 ] = ReadShort ( m ) ;
tv - > staticsound [ tv - > staticsound_count ] . origin [ 2 ] = ReadShort ( m ) ;
tv - > staticsound [ tv - > staticsound_count ] . soundindex = ReadByte ( m ) ;
tv - > staticsound [ tv - > staticsound_count ] . volume = ReadByte ( m ) ;
tv - > staticsound [ tv - > staticsound_count ] . attenuation = ReadByte ( m ) ;
tv - > staticsound_count + + ;
2007-07-23 10:53:59 +00:00
2007-08-03 14:10:47 +00:00
ConnectionData ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , Q1 ) ;
2005-09-06 01:09:36 +00:00
}
2005-09-24 04:48:20 +00:00
static void ParseIntermission ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadByte ( m ) ;
ReadByte ( m ) ;
ReadByte ( m ) ;
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , QW ) ;
2005-09-24 04:48:20 +00:00
}
void ParseSpawnStatic ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
if ( tv - > spawnstatic_count = = MAX_STATICENTITIES )
{
tv - > spawnstatic_count - - ; // don't be fatal.
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " Too many static entities \n " ) ;
2005-09-24 04:48:20 +00:00
}
ParseEntityState ( & tv - > spawnstatic [ tv - > spawnstatic_count ] , m ) ;
tv - > spawnstatic_count + + ;
2005-09-24 21:31:01 +00:00
2007-08-03 14:10:47 +00:00
ConnectionData ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , Q1 ) ;
2005-09-24 04:48:20 +00:00
}
2006-02-21 19:55:12 +00:00
extern const usercmd_t nullcmd ;
2005-10-07 02:02:15 +00:00
static void ParsePlayerInfo ( sv_t * tv , netmsg_t * m , qboolean clearoldplayers )
2005-09-06 01:09:36 +00:00
{
2006-02-21 19:55:12 +00:00
usercmd_t nonnullcmd ;
2005-09-06 01:09:36 +00:00
int flags ;
int num ;
int i ;
2005-10-07 02:02:15 +00:00
if ( clearoldplayers )
{
for ( i = 0 ; i < MAX_CLIENTS ; i + + )
{ //hide players
//they'll be sent after this packet.
tv - > players [ i ] . active = false ;
}
}
2005-09-06 01:09:36 +00:00
num = ReadByte ( m ) ;
if ( num > = MAX_CLIENTS )
{
num = 0 ; // don't be fatal.
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " Too many svc_playerinfos, wrapping \n " ) ;
2005-09-06 01:09:36 +00:00
}
tv - > players [ num ] . old = tv - > players [ num ] . current ;
2007-07-23 10:53:59 +00:00
if ( tv - > usequakeworldprotocols )
2005-09-06 01:09:36 +00:00
{
2006-02-21 19:55:12 +00:00
tv - > players [ num ] . old = tv - > players [ num ] . current ;
flags = ( unsigned short ) ReadShort ( m ) ;
2005-09-06 01:09:36 +00:00
2006-02-21 19:55:12 +00:00
tv - > players [ num ] . current . origin [ 0 ] = ReadShort ( m ) ;
tv - > players [ num ] . current . origin [ 1 ] = ReadShort ( m ) ;
tv - > players [ num ] . current . origin [ 2 ] = ReadShort ( m ) ;
tv - > players [ num ] . current . frame = ReadByte ( m ) ;
if ( flags & PF_MSEC )
ReadByte ( m ) ;
if ( flags & PF_COMMAND )
{
ReadDeltaUsercmd ( m , & nullcmd , & nonnullcmd ) ;
tv - > players [ num ] . current . angles [ 0 ] = nonnullcmd . angles [ 0 ] ;
tv - > players [ num ] . current . angles [ 1 ] = nonnullcmd . angles [ 1 ] ;
tv - > players [ num ] . current . angles [ 2 ] = nonnullcmd . angles [ 2 ] ;
}
2006-09-17 01:27:32 +00:00
else
2006-11-03 15:53:04 +00:00
{ //the only reason we'd not get a command is if it's us.
if ( tv - > controller )
{
tv - > players [ num ] . current . angles [ 0 ] = tv - > controller - > ucmds [ 2 ] . angles [ 0 ] ;
tv - > players [ num ] . current . angles [ 1 ] = tv - > controller - > ucmds [ 2 ] . angles [ 1 ] ;
tv - > players [ num ] . current . angles [ 2 ] = tv - > controller - > ucmds [ 2 ] . angles [ 2 ] ;
}
else
{
tv - > players [ num ] . current . angles [ 0 ] = tv - > proxyplayerangles [ 0 ] / 360 * 65535 ;
tv - > players [ num ] . current . angles [ 1 ] = tv - > proxyplayerangles [ 1 ] / 360 * 65535 ;
tv - > players [ num ] . current . angles [ 2 ] = tv - > proxyplayerangles [ 2 ] / 360 * 65535 ;
}
2006-09-17 01:27:32 +00:00
}
2006-02-21 19:55:12 +00:00
for ( i = 0 ; i < 3 ; i + + )
2005-09-06 01:09:36 +00:00
{
2006-02-21 19:55:12 +00:00
if ( flags & ( PF_VELOCITY1 < < i ) )
2006-04-11 22:15:09 +00:00
tv - > players [ num ] . current . velocity [ i ] = ReadShort ( m ) ;
else
tv - > players [ num ] . current . velocity [ i ] = 0 ;
2005-09-06 01:09:36 +00:00
}
2006-02-21 19:55:12 +00:00
2007-09-10 18:56:01 +00:00
tv - > players [ num ] . gibbed = ! ! ( flags & PF_GIB ) ;
tv - > players [ num ] . dead = ! ! ( flags & PF_DEAD ) ;
2006-02-21 19:55:12 +00:00
if ( flags & PF_MODEL )
tv - > players [ num ] . current . modelindex = ReadByte ( m ) ;
else
tv - > players [ num ] . current . modelindex = tv - > modelindex_player ;
if ( flags & PF_SKINNUM )
tv - > players [ num ] . current . skinnum = ReadByte ( m ) ;
else
tv - > players [ num ] . current . skinnum = 0 ;
if ( flags & PF_EFFECTS )
tv - > players [ num ] . current . effects = ReadByte ( m ) ;
else
tv - > players [ num ] . current . effects = 0 ;
if ( flags & PF_WEAPONFRAME )
tv - > players [ num ] . current . weaponframe = ReadByte ( m ) ;
else
tv - > players [ num ] . current . weaponframe = 0 ;
2006-04-11 22:15:09 +00:00
tv - > players [ num ] . active = true ;
2005-09-06 01:09:36 +00:00
}
2006-02-21 19:55:12 +00:00
else
{
flags = ReadShort ( m ) ;
tv - > players [ num ] . gibbed = ! ! ( flags & DF_GIB ) ;
tv - > players [ num ] . dead = ! ! ( flags & DF_DEAD ) ;
tv - > players [ num ] . current . frame = ReadByte ( m ) ;
for ( i = 0 ; i < 3 ; i + + )
{
if ( flags & ( DF_ORIGIN < < i ) )
tv - > players [ num ] . current . origin [ i ] = ReadShort ( m ) ;
}
2005-09-06 01:09:36 +00:00
2006-02-21 19:55:12 +00:00
for ( i = 0 ; i < 3 ; i + + )
{
if ( flags & ( DF_ANGLES < < i ) )
{
tv - > players [ num ] . current . angles [ i ] = ReadShort ( m ) ;
}
}
2005-09-06 01:09:36 +00:00
2006-02-21 19:55:12 +00:00
if ( flags & DF_MODEL )
tv - > players [ num ] . current . modelindex = ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
2006-02-21 19:55:12 +00:00
if ( flags & DF_SKINNUM )
tv - > players [ num ] . current . skinnum = ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
2006-02-21 19:55:12 +00:00
if ( flags & DF_EFFECTS )
tv - > players [ num ] . current . effects = ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
2006-02-21 19:55:12 +00:00
if ( flags & DF_WEAPONFRAME )
tv - > players [ num ] . current . weaponframe = ReadByte ( m ) ;
2005-09-24 04:48:20 +00:00
2006-02-21 19:55:12 +00:00
tv - > players [ num ] . active = true ;
}
2005-09-24 04:48:20 +00:00
2005-09-25 20:50:57 +00:00
tv - > players [ num ] . leafcount = BSP_SphereLeafNums ( tv - > bsp , MAX_ENTITY_LEAFS , tv - > players [ num ] . leafs ,
2005-09-24 04:48:20 +00:00
tv - > players [ num ] . current . origin [ 0 ] / 8.0f ,
tv - > players [ num ] . current . origin [ 1 ] / 8.0f ,
tv - > players [ num ] . current . origin [ 2 ] / 8.0f , 32 ) ;
2005-09-06 01:09:36 +00:00
}
2006-12-26 21:26:10 +00:00
static int readentitynum ( netmsg_t * m , unsigned int * retflags )
2005-09-06 01:09:36 +00:00
{
2006-12-26 21:26:10 +00:00
int entnum ;
unsigned int flags ;
flags = ReadShort ( m ) ;
if ( ! flags )
{
* retflags = 0 ;
return 0 ;
}
entnum = flags & 511 ;
flags & = ~ 511 ;
if ( flags & U_MOREBITS )
{
flags | = ReadByte ( m ) ;
/* if (flags & U_EVENMORE)
flags | = ReadByte ( m ) < < 16 ;
if ( flags & U_YETMORE )
flags | = ReadByte ( m ) < < 24 ;
*/ }
/* if (flags & U_ENTITYDBL)
entnum + = 512 ;
if ( flags & U_ENTITYDBL2 )
entnum + = 1024 ;
*/
* retflags = flags ;
return entnum ;
2005-09-06 01:09:36 +00:00
}
2006-12-26 21:26:10 +00:00
static void ParseEntityDelta ( sv_t * tv , netmsg_t * m , entity_state_t * old , entity_state_t * new , unsigned int flags , entity_t * ent , qboolean forcerelink )
2005-09-06 01:09:36 +00:00
{
2006-12-26 21:26:10 +00:00
memcpy ( new , old , sizeof ( entity_state_t ) ) ;
if ( flags & U_MODEL )
new - > modelindex = ReadByte ( m ) ;
if ( flags & U_FRAME )
new - > frame = ReadByte ( m ) ;
if ( flags & U_COLORMAP )
new - > colormap = ReadByte ( m ) ;
if ( flags & U_SKIN )
new - > skinnum = ReadByte ( m ) ;
if ( flags & U_EFFECTS )
new - > effects = ReadByte ( m ) ;
if ( flags & U_ORIGIN1 )
new - > origin [ 0 ] = ReadShort ( m ) ;
if ( flags & U_ANGLE1 )
new - > angles [ 0 ] = ReadByte ( m ) ;
if ( flags & U_ORIGIN2 )
new - > origin [ 1 ] = ReadShort ( m ) ;
if ( flags & U_ANGLE2 )
new - > angles [ 1 ] = ReadByte ( m ) ;
if ( flags & U_ORIGIN3 )
new - > origin [ 2 ] = ReadShort ( m ) ;
if ( flags & U_ANGLE3 )
new - > angles [ 2 ] = ReadByte ( m ) ;
if ( forcerelink | | ( flags & ( U_ORIGIN1 | U_ORIGIN2 | U_ORIGIN3 | U_MODEL ) ) )
{
ent - > leafcount =
BSP_SphereLeafNums ( tv - > bsp , MAX_ENTITY_LEAFS , ent - > leafs ,
new - > origin [ 0 ] / 8.0f ,
new - > origin [ 1 ] / 8.0f ,
new - > origin [ 2 ] / 8.0f , 32 ) ;
}
}
static int ExpandFrame ( unsigned int newmax , frame_t * frame )
{
entity_state_t * newents ;
unsigned short * newnums ;
if ( newmax < frame - > maxents )
return true ;
newmax + = 16 ;
newents = malloc ( sizeof ( * newents ) * newmax ) ;
if ( ! newents )
return false ;
newnums = malloc ( sizeof ( * newnums ) * newmax ) ;
if ( ! newnums )
{
free ( newents ) ;
return false ;
}
memcpy ( newents , frame - > ents , sizeof ( * newents ) * frame - > maxents ) ;
memcpy ( newnums , frame - > entnums , sizeof ( * newnums ) * frame - > maxents ) ;
if ( frame - > ents )
free ( frame - > ents ) ;
if ( frame - > entnums )
free ( frame - > entnums ) ;
frame - > ents = newents ;
frame - > entnums = newnums ;
frame - > maxents = newmax ;
return true ;
}
static void ParsePacketEntities ( sv_t * tv , netmsg_t * m , int deltaframe )
{
frame_t * newframe ;
frame_t * oldframe ;
int oldcount ;
int newnum , oldnum ;
int newindex , oldindex ;
unsigned int flags ;
2005-09-06 01:09:36 +00:00
viewer_t * v ;
2006-04-11 22:15:09 +00:00
tv - > nailcount = 0 ;
2005-09-24 04:48:20 +00:00
tv - > physicstime = tv - > parsetime ;
2005-10-07 02:02:15 +00:00
if ( tv - > cluster - > chokeonnotupdated )
for ( v = tv - > cluster - > viewers ; v ; v = v - > next )
2005-09-06 01:09:36 +00:00
{
2005-10-07 02:02:15 +00:00
if ( v - > server = = tv )
v - > chokeme = false ;
2005-09-06 01:09:36 +00:00
}
2007-03-03 18:46:43 +00:00
for ( v = tv - > cluster - > viewers ; v ; v = v - > next )
{
if ( v - > server = = tv & & v - > netchan . isnqprotocol )
v - > maysend = true ;
}
2005-09-06 01:09:36 +00:00
2006-12-26 21:26:10 +00:00
if ( deltaframe ! = - 1 )
deltaframe & = ( ENTITY_FRAMES - 1 ) ;
2007-07-23 10:53:59 +00:00
if ( tv - > usequakeworldprotocols )
2006-12-26 21:26:10 +00:00
{
newframe = & tv - > frame [ tv - > netchan . incoming_sequence & ( ENTITY_FRAMES - 1 ) ] ;
2007-01-09 05:24:03 +00:00
if ( tv - > netchan . outgoing_sequence - tv - > netchan . incoming_sequence > = ENTITY_FRAMES - 1 )
{
//should drop it
Sys_Printf ( tv - > cluster , " Outdated frames \n " ) ;
}
else if ( deltaframe ! = - 1 & & newframe - > oldframe ! = deltaframe )
2006-12-26 21:26:10 +00:00
Sys_Printf ( tv - > cluster , " Mismatching delta frames \n " ) ;
}
else
{
deltaframe = tv - > netchan . incoming_sequence & ( ENTITY_FRAMES - 1 ) ;
tv - > netchan . incoming_sequence + + ;
newframe = & tv - > frame [ tv - > netchan . incoming_sequence & ( ENTITY_FRAMES - 1 ) ] ;
}
if ( deltaframe ! = - 1 )
{
oldframe = & tv - > frame [ deltaframe ] ;
oldcount = oldframe - > numents ;
}
else
{
oldframe = NULL ;
oldcount = 0 ;
}
oldindex = 0 ;
newindex = 0 ;
//printf("frame\n");
for ( ; ; )
{
newnum = readentitynum ( m , & flags ) ;
if ( ! newnum )
{
//end of packet
//any remaining old ents need to be copied to the new frame
while ( oldindex < oldcount )
{
//printf("Propogate (spare)\n");
if ( ! ExpandFrame ( newindex , newframe ) )
break ;
memcpy ( & newframe - > ents [ newindex ] , & oldframe - > ents [ oldindex ] , sizeof ( entity_state_t ) ) ;
newframe - > entnums [ newindex ] = oldframe - > entnums [ oldindex ] ;
newindex + + ;
oldindex + + ;
}
break ;
}
if ( oldindex > = oldcount )
oldnum = 0xffff ;
else
oldnum = oldframe - > entnums [ oldindex ] ;
while ( newnum > oldnum )
{
//printf("Propogate (unchanged)\n");
if ( ! ExpandFrame ( newindex , newframe ) )
break ;
memcpy ( & newframe - > ents [ newindex ] , & oldframe - > ents [ oldindex ] , sizeof ( entity_state_t ) ) ;
newframe - > entnums [ newindex ] = oldframe - > entnums [ oldindex ] ;
newindex + + ;
oldindex + + ;
if ( oldindex > = oldcount )
oldnum = 0xffff ;
else
oldnum = oldframe - > entnums [ oldindex ] ;
}
if ( newnum < oldnum )
{ //this ent wasn't in the last packet
//printf("add\n");
if ( flags & U_REMOVE )
{ //remove this ent... just don't copy it across.
//printf("add\n");
continue ;
}
if ( ! ExpandFrame ( newindex , newframe ) )
break ;
ParseEntityDelta ( tv , m , & tv - > entity [ newnum ] . baseline , & newframe - > ents [ newindex ] , flags , & tv - > entity [ newnum ] , true ) ;
newframe - > entnums [ newindex ] = newnum ;
newindex + + ;
}
else if ( newnum = = oldnum )
{
if ( flags & U_REMOVE )
{ //remove this ent... just don't copy it across.
//printf("add\n");
oldindex + + ;
continue ;
}
//printf("Propogate (changed)\n");
if ( ! ExpandFrame ( newindex , newframe ) )
break ;
ParseEntityDelta ( tv , m , & oldframe - > ents [ oldindex ] , & newframe - > ents [ newindex ] , flags , & tv - > entity [ newnum ] , false ) ;
newframe - > entnums [ newindex ] = newnum ;
newindex + + ;
oldindex + + ;
}
}
newframe - > numents = newindex ;
return ;
/*
2005-09-06 01:09:36 +00:00
//luckilly, only updated entities are here, so that keeps cpu time down a bit.
for ( ; ; )
{
flags = ReadShort ( m ) ;
if ( ! flags )
break ;
entnum = flags & 511 ;
if ( tv - > maxents < entnum )
tv - > maxents = entnum ;
flags & = ~ 511 ;
2005-09-24 04:48:20 +00:00
memcpy ( & tv - > entity [ entnum ] . old , & tv - > entity [ entnum ] . current , sizeof ( entity_state_t ) ) ; //ow.
2005-09-06 01:09:36 +00:00
if ( flags & U_REMOVE )
{
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . modelindex = 0 ;
2005-09-06 01:09:36 +00:00
continue ;
}
2005-09-24 04:48:20 +00:00
if ( ! tv - > entity [ entnum ] . current . modelindex ) //lerp from baseline
{
memcpy ( & tv - > entity [ entnum ] . current , & tv - > entity [ entnum ] . baseline , sizeof ( entity_state_t ) ) ;
forcerelink = true ;
}
else
forcerelink = false ;
2005-09-06 01:09:36 +00:00
if ( flags & U_MOREBITS )
flags | = ReadByte ( m ) ;
if ( flags & U_MODEL )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . modelindex = ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
if ( flags & U_FRAME )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . frame = ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
if ( flags & U_COLORMAP )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . colormap = ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
if ( flags & U_SKIN )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . skinnum = ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
if ( flags & U_EFFECTS )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . effects = ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
if ( flags & U_ORIGIN1 )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . origin [ 0 ] = ReadShort ( m ) ;
2005-09-06 01:09:36 +00:00
if ( flags & U_ANGLE1 )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . angles [ 0 ] = ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
if ( flags & U_ORIGIN2 )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . origin [ 1 ] = ReadShort ( m ) ;
2005-09-06 01:09:36 +00:00
if ( flags & U_ANGLE2 )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . angles [ 1 ] = ReadByte ( m ) ;
2005-09-06 01:09:36 +00:00
if ( flags & U_ORIGIN3 )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . origin [ 2 ] = ReadShort ( m ) ;
2005-09-06 01:09:36 +00:00
if ( flags & U_ANGLE3 )
2005-09-24 04:48:20 +00:00
tv - > entity [ entnum ] . current . angles [ 2 ] = ReadByte ( m ) ;
tv - > entity [ entnum ] . updatetime = tv - > curtime ;
if ( ! tv - > entity [ entnum ] . old . modelindex ) //no old state
memcpy ( & tv - > entity [ entnum ] . old , & tv - > entity [ entnum ] . current , sizeof ( entity_state_t ) ) ; //copy the new to the old, so we don't end up with interpolation glitches
2005-09-06 01:09:36 +00:00
2005-09-24 04:48:20 +00:00
if ( ( flags & ( U_ORIGIN1 | U_ORIGIN2 | U_ORIGIN3 ) ) | | forcerelink )
tv - > entity [ entnum ] . leafcount = BSP_SphereLeafNums ( tv - > bsp , MAX_ENTITY_LEAFS , tv - > entity [ entnum ] . leafs ,
tv - > entity [ entnum ] . current . origin [ 0 ] / 8.0f ,
tv - > entity [ entnum ] . current . origin [ 1 ] / 8.0f ,
tv - > entity [ entnum ] . current . origin [ 2 ] / 8.0f , 32 ) ;
2005-09-06 01:09:36 +00:00
}
2006-12-26 21:26:10 +00:00
*/
2005-09-06 01:09:36 +00:00
}
static void ParseUpdatePing ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
int pnum ;
int ping ;
pnum = ReadByte ( m ) ;
ping = ReadShort ( m ) ;
2005-09-24 21:31:01 +00:00
if ( pnum < MAX_CLIENTS )
tv - > players [ pnum ] . ping = ping ;
else
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " svc_updateping: invalid player number \n " ) ;
2005-09-06 01:09:36 +00:00
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , QW ) ;
2005-09-06 01:09:36 +00:00
}
static void ParseUpdateFrags ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
int pnum ;
int frags ;
pnum = ReadByte ( m ) ;
2006-04-11 22:15:09 +00:00
frags = ( signed short ) ReadShort ( m ) ;
2005-09-06 01:09:36 +00:00
2005-09-24 21:31:01 +00:00
if ( pnum < MAX_CLIENTS )
tv - > players [ pnum ] . frags = frags ;
else
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " svc_updatefrags: invalid player number \n " ) ;
2005-09-06 01:09:36 +00:00
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , ( pnum < 16 ) ? Q1 : QW ) ;
2005-09-06 01:09:36 +00:00
}
static void ParseUpdateStat ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
unsigned int pnum ;
int value ;
int statnum ;
statnum = ReadByte ( m ) ;
value = ReadByte ( m ) ;
2005-09-24 21:31:01 +00:00
if ( statnum < MAX_STATS )
2005-09-06 01:09:36 +00:00
{
2005-09-24 21:31:01 +00:00
for ( pnum = 0 ; pnum < MAX_CLIENTS ; pnum + + )
{
if ( mask & ( 1 < < pnum ) )
tv - > players [ pnum ] . stats [ statnum ] = value ;
}
2005-09-06 01:09:36 +00:00
}
2005-09-24 21:31:01 +00:00
else
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " svc_updatestat: invalid stat number \n " ) ;
2005-09-06 01:09:36 +00:00
2007-08-03 14:10:47 +00:00
// Multicast(tv, (char*)m->data+m->startpos, m->readpos - m->startpos, to, mask, QW);
2005-09-06 01:09:36 +00:00
}
static void ParseUpdateStatLong ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
unsigned int pnum ;
int value ;
int statnum ;
statnum = ReadByte ( m ) ;
value = ReadLong ( m ) ;
2005-09-24 21:31:01 +00:00
if ( statnum < MAX_STATS )
2005-09-06 01:09:36 +00:00
{
2005-09-24 21:31:01 +00:00
for ( pnum = 0 ; pnum < MAX_CLIENTS ; pnum + + )
{
if ( mask & ( 1 < < pnum ) )
tv - > players [ pnum ] . stats [ statnum ] = value ;
}
2005-09-06 01:09:36 +00:00
}
2005-09-24 21:31:01 +00:00
else
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " svc_updatestatlong: invalid stat number \n " ) ;
2005-09-06 01:09:36 +00:00
2007-08-03 14:10:47 +00:00
// Multicast(tv, (char*)m->data+m->startpos, m->readpos - m->startpos, to, mask, QW);
2005-09-06 01:09:36 +00:00
}
2006-02-21 19:55:12 +00:00
static void ParseUpdateUserinfo ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
2005-09-06 01:09:36 +00:00
{
int pnum ;
pnum = ReadByte ( m ) ;
ReadLong ( m ) ;
2005-09-24 21:31:01 +00:00
if ( pnum < MAX_CLIENTS )
ReadString ( m , tv - > players [ pnum ] . userinfo , sizeof ( tv - > players [ pnum ] . userinfo ) ) ;
else
{
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " svc_updateuserinfo: invalid player number \n " ) ;
2005-09-24 21:31:01 +00:00
while ( ReadByte ( m ) ) //suck out the message.
{
}
}
2006-02-21 19:55:12 +00:00
2007-09-10 19:27:39 +00:00
ConnectionData ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , QW ) ;
2005-09-06 01:09:36 +00:00
}
static void ParsePacketloss ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
unsigned int pnum ;
int value ;
pnum = ReadByte ( m ) % MAX_CLIENTS ;
value = ReadByte ( m ) ;
2005-09-24 21:31:01 +00:00
if ( pnum < MAX_CLIENTS )
tv - > players [ pnum ] . packetloss = value ;
else
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " svc_updatepl: invalid player number \n " ) ;
2005-09-06 01:09:36 +00:00
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , QW ) ;
2005-09-06 01:09:36 +00:00
}
static void ParseUpdateEnterTime ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
unsigned int pnum ;
float value ;
pnum = ReadByte ( m ) % MAX_CLIENTS ;
value = ReadFloat ( m ) ;
2005-09-24 21:31:01 +00:00
if ( pnum < MAX_CLIENTS )
tv - > players [ pnum ] . entertime = value ;
else
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " svc_updateentertime: invalid player number \n " ) ;
2005-09-06 01:09:36 +00:00
2007-09-10 19:27:39 +00:00
ConnectionData ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , QW ) ;
2005-09-06 01:09:36 +00:00
}
static void ParseSound ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
# define SND_VOLUME (1<<15) // a qbyte
# define SND_ATTENUATION (1<<14) // a qbyte
# define DEFAULT_SOUND_PACKET_VOLUME 255
# define DEFAULT_SOUND_PACKET_ATTENUATION 1.0
int i ;
2006-09-19 01:48:12 +00:00
int channel ;
2005-09-06 01:09:36 +00:00
unsigned char vol ;
unsigned char atten ;
unsigned char sound_num ;
short org [ 3 ] ;
2006-09-19 01:48:12 +00:00
int ent ;
unsigned char nqversion [ 64 ] ;
int nqlen = 0 ;
channel = ( unsigned short ) ReadShort ( m ) ;
2005-09-06 01:09:36 +00:00
2006-09-19 01:48:12 +00:00
if ( channel & SND_VOLUME )
2005-09-06 01:09:36 +00:00
vol = ReadByte ( m ) ;
else
vol = DEFAULT_SOUND_PACKET_VOLUME ;
2005-09-25 20:50:57 +00:00
2006-09-19 01:48:12 +00:00
if ( channel & SND_ATTENUATION )
2005-09-06 01:09:36 +00:00
atten = ReadByte ( m ) / 64.0 ;
else
atten = DEFAULT_SOUND_PACKET_ATTENUATION ;
2005-09-25 20:50:57 +00:00
2005-09-06 01:09:36 +00:00
sound_num = ReadByte ( m ) ;
2006-09-19 01:48:12 +00:00
ent = ( channel > > 3 ) & 1023 ;
channel & = 7 ;
2005-09-06 01:09:36 +00:00
for ( i = 0 ; i < 3 ; i + + )
org [ i ] = ReadShort ( m ) ;
2005-09-25 20:50:57 +00:00
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , QW ) ;
2006-09-19 01:48:12 +00:00
nqversion [ 0 ] = svc_sound ;
nqversion [ 1 ] = 0 ;
if ( vol ! = DEFAULT_SOUND_PACKET_VOLUME )
nqversion [ 1 ] | = 1 ;
if ( atten ! = DEFAULT_SOUND_PACKET_ATTENUATION )
nqversion [ 1 ] | = 2 ;
nqlen = 2 ;
if ( nqversion [ 1 ] & 1 )
nqversion [ nqlen + + ] = vol ;
if ( nqversion [ 1 ] & 2 )
nqversion [ nqlen + + ] = atten * 64 ;
channel = ( ent < < 3 ) | channel ;
nqversion [ nqlen + + ] = ( channel & 0x00ff ) > > 0 ;
nqversion [ nqlen + + ] = ( channel & 0xff00 ) > > 8 ;
nqversion [ nqlen + + ] = sound_num ;
nqversion [ nqlen + + ] = 0 ;
nqversion [ nqlen + + ] = 0 ;
nqversion [ nqlen + + ] = 0 ;
nqversion [ nqlen + + ] = 0 ;
nqversion [ nqlen + + ] = 0 ;
nqversion [ nqlen + + ] = 0 ;
Multicast ( tv , nqversion , nqlen , to , mask , NQ ) ;
2005-09-06 01:09:36 +00:00
}
static void ParseDamage ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
ReadByte ( m ) ;
ReadByte ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , QW ) ;
2005-09-06 01:09:36 +00:00
}
enum {
TE_SPIKE = 0 ,
TE_SUPERSPIKE = 1 ,
TE_GUNSHOT = 2 ,
TE_EXPLOSION = 3 ,
TE_TAREXPLOSION = 4 ,
TE_LIGHTNING1 = 5 ,
TE_LIGHTNING2 = 6 ,
TE_WIZSPIKE = 7 ,
TE_KNIGHTSPIKE = 8 ,
TE_LIGHTNING3 = 9 ,
TE_LAVASPLASH = 10 ,
TE_TELEPORT = 11 ,
TE_BLOOD = 12 ,
TE_LIGHTNINGBLOOD = 13 ,
} ;
static void ParseTempEntity ( sv_t * tv , netmsg_t * m , int to , unsigned int mask )
{
int i ;
2006-09-19 01:48:12 +00:00
int dest = QW ;
char nqversion [ 64 ] ;
int nqversionlength = 0 ;
2005-09-06 01:09:36 +00:00
i = ReadByte ( m ) ;
switch ( i )
{
case TE_SPIKE :
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
2006-09-19 01:48:12 +00:00
dest | = NQ ;
2005-09-06 01:09:36 +00:00
break ;
case TE_SUPERSPIKE :
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
2006-09-19 01:48:12 +00:00
dest | = NQ ;
2005-09-06 01:09:36 +00:00
break ;
case TE_GUNSHOT :
ReadByte ( m ) ;
2006-09-19 01:48:12 +00:00
nqversion [ 0 ] = svc_temp_entity ;
nqversion [ 1 ] = TE_GUNSHOT ;
nqversion [ 2 ] = ReadByte ( m ) ; nqversion [ 3 ] = ReadByte ( m ) ;
nqversion [ 4 ] = ReadByte ( m ) ; nqversion [ 5 ] = ReadByte ( m ) ;
nqversion [ 6 ] = ReadByte ( m ) ; nqversion [ 7 ] = ReadByte ( m ) ;
nqversionlength = 8 ;
2005-09-06 01:09:36 +00:00
break ;
case TE_EXPLOSION :
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
2006-09-19 01:48:12 +00:00
dest | = NQ ;
2005-09-06 01:09:36 +00:00
break ;
case TE_TAREXPLOSION :
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
2006-09-19 01:48:12 +00:00
dest | = NQ ;
2005-09-06 01:09:36 +00:00
break ;
case TE_LIGHTNING1 :
case TE_LIGHTNING2 :
case TE_LIGHTNING3 :
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
2006-09-19 01:48:12 +00:00
dest | = NQ ;
2005-09-06 01:09:36 +00:00
break ;
case TE_WIZSPIKE :
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
2006-09-19 01:48:12 +00:00
dest | = NQ ;
2005-09-06 01:09:36 +00:00
break ;
case TE_KNIGHTSPIKE :
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
2006-09-19 01:48:12 +00:00
dest | = NQ ;
2005-09-06 01:09:36 +00:00
break ;
case TE_LAVASPLASH :
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
2006-09-19 01:48:12 +00:00
dest | = NQ ;
2005-09-06 01:09:36 +00:00
break ;
case TE_TELEPORT :
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
2006-09-19 01:48:12 +00:00
dest | = NQ ;
2005-09-06 01:09:36 +00:00
break ;
case TE_BLOOD :
ReadByte ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
break ;
case TE_LIGHTNINGBLOOD :
ReadShort ( m ) ;
ReadShort ( m ) ;
ReadShort ( m ) ;
break ;
default :
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " temp entity %i not recognised \n " , i ) ;
2005-09-06 01:09:36 +00:00
return ;
}
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , to , mask , dest ) ;
2006-09-19 01:48:12 +00:00
if ( nqversionlength )
Multicast ( tv , nqversion , nqversionlength , to , mask , NQ ) ;
2005-09-06 01:09:36 +00:00
}
void ParseLightstyle ( sv_t * tv , netmsg_t * m )
{
int style ;
style = ReadByte ( m ) ;
2005-09-24 21:31:01 +00:00
if ( style < MAX_LIGHTSTYLES )
ReadString ( m , tv - > lightstyle [ style ] . name , sizeof ( tv - > lightstyle [ style ] . name ) ) ;
else
{
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " svc_lightstyle: invalid lightstyle index (%i) \n " , style ) ;
2005-09-24 21:31:01 +00:00
while ( ReadByte ( m ) ) //suck out the message.
{
}
}
2005-09-06 01:09:36 +00:00
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) m - > data + m - > startpos , m - > readpos - m - > startpos , dem_read , ( unsigned ) - 1 , Q1 ) ;
2005-09-06 01:09:36 +00:00
}
2006-02-21 23:25:54 +00:00
void ParseNails ( sv_t * tv , netmsg_t * m , qboolean nails2 )
2006-02-20 01:33:13 +00:00
{
int count ;
int i ;
count = ( unsigned char ) ReadByte ( m ) ;
2006-04-11 22:15:09 +00:00
while ( count > sizeof ( tv - > nails ) / sizeof ( tv - > nails [ 0 ] ) )
2007-07-23 10:53:59 +00:00
{ //they sent too many, suck it out.
2006-04-11 22:15:09 +00:00
count - - ;
if ( nails2 )
ReadByte ( m ) ;
for ( i = 0 ; i < 6 ; i + + )
ReadByte ( m ) ;
}
tv - > nailcount = count ;
2006-02-20 01:33:13 +00:00
while ( count - - > 0 )
{
2006-02-21 23:25:54 +00:00
if ( nails2 )
2006-04-11 22:15:09 +00:00
tv - > nails [ count ] . number = ReadByte ( m ) ;
2006-02-21 23:25:54 +00:00
else
2006-04-11 22:15:09 +00:00
tv - > nails [ count ] . number = count ;
2006-02-20 01:33:13 +00:00
for ( i = 0 ; i < 6 ; i + + )
2006-04-11 22:15:09 +00:00
tv - > nails [ count ] . bits [ i ] = ReadByte ( m ) ;
}
}
void ParseDownload ( sv_t * tv , netmsg_t * m )
{
2008-02-01 06:13:30 +00:00
//warning this needs looking at (controller downloads)
2006-04-11 22:15:09 +00:00
int size , b ;
unsigned int percent ;
char buffer [ 2048 ] ;
2006-10-22 19:18:15 +00:00
size = ( signed short ) ReadShort ( m ) ;
2006-04-11 22:15:09 +00:00
percent = ReadByte ( m ) ;
if ( size < 0 )
{
Sys_Printf ( tv - > cluster , " Downloading failed \n " ) ;
2006-10-22 19:18:15 +00:00
if ( tv - > downloadfile )
fclose ( tv - > downloadfile ) ;
tv - > downloadfile = NULL ;
2007-12-12 11:17:18 +00:00
tv - > errored = ERR_PERMANENT ;
2007-01-08 03:15:37 +00:00
QW_StreamPrint ( tv - > cluster , tv , NULL , " Map download failed \n " ) ;
2006-04-11 22:15:09 +00:00
return ;
}
for ( b = 0 ; b < size ; b + + )
buffer [ b ] = ReadByte ( m ) ;
2006-10-22 19:18:15 +00:00
if ( ! tv - > downloadfile )
2006-04-11 22:15:09 +00:00
{
Sys_Printf ( tv - > cluster , " Not downloading anything \n " ) ;
2007-12-12 11:17:18 +00:00
tv - > errored = ERR_PERMANENT ;
2006-04-11 22:15:09 +00:00
return ;
}
2006-10-22 19:18:15 +00:00
fwrite ( buffer , 1 , size , tv - > downloadfile ) ;
2006-04-11 22:15:09 +00:00
if ( percent = = 100 )
{
2006-10-22 19:18:15 +00:00
fclose ( tv - > downloadfile ) ;
tv - > downloadfile = NULL ;
2006-09-17 01:27:32 +00:00
snprintf ( buffer , sizeof ( buffer ) , " %s/%s " , ( tv - > gamedir & & * tv - > gamedir ) ? tv - > gamedir : " id1 " , tv - > modellist [ 1 ] . name ) ;
rename ( tv - > downloadname , buffer ) ;
2006-04-11 22:15:09 +00:00
Sys_Printf ( tv - > cluster , " Download complete \n " ) ;
tv - > bsp = BSP_LoadModel ( tv - > cluster , tv - > gamedir , tv - > modellist [ 1 ] . name ) ;
if ( ! tv - > bsp )
2006-10-22 19:18:15 +00:00
{
Sys_Printf ( tv - > cluster , " Failed to read BSP \n " ) ;
2007-12-12 11:17:18 +00:00
tv - > errored = ERR_PERMANENT ;
2006-10-22 19:18:15 +00:00
}
2006-04-11 22:15:09 +00:00
else
{
SendClientCommand ( tv , " prespawn %i 0 %i \n " , tv - > clservercount , LittleLong ( BSP_Checksum ( tv - > bsp ) ) ) ;
strcpy ( tv - > status , " Prespawning \n " ) ;
}
}
else
{
snprintf ( tv - > status , sizeof ( tv - > status ) , " Downloading map, %i%% \n " , percent ) ;
SendClientCommand ( tv , " nextdl \n " ) ;
2006-02-20 01:33:13 +00:00
}
}
2007-07-23 10:53:59 +00:00
void ParseMessage ( sv_t * tv , void * buffer , int length , int to , int mask )
2005-09-06 01:09:36 +00:00
{
2006-02-21 19:55:12 +00:00
int i ;
2005-09-06 01:09:36 +00:00
netmsg_t buf ;
2005-10-07 02:02:15 +00:00
qboolean clearoldplayers = true ;
2005-09-06 01:09:36 +00:00
buf . cursize = length ;
buf . maxsize = length ;
buf . readpos = 0 ;
buf . data = buffer ;
buf . startpos = 0 ;
while ( buf . readpos < buf . cursize )
{
if ( buf . readpos > buf . cursize )
{
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " Read past end of parse buffer \n " ) ;
2005-09-06 01:09:36 +00:00
return ;
}
// printf("%i\n", buf.buffer[0]);
buf . startpos = buf . readpos ;
switch ( ReadByte ( & buf ) )
{
case svc_bad :
ParseError ( & buf ) ;
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " ParseMessage: svc_bad \n " ) ;
2005-09-06 01:09:36 +00:00
return ;
case svc_nop : //quakeworld isn't meant to send these.
2007-05-28 02:31:48 +00:00
QTV_Printf ( tv , " nop \n " ) ;
2005-09-06 01:09:36 +00:00
break ;
2005-09-24 04:48:20 +00:00
case svc_disconnect :
2005-09-24 21:31:01 +00:00
//mvdsv safely terminates it's mvds with an svc_disconnect.
//the client is meant to read that and disconnect without reading the intentionally corrupt packet following it.
//however, our demo playback is chained and looping and buffered.
//so we've already found the end of the source file and restarted parsing.
2007-07-23 10:53:59 +00:00
//in fte at least, the server does give the packet the correct length
//I hope mvdsv is the same
if ( tv - > sourcetype ! = SRC_DEMO )
2007-10-31 19:59:40 +00:00
{
# ifndef _MSC_VER
# warning QTV is meant to disconnect when servers tells it to.
# endif
// FIXME: Servers are today sending the svc_disconnect in a non-standard way, which makes QTV drop when it shouldn't.
// Tell the server developers to fix the servers.
//tv->drop = true;
}
2007-07-23 10:53:59 +00:00
else
{
while ( ReadByte ( & buf ) )
;
}
2005-09-24 21:31:01 +00:00
return ;
2005-09-06 01:09:36 +00:00
case svc_updatestat :
ParseUpdateStat ( tv , & buf , to , mask ) ;
break ;
//#define svc_version 4 // [long] server version
2007-07-23 10:53:59 +00:00
case svc_nqsetview :
ReadShort ( & buf ) ;
//no actual handling is done!
break ;
2005-09-06 01:09:36 +00:00
case svc_sound :
ParseSound ( tv , & buf , to , mask ) ;
break ;
2007-07-23 10:53:59 +00:00
case svc_nqtime :
ReadFloat ( & buf ) ;
//no actual handling is done!
break ;
2006-09-17 01:27:32 +00:00
2005-09-06 01:09:36 +00:00
case svc_print :
ParsePrint ( tv , & buf , to , mask ) ;
break ;
case svc_stufftext :
ParseStufftext ( tv , & buf , to , mask ) ;
break ;
case svc_setangle :
2007-07-23 10:53:59 +00:00
if ( ! tv - > usequakeworldprotocols )
2006-04-11 22:15:09 +00:00
ReadByte ( & buf ) ;
2006-09-17 01:27:32 +00:00
tv - > proxyplayerangles [ 0 ] = ReadByte ( & buf ) * 360.0 / 255 ;
tv - > proxyplayerangles [ 1 ] = ReadByte ( & buf ) * 360.0 / 255 ;
tv - > proxyplayerangles [ 2 ] = ReadByte ( & buf ) * 360.0 / 255 ;
2006-04-11 22:15:09 +00:00
2007-07-23 10:53:59 +00:00
if ( tv - > usequakeworldprotocols & & tv - > controller )
2007-08-03 14:10:47 +00:00
SendBufferToViewer ( tv - > controller , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , true ) ;
2006-09-17 01:27:32 +00:00
{
char nq [ 4 ] ;
nq [ 0 ] = svc_setangle ;
nq [ 1 ] = tv - > proxyplayerangles [ 0 ] ;
nq [ 2 ] = tv - > proxyplayerangles [ 1 ] ;
nq [ 3 ] = tv - > proxyplayerangles [ 2 ] ;
2006-09-19 01:48:12 +00:00
// Multicast(tv, nq, 4, to, mask, Q1);
2006-09-17 01:27:32 +00:00
}
2005-09-06 01:09:36 +00:00
break ;
case svc_serverdata :
ParseServerData ( tv , & buf , to , mask ) ;
break ;
case svc_lightstyle :
ParseLightstyle ( tv , & buf ) ;
break ;
//#define svc_updatename 13 // [qbyte] [string]
2006-09-17 01:27:32 +00:00
2005-09-06 01:09:36 +00:00
case svc_updatefrags :
ParseUpdateFrags ( tv , & buf , to , mask ) ;
break ;
2006-09-17 01:27:32 +00:00
2005-09-06 01:09:36 +00:00
//#define svc_clientdata 15 // <shortbits + data>
//#define svc_stopsound 16 // <see code>
//#define svc_updatecolors 17 // [qbyte] [qbyte] [qbyte]
2006-04-11 22:15:09 +00:00
case svc_particle :
ReadShort ( & buf ) ;
ReadShort ( & buf ) ;
ReadShort ( & buf ) ;
ReadByte ( & buf ) ;
ReadByte ( & buf ) ;
ReadByte ( & buf ) ;
ReadByte ( & buf ) ;
ReadByte ( & buf ) ;
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , dem_read , ( unsigned ) - 1 , Q1 ) ;
2006-04-11 22:15:09 +00:00
break ;
2006-09-17 01:27:32 +00:00
2005-09-06 01:09:36 +00:00
case svc_damage :
ParseDamage ( tv , & buf , to , mask ) ;
break ;
2005-09-25 20:50:57 +00:00
2005-09-24 04:48:20 +00:00
case svc_spawnstatic :
ParseSpawnStatic ( tv , & buf , to , mask ) ;
break ;
2005-09-06 01:09:36 +00:00
//#define svc_spawnstatic2 21
case svc_spawnbaseline :
ParseBaseline ( tv , & buf , to , mask ) ;
break ;
2005-09-25 20:50:57 +00:00
2005-09-06 01:09:36 +00:00
case svc_temp_entity :
ParseTempEntity ( tv , & buf , to , mask ) ;
break ;
2006-02-21 23:25:54 +00:00
case svc_setpause : // [qbyte] on / off
tv - > ispaused = ReadByte ( & buf ) ;
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , dem_read , ( unsigned ) - 1 , Q1 ) ;
2006-02-21 23:25:54 +00:00
break ;
2005-09-06 01:09:36 +00:00
//#define svc_signonnum 25 // [qbyte] used for the signon sequence
case svc_centerprint :
ParseCenterprint ( tv , & buf , to , mask ) ;
break ;
case svc_spawnstaticsound :
ParseStaticSound ( tv , & buf , to , mask ) ;
break ;
2005-09-24 04:48:20 +00:00
case svc_intermission :
ParseIntermission ( tv , & buf , to , mask ) ;
break ;
2007-07-23 10:53:59 +00:00
case svc_finale :
while ( ReadByte ( & buf ) )
;
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , dem_read , ( unsigned ) - 1 , Q1 ) ;
2007-07-23 10:53:59 +00:00
break ;
2005-09-06 01:09:36 +00:00
case svc_cdtrack :
ParseCDTrack ( tv , & buf , to , mask ) ;
break ;
2006-09-17 01:27:32 +00:00
2007-07-23 10:53:59 +00:00
case svc_sellscreen :
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , dem_read , ( unsigned ) - 1 , Q1 ) ;
2007-07-23 10:53:59 +00:00
break ;
2005-09-06 01:09:36 +00:00
//#define svc_cutscene 34 //hmm... nq only... added after qw tree splitt?
case svc_smallkick :
case svc_bigkick :
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , to , mask , QW ) ;
2005-09-06 01:09:36 +00:00
break ;
case svc_updateping :
ParseUpdatePing ( tv , & buf , to , mask ) ;
break ;
case svc_updateentertime :
ParseUpdateEnterTime ( tv , & buf , to , mask ) ;
break ;
case svc_updatestatlong :
ParseUpdateStatLong ( tv , & buf , to , mask ) ;
break ;
case svc_muzzleflash :
ReadShort ( & buf ) ;
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , to , mask , QW ) ;
2005-09-06 01:09:36 +00:00
break ;
case svc_updateuserinfo :
2006-02-21 19:55:12 +00:00
ParseUpdateUserinfo ( tv , & buf , to , mask ) ;
2005-09-06 01:09:36 +00:00
break ;
2006-04-11 22:15:09 +00:00
case svc_download : // [short] size [size bytes]
ParseDownload ( tv , & buf ) ;
break ;
2006-09-17 01:27:32 +00:00
2005-09-06 01:09:36 +00:00
case svc_playerinfo :
2005-10-07 02:02:15 +00:00
ParsePlayerInfo ( tv , & buf , clearoldplayers ) ;
clearoldplayers = false ;
2005-09-06 01:09:36 +00:00
break ;
2006-09-17 01:27:32 +00:00
2006-02-21 23:25:54 +00:00
case svc_nails :
ParseNails ( tv , & buf , false ) ;
break ;
2005-09-06 01:09:36 +00:00
case svc_chokecount :
ReadByte ( & buf ) ;
break ;
2006-09-17 01:27:32 +00:00
2005-09-06 01:09:36 +00:00
case svc_modellist :
2006-02-21 19:55:12 +00:00
i = ParseList ( tv , & buf , tv - > modellist , to , mask ) ;
if ( ! i )
2005-09-24 04:48:20 +00:00
{
2006-02-21 19:55:12 +00:00
int j ;
2005-09-24 04:48:20 +00:00
if ( tv - > bsp )
BSP_Free ( tv - > bsp ) ;
2007-01-06 09:46:32 +00:00
if ( tv - > cluster - > nobsp ) // || !tv->usequkeworldprotocols)
2005-09-24 04:48:20 +00:00
tv - > bsp = NULL ;
else
2005-10-07 02:02:15 +00:00
tv - > bsp = BSP_LoadModel ( tv - > cluster , tv - > gamedir , tv - > modellist [ 1 ] . name ) ;
2005-09-24 04:48:20 +00:00
tv - > numinlines = 0 ;
2006-02-21 19:55:12 +00:00
for ( j = 2 ; j < 256 ; j + + )
2005-09-24 04:48:20 +00:00
{
2006-02-21 19:55:12 +00:00
if ( * tv - > modellist [ j ] . name ! = ' * ' )
2005-09-24 04:48:20 +00:00
break ;
2006-02-21 19:55:12 +00:00
tv - > numinlines = j ;
2005-09-24 04:48:20 +00:00
}
2008-11-09 23:10:28 +00:00
tv - > modelindex_player = 0 ;
tv - > modelindex_spike = 0 ;
for ( j = 2 ; j < 256 ; j + + )
{
if ( ! * tv - > modellist [ j ] . name )
break ;
if ( ! strcmp ( tv - > modellist [ j ] . name , " progs/player.mdl " ) )
tv - > modelindex_player = j ;
if ( ! strcmp ( tv - > modellist [ j ] . name , " progs/spike.mdl " ) )
tv - > modelindex_spike = j ;
}
2006-04-11 22:15:09 +00:00
strcpy ( tv - > status , " Prespawning \n " ) ;
2005-09-24 04:48:20 +00:00
}
2007-09-08 20:15:59 +00:00
ConnectionData ( tv , ( void * ) ( ( char * ) buf . data + buf . startpos ) , buf . readpos - buf . startpos , to , mask , QW ) ;
if ( tv - > usequakeworldprotocols & & ! tv - > controller )
2006-02-21 19:55:12 +00:00
{
if ( i )
SendClientCommand ( tv , " modellist %i %i \n " , tv - > clservercount , i ) ;
2006-10-22 19:18:15 +00:00
else if ( ! tv - > bsp & & ! tv - > cluster - > nobsp )
2006-04-11 22:15:09 +00:00
{
2006-10-22 19:18:15 +00:00
if ( tv - > downloadfile )
2006-04-11 22:15:09 +00:00
{
2006-10-22 19:18:15 +00:00
fclose ( tv - > downloadfile ) ;
2006-06-10 22:36:05 +00:00
unlink ( tv - > downloadname ) ;
2006-09-17 01:27:32 +00:00
Sys_Printf ( tv - > cluster , " Was already downloading %s \n Old download canceled \n " , tv - > downloadname ) ;
2006-10-22 19:18:15 +00:00
tv - > downloadfile = NULL ;
2006-04-11 22:15:09 +00:00
}
2006-09-17 01:27:32 +00:00
snprintf ( tv - > downloadname , sizeof ( tv - > downloadname ) , " %s/%s.tmp " , ( tv - > gamedir & & * tv - > gamedir ) ? tv - > gamedir : " id1 " , tv - > modellist [ 1 ] . name ) ;
2006-10-22 19:18:15 +00:00
tv - > downloadfile = fopen ( tv - > downloadname , " wb " ) ;
if ( ! tv - > downloadfile )
{
Sys_Printf ( tv - > cluster , " Couldn't open temporary file %s \n " , tv - > downloadname ) ;
}
2006-04-11 22:15:09 +00:00
else
{
strcpy ( tv - > status , " Downloading map \n " ) ;
Sys_Printf ( tv - > cluster , " Attempting download of %s \n " , tv - > downloadname ) ;
SendClientCommand ( tv , " download %s \n " , tv - > modellist [ 1 ] . name ) ;
2007-01-08 04:18:41 +00:00
QW_StreamPrint ( tv - > cluster , tv , NULL , " [QTV] Attempting map download \n " ) ;
2006-04-11 22:15:09 +00:00
}
}
2006-02-21 19:55:12 +00:00
else
2006-04-11 22:15:09 +00:00
{
2006-02-22 02:38:48 +00:00
SendClientCommand ( tv , " prespawn %i 0 %i \n " , tv - > clservercount , LittleLong ( BSP_Checksum ( tv - > bsp ) ) ) ;
2006-04-11 22:15:09 +00:00
}
2006-02-21 19:55:12 +00:00
}
2005-09-06 01:09:36 +00:00
break ;
case svc_soundlist :
2006-02-21 19:55:12 +00:00
i = ParseList ( tv , & buf , tv - > soundlist , to , mask ) ;
2006-04-11 22:15:09 +00:00
if ( ! i )
strcpy ( tv - > status , " Receiving modellist \n " ) ;
2007-09-08 20:15:59 +00:00
ConnectionData ( tv , ( void * ) ( ( char * ) buf . data + buf . startpos ) , buf . readpos - buf . startpos , to , mask , QW ) ;
if ( tv - > usequakeworldprotocols & & ! tv - > controller )
2006-02-21 19:55:12 +00:00
{
if ( i )
SendClientCommand ( tv , " soundlist %i %i \n " , tv - > clservercount , i ) ;
else
SendClientCommand ( tv , " modellist %i 0 \n " , tv - > clservercount ) ;
}
2005-09-06 01:09:36 +00:00
break ;
2006-09-17 01:27:32 +00:00
2005-09-06 01:09:36 +00:00
case svc_packetentities :
2006-12-26 21:26:10 +00:00
// FlushPacketEntities(tv);
ParsePacketEntities ( tv , & buf , - 1 ) ;
2005-09-06 01:09:36 +00:00
break ;
case svc_deltapacketentities :
2006-12-26 21:26:10 +00:00
ParsePacketEntities ( tv , & buf , ReadByte ( & buf ) ) ;
2005-09-06 01:09:36 +00:00
break ;
2006-09-17 01:27:32 +00:00
case svc_entgravity : // gravity change, for prediction
ReadFloat ( & buf ) ;
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , to , mask , QW ) ;
2006-09-17 01:27:32 +00:00
break ;
2007-05-28 02:31:48 +00:00
case svc_maxspeed : // maxspeed change, for prediction
2006-09-17 01:27:32 +00:00
ReadFloat ( & buf ) ;
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , to , mask , QW ) ;
2006-09-17 01:27:32 +00:00
break ;
2005-10-07 02:02:15 +00:00
case svc_setinfo :
ParseSetInfo ( tv , & buf ) ;
break ;
2005-09-06 01:09:36 +00:00
case svc_serverinfo :
ParseServerinfo ( tv , & buf ) ;
break ;
case svc_updatepl :
ParsePacketloss ( tv , & buf , to , mask ) ;
break ;
2006-02-20 01:33:13 +00:00
case svc_nails2 :
2006-02-21 23:25:54 +00:00
ParseNails ( tv , & buf , true ) ;
2006-02-20 01:33:13 +00:00
break ;
2006-09-17 01:27:32 +00:00
2007-05-28 02:31:48 +00:00
case svc_killedmonster :
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , to , mask , Q1 ) ;
2007-05-28 02:31:48 +00:00
break ;
case svc_foundsecret :
2007-08-03 14:10:47 +00:00
Multicast ( tv , ( char * ) buf . data + buf . startpos , buf . readpos - buf . startpos , to , mask , Q1 ) ;
2007-05-28 02:31:48 +00:00
break ;
2005-09-06 01:09:36 +00:00
default :
buf . readpos = buf . startpos ;
2005-10-07 02:02:15 +00:00
Sys_Printf ( tv - > cluster , " Can't handle svc %i \n " , ( unsigned int ) ReadByte ( & buf ) ) ;
2005-09-06 01:09:36 +00:00
return ;
}
}
}
2006-12-26 21:26:10 +00:00