1 /*
2  * cl_parse.c -- parse a message received from the server
3  * $Id: cl_parse.c 5977 2017-09-17 08:01:41Z sezero $
4  *
5  * Copyright (C) 1996-1997  Id Software, Inc.
6  * Copyright (C) 1997-1998  Raven Software Corp.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23 
24 #include "quakedef.h"
25 #include "bgmusic.h"
26 #include "cdaudio.h"
27 #include "r_shared.h"
28 
29 static const char *svc_strings[] =
30 {
31 	"svc_bad",
32 	"svc_nop",
33 	"svc_disconnect",
34 	"svc_updatestat",
35 	"svc_version",		// [long] server version
36 	"svc_setview",		// [short] entity number
37 	"svc_sound",		// <see code>
38 	"svc_time",		// [float] server time
39 	"svc_print",		// [string] null terminated string
40 	"svc_stufftext",	// [string] stuffed into client's console buffer
41 				// the string should be \n terminated
42 	"svc_setangle",		// [vec3] set the view angle to this absolute value
43 
44 	"svc_serverdata",	// [long] version ...
45 	"svc_lightstyle",	// [byte] [string]
46 	"svc_updatename",	// [byte] [string]
47 	"svc_updatefrags",	// [byte] [short]
48 	"svc_clientdata",	// <shortbits + data>
49 	"svc_stopsound",	// <see code>
50 	"svc_updatecolors",	// [byte] [byte]
51 	"svc_particle",		// [vec3] <variable>
52 	"svc_damage",		// [byte] impact [byte] blood [vec3] from
53 
54 	"svc_spawnstatic",
55 	"OBSOLETE svc_spawnbinary",
56 	"svc_spawnbaseline",
57 
58 	"svc_temp_entity",	// <variable>
59 	"svc_setpause",
60 	"svc_signonnum",
61 	"svc_centerprint",
62 	"svc_killedmonster",
63 	"svc_foundsecret",
64 	"svc_spawnstaticsound",
65 	"svc_intermission",
66 	"svc_finale",
67 
68 	"svc_cdtrack",
69 	"svc_sellscreen",
70 
71 	"svc_smallkick",
72 	"svc_bigkick",
73 
74 	"svc_updateping",
75 	"svc_updateentertime",
76 
77 	"svc_updatestatlong",
78 	"svc_muzzleflash",
79 	"svc_updateuserinfo",
80 	"svc_download",
81 	"svc_playerinfo",
82 	"svc_nails",
83 	"svc_choke",
84 	"svc_modellist",
85 	"svc_soundlist",
86 	"svc_packetentities",
87  	"svc_deltapacketentities",
88 	"svc_maxspeed",
89 	"svc_entgravity",
90 
91 	"svc_plaque",
92 	"svc_particle_explosion",
93 	"svc_set_view_tint",
94 	"svc_start_effect",
95 	"svc_end_effect",
96 	"svc_set_view_flags",
97 	"svc_clear_view_flags",
98 	"svc_update_inv",
99 	"svc_particle2",
100 	"svc_particle3",
101 	"svc_particle4",
102 	"svc_turn_effect",
103 	"svc_update_effect",
104 	"svc_multieffect",
105 	"svc_midi_name",
106 	"svc_raineffect",
107 	"svc_packmissile",
108 
109 	"svc_indexed_print",
110 	"svc_targetupdate",
111 	"svc_name_print",
112 	"svc_sound_update_pos",
113 	"svc_update_piv",
114 	"svc_player_sound",
115 	"svc_updatepclass",
116 	"svc_updatedminfo",	// [byte] [short] [byte]
117 	"svc_updatesiegeinfo",	// [byte] [byte]
118 	"svc_updatesiegeteam",	// [byte] [byte]
119 	"svc_updatesiegelosses",// [byte] [byte]
120 	"svc_haskey",		// [byte] [byte]
121 	"svc_nonehaskey",	// [byte]
122 	"svc_isdoc",		// [byte] [byte]
123 	"svc_nodoc",		// [byte]
124 	"svc_playerskipped"	// [byte]
125 	"NEW PROTOCOL",
126 	"NEW PROTOCOL",
127 	"NEW PROTOCOL",
128 	"NEW PROTOCOL"
129 };
130 #define	NUM_SVC_STRINGS	(sizeof(svc_strings) / sizeof(svc_strings[0]))
131 
132 int		parsecountmod;
133 double		parsecounttime;
134 
135 qmodel_t	*player_models[MAX_PLAYER_CLASS];
136 
137 int		cl_spikeindex, cl_playerindex[MAX_PLAYER_CLASS], cl_flagindex;
138 int		cl_ballindex, cl_missilestarindex, cl_ravenindex, cl_raven2index;
139 
140 
141 //=============================================================================
142 
143 
144 /*
145 ===============
146 CL_CheckOrDownloadFile
147 
148 Returns true if the file exists, otherwise it attempts
149 to start a download from the server.
150 ===============
151 */
CL_CheckOrDownloadFile(const char * filename)152 qboolean CL_CheckOrDownloadFile (const char *filename)
153 {
154 	if (strstr (filename, ".."))
155 	{
156 		Con_Printf ("Refusing to download a path with ..\n");
157 		return true;
158 	}
159 
160 	if (FS_FileExists(filename, NULL))
161 	{	// it exists, no need to download
162 		return true;
163 	}
164 
165 	//ZOID - can't download when recording
166 	if (cls.demorecording)
167 	{
168 		Con_Printf("Unable to download %s in record mode.\n", cls.downloadname);
169 		return true;
170 	}
171 	//ZOID - can't download when playback
172 	if (cls.demoplayback)
173 		return true;
174 
175 	q_strlcpy (cls.downloadname, filename, MAX_OSPATH);
176 	Con_Printf ("Downloading %s...\n", cls.downloadname);
177 
178 	// download to a temp name, and only rename
179 	// to the real name when done, so if interrupted
180 	// a runt file wont be left
181 	COM_StripExtension (cls.downloadname, cls.downloadtempname, sizeof(cls.downloadtempname));
182 	q_strlcat (cls.downloadtempname, ".tmp", sizeof(cls.downloadtempname));
183 
184 	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
185 	MSG_WriteString (&cls.netchan.message, va("download %s", cls.downloadname));
186 
187 	cls.downloadnumber++;
188 
189 	return false;
190 }
191 
192 /*
193 =================
194 Model_NextDownload
195 =================
196 */
Model_NextDownload(void)197 static void Model_NextDownload (void)
198 {
199 	const char	*s;
200 	int	i;
201 
202 	if (cls.downloadnumber == 0)
203 	{
204 		Con_Printf ("Checking models...\n");
205 		cls.downloadnumber = 1;
206 	}
207 
208 	cls.downloadtype = dl_model;
209 	for ( ; cl.model_name[cls.downloadnumber][0] ; cls.downloadnumber++)
210 	{
211 		s = cl.model_name[cls.downloadnumber];
212 		if (s[0] == '*')
213 			continue;	// inline brush model
214 		if (!CL_CheckOrDownloadFile(s))
215 			return;		// started a download
216 	}
217 
218 	for (i = 1; i < MAX_MODELS; i++)
219 	{
220 		if (!cl.model_name[i][0])
221 			break;
222 		cl.model_precache[i] = Mod_ForName (cl.model_name[i], false);
223 		if (!cl.model_precache[i])
224 		{
225 			Con_Printf ("\nThe required model file '%s' could not be found or downloaded.\n\n", cl.model_name[i]);
226 			Con_Printf ("You may need to download or purchase a %s client "
227 					"pack in order to play on this server.\n\n", fs_gamedir_nopath);
228 			CL_Disconnect ();
229 			return;
230 		}
231 	}
232 
233 	// copy the naked name of the map file to the cl structure
234 	COM_FileBase (cl.model_name[1], cl.mapname, sizeof(cl.mapname));
235 
236 	// all done
237 	cl.worldmodel = cl.model_precache[1];
238 	R_NewMap ();
239 
240 	Host_LoadStrings();
241 
242 	Hunk_Check ();		// make sure nothing is hurt
243 
244 	// done with modellist, request first of static signon messages
245 	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
246 	MSG_WriteString (&cls.netchan.message, va("prespawn %i", cl.servercount));
247 }
248 
249 /*
250 =================
251 Sound_NextDownload
252 =================
253 */
Sound_NextDownload(void)254 static void Sound_NextDownload (void)
255 {
256 	const char	*s;
257 	int	i;
258 
259 	if (cls.downloadnumber == 0)
260 	{
261 		Con_Printf ("Checking sounds...\n");
262 		cls.downloadnumber = 1;
263 	}
264 
265 	cls.downloadtype = dl_sound;
266 	for ( ; cl.sound_name[cls.downloadnumber][0] ; cls.downloadnumber++)
267 	{
268 		s = cl.sound_name[cls.downloadnumber];
269 		if (!CL_CheckOrDownloadFile(va("sound/%s",s)))
270 			return;		// started a download
271 	}
272 
273 	for (i = 1; i < MAX_SOUNDS; i++)
274 	{
275 		if (!cl.sound_name[i][0])
276 			break;
277 		cl.sound_precache[i] = S_PrecacheSound (cl.sound_name[i]);
278 	}
279 
280 	// done with sounds, request models now
281 	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
282 	MSG_WriteString (&cls.netchan.message, va("modellist %i", cl.servercount));
283 }
284 
285 
286 /*
287 ======================
288 CL_RequestNextDownload
289 ======================
290 */
CL_RequestNextDownload(void)291 static void CL_RequestNextDownload (void)
292 {
293 	switch (cls.downloadtype)
294 	{
295 	case dl_single:
296 		break;
297 	case dl_skin:
298 		Skin_NextDownload ();
299 		break;
300 	case dl_model:
301 		Model_NextDownload ();
302 		break;
303 	case dl_sound:
304 		Sound_NextDownload ();
305 		break;
306 	case dl_none:
307 	default:
308 		Con_DPrintf("Unknown download type.\n");
309 	}
310 }
311 
312 /*
313 =====================
314 CL_ParseDownload
315 
316 A download message has been received from the server
317 =====================
318 */
CL_ParseDownload(void)319 static void CL_ParseDownload (void)
320 {
321 	int	size, percent;
322 	char	name[MAX_OSPATH];
323 
324 	// read the data
325 	size = MSG_ReadShort ();
326 	percent = MSG_ReadByte ();
327 
328 	if (cls.demoplayback)
329 	{
330 		if (size > 0)
331 			msg_readcount += size;
332 		return; // not in demo playback
333 	}
334 
335 	if (size == -1)
336 	{
337 		Con_Printf ("File not found.\n");
338 		if (cls.download)
339 		{
340 			Con_Printf ("cls.download shouldn't have been set\n");
341 			fclose (cls.download);
342 			cls.download = NULL;
343 		}
344 		CL_RequestNextDownload ();
345 		return;
346 	}
347 
348 	// open the file if not opened yet
349 	if (!cls.download)
350 	{
351 		FS_MakePath_BUF (FS_USERDIR, NULL, name, sizeof(name), cls.downloadtempname);
352 		if ( FS_CreatePath(name) )
353 		{
354 			msg_readcount += size;
355 			Con_Printf ("Unable to create directory for downloading %s\n", cls.downloadtempname);
356 			CL_RequestNextDownload ();
357 			return;
358 		}
359 
360 		cls.download = fopen (name, "wb");
361 		if (!cls.download)
362 		{
363 			msg_readcount += size;
364 			Con_Printf ("Failed to open %s\n", cls.downloadtempname);
365 			CL_RequestNextDownload ();
366 			return;
367 		}
368 	}
369 
370 	fwrite (net_message.data + msg_readcount, 1, size, cls.download);
371 	msg_readcount += size;
372 
373 	if (percent != 100)
374 	{
375 		// request next block
376 		cls.downloadpercent = percent;
377 
378 		MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
379 		SZ_Print (&cls.netchan.message, "nextdl");
380 	}
381 	else
382 	{
383 		// rename the temp file to it's final name
384 		char	oldn[MAX_OSPATH];
385 		char	newn[MAX_OSPATH];
386 
387 		fclose (cls.download);
388 		cls.download = NULL;
389 		cls.downloadpercent = 0;
390 
391 		FS_MakePath_BUF (FS_USERDIR, NULL, oldn, sizeof(oldn), cls.downloadtempname);
392 		FS_MakePath_BUF (FS_USERDIR, NULL, newn, sizeof(newn), cls.downloadname);
393 		if (Sys_rename(oldn, newn) != 0)
394 			Con_Printf ("failed to rename.\n");
395 
396 		// get another file if needed
397 		CL_RequestNextDownload ();
398 	}
399 }
400 
401 
402 /*
403 =====================================================================
404 
405 SERVER CONNECTING MESSAGES
406 
407 =====================================================================
408 */
409 
410 /*
411 ==================
412 CL_ParseServerData
413 ==================
414 */
CL_ParseServerData(void)415 static void CL_ParseServerData (void)
416 {
417 	const char	*str;
418 
419 	Con_DPrintf ("Serverdata packet received.\n");
420 
421 //
422 // wipe the client_state_t struct
423 //
424 	CL_ClearState ();
425 
426 	// CL_ClearState() clears the cl structure already,
427 	// so no need zero'ing the sound/model list arrays.
428 	//memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
429 	//memset (cl.model_precache, 0, sizeof(cl.model_precache));
430 	cl_playerindex[0] = -1;
431 	cl_playerindex[1] = -1;
432 	cl_playerindex[2] = -1;
433 	cl_playerindex[3] = -1;
434 	cl_playerindex[4] = -1;
435 	cl_playerindex[5] = -1;//mg-siege
436 	cl_spikeindex = -1;
437 	cl_flagindex = -1;
438 	cl_ballindex = -1;
439 	cl_missilestarindex = -1;
440 	cl_ravenindex = -1;
441 	cl_raven2index = -1;
442 
443 // parse protocol version number
444 	cl.protocol = MSG_ReadLong ();
445 	switch (cl.protocol) {
446 	case OLD_PROTOCOL_VERSION:
447 	case PROTOCOL_VERSION:
448 	case PROTOCOL_VERSION_EXT:
449 		Con_Printf ("Server using protocol %i\n", cl.protocol);
450 		break;
451 	default:
452 		Host_EndGame ("Server returned unsupported protocol %i", cl.protocol);
453 	}
454 
455 	cl.servercount = MSG_ReadLong ();
456 
457 	// game directory
458 	str = MSG_ReadString ();
459 
460 	if (q_strcasecmp(fs_gamedir_nopath, str))
461 	{
462 		Con_Printf("Server set the gamedir to %s\n", str);
463 
464 		// save current config
465 		Host_WriteConfiguration ("config.cfg");
466 
467 		// set the new gamedir and userdir
468 		FS_Gamedir(str);
469 
470 		// ZOID - run autoexec.cfg in the gamedir if it exists
471 		if (FS_FileInGamedir("config.cfg"))
472 		{
473 		// remove any weird mod specific key bindings / aliases
474 			Cbuf_AddText("unbindall\n");
475 			Cbuf_AddText("unaliasall\n");
476 			Cbuf_AddText("exec autoexec.cfg\n");
477 			Cbuf_AddText("exec config.cfg\n");
478 		}
479 		// gamespy crap
480 		if (FS_FileInGamedir("frontend.cfg"))
481 			Cbuf_AddText("exec frontend.cfg\n");
482 
483 		Cbuf_Execute ();
484 
485 		// re-init draw
486 		Draw_ReInit ();
487 	}
488 
489 	// parse player slot, high bit means spectator
490 	cl.playernum = MSG_ReadByte ();
491 	if (cl.playernum & 128)
492 	{
493 		cl.spectator = true;
494 		cl.playernum &= ~128;
495 	}
496 
497 	// get the full level name
498 	str = MSG_ReadString ();
499 	q_strlcpy (cl.levelname, str, sizeof(cl.levelname));
500 
501 	// get the movevars
502 	if (cl.protocol >= PROTOCOL_VERSION)
503 	{
504 		movevars.gravity		= MSG_ReadFloat();
505 		movevars.stopspeed		= MSG_ReadFloat();
506 		movevars.maxspeed		= MSG_ReadFloat();
507 		movevars.spectatormaxspeed	= MSG_ReadFloat();
508 		movevars.accelerate		= MSG_ReadFloat();
509 		movevars.airaccelerate		= MSG_ReadFloat();
510 		movevars.wateraccelerate	= MSG_ReadFloat();
511 		movevars.friction		= MSG_ReadFloat();
512 		movevars.waterfriction		= MSG_ReadFloat();
513 		movevars.entgravity		= MSG_ReadFloat();
514 	}
515 	else
516 	{
517 		movevars.gravity		= 800;
518 		movevars.stopspeed		= 100;
519 		movevars.maxspeed		= 320;
520 		movevars.spectatormaxspeed	= 500;
521 		movevars.accelerate		= 10;
522 		movevars.airaccelerate		= 0.7;
523 		movevars.wateraccelerate	= 10;
524 		movevars.friction		= 6;
525 		movevars.waterfriction		= 1;
526 		movevars.entgravity		= 1.0;
527 	}
528 
529 	// seperate the printfs so the server message can have a color
530 	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");
531 	Con_Printf ("%c%s\n", 2, str);
532 
533 	// ask for the sound list next
534 	MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
535 	MSG_WriteString (&cls.netchan.message, va("soundlist %i", cl.servercount));
536 
537 	// now waiting for downloads, etc
538 	cls.state = ca_onserver;
539 	cl_keyholder = -1;
540 	cl_doc = -1;
541 }
542 
CL_ParseSoundlistChunks(void)543 static void CL_ParseSoundlistChunks (void) /* from QW */
544 {
545 	int	numsounds, n;
546 	const char	*str;
547 
548 	// precache sounds
549 	numsounds = MSG_ReadLong ();
550 
551 	for (;;) {
552 		str = MSG_ReadString ();
553 		if (!str[0])
554 			break;
555 		numsounds++;
556 		if (numsounds >= MAX_SOUNDS)
557 			Host_Error ("Server sent too many sound_precache");
558 		strcpy (cl.sound_name[numsounds], str);
559 	}
560 
561 	n = MSG_ReadLong ();
562 	if (n)
563 	{
564 		if (!cls.demoplayback) {
565 			MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
566 			MSG_WriteString (&cls.netchan.message,
567 						 va ("soundlist %i %i", cl.servercount, n));
568 		}
569 		return;
570 	}
571 
572 	cls.downloadnumber = 0;
573 	cls.downloadtype = dl_sound;
574 	Sound_NextDownload ();
575 }
576 
577 /*
578 ==================
579 CL_ParseSoundlist
580 ==================
581 */
CL_ParseSoundlist(void)582 static void CL_ParseSoundlist (void)
583 {
584 	int	numsounds;
585 	const char	*str;
586 
587 // precache sounds
588 	for (numsounds = 1 ; ; numsounds++)
589 	{
590 		str = MSG_ReadString ();
591 		if (!str[0])
592 			break;
593 		if (numsounds == MAX_SOUNDS)
594 			Host_EndGame ("Server sent too many sound_precache");
595 		q_strlcpy (cl.sound_name[numsounds], str, MAX_QPATH);
596 	}
597 
598 	cls.downloadnumber = 0;
599 	cls.downloadtype = dl_sound;
600 	Sound_NextDownload ();
601 }
602 
CL_ParseModellistChunks(void)603 static void CL_ParseModellistChunks (void) /* from QW */
604 {
605 	int	nummodels, n;
606 	const char	*str;
607 
608 	// precache models and note certain default indexes
609 	nummodels = MSG_ReadLong ();
610 
611 	for (;;)
612 	{
613 		str = MSG_ReadString ();
614 		if (!str[0])
615 			break;
616 
617 		nummodels++;
618 		if (nummodels >= MAX_MODELS)
619 			Host_EndGame ("Server sent too many model_precache");
620 
621 		q_strlcpy (cl.model_name[nummodels], str, MAX_QPATH);
622 
623 		if (!strcmp(cl.model_name[nummodels],"progs/spike.mdl"))
624 			cl_spikeindex = nummodels;
625 		if (!strcmp(cl.model_name[nummodels],"models/paladin.mdl"))
626 			cl_playerindex[0] = nummodels;
627 		if (!strcmp(cl.model_name[nummodels],"models/crusader.mdl"))
628 			cl_playerindex[1] = nummodels;
629 		if (!strcmp(cl.model_name[nummodels],"models/necro.mdl"))
630 			cl_playerindex[2] = nummodels;
631 		if (!strcmp(cl.model_name[nummodels],"models/assassin.mdl"))
632 			cl_playerindex[3] = nummodels;
633 		if (!strcmp(cl.model_name[nummodels],"models/succubus.mdl"))
634 			cl_playerindex[4] = nummodels;
635 		if (!strcmp(cl.model_name[nummodels],"models/hank.mdl"))
636 			cl_playerindex[5] = nummodels;//mg-siege
637 		if (!strcmp(cl.model_name[nummodels],"progs/flag.mdl"))
638 			cl_flagindex = nummodels;
639 		if (!strcmp(cl.model_name[nummodels],"models/ball.mdl"))
640 			cl_ballindex = nummodels;
641 		if (!strcmp(cl.model_name[nummodels],"models/newmmis.mdl"))
642 			cl_missilestarindex = nummodels;
643 		if (!strcmp(cl.model_name[nummodels],"models/ravproj.mdl"))
644 			cl_ravenindex = nummodels;
645 		if (!strcmp(cl.model_name[nummodels],"models/vindsht1.mdl"))
646 			cl_raven2index = nummodels;
647 	}
648 
649 	player_models[0] = (qmodel_t *)Mod_FindName ("models/paladin.mdl");
650 	player_models[1] = !(gameflags & GAME_OLD_DEMO) ? (qmodel_t *)Mod_FindName ("models/crusader.mdl") : NULL;
651 	player_models[2] = !(gameflags & GAME_OLD_DEMO) ? (qmodel_t *)Mod_FindName ("models/necro.mdl") : NULL;
652 	player_models[3] = (qmodel_t *)Mod_FindName ("models/assassin.mdl");
653 	player_models[4] = (qmodel_t *)Mod_FindName ("models/succubus.mdl");
654 	player_models[5] = (qmodel_t *)Mod_FindName ("models/hank.mdl");//siege
655 
656 	n = MSG_ReadLong ();
657 	if (n)
658 	{
659 		if (!cls.demoplayback) {
660 			MSG_WriteByte (&cls.netchan.message, clc_stringcmd);
661 			MSG_WriteString (&cls.netchan.message,
662 							 va ("modellist %i %i", cl.servercount, n));
663 		}
664 		return;
665 	}
666 
667 	cls.downloadnumber = 0;
668 	cls.downloadtype = dl_model;
669 	Model_NextDownload ();
670 }
671 
672 /*
673 ==================
674 CL_ParseModellist
675 ==================
676 */
CL_ParseModellist(void)677 static void CL_ParseModellist (void)
678 {
679 	int	nummodels;
680 	const char	*str;
681 
682 // precache models and note certain default indexes
683 	for (nummodels = 1 ; ; nummodels++)
684 	{
685 		str = MSG_ReadString ();
686 		if (!str[0])
687 			break;
688 		if (nummodels == MAX_MODELS)
689 			Host_EndGame ("Server sent too many model_precache");
690 		q_strlcpy (cl.model_name[nummodels], str, MAX_QPATH);
691 
692 		if (!strcmp(cl.model_name[nummodels],"progs/spike.mdl"))
693 			cl_spikeindex = nummodels;
694 		if (!strcmp(cl.model_name[nummodels],"models/paladin.mdl"))
695 			cl_playerindex[0] = nummodels;
696 		if (!strcmp(cl.model_name[nummodels],"models/crusader.mdl"))
697 			cl_playerindex[1] = nummodels;
698 		if (!strcmp(cl.model_name[nummodels],"models/necro.mdl"))
699 			cl_playerindex[2] = nummodels;
700 		if (!strcmp(cl.model_name[nummodels],"models/assassin.mdl"))
701 			cl_playerindex[3] = nummodels;
702 		if (!strcmp(cl.model_name[nummodels],"models/succubus.mdl"))
703 			cl_playerindex[4] = nummodels;
704 		if (!strcmp(cl.model_name[nummodels],"models/hank.mdl"))
705 			cl_playerindex[5] = nummodels;//mg-siege
706 		if (!strcmp(cl.model_name[nummodels],"progs/flag.mdl"))
707 			cl_flagindex = nummodels;
708 		if (!strcmp(cl.model_name[nummodels],"models/ball.mdl"))
709 			cl_ballindex = nummodels;
710 		if (!strcmp(cl.model_name[nummodels],"models/newmmis.mdl"))
711 			cl_missilestarindex = nummodels;
712 		if (!strcmp(cl.model_name[nummodels],"models/ravproj.mdl"))
713 			cl_ravenindex = nummodels;
714 		if (!strcmp(cl.model_name[nummodels],"models/vindsht1.mdl"))
715 			cl_raven2index = nummodels;
716 	}
717 
718 	player_models[0] = (qmodel_t *)Mod_FindName ("models/paladin.mdl");
719 	player_models[1] = !(gameflags & GAME_OLD_DEMO) ? (qmodel_t *)Mod_FindName ("models/crusader.mdl") : NULL;
720 	player_models[2] = !(gameflags & GAME_OLD_DEMO) ? (qmodel_t *)Mod_FindName ("models/necro.mdl") : NULL;
721 	player_models[3] = (qmodel_t *)Mod_FindName ("models/assassin.mdl");
722 	player_models[4] = (qmodel_t *)Mod_FindName ("models/succubus.mdl");
723 	player_models[5] = (qmodel_t *)Mod_FindName ("models/hank.mdl");//siege
724 
725 	cls.downloadnumber = 0;
726 	cls.downloadtype = dl_model;
727 	Model_NextDownload ();
728 }
729 
730 /*
731 ==================
732 CL_ParseBaseline
733 ==================
734 */
CL_ParseBaseline(entity_state_t * es)735 static void CL_ParseBaseline (entity_state_t *es)
736 {
737 	int	i;
738 
739 	es->modelindex = MSG_ReadShort ();
740 	es->frame = MSG_ReadByte ();
741 	es->colormap = MSG_ReadByte();
742 	es->skinnum = MSG_ReadByte();
743 	es->scale = MSG_ReadByte();
744 	es->drawflags = MSG_ReadByte();
745 	es->abslight = MSG_ReadByte();
746 
747 	for (i = 0; i < 3; i++)
748 	{
749 		es->origin[i] = MSG_ReadCoord ();
750 		es->angles[i] = MSG_ReadAngle ();
751 	}
752 }
753 
754 
755 /*
756 =====================
757 CL_ParseStatic
758 
759 Static entities are non-interactive world objects
760 like torches
761 =====================
762 */
CL_ParseStatic(void)763 static void CL_ParseStatic (void)
764 {
765 	entity_t *ent;
766 	int	i;
767 	entity_state_t	es;
768 
769 	CL_ParseBaseline (&es);
770 
771 	i = cl.num_statics;
772 	if (i >= MAX_STATIC_ENTITIES)
773 		Host_EndGame ("Too many static entities");
774 	ent = &cl_static_entities[i];
775 	cl.num_statics++;
776 
777 // copy it to the current state
778 	ent->model = cl.model_precache[es.modelindex];
779 	ent->frame = es.frame;
780 	ent->colormap = vid.colormap;
781 	ent->skinnum = es.skinnum;
782 	ent->scale = es.scale;
783 	ent->drawflags = es.drawflags;
784 	ent->abslight = es.abslight;
785 
786 	VectorCopy (es.origin, ent->origin);
787 	VectorCopy (es.angles, ent->angles);
788 
789 	R_AddEfrags (ent);
790 }
791 
792 /*
793 ===================
794 CL_ParseStaticSound
795 ===================
796 */
CL_ParseStaticSound(void)797 static void CL_ParseStaticSound (void)
798 {
799 	vec3_t	org;
800 	int	sound_num, vol, atten;
801 	int	i;
802 
803 	for (i = 0; i < 3; i++)
804 		org[i] = MSG_ReadCoord ();
805 	sound_num = MSG_ReadByte ();
806 	vol = MSG_ReadByte ();
807 	atten = MSG_ReadByte ();
808 
809 	S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
810 }
811 
812 
813 /*
814 =====================================================================
815 
816 ACTION MESSAGES
817 
818 =====================================================================
819 */
820 
821 /*
822 ==================
823 CL_ParseStartSoundPacket
824 ==================
825 */
CL_ParseStartSoundPacket(void)826 static void CL_ParseStartSoundPacket(void)
827 {
828 	vec3_t	pos;
829 	int	channel, ent;
830 	int	sound_num, volume;
831 	float	attenuation;
832 	int	i;
833 
834 	channel = MSG_ReadShort();
835 
836 	if (channel & SND_VOLUME)
837 		volume = MSG_ReadByte ();
838 	else	volume = DEFAULT_SOUND_PACKET_VOLUME;
839 
840 	if (channel & SND_ATTENUATION)
841 		attenuation = MSG_ReadByte () / 32.0;
842 	else	attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
843 
844 	sound_num = MSG_ReadByte ();
845 
846 	for (i = 0; i < 3; i++)
847 		pos[i] = MSG_ReadCoord ();
848 
849 	ent = (channel>>3)&1023;
850 	channel &= 7;
851 
852 	if (ent > MAX_EDICTS)
853 		Host_EndGame ("%s: ent = %i", __thisfunc__, ent);
854 
855 	S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
856 }
857 
858 
859 /*
860 ==================
861 CL_ParseClientdata
862 
863 Server information pertaining to this client only, sent every frame
864 ==================
865 */
CL_ParseClientdata(void)866 static void CL_ParseClientdata (void)
867 {
868 	int		i;
869 	float		latency;
870 	frame_t		*frame;
871 
872 // calculate simulated time of message
873 
874 	i = cls.netchan.incoming_acknowledged;
875 	cl.parsecount = i;
876 	i &= UPDATE_MASK;
877 	parsecountmod = i;
878 	frame = &cl.frames[i];
879 	parsecounttime = cl.frames[i].senttime;
880 
881 	frame->receivedtime = realtime;
882 
883 // calculate latency
884 	latency = frame->receivedtime - frame->senttime;
885 
886 	if (latency < 0 || latency > 1.0)
887 	{
888 	//	Con_Printf ("Odd latency: %5.2f\n", latency);
889 	}
890 	else
891 	{
892 	// drift the average latency towards the observed latency
893 		if (latency < cls.latency)
894 			cls.latency = latency;
895 		else	cls.latency += 0.001;	// drift up, so correction are needed
896 	}
897 }
898 
899 /*
900 =====================
901 CL_NewTranslation
902 =====================
903 */
CL_NewTranslation(int slot)904 static void CL_NewTranslation (int slot)
905 {
906 #ifdef GLQUAKE
907 	if (slot >= MAX_CLIENTS)
908 		Sys_Error ("%s: slot > MAX_CLIENTS", __thisfunc__);
909 
910 	R_TranslatePlayerSkin(slot);
911 #else
912 
913 	int	i, j;
914 	int	top, bottom;
915 	byte	*dest, *source, *sourceA, *sourceB, *colorA, *colorB;
916 	player_info_t	*player;
917 
918 	if (slot >= MAX_CLIENTS)
919 		Sys_Error ("%s: slot > MAX_CLIENTS", __thisfunc__);
920 
921 	player = &cl.players[slot];
922 	if (!player->playerclass)
923 		return;
924 
925 	dest = player->translations;
926 	source = vid.colormap;
927 	memcpy (dest, vid.colormap, sizeof(player->translations));
928 
929 	top = player->topcolor;
930 	if (top > 10 || top < 0)
931 		top = 10;
932 	bottom = player->bottomcolor;
933 	if (bottom > 10 || bottom < 0)
934 		bottom = 10;
935 	top -= 1;
936 	bottom -= 1;
937 
938 	for (i = 0; i < VID_GRADES; i++, dest += 256, source += 256)
939 	{
940 		colorA = playerTranslation + 256 + color_offsets[(int)player->playerclass-1];
941 		colorB = colorA + 256;
942 		sourceA = colorB + 256 + (top * 256);
943 		sourceB = colorB + 256 + (bottom * 256);
944 		for (j = 0; j < 256; j++, colorA++, colorB++, sourceA++, sourceB++)
945 		{
946 			if (top >= 0 && (*colorA != 255))
947 				dest[j] = source[*sourceA];
948 			if (bottom >= 0 && (*colorB != 255))
949 				dest[j] = source[*sourceB];
950 		}
951 	}
952 #endif
953 }
954 
955 /*
956 ==============
957 CL_UpdateUserinfo
958 ==============
959 */
CL_UpdateUserinfo(void)960 static void CL_UpdateUserinfo (void)
961 {
962 	int		slot;
963 	player_info_t	*player;
964 
965 	slot = MSG_ReadByte ();
966 	if (slot >= MAX_CLIENTS)
967 		Host_EndGame ("%s: svc_updateuserinfo > MAX_CLIENTS", __thisfunc__);
968 
969 	player = &cl.players[slot];
970 	player->userid = MSG_ReadLong ();
971 	q_strlcpy (player->userinfo, MSG_ReadString(), sizeof(player->userinfo));
972 
973 	q_strlcpy (player->name, Info_ValueForKey (player->userinfo, "name"), sizeof(player->name));
974 	player->topcolor = atoi(Info_ValueForKey (player->userinfo, "topcolor"));
975 	player->bottomcolor = atoi(Info_ValueForKey (player->userinfo, "bottomcolor"));
976 	if (Info_ValueForKey (player->userinfo, "*spectator")[0])
977 		player->spectator = true;
978 	else	player->spectator = false;
979 
980 	if (cls.state == ca_active)
981 		Skin_Find (player);
982 
983 	player->playerclass = atoi(Info_ValueForKey (player->userinfo, "playerclass"));
984 	/*
985 	if (cl.playernum == slot && player->playerclass != playerclass.integer)
986 		Cvar_SetValue ("playerclass",player->playerclass);
987 	*/
988 	Sbar_Changed ();
989 	player->Translated = false;
990 	CL_NewTranslation (slot);
991 }
992 
993 
994 /*
995 =====================
996 CL_SetStat
997 =====================
998 */
CL_SetStat(int idx,int value)999 static void CL_SetStat (int idx, int value)
1000 {
1001 	int	j;
1002 
1003 	if (idx < 0 || idx >= MAX_CL_STATS)
1004 		Sys_Error ("%s: %i is invalid", __thisfunc__, idx);
1005 
1006 	Sbar_Changed ();
1007 
1008 	if (idx == STAT_ITEMS)
1009 	{	// set flash times
1010 		Sbar_Changed ();
1011 		for (j = 0; j < 32; j++)
1012 			if ((value & (1<<j)) && !(cl.stats[idx] & (1<<j)))
1013 				cl.item_gettime[j] = cl.time;
1014 	}
1015 
1016 	cl.stats[idx] = value;
1017 }
1018 
1019 /*
1020 ==============
1021 CL_MuzzleFlash
1022 ==============
1023 */
CL_MuzzleFlash(void)1024 static void CL_MuzzleFlash (void)
1025 {
1026 	vec3_t	fv, rv, uv;
1027 	dlight_t	*dl;
1028 	int		i;
1029 	player_state_t	*pl;
1030 
1031 	i = MSG_ReadShort ();
1032 
1033 	if ((unsigned int)(i - 1) >= MAX_CLIENTS)
1034 		return;
1035 #ifdef GLQUAKE
1036 	// don't draw our own muzzle flash in gl if flashblending
1037 	if (i - 1 == cl.playernum && gl_flashblend.integer)
1038 		return;
1039 #endif
1040 	pl = &cl.frames[parsecountmod].playerstate[i-1];
1041 
1042 	dl = CL_AllocDlight (i);
1043 	VectorCopy (pl->origin,  dl->origin);
1044 	AngleVectors (pl->viewangles, fv, rv, uv);
1045 
1046 	VectorMA (dl->origin, 18, fv, dl->origin);
1047 	dl->radius = 200 + (rand() & 31);
1048 	dl->minlight = 32;
1049 	dl->die = cl.time + 0.1;
1050 	dl->color[0] = 0.2;
1051 	dl->color[1] = 0.1;
1052 	dl->color[2] = 0.05;
1053 	dl->color[3] = 0.7;
1054 }
1055 
CL_Plaque(void)1056 static void CL_Plaque(void)
1057 {
1058 	int	idx;
1059 
1060 	idx = MSG_ReadShort ();
1061 
1062 	if (idx > 0 && idx <= host_string_count)
1063 		SCR_SetPlaqueMessage (Host_GetString(idx - 1));
1064 	else	SCR_SetPlaqueMessage ("");
1065 }
1066 
CL_IndexedPrint(void)1067 static void CL_IndexedPrint(void)
1068 {
1069 	int	idx, i;
1070 
1071 	i = MSG_ReadByte ();
1072 	if (i == PRINT_CHAT)
1073 	{
1074 		S_LocalSound ("misc/talk.wav");
1075 		con_ormask = 256;
1076 	}
1077 
1078 	idx = MSG_ReadShort ();
1079 	if (idx > 0 && idx <= host_string_count)
1080 		Con_Printf ("%s", Host_GetString(idx - 1));
1081 
1082 	con_ormask = 0;
1083 }
1084 
CL_NamePrint(void)1085 static void CL_NamePrint(void)
1086 {
1087 	int idx, i;
1088 
1089 	i = MSG_ReadByte ();
1090 	if (i == PRINT_CHAT)
1091 	{
1092 		S_LocalSound ("misc/talk.wav");
1093 		con_ormask = 256;
1094 	}
1095 
1096 	idx = MSG_ReadByte ();
1097 	if (idx >= 0 && idx < MAX_CLIENTS)
1098 		Con_Printf ("%s", cl.players[idx].name);
1099 
1100 	con_ormask = 0;
1101 }
1102 
CL_ParticleExplosion(void)1103 static void CL_ParticleExplosion(void)
1104 {
1105 	vec3_t org;
1106 	short color, radius, counter;
1107 
1108 	org[0] = MSG_ReadCoord();
1109 	org[1] = MSG_ReadCoord();
1110 	org[2] = MSG_ReadCoord();
1111 	color = MSG_ReadShort();
1112 	radius = MSG_ReadShort();
1113 	counter = MSG_ReadShort();
1114 
1115 	R_ColoredParticleExplosion(org,color,radius,counter);
1116 }
1117 
1118 #if 0	/* for debugging. from fteqw. */
1119 static void CL_DumpPacket (void)
1120 {
1121 	int			i, pos;
1122 	char	*packet = net_message.data;
1123 
1124 	Con_Printf("%s, BEGIN:\n", __thisfunc__);
1125 	pos = 0;
1126 	while (pos < net_message.cursize)
1127 	{
1128 		Con_Printf("%5i ", pos);
1129 		for (i = 0; i < 16; i++)
1130 		{
1131 			if (pos >= net_message.cursize)
1132 				Con_Printf(" X ");
1133 			else	Con_Printf("%2x ", (unsigned char)packet[pos]);
1134 			pos++;
1135 		}
1136 		pos -= 16;
1137 		for (i = 0; i < 16; i++)
1138 		{
1139 			if (pos >= net_message.cursize)
1140 				Con_Printf("X");
1141 			else if (packet[pos] == 0)
1142 				Con_Printf(".");
1143 			else	Con_Printf("%c", (unsigned char)packet[pos]);
1144 			pos++;
1145 		}
1146 		Con_Printf("\n");
1147 	}
1148 
1149 	Con_Printf("%s, --- END ---\n", __thisfunc__);
1150 }
1151 #endif	/* CL_DumpPacket */
1152 
1153 #define SHOWNET(S)						\
1154 do {								\
1155 	if (cl_shownet.integer == 2)				\
1156 		Con_Printf ("%3i:%s\n", msg_readcount-1, (S));	\
1157 } while (0)
1158 
1159 /*
1160 =====================
1161 CL_ParseServerMessage
1162 =====================
1163 */
1164 //static int	received_framecount;
1165 int LastServerMessageSize = 0;
1166 
CL_ParseServerMessage(void)1167 void CL_ParseServerMessage (void)
1168 {
1169 	int		cmd;
1170 	const char	*s;
1171 	int		i, j;
1172 	unsigned int	sc1, sc2;
1173 	byte		test;
1174 	char		temp[100];
1175 	vec3_t		pos;
1176 
1177 	LastServerMessageSize += net_message.cursize;
1178 
1179 //	received_framecount = host_framecount;
1180 	cl.last_servermessage = realtime;
1181 	CL_ClearProjectiles ();
1182 	CL_ClearMissiles ();
1183 	v_targDist = 0;	// This clears out the target field on each netupdate;
1184 			// it won't be drawn unless another update comes...
1185 
1186 // if recording demos, copy the message out
1187 	if (cl_shownet.integer == 1)
1188 		Con_Printf ("%i ",net_message.cursize);
1189 	else if (cl_shownet.integer == 2)
1190 		Con_Printf ("------------------\n");
1191 
1192 	CL_ParseClientdata ();
1193 
1194 // parse the message
1195 	while (1)
1196 	{
1197 		if (msg_badread)
1198 		{
1199 			Host_EndGame ("%s: Bad server message", __thisfunc__);
1200 			break;
1201 		}
1202 
1203 		cmd = MSG_ReadByte ();
1204 		if (cmd == -1)
1205 		{
1206 			msg_readcount++;	// so the EOM showner has the right value
1207 			SHOWNET("END OF MESSAGE");
1208 			break;
1209 		}
1210 		if (cmd < (int)NUM_SVC_STRINGS) {
1211 			SHOWNET(svc_strings[cmd]);
1212 		}
1213 
1214 	// other commands
1215 		switch (cmd)
1216 		{
1217 		default:
1218 		//	CL_DumpPacket ();
1219 			Host_EndGame ("%s: Illegible server message %d", __thisfunc__, cmd);
1220 			break;
1221 
1222 		case svc_nop:
1223 		//	Con_Printf ("svc_nop\n");
1224 			break;
1225 
1226 		case svc_disconnect:
1227 			Host_EndGame ("Server disconnected\n");
1228 			break;
1229 
1230 		case svc_print:
1231 			i = MSG_ReadByte ();
1232 			if (i == PRINT_CHAT)
1233 			{
1234 				S_LocalSound ("misc/talk.wav");
1235 				con_ormask = 256;
1236 			}
1237 			else if (i >= PRINT_SOUND)
1238 			{
1239 				if (talksounds.integer)
1240 				{
1241 					q_snprintf (temp, sizeof(temp), "taunt/taunt%.3d.wav", i - PRINT_SOUND + 1);
1242 					S_LocalSound (temp);
1243 					con_ormask = 256;
1244 				}
1245 				else
1246 				{
1247 					MSG_ReadString();
1248 					break;
1249 				}
1250 			}
1251 			Con_Printf ("%s", MSG_ReadString ());
1252 			con_ormask = 0;
1253 			break;
1254 
1255 		case svc_centerprint:
1256 			SCR_CenterPrint (MSG_ReadString ());
1257 			break;
1258 
1259 		case svc_stufftext:
1260 			s = MSG_ReadString ();
1261 			Con_DPrintf ("stufftext: %s\n", s);
1262 			Cbuf_AddText (s);
1263 			break;
1264 
1265 		case svc_damage:
1266 			V_ParseDamage ();
1267 			break;
1268 
1269 		case svc_serverdata:
1270 			Cbuf_Execute ();		// make sure any stuffed commands are done
1271 			CL_ParseServerData ();
1272 			vid.recalc_refdef = true;	// leave full screen intermission
1273 			break;
1274 
1275 		case svc_setangle:
1276 			for (i = 0; i < 3; i++)
1277 				cl.viewangles[i] = MSG_ReadAngle ();
1278 		//	cl.viewangles[PITCH] = cl.viewangles[ROLL] = 0;
1279 			break;
1280 
1281 		case svc_lightstyle:
1282 			i = MSG_ReadByte ();
1283 			if (i >= MAX_LIGHTSTYLES)
1284 				Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
1285 			q_strlcpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING);
1286 			cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1287 			break;
1288 
1289 		case svc_sound:
1290 			CL_ParseStartSoundPacket();
1291 			break;
1292 
1293 		case svc_sound_update_pos:
1294 		  {	// FIXME: put a field on the entity that lists the channels
1295 			// it should update when it moves- if a certain flag
1296 			// is on the ent, this update_channels field could
1297 			// be set automatically by each sound and stopSound
1298 			// called for this ent?
1299 			int	channel, ent_num;
1300 
1301 			channel = MSG_ReadShort ();
1302 
1303 			ent_num = channel >> 3;
1304 			channel &= 7;
1305 
1306 			if (ent_num > MAX_EDICTS)
1307 				Host_Error ("svc_sound_update_pos: ent = %i", ent_num);
1308 
1309 			for (i = 0; i < 3; i++)
1310 				pos[i] = MSG_ReadCoord ();
1311 
1312 			S_UpdateSoundPos (ent_num, channel, pos);
1313 		  }	break;
1314 
1315 		case svc_stopsound:
1316 			i = MSG_ReadShort();
1317 			S_StopSound(i>>3, i&7);
1318 			break;
1319 
1320 		case svc_updatefrags:
1321 			Sbar_Changed ();
1322 			i = MSG_ReadByte ();
1323 			if (i >= MAX_CLIENTS)
1324 				Host_EndGame ("%s: svc_updatefrags > MAX_CLIENTS", __thisfunc__);
1325 			cl.players[i].frags = MSG_ReadShort ();
1326 			break;
1327 
1328 		case svc_updateping:
1329 			i = MSG_ReadByte ();
1330 			if (i >= MAX_CLIENTS)
1331 				Host_EndGame ("%s: svc_updateping > MAX_CLIENTS", __thisfunc__);
1332 			cl.players[i].ping = MSG_ReadShort ();
1333 			break;
1334 
1335 		case svc_updateentertime:
1336 		// time is sent over as seconds ago
1337 			i = MSG_ReadByte ();
1338 			if (i >= MAX_CLIENTS)
1339 				Host_EndGame ("%s: svc_updateentertime > MAX_CLIENTS", __thisfunc__);
1340 			cl.players[i].entertime = realtime - MSG_ReadFloat ();
1341 			break;
1342 
1343 		case svc_updatepclass:
1344 		// playerclass has changed for this dude
1345 			i = MSG_ReadByte ();
1346 			if (i >= MAX_CLIENTS)
1347 				Host_EndGame ("%s: svc_updatepclass > MAX_CLIENTS", __thisfunc__);
1348 			cl.players[i].playerclass = MSG_ReadByte ();
1349 			cl.players[i].level = cl.players[i].playerclass&31;
1350 			cl.players[i].playerclass = cl.players[i].playerclass>>5;
1351 			break;
1352 
1353 		case svc_updatedminfo:
1354 		// This dude killed someone, update his frags and level
1355 			i = MSG_ReadByte ();
1356 			if (i >= MAX_CLIENTS)
1357 				Host_EndGame ("%s: svc_updatedminfo > MAX_CLIENTS", __thisfunc__);
1358 			cl.players[i].frags = MSG_ReadShort ();
1359 			cl.players[i].playerclass = MSG_ReadByte ();
1360 			cl.players[i].level = cl.players[i].playerclass&31;
1361 			cl.players[i].playerclass = cl.players[i].playerclass>>5;
1362 			break;
1363 
1364 		case svc_updatesiegelosses:
1365 		// This dude killed someone, update his frags and level
1366 			defLosses = MSG_ReadByte ();
1367 			attLosses = MSG_ReadByte ();
1368 			break;
1369 
1370 		case svc_updatesiegeteam:
1371 		// This dude killed someone, update his frags and level
1372 			i = MSG_ReadByte ();
1373 			if (i >= MAX_CLIENTS)
1374 				Host_EndGame ("%s: svc_updatesiegeteam > MAX_CLIENTS", __thisfunc__);
1375 			cl.players[i].siege_team = MSG_ReadByte ();
1376 			break;
1377 
1378 		case svc_updatesiegeinfo:
1379 		// We are on a siege server, set cl_siege
1380 			cl_siege = true;
1381 			cl_timelimit = MSG_ReadByte () * 60;
1382 			cl_fraglimit = MSG_ReadByte ();
1383 			break;
1384 
1385 		case svc_haskey:
1386 			cl_keyholder = MSG_ReadShort() - 1;
1387 			break;
1388 
1389 		case svc_isdoc:
1390 			cl_doc = MSG_ReadShort() - 1;
1391 			break;
1392 
1393 		case svc_nonehaskey:
1394 			cl_keyholder = -1;
1395 			break;
1396 
1397 		case svc_nodoc:
1398 			cl_doc = -1;
1399 			break;
1400 
1401 		case svc_time:
1402 			cl_server_time_offset = ((int)MSG_ReadFloat()) - cl.time;
1403 			break;
1404 
1405 		case svc_spawnbaseline:
1406 			i = MSG_ReadShort ();
1407 			CL_ParseBaseline (&cl_baselines[i]);
1408 			break;
1409 		case svc_spawnstatic:
1410 			CL_ParseStatic ();
1411 			break;
1412 		case svc_temp_entity:
1413 			CL_ParseTEnt ();
1414 			break;
1415 
1416 		case svc_killedmonster:
1417 			cl.stats[STAT_MONSTERS]++;
1418 			break;
1419 
1420 		case svc_foundsecret:
1421 			cl.stats[STAT_SECRETS]++;
1422 			break;
1423 
1424 		case svc_updatestat:
1425 			i = MSG_ReadByte ();
1426 			j = MSG_ReadByte ();
1427 			CL_SetStat (i, j);
1428 			break;
1429 		case svc_updatestatlong:
1430 			i = MSG_ReadByte ();
1431 			j = MSG_ReadLong ();
1432 			CL_SetStat (i, j);
1433 			break;
1434 
1435 		case svc_spawnstaticsound:
1436 			CL_ParseStaticSound ();
1437 			break;
1438 
1439 		case svc_cdtrack:
1440 			cl.cdtrack = MSG_ReadByte ();
1441 			if (q_strcasecmp(bgmtype.string,"cd") != 0)
1442 				CDAudio_Stop ();
1443 			else	CDAudio_Play ((byte)cl.cdtrack, true);
1444 			break;
1445 
1446 		case svc_midi_name:
1447 			q_strlcpy (cl.midi_name, MSG_ReadString(), sizeof(cl.midi_name));
1448 			if (q_strcasecmp(bgmtype.string,"midi") != 0)
1449 				BGM_Stop();
1450 			else	BGM_PlayMIDIorMusic(cl.midi_name);
1451 			break;
1452 
1453 		case svc_intermission:
1454 			/*
1455 			if (cl_siege) {//MG
1456 			*/
1457 				CL_SetupIntermission (MSG_ReadByte());
1458 				vid.recalc_refdef = true;	// go to full screen
1459 				break;
1460 			/*
1461 			} else { // Old Quake way- won't work
1462 				cl.intermission = 1;
1463 				cl.completed_time = realtime;
1464 				vid.recalc_refdef = true;	// go to full screen
1465 				for (i = 0; i < 3; i++)
1466 					cl.simorg[i] = MSG_ReadCoord ();
1467 				for (i = 0; i < 3; i++)
1468 					cl.simangles[i] = MSG_ReadAngle ();
1469 				VectorClear (cl.simvel);
1470 				break;
1471 			}
1472 			*/
1473 		case svc_finale:
1474 			cl.intermission = 2;
1475 			cl.completed_time = realtime;
1476 			vid.recalc_refdef = true;	// go to full screen
1477 			SCR_CenterPrint (MSG_ReadString ());
1478 			break;
1479 
1480 		case svc_sellscreen:
1481 			Cmd_ExecuteString ("help", src_command);
1482 			break;
1483 
1484 		case svc_smallkick:
1485 			cl.punchangle = -2;
1486 			break;
1487 		case svc_bigkick:
1488 			cl.punchangle = -4;
1489 			break;
1490 
1491 		case svc_muzzleflash:
1492 			CL_MuzzleFlash ();
1493 			break;
1494 
1495 		case svc_updateuserinfo:
1496 			CL_UpdateUserinfo ();
1497 			break;
1498 
1499 		case svc_download:
1500 			CL_ParseDownload ();
1501 			break;
1502 
1503 		case svc_playerinfo:
1504 			CL_ParsePlayerinfo ();
1505 			break;
1506 
1507 		case svc_playerskipped:
1508 			CL_SavePlayer ();
1509 			break;
1510 
1511 		case svc_nails:
1512 			CL_ParseProjectiles ();
1513 			break;
1514 
1515 		case svc_packmissile:
1516 			CL_ParsePackMissiles ();
1517 			break;
1518 
1519 		case svc_chokecount:		// some preceding packets were choked
1520 			i = MSG_ReadByte ();
1521 			for (j = 0; j < i; j++)
1522 				cl.frames[ (cls.netchan.incoming_acknowledged-1-j)&UPDATE_MASK ].receivedtime = -2;
1523 			break;
1524 
1525 		case svc_modellist:
1526 			if (cl.protocol >= PROTOCOL_VERSION_EXT) /* from QW */
1527 			{
1528 				CL_ParseModellistChunks ();
1529 				break;
1530 			}
1531 			CL_ParseModellist ();
1532 			break;
1533 
1534 		case svc_soundlist:
1535 			if (cl.protocol >= PROTOCOL_VERSION_EXT) /* from QW */
1536 			{
1537 				CL_ParseSoundlistChunks ();
1538 				break;
1539 			}
1540 			CL_ParseSoundlist ();
1541 			break;
1542 
1543 		case svc_packetentities:
1544 			CL_ParsePacketEntities (false);
1545 			break;
1546 
1547 		case svc_deltapacketentities:
1548 			CL_ParsePacketEntities (true);
1549 			break;
1550 
1551 		case svc_maxspeed :
1552 			movevars.maxspeed = MSG_ReadFloat();
1553 			break;
1554 
1555 		case svc_entgravity :
1556 			movevars.entgravity = MSG_ReadFloat();
1557 			break;
1558 
1559 		case svc_plaque:
1560 			CL_Plaque();
1561 			break;
1562 
1563 		case svc_indexed_print:
1564 			CL_IndexedPrint();
1565 			break;
1566 
1567 		case svc_name_print:
1568 			CL_NamePrint();
1569 			break;
1570 
1571 		case svc_particle_explosion:
1572 			CL_ParticleExplosion();
1573 			break;
1574 
1575 		case svc_set_view_tint:
1576 			i = MSG_ReadByte();
1577 		//	cl.viewent.colorshade = i;
1578 			break;
1579 
1580 		case svc_start_effect:
1581 			CL_ParseEffect();
1582 			break;
1583 
1584 		case svc_end_effect:
1585 			CL_EndEffect();
1586 			break;
1587 
1588 		case svc_set_view_flags:
1589 			cl.viewent.drawflags |= MSG_ReadByte();
1590 			break;
1591 
1592 		case svc_clear_view_flags:
1593 			cl.viewent.drawflags &= ~MSG_ReadByte();
1594 			break;
1595 
1596 		case svc_update_inv:
1597 			sc1 = sc2 = 0;
1598 
1599 			test = MSG_ReadByte();
1600 			if (test & 1)
1601 				sc1 |= ((int)MSG_ReadByte());
1602 			if (test & 2)
1603 				sc1 |= ((int)MSG_ReadByte())<<8;
1604 			if (test & 4)
1605 				sc1 |= ((int)MSG_ReadByte())<<16;
1606 			if (test & 8)
1607 				sc1 |= ((int)MSG_ReadByte())<<24;
1608 			if (test & 16)
1609 				sc2 |= ((int)MSG_ReadByte());
1610 			if (test & 32)
1611 				sc2 |= ((int)MSG_ReadByte())<<8;
1612 			if (test & 64)
1613 				sc2 |= ((int)MSG_ReadByte())<<16;
1614 			if (test & 128)
1615 				sc2 |= ((int)MSG_ReadByte())<<24;
1616 
1617 			if (sc1 & SC1_HEALTH)
1618 				cl.v.health = MSG_ReadShort();
1619 			if (sc1 & SC1_LEVEL)
1620 				cl.v.level = MSG_ReadByte();
1621 			if (sc1 & SC1_INTELLIGENCE)
1622 				cl.v.intelligence = MSG_ReadByte();
1623 			if (sc1 & SC1_WISDOM)
1624 				cl.v.wisdom = MSG_ReadByte();
1625 			if (sc1 & SC1_STRENGTH)
1626 				cl.v.strength = MSG_ReadByte();
1627 			if (sc1 & SC1_DEXTERITY)
1628 				cl.v.dexterity = MSG_ReadByte();
1629 		//	if (sc1 & SC1_WEAPON)
1630 		//		cl.v.weapon = MSG_ReadByte();
1631 			if (sc1 & SC1_TELEPORT_TIME)
1632 			{
1633 		//		Con_Printf("Teleport_time>time, got bit\n");
1634 				cl.v.teleport_time = realtime + 2; // can't airmove for 2s
1635 			}
1636 
1637 			if (sc1 & SC1_BLUEMANA)
1638 				cl.v.bluemana = MSG_ReadByte();
1639 			if (sc1 & SC1_GREENMANA)
1640 				cl.v.greenmana = MSG_ReadByte();
1641 			if (sc1 & SC1_EXPERIENCE)
1642 				cl.v.experience = MSG_ReadLong();
1643 			if (sc1 & SC1_CNT_TORCH)
1644 				cl.v.cnt_torch = MSG_ReadByte();
1645 			if (sc1 & SC1_CNT_H_BOOST)
1646 				cl.v.cnt_h_boost = MSG_ReadByte();
1647 			if (sc1 & SC1_CNT_SH_BOOST)
1648 				cl.v.cnt_sh_boost = MSG_ReadByte();
1649 			if (sc1 & SC1_CNT_MANA_BOOST)
1650 				cl.v.cnt_mana_boost = MSG_ReadByte();
1651 			if (sc1 & SC1_CNT_TELEPORT)
1652 				cl.v.cnt_teleport = MSG_ReadByte();
1653 			if (sc1 & SC1_CNT_TOME)
1654 				cl.v.cnt_tome = MSG_ReadByte();
1655 			if (sc1 & SC1_CNT_SUMMON)
1656 				cl.v.cnt_summon = MSG_ReadByte();
1657 			if (sc1 & SC1_CNT_INVISIBILITY)
1658 				cl.v.cnt_invisibility = MSG_ReadByte();
1659 			if (sc1 & SC1_CNT_GLYPH)
1660 				cl.v.cnt_glyph = MSG_ReadByte();
1661 			if (sc1 & SC1_CNT_HASTE)
1662 				cl.v.cnt_haste = MSG_ReadByte();
1663 			if (sc1 & SC1_CNT_BLAST)
1664 				cl.v.cnt_blast = MSG_ReadByte();
1665 			if (sc1 & SC1_CNT_POLYMORPH)
1666 				cl.v.cnt_polymorph = MSG_ReadByte();
1667 			if (sc1 & SC1_CNT_FLIGHT)
1668 				cl.v.cnt_flight = MSG_ReadByte();
1669 			if (sc1 & SC1_CNT_CUBEOFFORCE)
1670 				cl.v.cnt_cubeofforce = MSG_ReadByte();
1671 			if (sc1 & SC1_CNT_INVINCIBILITY)
1672 				cl.v.cnt_invincibility = MSG_ReadByte();
1673 			if (sc1 & SC1_ARTIFACT_ACTIVE)
1674 				cl.v.artifact_active = MSG_ReadByte();
1675 			if (sc1 & SC1_ARTIFACT_LOW)
1676 				cl.v.artifact_low = MSG_ReadByte();
1677 			if (sc1 & SC1_MOVETYPE)
1678 				cl.v.movetype = MSG_ReadByte();
1679 			if (sc1 & SC1_CAMERAMODE)
1680 				cl.v.cameramode = MSG_ReadByte();
1681 			if (sc1 & SC1_HASTED)
1682 				cl.v.hasted = MSG_ReadFloat();
1683 			if (sc1 & SC1_INVENTORY)
1684 				cl.v.inventory = MSG_ReadByte();
1685 			if (sc1 & SC1_RINGS_ACTIVE)
1686 				cl.v.rings_active = MSG_ReadByte();
1687 
1688 			if (sc2 & SC2_RINGS_LOW)
1689 				cl.v.rings_low = MSG_ReadByte();
1690 			if (sc2 & SC2_AMULET)
1691 				cl.v.armor_amulet = MSG_ReadByte();
1692 			if (sc2 & SC2_BRACER)
1693 				cl.v.armor_bracer = MSG_ReadByte();
1694 			if (sc2 & SC2_BREASTPLATE)
1695 				cl.v.armor_breastplate = MSG_ReadByte();
1696 			if (sc2 & SC2_HELMET)
1697 				cl.v.armor_helmet = MSG_ReadByte();
1698 			if (sc2 & SC2_FLIGHT_T)
1699 				cl.v.ring_flight = MSG_ReadByte();
1700 			if (sc2 & SC2_WATER_T)
1701 				cl.v.ring_water = MSG_ReadByte();
1702 			if (sc2 & SC2_TURNING_T)
1703 				cl.v.ring_turning = MSG_ReadByte();
1704 			if (sc2 & SC2_REGEN_T)
1705 				cl.v.ring_regeneration = MSG_ReadByte();
1706 		//	if (sc2 & SC2_HASTE_T)
1707 		//		cl.v.haste_time = MSG_ReadFloat();
1708 		//	if (sc2 & SC2_TOME_T)
1709 		//		cl.v.tome_time = MSG_ReadFloat();
1710 			if (sc2 & SC2_PUZZLE1)
1711 				q_snprintf(cl.puzzle_pieces[0], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString());
1712 			if (sc2 & SC2_PUZZLE2)
1713 				q_snprintf(cl.puzzle_pieces[1], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString());
1714 			if (sc2 & SC2_PUZZLE3)
1715 				q_snprintf(cl.puzzle_pieces[2], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString());
1716 			if (sc2 & SC2_PUZZLE4)
1717 				q_snprintf(cl.puzzle_pieces[3], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString());
1718 			if (sc2 & SC2_PUZZLE5)
1719 				q_snprintf(cl.puzzle_pieces[4], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString());
1720 			if (sc2 & SC2_PUZZLE6)
1721 				q_snprintf(cl.puzzle_pieces[5], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString());
1722 			if (sc2 & SC2_PUZZLE7)
1723 				q_snprintf(cl.puzzle_pieces[6], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString());
1724 			if (sc2 & SC2_PUZZLE8)
1725 				q_snprintf(cl.puzzle_pieces[7], sizeof(cl.puzzle_pieces[0]), "%.9s", MSG_ReadString());
1726 			if (sc2 & SC2_MAXHEALTH)
1727 				cl.v.max_health = MSG_ReadShort();
1728 			if (sc2 & SC2_MAXMANA)
1729 				cl.v.max_mana = MSG_ReadByte();
1730 			if (sc2 & SC2_FLAGS)
1731 				cl.v.flags = MSG_ReadFloat();
1732 
1733 			if ((sc1 & SC1_STAT_BAR) || (sc2 & SC2_STAT_BAR))
1734 				Sbar_Changed();
1735 
1736 			if ((sc1 & SC1_INV) || (sc2 & SC2_INV))
1737 				SB_InvChanged();
1738 			break;
1739 
1740 		case svc_particle:
1741 			R_ParseParticleEffect ();
1742 			break;
1743 		case svc_particle2:
1744 			R_ParseParticleEffect2 ();
1745 			break;
1746 		case svc_particle3:
1747 			R_ParseParticleEffect3 ();
1748 			break;
1749 		case svc_particle4:
1750 			R_ParseParticleEffect4 ();
1751 			break;
1752 		case svc_turn_effect:
1753 			CL_TurnEffect ();
1754 			break;
1755 		case svc_update_effect:
1756 			CL_ReviseEffect();
1757 			break;
1758 
1759 		case svc_multieffect:
1760 			CL_ParseMultiEffect();
1761 			break;
1762 
1763 		case svc_raineffect:
1764 			R_ParseRainEffect();
1765 			break;
1766 
1767 		case svc_targetupdate:
1768 			V_ParseTarget();
1769 			break;
1770 
1771 		case svc_update_piv:
1772 			cl.PIV = MSG_ReadLong();
1773 			break;
1774 
1775 		case svc_player_sound:
1776 			test = MSG_ReadByte();
1777 			pos[0] = MSG_ReadCoord();
1778 			pos[1] = MSG_ReadCoord();
1779 			pos[2] = MSG_ReadCoord();
1780 			i = MSG_ReadShort ();
1781 			S_StartSound(test, 1, cl.sound_precache[i], pos, 1.0, 1.0);
1782 			break;
1783 		}
1784 	}
1785 
1786 	CL_SetSolidEntities ();
1787 }
1788 
1789