From 7ec560779c23a9cce62b3dee98785698d6ade6ef Mon Sep 17 00:00:00 2001 From: havoc Date: Sat, 16 Apr 2005 09:15:18 +0000 Subject: [PATCH] fix a crash when s->tag_entity is higher than current d->maxedicts git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5185 d7cf8633-e32d-0410-b094-e92efae38249 --- protocol.c | 34 ++++++++++++++++++++++------------ protocol.h | 5 +++-- sv_user.c | 2 +- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/protocol.c b/protocol.c index 38e6783b..702dbbd6 100644 --- a/protocol.c +++ b/protocol.c @@ -1420,18 +1420,26 @@ void EntityFrame5_ExpandEdicts(entityframe5_database_t *d, int newmax) } } -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) @@ -1444,12 +1452,16 @@ int EntityState5_Priority(entityframe5_database_t *d, entity_state_t *view, enti 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); @@ -1852,7 +1864,7 @@ void EntityFrame5_CL_ReadFrame(void) } } -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; @@ -1889,10 +1901,7 @@ void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum, int viewen // 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++) @@ -1936,6 +1945,7 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num 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 @@ -1944,7 +1954,7 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num break; if (packetlognumber == ENTITYFRAME5_MAXPACKETLOGS) { - EntityFrame5_LostFrame(d, framenum, viewentnum); + EntityFrame5_LostFrame(d, framenum); packetlognumber = 0; } @@ -1975,7 +1985,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, 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; } @@ -1989,7 +1999,7 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int 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 @@ -2002,7 +2012,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, 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; } diff --git a/protocol.h b/protocol.h index 96e46ef8..b0ff854d 100644 --- a/protocol.h +++ b/protocol.h @@ -716,6 +716,8 @@ typedef struct entityframe5_database_s { // number of the latest message sent to client int latestframenum; + // updated by WriteFrame for internal use + int viewentnum; // logs of all recently sent messages (between acked and latest) entityframe5_packetlog_t packetlog[ENTITYFRAME5_MAXPACKETLOGS]; @@ -760,11 +762,10 @@ entityframe5_database_t; entityframe5_database_t *EntityFrame5_AllocDatabase(mempool_t *pool); void EntityFrame5_FreeDatabase(entityframe5_database_t *d); void EntityFrame5_ResetDatabase(entityframe5_database_t *d); -int EntityState5_Priority(entityframe5_database_t *d, entity_state_t *view, entity_state_t *s, int changedbits, int age); void EntityState5_WriteUpdate(int number, const entity_state_t *s, int changedbits, sizebuf_t *msg); int EntityState5_DeltaBitsForState(entity_state_t *o, entity_state_t *n); void EntityFrame5_CL_ReadFrame(void); -void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum, int viewentnum); +void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum); void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum); void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats); diff --git a/sv_user.c b/sv_user.c index 7015dd50..24cc9a7b 100644 --- a/sv_user.c +++ b/sv_user.c @@ -709,7 +709,7 @@ void SV_ReadClientMove (usercmd_t *move) void SV_FrameLost(int framenum) { if (host_client->entitydatabase5) - EntityFrame5_LostFrame(host_client->entitydatabase5, framenum, host_client - svs.clients + 1); + EntityFrame5_LostFrame(host_client->entitydatabase5, framenum); } void SV_FrameAck(int framenum) -- 2.39.2