entity_t *ent;
entityframe_database_t *d;
if (!cl.entitydatabase)
- cl.entitydatabase = EntityFrame_AllocDatabase(cl_entities_mempool);
+ cl.entitydatabase = EntityFrame_AllocDatabase(cl_mempool);
d = cl.entitydatabase;
EntityFrame_Clear(f, NULL, -1);
entity_state_t *s;
entityframe4_database_t *d;
if (!cl.entitydatabase4)
- cl.entitydatabase4 = EntityFrame4_AllocDatabase(cl_entities_mempool);
+ cl.entitydatabase4 = EntityFrame4_AllocDatabase(cl_mempool);
d = cl.entitydatabase4;
// read the number of the frame this refers to
referenceframenum = MSG_ReadLong();
void EntityFrame5_FreeDatabase(entityframe5_database_t *d)
{
+ // all the [maxedicts] memory is allocated at once, so there's only one
+ // thing to free
+ if (d->maxedicts)
+ Mem_Free(d->deltabits);
Mem_Free(d);
}
int i;
memset(d, 0, sizeof(*d));
d->latestframenum = 0;
- for (i = 0;i < MAX_EDICTS;i++)
+ for (i = 0;i < d->maxedicts;i++)
d->states[i] = defaultstate;
}
+void EntityFrame5_ExpandEdicts(entityframe5_database_t *d, int newmax)
+{
+ if (d->maxedicts < newmax)
+ {
+ qbyte *data;
+ int oldmaxedicts = d->maxedicts;
+ int *olddeltabits = d->deltabits;
+ qbyte *oldpriorities = d->priorities;
+ int *oldupdateframenum = d->updateframenum;
+ entity_state_t *oldstates = d->states;
+ qbyte *oldvisiblebits = d->visiblebits;
+ d->maxedicts = newmax;
+ data = Mem_Alloc(sv_mempool, d->maxedicts * sizeof(int) + d->maxedicts * sizeof(qbyte) + d->maxedicts * sizeof(int) + d->maxedicts * sizeof(entity_state_t) + (d->maxedicts+7)/8 * sizeof(qbyte));
+ d->deltabits = (void *)data;data += d->maxedicts * sizeof(int);
+ d->priorities = (void *)data;data += d->maxedicts * sizeof(qbyte);
+ d->updateframenum = (void *)data;data += d->maxedicts * sizeof(int);
+ d->states = (void *)data;data += d->maxedicts * sizeof(entity_state_t);
+ d->visiblebits = (void *)data;data += (d->maxedicts+7)/8 * sizeof(qbyte);
+ if (oldmaxedicts)
+ {
+ memcpy(d->deltabits, olddeltabits, oldmaxedicts * sizeof(int));
+ memcpy(d->priorities, oldpriorities, oldmaxedicts * sizeof(qbyte));
+ memcpy(d->updateframenum, oldupdateframenum, oldmaxedicts * sizeof(int));
+ memcpy(d->states, oldstates, oldmaxedicts * sizeof(entity_state_t));
+ memcpy(d->visiblebits, oldvisiblebits, (oldmaxedicts+7)/8 * sizeof(qbyte));
+ // the previous buffers were a single allocation, so just one free
+ Mem_Free(olddeltabits);
+ }
+ }
+}
-int EntityState5_Priority(entityframe5_database_t *d, entity_state_t *view, entity_state_t *s, int changedbits, int age)
+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 (!s->active/* && changedbits & E5_FULLUPDATE*/)
+ if (!d->states[stateindex].active/* && changedbits & E5_FULLUPDATE*/)
return E5_PROTOCOL_PRIORITYLEVELS - 1;
// check whole attachment chain to judge relevance to player
+ view = d->states + d->viewentnum;
lowprecision = false;
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;
break;
}
- s = d->states + s->tagentity;
+ stateindex = s->tagentity;
}
if (limit >= 256)
- Con_Printf("Protocol: Runaway loop recursing tagentity links on entity %i\n", s->number);
+ {
+ 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);
else
{
bits = changedbits;
- if ((bits & E5_ORIGIN) && (s->origin[0] < -4096 || s->origin[0] >= 4096 || s->origin[1] < -4096 || s->origin[1] >= 4096 || s->origin[2] < -4096 || s->origin[2] >= 4096))
+ if ((bits & E5_ORIGIN) && (!(s->flags & RENDER_LOWPRECISION) || s->origin[0] < -4096 || s->origin[0] >= 4096 || s->origin[1] < -4096 || s->origin[1] >= 4096 || s->origin[2] < -4096 || s->origin[2] >= 4096))
bits |= E5_ORIGIN32;
if ((bits & E5_ANGLES) && !(s->flags & RENDER_LOWPRECISION))
bits |= E5_ANGLES16;
}
}
-void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum, int viewentnum)
+void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum)
{
int i, j, k, l, bits;
entityframe5_changestate_t *s, *s2;
// if the bits haven't all been cleared, there were some bits
// lost with this packet, so set them again now
if (bits)
- {
d->deltabits[s->number] |= bits;
- d->priorities[s->number] = EntityState5_Priority(d, d->states + viewentnum, d->states + s->number, d->deltabits[s->number], d->latestframenum - d->updateframenum[s->number]);
- }
}
// mark lost stats
for (j = 0;j < MAX_CL_STATS;j++)
qbyte data[128];
entityframe5_packetlog_t *packetlog;
+ if (sv.num_edicts > d->maxedicts)
+ EntityFrame5_ExpandEdicts(d, (sv.num_edicts + 255) & ~255);
+
framenum = d->latestframenum + 1;
+ d->viewentnum = viewentnum;
// if packet log is full, mark all frames as lost, this will cause
// it to send the lost data again
break;
if (packetlognumber == ENTITYFRAME5_MAXPACKETLOGS)
{
- EntityFrame5_LostFrame(d, framenum, viewentnum);
+ EntityFrame5_LostFrame(d, framenum);
packetlognumber = 0;
}
{
CLEARPVSBIT(d->visiblebits, num);
d->deltabits[num] = E5_FULLUPDATE;
- d->priorities[num] = EntityState5_Priority(d, d->states + viewentnum, d->states + num, d->deltabits[num], framenum - d->updateframenum[num]);
+ d->priorities[num] = EntityState5_Priority(d, num);
d->states[num] = defaultstate;
d->states[num].number = num;
}
}
SETPVSBIT(d->visiblebits, num);
d->deltabits[num] |= EntityState5_DeltaBits(d->states + num, n);
- d->priorities[num] = EntityState5_Priority(d, d->states + viewentnum, d->states + num, d->deltabits[num], framenum - d->updateframenum[num]);
+ d->priorities[num] = EntityState5_Priority(d, num);
d->states[num] = *n;
d->states[num].number = num;
// advance to next entity so the next iteration doesn't immediately remove it
{
CLEARPVSBIT(d->visiblebits, num);
d->deltabits[num] = E5_FULLUPDATE;
- d->priorities[num] = EntityState5_Priority(d, d->states + viewentnum, d->states + num, d->deltabits[num], framenum - d->updateframenum[num]);
+ d->priorities[num] = EntityState5_Priority(d, num);
d->states[num] = defaultstate;
d->states[num].number = num;
}