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

417 lines
10 KiB
C
Raw Normal View History

2007-06-21 22:00:00 +02:00
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// cl_parse.c -- parse a message received from the server
2008-06-09 22:00:00 +02:00
#include "common.h"
2007-06-21 22:00:00 +02:00
#include "client.h"
/*
===============
CL_CheckOrDownloadFile
Returns true if the file exists, otherwise it attempts
to start a download from the server.
===============
*/
2008-08-02 22:00:00 +02:00
bool 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-08-02 22:00:00 +02:00
int 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 );
2008-07-15 22:00:00 +02:00
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
2008-08-02 22:00:00 +02:00
MSG_Print( &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 );
2008-07-15 22:00:00 +02:00
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
2008-08-02 22:00:00 +02:00
MSG_Print( &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
=====================
*/
2008-05-20 22:00:00 +02:00
void CL_ParseDownload( sizebuf_t *msg )
2007-06-21 22:00:00 +02:00
{
int size, percent;
2008-05-20 22:00:00 +02:00
string name;
2007-06-21 22:00:00 +02:00
int r;
// read the data
2008-05-20 22:00:00 +02:00
size = MSG_ReadShort( msg );
percent = MSG_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
{
2008-05-20 22:00:00 +02:00
msg->readcount += size;
2008-08-02 22:00:00 +02:00
Msg( "Failed to open %s\n", cls.downloadtempname );
CL_RequestNextDownload();
2007-06-21 22:00:00 +02:00
return;
}
}
2008-08-02 22:00:00 +02:00
FS_Write( cls.download, msg->data + msg->readcount, size );
2008-05-20 22:00:00 +02:00
msg->readcount += 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
cls.downloadpercent = percent;
2008-07-15 22:00:00 +02:00
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
MSG_Print( &cls.netchan.message, "nextdl" );
2007-06-21 22:00:00 +02:00
}
else
{
2008-07-23 22:00:00 +02:00
string oldn, newn;
2007-06-21 22:00:00 +02:00
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
2008-08-02 22:00:00 +02:00
com.strncpy( oldn, cls.downloadtempname, MAX_STRING );
com.strncpy( newn, cls.downloadname, MAX_STRING );
r = rename( oldn, newn );
if( r ) MsgDev( D_ERROR, "failed to rename.\n" );
2007-06-21 22:00:00 +02:00
cls.download = NULL;
cls.downloadpercent = 0;
// get another file if needed
2008-08-02 22:00:00 +02:00
CL_RequestNextDownload();
}
}
/*
======================
CL_RegisterSounds
======================
*/
void CL_RegisterSounds( void )
{
int i;
2007-06-21 22:00:00 +02:00
2008-08-02 22:00:00 +02:00
S_BeginRegistration();
for( i = 1; i < MAX_SOUNDS; i++ )
{
if (!cl.configstrings[CS_SOUNDS+i][0]) break;
cl.sound_precache[i] = S_RegisterSound (cl.configstrings[CS_SOUNDS+i]);
Sys_SendKeyEvents(); // pump message loop
2007-06-21 22:00:00 +02:00
}
2008-08-02 22:00:00 +02:00
S_EndRegistration();
2007-06-21 22:00:00 +02:00
}
/*
=====================================================================
SERVER CONNECTING MESSAGES
=====================================================================
*/
/*
==================
CL_ParseServerData
==================
*/
2008-05-20 22:00:00 +02:00
void CL_ParseServerData( sizebuf_t *msg )
2007-06-21 22:00:00 +02:00
{
2007-11-17 22:00:00 +01:00
char *str;
2007-06-21 22:00:00 +02:00
int i;
2007-10-19 22:00:00 +02:00
2008-07-11 22:00:00 +02:00
MsgDev(D_INFO, "Serverdata packet received.\n");
2007-11-04 22:00:00 +01:00
// wipe the client_t struct
2008-07-12 22:00:00 +02:00
CL_ClearState();
2007-06-21 22:00:00 +02:00
cls.state = ca_connected;
2007-09-10 22:00:00 +02:00
// parse protocol version number
2008-05-20 22:00:00 +02:00
i = MSG_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 )
Host_Error("Server use invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION );
2007-06-21 22:00:00 +02:00
2008-05-20 22:00:00 +02:00
cl.servercount = MSG_ReadLong( msg );
cl.playernum = MSG_ReadShort( msg );
str = MSG_ReadString( msg );
2007-06-21 22:00:00 +02:00
2008-08-02 22:00:00 +02:00
// get splash name
Cvar_Set( "cl_levelshot_name", va("background/%s.tga", str ));
Cvar_SetValue("scr_loading", 0.0f ); // reset progress bar
if(!FS_FileExists(va("gfx/%s", Cvar_VariableString("cl_levelshot_name"))))
2007-06-21 22:00:00 +02:00
{
2008-08-02 22:00:00 +02:00
Cvar_Set("cl_levelshot_name", "common/black");
cl.make_levelshot = true; // make levelshot
2007-06-21 22:00:00 +02:00
}
2008-08-02 22:00:00 +02:00
// seperate the printfs so the server message can have a color
Msg("\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n");
// need to prep refresh at next oportunity
cl.refresh_prepped = false;
2007-06-21 22:00:00 +02:00
}
/*
==================
CL_ParseBaseline
==================
*/
2008-05-20 22:00:00 +02:00
void CL_ParseBaseline( sizebuf_t *msg )
2007-06-21 22:00:00 +02:00
{
2007-10-29 22:00:00 +01:00
int newnum;
2007-06-21 22:00:00 +02:00
entity_state_t nullstate;
2008-07-01 22:00:00 +02:00
edict_t *ent;
2007-06-21 22:00:00 +02:00
2008-07-15 22:00:00 +02:00
CL_VM_Begin();
memset( &nullstate, 0, sizeof(nullstate));
newnum = MSG_ReadBits( msg, NET_WORD );
2008-07-01 22:00:00 +02:00
2008-08-02 22:00:00 +02:00
// increase edicts
2008-07-01 22:00:00 +02:00
while( newnum >= prog->num_edicts ) PRVM_ED_Alloc();
ent = PRVM_EDICT_NUM( newnum );
2008-07-12 22:00:00 +02:00
MSG_ReadDeltaEntity( msg, &nullstate, &ent->priv.cl->baseline, newnum );
2007-06-21 22:00:00 +02:00
}
/*
================
CL_ParseConfigString
================
*/
2008-05-20 22:00:00 +02:00
void CL_ParseConfigString( sizebuf_t *msg )
2007-06-21 22:00:00 +02:00
{
int i;
2008-05-20 22:00:00 +02:00
i = MSG_ReadShort( msg );
2008-08-02 22:00:00 +02:00
if( i < 0 || i >= MAX_CONFIGSTRINGS )
Host_Error("configstring > MAX_CONFIGSTRINGS\n");
com.strcpy( cl.configstrings[i], MSG_ReadString( msg ));
2007-06-21 22:00:00 +02:00
// do something apropriate
2008-08-02 22:00:00 +02:00
if( i >= CS_MODELS && i < CS_MODELS+MAX_MODELS )
2007-06-21 22:00:00 +02:00
{
2008-08-02 22:00:00 +02:00
if( cl.refresh_prepped )
2007-06-21 22:00:00 +02:00
{
2008-08-02 22:00:00 +02:00
re->RegisterModel( cl.configstrings[i], i-CS_MODELS );
2008-07-30 22:00:00 +02:00
cl.models[i-CS_MODELS] = pe->RegisterModel( cl.configstrings[i] );
2007-06-21 22:00:00 +02:00
}
}
2008-08-02 22:00:00 +02:00
else if( i >= CS_SOUNDS && i < CS_SOUNDS+MAX_MODELS )
2007-06-21 22:00:00 +02:00
{
2008-08-02 22:00:00 +02:00
if( cl.refresh_prepped )
cl.sound_precache[i-CS_SOUNDS] = S_RegisterSound( cl.configstrings[i] );
2007-06-21 22:00:00 +02:00
}
2008-08-02 22:00:00 +02:00
else if( i >= CS_CLASSNAMES && i < CS_CLASSNAMES+MAX_CLASSNAMES )
2007-06-21 22:00:00 +02:00
{
2008-08-02 22:00:00 +02:00
// prvm classnames for search by classname on client vm
cl.edict_classnames[i-CS_CLASSNAMES] = PRVM_SetEngineString( cl.configstrings[i] );
2007-06-21 22:00:00 +02:00
}
2008-08-02 22:00:00 +02:00
else if( i >= CS_LIGHTSTYLES && i < CS_LIGHTSTYLES+MAX_LIGHTSTYLES )
2007-06-21 22:00:00 +02:00
{
2008-08-02 22:00:00 +02:00
CL_SetLightstyle( i - CS_LIGHTSTYLES );
2007-06-21 22:00:00 +02:00
}
}
/*
=====================================================================
ACTION MESSAGES
=====================================================================
*/
/*
==================
CL_ParseStartSoundPacket
==================
*/
2008-05-20 22:00:00 +02:00
void CL_ParseStartSoundPacket( sizebuf_t *msg )
2007-06-21 22:00:00 +02:00
{
2008-05-20 22:00:00 +02:00
vec3_t pos_v;
2008-07-16 22:00:00 +02:00
float *pos = NULL;
int channel = 0;
2007-10-29 22:00:00 +01:00
int sound_num;
float volume;
2008-07-16 22:00:00 +02:00
int attenuation;
int flags, ent = 0;
2007-06-21 22:00:00 +02:00
2008-05-20 22:00:00 +02:00
flags = MSG_ReadByte( msg );
sound_num = MSG_ReadByte( msg );
2007-06-21 22:00:00 +02:00
2008-07-16 22:00:00 +02:00
if( flags & SND_VOL ) volume = MSG_ReadBits( msg, NET_COLOR );
else volume = 1.0f;
if( flags & SND_ATTN ) attenuation = MSG_ReadByte( msg );
else attenuation = ATTN_NORM;
2007-06-21 22:00:00 +02:00
2008-07-16 22:00:00 +02:00
if( flags & SND_ENT )
2007-09-10 22:00:00 +02:00
{
// entity reletive
2008-05-20 22:00:00 +02:00
channel = MSG_ReadShort( msg );
2007-06-21 22:00:00 +02:00
ent = channel>>3;
2008-07-17 22:00:00 +02:00
if( ent > host.max_edicts ) Host_Error("CL_ParseStartSoundPacket: ent out of range\n" );
2007-06-21 22:00:00 +02:00
channel &= 7;
}
2008-07-16 22:00:00 +02:00
if( flags & SND_POS )
2007-10-29 22:00:00 +01:00
{
// positioned in space
2008-07-16 22:00:00 +02:00
MSG_ReadPos( msg, pos_v );
2007-06-21 22:00:00 +02:00
pos = pos_v;
}
2008-07-16 22:00:00 +02:00
if(!cl.sound_precache[sound_num]) return;
S_StartSound( pos, ent, channel, cl.sound_precache[sound_num], volume, attenuation );
2007-06-21 22:00:00 +02:00
}
/*
=====================
CL_ParseServerMessage
=====================
*/
2008-05-20 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;
int cmd;
2007-06-21 22:00:00 +02:00
2008-08-02 22:00:00 +02:00
// client progs can recivied messages too
cls.multicast = msg;
2008-05-23 22:00:00 +02: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
{
2008-07-12 22:00:00 +02:00
if( msg->readcount > msg->cursize )
2007-06-21 22:00:00 +02:00
{
2007-09-10 22:00:00 +02:00
Host_Error("CL_ParseServerMessage: Bad server message\n");
2007-06-21 22:00:00 +02:00
break;
}
2008-05-20 22:00:00 +02:00
cmd = MSG_ReadByte( msg );
2008-07-12 22:00:00 +02:00
if( cmd == -1 ) break;
2008-07-15 22:00:00 +02:00
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
{
case svc_nop:
2008-06-30 22:00:00 +02:00
MsgDev( D_ERROR, "CL_ParseServerMessage: user message out of bounds\n" );
2007-06-21 22:00:00 +02:00
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;
case svc_reconnect:
2008-06-30 22:00:00 +02:00
Msg( "Server disconnected, reconnecting\n" );
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;
case svc_stufftext:
2008-05-20 22:00:00 +02:00
s = MSG_ReadString( msg );
2008-06-30 22:00:00 +02:00
Cbuf_AddText( s );
2007-06-21 22:00:00 +02:00
break;
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;
case svc_configstring:
2008-05-20 22:00:00 +02:00
CL_ParseConfigString( msg );
2007-06-21 22:00:00 +02:00
break;
case svc_sound:
2008-05-20 22:00:00 +02:00
CL_ParseStartSoundPacket( msg );
2007-06-21 22:00:00 +02:00
break;
case svc_spawnbaseline:
2008-05-20 22:00:00 +02:00
CL_ParseBaseline( msg );
2007-06-21 22:00:00 +02:00
break;
case svc_temp_entity:
2008-06-30 22:00:00 +02:00
CL_ParseTempEnts( msg );
2007-06-21 22:00:00 +02:00
break;
case svc_download:
2008-05-20 22:00:00 +02:00
CL_ParseDownload( msg );
2007-06-21 22:00:00 +02:00
break;
case svc_frame:
2008-05-20 22:00:00 +02:00
CL_ParseFrame( msg );
2007-06-21 22:00:00 +02:00
break;
2008-08-02 22:00:00 +02:00
case svc_clientindex:
2007-06-21 22:00:00 +02:00
case svc_packetentities:
case svc_deltapacketentities:
2008-08-02 22:00:00 +02:00
Host_Error( "CL_ParseServerMessage: out of place frame data\n" );
2008-06-30 22:00:00 +02:00
break;
case svc_bad:
2008-08-02 22:00:00 +02:00
Host_Error( "CL_ParseServerMessage: svc_bad\n" );
2007-06-21 22:00:00 +02:00
break;
2007-11-17 22:00:00 +01:00
default:
2008-06-30 22:00:00 +02:00
// parse user messages
if(!CL_ParseUserMessage( cmd ))
Host_Error("CL_ParseServerMessage: illegible server message %d\n", cmd );
2007-11-17 22:00:00 +01:00
break;
2007-06-21 22:00:00 +02:00
}
}
2008-06-30 22:00:00 +02:00
}