Home | History | Annotate | Download | only in WinQuake
      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 const 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",			// <see code>
     33 	"svc_time",			// [float] server time
     34 	"svc_print",			// [string] null terminated string
     35 	"svc_stufftext",		// [string] stuffed into client's console buffer
     36 						// the string should be \n terminated
     37 	"svc_setangle",		// [vec3] set the view angle to this absolute value
     38 
     39 	"svc_serverinfo",		// [long] version
     40 						// [string] signon string
     41 						// [string]..[0]model cache [string]...[0]sounds cache
     42 						// [string]..[0]item cache
     43 	"svc_lightstyle",		// [byte] [string]
     44 	"svc_updatename",		// [byte] [string]
     45 	"svc_updatefrags",	// [byte] [short]
     46 	"svc_clientdata",		// <shortbits + data>
     47 	"svc_stopsound",		// <see code>
     48 	"svc_updatecolors",	// [byte] [byte]
     49 	"svc_particle",		// [vec3] <variable>
     50 	"svc_damage",			// [byte] impact [byte] blood [vec3] from
     51 
     52 	"svc_spawnstatic",
     53 	"OBSOLETE svc_spawnbinary",
     54 	"svc_spawnbaseline",
     55 
     56 	"svc_temp_entity",		// <variable>
     57 	"svc_setpause",
     58 	"svc_signonnum",
     59 	"svc_centerprint",
     60 	"svc_killedmonster",
     61 	"svc_foundsecret",
     62 	"svc_spawnstaticsound",
     63 	"svc_intermission",
     64 	"svc_finale",			// [string] music [string] text
     65 	"svc_cdtrack",			// [byte] track [byte] looptrack
     66 	"svc_sellscreen",
     67 	"svc_cutscene"
     68 };
     69 
     70 //=============================================================================
     71 
     72 /*
     73 ===============
     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 = (scoreboard_t*) Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
    234 
    235 // parse gametype
    236 	cl.gametype = MSG_ReadByte ();
    237 
    238 // parse signon message
    239 	str = MSG_ReadString ();
    240 	strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
    241 
    242 // seperate the printfs so the server message can have a color
    243 	Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n");
    244 	Con_Printf ("%c%s\n", 2, str);
    245 
    246 //
    247 // first we go through and touch all of the precache data that still
    248 // happens to be in the cache, so precaching something else doesn't
    249 // needlessly purge it
    250 //
    251 
    252 // precache models
    253 	memset (cl.model_precache, 0, sizeof(cl.model_precache));
    254 	for (nummodels=1 ; ; nummodels++)
    255 	{
    256 		str = MSG_ReadString ();
    257 		if (!str[0])
    258 			break;
    259 		if (nummodels==MAX_MODELS)
    260 		{
    261 			Con_Printf ("Server sent too many model precaches\n");
    262 			return;
    263 		}
    264 		strcpy (model_precache[nummodels], str);
    265 		Mod_TouchModel (str);
    266 	}
    267 
    268 // precache sounds
    269 	memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
    270 	for (numsounds=1 ; ; numsounds++)
    271 	{
    272 		str = MSG_ReadString ();
    273 		if (!str[0])
    274 			break;
    275 		if (numsounds==MAX_SOUNDS)
    276 		{
    277 			Con_Printf ("Server sent too many sound precaches\n");
    278 			return;
    279 		}
    280 		strcpy (sound_precache[numsounds], str);
    281 		S_TouchSound (str);
    282 	}
    283 
    284 //
    285 // now we try to load everything else until a cache allocation fails
    286 //
    287 
    288 	for (i=1 ; i<nummodels ; i++)
    289 	{
    290 		cl.model_precache[i] = Mod_ForName (model_precache[i], false);
    291 		if (cl.model_precache[i] == NULL)
    292 		{
    293 			Con_Printf("Model %s not found\n", model_precache[i]);
    294 			return;
    295 		}
    296 		CL_KeepaliveMessage ();
    297 	}
    298 
    299 	S_BeginPrecaching ();
    300 	for (i=1 ; i<numsounds ; i++)
    301 	{
    302 		cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
    303 		CL_KeepaliveMessage ();
    304 	}
    305 	S_EndPrecaching ();
    306 
    307 
    308 // local state
    309 	cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
    310 
    311 	R_NewMap ();
    312 
    313 	Hunk_Check ();		// make sure nothing is hurt
    314 
    315 	noclip_anglehack = false;		// noclip is turned off at start
    316 }
    317 
    318 
    319 /*
    320 ==================
    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<<i))
    361 	bitcounts[i]++;
    362 
    363 	if (ent->msgtime != cl.mtime[1])
    364 		forcelink = true;	// no previous frame to lerp from
    365 	else
    366 		forcelink = false;
    367 
    368 	ent->msgtime = cl.mtime[0];
    369 
    370 	if (bits & U_MODEL)
    371 	{
    372 		modnum = MSG_ReadByte ();
    373 		if (modnum >= MAX_MODELS)
    374 			Host_Error ("CL_ParseModel: bad modnum");
    375 	}
    376 	else
    377 		modnum = ent->baseline.modelindex;
    378 
    379 	model = cl.model_precache[modnum];
    380 	if (model != ent->model)
    381 	{
    382 		ent->model = model;
    383 	// automatic animation (torches, etc) can be either all together
    384 	// or randomized
    385 		if (model)
    386 		{
    387 			if (model->synctype == ST_RAND)
    388 				ent->syncbase = (float)(rand()&0x7fff) / 0x7fff;
    389 			else
    390 				ent->syncbase = 0.0;
    391 		}
    392 		else
    393 			forcelink = true;	// hack to make null model players work
    394 #ifdef GLQUAKE
    395 		if (num > 0 && num <= cl.maxclients)
    396 			R_TranslatePlayerSkin (num - 1);
    397 #endif
    398 	}
    399 
    400 	if (bits & U_FRAME)
    401 		ent->frame = MSG_ReadByte ();
    402 	else
    403 		ent->frame = ent->baseline.frame;
    404 
    405 	if (bits & U_COLORMAP)
    406 		i = MSG_ReadByte();
    407 	else
    408 		i = ent->baseline.colormap;
    409 	if (!i)
    410 		ent->colormap = vid.colormap;
    411 	else
    412 	{
    413 		if (i > cl.maxclients)
    414 			Sys_Error ("i >= cl.maxclients");
    415 		ent->colormap = cl.scores[i-1].translations;
    416 	}
    417 
    418 #ifdef GLQUAKE
    419 	if (bits & U_SKIN)
    420 		skin = MSG_ReadByte();
    421 	else
    422 		skin = ent->baseline.skin;
    423 	if (skin != ent->skinnum) {
    424 		ent->skinnum = skin;
    425 		if (num > 0 && num <= cl.maxclients)
    426 			R_TranslatePlayerSkin (num - 1);
    427 	}
    428 
    429 #else
    430 
    431 	if (bits & U_SKIN)
    432 		ent->skinnum = MSG_ReadByte();
    433 	else
    434 		ent->skinnum = ent->baseline.skin;
    435 #endif
    436 
    437 	if (bits & U_EFFECTS)
    438 		ent->effects = MSG_ReadByte();
    439 	else
    440 		ent->effects = ent->baseline.effects;
    441 
    442 // shift the known values for interpolation
    443 	VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
    444 	VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
    445 
    446 	if (bits & U_ORIGIN1)
    447 		ent->msg_origins[0][0] = MSG_ReadCoord ();
    448 	else
    449 		ent->msg_origins[0][0] = ent->baseline.origin[0];
    450 	if (bits & U_ANGLE1)
    451 		ent->msg_angles[0][0] = MSG_ReadAngle();
    452 	else
    453 		ent->msg_angles[0][0] = ent->baseline.angles[0];
    454 
    455 	if (bits & U_ORIGIN2)
    456 		ent->msg_origins[0][1] = MSG_ReadCoord ();
    457 	else
    458 		ent->msg_origins[0][1] = ent->baseline.origin[1];
    459 	if (bits & U_ANGLE2)
    460 		ent->msg_angles[0][1] = MSG_ReadAngle();
    461 	else
    462 		ent->msg_angles[0][1] = ent->baseline.angles[1];
    463 
    464 	if (bits & U_ORIGIN3)
    465 		ent->msg_origins[0][2] = MSG_ReadCoord ();
    466 	else
    467 		ent->msg_origins[0][2] = ent->baseline.origin[2];
    468 	if (bits & U_ANGLE3)
    469 		ent->msg_angles[0][2] = MSG_ReadAngle();
    470 	else
    471 		ent->msg_angles[0][2] = ent->baseline.angles[2];
    472 
    473 	if ( bits & U_NOLERP )
    474 		ent->forcelink = true;
    475 
    476 	if ( forcelink )
    477 	{	// didn't have an update last message
    478 		VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
    479 		VectorCopy (ent->msg_origins[0], ent->origin);
    480 		VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
    481 		VectorCopy (ent->msg_angles[0], ent->angles);
    482 		ent->forcelink = true;
    483 	}
    484 }
    485 
    486 /*
    487 ==================
    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<<i) )
    532 			cl.punchangle[i] = MSG_ReadChar();
    533 		else
    534 			cl.punchangle[i] = 0;
    535 		if (bits & (SU_VELOCITY1<<i) )
    536 			cl.mvelocity[0][i] = MSG_ReadChar()*16;
    537 		else
    538 			cl.mvelocity[0][i] = 0;
    539 	}
    540 
    541 // [always sent]	if (bits & SU_ITEMS)
    542 		i = MSG_ReadLong ();
    543 
    544 	if (cl.items != i)
    545 	{	// set flash times
    546 		Sbar_Changed ();
    547 		for (j=0 ; j<32 ; j++)
    548 			if ( (i & (1<<j)) && !(cl.items & (1<<j)))
    549 				cl.item_gettime[j] = cl.time;
    550 		cl.items = i;
    551 	}
    552 
    553 	cl.onground = (bits & SU_ONGROUND) != 0;
    554 	cl.inwater = (bits & SU_INWATER) != 0;
    555 
    556 	if (bits & SU_WEAPONFRAME)
    557 		cl.stats[STAT_WEAPONFRAME] = MSG_ReadByte ();
    558 	else
    559 		cl.stats[STAT_WEAPONFRAME] = 0;
    560 
    561 	if (bits & SU_ARMOR)
    562 		i = MSG_ReadByte ();
    563 	else
    564 		i = 0;
    565 	if (cl.stats[STAT_ARMOR] != i)
    566 	{
    567 		cl.stats[STAT_ARMOR] = i;
    568 		Sbar_Changed ();
    569 	}
    570 
    571 	if (bits & SU_WEAPON)
    572 		i = MSG_ReadByte ();
    573 	else
    574 		i = 0;
    575 	if (cl.stats[STAT_WEAPON] != i)
    576 	{
    577 		cl.stats[STAT_WEAPON] = i;
    578 		Sbar_Changed ();
    579 	}
    580 
    581 	i = MSG_ReadShort ();
    582 	if (cl.stats[STAT_HEALTH] != i)
    583 	{
    584 		cl.stats[STAT_HEALTH] = i;
    585 		Sbar_Changed ();
    586 	}
    587 
    588 	i = MSG_ReadByte ();
    589 	if (cl.stats[STAT_AMMO] != i)
    590 	{
    591 		cl.stats[STAT_AMMO] = i;
    592 		Sbar_Changed ();
    593 	}
    594 
    595 	for (i=0 ; i<4 ; i++)
    596 	{
    597 		j = MSG_ReadByte ();
    598 		if (cl.stats[STAT_SHELLS+i] != j)
    599 		{
    600 			cl.stats[STAT_SHELLS+i] = j;
    601 			Sbar_Changed ();
    602 		}
    603 	}
    604 
    605 	i = MSG_ReadByte ();
    606 
    607 	if (standard_quake)
    608 	{
    609 		if (cl.stats[STAT_ACTIVEWEAPON] != i)
    610 		{
    611 			cl.stats[STAT_ACTIVEWEAPON] = i;
    612 			Sbar_Changed ();
    613 		}
    614 	}
    615 	else
    616 	{
    617 		if (cl.stats[STAT_ACTIVEWEAPON] != (1<<i))
    618 		{
    619 			cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
    620 			Sbar_Changed ();
    621 		}
    622 	}
    623 }
    624 
    625 /*
    626 =====================
    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<VID_GRADES ; i++, dest += 256, source+=256)
    648 	{
    649 		if (top < 128)	// the artists made some backwards ranges.  sigh.
    650 			memcpy (dest + TOP_RANGE, source + top, 16);
    651 		else
    652 			for (j=0 ; j<16 ; j++)
    653 				dest[TOP_RANGE+j] = source[top+15-j];
    654 
    655 		if (bottom < 128)
    656 			memcpy (dest + BOTTOM_RANGE, source + bottom, 16);
    657 		else
    658 			for (j=0 ; j<16 ; j++)
    659 				dest[BOTTOM_RANGE+j] = source[bottom+15-j];
    660 	}
    661 }
    662 
    663 /*
    664 =====================
    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 = (int) 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 = (int) 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 = (int) 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_ExecuteString2 ("help", src_command);
    959 			break;
    960 		}
    961 	}
    962 }
    963 
    964