/* ================= FlushEntityPacket ================= */ void FlushEntityPacket (void) { int word; entity_state_t olde, newe; Con_DPrintf ("FlushEntityPacket\n"); memset (&olde, 0, sizeof(olde)); cl.validsequence = 0; // can't render a frame cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].invalid = true; // read it all, but ignore it while (1) { word = (unsigned short)MSG_ReadShort (); if (msg_badread) { // something didn't parse right... Host_EndGame ("msg_badread in packetentities"); return; } if (!word) break; // done CL_ParseDelta (&olde, &newe, word); } }
/* * Parses deltas from the given base and adds the resulting entity to * the current frame */ void CL_DeltaEntity(frame_t *frame, int newnum, entity_state_t *old, int bits) { centity_t *ent; entity_state_t *state; ent = &cl_entities[newnum]; state = &cl_parse_entities[cl.parse_entities & (MAX_PARSE_ENTITIES - 1)]; cl.parse_entities++; frame->num_entities++; CL_ParseDelta(old, state, newnum, bits); /* some data changes will force no lerping */ if ((state->modelindex != ent->current.modelindex) || (state->modelindex2 != ent->current.modelindex2) || (state->modelindex3 != ent->current.modelindex3) || (state->modelindex4 != ent->current.modelindex4) || (state->event == EV_PLAYER_TELEPORT) || (state->event == EV_OTHER_TELEPORT) || (abs((int)(state->origin[0] - ent->current.origin[0])) > 512) || (abs((int)(state->origin[1] - ent->current.origin[1])) > 512) || (abs((int)(state->origin[2] - ent->current.origin[2])) > 512) ) { ent->serverframe = -99; } /* wasn't in last update, so initialize some things */ if (ent->serverframe != cl.frame.serverframe - 1) { ent->trailcount = 1024; /* for diminishing rocket / grenade trails */ /* duplicate the current state so lerping doesn't hurt anything */ ent->prev = *state; if (state->event == EV_OTHER_TELEPORT) { VectorCopy(state->origin, ent->prev.origin); VectorCopy(state->origin, ent->lerp_origin); } else { VectorCopy(state->old_origin, ent->prev.origin); VectorCopy(state->old_origin, ent->lerp_origin); } } else { /* shuffle the last state to previous */ ent->prev = ent->current; } ent->serverframe = cl.frame.serverframe; ent->current = *state; }
/* ================== CL_ParseBaseline ================== */ void CL_ParseBaseline (void) { entity_state_t *es; uint32 bits; int newnum; newnum = CL_ParseEntityBits (&bits); es = &cl_entities[newnum].baseline; CL_ParseDelta (&null_entity_state, es, newnum, bits); }
/* ================== CL_ParseBaseline ================== */ void CL_ParseBaseline(void) { entity_state_t * es; int bits; int newnum; entity_state_t nullstate; memset(&nullstate, 0, sizeof(nullstate)); newnum = CL_ParseEntityBits(&bits); es = &cl_entities[newnum].baseline; CL_ParseDelta(&nullstate, es, newnum, bits); }
/* ================== CL_ParsePacketEntities An svc_packetentities has just been parsed, deal with the rest of the data stream. ================== */ void CL_ParsePacketEntities (qboolean delta) { int oldpacket, newpacket; packet_entities_t *oldp, *newp, dummy; int oldindex, newindex; int word, newnum, oldnum; qboolean full; byte from; newpacket = cls.netchan.incoming_sequence&UPDATE_MASK; newp = &cl.frames[newpacket].packet_entities; cl.frames[newpacket].invalid = false; if (delta) { from = MSG_ReadByte (); oldpacket = cl.frames[newpacket].delta_sequence; if ( (from&UPDATE_MASK) != (oldpacket&UPDATE_MASK) ) Con_DPrintf ("WARNING: from mismatch\n"); } else oldpacket = -1; full = false; if (oldpacket != -1) { if (cls.netchan.outgoing_sequence - oldpacket >= UPDATE_BACKUP-1) { // we can't use this, it is too old FlushEntityPacket (); return; } cl.validsequence = cls.netchan.incoming_sequence; oldp = &cl.frames[oldpacket&UPDATE_MASK].packet_entities; } else { // this is a full update that we can start delta compressing from now oldp = &dummy; dummy.num_entities = 0; cl.validsequence = cls.netchan.incoming_sequence; full = true; } oldindex = 0; newindex = 0; newp->num_entities = 0; while (1) { word = (unsigned short)MSG_ReadShort (); if (msg_badread) { // something didn't parse right... Host_EndGame ("msg_badread in packetentities"); return; } if (!word) { while (oldindex < oldp->num_entities) { // copy all the rest of the entities from the old packet //Con_Printf ("copy %i\n", oldp->entities[oldindex].number); if (newindex >= MAX_PACKET_ENTITIES) Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES ... 1"); newp->entities[newindex] = oldp->entities[oldindex]; newindex++; oldindex++; } break; } newnum = word&511; oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; while (newnum > oldnum) { if (full) { Con_Printf ("WARNING: oldcopy on full update"); FlushEntityPacket (); return; } //Con_Printf ("copy %i\n", oldnum); // copy one of the old entities over to the new packet unchanged if (newindex >= MAX_PACKET_ENTITIES) Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES ... 2"); newp->entities[newindex] = oldp->entities[oldindex]; newindex++; oldindex++; oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; } if (newnum < oldnum) { // new from baseline //Con_Printf ("baseline %i\n", newnum); if (word & U_REMOVE) { if (full) { cl.validsequence = 0; Con_Printf ("WARNING: U_REMOVE on full update\n"); FlushEntityPacket (); return; } continue; } if (newindex >= MAX_PACKET_ENTITIES) Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES ... 3"); CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], word); newindex++; continue; } if (newnum == oldnum) { // delta from previous if (full) { cl.validsequence = 0; Con_Printf ("WARNING: delta on full update"); } if (word & U_REMOVE) { oldindex++; continue; } //Con_Printf ("delta %i\n",newnum); CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word); newindex++; oldindex++; } } newp->num_entities = newindex; }