X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=protocol.c;h=cfa837bf51d4f6266b72217372c953e1933dad45;hb=fe0d5dc2d85167fb8042bcb5157e93728e74e53a;hp=91e0b7cbc88cdc8b4a1fbbc70b2085ef09fd51a4;hpb=7d08a8ba9d7925d79b903a087b97357968e011de;p=xonotic%2Fdarkplaces.git diff --git a/protocol.c b/protocol.c index 91e0b7cb..cfa837bf 100644 --- a/protocol.c +++ b/protocol.c @@ -1,6 +1,8 @@ #include "quakedef.h" +#define E5_PROTOCOL_PRIORITYLEVELS 32 + // this is 88 bytes (must match entity_state_t in protocol.h) entity_state_t defaultstate = { @@ -60,6 +62,17 @@ protocolversioninfo[] = {0, NULL} }; +static mempool_t *sv2csqc = NULL; +int csqc_clent = 0; +sizebuf_t *sv2csqcbuf = NULL; +static unsigned char *sv2csqcents_version[MAX_SCOREBOARD]; + +static entity_frame_t deltaframe; // FIXME? +static entity_frame_t framedata; // FIXME? + +int entityframe5_prioritychaincounts[E5_PROTOCOL_PRIORITYLEVELS]; +unsigned short entityframe5_prioritychains[E5_PROTOCOL_PRIORITYLEVELS][ENTITYFRAME5_MAXSTATES]; + protocolversion_t Protocol_EnumForName(const char *s) { int i; @@ -102,10 +115,6 @@ void Protocol_Names(char *buffer, size_t buffersize) } } -// keep track of quake entities because they need to be killed if they get stale -int cl_lastquakeentity = 0; -unsigned char cl_isquakeentity[MAX_EDICTS]; - void EntityFrameQuake_ReadEntity(int bits) { int num; @@ -131,14 +140,14 @@ void EntityFrameQuake_ReadEntity(int bits) if (num < 1) Host_Error("EntityFrameQuake_ReadEntity: invalid entity number (%i)", num); - if (cl_num_entities <= num) + if (cl.num_entities <= num) { - cl_num_entities = num + 1; - if (num >= cl_max_entities) + cl.num_entities = num + 1; + if (num >= cl.max_entities) CL_ExpandEntities(num); } - ent = cl_entities + num; + ent = cl.entities + num; // note: this inherits the 'active' state of the baseline chosen // (state_baseline is always active, state_current may not be active if @@ -151,9 +160,9 @@ void EntityFrameQuake_ReadEntity(int bits) s.active = true; } - cl_isquakeentity[num] = true; - if (cl_lastquakeentity < num) - cl_lastquakeentity = num; + cl.isquakeentity[num] = true; + if (cl.lastquakeentity < num) + cl.lastquakeentity = num; s.number = num; s.time = cl.mtime[0]; s.flags = 0; @@ -185,11 +194,11 @@ void EntityFrameQuake_ReadEntity(int bits) if (cls.protocol == PROTOCOL_NEHAHRAMOVIE && (bits & U_EXTEND1)) { // LordHavoc: evil format - int i = MSG_ReadFloat(); - int j = MSG_ReadFloat() * 255.0f; + int i = (int)MSG_ReadFloat(); + int j = (int)(MSG_ReadFloat() * 255.0f); if (i == 2) { - i = MSG_ReadFloat(); + i = (int)MSG_ReadFloat(); if (i) s.effects |= EF_FULLBRIGHT; } @@ -206,7 +215,7 @@ void EntityFrameQuake_ReadEntity(int bits) if (ent->state_current.active) { CL_MoveLerpEntityStates(ent); - cl_entities_active[ent->state_current.number] = true; + cl.entities_active[ent->state_current.number] = true; } if (msg_badread) @@ -216,35 +225,30 @@ void EntityFrameQuake_ReadEntity(int bits) void EntityFrameQuake_ISeeDeadEntities(void) { int num, lastentity; - if (cl_lastquakeentity == 0) + if (cl.lastquakeentity == 0) return; - lastentity = cl_lastquakeentity; - cl_lastquakeentity = 0; + lastentity = cl.lastquakeentity; + cl.lastquakeentity = 0; for (num = 0;num <= lastentity;num++) { - if (cl_isquakeentity[num]) + if (cl.isquakeentity[num]) { - if (cl_entities_active[num] && cl_entities[num].state_current.time == cl.mtime[0]) + if (cl.entities_active[num] && cl.entities[num].state_current.time == cl.mtime[0]) { - cl_isquakeentity[num] = true; - cl_lastquakeentity = num; + cl.isquakeentity[num] = true; + cl.lastquakeentity = num; } else { - cl_isquakeentity[num] = false; - cl_entities_active[num] = false; - cl_entities[num].state_current = defaultstate; - cl_entities[num].state_current.number = num; + cl.isquakeentity[num] = false; + cl.entities_active[num] = false; + cl.entities[num].state_current = defaultstate; + cl.entities[num].state_current.number = num; } } } } -static mempool_t *sv2csqc = NULL; -int csqc_clent = 0; -sizebuf_t *sv2csqcbuf = NULL; -static unsigned char *sv2csqcents_version[64]; - void EntityFrameCSQC_ClearVersions (void) { if(sv2csqc) @@ -252,7 +256,7 @@ void EntityFrameCSQC_ClearVersions (void) Mem_FreePool(&sv2csqc); sv2csqc = NULL; } - memset(sv2csqcents_version, 0, 64*sizeof(unsigned char *)); + memset(sv2csqcents_version, 0, MAX_SCOREBOARD*sizeof(unsigned char *)); } void EntityFrameCSQC_InitClientVersions (int client, qboolean clear) @@ -264,7 +268,7 @@ void EntityFrameCSQC_InitClientVersions (int client, qboolean clear) Mem_Free(sv2csqcents_version[client]); sv2csqcents_version[client] = NULL; } - sv2csqcents_version[client] = Mem_Alloc(sv2csqc, MAX_EDICTS); + sv2csqcents_version[client] = (unsigned char *)Mem_Alloc(sv2csqc, MAX_EDICTS); memset(sv2csqcents_version[client], 0, MAX_EDICTS); } @@ -278,7 +282,7 @@ void EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int numstates, const entity_sta prvm_eval_t *val, *val2; int csqcents = 0; - if(!eval_SendEntity || !eval_Version) + if(prog->fieldoffsets.SendEntity < 0 || prog->fieldoffsets.Version < 0) return; --csqc_clent; if(!sv2csqcents_version[csqc_clent]) @@ -319,10 +323,10 @@ void EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int numstates, const entity_sta // if(!s->active) // continue; - val = PRVM_GETEDICTFIELDVALUE((&prog->edicts[s->number]), eval_SendEntity); + val = PRVM_EDICTFIELDVALUE((&prog->edicts[s->number]), prog->fieldoffsets.SendEntity); if(val->function) { - val2 = PRVM_GETEDICTFIELDVALUE((&prog->edicts[s->number]), eval_Version); + val2 = PRVM_EDICTFIELDVALUE((&prog->edicts[s->number]), prog->fieldoffsets.Version); if(sv2csqcents_version[csqc_clent][s->number] == (unsigned char)val2->_float) continue; if(!csqcents) @@ -387,7 +391,7 @@ void EntityFrameQuake_WriteFrame(sizebuf_t *msg, int numstates, const entity_sta for (i = 0, s = states;i < numstates;i++, s++) { - val = PRVM_GETEDICTFIELDVALUE((&prog->edicts[s->number]), eval_SendEntity); + val = PRVM_EDICTFIELDVALUE((&prog->edicts[s->number]), prog->fieldoffsets.SendEntity); if(val && val->function) continue; @@ -1007,7 +1011,6 @@ void EntityFrame_AddFrame(entityframe_database_t *d, vec3_t eye, int framenum, i } // (server) writes a frame to network stream -static entity_frame_t deltaframe; // FIXME? void EntityFrame_WriteFrame(sizebuf_t *msg, entityframe_database_t *d, int numstates, const entity_state_t *states, int viewentnum) { int i, onum, number; @@ -1045,7 +1048,7 @@ void EntityFrame_WriteFrame(sizebuf_t *msg, entityframe_database_t *d, int numst ent = states + i; number = ent->number; - val = PRVM_GETEDICTFIELDVALUE((&prog->edicts[number]), eval_SendEntity); + val = PRVM_EDICTFIELDVALUE((&prog->edicts[number]), prog->fieldoffsets.SendEntity); if(val && val->function) continue; for (;onum < o->numentities && o->entitydata[onum].number < number;onum++) @@ -1076,7 +1079,6 @@ void EntityFrame_WriteFrame(sizebuf_t *msg, entityframe_database_t *d, int numst } // (client) reads a frame from network stream -static entity_frame_t framedata; // FIXME? void EntityFrame_CL_ReadFrame(void) { int i, number, removed; @@ -1085,7 +1087,7 @@ void EntityFrame_CL_ReadFrame(void) entity_t *ent; entityframe_database_t *d; if (!cl.entitydatabase) - cl.entitydatabase = EntityFrame_AllocDatabase(cl_mempool); + cl.entitydatabase = EntityFrame_AllocDatabase(cls.levelmempool); d = cl.entitydatabase; EntityFrame_Clear(f, NULL, -1); @@ -1147,13 +1149,13 @@ void EntityFrame_CL_ReadFrame(void) *e = defaultstate; } - if (cl_num_entities <= number) + if (cl.num_entities <= number) { - cl_num_entities = number + 1; - if (number >= cl_max_entities) + cl.num_entities = number + 1; + if (number >= cl.max_entities) CL_ExpandEntities(number); } - cl_entities_active[number] = true; + cl.entities_active[number] = true; e->active = true; e->time = cl.mtime[0]; e->number = number; @@ -1169,35 +1171,35 @@ void EntityFrame_CL_ReadFrame(void) } EntityFrame_AddFrame(d, f->eye, f->framenum, f->numentities, f->entitydata); - memset(cl_entities_active, 0, cl_num_entities * sizeof(unsigned char)); + memset(cl.entities_active, 0, cl.num_entities * sizeof(unsigned char)); number = 1; for (i = 0;i < f->numentities;i++) { - for (;number < f->entitydata[i].number && number < cl_num_entities;number++) + for (;number < f->entitydata[i].number && number < cl.num_entities;number++) { - if (cl_entities_active[number]) + if (cl.entities_active[number]) { - cl_entities_active[number] = false; - cl_entities[number].state_current.active = false; + cl.entities_active[number] = false; + cl.entities[number].state_current.active = false; } } - if (number >= cl_num_entities) + if (number >= cl.num_entities) break; // update the entity - ent = &cl_entities[number]; + ent = &cl.entities[number]; ent->state_previous = ent->state_current; ent->state_current = f->entitydata[i]; CL_MoveLerpEntityStates(ent); // the entity lives again... - cl_entities_active[number] = true; + cl.entities_active[number] = true; number++; } - for (;number < cl_num_entities;number++) + for (;number < cl.num_entities;number++) { - if (cl_entities_active[number]) + if (cl.entities_active[number]) { - cl_entities_active[number] = false; - cl_entities[number].state_current.active = false; + cl.entities_active[number] = false; + cl.entities[number].state_current.active = false; } } } @@ -1355,7 +1357,7 @@ void EntityFrame4_CL_ReadFrame(void) entity_state_t *s; entityframe4_database_t *d; if (!cl.entitydatabase4) - cl.entitydatabase4 = EntityFrame4_AllocDatabase(cl_mempool); + cl.entitydatabase4 = EntityFrame4_AllocDatabase(cls.levelmempool); d = cl.entitydatabase4; // read the number of the frame this refers to referenceframenum = MSG_ReadLong(); @@ -1410,10 +1412,10 @@ void EntityFrame4_CL_ReadFrame(void) // high bit means it's a remove message cnumber = n & 0x7FFF; // if this is a live entity we may need to expand the array - if (cl_num_entities <= cnumber && !(n & 0x8000)) + if (cl.num_entities <= cnumber && !(n & 0x8000)) { - cl_num_entities = cnumber + 1; - if (cnumber >= cl_max_entities) + cl.num_entities = cnumber + 1; + if (cnumber >= cl.max_entities) CL_ExpandEntities(cnumber); } // add one (the changed one) if not done @@ -1421,7 +1423,7 @@ void EntityFrame4_CL_ReadFrame(void) // process entities in range from the last one to the changed one for (;enumber < stopnumber;enumber++) { - if (skip || enumber >= cl_num_entities) + if (skip || enumber >= cl.num_entities) { if (enumber == cnumber && (n & 0x8000) == 0) { @@ -1431,10 +1433,10 @@ void EntityFrame4_CL_ReadFrame(void) continue; } // slide the current into the previous slot - cl_entities[enumber].state_previous = cl_entities[enumber].state_current; + cl.entities[enumber].state_previous = cl.entities[enumber].state_current; // copy a new current from reference database - cl_entities[enumber].state_current = *EntityFrame4_GetReferenceEntity(d, enumber); - s = &cl_entities[enumber].state_current; + cl.entities[enumber].state_current = *EntityFrame4_GetReferenceEntity(d, enumber); + s = &cl.entities[enumber].state_current; // if this is the one to modify, read more data... if (enumber == cnumber) { @@ -1456,24 +1458,24 @@ void EntityFrame4_CL_ReadFrame(void) } else if (developer_networkentities.integer >= 4) Con_Printf("entity %i: copy\n", enumber); - // set the cl_entities_active flag - cl_entities_active[enumber] = s->active; + // set the cl.entities_active flag + cl.entities_active[enumber] = s->active; // set the update time s->time = cl.mtime[0]; // fix the number (it gets wiped occasionally by copying from defaultstate) s->number = enumber; // check if we need to update the lerp stuff if (s->active) - CL_MoveLerpEntityStates(&cl_entities[enumber]); + CL_MoveLerpEntityStates(&cl.entities[enumber]); // add this to the commit entry whether it is modified or not if (d->currentcommit) - EntityFrame4_AddCommitEntity(d, &cl_entities[enumber].state_current); + EntityFrame4_AddCommitEntity(d, &cl.entities[enumber].state_current); // print extra messages if desired - if (developer_networkentities.integer >= 2 && cl_entities[enumber].state_current.active != cl_entities[enumber].state_previous.active) + if (developer_networkentities.integer >= 2 && cl.entities[enumber].state_current.active != cl.entities[enumber].state_previous.active) { - if (cl_entities[enumber].state_current.active) + if (cl.entities[enumber].state_current.active) Con_Printf("entity #%i has become active\n", enumber); - else if (cl_entities[enumber].state_previous.active) + else if (cl.entities[enumber].state_previous.active) Con_Printf("entity #%i has become inactive\n", enumber); } } @@ -1535,7 +1537,7 @@ void EntityFrame4_WriteFrame(sizebuf_t *msg, entityframe4_database_t *d, int num d->currententitynumber = 1; for (i = 0, n = startnumber;n < prog->max_edicts;n++) { - val = PRVM_GETEDICTFIELDVALUE((&prog->edicts[n]), eval_SendEntity); + val = PRVM_EDICTFIELDVALUE((&prog->edicts[n]), prog->fieldoffsets.SendEntity); if(val && val->function) continue; // find the old state to delta from @@ -1590,8 +1592,6 @@ void EntityFrame4_WriteFrame(sizebuf_t *msg, entityframe4_database_t *d, int num -#define E5_PROTOCOL_PRIORITYLEVELS 32 - entityframe5_database_t *EntityFrame5_AllocDatabase(mempool_t *pool) { int i; @@ -1645,54 +1645,45 @@ void EntityFrame5_ExpandEdicts(entityframe5_database_t *d, int newmax) int EntityState5_Priority(entityframe5_database_t *d, int stateindex) { - int lowprecision, limit, priority; - double distance; - int changedbits; - int age; - entity_state_t *view, *s; - changedbits = d->deltabits[stateindex]; - if (!changedbits) - return 0; - if (!d->states[stateindex].active/* && changedbits & E5_FULLUPDATE*/) + int limit, priority; + entity_state_t *s; + // if it is the player, update urgently + if (stateindex == d->viewentnum) return E5_PROTOCOL_PRIORITYLEVELS - 1; - // check whole attachment chain to judge relevance to player - view = d->states + d->viewentnum; - lowprecision = false; + // priority increases each frame no matter what happens + priority = d->priorities[stateindex] + 1; + // players get an extra priority boost + if (stateindex <= svs.maxclients) + priority++; + // remove dead entities very quickly because they are just 2 bytes + if (!d->states[stateindex].active) + { + priority++; + return bound(1, priority, E5_PROTOCOL_PRIORITYLEVELS - 1); + } + // certain changes are more noticable than others + if (d->deltabits[stateindex] & (E5_FULLUPDATE | E5_ATTACHMENT | E5_MODEL | E5_FLAGS | E5_COLORMAP)) + priority++; + // find the root entity this one is attached to, and judge relevance by it for (limit = 0;limit < 256;limit++) { - if (d->maxedicts < stateindex) - EntityFrame5_ExpandEdicts(d, (stateindex+256)&~255); s = d->states + stateindex; - if (s == view) - return E5_PROTOCOL_PRIORITYLEVELS - 1; if (s->flags & RENDER_VIEWMODEL) - return E5_PROTOCOL_PRIORITYLEVELS - 1; - if (s->flags & RENDER_LOWPRECISION) - lowprecision = true; - if (!s->tagentity) - { - if (VectorCompare(s->origin, view->origin)) - return E5_PROTOCOL_PRIORITYLEVELS - 1; + stateindex = d->viewentnum; + else if (s->tagentity) + stateindex = s->tagentity; + else break; - } - stateindex = s->tagentity; + if (d->maxedicts < stateindex) + EntityFrame5_ExpandEdicts(d, (stateindex+256)&~255); } if (limit >= 256) - { - Con_Printf("Protocol: Runaway loop recursing tagentity links on entity %i\n", stateindex); - return 0; - } - // it's not a viewmodel for this client - distance = VectorDistance(view->origin, s->origin); - age = d->latestframenum - d->updateframenum[stateindex]; - priority = (E5_PROTOCOL_PRIORITYLEVELS / 2) + age - (int)(distance * (E5_PROTOCOL_PRIORITYLEVELS / 16384.0f)); - if (lowprecision) - priority -= (E5_PROTOCOL_PRIORITYLEVELS / 4); - //if (changedbits & E5_FULLUPDATE) - // priority += 4; - //if (changedbits & (E5_ATTACHMENT | E5_MODEL | E5_FLAGS | E5_COLORMAP)) - // priority += 4; - return (int) bound(1, priority, E5_PROTOCOL_PRIORITYLEVELS - 1); + Con_DPrintf("Protocol: Runaway loop recursing tagentity links on entity %i\n", stateindex); + // now that we have the parent entity we can make some decisions based on + // distance from the player + if (VectorDistance(d->states[d->viewentnum].origin, s->origin) < 1024.0f) + priority++; + return bound(1, priority, E5_PROTOCOL_PRIORITYLEVELS - 1); } void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbits, sizebuf_t *msg) @@ -1700,7 +1691,7 @@ void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbi unsigned int bits = 0; prvm_eval_t *val; - val = PRVM_GETEDICTFIELDVALUE((&prog->edicts[s->number]), eval_SendEntity); + val = PRVM_EDICTFIELDVALUE((&prog->edicts[s->number]), prog->fieldoffsets.SendEntity); if(val && val->function) return; @@ -2055,14 +2046,14 @@ void EntityFrame5_CL_ReadFrame(void) // get the entity number enumber = n & 0x7FFF; // we may need to expand the array - if (cl_num_entities <= enumber) + if (cl.num_entities <= enumber) { - cl_num_entities = enumber + 1; - if (enumber >= cl_max_entities) + cl.num_entities = enumber + 1; + if (enumber >= cl.max_entities) CL_ExpandEntities(enumber); } // look up the entity - ent = cl_entities + enumber; + ent = cl.entities + enumber; // slide the current into the previous slot ent->state_previous = ent->state_current; // read the update @@ -2077,21 +2068,21 @@ void EntityFrame5_CL_ReadFrame(void) // update entity EntityState5_ReadUpdate(s); } - // set the cl_entities_active flag - cl_entities_active[enumber] = s->active; + // set the cl.entities_active flag + cl.entities_active[enumber] = s->active; // set the update time s->time = cl.mtime[0]; // fix the number (it gets wiped occasionally by copying from defaultstate) s->number = enumber; // check if we need to update the lerp stuff if (s->active) - CL_MoveLerpEntityStates(&cl_entities[enumber]); + CL_MoveLerpEntityStates(&cl.entities[enumber]); // print extra messages if desired - if (developer_networkentities.integer >= 2 && cl_entities[enumber].state_current.active != cl_entities[enumber].state_previous.active) + if (developer_networkentities.integer >= 2 && cl.entities[enumber].state_current.active != cl.entities[enumber].state_previous.active) { - if (cl_entities[enumber].state_current.active) + if (cl.entities[enumber].state_current.active) Con_Printf("entity #%i has become active\n", enumber); - else if (cl_entities[enumber].state_previous.active) + else if (cl.entities[enumber].state_previous.active) Con_Printf("entity #%i has become inactive\n", enumber); } } @@ -2136,7 +2127,11 @@ void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum) if (bits) { d->deltabits[s->number] |= bits; - d->priorities[s->number] = EntityState5_Priority(d, s->number); + // if it was a very important update, set priority higher + if (bits & (E5_FULLUPDATE | E5_ATTACHMENT | E5_MODEL || E5_COLORMAP)) + d->priorities[s->number] = max(d->priorities[s->number], 4); + else + d->priorities[s->number] = max(d->priorities[s->number], 1); } } // mark lost stats @@ -2166,9 +2161,6 @@ void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum) d->packetlog[i].packetnumber = 0; } -int entityframe5_prioritychaincounts[E5_PROTOCOL_PRIORITYLEVELS]; -unsigned short entityframe5_prioritychains[E5_PROTOCOL_PRIORITYLEVELS][ENTITYFRAME5_MAXSTATES]; - void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats, int movesequence) { const entity_state_t *n; @@ -2222,7 +2214,7 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num { CLEARPVSBIT(d->visiblebits, num); d->deltabits[num] = E5_FULLUPDATE; - d->priorities[num] = EntityState5_Priority(d, num); + d->priorities[num] = max(d->priorities[num], 8); // removal is cheap d->states[num] = defaultstate; d->states[num].number = num; } @@ -2233,10 +2225,13 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num // entity just spawned in, don't let it completely hog priority // because of being ancient on the first frame d->updateframenum[num] = framenum; + // initial priority is a bit high to make projectiles send on the + // first frame, among other things + d->priorities[num] = max(d->priorities[num], 4); } SETPVSBIT(d->visiblebits, num); d->deltabits[num] |= EntityState5_DeltaBits(d->states + num, n); - d->priorities[num] = EntityState5_Priority(d, num); + d->priorities[num] = max(d->priorities[num], 1); d->states[num] = *n; d->states[num].number = num; // advance to next entity so the next iteration doesn't immediately remove it @@ -2249,7 +2244,7 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num { CLEARPVSBIT(d->visiblebits, num); d->deltabits[num] = E5_FULLUPDATE; - d->priorities[num] = EntityState5_Priority(d, num); + d->priorities[num] = max(d->priorities[num], 8); // removal is cheap d->states[num] = defaultstate; d->states[num].number = num; } @@ -2267,6 +2262,8 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num { if (d->priorities[num]) { + if (d->priorities[num] < (E5_PROTOCOL_PRIORITYLEVELS - 1)) + d->priorities[num] = EntityState5_Priority(d, num); l = num; priority = d->priorities[num]; if (entityframe5_prioritychaincounts[priority] < ENTITYFRAME5_MAXSTATES) @@ -2389,7 +2386,7 @@ void EntityStateQW_ReadPlayerUpdate(void) int bits; entity_state_t *s; // look up the entity - entity_t *ent = cl_entities + enumber; + entity_t *ent = cl.entities + enumber; vec3_t viewangles; vec3_t velocity; @@ -2500,15 +2497,15 @@ void EntityStateQW_ReadPlayerUpdate(void) cl.stats[STAT_VIEWHEIGHT] = 22; } - // set the cl_entities_active flag - cl_entities_active[enumber] = s->active; + // set the cl.entities_active flag + cl.entities_active[enumber] = s->active; // set the update time s->time = cl.mtime[0] - msec * 0.001; // qw has no clock // fix the number (it gets wiped occasionally by copying from defaultstate) s->number = enumber; // check if we need to update the lerp stuff if (s->active) - CL_MoveLerpEntityStates(&cl_entities[enumber]); + CL_MoveLerpEntityStates(&cl.entities[enumber]); } static void EntityStateQW_ReadEntityUpdate(entity_state_t *s, int bits) @@ -2597,10 +2594,16 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta) entityframeqw_snapshot_t *oldsnap, *newsnap; if (!cl.entitydatabaseqw) - cl.entitydatabaseqw = EntityFrameQW_AllocDatabase(cl_mempool); + cl.entitydatabaseqw = EntityFrameQW_AllocDatabase(cls.levelmempool); d = cl.entitydatabaseqw; - newsnapindex = cls.netcon->qw.incoming_sequence & QW_UPDATE_MASK; + // there is no cls.netcon in demos, so this reading code can't access + // cls.netcon-> at all... so cls.qw_incoming_sequence and + // cls.qw_outgoing_sequence are updated every time the corresponding + // cls.netcon->qw. variables are updated + // read the number of this frame to echo back in next input packet + cl.qw_validsequence = cls.qw_incoming_sequence; + newsnapindex = cl.qw_validsequence & QW_UPDATE_MASK; newsnap = d->snapshot + newsnapindex; memset(newsnap, 0, sizeof(*newsnap)); oldsnapindex = -1; @@ -2613,7 +2616,7 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta) Con_DPrintf("WARNING: from mismatch\n"); if (oldsnapindex != -1) { - if (cls.netcon->qw.outgoing_sequence - oldsnapindex >= QW_UPDATE_BACKUP-1) + if (cls.qw_outgoing_sequence - oldsnapindex >= QW_UPDATE_BACKUP-1) { Con_DPrintf("delta update too old\n"); newsnap->invalid = invalid = true; // too old @@ -2625,8 +2628,7 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta) delta = false; } - // read the number of this frame to echo back in next input packet - cl.qw_validsequence = cls.netcon->qw.incoming_sequence; + // if we can't decode this frame properly, report that to the server if (invalid) cl.qw_validsequence = 0; @@ -2680,7 +2682,7 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta) { if (newsnap->num_entities >= QW_MAX_PACKET_ENTITIES) Host_Error("EntityFrameQW_CL_ReadFrame: newsnap->num_entities == MAX_PACKETENTITIES"); - newsnap->entities[newsnap->num_entities] = (newnum == oldnum) ? oldsnap->entities[oldindex] : cl_entities[newnum].state_baseline; + newsnap->entities[newsnap->num_entities] = (newnum == oldnum) ? oldsnap->entities[oldindex] : cl.entities[newnum].state_baseline; EntityStateQW_ReadEntityUpdate(newsnap->entities + newsnap->num_entities, word); newsnap->num_entities++; } @@ -2689,12 +2691,12 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta) oldindex++; } - // expand cl_num_entities to include every entity we've seen this game + // expand cl.num_entities to include every entity we've seen this game newnum = newsnap->num_entities ? newsnap->entities[newsnap->num_entities - 1].number : 1; - if (cl_num_entities <= newnum) + if (cl.num_entities <= newnum) { - cl_num_entities = newnum + 1; - if (cl_max_entities < newnum + 1) + cl.num_entities = newnum + 1; + if (cl.max_entities < newnum + 1) CL_ExpandEntities(newnum); } @@ -2702,26 +2704,26 @@ void EntityFrameQW_CL_ReadFrame(qboolean delta) number = cl.maxclients + 1; for (newindex = 0;;newindex++) { - newnum = newindex >= newsnap->num_entities ? cl_num_entities : newsnap->entities[newindex].number; + newnum = newindex >= newsnap->num_entities ? cl.num_entities : newsnap->entities[newindex].number; // kill any missing entities for (;number < newnum;number++) { - if (cl_entities_active[number]) + if (cl.entities_active[number]) { - cl_entities_active[number] = false; - cl_entities[number].state_current.active = false; + cl.entities_active[number] = false; + cl.entities[number].state_current.active = false; } } - if (number >= cl_num_entities) + if (number >= cl.num_entities) break; // update the entity - ent = &cl_entities[number]; + ent = &cl.entities[number]; ent->state_previous = ent->state_current; ent->state_current = newsnap->entities[newindex]; ent->state_current.time = cl.mtime[0]; CL_MoveLerpEntityStates(ent); // the entity lives again... - cl_entities_active[number] = true; + cl.entities_active[number] = true; number++; } }