Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 1
/*
2
Copyright (C) 1996-1997 Id Software, Inc.
3
 
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
 
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
 
13
See the GNU General Public License for more details.
14
 
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
 
19
*/
20
// cl_parse.c  -- parse a message received from the server
21
 
22
#include "quakedef.h"
23
 
24
char *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",			// 
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",		// 
47
	"svc_stopsound",		// 
48
	"svc_updatecolors",	// [byte] [byte]
49
	"svc_particle",		// [vec3] 
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",		// 
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
===============
74
CL_EntityNum
75
 
76
This error checks and tracks the total number of entities
77
===============
78
*/
79
entity_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
==================
98
CL_ParseStartSoundPacket
99
==================
100
*/
101
void 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
==================
140
CL_KeepaliveMessage
141
 
142
When the client is taking a long time to load stuff, send keepalive messages
143
so the server doesn't disconnect.
144
==================
145
*/
146
void 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
==================
201
CL_ParseServerInfo
202
==================
203
*/
204
void 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
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
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
==================
321
CL_ParseUpdate
322
 
323
Parse an entity update message from the server
324
If an entities model or origin changes from frame to frame, it must be
325
relinked.  Other attributes can change without relinking.
326
==================
327
*/
328
int	bitcounts[16];
329
 
330
void 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
 
359
for (i=0 ; i<16 ; i++)
360
if (bits&(1<
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
==================
488
CL_ParseBaseline
489
==================
490
*/
491
void 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
==================
509
CL_ParseClientdata
510
 
511
Server information pertaining to this client only
512
==================
513
*/
514
void 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<
532
			cl.punchangle[i] = MSG_ReadChar();
533
		else
534
			cl.punchangle[i] = 0;
535
		if (bits & (SU_VELOCITY1<
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<
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<
618
		{
619
			cl.stats[STAT_ACTIVEWEAPON] = (1<
620
			Sbar_Changed ();
621
		}
622
	}
623
}
624
 
625
/*
626
=====================
627
CL_NewTranslation
628
=====================
629
*/
630
void 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
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
=====================
665
CL_ParseStatic
666
=====================
667
*/
668
void 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
===================
694
CL_ParseStaticSound
695
===================
696
*/
697
void 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
=====================
717
CL_ParseServerMessage
718
=====================
719
*/
720
void 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 ();
887
#ifdef _WIN32
888
					VID_HandlePause (true);
889
#endif
890
				}
891
				else
892
				{
893
					CDAudio_Resume ();
894
#ifdef _WIN32
895
					VID_HandlePause (false);
896
#endif
897
				}
898
			}
899
			break;
900
 
901
		case svc_signonnum:
902
			i = MSG_ReadByte ();
903
			if (i <= cls.signon)
904
				Host_Error ("Received signon %i when at %i", i, cls.signon);
905
			cls.signon = i;
906
			CL_SignonReply ();
907
			break;
908
 
909
		case svc_killedmonster:
910
			cl.stats[STAT_MONSTERS]++;
911
			break;
912
 
913
		case svc_foundsecret:
914
			cl.stats[STAT_SECRETS]++;
915
			break;
916
 
917
		case svc_updatestat:
918
			i = MSG_ReadByte ();
919
			if (i < 0 || i >= MAX_CL_STATS)
920
				Sys_Error ("svc_updatestat: %i is invalid", i);
921
			cl.stats[i] = MSG_ReadLong ();;
922
			break;
923
 
924
		case svc_spawnstaticsound:
925
			CL_ParseStaticSound ();
926
			break;
927
 
928
		case svc_cdtrack:
929
			cl.cdtrack = MSG_ReadByte ();
930
			cl.looptrack = MSG_ReadByte ();
931
			if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
932
				CDAudio_Play ((byte)cls.forcetrack, true);
933
			else
934
				CDAudio_Play ((byte)cl.cdtrack, true);
935
			break;
936
 
937
		case svc_intermission:
938
			cl.intermission = 1;
939
			cl.completed_time = cl.time;
940
			vid.recalc_refdef = true;	// go to full screen
941
			break;
942
 
943
		case svc_finale:
944
			cl.intermission = 2;
945
			cl.completed_time = cl.time;
946
			vid.recalc_refdef = true;	// go to full screen
947
			SCR_CenterPrint (MSG_ReadString ());
948
			break;
949
 
950
		case svc_cutscene:
951
			cl.intermission = 3;
952
			cl.completed_time = cl.time;
953
			vid.recalc_refdef = true;	// go to full screen
954
			SCR_CenterPrint (MSG_ReadString ());
955
			break;
956
 
957
		case svc_sellscreen:
958
			Cmd_ExecuteString ("help", src_command);
959
			break;
960
		}
961
	}
962
}
963