From 3a94bd4fefd660eb4741068f47c6eda3916d5a09 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Wed, 9 Jul 2014 17:32:32 -0400 Subject: [PATCH 1/3] Add support to Get/SetEntPropEnt for FIELD_CLASSPTR and FIELD_CLASSPTR datadesc fields. --- core/smn_entities.cpp | 143 +++++++++++++++++++++++++++++++++--------- 1 file changed, 113 insertions(+), 30 deletions(-) diff --git a/core/smn_entities.cpp b/core/smn_entities.cpp index 9131818a..a7cd4646 100644 --- a/core/smn_entities.cpp +++ b/core/smn_entities.cpp @@ -1519,6 +1519,13 @@ static cell_t SetEntPropFloat(IPluginContext *pContext, const cell_t *params) return 1; } +enum PropEntType +{ + PropEnt_Handle, + PropEnt_Entity, + PropEnt_Edict, +}; + static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params) { CBaseEntity *pEntity; @@ -1526,6 +1533,7 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params) int offset; int bit_count; edict_t *pEdict; + PropEntType type; int element = 0; if (params[0] >= 4) @@ -1548,12 +1556,21 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params) FIND_PROP_DATA(td); - if (td->fieldType != FIELD_EHANDLE) + switch (td->fieldType) { - return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)", + case FIELD_EHANDLE: + type = PropEnt_Handle; + break; + case FIELD_CLASSPTR: + type = PropEnt_Entity; + break; + case FIELD_EDICT: + type = PropEnt_Edict; + break; + default: + return pContext->ThrowNativeError("Data field %s is not an entity nor edict (%d)", prop, - td->fieldType, - FIELD_EHANDLE); + td->fieldType); } CHECK_SET_PROP_DATA_OFFSET(); @@ -1562,6 +1579,7 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params) } case Prop_Send: { + type = PropEnt_Handle; FIND_PROP_SEND(DPT_Int, "integer"); break; } @@ -1571,13 +1589,34 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params) } } - CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset); - CBaseEntity *pHandleEntity = g_HL2.ReferenceToEntity(hndl.GetEntryIndex()); + switch (type) + { + case PropEnt_Handle: + { + CBaseHandle &hndl = *(CBaseHandle *) ((uint8_t *) pEntity + offset); + CBaseEntity *pHandleEntity = g_HL2.ReferenceToEntity(hndl.GetEntryIndex()); - if (!pHandleEntity || hndl != reinterpret_cast(pHandleEntity)->GetRefEHandle()) - return -1; + if (!pHandleEntity || hndl != reinterpret_cast(pHandleEntity)->GetRefEHandle()) + return -1; - return g_HL2.EntityToBCompatRef(pHandleEntity); + return g_HL2.EntityToBCompatRef(pHandleEntity); + } + case PropEnt_Entity: + { + CBaseEntity *pPropEntity = *(CBaseEntity **) ((uint8_t *) pEntity + offset); + return g_HL2.EntityToBCompatRef(pPropEntity); + } + case PropEnt_Edict: + { + edict_t *pEdict = *(edict_t **) ((uint8_t *) pEntity + offset); + if (!pEdict || pEdict->IsFree()) + return -1; + + return IndexOfEdict(pEdict); + } + } + + return -1; } static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params) @@ -1587,6 +1626,7 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params) int offset; int bit_count; edict_t *pEdict; + PropEntType type; int element = 0; if (params[0] >= 5) @@ -1609,12 +1649,23 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params) FIND_PROP_DATA(td); - if (td->fieldType != FIELD_EHANDLE) + switch (td->fieldType) { - return pContext->ThrowNativeError("Data field %s is not an entity (%d != %d)", + case FIELD_EHANDLE: + type = PropEnt_Handle; + break; + case FIELD_CLASSPTR: + type = PropEnt_Entity; + break; + case FIELD_EDICT: + type = PropEnt_Edict; + if (!pEdict) + return pContext->ThrowNativeError("Edict %d is invalid", params[1]); + break; + default: + return pContext->ThrowNativeError("Data field %s is not an entity nor edict (%d)", prop, - td->fieldType, - FIELD_EHANDLE); + td->fieldType); } CHECK_SET_PROP_DATA_OFFSET(); @@ -1623,6 +1674,7 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params) } case Prop_Send: { + type = PropEnt_Handle; FIND_PROP_SEND(DPT_Int, "integer"); break; } @@ -1632,28 +1684,59 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params) } } - CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset); - - if (params[4] == -1) + CBaseEntity *pOther = GetEntity(params[4]); + if (!pOther) { - hndl.Set(NULL); + return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[4]), params[4]); } - else - { - CBaseEntity *pOther = GetEntity(params[4]); - if (!pOther) - { - return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[4]), params[4]); + switch (type) + { + case PropEnt_Handle: + { + CBaseHandle &hndl = *(CBaseHandle *) ((uint8_t *) pEntity + offset); + + if (!pOther) + { + hndl.Set(NULL); + } + else + { + IHandleEntity *pHandleEnt = (IHandleEntity *) pOther; + hndl.Set(pHandleEnt); + } + + if (params[2] == Prop_Send && (pEdict != NULL)) + { + g_HL2.SetEdictStateChanged(pEdict, offset); + } } - IHandleEntity *pHandleEnt = (IHandleEntity *)pOther; - hndl.Set(pHandleEnt); - } - - if (params[2] == Prop_Send && (pEdict != NULL)) - { - g_HL2.SetEdictStateChanged(pEdict, offset); + break; + + case PropEnt_Entity: + { + *(CBaseEntity **) ((uint8_t *) pEntity + offset) = pOther; + break; + } + + case PropEnt_Edict: + { + IServerNetworkable *pNetworkable = ((IServerUnknown *) pOther)->GetNetworkable(); + if (!pNetworkable) + { + return pContext->ThrowNativeError("Entity %d (%d) does not have a valid edict", g_HL2.ReferenceToIndex(params[4]), params[4]); + } + + edict_t *pOtherEdict = pNetworkable->GetEdict(); + if (!pOtherEdict || pOtherEdict->IsFree()) + { + return pContext->ThrowNativeError("Entity %d (%d) does not have a valid edict", g_HL2.ReferenceToIndex(params[4]), params[4]); + } + + *(edict_t **) ((uint8_t *) pEntity + offset) = pOtherEdict; + break; + } } return 1; From f7a64167fc7ac41d7d99f0a7652bef446555f77b Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Wed, 9 Jul 2014 19:25:45 -0400 Subject: [PATCH 2/3] Fix Dota 2 build. --- core/smn_entities.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/smn_entities.cpp b/core/smn_entities.cpp index a7cd4646..5d14a9a1 100644 --- a/core/smn_entities.cpp +++ b/core/smn_entities.cpp @@ -1564,9 +1564,11 @@ static cell_t GetEntPropEnt(IPluginContext *pContext, const cell_t *params) case FIELD_CLASSPTR: type = PropEnt_Entity; break; +#if SOURCE_ENGINE != SE_DOTA case FIELD_EDICT: type = PropEnt_Edict; break; +#endif default: return pContext->ThrowNativeError("Data field %s is not an entity nor edict (%d)", prop, @@ -1657,11 +1659,13 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params) case FIELD_CLASSPTR: type = PropEnt_Entity; break; +#if SOURCE_ENGINE != SE_DOTA case FIELD_EDICT: type = PropEnt_Edict; if (!pEdict) return pContext->ThrowNativeError("Edict %d is invalid", params[1]); break; +#endif default: return pContext->ThrowNativeError("Data field %s is not an entity nor edict (%d)", prop, From 0b5e587db938a448b48b1c537bf38c24d759e718 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Wed, 9 Jul 2014 20:33:38 -0400 Subject: [PATCH 3/3] Remove unnecessary null check. --- core/smn_entities.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/core/smn_entities.cpp b/core/smn_entities.cpp index 5d14a9a1..461131e9 100644 --- a/core/smn_entities.cpp +++ b/core/smn_entities.cpp @@ -1699,16 +1699,7 @@ static cell_t SetEntPropEnt(IPluginContext *pContext, const cell_t *params) case PropEnt_Handle: { CBaseHandle &hndl = *(CBaseHandle *) ((uint8_t *) pEntity + offset); - - if (!pOther) - { - hndl.Set(NULL); - } - else - { - IHandleEntity *pHandleEnt = (IHandleEntity *) pOther; - hndl.Set(pHandleEnt); - } + hndl.Set((IHandleEntity *) pOther); if (params[2] == Prop_Send && (pEdict != NULL)) {