1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/extensions/sdktools/gamerulesnatives.cpp Wed Jul 06 17:37:35 2011 -0400
1.3 @@ -0,0 +1,609 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod SDKTools Extension
1.8 + * Copyright (C) 2004-2011 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include "extension.h"
1.36 +#include "gamerulesnatives.h"
1.37 +#include "vglobals.h"
1.38 +
1.39 +const char *g_szGameRulesProxy;
1.40 +
1.41 +void GameRulesNativesInit()
1.42 +{
1.43 + g_szGameRulesProxy = g_pGameConf->GetKeyValue("GameRulesProxy");
1.44 +}
1.45 +
1.46 +static CBaseEntity *FindEntityByNetClass(int start, const char *classname)
1.47 +{
1.48 + int maxEntities = gpGlobals->maxEntities;
1.49 + for (int i = start; i < maxEntities; i++)
1.50 + {
1.51 + edict_t *current = gamehelpers->EdictOfIndex(i);
1.52 + if (current == NULL)
1.53 + continue;
1.54 +
1.55 + IServerNetworkable *network = current->GetNetworkable();
1.56 + if (network == NULL)
1.57 + continue;
1.58 +
1.59 + ServerClass *sClass = network->GetServerClass();
1.60 + const char *name = sClass->GetName();
1.61 +
1.62 + if (!strcmp(name, classname))
1.63 + return gamehelpers->ReferenceToEntity(gamehelpers->IndexOfEdict(current));
1.64 + }
1.65 +
1.66 + return NULL;
1.67 +}
1.68 +
1.69 +static CBaseEntity* GetGameRulesProxyEnt()
1.70 +{
1.71 + static cell_t proxyEntRef = -1;
1.72 + CBaseEntity *pProxy;
1.73 + if (proxyEntRef == -1 || (pProxy = gamehelpers->ReferenceToEntity(proxyEntRef)) == NULL)
1.74 + {
1.75 + pProxy = FindEntityByNetClass(playerhelpers->GetMaxClients(), g_szGameRulesProxy);
1.76 + proxyEntRef = gamehelpers->EntityToReference(pProxy);
1.77 + }
1.78 +
1.79 + return pProxy;
1.80 +}
1.81 +
1.82 +enum PropFieldType
1.83 +{
1.84 + PropField_Unsupported, /**< The type is unsupported. */
1.85 + PropField_Integer, /**< Valid for SendProp and Data fields */
1.86 + PropField_Float, /**< Valid for SendProp and Data fields */
1.87 + PropField_Entity, /**< Valid for Data fields only (SendProp shows as int) */
1.88 + PropField_Vector, /**< Valid for SendProp and Data fields */
1.89 + PropField_String, /**< Valid for SendProp and Data fields */
1.90 + PropField_String_T, /**< Valid for Data fields. Read only! */
1.91 +};
1.92 +
1.93 +#define FIND_PROP_SEND(type, type_name) \
1.94 + sm_sendprop_info_t info;\
1.95 + if (!gamehelpers->FindSendPropInfo(g_szGameRulesProxy, prop, &info)) \
1.96 + { \
1.97 + return pContext->ThrowNativeError("Property \"%s\" not found on the gamerules proxy", prop); \
1.98 + } \
1.99 + \
1.100 + offset = info.actual_offset; \
1.101 + bit_count = info.prop->m_nBits; \
1.102 + \
1.103 + switch (info.prop->GetType()) \
1.104 + { \
1.105 + case type: \
1.106 + { \
1.107 + if (element > 0) \
1.108 + { \
1.109 + return pContext->ThrowNativeError("SendProp %s is not an array. Element %d is invalid.", \
1.110 + prop, \
1.111 + element); \
1.112 + } \
1.113 + break; \
1.114 + } \
1.115 + case DPT_DataTable: \
1.116 + { \
1.117 + SendProp *pProp; \
1.118 + FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name); \
1.119 + \
1.120 + offset += pProp->GetOffset(); \
1.121 + bit_count = pProp->m_nBits; \
1.122 + break; \
1.123 + } \
1.124 + default: \
1.125 + { \
1.126 + return pContext->ThrowNativeError("SendProp %s type is not " type_name " (%d != %d)", \
1.127 + prop, \
1.128 + info.prop->GetType(), \
1.129 + type); \
1.130 + } \
1.131 + } \
1.132 +
1.133 +#define FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name) \
1.134 + SendTable *pTable = info.prop->GetDataTable(); \
1.135 + if (!pTable) \
1.136 + { \
1.137 + return pContext->ThrowNativeError("Error looking up DataTable for prop %s", \
1.138 + prop); \
1.139 + } \
1.140 + \
1.141 + int elementCount = pTable->GetNumProps(); \
1.142 + if (element >= elementCount) \
1.143 + { \
1.144 + return pContext->ThrowNativeError("Element %d is out of bounds (Prop %s has %d elements).", \
1.145 + element, \
1.146 + prop, \
1.147 + elementCount); \
1.148 + } \
1.149 + \
1.150 + pProp = pTable->GetProp(element); \
1.151 + if (pProp->GetType() != type) \
1.152 + { \
1.153 + return pContext->ThrowNativeError("SendProp %s type is not " type_name " ([%d,%d] != %d)", \
1.154 + prop, \
1.155 + info.prop->GetType(), \
1.156 + info.prop->m_nBits, \
1.157 + type); \
1.158 + }
1.159 +
1.160 +static cell_t GameRules_GetProp(IPluginContext *pContext, const cell_t *params)
1.161 +{
1.162 + char *prop;
1.163 + int element = params[3];
1.164 + int offset;
1.165 + int bit_count;
1.166 +
1.167 + if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
1.168 + return pContext->ThrowNativeError("Gamerules lookup failed.");
1.169 +
1.170 + pContext->LocalToString(params[1], &prop);
1.171 +
1.172 + int elementCount = 1;
1.173 +
1.174 + FIND_PROP_SEND(DPT_Int, "integer");
1.175 +
if (bit_count < 1)
1.176 + {
1.177 + bit_count = params[2] * 8;
1.178 + }
1.179 +
1.180 + void *pGameRules = *g_pGameRules;
1.181 +
1.182 + if (bit_count >= 17)
1.183 + {
1.184 + return *(int32_t *)((intptr_t)pGameRules + offset);
1.185 + }
1.186 + else if (bit_count >= 9)
1.187 + {
1.188 + return *(int16_t *)((intptr_t)pGameRules + offset);
1.189 + }
1.190 + else if (bit_count >= 2)
1.191 + {
1.192 + return *(int8_t *)((intptr_t)pGameRules + offset);
1.193 + }
1.194 + else
1.195 + {
1.196 + return *(bool *)((intptr_t)pGameRules + offset) ? 1 : 0;
1.197 + }
1.198 +
1.199 + return -1;
1.200 +}
1.201 +
1.202 +static cell_t GameRules_SetProp(IPluginContext *pContext, const cell_t *params)
1.203 +{
1.204 + char *prop;
1.205 + int element = params[4];
1.206 + int offset;
1.207 + int bit_count;
1.208 +
1.209 + bool sendChange = true;
1.210 + if (params[5] == 0)
1.211 + sendChange = false;
1.212 +
1.213 + CBaseEntity *pProxy = NULL;
1.214 + if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
1.215 + return pContext->ThrowNativeError("Couldn't find gamerules proxy entity");
1.216 +
1.217 + if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
1.218 + return pContext->ThrowNativeError("Gamerules lookup failed");
1.219 +
1.220 + pContext->LocalToString(params[1], &prop);
1.221 +
1.222 + FIND_PROP_SEND(DPT_Int, "integer");
1.223 +
1.224 + void *pGameRules = *g_pGameRules;
1.225 +
1.226 + if (bit_count < 1)
1.227 + {
1.228 + bit_count = params[3] * 8;
1.229 + }
1.230 +
1.231 + if (bit_count >= 17)
1.232 + {
1.233 + *(int32_t *)((intptr_t)pGameRules + offset) = params[2];
1.234 + if (sendChange)
1.235 + {
1.236 + *(int32_t *)((intptr_t)pProxy + offset) = params[2];
1.237 + gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
1.238 + }
1.239 + }
1.240 + else if (bit_count >= 9)
1.241 + {
1.242 + *(int16_t *)((intptr_t)pGameRules + offset) = (int16_t)params[2];
1.243 + if (sendChange)
1.244 + {
1.245 + *(int16_t *)((intptr_t)pProxy + offset) = (int16_t)params[2];
1.246 + gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
1.247 + }
1.248 + }
1.249 + else if (bit_count >= 2)
1.250 + {
1.251 + *(int8_t *)((intptr_t)pGameRules + offset) = (int8_t)params[2];
1.252 + if (sendChange)
1.253 + {
1.254 + *(int8_t *)((intptr_t)pProxy + offset) = (int8_t)params[2];
1.255 + gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
1.256 + }
1.257 + }
1.258 + else
1.259 + {
1.260 + *(bool *)((intptr_t)pGameRules + offset) = (params[2] == 0) ? false : true;
1.261 + if (sendChange)
1.262 + {
1.263 + *(bool *)((intptr_t)pProxy + offset) = (params[2] == 0) ? false : true;
1.264 + gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
1.265 + }
1.266 + }
1.267 +
1.268 + return 0;
1.269 +}
1.270 +
1.271 +static cell_t GameRules_GetPropFloat(IPluginContext *pContext, const cell_t *params)
1.272 +{
1.273 + char *prop;
1.274 + int element = params[2];
1.275 + int offset;
1.276 + int bit_count;
1.277 +
1.278 + if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
1.279 + return pContext->ThrowNativeError("Gamerules lookup failed.");
1.280 +
1.281 + pContext->LocalToString(params[1], &prop);
1.282 +
1.283 + FIND_PROP_SEND(DPT_Float, "float");
1.284 +
1.285 + void *pGameRules = *g_pGameRules;
1.286 +
1.287 + float val = *(float *)((intptr_t)pGameRules + offset);
1.288 +
1.289 + return sp_ftoc(val);
1.290 +}
1.291 +
1.292 +static cell_t GameRules_SetPropFloat(IPluginContext *pContext, const cell_t *params)
1.293 +{
1.294 + char *prop;
1.295 + int element = params[3];
1.296 + int offset;
1.297 + int bit_count;
1.298 +
1.299 + bool sendChange = true;
1.300 + if (params[4] == 0)
1.301 + sendChange = false;
1.302 +
1.303 + CBaseEntity *pProxy = NULL;
1.304 + if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
1.305 + return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
1.306 +
1.307 + if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
1.308 + return pContext->ThrowNativeError("Gamerules lookup failed.");
1.309 +
1.310 + pContext->LocalToString(params[1], &prop);
1.311 +
1.312 + FIND_PROP_SEND(DPT_Float, "float");
1.313 +
1.314 + void *pGameRules = *g_pGameRules;
1.315 + float newVal = sp_ctof(params[2]);
1.316 +
1.317 + *(float *)((intptr_t)pGameRules + offset) = newVal;
1.318 +
1.319 + if (sendChange)
1.320 + {
1.321 + *(float *)((intptr_t)pProxy + offset) = newVal;
1.322 + gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
1.323 + }
1.324 +
1.325 + return 0;
1.326 +}
1.327 +
1.328 +static cell_t GameRules_GetPropEnt(IPluginContext *pContext, const cell_t *params)
1.329 +{
1.330 + char *prop;
1.331 + int element = params[2];
1.332 + int offset;
1.333 + int bit_count;
1.334 +
1.335 + if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
1.336 + return pContext->ThrowNativeError("Gamerules lookup failed.");
1.337 +
1.338 + pContext->LocalToString(params[1], &prop);
1.339 +
1.340 + FIND_PROP_SEND(DPT_Int, "Integer");
1.341 +
1.342 + void *pGameRules = *g_pGameRules;
1.343 +
1.344 + CBaseHandle &hndl = *(CBaseHandle *)((intptr_t)pGameRules + offset);
1.345 +
1.346 + int ref = gamehelpers->IndexToReference(hndl.GetEntryIndex());
1.347 + return gamehelpers->ReferenceToBCompatRef(ref);
1.348 +}
1.349 +
1.350 +static cell_t GameRules_SetPropEnt(IPluginContext *pContext, const cell_t *params)
1.351 +{
1.352 + char *prop;
1.353 + int element = params[3];
1.354 + int offset;
1.355 + int bit_count;
1.356 +
1.357 + bool sendChange = true;
1.358 + if (params[4] == 0)
1.359 + sendChange = false;
1.360 +
1.361 + CBaseEntity *pProxy = NULL;
1.362 + if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
1.363 + return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
1.364 +
1.365 + if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
1.366 + return pContext->ThrowNativeError("Gamerules lookup failed.");
1.367 +
1.368 + pContext->LocalToString(params[1], &prop);
1.369 +
1.370 + FIND_PROP_SEND(DPT_Int, "integer");
1.371 +
1.372 + void *pGameRules = *g_pGameRules;
1.373 +
1.374 + CBaseHandle &hndl = *(CBaseHandle *)((intptr_t)pGameRules + offset);
1.375 + CBaseEntity *pOther;
1.376 +
1.377 + if (params[2] == -1)
1.378 + {
1.379 + hndl.Set(NULL);
1.380 + }
1.381 + else
1.382 + {
1.383 + pOther = gamehelpers->ReferenceToEntity(params[2]);
1.384 +
1.385 + if (!pOther)
1.386 + {
1.387 + return pContext->ThrowNativeError("Entity %d (%d) is invalid", gamehelpers->ReferenceToIndex(params[4]), params[4]);
1.388 + }
1.389 +
1.390 + IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
1.391 + hndl.Set(pHandleEnt);
1.392 + }
1.393 +
1.394 + if (sendChange)
1.395 + {
1.396 + CBaseHandle &hndl = *(CBaseHandle *)((intptr_t)pProxy + offset);
1.397 + if (params[2] == -1)
1.398 + {
1.399 + hndl.Set(NULL);
1.400 + }
1.401 + else
1.402 + {
1.403 + IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
1.404 + hndl.Set(pHandleEnt);
1.405 + }
1.406 +
1.407 + gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
1.408 + }
1.409 +
1.410 + return 0;
1.411 +}
1.412 +
1.413 +static cell_t GameRules_GetPropVector(IPluginContext *pContext, const cell_t *params)
1.414 +{
1.415 + char *prop;
1.416 + int element = params[3];
1.417 + int offset;
1.418 + int bit_count;
1.419 +
1.420 + if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
1.421 + return pContext->ThrowNativeError("Gamerules lookup failed.");
1.422 +
1.423 + pContext->LocalToString(params[1], &prop);
1.424 +
1.425 + FIND_PROP_SEND(DPT_Vector, "vector");
1.426 +
1.427 + void *pGameRules = *g_pGameRules;
1.428 +
1.429 + Vector *v = (Vector *)((intptr_t)pGameRules + offset);
1.430 +
1.431 + cell_t *vec;
1.432 + pContext->LocalToPhysAddr(params[2], &vec);
1.433 +
1.434 + vec[0] = sp_ftoc(v->x);
1.435 + vec[1] = sp_ftoc(v->y);
1.436 + vec[2] = sp_ftoc(v->z);
1.437 +
1.438 + return 1;
1.439 +}
1.440 +
1.441 +static cell_t GameRules_SetPropVector(IPluginContext *pContext, const cell_t *params)
1.442 +{
1.443 + char *prop;
1.444 + int element = params[3];
1.445 + int offset;
1.446 + int bit_count;
1.447 +
1.448 + bool sendChange = true;
1.449 + if (params[4] == 0)
1.450 + sendChange = false;
1.451 +
1.452 + CBaseEntity *pProxy = NULL;
1.453 + if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
1.454 + return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
1.455 +
1.456 + if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
1.457 + return pContext->ThrowNativeError("Gamerules lookup failed.");
1.458 +
1.459 + pContext->LocalToString(params[1], &prop);
1.460 +
1.461 + FIND_PROP_SEND(DPT_Vector, "vector");
1.462 +
1.463 + void *pGameRules = *g_pGameRules;
1.464 +
1.465 + Vector *v = (Vector *)((intptr_t)pGameRules + offset);
1.466 +
1.467 + cell_t *vec;
1.468 + pContext->LocalToPhysAddr(params[2], &vec);
1.469 +
1.470 + v->x = sp_ctof(vec[0]);
1.471 + v->y = sp_ctof(vec[1]);
1.472 + v->z = sp_ctof(vec[2]);
1.473 +
1.474 + if (sendChange)
1.475 + {
1.476 + v = (Vector *)((intptr_t)g_pGameRules + offset);
1.477 + v->x = sp_ctof(vec[0]);
1.478 + v->y = sp_ctof(vec[1]);
1.479 + v->z = sp_ctof(vec[2]);
1.480 +
1.481 + gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
1.482 + }
1.483 +
1.484 + return 1;
1.485 +}
1.486 +
1.487 +static cell_t GameRules_GetPropString(IPluginContext *pContext, const cell_t *params)
1.488 +{
1.489 + char *prop;
1.490 + int offset;
1.491 +
1.492 + if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
1.493 + return pContext->ThrowNativeError("Gamerules lookup failed.");
1.494 +
1.495 + pContext->LocalToString(params[1], &prop);
1.496 +
1.497 + sm_sendprop_info_t info;
1.498 + if (!gamehelpers->FindSendPropInfo(g_szGameRulesProxy, prop, &info))
1.499 + {
1.500 + return pContext->ThrowNativeError("Property \"%s\" not found on the gamerules proxy", prop);
1.501 + }
1.502 +
1.503 + offset = info.actual_offset;
1.504 +
1.505 + if (info.prop->GetType() != DPT_String)
1.506 + {
1.507 + return pContext->ThrowNativeError("SendProp %s type is not a string (%d != %d)",
1.508 + prop,
1.509 + info.prop->GetType(),
1.510 + DPT_String);
1.511 + }
1.512 +
1.513 + void *pGameRules = *g_pGameRules;
1.514 +
1.515 + size_t len;
1.516 + const char *src;
1.517 +
1.518 + src = (char *)((intptr_t)pGameRules + offset);
1.519 +
1.520 + pContext->StringToLocalUTF8(params[2], params[3], src, &len);
1.521 +
1.522 + return len;
1.523 +}
1.524 +
1.525 +// From sm_stringutil
1.526 +inline int strncopy(char *dest, const char *src, size_t count)
1.527 +{
1.528 + if (!count)
1.529 + {
1.530 + return 0;
1.531 + }
1.532 +
1.533 + char *start = dest;
1.534 + while ((*src) && (--count))
1.535 + {
1.536 + *dest++ = *src++;
1.537 + }
1.538 + *dest = '\0';
1.539 +
1.540 + return (dest - start);
1.541 +}
1.542 +//
1.543 +
1.544 +static cell_t GameRules_SetPropString(IPluginContext *pContext, const cell_t *params)
1.545 +{
1.546 + char *prop;
1.547 + int offset;
1.548 + int maxlen;
1.549 +
1.550 + bool sendChange = true;
1.551 + if (params[3] == 0)
1.552 + sendChange = false;
1.553 +
1.554 + CBaseEntity *pProxy = NULL;
1.555 + if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
1.556 + return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
1.557 +
1.558 + if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
1.559 + return pContext->ThrowNativeError("Gamerules lookup failed.");
1.560 +
1.561 + pContext->LocalToString(params[1], &prop);
1.562 +
1.563 + sm_sendprop_info_t info;
1.564 + if (!gamehelpers->FindSendPropInfo(g_szGameRulesProxy, prop, &info))
1.565 + {
1.566 + return pContext->ThrowNativeError("Property \"%s\" not found on the gamerules proxy", prop);
1.567 + }
1.568 +
1.569 + offset = info.actual_offset;
1.570 +
1.571 + if (info.prop->GetType() != DPT_String)
1.572 + {
1.573 + return pContext->ThrowNativeError("SendProp %s type is not a string (%d != %d)",
1.574 + prop,
1.575 + info.prop->GetType(),
1.576 + DPT_String);
1.577 + }
1.578 +
1.579 + void *pGameRules = *g_pGameRules;
1.580 + maxlen = DT_MAX_STRING_BUFFERSIZE;
1.581 +
1.582 + char *src;
1.583 + char *dest = (char *)((intptr_t)pGameRules + offset);
1.584 +
1.585 + pContext->LocalToString(params[2], &src);
1.586 + size_t len = strncopy(dest, src, maxlen);
1.587 +
1.588 + if (sendChange)
1.589 + {
1.590 + dest = (char *)((intptr_t)pProxy + offset);
1.591 + strncopy(dest, src, maxlen);
1.592 + gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
1.593 + }
1.594 +
1.595 + return len;
1.596 +}
1.597 +
1.598 +sp_nativeinfo_t g_GameRulesNatives[] =
1.599 +{
1.600 + {"GameRules_GetProp", GameRules_GetProp},
1.601 + {"GameRules_SetProp", GameRules_SetProp},
1.602 + {"GameRules_GetPropFloat", GameRules_GetPropFloat},
1.603 + {"GameRules_SetPropFloat", GameRules_SetPropFloat},
1.604 + {"GameRules_GetPropEnt", GameRules_GetPropEnt},
1.605 + {"GameRules_SetPropEnt", GameRules_SetPropEnt},
1.606 + {"GameRules_GetPropVector", GameRules_GetPropVector},
1.607 + {"GameRules_SetPropVector", GameRules_SetPropVector},
1.608 + {"GameRules_GetPropString", GameRules_GetPropString},
1.609 + {"GameRules_SetPropString", GameRules_SetPropString},
1.610 + {NULL, NULL},
1.611 +};
1.612 +