Sigrid Solveig HaflínudóttirCL_ParseUpdate: remove bitcounts636ce8d1 year agoHistory
785 lines · 20.7 KB · C
RawDownload
#include "quakedef.h" static const char *svc_strings[] = {	[svc_bad] = "svc_bad",	[svc_nop] = "svc_nop",	[svc_disconnect] = "svc_disconnect",	[svc_updatestat] = "svc_updatestat",	[svc_version] = "svc_version", // [long] server version	[svc_setview] = "svc_setview", // [short] entity number	[svc_sound] = "svc_sound", // <see code>	[svc_time] = "svc_time", // [float] server time	[svc_print] = "svc_print", // [string] null terminated string	[svc_stufftext] = "svc_stufftext", // [string] stuffed into client's console buffer									   // the string should be \n terminated	[svc_setangle] = "svc_setangle", // [vec3] set the view angle to this absolute value	[svc_serverinfo] = "svc_serverinfo", // [long] version										 // [string] signon string										 // [string]..[0]model cache [string]...[0]sounds cache										 // [string]..[0]item cache	[svc_lightstyle] = "svc_lightstyle", // [byte] [string]	[svc_updatename] = "svc_updatename", // [byte] [string]	[svc_updatefrags] = "svc_updatefrags", // [byte] [short]	[svc_clientdata] = "svc_clientdata", // <shortbits + data>	[svc_stopsound] = "svc_stopsound", // <see code>	[svc_updatecolors] = "svc_updatecolors", // [byte] [byte]	[svc_particle] = "svc_particle", // [vec3] <variable>	[svc_damage] = "svc_damage", // [byte] impact [byte] blood [vec3] from	[svc_spawnstatic] = "svc_spawnstatic",	[svc_spawnbinary] = "OBSOLETE svc_spawnbinary",	[svc_spawnbaseline] = "svc_spawnbaseline",	[svc_temp_entity] = "svc_temp_entity", // <variable>	[svc_setpause] = "svc_setpause",	[svc_signonnum] = "svc_signonnum",	[svc_centerprint] = "svc_centerprint",	[svc_killedmonster] = "svc_killedmonster",	[svc_foundsecret] = "svc_foundsecret",	[svc_spawnstaticsound] = "svc_spawnstaticsound",	[svc_intermission] = "svc_intermission",	[svc_finale] = "svc_finale", // [string] music [string] text	[svc_cdtrack] = "svc_cdtrack", // [byte] track [byte] looptrack	[svc_sellscreen] = "svc_sellscreen",	[svc_cutscene] = "svc_cutscene",	[svc_spawnbaseline2] = "svc_spawnbaseline2",	[svc_spawnstatic2] = "svc_spawnstatic2",	[svc_spawnstaticsound2] = "svc_spawnstaticsound2",	[svc_showlmp] = "svc_showlmp",	[svc_hidelmp] = "svc_hidelmp",	[svc_skybox] = "svc_skybox",	[svc_skyboxsize] = "svc_skyboxsize",	[svc_fog] = "svc_fog",}; /* This error checks and tracks the total number of entities */static entity_t *CL_EntityNum(int num){	if(num >= cl.num_entities) {		if(num >= MAX_EDICTS)			Host_Error("CL_EntityNum: %d 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];} static voidCL_ParseStartSoundPacket(void){	int channel, ent, sound_num, field_mask;	float volume, attenuation;	vec3_t pos; 	field_mask = MSG_ReadByte();	volume = (field_mask & SND_VOLUME) ? MSG_ReadByte() : Spktvol;	attenuation = (field_mask & SND_ATTENUATION) ? MSG_ReadByte() / 64.0 : Spktatt;	if(field_mask & (cl.protocol.fl_large_entity | cl.protocol.fl_large_channel)) {		ent = MSG_ReadShort();		channel = MSG_ReadByte();	} else {		channel = MSG_ReadShort();		ent = channel >> 3;		channel &= 7;	}	sound_num = (field_mask & cl.protocol.fl_large_sound) ? MSG_ReadShort() : MSG_ReadByte(); 	if(ent >= MAX_EDICTS)		Host_Error("CL_ParseStartSoundPacket: ent = %d", ent); 	MSG_ReadVec(cl.protocol, pos);	startsfx(ent, channel, cl.sound_precache[sound_num], pos, volume / 255.0, attenuation);} /* * When the client is taking a long time to load stuff, send keepalive messages * so the server doesn't disconnect. */static voidCL_KeepaliveMessage(void){	static byte olddata[NET_MAXMESSAGE];	static float lastmsg;	sizebuf_t old;	float time;	int ret; 	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 = readcl();		switch(ret) {		default:			Host_Error("CL_KeepaliveMessage: readcl 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 = dtime();	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);} static voidCL_ParseServerInfo(void){	static char model_precache[MAX_MODELS][Npath], sound_precache[MAX_SOUNDS][Npath];	int i, n, nummodels, numsounds;	char *str, *e;	void *p; 	Con_DPrintf("CL_ParseServerInfo: parsing serverinfo pkt...\n");	CL_ClearState(); 	// parse protocol version number	i = MSG_ReadLong();	p = nil;	for(n = 0; n < nelem(protos); n++) {		if(protos[n].version == i) {			p = &protos[n];			break;		}	}	if(p == nil) {		Con_Printf("Server returned unknown protocol version %d", i);		return;	}	memmove(&cl.protocol, p, sizeof(cl.protocol));	cl.protocol.MSG_ReadProtocolInfo(&cl.protocol); 	// parse maxclients	cl.maxclients = MSG_ReadByte();	if(cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD) {		Con_Printf("Bad maxclients (%d) from server\n", cl.maxclients);		return;	}	cl.scores = Hunk_Alloc(cl.maxclients * sizeof(*cl.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));	sfxbegin();	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);		touchsfx(str);	}	sfxend(); 	// 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] == nil) {			Con_Printf("Model %s not found\n", model_precache[i]);			return;		}		CL_KeepaliveMessage();	} 	for(i = 1; i < numsounds; i++) {		cl.sound_precache[i] = precachesfx(sound_precache[i]);		CL_KeepaliveMessage();	} 	// local state	cl_entities[0].model = cl.worldmodel = cl.model_precache[1];	if((str = strchr(model_precache[1], '/')) != nil) {		str++;		if((e = strrchr(model_precache[1], '.')) != nil)			*e = 0;	}	setcvar("mapname", str == nil ? "<invalid>" : str); 	R_NewMap();	V_NewMap();	CL_NewMap(); 	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. */static voidCL_ParseUpdate(int bits){	int modnum, num, skin, colormap;	model_t *model;	bool forcelink;	entity_t *ent; 	if(cls.signon == SIGNONS - 1) { // first update is the final signon stage		cls.signon = SIGNONS;		CL_SignonReply();	} 	if(bits & U_MOREBITS) {		bits |= MSG_ReadByte() << 8;		if(bits & U_MOREBITS2) {			bits |= MSG_ReadByte() << 16;			if(bits & U_MOREBITS3)				bits |= MSG_ReadByte() << 24;		}		if(bits == -1)			Host_Error("CL_ParseUpdate: unexpected EOF while reading extended bits");	} 	num = (bits & U_LONGENTITY) ? MSG_ReadShort() : MSG_ReadByte();	ent = CL_EntityNum(num); 	forcelink = ent->msgtime != cl.mtime[1]; // no previous frame to lerp from	ent->msgtime = cl.mtime[0]; 	// shift the known values for interpolation	VectorCopy(ent->msg_origins[0], ent->msg_origins[1]);	VectorCopy(ent->msg_angles[0], ent->msg_angles[1]); 	modnum = (bits & U_MODEL) ? MSG_ReadByte() : ent->baseline.modelindex;	ent->frame = (bits & U_FRAME) ? MSG_ReadByte() : ent->baseline.frame;	colormap = (bits & U_COLORMAP) ? MSG_ReadByte() : ent->baseline.colormap;	skin = (bits & U_SKIN) ? MSG_ReadByte() : ent->baseline.skin;	ent->effects = (bits & U_EFFECTS) ? MSG_ReadByte() : ent->baseline.effects; 	if(colormap == 0)		ent->colormap = vid.colormap;	else if(colormap > cl.maxclients)		fatal("colormap > cl.maxclients");	else		ent->colormap = cl.scores[colormap - 1].translations; 	if(skin != ent->skinnum && num >= 0) {		// FIXME(sigrid): update the skin		ent->skinnum = skin;	} 	ent->msg_origins[0][0] =		(bits & U_ORIGIN1) ? cl.protocol.MSG_ReadCoord() : ent->baseline.origin[0];	ent->msg_angles[0][0] =		(bits & U_ANGLE1) ? cl.protocol.MSG_ReadAngle() : ent->baseline.angles[0];	ent->msg_origins[0][1] =		(bits & U_ORIGIN2) ? cl.protocol.MSG_ReadCoord() : ent->baseline.origin[1];	ent->msg_angles[0][1] =		(bits & U_ANGLE2) ? cl.protocol.MSG_ReadAngle() : ent->baseline.angles[1];	ent->msg_origins[0][2] =		(bits & U_ORIGIN3) ? cl.protocol.MSG_ReadCoord() : ent->baseline.origin[2];	ent->msg_angles[0][2] =		(bits & U_ANGLE3) ? cl.protocol.MSG_ReadAngle() : ent->baseline.angles[2]; 	ent->alpha = (bits & cl.protocol.fl_alpha) ? MSG_ReadByte() : ent->baseline.alpha; 	if(bits & U_NOLERP)		ent->forcelink = true; 	if(bits & cl.protocol.fl_large_frame)		ent->frame |= MSG_ReadByte() << 8;	if(bits & cl.protocol.fl_large_model)		modnum |= MSG_ReadByte() << 8; 	if(modnum < 0 || modnum >= MAX_MODELS)		Host_Error("CL_ParseModel: bad modnum: %d (bits 0x%08ux)", modnum, bits);	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) {			if(model->synctype == ST_RAND)				ent->syncbase = (float)(rand() & 0x7fff) / 0x7fff;			else				ent->syncbase = 0.0;		} else			forcelink = true; // hack to make null model players work	} 	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;	}} static voidCL_ParseBaseline(int withbits, entity_t *ent){	int i, bits; 	bits = withbits ? MSG_ReadByte() : 0;	ent->baseline.modelindex =		(bits & cl.protocol.fl_large_baseline_model) ? MSG_ReadShort() : MSG_ReadByte();	ent->baseline.frame =		(bits & cl.protocol.fl_large_baseline_frame) ? MSG_ReadShort() : MSG_ReadByte();	ent->baseline.colormap = MSG_ReadByte();	ent->baseline.skin = MSG_ReadByte();	for(i = 0; i < 3; i++) {		ent->baseline.origin[i] = cl.protocol.MSG_ReadCoord();		ent->baseline.angles[i] = cl.protocol.MSG_ReadAngle();	}	ent->baseline.alpha = (bits & cl.protocol.fl_baseline_alpha) ? MSG_ReadByte() : DEFAULT_ALPHA;	ent->baseline.effects = (bits & cl.protocol.fl_baseline_effects) ? MSG_ReadByte() : 0;} /* Server information pertaining to this client only */static voidCL_ParseClientdata(unsigned int bits){	unsigned int i, j, weaponmodel; 	if(bits & SU_MOREBITS) {		bits |= MSG_ReadByte() << 16;		if(bits & SU_MOREBITS2)			bits |= MSG_ReadByte() << 24;	} 	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;	} 	i = (bits & SU_ITEMS) ? (unsigned)MSG_ReadLong() : cl.items;	if(cl.items != i) { // set flash times		for(j = 0; j < 32; j++)			if((i & (1U << j)) && !(cl.items & (1U << 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;	cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;	weaponmodel = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;	cl.stats[STAT_HEALTH] = MSG_ReadShort();	cl.stats[STAT_AMMO] = MSG_ReadByte(); 	for(i = 0; i < 4; i++)		cl.stats[STAT_SHELLS + i] = MSG_ReadByte(); 	i = MSG_ReadByte();	cl.stats[STAT_ACTIVEWEAPON] = standard_quake ? i : (1U << i); 	if(bits & cl.protocol.fl_large_weaponmodel)		weaponmodel |= MSG_ReadByte() << 8;	cl.stats[STAT_WEAPON] = weaponmodel; 	if(bits & cl.protocol.fl_large_weaponframe)		cl.stats[STAT_WEAPONFRAME] |= MSG_ReadByte() << 8;	cl.viewent.alpha = (bits & cl.protocol.fl_weapon_alpha) ? MSG_ReadByte() : DEFAULT_ALPHA; 	if(cl.viewent.model != cl.model_precache[cl.stats[STAT_WEAPON]]) {		// FIXME(sigrid) - reset lerp	}} static voidCL_NewTranslation(int slot){	int i, j, top, bottom;	pixel_t *dest, *source; 	if(slot > cl.maxclients)		fatal("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 * sizeof(pixel_t));		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 * sizeof(pixel_t));		else			for(j = 0; j < 16; j++)				dest[BOTTOM_RANGE + j] = source[bottom + 15 - j];	}} static voidCL_ParseStatic(int withbits){	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(withbits, ent); 	// copy it to the current state	ent->model = cl.model_precache[ent->baseline.modelindex];	ent->alpha = ent->baseline.alpha;	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);}

Lines 1–500 of 785.

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