From b56de5d546718e1d78b3ab39a2eba4716165ba9f Mon Sep 17 00:00:00 2001 From: Borja Ferrer Date: Sat, 14 Apr 2007 02:24:23 +0000 Subject: [PATCH] added entity string natives --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40700 --- core/smn_entities.cpp | 212 +++++++++++++++++++++++++++++++++++++ plugins/include/entity.inc | 56 +++++++++- 2 files changed, 266 insertions(+), 2 deletions(-) diff --git a/core/smn_entities.cpp b/core/smn_entities.cpp index 26311228..93e0f662 100644 --- a/core/smn_entities.cpp +++ b/core/smn_entities.cpp @@ -19,6 +19,13 @@ #include "PlayerManager.h" #include "HalfLife2.h" #include "GameConfigs.h" +#include "sm_stringutil.h" + +enum PropType +{ + Prop_Send = 0, + Prop_Data +}; inline edict_t *GetEdict(cell_t num) { @@ -557,6 +564,207 @@ static cell_t FindDataMapOffs(IPluginContext *pContext, const cell_t *params) return td->fieldOffset[TD_OFFSET_NORMAL]; } +static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params) +{ + CBaseEntity *pEntity; + edict_t *pEdict = GetEntity(params[1], &pEntity); + + if (!pEdict || !pEntity) + { + return pContext->ThrowNativeError("Entity %d is invalid", params[1]); + } + + int offset = params[2]; + if (offset < 0 || offset > 32768) + { + return pContext->ThrowNativeError("Offset %d is invalid", offset); + } + + size_t len; + char *src = (char *)((uint8_t *)pEntity + offset); + pContext->StringToLocalUTF8(params[3], params[4], src, &len); + + return len; +} + +static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params) +{ + CBaseEntity *pEntity; + edict_t *pEdict = GetEntity(params[1], &pEntity); + + if (!pEdict || !pEntity) + { + return pContext->ThrowNativeError("Entity %d is invalid", params[1]); + } + + int offset = params[2]; + if (offset < 0 || offset > 32768) + { + return pContext->ThrowNativeError("Offset %d is invalid", offset); + } + + char *src; + char *dest = (char *)((uint8_t *)pEntity + offset); + + pContext->LocalToString(params[3], &src); + size_t len = strncopy(dest, src, params[4]); + + if (params[5]) + { + g_HL2.SetEdictStateChanged(pEdict, offset); + } + + return len; +} + +static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params) +{ + CBaseEntity *pEntity; + char *prop; + int offset; + edict_t *pEdict = GetEntity(params[1], &pEntity); + + if (!pEdict || !pEntity) + { + return pContext->ThrowNativeError("Entity %d is invalid", params[1]); + } + + switch (params[2]) + { + case Prop_Data: + { + datamap_t *pMap; + typedescription_t *td; + if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL) + { + return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset"); + } + pContext->LocalToString(params[3], &prop); + if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL) + { + return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]); + } + if (td->fieldType != FIELD_CHARACTER) + { + return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop); + } + offset = td->fieldOffset[TD_OFFSET_NORMAL]; + break; + } + case Prop_Send: + { + char *prop; + IServerNetworkable *pNet = pEdict->GetNetworkable(); + if (!pNet) + { + return pContext->ThrowNativeError("The edict is not networkable"); + } + pContext->LocalToString(params[3], &prop); + SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop); + if (!pSend) + { + return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]); + } + if (pSend->GetType() != DPT_String) + { + return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop); + } + offset = pSend->GetOffset(); + break; + } + default: + { + return pContext->ThrowNativeError("Invalid Property type %d", params[2]); + } + } + + size_t len; + char *src = (char *)((uint8_t *)pEntity + offset); + pContext->StringToLocalUTF8(params[4], params[5], src, &len); + + return len; +} + +static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params) +{ + CBaseEntity *pEntity; + char *prop; + int offset; + int maxlen; + bool is_sendprop = false; + edict_t *pEdict = GetEntity(params[1], &pEntity); + + if (!pEdict || !pEntity) + { + return pContext->ThrowNativeError("Entity %d is invalid", params[1]); + } + + switch (params[2]) + { + case Prop_Data: + { + datamap_t *pMap; + typedescription_t *td; + if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL) + { + return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset"); + } + pContext->LocalToString(params[3], &prop); + if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL) + { + return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]); + } + if (td->fieldType != FIELD_CHARACTER) + { + return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop); + } + offset = td->fieldOffset[TD_OFFSET_NORMAL]; + maxlen = td->fieldSize; + break; + } + case Prop_Send: + { + char *prop; + IServerNetworkable *pNet = pEdict->GetNetworkable(); + if (!pNet) + { + return pContext->ThrowNativeError("The edict is not networkable"); + } + pContext->LocalToString(params[3], &prop); + SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop); + if (!pSend) + { + return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]); + } + if (pSend->GetType() != DPT_String) + { + return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop); + } + offset = pSend->GetOffset(); + maxlen = DT_MAX_STRING_BUFFERSIZE; + is_sendprop = true; + break; + } + default: + { + return pContext->ThrowNativeError("Invalid Property type %d", params[2]); + } + } + + char *src; + char *dest = (char *)((uint8_t *)pEntity + offset); + + pContext->LocalToString(params[4], &src); + size_t len = strncopy(dest, src, maxlen); + + if (is_sendprop) + { + g_HL2.SetEdictStateChanged(pEdict, offset); + } + + return len; +} + REGISTER_NATIVES(entityNatives) { {"ChangeEdictState", ChangeEdictState}, @@ -581,5 +789,9 @@ REGISTER_NATIVES(entityNatives) {"SetEntDataFloat", SetEntDataFloat}, {"SetEntDataVector", SetEntDataVector}, {"FindDataMapOffs", FindDataMapOffs}, + {"GetEntDataString", GetEntDataString}, + {"SetEntDataString", SetEntDataString}, + {"GetEntPropString", GetEntPropString}, + {"SetEntPropString", SetEntPropString}, {NULL, NULL} }; diff --git a/plugins/include/entity.inc b/plugins/include/entity.inc index f2e0eced..38eb7cdb 100644 --- a/plugins/include/entity.inc +++ b/plugins/include/entity.inc @@ -234,7 +234,7 @@ native SetEntDataFloat(entity, offset, Float:value, bool:changeState=false); native GetEntDataEnt(entity, offset); /** - * Peeks into an entity's object data and sest the entity handle info + * Peeks into an entity's object data and sets the entity handle info * at the given offset. * * @param entity Edict index. @@ -275,6 +275,33 @@ native GetEntDataVector(entity, offset, Float:vec[3]); */ native SetEntDataVector(entity, offset, const Float:vec[3], bool:changeState=false); +/** + * Peeks into an entity's object data and retrieves the string at + * the given offset. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param buffer Destination string buffer. + * @param maxlen Maximum length of output string buffer. + * @return Number of non-null bytes written. + * @error Invalid entity or offset out of reasonable bounds. + */ +native GetEntDataString(entity, offset, String:buffer[], maxlen); + +/** + * Peeks into an entity's object data and sets the string at + * the given offset. + * + * @param entity Edict index. + * @param offset Offset to use. + * @param buffer String to set. + * @param maxlen Maximum length of bytes to write. + * @param changeState If true, change will be sent over the network. + * @return Number of non-null bytes written. + * @error Invalid entity or offset out of reasonable bounds. + */ +native SetEntDataString(entity, offset, const String:buffer[], maxlen, bool:changeState=false); + /** * @endsection */ @@ -400,7 +427,7 @@ stock SetEntProp(entity, PropType:type, const String:prop[], value, size=4) * @param entity Edict index. * @param type Property type. * @param prop Property to use. - * @return Value at the given property offset.. + * @return Value at the given property offset. * @error Invalid entity or offset out of reasonable bounds. */ stock Float:GetEntPropFloat(entity, PropType:type, const String:prop[]) @@ -623,3 +650,28 @@ stock SetEntPropVector(entity, PropType:type, const String:prop[], const Float:v return SetEntDataVector(entity, offs, vec, true); } + +/** + * Gets a network property as a string. + * + * @param entity Edict index. + * @param type Property type. + * @param prop Property to use. + * @param buffer Destination string buffer. + * @param maxlen Maximum length of output string buffer. + * @return Number of non-null bytes written. + * @error Invalid entity, offset out of reasonable bounds, or property is not a valid string. + */ +native GetEntPropString(entity, PropType:type, const String:prop[], String:buffer[], maxlen); + +/** + * Sets a network property as a string. + * + * @param entity Edict index. + * @param type Property type. + * @param prop Property to use. + * @param buffer String to set. + * @return Number of non-null bytes written. + * @error Invalid entity, offset out of reasonable bounds, or property is not a valid string. + */ +native SetEntPropString(entity, PropType:type, const String:prop[], const String:buffer[]);