Add support for nested datatables. (bug 5446, r=asherkin)
1.1 --- a/core/HalfLife2.cpp Mon Aug 12 00:45:29 2013 +0100
1.2 +++ b/core/HalfLife2.cpp Mon Aug 12 00:54:21 2013 +0100
1.3 @@ -115,7 +115,7 @@
1.4 {
1.5 if (h_iter->val.trie)
1.6 {
1.7 - sm_trie_destroy(h_iter->val.trie);
1.8 + delete h_iter->val.trie;
1.9 h_iter->val.trie = NULL;
1.10 }
1.11 }
1.12 @@ -343,16 +343,11 @@
1.13 return false;
1.14 }
1.15
1.16 -typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name, bool *isNested)
1.17 +bool UTIL_FindDataMapInfo(datamap_t *pMap, const char *name, sm_datatable_info_t *pDataTable)
1.18 {
1.19 - if (isNested)
1.20 - {
1.21 - *isNested = false;
1.22 - }
1.23 -
1.24 while (pMap)
1.25 {
1.26 - for (int i=0; i<pMap->dataNumFields; i++)
1.27 + for (int i = 0; i < pMap->dataNumFields; ++i)
1.28 {
1.29 if (pMap->dataDesc[i].fieldName == NULL)
1.30 {
1.31 @@ -360,32 +355,23 @@
1.32 }
1.33 if (strcmp(name, pMap->dataDesc[i].fieldName) == 0)
1.34 {
1.35 - return &(pMap->dataDesc[i]);
1.36 + pDataTable->prop = &(pMap->dataDesc[i]);
1.37 + pDataTable->actual_offset = GetTypeDescOffs(pDataTable->prop);
1.38 + return true;
1.39 }
1.40 - if (pMap->dataDesc[i].td)
1.41 + if (pMap->dataDesc[i].td == NULL || !UTIL_FindDataMapInfo(pMap->dataDesc[i].td, name, pDataTable))
1.42 {
1.43 - if (isNested)
1.44 - {
1.45 - *isNested = (UTIL_FindInDataMap(pMap->dataDesc[i].td, name, NULL) != NULL);
1.46 - if (*isNested)
1.47 - {
1.48 - return NULL;
1.49 - } else {
1.50 - continue;
1.51 - }
1.52 - } else { // Use the old behaviour, we dont want to spring this on extensions - even if they're doing bad things.
1.53 - typedescription_t *_td;
1.54 - if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name, NULL)) != NULL)
1.55 - {
1.56 - return _td;
1.57 - }
1.58 - }
1.59 + continue;
1.60 }
1.61 +
1.62 + pDataTable->actual_offset += GetTypeDescOffs(&(pMap->dataDesc[i]));
1.63 + return true;
1.64 }
1.65 +
1.66 pMap = pMap->baseMap;
1.67 }
1.68
1.69 - return NULL;
1.70 + return false;
1.71 }
1.72
1.73 ServerClass *CHalfLife2::FindServerClass(const char *classname)
1.74 @@ -472,27 +458,44 @@
1.75
1.76 typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
1.77 {
1.78 - return this->FindInDataMap(pMap, offset, NULL);
1.79 + sm_datatable_info_t dt_info;
1.80 +
1.81 + if (!(this->FindDataMapInfo(pMap, offset, &dt_info)))
1.82 + {
1.83 + return NULL;
1.84 + }
1.85 +
1.86 + return dt_info.prop;
1.87 }
1.88
1.89 -typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset, bool *isNested)
1.90 +bool CHalfLife2::FindDataMapInfo(datamap_t *pMap, const char *offset, sm_datatable_info_t *pDataTable)
1.91 {
1.92 - typedescription_t *td = NULL;
1.93 DataMapTrie &val = m_Maps[pMap];
1.94
1.95 if (!val.trie)
1.96 {
1.97 - val.trie = sm_trie_create();
1.98 + val.trie = new KTrie<sm_datatable_info_t>;
1.99 }
1.100 - if (!sm_trie_retrieve(val.trie, offset, (void **)&td))
1.101 +
1.102 + sm_datatable_info_t * pNewTable = val.trie->retrieve(offset);
1.103 +
1.104 + if (!pNewTable)
1.105 {
1.106 - if ((td = UTIL_FindInDataMap(pMap, offset, isNested)) != NULL)
1.107 + if (UTIL_FindDataMapInfo(pMap, offset, pDataTable))
1.108 {
1.109 - sm_trie_insert(val.trie, offset, td);
1.110 + val.trie->insert(offset, *pDataTable);
1.111 + }
1.112 + else
1.113 + {
1.114 + pDataTable->prop = NULL;
1.115 }
1.116 }
1.117 + else
1.118 + {
1.119 + *pDataTable = *pNewTable;
1.120 + }
1.121
1.122 - return td;
1.123 + return (pDataTable->prop != NULL);
1.124 }
1.125
1.126 void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
1.127 @@ -1221,8 +1224,14 @@
1.128 {
1.129 CBaseEntity *pGetterEnt = ReferenceToEntity(0);
1.130 datamap_t *pMap = GetDataMap(pGetterEnt);
1.131 - typedescription_t *pDesc = FindInDataMap(pMap, "m_iClassname");
1.132 - offset = GetTypeDescOffs(pDesc);
1.133 +
1.134 + sm_datatable_info_t info;
1.135 + if (!FindDataMapInfo(pMap, "m_iClassname", &info))
1.136 + {
1.137 + return NULL;
1.138 + }
1.139 +
1.140 + offset = info.actual_offset;
1.141 }
1.142
1.143 return *(const char **)(((unsigned char *)pEntity) + offset);
2.1 --- a/core/HalfLife2.h Mon Aug 12 00:45:29 2013 +0100
2.2 +++ b/core/HalfLife2.h Mon Aug 12 00:54:21 2013 +0100
2.3 @@ -66,7 +66,7 @@
2.4 struct DataMapTrie
2.5 {
2.6 DataMapTrie() : trie(NULL) {}
2.7 - Trie *trie;
2.8 + KTrie<sm_datatable_info_t> *trie;
2.9 };
2.10
2.11 struct DelayedFakeCliCmd
2.12 @@ -123,7 +123,7 @@
2.13 datamap_t *GetDataMap(CBaseEntity *pEntity);
2.14 ServerClass *FindServerClass(const char *classname);
2.15 typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset);
2.16 - typedescription_t *FindInDataMap(datamap_t *pMap, const char *offset, bool *isNested);
2.17 + bool FindDataMapInfo(datamap_t *pMap, const char *offset, sm_datatable_info_t *pDataTable);
2.18 void SetEdictStateChanged(edict_t *pEdict, unsigned short offset);
2.19 bool TextMsg(int client, int dest, const char *msg);
2.20 bool HintTextMsg(int client, const char *msg);
3.1 --- a/core/smn_entities.cpp Mon Aug 12 00:45:29 2013 +0100
3.2 +++ b/core/smn_entities.cpp Mon Aug 12 00:54:21 2013 +0100
3.3 @@ -796,6 +796,82 @@
3.4 return info.actual_offset;
3.5 }
3.6
3.7 +static void GuessDataPropTypes(typedescription_t *td, cell_t * pSize, cell_t * pType)
3.8 +{
3.9 + switch (td->fieldType)
3.10 + {
3.11 + case FIELD_TICK:
3.12 + case FIELD_MODELINDEX:
3.13 + case FIELD_MATERIALINDEX:
3.14 + case FIELD_INTEGER:
3.15 + case FIELD_COLOR32:
3.16 + {
3.17 + *pType = PropField_Integer;
3.18 + *pSize = 32;
3.19 + break;
3.20 + }
3.21 + case FIELD_VECTOR:
3.22 + case FIELD_POSITION_VECTOR:
3.23 + {
3.24 + *pType = PropField_Vector;
3.25 + *pSize = 12;
3.26 + break;
3.27 + }
3.28 + case FIELD_SHORT:
3.29 + {
3.30 + *pType = PropField_Integer;
3.31 + *pSize = 16;
3.32 + break;
3.33 + }
3.34 + case FIELD_BOOLEAN:
3.35 + {
3.36 + *pType = PropField_Integer;
3.37 + *pSize = 1;
3.38 + break;
3.39 + }
3.40 + case FIELD_CHARACTER:
3.41 + {
3.42 + if (td->fieldSize == 1)
3.43 + {
3.44 + *pType = PropField_Integer;
3.45 + *pSize = 8;
3.46 + }
3.47 + else
3.48 + {
3.49 + *pType = PropField_String;
3.50 + *pSize = 8 * td->fieldSize;
3.51 + }
3.52 + break;
3.53 + }
3.54 + case FIELD_MODELNAME:
3.55 + case FIELD_SOUNDNAME:
3.56 + case FIELD_STRING:
3.57 + {
3.58 + *pSize = sizeof(string_t);
3.59 + *pType = PropField_String_T;
3.60 + break;
3.61 + }
3.62 + case FIELD_FLOAT:
3.63 + case FIELD_TIME:
3.64 + {
3.65 + *pType = PropField_Float;
3.66 + *pSize = 32;
3.67 + break;
3.68 + }
3.69 + case FIELD_EHANDLE:
3.70 + {
3.71 + *pType = PropField_Entity;
3.72 + *pSize = 32;
3.73 + break;
3.74 + }
3.75 + default:
3.76 + {
3.77 + *pType = PropField_Unsupported;
3.78 + *pSize = 0;
3.79 + }
3.80 + }
3.81 +}
3.82 +
3.83 static cell_t FindDataMapOffs(IPluginContext *pContext, const cell_t *params)
3.84 {
3.85 CBaseEntity *pEntity;
3.86 @@ -815,14 +891,13 @@
3.87 }
3.88
3.89 pContext->LocalToString(params[2], &offset);
3.90 - bool isNested = false;
3.91 - if ((td=g_HL2.FindInDataMap(pMap, offset, &isNested)) == NULL)
3.92 + sm_datatable_info_t info;
3.93 + if (!g_HL2.FindDataMapInfo(pMap, offset, &info))
3.94 {
3.95 - if (isNested)
3.96 - return pContext->ThrowNativeError("Property \"%s\" is not safe to access for entity %d", offset, params[1]);
3.97 - else
3.98 - return -1;
3.99 + return -1;
3.100 }
3.101 +
3.102 + td = info.prop;
3.103
3.104 if (params[0] == 4)
3.105 {
3.106 @@ -830,82 +905,60 @@
3.107
3.108 pContext->LocalToPhysAddr(params[3], &pType);
3.109 pContext->LocalToPhysAddr(params[4], &pSize);
3.110 +
3.111 + GuessDataPropTypes(td, pSize, pType);
3.112 + }
3.113
3.114 - switch (td->fieldType)
3.115 + return GetTypeDescOffs(td);
3.116 +}
3.117 +
3.118 +static cell_t FindDataMapInfo(IPluginContext *pContext, const cell_t *params)
3.119 +{
3.120 + CBaseEntity *pEntity;
3.121 + datamap_t *pMap;
3.122 + typedescription_t *td;
3.123 + char *offset;
3.124 + pEntity = GetEntity(params[1]);
3.125 +
3.126 + if (!pEntity)
3.127 + {
3.128 + return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
3.129 + }
3.130 +
3.131 + if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
3.132 + {
3.133 + return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
3.134 + }
3.135 +
3.136 + pContext->LocalToString(params[2], &offset);
3.137 + sm_datatable_info_t info;
3.138 + if (!g_HL2.FindDataMapInfo(pMap, offset, &info))
3.139 + {
3.140 + return -1;
3.141 + }
3.142 +
3.143 + td = info.prop;
3.144 +
3.145 + if (params[0] >= 4)
3.146 + {
3.147 + cell_t *pType, *pSize;
3.148 +
3.149 + pContext->LocalToPhysAddr(params[3], &pType);
3.150 + pContext->LocalToPhysAddr(params[4], &pSize);
3.151 +
3.152 + GuessDataPropTypes(td, pSize, pType);
3.153 +
3.154 + if (params[0] == 5)
3.155 {
3.156 - case FIELD_TICK:
3.157 - case FIELD_MODELINDEX:
3.158 - case FIELD_MATERIALINDEX:
3.159 - case FIELD_INTEGER:
3.160 - case FIELD_COLOR32:
3.161 - {
3.162 - *pType = PropField_Integer;
3.163 - *pSize = 32;
3.164 - break;
3.165 - }
3.166 - case FIELD_VECTOR:
3.167 - case FIELD_POSITION_VECTOR:
3.168 - {
3.169 - *pType = PropField_Vector;
3.170 - *pSize = 12;
3.171 - break;
3.172 - }
3.173 - case FIELD_SHORT:
3.174 - {
3.175 - *pType = PropField_Integer;
3.176 - *pSize = 16;
3.177 - break;
3.178 - }
3.179 - case FIELD_BOOLEAN:
3.180 - {
3.181 - *pType = PropField_Integer;
3.182 - *pSize = 1;
3.183 - break;
3.184 - }
3.185 - case FIELD_CHARACTER:
3.186 - {
3.187 - if (td->fieldSize == 1)
3.188 - {
3.189 - *pType = PropField_Integer;
3.190 - *pSize = 8;
3.191 - }
3.192 - else
3.193 - {
3.194 - *pType = PropField_String;
3.195 - *pSize = 8 * td->fieldSize;
3.196 - }
3.197 - break;
3.198 - }
3.199 - case FIELD_MODELNAME:
3.200 - case FIELD_SOUNDNAME:
3.201 - case FIELD_STRING:
3.202 - {
3.203 - *pSize = sizeof(string_t);
3.204 - *pType = PropField_String_T;
3.205 - break;
3.206 - }
3.207 - case FIELD_FLOAT:
3.208 - case FIELD_TIME:
3.209 - {
3.210 - *pType = PropField_Float;
3.211 - *pSize = 32;
3.212 - break;
3.213 - }
3.214 - case FIELD_EHANDLE:
3.215 - {
3.216 - *pType = PropField_Entity;
3.217 - *pSize = 32;
3.218 - break;
3.219 - }
3.220 - default:
3.221 - {
3.222 - *pType = PropField_Unsupported;
3.223 - *pSize = 0;
3.224 - }
3.225 + cell_t *pLocalOffs;
3.226 +
3.227 + pContext->LocalToPhysAddr(params[5], &pLocalOffs);
3.228 +
3.229 + *pLocalOffs = GetTypeDescOffs(info.prop);
3.230 }
3.231 }
3.232
3.233 - return GetTypeDescOffs(td);
3.234 + return info.actual_offset;
3.235 }
3.236
3.237 static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params)
3.238 @@ -966,23 +1019,16 @@
3.239 { \
3.240 return pContext->ThrowNativeError("Could not retrieve datamap"); \
3.241 } \
3.242 - bool isNested = false; \
3.243 - if ((td = g_HL2.FindInDataMap(pMap, prop, &isNested)) == NULL) \
3.244 + sm_datatable_info_t info; \
3.245 + if (!g_HL2.FindDataMapInfo(pMap, prop, &info)) \
3.246 { \
3.247 const char *class_name = g_HL2.GetEntityClassname(pEntity); \
3.248 - if (isNested) \
3.249 - { \
3.250 - return pContext->ThrowNativeError("Property \"%s\" not safe to access (entity %d/%s)", \
3.251 - prop, \
3.252 - params[1], \
3.253 - ((class_name) ? class_name : "")); \
3.254 - } else { \
3.255 - return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
3.256 - prop, \
3.257 - params[1], \
3.258 - ((class_name) ? class_name : "")); \
3.259 - } \
3.260 - }
3.261 + return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
3.262 + prop, \
3.263 + params[1], \
3.264 + ((class_name) ? class_name : "")); \
3.265 + } \
3.266 + td = info.prop;
3.267
3.268 #define CHECK_SET_PROP_DATA_OFFSET() \
3.269 if (element < 0 || element >= td->fieldSize) \
3.270 @@ -993,7 +1039,7 @@
3.271 td->fieldSize); \
3.272 } \
3.273 \
3.274 - offset = GetTypeDescOffs(td) + (element * (td->fieldSizeInBytes / td->fieldSize));
3.275 + offset = info.actual_offset + (element * (td->fieldSizeInBytes / td->fieldSize));
3.276
3.277 #define FIND_PROP_SEND(type, type_name) \
3.278 sm_sendprop_info_t info;\
3.279 @@ -1808,7 +1854,7 @@
3.280 element);
3.281 }
3.282
3.283 - offset = GetTypeDescOffs(td);
3.284 + offset = info.actual_offset;
3.285 if (bIsStringIndex)
3.286 {
3.287 offset += (element * (td->fieldSizeInBytes / td->fieldSize));
3.288 @@ -1896,25 +1942,23 @@
3.289 case Prop_Data:
3.290 {
3.291 datamap_t *pMap;
3.292 - typedescription_t *td;
3.293 if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
3.294 {
3.295 return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
3.296 }
3.297 pContext->LocalToString(params[3], &prop);
3.298 - bool isNested = false;
3.299 - if ((td=g_HL2.FindInDataMap(pMap, prop, &isNested)) == NULL)
3.300 + sm_datatable_info_t info;
3.301 + if (!g_HL2.FindDataMapInfo(pMap, prop, &info))
3.302 {
3.303 - if (isNested)
3.304 - return pContext->ThrowNativeError("Property \"%s\" is not safe to access for entity %d", prop, params[1]);
3.305 - else
3.306 - return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
3.307 + return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
3.308 }
3.309 +
3.310 + typedescription_t *td = info.prop;
3.311 if (td->fieldType != FIELD_CHARACTER)
3.312 {
3.313 return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
3.314 }
3.315 - offset = GetTypeDescOffs(td);
3.316 + offset = info.actual_offset;
3.317 maxlen = td->fieldSize;
3.318 break;
3.319 }
3.320 @@ -2138,14 +2182,16 @@
3.321 {
3.322 return pContext->ThrowNativeError("Could not retrieve datamap");
3.323 }
3.324 - if ((td = g_HL2.FindInDataMap(pMap, prop)) == NULL)
3.325 +
3.326 + sm_datatable_info_t info;
3.327 + if (!g_HL2.FindDataMapInfo(pMap, prop, &info))
3.328 {
3.329 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d)",
3.330 prop,
3.331 params[1]);
3.332 }
3.333
3.334 - int offset = GetTypeDescOffs(td);
3.335 + int offset = info.actual_offset;
3.336
3.337 int32_t actual_flags = *(int32_t *)((uint8_t *)pEntity + offset);
3.338 int32_t sm_flags = 0;
3.339 @@ -2176,21 +2222,22 @@
3.340 return pContext->ThrowNativeError("Could not find m_fFlags prop in gamedata");
3.341 }
3.342
3.343 - typedescription_t *td;
3.344 datamap_t *pMap;
3.345
3.346 if ((pMap = CBaseEntity_GetDataDescMap(pEntity)) == NULL)
3.347 {
3.348 return pContext->ThrowNativeError("Could not retrieve datamap");
3.349 }
3.350 - if ((td = g_HL2.FindInDataMap(pMap, prop)) == NULL)
3.351 +
3.352 + sm_datatable_info_t info;
3.353 + if (!g_HL2.FindDataMapInfo(pMap, prop, &info))
3.354 {
3.355 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d)",
3.356 prop,
3.357 params[1]);
3.358 }
3.359
3.360 - int offset = GetTypeDescOffs(td);
3.361 + int offset = info.actual_offset;
3.362
3.363 int32_t sm_flags = params[2];
3.364 int32_t actual_flags = 0;
3.365 @@ -2262,5 +2309,6 @@
3.366 {"SetEntPropString", SetEntPropString},
3.367 {"SetEntPropVector", SetEntPropVector},
3.368 {"GetEntityAddress", GetEntityAddress},
3.369 + {"FindDataMapInfo", FindDataMapInfo},
3.370 {NULL, NULL}
3.371 };
4.1 --- a/extensions/sdktools/output.cpp Mon Aug 12 00:45:29 2013 +0100
4.2 +++ b/extensions/sdktools/output.cpp Mon Aug 12 00:54:21 2013 +0100
4.3 @@ -356,8 +356,13 @@
4.4 if (offset == -1)
4.5 {
4.6 datamap_t *pMap = gamehelpers->GetDataMap(pEntity);
4.7 - typedescription_t *pDesc = gamehelpers->FindInDataMap(pMap, "m_iClassname");
4.8 - offset = GetTypeDescOffs(pDesc);
4.9 + sm_datatable_info_t info;
4.10 + if (!gamehelpers->FindDataMapInfo(pMap, "m_iClassname", &info))
4.11 + {
4.12 + return NULL;
4.13 + }
4.14 +
4.15 + offset = info.actual_offset;
4.16 }
4.17
4.18 return *(const char **)(((unsigned char *)pEntity) + offset);
5.1 --- a/extensions/sdktools/vhelpers.cpp Mon Aug 12 00:45:29 2013 +0100
5.2 +++ b/extensions/sdktools/vhelpers.cpp Mon Aug 12 00:54:21 2013 +0100
5.3 @@ -585,14 +585,17 @@
5.4
5.5 fprintf(fp, "// Dump of all classes for \"%s\" as at %s\n//\n\n", g_pSM->GetGameFolderName(), buffer);
5.6
5.7 + sm_datatable_info_t info;
5.8 for ( int i = dict->m_Factories.First(); i != dict->m_Factories.InvalidIndex(); i = dict->m_Factories.Next( i ) )
5.9 {
5.10 IServerNetworkable *entity = dict->Create(dict->m_Factories.GetElementName(i));
5.11 ServerClass *sclass = entity->GetServerClass();
5.12 fprintf(fp,"%s - %s\n",sclass->GetName(), dict->m_Factories.GetElementName(i));
5.13 -
5.14 - typedescription_t *datamap = gamehelpers->FindInDataMap(gamehelpers->GetDataMap(entity->GetBaseEntity()), "m_iEFlags");
5.15 - int *eflags = (int *)((char *)entity->GetBaseEntity() + GetTypeDescOffs(datamap));
5.16 +
5.17 + if (!gamehelpers->FindDataMapInfo(gamehelpers->GetDataMap(entity->GetBaseEntity()), "m_iEFlags", &info))
5.18 + continue;
5.19 +
5.20 + int *eflags = (int *)((char *)entity->GetBaseEntity() + info.actual_offset);
5.21 *eflags |= (1<<0); // EFL_KILLME
5.22 }
5.23
5.24 @@ -819,14 +822,13 @@
5.25
5.26 if (offsEFlags == -1)
5.27 {
5.28 - typedescription_t *datamap = gamehelpers->FindInDataMap(pMap, "m_iEFlags");
5.29 -
5.30 - if (!datamap)
5.31 + sm_datatable_info_t info;
5.32 + if (!gamehelpers->FindDataMapInfo(pMap, "m_iEFlags", &info))
5.33 {
5.34 continue;
5.35 }
5.36
5.37 - offsEFlags = GetTypeDescOffs(datamap);
5.38 + offsEFlags = info.actual_offset;
5.39 }
5.40
5.41 int *eflags = (int *)((char *)entity->GetBaseEntity() + offsEFlags);
6.1 --- a/extensions/sdktools/vnatives.cpp Mon Aug 12 00:45:29 2013 +0100
6.2 +++ b/extensions/sdktools/vnatives.cpp Mon Aug 12 00:54:21 2013 +0100
6.3 @@ -548,10 +548,10 @@
6.4 if (frag_prop)
6.5 {
6.6 datamap_t *pMap = gamehelpers->GetDataMap(pEntity);
6.7 - typedescription_t *pType = gamehelpers->FindInDataMap(pMap, frag_prop);
6.8 - if (pType != NULL)
6.9 + sm_datatable_info_t info;
6.10 + if (gamehelpers->FindDataMapInfo(pMap, frag_prop, &info))
6.11 {
6.12 - s_frag_offs = GetTypeDescOffs(pType);
6.13 + s_frag_offs = info.actual_offset;
6.14 }
6.15 }
6.16 if (!s_frag_offs)
6.17 @@ -684,10 +684,13 @@
6.18 static int offset = -1;
6.19 if (offset == -1)
6.20 {
6.21 - offset = GetTypeDescOffs(
6.22 - gamehelpers->FindInDataMap(gamehelpers->GetDataMap(pEntity),
6.23 - "m_iClassname")
6.24 - );
6.25 + sm_datatable_info_t info;
6.26 + if (!gamehelpers->FindDataMapInfo(gamehelpers->GetDataMap(pEntity), "m_iClassname", &info))
6.27 + {
6.28 + return -1;
6.29 + }
6.30 +
6.31 + offset = info.actual_offset;
6.32 }
6.33
6.34 string_t s;
7.1 --- a/plugins/include/entity.inc Mon Aug 12 00:45:29 2013 +0100
7.2 +++ b/plugins/include/entity.inc Mon Aug 12 00:54:21 2013 +0100
7.3 @@ -449,6 +449,26 @@
7.4 const String:prop[],
7.5 &PropFieldType:type=PropFieldType:0,
7.6 &num_bits=0);
7.7 +
7.8 +/**
7.9 + * Given an entity, finds a nested datamap property offset.
7.10 + * This information is cached for future calls.
7.11 + *
7.12 + * @param entity Entity index.
7.13 + * @param prop Property name.
7.14 + * @param type Optional parameter to store the type.
7.15 + * @param num_bits Optional parameter to store the number of bits the field
7.16 + * uses. The bit count will either be 1 (for boolean) or
7.17 + * divisible by 8 (including 0 if unknown).
7.18 + * @param local_offset Optional parameter to store the local offset, as
7.19 + * FindDataMapOffs() would return.
7.20 + * @return An offset, or -1 on failure.
7.21 + */
7.22 +native FindDataMapInfo(entity,
7.23 + const String:prop[],
7.24 + &PropFieldType:type=PropFieldType:0,
7.25 + &num_bits=0,
7.26 + &local_offset=0);
7.27
7.28 /**
7.29 * Wrapper function for finding a send property for a particular entity.
8.1 --- a/public/IGameHelpers.h Mon Aug 12 00:45:29 2013 +0100
8.2 +++ b/public/IGameHelpers.h Mon Aug 12 00:54:21 2013 +0100
8.3 @@ -40,7 +40,7 @@
8.4 */
8.5
8.6 #define SMINTERFACE_GAMEHELPERS_NAME "IGameHelpers"
8.7 -#define SMINTERFACE_GAMEHELPERS_VERSION 9
8.8 +#define SMINTERFACE_GAMEHELPERS_VERSION 10
8.9
8.10 class CBaseEntity;
8.11 class CBaseHandle;
8.12 @@ -66,6 +66,12 @@
8.13 SendProp *prop; /**< Property instance. */
8.14 unsigned int actual_offset; /**< Actual computed offset. */
8.15 };
8.16 +
8.17 + struct sm_datatable_info_t
8.18 + {
8.19 + typedescription_t *prop; /**< Property instance. */
8.20 + unsigned int actual_offset; /**< Actual computed offset. */
8.21 + };
8.22
8.23 class IGameHelpers : public SMInterface
8.24 {
8.25 @@ -318,6 +324,17 @@
8.26 * @return True if valid, otherwise false.
8.27 */
8.28 virtual bool IsMapValid(const char *map) =0;
8.29 +
8.30 + /**
8.31 + * @brief Finds a datamap_t definition.
8.32 + *
8.33 + * @param pMap datamap_t pointer.
8.34 + * @param offset Property name.
8.35 + * @param pDataTable Buffer to store sm_datatable_info_t data.
8.36 + * @return typedescription_t pointer on success, NULL
8.37 + * on failure.
8.38 + */
8.39 + virtual bool FindDataMapInfo(datamap_t *pMap, const char *offset, sm_datatable_info_t *pDataTable) =0;
8.40 };
8.41 }
8.42