This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/client/cl_parse.c

1347 lines
31 KiB
C
Raw Normal View History

2009-11-23 22:00:00 +01:00
//=======================================================================
// Copyright XashXT Group 2009 <20>
// cl_parse.c -- parse a message received from the server
//=======================================================================
2007-06-21 22:00:00 +02:00
2008-06-09 22:00:00 +02:00
#include "common.h"
2007-06-21 22:00:00 +02:00
#include "client.h"
2010-08-04 22:00:00 +02:00
#include "net_encode.h"
2010-08-07 22:00:00 +02:00
#include "event_flags.h"
2010-11-06 22:00:00 +01:00
#include "cl_tent.h"
2010-10-31 22:00:00 +01:00
#include "shake.h"
2007-06-21 22:00:00 +02:00
2010-03-27 22:00:00 +01:00
#define MSG_COUNT 32 // last 32 messages parsed
#define MSG_MASK (MSG_COUNT - 1)
2010-04-02 22:00:00 +02:00
int CL_UPDATE_BACKUP = SINGLEPLAYER_BACKUP;
2010-08-16 22:00:00 +02:00
const char *svc_strings[256] =
2009-10-13 22:00:00 +02:00
{
"svc_bad",
"svc_nop",
"svc_disconnect",
2010-08-16 22:00:00 +02:00
"svc_changing",
2010-11-19 22:00:00 +01:00
"svc_unused4",
2010-08-16 22:00:00 +02:00
"svc_setview",
"svc_sound",
"svc_time",
"svc_print",
2009-10-13 22:00:00 +02:00
"svc_stufftext",
2010-08-16 22:00:00 +02:00
"svc_setangle",
2009-10-13 22:00:00 +02:00
"svc_serverdata",
2010-10-28 22:00:00 +02:00
"svc_lightstyle",
2010-10-17 22:00:00 +02:00
"svc_updateuserinfo",
2010-10-28 22:00:00 +02:00
"svc_deltatable",
2010-08-16 22:00:00 +02:00
"svc_clientdata",
2009-10-13 22:00:00 +02:00
"svc_download",
2010-10-14 22:00:00 +02:00
"svc_updatepings",
2010-08-16 22:00:00 +02:00
"svc_particle",
2010-10-17 22:00:00 +02:00
"svc_frame",
2010-08-16 22:00:00 +02:00
"svc_spawnstatic",
2010-10-26 22:00:00 +02:00
"svc_event_reliable",
2010-08-16 22:00:00 +02:00
"svc_spawnbaseline",
"svc_temp_entity",
2009-11-10 22:00:00 +01:00
"svc_setpause",
2010-10-26 22:00:00 +02:00
"svc_unused25",
2010-08-16 22:00:00 +02:00
"svc_centerprint",
2009-12-02 22:00:00 +01:00
"svc_event",
2010-10-26 22:00:00 +02:00
"svc_soundindex",
2010-10-17 22:00:00 +02:00
"svc_ambientsound",
2010-08-16 22:00:00 +02:00
"svc_intermission",
2010-10-26 22:00:00 +02:00
"svc_modelindex",
2010-08-16 22:00:00 +02:00
"svc_cdtrack",
2010-06-20 22:00:00 +02:00
"svc_serverinfo",
2010-10-28 22:00:00 +02:00
"svc_eventindex",
2010-08-16 22:00:00 +02:00
"svc_weaponanim",
"svc_bspdecal",
"svc_roomtype",
2010-10-14 22:00:00 +02:00
"svc_addangle",
2010-10-19 22:00:00 +02:00
"svc_usermessage",
2010-10-14 22:00:00 +02:00
"svc_packetentities",
"svc_deltapacketentities",
"svc_chokecount",
2010-08-16 22:00:00 +02:00
"svc_unused43",
2010-10-26 22:00:00 +02:00
"svc_deltamovevars",
2010-08-16 22:00:00 +02:00
"svc_unused45",
"svc_unused46",
2010-10-19 22:00:00 +02:00
"svc_crosshairangle",
"svc_soundfade",
2010-08-16 22:00:00 +02:00
"svc_unused49",
"svc_unused50",
"svc_director",
2009-10-13 22:00:00 +02:00
};
2010-03-27 22:00:00 +01:00
typedef struct
{
int command;
int starting_offset;
int frame_number;
} oldcmd_t;
typedef struct
{
oldcmd_t oldcmd[MSG_COUNT];
int currentcmd;
2010-10-26 22:00:00 +02:00
qboolean parsing;
2010-03-27 22:00:00 +01:00
} msg_debug_t;
static msg_debug_t cls_message_debug;
static int starting_count;
const char *CL_MsgInfo( int cmd )
{
static string sz;
com.strcpy( sz, "???" );
2010-08-16 22:00:00 +02:00
if( cmd >= 0 && cmd < svc_lastmsg )
2010-03-27 22:00:00 +01:00
{
// get engine message name
2010-08-16 22:00:00 +02:00
com.strncpy( sz, svc_strings[cmd], sizeof( sz ));
2010-03-27 22:00:00 +01:00
}
2010-08-16 22:00:00 +02:00
else if( cmd >= svc_lastmsg && cmd < ( svc_lastmsg + MAX_USER_MESSAGES ))
2010-03-27 22:00:00 +01:00
{
2010-08-16 22:00:00 +02:00
int i;
for( i = 0; i < MAX_USER_MESSAGES; i++ )
{
if( clgame.msg[i].number == cmd )
{
com.strncpy( sz, clgame.msg[i].name, sizeof( sz ));
break;
}
}
2010-03-27 22:00:00 +01:00
}
return sz;
}
/*
=====================
CL_Parse_RecordCommand
record new message params into debug buffer
=====================
*/
void CL_Parse_RecordCommand( int cmd, int startoffset )
{
int slot;
if( cmd == svc_nop ) return;
slot = ( cls_message_debug.currentcmd++ & MSG_MASK );
cls_message_debug.oldcmd[slot].command = cmd;
cls_message_debug.oldcmd[slot].starting_offset = startoffset;
cls_message_debug.oldcmd[slot].frame_number = host.framecount;
}
/*
=====================
CL_WriteErrorMessage
write net_message into buffer.dat for debugging
=====================
*/
2010-08-06 22:00:00 +02:00
void CL_WriteErrorMessage( int current_count, sizebuf_t *msg )
2010-03-27 22:00:00 +01:00
{
file_t *fp;
const char *buffer_file = "buffer.dat";
fp = FS_Open( buffer_file, "wb" );
if( !fp ) return;
FS_Write( fp, &starting_count, sizeof( int ));
FS_Write( fp, &current_count, sizeof( int ));
2010-08-04 22:00:00 +02:00
FS_Write( fp, BF_GetData( msg ), BF_GetMaxBytes( msg ));
2010-03-27 22:00:00 +01:00
FS_Close( fp );
MsgDev( D_INFO, "Wrote erroneous message to %s\n", buffer_file );
}
/*
=====================
CL_WriteMessageHistory
list last 32 messages for debugging net troubleshooting
=====================
*/
void CL_WriteMessageHistory( void )
{
int i, thecmd;
oldcmd_t *old, *failcommand;
2010-08-06 22:00:00 +02:00
sizebuf_t *msg = &net_message;
2010-03-27 22:00:00 +01:00
if( !cls.initialized || cls.state == ca_disconnected )
return;
if( !cls_message_debug.parsing )
return;
MsgDev( D_INFO, "Last %i messages parsed.\n", MSG_COUNT );
// finish here
thecmd = cls_message_debug.currentcmd - 1;
thecmd -= ( MSG_COUNT - 1 ); // back up to here
for( i = 0; i < MSG_COUNT - 1; i++ )
{
2010-10-14 22:00:00 +02:00
thecmd &= MSG_MASK;
2010-03-27 22:00:00 +01:00
old = &cls_message_debug.oldcmd[thecmd];
2010-03-28 22:00:00 +02:00
MsgDev( D_INFO,"%i %04i %s\n", old->frame_number, old->starting_offset, CL_MsgInfo( old->command ));
2010-03-27 22:00:00 +01:00
thecmd++;
}
failcommand = &cls_message_debug.oldcmd[thecmd];
2010-08-04 22:00:00 +02:00
MsgDev( D_INFO, "BAD: %3i:%s\n", BF_GetNumBytesRead( msg ) - 1, CL_MsgInfo( failcommand->command ));
2010-03-27 22:00:00 +01:00
if( host.developer >= 3 )
{
2010-08-04 22:00:00 +02:00
CL_WriteErrorMessage( BF_GetNumBytesRead( msg ) - 1, msg );
2010-03-27 22:00:00 +01:00
}
cls_message_debug.parsing = false;
}
2007-06-21 22:00:00 +02:00
/*
===============
CL_CheckOrDownloadFile
Returns true if the file exists, otherwise it attempts
to start a download from the server.
===============
*/
2010-10-26 22:00:00 +02:00
qboolean CL_CheckOrDownloadFile( const char *filename )
2007-06-21 22:00:00 +02:00
{
2008-08-02 22:00:00 +02:00
string name;
file_t *f;
2007-06-21 22:00:00 +02:00
2008-08-02 22:00:00 +02:00
if( FS_FileExists( filename ))
2007-06-21 22:00:00 +02:00
{
// it exists, no need to download
return true;
}
2008-08-02 22:00:00 +02:00
com.strncpy( cls.downloadname, filename, MAX_STRING );
com.strncpy( cls.downloadtempname, filename, MAX_STRING );
2007-06-21 22:00:00 +02:00
2008-08-02 22:00:00 +02:00
// download to a temp name, and only rename to the real name when done,
// so if interrupted a runt file won't be left
FS_StripExtension( cls.downloadtempname );
FS_DefaultExtension( cls.downloadtempname, ".tmp" );
com.strncpy( name, cls.downloadtempname, MAX_STRING );
2007-06-21 22:00:00 +02:00
2008-08-02 22:00:00 +02:00
f = FS_Open( name, "a+b" );
if( f )
2007-06-21 22:00:00 +02:00
{
// it exists
2008-11-27 22:00:00 +01:00
size_t len = FS_Tell( f );
2007-06-21 22:00:00 +02:00
2008-08-02 22:00:00 +02:00
cls.download = f;
2007-06-21 22:00:00 +02:00
// give the server an offset to start the download
2008-08-02 22:00:00 +02:00
MsgDev( D_INFO, "Resume download %s at %i\n", cls.downloadname, len );
2010-08-04 22:00:00 +02:00
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, va("download %s %i", cls.downloadname, len ));
2007-06-21 22:00:00 +02:00
}
else
{
2008-08-02 22:00:00 +02:00
MsgDev( D_INFO, "Start download %s\n", cls.downloadname );
2010-08-04 22:00:00 +02:00
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, va("download %s", cls.downloadname ));
2007-06-21 22:00:00 +02:00
}
cls.downloadnumber++;
return false;
}
/*
=====================
CL_ParseDownload
A download message has been received from the server
=====================
*/
2010-08-06 22:00:00 +02:00
void CL_ParseDownload( sizebuf_t *msg )
2007-06-21 22:00:00 +02:00
{
2010-08-04 22:00:00 +02:00
int size, percent;
char buffer[MAX_MSGLEN];
string name;
int r;
2007-06-21 22:00:00 +02:00
// read the data
2010-08-04 22:00:00 +02:00
size = BF_ReadShort( msg );
percent = BF_ReadByte( msg );
2008-08-02 22:00:00 +02:00
if( size == -1 )
2007-06-21 22:00:00 +02:00
{
2008-08-02 22:00:00 +02:00
Msg( "Server does not have this file.\n" );
if( cls.download )
2007-06-21 22:00:00 +02:00
{
// if here, we tried to resume a file but the server said no
2008-08-02 22:00:00 +02:00
FS_Close( cls.download );
2007-06-21 22:00:00 +02:00
cls.download = NULL;
}
2008-08-02 22:00:00 +02:00
CL_RequestNextDownload();
2007-06-21 22:00:00 +02:00
return;
}
// open the file if not opened yet
2008-08-02 22:00:00 +02:00
if( !cls.download )
2007-06-21 22:00:00 +02:00
{
2008-08-02 22:00:00 +02:00
com.strncpy( name, cls.downloadtempname, MAX_STRING );
cls.download = FS_Open ( name, "wb" );
2007-06-21 22:00:00 +02:00
2008-08-02 22:00:00 +02:00
if( !cls.download )
2007-06-21 22:00:00 +02:00
{
2010-08-04 22:00:00 +02:00
msg->iCurBit += size << 3; // FIXME!!!
MsgDev( D_ERROR, "failed to open %s\n", cls.downloadtempname );
2008-08-02 22:00:00 +02:00
CL_RequestNextDownload();
2007-06-21 22:00:00 +02:00
return;
}
}
2010-08-04 22:00:00 +02:00
ASSERT( size <= sizeof( buffer ));
BF_ReadBytes( msg, buffer, size );
FS_Write( cls.download, buffer, size );
2007-06-21 22:00:00 +02:00
2008-08-02 22:00:00 +02:00
if( percent != 100 )
2007-06-21 22:00:00 +02:00
{
// request next block
2010-10-31 22:00:00 +01:00
Cvar_SetFloat("scr_download", percent );
2010-08-04 22:00:00 +02:00
BF_WriteByte( &cls.netchan.message, clc_stringcmd );
BF_WriteString( &cls.netchan.message, "nextdl" );
2007-06-21 22:00:00 +02:00
}
else
{
2008-08-02 22:00:00 +02:00
FS_Close( cls.download );
2007-06-21 22:00:00 +02:00
// rename the temp file to it's final name
2010-03-27 22:00:00 +01:00
r = FS_Rename( cls.downloadtempname, cls.downloadname );
2008-08-02 22:00:00 +02:00
if( r ) MsgDev( D_ERROR, "failed to rename.\n" );
2007-06-21 22:00:00 +02:00
cls.download = NULL;
2010-10-31 22:00:00 +01:00
Cvar_SetFloat( "scr_download", 0.0f );
2007-06-21 22:00:00 +02:00
// get another file if needed
2008-08-02 22:00:00 +02:00
CL_RequestNextDownload();
}
}
2008-12-21 22:00:00 +01:00
/*
==================
CL_ParseSoundPacket
==================
*/
2010-10-26 22:00:00 +02:00
void CL_ParseSoundPacket( sizebuf_t *msg, qboolean is_ambient )
2008-12-21 22:00:00 +01:00
{
2009-10-11 22:00:00 +02:00
vec3_t pos_;
float *pos = NULL;
2010-04-24 22:00:00 +02:00
int chan, sound;
float volume, attn;
2008-12-21 22:00:00 +01:00
int flags, pitch, entnum;
2010-08-30 22:00:00 +02:00
sound_t handle = 0;
2008-12-21 22:00:00 +01:00
2010-08-04 22:00:00 +02:00
flags = BF_ReadWord( msg );
sound = BF_ReadWord( msg );
chan = BF_ReadByte( msg );
2008-12-21 22:00:00 +01:00
2009-09-29 22:00:00 +02:00
if( flags & SND_VOLUME )
2010-08-04 22:00:00 +02:00
volume = BF_ReadByte( msg ) / 255.0f;
2009-09-29 22:00:00 +02:00
else volume = VOL_NORM;
2010-04-21 22:00:00 +02:00
2010-04-24 22:00:00 +02:00
if( flags & SND_ATTENUATION )
2010-08-04 22:00:00 +02:00
attn = BF_ReadByte( msg ) / 64.0f;
2010-04-24 22:00:00 +02:00
else attn = ATTN_NONE;
2010-04-21 22:00:00 +02:00
2008-12-21 22:00:00 +01:00
if( flags & SND_PITCH )
2010-08-04 22:00:00 +02:00
pitch = BF_ReadByte( msg );
2008-12-21 22:00:00 +01:00
else pitch = PITCH_NORM;
// entity reletive
2010-08-04 22:00:00 +02:00
entnum = BF_ReadWord( msg );
2008-12-21 22:00:00 +01:00
2009-09-29 22:00:00 +02:00
// positioned in space
2009-10-11 22:00:00 +02:00
if( flags & SND_FIXED_ORIGIN )
{
pos = pos_;
2010-08-04 22:00:00 +02:00
BF_ReadBitVec3Coord( msg, pos );
2009-10-11 22:00:00 +02:00
}
2010-04-21 22:00:00 +02:00
2010-06-27 22:00:00 +02:00
if( flags & SND_SENTENCE )
{
char sentenceName[32];
com.snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
handle = S_RegisterSound( sentenceName );
}
2010-10-26 22:00:00 +02:00
else handle = cl.sound_index[sound]; // see precached sound
2010-06-27 22:00:00 +02:00
2010-04-24 22:00:00 +02:00
if( is_ambient )
{
2010-06-27 22:00:00 +02:00
S_AmbientSound( pos, entnum, chan, handle, volume, attn, pitch, flags );
2010-04-24 22:00:00 +02:00
}
else
{
2010-06-27 22:00:00 +02:00
S_StartSound( pos, entnum, chan, handle, volume, attn, pitch, flags );
2010-04-24 22:00:00 +02:00
}
2008-12-21 22:00:00 +01:00
}
2009-11-10 22:00:00 +01:00
/*
==================
CL_ParseMovevars
==================
*/
2010-08-06 22:00:00 +02:00
void CL_ParseMovevars( sizebuf_t *msg )
2009-11-10 22:00:00 +01:00
{
2010-08-06 22:00:00 +02:00
MSG_ReadDeltaMovevars( msg, &clgame.oldmovevars, &clgame.movevars );
2010-08-18 22:00:00 +02:00
// update sky if changed
if( com.strcmp( clgame.oldmovevars.skyName, clgame.movevars.skyName ) && cl.video_prepped )
re->RegisterShader( clgame.movevars.skyName, SHADER_SKY );
2009-11-10 22:00:00 +01:00
Mem_Copy( &clgame.oldmovevars, &clgame.movevars, sizeof( movevars_t ));
2010-11-15 22:00:00 +01:00
clgame.entities->curstate.scale = clgame.movevars.waveHeight;
2009-11-10 22:00:00 +01:00
}
2009-11-23 22:00:00 +01:00
/*
==================
CL_ParseParticles
==================
*/
2010-08-06 22:00:00 +02:00
void CL_ParseParticles( sizebuf_t *msg )
2009-11-23 22:00:00 +01:00
{
vec3_t org, dir;
int i, count, color;
2010-08-04 22:00:00 +02:00
BF_ReadBitVec3Coord( msg, org );
2009-11-23 22:00:00 +01:00
for( i = 0; i < 3; i++ )
2010-08-04 22:00:00 +02:00
dir[i] = BF_ReadChar( msg ) * (1.0f / 16);
2009-11-23 22:00:00 +01:00
2010-08-04 22:00:00 +02:00
count = BF_ReadByte( msg );
color = BF_ReadByte( msg );
2010-03-15 22:00:00 +01:00
if( count == 255 ) count = 1024;
2009-11-23 22:00:00 +01:00
2010-11-15 22:00:00 +01:00
CL_RunParticleEffect( org, dir, color, count );
2009-11-23 22:00:00 +01:00
}
2010-10-17 22:00:00 +02:00
/*
==================
CL_ParseStaticEntity
==================
*/
void CL_ParseStaticEntity( sizebuf_t *msg )
{
entity_state_t ent;
int i;
Mem_Set( &ent, 0, sizeof( ent ));
ent.modelindex = BF_ReadShort( msg );
ent.sequence = BF_ReadByte( msg );
ent.frame = BF_ReadByte( msg );
ent.colormap = BF_ReadWord( msg );
ent.skin = BF_ReadByte( msg );
for( i = 0; i < 3; i++ )
{
ent.origin[i] = BF_ReadBitCoord( msg );
ent.angles[i] = BF_ReadBitAngle( msg, 16 );
}
ent.rendermode = BF_ReadByte( msg );
if( ent.rendermode != kRenderNormal )
{
ent.renderamt = BF_ReadByte( msg );
ent.rendercolor.r = BF_ReadByte( msg );
ent.rendercolor.g = BF_ReadByte( msg );
ent.rendercolor.b = BF_ReadByte( msg );
ent.renderfx = BF_ReadByte( msg );
}
// FIXME: allocate client entity, add new static...
MsgDev( D_ERROR, "Static entities are not implemented\n" );
}
2009-11-23 22:00:00 +01:00
/*
==================
CL_ParseStaticDecal
==================
*/
2010-08-06 22:00:00 +02:00
void CL_ParseStaticDecal( sizebuf_t *msg )
2009-11-23 22:00:00 +01:00
{
vec3_t origin;
int decalIndex, entityIndex, modelIndex;
2010-07-01 22:00:00 +02:00
int flags;
2009-11-23 22:00:00 +01:00
2010-08-04 22:00:00 +02:00
BF_ReadBitVec3Coord( msg, origin );
decalIndex = BF_ReadWord( msg );
entityIndex = BF_ReadShort( msg );
2009-11-25 22:00:00 +01:00
2010-07-02 22:00:00 +02:00
if( entityIndex > 0 )
2010-08-04 22:00:00 +02:00
modelIndex = BF_ReadWord( msg );
2010-06-30 22:00:00 +02:00
else modelIndex = 0;
2010-08-04 22:00:00 +02:00
flags = BF_ReadByte( msg );
2009-11-23 22:00:00 +01:00
2010-10-26 22:00:00 +02:00
if( !cl.decal_index[decalIndex] )
2010-10-28 22:00:00 +02:00
cl.decal_index[decalIndex] = re->RegisterShader( host.draw_decals[decalIndex], SHADER_DECAL );
2010-10-26 22:00:00 +02:00
CL_DecalShoot( cl.decal_index[decalIndex], entityIndex, modelIndex, origin, flags );
2009-11-23 22:00:00 +01:00
}
2010-08-06 22:00:00 +02:00
void CL_ParseSoundFade( sizebuf_t *msg )
2009-11-25 22:00:00 +01:00
{
float fadePercent, fadeOutSeconds;
float holdTime, fadeInSeconds;
2010-10-19 22:00:00 +02:00
fadePercent = (float)BF_ReadByte( msg );
holdTime = (float)BF_ReadByte( msg );
fadeOutSeconds = (float)BF_ReadByte( msg );
fadeInSeconds = (float)BF_ReadByte( msg );
2009-11-25 22:00:00 +01:00
S_FadeClientVolume( fadePercent, fadeOutSeconds, holdTime, fadeInSeconds );
}
2010-08-06 22:00:00 +02:00
void CL_ParseReliableEvent( sizebuf_t *msg, int flags )
2009-12-02 22:00:00 +01:00
{
int event_index;
event_args_t nullargs, args;
float delay;
Mem_Set( &nullargs, 0, sizeof( nullargs ));
2010-08-04 22:00:00 +02:00
event_index = BF_ReadWord( msg ); // read event index
delay = BF_ReadWord( msg ) / 100.0f; // read event delay
2009-12-02 22:00:00 +01:00
MSG_ReadDeltaEvent( msg, &nullargs, &args ); // FIXME: zero-compressing
CL_QueueEvent( flags, event_index, delay, &args );
}
2010-08-06 22:00:00 +02:00
void CL_ParseEvent( sizebuf_t *msg )
2009-12-02 22:00:00 +01:00
{
int i, num_events;
2010-08-04 22:00:00 +02:00
num_events = BF_ReadByte( msg );
2009-12-02 22:00:00 +01:00
// parse events queue
for( i = 0 ; i < num_events; i++ )
CL_ParseReliableEvent( msg, 0 );
}
2007-06-21 22:00:00 +02:00
/*
=====================================================================
SERVER CONNECTING MESSAGES
=====================================================================
*/
/*
==================
CL_ParseServerData
==================
*/
2010-08-06 22:00:00 +02:00
void CL_ParseServerData( sizebuf_t *msg )
2007-06-21 22:00:00 +02:00
{
2010-03-28 22:00:00 +02:00
int i;
2007-10-19 22:00:00 +02:00
2009-09-28 22:00:00 +02:00
MsgDev( D_NOTE, "Serverdata packet received.\n" );
2008-07-11 22:00:00 +02:00
2007-11-04 22:00:00 +01:00
// wipe the client_t struct
2008-07-12 22:00:00 +02:00
CL_ClearState();
2010-07-18 22:00:00 +02:00
UI_SetActiveMenu( false );
2007-06-21 22:00:00 +02:00
cls.state = ca_connected;
2007-09-10 22:00:00 +02:00
// parse protocol version number
2010-08-04 22:00:00 +02:00
i = BF_ReadLong( msg );
2007-06-21 22:00:00 +02:00
cls.serverProtocol = i;
2008-08-02 22:00:00 +02:00
if( i != PROTOCOL_VERSION )
2009-06-24 22:00:00 +02:00
Host_Error( "Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION );
2007-06-21 22:00:00 +02:00
2010-08-04 22:00:00 +02:00
cl.servercount = BF_ReadLong( msg );
2010-10-31 22:00:00 +01:00
cl.checksum = BF_ReadLong( msg );
2010-08-04 22:00:00 +02:00
cl.playernum = BF_ReadByte( msg );
2010-08-20 22:00:00 +02:00
cl.maxclients = BF_ReadByte( msg );
clgame.maxEntities = BF_ReadWord( msg );
com.strncpy( clgame.mapname, BF_ReadString( msg ), MAX_STRING );
2010-08-04 22:00:00 +02:00
com.strncpy( clgame.maptitle, BF_ReadString( msg ), MAX_STRING );
2010-08-30 22:00:00 +02:00
cl.refdef.viewentity = cl.playernum + 1; // always keep viewent an actual
2010-03-28 22:00:00 +02:00
2010-11-15 22:00:00 +01:00
menu.globals->maxClients = cl.maxclients;
com.strncpy( menu.globals->maptitle, clgame.maptitle, sizeof( menu.globals->maptitle ));
2010-07-18 22:00:00 +02:00
2010-03-28 22:00:00 +02:00
// no effect for local client
2010-02-28 22:00:00 +01:00
// merge entcount only for remote clients
2010-08-20 22:00:00 +02:00
GI->max_edicts = clgame.maxEntities;
2007-06-21 22:00:00 +02:00
2009-11-27 22:00:00 +01:00
CL_InitEdicts (); // re-arrange edicts
2008-08-02 22:00:00 +02:00
// get splash name
2010-08-20 22:00:00 +02:00
Cvar_Set( "cl_levelshot_name", va( "levelshots/%s", clgame.mapname ));
2010-10-31 22:00:00 +01:00
Cvar_SetFloat( "scr_loading", 0.0f ); // reset progress bar
2009-07-27 22:00:00 +02:00
2010-07-17 22:00:00 +02:00
if( cl_allow_levelshots->integer && !cls.changelevel )
2007-06-21 22:00:00 +02:00
{
2010-07-17 22:00:00 +02:00
// FIXME: Quake3 may be use both 'jpg' and 'tga' levelshot types
2010-09-10 22:00:00 +02:00
if( !FS_FileExistsEx( va( "%s.%s", cl_levelshot_name->string, SI->levshot_ext ), true ))
2010-07-17 22:00:00 +02:00
{
Cvar_Set( "cl_levelshot_name", MAP_DEFAULT_SHADER ); // render a black screen
cls.scrshot_request = scrshot_plaque; // make levelshot
}
2007-06-21 22:00:00 +02:00
}
2010-03-10 22:00:00 +01:00
2010-10-31 22:00:00 +01:00
if( scr_dark->integer )
{
screenfade_t *sf = &clgame.fade;
sf->fadeFlags = FFADE_IN;
sf->fader = sf->fadeg = sf->fadeb = 0;
sf->fadeEnd = sf->fadeReset = 4.0f;
sf->fadealpha = 255;
sf->fadeSpeed = (float)sf->fadealpha / sf->fadeEnd;
sf->fadeReset += cl.time;
sf->fadeEnd += sf->fadeReset;
Cvar_SetFloat( "v_dark", 0.0f );
}
2008-08-02 22:00:00 +02:00
// need to prep refresh at next oportunity
2008-08-03 22:00:00 +02:00
cl.video_prepped = false;
cl.audio_prepped = false;
2009-11-28 22:00:00 +01:00
2010-08-19 22:00:00 +02:00
Mem_Set( &clgame.movevars, 0, sizeof( clgame.movevars ));
Mem_Set( &clgame.oldmovevars, 0, sizeof( clgame.oldmovevars ));
2007-06-21 22:00:00 +02:00
}
2010-10-14 22:00:00 +02:00
/*
===================
CL_ParseClientData
===================
*/
void CL_ParseClientData( sizebuf_t *msg )
{
int i, j;
clientdata_t *from_cd, *to_cd;
weapon_data_t *from_wd, *to_wd;
weapon_data_t nullwd[32];
clientdata_t nullcd;
frame_t *frame;
int idx;
// this is the frame update that this message corresponds to
i = cls.netchan.incoming_sequence;
// did we drop some frames?
if( i > cl.last_incoming_sequence + 1 )
{
// mark as dropped
for( j = cl.last_incoming_sequence + 1; j < i; j++ )
{
if( cl.frames[j & CL_UPDATE_MASK].receivedtime >= 0.0 )
{
cl.frames[j & CL_UPDATE_MASK ].receivedtime = -1;
cl.frames[j & CL_UPDATE_MASK ].latency = 0;
}
}
}
cl.parsecount = i; // ack'd incoming messages.
cl.parsecountmod = cl.parsecount & CL_UPDATE_MASK; // index into window.
frame = &cl.frames[cl.parsecountmod]; // frame at index.
frame->time = cl.mtime[0]; // mark network received time
frame->receivedtime = host.realtime; // time now that we are parsing.
// Fixme, do this after all packets read for this frame?
cl.last_incoming_sequence = cls.netchan.incoming_sequence;
2010-11-15 22:00:00 +01:00
to_cd = &frame->local.client;
to_wd = frame->local.weapondata;
2010-10-14 22:00:00 +02:00
// clear to old value before delta parsing
if( !BF_ReadOneBit( msg ))
{
Mem_Set( &nullcd, 0, sizeof( nullcd ));
Mem_Set( nullwd, 0, sizeof( nullwd ));
from_cd = &nullcd;
from_wd = nullwd;
}
else
{
int delta_sequence = BF_ReadByte( msg );
2010-11-15 22:00:00 +01:00
from_cd = &cl.frames[delta_sequence & CL_UPDATE_MASK].local.client;
from_wd = cl.frames[delta_sequence & CL_UPDATE_MASK].local.weapondata;
2010-10-14 22:00:00 +02:00
if(( delta_sequence & CL_UPDATE_MASK ) != ( cl.delta_sequence & CL_UPDATE_MASK ))
MsgDev( D_WARN, "CL_ParseClientData: mismatch delta_sequence\n" );
}
MSG_ReadClientData( msg, from_cd, to_cd, sv_time( ));
for( i = 0; i < MAX_WEAPONS; i++ )
{
// check for end of weapondata (and clientdata_t message)
if( !BF_ReadOneBit( msg )) break;
// read the weapon idx
idx = BF_ReadUBitLong( msg, MAX_WEAPON_BITS );
MSG_ReadWeaponData( msg, &from_wd[idx], &to_wd[idx], sv_time( ));
}
}
2007-06-21 22:00:00 +02:00
/*
==================
CL_ParseBaseline
==================
*/
2010-08-06 22:00:00 +02:00
void CL_ParseBaseline( sizebuf_t *msg )
2007-06-21 22:00:00 +02:00
{
2010-08-18 22:00:00 +02:00
int newnum;
2010-10-09 22:00:00 +02:00
float timebase;
2010-08-07 22:00:00 +02:00
cl_entity_t *ent;
Delta_InitClient (); // finalize client delta's
2007-06-21 22:00:00 +02:00
2010-08-04 22:00:00 +02:00
newnum = BF_ReadWord( msg );
2008-07-01 22:00:00 +02:00
2009-11-27 22:00:00 +01:00
if( newnum < 0 ) Host_Error( "CL_SpawnEdict: invalid number %i\n", newnum );
2010-08-20 22:00:00 +02:00
if( newnum > clgame.maxEntities ) Host_Error( "CL_AllocEdict: no free edicts\n" );
2009-11-27 22:00:00 +01:00
// increase edicts
2010-08-20 22:00:00 +02:00
while( newnum >= clgame.numEntities )
clgame.numEntities++;
2009-11-27 22:00:00 +01:00
ent = EDICT_NUM( newnum );
2010-08-18 22:00:00 +02:00
Mem_Set( &ent->prevstate, 0, sizeof( ent->prevstate ));
2010-08-04 22:00:00 +02:00
if( cls.state == ca_active )
2010-10-09 22:00:00 +02:00
timebase = sv_time();
else timebase = 1.0f; // sv.state == ss_loading
2010-08-04 22:00:00 +02:00
2010-10-20 22:00:00 +02:00
MSG_ReadDeltaEntity( msg, &ent->prevstate, &ent->baseline, newnum, CL_IsPlayerIndex( newnum ), timebase );
2007-06-21 22:00:00 +02:00
}
2010-10-28 22:00:00 +02:00
/*
================
CL_ParseLightStyle
================
*/
void CL_ParseLightStyle( sizebuf_t *msg )
{
int style;
const char *s;
style = BF_ReadByte( msg );
s = BF_ReadString( msg );
CL_SetLightstyle( style, s );
}
2008-11-27 22:00:00 +01:00
/*
================
CL_ParseSetAngle
set the view angle to this absolute value
================
*/
2010-08-06 22:00:00 +02:00
void CL_ParseSetAngle( sizebuf_t *msg )
2008-11-27 22:00:00 +01:00
{
2010-08-04 22:00:00 +02:00
cl.refdef.cl_viewangles[0] = BF_ReadBitAngle( msg, 16 );
cl.refdef.cl_viewangles[1] = BF_ReadBitAngle( msg, 16 );
2008-11-27 22:00:00 +01:00
}
2007-06-21 22:00:00 +02:00
2010-04-12 22:00:00 +02:00
/*
================
CL_ParseAddAngle
add the view angle yaw
================
*/
2010-08-06 22:00:00 +02:00
void CL_ParseAddAngle( sizebuf_t *msg )
2010-04-12 22:00:00 +02:00
{
2010-06-20 22:00:00 +02:00
float add_angle;
2010-04-12 22:00:00 +02:00
2010-08-04 22:00:00 +02:00
add_angle = BF_ReadBitAngle( msg, 16 );
2010-06-20 22:00:00 +02:00
cl.refdef.cl_viewangles[1] += add_angle;
2010-04-12 22:00:00 +02:00
}
2010-10-19 22:00:00 +02:00
2009-01-23 22:00:00 +01:00
/*
================
CL_ParseCrosshairAngle
offset crosshair angles
================
*/
2010-08-06 22:00:00 +02:00
void CL_ParseCrosshairAngle( sizebuf_t *msg )
2009-01-23 22:00:00 +01:00
{
2010-10-19 22:00:00 +02:00
cl.refdef.crosshairangle[0] = BF_ReadChar( msg ) * 0.2f;
cl.refdef.crosshairangle[1] = BF_ReadChar( msg ) * 0.2f;
2009-12-04 22:00:00 +01:00
cl.refdef.crosshairangle[2] = 0.0f; // not used for screen space
}
2010-06-22 22:00:00 +02:00
/*
================
CL_RegisterUserMessage
register new user message or update existing
================
*/
2010-08-06 22:00:00 +02:00
void CL_RegisterUserMessage( sizebuf_t *msg )
2010-06-22 22:00:00 +02:00
{
char *pszName;
int svc_num, size;
2010-08-04 22:00:00 +02:00
svc_num = BF_ReadByte( msg );
size = BF_ReadByte( msg );
2010-10-19 22:00:00 +02:00
pszName = BF_ReadString( msg );
2010-06-22 22:00:00 +02:00
// important stuff
if( size == 0xFF ) size = -1;
2010-08-16 22:00:00 +02:00
svc_num = bound( 0, svc_num, 255 );
2010-06-22 22:00:00 +02:00
CL_LinkUserMessage( pszName, svc_num, size );
}
2009-12-04 22:00:00 +01:00
/*
================
CL_UpdateUserinfo
collect userinfo from all players
================
*/
2010-08-06 22:00:00 +02:00
void CL_UpdateUserinfo( sizebuf_t *msg )
2009-12-04 22:00:00 +01:00
{
int slot;
2010-10-26 22:00:00 +02:00
qboolean active;
2009-12-04 22:00:00 +01:00
player_info_t *player;
2010-10-09 22:00:00 +02:00
slot = BF_ReadUBitLong( msg, MAX_CLIENT_BITS );
2009-12-04 22:00:00 +01:00
if( slot >= MAX_CLIENTS )
2010-04-20 22:00:00 +02:00
Host_Error( "CL_ParseServerMessage: svc_updateuserinfo > MAX_CLIENTS\n" );
2009-12-04 22:00:00 +01:00
player = &cl.players[slot];
2010-10-09 22:00:00 +02:00
active = BF_ReadOneBit( msg ) ? true : false;
2009-12-04 22:00:00 +01:00
if( active )
{
2010-08-04 22:00:00 +02:00
com.strncpy( player->userinfo, BF_ReadString( msg ), sizeof( player->userinfo ));
2009-12-04 22:00:00 +01:00
com.strncpy( player->name, Info_ValueForKey( player->userinfo, "name" ), sizeof( player->name ));
com.strncpy( player->model, Info_ValueForKey( player->userinfo, "model" ), sizeof( player->model ));
}
else Mem_Set( player, 0, sizeof( *player ));
2009-01-23 22:00:00 +01:00
}
2010-10-26 22:00:00 +02:00
/*
================
CL_PrecacheModel
prceache model from server
================
*/
void CL_PrecacheModel( sizebuf_t *msg )
{
int modelIndex;
modelIndex = BF_ReadUBitLong( msg, MAX_MODEL_BITS );
if( modelIndex < 0 || modelIndex >= MAX_MODELS )
Host_Error( "CL_PrecacheModel: bad modelindex %i\n", modelIndex );
2010-10-28 22:00:00 +02:00
com.strncpy( cl.model_precache[modelIndex], BF_ReadString( msg ), sizeof( cl.model_precache[0] ));
2010-10-26 22:00:00 +02:00
// when we loading map all resources is precached sequentially
if( !cl.video_prepped ) return;
re->RegisterModel( cl.model_precache[modelIndex], modelIndex );
CM_RegisterModel( cl.model_precache[modelIndex], modelIndex );
}
/*
================
CL_PrecacheSound
prceache sound from server
================
*/
void CL_PrecacheSound( sizebuf_t *msg )
{
int soundIndex;
soundIndex = BF_ReadUBitLong( msg, MAX_SOUND_BITS );
if( soundIndex < 0 || soundIndex >= MAX_SOUNDS )
Host_Error( "CL_PrecacheSound: bad soundindex %i\n", soundIndex );
2010-10-28 22:00:00 +02:00
com.strncpy( cl.sound_precache[soundIndex], BF_ReadString( msg ), sizeof( cl.sound_precache[0] ));
2010-10-26 22:00:00 +02:00
// when we loading map all resources is precached sequentially
if( !cl.audio_prepped ) return;
cl.sound_index[soundIndex] = S_RegisterSound( cl.sound_precache[soundIndex] );
}
2010-10-28 22:00:00 +02:00
/*
================
CL_PrecacheEvent
prceache event from server
================
*/
void CL_PrecacheEvent( sizebuf_t *msg )
{
int eventIndex;
eventIndex = BF_ReadUBitLong( msg, MAX_EVENT_BITS );
if( eventIndex < 0 || eventIndex >= MAX_EVENTS )
Host_Error( "CL_PrecacheEvent: bad eventindex %i\n", eventIndex );
com.strncpy( cl.event_precache[eventIndex], BF_ReadString( msg ), sizeof( cl.event_precache[0] ));
// can be set now
CL_SetEventIndex( cl.event_precache[eventIndex], eventIndex );
}
2010-10-14 22:00:00 +02:00
/*
================
CL_UpdateUserPings
collect pings and packet lossage from clients
================
*/
void CL_UpdateUserPings( sizebuf_t *msg )
{
int i, slot;
player_info_t *player;
for( i = 0; i < MAX_CLIENTS; i++ )
{
if( !BF_ReadOneBit( msg )) break; // end of message
slot = BF_ReadUBitLong( msg, MAX_CLIENT_BITS );
if( slot >= MAX_CLIENTS )
Host_Error( "CL_ParseServerMessage: svc_updatepings > MAX_CLIENTS\n" );
player = &cl.players[slot];
player->ping = BF_ReadUBitLong( msg, 12 );
player->packet_loss = BF_ReadUBitLong( msg, 7 );
}
}
2010-03-30 22:00:00 +02:00
/*
==============
CL_ServerInfo
change serverinfo
==============
*/
2010-08-06 22:00:00 +02:00
void CL_ServerInfo( sizebuf_t *msg )
2010-03-30 22:00:00 +02:00
{
char key[MAX_MSGLEN];
char value[MAX_MSGLEN];
2010-08-04 22:00:00 +02:00
com.strncpy( key, BF_ReadString( msg ), sizeof( key ));
com.strncpy( value, BF_ReadString( msg ), sizeof( value ));
2010-03-30 22:00:00 +02:00
Info_SetValueForKey( cl.serverinfo, key, value );
}
2010-08-16 22:00:00 +02:00
/*
==============
CL_ParseDirector
hltv is handled in the client.dll
==============
*/
void CL_ParseDirector( sizebuf_t *msg )
{
byte pbuf[256];
int iSize = BF_ReadByte( msg );
// parse user message into buffer
BF_ReadBytes( msg, pbuf, iSize );
clgame.dllFuncs.pfnDirectorMessage( iSize, pbuf );
}
2010-10-31 22:00:00 +01:00
/*
==============
CL_ParseScreenShake
Set screen shake
==============
*/
void CL_ParseScreenShake( sizebuf_t *msg )
{
clgame.shake.amplitude = (float)(word)BF_ReadShort( msg ) * (1.0f / (float)(1<<12));
clgame.shake.duration = (float)(word)BF_ReadShort( msg ) * (1.0f / (float)(1<<12));
clgame.shake.frequency = (float)(word)BF_ReadShort( msg ) * (1.0f / (float)(1<<8));
clgame.shake.time = cl.time + max( clgame.shake.duration, 0.01f );
clgame.shake.next_shake = 0.0f; // apply immediately
}
/*
==============
CL_ParseScreenFade
Set screen fade
==============
*/
void CL_ParseScreenFade( sizebuf_t *msg )
{
float duration, holdTime;
screenfade_t *sf = &clgame.fade;
duration = (float)(word)BF_ReadShort( msg ) * (1.0f / (float)(1<<12));
holdTime = (float)(word)BF_ReadShort( msg ) * (1.0f / (float)(1<<12));
sf->fadeFlags = BF_ReadShort( msg );
sf->fader = BF_ReadByte( msg );
sf->fadeg = BF_ReadByte( msg );
sf->fadeb = BF_ReadByte( msg );
sf->fadealpha = BF_ReadByte( msg );
sf->fadeSpeed = 0.0f;
sf->fadeEnd = duration;
sf->fadeReset = holdTime;
// calc fade speed
if( duration > 0 )
{
if( sf->fadeFlags & FFADE_OUT )
{
if( sf->fadeEnd )
{
sf->fadeSpeed = -(float)sf->fadealpha / sf->fadeEnd;
}
sf->fadeEnd += cl.time;
sf->fadeReset += sf->fadeEnd;
}
else
{
if( sf->fadeEnd )
{
sf->fadeSpeed = (float)sf->fadealpha / sf->fadeEnd;
}
sf->fadeReset += cl.time;
sf->fadeEnd += sf->fadeReset;
}
}
}
2010-11-15 22:00:00 +01:00
/*
==============
CL_DispatchUserMessage
Dispatch user message by engine request
==============
*/
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf )
{
int i;
if( !pszName || !*pszName )
return false;
for( i = 0; i < MAX_USER_MESSAGES; i++ )
{
// search for user message
if( !com.strcmp( clgame.msg[i].name, pszName ))
break;
}
if( i == MAX_USER_MESSAGES )
{
MsgDev( D_ERROR, "CL_DispatchUserMessage: bad message %s\n", pszName );
return false;
}
if( clgame.msg[i].func ) clgame.msg[i].func( pszName, iSize, pbuf );
else MsgDev( D_ERROR, "CL_DispatchUserMessage: %s not hooked\n", pszName );
return true;
}
2010-06-22 22:00:00 +02:00
/*
==============
CL_ParseUserMessage
handles all user messages
==============
*/
2010-08-06 22:00:00 +02:00
void CL_ParseUserMessage( sizebuf_t *msg, int svc_num )
2010-06-22 22:00:00 +02:00
{
2010-08-04 22:00:00 +02:00
int i, iSize;
2010-08-16 22:00:00 +02:00
byte pbuf[256]; // message can't be larger than 255 bytes
2010-06-22 22:00:00 +02:00
// NOTE: any user message parse on engine, not in client.dll
2010-08-16 22:00:00 +02:00
if( svc_num < svc_lastmsg || svc_num >= ( MAX_USER_MESSAGES + svc_lastmsg ))
2010-06-22 22:00:00 +02:00
{
// out or range
Host_Error( "CL_ParseUserMessage: illegible server message %d\n", svc_num );
return;
}
2010-08-16 22:00:00 +02:00
for( i = 0; i < MAX_USER_MESSAGES; i++ )
2010-08-04 22:00:00 +02:00
{
2010-08-16 22:00:00 +02:00
// search for user message
if( clgame.msg[i].number == svc_num )
break;
2010-08-04 22:00:00 +02:00
}
2010-06-22 22:00:00 +02:00
2010-08-16 22:00:00 +02:00
if( i == MAX_USER_MESSAGES )
Host_Error( "CL_ParseUserMessage: illegible server message %d\n", svc_num );
2010-10-31 22:00:00 +01:00
// NOTE: some user messages handled into engine
if( !com.strcmp( clgame.msg[i].name, "ScreenShake" ))
{
CL_ParseScreenShake( msg );
return;
}
else if( !com.strcmp( clgame.msg[i].name, "ScreenFade" ))
{
CL_ParseScreenFade( msg );
return;
}
2010-08-16 22:00:00 +02:00
iSize = clgame.msg[i].size;
2010-06-22 22:00:00 +02:00
// message with variable sizes receive an actual size as first byte
2010-08-04 22:00:00 +02:00
if( iSize == -1 ) iSize = BF_ReadByte( msg );
2010-06-22 22:00:00 +02:00
// parse user message into buffer
2010-08-04 22:00:00 +02:00
BF_ReadBytes( msg, pbuf, iSize );
2010-06-22 22:00:00 +02:00
2010-08-16 22:00:00 +02:00
if( clgame.msg[i].func ) clgame.msg[i].func( clgame.msg[i].name, iSize, pbuf );
else MsgDev( D_ERROR, "CL_ParseUserMessage: %s not hooked\n", clgame.msg[i].name );
2010-06-22 22:00:00 +02:00
}
2007-06-21 22:00:00 +02:00
/*
=====================================================================
ACTION MESSAGES
=====================================================================
*/
/*
=====================
CL_ParseServerMessage
=====================
*/
2010-08-06 22:00:00 +02:00
void CL_ParseServerMessage( sizebuf_t *msg )
2007-06-21 22:00:00 +02:00
{
2008-06-30 22:00:00 +02:00
char *s;
2010-10-14 22:00:00 +02:00
int i, j, cmd;
2010-08-16 22:00:00 +02:00
int param1, param2;
2010-03-27 22:00:00 +01:00
int bufStart;
2007-06-21 22:00:00 +02:00
2010-08-04 22:00:00 +02:00
cls_message_debug.parsing = true; // begin parsing
starting_count = BF_GetNumBytesRead( msg ); // updates each frame
2010-03-27 22:00:00 +01:00
2007-08-17 22:00:00 +02:00
// parse the message
2008-05-20 22:00:00 +02:00
while( 1 )
2007-06-21 22:00:00 +02:00
{
2010-08-04 22:00:00 +02:00
if( BF_CheckOverflow( msg ))
2007-06-21 22:00:00 +02:00
{
2010-03-27 22:00:00 +01:00
Host_Error( "CL_ParseServerMessage: bad server message\n" );
2009-06-24 22:00:00 +02:00
return;
2007-06-21 22:00:00 +02:00
}
2010-03-27 22:00:00 +01:00
// mark start position
2010-08-04 22:00:00 +02:00
bufStart = BF_GetNumBytesRead( msg );
// end of message
if( BF_GetNumBitsLeft( msg ) < 8 )
break;
2010-03-27 22:00:00 +01:00
2010-08-04 22:00:00 +02:00
cmd = BF_ReadByte( msg );
2008-07-15 22:00:00 +02:00
2010-03-27 22:00:00 +01:00
// record command for debugging spew on parse problem
CL_Parse_RecordCommand( cmd, bufStart );
2007-08-17 22:00:00 +02:00
// other commands
2008-06-30 22:00:00 +02:00
switch( cmd )
2007-06-21 22:00:00 +02:00
{
2010-08-16 22:00:00 +02:00
case svc_bad:
Host_Error( "svc_bad\n" );
break;
2007-06-21 22:00:00 +02:00
case svc_nop:
break;
case svc_disconnect:
2007-09-10 22:00:00 +02:00
CL_Drop ();
Host_AbortCurrentFrame();
2007-06-21 22:00:00 +02:00
break;
2010-03-28 22:00:00 +02:00
case svc_changing:
2010-08-16 22:00:00 +02:00
if( BF_ReadOneBit( msg ))
{
cls.changelevel = true;
S_StopAllSounds();
}
else MsgDev( D_INFO, "Server disconnected, reconnecting\n" );
2008-06-30 22:00:00 +02:00
if( cls.download )
2007-06-21 22:00:00 +02:00
{
2008-06-30 22:00:00 +02:00
FS_Close( cls.download );
2007-06-21 22:00:00 +02:00
cls.download = NULL;
}
cls.state = ca_connecting;
2008-06-30 22:00:00 +02:00
cls.connect_time = MAX_HEARTBEAT; // CL_CheckForResend() will fire immediately
2007-06-21 22:00:00 +02:00
break;
2010-08-16 22:00:00 +02:00
case svc_setview:
cl.refdef.viewentity = BF_ReadWord( msg );
break;
case svc_sound:
CL_ParseSoundPacket( msg, false );
break;
case svc_time:
2010-10-14 22:00:00 +02:00
cl.mtime[1] = cl.mtime[0];
cl.mtime[0] = BF_ReadFloat( msg );
break;
2010-08-16 22:00:00 +02:00
case svc_print:
i = BF_ReadByte( msg );
if( i == PRINT_CHAT ) // chat
2010-08-20 22:00:00 +02:00
S_StartLocalSound( "common/menu2.wav" ); // FIXME: INTRESOURCE
2010-08-16 22:00:00 +02:00
MsgDev( D_INFO, "^6%s\n", BF_ReadString( msg ));
break;
2007-06-21 22:00:00 +02:00
case svc_stufftext:
2010-08-04 22:00:00 +02:00
s = BF_ReadString( msg );
2008-06-30 22:00:00 +02:00
Cbuf_AddText( s );
2007-06-21 22:00:00 +02:00
break;
2010-10-28 22:00:00 +02:00
case svc_lightstyle:
CL_ParseLightStyle( msg );
break;
2010-08-16 22:00:00 +02:00
case svc_setangle:
CL_ParseSetAngle( msg );
break;
2007-06-21 22:00:00 +02:00
case svc_serverdata:
2008-08-02 22:00:00 +02:00
Cbuf_Execute(); // make sure any stuffed commands are done
2008-05-20 22:00:00 +02:00
CL_ParseServerData( msg );
2007-06-21 22:00:00 +02:00
break;
2010-08-16 22:00:00 +02:00
case svc_addangle:
CL_ParseAddAngle( msg );
2007-06-21 22:00:00 +02:00
break;
2010-08-16 22:00:00 +02:00
case svc_clientdata:
2010-10-14 22:00:00 +02:00
CL_ParseClientData( msg );
2010-08-16 22:00:00 +02:00
break;
case svc_packetentities:
2010-10-14 22:00:00 +02:00
CL_ParsePacketEntities( msg, false );
break;
case svc_deltapacketentities:
CL_ParsePacketEntities( msg, true );
2010-08-05 22:00:00 +02:00
break;
2007-06-21 22:00:00 +02:00
case svc_download:
2008-05-20 22:00:00 +02:00
CL_ParseDownload( msg );
2007-06-21 22:00:00 +02:00
break;
2010-10-14 22:00:00 +02:00
case svc_updatepings:
CL_UpdateUserPings( msg );
break;
2010-08-16 22:00:00 +02:00
case svc_usermessage:
CL_RegisterUserMessage( msg );
break;
case svc_particle:
CL_ParseParticles( msg );
2010-04-24 22:00:00 +02:00
break;
2010-10-17 22:00:00 +02:00
case svc_spawnstatic:
CL_ParseStaticEntity( msg );
break;
2010-04-24 22:00:00 +02:00
case svc_ambientsound:
CL_ParseSoundPacket( msg, true );
2008-12-21 22:00:00 +01:00
break;
2009-01-23 22:00:00 +01:00
case svc_crosshairangle:
CL_ParseCrosshairAngle( msg );
break;
2010-08-16 22:00:00 +02:00
case svc_spawnbaseline:
CL_ParseBaseline( msg );
2008-12-26 22:00:00 +01:00
break;
2010-08-16 22:00:00 +02:00
case svc_temp_entity:
CL_ParseTempEntity( msg );
2009-11-23 22:00:00 +01:00
break;
2009-11-10 22:00:00 +01:00
case svc_setpause:
2010-08-16 22:00:00 +02:00
cl.refdef.paused = (BF_ReadOneBit( msg ) != 0 );
2009-11-10 22:00:00 +01:00
break;
2010-08-16 22:00:00 +02:00
case svc_deltamovevars:
2009-11-10 22:00:00 +01:00
CL_ParseMovevars( msg );
break;
2010-08-16 22:00:00 +02:00
case svc_centerprint:
CL_CenterPrint( BF_ReadString( msg ), 0.35f );
2009-11-25 22:00:00 +01:00
break;
2009-12-02 22:00:00 +01:00
case svc_event:
CL_ParseEvent( msg );
break;
case svc_event_reliable:
CL_ParseReliableEvent( msg, FEV_RELIABLE );
break;
2009-12-04 22:00:00 +01:00
case svc_updateuserinfo:
CL_UpdateUserinfo( msg );
break;
2010-08-16 22:00:00 +02:00
case svc_intermission:
cl.refdef.intermission = true;
break;
2010-10-26 22:00:00 +02:00
case svc_modelindex:
CL_PrecacheModel( msg );
break;
case svc_soundindex:
CL_PrecacheSound( msg );
break;
2010-08-16 22:00:00 +02:00
case svc_soundfade:
CL_ParseSoundFade( msg );
break;
case svc_cdtrack:
2010-11-19 22:00:00 +01:00
param1 = bound( 1, BF_ReadByte( msg ), 32 ); // tracknum
param2 = bound( 1, BF_ReadByte( msg ), 32 ); // loopnum
S_StartBackgroundTrack( clgame.cdtracks[param1-1], clgame.cdtracks[param2-1] );
2010-08-16 22:00:00 +02:00
break;
2010-03-30 22:00:00 +02:00
case svc_serverinfo:
CL_ServerInfo( msg );
break;
2010-10-28 22:00:00 +02:00
case svc_eventindex:
CL_PrecacheEvent( msg );
break;
2010-08-16 22:00:00 +02:00
case svc_deltatable:
Delta_ParseTableField( msg );
2007-06-21 22:00:00 +02:00
break;
2010-08-16 22:00:00 +02:00
case svc_weaponanim:
param1 = BF_ReadByte( msg ); // iAnim
param2 = BF_ReadByte( msg ); // body
CL_WeaponAnim( param1, param2 );
2008-06-30 22:00:00 +02:00
break;
2010-08-16 22:00:00 +02:00
case svc_bspdecal:
CL_ParseStaticDecal( msg );
break;
case svc_roomtype:
param1 = BF_ReadShort( msg );
2010-10-31 22:00:00 +01:00
Cvar_SetFloat( "room_type", param1 );
2010-08-16 22:00:00 +02:00
break;
2010-10-14 22:00:00 +02:00
case svc_chokecount:
i = BF_ReadByte( msg );
j = cls.netchan.incoming_acknowledged - 1;
for( ; i > 0 && j > cls.netchan.outgoing_sequence - CL_UPDATE_BACKUP; j-- )
{
if( cl.frames[j & CL_UPDATE_MASK].receivedtime != -3.0 )
{
cl.frames[j & CL_UPDATE_MASK].receivedtime = -2.0;
i--;
}
}
break;
2010-08-16 22:00:00 +02:00
case svc_director:
CL_ParseDirector( msg );
2007-06-21 22:00:00 +02:00
break;
2007-11-17 22:00:00 +01:00
default:
2008-12-25 22:00:00 +01:00
CL_ParseUserMessage( msg, cmd );
2007-11-17 22:00:00 +01:00
break;
2007-06-21 22:00:00 +02:00
}
}
2010-08-19 22:00:00 +02:00
2010-03-27 22:00:00 +01:00
cls_message_debug.parsing = false; // done
2008-06-30 22:00:00 +02:00
}