blob: 6a2856709e4a5be71e686320f96f8cff2c0a773b [file] [log] [blame]
Franklin Wei5d05b9d2018-02-11 15:34:30 -05001/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20// cl_parse.c -- parse a message received from the server
21
22#include "quakedef.h"
23
24char *svc_strings[] =
25{
26 "svc_bad",
27 "svc_nop",
28 "svc_disconnect",
29 "svc_updatestat",
30 "svc_version", // [long] server version
31 "svc_setview", // [short] entity number
32 "svc_sound", // <see code>
33 "svc_time", // [float] server time
34 "svc_print", // [string] null terminated string
35 "svc_stufftext", // [string] stuffed into client's console buffer
36 // the string should be \n terminated
37 "svc_setangle", // [vec3] set the view angle to this absolute value
38
39 "svc_serverinfo", // [long] version
40 // [string] signon string
41 // [string]..[0]model cache [string]...[0]sounds cache
42 // [string]..[0]item cache
43 "svc_lightstyle", // [byte] [string]
44 "svc_updatename", // [byte] [string]
45 "svc_updatefrags", // [byte] [short]
46 "svc_clientdata", // <shortbits + data>
47 "svc_stopsound", // <see code>
48 "svc_updatecolors", // [byte] [byte]
49 "svc_particle", // [vec3] <variable>
50 "svc_damage", // [byte] impact [byte] blood [vec3] from
51
52 "svc_spawnstatic",
53 "OBSOLETE svc_spawnbinary",
54 "svc_spawnbaseline",
55
56 "svc_temp_entity", // <variable>
57 "svc_setpause",
58 "svc_signonnum",
59 "svc_centerprint",
60 "svc_killedmonster",
61 "svc_foundsecret",
62 "svc_spawnstaticsound",
63 "svc_intermission",
64 "svc_finale", // [string] music [string] text
65 "svc_cdtrack", // [byte] track [byte] looptrack
66 "svc_sellscreen",
67 "svc_cutscene"
68};
69
70//=============================================================================
71
72/*
73===============
74CL_EntityNum
75
76This error checks and tracks the total number of entities
77===============
78*/
79entity_t *CL_EntityNum (int num)
80{
81 if (num >= cl.num_entities)
82 {
83 if (num >= MAX_EDICTS)
84 Host_Error ("CL_EntityNum: %i is an invalid number",num);
85 while (cl.num_entities<=num)
86 {
87 cl_entities[cl.num_entities].colormap = vid.colormap;
88 cl.num_entities++;
89 }
90 }
91
92 return &cl_entities[num];
93}
94
95
96/*
97==================
98CL_ParseStartSoundPacket
99==================
100*/
101void CL_ParseStartSoundPacket(void)
102{
103 vec3_t pos;
104 int channel, ent;
105 int sound_num;
106 int volume;
107 int field_mask;
108 float attenuation;
109 int i;
110
111 field_mask = MSG_ReadByte();
112
113 if (field_mask & SND_VOLUME)
114 volume = MSG_ReadByte ();
115 else
116 volume = DEFAULT_SOUND_PACKET_VOLUME;
117
118 if (field_mask & SND_ATTENUATION)
119 attenuation = MSG_ReadByte () / 64.0;
120 else
121 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
122
123 channel = MSG_ReadShort ();
124 sound_num = MSG_ReadByte ();
125
126 ent = channel >> 3;
127 channel &= 7;
128
129 if (ent > MAX_EDICTS)
130 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
131
132 for (i=0 ; i<3 ; i++)
133 pos[i] = MSG_ReadCoord ();
134
135 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
136}
137
138/*
139==================
140CL_KeepaliveMessage
141
142When the client is taking a long time to load stuff, send keepalive messages
143so the server doesn't disconnect.
144==================
145*/
146void CL_KeepaliveMessage (void)
147{
148 float time;
149 static float lastmsg;
150 int ret;
151 sizebuf_t old;
152 byte olddata[8192];
153
154 if (sv.active)
155 return; // no need if server is local
156 if (cls.demoplayback)
157 return;
158
159// read messages from server, should just be nops
160 old = net_message;
161 memcpy (olddata, net_message.data, net_message.cursize);
162
163 do
164 {
165 ret = CL_GetMessage ();
166 switch (ret)
167 {
168 default:
169 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
170 case 0:
171 break; // nothing waiting
172 case 1:
173 Host_Error ("CL_KeepaliveMessage: received a message");
174 break;
175 case 2:
176 if (MSG_ReadByte() != svc_nop)
177 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
178 break;
179 }
180 } while (ret);
181
182 net_message = old;
183 memcpy (net_message.data, olddata, net_message.cursize);
184
185// check time
186 time = Sys_FloatTime ();
187 if (time - lastmsg < 5)
188 return;
189 lastmsg = time;
190
191// write out a nop
192 Con_Printf ("--> client to server keepalive\n");
193
194 MSG_WriteByte (&cls.message, clc_nop);
195 NET_SendMessage (cls.netcon, &cls.message);
196 SZ_Clear (&cls.message);
197}
198
199/*
200==================
201CL_ParseServerInfo
202==================
203*/
204void CL_ParseServerInfo (void)
205{
206 char *str;
207 int i;
208 int nummodels, numsounds;
209 char model_precache[MAX_MODELS][MAX_QPATH];
210 char sound_precache[MAX_SOUNDS][MAX_QPATH];
211
212 Con_DPrintf ("Serverinfo packet received.\n");
213//
214// wipe the client_state_t struct
215//
216 CL_ClearState ();
217
218// parse protocol version number
219 i = MSG_ReadLong ();
220 if (i != PROTOCOL_VERSION)
221 {
222 Con_Printf ("Server returned version %i, not %i", i, PROTOCOL_VERSION);
223 return;
224 }
225
226// parse maxclients
227 cl.maxclients = MSG_ReadByte ();
228 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
229 {
230 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
231 return;
232 }
233 cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
234
235// parse gametype
236 cl.gametype = MSG_ReadByte ();
237
238// parse signon message
239 str = MSG_ReadString ();
240 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
241
242// seperate the printfs so the server message can have a color
243 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");
244 Con_Printf ("%c%s\n", 2, str);
245
246//
247// first we go through and touch all of the precache data that still
248// happens to be in the cache, so precaching something else doesn't
249// needlessly purge it
250//
251
252// precache models
253 memset (cl.model_precache, 0, sizeof(cl.model_precache));
254 for (nummodels=1 ; ; nummodels++)
255 {
256 str = MSG_ReadString ();
257 if (!str[0])
258 break;
259 if (nummodels==MAX_MODELS)
260 {
261 Con_Printf ("Server sent too many model precaches\n");
262 return;
263 }
264 strcpy (model_precache[nummodels], str);
265 Mod_TouchModel (str);
266 }
267
268// precache sounds
269 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
270 for (numsounds=1 ; ; numsounds++)
271 {
272 str = MSG_ReadString ();
273 if (!str[0])
274 break;
275 if (numsounds==MAX_SOUNDS)
276 {
277 Con_Printf ("Server sent too many sound precaches\n");
278 return;
279 }
280 strcpy (sound_precache[numsounds], str);
281 S_TouchSound (str);
282 }
283
284//
285// now we try to load everything else until a cache allocation fails
286//
287
288 for (i=1 ; i<nummodels ; i++)
289 {
290 cl.model_precache[i] = Mod_ForName (model_precache[i], false);
291 if (cl.model_precache[i] == NULL)
292 {
293 Con_Printf("Model %s not found\n", model_precache[i]);
294 return;
295 }
296 CL_KeepaliveMessage ();
297 }
298
299 S_BeginPrecaching ();
300 for (i=1 ; i<numsounds ; i++)
301 {
302 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
303 CL_KeepaliveMessage ();
304 }
305 S_EndPrecaching ();
306
307
308// local state
309 cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
310
311 R_NewMap ();
312
313 Hunk_Check (); // make sure nothing is hurt
314
315 noclip_anglehack = false; // noclip is turned off at start
316}
317
318
319/*
320==================
321CL_ParseUpdate
322
323Parse an entity update message from the server
324If an entities model or origin changes from frame to frame, it must be
325relinked. Other attributes can change without relinking.
326==================
327*/
328int bitcounts[16];
329
330void CL_ParseUpdate (int bits)
331{
332 int i;
333 model_t *model;
334 int modnum;
335 qboolean forcelink;
336 entity_t *ent;
337 int num;
338 int skin;
339
340 if (cls.signon == SIGNONS - 1)
341 { // first update is the final signon stage
342 cls.signon = SIGNONS;
343 CL_SignonReply ();
344 }
345
346 if (bits & U_MOREBITS)
347 {
348 i = MSG_ReadByte ();
349 bits |= (i<<8);
350 }
351
352 if (bits & U_LONGENTITY)
353 num = MSG_ReadShort ();
354 else
355 num = MSG_ReadByte ();
356
357 ent = CL_EntityNum (num);
358
359for (i=0 ; i<16 ; i++)
360if (bits&(1<<i))
361 bitcounts[i]++;
362
363 if (ent->msgtime != cl.mtime[1])
364 forcelink = true; // no previous frame to lerp from
365 else
366 forcelink = false;
367
368 ent->msgtime = cl.mtime[0];
369
370 if (bits & U_MODEL)
371 {
372 modnum = MSG_ReadByte ();
373 if (modnum >= MAX_MODELS)
374 Host_Error ("CL_ParseModel: bad modnum");
375 }
376 else
377 modnum = ent->baseline.modelindex;
378
379 model = cl.model_precache[modnum];
380 if (model != ent->model)
381 {
382 ent->model = model;
383 // automatic animation (torches, etc) can be either all together
384 // or randomized
385 if (model)
386 {
387 if (model->synctype == ST_RAND)
388 ent->syncbase = (float)(rand()&0x7fff) / 0x7fff;
389 else
390 ent->syncbase = 0.0;
391 }
392 else
393 forcelink = true; // hack to make null model players work
394#ifdef GLQUAKE
395 if (num > 0 && num <= cl.maxclients)
396 R_TranslatePlayerSkin (num - 1);
397#endif
398 }
399
400 if (bits & U_FRAME)
401 ent->frame = MSG_ReadByte ();
402 else
403 ent->frame = ent->baseline.frame;
404
405 if (bits & U_COLORMAP)
406 i = MSG_ReadByte();
407 else
408 i = ent->baseline.colormap;
409 if (!i)
410 ent->colormap = vid.colormap;
411 else
412 {
413 if (i > cl.maxclients)
414 Sys_Error ("i >= cl.maxclients");
415 ent->colormap = cl.scores[i-1].translations;
416 }
417
418#ifdef GLQUAKE
419 if (bits & U_SKIN)
420 skin = MSG_ReadByte();
421 else
422 skin = ent->baseline.skin;
423 if (skin != ent->skinnum) {
424 ent->skinnum = skin;
425 if (num > 0 && num <= cl.maxclients)
426 R_TranslatePlayerSkin (num - 1);
427 }
428
429#else
430
431 if (bits & U_SKIN)
432 ent->skinnum = MSG_ReadByte();
433 else
434 ent->skinnum = ent->baseline.skin;
435#endif
436
437 if (bits & U_EFFECTS)
438 ent->effects = MSG_ReadByte();
439 else
440 ent->effects = ent->baseline.effects;
441
442// shift the known values for interpolation
443 VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
444 VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
445
446 if (bits & U_ORIGIN1)
447 ent->msg_origins[0][0] = MSG_ReadCoord ();
448 else
449 ent->msg_origins[0][0] = ent->baseline.origin[0];
450 if (bits & U_ANGLE1)
451 ent->msg_angles[0][0] = MSG_ReadAngle();
452 else
453 ent->msg_angles[0][0] = ent->baseline.angles[0];
454
455 if (bits & U_ORIGIN2)
456 ent->msg_origins[0][1] = MSG_ReadCoord ();
457 else
458 ent->msg_origins[0][1] = ent->baseline.origin[1];
459 if (bits & U_ANGLE2)
460 ent->msg_angles[0][1] = MSG_ReadAngle();
461 else
462 ent->msg_angles[0][1] = ent->baseline.angles[1];
463
464 if (bits & U_ORIGIN3)
465 ent->msg_origins[0][2] = MSG_ReadCoord ();
466 else
467 ent->msg_origins[0][2] = ent->baseline.origin[2];
468 if (bits & U_ANGLE3)
469 ent->msg_angles[0][2] = MSG_ReadAngle();
470 else
471 ent->msg_angles[0][2] = ent->baseline.angles[2];
472
473 if ( bits & U_NOLERP )
474 ent->forcelink = true;
475
476 if ( forcelink )
477 { // didn't have an update last message
478 VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
479 VectorCopy (ent->msg_origins[0], ent->origin);
480 VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
481 VectorCopy (ent->msg_angles[0], ent->angles);
482 ent->forcelink = true;
483 }
484}
485
486/*
487==================
488CL_ParseBaseline
489==================
490*/
491void CL_ParseBaseline (entity_t *ent)
492{
493 int i;
494
495 ent->baseline.modelindex = MSG_ReadByte ();
496 ent->baseline.frame = MSG_ReadByte ();
497 ent->baseline.colormap = MSG_ReadByte();
498 ent->baseline.skin = MSG_ReadByte();
499 for (i=0 ; i<3 ; i++)
500 {
501 ent->baseline.origin[i] = MSG_ReadCoord ();
502 ent->baseline.angles[i] = MSG_ReadAngle ();
503 }
504}
505
506
507/*
508==================
509CL_ParseClientdata
510
511Server information pertaining to this client only
512==================
513*/
514void CL_ParseClientdata (int bits)
515{
516 int i, j;
517
518 if (bits & SU_VIEWHEIGHT)
519 cl.viewheight = MSG_ReadChar ();
520 else
521 cl.viewheight = DEFAULT_VIEWHEIGHT;
522
523 if (bits & SU_IDEALPITCH)
524 cl.idealpitch = MSG_ReadChar ();
525 else
526 cl.idealpitch = 0;
527
528 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
529 for (i=0 ; i<3 ; i++)
530 {
531 if (bits & (SU_PUNCH1<<i) )
532 cl.punchangle[i] = MSG_ReadChar();
533 else
534 cl.punchangle[i] = 0;
535 if (bits & (SU_VELOCITY1<<i) )
536 cl.mvelocity[0][i] = MSG_ReadChar()*16;
537 else
538 cl.mvelocity[0][i] = 0;
539 }
540
541// [always sent] if (bits & SU_ITEMS)
542 i = MSG_ReadLong ();
543
544 if (cl.items != i)
545 { // set flash times
546 Sbar_Changed ();
547 for (j=0 ; j<32 ; j++)
548 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
549 cl.item_gettime[j] = cl.time;
550 cl.items = i;
551 }
552
553 cl.onground = (bits & SU_ONGROUND) != 0;
554 cl.inwater = (bits & SU_INWATER) != 0;
555
556 if (bits & SU_WEAPONFRAME)
557 cl.stats[STAT_WEAPONFRAME] = MSG_ReadByte ();
558 else
559 cl.stats[STAT_WEAPONFRAME] = 0;
560
561 if (bits & SU_ARMOR)
562 i = MSG_ReadByte ();
563 else
564 i = 0;
565 if (cl.stats[STAT_ARMOR] != i)
566 {
567 cl.stats[STAT_ARMOR] = i;
568 Sbar_Changed ();
569 }
570
571 if (bits & SU_WEAPON)
572 i = MSG_ReadByte ();
573 else
574 i = 0;
575 if (cl.stats[STAT_WEAPON] != i)
576 {
577 cl.stats[STAT_WEAPON] = i;
578 Sbar_Changed ();
579 }
580
581 i = MSG_ReadShort ();
582 if (cl.stats[STAT_HEALTH] != i)
583 {
584 cl.stats[STAT_HEALTH] = i;
585 Sbar_Changed ();
586 }
587
588 i = MSG_ReadByte ();
589 if (cl.stats[STAT_AMMO] != i)
590 {
591 cl.stats[STAT_AMMO] = i;
592 Sbar_Changed ();
593 }
594
595 for (i=0 ; i<4 ; i++)
596 {
597 j = MSG_ReadByte ();
598 if (cl.stats[STAT_SHELLS+i] != j)
599 {
600 cl.stats[STAT_SHELLS+i] = j;
601 Sbar_Changed ();
602 }
603 }
604
605 i = MSG_ReadByte ();
606
607 if (standard_quake)
608 {
609 if (cl.stats[STAT_ACTIVEWEAPON] != i)
610 {
611 cl.stats[STAT_ACTIVEWEAPON] = i;
612 Sbar_Changed ();
613 }
614 }
615 else
616 {
617 if (cl.stats[STAT_ACTIVEWEAPON] != (1<<i))
618 {
619 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
620 Sbar_Changed ();
621 }
622 }
623}
624
625/*
626=====================
627CL_NewTranslation
628=====================
629*/
630void CL_NewTranslation (int slot)
631{
632 int i, j;
633 int top, bottom;
634 byte *dest, *source;
635
636 if (slot > cl.maxclients)
637 Sys_Error ("CL_NewTranslation: slot > cl.maxclients");
638 dest = cl.scores[slot].translations;
639 source = vid.colormap;
640 memcpy (dest, vid.colormap, sizeof(cl.scores[slot].translations));
641 top = cl.scores[slot].colors & 0xf0;
642 bottom = (cl.scores[slot].colors &15)<<4;
643#ifdef GLQUAKE
644 R_TranslatePlayerSkin (slot);
645#endif
646
647 for (i=0 ; i<VID_GRADES ; i++, dest += 256, source+=256)
648 {
649 if (top < 128) // the artists made some backwards ranges. sigh.
650 memcpy (dest + TOP_RANGE, source + top, 16);
651 else
652 for (j=0 ; j<16 ; j++)
653 dest[TOP_RANGE+j] = source[top+15-j];
654
655 if (bottom < 128)
656 memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
657 else
658 for (j=0 ; j<16 ; j++)
659 dest[BOTTOM_RANGE+j] = source[bottom+15-j];
660 }
661}
662
663/*
664=====================
665CL_ParseStatic
666=====================
667*/
668void CL_ParseStatic (void)
669{
670 entity_t *ent;
671 int i;
672
673 i = cl.num_statics;
674 if (i >= MAX_STATIC_ENTITIES)
675 Host_Error ("Too many static entities");
676 ent = &cl_static_entities[i];
677 cl.num_statics++;
678 CL_ParseBaseline (ent);
679
680// copy it to the current state
681 ent->model = cl.model_precache[ent->baseline.modelindex];
682 ent->frame = ent->baseline.frame;
683 ent->colormap = vid.colormap;
684 ent->skinnum = ent->baseline.skin;
685 ent->effects = ent->baseline.effects;
686
687 VectorCopy (ent->baseline.origin, ent->origin);
688 VectorCopy (ent->baseline.angles, ent->angles);
689 R_AddEfrags (ent);
690}
691
692/*
693===================
694CL_ParseStaticSound
695===================
696*/
697void CL_ParseStaticSound (void)
698{
699 vec3_t org;
700 int sound_num, vol, atten;
701 int i;
702
703 for (i=0 ; i<3 ; i++)
704 org[i] = MSG_ReadCoord ();
705 sound_num = MSG_ReadByte ();
706 vol = MSG_ReadByte ();
707 atten = MSG_ReadByte ();
708
709 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
710}
711
712
713#define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
714
715/*
716=====================
717CL_ParseServerMessage
718=====================
719*/
720void CL_ParseServerMessage (void)
721{
722 int cmd;
723 int i;
724
725//
726// if recording demos, copy the message out
727//
728 if (cl_shownet.value == 1)
729 Con_Printf ("%i ",net_message.cursize);
730 else if (cl_shownet.value == 2)
731 Con_Printf ("------------------\n");
732
733 cl.onground = false; // unless the server says otherwise
734//
735// parse the message
736//
737 MSG_BeginReading ();
738
739 while (1)
740 {
741 if (msg_badread)
742 Host_Error ("CL_ParseServerMessage: Bad server message");
743
744 cmd = MSG_ReadByte ();
745
746 if (cmd == -1)
747 {
748 SHOWNET("END OF MESSAGE");
749 return; // end of message
750 }
751
752 // if the high bit of the command byte is set, it is a fast update
753 if (cmd & 128)
754 {
755 SHOWNET("fast update");
756 CL_ParseUpdate (cmd&127);
757 continue;
758 }
759
760 SHOWNET(svc_strings[cmd]);
761
762 // other commands
763 switch (cmd)
764 {
765 default:
766 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
767 break;
768
769 case svc_nop:
770// Con_Printf ("svc_nop\n");
771 break;
772
773 case svc_time:
774 cl.mtime[1] = cl.mtime[0];
775 cl.mtime[0] = MSG_ReadFloat ();
776 break;
777
778 case svc_clientdata:
779 i = MSG_ReadShort ();
780 CL_ParseClientdata (i);
781 break;
782
783 case svc_version:
784 i = MSG_ReadLong ();
785 if (i != PROTOCOL_VERSION)
786 Host_Error ("CL_ParseServerMessage: Server is protocol %i instead of %i\n", i, PROTOCOL_VERSION);
787 break;
788
789 case svc_disconnect:
790 Host_EndGame ("Server disconnected\n");
791
792 case svc_print:
793 Con_Printf ("%s", MSG_ReadString ());
794 break;
795
796 case svc_centerprint:
797 SCR_CenterPrint (MSG_ReadString ());
798 break;
799
800 case svc_stufftext:
801 Cbuf_AddText (MSG_ReadString ());
802 break;
803
804 case svc_damage:
805 V_ParseDamage ();
806 break;
807
808 case svc_serverinfo:
809 CL_ParseServerInfo ();
810 vid.recalc_refdef = true; // leave intermission full screen
811 break;
812
813 case svc_setangle:
814 for (i=0 ; i<3 ; i++)
815 cl.viewangles[i] = MSG_ReadAngle ();
816 break;
817
818 case svc_setview:
819 cl.viewentity = MSG_ReadShort ();
820 break;
821
822 case svc_lightstyle:
823 i = MSG_ReadByte ();
824 if (i >= MAX_LIGHTSTYLES)
825 Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
826 Q_strcpy (cl_lightstyle[i].map, MSG_ReadString());
827 cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map);
828 break;
829
830 case svc_sound:
831 CL_ParseStartSoundPacket();
832 break;
833
834 case svc_stopsound:
835 i = MSG_ReadShort();
836 S_StopSound(i>>3, i&7);
837 break;
838
839 case svc_updatename:
840 Sbar_Changed ();
841 i = MSG_ReadByte ();
842 if (i >= cl.maxclients)
843 Host_Error ("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD");
844 strcpy (cl.scores[i].name, MSG_ReadString ());
845 break;
846
847 case svc_updatefrags:
848 Sbar_Changed ();
849 i = MSG_ReadByte ();
850 if (i >= cl.maxclients)
851 Host_Error ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD");
852 cl.scores[i].frags = MSG_ReadShort ();
853 break;
854
855 case svc_updatecolors:
856 Sbar_Changed ();
857 i = MSG_ReadByte ();
858 if (i >= cl.maxclients)
859 Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
860 cl.scores[i].colors = MSG_ReadByte ();
861 CL_NewTranslation (i);
862 break;
863
864 case svc_particle:
865 R_ParseParticleEffect ();
866 break;
867
868 case svc_spawnbaseline:
869 i = MSG_ReadShort ();
870 // must use CL_EntityNum() to force cl.num_entities up
871 CL_ParseBaseline (CL_EntityNum(i));
872 break;
873 case svc_spawnstatic:
874 CL_ParseStatic ();
875 break;
876 case svc_temp_entity:
877 CL_ParseTEnt ();
878 break;
879
880 case svc_setpause:
881 {
882 cl.paused = MSG_ReadByte ();
883
884 if (cl.paused)
885 {
886 CDAudio_Pause ();
Franklin Wei5d05b9d2018-02-11 15:34:30 -0500887 }
888 else
889 {
890 CDAudio_Resume ();
Franklin Wei5d05b9d2018-02-11 15:34:30 -0500891 }
892 }
893 break;
894
895 case svc_signonnum:
896 i = MSG_ReadByte ();
897 if (i <= cls.signon)
898 Host_Error ("Received signon %i when at %i", i, cls.signon);
899 cls.signon = i;
900 CL_SignonReply ();
901 break;
902
903 case svc_killedmonster:
904 cl.stats[STAT_MONSTERS]++;
905 break;
906
907 case svc_foundsecret:
908 cl.stats[STAT_SECRETS]++;
909 break;
910
911 case svc_updatestat:
912 i = MSG_ReadByte ();
913 if (i < 0 || i >= MAX_CL_STATS)
914 Sys_Error ("svc_updatestat: %i is invalid", i);
915 cl.stats[i] = MSG_ReadLong ();;
916 break;
917
918 case svc_spawnstaticsound:
919 CL_ParseStaticSound ();
920 break;
921
922 case svc_cdtrack:
923 cl.cdtrack = MSG_ReadByte ();
924 cl.looptrack = MSG_ReadByte ();
925 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
926 CDAudio_Play ((byte)cls.forcetrack, true);
927 else
928 CDAudio_Play ((byte)cl.cdtrack, true);
929 break;
930
931 case svc_intermission:
932 cl.intermission = 1;
933 cl.completed_time = cl.time;
934 vid.recalc_refdef = true; // go to full screen
935 break;
936
937 case svc_finale:
938 cl.intermission = 2;
939 cl.completed_time = cl.time;
940 vid.recalc_refdef = true; // go to full screen
941 SCR_CenterPrint (MSG_ReadString ());
942 break;
943
944 case svc_cutscene:
945 cl.intermission = 3;
946 cl.completed_time = cl.time;
947 vid.recalc_refdef = true; // go to full screen
948 SCR_CenterPrint (MSG_ReadString ());
949 break;
950
951 case svc_sellscreen:
952 Cmd_ExecuteString ("help", src_command);
953 break;
954 }
955 }
956}
957