Skip to content

Commit b378fe5

Browse files
committed
Don't reload the map in long matches with many players
In matches with many players the server would run out of indexes for snapshot entities. This is internal to the server for delta updates. Adjust values so they don't go negative and delta updates still work. Based on change in Quake3e by Eugene C. in July 2016; Fix: no more "Restarting server due to numSnapshotEntities wrapping" ec-/Quake3e@ef47444
1 parent bffb764 commit b378fe5

2 files changed

Lines changed: 26 additions & 9 deletions

File tree

code/server/sv_main.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,12 +1105,6 @@ void SV_Frame( int msec ) {
11051105
Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) );
11061106
return;
11071107
}
1108-
// this can happen considerably earlier when lots of clients play and the map doesn't change
1109-
if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - svs.numSnapshotEntities ) {
1110-
SV_Shutdown( "Restarting server due to numSnapshotEntities wrapping" );
1111-
Cbuf_AddText( va( "map %s\n", Cvar_VariableString( "mapname" ) ) );
1112-
return;
1113-
}
11141108

11151109
if( sv.restartTime && sv.time >= sv.restartTime ) {
11161110
sv.restartTime = 0;

code/server/sv_snapshot.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -441,15 +441,16 @@ For viewing through other player's eyes, clent can be something other than clien
441441
*/
442442
static void SV_BuildClientSnapshot( client_t *client ) {
443443
vec3_t org;
444-
clientSnapshot_t *frame;
444+
clientSnapshot_t *frame, *oldframe;
445445
snapshotEntityNumbers_t entityNumbers;
446-
int i;
446+
int i, j;
447447
sharedEntity_t *ent;
448448
entityState_t *state;
449449
svEntity_t *svEnt;
450450
sharedEntity_t *clent;
451451
int clientNum;
452452
playerState_t *ps;
453+
int offset;
453454

454455
// bump the counter used to prevent double adding
455456
sv.snapshotCounter++;
@@ -504,6 +505,28 @@ static void SV_BuildClientSnapshot( client_t *client ) {
504505
((int *)frame->areabits)[i] = ((int *)frame->areabits)[i] ^ -1;
505506
}
506507

508+
// avoid wrapping snapshot entities index to negative while keeping the same modulo value
509+
// and lower existing first_entity for detecting rolling off the buffer
510+
if ( svs.nextSnapshotEntities >= 0x7FFFFFFE - entityNumbers.numSnapshotEntities ) {
511+
Com_DPrintf( "Updating snapshot entities to avoid numSnapshotEntities wrapping.\n" );
512+
513+
offset = ( ( svs.nextSnapshotEntities / svs.numSnapshotEntities ) - 2 ) * svs.numSnapshotEntities;
514+
515+
for ( i = 0; i < sv_maxclients->integer; i++ ) {
516+
oldframe = svs.clients[i].frames;
517+
518+
for ( j = 0; j < PACKET_BACKUP; j++, oldframe++ ) {
519+
if ( oldframe->first_entity <= svs.nextSnapshotEntities - svs.numSnapshotEntities ) {
520+
oldframe->first_entity %= svs.numSnapshotEntities;
521+
} else {
522+
oldframe->first_entity -= offset;
523+
}
524+
}
525+
}
526+
527+
svs.nextSnapshotEntities -= offset;
528+
}
529+
507530
// copy the entity states out
508531
frame->num_entities = 0;
509532
frame->first_entity = svs.nextSnapshotEntities;
@@ -512,7 +535,7 @@ static void SV_BuildClientSnapshot( client_t *client ) {
512535
state = &svs.snapshotEntities[svs.nextSnapshotEntities % svs.numSnapshotEntities];
513536
*state = ent->s;
514537
svs.nextSnapshotEntities++;
515-
// this should never hit, map should always be restarted first in SV_Frame
538+
// this should never hit
516539
if ( svs.nextSnapshotEntities >= 0x7FFFFFFE ) {
517540
Com_Error(ERR_FATAL, "svs.nextSnapshotEntities wrapped");
518541
}

0 commit comments

Comments
 (0)