2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // cl_parse.c -- parse a message received from the server
23 #include "cl_collision.h"
25 char *svc_strings[128] =
31 "svc_version", // [long] server version
32 "svc_setview", // [short] entity number
33 "svc_sound", // <see code>
34 "svc_time", // [float] server time
35 "svc_print", // [string] null terminated string
36 "svc_stufftext", // [string] stuffed into client's console buffer
37 // the string should be \n terminated
38 "svc_setangle", // [vec3] set the view angle to this absolute value
40 "svc_serverinfo", // [long] version
41 // [string] signon string
42 // [string]..[0]model cache [string]...[0]sounds cache
43 // [string]..[0]item cache
44 "svc_lightstyle", // [byte] [string]
45 "svc_updatename", // [byte] [string]
46 "svc_updatefrags", // [byte] [short]
47 "svc_clientdata", // <shortbits + data>
48 "svc_stopsound", // <see code>
49 "svc_updatecolors", // [byte] [byte]
50 "svc_particle", // [vec3] <variable>
51 "svc_damage", // [byte] impact [byte] blood [vec3] from
54 "OBSOLETE svc_spawnbinary",
57 "svc_temp_entity", // <variable>
63 "svc_spawnstaticsound",
65 "svc_finale", // [string] music [string] text
66 "svc_cdtrack", // [byte] track [byte] looptrack
69 "svc_showlmp", // [string] iconlabel [string] lmpfile [short] x [short] y
70 "svc_hidelmp", // [string] iconlabel
71 "svc_skybox", // [string] skyname
84 "svc_cgame", // 50 // [short] length [bytes] data
85 "svc_unusedlh1", // 51 // unused
86 "svc_effect", // 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
87 "svc_effect2", // 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
88 "svc_sound2", // 54 // short soundindex instead of byte
89 "svc_spawnbaseline2", // 55 // short modelindex instead of byte
90 "svc_spawnstatic2", // 56 // short modelindex instead of byte
91 "svc_entities", // 57 // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata
92 "svc_unusedlh3", // 58
93 "svc_spawnstaticsound2", // 59 // [coord3] [short] samp [byte] vol [byte] aten
96 //=============================================================================
98 cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
100 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
101 int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces
103 mempool_t *cl_scores_mempool;
107 CL_ParseStartSoundPacket
110 void CL_ParseStartSoundPacket(int largesoundindex)
120 field_mask = MSG_ReadByte();
122 if (field_mask & SND_VOLUME)
123 volume = MSG_ReadByte ();
125 volume = DEFAULT_SOUND_PACKET_VOLUME;
127 if (field_mask & SND_ATTENUATION)
128 attenuation = MSG_ReadByte () / 64.0;
130 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
132 if (field_mask & SND_LARGEENTITY)
134 ent = (unsigned short) MSG_ReadShort ();
135 channel = MSG_ReadByte ();
139 channel = (unsigned short) MSG_ReadShort ();
144 if (largesoundindex || field_mask & SND_LARGESOUND)
145 sound_num = (unsigned short) MSG_ReadShort ();
147 sound_num = MSG_ReadByte ();
149 if (sound_num >= MAX_SOUNDS)
150 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
153 if (ent >= MAX_EDICTS)
154 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
156 for (i = 0;i < 3;i++)
157 pos[i] = MSG_ReadCoord ();
159 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
166 When the client is taking a long time to load stuff, send keepalive messages
167 so the server doesn't disconnect.
171 static qbyte olddata[NET_MAXMESSAGE];
172 void CL_KeepaliveMessage (void)
175 static float lastmsg;
180 // no need if server is local and definitely not if this is a demo
181 if (sv.active || cls.demoplayback)
184 // read messages from server, should just be nops
185 oldreadcount = msg_readcount;
186 oldbadread = msg_badread;
188 memcpy(olddata, net_message.data, net_message.cursize);
190 NetConn_ClientFrame();
192 msg_readcount = oldreadcount;
193 msg_badread = oldbadread;
195 memcpy(net_message.data, olddata, net_message.cursize);
197 if (cls.netcon && NetConn_CanSendMessage(cls.netcon) && (time = Sys_DoubleTime()) - lastmsg >= 5)
203 // LordHavoc: must use unreliable because reliable could kill the sigon message!
204 Con_Printf("--> client to server keepalive\n");
206 msg.maxsize = sizeof(buf);
208 MSG_WriteChar(&msg, svc_nop);
209 NetConn_SendUnreliableMessage(cls.netcon, &msg);
210 // try not to utterly crush the computer with work, that's just rude
215 void CL_ParseEntityLump(char *entdata)
218 char key[128], value[4096];
219 FOG_clear(); // LordHavoc: no fog until set
220 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
224 if (!COM_ParseToken(&data, false))
226 if (com_token[0] != '{')
230 if (!COM_ParseToken(&data, false))
232 if (com_token[0] == '}')
233 break; // end of worldspawn
234 if (com_token[0] == '_')
235 strcpy(key, com_token + 1);
237 strcpy(key, com_token);
238 while (key[strlen(key)-1] == ' ') // remove trailing spaces
239 key[strlen(key)-1] = 0;
240 if (!COM_ParseToken(&data, false))
242 strcpy(value, com_token);
243 if (!strcmp("sky", key))
245 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
247 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
249 else if (!strcmp("fog", key))
250 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
251 else if (!strcmp("fog_density", key))
252 fog_density = atof(value);
253 else if (!strcmp("fog_red", key))
254 fog_red = atof(value);
255 else if (!strcmp("fog_green", key))
256 fog_green = atof(value);
257 else if (!strcmp("fog_blue", key))
258 fog_blue = atof(value);
263 =====================
266 An svc_signonnum has been received, perform a client side setup
267 =====================
269 static void CL_SignonReply (void)
273 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
278 MSG_WriteByte (&cls.message, clc_stringcmd);
279 MSG_WriteString (&cls.message, "prespawn");
283 MSG_WriteByte (&cls.message, clc_stringcmd);
284 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
286 MSG_WriteByte (&cls.message, clc_stringcmd);
287 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
289 if (cl_pmodel.integer)
291 MSG_WriteByte (&cls.message, clc_stringcmd);
292 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
295 MSG_WriteByte (&cls.message, clc_stringcmd);
296 MSG_WriteString (&cls.message, "spawn");
300 MSG_WriteByte (&cls.message, clc_stringcmd);
301 MSG_WriteString (&cls.message, "begin");
315 qbyte entlife[MAX_EDICTS];
316 // FIXME: this is a lot of memory to be keeping around, this needs to be dynamically allocated and freed
317 static char parse_model_precache[MAX_MODELS][MAX_QPATH];
318 static char parse_sound_precache[MAX_SOUNDS][MAX_QPATH];
319 void CL_ParseServerInfo (void)
323 int nummodels, numsounds;
326 Con_DPrintf ("Serverinfo packet received.\n");
328 // wipe the client_state_t struct
332 // parse protocol version number
334 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != DPPROTOCOL_VERSION4 && i != 250)
336 Host_Error ("Server is protocol %i, not %i, %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, DPPROTOCOL_VERSION4, PROTOCOL_VERSION);
339 Nehahrademcompatibility = false;
341 Nehahrademcompatibility = true;
342 if (cls.demoplayback && demo_nehahra.integer)
343 Nehahrademcompatibility = true;
345 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3 && dpprotocol != DPPROTOCOL_VERSION4)
349 cl.maxclients = MSG_ReadByte ();
350 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
352 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
355 Mem_EmptyPool(cl_scores_mempool);
356 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
359 cl.gametype = MSG_ReadByte ();
361 // parse signon message
362 str = MSG_ReadString ();
363 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
365 // seperate the printfs so the server message can have a color
366 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
368 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");
369 Con_Printf ("%c%s\n", 2, str);
372 // check memory integrity
373 Mem_CheckSentinelsGlobal();
375 // disable until we get textures for it
378 memset(cl.model_precache, 0, sizeof(cl.model_precache));
379 memset(cl.sound_precache, 0, sizeof(cl.sound_precache));
381 // parse model precache list
382 for (nummodels=1 ; ; nummodels++)
384 str = MSG_ReadString();
387 if (nummodels==MAX_MODELS)
388 Host_Error ("Server sent too many model precaches\n");
389 if (strlen(str) >= MAX_QPATH)
390 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
391 strcpy(parse_model_precache[nummodels], str);
393 // parse sound precache list
394 for (numsounds=1 ; ; numsounds++)
396 str = MSG_ReadString();
399 if (numsounds==MAX_SOUNDS)
400 Host_Error("Server sent too many sound precaches\n");
401 if (strlen(str) >= MAX_QPATH)
402 Host_Error("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
403 strcpy(parse_sound_precache[numsounds], str);
406 // touch all of the precached models that are still loaded so we can free
407 // anything that isn't needed
409 for (i = 1;i < nummodels;i++)
411 CL_KeepaliveMessage();
412 Mod_TouchModel(parse_model_precache[i]);
414 // do the same for sounds
415 for (i = 1;i < numsounds;i++)
417 CL_KeepaliveMessage();
418 S_TouchSound(parse_sound_precache[i]);
420 // purge anything that was not touched
423 // now we try to load everything that is new
426 CL_KeepaliveMessage ();
427 cl.model_precache[1] = Mod_ForName(parse_model_precache[1], false, false, true);
428 if (cl.model_precache[1] == NULL)
429 Con_Printf("Map %s not found\n", parse_model_precache[1]);
432 for (i=2 ; i<nummodels ; i++)
434 CL_KeepaliveMessage();
435 if ((cl.model_precache[i] = Mod_ForName(parse_model_precache[i], false, false, false)) == NULL)
436 Con_Printf("Model %s not found\n", parse_model_precache[i]);
440 S_BeginPrecaching ();
441 for (i=1 ; i<numsounds ; i++)
443 CL_KeepaliveMessage();
444 cl.sound_precache[i] = S_PrecacheSound(parse_sound_precache[i], true);
449 ent = &cl_entities[0];
450 // entire entity array was cleared, so just fill in a few fields
451 ent->state_current.active = true;
452 ent->render.model = cl.worldmodel = cl.model_precache[1];
453 //ent->render.scale = 1;
454 ent->render.alpha = 1;
455 ent->render.flags = RENDER_SHADOW;
456 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
457 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
458 CL_BoundingBoxForEntity(&ent->render);
459 // clear entlife array
460 memset(entlife, 0, MAX_EDICTS);
467 // noclip is turned off at start
468 noclip_anglehack = false;
470 // check memory integrity
471 Mem_CheckSentinelsGlobal();
474 void CL_ValidateState(entity_state_t *s)
481 if (s->modelindex >= MAX_MODELS)
482 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
484 // colormap is client index + 1
485 if (s->colormap > cl.maxclients)
486 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
488 model = cl.model_precache[s->modelindex];
489 Mod_CheckLoaded(model);
490 if (model && s->frame >= model->numframes)
492 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
495 if (model && s->skin > 0 && s->skin >= model->numskins)
497 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
502 void CL_MoveLerpEntityStates(entity_t *ent)
504 float odelta[3], adelta[3];
505 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
506 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
507 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
509 // we definitely shouldn't lerp
510 ent->persistent.lerpdeltatime = 0;
511 ent->persistent.lerpstarttime = cl.mtime[1];
512 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
513 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
514 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
515 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
517 else if (ent->state_current.flags & RENDER_STEP)
519 // monster interpolation
520 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
522 ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
523 ent->persistent.lerpstarttime = cl.mtime[1];
524 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
525 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
526 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
527 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
533 ent->persistent.lerpstarttime = cl.mtime[1];
534 // no lerp if it's singleplayer
536 ent->persistent.lerpdeltatime = 0;
538 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
539 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
540 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
541 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
542 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
550 Parse an entity update message from the server
551 If an entities model or origin changes from frame to frame, it must be
552 relinked. Other attributes can change without relinking.
555 void CL_ParseUpdate (int bits)
561 if (bits & U_MOREBITS)
562 bits |= (MSG_ReadByte()<<8);
563 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
565 bits |= MSG_ReadByte() << 16;
566 if (bits & U_EXTEND2)
567 bits |= MSG_ReadByte() << 24;
570 if (bits & U_LONGENTITY)
571 num = (unsigned) MSG_ReadShort ();
573 num = (unsigned) MSG_ReadByte ();
575 if (num >= MAX_EDICTS)
576 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
578 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
580 ent = cl_entities + num;
582 // note: this inherits the 'active' state of the baseline chosen
583 // (state_baseline is always active, state_current may not be active if
584 // the entity was missing in the last frame)
586 new = ent->state_current;
589 new = ent->state_baseline;
594 new.time = cl.mtime[0];
596 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
597 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
598 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
599 if (bits & U_SKIN) new.skin = MSG_ReadByte();
600 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
601 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
602 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
603 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
604 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
605 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
606 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
607 if (bits & U_STEP) new.flags |= RENDER_STEP;
608 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
609 if (bits & U_SCALE) new.scale = MSG_ReadByte();
610 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
611 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
612 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
613 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
614 if (bits & U_COLORMOD) MSG_ReadByte();
615 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
616 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
617 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
618 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
619 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
621 // LordHavoc: to allow playback of the Nehahra movie
622 if (Nehahrademcompatibility && (bits & U_EXTEND1))
624 // LordHavoc: evil format
625 int i = MSG_ReadFloat();
626 int j = MSG_ReadFloat() * 255.0f;
631 new.effects |= EF_FULLBRIGHT;
635 else if (j == 0 || j >= 255)
642 CL_ValidateState(&new);
644 ent->state_previous = ent->state_current;
645 ent->state_current = new;
646 if (ent->state_current.active)
648 CL_MoveLerpEntityStates(ent);
649 cl_entities_active[ent->state_current.number] = true;
650 // mark as visible (no kill this frame)
651 entlife[ent->state_current.number] = 2;
655 static entity_frame_t entityframe;
656 extern mempool_t *cl_entities_mempool;
657 void CL_ReadEntityFrame(void)
659 if (dpprotocol == DPPROTOCOL_VERSION1 || dpprotocol == DPPROTOCOL_VERSION2 || dpprotocol == DPPROTOCOL_VERSION3)
663 EntityFrame_Read(&cl.entitydatabase);
664 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
665 for (i = 0;i < entityframe.numentities;i++)
668 ent = &cl_entities[entityframe.entitydata[i].number];
669 ent->state_previous = ent->state_current;
670 ent->state_current = entityframe.entitydata[i];
671 CL_MoveLerpEntityStates(ent);
672 // the entity lives again...
673 entlife[ent->state_current.number] = 2;
674 cl_entities_active[ent->state_current.number] = true;
679 if (!cl.entitydatabase4)
680 cl.entitydatabase4 = EntityFrame4_AllocDatabase(cl_entities_mempool);
681 EntityFrame4_CL_ReadFrame(cl.entitydatabase4);
685 void CL_EntityUpdateSetup(void)
689 void CL_EntityUpdateEnd(void)
691 if (dpprotocol == PROTOCOL_VERSION || dpprotocol == DPPROTOCOL_VERSION1 || dpprotocol == DPPROTOCOL_VERSION2 || dpprotocol == DPPROTOCOL_VERSION3)
694 // disable entities that disappeared this frame
695 for (i = 1;i < MAX_EDICTS;i++)
697 // clear only the entities that were active last frame but not this
698 // frame, don't waste time clearing all entities (which would cause
704 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
715 void CL_ParseBaseline (entity_t *ent, int large)
719 ClearStateToDefault(&ent->state_baseline);
720 ent->state_baseline.active = true;
723 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
724 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
728 ent->state_baseline.modelindex = MSG_ReadByte ();
729 ent->state_baseline.frame = MSG_ReadByte ();
731 ent->state_baseline.colormap = MSG_ReadByte();
732 ent->state_baseline.skin = MSG_ReadByte();
733 for (i = 0;i < 3;i++)
735 ent->state_baseline.origin[i] = MSG_ReadCoord ();
736 ent->state_baseline.angles[i] = MSG_ReadAngle ();
738 CL_ValidateState(&ent->state_baseline);
739 ent->state_previous = ent->state_current = ent->state_baseline;
747 Server information pertaining to this client only
750 void CL_ParseClientdata (int bits)
755 if (bits & SU_EXTEND1)
756 bits |= (MSG_ReadByte() << 16);
757 if (bits & SU_EXTEND2)
758 bits |= (MSG_ReadByte() << 24);
760 if (bits & SU_VIEWHEIGHT)
761 cl.viewheight = MSG_ReadChar ();
763 cl.viewheight = DEFAULT_VIEWHEIGHT;
765 if (bits & SU_IDEALPITCH)
766 cl.idealpitch = MSG_ReadChar ();
770 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
771 for (i=0 ; i<3 ; i++)
773 if (bits & (SU_PUNCH1<<i) )
776 cl.punchangle[i] = MSG_ReadPreciseAngle();
778 cl.punchangle[i] = MSG_ReadChar();
781 cl.punchangle[i] = 0;
782 if (bits & (SU_PUNCHVEC1<<i))
783 cl.punchvector[i] = MSG_ReadCoord();
785 cl.punchvector[i] = 0;
786 if (bits & (SU_VELOCITY1<<i) )
787 cl.mvelocity[0][i] = MSG_ReadChar()*16;
789 cl.mvelocity[0][i] = 0;
795 for (j=0 ; j<32 ; j++)
796 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
797 cl.item_gettime[j] = cl.time;
801 cl.onground = (bits & SU_ONGROUND) != 0;
802 cl.inwater = (bits & SU_INWATER) != 0;
804 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
805 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
806 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
807 cl.stats[STAT_HEALTH] = MSG_ReadShort();
808 cl.stats[STAT_AMMO] = MSG_ReadByte();
810 cl.stats[STAT_SHELLS] = MSG_ReadByte();
811 cl.stats[STAT_NAILS] = MSG_ReadByte();
812 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
813 cl.stats[STAT_CELLS] = MSG_ReadByte();
817 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
818 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
820 cl.stats[STAT_ACTIVEWEAPON] = i;
822 cl.viewzoomold = cl.viewzoomnew; // for interpolation
823 if (bits & SU_VIEWZOOM)
828 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
836 =====================
838 =====================
840 void CL_ParseStatic (int large)
844 if (cl_num_static_entities >= cl_max_static_entities)
845 Host_Error ("Too many static entities");
846 ent = &cl_static_entities[cl_num_static_entities++];
847 CL_ParseBaseline (ent, large);
849 // copy it to the current state
850 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
851 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
852 ent->render.framelerp = 0;
853 // make torchs play out of sync
854 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
855 ent->render.colormap = -1; // no special coloring
856 ent->render.skinnum = ent->state_baseline.skin;
857 ent->render.effects = ent->state_baseline.effects;
858 ent->render.alpha = 1;
859 //ent->render.scale = 1;
861 //VectorCopy (ent->state_baseline.origin, ent->render.origin);
862 //VectorCopy (ent->state_baseline.angles, ent->render.angles);
864 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, ent->state_baseline.origin[0], ent->state_baseline.origin[1], ent->state_baseline.origin[2], ent->state_baseline.angles[0], ent->state_baseline.angles[1], ent->state_baseline.angles[2], 1);
865 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
866 CL_BoundingBoxForEntity(&ent->render);
868 // This is definitely cheating...
869 if (ent->render.model == NULL)
870 cl_num_static_entities--;
878 void CL_ParseStaticSound (int large)
881 int sound_num, vol, atten;
885 sound_num = (unsigned short) MSG_ReadShort ();
887 sound_num = MSG_ReadByte ();
888 vol = MSG_ReadByte ();
889 atten = MSG_ReadByte ();
891 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
894 void CL_ParseEffect (void)
897 int modelindex, startframe, framecount, framerate;
900 modelindex = MSG_ReadByte ();
901 startframe = MSG_ReadByte ();
902 framecount = MSG_ReadByte ();
903 framerate = MSG_ReadByte ();
905 CL_Effect(org, modelindex, startframe, framecount, framerate);
908 void CL_ParseEffect2 (void)
911 int modelindex, startframe, framecount, framerate;
914 modelindex = MSG_ReadShort ();
915 startframe = MSG_ReadShort ();
916 framecount = MSG_ReadByte ();
917 framerate = MSG_ReadByte ();
919 CL_Effect(org, modelindex, startframe, framecount, framerate);
922 model_t *cl_model_bolt = NULL;
923 model_t *cl_model_bolt2 = NULL;
924 model_t *cl_model_bolt3 = NULL;
925 model_t *cl_model_beam = NULL;
927 sfx_t *cl_sfx_wizhit;
928 sfx_t *cl_sfx_knighthit;
933 sfx_t *cl_sfx_r_exp3;
940 void CL_InitTEnts (void)
942 cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
943 cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
944 cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
945 cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
946 cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
947 cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
948 cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
951 void CL_ParseBeam (model_t *m, int lightning)
957 ent = MSG_ReadShort ();
958 MSG_ReadVector(start);
961 if (ent >= MAX_EDICTS)
963 Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
967 // override any beam with the same entity
968 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
970 if (b->entity == ent)
973 b->lightning = lightning;
974 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
976 b->endtime = cl.time + 0.2;
977 VectorCopy (start, b->start);
978 VectorCopy (end, b->end);
984 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
986 if (!b->model || b->endtime < cl.time)
989 b->lightning = lightning;
990 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
992 b->endtime = cl.time + 0.2;
993 VectorCopy (start, b->start);
994 VectorCopy (end, b->end);
998 Con_Printf ("beam list overflow!\n");
1001 void CL_ParseTempEntity(void)
1009 int colorStart, colorLength, count;
1010 float velspeed, radius;
1013 type = MSG_ReadByte();
1017 // spike hitting wall
1018 MSG_ReadVector(pos);
1019 CL_FindNonSolidLocation(pos, pos, 4);
1020 CL_AllocDlight(NULL, pos, 50, 0.25f, 1.00f, 0.25f, 250, 0.2);
1021 CL_RunParticleEffect(pos, vec3_origin, 20, 30);
1022 S_StartSound(-1, 0, cl_sfx_wizhit, pos, 1, 1);
1025 case TE_KNIGHTSPIKE:
1026 // spike hitting wall
1027 MSG_ReadVector(pos);
1028 CL_FindNonSolidLocation(pos, pos, 4);
1029 CL_AllocDlight(NULL, pos, 50, 1.0f, 0.60f, 0.20f, 250, 0.2);
1030 CL_RunParticleEffect(pos, vec3_origin, 226, 20);
1031 S_StartSound(-1, 0, cl_sfx_knighthit, pos, 1, 1);
1035 // spike hitting wall
1036 MSG_ReadVector(pos);
1037 CL_FindNonSolidLocation(pos, pos, 4);
1038 // LordHavoc: changed to spark shower
1039 CL_SparkShower(pos, vec3_origin, 15);
1041 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1046 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1048 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1050 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1054 // quad spike hitting wall
1055 MSG_ReadVector(pos);
1056 CL_FindNonSolidLocation(pos, pos, 4);
1057 // LordHavoc: changed to spark shower
1058 CL_SparkShower(pos, vec3_origin, 15);
1059 CL_AllocDlight(NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1060 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1062 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1067 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1069 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1071 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1075 // super spike hitting wall
1076 MSG_ReadVector(pos);
1077 CL_FindNonSolidLocation(pos, pos, 4);
1078 // LordHavoc: changed to dust shower
1079 CL_SparkShower(pos, vec3_origin, 30);
1081 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1086 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1088 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1090 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1093 case TE_SUPERSPIKEQUAD:
1094 // quad super spike hitting wall
1095 MSG_ReadVector(pos);
1096 CL_FindNonSolidLocation(pos, pos, 4);
1097 // LordHavoc: changed to dust shower
1098 CL_SparkShower(pos, vec3_origin, 30);
1099 CL_AllocDlight(NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1101 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1106 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1108 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1110 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1113 // LordHavoc: added for improved blood splatters
1116 MSG_ReadVector(pos);
1117 CL_FindNonSolidLocation(pos, pos, 4);
1118 dir[0] = MSG_ReadChar();
1119 dir[1] = MSG_ReadChar();
1120 dir[2] = MSG_ReadChar();
1121 count = MSG_ReadByte();
1122 CL_BloodPuff(pos, dir, count);
1126 MSG_ReadVector(pos);
1127 CL_FindNonSolidLocation(pos, pos, 4);
1128 dir[0] = MSG_ReadChar();
1129 dir[1] = MSG_ReadChar();
1130 dir[2] = MSG_ReadChar();
1131 count = MSG_ReadByte();
1132 CL_SparkShower(pos, dir, count);
1135 MSG_ReadVector(pos);
1136 CL_FindNonSolidLocation(pos, pos, 4);
1137 CL_AllocDlight(NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1140 // LordHavoc: added for improved gore
1141 case TE_BLOODSHOWER:
1143 MSG_ReadVector(pos); // mins
1144 MSG_ReadVector(pos2); // maxs
1145 velspeed = MSG_ReadCoord(); // speed
1146 count = MSG_ReadShort(); // number of particles
1147 CL_BloodShower(pos, pos2, velspeed, count);
1149 case TE_PARTICLECUBE:
1150 // general purpose particle effect
1151 MSG_ReadVector(pos); // mins
1152 MSG_ReadVector(pos2); // maxs
1153 MSG_ReadVector(dir); // dir
1154 count = MSG_ReadShort(); // number of particles
1155 colorStart = MSG_ReadByte(); // color
1156 colorLength = MSG_ReadByte(); // gravity (1 or 0)
1157 velspeed = MSG_ReadCoord(); // randomvel
1158 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1161 case TE_PARTICLERAIN:
1162 // general purpose particle effect
1163 MSG_ReadVector(pos); // mins
1164 MSG_ReadVector(pos2); // maxs
1165 MSG_ReadVector(dir); // dir
1166 count = MSG_ReadShort(); // number of particles
1167 colorStart = MSG_ReadByte(); // color
1168 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1171 case TE_PARTICLESNOW:
1172 // general purpose particle effect
1173 MSG_ReadVector(pos); // mins
1174 MSG_ReadVector(pos2); // maxs
1175 MSG_ReadVector(dir); // dir
1176 count = MSG_ReadShort(); // number of particles
1177 colorStart = MSG_ReadByte(); // color
1178 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1182 // bullet hitting wall
1183 MSG_ReadVector(pos);
1184 CL_FindNonSolidLocation(pos, pos, 4);
1185 // LordHavoc: changed to dust shower
1186 CL_SparkShower(pos, vec3_origin, 15);
1189 case TE_GUNSHOTQUAD:
1190 // quad bullet hitting wall
1191 MSG_ReadVector(pos);
1192 CL_FindNonSolidLocation(pos, pos, 4);
1193 CL_SparkShower(pos, vec3_origin, 15);
1194 CL_AllocDlight(NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1199 MSG_ReadVector(pos);
1200 CL_FindNonSolidLocation(pos, pos, 10);
1201 CL_ParticleExplosion(pos);
1202 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1203 CL_AllocDlight(NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
1204 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1207 case TE_EXPLOSIONQUAD:
1208 // quad rocket explosion
1209 MSG_ReadVector(pos);
1210 CL_FindNonSolidLocation(pos, pos, 10);
1211 CL_ParticleExplosion(pos);
1212 CL_AllocDlight(NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
1213 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1217 // Nehahra movie colored lighting explosion
1218 MSG_ReadVector(pos);
1219 CL_FindNonSolidLocation(pos, pos, 10);
1220 CL_ParticleExplosion(pos);
1221 CL_AllocDlight(NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
1222 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1225 case TE_EXPLOSIONRGB:
1226 // colored lighting explosion
1227 MSG_ReadVector(pos);
1228 CL_FindNonSolidLocation(pos, pos, 10);
1229 CL_ParticleExplosion(pos);
1230 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1231 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1232 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1233 CL_AllocDlight(NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
1234 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1237 case TE_TAREXPLOSION:
1238 // tarbaby explosion
1239 MSG_ReadVector(pos);
1240 CL_FindNonSolidLocation(pos, pos, 10);
1241 CL_BlobExplosion(pos);
1243 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1244 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1245 CL_AllocDlight(NULL, pos, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5);
1249 MSG_ReadVector(pos);
1250 CL_FindNonSolidLocation(pos, pos, 10);
1251 CL_AllocDlight(NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1254 case TE_CUSTOMFLASH:
1255 MSG_ReadVector(pos);
1256 CL_FindNonSolidLocation(pos, pos, 4);
1257 radius = MSG_ReadByte() * 8;
1258 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1259 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1260 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1261 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1262 CL_AllocDlight(NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
1266 MSG_ReadVector(pos);
1267 MSG_ReadVector(dir);
1268 count = MSG_ReadByte();
1269 CL_Flames(pos, dir, count);
1275 cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1276 CL_ParseBeam(cl_model_bolt, true);
1281 if (!cl_model_bolt2)
1282 cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1283 CL_ParseBeam(cl_model_bolt2, true);
1288 if (!cl_model_bolt3)
1289 cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1290 CL_ParseBeam(cl_model_bolt3, false);
1295 // grappling hook beam
1297 cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1298 CL_ParseBeam(cl_model_beam, false);
1302 // LordHavoc: for compatibility with the Nehahra movie...
1303 case TE_LIGHTNING4NEH:
1304 CL_ParseBeam(Mod_ForName(MSG_ReadString(), true, false, false), false);
1308 pos[0] = MSG_ReadCoord();
1309 pos[1] = MSG_ReadCoord();
1310 pos[2] = MSG_ReadCoord();
1315 pos[0] = MSG_ReadCoord();
1316 pos[1] = MSG_ReadCoord();
1317 pos[2] = MSG_ReadCoord();
1318 CL_AllocDlight(NULL, pos, 500, 1.0f, 1.0f, 1.0f, 1500, 99.0f);
1319 // CL_TeleportSplash(pos);
1323 // color mapped explosion
1324 MSG_ReadVector(pos);
1325 CL_FindNonSolidLocation(pos, pos, 10);
1326 colorStart = MSG_ReadByte();
1327 colorLength = MSG_ReadByte();
1328 CL_ParticleExplosion2(pos, colorStart, colorLength);
1329 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1330 CL_AllocDlight(NULL, pos, 350, tempcolor[0] * (1.0f / 255.0f), tempcolor[1] * (1.0f / 255.0f), tempcolor[2] * (1.0f / 255.0f), 700, 0.5);
1331 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1335 MSG_ReadVector(pos);
1336 MSG_ReadVector(pos2);
1337 MSG_ReadVector(dir);
1338 CL_BeamParticle(pos, pos2, 12, 1, 0.3, 0.1, 1, 1);
1339 CL_BeamParticle(pos, pos2, 5, 1, 0.9, 0.3, 1, 1);
1343 MSG_ReadVector(pos);
1344 MSG_ReadVector(dir);
1345 count = MSG_ReadByte();
1346 CL_FindNonSolidLocation(pos, pos, 4);
1347 CL_Tei_Smoke(pos, dir, count);
1350 case TE_TEI_BIGEXPLOSION:
1351 MSG_ReadVector(pos);
1352 CL_FindNonSolidLocation(pos, pos, 10);
1353 CL_ParticleExplosion(pos);
1354 CL_AllocDlight(NULL, pos, 500, 1.25f, 1.0f, 0.5f, 500, 9999);
1355 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1358 case TE_TEI_PLASMAHIT:
1359 MSG_ReadVector(pos);
1360 MSG_ReadVector(dir);
1361 count = MSG_ReadByte();
1362 CL_FindNonSolidLocation(pos, pos, 5);
1363 CL_Tei_PlasmaHit(pos, dir, count);
1364 CL_AllocDlight(NULL, pos, 500, 0.3, 0.6, 1.0f, 2000, 9999);
1368 Host_Error("CL_ParseTempEntity: bad type %d (hex %02X)", type, type);
1372 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1374 static qbyte cgamenetbuffer[65536];
1377 =====================
1378 CL_ParseServerMessage
1379 =====================
1381 int parsingerror = false;
1382 void CL_ParseServerMessage(void)
1385 int i, entitiesupdated;
1387 char *cmdlogname[32], *temp;
1388 int cmdindex, cmdcount = 0;
1390 if (cls.demorecording)
1391 CL_WriteDemoMessage ();
1393 cl.last_received_message = realtime;
1396 // if recording demos, copy the message out
1398 if (cl_shownet.integer == 1)
1399 Con_Printf ("%f %i\n", realtime, net_message.cursize);
1400 else if (cl_shownet.integer == 2)
1401 Con_Printf ("------------------\n");
1403 cl.onground = false; // unless the server says otherwise
1405 // parse the message
1407 //MSG_BeginReading ();
1409 entitiesupdated = false;
1411 parsingerror = true;
1416 Host_Error ("CL_ParseServerMessage: Bad server message");
1418 cmd = MSG_ReadByte ();
1422 SHOWNET("END OF MESSAGE");
1423 break; // end of message
1426 cmdindex = cmdcount & 31;
1428 cmdlog[cmdindex] = cmd;
1430 // if the high bit of the command byte is set, it is a fast update
1433 // LordHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer)
1435 cmdlogname[cmdindex] = temp;
1436 SHOWNET("fast update");
1437 if (cls.signon == SIGNONS - 1)
1439 // first update is the final signon stage
1440 cls.signon = SIGNONS;
1443 CL_ParseUpdate (cmd&127);
1447 SHOWNET(svc_strings[cmd]);
1448 cmdlogname[cmdindex] = svc_strings[cmd];
1449 if (!cmdlogname[cmdindex])
1451 // LordHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer)
1453 cmdlogname[cmdindex] = temp;
1461 char description[32*64], temp[64];
1463 strcpy(description, "packet dump: ");
1467 count = cmdcount - i;
1471 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1472 strcat(description, temp);
1477 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1478 Con_Printf("%s", description);
1479 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1484 if (cls.signon < SIGNONS)
1485 Con_Printf("<-- server to client keepalive\n");
1489 if (!entitiesupdated)
1491 // this is a new frame, we'll be seeing entities,
1492 // so prepare for entity updates
1493 CL_EntityUpdateSetup();
1494 entitiesupdated = true;
1496 cl.mtime[1] = cl.mtime[0];
1497 cl.mtime[0] = MSG_ReadFloat ();
1500 case svc_clientdata:
1501 i = MSG_ReadShort ();
1502 CL_ParseClientdata (i);
1506 i = MSG_ReadLong ();
1507 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != DPPROTOCOL_VERSION4 && i != 250)
1508 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, DPPROTOCOL_VERSION4, PROTOCOL_VERSION);
1509 Nehahrademcompatibility = false;
1511 Nehahrademcompatibility = true;
1512 if (cls.demoplayback && demo_nehahra.integer)
1513 Nehahrademcompatibility = true;
1515 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3 && dpprotocol != DPPROTOCOL_VERSION4)
1519 case svc_disconnect:
1520 Host_EndGame ("Server disconnected\n");
1523 Con_Printf ("%s", MSG_ReadString ());
1526 case svc_centerprint:
1527 SCR_CenterPrint (MSG_ReadString ());
1531 Cbuf_AddText (MSG_ReadString ());
1538 case svc_serverinfo:
1539 CL_ParseServerInfo ();
1543 for (i=0 ; i<3 ; i++)
1544 cl.viewangles[i] = MSG_ReadAngle ();
1548 cl.viewentity = (unsigned short)MSG_ReadShort ();
1549 if (cl.viewentity >= MAX_EDICTS)
1550 Host_Error("svc_setview >= MAX_EDICTS\n");
1551 // LordHavoc: assume first setview recieved is the real player entity
1552 if (!cl.playerentity)
1553 cl.playerentity = cl.viewentity;
1556 case svc_lightstyle:
1557 i = MSG_ReadByte ();
1558 if (i >= MAX_LIGHTSTYLES)
1559 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1560 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1561 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1562 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1566 CL_ParseStartSoundPacket(false);
1570 CL_ParseStartSoundPacket(true);
1574 i = MSG_ReadShort();
1575 S_StopSound(i>>3, i&7);
1578 case svc_updatename:
1579 i = MSG_ReadByte ();
1580 if (i >= cl.maxclients)
1581 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1582 strcpy (cl.scores[i].name, MSG_ReadString ());
1585 case svc_updatefrags:
1586 i = MSG_ReadByte ();
1587 if (i >= cl.maxclients)
1588 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1589 cl.scores[i].frags = MSG_ReadShort ();
1592 case svc_updatecolors:
1593 i = MSG_ReadByte ();
1594 if (i >= cl.maxclients)
1595 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1596 cl.scores[i].colors = MSG_ReadByte ();
1600 CL_ParseParticleEffect ();
1611 case svc_spawnbaseline:
1612 i = MSG_ReadShort ();
1613 if (i < 0 || i >= MAX_EDICTS)
1614 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1615 CL_ParseBaseline (cl_entities + i, false);
1617 case svc_spawnbaseline2:
1618 i = MSG_ReadShort ();
1619 if (i < 0 || i >= MAX_EDICTS)
1620 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1621 CL_ParseBaseline (cl_entities + i, true);
1623 case svc_spawnstatic:
1624 CL_ParseStatic (false);
1626 case svc_spawnstatic2:
1627 CL_ParseStatic (true);
1629 case svc_temp_entity:
1630 CL_ParseTempEntity ();
1634 cl.paused = MSG_ReadByte ();
1642 i = MSG_ReadByte ();
1643 if (i <= cls.signon)
1644 Host_Error ("Received signon %i when at %i", i, cls.signon);
1649 case svc_killedmonster:
1650 cl.stats[STAT_MONSTERS]++;
1653 case svc_foundsecret:
1654 cl.stats[STAT_SECRETS]++;
1657 case svc_updatestat:
1658 i = MSG_ReadByte ();
1659 if (i < 0 || i >= MAX_CL_STATS)
1660 Host_Error ("svc_updatestat: %i is invalid", i);
1661 cl.stats[i] = MSG_ReadLong ();
1664 case svc_spawnstaticsound:
1665 CL_ParseStaticSound (false);
1668 case svc_spawnstaticsound2:
1669 CL_ParseStaticSound (true);
1673 cl.cdtrack = MSG_ReadByte ();
1674 cl.looptrack = MSG_ReadByte ();
1675 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1676 CDAudio_Play ((qbyte)cls.forcetrack, true);
1678 CDAudio_Play ((qbyte)cl.cdtrack, true);
1681 case svc_intermission:
1682 cl.intermission = 1;
1683 cl.completed_time = cl.time;
1687 cl.intermission = 2;
1688 cl.completed_time = cl.time;
1689 SCR_CenterPrint (MSG_ReadString ());
1693 cl.intermission = 3;
1694 cl.completed_time = cl.time;
1695 SCR_CenterPrint (MSG_ReadString ());
1698 case svc_sellscreen:
1699 Cmd_ExecuteString ("help", src_command);
1702 SHOWLMP_decodehide();
1705 SHOWLMP_decodeshow();
1708 R_SetSkyBox(MSG_ReadString());
1713 length = (int) ((unsigned short) MSG_ReadShort());
1714 for (i = 0;i < length;i++)
1715 cgamenetbuffer[i] = MSG_ReadByte();
1717 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1721 if (cls.signon == SIGNONS - 1)
1723 // first update is the final signon stage
1724 cls.signon = SIGNONS;
1727 CL_ReadEntityFrame();
1732 if (entitiesupdated)
1733 CL_EntityUpdateEnd();
1735 parsingerror = false;
1738 void CL_Parse_DumpPacket(void)
1742 Con_Printf("Packet dump:\n");
1743 SZ_HexDumpToConsole(&net_message);
1744 parsingerror = false;
1747 void CL_Parse_Init(void)
1749 // LordHavoc: added demo_nehahra cvar
1750 cl_scores_mempool = Mem_AllocPool("client player info");
1751 Cvar_RegisterVariable (&demo_nehahra);
1752 if (gamemode == GAME_NEHAHRA)
1753 Cvar_SetValue("demo_nehahra", 1);