Cache created entities by reference instead of index in SDKHooks (#634)
Fixes #663.
This commit is contained in:
parent
fdac8a1677
commit
29d1187434
@ -103,8 +103,6 @@ SMEXT_LINK(&g_Interface);
|
||||
CGlobalVars *gpGlobals;
|
||||
ke::Vector<CVTableList *> g_HookList[SDKHook_MAXHOOKS];
|
||||
|
||||
CBitVec<NUM_ENT_ENTRIES> m_EntityExists;
|
||||
|
||||
IBinTools *g_pBinTools = NULL;
|
||||
ICvar *icvar = NULL;
|
||||
|
||||
@ -231,6 +229,8 @@ bool SDKHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(m_EntityCache, INVALID_EHANDLE_INDEX, sizeof(m_EntityCache));
|
||||
|
||||
CUtlVector<IEntityListener *> *entListeners = EntListeners();
|
||||
if (!entListeners)
|
||||
{
|
||||
@ -270,13 +270,20 @@ bool SDKHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
continue;
|
||||
|
||||
index = hndl.GetEntryIndex();
|
||||
m_EntityExists.Set(index);
|
||||
if (IsEntityIndexInRange(index))
|
||||
{
|
||||
m_EntityCache[index] = gamehelpers->IndexToReference(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_pSM->LogError(myself, "SDKHooks::HandleEntityCreated - Got entity index out of range (%d)", index);
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < NUM_ENT_ENTRIES; i++)
|
||||
{
|
||||
if (gamehelpers->ReferenceToEntity(i) != NULL)
|
||||
m_EntityExists.Set(i);
|
||||
m_EntityCache[i] = gamehelpers->IndexToReference(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -411,14 +418,14 @@ void SDKHooks::OnClientPutInServer(int client)
|
||||
{
|
||||
CBaseEntity *pPlayer = gamehelpers->ReferenceToEntity(client);
|
||||
|
||||
HandleEntityCreated(pPlayer, client);
|
||||
HandleEntityCreated(pPlayer, client, gamehelpers->EntityToReference(pPlayer));
|
||||
}
|
||||
|
||||
void SDKHooks::OnClientDisconnecting(int client)
|
||||
{
|
||||
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(client);
|
||||
|
||||
HandleEntityDeleted(pEntity, client);
|
||||
HandleEntityDeleted(pEntity);
|
||||
}
|
||||
|
||||
void SDKHooks::AddEntityListener(ISMEntityListener *listener)
|
||||
@ -849,16 +856,26 @@ void SDKHooks::Unhook(int entity, SDKHookType type, IPluginFunction *pCallback)
|
||||
void SDKHooks::OnEntityCreated(CBaseEntity *pEntity)
|
||||
{
|
||||
// Call OnEntityCreated forward
|
||||
int ref = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
int ref = gamehelpers->EntityToReference(pEntity);
|
||||
int index = gamehelpers->ReferenceToIndex(ref);
|
||||
|
||||
// This can be -1 for player ents before any players have connected
|
||||
if ((unsigned)index == INVALID_EHANDLE_INDEX || m_EntityExists.IsBitSet(index) || (index > 0 && index <= playerhelpers->GetMaxClients()))
|
||||
if ((unsigned)index == INVALID_EHANDLE_INDEX || (index > 0 && index <= playerhelpers->GetMaxClients()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HandleEntityCreated(pEntity, ref);
|
||||
if (!IsEntityIndexInRange(index))
|
||||
{
|
||||
g_pSM->LogError(myself, "SDKHooks::OnEntityCreated - Got entity index out of range (%d)", index);
|
||||
return;
|
||||
}
|
||||
|
||||
// The entity could already exist. The creation notifier fires twice for some paths
|
||||
if (m_EntityCache[index] != ref)
|
||||
{
|
||||
HandleEntityCreated(pEntity, index, ref);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GAMEDESC_CAN_CHANGE
|
||||
@ -1633,8 +1650,7 @@ void SDKHooks::Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_T
|
||||
|
||||
void SDKHooks::OnEntityDeleted(CBaseEntity *pEntity)
|
||||
{
|
||||
int ref = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
int index = gamehelpers->ReferenceToIndex(ref);
|
||||
int index = gamehelpers->ReferenceToIndex(gamehelpers->EntityToReference(pEntity));
|
||||
|
||||
// This can be -1 for player ents before any players have connected
|
||||
if ((unsigned)index == INVALID_EHANDLE_INDEX || (index > 0 && index <= playerhelpers->GetMaxClients()))
|
||||
@ -1642,7 +1658,7 @@ void SDKHooks::OnEntityDeleted(CBaseEntity *pEntity)
|
||||
return;
|
||||
}
|
||||
|
||||
HandleEntityDeleted(pEntity, ref);
|
||||
HandleEntityDeleted(pEntity);
|
||||
}
|
||||
|
||||
void SDKHooks::Hook_VPhysicsUpdate(IPhysicsObject *pPhysics)
|
||||
@ -1752,9 +1768,10 @@ bool SDKHooks::Hook_WeaponSwitchPost(CBaseCombatWeapon *pWeapon, int viewmodelin
|
||||
RETURN_META_VALUE(MRES_IGNORED, true);
|
||||
}
|
||||
|
||||
void SDKHooks::HandleEntityCreated(CBaseEntity *pEntity, int ref)
|
||||
void SDKHooks::HandleEntityCreated(CBaseEntity *pEntity, int index, cell_t ref)
|
||||
{
|
||||
const char *pName = gamehelpers->GetEntityClassname(pEntity);
|
||||
cell_t bcompatRef = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
|
||||
// Send OnEntityCreated to SM listeners
|
||||
SourceHook::List<ISMEntityListener *>::iterator iter;
|
||||
@ -1766,15 +1783,17 @@ void SDKHooks::HandleEntityCreated(CBaseEntity *pEntity, int ref)
|
||||
}
|
||||
|
||||
// Call OnEntityCreated forward
|
||||
g_pOnEntityCreated->PushCell(ref);
|
||||
g_pOnEntityCreated->PushCell(bcompatRef);
|
||||
g_pOnEntityCreated->PushString(pName ? pName : "");
|
||||
g_pOnEntityCreated->Execute(NULL);
|
||||
|
||||
m_EntityExists.Set(gamehelpers->ReferenceToIndex(ref));
|
||||
m_EntityCache[index] = ref;
|
||||
}
|
||||
|
||||
void SDKHooks::HandleEntityDeleted(CBaseEntity *pEntity, int ref)
|
||||
void SDKHooks::HandleEntityDeleted(CBaseEntity *pEntity)
|
||||
{
|
||||
cell_t bcompatRef = gamehelpers->EntityToBCompatRef(pEntity);
|
||||
|
||||
// Send OnEntityDestroyed to SM listeners
|
||||
SourceHook::List<ISMEntityListener *>::iterator iter;
|
||||
ISMEntityListener *pListener = NULL;
|
||||
@ -1785,10 +1804,8 @@ void SDKHooks::HandleEntityDeleted(CBaseEntity *pEntity, int ref)
|
||||
}
|
||||
|
||||
// Call OnEntityDestroyed forward
|
||||
g_pOnEntityDestroyed->PushCell(ref);
|
||||
g_pOnEntityDestroyed->PushCell(bcompatRef);
|
||||
g_pOnEntityDestroyed->Execute(NULL);
|
||||
|
||||
Unhook(pEntity);
|
||||
|
||||
m_EntityExists.Set(gamehelpers->ReferenceToIndex(ref), false);
|
||||
}
|
||||
|
@ -311,7 +311,6 @@ public:
|
||||
void Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr);
|
||||
void Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr);
|
||||
#endif
|
||||
void Hook_UpdateOnRemove();
|
||||
void Hook_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
||||
void Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value);
|
||||
void Hook_VPhysicsUpdate(IPhysicsObject *pPhysics);
|
||||
@ -330,14 +329,18 @@ public:
|
||||
bool Hook_WeaponSwitchPost(CBaseCombatWeapon *pWeapon, int viewmodelindex);
|
||||
|
||||
private:
|
||||
void HandleEntityCreated(CBaseEntity *pEntity, int ref);
|
||||
void HandleEntityDeleted(CBaseEntity *pEntity, int ref);
|
||||
void HandleEntityCreated(CBaseEntity *pEntity, int index, cell_t ref);
|
||||
void HandleEntityDeleted(CBaseEntity *pEntity);
|
||||
void Unhook(CBaseEntity *pEntity);
|
||||
void Unhook(IPluginContext *pContext);
|
||||
|
||||
private:
|
||||
int HandleOnTakeDamageHook(CTakeDamageInfoHack &info, SDKHookType hookType);
|
||||
int HandleOnTakeDamageHookPost(CTakeDamageInfoHack &info, SDKHookType hookType);
|
||||
|
||||
private:
|
||||
inline bool IsEntityIndexInRange(int i) { return i >= 0 && i < NUM_ENT_ENTRIES; }
|
||||
cell_t m_EntityCache[NUM_ENT_ENTRIES];
|
||||
};
|
||||
|
||||
extern CGlobalVars *gpGlobals;
|
||||
|
Loading…
Reference in New Issue
Block a user