123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964 |
- /*
- Copyright (C) 1996-1997 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the 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"
- char *svc_strings[] =
- {
- "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",
- "OBSOLETE svc_spawnbinary",
- "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"
- };
- //=============================================================================
- /*
- ===============
- CL_EntityNum
- This error checks and tracks the total number of entities
- ===============
- */
- entity_t *CL_EntityNum (int num)
- {
- if (num >= cl.num_entities)
- {
- if (num >= MAX_EDICTS)
- Host_Error ("CL_EntityNum: %i is an invalid number",num);
- while (cl.num_entities<=num)
- {
- cl_entities[cl.num_entities].colormap = vid.colormap;
- cl.num_entities++;
- }
- }
-
- return &cl_entities[num];
- }
- /*
- ==================
- CL_ParseStartSoundPacket
- ==================
- */
- void CL_ParseStartSoundPacket(void)
- {
- vec3_t pos;
- int channel, ent;
- int sound_num;
- int volume;
- int field_mask;
- float attenuation;
- int i;
-
- field_mask = MSG_ReadByte();
- if (field_mask & SND_VOLUME)
- volume = MSG_ReadByte ();
- else
- volume = DEFAULT_SOUND_PACKET_VOLUME;
-
- if (field_mask & SND_ATTENUATION)
- attenuation = MSG_ReadByte () / 64.0;
- else
- attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
-
- channel = MSG_ReadShort ();
- sound_num = MSG_ReadByte ();
- ent = channel >> 3;
- channel &= 7;
- if (ent > MAX_EDICTS)
- Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
-
- for (i=0 ; i<3 ; i++)
- pos[i] = MSG_ReadCoord ();
-
- S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
- }
- /*
- ==================
- CL_KeepaliveMessage
- When the client is taking a long time to load stuff, send keepalive messages
- so the server doesn't disconnect.
- ==================
- */
- void CL_KeepaliveMessage (void)
- {
- float time;
- static float lastmsg;
- int ret;
- sizebuf_t old;
- byte olddata[8192];
-
- if (sv.active)
- return; // no need if server is local
- if (cls.demoplayback)
- return;
- // read messages from server, should just be nops
- 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
- time = Sys_FloatTime ();
- 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);
- }
- /*
- ==================
- CL_ParseServerInfo
- ==================
- */
- void CL_ParseServerInfo (void)
- {
- char *str;
- int i;
- int nummodels, numsounds;
- char model_precache[MAX_MODELS][MAX_QPATH];
- char sound_precache[MAX_SOUNDS][MAX_QPATH];
-
- Con_DPrintf ("Serverinfo packet received.\n");
- //
- // wipe the client_state_t struct
- //
- CL_ClearState ();
- // parse protocol version number
- i = MSG_ReadLong ();
- if (i != PROTOCOL_VERSION)
- {
- Con_Printf ("Server returned version %i, not %i", i, PROTOCOL_VERSION);
- return;
- }
- // parse maxclients
- cl.maxclients = MSG_ReadByte ();
- if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
- {
- Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
- return;
- }
- cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
- // parse gametype
- cl.gametype = MSG_ReadByte ();
- // parse signon message
- str = MSG_ReadString ();
- strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
- // seperate the printfs so the server message can have a color
- Con_Printf("\n\n\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\n");
- Con_Printf ("%c%s\n", 2, str);
- //
- // 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));
- for (nummodels=1 ; ; nummodels++)
- {
- str = MSG_ReadString ();
- if (!str[0])
- break;
- if (nummodels==MAX_MODELS)
- {
- Con_Printf ("Server sent too many model precaches\n");
- return;
- }
- strcpy (model_precache[nummodels], str);
- Mod_TouchModel (str);
- }
- // precache sounds
- memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
- for (numsounds=1 ; ; numsounds++)
- {
- str = MSG_ReadString ();
- if (!str[0])
- break;
- if (numsounds==MAX_SOUNDS)
- {
- Con_Printf ("Server sent too many sound precaches\n");
- return;
- }
- strcpy (sound_precache[numsounds], str);
- S_TouchSound (str);
- }
- //
- // now we try to load everything else until a cache allocation fails
- //
- for (i=1 ; i<nummodels ; i++)
- {
- cl.model_precache[i] = Mod_ForName (model_precache[i], false);
- if (cl.model_precache[i] == NULL)
- {
- Con_Printf("Model %s not found\n", model_precache[i]);
- return;
- }
- CL_KeepaliveMessage ();
- }
- S_BeginPrecaching ();
- for (i=1 ; i<numsounds ; i++)
- {
- cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
- CL_KeepaliveMessage ();
- }
- S_EndPrecaching ();
- // local state
- cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
-
- R_NewMap ();
- Hunk_Check (); // make sure nothing is hurt
-
- noclip_anglehack = false; // noclip is turned off at start
- }
- /*
- ==================
- 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.
- ==================
- */
- int bitcounts[16];
- void CL_ParseUpdate (int bits)
- {
- int i;
- model_t *model;
- int modnum;
- qboolean forcelink;
- entity_t *ent;
- int num;
- int skin;
- 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);
- }
- if (bits & U_LONGENTITY)
- num = MSG_ReadShort ();
- else
- num = MSG_ReadByte ();
- ent = CL_EntityNum (num);
- for (i=0 ; i<16 ; i++)
- if (bits&(1<<i))
- bitcounts[i]++;
- if (ent->msgtime != cl.mtime[1])
- forcelink = true; // no previous frame to lerp from
- else
- forcelink = false;
- ent->msgtime = cl.mtime[0];
-
- if (bits & U_MODEL)
- {
- modnum = MSG_ReadByte ();
- if (modnum >= MAX_MODELS)
- Host_Error ("CL_ParseModel: bad modnum");
- }
- else
- modnum = ent->baseline.modelindex;
-
- 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
- #ifdef GLQUAKE
- if (num > 0 && num <= cl.maxclients)
- R_TranslatePlayerSkin (num - 1);
- #endif
- }
-
- if (bits & U_FRAME)
- ent->frame = MSG_ReadByte ();
- else
- ent->frame = ent->baseline.frame;
- if (bits & U_COLORMAP)
- i = MSG_ReadByte();
- else
- i = ent->baseline.colormap;
- if (!i)
- ent->colormap = vid.colormap;
- else
- {
- if (i > cl.maxclients)
- Sys_Error ("i >= cl.maxclients");
- ent->colormap = cl.scores[i-1].translations;
- }
- #ifdef GLQUAKE
- if (bits & U_SKIN)
- skin = MSG_ReadByte();
- else
- skin = ent->baseline.skin;
- if (skin != ent->skinnum) {
- ent->skinnum = skin;
- if (num > 0 && num <= cl.maxclients)
- R_TranslatePlayerSkin (num - 1);
- }
- #else
- if (bits & U_SKIN)
- ent->skinnum = MSG_ReadByte();
- else
- ent->skinnum = ent->baseline.skin;
- #endif
- 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)
- ent->msg_origins[0][0] = MSG_ReadCoord ();
- else
- ent->msg_origins[0][0] = ent->baseline.origin[0];
- if (bits & U_ANGLE1)
- ent->msg_angles[0][0] = MSG_ReadAngle();
- else
- ent->msg_angles[0][0] = ent->baseline.angles[0];
- if (bits & U_ORIGIN2)
- ent->msg_origins[0][1] = MSG_ReadCoord ();
- else
- ent->msg_origins[0][1] = ent->baseline.origin[1];
- if (bits & U_ANGLE2)
- ent->msg_angles[0][1] = MSG_ReadAngle();
- else
- ent->msg_angles[0][1] = ent->baseline.angles[1];
- if (bits & U_ORIGIN3)
- ent->msg_origins[0][2] = MSG_ReadCoord ();
- else
- ent->msg_origins[0][2] = ent->baseline.origin[2];
- if (bits & U_ANGLE3)
- ent->msg_angles[0][2] = MSG_ReadAngle();
- else
- ent->msg_angles[0][2] = ent->baseline.angles[2];
- if ( bits & U_NOLERP )
- ent->forcelink = true;
- 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
- ==================
- */
- void CL_ParseBaseline (entity_t *ent)
- {
- int i;
-
- ent->baseline.modelindex = MSG_ReadByte ();
- ent->baseline.frame = MSG_ReadByte ();
- ent->baseline.colormap = MSG_ReadByte();
- ent->baseline.skin = MSG_ReadByte();
- for (i=0 ; i<3 ; i++)
- {
- ent->baseline.origin[i] = MSG_ReadCoord ();
- ent->baseline.angles[i] = MSG_ReadAngle ();
- }
- }
- /*
- ==================
- CL_ParseClientdata
- Server information pertaining to this client only
- ==================
- */
- void CL_ParseClientdata (int bits)
- {
- int i, j;
-
- if (bits & SU_VIEWHEIGHT)
- cl.viewheight = MSG_ReadChar ();
- else
- cl.viewheight = DEFAULT_VIEWHEIGHT;
- if (bits & SU_IDEALPITCH)
- cl.idealpitch = MSG_ReadChar ();
- else
- cl.idealpitch = 0;
-
- VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
- for (i=0 ; i<3 ; i++)
- {
- if (bits & (SU_PUNCH1<<i) )
- cl.punchangle[i] = MSG_ReadChar();
- else
- cl.punchangle[i] = 0;
- if (bits & (SU_VELOCITY1<<i) )
- cl.mvelocity[0][i] = MSG_ReadChar()*16;
- else
- cl.mvelocity[0][i] = 0;
- }
- // [always sent] if (bits & SU_ITEMS)
- i = MSG_ReadLong ();
- if (cl.items != i)
- { // set flash times
- Sbar_Changed ();
- for (j=0 ; j<32 ; j++)
- if ( (i & (1<<j)) && !(cl.items & (1<<j)))
- cl.item_gettime[j] = cl.time;
- cl.items = i;
- }
-
- cl.onground = (bits & SU_ONGROUND) != 0;
- cl.inwater = (bits & SU_INWATER) != 0;
- if (bits & SU_WEAPONFRAME)
- cl.stats[STAT_WEAPONFRAME] = MSG_ReadByte ();
- else
- cl.stats[STAT_WEAPONFRAME] = 0;
- if (bits & SU_ARMOR)
- i = MSG_ReadByte ();
- else
- i = 0;
- if (cl.stats[STAT_ARMOR] != i)
- {
- cl.stats[STAT_ARMOR] = i;
- Sbar_Changed ();
- }
- if (bits & SU_WEAPON)
- i = MSG_ReadByte ();
- else
- i = 0;
- if (cl.stats[STAT_WEAPON] != i)
- {
- cl.stats[STAT_WEAPON] = i;
- Sbar_Changed ();
- }
-
- i = MSG_ReadShort ();
- if (cl.stats[STAT_HEALTH] != i)
- {
- cl.stats[STAT_HEALTH] = i;
- Sbar_Changed ();
- }
- i = MSG_ReadByte ();
- if (cl.stats[STAT_AMMO] != i)
- {
- cl.stats[STAT_AMMO] = i;
- Sbar_Changed ();
- }
- for (i=0 ; i<4 ; i++)
- {
- j = MSG_ReadByte ();
- if (cl.stats[STAT_SHELLS+i] != j)
- {
- cl.stats[STAT_SHELLS+i] = j;
- Sbar_Changed ();
- }
- }
- i = MSG_ReadByte ();
- if (standard_quake)
- {
- if (cl.stats[STAT_ACTIVEWEAPON] != i)
- {
- cl.stats[STAT_ACTIVEWEAPON] = i;
- Sbar_Changed ();
- }
- }
- else
- {
- if (cl.stats[STAT_ACTIVEWEAPON] != (1<<i))
- {
- cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
- Sbar_Changed ();
- }
- }
- }
- /*
- =====================
- CL_NewTranslation
- =====================
- */
- void CL_NewTranslation (int slot)
- {
- int i, j;
- int top, bottom;
- byte *dest, *source;
-
- if (slot > cl.maxclients)
- Sys_Error ("CL_NewTranslation: slot > cl.maxclients");
- dest = cl.scores[slot].translations;
- source = vid.colormap;
- memcpy (dest, vid.colormap, sizeof(cl.scores[slot].translations));
- top = cl.scores[slot].colors & 0xf0;
- bottom = (cl.scores[slot].colors &15)<<4;
- #ifdef GLQUAKE
- R_TranslatePlayerSkin (slot);
- #endif
- for (i=0 ; i<VID_GRADES ; i++, dest += 256, source+=256)
- {
- if (top < 128) // the artists made some backwards ranges. sigh.
- memcpy (dest + TOP_RANGE, source + top, 16);
- else
- for (j=0 ; j<16 ; j++)
- dest[TOP_RANGE+j] = source[top+15-j];
-
- if (bottom < 128)
- memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
- else
- for (j=0 ; j<16 ; j++)
- dest[BOTTOM_RANGE+j] = source[bottom+15-j];
- }
- }
- /*
- =====================
- CL_ParseStatic
- =====================
- */
- void CL_ParseStatic (void)
- {
- entity_t *ent;
- int i;
-
- i = cl.num_statics;
- if (i >= MAX_STATIC_ENTITIES)
- Host_Error ("Too many static entities");
- ent = &cl_static_entities[i];
- cl.num_statics++;
- CL_ParseBaseline (ent);
- // copy it to the current state
- ent->model = cl.model_precache[ent->baseline.modelindex];
- ent->frame = ent->baseline.frame;
- ent->colormap = vid.colormap;
- ent->skinnum = ent->baseline.skin;
- ent->effects = ent->baseline.effects;
- VectorCopy (ent->baseline.origin, ent->origin);
- VectorCopy (ent->baseline.angles, ent->angles);
- R_AddEfrags (ent);
- }
- /*
- ===================
- CL_ParseStaticSound
- ===================
- */
- void CL_ParseStaticSound (void)
- {
- vec3_t org;
- int sound_num, vol, atten;
- int i;
-
- for (i=0 ; i<3 ; i++)
- org[i] = MSG_ReadCoord ();
- sound_num = MSG_ReadByte ();
- vol = MSG_ReadByte ();
- atten = MSG_ReadByte ();
-
- S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
- }
- #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
- /*
- =====================
- CL_ParseServerMessage
- =====================
- */
- void CL_ParseServerMessage (void)
- {
- int cmd;
- int i;
-
- //
- // 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");
-
- cl.onground = false; // unless the server says otherwise
- //
- // parse the message
- //
- MSG_BeginReading ();
-
- while (1)
- {
- if (msg_badread)
- Host_Error ("CL_ParseServerMessage: Bad server message");
- cmd = MSG_ReadByte ();
- if (cmd == -1)
- {
- SHOWNET("END OF MESSAGE");
- return; // end of message
- }
- // if the high bit of the command byte is set, it is a fast update
- if (cmd & 128)
- {
- SHOWNET("fast update");
- CL_ParseUpdate (cmd&127);
- continue;
- }
- SHOWNET(svc_strings[cmd]);
-
- // other commands
- switch (cmd)
- {
- default:
- Host_Error ("CL_ParseServerMessage: Illegible server message\n");
- break;
-
- case svc_nop:
- // Con_Printf ("svc_nop\n");
- break;
-
- case svc_time:
- cl.mtime[1] = cl.mtime[0];
- cl.mtime[0] = MSG_ReadFloat ();
- break;
-
- case svc_clientdata:
- i = MSG_ReadShort ();
- CL_ParseClientdata (i);
- break;
-
- case svc_version:
- i = MSG_ReadLong ();
- if (i != PROTOCOL_VERSION)
- Host_Error ("CL_ParseServerMessage: Server is protocol %i instead of %i\n", i, PROTOCOL_VERSION);
- break;
-
- case svc_disconnect:
- Host_EndGame ("Server disconnected\n");
- case svc_print:
- Con_Printf ("%s", MSG_ReadString ());
- break;
-
- case svc_centerprint:
- SCR_CenterPrint (MSG_ReadString ());
- break;
-
- case svc_stufftext:
- Cbuf_AddText (MSG_ReadString ());
- 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++)
- cl.viewangles[i] = MSG_ReadAngle ();
- break;
-
- case svc_setview:
- cl.viewentity = MSG_ReadShort ();
- break;
-
- case svc_lightstyle:
- i = MSG_ReadByte ();
- if (i >= MAX_LIGHTSTYLES)
- Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
- Q_strcpy (cl_lightstyle[i].map, MSG_ReadString());
- cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map);
- 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");
- strcpy (cl.scores[i].name, MSG_ReadString ());
- 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));
- break;
- case svc_spawnstatic:
- CL_ParseStatic ();
- break;
- case svc_temp_entity:
- CL_ParseTEnt ();
- break;
- case svc_setpause:
- {
- cl.paused = MSG_ReadByte ();
- if (cl.paused)
- {
- CDAudio_Pause ();
- #ifdef _WIN32
- VID_HandlePause (true);
- #endif
- }
- else
- {
- CDAudio_Resume ();
- #ifdef _WIN32
- VID_HandlePause (false);
- #endif
- }
- }
- 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;
- CL_SignonReply ();
- break;
- case svc_killedmonster:
- cl.stats[STAT_MONSTERS]++;
- break;
- case svc_foundsecret:
- cl.stats[STAT_SECRETS]++;
- break;
- case svc_updatestat:
- i = MSG_ReadByte ();
- if (i < 0 || i >= MAX_CL_STATS)
- Sys_Error ("svc_updatestat: %i is invalid", i);
- cl.stats[i] = MSG_ReadLong ();;
- break;
-
- case svc_spawnstaticsound:
- CL_ParseStaticSound ();
- break;
- case svc_cdtrack:
- cl.cdtrack = MSG_ReadByte ();
- cl.looptrack = MSG_ReadByte ();
- if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
- CDAudio_Play ((byte)cls.forcetrack, true);
- else
- CDAudio_Play ((byte)cl.cdtrack, true);
- 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
- SCR_CenterPrint (MSG_ReadString ());
- break;
- case svc_cutscene:
- cl.intermission = 3;
- cl.completed_time = cl.time;
- vid.recalc_refdef = true; // go to full screen
- SCR_CenterPrint (MSG_ReadString ());
- break;
- case svc_sellscreen:
- Cmd_ExecuteString ("help", src_command);
- break;
- }
- }
- }
|