1 /*
2 	cl_parse.c
3 
4 	parse a message received from the server
5 
6 	Copyright (C) 1996-1997  Id Software, Inc.
7 
8 	This program is free software; you can redistribute it and/or
9 	modify it under the terms of the GNU General Public License
10 	as published by the Free Software Foundation; either version 2
11 	of the License, or (at your option) any later version.
12 
13 	This program is distributed in the hope that it will be useful,
14 	but 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
20 	along with this program; if not, write to:
21 
22 		Free Software Foundation, Inc.
23 		59 Temple Place - Suite 330
24 		Boston, MA  02111-1307, USA
25 
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 
31 #ifdef HAVE_STRING_H
32 # include <string.h>
33 #endif
34 #ifdef HAVE_STRINGS_H
35 # include <strings.h>
36 #endif
37 
38 #include "QF/cbuf.h"
39 #include "QF/cdaudio.h"
40 #include "QF/cmd.h"
41 #include "QF/console.h"
42 #include "QF/cvar.h"
43 #include "QF/dstring.h"
44 #include "QF/idparse.h"
45 #include "QF/input.h"
46 #include "QF/msg.h"
47 #include "QF/qfplist.h"
48 #include "QF/sys.h"
49 #include "QF/screen.h"
50 #include "QF/skin.h"
51 #include "QF/sound.h" // FIXME: DEFAULT_SOUND_PACKET_*
52 #include "QF/va.h"
53 
54 #include "QF/plugin/vid_render.h"
55 
56 #include "client.h"
57 #include "compat.h"
58 #include "host.h"
59 #include "sbar.h"
60 #include "server.h"
61 #include "game.h"
62 
63 const char *svc_strings[] = {
64 	"svc_bad",
65 	"svc_nop",
66 	"svc_disconnect",
67 	"svc_updatestat",
68 	"svc_version",				// [long] server version
69 	"svc_setview",				// [short] entity number
70 	"svc_sound",				// <see code>
71 	"svc_time",					// [float] server time
72 	"svc_print",				// [string] null terminated string
73 	"svc_stufftext",			// [string] stuffed into client's console
74 								// buffer the string should be \n terminated
75 	"svc_setangle",				// [vec3] set view angle to this absolute value
76 
77 	"svc_serverinfo",			// [long] version
78 								// [string] signon string
79 								// [string]..[0]model cache
80 								// [string]...[0]sounds cache
81 								// [string]..[0]item cache
82 	"svc_lightstyle",			// [byte] [string]
83 	"svc_updatename",			// [byte] [string]
84 	"svc_updatefrags",			// [byte] [short]
85 	"svc_clientdata",			// <shortbits + data>
86 	"svc_stopsound",			// <see code>
87 	"svc_updatecolors",			// [byte] [byte]
88 	"svc_particle",				// [vec3] <variable>
89 	"svc_damage",				// [byte] impact [byte] blood [vec3] from
90 
91 	"svc_spawnstatic",
92 	"OBSOLETE svc_spawnbinary",
93 	"svc_spawnbaseline",
94 
95 	"svc_temp_entity",			// <variable>
96 	"svc_setpause",
97 	"svc_signonnum",
98 	"svc_centerprint",
99 	"svc_killedmonster",
100 	"svc_foundsecret",
101 	"svc_spawnstaticsound",
102 	"svc_intermission",
103 	"svc_finale",				// [string] text
104 	"svc_cdtrack",				// [byte] track [byte] looptrack
105 	"svc_sellscreen",
106 	"svc_cutscene",
107 	// end of iD svc
108 	// FIXME switchable extensions?
109 	// protocol 666
110 	"",
111 	"",
112 	"svc_skybox",
113 	"",
114 	"",
115 	"svc_bf",
116 	"svc_fog",
117 	"svc_spawnbaseline2",
118 	"svc_spawnstatic2",
119 	"svc_spawnstaticsound2",
120 };
121 
122 dstring_t  *centerprint;
123 
124 static void
CL_LoadSky(void)125 CL_LoadSky (void)
126 {
127 	plitem_t   *item;
128 	const char *name = 0;
129 
130 	if (!cl.worldspawn) {
131 		r_funcs->R_LoadSkys (0);
132 		return;
133 	}
134 	if ((item = PL_ObjectForKey (cl.worldspawn, "sky")) // Q2/DarkPlaces
135 		|| (item = PL_ObjectForKey (cl.worldspawn, "skyname")) // old QF
136 		|| (item = PL_ObjectForKey (cl.worldspawn, "qlsky"))) /* QuakeLives */ {
137 		name = PL_String (item);
138 	}
139 	r_funcs->R_LoadSkys (name);
140 }
141 
142 /*
143 	CL_EntityNum
144 
145 	This error checks and tracks the total number of entities
146 */
147 static entity_state_t *
CL_EntityNum(int num)148 CL_EntityNum (int num)
149 {
150 	if (num < 0 || num >= MAX_EDICTS)
151 		Host_Error ("CL_EntityNum: %i is an invalid number", num);
152 	if (num >= cl.num_entities)
153 		cl.num_entities = num + 1;
154 
155 	return &nq_entstates.baseline[num];
156 }
157 
158 static void
CL_ParseStartSoundPacket(void)159 CL_ParseStartSoundPacket (void)
160 {
161 	float       attenuation;
162 	int         channel, ent, field_mask, sound_num, volume;
163 	vec3_t      pos;
164 
165 	field_mask = MSG_ReadByte (net_message);
166 
167 	if (field_mask & SND_VOLUME)
168 		volume = MSG_ReadByte (net_message);
169 	else
170 		volume = DEFAULT_SOUND_PACKET_VOLUME;
171 
172 	if (field_mask & SND_ATTENUATION)
173 		attenuation = MSG_ReadByte (net_message) / 64.0;
174 	else
175 		attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
176 
177 	if (field_mask & SND_LARGEENTITY) {
178 		ent = MSG_ReadShort (net_message);
179 		channel = MSG_ReadByte (net_message);
180 	} else {
181 		channel = MSG_ReadShort (net_message);
182 		ent = channel >> 3;
183 		channel &= 7;
184 	}
185 
186 	if (field_mask & SND_LARGESOUND)
187 		sound_num = MSG_ReadShort (net_message);
188 	else
189 		sound_num = MSG_ReadByte (net_message);
190 
191 	if (sound_num >= MAX_SOUNDS)
192 		Host_Error ("CL_ParseStartSoundPacket: %i > MAX_SOUNDS", sound_num);
193 	if (ent > MAX_EDICTS)
194 		Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
195 
196 	MSG_ReadCoordV (net_message, pos);
197 
198 	S_StartSound (ent, channel, cl.sound_precache[sound_num], pos,
199 				  volume / 255.0, attenuation);
200 }
201 
202 /*
203 	CL_KeepaliveMessage
204 
205 	When the client is taking a long time to load stuff, send keepalive
206 	messages so the server doesn't disconnect.
207 */
208 static void
CL_KeepaliveMessage(void)209 CL_KeepaliveMessage (void)
210 {
211 	byte        olddata[8192];
212 	float       time;
213 	static float lastmsg;
214 	int         ret;
215 	sizebuf_t   old;
216 
217 	if (sv.active)
218 		return;							// no need if server is local
219 	if (cls.demoplayback)
220 		return;
221 
222 	// read messages from server, should just be nops
223 	old = *net_message->message;
224 	memcpy (olddata, net_message->message->data,
225 			net_message->message->cursize);
226 
227 	do {
228 		ret = CL_GetMessage ();
229 		switch (ret) {
230 		default:
231 			Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
232 		case 0:
233 			break;						// nothing waiting
234 		case 1:
235 			Host_Error ("CL_KeepaliveMessage: received a message");
236 			break;
237 		case 2:
238 			if (MSG_ReadByte (net_message) != svc_nop)
239 				Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
240 			break;
241 		}
242 	} while (ret);
243 
244 	*net_message->message = old;
245 	memcpy (net_message->message->data, olddata,
246 			net_message->message->cursize);
247 
248 	// check time
249 	time = Sys_DoubleTime ();
250 	if (time - lastmsg < 5)
251 		return;
252 	lastmsg = time;
253 
254 	// write out a nop
255 	Sys_Printf ("--> client to server keepalive\n");
256 
257 	MSG_WriteByte (&cls.message, clc_nop);
258 	NET_SendMessage (cls.netcon, &cls.message);
259 	SZ_Clear (&cls.message);
260 }
261 
262 static void
map_cfg(const char * mapname,int all)263 map_cfg (const char *mapname, int all)
264 {
265 	char       *name = malloc (strlen (mapname) + 4 + 1);
266 	cbuf_t     *cbuf = Cbuf_New (&id_interp);
267 	QFile      *f;
268 
269 	QFS_StripExtension (mapname, name);
270 	strcat (name, ".cfg");
271 	QFS_FOpenFile (name, &f);
272 	if (f) {
273 		Qclose (f);
274 		Cmd_Exec_File (cbuf, name, 1);
275 	} else {
276 		Cmd_Exec_File (cbuf, "maps_default.cfg", 1);
277 	}
278 	if (all) {
279 		Cbuf_Execute_Stack (cbuf);
280 	} else {
281 		Cbuf_Execute_Sets (cbuf);
282 	}
283 	free (name);
284 	Cbuf_Delete (cbuf);
285 }
286 
287 static plitem_t *
map_ent(const char * mapname)288 map_ent (const char *mapname)
289 {
290 	static progs_t edpr;
291 	char       *name = malloc (strlen (mapname) + 4 + 1);
292 	char       *buf;
293 	plitem_t   *edicts = 0;
294 
295 	QFS_StripExtension (mapname, name);
296 	strcat (name, ".ent");
297 	if ((buf = (char *) QFS_LoadFile (name, 0))) {
298 		edicts = ED_Parse (&edpr, buf);
299 		free (buf);
300 	} else {
301 		edicts = ED_Parse (&edpr, cl.model_precache[1]->entities);
302 	}
303 	free (name);
304 	return edicts;
305 }
306 
307 static void
CL_NewMap(const char * mapname)308 CL_NewMap (const char *mapname)
309 {
310 	r_funcs->R_NewMap (cl.worldmodel, cl.model_precache, cl.nummodels);
311 	Con_NewMap ();
312 	Hunk_Check ();								// make sure nothing is hurt
313 	Sbar_CenterPrint (0);
314 
315 	if (cl.model_precache[1] && cl.model_precache[1]->entities) {
316 		cl.edicts = map_ent (mapname);
317 		if (cl.edicts) {
318 			cl.worldspawn = PL_ObjectAtIndex (cl.edicts, 0);
319 			CL_LoadSky ();
320 			if (r_funcs->Fog_ParseWorldspawn)
321 				r_funcs->Fog_ParseWorldspawn (cl.worldspawn);
322 		}
323 	}
324 
325 	map_cfg (mapname, 1);
326 }
327 
328 static void
CL_ParseServerInfo(void)329 CL_ParseServerInfo (void)
330 {
331 	char        model_precache[MAX_MODELS][MAX_QPATH];
332 	char        sound_precache[MAX_SOUNDS][MAX_QPATH];
333 	const char *str;
334 	int         i;
335 
336 	Sys_MaskPrintf (SYS_DEV, "Serverinfo packet received.\n");
337 
338 	S_BlockSound ();
339 	S_StopAllSounds ();
340 
341 	// wipe the client_state_t struct
342 	CL_ClearState ();
343 
344 	// parse protocol version number
345 	i = MSG_ReadLong (net_message);
346 	if (i != PROTOCOL_NETQUAKE && i!= PROTOCOL_FITZQUAKE) {
347 		Host_Error ("Server returned version %i, not %i or %i\n", i,
348 					PROTOCOL_NETQUAKE, PROTOCOL_FITZQUAKE);
349 		goto done;
350 	}
351 	cl.protocol = i;
352 	if (cl.protocol == PROTOCOL_FITZQUAKE)
353 		write_angles = MSG_WriteAngle16V;
354 	else
355 		write_angles = MSG_WriteAngleV;
356 	// parse maxclients
357 	cl.maxclients = MSG_ReadByte (net_message);
358 	if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD) {
359 		Sys_Printf ("Bad maxclients (%u) from server\n", cl.maxclients);
360 		goto done;
361 	}
362 	cl.scores = Hunk_AllocName (cl.maxclients * sizeof (*cl.scores), "scores");
363 	for (i = 0; i < cl.maxclients; i++) {
364 		cl.scores[i].info = Info_ParseString ("name\\", 0, 0);
365 		cl.scores[i].name = Info_Key (cl.scores[i].info, "name");
366 		cl.scores[i].topcolor = 0;
367 		cl.scores[i].bottomcolor = 0;
368 	}
369 
370 	// parse gametype
371 	cl.gametype = MSG_ReadByte (net_message);
372 
373 	// parse signon message
374 	str = MSG_ReadString (net_message);
375 	strncpy (cl.levelname, str, sizeof (cl.levelname) - 1);
376 
377 	// separate the printfs so the server message can have a color
378 	Sys_Printf ("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36"
379 				"\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n"
380 				"\n");
381 	Sys_Printf ("%c%s\n", 2, str);
382 
383 	// first we go through and touch all of the precache data that still
384 	// happens to be in the cache, so precaching something else doesn't
385 	// needlessly purge it
386 
387 	// precache models
388 	memset (cl.model_precache, 0, sizeof (cl.model_precache));
389 	for (cl.nummodels = 1;; cl.nummodels++) {
390 		str = MSG_ReadString (net_message);
391 		if (!str[0])
392 			break;
393 		if (cl.nummodels >= MAX_MODELS) {
394 			Sys_Printf ("Server sent too many model precaches\n");
395 			goto done;
396 		}
397 		strcpy (model_precache[cl.nummodels], str);
398 		Mod_TouchModel (str);
399 	}
400 
401 	// precache sounds
402 	memset (cl.sound_precache, 0, sizeof (cl.sound_precache));
403 	for (cl.numsounds = 1;; cl.numsounds++) {
404 		str = MSG_ReadString (net_message);
405 		if (!str[0])
406 			break;
407 		if (cl.numsounds >= MAX_SOUNDS) {
408 			Sys_Printf ("Server sent too many sound precaches\n");
409 			goto done;
410 		}
411 		strcpy (sound_precache[cl.numsounds], str);
412 	}
413 
414 	// now we try to load everything else until a cache allocation fails
415 	if (model_precache[1])
416 		map_cfg (model_precache[1], 0);
417 
418 	for (i = 1; i < cl.nummodels; i++) {
419 		cl.model_precache[i] = Mod_ForName (model_precache[i], false);
420 		if (cl.model_precache[i] == NULL) {
421 			Sys_Printf ("Model %s not found\n", model_precache[i]);
422 			goto done;
423 		}
424 		CL_KeepaliveMessage ();
425 	}
426 
427 	for (i = 1; i < cl.numsounds; i++) {
428 		cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
429 		CL_KeepaliveMessage ();
430 	}
431 
432 	// local state
433 	cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
434 	if (!centerprint)
435 		centerprint = dstring_newstr ();
436 	else
437 		dstring_clearstr (centerprint);
438 	CL_NewMap (model_precache[1]);
439 
440 	Hunk_Check ();						// make sure nothing is hurt
441 
442 	noclip_anglehack = false;			// noclip is turned off at start
443 	r_data->gravity = 800.0;			// Set up gravity for renderer effects
444 done:
445 	S_UnblockSound ();
446 }
447 
448 int         bitcounts[16];
449 
450 /*
451 	CL_ParseUpdate
452 
453 	Parse an entity update message from the server
454 	If an entities model or origin changes from frame to frame, it must be
455 	relinked.  Other attributes can change without relinking.
456 */
457 static void
CL_ParseUpdate(int bits)458 CL_ParseUpdate (int bits)
459 {
460 	entity_state_t *baseline;
461 	entity_state_t *state;
462 	int         modnum, num, i;
463 	qboolean    forcelink;
464 
465 	if (cls.signon == so_begin) {
466 		// first update is the final signon stage
467 		cls.signon = so_active;
468 		CL_SignonReply ();
469 	}
470 
471 	if (bits & U_MOREBITS) {
472 		i = MSG_ReadByte (net_message);
473 		bits |= (i << 8);
474 	}
475 
476 	if (cl.protocol == PROTOCOL_FITZQUAKE) {
477 		if (bits & U_EXTEND1)
478 			bits |= MSG_ReadByte(net_message) << 16;
479 		if (bits & U_EXTEND2)
480 			bits |= MSG_ReadByte(net_message) << 24;
481 	}
482 
483 	if (bits & U_LONGENTITY)
484 		num = MSG_ReadShort (net_message);
485 	else
486 		num = MSG_ReadByte (net_message);
487 
488 	baseline = CL_EntityNum (num);
489 	state = &nq_entstates.frame[0 + cl.mindex][num];
490 
491 	for (i = 0; i < 16; i++)
492 		if (bits & (1 << i))
493 			bitcounts[i]++;
494 
495 	if (cl_msgtime[num] != cl.mtime[1])
496 		forcelink = true;				// no previous frame to lerp from
497 	else
498 		forcelink = false;
499 
500 	cl_msgtime[num] = cl.mtime[0];
501 
502 	if (bits & U_MODEL) {
503 		modnum = MSG_ReadByte (net_message);
504 		if (modnum >= MAX_MODELS)
505 			Host_Error ("CL_ParseModel: bad modnum");
506 	} else
507 		modnum = baseline->modelindex;
508 
509 	if (bits & U_FRAME)
510 		state->frame = MSG_ReadByte (net_message);
511 	else
512 		state->frame = baseline->frame;
513 
514 	if (bits & U_COLORMAP)
515 		state->colormap = MSG_ReadByte (net_message);
516 	else
517 		state->colormap = baseline->colormap;
518 	if (state->colormap > cl.maxclients)
519 		Sys_Error ("colormap > cl.maxclients");
520 
521 	if (bits & U_SKIN)
522 		state->skinnum = MSG_ReadByte (net_message);
523 	else
524 		state->skinnum = baseline->skinnum;
525 
526 	if (bits & U_EFFECTS)
527 		state->effects = MSG_ReadByte (net_message);
528 	else
529 		state->effects = baseline->effects;
530 
531 	if (bits & U_ORIGIN1)
532 		state->origin[0] = MSG_ReadCoord (net_message);
533 	else
534 		state->origin[0] = baseline->origin[0];
535 	if (bits & U_ANGLE1)
536 		state->angles[0] = MSG_ReadAngle (net_message);
537 	else
538 		state->angles[0] = baseline->angles[0];
539 
540 	if (bits & U_ORIGIN2)
541 		state->origin[1] = MSG_ReadCoord (net_message);
542 	else
543 		state->origin[1] = baseline->origin[1];
544 	if (bits & U_ANGLE2)
545 		state->angles[1] = MSG_ReadAngle (net_message);
546 	else
547 		state->angles[1] = baseline->angles[1];
548 
549 	if (bits & U_ORIGIN3)
550 		state->origin[2] = MSG_ReadCoord (net_message);
551 	else
552 		state->origin[2] = baseline->origin[2];
553 	if (bits & U_ANGLE3)
554 		state->angles[2] = MSG_ReadAngle (net_message);
555 	else
556 		state->angles[2] = baseline->angles[2];
557 
558 //	if (bits & U_STEP)	//FIXME lerping (see fitzquake)
559 //		forcelink = true;
560 
561 	if (cl.protocol == PROTOCOL_FITZQUAKE) {
562 		if (bits & U_ALPHA)
563 			state->alpha = MSG_ReadByte(net_message);
564 		else
565 			state->alpha = baseline->alpha;
566 		if (bits & U_FRAME2)
567 			state->frame |= MSG_ReadByte(net_message) << 8;
568 		if (bits & U_MODEL2)
569 			modnum |= MSG_ReadByte(net_message) << 8;
570 		if (bits & U_LERPFINISH) {
571 			MSG_ReadByte (net_message); //FIXME ignored for now. see fitzquake
572 		}
573 		state->scale = 16;
574 		state->glow_size = 0;
575 		state->glow_color = 254;
576 		state->colormod = 255;
577 	} else {
578 		baseline->alpha = 255;
579 		state->scale = 16;
580 		state->glow_size = 0;
581 		state->glow_color = 254;
582 		state->colormod = 255;
583 	}
584 
585 	state->modelindex = modnum;
586 
587 	if (forcelink) {					// didn't have an update last message
588 		//VectorCopy (state->msg_origins[0], state->msg_origins[1]);
589 		//VectorCopy (state->msg_origins[0], ent->origin);
590 		//VectorCopy (state->msg_angles[0], state->msg_angles[1]);
591 		//CL_TransformEntity (ent, state->msg_angles[0], true);
592 		//state->forcelink = true;
593 		cl_forcelink[num] = true;
594 	}
595 }
596 
597 static void
CL_ParseBaseline(entity_state_t * baseline,int version)598 CL_ParseBaseline (entity_state_t *baseline, int version)
599 {
600 	int         bits = 0;
601 
602 	if (version == 2)
603 		bits = MSG_ReadByte (net_message);
604 
605 	if (bits & B_LARGEMODEL)
606 		baseline->modelindex = MSG_ReadShort (net_message);
607 	else
608 		baseline->modelindex = MSG_ReadByte (net_message);
609 
610 	if (bits & B_LARGEFRAME)
611 		baseline->frame = MSG_ReadShort (net_message);
612 	else
613 		baseline->frame = MSG_ReadByte (net_message);
614 
615 	baseline->colormap = MSG_ReadByte (net_message);
616 	baseline->skinnum = MSG_ReadByte (net_message);
617 
618 	MSG_ReadCoordAngleV (net_message, baseline->origin, baseline->angles);
619 
620 	if (bits & B_ALPHA)
621 		baseline->alpha = MSG_ReadByte (net_message);
622 	else
623 		baseline->alpha = 255;//FIXME alpha
624 	baseline->scale = 16;
625 	baseline->glow_size = 0;
626 	baseline->glow_color = 254;
627 	baseline->colormod = 255;
628 }
629 
630 /*
631 	CL_ParseClientdata
632 
633 	Server information pertaining to only this client
634 */
635 static void
CL_ParseClientdata(void)636 CL_ParseClientdata (void)
637 {
638 	int         i, j;
639 	int         bits;
640 
641 	bits = MSG_ReadShort (net_message);
642 	if (bits & SU_EXTEND1)
643 		bits |= MSG_ReadByte (net_message) << 16;
644 	if (bits & SU_EXTEND2)
645 		bits |= MSG_ReadByte (net_message) << 24;
646 
647 	if (bits & SU_VIEWHEIGHT)
648 		cl.viewheight = ((signed char) MSG_ReadByte (net_message));
649 	else
650 		cl.viewheight = DEFAULT_VIEWHEIGHT;
651 
652 	if (bits & SU_IDEALPITCH)
653 		cl.idealpitch = ((signed char) MSG_ReadByte (net_message));
654 	else
655 		cl.idealpitch = 0;
656 
657 	VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
658 	for (i = 0; i < 3; i++) {
659 		if (bits & (SU_PUNCH1 << i))
660 			cl.punchangle[i] = ((signed char) MSG_ReadByte (net_message));
661 		else
662 			cl.punchangle[i] = 0;
663 		if (bits & (SU_VELOCITY1 << i))
664 			cl.mvelocity[0][i] = ((signed char) MSG_ReadByte (net_message))
665 				* 16;
666 		else
667 			cl.mvelocity[0][i] = 0;
668 	}
669 
670 	//FIXME
671 	//if (!VectorCompare (v_punchangles[0], cl.punchangle[0])) {
672 	//	VectorCopy (v_punchangles[0], v_punchangles[1]);
673 	//	VectorCopy (cl.punchangle, v_punchangles[0]);
674 	//}
675 
676 	// [always sent]    if (bits & SU_ITEMS)
677 	i = MSG_ReadLong (net_message);
678 
679 	if (cl.stats[STAT_ITEMS] != i) {				// set flash times
680 		Sbar_Changed ();
681 		for (j = 0; j < 32; j++)
682 			if ((i & (1 << j)) && !(cl.stats[STAT_ITEMS] & (1 << j)))
683 				cl.item_gettime[j] = cl.time;
684 		cl.stats[STAT_ITEMS] = i;
685 	}
686 
687 	cl.onground = (bits & SU_ONGROUND) ? 0 : -1;
688 	cl.inwater = (bits & SU_INWATER) != 0;
689 
690 	if (bits & SU_WEAPONFRAME)
691 		cl.stats[STAT_WEAPONFRAME] = MSG_ReadByte (net_message);
692 	else
693 		cl.stats[STAT_WEAPONFRAME] = 0;
694 
695 	if (bits & SU_ARMOR)
696 		i = MSG_ReadByte (net_message);
697 	else
698 		i = 0;
699 	if (cl.stats[STAT_ARMOR] != i) {
700 		cl.stats[STAT_ARMOR] = i;
701 		Sbar_Changed ();
702 	}
703 
704 	if (bits & SU_WEAPON)
705 		i = MSG_ReadByte (net_message);
706 	else
707 		i = 0;
708 	if (cl.stats[STAT_WEAPON] != i) {
709 		cl.stats[STAT_WEAPON] = i;
710 		Sbar_Changed ();
711 	}
712 
713 	i = (short) MSG_ReadShort (net_message);
714 	if (cl.stats[STAT_HEALTH] != i) {
715 		cl.stats[STAT_HEALTH] = i;
716 		Sbar_Changed ();
717 	}
718 
719 	i = MSG_ReadByte (net_message);
720 	if (cl.stats[STAT_AMMO] != i) {
721 		cl.stats[STAT_AMMO] = i;
722 		Sbar_Changed ();
723 	}
724 
725 	for (i = 0; i < 4; i++) {
726 		j = MSG_ReadByte (net_message);
727 		if (cl.stats[STAT_SHELLS + i] != j) {
728 			cl.stats[STAT_SHELLS + i] = j;
729 			Sbar_Changed ();
730 		}
731 	}
732 
733 	i = MSG_ReadByte (net_message);
734 
735 	if (standard_quake) {
736 		if (cl.stats[STAT_ACTIVEWEAPON] != i) {
737 			cl.stats[STAT_ACTIVEWEAPON] = i;
738 			Sbar_Changed ();
739 		}
740 	} else {
741 		// hipnotic/rogue weapon "bit field" (stupid idea)
742 		if (cl.stats[STAT_ACTIVEWEAPON] != (1 << i)) {
743 			cl.stats[STAT_ACTIVEWEAPON] = (1 << i);
744 			Sbar_Changed ();
745 		}
746 	}
747 
748 	if (bits & SU_WEAPON2)
749 		cl.stats[STAT_WEAPON] |= MSG_ReadByte (net_message) << 8;
750 	if (bits & SU_ARMOR2)
751 		cl.stats[STAT_ARMOR] |= MSG_ReadByte (net_message) << 8;
752 	if (bits & SU_AMMO2)
753 		cl.stats[STAT_AMMO] |= MSG_ReadByte (net_message) << 8;
754 	if (bits & SU_SHELLS2)
755 		cl.stats[STAT_SHELLS] |= MSG_ReadByte (net_message) << 8;
756 	if (bits & SU_NAILS2)
757 		cl.stats[STAT_NAILS] |= MSG_ReadByte (net_message) << 8;
758 	if (bits & SU_ROCKETS2)
759 		cl.stats[STAT_ROCKETS] |= MSG_ReadByte (net_message) << 8;
760 	if (bits & SU_CELLS2)
761 		cl.stats[STAT_CELLS] |= MSG_ReadByte (net_message) << 8;
762 	if (bits & SU_WEAPONFRAME2)
763 		cl.stats[STAT_WEAPONFRAME] |= MSG_ReadByte (net_message) << 8;
764 	if (bits & SU_WEAPONALPHA) {
765 		byte alpha = MSG_ReadByte (net_message);
766 		cl.viewent.colormod[3] = ENTALPHA_DECODE (alpha);
767 	} else {
768 		cl.viewent.colormod[3] = 1.0;
769 	}
770 }
771 
772 static void
CL_ParseStatic(int version)773 CL_ParseStatic (int version)
774 {
775 	entity_state_t baseline;
776 	entity_t   *ent;
777 
778 	ent = r_funcs->R_AllocEntity ();
779 	CL_Init_Entity (ent);
780 
781 	CL_ParseBaseline (&baseline, version);
782 
783 	// copy it to the current state
784 	//FIXME alpha & lerp
785 	ent->model = cl.model_precache[baseline.modelindex];
786 	ent->frame = baseline.frame;
787 	ent->skin = 0;
788 	ent->skinnum = baseline.skinnum;
789 	VectorCopy (ent_colormod[baseline.colormod], ent->colormod);
790 	ent->colormod[3] = ENTALPHA_DECODE (baseline.alpha);
791 	ent->scale = baseline.scale / 16.0;
792 	VectorCopy (baseline.origin, ent->origin);
793 	CL_TransformEntity (ent, baseline.angles, true);
794 
795 	r_funcs->R_AddEfrags (ent);
796 }
797 
798 static void
CL_ParseStaticSound(int version)799 CL_ParseStaticSound (int version)
800 {
801 	int         sound_num, vol, atten;
802 	vec3_t      org;
803 
804 	MSG_ReadCoordV (net_message, org);
805 	if (version == 2)
806 		sound_num = MSG_ReadShort (net_message);
807 	else
808 		sound_num = MSG_ReadByte (net_message);
809 	vol = MSG_ReadByte (net_message);
810 	atten = MSG_ReadByte (net_message);
811 
812 	S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
813 }
814 
815 static void
CL_SetStat(int stat,int value)816 CL_SetStat (int stat, int value)
817 {
818 	if (stat < 0 || stat >= MAX_CL_STATS)
819 		Host_Error ("CL_SetStat: %i is invalid", stat);
820 	cl.stats[stat] = value;
821 }
822 
823 #define SHOWNET(x) \
824 	if (cl_shownet->int_val == 2) \
825 		Sys_Printf ("%3i:%s\n", net_message->readcount - 1, x);
826 
827 void
CL_ParseServerMessage(void)828 CL_ParseServerMessage (void)
829 {
830 	int         cmd = 0, i, j;
831 	const char *str;
832 	static dstring_t *stuffbuf;
833 	signon_t    so;
834 
835 	// if recording demos, copy the message out
836 	if (cl_shownet->int_val == 1)
837 		Sys_Printf ("%i ", net_message->message->cursize);
838 	else if (cl_shownet->int_val == 2)
839 		Sys_Printf ("------------------\n");
840 
841 	cl.onground = -1;				// unless the server says otherwise
842 
843 	// parse the message
844 	MSG_BeginReading (net_message);
845 
846 	while (1) {
847 		if (net_message->badread)
848 			Host_Error ("CL_ParseServerMessage: Bad server message: %s\n",
849 						svc_strings[cmd]);
850 
851 		cmd = MSG_ReadByte (net_message);
852 
853 		if (cmd == -1) {
854 			net_message->readcount++;	// so the EOM SHOWNET has the right
855 										// value
856 			SHOWNET ("END OF MESSAGE");
857 			break;						// end of message
858 		}
859 		// if the high bit of the command byte is set, it is a fast update
860 		if (cmd & U_SIGNAL) {
861 			SHOWNET ("fast update");
862 			CL_ParseUpdate (cmd & ~U_SIGNAL);
863 			continue;
864 		}
865 
866 		SHOWNET (va ("%s(%d)", svc_strings[cmd], cmd));
867 
868 		// other commands
869 		switch (cmd) {
870 			default:
871 				Host_Error ("CL_ParseServerMessage: Illegible server "
872 							"message: %d\n", cmd);
873 				break;
874 
875 			case svc_nop:
876 				break;
877 
878 			case svc_disconnect:
879 				if (cls.state == ca_connected)
880 					Host_EndGame ("Server disconnected\n"
881 								  "Server version may not be compatible");
882 				else
883 					Host_EndGame ("Server disconnected\n");
884 
885 			case svc_updatestat:
886 				i = MSG_ReadByte (net_message);
887 				j = MSG_ReadLong (net_message);
888 				CL_SetStat (i, j);
889 				break;
890 
891 			case svc_version:
892 				i = MSG_ReadLong (net_message);
893 				if (i != PROTOCOL_NETQUAKE && i!= PROTOCOL_FITZQUAKE)
894 					Host_Error ("CL_ParseServerMessage: Server is protocol %i "
895 								"instead of %i or %i\n", i, PROTOCOL_NETQUAKE,
896 								PROTOCOL_FITZQUAKE);
897 				cl.protocol = i;
898 				break;
899 
900 			case svc_setview:
901 				cl.viewentity = MSG_ReadShort (net_message);
902 				break;
903 
904 			case svc_sound:
905 				CL_ParseStartSoundPacket ();
906 				break;
907 
908 			case svc_time:
909 				cl.mtime[1] = cl.mtime[0];
910 				cl.mtime[0] = MSG_ReadFloat (net_message);
911 				cl.mindex = !cl.mindex;
912 				break;
913 
914 			case svc_print:
915 				Sys_Printf ("%s", MSG_ReadString (net_message));
916 				break;
917 
918 			case svc_stufftext:
919 				str = MSG_ReadString (net_message);
920 				if (str[strlen (str) - 1] == '\n') {
921 					if (stuffbuf && stuffbuf->str[0]) {
922 						Sys_MaskPrintf (SYS_DEV, "stufftext: %s%s\n",
923 										stuffbuf->str, str);
924 						Cbuf_AddText (host_cbuf, stuffbuf->str);
925 						dstring_clearstr (stuffbuf);
926 					} else {
927 						Sys_MaskPrintf (SYS_DEV, "stufftext: %s\n", str);
928 					}
929 					Cbuf_AddText (host_cbuf, str);
930 				} else {
931 					Sys_MaskPrintf (SYS_DEV, "partial stufftext: %s\n", str);
932 					if (!stuffbuf)
933 						stuffbuf = dstring_newstr ();
934 					dstring_appendstr (stuffbuf, str);
935 				}
936 				break;
937 
938 			case svc_setangle:
939 			{
940 				vec_t      *dest = cl.viewangles;
941 
942 				MSG_ReadAngleV (net_message, dest);
943 				break;
944 			}
945 			case svc_serverinfo:
946 				// make sure any stuffed commands are done
947 				if (stuffbuf && stuffbuf->str[0]) {
948 					Cbuf_AddText (host_cbuf, stuffbuf->str);
949 					dstring_clearstr (stuffbuf);
950 				}
951 				Cbuf_Execute_Stack (host_cbuf);
952 				CL_ParseServerInfo ();
953 				// leave full screen intermission
954 				r_data->vid->recalc_refdef = true;
955 				break;
956 
957 			case svc_lightstyle:
958 				i = MSG_ReadByte (net_message);
959 				if (i >= MAX_LIGHTSTYLES)
960 					Host_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
961 				strcpy (cl.lightstyle[i].map, MSG_ReadString (net_message));
962 				cl.lightstyle[i].length = strlen (cl.lightstyle[i].map);
963 				if (cl.lightstyle[i].length) {
964 					int         total = 0;
965 
966 					cl.lightstyle[i].peak = 'a';
967 					for (j = 0; j < cl.lightstyle[i].length; j++) {
968 						total += cl.lightstyle[i].map[j] - 'a';
969 						cl.lightstyle[i].peak = max (cl.lightstyle[i].peak,
970 													 cl.lightstyle[i].map[j]);
971 					}
972 					total /= cl.lightstyle[i].length;
973 					cl.lightstyle[i].average = total + 'a';
974 				} else {
975 					cl.lightstyle[i].average = 'm';
976 					cl.lightstyle[i].peak = 'm';
977 				}
978 				break;
979 
980 			case svc_updatename:
981 				Sbar_Changed ();
982 				i = MSG_ReadByte (net_message);
983 				if (i >= cl.maxclients)
984 					Host_Error ("CL_ParseServerMessage: svc_updatename > "
985 								"MAX_SCOREBOARD");
986 				Info_SetValueForKey (cl.scores[i].info, "name",
987 									 MSG_ReadString (net_message), 0);
988 				break;
989 
990 			case svc_updatefrags:
991 				Sbar_Changed ();
992 				i = MSG_ReadByte (net_message);
993 				if (i >= cl.maxclients)
994 					Host_Error ("CL_ParseServerMessage: svc_updatefrags > "
995 								"MAX_SCOREBOARD");
996 				cl.scores[i].frags = (short) MSG_ReadShort (net_message);
997 				break;
998 
999 			case svc_clientdata:
1000 				CL_ParseClientdata ();
1001 				break;
1002 
1003 			case svc_stopsound:
1004 				i = MSG_ReadShort (net_message);
1005 				S_StopSound (i >> 3, i & 7);
1006 				break;
1007 
1008 			case svc_updatecolors:
1009 				Sbar_Changed ();
1010 				i = MSG_ReadByte (net_message);
1011 				if (i >= cl.maxclients) {
1012 					Host_Error ("CL_ParseServerMessage: svc_updatecolors > "
1013 								"MAX_SCOREBOARD");
1014 				} else {
1015 					entity_t   *ent = &cl_entities[i+1];
1016 					byte        col = MSG_ReadByte (net_message);
1017 					byte        top = col >> 4;
1018 					byte        bot = col & 0xf;
1019 					if (top != cl.scores[i].topcolor
1020 						|| bot != cl.scores[i].bottomcolor)
1021 						mod_funcs->Skin_SetTranslation (i + 1, top, bot);
1022 					cl.scores[i].topcolor = top;
1023 					cl.scores[i].bottomcolor = bot;
1024 					ent->skin = mod_funcs->Skin_SetColormap (ent->skin, i + 1);
1025 				}
1026 				break;
1027 
1028 			case svc_particle:
1029 				CL_ParseParticleEffect ();
1030 				break;
1031 
1032 			case svc_damage:
1033 				V_ParseDamage ();
1034 				break;
1035 
1036 			case svc_spawnstatic:
1037 				CL_ParseStatic (1);
1038 				break;
1039 
1040 			//   svc_spawnbinary
1041 
1042 			case svc_spawnbaseline:
1043 				i = MSG_ReadShort (net_message);
1044 				// must use CL_EntityNum () to force cl.num_entities up
1045 				CL_ParseBaseline (CL_EntityNum (i), 1);
1046 				break;
1047 
1048 			case svc_temp_entity:
1049 				CL_ParseTEnt ();
1050 				break;
1051 
1052 			case svc_setpause:
1053 				r_data->paused = cl.paused = MSG_ReadByte (net_message);
1054 				if (cl.paused)
1055 					CDAudio_Pause ();
1056 				else
1057 					CDAudio_Resume ();
1058 				break;
1059 
1060 			case svc_signonnum:
1061 				so = MSG_ReadByte (net_message);
1062 				if (so <= cls.signon || so >= so_active)
1063 					Host_Error ("Received signon %i when at %i", so,
1064 								cls.signon);
1065 				cls.signon = so;
1066 				CL_SignonReply ();
1067 				break;
1068 
1069 			case svc_centerprint:
1070 				str = MSG_ReadString (net_message);
1071 				if (strcmp (str, centerprint->str)) {
1072 					dstring_copystr (centerprint, str);
1073 					//FIXME logging
1074 				}
1075 				Sbar_CenterPrint (str);
1076 				break;
1077 
1078 			case svc_killedmonster:
1079 				cl.stats[STAT_MONSTERS]++;
1080 				break;
1081 
1082 			case svc_foundsecret:
1083 				cl.stats[STAT_SECRETS]++;
1084 				break;
1085 
1086 			case svc_spawnstaticsound:
1087 				CL_ParseStaticSound (1);
1088 				break;
1089 
1090 			case svc_intermission:
1091 				cl.intermission = 1;
1092 				r_data->force_fullscreen = 1;
1093 				cl.completed_time = cl.time;
1094 				r_data->vid->recalc_refdef = true;		// go to full screen
1095 				break;
1096 
1097 			case svc_finale:
1098 				cl.intermission = 2;
1099 				r_data->force_fullscreen = 1;
1100 				cl.completed_time = cl.time;
1101 				r_data->vid->recalc_refdef = true;		// go to full screen
1102 				str = MSG_ReadString (net_message);
1103 				if (strcmp (str, centerprint->str)) {
1104 					dstring_copystr (centerprint, str);
1105 					//FIXME logging
1106 				}
1107 				Sbar_CenterPrint (str);
1108 				break;
1109 
1110 			case svc_cdtrack:
1111 				cl.cdtrack = MSG_ReadByte (net_message);
1112 				MSG_ReadByte (net_message);	// looptrack (not used)
1113 				if ((cls.demoplayback || cls.demorecording)
1114 					&& (cls.forcetrack != -1))
1115 					CDAudio_Play ((byte) cls.forcetrack, true);
1116 				else
1117 					CDAudio_Play ((byte) cl.cdtrack, true);
1118 				break;
1119 
1120 			case svc_sellscreen:
1121 				Cmd_ExecuteString ("help", src_command);
1122 				break;
1123 
1124 			case svc_cutscene:
1125 				cl.intermission = 3;
1126 				r_data->force_fullscreen = 1;
1127 				cl.completed_time = cl.time;
1128 				r_data->vid->recalc_refdef = true;	// go to full screen
1129 				str = MSG_ReadString (net_message);
1130 				if (strcmp (str, centerprint->str)) {
1131 					dstring_copystr (centerprint, str);
1132 					//FIXME logging
1133 				}
1134 				Sbar_CenterPrint (str);
1135 				break;
1136 
1137 			//   svc_smallkick (same value as svc_cutscene)
1138 			//   svc_bigkick
1139 			//   svc_updateping
1140 			//   svc_updateentertime
1141 			//   svc_updatestatlong
1142 			//   svc_muzzleflash
1143 			//   svc_updateuserinfo
1144 			//   svc_download
1145 			//   svc_playerinfo
1146 			//   svc_nails
1147 			//   svc_chokecount
1148 			//   svc_modellist
1149 			//   svc_soundlist
1150 			//   svc_packetentities
1151 			//   svc_deltapacketentities
1152 			//   svc_maxspeed
1153 			//   svc_entgravity
1154 			//   svc_setinfo
1155 			//   svc_serverinfo
1156 			//   svc_updatepl
1157 
1158 			// PROTOCOL_FITZQUAKE (these overlap with the above listed qw svcs)
1159 			case svc_skybox:
1160 				r_funcs->R_LoadSkys (MSG_ReadString(net_message));
1161 				break;
1162 			case svc_bf:
1163 				Cmd_ExecuteString ("bf", src_command);
1164 				break;
1165 			case svc_fog:
1166 				{
1167 					float density, red, green, blue, time;
1168 					density = MSG_ReadByte (net_message) / 255.0;
1169 					red = MSG_ReadByte (net_message) / 255.0;
1170 					green = MSG_ReadByte (net_message) / 255.0;
1171 					blue = MSG_ReadByte (net_message) / 255.0;
1172 					time = (short) MSG_ReadShort (net_message) / 100.0;
1173 					time = max (0.0, time);
1174 					if (r_funcs->Fog_Update)
1175 						r_funcs->Fog_Update (density, red, green, blue, time);
1176 				}
1177 				break;
1178 			case svc_spawnbaseline2:
1179 				i = MSG_ReadShort (net_message);
1180 				// must use CL_EntityNum() to force cl.num_entities up
1181 				CL_ParseBaseline (CL_EntityNum(i), 2);
1182 				break;
1183 			case svc_spawnstatic2:
1184 				CL_ParseStatic (2);
1185 				break;
1186 			case svc_spawnstaticsound2:
1187 				CL_ParseStaticSound (2);
1188 				break;
1189 		}
1190 	}
1191 }
1192