741 lines · 17.2 KB · C
RawDownload
// cl_parse.c -- parse a message received from the server #include <stdio.h>#include <stdlib.h>#include "quakedef.h" static const char *svc_strings[] ={	"svc_bad",	"svc_nop",	"svc_disconnect",	"svc_updatestat",	"svc_version", // [long] server version	"svc_setview", // [short] entity number	"svc_sound", // <see code>	"svc_time", // [float] server time	"svc_print", // [string] null terminated string	"svc_stufftext", // [string] stuffed into client's console buffer						// the string should be \n terminated	"svc_setangle", // [vec3] set the view angle to this absolute value 	"svc_serverinfo", // [long] version						// [string] signon string						// [string]..[0]model cache [string]...[0]sounds cache						// [string]..[0]item cache	"svc_lightstyle", // [byte] [string]	"svc_updatename", // [byte] [string]	"svc_updatefrags", // [byte] [short]	"svc_clientdata", // <shortbits + data>	"svc_stopsound", // <see code>	"svc_updatecolors", // [byte] [byte]	"svc_particle", // [vec3] <variable>	"svc_damage", // [byte] impact [byte] blood [vec3] from 	"svc_spawnstatic",	"OBSOLETE svc_spawnbinary",	"svc_spawnbaseline", 	"svc_temp_entity", // <variable>	"svc_setpause",	"svc_signonnum",	"svc_centerprint",	"svc_killedmonster",	"svc_foundsecret",	"svc_spawnstaticsound",	"svc_intermission",	"svc_finale", // [string] music [string] text	"svc_cdtrack", // [byte] track [byte] looptrack	"svc_sellscreen",	"svc_cutscene"}; entity_t *CL_EntityNum(int num){	if (num >= cl.num_entities) {		if (num >= MAX_EDICTS)			Host_Error("CL_EntityNum: %i is an invalid number",num);		while (cl.num_entities <= num) {			cl_entities[cl.num_entities].colormap = vid.colormap;			cl.num_entities++;		}	} 	return &cl_entities[num];} voidCL_ParseStartSoundPacket(void){    vec3_t pos;    int channel, ent;    int sound_num;    int volume;    int field_mask;    float attenuation; 	int i;     field_mask = MSG_ReadByte();     if (field_mask & SND_VOLUME)		volume = MSG_ReadByte();	else		volume = DEFAULT_SOUND_PACKET_VOLUME;     if (field_mask & SND_ATTENUATION)		attenuation = MSG_ReadByte() / 64.0;	else		attenuation = DEFAULT_SOUND_PACKET_ATTENUATION; 	channel = MSG_ReadShort();	sound_num = MSG_ReadByte(); 	ent = channel >> 3;	channel &= 7; 	if (ent > MAX_EDICTS)		Host_Error("CL_ParseStartSoundPacket: ent = %i", ent); 	for (i = 0; i < 3; i++)		pos[i] = MSG_ReadCoord();     S_StartSound(ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);} voidCL_KeepaliveMessage (void){	float time;	static float lastmsg;	int ret;	sizebuf_t old;	uint8_t olddata[8192]; 	if (sv.active)		return; // no need if server is local	if (cls.demoplayback)		return; 	// read messages from server, should just be nops	old = net_message;	memmove(olddata, net_message.data, net_message.cursize); 	do {		ret = CL_GetMessage();		switch (ret) {		default:			Host_Error("CL_KeepaliveMessage: CL_GetMessage failed");		case 0:			break; // nothing waiting		case 1:			Host_Error("CL_KeepaliveMessage: received a message");			break;		case 2:			if (MSG_ReadByte() != svc_nop)				Host_Error("CL_KeepaliveMessage: datagram wasn't a nop");			break;		}	} while (ret); 	net_message = old;	memmove(net_message.data, olddata, net_message.cursize); 	// check time	time = Sys_FloatTime();	if (time - lastmsg < 5)		return;	lastmsg = time; 	// write out a nop	Con_Printf("--> client to server keepalive\n"); 	MSG_WriteByte(&cls.message, clc_nop);	NET_SendMessage(cls.netcon, &cls.message);	SZ_Clear(&cls.message);} voidCL_ParseServerInfo(void){	char *str;	int i;	int nummodels, numsounds;	char model_precache[MAX_MODELS][MAX_QPATH];	char sound_precache[MAX_SOUNDS][MAX_QPATH]; 	Con_DPrintf("Serverinfo packet received.\n"); 	// wipe the client_state_t struct	CL_ClearState(); 	// parse protocol version number	i = MSG_ReadLong();	if (i != PROTOCOL_VERSION) {		Con_Printf ("Server returned version %i, not %i", i, PROTOCOL_VERSION);		return;	} 	// parse maxclients	cl.maxclients = MSG_ReadByte();	if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD) {		Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);		return;	}	cl.scores = Hunk_AllocName(cl.maxclients*sizeof(*cl.scores), "scores"); 	// parse gametype	cl.gametype = MSG_ReadByte(); 	// parse signon message	str = MSG_ReadString();	strncpy(cl.levelname, str, sizeof(cl.levelname)-1); 	// seperate the printfs so the server message can have a color	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");	Con_Printf("%c%s\n", 2, str); 	// first we go through and touch all of the precache data that still	// happens to be in the cache, so precaching something else doesn't	// needlessly purge it 	// precache models	memset(cl.model_precache, 0, sizeof(cl.model_precache));	for (nummodels = 1;; nummodels++) {		str = MSG_ReadString();		if (!str[0])			break;		if (nummodels == MAX_MODELS) {			Con_Printf("Server sent too many model precaches\n");			return;		}		strcpy(model_precache[nummodels], str);		Mod_TouchModel(str);	} 	// precache sounds	memset(cl.sound_precache, 0, sizeof(cl.sound_precache));	for (numsounds = 1;; numsounds++) {		str = MSG_ReadString();		if (!str[0])			break;		if (numsounds == MAX_SOUNDS) {			Con_Printf ("Server sent too many sound precaches\n");			return;		}		strcpy(sound_precache[numsounds], str);		S_TouchSound(str);	} 	// now we try to load everything else until a cache allocation fails 	for (i = 1; i < nummodels; i++) {		cl.model_precache[i] = Mod_ForName(model_precache[i], false);		if (cl.model_precache[i] == NULL) {			Con_Printf("Model %s not found\n", model_precache[i]);			return;		}		CL_KeepaliveMessage();	} 	S_BeginPrecaching();	for (i = 1; i < numsounds; i++) {		cl.sound_precache[i] = S_PrecacheSound(sound_precache[i]);		CL_KeepaliveMessage();	}	S_EndPrecaching(); 	// local state	cl_entities[0].model = cl.worldmodel = cl.model_precache[1]; 	R_NewMap();	Hunk_Check(); // make sure nothing is hurt	noclip_anglehack = false; // noclip is turned off at start} /* * Parse an entity update message from the server * If an entities model or origin changes from frame to frame, it must be * relinked. Other attributes can change without relinking. */int bitcounts[16]; voidCL_ParseUpdate(int bits){	int i;	model_t *model;	int modnum;	bool forcelink;	entity_t *ent;	int num; 	if (cls.signon == SIGNONS - 1) { // first update is the final signon stage		cls.signon = SIGNONS;		CL_SignonReply();	} 	if (bits & U_MOREBITS) {		i = MSG_ReadByte();		bits |= i<<8;	} 	num = (bits & U_LONGENTITY) ? MSG_ReadShort() : MSG_ReadByte();	ent = CL_EntityNum(num); 	for (i = 0; i < 16; i++) {		if (bits & (1<<i))			bitcounts[i]++;	} 	forcelink = ent->msgtime != cl.mtime[1]; // no previous frame to lerp from	ent->msgtime = cl.mtime[0]; 	if (bits & U_MODEL) {		modnum = MSG_ReadByte();		if (modnum >= MAX_MODELS)			Host_Error("CL_ParseModel: bad modnum");	} else {		modnum = ent->baseline.modelindex;	} 	model = cl.model_precache[modnum];	if (model != ent->model) {		ent->model = model;		// automatic animation (torches, etc) can be either all together		// or randomized		if (model)			ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0;		else			forcelink = true; // hack to make null model players work	} 	ent->frame = (bits & U_FRAME) ? MSG_ReadByte() : ent->baseline.frame;	i = (bits & U_COLORMAP) ? MSG_ReadByte() : ent->baseline.colormap;	if (!i) {		ent->colormap = vid.colormap;	} else {		if (i > cl.maxclients)			Sys_Error("i >= cl.maxclients");		ent->colormap = cl.scores[i-1].translations;	} 	ent->skinnum = (bits & U_SKIN) ? MSG_ReadByte() : ent->baseline.skin;	ent->effects = (bits & U_EFFECTS) ? MSG_ReadByte() : ent->baseline.effects; 	// shift the known values for interpolation	VectorCopy(ent->msg_origins[0], ent->msg_origins[1]);	VectorCopy(ent->msg_angles[0], ent->msg_angles[1]); 	ent->msg_origins[0][0] = (bits & U_ORIGIN1) ? MSG_ReadCoord() : ent->baseline.origin[0];	ent->msg_angles[0][0] = (bits & U_ANGLE1) ? MSG_ReadAngle() : ent->baseline.angles[0];	ent->msg_origins[0][1] = (bits & U_ORIGIN2) ? MSG_ReadCoord() : ent->baseline.origin[1];	ent->msg_angles[0][1] = (bits & U_ANGLE2) ? MSG_ReadAngle() : ent->baseline.angles[1];	ent->msg_origins[0][2] = (bits & U_ORIGIN3) ? MSG_ReadCoord() : ent->baseline.origin[2];	ent->msg_angles[0][2] = (bits & U_ANGLE3) ? MSG_ReadAngle() : ent->baseline.angles[2]; 	if (bits & U_NOLERP)		ent->forcelink = true; 	if (forcelink) { // didn't have an update last message		VectorCopy(ent->msg_origins[0], ent->msg_origins[1]);		VectorCopy(ent->msg_origins[0], ent->origin);		VectorCopy(ent->msg_angles[0], ent->msg_angles[1]);		VectorCopy(ent->msg_angles[0], ent->angles);		ent->forcelink = true;	}} voidCL_ParseBaseline(entity_t *ent){	int i; 	ent->baseline.modelindex = MSG_ReadByte();	ent->baseline.frame = MSG_ReadByte();	ent->baseline.colormap = MSG_ReadByte();	ent->baseline.skin = MSG_ReadByte();	for (i = 0; i < 3; i++) {		ent->baseline.origin[i] = MSG_ReadCoord();		ent->baseline.angles[i] = MSG_ReadAngle();	}} voidCL_ParseClientdata(int bits){	int i, j; 	cl.viewheight = (bits & SU_VIEWHEIGHT) ? MSG_ReadChar() : DEFAULT_VIEWHEIGHT;	cl.idealpitch = (bits & SU_IDEALPITCH) ? MSG_ReadChar() : 0; 	VectorCopy(cl.mvelocity[0], cl.mvelocity[1]);	for (i = 0; i < 3; i++) {		cl.punchangle[i] = (bits & (SU_PUNCH1<<i)) ? MSG_ReadChar() : 0;		cl.mvelocity[0][i] = (bits & (SU_VELOCITY1<<i)) ? MSG_ReadChar()*16 : 0;	} 	// [always sent] if (bits & SU_ITEMS)	i = MSG_ReadLong(); 	if (cl.items != i) { // set flash times		Sbar_Changed ();		for (j = 0; j < 32; j++) {			if ((i & (1<<j)) && !(cl.items & (1<<j)))				cl.item_gettime[j] = cl.time;		}		cl.items = i;	} 	cl.onground = (bits & SU_ONGROUND) != 0;	cl.inwater = (bits & SU_INWATER) != 0; 	cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0; 	i = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;	if (cl.stats[STAT_ARMOR] != i) {		cl.stats[STAT_ARMOR] = i;		Sbar_Changed();	} 	i = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;	if (cl.stats[STAT_WEAPON] != i) {		cl.stats[STAT_WEAPON] = i;		Sbar_Changed();	} 	i = MSG_ReadShort();	if (cl.stats[STAT_HEALTH] != i) {		cl.stats[STAT_HEALTH] = i;		Sbar_Changed();	} 	i = MSG_ReadByte();	if (cl.stats[STAT_AMMO] != i) {		cl.stats[STAT_AMMO] = i;		Sbar_Changed();	} 	for (i = 0; i < 4; i++) {		j = MSG_ReadByte();		if (cl.stats[STAT_SHELLS+i] != j) {			cl.stats[STAT_SHELLS+i] = j;			Sbar_Changed();		}	} 	i = MSG_ReadByte(); 	if (standard_quake) {		if (cl.stats[STAT_ACTIVEWEAPON] != i) {			cl.stats[STAT_ACTIVEWEAPON] = i;			Sbar_Changed();		}	} else {		if (cl.stats[STAT_ACTIVEWEAPON] != (1<<i)) {			cl.stats[STAT_ACTIVEWEAPON] = (1<<i);			Sbar_Changed();		}	}} voidCL_NewTranslation(int slot){	int i, j;	int top, bottom;	uint8_t *dest, *source; 	if (slot > cl.maxclients)		Sys_Error("CL_NewTranslation: slot > cl.maxclients");	dest = cl.scores[slot].translations;	source = vid.colormap;	memmove(dest, vid.colormap, sizeof(cl.scores[slot].translations));	top = cl.scores[slot].colors & 0xf0;	bottom = (cl.scores[slot].colors &15)<<4; 	for (i = 0; i < VID_GRADES; i++, dest += 256, source += 256) {		if (top < 128) // the artists made some backwards ranges. sigh.			memmove(dest + TOP_RANGE, source + top, 16);		else			for (j = 0; j < 16; j++)				dest[TOP_RANGE+j] = source[top+15-j]; 		if (bottom < 128)			memmove(dest + BOTTOM_RANGE, source + bottom, 16);		else			for (j = 0; j < 16; j++)				dest[BOTTOM_RANGE+j] = source[bottom+15-j];	}} voidCL_ParseStatic(void){	entity_t *ent;	int i; 	i = cl.num_statics;	if (i >= MAX_STATIC_ENTITIES)		Host_Error("Too many static entities");	ent = &cl_static_entities[i];	cl.num_statics++;	CL_ParseBaseline(ent); 	// copy it to the current state	ent->model = cl.model_precache[ent->baseline.modelindex];	ent->frame = ent->baseline.frame;	ent->colormap = vid.colormap;	ent->skinnum = ent->baseline.skin;	ent->effects = ent->baseline.effects; 	VectorCopy(ent->baseline.origin, ent->origin);	VectorCopy(ent->baseline.angles, ent->angles);	R_AddEfrags(ent);} voidCL_ParseStaticSound (void){	vec3_t org;

Lines 1–500 of 741.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t