}
-qboolean EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, const entity_state_t *states)
+qboolean EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, const entity_state_t **states)
{
const entity_state_t *s;
entity_state_t baseline;
buf.data = data;
buf.maxsize = sizeof(data);
- for (i = 0, s = states;i < numstates;i++, s++)
+ for (i = 0;i < numstates;i++)
{
- ENTITYSIZEPROFILING_START(msg, s->number);
+ ENTITYSIZEPROFILING_START(msg, states[i]->number);
+ s = states[i];
val = PRVM_EDICTFIELDVALUE((&prog->edicts[s->number]), prog->fieldoffsets.SendEntity);
if(val && val->function)
continue;
}
}
-// (server and client) adds a entity_frame to the database, for future reference
-void EntityFrame_AddFrame(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t *entitydata)
+// (client) adds a entity_frame to the database, for future reference
+void EntityFrame_AddFrame_Client(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t *entitydata)
+{
+ int n, e;
+ entity_frameinfo_t *info;
+
+ VectorCopy(eye, d->eye);
+
+ // figure out how many entity slots are used already
+ if (d->numframes)
+ {
+ n = d->frames[d->numframes - 1].endentity - d->frames[0].firstentity;
+ if (n + numentities > MAX_ENTITY_DATABASE || d->numframes >= MAX_ENTITY_HISTORY)
+ {
+ // ran out of room, dump database
+ EntityFrame_ClearDatabase(d);
+ }
+ }
+
+ info = &d->frames[d->numframes];
+ info->framenum = framenum;
+ e = -1000;
+ // make sure we check the newly added frame as well, but we haven't incremented numframes yet
+ for (n = 0;n <= d->numframes;n++)
+ {
+ if (e >= d->frames[n].framenum)
+ {
+ if (e == framenum)
+ Con_Print("EntityFrame_AddFrame: tried to add out of sequence frame to database\n");
+ else
+ Con_Print("EntityFrame_AddFrame: out of sequence frames in database\n");
+ return;
+ }
+ e = d->frames[n].framenum;
+ }
+ // if database still has frames after that...
+ if (d->numframes)
+ info->firstentity = d->frames[d->numframes - 1].endentity;
+ else
+ info->firstentity = 0;
+ info->endentity = info->firstentity + numentities;
+ d->numframes++;
+
+ n = info->firstentity % MAX_ENTITY_DATABASE;
+ e = MAX_ENTITY_DATABASE - n;
+ if (e > numentities)
+ e = numentities;
+ memcpy(d->entitydata + n, entitydata, sizeof(entity_state_t) * e);
+ if (numentities > e)
+ memcpy(d->entitydata, entitydata + e, sizeof(entity_state_t) * (numentities - e));
+}
+
+// (server) adds a entity_frame to the database, for future reference
+void EntityFrame_AddFrame_Server(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t **entitydata)
{
int n, e;
entity_frameinfo_t *info;
}
// (server) writes a frame to network stream
-qboolean EntityFrame_WriteFrame(sizebuf_t *msg, int maxsize, entityframe_database_t *d, int numstates, const entity_state_t *states, int viewentnum)
+qboolean EntityFrame_WriteFrame(sizebuf_t *msg, int maxsize, entityframe_database_t *d, int numstates, const entity_state_t **states, int viewentnum)
{
int i, onum, number;
entity_frame_t *o = &d->deltaframe;
VectorClear(eye);
for (i = 0;i < numstates;i++)
{
- if (states[i].number == viewentnum)
+ ent = states[i];
+ if (ent->number == viewentnum)
{
- VectorSet(eye, states[i].origin[0], states[i].origin[1], states[i].origin[2] + 22);
+ VectorSet(eye, ent->origin[0], ent->origin[1], ent->origin[2] + 22);
break;
}
}
- EntityFrame_AddFrame(d, eye, d->latestframenum, numstates, states);
+ EntityFrame_AddFrame_Server(d, eye, d->latestframenum, numstates, states);
EntityFrame_FetchFrame(d, d->ackframenum, o);
onum = 0;
for (i = 0;i < numstates;i++)
{
- ent = states + i;
+ ent = states[i];
number = ent->number;
val = PRVM_EDICTFIELDVALUE((&prog->edicts[number]), prog->fieldoffsets.SendEntity);
f->entitydata[f->numentities] = *old++;
f->entitydata[f->numentities++].time = cl.mtime[0];
}
- EntityFrame_AddFrame(d, f->eye, f->framenum, f->numentities, f->entitydata);
+ EntityFrame_AddFrame_Client(d, f->eye, f->framenum, f->numentities, f->entitydata);
memset(cl.entities_active, 0, cl.num_entities * sizeof(unsigned char));
number = 1;
EntityFrame4_ResetDatabase(d);
}
-qboolean EntityFrame4_WriteFrame(sizebuf_t *msg, int maxsize, entityframe4_database_t *d, int numstates, const entity_state_t *states)
+qboolean EntityFrame4_WriteFrame(sizebuf_t *msg, int maxsize, entityframe4_database_t *d, int numstates, const entity_state_t **states)
{
const entity_state_t *e, *s;
entity_state_t inactiveentitystate;
SZ_Clear(&buf);
// entity exists, build an update (if empty there is no change)
// find the state in the list
- for (;i < numstates && states[i].number < n;i++);
+ for (;i < numstates && states[i]->number < n;i++);
// make the message
- s = states + i;
+ s = states[i];
if (s->number == n)
{
// build the update
d->packetlog[i].packetnumber = 0;
}
-qboolean EntityFrame5_WriteFrame(sizebuf_t *msg, int maxsize, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int movesequence, qboolean need_empty)
+qboolean EntityFrame5_WriteFrame(sizebuf_t *msg, int maxsize, entityframe5_database_t *d, int numstates, const entity_state_t **states, int viewentnum, int movesequence, qboolean need_empty)
{
const entity_state_t *n;
int i, num, l, framenum, packetlognumber, priority;
// detect changes in states
num = 1;
- for (i = 0, n = states;i < numstates;i++, n++)
+ for (i = 0;i < numstates;i++)
{
+ n = states[i];
// mark gaps in entity numbering as removed entities
for (;num < n->number;num++)
{
unsigned char tagindex;
unsigned char colormod[3];
unsigned char glowmod[3];
- // padding to a multiple of 8 bytes (to align the double time)
- unsigned char unused[2];
}
entity_state_t;
void Protocol_WriteStatsReliable(void);
// writes a list of quake entities to the network stream
// (or as many will fit)
-qboolean EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, const entity_state_t *states);
+qboolean EntityFrameQuake_WriteFrame(sizebuf_t *msg, int maxsize, int numstates, const entity_state_t **states);
// cleans up dead entities each frame after ReadEntity (which doesn't clear unused entities)
void EntityFrameQuake_ISeeDeadEntities(void);
void EntityFrame_Clear(entity_frame_t *f, vec3_t eye, int framenum);
// (server and client) reads a frame from the database
void EntityFrame_FetchFrame(entityframe_database_t *d, int framenum, entity_frame_t *f);
-// (server and client) adds a entity_frame to the database, for future
-// reference
-void EntityFrame_AddFrame(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t *entitydata);
+// (client) adds a entity_frame to the database, for future reference
+void EntityFrame_AddFrame_Client(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t *entitydata);
+// (server) adds a entity_frame to the database, for future reference
+void EntityFrame_AddFrame_Server(entityframe_database_t *d, vec3_t eye, int framenum, int numentities, const entity_state_t **entitydata);
// (server) writes a frame to network stream
-qboolean EntityFrame_WriteFrame(sizebuf_t *msg, int maxsize, entityframe_database_t *d, int numstates, const entity_state_t *states, int viewentnum);
+qboolean EntityFrame_WriteFrame(sizebuf_t *msg, int maxsize, entityframe_database_t *d, int numstates, const entity_state_t **states, int viewentnum);
// (client) reads a frame from network stream
void EntityFrame_CL_ReadFrame(void);
// (client) returns the frame number of the most recent frame recieved
// updates database to account for a frame-received acknowledgment
int EntityFrame4_AckFrame(entityframe4_database_t *d, int framenum, int servermode);
// writes a frame to the network stream
-qboolean EntityFrame4_WriteFrame(sizebuf_t *msg, int maxsize, entityframe4_database_t *d, int numstates, const entity_state_t *states);
+qboolean EntityFrame4_WriteFrame(sizebuf_t *msg, int maxsize, entityframe4_database_t *d, int numstates, const entity_state_t **states);
// reads a frame from the network stream
void EntityFrame4_CL_ReadFrame(void);
void EntityFrame5_CL_ReadFrame(void);
void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum);
void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum);
-qboolean EntityFrame5_WriteFrame(sizebuf_t *msg, int maxsize, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int movesequence, qboolean need_empty);
+qboolean EntityFrame5_WriteFrame(sizebuf_t *msg, int maxsize, entityframe5_database_t *d, int numstates, const entity_state_t **states, int viewentnum, int movesequence, qboolean need_empty);
extern cvar_t developer_networkentities;
numcsqcsendstates = 0;
for (i = 0;i < sv.numsendentities;i++)
{
- if (sv.sententities[sv.sendentities[i].number] == sv.sententitiesmark)
+ s = &sv.sendentities[i];
+ if (sv.sententities[s->number] == sv.sententitiesmark)
{
- if(sv.sendentities[i].active == ACTIVE_NETWORK)
+ if(s->active == ACTIVE_NETWORK)
{
- s = &sv.writeentitiestoclient_sendstates[numsendstates++];
- *s = sv.sendentities[i];
- if (s->exteriormodelforclient && s->exteriormodelforclient == sv.writeentitiestoclient_cliententitynumber)
- s->flags |= RENDER_EXTERIORMODEL;
+ if (s->exteriormodelforclient)
+ {
+ if (s->exteriormodelforclient == sv.writeentitiestoclient_cliententitynumber)
+ s->flags |= RENDER_EXTERIORMODEL;
+ else
+ s->flags &= ~RENDER_EXTERIORMODEL;
+ }
+ sv.writeentitiestoclient_sendstates[numsendstates++] = s;
}
else if(sv.sendentities[i].active == ACTIVE_SHARED)
- sv.writeentitiestoclient_csqcsendstates[numcsqcsendstates++] = sv.sendentities[i].number;
+ sv.writeentitiestoclient_csqcsendstates[numcsqcsendstates++] = s->number;
else
- Con_Printf("entity %d is in sv.sendentities and marked, but not active, please breakpoint me\n", sv.sendentities[i].number);
+ Con_Printf("entity %d is in sv.sendentities and marked, but not active, please breakpoint me\n", s->number);
}
}