Bug #431

Fix level.num_entities

Added by IR4T4 almost 5 years ago. Updated about 4 years ago.

Status:In Progress% Done:

0%

Priority:Normal
Assignee:-
Category:Mod CGAME
Target version:2.77
OS: Arch:

Description

I do suppose the introduction of antilag (see G_Trace and usage of G_BuildLeg/G_BuildHead) messed up level.num_entities.

With 20 players level.num_entities grows rapidly to a max value of MAX_GENTITIES-1. This wasn’t originally intended - quake f.e. isn’t affected. To test: Run a server with 20 bots and call 'entitiylist’ cmd regularily.

level.num_entities should be keept as small as possible (it’s the max index of used game entities) so all the loops spread over in the code are kept as short as possible. The intensive usage of G_BuildLeg/G_BuildHead/G_Trace denies that.

Here is my first fix:

/*
=================
G_FreeEntity

Marks the entity as free
=================
*/
void G_FreeEntity(gentity_t *ed)
{
#ifdef FEATURE_OMNIBOT
    Bot_Event_EntityDeleted(ed);
#endif

    if (ed->free)
    {
        ed->free(ed);
    }

    trap_UnlinkEntity(ed);       // unlink from world

    if (ed->neverFree)
    {
        return;
    }

    // this fixes level.num_entities rapidly reaching MAX_GENTITIES-1
    // real temporary server ents don't have to relax (=spawned, immediately freed and not transmitted)
    // ET_TEMP* entities are linked for a short amount of time but have no ent->r.svFlags set (not broadcasted)
    //
    // FIXME: inspect events & optimize in same way
    // - if events are freed EVENT_VALID_MSEC has already passed - but keep in mind these are broadcasted
    // || e->s.eType > ET_EVENTS // if freeAfterEvent is set don't relax ...
    if ((ed->s.eType == ET_TEMPHEAD || ed->s.eType == ET_TEMPLEGS) && trap_Cvar_VariableIntegerValue("l_free") == 0)
    {
        memset(ed, 0, sizeof(*ed));
        ed->classname = "freed";
        // ents are immediately available (and reuse a 'slot')
        ed->freetime  = -9999;  // e->freetime is never greater than level.startTime + 2000 see G_Spawn()
        ed->inuse     = qfalse;

        if (trap_Cvar_VariableIntegerValue("l_see") == 1)
        {
            G_Printf("------> freed %4i:\n", level.num_entities );
        }
    }
    else // all other ents relax
    {
        memset(ed, 0, sizeof(*ed));
        ed->classname = "freed";
        ed->freetime  = level.time;
        ed->inuse     = qfalse;
    }
}

level.num_entities no longer reaches MAX_GENTITIES-1 quickly ... even with 20 bots the value is 'constant’ and far away from MAX_GENTITIES-1 - do same test as above.

I didn’t commit this because I want to ensure there are no side effects on network games. Listen server works properly.

Let’s test!

note: entitlist won’t show ET_TEMP* entities - they are processed in between a frame.

Associated revisions

Revision 8a7d58af
Added by IR4T4 almost 5 years ago

game: relax level.num_entities refs #431

History

#1 Updated by Radegast almost 5 years ago

  • Description updated (diff)

#2 Updated by IR4T4 almost 5 years ago

  • Description updated (diff)

#3 Updated by IR4T4 almost 5 years ago

Code is commited. I’ve added a cvar 'l_free’ which disables the optimization if set to 1.

remove the tmp cvar

#4 Updated by IR4T4 almost 5 years ago

  • Status changed from New to In Progress
  • Target version changed from 2.71rc4 to 2.77

#5 Updated by IR4T4 over 4 years ago

  • Target version changed from 2.77 to 2.71

#6 Updated by IR4T4 about 4 years ago

  • Target version changed from 2.71 to 2.77

Also available in: Atom PDF