2010-02-15 23:26:55 +00:00
/*
Copyright ( C ) 1996 - 2001 Id Software , Inc .
Copyright ( C ) 2002 - 2009 John Fitzgibbons and others
Copyright ( C ) 2007 - 2008 Kristian Duske
2014-09-22 08:55:46 +00:00
Copyright ( C ) 2010 - 2014 QuakeSpasm developers
2017-09-17 02:12:53 +00:00
Copyright ( C ) 2016 Spike
2010-02-15 23:26:55 +00:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
// cl_parse.c -- parse a message received from the server
# include "quakedef.h"
Backported external music files support using decoder libraries and the
new raw samples interface from Hammer of Thyrion (uhexen2) :
- bgmusic.c, bgmusic.h: New BGM interface for background music handling.
Handles streaming music as raw sound samples.
- bgmnull.c: BGM source for cases where the engine is configured for no
sound.
- cl_main.c: Include bgmusic.h. Call BGM_Stop() and CDAudio_Stop() in
CL_Disconnect().
- cd_sdl.c: Moved bgmvolume boundary checking to bgmusic.c upon value
changes.
- gl_vidnt.c, gl_vidsdl.c, cl_parse.c: Include bgmusic.h. Add BGM_Pause()
and BGM_Resume() calls along with CDAudio_ counterparts.
- cl_parse.c: Replace CDAudio_Play() call by the new BGM_PlayCDtrack()
which first tries CDAudio_Play() and then streaming music if it fails.
- host.c: Include bgmusic.h. Call BGM_Update() just before S_Update()
in Host_Frame(). In Host_Init(), call BGM_Init() after other audio init
calls. In Host_Shutdown(), call BGM_Shutdown() before all other audio
shutdown calls.
- snd_dma.c: Include snd_codec.h and bgmusic.h. Call S_CodecInit() from
S_Init(). Call S_CodecShutdown() from S_Shutdown().
- snd_codec.c, snd_codec.h: New public codec interface for streaming
music as raw samples. Adapted from quake2 and ioquake3 with changes.
Individual codecs are responsible for handling any necessary byte swap
operations.
- snd_codeci.h: New header for snd_codec internals.
- snd_wave.c, snd_wave.h: Codec for WAV format streaming music. Adapted
from ioquake3 with changes.
- snd_vorbis.c, snd_vorbis.h: Codec for Ogg/Vorbis format streaming music.
- snd_mp3.c, snd_mp3.h: Codec for MP3 format streaming music using libmad.
Adapted from the SoX project with changes.
- Makefile: Adjusted for the new sources. Added switches USE_CODEC_WAVE,
USE_CODEC_MP3, USE_CODEC_VORBIS for enabling and disabling individual
codecs.
- Windows makefiles and project files as well as other CodeBlocks project
files will be updated shortly.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@374 af15c1b1-3010-417e-b628-4374ebc0bcbd
2011-01-05 19:50:43 +00:00
# include "bgmusic.h"
2010-02-15 23:26:55 +00:00
2017-09-17 02:12:53 +00:00
const char * svc_strings [ 128 ] =
2010-02-15 23:26:55 +00:00
{
" svc_bad " ,
" svc_nop " ,
" svc_disconnect " ,
" svc_updatestat " ,
" svc_version " , // [long] server version
" svc_setview " , // [short] entity number
" svc_sound " , // <see code>
" svc_time " , // [float] server time
" svc_print " , // [string] null terminated string
" svc_stufftext " , // [string] stuffed into client's console buffer
// the string should be \n terminated
" svc_setangle " , // [vec3] set the view angle to this absolute value
" svc_serverinfo " , // [long] version
// [string] signon string
// [string]..[0]model cache [string]...[0]sounds cache
// [string]..[0]item cache
" svc_lightstyle " , // [byte] [string]
" svc_updatename " , // [byte] [string]
" svc_updatefrags " , // [byte] [short]
" svc_clientdata " , // <shortbits + data>
" svc_stopsound " , // <see code>
" svc_updatecolors " , // [byte] [byte]
" svc_particle " , // [vec3] <variable>
" svc_damage " , // [byte] impact [byte] blood [vec3] from
" svc_spawnstatic " ,
2017-09-17 02:12:53 +00:00
/*"OBSOLETE svc_spawnbinary"*/ " 21 svc_spawnstatic_fte " ,
2010-02-15 23:26:55 +00:00
" svc_spawnbaseline " ,
" svc_temp_entity " , // <variable>
" svc_setpause " ,
" svc_signonnum " ,
" svc_centerprint " ,
" svc_killedmonster " ,
" svc_foundsecret " ,
" svc_spawnstaticsound " ,
" svc_intermission " ,
" svc_finale " , // [string] music [string] text
" svc_cdtrack " , // [byte] track [byte] looptrack
" svc_sellscreen " ,
" svc_cutscene " ,
//johnfitz -- new server messages
2021-03-06 06:25:24 +00:00
" svc_showpic_dp " , // 35
" svc_hidepic_dp " , // 36
2017-09-17 02:12:53 +00:00
" svc_skybox_fitz " , // 37 // [string] skyname
" 38 " , // 38
" 39 " , // 39
" svc_bf_fitz " , // 40 // no data
" svc_fog_fitz " , // 41 // [byte] density [byte] red [byte] green [byte] blue [float] time
" svc_spawnbaseline2_fitz " , //42 // support for large modelindex, large framenum, alpha, using flags
" svc_spawnstatic2_fitz " , // 43 // support for large modelindex, large framenum, alpha, using flags
" svc_spawnstaticsound2_fitz " , // 44 // [coord3] [short] samp [byte] vol [byte] aten
" 45 " , // 45
" 46 " , // 46
" 47 " , // 47
" 48 " , // 48
" 49 " , // 49
2010-02-15 23:26:55 +00:00
//johnfitz
2017-09-17 02:12:53 +00:00
//spike -- particle stuff, and padded to 128 to avoid possible crashes.
" 50 svc_downloaddata_dp " , // 50
" 51 svc_updatestatbyte " , // 51
" 52 svc_effect_dp " , // 52
" 53 svc_effect2_dp " , // 53
" 54 svc_precache " , // 54 //[short] type+idx [string] name
" 55 svc_baseline2_dp " , // 55
" 56 svc_spawnstatic2_dp " , // 56
" 57 svc_entities_dp " , // 57
" 58 svc_csqcentities " , // 58
" 59 svc_spawnstaticsound2_dp " , // 59
" 60 svc_trailparticles " , // 60
" 61 svc_pointparticles " , // 61
" 62 svc_pointparticles1 " , // 62
" 63 svc_particle2_fte " , // 63
" 64 svc_particle3_fte " , // 64
" 65 svc_particle4_fte " , // 65
" 66 svc_spawnbaseline_fte " , // 66
" 67 svc_customtempent_fte " , // 67
" 68 svc_selectsplitscreen_fte " , // 68
" 69 svc_showpic_fte " , // 69
" 70 svc_hidepic_fte " , // 70
" 71 svc_movepic_fte " , // 71
" 72 svc_updatepic_fte " , // 72
" 73 " , // 73
" 74 " , // 74
" 75 " , // 75
" 76 svc_csqcentities_fte " , // 76
" 77 " , // 77
" 78 svc_updatestatstring_fte " , // 78
" 79 svc_updatestatfloat_fte " , // 79
" 80 " , // 80
" 81 " , // 81
" 82 " , // 82
" 83 svc_cgamepacket_fte " , // 83
" 84 svc_voicechat_fte " , // 84
" 85 svc_setangledelta_fte " , // 85
" 86 svc_updateentities_fte " , // 86
" 87 svc_brushedit_fte " , // 87
" 88 svc_updateseats_fte " , // 88
" 89 " , // 89
" 90 " , // 90
" 91 " , // 91
" 92 " , // 92
" 93 " , // 93
" 94 " , // 94
" 95 " , // 95
" 96 " , // 96
" 97 " , // 97
" 98 " , // 98
" 99 " , // 99
" 100 " , // 100
" 101 " , // 101
" 102 " , // 102
" 103 " , // 103
" 104 " , // 104
" 105 " , // 105
" 106 " , // 106
" 107 " , // 107
" 108 " , // 108
" 109 " , // 109
" 110 " , // 110
" 111 " , // 111
" 112 " , // 112
" 113 " , // 113
" 114 " , // 114
" 115 " , // 115
" 116 " , // 116
" 117 " , // 117
" 118 " , // 118
" 119 " , // 119
" 120 " , // 120
" 121 " , // 121
" 122 " , // 122
" 123 " , // 123
" 124 " , // 124
" 125 " , // 125
" 126 " , // 126
" 127 " , // 127
2010-02-15 23:26:55 +00:00
} ;
qboolean warn_about_nehahra_protocol ; //johnfitz
extern vec3_t v_punchangles [ 2 ] ; //johnfitz
2020-10-13 17:11:34 +00:00
extern double v_punchangles_times [ 2 ] ; //spike -- don't assume 10fps...
2010-02-15 23:26:55 +00:00
//=============================================================================
/*
= = = = = = = = = = = = = = =
CL_EntityNum
This error checks and tracks the total number of entities
= = = = = = = = = = = = = = =
*/
entity_t * CL_EntityNum ( int num )
{
//johnfitz -- check minimum number too
if ( num < 0 )
Host_Error ( " CL_EntityNum: %i is an invalid number " , num ) ;
//john
if ( num > = cl . num_entities )
{
2017-09-17 02:12:53 +00:00
if ( num > = cl . max_edicts ) //johnfitz -- no more MAX_EDICTS
2010-02-15 23:26:55 +00:00
Host_Error ( " CL_EntityNum: %i is an invalid number " , num ) ;
while ( cl . num_entities < = num )
{
2017-09-17 02:12:53 +00:00
cl . entities [ cl . num_entities ] . baseline = nullentitystate ;
cl . entities [ cl . num_entities ] . lerpflags | = LERP_RESETMOVE | LERP_RESETANIM ; //johnfitz
2010-02-15 23:26:55 +00:00
cl . num_entities + + ;
}
}
2017-09-17 02:12:53 +00:00
return & cl . entities [ num ] ;
}
2020-09-04 10:58:21 +00:00
static int MSG_ReadSize16 ( sizebuf_t * sb )
{
unsigned short ssolid = MSG_ReadShort ( ) ;
if ( ssolid = = ES_SOLID_BSP )
return ssolid ;
else
{
int solid = ( ( ( ssolid > > 7 ) & 0x1F8 ) - 32 + 32768 ) < < 16 ; /*up can be negative*/
solid | = ( ( ssolid & 0x1F ) < < 3 ) ;
solid | = ( ( ssolid & 0x3E0 ) < < 10 ) ;
return solid ;
}
}
2017-09-17 02:12:53 +00:00
static unsigned int CLFTE_ReadDelta ( unsigned int entnum , entity_state_t * news , const entity_state_t * olds , const entity_state_t * baseline )
{
unsigned int predbits = 0 ;
unsigned int bits ;
bits = MSG_ReadByte ( ) ;
if ( bits & UF_EXTEND1 )
bits | = MSG_ReadByte ( ) < < 8 ;
if ( bits & UF_EXTEND2 )
bits | = MSG_ReadByte ( ) < < 16 ;
if ( bits & UF_EXTEND3 )
bits | = MSG_ReadByte ( ) < < 24 ;
if ( cl_shownet . value > = 3 )
Con_SafePrintf ( " %3i: Update %4i 0x%x \n " , msg_readcount , entnum , bits ) ;
if ( bits & UF_RESET )
{
// Con_Printf("%3i: Reset %i @ %i\n", msg_readcount, entnum, cls.netchan.incoming_sequence);
* news = * baseline ;
}
else if ( ! olds )
{
/*reset got lost, probably the data will be filled in later - FIXME: we should probably ignore this entity*/
Con_DPrintf ( " New entity %i without reset \n " , entnum ) ;
* news = nullentitystate ;
}
else
* news = * olds ;
if ( bits & UF_FRAME )
{
if ( bits & UF_16BIT )
news - > frame = MSG_ReadShort ( ) ;
else
news - > frame = MSG_ReadByte ( ) ;
}
if ( bits & UF_ORIGINXY )
{
news - > origin [ 0 ] = MSG_ReadCoord ( cl . protocolflags ) ;
news - > origin [ 1 ] = MSG_ReadCoord ( cl . protocolflags ) ;
}
if ( bits & UF_ORIGINZ )
news - > origin [ 2 ] = MSG_ReadCoord ( cl . protocolflags ) ;
if ( ( bits & UF_PREDINFO ) & & ! ( cl . protocol_pext2 & PEXT2_PREDINFO ) )
{
//predicted stuff gets more precise angles
if ( bits & UF_ANGLESXZ )
{
news - > angles [ 0 ] = MSG_ReadAngle16 ( cl . protocolflags ) ;
news - > angles [ 2 ] = MSG_ReadAngle16 ( cl . protocolflags ) ;
}
if ( bits & UF_ANGLESY )
news - > angles [ 1 ] = MSG_ReadAngle16 ( cl . protocolflags ) ;
}
else
{
if ( bits & UF_ANGLESXZ )
{
news - > angles [ 0 ] = MSG_ReadAngle ( cl . protocolflags ) ;
news - > angles [ 2 ] = MSG_ReadAngle ( cl . protocolflags ) ;
}
if ( bits & UF_ANGLESY )
news - > angles [ 1 ] = MSG_ReadAngle ( cl . protocolflags ) ;
}
if ( ( bits & ( UF_EFFECTS | UF_EFFECTS2 ) ) = = ( UF_EFFECTS | UF_EFFECTS2 ) )
news - > effects = MSG_ReadLong ( ) ;
else if ( bits & UF_EFFECTS2 )
news - > effects = ( unsigned short ) MSG_ReadShort ( ) ;
else if ( bits & UF_EFFECTS )
news - > effects = MSG_ReadByte ( ) ;
// news->movement[0] = 0;
// news->movement[1] = 0;
// news->movement[2] = 0;
news - > velocity [ 0 ] = 0 ;
news - > velocity [ 1 ] = 0 ;
news - > velocity [ 2 ] = 0 ;
if ( bits & UF_PREDINFO )
{
predbits = MSG_ReadByte ( ) ;
if ( predbits & UFP_FORWARD )
/*news->movement[0] =*/ MSG_ReadShort ( ) ;
//else
// news->movement[0] = 0;
if ( predbits & UFP_SIDE )
/*news->movement[1] =*/ MSG_ReadShort ( ) ;
//else
// news->movement[1] = 0;
if ( predbits & UFP_UP )
/*news->movement[2] =*/ MSG_ReadShort ( ) ;
//else
// news->movement[2] = 0;
if ( predbits & UFP_MOVETYPE )
news - > pmovetype = MSG_ReadByte ( ) ;
if ( predbits & UFP_VELOCITYXY )
{
news - > velocity [ 0 ] = MSG_ReadShort ( ) ;
news - > velocity [ 1 ] = MSG_ReadShort ( ) ;
}
else
{
news - > velocity [ 0 ] = 0 ;
news - > velocity [ 1 ] = 0 ;
}
if ( predbits & UFP_VELOCITYZ )
news - > velocity [ 2 ] = MSG_ReadShort ( ) ;
else
news - > velocity [ 2 ] = 0 ;
if ( predbits & UFP_MSEC ) //the msec value is how old the update is (qw clients normally predict without the server running an update every frame)
/*news->msec =*/ MSG_ReadByte ( ) ;
//else
// news->msec = 0;
if ( cl . protocol_pext2 & PEXT2_PREDINFO )
{
if ( predbits & UFP_VIEWANGLE )
{
if ( bits & UF_ANGLESXZ )
{
/*news->vangle[0] =*/ MSG_ReadShort ( ) ;
/*news->vangle[2] =*/ MSG_ReadShort ( ) ;
}
if ( bits & UF_ANGLESY )
/*news->vangle[1] =*/ MSG_ReadShort ( ) ;
}
}
else
{
if ( predbits & UFP_WEAPONFRAME_OLD )
{
int wframe ;
wframe = MSG_ReadByte ( ) ;
if ( wframe & 0x80 )
wframe = ( wframe & 127 ) | ( MSG_ReadByte ( ) < < 7 ) ;
}
}
}
else
{
//news->msec = 0;
}
if ( ! ( predbits & UFP_VIEWANGLE ) | | ! ( cl . protocol_pext2 & PEXT2_PREDINFO ) )
{ /*
if ( bits & UF_ANGLESXZ )
news - > vangle [ 0 ] = ANGLE2SHORT ( news - > angles [ 0 ] * ( ( bits & UF_PREDINFO ) ? - 3 : - 1 ) ) ;
if ( bits & UF_ANGLESY )
news - > vangle [ 1 ] = ANGLE2SHORT ( news - > angles [ 1 ] ) ;
if ( bits & UF_ANGLESXZ )
news - > vangle [ 2 ] = ANGLE2SHORT ( news - > angles [ 2 ] ) ;
*/
}
if ( bits & UF_MODEL )
{
if ( bits & UF_16BIT )
news - > modelindex = MSG_ReadShort ( ) ;
else
news - > modelindex = MSG_ReadByte ( ) ;
}
if ( bits & UF_SKIN )
{
if ( bits & UF_16BIT )
news - > skin = MSG_ReadShort ( ) ;
else
news - > skin = MSG_ReadByte ( ) ;
}
if ( bits & UF_COLORMAP )
news - > colormap = MSG_ReadByte ( ) ;
if ( bits & UF_SOLID )
{ //knowing the size of an entity is important for prediction
//without prediction, its a bit pointless.
if ( cl . protocol_pext2 & PEXT2_NEWSIZEENCODING )
{
byte enc = MSG_ReadByte ( ) ;
if ( enc = = 0 )
2020-09-04 10:58:21 +00:00
news - > solidsize = ES_SOLID_NOT ;
2017-09-17 02:12:53 +00:00
else if ( enc = = 1 )
2020-09-04 10:58:21 +00:00
news - > solidsize = ES_SOLID_BSP ;
2017-09-17 02:12:53 +00:00
else if ( enc = = 2 )
2020-09-04 10:58:21 +00:00
news - > solidsize = ES_SOLID_HULL1 ;
2017-09-17 02:12:53 +00:00
else if ( enc = = 3 )
2020-09-04 10:58:21 +00:00
news - > solidsize = ES_SOLID_HULL2 ;
2017-09-17 02:12:53 +00:00
else if ( enc = = 16 )
2020-09-04 10:58:21 +00:00
news - > solidsize = MSG_ReadSize16 ( & net_message ) ;
2017-09-17 02:12:53 +00:00
else if ( enc = = 32 )
2020-09-04 10:58:21 +00:00
news - > solidsize = MSG_ReadLong ( ) ;
2017-09-17 02:12:53 +00:00
else
Sys_Error ( " Solid+Size encoding not known " ) ;
}
else
2020-09-04 10:58:21 +00:00
news - > solidsize = MSG_ReadSize16 ( & net_message ) ;
2017-09-17 02:12:53 +00:00
}
if ( bits & UF_FLAGS )
news - > eflags = MSG_ReadByte ( ) ;
if ( bits & UF_ALPHA )
news - > alpha = ( MSG_ReadByte ( ) + 1 ) & 0xff ;
if ( bits & UF_SCALE )
news - > scale = MSG_ReadByte ( ) ;
if ( bits & UF_BONEDATA )
{
unsigned char fl = MSG_ReadByte ( ) ;
if ( fl & 0x80 )
{
//this is NOT finalized
int i ;
int bonecount = MSG_ReadByte ( ) ;
//short *bonedata = AllocateBoneSpace(newp, bonecount, &news->boneoffset);
for ( i = 0 ; i < bonecount * 7 ; i + + )
/*bonedata[i] =*/ MSG_ReadShort ( ) ;
//news->bonecount = bonecount;
}
//else
//news->bonecount = 0; //oo, it went away.
if ( fl & 0x40 )
{
/*news->basebone =*/ MSG_ReadByte ( ) ;
/*news->baseframe =*/ MSG_ReadShort ( ) ;
}
/*else
{
news - > basebone = 0 ;
news - > baseframe = 0 ;
} */
//fixme: basebone, baseframe, etc.
if ( fl & 0x3f )
Host_EndGame ( " unsupported entity delta info \n " ) ;
}
// else if (news->bonecount)
// { //still has bone data from the previous frame.
// short *bonedata = AllocateBoneSpace(newp, news->bonecount, &news->boneoffset);
// memcpy(bonedata, oldp->bonedata+olds->boneoffset, sizeof(short)*7*news->bonecount);
// }
if ( bits & UF_DRAWFLAGS )
{
int drawflags = MSG_ReadByte ( ) ;
if ( ( drawflags & /*MLS_MASK*/ 7 ) = = /*MLS_ABSLIGHT*/ 7 )
/*news->abslight =*/ MSG_ReadByte ( ) ;
//else
// news->abslight = 0;
//news->drawflags = drawflags;
}
if ( bits & UF_TAGINFO )
{
2018-05-01 00:35:14 +00:00
news - > tagentity = MSG_ReadEntity ( cl . protocol_pext2 ) ;
2017-09-17 02:12:53 +00:00
news - > tagindex = MSG_ReadByte ( ) ;
}
if ( bits & UF_LIGHT )
{
/*news->light[0] =*/ MSG_ReadShort ( ) ;
/*news->light[1] =*/ MSG_ReadShort ( ) ;
/*news->light[2] =*/ MSG_ReadShort ( ) ;
/*news->light[3] =*/ MSG_ReadShort ( ) ;
/*news->lightstyle =*/ MSG_ReadByte ( ) ;
/*news->lightpflags =*/ MSG_ReadByte ( ) ;
}
if ( bits & UF_TRAILEFFECT )
{
unsigned short v = MSG_ReadShort ( ) ;
news - > emiteffectnum = 0 ;
news - > traileffectnum = v & 0x3fff ;
if ( v & 0x8000 )
news - > emiteffectnum = MSG_ReadShort ( ) & 0x3fff ;
if ( news - > traileffectnum > = MAX_PARTICLETYPES )
news - > traileffectnum = 0 ;
if ( news - > emiteffectnum > = MAX_PARTICLETYPES )
news - > emiteffectnum = 0 ;
}
if ( bits & UF_COLORMOD )
{
news - > colormod [ 0 ] = MSG_ReadByte ( ) ;
news - > colormod [ 1 ] = MSG_ReadByte ( ) ;
news - > colormod [ 2 ] = MSG_ReadByte ( ) ;
}
if ( bits & UF_GLOW )
{
/*news->glowsize =*/ MSG_ReadByte ( ) ;
/*news->glowcolour =*/ MSG_ReadByte ( ) ;
/*news->glowmod[0] =*/ MSG_ReadByte ( ) ;
/*news->glowmod[1] =*/ MSG_ReadByte ( ) ;
/*news->glowmod[2] =*/ MSG_ReadByte ( ) ;
}
if ( bits & UF_FATNESS )
/*news->fatness =*/ MSG_ReadByte ( ) ;
if ( bits & UF_MODELINDEX2 )
{
if ( bits & UF_16BIT )
/*news->modelindex2 =*/ MSG_ReadShort ( ) ;
else
/*news->modelindex2 =*/ MSG_ReadByte ( ) ;
}
if ( bits & UF_GRAVITYDIR )
{
/*news->gravitydir[0] =*/ MSG_ReadByte ( ) ;
/*news->gravitydir[1] =*/ MSG_ReadByte ( ) ;
}
if ( bits & UF_UNUSED2 )
{
Host_EndGame ( " UF_UNUSED2 bit \n " ) ;
}
if ( bits & UF_UNUSED1 )
{
Host_EndGame ( " UF_UNUSED1 bit \n " ) ;
}
return bits ;
}
static void CLFTE_ParseBaseline ( entity_state_t * es )
{
CLFTE_ReadDelta ( 0 , es , & nullentitystate , & nullentitystate ) ;
}
//called with both fte+dp deltas
static void CL_EntitiesDeltaed ( void )
{
2020-09-03 09:59:23 +00:00
int newnum ;
2017-09-17 02:12:53 +00:00
qmodel_t * model ;
qboolean forcelink ;
entity_t * ent ;
int skin ;
for ( newnum = 1 ; newnum < cl . num_entities ; newnum + + )
{
ent = CL_EntityNum ( newnum ) ;
if ( ! ent - > update_type )
continue ; //not interested in this one
if ( ent - > msgtime ! = cl . mtime [ 1 ] )
forcelink = true ; // no previous frame to lerp from
else
forcelink = false ;
//johnfitz -- lerping
if ( ent - > msgtime + 0.2 < cl . mtime [ 0 ] ) //more than 0.2 seconds since the last message (most entities think every 0.1 sec)
ent - > lerpflags | = LERP_RESETANIM ; //if we missed a think, we'd be lerping from the wrong frame
ent - > msgtime = cl . mtime [ 0 ] ;
skin = ent - > netstate . skin ;
if ( skin ! = ent - > skinnum )
{
ent - > skinnum = skin ;
if ( newnum > 0 & & newnum < = cl . maxclients )
R_TranslateNewPlayerSkin ( newnum - 1 ) ; //johnfitz -- was R_TranslatePlayerSkin
}
ent - > effects = ent - > netstate . effects ;
// shift the known values for interpolation
VectorCopy ( ent - > msg_origins [ 0 ] , ent - > msg_origins [ 1 ] ) ;
VectorCopy ( ent - > msg_angles [ 0 ] , ent - > msg_angles [ 1 ] ) ;
2021-03-21 14:13:20 +00:00
VectorCopy ( ent - > netstate . origin , ent - > msg_origins [ 0 ] ) ;
VectorCopy ( ent - > netstate . angles , ent - > msg_angles [ 0 ] ) ;
2017-09-17 02:12:53 +00:00
//johnfitz -- lerping for movetype_step entities
if ( ent - > netstate . eflags & EFLAGS_STEP )
{
ent - > lerpflags | = LERP_MOVESTEP ;
ent - > forcelink = true ;
}
else
ent - > lerpflags & = ~ LERP_MOVESTEP ;
ent - > alpha = ent - > netstate . alpha ;
/* if (bits & U_LERPFINISH)
{
ent - > lerpfinish = ent - > msgtime + ( ( float ) ( MSG_ReadByte ( ) ) / 255 ) ;
ent - > lerpflags | = LERP_FINISH ;
}
else */
ent - > lerpflags & = ~ LERP_FINISH ;
model = cl . model_precache [ ent - > netstate . modelindex ] ;
if ( model ! = ent - > model )
{
ent - > model = model ;
// automatic animation (torches, etc) can be either all together
// or randomized
if ( model )
{
2020-06-24 01:57:44 +00:00
if ( model - > synctype = = ST_FRAMETIME )
ent - > syncbase = - cl . time ;
else if ( model - > synctype = = ST_RAND )
2017-09-17 02:12:53 +00:00
ent - > syncbase = ( float ) ( rand ( ) & 0x7fff ) / 0x7fff ;
else
ent - > syncbase = 0.0 ;
}
else
forcelink = true ; // hack to make null model players work
if ( newnum > 0 & & newnum < = cl . maxclients )
R_TranslateNewPlayerSkin ( newnum - 1 ) ; //johnfitz -- was R_TranslatePlayerSkin
ent - > lerpflags | = LERP_RESETANIM ; //johnfitz -- don't lerp animation across model changes
}
2020-06-24 01:57:44 +00:00
else if ( model & & model - > synctype = = ST_FRAMETIME & & ent - > frame ! = ent - > netstate . frame )
ent - > syncbase = - cl . time ;
ent - > frame = ent - > netstate . frame ;
2017-09-17 02:12:53 +00:00
if ( forcelink )
{ // didn't have an update last message
VectorCopy ( ent - > msg_origins [ 0 ] , ent - > msg_origins [ 1 ] ) ;
VectorCopy ( ent - > msg_origins [ 0 ] , ent - > origin ) ;
VectorCopy ( ent - > msg_angles [ 0 ] , ent - > msg_angles [ 1 ] ) ;
VectorCopy ( ent - > msg_angles [ 0 ] , ent - > angles ) ;
ent - > forcelink = true ;
}
}
}
static void CLFTE_ParseEntitiesUpdate ( void )
{
int newnum ;
qboolean removeflag ;
entity_t * ent ;
float newtime ;
//so the server can know when we got it, and guess which frames we didn't get
2018-10-16 19:36:23 +00:00
if ( cls . netcon & & cl . ackframes_count < sizeof ( cl . ackframes ) / sizeof ( cl . ackframes [ 0 ] ) )
2017-09-17 02:12:53 +00:00
cl . ackframes [ cl . ackframes_count + + ] = NET_QSocketGetSequenceIn ( cls . netcon ) ;
if ( cl . protocol_pext2 & PEXT2_PREDINFO )
2020-09-04 11:18:05 +00:00
{
int seq = ( cl . movemessages & 0xffff0000 ) | ( unsigned short ) MSG_ReadShort ( ) ; //an ack from our input sequences. strictly ascending-or-equal
if ( seq > cl . movemessages )
seq - = 0x10000 ; //check for cl.movemessages overflowing the low 16 bits, and compensate.
cl . ackedmovemessages = seq ;
if ( cl . qcvm . extglobals . servercommandframe )
* cl . qcvm . extglobals . servercommandframe = cl . ackedmovemessages ;
}
2017-09-17 02:12:53 +00:00
newtime = MSG_ReadFloat ( ) ;
if ( newtime ! = cl . mtime [ 0 ] )
{ //don't mess up lerps if the server is splitting entities into multiple packets.
cl . mtime [ 1 ] = cl . mtime [ 0 ] ;
cl . mtime [ 0 ] = newtime ;
}
for ( ; ; )
{
newnum = ( unsigned short ) ( short ) MSG_ReadShort ( ) ;
removeflag = ! ! ( newnum & 0x8000 ) ;
if ( newnum & 0x4000 )
newnum = ( newnum & 0x3fff ) | ( MSG_ReadByte ( ) < < 14 ) ;
else
newnum & = ~ 0x8000 ;
if ( ( ! newnum & & ! removeflag ) | | msg_badread )
break ;
ent = CL_EntityNum ( newnum ) ;
if ( removeflag )
2020-10-02 18:46:25 +00:00
{ //removal.
2017-09-17 02:12:53 +00:00
if ( cl_shownet . value > = 3 )
Con_SafePrintf ( " %3i: Remove %i \n " , msg_readcount , newnum ) ;
if ( ! newnum )
{
/*removal of world - means forget all entities, aka a full reset*/
if ( cl_shownet . value > = 3 )
Con_SafePrintf ( " %3i: Reset all \n " , msg_readcount ) ;
for ( newnum = 1 ; newnum < cl . num_entities ; newnum + + )
{
CL_EntityNum ( newnum ) - > netstate . pmovetype = 0 ;
CL_EntityNum ( newnum ) - > model = NULL ;
}
cl . requestresend = false ; //we got it.
continue ;
}
ent - > update_type = false ; //no longer valid
ent - > model = NULL ;
continue ;
}
2020-10-02 18:46:25 +00:00
else if ( ent - > update_type )
{ //simple update
CLFTE_ReadDelta ( newnum , & ent - > netstate , & ent - > netstate , & ent - > baseline ) ;
}
2017-09-17 02:12:53 +00:00
else
2020-10-02 18:46:25 +00:00
{ //we had no previous copy of this entity...
2017-09-17 02:12:53 +00:00
ent - > update_type = true ;
2020-10-02 18:46:25 +00:00
CLFTE_ReadDelta ( newnum , & ent - > netstate , NULL , & ent - > baseline ) ;
//stupid interpolation junk.
ent - > lerpflags | = LERP_RESETMOVE | LERP_RESETANIM ;
2017-09-17 02:12:53 +00:00
}
}
CL_EntitiesDeltaed ( ) ;
if ( cl . protocol_pext2 & PEXT2_PREDINFO )
{ //stats should normally be sent before the entity data.
2020-10-13 17:11:34 +00:00
extern cvar_t v_gunkick ;
2017-09-17 02:12:53 +00:00
VectorCopy ( cl . mvelocity [ 0 ] , cl . mvelocity [ 1 ] ) ;
ent = CL_EntityNum ( cl . viewentity ) ;
cl . mvelocity [ 0 ] [ 0 ] = ent - > netstate . velocity [ 0 ] * ( 1 / 8.0 ) ;
cl . mvelocity [ 0 ] [ 1 ] = ent - > netstate . velocity [ 1 ] * ( 1 / 8.0 ) ;
cl . mvelocity [ 0 ] [ 2 ] = ent - > netstate . velocity [ 2 ] * ( 1 / 8.0 ) ;
cl . onground = ( ent - > netstate . eflags & EFLAGS_ONGROUND ) ? true : false ;
2020-10-13 17:11:34 +00:00
if ( v_gunkick . value = = 1 )
{ //truncate away any extra precision, like vanilla/qs would.
cl . punchangle [ 0 ] = cl . stats [ STAT_PUNCHANGLE_X ] ;
cl . punchangle [ 1 ] = cl . stats [ STAT_PUNCHANGLE_Y ] ;
cl . punchangle [ 2 ] = cl . stats [ STAT_PUNCHANGLE_Z ] ;
}
else
{ //woo, more precision
cl . punchangle [ 0 ] = cl . statsf [ STAT_PUNCHANGLE_X ] ;
cl . punchangle [ 1 ] = cl . statsf [ STAT_PUNCHANGLE_Y ] ;
cl . punchangle [ 2 ] = cl . statsf [ STAT_PUNCHANGLE_Z ] ;
}
2017-09-17 02:12:53 +00:00
if ( v_punchangles [ 0 ] [ 0 ] ! = cl . punchangle [ 0 ] | | v_punchangles [ 0 ] [ 1 ] ! = cl . punchangle [ 1 ] | | v_punchangles [ 0 ] [ 2 ] ! = cl . punchangle [ 2 ] )
{
2020-10-13 17:11:34 +00:00
v_punchangles_times [ 1 ] = v_punchangles_times [ 0 ] ;
v_punchangles_times [ 0 ] = newtime ;
2017-09-17 02:12:53 +00:00
VectorCopy ( v_punchangles [ 0 ] , v_punchangles [ 1 ] ) ;
VectorCopy ( cl . punchangle , v_punchangles [ 0 ] ) ;
}
}
if ( ! cl . requestresend )
{
if ( cls . signon = = SIGNONS - 1 )
{ // first update is the final signon stage
cls . signon = SIGNONS ;
CL_SignonReply ( ) ;
}
}
}
2020-09-04 10:53:42 +00:00
static void CSQC_ClearCsEdictForSSQC ( size_t entnum )
{
edict_t * ed ;
if ( entnum > = cl . ssqc_to_csqc_max )
return ; //invalid...
ed = cl . ssqc_to_csqc [ entnum ] ;
if ( ed )
{
cl . ssqc_to_csqc [ entnum ] = NULL ;
//let the csqc know.
pr_global_struct - > self = EDICT_TO_PROG ( ed ) ;
if ( qcvm - > extfuncs . CSQC_Ent_Remove )
PR_ExecuteProgram ( qcvm - > extfuncs . CSQC_Ent_Remove ) ;
else
ED_Free ( ed ) ;
}
}
static void CSQC_UpdateCsEdictForSSQC ( size_t entnum )
{
edict_t * ed ;
eval_t * ev ;
qboolean isnew ;
if ( entnum > = cl . ssqc_to_csqc_max )
{
size_t nc = q_min ( MAX_EDICTS , entnum + 64 ) ;
void * nptr ;
if ( entnum > = nc )
Host_EndGame ( " entnum > MAX_EDICTS " ) ;
nptr = realloc ( cl . ssqc_to_csqc , nc * sizeof ( * cl . ssqc_to_csqc ) ) ;
if ( ! nptr )
Sys_Error ( " realloc failure " ) ;
cl . ssqc_to_csqc = nptr ;
memset ( cl . ssqc_to_csqc + cl . ssqc_to_csqc_max , 0 , ( nc - cl . ssqc_to_csqc_max ) * sizeof ( * cl . ssqc_to_csqc ) ) ;
cl . ssqc_to_csqc_max = nc ;
}
ed = cl . ssqc_to_csqc [ entnum ] ;
if ( ! ed )
{
//allocate our new ent.
ed = cl . ssqc_to_csqc [ entnum ] = ED_Alloc ( ) ;
//fill its entnum field too.
ev = GetEdictFieldValue ( ed , qcvm - > extfields . entnum ) ;
if ( ev )
ev - > _float = entnum ;
isnew = true ;
}
else
isnew = false ;
G_FLOAT ( OFS_PARM0 ) = isnew ;
pr_global_struct - > self = EDICT_TO_PROG ( ed ) ;
PR_ExecuteProgram ( cl . qcvm . extfuncs . CSQC_Ent_Update ) ;
}
2018-05-01 00:35:14 +00:00
//csqc entities protocol, payload is identical in both fte+dp. just the svcs differ.
void CLFTE_ParseCSQCEntitiesUpdate ( void )
{
2020-09-04 10:53:42 +00:00
if ( qcvm - > extfuncs . CSQC_Ent_Update )
2018-05-01 00:35:14 +00:00
{
2020-09-04 10:53:42 +00:00
unsigned int entnum ;
qboolean removeflag ;
2018-05-01 00:35:14 +00:00
for ( ; ; )
{
//replacement deltas now also includes 22bit entity num indicies.
2020-09-04 10:53:42 +00:00
if ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS )
2018-05-01 00:35:14 +00:00
{
entnum = ( unsigned short ) MSG_ReadShort ( ) ;
removeflag = ! ! ( entnum & 0x8000 ) ;
if ( entnum & 0x4000 )
entnum = ( entnum & 0x3fff ) | ( MSG_ReadByte ( ) < < 14 ) ;
else
entnum & = ~ 0x8000 ;
}
else
{ //otherwise just a 16bit value, with the high bit used as a 'remove' flag
entnum = ( unsigned short ) MSG_ReadShort ( ) ;
removeflag = ! ! ( entnum & 0x8000 ) ;
entnum & = ~ 0x8000 ;
}
if ( ( ! entnum & & ! removeflag ) | | msg_badread )
break ; //end of svc
if ( removeflag )
{
2020-09-04 10:53:42 +00:00
if ( cl_shownet . value > = 3 )
Con_SafePrintf ( " %3i: Remove %i \n " , msg_readcount , entnum ) ;
CSQC_ClearCsEdictForSSQC ( entnum ) ;
2018-05-01 00:35:14 +00:00
}
else
{
2020-09-04 10:53:42 +00:00
/* if (sized)
2018-05-01 00:35:14 +00:00
{
2020-09-04 10:53:42 +00:00
packetsize = MSG_ReadShort ( ) ;
if ( cl_shownet . value > = 3 )
Con_SafePrintf ( " %3i - %3i: Update %i \n " , msg_readcount , msg_readcount + packetsize - 1 , entnum ) ;
2018-05-01 00:35:14 +00:00
}
else
2020-09-04 10:53:42 +00:00
*/ {
if ( cl_shownet . value > = 3 )
Con_SafePrintf ( " %3i: Update %i \n " , msg_readcount , entnum ) ;
}
CSQC_UpdateCsEdictForSSQC ( entnum ) ;
// if (sized)
// ;//TODO make sure we read the right size...
2018-05-01 00:35:14 +00:00
}
}
}
2020-09-04 10:53:42 +00:00
else
2018-10-16 19:36:23 +00:00
Host_Error ( " Received svc_csqcentities but unable to parse " ) ;
2018-05-01 00:35:14 +00:00
}
2017-09-17 02:12:53 +00:00
//darkplaces protocols 5 to 7 use these
# define E5_FULLUPDATE (1<<0)
# define E5_ORIGIN (1<<1)
# define E5_ANGLES (1<<2)
# define E5_MODEL (1<<3)
# define E5_FRAME (1<<4)
# define E5_SKIN (1<<5)
# define E5_EFFECTS (1<<6)
# define E5_EXTEND1 (1<<7)
# define E5_FLAGS (1<<8)
# define E5_ALPHA (1<<9)
# define E5_SCALE (1<<10)
# define E5_ORIGIN32 (1<<11)
# define E5_ANGLES16 (1<<12)
# define E5_MODEL16 (1<<13)
# define E5_COLORMAP (1<<14)
# define E5_EXTEND2 (1<<15)
# define E5_ATTACHMENT (1<<16)
# define E5_LIGHT (1<<17)
# define E5_GLOW (1<<18)
# define E5_EFFECTS16 (1<<19)
# define E5_EFFECTS32 (1<<20)
# define E5_FRAME16 (1<<21)
# define E5_COLORMOD (1<<22)
# define E5_EXTEND3 (1<<23)
# define E5_GLOWMOD (1<<24)
# define E5_COMPLEXANIMATION (1<<25)
# define E5_TRAILEFFECTNUM (1<<26)
# define E5_UNUSED27 (1<<27)
# define E5_UNUSED28 (1<<28)
# define E5_UNUSED29 (1<<29)
# define E5_UNUSED30 (1<<30)
# define E5_EXTEND4 (1<<31)
# define E5_ALLUNUSED (E5_UNUSED27|E5_UNUSED28|E5_UNUSED29|E5_UNUSED30|E5_EXTEND4)
# define E5_ALLUNSUPPORTED (E5_LIGHT|E5_GLOW|E5_GLOWMOD|E5_COMPLEXANIMATION)
static void CLDP_ReadDelta ( unsigned int entnum , entity_state_t * s , const entity_state_t * olds , const entity_state_t * baseline )
{
unsigned int bits = MSG_ReadByte ( ) ;
if ( bits & E5_EXTEND1 )
{
bits | = MSG_ReadByte ( ) < < 8 ;
if ( bits & E5_EXTEND2 )
{
bits | = MSG_ReadByte ( ) < < 16 ;
if ( bits & E5_EXTEND3 )
bits | = MSG_ReadByte ( ) < < 24 ;
}
}
if ( bits & ( E5_ALLUNSUPPORTED | E5_ALLUNUSED ) )
{
if ( bits & E5_ALLUNUSED )
Host_Error ( " E5 update contains unknown bits %x " , bits & E5_ALLUNUSED ) ;
else
Con_DPrintf ( " E5 update contains unsupported bits %x " , bits & E5_ALLUNSUPPORTED ) ;
}
if ( bits & E5_FULLUPDATE )
{
// Con_Printf("%3i: Reset %i @ %i\n", msg_readcount, entnum, cls.netchan.incoming_sequence);
* s = * baseline ;
}
else if ( ! olds )
{
/*reset got lost, probably the data will be filled in later - FIXME: we should probably ignore this entity*/
Con_DPrintf ( " New entity %i without reset \n " , entnum ) ;
* s = nullentitystate ;
}
else
* s = * olds ;
if ( bits & E5_FLAGS )
{
int i = MSG_ReadByte ( ) ;
s - > eflags = i ;
}
if ( bits & E5_ORIGIN )
{
if ( bits & E5_ORIGIN32 )
{
s - > origin [ 0 ] = MSG_ReadFloat ( ) ;
s - > origin [ 1 ] = MSG_ReadFloat ( ) ;
s - > origin [ 2 ] = MSG_ReadFloat ( ) ;
}
else
{
s - > origin [ 0 ] = MSG_ReadShort ( ) * ( 1 / 8.0f ) ;
s - > origin [ 1 ] = MSG_ReadShort ( ) * ( 1 / 8.0f ) ;
s - > origin [ 2 ] = MSG_ReadShort ( ) * ( 1 / 8.0f ) ;
}
}
if ( bits & E5_ANGLES )
{
if ( bits & E5_ANGLES16 )
{
s - > angles [ 0 ] = MSG_ReadAngle ( PRFL_SHORTANGLE ) ;
s - > angles [ 1 ] = MSG_ReadAngle ( PRFL_SHORTANGLE ) ;
s - > angles [ 2 ] = MSG_ReadAngle ( PRFL_SHORTANGLE ) ;
}
else
{
s - > angles [ 0 ] = MSG_ReadChar ( ) * ( 360.0 / 256 ) ;
s - > angles [ 1 ] = MSG_ReadChar ( ) * ( 360.0 / 256 ) ;
s - > angles [ 2 ] = MSG_ReadChar ( ) * ( 360.0 / 256 ) ;
}
}
if ( bits & E5_MODEL )
{
if ( bits & E5_MODEL16 )
s - > modelindex = ( unsigned short ) MSG_ReadShort ( ) ;
else
s - > modelindex = MSG_ReadByte ( ) ;
}
if ( bits & E5_FRAME )
{
if ( bits & E5_FRAME16 )
s - > frame = ( unsigned short ) MSG_ReadShort ( ) ;
else
s - > frame = MSG_ReadByte ( ) ;
}
if ( bits & E5_SKIN )
s - > skin = MSG_ReadByte ( ) ;
if ( bits & E5_EFFECTS )
{
if ( bits & E5_EFFECTS32 )
s - > effects = ( unsigned int ) MSG_ReadLong ( ) ;
else if ( bits & E5_EFFECTS16 )
s - > effects = ( unsigned short ) MSG_ReadShort ( ) ;
else
s - > effects = MSG_ReadByte ( ) ;
}
if ( bits & E5_ALPHA )
2018-05-25 10:50:13 +00:00
s - > alpha = ( MSG_ReadByte ( ) + 1 ) & 0xff ;
2017-09-17 02:12:53 +00:00
if ( bits & E5_SCALE )
s - > scale = MSG_ReadByte ( ) ;
if ( bits & E5_COLORMAP )
s - > colormap = MSG_ReadByte ( ) ;
if ( bits & E5_ATTACHMENT )
{
2018-05-01 00:35:14 +00:00
s - > tagentity = MSG_ReadEntity ( cl . protocol_pext2 ) ;
2017-09-17 02:12:53 +00:00
s - > tagindex = MSG_ReadByte ( ) ;
}
if ( bits & E5_LIGHT )
{
/*s->light[0] =*/ MSG_ReadShort ( ) ;
/*s->light[1] =*/ MSG_ReadShort ( ) ;
/*s->light[2] =*/ MSG_ReadShort ( ) ;
/*s->light[3] =*/ MSG_ReadShort ( ) ;
/*s->lightstyle =*/ MSG_ReadByte ( ) ;
/*s->lightpflags =*/ MSG_ReadByte ( ) ;
}
if ( bits & E5_GLOW )
{
/*s->glowsize =*/ MSG_ReadByte ( ) ;
/*s->glowcolour =*/ MSG_ReadByte ( ) ;
}
if ( bits & E5_COLORMOD )
{
s - > colormod [ 0 ] = MSG_ReadByte ( ) ;
s - > colormod [ 1 ] = MSG_ReadByte ( ) ;
s - > colormod [ 2 ] = MSG_ReadByte ( ) ;
}
if ( bits & E5_GLOWMOD )
{
/*s->glowmod[0] =*/ MSG_ReadByte ( ) ;
/*s->glowmod[1] =*/ MSG_ReadByte ( ) ;
/*s->glowmod[2] =*/ MSG_ReadByte ( ) ;
}
if ( bits & E5_COMPLEXANIMATION )
{
int type = MSG_ReadByte ( ) ;
int i , numbones ;
if ( type = = 4 )
{
/*modelindex = */ MSG_ReadShort ( ) ;
numbones = MSG_ReadByte ( ) ;
for ( i = 0 ; i < numbones * 7 ; i + + )
/*bonedata[i] =*/ MSG_ReadShort ( ) ;
}
else if ( type < 4 )
{ //n-way blends
type + + ;
for ( i = 0 ; i < type ; i + + )
/*frame = */ MSG_ReadShort ( ) ;
for ( i = 0 ; i < type ; i + + )
/*age = */ MSG_ReadShort ( ) ;
for ( i = 0 ; i < type ; i + + )
/*frac = */ ( type = = 1 ) ? 255 : MSG_ReadByte ( ) ;
}
else
Host_Error ( " E5_COMPLEXANIMATION: Parse error - unknown type %i \n " , type ) ;
}
if ( bits & E5_TRAILEFFECTNUM )
s - > traileffectnum = MSG_ReadShort ( ) ;
}
//dpp5-7 compat
static void CLDP_ParseEntitiesUpdate ( void )
{
entity_t * ent ;
unsigned short id ;
int ack ;
ack = MSG_ReadLong ( ) ; //delta sequence number (must be acked)
if ( cl . ackframes_count < sizeof ( cl . ackframes ) / sizeof ( cl . ackframes [ 0 ] ) )
cl . ackframes [ cl . ackframes_count + + ] = ack ;
2020-09-04 11:18:05 +00:00
cl . ackedmovemessages = MSG_ReadLong ( ) ; //input sequence ack
if ( cl . qcvm . extglobals . servercommandframe )
* cl . qcvm . extglobals . servercommandframe = cl . ackedmovemessages ;
2017-09-17 02:12:53 +00:00
for ( ; ; )
{
id = MSG_ReadShort ( ) ;
if ( msg_badread )
break ;
if ( id & 0x8000 )
{
id & = ~ 0x8000 ;
if ( ! id )
break ; //no more
ent = CL_EntityNum ( id ) ;
ent - > update_type = false ;
ent - > model = NULL ;
}
else
{
ent = CL_EntityNum ( id ) ;
CLDP_ReadDelta ( id , & ent - > netstate , ent - > update_type ? & ent - > netstate : NULL , & ent - > baseline ) ;
ent - > update_type = true ;
}
}
if ( cls . signon = = SIGNONS - 1 )
{ // first update is the final signon stage
cls . signon = SIGNONS ;
CL_SignonReply ( ) ;
}
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
CL_ParseStartSoundPacket
= = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
static void CL_ParseStartSoundPacket ( void )
2010-02-15 23:26:55 +00:00
{
2011-12-29 19:06:08 +00:00
vec3_t pos ;
int channel , ent ;
int sound_num ;
int volume ;
int field_mask ;
float attenuation ;
int i ;
2010-02-15 23:26:55 +00:00
2011-12-29 19:06:08 +00:00
field_mask = MSG_ReadByte ( ) ;
2010-02-15 23:26:55 +00:00
2017-09-17 02:12:53 +00:00
if ( cl . protocol = = PROTOCOL_VERSION_BJP3 )
field_mask | = SND_LARGESOUND ;
//spike -- extra channel flags
if ( field_mask & SND_FTE_MOREFLAGS )
field_mask | = MSG_ReadByte ( ) < < 8 ;
2011-12-29 19:06:08 +00:00
if ( field_mask & SND_VOLUME )
2010-02-15 23:26:55 +00:00
volume = MSG_ReadByte ( ) ;
else
volume = DEFAULT_SOUND_PACKET_VOLUME ;
2011-12-29 19:06:08 +00:00
if ( field_mask & SND_ATTENUATION )
2010-02-15 23:26:55 +00:00
attenuation = MSG_ReadByte ( ) / 64.0 ;
else
attenuation = DEFAULT_SOUND_PACKET_ATTENUATION ;
2017-09-17 02:12:53 +00:00
//fte's sound extensions
if ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS )
{
//spike -- our mixer can't deal with these, so just parse and ignore
if ( field_mask & SND_FTE_PITCHADJ )
MSG_ReadByte ( ) ; //percentage
if ( field_mask & SND_FTE_TIMEOFS )
MSG_ReadShort ( ) ; //in ms
if ( field_mask & SND_FTE_VELOCITY )
{
MSG_ReadShort ( ) ; //1/8th
MSG_ReadShort ( ) ; //1/8th
MSG_ReadShort ( ) ; //1/8th
}
}
else if ( field_mask & ( SND_FTE_MOREFLAGS | SND_FTE_PITCHADJ | SND_FTE_TIMEOFS ) )
Con_Warning ( " Unknown meaning for sound flags \n " ) ;
//dp's sound extension
if ( cl . protocol = = PROTOCOL_VERSION_DP7 | | ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS ) )
{
if ( field_mask & SND_DP_PITCH )
MSG_ReadShort ( ) ;
}
else if ( field_mask & SND_DP_PITCH )
Con_Warning ( " Unknown meaning for sound flags \n " ) ;
2010-02-15 23:26:55 +00:00
//johnfitz -- PROTOCOL_FITZQUAKE
if ( field_mask & SND_LARGEENTITY )
{
ent = ( unsigned short ) MSG_ReadShort ( ) ;
channel = MSG_ReadByte ( ) ;
}
else
{
channel = ( unsigned short ) MSG_ReadShort ( ) ;
ent = channel > > 3 ;
channel & = 7 ;
}
if ( field_mask & SND_LARGESOUND )
sound_num = ( unsigned short ) MSG_ReadShort ( ) ;
else
sound_num = MSG_ReadByte ( ) ;
//johnfitz
//johnfitz -- check soundnum
if ( sound_num > = MAX_SOUNDS )
Host_Error ( " CL_ParseStartSoundPacket: %i > MAX_SOUNDS " , sound_num ) ;
//johnfitz
2017-09-17 02:12:53 +00:00
if ( ent > cl . max_edicts ) //johnfitz -- no more MAX_EDICTS
2010-02-15 23:26:55 +00:00
Host_Error ( " CL_ParseStartSoundPacket: ent = %i " , ent ) ;
2011-12-29 19:06:08 +00:00
for ( i = 0 ; i < 3 ; i + + )
2016-06-24 06:15:41 +00:00
pos [ i ] = MSG_ReadCoord ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
2011-12-29 19:06:08 +00:00
S_StartSound ( ent , channel , cl . sound_precache [ sound_num ] , pos , volume / 255.0 , attenuation ) ;
2010-02-15 23:26:55 +00:00
}
2017-09-17 02:12:53 +00:00
#if 0
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = =
CL_KeepaliveMessage
When the client is taking a long time to load stuff , send keepalive messages
so the server doesn ' t disconnect .
= = = = = = = = = = = = = = = = = =
*/
2011-04-08 06:01:39 +00:00
static byte net_olddata [ NET_MAXMESSAGE ] ;
2017-09-17 02:12:53 +00:00
static void CL_KeepaliveMessage ( void )
2010-02-15 23:26:55 +00:00
{
float time ;
static float lastmsg ;
int ret ;
sizebuf_t old ;
2011-04-08 06:01:39 +00:00
byte * olddata ;
2010-02-15 23:26:55 +00:00
if ( sv . active )
return ; // no need if server is local
if ( cls . demoplayback )
return ;
// read messages from server, should just be nops
2011-04-08 06:01:39 +00:00
olddata = net_olddata ;
2010-02-15 23:26:55 +00:00
old = net_message ;
memcpy ( olddata , net_message . data , net_message . cursize ) ;
do
{
ret = CL_GetMessage ( ) ;
switch ( ret )
{
default :
Host_Error ( " CL_KeepaliveMessage: CL_GetMessage failed " ) ;
case 0 :
break ; // nothing waiting
case 1 :
Host_Error ( " CL_KeepaliveMessage: received a message " ) ;
break ;
case 2 :
if ( MSG_ReadByte ( ) ! = svc_nop )
Host_Error ( " CL_KeepaliveMessage: datagram wasn't a nop " ) ;
break ;
}
} while ( ret ) ;
net_message = old ;
memcpy ( net_message . data , olddata , net_message . cursize ) ;
// check time
2011-12-12 16:01:01 +00:00
time = Sys_DoubleTime ( ) ;
2010-02-15 23:26:55 +00:00
if ( time - lastmsg < 5 )
return ;
lastmsg = time ;
// write out a nop
Con_Printf ( " --> client to server keepalive \n " ) ;
MSG_WriteByte ( & cls . message , clc_nop ) ;
NET_SendMessage ( cls . netcon , & cls . message ) ;
SZ_Clear ( & cls . message ) ;
}
2017-09-17 02:12:53 +00:00
# endif
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = =
CL_ParseServerInfo
= = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
static void CL_ParseServerInfo ( void )
2010-02-15 23:26:55 +00:00
{
2010-08-29 02:22:55 +00:00
const char * str ;
2010-02-15 23:26:55 +00:00
int i ;
2017-09-17 02:12:53 +00:00
qboolean gamedirswitchwarning = false ;
char gamedir [ 1024 ] ;
char protname [ 64 ] ;
2010-02-15 23:26:55 +00:00
Con_DPrintf ( " Serverinfo packet received. \n " ) ;
2014-08-25 02:55:25 +00:00
// ericw -- bring up loading plaque for map changes within a demo.
// it will be hidden in CL_SignonReply.
if ( cls . demoplayback )
SCR_BeginLoadingPlaque ( ) ;
2010-02-15 23:26:55 +00:00
//
// wipe the client_state_t struct
//
2017-09-17 02:12:53 +00:00
i = cl . protocol_dpdownload ; //for some absurd reason, this is sent just before the serverinfo, which just confuses everything.
2010-02-15 23:26:55 +00:00
CL_ClearState ( ) ;
2017-09-17 02:12:53 +00:00
cl . protocol_dpdownload = i ;
2010-02-15 23:26:55 +00:00
// parse protocol version number
2017-09-17 02:12:53 +00:00
for ( ; ; )
{
i = MSG_ReadLong ( ) ;
2018-10-16 19:36:23 +00:00
if ( i = = PROTOCOL_FTE_PEXT1 )
{
2020-09-03 08:37:49 +00:00
cl . protocol_pext1 = MSG_ReadLong ( ) ;
if ( cl . protocol_pext1 & ~ PEXT1_ACCEPTED_CLIENT )
Host_Error ( " Server returned FTE1 protocol extensions that are not supported (%#x) " , cl . protocol_pext1 & ~ PEXT1_SUPPORTED_CLIENT ) ;
2018-10-16 19:36:23 +00:00
continue ;
}
2017-09-17 02:12:53 +00:00
if ( i = = PROTOCOL_FTE_PEXT2 )
{
cl . protocol_pext2 = MSG_ReadLong ( ) ;
2018-10-16 19:36:23 +00:00
if ( cl . protocol_pext2 & ~ PEXT2_ACCEPTED_CLIENT )
Host_Error ( " Server returned FTE2 protocol extensions that are not supported (%#x) " , cl . protocol_pext2 & ~ PEXT2_SUPPORTED_CLIENT ) ;
2017-09-17 02:12:53 +00:00
continue ;
}
break ;
}
2010-02-15 23:26:55 +00:00
//johnfitz -- support multiple protocols
2017-09-17 02:12:53 +00:00
if ( i ! = PROTOCOL_NETQUAKE & & i ! = PROTOCOL_FITZQUAKE & & i ! = PROTOCOL_RMQ & & i ! = PROTOCOL_VERSION_BJP3 & & i ! = PROTOCOL_VERSION_DP7 ) {
2013-10-18 10:43:54 +00:00
Con_Printf ( " \n " ) ; //because there's no newline after serverinfo print
2016-06-24 06:15:41 +00:00
Host_Error ( " Server returned version %i, not %i or %i or %i " , i , PROTOCOL_NETQUAKE , PROTOCOL_FITZQUAKE , PROTOCOL_RMQ ) ;
2010-02-15 23:26:55 +00:00
}
cl . protocol = i ;
//johnfitz
2016-06-24 06:15:41 +00:00
if ( cl . protocol = = PROTOCOL_RMQ )
{
const unsigned int supportedflags = ( PRFL_SHORTANGLE | PRFL_FLOATANGLE | PRFL_24BITCOORD | PRFL_FLOATCOORD | PRFL_EDICTSCALE | PRFL_INT32COORD ) ;
// mh - read protocol flags from server so that we know what protocol features to expect
cl . protocolflags = ( unsigned int ) MSG_ReadLong ( ) ;
if ( 0 ! = ( cl . protocolflags & ( ~ supportedflags ) ) )
{
Con_Warning ( " PROTOCOL_RMQ protocolflags %i contains unsupported flags \n " , cl . protocolflags ) ;
}
}
2017-09-17 02:12:53 +00:00
else if ( cl . protocol = = PROTOCOL_VERSION_DP7 )
cl . protocolflags = PRFL_SHORTANGLE | PRFL_FLOATCOORD ;
2016-06-24 06:15:41 +00:00
else cl . protocolflags = 0 ;
2017-09-17 02:12:53 +00:00
* gamedir = 0 ;
if ( cl . protocol_pext2 & PEXT2_PREDINFO )
{
q_strlcpy ( gamedir , MSG_ReadString ( ) , sizeof ( gamedir ) ) ;
if ( ! COM_GameDirMatches ( gamedir ) )
{
gamedirswitchwarning = true ;
}
}
2010-02-15 23:26:55 +00:00
// parse maxclients
cl . maxclients = MSG_ReadByte ( ) ;
if ( cl . maxclients < 1 | | cl . maxclients > MAX_SCOREBOARD )
{
2013-10-18 10:43:54 +00:00
Host_Error ( " Bad maxclients (%u) from server " , cl . maxclients ) ;
2010-02-15 23:26:55 +00:00
}
host_cmd.c, console.c, gl_draw.c, image.c, gl_model.c, r_sprite.c, cl_parse.c,
gl_warp.c, host.c, gl_mesh.c, gl_sky.c, gl_texmgr.c, cvar.c, sv_main.c, cvar.h,
gl_screen.c, r_brush.c, gl_vidsdl.c, zone.c, cl_main.c, cmd.c, snd_dma.c,
snd_mem.c, common.c, sv_phys.c: Added explicit casts to eliminate -Wc++-compat
warnings.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@170 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-05-31 07:42:36 +00:00
cl . scores = ( scoreboard_t * ) Hunk_AllocName ( cl . maxclients * sizeof ( * cl . scores ) , " scores " ) ;
2010-02-15 23:26:55 +00:00
// parse gametype
cl . gametype = MSG_ReadByte ( ) ;
// parse signon message
str = MSG_ReadString ( ) ;
2011-12-27 13:15:31 +00:00
q_strlcpy ( cl . levelname , str , sizeof ( cl . levelname ) ) ;
2010-02-15 23:26:55 +00:00
// seperate the printfs so the server message can have a color
Con_Printf ( " \n %s \n " , Con_Quakebar ( 40 ) ) ; //johnfitz
Con_Printf ( " %c%s \n " , 2 , str ) ;
//johnfitz -- tell user which protocol this is
2017-09-17 02:12:53 +00:00
if ( developer . value )
{
//spike: be a little more verbose about it
switch ( cl . protocol )
{
case PROTOCOL_VERSION_DP7 :
q_snprintf ( protname , sizeof ( protname ) , " %i(dpp7) " , cl . protocol ) ;
break ;
case PROTOCOL_VERSION_BJP3 :
q_snprintf ( protname , sizeof ( protname ) , " %i(bjp3) " , cl . protocol ) ;
break ;
case PROTOCOL_RMQ :
q_snprintf ( protname , sizeof ( protname ) , " %i(rmq) " , cl . protocol ) ;
break ;
case PROTOCOL_FITZQUAKE :
q_snprintf ( protname , sizeof ( protname ) , " %i(fitz) " , cl . protocol ) ;
break ;
case PROTOCOL_NETQUAKE :
if ( NET_QSocketGetProQuakeAngleHack ( cls . netcon ) )
q_snprintf ( protname , sizeof ( protname ) , " %i(proquake) " , cl . protocol ) ;
else
q_snprintf ( protname , sizeof ( protname ) , " %i(vanilla) " , cl . protocol ) ;
break ;
default :
q_snprintf ( protname , sizeof ( protname ) , " %i " , cl . protocol ) ;
break ;
}
if ( cl . protocol_pext2 )
{
if ( cl . protocol = = PROTOCOL_NETQUAKE )
* protname = 0 ;
else
q_strlcat ( protname , " + " , sizeof ( protname ) ) ;
q_strlcat ( protname , va ( " fte2(%#x) " , cl . protocol_pext2 ) , sizeof ( protname ) ) ;
}
}
else if ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS )
q_snprintf ( protname , sizeof ( protname ) , " fte%i " , cl . protocol ) ;
else
q_snprintf ( protname , sizeof ( protname ) , " %i " , cl . protocol ) ;
Con_Printf ( " Using protocol %s " , protname ) ;
Con_Printf ( " \n " ) ;
2010-02-15 23:26:55 +00:00
// first we go through and touch all of the precache data that still
// happens to be in the cache, so precaching something else doesn't
// needlessly purge it
// precache models
memset ( cl . model_precache , 0 , sizeof ( cl . model_precache ) ) ;
2017-09-17 02:12:53 +00:00
for ( cl . model_count = 1 ; ; cl . model_count + + )
2010-02-15 23:26:55 +00:00
{
str = MSG_ReadString ( ) ;
if ( ! str [ 0 ] )
break ;
2017-09-17 02:12:53 +00:00
if ( cl . model_count = = MAX_MODELS )
2010-02-15 23:26:55 +00:00
{
2013-10-18 10:43:54 +00:00
Host_Error ( " Server sent too many model precaches " ) ;
2010-02-15 23:26:55 +00:00
}
2017-09-17 02:12:53 +00:00
q_strlcpy ( cl . model_name [ cl . model_count ] , str , MAX_QPATH ) ;
2010-02-15 23:26:55 +00:00
Mod_TouchModel ( str ) ;
}
//johnfitz -- check for excessive models
2017-09-17 02:12:53 +00:00
if ( cl . model_count > = 256 )
Con_DWarning ( " %i models exceeds standard limit of 256 (max = %d). \n " , cl . model_count , MAX_MODELS ) ;
2010-02-15 23:26:55 +00:00
//johnfitz
// precache sounds
memset ( cl . sound_precache , 0 , sizeof ( cl . sound_precache ) ) ;
2017-09-17 02:12:53 +00:00
for ( cl . sound_count = 1 ; ; cl . sound_count + + )
2010-02-15 23:26:55 +00:00
{
str = MSG_ReadString ( ) ;
if ( ! str [ 0 ] )
break ;
2017-09-17 02:12:53 +00:00
if ( cl . sound_count = = MAX_SOUNDS )
2010-02-15 23:26:55 +00:00
{
2013-10-18 10:43:54 +00:00
Host_Error ( " Server sent too many sound precaches " ) ;
2010-02-15 23:26:55 +00:00
}
2017-09-17 02:12:53 +00:00
q_strlcpy ( cl . sound_name [ cl . sound_count ] , str , MAX_QPATH ) ;
2010-02-15 23:26:55 +00:00
S_TouchSound ( str ) ;
}
//johnfitz -- check for excessive sounds
2017-09-17 02:12:53 +00:00
if ( cl . sound_count > = 256 )
Con_DWarning ( " %i sounds exceeds standard limit of 256 (max = %d). \n " , cl . sound_count , MAX_SOUNDS ) ;
2010-02-15 23:26:55 +00:00
//
// now we try to load everything else until a cache allocation fails
//
2010-02-16 09:47:04 +00:00
// copy the naked name of the map file to the cl structure -- O.S
2017-09-17 02:12:53 +00:00
COM_StripExtension ( COM_SkipPath ( cl . model_name [ 1 ] ) , cl . mapname , sizeof ( cl . mapname ) ) ;
2010-02-15 23:26:55 +00:00
//johnfitz -- clear out string; we don't consider identical
//messages to be duplicates if the map has changed in between
con_lastcenterstring [ 0 ] = 0 ;
//johnfitz
Hunk_Check ( ) ; // make sure nothing is hurt
noclip_anglehack = false ; // noclip is turned off at start
warn_about_nehahra_protocol = true ; //johnfitz -- warn about nehahra protocol hack once per server connection
//johnfitz -- reset developer stats
memset ( & dev_stats , 0 , sizeof ( dev_stats ) ) ;
memset ( & dev_peakstats , 0 , sizeof ( dev_peakstats ) ) ;
memset ( & dev_overflows , 0 , sizeof ( dev_overflows ) ) ;
2017-09-17 02:12:53 +00:00
cl . requestresend = true ;
cl . ackframes_count = 0 ;
if ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS )
cl . ackframes [ cl . ackframes_count + + ] = - 1 ;
//this is here, to try to make sure its a little more obvious that its there.
if ( gamedirswitchwarning )
{
Con_Warning ( " Server is using a different gamedir. \n " ) ;
Con_Warning ( " Current: %s \n " , COM_GetGameNames ( false ) ) ;
Con_Warning ( " Server: %s \n " , gamedir ) ;
Con_Warning ( " You will probably want to switch gamedir to match the server. \n " ) ;
}
S_Voip_MapChange ( ) ;
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
CL_ParseUpdate
Parse an entity update message from the server
If an entities model or origin changes from frame to frame , it must be
relinked . Other attributes can change without relinking .
= = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
static void CL_ParseUpdate ( int bits )
2010-02-15 23:26:55 +00:00
{
2011-12-13 19:00:25 +00:00
int i ;
2012-05-30 08:56:06 +00:00
qmodel_t * model ;
2018-07-19 21:02:25 +00:00
unsigned int modnum ;
2010-02-15 23:26:55 +00:00
qboolean forcelink ;
entity_t * ent ;
2011-12-13 19:00:25 +00:00
int num ;
int skin ;
2010-02-15 23:26:55 +00:00
if ( cls . signon = = SIGNONS - 1 )
{ // first update is the final signon stage
cls . signon = SIGNONS ;
CL_SignonReply ( ) ;
}
if ( bits & U_MOREBITS )
{
i = MSG_ReadByte ( ) ;
bits | = ( i < < 8 ) ;
}
//johnfitz -- PROTOCOL_FITZQUAKE
2016-06-24 06:15:41 +00:00
if ( cl . protocol = = PROTOCOL_FITZQUAKE | | cl . protocol = = PROTOCOL_RMQ )
2010-02-15 23:26:55 +00:00
{
if ( bits & U_EXTEND1 )
bits | = MSG_ReadByte ( ) < < 16 ;
if ( bits & U_EXTEND2 )
bits | = MSG_ReadByte ( ) < < 24 ;
}
//johnfitz
if ( bits & U_LONGENTITY )
num = MSG_ReadShort ( ) ;
else
num = MSG_ReadByte ( ) ;
ent = CL_EntityNum ( num ) ;
if ( ent - > msgtime ! = cl . mtime [ 1 ] )
forcelink = true ; // no previous frame to lerp from
else
forcelink = false ;
//johnfitz -- lerping
if ( ent - > msgtime + 0.2 < cl . mtime [ 0 ] ) //more than 0.2 seconds since the last message (most entities think every 0.1 sec)
ent - > lerpflags | = LERP_RESETANIM ; //if we missed a think, we'd be lerping from the wrong frame
//johnfitz
ent - > msgtime = cl . mtime [ 0 ] ;
2021-03-21 14:13:20 +00:00
//copy the baseline into the netstate for the rest of the code to use.
//do NOT copy the origin/angles values, so we don't forget them when hipnotic sends a random pointless fastupdate[playerent] at us with its angles. this way our deltas won't forget it.
//we don't worry too much about extension stuff going stale, because mods tend not to know about that stuff anyway.
# define netstate_start offsetof(entity_state_t, scale)
memcpy ( ( char * ) & ent - > netstate + offsetof ( entity_state_t , modelindex ) , ( const char * ) & ent - > baseline + offsetof ( entity_state_t , modelindex ) , sizeof ( ent - > baseline ) - offsetof ( entity_state_t , modelindex ) ) ;
2010-02-15 23:26:55 +00:00
if ( bits & U_MODEL )
{
2017-09-17 02:12:53 +00:00
if ( cl . protocol = = PROTOCOL_VERSION_BJP3 )
modnum = MSG_ReadShort ( ) ;
else
modnum = MSG_ReadByte ( ) ;
2010-02-15 23:26:55 +00:00
if ( modnum > = MAX_MODELS )
Host_Error ( " CL_ParseModel: bad modnum " ) ;
}
else
modnum = ent - > baseline . modelindex ;
if ( bits & U_FRAME )
ent - > frame = MSG_ReadByte ( ) ;
else
ent - > frame = ent - > baseline . frame ;
if ( bits & U_COLORMAP )
2020-09-03 09:59:23 +00:00
ent - > netstate . colormap = MSG_ReadByte ( ) ;
2010-02-15 23:26:55 +00:00
if ( bits & U_SKIN )
skin = MSG_ReadByte ( ) ;
else
skin = ent - > baseline . skin ;
2011-12-29 19:06:08 +00:00
if ( skin ! = ent - > skinnum )
{
2010-02-15 23:26:55 +00:00
ent - > skinnum = skin ;
if ( num > 0 & & num < = cl . maxclients )
R_TranslateNewPlayerSkin ( num - 1 ) ; //johnfitz -- was R_TranslatePlayerSkin
}
if ( bits & U_EFFECTS )
ent - > effects = MSG_ReadByte ( ) ;
else
ent - > effects = ent - > baseline . effects ;
// shift the known values for interpolation
VectorCopy ( ent - > msg_origins [ 0 ] , ent - > msg_origins [ 1 ] ) ;
VectorCopy ( ent - > msg_angles [ 0 ] , ent - > msg_angles [ 1 ] ) ;
if ( bits & U_ORIGIN1 )
2016-06-24 06:15:41 +00:00
ent - > msg_origins [ 0 ] [ 0 ] = MSG_ReadCoord ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
else
ent - > msg_origins [ 0 ] [ 0 ] = ent - > baseline . origin [ 0 ] ;
if ( bits & U_ANGLE1 )
2016-06-24 06:15:41 +00:00
ent - > msg_angles [ 0 ] [ 0 ] = MSG_ReadAngle ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
else
ent - > msg_angles [ 0 ] [ 0 ] = ent - > baseline . angles [ 0 ] ;
if ( bits & U_ORIGIN2 )
2016-06-24 06:15:41 +00:00
ent - > msg_origins [ 0 ] [ 1 ] = MSG_ReadCoord ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
else
ent - > msg_origins [ 0 ] [ 1 ] = ent - > baseline . origin [ 1 ] ;
if ( bits & U_ANGLE2 )
2016-06-24 06:15:41 +00:00
ent - > msg_angles [ 0 ] [ 1 ] = MSG_ReadAngle ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
else
ent - > msg_angles [ 0 ] [ 1 ] = ent - > baseline . angles [ 1 ] ;
if ( bits & U_ORIGIN3 )
2016-06-24 06:15:41 +00:00
ent - > msg_origins [ 0 ] [ 2 ] = MSG_ReadCoord ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
else
ent - > msg_origins [ 0 ] [ 2 ] = ent - > baseline . origin [ 2 ] ;
if ( bits & U_ANGLE3 )
2016-06-24 06:15:41 +00:00
ent - > msg_angles [ 0 ] [ 2 ] = MSG_ReadAngle ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
else
ent - > msg_angles [ 0 ] [ 2 ] = ent - > baseline . angles [ 2 ] ;
//johnfitz -- lerping for movetype_step entities
2011-12-29 19:06:08 +00:00
if ( bits & U_STEP )
2010-02-15 23:26:55 +00:00
{
ent - > lerpflags | = LERP_MOVESTEP ;
ent - > forcelink = true ;
}
else
ent - > lerpflags & = ~ LERP_MOVESTEP ;
//johnfitz
//johnfitz -- PROTOCOL_FITZQUAKE and PROTOCOL_NEHAHRA
2016-06-24 06:15:41 +00:00
if ( cl . protocol = = PROTOCOL_FITZQUAKE | | cl . protocol = = PROTOCOL_RMQ )
2010-02-15 23:26:55 +00:00
{
if ( bits & U_ALPHA )
ent - > alpha = MSG_ReadByte ( ) ;
else
ent - > alpha = ent - > baseline . alpha ;
2016-06-24 06:15:41 +00:00
if ( bits & U_SCALE )
2017-09-17 02:12:53 +00:00
ent - > netstate . scale = MSG_ReadByte ( ) ; // PROTOCOL_RMQ
2010-02-15 23:26:55 +00:00
if ( bits & U_FRAME2 )
ent - > frame = ( ent - > frame & 0x00FF ) | ( MSG_ReadByte ( ) < < 8 ) ;
if ( bits & U_MODEL2 )
2018-07-19 21:02:25 +00:00
{
2010-02-15 23:26:55 +00:00
modnum = ( modnum & 0x00FF ) | ( MSG_ReadByte ( ) < < 8 ) ;
2018-07-19 21:02:25 +00:00
if ( modnum > = MAX_MODELS )
Host_Error ( " CL_ParseModel: bad modnum " ) ;
}
2010-02-15 23:26:55 +00:00
if ( bits & U_LERPFINISH )
{
ent - > lerpfinish = ent - > msgtime + ( ( float ) ( MSG_ReadByte ( ) ) / 255 ) ;
ent - > lerpflags | = LERP_FINISH ;
}
else
ent - > lerpflags & = ~ LERP_FINISH ;
}
2017-09-17 02:12:53 +00:00
else if ( cl . protocol = = PROTOCOL_NETQUAKE | | cl . protocol = = PROTOCOL_VERSION_BJP3 )
2010-02-15 23:26:55 +00:00
{
2017-09-17 02:12:53 +00:00
//HACK: if this bit is set, assume this is PROTOCOL_NEHAHRA instead of PROTOCOL_NETQUAKE
2010-02-15 23:26:55 +00:00
if ( bits & U_TRANS )
{
2011-12-29 19:06:08 +00:00
float a , b ;
2010-02-15 23:26:55 +00:00
2017-09-17 02:12:53 +00:00
if ( cl . protocol = = PROTOCOL_NETQUAKE & & warn_about_nehahra_protocol )
2011-12-29 19:06:08 +00:00
{
2010-02-15 23:26:55 +00:00
Con_Warning ( " nonstandard update bit, assuming Nehahra protocol \n " ) ;
warn_about_nehahra_protocol = false ;
}
a = MSG_ReadFloat ( ) ;
b = MSG_ReadFloat ( ) ; //alpha
if ( a = = 2 )
2017-09-17 02:12:53 +00:00
{
if ( MSG_ReadFloat ( ) > = 0.5 ) //parse fullbright, even if we don't use it yet.
ent - > effects | = EF_FULLBRIGHT ;
}
2010-02-15 23:26:55 +00:00
ent - > alpha = ENTALPHA_ENCODE ( b ) ;
}
else
ent - > alpha = ent - > baseline . alpha ;
}
2017-09-17 02:12:53 +00:00
else
ent - > alpha = ent - > baseline . alpha ;
2010-02-15 23:26:55 +00:00
//johnfitz
2018-10-16 19:36:23 +00:00
2010-02-15 23:26:55 +00:00
//johnfitz -- moved here from above
model = cl . model_precache [ modnum ] ;
if ( model ! = ent - > model )
{
ent - > model = model ;
// automatic animation (torches, etc) can be either all together
// or randomized
if ( model )
{
if ( model - > synctype = = ST_RAND )
ent - > syncbase = ( float ) ( rand ( ) & 0x7fff ) / 0x7fff ;
else
ent - > syncbase = 0.0 ;
}
else
forcelink = true ; // hack to make null model players work
if ( num > 0 & & num < = cl . maxclients )
R_TranslateNewPlayerSkin ( num - 1 ) ; //johnfitz -- was R_TranslatePlayerSkin
ent - > lerpflags | = LERP_RESETANIM ; //johnfitz -- don't lerp animation across model changes
}
//johnfitz
if ( forcelink )
{ // didn't have an update last message
VectorCopy ( ent - > msg_origins [ 0 ] , ent - > msg_origins [ 1 ] ) ;
VectorCopy ( ent - > msg_origins [ 0 ] , ent - > origin ) ;
VectorCopy ( ent - > msg_angles [ 0 ] , ent - > msg_angles [ 1 ] ) ;
VectorCopy ( ent - > msg_angles [ 0 ] , ent - > angles ) ;
ent - > forcelink = true ;
}
}
/*
= = = = = = = = = = = = = = = = = =
CL_ParseBaseline
= = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
static void CL_ParseBaseline ( entity_t * ent , int version ) //johnfitz -- added argument
2010-02-15 23:26:55 +00:00
{
int i ;
int bits ; //johnfitz
2017-09-17 02:12:53 +00:00
if ( version = = 6 )
{
CLFTE_ParseBaseline ( & ent - > baseline ) ;
return ;
}
ent - > baseline = nullentitystate ;
2010-02-15 23:26:55 +00:00
//johnfitz -- PROTOCOL_FITZQUAKE
2017-09-17 02:12:53 +00:00
if ( cl . protocol = = PROTOCOL_VERSION_BJP3 & & version = = 1 )
bits = B_LARGEMODEL ;
else if ( version = = 7 )
bits = B_LARGEMODEL | B_LARGEFRAME ; //dpp7's spawnstatic2
else
bits = ( version = = 2 ) ? MSG_ReadByte ( ) : 0 ;
2010-02-15 23:26:55 +00:00
ent - > baseline . modelindex = ( bits & B_LARGEMODEL ) ? MSG_ReadShort ( ) : MSG_ReadByte ( ) ;
ent - > baseline . frame = ( bits & B_LARGEFRAME ) ? MSG_ReadShort ( ) : MSG_ReadByte ( ) ;
//johnfitz
ent - > baseline . colormap = MSG_ReadByte ( ) ;
ent - > baseline . skin = MSG_ReadByte ( ) ;
2011-12-29 19:06:08 +00:00
for ( i = 0 ; i < 3 ; i + + )
2010-02-15 23:26:55 +00:00
{
2016-06-24 06:15:41 +00:00
ent - > baseline . origin [ i ] = MSG_ReadCoord ( cl . protocolflags ) ;
ent - > baseline . angles [ i ] = MSG_ReadAngle ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
}
ent - > baseline . alpha = ( bits & B_ALPHA ) ? MSG_ReadByte ( ) : ENTALPHA_DEFAULT ; //johnfitz -- PROTOCOL_FITZQUAKE
}
2020-10-13 17:07:57 +00:00
# define CL_SetStati(stat, val) cl.statsf[stat] = (cl.stats[stat] = val)
# define CL_SetHudStat(stat, val) if (cl.stats[stat] != val)Sbar_Changed(); CL_SetStati(stat,val)
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = =
CL_ParseClientdata
Server information pertaining to this client only
2020-10-13 17:07:57 +00:00
Spike - - tweaked this function to ensure float stats get set as well as int ones ( so csqc can ' t get confused ) .
2010-02-15 23:26:55 +00:00
= = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
static void CL_ParseClientdata ( void )
2010-02-15 23:26:55 +00:00
{
2020-10-13 17:07:57 +00:00
int i ;
2010-02-15 23:26:55 +00:00
int bits ; //johnfitz
bits = ( unsigned short ) MSG_ReadShort ( ) ; //johnfitz -- read bits here isntead of in CL_ParseServerMessage()
//johnfitz -- PROTOCOL_FITZQUAKE
if ( bits & SU_EXTEND1 )
bits | = ( MSG_ReadByte ( ) < < 16 ) ;
if ( bits & SU_EXTEND2 )
bits | = ( MSG_ReadByte ( ) < < 24 ) ;
//johnfitz
2017-09-17 02:12:53 +00:00
if ( cl . protocol ! = PROTOCOL_VERSION_DP7 )
bits | = SU_ITEMS ;
2010-02-15 23:26:55 +00:00
if ( bits & SU_VIEWHEIGHT )
2020-10-13 17:07:57 +00:00
CL_SetStati ( STAT_VIEWHEIGHT , MSG_ReadChar ( ) ) ;
2017-09-17 02:12:53 +00:00
else if ( cl . protocol ! = PROTOCOL_VERSION_DP7 )
2020-10-13 17:07:57 +00:00
CL_SetStati ( STAT_VIEWHEIGHT , DEFAULT_VIEWHEIGHT ) ;
2010-02-15 23:26:55 +00:00
if ( bits & SU_IDEALPITCH )
2020-10-13 17:07:57 +00:00
CL_SetStati ( STAT_IDEALPITCH , MSG_ReadChar ( ) ) ;
2010-02-15 23:26:55 +00:00
else
2020-10-13 17:07:57 +00:00
CL_SetStati ( STAT_IDEALPITCH , 0 ) ;
2010-02-15 23:26:55 +00:00
VectorCopy ( cl . mvelocity [ 0 ] , cl . mvelocity [ 1 ] ) ;
2011-12-29 19:06:08 +00:00
for ( i = 0 ; i < 3 ; i + + )
2010-02-15 23:26:55 +00:00
{
if ( bits & ( SU_PUNCH1 < < i ) )
2017-09-17 02:12:53 +00:00
cl . punchangle [ i ] = ( cl . protocol = = PROTOCOL_VERSION_DP7 ) ? MSG_ReadAngle ( PRFL_SHORTANGLE ) : MSG_ReadChar ( ) ;
2010-02-15 23:26:55 +00:00
else
cl . punchangle [ i ] = 0 ;
2017-09-17 02:12:53 +00:00
if ( cl . protocol = = PROTOCOL_VERSION_DP7 )
if ( bits & ( DPSU_PUNCHVEC1 < < i ) )
/*cl.punchvector[i] = */ MSG_ReadCoord ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
if ( bits & ( SU_VELOCITY1 < < i ) )
2017-09-17 02:12:53 +00:00
cl . mvelocity [ 0 ] [ i ] = ( cl . protocol = = PROTOCOL_VERSION_DP7 ) ? MSG_ReadFloat ( ) : ( MSG_ReadChar ( ) * 16 ) ;
2010-02-15 23:26:55 +00:00
else
cl . mvelocity [ 0 ] [ i ] = 0 ;
}
//johnfitz -- update v_punchangles
if ( v_punchangles [ 0 ] [ 0 ] ! = cl . punchangle [ 0 ] | | v_punchangles [ 0 ] [ 1 ] ! = cl . punchangle [ 1 ] | | v_punchangles [ 0 ] [ 2 ] ! = cl . punchangle [ 2 ] )
{
2020-10-13 17:07:57 +00:00
v_punchangles_times [ 1 ] = v_punchangles_times [ 0 ] ;
v_punchangles_times [ 0 ] = cl . mtime [ 0 ] ;
2010-02-15 23:26:55 +00:00
VectorCopy ( v_punchangles [ 0 ] , v_punchangles [ 1 ] ) ;
VectorCopy ( cl . punchangle , v_punchangles [ 0 ] ) ;
}
//johnfitz
2017-09-17 02:12:53 +00:00
if ( bits & SU_ITEMS )
2020-10-13 17:07:57 +00:00
CL_SetStati ( STAT_ITEMS , MSG_ReadLong ( ) ) ;
2010-02-15 23:26:55 +00:00
cl . onground = ( bits & SU_ONGROUND ) ! = 0 ;
cl . inwater = ( bits & SU_INWATER ) ! = 0 ;
2017-09-17 02:12:53 +00:00
if ( cl . protocol = = PROTOCOL_VERSION_DP7 )
{ //dpp7 doesn't really send much here, instead using deltas.
cl . viewent . alpha = ENTALPHA_DEFAULT ;
2010-02-15 23:26:55 +00:00
}
else
{
2020-10-13 17:07:57 +00:00
unsigned short weaponframe = 0 ;
unsigned short armourval = 0 ;
unsigned short weaponmodel = 0 ;
unsigned int activeweapon ;
short health ;
unsigned short ammo ;
unsigned short ammovals [ 4 ] ;
2010-02-15 23:26:55 +00:00
2020-10-13 17:07:57 +00:00
if ( bits & SU_WEAPONFRAME )
weaponframe = MSG_ReadByte ( ) ;
2017-09-17 02:12:53 +00:00
if ( bits & SU_ARMOR )
2020-10-13 17:07:57 +00:00
armourval = MSG_ReadByte ( ) ;
2017-09-17 02:12:53 +00:00
if ( bits & SU_WEAPON )
{
if ( cl . protocol = = PROTOCOL_VERSION_BJP3 )
2020-10-13 17:07:57 +00:00
weaponmodel = MSG_ReadShort ( ) ;
2017-09-17 02:12:53 +00:00
else
2020-10-13 17:07:57 +00:00
weaponmodel = MSG_ReadByte ( ) ;
2010-02-15 23:26:55 +00:00
}
2020-10-13 17:07:57 +00:00
health = MSG_ReadShort ( ) ;
ammo = MSG_ReadByte ( ) ;
2017-09-17 02:12:53 +00:00
for ( i = 0 ; i < 4 ; i + + )
2020-10-13 17:07:57 +00:00
ammovals [ i ] = MSG_ReadByte ( ) ;
activeweapon = MSG_ReadByte ( ) ;
if ( ! standard_quake )
activeweapon = 1u < < activeweapon ;
2017-09-17 02:12:53 +00:00
//johnfitz -- PROTOCOL_FITZQUAKE
if ( bits & SU_WEAPON2 )
2020-10-13 17:07:57 +00:00
weaponmodel | = ( MSG_ReadByte ( ) < < 8 ) ;
2017-09-17 02:12:53 +00:00
if ( bits & SU_ARMOR2 )
2020-10-13 17:07:57 +00:00
armourval | = ( MSG_ReadByte ( ) < < 8 ) ;
2017-09-17 02:12:53 +00:00
if ( bits & SU_AMMO2 )
2020-10-13 17:07:57 +00:00
ammo | = ( MSG_ReadByte ( ) < < 8 ) ;
2017-09-17 02:12:53 +00:00
if ( bits & SU_SHELLS2 )
2020-10-13 17:07:57 +00:00
ammovals [ 0 ] | = ( MSG_ReadByte ( ) < < 8 ) ;
2017-09-17 02:12:53 +00:00
if ( bits & SU_NAILS2 )
2020-10-13 17:07:57 +00:00
ammovals [ 1 ] | = ( MSG_ReadByte ( ) < < 8 ) ;
2017-09-17 02:12:53 +00:00
if ( bits & SU_ROCKETS2 )
2020-10-13 17:07:57 +00:00
ammovals [ 2 ] | = ( MSG_ReadByte ( ) < < 8 ) ;
2017-09-17 02:12:53 +00:00
if ( bits & SU_CELLS2 )
2020-10-13 17:07:57 +00:00
ammovals [ 3 ] | = ( MSG_ReadByte ( ) < < 8 ) ;
2017-09-17 02:12:53 +00:00
if ( bits & SU_WEAPONFRAME2 )
2020-10-13 17:07:57 +00:00
weaponframe | = ( MSG_ReadByte ( ) < < 8 ) ;
2017-09-17 02:12:53 +00:00
if ( bits & SU_WEAPONALPHA )
cl . viewent . alpha = MSG_ReadByte ( ) ;
else
cl . viewent . alpha = ENTALPHA_DEFAULT ;
//johnfitz
2020-10-13 17:07:57 +00:00
CL_SetHudStat ( STAT_WEAPONFRAME , weaponframe ) ;
CL_SetHudStat ( STAT_ARMOR , armourval ) ;
CL_SetHudStat ( STAT_WEAPON , weaponmodel ) ;
CL_SetHudStat ( STAT_ACTIVEWEAPON , activeweapon ) ;
CL_SetHudStat ( STAT_HEALTH , health ) ;
CL_SetHudStat ( STAT_AMMO , ammo ) ;
CL_SetHudStat ( STAT_SHELLS , ammovals [ 0 ] ) ;
CL_SetHudStat ( STAT_NAILS , ammovals [ 1 ] ) ;
CL_SetHudStat ( STAT_ROCKETS , ammovals [ 2 ] ) ;
CL_SetHudStat ( STAT_CELLS , ammovals [ 3 ] ) ;
2010-02-15 23:26:55 +00:00
}
2015-05-16 22:15:15 +00:00
//johnfitz -- lerping
//ericw -- this was done before the upper 8 bits of cl.stats[STAT_WEAPON] were filled in, breaking on large maps like zendar.bsp
if ( cl . viewent . model ! = cl . model_precache [ cl . stats [ STAT_WEAPON ] ] )
{
cl . viewent . lerpflags | = LERP_RESETANIM ; //don't lerp animation across model changes
}
//johnfitz
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = =
CL_NewTranslation
= = = = = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
static void CL_NewTranslation ( int slot )
2010-02-15 23:26:55 +00:00
{
if ( slot > cl . maxclients )
Sys_Error ( " CL_NewTranslation: slot > cl.maxclients " ) ;
R_TranslatePlayerSkin ( slot ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
CL_ParseStatic
= = = = = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
static void CL_ParseStatic ( int version ) //johnfitz -- added a parameter
2010-02-15 23:26:55 +00:00
{
entity_t * ent ;
int i ;
i = cl . num_statics ;
2017-09-17 02:12:53 +00:00
if ( i > = cl . max_static_entities )
{
int ec = 64 ;
entity_t * * newstatics = realloc ( cl . static_entities , sizeof ( * newstatics ) * ( cl . max_static_entities + ec ) ) ;
entity_t * newents = Hunk_Alloc ( sizeof ( * newents ) * ec ) ;
if ( ! newstatics | | ! newents )
Host_Error ( " Too many static entities " ) ;
cl . static_entities = newstatics ;
while ( ec - - )
cl . static_entities [ cl . max_static_entities + + ] = newents + + ;
}
2010-02-15 23:26:55 +00:00
2017-09-17 02:12:53 +00:00
ent = cl . static_entities [ i ] ;
2010-02-15 23:26:55 +00:00
cl . num_statics + + ;
CL_ParseBaseline ( ent , version ) ; //johnfitz -- added second parameter
// copy it to the current state
2017-09-17 02:12:53 +00:00
ent - > netstate = ent - > baseline ;
2019-01-30 01:53:15 +00:00
ent - > eflags = ent - > netstate . eflags ; //spike -- annoying and probably not used anyway, but w/e
2017-09-17 02:12:53 +00:00
ent - > trailstate = NULL ;
ent - > emitstate = NULL ;
2010-02-15 23:26:55 +00:00
ent - > model = cl . model_precache [ ent - > baseline . modelindex ] ;
ent - > lerpflags | = LERP_RESETANIM ; //johnfitz -- lerping
ent - > frame = ent - > baseline . frame ;
ent - > skinnum = ent - > baseline . skin ;
ent - > effects = ent - > baseline . effects ;
ent - > alpha = ent - > baseline . alpha ; //johnfitz -- alpha
VectorCopy ( ent - > baseline . origin , ent - > origin ) ;
VectorCopy ( ent - > baseline . angles , ent - > angles ) ;
2017-09-17 02:12:53 +00:00
if ( ent - > model )
R_AddEfrags ( ent ) ;
2010-02-15 23:26:55 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
CL_ParseStaticSound
= = = = = = = = = = = = = = = = = = =
*/
2017-09-17 02:12:53 +00:00
static void CL_ParseStaticSound ( int version ) //johnfitz -- added argument
2010-02-15 23:26:55 +00:00
{
vec3_t org ;
int sound_num , vol , atten ;
int i ;
2011-12-29 19:06:08 +00:00
for ( i = 0 ; i < 3 ; i + + )
2016-06-24 06:15:41 +00:00
org [ i ] = MSG_ReadCoord ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
//johnfitz -- PROTOCOL_FITZQUAKE
if ( version = = 2 )
sound_num = MSG_ReadShort ( ) ;
else
sound_num = MSG_ReadByte ( ) ;
//johnfitz
vol = MSG_ReadByte ( ) ;
atten = MSG_ReadByte ( ) ;
S_StaticSound ( cl . sound_precache [ sound_num ] , org , vol , atten ) ;
}
2017-09-17 02:12:53 +00:00
/*
CL_ParsePrecache
spike - - added this mostly for particle effects , but its also used for models + sounds ( if needed )
*/
static void CL_ParsePrecache ( void )
{
unsigned short code = MSG_ReadShort ( ) ;
unsigned int index = code & 0x3fff ;
const char * name = MSG_ReadString ( ) ;
switch ( ( code > > 14 ) & 0x3 )
{
case 0 : //models
if ( index < MAX_MODELS )
{
cl . model_precache [ index ] = Mod_ForName ( name , false ) ;
//FIXME: if its a bsp model, generate lightmaps.
//FIXME: update static entities with that modelindex
}
break ;
# ifdef PSET_SCRIPT
case 1 : //particles
if ( index < MAX_PARTICLETYPES )
{
if ( * name )
{
cl . particle_precache [ index ] . name = strcpy ( Hunk_Alloc ( strlen ( name ) + 1 ) , name ) ;
cl . particle_precache [ index ] . index = PScript_FindParticleType ( cl . particle_precache [ index ] . name ) ;
}
else
{
cl . particle_precache [ index ] . name = NULL ;
cl . particle_precache [ index ] . index = - 1 ;
}
}
break ;
# endif
case 2 : //sounds
if ( index < MAX_SOUNDS )
cl . sound_precache [ index ] = S_PrecacheSound ( name ) ;
break ;
// case 3: //unused
default :
Con_Warning ( " CL_ParsePrecache: unsupported precache type \n " ) ;
break ;
}
}
# ifdef PSET_SCRIPT
int CL_GenerateRandomParticlePrecache ( const char * pname ) ;
//small function for simpler reuse
static void CL_ForceProtocolParticles ( void )
{
cl . protocol_particles = true ;
PScript_FindParticleType ( " effectinfo. " ) ; //make sure this is implicitly loaded.
COM_Effectinfo_Enumerate ( CL_GenerateRandomParticlePrecache ) ;
Con_Warning ( " Received svcdp_pointparticles1 but extension not active " ) ;
}
/*
CL_RegisterParticles
called when the particle system has changed , and any cached indexes are now probably stale .
*/
void CL_RegisterParticles ( void )
{
extern qmodel_t mod_known [ ] ;
extern int mod_numknown ;
int i ;
if ( cl . protocol = = PROTOCOL_VERSION_DP7 ) //dpp7 sucks.
PScript_FindParticleType ( " effectinfo. " ) ; //make sure this is implicitly loaded.
//make sure the precaches know the right effects
for ( i = 0 ; i < MAX_PARTICLETYPES ; i + + )
{
if ( cl . particle_precache [ i ] . name )
cl . particle_precache [ i ] . index = PScript_FindParticleType ( cl . particle_precache [ i ] . name ) ;
else
cl . particle_precache [ i ] . index = - 1 ;
}
//and make sure models get the right effects+trails etc too
for ( i = 0 ; i < mod_numknown ; i + + )
PScript_UpdateModelEffects ( & mod_known [ i ] ) ;
}
/*
CL_ParseParticles
spike - - this handles the various ssqc builtins ( the ones that were based on csqc )
*/
static void CL_ParseParticles ( int type )
{
vec3_t org , vel ;
if ( type < 0 )
{ //trail
entity_t * ent ;
int entity = MSG_ReadShort ( ) ;
int efnum = MSG_ReadShort ( ) ;
org [ 0 ] = MSG_ReadCoord ( cl . protocolflags ) ;
org [ 1 ] = MSG_ReadCoord ( cl . protocolflags ) ;
org [ 2 ] = MSG_ReadCoord ( cl . protocolflags ) ;
vel [ 0 ] = MSG_ReadCoord ( cl . protocolflags ) ;
vel [ 1 ] = MSG_ReadCoord ( cl . protocolflags ) ;
vel [ 2 ] = MSG_ReadCoord ( cl . protocolflags ) ;
ent = CL_EntityNum ( entity ) ;
if ( efnum < MAX_PARTICLETYPES & & cl . particle_precache [ efnum ] . name )
2019-01-30 04:17:18 +00:00
PScript_ParticleTrail ( org , vel , cl . particle_precache [ efnum ] . index , 1 , 0 , NULL , & ent - > trailstate ) ;
2017-09-17 02:12:53 +00:00
}
else
{ //point
int efnum = MSG_ReadShort ( ) ;
int count ;
org [ 0 ] = MSG_ReadCoord ( cl . protocolflags ) ;
org [ 1 ] = MSG_ReadCoord ( cl . protocolflags ) ;
org [ 2 ] = MSG_ReadCoord ( cl . protocolflags ) ;
if ( type )
{
vel [ 0 ] = vel [ 1 ] = vel [ 2 ] = 0 ;
count = 1 ;
}
else
{
vel [ 0 ] = MSG_ReadCoord ( cl . protocolflags ) ;
vel [ 1 ] = MSG_ReadCoord ( cl . protocolflags ) ;
vel [ 2 ] = MSG_ReadCoord ( cl . protocolflags ) ;
count = MSG_ReadShort ( ) ;
}
if ( efnum < MAX_PARTICLETYPES & & cl . particle_precache [ efnum ] . name )
{
PScript_RunParticleEffectState ( org , vel , count , cl . particle_precache [ efnum ] . index , NULL ) ;
}
}
}
# endif
2010-02-15 23:26:55 +00:00
# define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
2017-09-17 02:12:53 +00:00
static void CL_ParseStatNumeric ( int stat , int ival , float fval )
{
if ( stat < 0 | | stat > = MAX_CL_STATS )
{
Con_DWarning ( " svc_updatestat: %i is invalid \n " , stat ) ;
return ;
}
cl . stats [ stat ] = ival ;
cl . statsf [ stat ] = fval ;
if ( stat = = STAT_VIEWZOOM )
vid . recalc_refdef = true ;
//just assume that they all affect the hud
Sbar_Changed ( ) ;
}
static void CL_ParseStatFloat ( int stat , float fval )
{
CL_ParseStatNumeric ( stat , fval , fval ) ;
}
static void CL_ParseStatInt ( int stat , int ival )
{
CL_ParseStatNumeric ( stat , ival , ival ) ;
}
2020-06-19 22:19:07 +00:00
static void CL_ParseStatString ( int stat , const char * str )
{
if ( stat < 0 | | stat > = MAX_CL_STATS )
{
Con_DWarning ( " svc_updatestat: %i is invalid \n " , stat ) ;
return ;
}
free ( cl . statss [ stat ] ) ;
cl . statss [ stat ] = strdup ( str ) ;
//hud doesn't know/care about any of these strings so don't bother invalidating anything.
}
2017-09-17 02:12:53 +00:00
//mods and servers might not send the \n instantly.
//some mods bug out and omit the \n entirely, this function helps prevent the damage from spreading too much.
//some servers or mods use //prefixed commands as extensions to avoid spam about unrecognised commands.
//proquake has its own extension coding thing.
static void CL_ParseStuffText ( const char * msg )
{
const char * str ;
q_strlcat ( cl . stuffcmdbuf , msg , sizeof ( cl . stuffcmdbuf ) ) ;
2020-09-04 10:53:42 +00:00
for ( ; ( str = strchr ( cl . stuffcmdbuf , ' \n ' ) ) ; memmove ( cl . stuffcmdbuf , str , Q_strlen ( str ) + 1 ) )
2017-09-17 02:12:53 +00:00
{
2020-09-04 10:53:42 +00:00
qboolean handled = false ;
str + + ; //skip past the \n
2017-09-17 02:12:53 +00:00
if ( * cl . stuffcmdbuf = = 0x01 & & cl . protocol = = PROTOCOL_NETQUAKE ) //proquake message, just strip this and try again (doesn't necessarily have a trailing \n straight away)
{
for ( str = cl . stuffcmdbuf + 1 ; * str > = 0x01 & & * str < = 0x1f ; str + + )
; //FIXME: parse properly
continue ;
}
2020-09-04 10:53:42 +00:00
//handle special commands
2017-09-17 02:12:53 +00:00
if ( cl . stuffcmdbuf [ 0 ] = = ' / ' & & cl . stuffcmdbuf [ 1 ] = = ' / ' )
{
handled = Cmd_ExecuteString ( cl . stuffcmdbuf + 2 , src_server ) ;
if ( ! handled )
2020-09-04 10:53:42 +00:00
Con_DPrintf ( " Server sent unknown command %s \n " , Cmd_Argv ( 0 ) ) ;
2017-09-17 02:12:53 +00:00
}
else
handled = Cmd_ExecuteString ( cl . stuffcmdbuf , src_server ) ;
2020-09-04 10:53:42 +00:00
//give the csqc a chance to handle them
if ( ! handled & & cl . qcvm . extfuncs . CSQC_Parse_StuffCmd & & str - cl . stuffcmdbuf < STRINGTEMP_LENGTH )
{
char * tmp ;
PR_SwitchQCVM ( & cl . qcvm ) ;
tmp = PR_GetTempString ( ) ;
memcpy ( tmp , cl . stuffcmdbuf , str - cl . stuffcmdbuf ) ;
tmp [ str - cl . stuffcmdbuf ] = 0 ; //null terminate it.
G_INT ( OFS_PARM0 ) = PR_SetEngineString ( tmp ) ;
PR_ExecuteProgram ( cl . qcvm . extfuncs . CSQC_Parse_StuffCmd ) ;
handled = true ; //unfortunately the mod is expected to localcmd unknown things.
PR_SwitchQCVM ( NULL ) ;
}
//let the server exec general user commands (massive security hole)
2017-09-17 02:12:53 +00:00
if ( ! handled )
Cbuf_AddTextLen ( cl . stuffcmdbuf , str - cl . stuffcmdbuf ) ;
}
}
//warning: this text might not even be a complete line.
//we're screwed if someone names themselves something that triggers this or some such
//however, that's what has become standard for nq clients
static qboolean CL_ParseSpecialPrints ( const char * printtext )
{
const char * e = printtext + strlen ( printtext ) ;
if ( cl . printtype = = PRINT_PINGS )
{
//players are expected to be listed in slot order.
//names might need to be a little fuzzy due to some mods toying with svc_updatename.
//'unconnected' players might cause issues as they might be listed without being in .
const char * t = printtext ;
char * n ;
int ping ;
while ( * t = = ' ' )
t + + ;
ping = strtol ( t , & n , 10 ) ;
if ( t ! = n & & * n = = ' ' & & e [ - 1 ] = = ' \n ' )
{
int i ;
n + + ;
e - - ;
//warning: some servers might have set svc_playernames with extra text on the end that isn't known to the server itself, and thus won't appear here
//that text should at least be aligned such that the name part is padded to 15 chars
if ( ! strcmp ( n , " unconnected \n " ) )
return true ; //just ignore unconnecteds, too many dupes etc
for ( i = cl . printplayer ; i < MAX_SCOREBOARD ; i + + )
{
if ( ! * cl . scores [ i ] . name )
continue ; //player slot is empty
if ( strncmp ( cl . scores [ i ] . name , n , e - n ) )
continue ; //reported name is screwy
cl . scores [ i + + ] . ping = ping ;
cl . printplayer = i ;
return true ;
}
}
cl . printtype = PRINT_NONE ;
}
if ( ! strcmp ( printtext , " Client ping times: \n " ) & & cl . expectingpingtimes > realtime )
{
cl . printtype = PRINT_PINGS ;
cl . printplayer = 0 ;
return true ;
}
/*if (!strncmp(printtext, "host: ", 9) && cl.expectingstatus > Sys_DoubleTime())
{
//host: *\n
// *:*\n
//players: \n\n
//#%i name frags time
// ipaddress
return true ;
} */
//check for chat messages of the form 'name: q_version'
if ( ! cls . demoplayback & & * printtext = = 1 & & e - printtext > 13 & & ( ! strcmp ( e - 12 , " : f_version \n " ) | | ! strcmp ( e - 12 , " : q_version \n " ) ) )
{
if ( realtime > cl . printversionresponse )
{
MSG_WriteByte ( & cls . message , clc_stringcmd ) ;
MSG_WriteString ( & cls . message , va ( " say " ENGINE_NAME_AND_VER ) ) ;
cl . printversionresponse = realtime + 20 ;
}
}
return false ;
}
2020-09-04 10:53:42 +00:00
static void CL_ParsePrint ( const char * msg )
{
const char * str ;
char * tmp ;
if ( CL_ParseSpecialPrints ( msg ) )
return ;
if ( cl . qcvm . extfuncs . CSQC_Parse_Print )
{
q_strlcat ( cl . printbuffer , msg , sizeof ( cl . printbuffer ) ) ;
for ( ; * cl . printbuffer ; memmove ( cl . printbuffer , str , Q_strlen ( str ) + 1 ) )
{
for ( str = cl . printbuffer ; str < cl . printbuffer + STRINGTEMP_LENGTH - 1 ; str + + )
{
if ( * str = = ' \r ' | | * str = = ' \n ' )
{
str + + ;
break ;
}
if ( ! * str )
return ;
}
PR_SwitchQCVM ( & cl . qcvm ) ;
tmp = PR_GetTempString ( ) ;
memcpy ( tmp , cl . printbuffer , str - cl . printbuffer ) ;
tmp [ str - cl . printbuffer ] = 0 ;
G_INT ( OFS_PARM0 ) = PR_SetEngineString ( tmp ) ;
G_FLOAT ( OFS_PARM1 ) = ( ( * tmp = = ' \1 ' ) ? 3 : 2 ) ; //guess at the print level. we don't really have them in NQ.
PR_ExecuteProgram ( qcvm - > extfuncs . CSQC_Parse_Print ) ;
PR_SwitchQCVM ( NULL ) ;
}
}
else
{
if ( * cl . printbuffer )
{
Con_Printf ( " %s " , cl . printbuffer ) ;
* cl . printbuffer = 0 ;
}
Con_Printf ( " %s " , msg ) ;
}
}
static void CL_ParseCenterPrint ( const char * msg )
{
char * tmp ;
if ( cl . qcvm . extfuncs . CSQC_Parse_CenterPrint )
{ //let the csqc do it.
PR_SwitchQCVM ( & cl . qcvm ) ;
tmp = PR_GetTempString ( ) ;
q_strlcpy ( tmp , msg , STRINGTEMP_LENGTH ) ;
G_INT ( OFS_PARM0 ) = PR_SetEngineString ( tmp ) ;
PR_ExecuteProgram ( qcvm - > extfuncs . CSQC_Parse_CenterPrint ) ;
//qc calls cprint if it wants the legacy behaviour...
PR_SwitchQCVM ( NULL ) ;
}
else
SCR_CenterPrint ( msg ) ;
}
2010-02-15 23:26:55 +00:00
/*
= = = = = = = = = = = = = = = = = = = = =
CL_ParseServerMessage
= = = = = = = = = = = = = = = = = = = = =
*/
void CL_ParseServerMessage ( void )
{
int cmd ;
int i ;
2010-08-29 02:22:55 +00:00
const char * str ; //johnfitz
2019-09-10 14:41:11 +00:00
int lastcmd ; //johnfitz
2010-02-15 23:26:55 +00:00
//
// if recording demos, copy the message out
//
if ( cl_shownet . value = = 1 )
Con_Printf ( " %i " , net_message . cursize ) ;
else if ( cl_shownet . value = = 2 )
Con_Printf ( " ------------------ \n " ) ;
2017-09-17 02:12:53 +00:00
if ( ! ( cl . protocol_pext2 & PEXT2_PREDINFO ) )
cl . onground = false ; // unless the server says otherwise
2010-02-15 23:26:55 +00:00
//
// parse the message
//
MSG_BeginReading ( ) ;
chase.c, cl_input.c, cl_parse.c, client.h, common.c, common.h, console.h,
cvar.h, draw.h, gl_draw.c, gl_fog.c, gl_mesh.c, gl_model.c, gl_model.h,
gl_rmain.c, gl_rmisc.c, gl_screen.c, gl_sky.c, gl_texmgr.c, glquake.h,
host.c, keys.c, keys.h, main.c, menu.c, menu.h, pr_cmds.c, quakedef.h,
r_alias.c, r_brush.c, r_part.c, r_sprite.c, r_world.c, sbar.c, sbar.h,
screen.h, snd_dma.c, snd_mem.c, snd_mix.c, sv_main.c, sys_sdl.c, vid.h,
view.h, world.c, world.h: Loads of warning fixes about missing function
prototypes, missing parens around &, missing braces leading to ambiguous
else statements and unused and uninitialized variables. There are still a
couple of unitialised variables here and there, but not much. The warnings
about strict aliasing violations need taking care of.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@21 af15c1b1-3010-417e-b628-4374ebc0bcbd
2010-02-16 12:01:07 +00:00
lastcmd = 0 ;
2010-02-15 23:26:55 +00:00
while ( 1 )
{
if ( msg_badread )
Host_Error ( " CL_ParseServerMessage: Bad server message " ) ;
cmd = MSG_ReadByte ( ) ;
if ( cmd = = - 1 )
{
SHOWNET ( " END OF MESSAGE " ) ;
2017-09-17 02:12:53 +00:00
if ( cl . items ! = cl . stats [ STAT_ITEMS ] )
{
for ( i = 0 ; i < 32 ; i + + )
if ( ( cl . stats [ STAT_ITEMS ] & ( 1 < < i ) ) & & ! ( cl . items & ( 1 < < i ) ) )
cl . item_gettime [ i ] = cl . time ;
cl . items = cl . stats [ STAT_ITEMS ] ;
}
if ( cl . protocol = = PROTOCOL_VERSION_DP7 )
CL_EntitiesDeltaed ( ) ;
2018-05-01 00:35:14 +00:00
if ( * cl . stuffcmdbuf & & net_message . cursize < 512 )
CL_ParseStuffText ( " \n " ) ; //there's a few mods that forget to write \ns, that then fuck up other things too. So make sure it gets flushed to the cbuf. the cursize check is to reduce backbuffer overflows that would give a false positive.
2010-02-15 23:26:55 +00:00
return ; // end of message
}
// if the high bit of the command byte is set, it is a fast update
if ( cmd & U_SIGNAL ) //johnfitz -- was 128, changed for clarity
{
SHOWNET ( " fast update " ) ;
CL_ParseUpdate ( cmd & 127 ) ;
continue ;
}
SHOWNET ( svc_strings [ cmd ] ) ;
// other commands
switch ( cmd )
{
default :
2017-09-17 02:12:53 +00:00
Host_Error ( " Illegible server message %s, previous was %s " , svc_strings [ cmd ] , svc_strings [ lastcmd ] ) ; //johnfitz -- added svc_strings[lastcmd]
2010-02-15 23:26:55 +00:00
break ;
case svc_nop :
2011-12-29 19:06:08 +00:00
// Con_Printf ("svc_nop\n");
2010-02-15 23:26:55 +00:00
break ;
case svc_time :
cl . mtime [ 1 ] = cl . mtime [ 0 ] ;
cl . mtime [ 0 ] = MSG_ReadFloat ( ) ;
2017-09-17 02:12:53 +00:00
if ( cl . protocol_pext2 & PEXT2_PREDINFO )
MSG_ReadShort ( ) ; //input sequence ack.
2010-02-15 23:26:55 +00:00
break ;
case svc_clientdata :
CL_ParseClientdata ( ) ; //johnfitz -- removed bits parameter, we will read this inside CL_ParseClientdata()
break ;
case svc_version :
i = MSG_ReadLong ( ) ;
//johnfitz -- support multiple protocols
2016-06-24 06:15:41 +00:00
if ( i ! = PROTOCOL_NETQUAKE & & i ! = PROTOCOL_FITZQUAKE & & i ! = PROTOCOL_RMQ )
Host_Error ( " Server returned version %i, not %i or %i or %i " , i , PROTOCOL_NETQUAKE , PROTOCOL_FITZQUAKE , PROTOCOL_RMQ ) ;
2010-02-15 23:26:55 +00:00
cl . protocol = i ;
//johnfitz
break ;
case svc_disconnect :
Host_EndGame ( " Server disconnected \n " ) ;
case svc_print :
2020-09-04 10:53:42 +00:00
CL_ParsePrint ( MSG_ReadString ( ) ) ;
2010-02-15 23:26:55 +00:00
break ;
case svc_centerprint :
//johnfitz -- log centerprints to console
2020-09-04 10:53:42 +00:00
CL_ParseCenterPrint ( MSG_ReadString ( ) ) ;
2010-02-15 23:26:55 +00:00
//johnfitz
break ;
case svc_stufftext :
2017-09-17 02:12:53 +00:00
CL_ParseStuffText ( MSG_ReadString ( ) ) ;
2010-02-15 23:26:55 +00:00
break ;
case svc_damage :
V_ParseDamage ( ) ;
break ;
case svc_serverinfo :
CL_ParseServerInfo ( ) ;
vid . recalc_refdef = true ; // leave intermission full screen
break ;
case svc_setangle :
for ( i = 0 ; i < 3 ; i + + )
2016-06-24 06:15:41 +00:00
cl . viewangles [ i ] = MSG_ReadAngle ( cl . protocolflags ) ;
2010-02-15 23:26:55 +00:00
break ;
2017-09-17 02:12:53 +00:00
case svcfte_setangledelta :
for ( i = 0 ; i < 3 ; i + + )
cl . viewangles [ i ] + = MSG_ReadAngle16 ( cl . protocolflags ) ;
break ;
2010-02-15 23:26:55 +00:00
case svc_setview :
cl . viewentity = MSG_ReadShort ( ) ;
break ;
case svc_lightstyle :
i = MSG_ReadByte ( ) ;
2017-09-17 02:12:53 +00:00
str = MSG_ReadString ( ) ;
2019-09-10 14:41:11 +00:00
CL_UpdateLightstyle ( i , str ) ;
2010-02-15 23:26:55 +00:00
break ;
case svc_sound :
CL_ParseStartSoundPacket ( ) ;
break ;
case svc_stopsound :
i = MSG_ReadShort ( ) ;
S_StopSound ( i > > 3 , i & 7 ) ;
break ;
case svc_updatename :
Sbar_Changed ( ) ;
i = MSG_ReadByte ( ) ;
if ( i > = cl . maxclients )
Host_Error ( " CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD " ) ;
2011-12-27 13:15:31 +00:00
q_strlcpy ( cl . scores [ i ] . name , MSG_ReadString ( ) , MAX_SCOREBOARDNAME ) ;
2010-02-15 23:26:55 +00:00
break ;
case svc_updatefrags :
Sbar_Changed ( ) ;
i = MSG_ReadByte ( ) ;
if ( i > = cl . maxclients )
Host_Error ( " CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD " ) ;
cl . scores [ i ] . frags = MSG_ReadShort ( ) ;
break ;
case svc_updatecolors :
Sbar_Changed ( ) ;
i = MSG_ReadByte ( ) ;
if ( i > = cl . maxclients )
Host_Error ( " CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD " ) ;
cl . scores [ i ] . colors = MSG_ReadByte ( ) ;
CL_NewTranslation ( i ) ;
break ;
case svc_particle :
R_ParseParticleEffect ( ) ;
break ;
case svc_spawnbaseline :
i = MSG_ReadShort ( ) ;
// must use CL_EntityNum() to force cl.num_entities up
CL_ParseBaseline ( CL_EntityNum ( i ) , 1 ) ; // johnfitz -- added second parameter
break ;
case svc_spawnstatic :
CL_ParseStatic ( 1 ) ; //johnfitz -- added parameter
break ;
case svc_temp_entity :
CL_ParseTEnt ( ) ;
break ;
case svc_setpause :
2011-12-29 19:06:08 +00:00
cl . paused = MSG_ReadByte ( ) ;
if ( cl . paused )
2010-02-15 23:26:55 +00:00
{
2011-12-29 19:06:08 +00:00
CDAudio_Pause ( ) ;
BGM_Pause ( ) ;
}
else
{
CDAudio_Resume ( ) ;
BGM_Resume ( ) ;
2010-02-15 23:26:55 +00:00
}
break ;
case svc_signonnum :
i = MSG_ReadByte ( ) ;
if ( i < = cls . signon )
Host_Error ( " Received signon %i when at %i " , i , cls . signon ) ;
cls . signon = i ;
//johnfitz -- if signonnum==2, signon packet has been fully parsed, so check for excessive static ents and efrags
if ( i = = 2 )
{
if ( cl . num_statics > 128 )
2017-09-17 02:12:53 +00:00
Con_DWarning ( " %i static entities exceeds standard limit of 128. \n " , cl . num_statics ) ;
2010-02-15 23:26:55 +00:00
R_CheckEfrags ( ) ;
}
//johnfitz
CL_SignonReply ( ) ;
break ;
case svc_killedmonster :
cl . stats [ STAT_MONSTERS ] + + ;
2018-05-01 00:35:14 +00:00
cl . statsf [ STAT_MONSTERS ] = cl . stats [ STAT_MONSTERS ] ;
2010-02-15 23:26:55 +00:00
break ;
case svc_foundsecret :
cl . stats [ STAT_SECRETS ] + + ;
2018-05-01 00:35:14 +00:00
cl . statsf [ STAT_SECRETS ] = cl . stats [ STAT_SECRETS ] ;
2010-02-15 23:26:55 +00:00
break ;
case svc_updatestat :
i = MSG_ReadByte ( ) ;
2017-09-17 02:12:53 +00:00
CL_ParseStatInt ( i , MSG_ReadLong ( ) ) ;
2010-02-15 23:26:55 +00:00
break ;
case svc_spawnstaticsound :
CL_ParseStaticSound ( 1 ) ; //johnfitz -- added parameter
break ;
case svc_cdtrack :
cl . cdtrack = MSG_ReadByte ( ) ;
cl . looptrack = MSG_ReadByte ( ) ;
if ( ( cls . demoplayback | | cls . demorecording ) & & ( cls . forcetrack ! = - 1 ) )
Backported external music files support using decoder libraries and the
new raw samples interface from Hammer of Thyrion (uhexen2) :
- bgmusic.c, bgmusic.h: New BGM interface for background music handling.
Handles streaming music as raw sound samples.
- bgmnull.c: BGM source for cases where the engine is configured for no
sound.
- cl_main.c: Include bgmusic.h. Call BGM_Stop() and CDAudio_Stop() in
CL_Disconnect().
- cd_sdl.c: Moved bgmvolume boundary checking to bgmusic.c upon value
changes.
- gl_vidnt.c, gl_vidsdl.c, cl_parse.c: Include bgmusic.h. Add BGM_Pause()
and BGM_Resume() calls along with CDAudio_ counterparts.
- cl_parse.c: Replace CDAudio_Play() call by the new BGM_PlayCDtrack()
which first tries CDAudio_Play() and then streaming music if it fails.
- host.c: Include bgmusic.h. Call BGM_Update() just before S_Update()
in Host_Frame(). In Host_Init(), call BGM_Init() after other audio init
calls. In Host_Shutdown(), call BGM_Shutdown() before all other audio
shutdown calls.
- snd_dma.c: Include snd_codec.h and bgmusic.h. Call S_CodecInit() from
S_Init(). Call S_CodecShutdown() from S_Shutdown().
- snd_codec.c, snd_codec.h: New public codec interface for streaming
music as raw samples. Adapted from quake2 and ioquake3 with changes.
Individual codecs are responsible for handling any necessary byte swap
operations.
- snd_codeci.h: New header for snd_codec internals.
- snd_wave.c, snd_wave.h: Codec for WAV format streaming music. Adapted
from ioquake3 with changes.
- snd_vorbis.c, snd_vorbis.h: Codec for Ogg/Vorbis format streaming music.
- snd_mp3.c, snd_mp3.h: Codec for MP3 format streaming music using libmad.
Adapted from the SoX project with changes.
- Makefile: Adjusted for the new sources. Added switches USE_CODEC_WAVE,
USE_CODEC_MP3, USE_CODEC_VORBIS for enabling and disabling individual
codecs.
- Windows makefiles and project files as well as other CodeBlocks project
files will be updated shortly.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@374 af15c1b1-3010-417e-b628-4374ebc0bcbd
2011-01-05 19:50:43 +00:00
BGM_PlayCDtrack ( ( byte ) cls . forcetrack , true ) ;
2010-02-15 23:26:55 +00:00
else
Backported external music files support using decoder libraries and the
new raw samples interface from Hammer of Thyrion (uhexen2) :
- bgmusic.c, bgmusic.h: New BGM interface for background music handling.
Handles streaming music as raw sound samples.
- bgmnull.c: BGM source for cases where the engine is configured for no
sound.
- cl_main.c: Include bgmusic.h. Call BGM_Stop() and CDAudio_Stop() in
CL_Disconnect().
- cd_sdl.c: Moved bgmvolume boundary checking to bgmusic.c upon value
changes.
- gl_vidnt.c, gl_vidsdl.c, cl_parse.c: Include bgmusic.h. Add BGM_Pause()
and BGM_Resume() calls along with CDAudio_ counterparts.
- cl_parse.c: Replace CDAudio_Play() call by the new BGM_PlayCDtrack()
which first tries CDAudio_Play() and then streaming music if it fails.
- host.c: Include bgmusic.h. Call BGM_Update() just before S_Update()
in Host_Frame(). In Host_Init(), call BGM_Init() after other audio init
calls. In Host_Shutdown(), call BGM_Shutdown() before all other audio
shutdown calls.
- snd_dma.c: Include snd_codec.h and bgmusic.h. Call S_CodecInit() from
S_Init(). Call S_CodecShutdown() from S_Shutdown().
- snd_codec.c, snd_codec.h: New public codec interface for streaming
music as raw samples. Adapted from quake2 and ioquake3 with changes.
Individual codecs are responsible for handling any necessary byte swap
operations.
- snd_codeci.h: New header for snd_codec internals.
- snd_wave.c, snd_wave.h: Codec for WAV format streaming music. Adapted
from ioquake3 with changes.
- snd_vorbis.c, snd_vorbis.h: Codec for Ogg/Vorbis format streaming music.
- snd_mp3.c, snd_mp3.h: Codec for MP3 format streaming music using libmad.
Adapted from the SoX project with changes.
- Makefile: Adjusted for the new sources. Added switches USE_CODEC_WAVE,
USE_CODEC_MP3, USE_CODEC_VORBIS for enabling and disabling individual
codecs.
- Windows makefiles and project files as well as other CodeBlocks project
files will be updated shortly.
git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@374 af15c1b1-3010-417e-b628-4374ebc0bcbd
2011-01-05 19:50:43 +00:00
BGM_PlayCDtrack ( ( byte ) cl . cdtrack , true ) ;
2010-02-15 23:26:55 +00:00
break ;
case svc_intermission :
cl . intermission = 1 ;
cl . completed_time = cl . time ;
vid . recalc_refdef = true ; // go to full screen
break ;
case svc_finale :
cl . intermission = 2 ;
cl . completed_time = cl . time ;
vid . recalc_refdef = true ; // go to full screen
//johnfitz -- log centerprints to console
2020-09-04 10:53:42 +00:00
CL_ParseCenterPrint ( MSG_ReadString ( ) ) ;
2010-02-15 23:26:55 +00:00
//johnfitz
break ;
case svc_cutscene :
cl . intermission = 3 ;
cl . completed_time = cl . time ;
vid . recalc_refdef = true ; // go to full screen
//johnfitz -- log centerprints to console
2020-09-04 10:53:42 +00:00
CL_ParseCenterPrint ( MSG_ReadString ( ) ) ;
2010-02-15 23:26:55 +00:00
//johnfitz
break ;
case svc_sellscreen :
Cmd_ExecuteString ( " help " , src_command ) ;
break ;
//johnfitz -- new svc types
case svc_skybox :
Sky_LoadSkyBox ( MSG_ReadString ( ) ) ;
break ;
case svc_bf :
Cmd_ExecuteString ( " bf " , src_command ) ;
break ;
case svc_fog :
Fog_ParseServerMessage ( ) ;
break ;
case svc_spawnbaseline2 : //PROTOCOL_FITZQUAKE
i = MSG_ReadShort ( ) ;
// must use CL_EntityNum() to force cl.num_entities up
CL_ParseBaseline ( CL_EntityNum ( i ) , 2 ) ;
break ;
case svc_spawnstatic2 : //PROTOCOL_FITZQUAKE
CL_ParseStatic ( 2 ) ;
break ;
case svc_spawnstaticsound2 : //PROTOCOL_FITZQUAKE
CL_ParseStaticSound ( 2 ) ;
break ;
//johnfitz
2017-09-17 02:12:53 +00:00
//spike -- for particles more than anything else
case svcdp_precache :
if ( cl . protocol ! = PROTOCOL_VERSION_DP7 & & ! cl . protocol_pext2 )
Host_Error ( " Received svcdp_precache but extension not active " ) ;
CL_ParsePrecache ( ) ;
break ;
# ifdef PSET_SCRIPT
case svcdp_trailparticles :
if ( ! cl . protocol_particles )
CL_ForceProtocolParticles ( ) ;
CL_ParseParticles ( - 1 ) ;
break ;
case svcdp_pointparticles :
if ( ! cl . protocol_particles )
CL_ForceProtocolParticles ( ) ;
CL_ParseParticles ( 0 ) ;
break ;
case svcdp_pointparticles1 :
if ( ! cl . protocol_particles )
CL_ForceProtocolParticles ( ) ;
CL_ParseParticles ( 1 ) ;
break ;
# endif
2021-03-06 06:25:24 +00:00
//these two are used by nehahra. we ignore them, parsing only to avoid crashing.
case svcdp_showpic :
/*slotname = */ MSG_ReadString ( ) ;
/*imagename = */ MSG_ReadString ( ) ;
/*x = */ MSG_ReadByte ( ) ; //FIXME: nehahra uses bytes, but DP uses shorts for other games. just use csqc instead.
/*y = */ MSG_ReadByte ( ) ;
Con_DPrintf ( " Ignoring svcdp_showpic \n " ) ;
break ;
case svcdp_hidepic :
/*slotname = */ MSG_ReadString ( ) ;
Con_DPrintf ( " Ignoring svcdp_hidepic \n " ) ;
break ;
2017-09-17 02:12:53 +00:00
case svcdp_effect :
2018-05-01 00:35:14 +00:00
case svcdp_effect2 : //these are kinda pointless when the particle system can do it
2017-09-17 02:12:53 +00:00
if ( cl . protocol ! = PROTOCOL_VERSION_DP7 )
Host_Error ( " Received svcdp_effect[1|2] but extension not active " ) ;
CL_ParseEffect ( cmd = = svcdp_effect2 ) ;
break ;
2018-05-01 00:35:14 +00:00
case svcdp_csqcentities : //FTE uses DP's svc number for nq, because compat (despite fte's svc being first). same payload either way.
if ( ! ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS ) & & cl . protocol ! = PROTOCOL_VERSION_DP7 )
2017-09-17 02:12:53 +00:00
Host_Error ( " Received svcdp_csqcentities but extension not active " ) ;
2020-09-04 10:53:42 +00:00
PR_SwitchQCVM ( & cl . qcvm ) ;
2018-05-01 00:35:14 +00:00
CLFTE_ParseCSQCEntitiesUpdate ( ) ;
2020-09-04 10:53:42 +00:00
PR_SwitchQCVM ( NULL ) ;
2017-09-17 02:12:53 +00:00
break ;
2018-05-01 00:35:14 +00:00
case svcdp_spawnbaseline2 : //limited to a handful of extra properties.
2017-09-17 02:12:53 +00:00
if ( cl . protocol ! = PROTOCOL_VERSION_DP7 )
Host_Error ( " Received svcdp_spawnbaseline2 but extension not active " ) ;
i = MSG_ReadShort ( ) ;
CL_ParseBaseline ( CL_EntityNum ( i ) , 7 ) ;
break ;
2018-05-01 00:35:14 +00:00
case svcdp_spawnstaticsound2 : //many different ways to use 16bit sounds... no other advantage
2017-09-17 02:12:53 +00:00
if ( cl . protocol ! = PROTOCOL_VERSION_DP7 )
Host_Error ( " Received svcdp_spawnstaticsound2 but extension not active " ) ;
CL_ParseStaticSound ( 2 ) ;
break ;
2018-05-01 00:35:14 +00:00
case svcdp_spawnstatic2 : //16bit model and frame. no alpha or anything fun.
2017-09-17 02:12:53 +00:00
if ( cl . protocol ! = PROTOCOL_VERSION_DP7 )
Host_Error ( " Received svcdp_spawnstatic2 but extension not active " ) ;
CL_ParseStatic ( 7 ) ;
break ;
case svcdp_entities :
if ( cl . protocol ! = PROTOCOL_VERSION_DP7 )
Host_Error ( " Received svcdp_entities but extension not active " ) ;
CLDP_ParseEntitiesUpdate ( ) ;
break ;
case svcdp_downloaddata :
if ( cl . protocol ! = PROTOCOL_VERSION_DP7 & & ! cl . protocol_dpdownload )
2020-02-29 02:07:39 +00:00
Host_Error ( " Received svcdp_downloaddata but extension not active " ) ;
2017-09-17 02:12:53 +00:00
CL_Download_Data ( ) ;
break ;
//spike -- new deltas (including new fields etc)
//stats also changed, and are sent unreliably using the same ack mechanism (which means they're not blocked until the reliables are acked, preventing the need to spam them in every packet).
case svcdp_updatestatbyte :
if ( ! ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS ) & & cl . protocol ! = PROTOCOL_VERSION_DP7 )
Host_Error ( " Received svcdp_updatestatbyte but extension not active " ) ;
i = MSG_ReadByte ( ) ;
CL_ParseStatInt ( i , MSG_ReadByte ( ) ) ;
break ;
case svcfte_updatestatstring :
if ( ! ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS ) )
Host_Error ( " Received svcfte_updatestatstring but extension not active " ) ;
i = MSG_ReadByte ( ) ;
2020-06-19 22:19:07 +00:00
CL_ParseStatString ( i , MSG_ReadString ( ) ) ;
2017-09-17 02:12:53 +00:00
break ;
case svcfte_updatestatfloat :
if ( ! ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS ) )
Host_Error ( " Received svcfte_updatestatfloat but extension not active " ) ;
i = MSG_ReadByte ( ) ;
CL_ParseStatFloat ( i , MSG_ReadFloat ( ) ) ;
break ;
//static ents get all the new fields too, even if the client will probably ignore most of them, the option is at least there to fix it without updating protocols separately.
case svcfte_spawnstatic2 :
if ( ! ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS ) )
Host_Error ( " Received svcfte_spawnstatic2 but extension not active " ) ;
CL_ParseStatic ( 6 ) ;
break ;
//baselines have all fields. hurrah for the same delta mechanism
case svcfte_spawnbaseline2 :
if ( ! ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS ) )
Host_Error ( " Received svcfte_spawnbaseline2 but extension not active " ) ;
2018-05-01 00:35:14 +00:00
i = MSG_ReadEntity ( cl . protocol_pext2 ) ;
2017-09-17 02:12:53 +00:00
// must use CL_EntityNum() to force cl.num_entities up
CL_ParseBaseline ( CL_EntityNum ( i ) , 6 ) ;
break ;
//ent updates replace svc_time too
case svcfte_updateentities :
if ( ! ( cl . protocol_pext2 & PEXT2_REPLACEMENTDELTAS ) )
Host_Error ( " Received svcfte_updateentities but extension not active " ) ;
CLFTE_ParseEntitiesUpdate ( ) ;
break ;
2018-05-01 00:35:14 +00:00
case svcfte_cgamepacket :
2020-09-03 08:37:49 +00:00
if ( ! ( cl . protocol_pext1 & PEXT1_CSQC ) )
Host_Error ( " Received svcfte_cgamepacket but extension not active " ) ;
2018-05-01 00:35:14 +00:00
if ( cl . qcvm . extfuncs . CSQC_Parse_Event )
{
PR_SwitchQCVM ( & cl . qcvm ) ;
PR_ExecuteProgram ( cl . qcvm . extfuncs . CSQC_Parse_Event ) ;
PR_SwitchQCVM ( NULL ) ;
}
else
Host_Error ( " CSQC_Parse_Event: Missing or incompatible CSQC \n " ) ;
break ;
2017-09-17 02:12:53 +00:00
//voicechat, because we can. why reduce packet sizes if you're not going to use that extra space?!?
case svcfte_voicechat :
if ( ! ( cl . protocol_pext2 & PEXT2_VOICECHAT ) )
Host_Error ( " Received svcfte_voicechat but extension not active " ) ;
S_Voip_Parse ( ) ;
break ;
//spike
2010-02-15 23:26:55 +00:00
}
lastcmd = cmd ; //johnfitz
}
}
2011-12-29 19:06:08 +00:00