1.1 --- a/core/smn_entities.cpp Wed Jun 01 20:36:16 2011 -0400
1.2 +++ b/core/smn_entities.cpp Sun Jun 05 21:52:36 2011 -0400
1.3 @@ -967,21 +967,94 @@
1.4 class_name); \
1.5 }
1.6
1.7 -#define FIND_PROP_SEND(pProp) \
1.8 +#define CHECK_SET_PROP_DATA_OFFSET() \
1.9 + if (element >= td->fieldSize) \
1.10 + { \
1.11 + return pContext->ThrowNativeError("Element %d is out of bounds (Prop %s has %d elements).", \
1.12 + element, \
1.13 + prop, \
1.14 + td->fieldSize); \
1.15 + } \
1.16 + \
1.17 + offset = GetTypeDescOffs(td) + (element * (td->fieldSizeInBytes / td->fieldSize));
1.18 +
1.19 +#define FIND_PROP_SEND(type, type_name) \
1.20 + sm_sendprop_info_t info;\
1.21 IServerUnknown *pUnk = (IServerUnknown *)pEntity; \
1.22 IServerNetworkable *pNet = pUnk->GetNetworkable(); \
1.23 if (!pNet) \
1.24 { \
1.25 return pContext->ThrowNativeError("Edict %d (%d) is not networkable", g_HL2.ReferenceToIndex(params[1]), params[1]); \
1.26 } \
1.27 - if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, pProp)) \
1.28 + if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info)) \
1.29 { \
1.30 return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)", \
1.31 prop, \
1.32 params[1], \
1.33 class_name); \
1.34 + } \
1.35 + \
1.36 + offset = info.actual_offset; \
1.37 + bit_count = info.prop->m_nBits; \
1.38 + \
1.39 + switch (info.prop->GetType()) \
1.40 + { \
1.41 + case type: \
1.42 + { \
1.43 + if (element > 0) \
1.44 + { \
1.45 + return pContext->ThrowNativeError("SendProp %s is not an array. Element %d is invalid.", \
1.46 + prop, \
1.47 + element); \
1.48 + } \
1.49 + break; \
1.50 + } \
1.51 + case DPT_DataTable: \
1.52 + { \
1.53 + SendProp *pProp; \
1.54 + FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name); \
1.55 + \
1.56 + offset += pProp->GetOffset(); \
1.57 + bit_count = pProp->m_nBits; \
1.58 + break; \
1.59 + } \
1.60 + default: \
1.61 + { \
1.62 + return pContext->ThrowNativeError("SendProp %s type is not " type_name " (%d != %d)", \
1.63 + prop, \
1.64 + info.prop->GetType(), \
1.65 + type); \
1.66 + } \
1.67 + } \
1.68 +
1.69 +#define FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name) \
1.70 + SendTable *pTable = info.prop->GetDataTable(); \
1.71 + if (!pTable) \
1.72 + { \
1.73 + return pContext->ThrowNativeError("Error looking up DataTable for prop %s", \
1.74 + prop); \
1.75 + } \
1.76 + \
1.77 + int elementCount = pTable->GetNumProps(); \
1.78 + if (element >= elementCount) \
1.79 + { \
1.80 + return pContext->ThrowNativeError("Element %d is out of bounds (Prop %s has %d elements).", \
1.81 + element, \
1.82 + prop, \
1.83 + elementCount); \
1.84 + } \
1.85 + \
1.86 + pProp = pTable->GetProp(element); \
1.87 + if (pProp->GetType() != type) \
1.88 + { \
1.89 + return pContext->ThrowNativeError("SendProp %s type is not " type_name " ([%d,%d] != %d)", \
1.90 + prop, \
1.91 + info.prop->GetType(), \
1.92 + info.prop->m_nBits, \
1.93 + type); \
1.94 }
1.95
1.96 +
1.97 inline int MatchFieldAsInteger(int field_type)
1.98 {
1.99 switch (field_type)
1.100 @@ -1005,6 +1078,75 @@
1.101 return 0;
1.102 }
1.103
1.104 +static cell_t GetEntPropArraySize(IPluginContext *pContext, const cell_t *params)
1.105 +{
1.106 + CBaseEntity *pEntity;
1.107 + char *prop;
1.108 + const char *class_name;
1.109 + edict_t *pEdict;
1.110 +
1.111 + if (!IndexToAThings(params[1], &pEntity, &pEdict))
1.112 + {
1.113 + return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1.114 + }
1.115 +
1.116 + if (!pEdict || (class_name = pEdict->GetClassName()) == NULL)
1.117 + {
1.118 + class_name = "";
1.119 + }
1.120 +
1.121 + pContext->LocalToString(params[3], &prop);
1.122 +
1.123 + switch (params[2])
1.124 + {
1.125 + case Prop_Data:
1.126 + {
1.127 + typedescription_t *td;
1.128 +
1.129 + FIND_PROP_DATA(td);
1.130 +
1.131 + return td->fieldSize;
1.132 + }
1.133 + case Prop_Send:
1.134 + {
1.135 + sm_sendprop_info_t info;
1.136 +
1.137 + IServerUnknown *pUnk = (IServerUnknown *)pEntity;
1.138 + IServerNetworkable *pNet = pUnk->GetNetworkable();
1.139 + if (!pNet)
1.140 + {
1.141 + return pContext->ThrowNativeError("Edict %d (%d) is not networkable", g_HL2.ReferenceToIndex(params[1]), params[1]);
1.142 + }
1.143 + if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info))
1.144 + {
1.145 + return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)",
1.146 + prop,
1.147 + params[1],
1.148 + class_name);
1.149 + }
1.150 +
1.151 + if (info.prop->GetType() != DPT_DataTable)
1.152 + {
1.153 + return 0;
1.154 + }
1.155 +
1.156 + SendTable *pTable = info.prop->GetDataTable();
1.157 + if (!pTable)
1.158 + {
1.159 + return pContext->ThrowNativeError("Error looking up DataTable for prop %s", prop);
1.160 + }
1.161 +
1.162 + return pTable->GetNumProps();
1.163 + }
1.164 + default:
1.165 + {
1.166 + return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
1.167 + }
1.168 + }
1.169 +
1.170 + return 1;
1.171 +}
1.172 +
1.173 static cell_t GetEntProp(IPluginContext *pContext, const cell_t *params)
1.174 {
1.175 CBaseEntity *pEntity;
1.176 @@ -1014,6 +1156,12 @@
1.177 edict_t *pEdict;
1.178 int bit_count;
1.179
1.180 + int element = 0;
1.181 + if (params[0] >= 5)
1.182 + {
1.183 + element = params[5];
1.184 + }
1.185 +
1.186 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1.187 {
1.188 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1.189 @@ -1042,26 +1190,13 @@
1.190 td->fieldType);
1.191 }
1.192
1.193 - offset = GetTypeDescOffs(td);
1.194 + CHECK_SET_PROP_DATA_OFFSET();
1.195 +
1.196 break;
1.197 }
1.198 case Prop_Send:
1.199 {
1.200 - sm_sendprop_info_t info;
1.201 -
1.202 - FIND_PROP_SEND(&info);
1.203 -
1.204 - if (info.prop->GetType() != DPT_Int)
1.205 - {
1.206 - return pContext->ThrowNativeError("SendProp %s is not an integer ([%d,%d] != %d)",
1.207 - prop,
1.208 - info.prop->GetType(),
1.209 - info.prop->m_nBits,
1.210 - DPT_Int);
1.211 - }
1.212 -
1.213 - bit_count = info.prop->m_nBits;
1.214 - offset = info.actual_offset;
1.215 + FIND_PROP_SEND(DPT_Int, "integer");
1.216 break;
1.217 }
1.218 default:
1.219 @@ -1104,6 +1239,12 @@
1.220 edict_t *pEdict;
1.221 int bit_count;
1.222
1.223 + int element = 0;
1.224 + if (params[0] >= 6)
1.225 + {
1.226 + element = params[6];
1.227 + }
1.228 +
1.229 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1.230 {
1.231 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1.232 @@ -1131,26 +1272,13 @@
1.233 td->fieldType);
1.234 }
1.235
1.236 - offset = GetTypeDescOffs(td);
1.237 + CHECK_SET_PROP_DATA_OFFSET();
1.238 +
1.239 break;
1.240 }
1.241 case Prop_Send:
1.242 {
1.243 - sm_sendprop_info_t info;
1.244 -
1.245 - FIND_PROP_SEND(&info);
1.246 -
1.247 - if (info.prop->GetType() != DPT_Int)
1.248 - {
1.249 - return pContext->ThrowNativeError("SendProp %s is not an integer ([%d,%d] != %d)",
1.250 - prop,
1.251 - info.prop->GetType(),
1.252 - info.prop->m_nBits,
1.253 - DPT_Int);
1.254 - }
1.255 -
1.256 - bit_count = info.prop->m_nBits;
1.257 - offset = info.actual_offset;
1.258 + FIND_PROP_SEND(DPT_Int, "integer");
1.259 break;
1.260 }
1.261 default:
1.262 @@ -1194,9 +1322,16 @@
1.263 CBaseEntity *pEntity;
1.264 char *prop;
1.265 int offset;
1.266 + int bit_count;
1.267 const char *class_name;
1.268 edict_t *pEdict;
1.269
1.270 + int element = 0;
1.271 + if (params[0] >= 4)
1.272 + {
1.273 + element = params[4];
1.274 + }
1.275 +
1.276 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1.277 {
1.278 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1.279 @@ -1227,24 +1362,13 @@
1.280 FIELD_TIME);
1.281 }
1.282
1.283 - offset = GetTypeDescOffs(td);
1.284 + CHECK_SET_PROP_DATA_OFFSET();
1.285 +
1.286 break;
1.287 }
1.288 case Prop_Send:
1.289 {
1.290 - sm_sendprop_info_t info;
1.291 -
1.292 - FIND_PROP_SEND(&info);
1.293 -
1.294 - if (info.prop->GetType() != DPT_Float)
1.295 - {
1.296 - return pContext->ThrowNativeError("SendProp %s is not a float (%d != %d)",
1.297 - prop,
1.298 - info.prop->GetType(),
1.299 - DPT_Float);
1.300 - }
1.301 -
1.302 - offset = info.actual_offset;
1.303 + FIND_PROP_SEND(DPT_Float, "float");
1.304 break;
1.305 }
1.306 default:
1.307 @@ -1263,9 +1387,16 @@
1.308 CBaseEntity *pEntity;
1.309 char *prop;
1.310 int offset;
1.311 + int bit_count;
1.312 const char *class_name;
1.313 edict_t *pEdict;
1.314
1.315 + int element = 0;
1.316 + if (params[0] >= 5)
1.317 + {
1.318 + element = params[5];
1.319 + }
1.320 +
1.321 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1.322 {
1.323 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1.324 @@ -1296,24 +1427,13 @@
1.325 FIELD_TIME);
1.326 }
1.327
1.328 - offset = GetTypeDescOffs(td);
1.329 + CHECK_SET_PROP_DATA_OFFSET();
1.330 +
1.331 break;
1.332 }
1.333 case Prop_Send:
1.334 {
1.335 - sm_sendprop_info_t info;
1.336 -
1.337 - FIND_PROP_SEND(&info);
1.338 -
1.339 - if (info.prop->GetType() != DPT_Float)
1.340 - {
1.341 - return pContext->ThrowNativeError("SendProp %s is not a float (%d != %d)",
1.342 - prop,
1.343 - info.prop->GetType(),
1.344 - DPT_Float);
1.345 - }
1.346 -
1.347 - offset = info.actual_offset;
1.348 + FIND_PROP_SEND(DPT_Float, "float");
1.349 break;
1.350 }
1.351 default:
1.352 @@ -1337,9 +1457,16 @@
1.353 CBaseEntity *pEntity;
1.354 char *prop;
1.355 int offset;
1.356 + int bit_count;
1.357 const char *class_name;
1.358 edict_t *pEdict;
1.359
1.360 + int element = 0;
1.361 + if (params[0] >= 4)
1.362 + {
1.363 + element = params[4];
1.364 + }
1.365 +
1.366 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1.367 {
1.368 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1.369 @@ -1368,24 +1495,13 @@
1.370 FIELD_EHANDLE);
1.371 }
1.372
1.373 - offset = GetTypeDescOffs(td);
1.374 + CHECK_SET_PROP_DATA_OFFSET();
1.375 +
1.376 break;
1.377 }
1.378 case Prop_Send:
1.379 {
1.380 - sm_sendprop_info_t info;
1.381 -
1.382 - FIND_PROP_SEND(&info);
1.383 -
1.384 - if (info.prop->GetType() != DPT_Int)
1.385 - {
1.386 - return pContext->ThrowNativeError("SendProp %s is not an integer (%d != %d)",
1.387 - prop,
1.388 - info.prop->GetType(),
1.389 - DPT_Int);
1.390 - }
1.391 -
1.392 - offset = info.actual_offset;
1.393 + FIND_PROP_SEND(DPT_Int, "integer");
1.394 break;
1.395 }
1.396 default:
1.397 @@ -1405,9 +1521,16 @@
1.398 CBaseEntity *pEntity;
1.399 char *prop;
1.400 int offset;
1.401 + int bit_count;
1.402 const char *class_name;
1.403 edict_t *pEdict;
1.404
1.405 + int element = 0;
1.406 + if (params[0] >= 5)
1.407 + {
1.408 + element = params[5];
1.409 + }
1.410 +
1.411 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1.412 {
1.413 return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[1]), params[1]);
1.414 @@ -1436,24 +1559,13 @@
1.415 FIELD_EHANDLE);
1.416 }
1.417
1.418 - offset = GetTypeDescOffs(td);
1.419 + CHECK_SET_PROP_DATA_OFFSET();
1.420 +
1.421 break;
1.422 }
1.423 case Prop_Send:
1.424 {
1.425 - sm_sendprop_info_t info;
1.426 -
1.427 - FIND_PROP_SEND(&info);
1.428 -
1.429 - if (info.prop->GetType() != DPT_Int)
1.430 - {
1.431 - return pContext->ThrowNativeError("SendProp %s is not an integer (%d != %d)",
1.432 - prop,
1.433 - info.prop->GetType(),
1.434 - DPT_Int);
1.435 - }
1.436 -
1.437 - offset = info.actual_offset;
1.438 + FIND_PROP_SEND(DPT_Int, "integer");
1.439 break;
1.440 }
1.441 default:
1.442 @@ -1494,8 +1606,15 @@
1.443 CBaseEntity *pEntity;
1.444 char *prop;
1.445 int offset;
1.446 + int bit_count;
1.447 const char *class_name;
1.448 edict_t *pEdict;
1.449 +
1.450 + int element = 0;
1.451 + if (params[0] >= 5)
1.452 + {
1.453 + element = params[5];
1.454 + }
1.455
1.456 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1.457 {
1.458 @@ -1527,24 +1646,13 @@
1.459 FIELD_POSITION_VECTOR);
1.460 }
1.461
1.462 - offset = GetTypeDescOffs(td);
1.463 + CHECK_SET_PROP_DATA_OFFSET();
1.464 +
1.465 break;
1.466 }
1.467 case Prop_Send:
1.468 {
1.469 - sm_sendprop_info_t info;
1.470 -
1.471 - FIND_PROP_SEND(&info);
1.472 -
1.473 - if (info.prop->GetType() != DPT_Vector)
1.474 - {
1.475 - return pContext->ThrowNativeError("SendProp %s is not a vector (%d != %d)",
1.476 - prop,
1.477 - info.prop->GetType(),
1.478 - DPT_Vector);
1.479 - }
1.480 -
1.481 - offset = info.actual_offset;
1.482 + FIND_PROP_SEND(DPT_Vector, "vector");
1.483 break;
1.484 }
1.485 default:
1.486 @@ -1570,8 +1678,15 @@
1.487 CBaseEntity *pEntity;
1.488 char *prop;
1.489 int offset;
1.490 + int bit_count;
1.491 const char *class_name;
1.492 edict_t *pEdict;
1.493 +
1.494 + int element = 0;
1.495 + if (params[0] >= 5)
1.496 + {
1.497 + element = params[5];
1.498 + }
1.499
1.500 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1.501 {
1.502 @@ -1603,24 +1718,13 @@
1.503 FIELD_POSITION_VECTOR);
1.504 }
1.505
1.506 - offset = GetTypeDescOffs(td);
1.507 + CHECK_SET_PROP_DATA_OFFSET();
1.508 +
1.509 break;
1.510 }
1.511 case Prop_Send:
1.512 {
1.513 - sm_sendprop_info_t info;
1.514 -
1.515 - FIND_PROP_SEND(&info);
1.516 -
1.517 - if (info.prop->GetType() != DPT_Vector)
1.518 - {
1.519 - return pContext->ThrowNativeError("SendProp %s is not a vector (%d != %d)",
1.520 - prop,
1.521 - info.prop->GetType(),
1.522 - DPT_Vector);
1.523 - }
1.524 -
1.525 - offset = info.actual_offset;
1.526 + FIND_PROP_SEND(DPT_Vector, "vector");
1.527 break;
1.528 }
1.529 default:
1.530 @@ -1654,6 +1758,12 @@
1.531 const char *class_name;
1.532 edict_t *pEdict;
1.533 bool bIsStringIndex;
1.534 +
1.535 + int element = 0;
1.536 + if (params[0] >= 6)
1.537 + {
1.538 + element = params[6];
1.539 + }
1.540
1.541 if (!IndexToAThings(params[1], &pEntity, &pEdict))
1.542 {
1.543 @@ -1690,14 +1800,46 @@
1.544
1.545 bIsStringIndex = (td->fieldType != FIELD_CHARACTER);
1.546
1.547 + if (bIsStringIndex && element >= td->fieldSize)
1.548 + {
1.549 + return pContext->ThrowNativeError("Element %d is out of bounds (Prop %s has %d elements).",
1.550 + element,
1.551 + prop,
1.552 + td->fieldSize);
1.553 + }
1.554 + else if (element > 1)
1.555 + {
1.556 + return pContext->ThrowNativeError("Prop %s is not an array. Element %d is invalid.",
1.557 + prop,
1.558 + element);
1.559 + }
1.560 +
1.561 offset = GetTypeDescOffs(td);
1.562 + if (bIsStringIndex)
1.563 + {
1.564 + offset += (element * (td->fieldSizeInBytes / td->fieldSize));
1.565 + }
1.566 break;
1.567 }
1.568 case Prop_Send:
1.569 {
1.570 sm_sendprop_info_t info;
1.571 +
1.572 + IServerUnknown *pUnk = (IServerUnknown *)pEntity;
1.573 + IServerNetworkable *pNet = pUnk->GetNetworkable();
1.574 + if (!pNet)
1.575 + {
1.576 + return pContext->ThrowNativeError("Edict %d (%d) is not networkable", g_HL2.ReferenceToIndex(params[1]), params[1]);
1.577 + }
1.578 + if (!g_HL2.FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, &info))
1.579 + {
1.580 + return pContext->ThrowNativeError("Property \"%s\" not found (entity %d/%s)",
1.581 + prop,
1.582 + params[1],
1.583 + class_name);
1.584 + }
1.585
1.586 - FIND_PROP_SEND(&info);
1.587 + offset = info.actual_offset;
1.588
1.589 if (info.prop->GetType() != DPT_String)
1.590 {
1.591 @@ -1706,9 +1848,13 @@
1.592 info.prop->GetType(),
1.593 DPT_String);
1.594 }
1.595 -
1.596 - offset = info.actual_offset;
1.597 - break;
1.598 + else if (element > 0)
1.599 + {
1.600 + return pContext->ThrowNativeError("SendProp %s is not an array. Element %d is invalid.",
1.601 + prop,
1.602 + element);
1.603 + }
1.604 +
1.605 break;
1.606 }
1.607 default:
1.608 @@ -2080,6 +2226,7 @@
1.609 {"GetEntDataString", GetEntDataString},
1.610 {"GetEntDataVector", GetEntDataVector},
1.611 {"GetEntProp", GetEntProp},
1.612 + {"GetEntPropArraySize", GetEntPropArraySize},
1.613 {"GetEntPropEnt", GetEntPropEnt},
1.614 {"GetEntPropFloat", GetEntPropFloat},
1.615 {"GetEntPropString", GetEntPropString},