Вопрос HighestEntityIndex offset changed ?

see cl_showents(CCommandContext const&, CCommand const&)
C++:
Expand Collapse Copy
// #STR: "(missing),", "(missing)", "Ent %3d: %s class %s\n"
__int64 cl_showents()
{
  unsigned int v0; // ebx
  __int64 v1; // rax
  _QWORD *v2; // rax
  char v4; // [rsp+0h] [rbp-230h]
  char v5; // [rsp+100h] [rbp-130h]

  if ( (signed int)CGameEntitySystem::GetHighestEntityIndex(g_pGameEntitySystem) >= 0 )
  {
    v0 = -1;
    do
    {
      v1 = CGameEntitySystem::GetBaseEntity((__int64)g_pGameEntitySystem, ++v0);
      if ( v1 )
      {
        v5 = 0;
        v2 = (_QWORD*)(* (__int64 (__fastcall**)(__int64, _QWORD))( *(_QWORD *)v1 + 240LL))(v1, v0);
        V_snprintf(&v4, 256, "'%s'", *v2);
        ConMsg("Ent %3d: %s class %s\n", v0, &v5, &v4);
      }
      else
      {
        V_snprintf(&v5, 256, "(missing), ");
        V_snprintf(&v4, 256, "(missing)");
      }
    }
    while ( (signed int)v0 < (signed int)CGameEntitySystem::GetHighestEntityIndex(g_pGameEntitySystem) );
  }
  return __stack_chk_guard;
}
search for string xref "Ent %3d" in client.dll
scroll to the beginning of the function(push ... + sub rsp, etc.), the first call will be to GetHighestEntityIndex
which will be something like(OUTDATED BELOW):
Код:
Expand Collapse Copy
00007FFDAB25D890 | 8B81 30150000              | mov eax,dword ptr ds:[rcx+1530]                                        |
00007FFDAB25D896 | 8902                       | mov dword ptr ds:[rdx],eax                                             |
00007FFDAB25D898 | 48:8BC2                    | mov rax,rdx                                                            |
00007FFDAB25D89B | C3                         | ret                                                                    |
 
1735412973898.png
 
Посмотреть вложение 294121
is it function needs to be hooked or 2100h is the new offset for highest entityindex ?
hooking is when you intercept someone else's(the game's) invocation of a function(in an attempt to observe/modify the game's behavior(react to the game performing some action or lie to the game about something)). basically a callback but forcefully installed. why would you need to hook this?
0x2100 should be the new offset. double-check it yourself in the game
 
They removed GetHighestEntityIndex. They have different way of iterating all entities now

C++:
Expand Collapse Copy
// #STR: "Ent %5d: class %s name \"%s\"\n"
unsigned int sub_18136E1C0()
{
  __int64 Ent; // r14
  int v1; // edx
  __int64 v2; // rcx
  __int64 v3; // rsi
  int v4; // eax
  int v5; // edi
  int v6; // eax
  __int64 v7; // rdx
  int v8; // ebx
  __int64 v9; // r8
  int v10; // eax
  char *EntInstance; // r14
  char *v12; // r15
  __int64 Entity; // rsi
  const char *entName; // rdi
  const char *className; // rbx
  unsigned int result; // eax
  char v17[24]; // [rsp+20h] [rbp-E0h] BYREF
  void **v18; // [rsp+38h] [rbp-C8h] BYREF
  int v19; // [rsp+40h] [rbp-C0h]
  char *EntityInstance; // [rsp+48h] [rbp-B8h] BYREF
  unsigned int v21; // [rsp+50h] [rbp-B0h]
  int v22; // [rsp+54h] [rbp-ACh]
  char v23[8200]; // [rsp+58h] [rbp-A8h] BYREF
  unsigned int entIndex; // [rsp+2090h] [rbp+1F90h] BYREF

  EntityInstance = 0i64;
  v21 = 1024;
  v22 = 0x80000000;
  if ( (&EntityInstance & 7) != 0 )
    sub_182E7E4D0();
  EntityInstance = v23;
  v19 = 0;
  sub_182A80FC0(v17, &v18, 0i64);
  v18 = &CDefaultTypedEntityInstanceFilter<C_BaseEntity>::`vftable';
  for ( Ent = sub_182A8B5A0(v17); Ent; Ent = sub_182A8F8F0(v17) )
  {
    v1 = v19;
    v2 = v21;
    v3 = v19;
    if ( v19 != v21 || (v4 = v22, (v22 & 0x40000000) != 0) )
    {
      v9 = EntityInstance;
    }
    else
    {
      if ( v21 == 0x7FFFFFFF )
      {
        UtlMemory_FailedAllocation(0x7FFFFFFFi64, 1i64);
        v4 = v22;
        v2 = v21;
      }
      v5 = v2 + 1;
      v6 = UtlMemory_CalcNewAllocationCount(v2, v4 & 0x3FFFFFFF, (v2 + 1), 8i64);
      v8 = v6;
      if ( v6 < v5 )
      {
        if ( v6 || v5 > -1 )
        {
          do
          {
            v7 = ((v8 + v5) >> 31);
            v8 = (v8 + v5) / 2;
          }
          while ( v8 < v5 );
        }
        else
        {
          v8 = -1;
        }
      }
      LOBYTE(v7) = (v22 & 0xC0000000) == 0;
      v9 = UtlMemory_Alloc(EntityInstance, v7, 8i64 * v8, 8i64 * v21);
      EntityInstance = v9;
      if ( (v22 & 0xC0000000) != 0 )
        v22 &= 0x3FFFFFFFu;
      v1 = v19;
      v21 = v8;
    }
    v19 = v1 + 1;
    *(v9 + 8 * v3) = Ent;
  }
  v10 = v19;
  if ( v19 > 1 )
  {
    V_qsort(EntityInstance, v19, 8i64, sub_181358FA0);
    v10 = v19;
  }
  EntInstance = EntityInstance;
  v12 = &EntityInstance[8 * v10];
  if ( EntityInstance != v12 )
  {
    do
    {
      Entity = *EntInstance;
      entName = &unk_182FB02FA;
      if ( *(*(*EntInstance + 16i64) + 24i64) )
        entName = *(*(*EntInstance + 16i64) + 24i64);
      className = *((*(**EntInstance + 352i64))(*EntInstance) + 8);
      sub_182AA0100(Entity, &entIndex);
      ConMsg("Ent %5d: class %s name \"%s\"\n", entIndex, className, entName);
      EntInstance += 8;
    }
    while ( EntInstance != v12 );
    EntInstance = EntityInstance;
  }
  v19 = 0;
  if ( (v21 & 0x80000000) != 0 || EntInstance == v23 )
  {
    result = v22;
  }
  else
  {
    if ( EntInstance && (v22 & 0xC0000000) == 0 )
      (*(*g_pMemAlloc + 24i64))(g_pMemAlloc, EntInstance);
    EntInstance = v23;
    EntityInstance = v23;
    result = v22 & 0x3FFFFFFF | 0x80000000;
    v21 = 1024;
    v22 = result;
  }
  if ( (result & 0xC0000000) == 0 )
  {
    if ( EntInstance )
      return (*(*g_pMemAlloc + 24i64))(g_pMemAlloc, EntInstance);
  }
  return result;
}
 
They removed GetHighestEntityIndex. They have a different way of iterating all entities now

C++:
Expand Collapse Copy
// #STR: "Ent %5d: class %s name \"%s\"\n"
unsigned int sub_18136E1C0()
{
  __int64 Ent; // r14
  int v1; // edx
  __int64 v2; // rcx
  __int64 v3; // rsi
  int v4; // eax
  int v5; // edi
  int v6; // eax
  __int64 v7; // rdx
  int v8; // ebx
  __int64 v9; // r8
  int v10; // eax
  char *EntInstance; // r14
  char *v12; // r15
  __int64 Entity; // rsi
  const char *entName; // rdi
  const char *className; // rbx
  unsigned int result; // eax
  char v17[24]; // [rsp+20h] [rbp-E0h] BYREF
  void **v18; // [rsp+38h] [rbp-C8h] BYREF
  int v19; // [rsp+40h] [rbp-C0h]
  char *EntityInstance; // [rsp+48h] [rbp-B8h] BYREF
  unsigned int v21; // [rsp+50h] [rbp-B0h]
  int v22; // [rsp+54h] [rbp-ACh]
  char v23[8200]; // [rsp+58h] [rbp-A8h] BYREF
  unsigned int entIndex; // [rsp+2090h] [rbp+1F90h] BYREF

  EntityInstance = 0i64;
  v21 = 1024;
  v22 = 0x80000000;
  if ( (&EntityInstance & 7) != 0 )
    sub_182E7E4D0();
  EntityInstance = v23;
  v19 = 0;
  sub_182A80FC0(v17, &v18, 0i64);
  v18 = &CDefaultTypedEntityInstanceFilter<C_BaseEntity>::`vftable';
  for ( Ent = sub_182A8B5A0(v17); Ent; Ent = sub_182A8F8F0(v17) )
  {
    v1 = v19;
    v2 = v21;
    v3 = v19;
    if ( v19 != v21 || (v4 = v22, (v22 & 0x40000000) != 0) )
    {
      v9 = EntityInstance;
    }
    else
    {
      if ( v21 == 0x7FFFFFFF )
      {
        UtlMemory_FailedAllocation(0x7FFFFFFFi64, 1i64);
        v4 = v22;
        v2 = v21;
      }
      v5 = v2 + 1;
      v6 = UtlMemory_CalcNewAllocationCount(v2, v4 & 0x3FFFFFFF, (v2 + 1), 8i64);
      v8 = v6;
      if ( v6 < v5 )
      {
        if ( v6 || v5 > -1 )
        {
          do
          {
            v7 = ((v8 + v5) >> 31);
            v8 = (v8 + v5) / 2;
          }
          while ( v8 < v5 );
        }
        else
        {
          v8 = -1;
        }
      }
      LOBYTE(v7) = (v22 & 0xC0000000) == 0;
      v9 = UtlMemory_Alloc(EntityInstance, v7, 8i64 * v8, 8i64 * v21);
      EntityInstance = v9;
      if ( (v22 & 0xC0000000) != 0 )
        v22 &= 0x3FFFFFFFu;
      v1 = v19;
      v21 = v8;
    }
    v19 = v1 + 1;
    *(v9 + 8 * v3) = Ent;
  }
  v10 = v19;
  if ( v19 > 1 )
  {
    V_qsort(EntityInstance, v19, 8i64, sub_181358FA0);
    v10 = v19;
  }
  EntInstance = EntityInstance;
  v12 = &EntityInstance[8 * v10];
  if ( EntityInstance != v12 )
  {
    do
    {
      Entity = *EntInstance;
      entName = &unk_182FB02FA;
      if ( *(*(*EntInstance + 16i64) + 24i64) )
        entName = *(*(*EntInstance + 16i64) + 24i64);
      className = *((*(**EntInstance + 352i64))(*EntInstance) + 8);
      sub_182AA0100(Entity, &entIndex);
      ConMsg("Ent %5d: class %s name \"%s\"\n", entIndex, className, entName);
      EntInstance += 8;
    }
    while ( EntInstance != v12 );
    EntInstance = EntityInstance;
  }
  v19 = 0;
  if ( (v21 & 0x80000000) != 0 || EntInstance == v23 )
  {
    result = v22;
  }
  else
  {
    if ( EntInstance && (v22 & 0xC0000000) == 0 )
      (*(*g_pMemAlloc + 24i64))(g_pMemAlloc, EntInstance);
    EntInstance = v23;
    EntityInstance = v23;
    result = v22 & 0x3FFFFFFF | 0x80000000;
    v21 = 1024;
    v22 = result;
  }
  if ( (result & 0xC0000000) == 0 )
  {
    if ( EntInstance )
      return (*(*g_pMemAlloc + 24i64))(g_pMemAlloc, EntInstance);
  }
  return result;
}

I can't understand the logic behind that. also why entity index goes from 3-digit to 5-digit? what is the purpose of doing this?

C++:
Expand Collapse Copy
[Console] Ent 242: class CDOTA_Item_TeleportScroll name "item_tpscroll"
[Console] Ent 16408: class CBaseModelEntity name "divine_ambient"
[Console] Ent 16409: class CPointCamera name "camera_1"
[Console] Ent 16418: class CParticleSystem name ""
 
Okay from what I understand:

C++:
Expand Collapse Copy
 for ( i = sub_2A8B710(v17); i; i = sub_2A8FA60(v17) )
  {
    v1 = v19;
    v2 = v21;
    v3 = v19;
    if ( v19 != v21 || (v4 = v22, (v22 & 0x40000000) != 0) )
    {
      v9 = (__int64)v20;
    }
    else
    {
      if ( v21 == 0x7FFFFFFF )
      {
        UtlMemory_FailedAllocation(0x7FFFFFFFi64, 1i64);
        v4 = v22;
        v2 = v21;
      }
      v5 = v2 + 1;
      v6 = UtlMemory_CalcNewAllocationCount(v2, v4 & 0x3FFFFFFF, (unsigned int)(v2 + 1), 8i64);
      v8 = v6;
      if ( v6 < v5 )
      {
        if ( v6 || v5 > -1 )
        {
          do
          {
            v7 = (unsigned int)((v8 + v5) >> 31);
            v8 = (v8 + v5) / 2;
          }
          while ( v8 < v5 );
        }
        else
        {
          v8 = -1;
        }
      }
      LOBYTE(v7) = (v22 & 0xC0000000) == 0;
      v9 = UtlMemory_Alloc(v20, v7, 8i64 * v8, 8i64 * (int)v21);
      v20 = (char *)v9;
      if ( (v22 & 0xC0000000) != 0 )
        v22 &= 0x3FFFFFFFu;
      v1 = v19;
      v21 = v8;
    }
    v19 = v1 + 1;
    *(_QWORD *)(v9 + 8 * v3) = i;
  }

it's filling a CUtlVector.

C++:
Expand Collapse Copy
v19: The current size (number of valid items stored so far).
v21: The allocated capacity (max elements that can currently be stored).
v20: Pointer to the memory buffer used to store the elements.

it's just iterating a linked list and adding them into a CUtilVector.
Also after doing sort the vector looks like this:
Пожалуйста, авторизуйтесь для просмотра ссылки.


C++:
Expand Collapse Copy
for ( i = sub_2A8B710(v17); i; i = sub_2A8FA60(v17) )
GetHead/GetNext of the linked list. inside it:
C++:
Expand Collapse Copy
 if ( !CGameEntitySystem )
    return 0i64;
  v2 = *a1; // current node
  if ( v2 )
  {
    v3 = *(_QWORD *)(v2 + 0x60); // v3 = current->next
  }
  else if ( *((_BYTE *)a1 + 0x10) )
  {
    v3 = *(_QWORD *)(CGameEntitySystem + 0x230 // alternate list (?)
  }
  else
  {
    v3 = *(_QWORD *)(CGameEntitySystem + 0x210); // default list (?)
  }

So now what is the best option for iterating over all entities?
 
Последнее редактирование:
C++:
Expand Collapse Copy
unsigned int ShowEnts()
{
  // Initialize values
  __int64 Ent;                         // Holds current entity
  int v1;                              // Index into entity list array
  __int64 v2, v3;                      // Misc pointers
  int v4, v5, v6, v8, v10;             // Temp counters & sizes
  __int64 v7, v9;                      // Temp ptrs
  char *EntInstance, *v12;            // Iterators over entity array
  __int64 Entity;                     // Actual entity pointer
  const char *entName, *className;    // Entity name / class
  unsigned int result;                // Return result
  __int64 v17[3];                     // Entity iterator struct
  void **v18;                         // Filter virtual table
  int v19;                            // Number of entities found
  char *EntityInstance;               // Pointer to allocated entity array
  unsigned int v21;                   // Capacity of entity array
  int v22;                            // Allocation flags
  char v23[8200];                     // Local buffer for entities (1024 entries * 8 bytes)
  unsigned int entIndex;             // Final entity index

  EntityInstance = 0;
  v21 = 1024;                         // Initial capacity
  v22 = 0x80000000;                   // Flag (MSB set means local stack buffer used)
  if ((&EntityInstance & 7) != 0)     // Alignment check (should be 8-byte aligned)
    sub_182E7E4D0();                  // (unknown alignment check failure handler)
  EntityInstance = v23;              // Use stack buffer
  v19 = 0;                            // Reset entity count

  // Setup entity iterator: v17 is likely an iterator/context structure
  sub_182A80FC0(v17, &v18, 0);        // Initialize iterator
  v18 = &CDefaultTypedEntityInstanceFilter<C_BaseEntity>::`vftable';  // Set default filter

  // ----------- Entity iteration begins -------------------
  for (Ent = sub_182A8B5A0(v17); Ent; Ent = sub_182A8F8F0(v17))
  {
    v1 = v19;                         // Current count
    v2 = v21;                         // Current capacity
    v3 = v19;

    // Check if there's room to store another entity
    if (v19 != v21 || (v4 = v22, (v22 & 0x40000000) != 0))
    {
      // If already have space or special flag set
      v9 = EntityInstance;
    }
    else
    {
      // Not enough space — resize entity array

      // Prevent overflow (if max size reached)
      if (v21 == 0x7FFFFFFF)
      {
        UtlMemory_FailedAllocation(0x7FFFFFFF, 1);
        v4 = v22;
        v2 = v21;
      }

      v5 = v2 + 1;   // New desired count
      v6 = UtlMemory_CalcNewAllocationCount(v2, v4 & 0x3FFFFFFF, v2 + 1, 8);  // Compute new size
      v8 = v6;
      if (v6 < v5)
      {
        // Binary search resize to find a safe capacity
        if (v6 || v5 > -1)
        {
          do
          {
            v7 = ((v8 + v5) >> 31);   // Sign check
            v8 = (v8 + v5) / 2;
          }
          while (v8 < v5);
        }
        else
        {
          v8 = -1;
        }
      }

      // Allocate new memory
      LOBYTE(v7) = (v22 & 0xC0000000) == 0;
      v9 = UtlMemory_Alloc(EntityInstance, v7, 8i64 * v8, 8i64 * v21);
      EntityInstance = v9;

      // Update flags
      if ((v22 & 0xC0000000) != 0)
        v22 &= 0x3FFFFFFF;
      v1 = v19;
      v21 = v8;
    }

    // Store the entity pointer
    v19 = v1 + 1;
    *(v9 + 8 * v3) = Ent;
  }

  v10 = v19;
  if (v19 > 1)
  {
    // Sort the entity list (by pointer or ent index)
    V_qsort(EntityInstance, v19, 8, sub_181358FA0);
    v10 = v19;
  }

  // ----------- Print out all stored entities --------------
  EntInstance = EntityInstance;
  v12 = &EntityInstance[8 * v10];

  if (EntityInstance != v12)
  {
    do
    {
      Entity = *EntInstance;     // Actual entity pointer

      // Default name (fallback if null)
      entName = &unk_182FB02FA;

      // Get entity name
      if (*(*(*EntInstance + 0x10i64) + 0x18i64)) // *(ent->m_pEntity + 0x10)->name
        entName = *(*(*EntInstance + 0x10i64) + 0x18i64);

      // Get class name: (*(vftable + 352)) returns struct, offset 8 has name
      className = *((*(**EntInstance + 352i64))(*EntInstance) + 8);

      // Get ent index from entity handle
      sub_182AA0100(Entity, &entIndex);

      // Print out: Ent 12345: class C_Foo name "MyEntity"
      ConMsg("Ent %5d: class %s name \"%s\"\n", entIndex, className, entName);

      EntInstance += 8;         // Next entity
    }
    while (EntInstance != v12);

    EntInstance = EntityInstance;  // Restore pointer
  }

  // ----------- Cleanup memory -----------------------------
  v19 = 0;
  if ((v21 & 0x80000000) != 0 || EntInstance == v23)
  {
    // Used stack buffer — no need to free
    result = v22;
  }
  else
  {
    // Free dynamically allocated memory
    if (EntInstance && (v22 & 0xC0000000) == 0)
      (*(*g_pMemAlloc + 0x18))(g_pMemAlloc, EntInstance);

    // Reset to stack buffer
    EntInstance = v23;
    EntityInstance = v23;
    result = (v22 & 0x3FFFFFFF) | 0x80000000;
    v21 = 1024;
    v22 = result;
  }

  // Final cleanup: free again if needed
  if ((result & 0xC0000000) == 0)
  {
    if (EntInstance)
      return (*(*g_pMemAlloc + 0x18))(g_pMemAlloc, EntInstance);
  }

  return result;
}
 
I can't understand the logic behind that. also why entity index goes from 3-digit to 5-digit? what is the purpose of doing this?

C++:
Expand Collapse Copy
[Console] Ent 242: class CDOTA_Item_TeleportScroll name "item_tpscroll"
[Console] Ent 16408: class CBaseModelEntity name "divine_ambient"
[Console] Ent 16409: class CPointCamera name "camera_1"
[Console] Ent 16418: class CParticleSystem name ""
if index > 16383, it's clientside-only(non-networkable) entities iirc(the server doesn't manage them)(you don't really need them most of the time it's shit like trees decorations etc.)
also the iteration in cl_showents is now just like in cl_ent_find, i.e. entitysystem->FirstIdentity()->m_pNext->m_pNext->m_pNext->...->nullptr (aka GetNextEnt)(CEntityIdentity are linked-list'ed with each other)(this form of iteration also gives you these crappy clientside entities, unlike the previous GetHighestIndex-based iteration which only gave you networkable entities)
you could also just loop through all entities once, fill your own entity-list-thingie with what you need and then hook/monitor entity creation/deletion and reflect the changes in your own list
unless I'm mistaken ofc
 
if index > 16383, it's clientside-only(non-networkable) entities iirc(the server doesn't manage them)(you don't really need them most of the time it's shit like trees decorations etc.)
also the iteration in cl_showents is now just like in cl_ent_find, ie entitysystem->FirstIdentity()->m_pNext->m_pNext->m_pNext->...->nullptr (aka GetNextEnt)(CEntityIdentity are linked-list'ed with each other)(this form of iteration also gives you these crappy clientside entities, unlike the previous GetHighestIndex-based iteration which only gave you networkable entities)
you could also just loop through all entities once, fill your own entity-list-thingie with what you need and then hook/monitor entity creation/deletion and reflect the changes in your own list
unless I'm mistaken


Some creep indices were greater than 16,383 for me. I need their health values for last-hitting.
Isn't there a better way to traverse the entity list? I really don't like the linkedlist method.
(Also what's offset for entitysystem->FirstIdentity, 0x10?, and m_pNext is 0x60?)
 
Последнее редактирование:
Isn't there a better way to traverse the entity list? I really don't like the linkedlist method.
(Also what's offset for entitysystem->FirstIdentity, 0x10?, and m_pNext is 0x60?)
0x210 or something for firstidentity, and m_pNext is documented in schema in CEntityIdentity
Some creep indices were greater than 16,383 for me. I need their health values for last-hitting.
you sure? mind double-checking?
cuz indices don't even correspond to each other on the client and on the server when they're > 16383
(they do for indices below that, though. and the server(unless I'm mistaken, ofc) uses indices to correlate networkable entities on the client and on the server, i.e. when your hero gets his hp updated, the server sends "entity at index 123 got its hp updated", and the client updates the hp of the entity at index 123, whichever entity that may be. if they don't match there will be problems. and they don't match for >16383)
Пожалуйста, авторизуйтесь для просмотра ссылки.
Пожалуйста, авторизуйтесь для просмотра ссылки.
" The first 2048 entries are reserved for entities with
Пожалуйста, авторизуйтесь для просмотра ссылки.
, which cross the client/server divide "(2048 is from a different game. for dota 2 it appears to be 16384)
Пожалуйста, авторизуйтесь для просмотра ссылки.
"In
Пожалуйста, авторизуйтесь для просмотра ссылки.
, specifically
Пожалуйста, авторизуйтесь для просмотра ссылки.
, the networked entity limit is 16384
Пожалуйста, авторизуйтесь для просмотра ссылки.
.
Пожалуйста, авторизуйтесь для просмотра ссылки.
- max 16384 edicts and 16384 server-only entities"
1748350979596.png

(cl_ is client command, without the prefix is the server command)
again, you can iterate once and populate your own list and then just track updates by hooking entity creation/deletion(OnAddEntity/OnRemoveEntity kind-of-thingie)
 
Последнее редактирование:
0x210 or something for firstidentity, and m_pNext is documented in schema in CEntityIdentity

are you sure? mind double-checking?
cuz indices don't even correspond to each other on the client and on the server when they're > 16383
(they do for indices below that, though. and the server(unless I'm mistaken, ofc) uses indices to correlate networkable entities on the client and on the server, ie when your hero gets his hp updated, the server sends "entity at index 123 got its hp updated", and the client updates the hp of the entity at index 123, whichever entity that may be. if they don't match there will be problems. and they don't match for >16383)
Пожалуйста, авторизуйтесь для просмотра ссылки.
Пожалуйста, авторизуйтесь для просмотра ссылки.
" The first 2048 entries are reserved for entities with
Пожалуйста, авторизуйтесь для просмотра ссылки.
, which cross the client/server divide "(2048 is from a different game. for dota 2 it appears to be 16384)
Пожалуйста, авторизуйтесь для просмотра ссылки.
"In
Пожалуйста, авторизуйтесь для просмотра ссылки.
, specifically
Пожалуйста, авторизуйтесь для просмотра ссылки.
, the networked entity limit is 16384
Пожалуйста, авторизуйтесь для просмотра ссылки.
.
Пожалуйста, авторизуйтесь для просмотра ссылки.
- max 16384 edicts and 16384 server-only entities"
Посмотреть вложение 307333
(cl_ is client command, without the prefix is the server command)
again, you can iterate once and populate your own list and then just track updates by hooking entity creation/deletion(OnAddEntity/OnRemoveEntity kind-of-thingie)

You are right. my mistake. I just work with linkedlist right now and it works fine. Thanks
 
Назад
Сверху Снизу