extensions/sdktools/gamerulesnatives.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Fri Jul 08 07:53:31 2011 -0400 (2011-07-08)
changeset 3348 fcae86e8cb8f
parent 3333 e247490894a1
child 3710 5559ea22b6b5
permissions -rw-r--r--
Backed out changeset: 9007dacc012d
skamonkey@3333
     1
/**
skamonkey@3333
     2
 * vim: set ts=4 :
skamonkey@3333
     3
 * =============================================================================
skamonkey@3333
     4
 * SourceMod SDKTools Extension
skamonkey@3333
     5
 * Copyright (C) 2004-2011 AlliedModders LLC.  All rights reserved.
skamonkey@3333
     6
 * =============================================================================
skamonkey@3333
     7
 *
skamonkey@3333
     8
 * This program is free software; you can redistribute it and/or modify it under
skamonkey@3333
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
skamonkey@3333
    10
 * Free Software Foundation.
skamonkey@3333
    11
 * 
skamonkey@3333
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
skamonkey@3333
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
skamonkey@3333
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
skamonkey@3333
    15
 * details.
skamonkey@3333
    16
 *
skamonkey@3333
    17
 * You should have received a copy of the GNU General Public License along with
skamonkey@3333
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
skamonkey@3333
    19
 *
skamonkey@3333
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
skamonkey@3333
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
skamonkey@3333
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
skamonkey@3333
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
skamonkey@3333
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
skamonkey@3333
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
skamonkey@3333
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
skamonkey@3333
    27
 * or <http://www.sourcemod.net/license.php>.
skamonkey@3333
    28
 *
skamonkey@3333
    29
 * Version: $Id$
skamonkey@3333
    30
 */
skamonkey@3333
    31
skamonkey@3333
    32
#include "extension.h"
skamonkey@3333
    33
#include "gamerulesnatives.h"
skamonkey@3333
    34
#include "vglobals.h"
skamonkey@3333
    35
skamonkey@3333
    36
const char *g_szGameRulesProxy;
skamonkey@3333
    37
skamonkey@3333
    38
void GameRulesNativesInit()
skamonkey@3333
    39
{
skamonkey@3333
    40
	g_szGameRulesProxy = g_pGameConf->GetKeyValue("GameRulesProxy");
skamonkey@3333
    41
}
skamonkey@3333
    42
skamonkey@3333
    43
static CBaseEntity *FindEntityByNetClass(int start, const char *classname)
skamonkey@3333
    44
{
skamonkey@3333
    45
	int maxEntities = gpGlobals->maxEntities;
skamonkey@3333
    46
	for (int i = start; i < maxEntities; i++)
skamonkey@3333
    47
	{
skamonkey@3333
    48
		edict_t *current = gamehelpers->EdictOfIndex(i);
skamonkey@3333
    49
		if (current == NULL)
skamonkey@3333
    50
			continue;
skamonkey@3333
    51
skamonkey@3333
    52
		IServerNetworkable *network = current->GetNetworkable();
skamonkey@3333
    53
		if (network == NULL)
skamonkey@3333
    54
			continue;
skamonkey@3333
    55
skamonkey@3333
    56
		ServerClass *sClass = network->GetServerClass();
skamonkey@3333
    57
		const char *name = sClass->GetName();
skamonkey@3333
    58
skamonkey@3333
    59
		if (!strcmp(name, classname))
skamonkey@3333
    60
			return gamehelpers->ReferenceToEntity(gamehelpers->IndexOfEdict(current));		
skamonkey@3333
    61
	}
skamonkey@3333
    62
skamonkey@3333
    63
	return NULL;
skamonkey@3333
    64
}
skamonkey@3333
    65
skamonkey@3333
    66
static CBaseEntity* GetGameRulesProxyEnt()
skamonkey@3333
    67
{
skamonkey@3333
    68
	static cell_t proxyEntRef = -1;
skamonkey@3333
    69
	CBaseEntity *pProxy;
skamonkey@3333
    70
	if (proxyEntRef == -1 || (pProxy = gamehelpers->ReferenceToEntity(proxyEntRef)) == NULL)
skamonkey@3333
    71
	{
skamonkey@3333
    72
		pProxy = FindEntityByNetClass(playerhelpers->GetMaxClients(), g_szGameRulesProxy);
skamonkey@3333
    73
		proxyEntRef = gamehelpers->EntityToReference(pProxy);
skamonkey@3333
    74
	}
skamonkey@3333
    75
	
skamonkey@3333
    76
	return pProxy;
skamonkey@3333
    77
}
skamonkey@3333
    78
skamonkey@3333
    79
enum PropFieldType
skamonkey@3333
    80
{
skamonkey@3333
    81
	PropField_Unsupported,		/**< The type is unsupported. */
skamonkey@3333
    82
	PropField_Integer,			/**< Valid for SendProp and Data fields */
skamonkey@3333
    83
	PropField_Float,			/**< Valid for SendProp and Data fields */
skamonkey@3333
    84
	PropField_Entity,			/**< Valid for Data fields only (SendProp shows as int) */
skamonkey@3333
    85
	PropField_Vector,			/**< Valid for SendProp and Data fields */
skamonkey@3333
    86
	PropField_String,			/**< Valid for SendProp and Data fields */
skamonkey@3333
    87
	PropField_String_T,			/**< Valid for Data fields.  Read only! */
skamonkey@3333
    88
};
skamonkey@3333
    89
skamonkey@3333
    90
#define FIND_PROP_SEND(type, type_name) \
skamonkey@3333
    91
	sm_sendprop_info_t info;\
skamonkey@3333
    92
	if (!gamehelpers->FindSendPropInfo(g_szGameRulesProxy, prop, &info)) \
skamonkey@3333
    93
	{ \
skamonkey@3333
    94
		return pContext->ThrowNativeError("Property \"%s\" not found on the gamerules proxy", prop); \
skamonkey@3333
    95
	} \
skamonkey@3333
    96
	\
skamonkey@3333
    97
	offset = info.actual_offset; \
skamonkey@3333
    98
	bit_count = info.prop->m_nBits; \
skamonkey@3333
    99
	\
skamonkey@3333
   100
	switch (info.prop->GetType()) \
skamonkey@3333
   101
	{ \
skamonkey@3333
   102
	case type: \
skamonkey@3333
   103
		{ \
skamonkey@3333
   104
			if (element > 0) \
skamonkey@3333
   105
			{ \
skamonkey@3333
   106
				return pContext->ThrowNativeError("SendProp %s is not an array. Element %d is invalid.", \
skamonkey@3333
   107
					prop, \
skamonkey@3333
   108
					element); \
skamonkey@3333
   109
			} \
skamonkey@3333
   110
			break; \
skamonkey@3333
   111
		} \
skamonkey@3333
   112
	case DPT_DataTable: \
skamonkey@3333
   113
		{ \
skamonkey@3333
   114
			SendProp *pProp; \
skamonkey@3333
   115
			FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name); \
skamonkey@3333
   116
			\
skamonkey@3333
   117
			offset += pProp->GetOffset(); \
skamonkey@3333
   118
			bit_count = pProp->m_nBits; \
skamonkey@3333
   119
			break; \
skamonkey@3333
   120
		} \
skamonkey@3333
   121
	default: \
skamonkey@3333
   122
		{ \
skamonkey@3333
   123
			return pContext->ThrowNativeError("SendProp %s type is not " type_name " (%d != %d)", \
skamonkey@3333
   124
				prop, \
skamonkey@3333
   125
				info.prop->GetType(), \
skamonkey@3333
   126
				type); \
skamonkey@3333
   127
		} \
skamonkey@3333
   128
	} \
skamonkey@3333
   129
skamonkey@3333
   130
#define FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name) \
skamonkey@3333
   131
	SendTable *pTable = info.prop->GetDataTable(); \
skamonkey@3333
   132
	if (!pTable) \
skamonkey@3333
   133
	{ \
skamonkey@3333
   134
		return pContext->ThrowNativeError("Error looking up DataTable for prop %s", \
skamonkey@3333
   135
			prop); \
skamonkey@3333
   136
	} \
skamonkey@3333
   137
	\
skamonkey@3333
   138
	int elementCount = pTable->GetNumProps(); \
skamonkey@3333
   139
	if (element >= elementCount) \
skamonkey@3333
   140
	{ \
skamonkey@3333
   141
		return pContext->ThrowNativeError("Element %d is out of bounds (Prop %s has %d elements).", \
skamonkey@3333
   142
			element, \
skamonkey@3333
   143
			prop, \
skamonkey@3333
   144
			elementCount); \
skamonkey@3333
   145
	} \
skamonkey@3333
   146
	\
skamonkey@3333
   147
	pProp = pTable->GetProp(element); \
skamonkey@3333
   148
	if (pProp->GetType() != type) \
skamonkey@3333
   149
	{ \
skamonkey@3333
   150
		return pContext->ThrowNativeError("SendProp %s type is not " type_name " ([%d,%d] != %d)", \
skamonkey@3333
   151
			prop, \
skamonkey@3333
   152
			info.prop->GetType(), \
skamonkey@3333
   153
			info.prop->m_nBits, \
skamonkey@3333
   154
			type); \
skamonkey@3333
   155
	}
skamonkey@3333
   156
skamonkey@3333
   157
static cell_t GameRules_GetProp(IPluginContext *pContext, const cell_t *params)
skamonkey@3333
   158
{
skamonkey@3333
   159
	char *prop;
skamonkey@3333
   160
	int element = params[3];
skamonkey@3333
   161
	int offset;
skamonkey@3333
   162
	int bit_count;
skamonkey@3333
   163
skamonkey@3333
   164
	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
skamonkey@3333
   165
		return pContext->ThrowNativeError("Gamerules lookup failed.");
skamonkey@3333
   166
skamonkey@3333
   167
	pContext->LocalToString(params[1], &prop);
skamonkey@3333
   168
skamonkey@3333
   169
	int elementCount = 1;
skamonkey@3333
   170
skamonkey@3333
   171
	FIND_PROP_SEND(DPT_Int, "integer");
skamonkey@3333
   172
skamonkey@3333
   173
	if (bit_count < 1)
skamonkey@3333
   174
	{
skamonkey@3333
   175
		bit_count = params[2] * 8;
skamonkey@3333
   176
	}
skamonkey@3333
   177
skamonkey@3333
   178
	void *pGameRules = *g_pGameRules;
skamonkey@3333
   179
skamonkey@3333
   180
	if (bit_count >= 17)
skamonkey@3333
   181
	{
skamonkey@3333
   182
		return *(int32_t *)((intptr_t)pGameRules + offset);
skamonkey@3333
   183
	}
skamonkey@3333
   184
	else if (bit_count >= 9)
skamonkey@3333
   185
	{
skamonkey@3333
   186
		return *(int16_t *)((intptr_t)pGameRules + offset);
skamonkey@3333
   187
	}
skamonkey@3333
   188
	else if (bit_count >= 2)
skamonkey@3333
   189
	{
skamonkey@3333
   190
		return *(int8_t *)((intptr_t)pGameRules + offset);
skamonkey@3333
   191
	}
skamonkey@3333
   192
	else
skamonkey@3333
   193
	{
skamonkey@3333
   194
		return *(bool *)((intptr_t)pGameRules + offset) ? 1 : 0;
skamonkey@3333
   195
	}
skamonkey@3333
   196
skamonkey@3333
   197
	return -1;
skamonkey@3333
   198
}
skamonkey@3333
   199
skamonkey@3333
   200
static cell_t GameRules_SetProp(IPluginContext *pContext, const cell_t *params)
skamonkey@3333
   201
{
skamonkey@3333
   202
	char *prop;
skamonkey@3333
   203
	int element = params[4];
skamonkey@3333
   204
	int offset;
skamonkey@3333
   205
	int bit_count;
skamonkey@3333
   206
skamonkey@3333
   207
	bool sendChange = true;
skamonkey@3333
   208
	if (params[5] == 0)
skamonkey@3333
   209
		sendChange = false;
skamonkey@3333
   210
skamonkey@3333
   211
	CBaseEntity *pProxy = NULL;
skamonkey@3333
   212
	if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
skamonkey@3333
   213
		return pContext->ThrowNativeError("Couldn't find gamerules proxy entity");
skamonkey@3333
   214
	
skamonkey@3333
   215
	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
skamonkey@3333
   216
		return pContext->ThrowNativeError("Gamerules lookup failed");
skamonkey@3333
   217
skamonkey@3333
   218
	pContext->LocalToString(params[1], &prop);
skamonkey@3333
   219
skamonkey@3333
   220
	FIND_PROP_SEND(DPT_Int, "integer");
skamonkey@3333
   221
skamonkey@3333
   222
	void *pGameRules = *g_pGameRules;
skamonkey@3333
   223
skamonkey@3333
   224
	if (bit_count < 1)
skamonkey@3333
   225
	{
skamonkey@3333
   226
		bit_count = params[3] * 8;
skamonkey@3333
   227
	}
skamonkey@3333
   228
skamonkey@3333
   229
	if (bit_count >= 17)
skamonkey@3333
   230
	{
skamonkey@3333
   231
		*(int32_t *)((intptr_t)pGameRules + offset) = params[2];
skamonkey@3333
   232
		if (sendChange)
skamonkey@3333
   233
		{
skamonkey@3333
   234
			*(int32_t *)((intptr_t)pProxy + offset) = params[2];
skamonkey@3333
   235
			gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
skamonkey@3333
   236
		}
skamonkey@3333
   237
	}
skamonkey@3333
   238
	else if (bit_count >= 9)
skamonkey@3333
   239
	{
skamonkey@3333
   240
		*(int16_t *)((intptr_t)pGameRules + offset) = (int16_t)params[2];
skamonkey@3333
   241
		if (sendChange)
skamonkey@3333
   242
		{
skamonkey@3333
   243
			*(int16_t *)((intptr_t)pProxy + offset) = (int16_t)params[2];
skamonkey@3333
   244
			gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
skamonkey@3333
   245
		}
skamonkey@3333
   246
	}
skamonkey@3333
   247
	else if (bit_count >= 2)
skamonkey@3333
   248
	{
skamonkey@3333
   249
		*(int8_t *)((intptr_t)pGameRules + offset) = (int8_t)params[2];
skamonkey@3333
   250
		if (sendChange)
skamonkey@3333
   251
		{
skamonkey@3333
   252
			*(int8_t *)((intptr_t)pProxy + offset) = (int8_t)params[2];
skamonkey@3333
   253
			gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
skamonkey@3333
   254
		}
skamonkey@3333
   255
	}
skamonkey@3333
   256
	else
skamonkey@3333
   257
	{
skamonkey@3333
   258
		*(bool *)((intptr_t)pGameRules + offset) = (params[2] == 0) ? false : true;
skamonkey@3333
   259
		if (sendChange)
skamonkey@3333
   260
		{
skamonkey@3333
   261
			*(bool *)((intptr_t)pProxy + offset) = (params[2] == 0) ? false : true;
skamonkey@3333
   262
			gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
skamonkey@3333
   263
		}
skamonkey@3333
   264
	}
skamonkey@3333
   265
skamonkey@3333
   266
	return 0;
skamonkey@3333
   267
}
skamonkey@3333
   268
skamonkey@3333
   269
static cell_t GameRules_GetPropFloat(IPluginContext *pContext, const cell_t *params)
skamonkey@3333
   270
{
skamonkey@3333
   271
	char *prop;
skamonkey@3333
   272
	int element = params[2];
skamonkey@3333
   273
	int offset;
skamonkey@3333
   274
	int bit_count;
skamonkey@3333
   275
skamonkey@3333
   276
	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
skamonkey@3333
   277
		return pContext->ThrowNativeError("Gamerules lookup failed.");
skamonkey@3333
   278
skamonkey@3333
   279
	pContext->LocalToString(params[1], &prop);
skamonkey@3333
   280
skamonkey@3333
   281
	FIND_PROP_SEND(DPT_Float, "float");
skamonkey@3333
   282
skamonkey@3333
   283
	void *pGameRules = *g_pGameRules;
skamonkey@3333
   284
skamonkey@3333
   285
	float val = *(float *)((intptr_t)pGameRules + offset);
skamonkey@3333
   286
skamonkey@3333
   287
	return sp_ftoc(val);
skamonkey@3333
   288
}
skamonkey@3333
   289
skamonkey@3333
   290
static cell_t GameRules_SetPropFloat(IPluginContext *pContext, const cell_t *params)
skamonkey@3333
   291
{
skamonkey@3333
   292
	char *prop;
skamonkey@3333
   293
	int element = params[3];
skamonkey@3333
   294
	int offset;
skamonkey@3333
   295
	int bit_count;
skamonkey@3333
   296
skamonkey@3333
   297
	bool sendChange = true;
skamonkey@3333
   298
	if (params[4] == 0)
skamonkey@3333
   299
		sendChange = false;
skamonkey@3333
   300
skamonkey@3333
   301
	CBaseEntity *pProxy = NULL;
skamonkey@3333
   302
	if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
skamonkey@3333
   303
		return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
skamonkey@3333
   304
	
skamonkey@3333
   305
	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
skamonkey@3333
   306
		return pContext->ThrowNativeError("Gamerules lookup failed.");
skamonkey@3333
   307
skamonkey@3333
   308
	pContext->LocalToString(params[1], &prop);
skamonkey@3333
   309
skamonkey@3333
   310
	FIND_PROP_SEND(DPT_Float, "float");
skamonkey@3333
   311
skamonkey@3333
   312
	void *pGameRules = *g_pGameRules;
skamonkey@3333
   313
	float newVal = sp_ctof(params[2]);
skamonkey@3333
   314
skamonkey@3333
   315
	*(float *)((intptr_t)pGameRules + offset) = newVal;
skamonkey@3333
   316
skamonkey@3333
   317
	if (sendChange)
skamonkey@3333
   318
	{
skamonkey@3333
   319
		*(float *)((intptr_t)pProxy + offset) = newVal;
skamonkey@3333
   320
		gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
skamonkey@3333
   321
	}
skamonkey@3333
   322
skamonkey@3333
   323
	return 0;
skamonkey@3333
   324
}
skamonkey@3333
   325
skamonkey@3333
   326
static cell_t GameRules_GetPropEnt(IPluginContext *pContext, const cell_t *params)
skamonkey@3333
   327
{
skamonkey@3333
   328
	char *prop;
skamonkey@3333
   329
	int element = params[2];
skamonkey@3333
   330
	int offset;
skamonkey@3333
   331
	int bit_count;
skamonkey@3333
   332
skamonkey@3333
   333
	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
skamonkey@3333
   334
		return pContext->ThrowNativeError("Gamerules lookup failed.");
skamonkey@3333
   335
skamonkey@3333
   336
	pContext->LocalToString(params[1], &prop);
skamonkey@3333
   337
skamonkey@3333
   338
	FIND_PROP_SEND(DPT_Int, "Integer");
skamonkey@3333
   339
skamonkey@3333
   340
	void *pGameRules = *g_pGameRules;
skamonkey@3333
   341
skamonkey@3333
   342
	CBaseHandle &hndl = *(CBaseHandle *)((intptr_t)pGameRules + offset);
skamonkey@3333
   343
skamonkey@3333
   344
	int ref = gamehelpers->IndexToReference(hndl.GetEntryIndex());
skamonkey@3333
   345
	return gamehelpers->ReferenceToBCompatRef(ref);
skamonkey@3333
   346
}
skamonkey@3333
   347
skamonkey@3333
   348
static cell_t GameRules_SetPropEnt(IPluginContext *pContext, const cell_t *params)
skamonkey@3333
   349
{
skamonkey@3333
   350
	char *prop;
skamonkey@3333
   351
	int element = params[3];
skamonkey@3333
   352
	int offset;
skamonkey@3333
   353
	int bit_count;
skamonkey@3333
   354
skamonkey@3333
   355
	bool sendChange = true;
skamonkey@3333
   356
	if (params[4] == 0)
skamonkey@3333
   357
		sendChange = false;
skamonkey@3333
   358
skamonkey@3333
   359
	CBaseEntity *pProxy = NULL;
skamonkey@3333
   360
	if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
skamonkey@3333
   361
		return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
skamonkey@3333
   362
	
skamonkey@3333
   363
	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
skamonkey@3333
   364
		return pContext->ThrowNativeError("Gamerules lookup failed.");
skamonkey@3333
   365
skamonkey@3333
   366
	pContext->LocalToString(params[1], &prop);
skamonkey@3333
   367
skamonkey@3333
   368
	FIND_PROP_SEND(DPT_Int, "integer");
skamonkey@3333
   369
skamonkey@3333
   370
	void *pGameRules = *g_pGameRules;
skamonkey@3333
   371
skamonkey@3333
   372
	CBaseHandle &hndl = *(CBaseHandle *)((intptr_t)pGameRules + offset);
skamonkey@3333
   373
	CBaseEntity *pOther;
skamonkey@3333
   374
skamonkey@3333
   375
	if (params[2] == -1)
skamonkey@3333
   376
	{
skamonkey@3333
   377
		hndl.Set(NULL);
skamonkey@3333
   378
	}
skamonkey@3333
   379
	else
skamonkey@3333
   380
	{
skamonkey@3333
   381
		pOther = gamehelpers->ReferenceToEntity(params[2]);
skamonkey@3333
   382
skamonkey@3333
   383
		if (!pOther)
skamonkey@3333
   384
		{
skamonkey@3333
   385
			return pContext->ThrowNativeError("Entity %d (%d) is invalid", gamehelpers->ReferenceToIndex(params[4]), params[4]);
skamonkey@3333
   386
		}
skamonkey@3333
   387
skamonkey@3333
   388
		IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
skamonkey@3333
   389
		hndl.Set(pHandleEnt);
skamonkey@3333
   390
	}
skamonkey@3333
   391
skamonkey@3333
   392
	if (sendChange)
skamonkey@3333
   393
	{
skamonkey@3333
   394
		CBaseHandle &hndl = *(CBaseHandle *)((intptr_t)pProxy + offset);
skamonkey@3333
   395
		if (params[2] == -1)
skamonkey@3333
   396
		{
skamonkey@3333
   397
			hndl.Set(NULL);
skamonkey@3333
   398
		}
skamonkey@3333
   399
		else
skamonkey@3333
   400
		{
skamonkey@3333
   401
			IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
skamonkey@3333
   402
			hndl.Set(pHandleEnt);
skamonkey@3333
   403
		}
skamonkey@3333
   404
skamonkey@3333
   405
		gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
skamonkey@3333
   406
	}
skamonkey@3333
   407
skamonkey@3333
   408
	return 0;
skamonkey@3333
   409
}
skamonkey@3333
   410
skamonkey@3333
   411
static cell_t GameRules_GetPropVector(IPluginContext *pContext, const cell_t *params)
skamonkey@3333
   412
{
skamonkey@3333
   413
	char *prop;
skamonkey@3333
   414
	int element = params[3];
skamonkey@3333
   415
	int offset;
skamonkey@3333
   416
	int bit_count;
skamonkey@3333
   417
skamonkey@3333
   418
	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
skamonkey@3333
   419
		return pContext->ThrowNativeError("Gamerules lookup failed.");
skamonkey@3333
   420
skamonkey@3333
   421
	pContext->LocalToString(params[1], &prop);
skamonkey@3333
   422
skamonkey@3333
   423
	FIND_PROP_SEND(DPT_Vector, "vector");
skamonkey@3333
   424
skamonkey@3333
   425
	void *pGameRules = *g_pGameRules;
skamonkey@3333
   426
skamonkey@3333
   427
	Vector *v = (Vector *)((intptr_t)pGameRules + offset);
skamonkey@3333
   428
skamonkey@3333
   429
	cell_t *vec;
skamonkey@3333
   430
	pContext->LocalToPhysAddr(params[2], &vec);
skamonkey@3333
   431
skamonkey@3333
   432
	vec[0] = sp_ftoc(v->x);
skamonkey@3333
   433
	vec[1] = sp_ftoc(v->y);
skamonkey@3333
   434
	vec[2] = sp_ftoc(v->z);
skamonkey@3333
   435
skamonkey@3333
   436
	return 1;
skamonkey@3333
   437
}
skamonkey@3333
   438
skamonkey@3333
   439
static cell_t GameRules_SetPropVector(IPluginContext *pContext, const cell_t *params)
skamonkey@3333
   440
{
skamonkey@3333
   441
	char *prop;
skamonkey@3333
   442
	int element = params[3];
skamonkey@3333
   443
	int offset;
skamonkey@3333
   444
	int bit_count;
skamonkey@3333
   445
skamonkey@3333
   446
	bool sendChange = true;
skamonkey@3333
   447
	if (params[4] == 0)
skamonkey@3333
   448
		sendChange = false;
skamonkey@3333
   449
skamonkey@3333
   450
	CBaseEntity *pProxy = NULL;
skamonkey@3333
   451
	if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
skamonkey@3333
   452
		return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
skamonkey@3333
   453
	
skamonkey@3333
   454
	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
skamonkey@3333
   455
		return pContext->ThrowNativeError("Gamerules lookup failed.");
skamonkey@3333
   456
skamonkey@3333
   457
	pContext->LocalToString(params[1], &prop);
skamonkey@3333
   458
skamonkey@3333
   459
	FIND_PROP_SEND(DPT_Vector, "vector");
skamonkey@3333
   460
skamonkey@3333
   461
	void *pGameRules = *g_pGameRules;
skamonkey@3333
   462
skamonkey@3333
   463
	Vector *v = (Vector *)((intptr_t)pGameRules + offset);
skamonkey@3333
   464
skamonkey@3333
   465
	cell_t *vec;
skamonkey@3333
   466
	pContext->LocalToPhysAddr(params[2], &vec);
skamonkey@3333
   467
skamonkey@3333
   468
	v->x = sp_ctof(vec[0]);
skamonkey@3333
   469
	v->y = sp_ctof(vec[1]);
skamonkey@3333
   470
	v->z = sp_ctof(vec[2]);
skamonkey@3333
   471
skamonkey@3333
   472
	if (sendChange)
skamonkey@3333
   473
	{
skamonkey@3333
   474
		v = (Vector *)((intptr_t)g_pGameRules + offset);
skamonkey@3333
   475
		v->x = sp_ctof(vec[0]);
skamonkey@3333
   476
		v->y = sp_ctof(vec[1]);
skamonkey@3333
   477
		v->z = sp_ctof(vec[2]);
skamonkey@3333
   478
skamonkey@3333
   479
		gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
skamonkey@3333
   480
	}
skamonkey@3333
   481
skamonkey@3333
   482
	return 1;
skamonkey@3333
   483
}
skamonkey@3333
   484
skamonkey@3333
   485
static cell_t GameRules_GetPropString(IPluginContext *pContext, const cell_t *params)
skamonkey@3333
   486
{
skamonkey@3333
   487
	char *prop;
skamonkey@3333
   488
	int offset;
skamonkey@3333
   489
skamonkey@3333
   490
	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
skamonkey@3333
   491
		return pContext->ThrowNativeError("Gamerules lookup failed.");
skamonkey@3333
   492
skamonkey@3333
   493
	pContext->LocalToString(params[1], &prop);
skamonkey@3333
   494
skamonkey@3333
   495
	sm_sendprop_info_t info;
skamonkey@3333
   496
	if (!gamehelpers->FindSendPropInfo(g_szGameRulesProxy, prop, &info))
skamonkey@3333
   497
	{
skamonkey@3333
   498
		return pContext->ThrowNativeError("Property \"%s\" not found on the gamerules proxy", prop);
skamonkey@3333
   499
	}
skamonkey@3333
   500
	
skamonkey@3333
   501
	offset = info.actual_offset;
skamonkey@3333
   502
	
skamonkey@3333
   503
	if (info.prop->GetType() != DPT_String)
skamonkey@3333
   504
	{
skamonkey@3333
   505
		return pContext->ThrowNativeError("SendProp %s type is not a string (%d != %d)",
skamonkey@3333
   506
				prop,
skamonkey@3333
   507
				info.prop->GetType(),
skamonkey@3333
   508
				DPT_String);
skamonkey@3333
   509
	}
skamonkey@3333
   510
skamonkey@3333
   511
	void *pGameRules = *g_pGameRules;
skamonkey@3333
   512
skamonkey@3333
   513
	size_t len;
skamonkey@3333
   514
	const char *src;
skamonkey@3333
   515
skamonkey@3333
   516
	src = (char *)((intptr_t)pGameRules + offset);
skamonkey@3333
   517
skamonkey@3333
   518
	pContext->StringToLocalUTF8(params[2], params[3], src, &len);
skamonkey@3333
   519
skamonkey@3333
   520
	return len;
skamonkey@3333
   521
}
skamonkey@3333
   522
skamonkey@3333
   523
// From sm_stringutil
skamonkey@3333
   524
inline int strncopy(char *dest, const char *src, size_t count)
skamonkey@3333
   525
{
skamonkey@3333
   526
	if (!count)
skamonkey@3333
   527
	{
skamonkey@3333
   528
		return 0;
skamonkey@3333
   529
	}
skamonkey@3333
   530
skamonkey@3333
   531
	char *start = dest;
skamonkey@3333
   532
	while ((*src) && (--count))
skamonkey@3333
   533
	{
skamonkey@3333
   534
		*dest++ = *src++;
skamonkey@3333
   535
	}
skamonkey@3333
   536
	*dest = '\0';
skamonkey@3333
   537
skamonkey@3333
   538
	return (dest - start);
skamonkey@3333
   539
}
skamonkey@3333
   540
//
skamonkey@3333
   541
skamonkey@3333
   542
static cell_t GameRules_SetPropString(IPluginContext *pContext, const cell_t *params)
skamonkey@3333
   543
{
skamonkey@3333
   544
	char *prop;
skamonkey@3333
   545
	int offset;
skamonkey@3333
   546
	int maxlen;
skamonkey@3333
   547
skamonkey@3333
   548
	bool sendChange = true;
skamonkey@3333
   549
	if (params[3] == 0)
skamonkey@3333
   550
		sendChange = false;
skamonkey@3333
   551
skamonkey@3333
   552
	CBaseEntity *pProxy = NULL;
skamonkey@3333
   553
	if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
skamonkey@3333
   554
		return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
skamonkey@3333
   555
	
skamonkey@3333
   556
	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
skamonkey@3333
   557
		return pContext->ThrowNativeError("Gamerules lookup failed.");
skamonkey@3333
   558
skamonkey@3333
   559
	pContext->LocalToString(params[1], &prop);
skamonkey@3333
   560
skamonkey@3333
   561
	sm_sendprop_info_t info;
skamonkey@3333
   562
	if (!gamehelpers->FindSendPropInfo(g_szGameRulesProxy, prop, &info))
skamonkey@3333
   563
	{
skamonkey@3333
   564
		return pContext->ThrowNativeError("Property \"%s\" not found on the gamerules proxy", prop);
skamonkey@3333
   565
	}
skamonkey@3333
   566
	
skamonkey@3333
   567
	offset = info.actual_offset;
skamonkey@3333
   568
	
skamonkey@3333
   569
	if (info.prop->GetType() != DPT_String)
skamonkey@3333
   570
	{
skamonkey@3333
   571
		return pContext->ThrowNativeError("SendProp %s type is not a string (%d != %d)",
skamonkey@3333
   572
				prop,
skamonkey@3333
   573
				info.prop->GetType(),
skamonkey@3333
   574
				DPT_String);
skamonkey@3333
   575
	}
skamonkey@3333
   576
skamonkey@3333
   577
	void *pGameRules = *g_pGameRules;
skamonkey@3333
   578
	maxlen = DT_MAX_STRING_BUFFERSIZE;
skamonkey@3333
   579
skamonkey@3333
   580
	char *src;
skamonkey@3333
   581
	char *dest = (char *)((intptr_t)pGameRules + offset);
skamonkey@3333
   582
skamonkey@3333
   583
	pContext->LocalToString(params[2], &src);
skamonkey@3333
   584
	size_t len = strncopy(dest, src, maxlen);
skamonkey@3333
   585
skamonkey@3333
   586
	if (sendChange)
skamonkey@3333
   587
	{
skamonkey@3333
   588
		dest = (char *)((intptr_t)pProxy + offset);
skamonkey@3333
   589
		strncopy(dest, src, maxlen);
skamonkey@3333
   590
		gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
skamonkey@3333
   591
	}
skamonkey@3333
   592
skamonkey@3333
   593
	return len;
skamonkey@3333
   594
}
skamonkey@3333
   595
skamonkey@3333
   596
sp_nativeinfo_t g_GameRulesNatives[] = 
skamonkey@3333
   597
{
skamonkey@3333
   598
	{"GameRules_GetProp",			GameRules_GetProp},
skamonkey@3333
   599
	{"GameRules_SetProp",			GameRules_SetProp},
skamonkey@3333
   600
	{"GameRules_GetPropFloat",		GameRules_GetPropFloat},
skamonkey@3333
   601
	{"GameRules_SetPropFloat",		GameRules_SetPropFloat},
skamonkey@3333
   602
	{"GameRules_GetPropEnt",		GameRules_GetPropEnt},
skamonkey@3333
   603
	{"GameRules_SetPropEnt",		GameRules_SetPropEnt},
skamonkey@3333
   604
	{"GameRules_GetPropVector",		GameRules_GetPropVector},
skamonkey@3333
   605
	{"GameRules_SetPropVector",		GameRules_SetPropVector},
skamonkey@3333
   606
	{"GameRules_GetPropString",		GameRules_GetPropString},
skamonkey@3333
   607
	{"GameRules_SetPropString",		GameRules_SetPropString},
skamonkey@3333
   608
	{NULL,							NULL},
skamonkey@3333
   609
};