Reconcile the concept of Edict & Networkable across the codebase (#1903)

* Reconcile the concept of Edict & Networkable across the codebase

* There's no need to check this, it's done elsewhere. Also could be null (segfault)

* This was never needed

* Pseudo review changes

Re-added removed null checks, and added new ones.

Changed the error messages in Get/SetProp natives to better reflect reality.

* Don't change the behaviour of GetEntityNetClass

* Overload IGameHelpers::FindServerClass

* Make error messages more accurate

* Fix a dev comment

* Rename FindServerClass

---------

Co-authored-by: Kenzzer <[email protected]>
This commit is contained in:
Benoist
2024-06-01 14:07:55 +00:00
committed by GitHub
co-authored by Kenzzer
parent 9f3584a056
commit 7df2f8e045
13 changed files with 152 additions and 118 deletions
+6 -3
View File
@@ -254,10 +254,13 @@ static cell_t CS_DropWeapon(IPluginContext *pContext, const cell_t *params)
//Psychonic is awesome for this
sm_sendprop_info_t spi;
IServerUnknown *pUnk = (IServerUnknown *)pWeapon;
IServerNetworkable *pNet = pUnk->GetNetworkable();
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pWeapon);
if (pServerClass == nullptr)
{
return pContext->ThrowNativeError("Failed to retrieve entity %d server class!", params[2]);
}
if (!UTIL_FindDataTable(pNet->GetServerClass()->m_pTable, "DT_WeaponCSBase", &spi, 0))
if (!UTIL_FindDataTable(pServerClass->m_pTable, "DT_WeaponCSBase", &spi, 0))
return pContext->ThrowNativeError("Entity index %d is not a weapon", params[2]);
if (!gamehelpers->FindSendPropInfo("CBaseCombatWeapon", "m_hOwnerEntity", &spi))
+9 -4
View File
@@ -614,11 +614,16 @@ HookReturn SDKHooks::Hook(int entity, SDKHookType type, IPluginFunction *callbac
if (!!strcmp(g_HookTypes[type].dtReq, ""))
{
IServerUnknown *pUnk = (IServerUnknown *)pEnt;
IServerNetworkable *pNet = pUnk->GetNetworkable();
if (pNet && !UTIL_ContainsDataTable(pNet->GetServerClass()->m_pTable, g_HookTypes[type].dtReq))
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEnt);
if (pServerClass == nullptr)
{
return HookRet_BadEntForHookType;
}
if (!UTIL_ContainsDataTable(pServerClass->m_pTable, g_HookTypes[type].dtReq))
{
return HookRet_BadEntForHookType;
}
}
size_t entry;
+22 -19
View File
@@ -60,15 +60,15 @@ cell_t Native_Hook(IPluginContext *pContext, const cell_t *params)
break;
case HookRet_BadEntForHookType:
{
CBaseEntity *pEnt = gamehelpers->ReferenceToEntity(params[1]);
const char *pClassname = pEnt ? gamehelpers->GetEntityClassname(pEnt) : NULL;
if (!pClassname)
{
pContext->ThrowNativeError("Hook type not valid for this type of entity (%i).", entity);
}
else
{
pContext->ThrowNativeError("Hook type not valid for this type of entity (%i/%s)", entity, pClassname);
CBaseEntity *pEnt = gamehelpers->ReferenceToEntity(params[1]);
const char *pClassname = pEnt ? gamehelpers->GetEntityClassname(pEnt) : NULL;
if (!pClassname)
{
pContext->ThrowNativeError("Hook type not valid for this type of entity (%i).", entity);
}
else
{
pContext->ThrowNativeError("Hook type not valid for this type of entity (%i/%s)", entity, pClassname);
}
break;
@@ -185,9 +185,9 @@ cell_t Native_TakeDamage(IPluginContext *pContext, const cell_t *params)
if (!pCall)
{
int offset;
if (!g_pGameConf->GetOffset("OnTakeDamage", &offset))
{
return pContext->ThrowNativeError("Could not find OnTakeDamage offset");
if (!g_pGameConf->GetOffset("OnTakeDamage", &offset))
{
return pContext->ThrowNativeError("Could not find OnTakeDamage offset");
}
PassInfo pass[2];
@@ -230,10 +230,13 @@ cell_t Native_DropWeapon(IPluginContext *pContext, const cell_t *params)
if (!pWeapon)
return pContext->ThrowNativeError("Invalid entity index %d for weapon", params[2]);
IServerUnknown *pUnk = (IServerUnknown *)pWeapon;
IServerNetworkable *pNet = pUnk->GetNetworkable();
if (!UTIL_ContainsDataTable(pNet->GetServerClass()->m_pTable, "DT_BaseCombatWeapon"))
ServerClass *pClass = gamehelpers->FindEntityServerClass(pWeapon);
if (pClass == nullptr)
{
return pContext->ThrowNativeError("Failed to retrieve entity %d server class!", params[2]);
}
if (!UTIL_ContainsDataTable(pClass->m_pTable, "DT_BaseCombatWeapon"))
return pContext->ThrowNativeError("Entity index %d is not a weapon", params[2]);
sm_sendprop_info_t spi;
@@ -291,9 +294,9 @@ cell_t Native_DropWeapon(IPluginContext *pContext, const cell_t *params)
if (!pCall)
{
int offset;
if (!g_pGameConf->GetOffset("Weapon_Drop", &offset))
{
return pContext->ThrowNativeError("Could not find Weapon_Drop offset");
if (!g_pGameConf->GetOffset("Weapon_Drop", &offset))
{
return pContext->ThrowNativeError("Could not find Weapon_Drop offset");
}
PassInfo pass[3];
+14 -13
View File
@@ -45,26 +45,27 @@ static CBaseEntity *FindEntityByNetClass(int start, const char *classname)
int maxEntities = gpGlobals->maxEntities;
for (int i = start; i < maxEntities; i++)
{
edict_t *current = gamehelpers->EdictOfIndex(i);
if (current == NULL || current->IsFree())
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == nullptr)
{
continue;
}
IServerNetworkable *network = current->GetNetworkable();
if (network == NULL)
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
if (pServerClass == nullptr)
{
continue;
}
IHandleEntity *pHandleEnt = network->GetEntityHandle();
if (pHandleEnt == NULL)
continue;
ServerClass *sClass = network->GetServerClass();
const char *name = sClass->GetName();
const char *name = pServerClass->GetName();
if (!strcmp(name, classname))
return gamehelpers->ReferenceToEntity(gamehelpers->IndexOfEdict(current));
{
return pEntity;
}
}
return NULL;
return nullptr;
}
static CBaseEntity* GetGameRulesProxyEnt()
+11 -11
View File
@@ -50,19 +50,20 @@ void InitTeamNatives()
int edictCount = gpGlobals->maxEntities;
for (int i=0; i<edictCount; i++)
for (int i = 0; i < edictCount; i++)
{
edict_t *pEdict = PEntityOfEntIndex(i);
if (!pEdict || pEdict->IsFree())
{
continue;
}
if (!pEdict->GetNetworkable())
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == nullptr)
{
continue;
}
ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
ServerClass *pClass = gamehelpers->FindEntityServerClass(pEntity);
if (pClass == nullptr)
{
continue;
}
if (FindNestedDataTable(pClass->m_pTable, "DT_Team"))
{
SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum");
@@ -70,15 +71,14 @@ void InitTeamNatives()
if (pTeamNumProp != NULL)
{
int offset = pTeamNumProp->GetOffset();
CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity();
int TeamIndex = *(int *)((unsigned char *)pEnt + offset);
int TeamIndex = *(int *)((unsigned char *)pEntity + offset);
if (TeamIndex >= (int)g_Teams.size())
{
g_Teams.resize(TeamIndex+1);
}
g_Teams[TeamIndex].ClassName = pClass->GetName();
g_Teams[TeamIndex].pEnt = pEnt;
g_Teams[TeamIndex].pEnt = pEntity;
}
}
}
+7 -12
View File
@@ -321,28 +321,23 @@ void GetResourceEntity()
{
int edictCount = gpGlobals->maxEntities;
for (int i=0; i<edictCount; i++)
for (int i = 0; i < edictCount; i++)
{
edict_t *pEdict = PEntityOfEntIndex(i);
if (!pEdict || pEdict->IsFree())
{
continue;
}
if (!pEdict->GetNetworkable())
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == nullptr)
{
continue;
}
IHandleEntity *pHandleEnt = pEdict->GetNetworkable()->GetEntityHandle();
if (!pHandleEnt)
ServerClass *pClass = gamehelpers->FindEntityServerClass(pEntity);
if (pClass == nullptr)
{
continue;
}
ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
if (FindNestedDataTable(pClass->m_pTable, "DT_PlayerResource"))
{
g_ResourceEntity = pHandleEnt->GetRefEHandle();
g_ResourceEntity = ((IHandleEntity *)pEntity)->GetRefEHandle();
break;
}
}
+12 -2
View File
@@ -1689,7 +1689,12 @@ static cell_t LookupEntityAttachment(IPluginContext* pContext, const cell_t* par
CBaseEntity* pEntity;
ENTINDEX_TO_CBASEENTITY(params[1], pEntity);
ServerClass* pClass = ((IServerUnknown*)pEntity)->GetNetworkable()->GetServerClass();
ServerClass* pClass = gamehelpers->FindEntityServerClass(pEntity);
if (pClass == nullptr)
{
return pContext->ThrowNativeError("Failed to retrieve entity %d (%d) server class!", gamehelpers->ReferenceToIndex(params[1]), params[1]);
}
if (!FindNestedDataTable(pClass->m_pTable, "DT_BaseAnimating"))
{
return pContext->ThrowNativeError("Entity %d (%d) is not a CBaseAnimating", gamehelpers->ReferenceToIndex(params[1]), params[1]);
@@ -1735,7 +1740,12 @@ static cell_t GetEntityAttachment(IPluginContext* pContext, const cell_t* params
CBaseEntity* pEntity;
ENTINDEX_TO_CBASEENTITY(params[1], pEntity);
ServerClass* pClass = ((IServerUnknown*)pEntity)->GetNetworkable()->GetServerClass();
ServerClass* pClass = gamehelpers->FindEntityServerClass(pEntity);
if (pClass == nullptr)
{
return pContext->ThrowNativeError("Failed to retrieve entity %d (%d) server class!", gamehelpers->ReferenceToIndex(params[1]), params[1]);
}
if (!FindNestedDataTable(pClass->m_pTable, "DT_BaseAnimating"))
{
return pContext->ThrowNativeError("Entity %d (%d) is not a CBaseAnimating", gamehelpers->ReferenceToIndex(params[1]), params[1]);
+22 -14
View File
@@ -76,16 +76,21 @@ bool CritManager::TryEnable()
for (size_t i = playerhelpers->GetMaxClients() + 1; i < MAX_EDICTS; ++i)
{
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == NULL)
if (pEntity == nullptr)
{
continue;
}
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
IServerNetworkable *pNetworkable = pUnknown->GetNetworkable();
if (!pNetworkable)
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
if (pServerClass == nullptr)
{
continue;
}
if (!UTIL_ContainsDataTable(pNetworkable->GetServerClass()->m_pTable, TF_WEAPON_DATATABLE))
if (!UTIL_ContainsDataTable(pServerClass->m_pTable, TF_WEAPON_DATATABLE))
{
continue;
}
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelper), false);
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelperNoCrits), false);
@@ -116,15 +121,20 @@ void CritManager::Disable()
void CritManager::OnEntityCreated(CBaseEntity *pEntity, const char *classname)
{
if (!m_enabled)
{
return;
}
IServerUnknown *pUnknown = (IServerUnknown *)pEntity;
IServerNetworkable *pNetworkable = pUnknown->GetNetworkable();
if (!pNetworkable)
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
if (pServerClass == nullptr)
{
return;
}
if (!UTIL_ContainsDataTable(pNetworkable->GetServerClass()->m_pTable, TF_WEAPON_DATATABLE))
if (!UTIL_ContainsDataTable(pServerClass->m_pTable, TF_WEAPON_DATATABLE))
{
return;
}
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelper, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelper), false);
SH_ADD_MANUALHOOK(CalcIsAttackCriticalHelperNoCrits, pEntity, SH_MEMBER(&g_CritManager, &CritManager::Hook_CalcIsAttackCriticalHelperNoCrits), false);
@@ -164,11 +174,9 @@ bool CritManager::Hook_CalcIsAttackCriticalHelpers(bool noCrits)
{
CBaseEntity *pWeapon = META_IFACEPTR(CBaseEntity);
// If there's an invalid ent or invalid networkable here, we've got issues elsewhere.
IServerNetworkable *pNetWeapon = ((IServerUnknown *)pWeapon)->GetNetworkable();
ServerClass *pServerClass = pNetWeapon->GetServerClass();
if (!pServerClass)
// If there's an invalid ent or invalid server class here, we've got issues elsewhere.
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pWeapon);
if (pServerClass == nullptr)
{
g_pSM->LogError(myself, "Invalid server class on weapon.");
RETURN_META_VALUE(MRES_IGNORED, false);
+5 -9
View File
@@ -435,23 +435,19 @@ int FindEntityByNetClass(int start, const char *classname)
for (int i = ((start != -1) ? start : 0); i < gpGlobals->maxEntities; i++)
{
current = engine->PEntityOfEntIndex(i);
if (current == NULL || current->IsFree())
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(i);
if (pEntity == nullptr)
{
continue;
}
IServerNetworkable *network = current->GetNetworkable();
if (network == NULL)
ServerClass *pServerClass = gamehelpers->FindEntityServerClass(pEntity);
if (pServerClass == nullptr)
{
continue;
}
ServerClass *sClass = network->GetServerClass();
const char *name = sClass->GetName();
const char *name = pServerClass->GetName();
if (strcmp(name, classname) == 0)
{
return i;