core/smn_entities.cpp
author David Anderson <dvander@alliedmods.net>
Sun Oct 14 17:55:02 2007 +0000 (2007-10-14)
changeset 1545 4ceff5fa5fdd
parent 1471 dac1c6d68abd
child 1847 5336a438763f
permissions -rw-r--r--
fixed compat wrappers including core stuff
dvander@555
     1
/**
ds@653
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@555
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@555
    28
 *
dvander@555
    29
 * Version: $Id$
dvander@555
    30
 */
dvander@555
    31
dvander@555
    32
#include "sm_globals.h"
dvander@555
    33
#include "sourcemod.h"
dvander@555
    34
#include "sourcemm_api.h"
dvander@556
    35
#include "server_class.h"
dvander@591
    36
#include "PlayerManager.h"
dvander@592
    37
#include "HalfLife2.h"
faluco@682
    38
#include "GameConfigs.h"
faluco@694
    39
#include "sm_stringutil.h"
faluco@694
    40
faluco@694
    41
enum PropType
faluco@694
    42
{
faluco@694
    43
	Prop_Send = 0,
faluco@694
    44
	Prop_Data
faluco@694
    45
};
dvander@555
    46
dvander@555
    47
inline edict_t *GetEdict(cell_t num)
dvander@555
    48
{
dvander@555
    49
	edict_t *pEdict = engine->PEntityOfEntIndex(num);
dvander@555
    50
	if (!pEdict || pEdict->IsFree())
dvander@555
    51
	{
dvander@555
    52
		return NULL;
dvander@555
    53
	}
dvander@1471
    54
	if (num > 0 && num <= g_Players.GetMaxClients())
dvander@556
    55
	{
dvander@556
    56
		CPlayer *pPlayer = g_Players.GetPlayerByIndex(num);
dvander@556
    57
		if (!pPlayer || !pPlayer->IsConnected())
dvander@556
    58
		{
dvander@556
    59
			return NULL;
dvander@556
    60
		}
dvander@556
    61
	}
dvander@555
    62
	return pEdict;
dvander@555
    63
}
dvander@555
    64
dvander@557
    65
inline edict_t *GetEntity(cell_t num, CBaseEntity **pData)
dvander@557
    66
{
dvander@557
    67
	edict_t *pEdict = engine->PEntityOfEntIndex(num);
dvander@557
    68
	if (!pEdict || pEdict->IsFree())
dvander@557
    69
	{
dvander@557
    70
		return NULL;
dvander@557
    71
	}
dvander@1471
    72
	if (num > 0 && num <= g_Players.GetMaxClients())
dvander@557
    73
	{
dvander@557
    74
		CPlayer *pPlayer = g_Players.GetPlayerByIndex(num);
dvander@557
    75
		if (!pPlayer || !pPlayer->IsConnected())
dvander@557
    76
		{
dvander@557
    77
			return NULL;
dvander@557
    78
		}
dvander@557
    79
	}
dvander@557
    80
	IServerUnknown *pUnk;
dvander@557
    81
	if ((pUnk=pEdict->GetUnknown()) == NULL)
dvander@557
    82
	{
dvander@557
    83
		return NULL;
dvander@557
    84
	}
dvander@557
    85
	*pData = pUnk->GetBaseEntity();
dvander@557
    86
	return pEdict;
dvander@557
    87
}
dvander@557
    88
faluco@682
    89
class VEmptyClass {};
faluco@682
    90
datamap_t *VGetDataDescMap(CBaseEntity *pThisPtr, int offset)
faluco@682
    91
{
faluco@682
    92
	void **this_ptr = *reinterpret_cast<void ***>(&pThisPtr);
faluco@682
    93
	void **vtable = *reinterpret_cast<void ***>(pThisPtr);
faluco@682
    94
	void *vfunc = vtable[offset];
faluco@682
    95
faluco@682
    96
	union
faluco@682
    97
	{
faluco@682
    98
		datamap_t *(VEmptyClass::*mfpnew)();
faluco@682
    99
#ifndef PLATFORM_POSIX
faluco@682
   100
		void *addr;
faluco@682
   101
	} u;
faluco@682
   102
	u.addr = vfunc;
faluco@682
   103
#else
faluco@682
   104
		struct  
faluco@682
   105
		{
faluco@682
   106
			void *addr;
faluco@682
   107
			intptr_t adjustor;
faluco@682
   108
		} s;
faluco@682
   109
	} u;
faluco@682
   110
	u.s.addr = vfunc;
faluco@682
   111
	u.s.adjustor = 0;
faluco@682
   112
#endif
faluco@682
   113
faluco@682
   114
	return (datamap_t *)(reinterpret_cast<VEmptyClass *>(this_ptr)->*u.mfpnew)();
faluco@682
   115
}
faluco@682
   116
faluco@682
   117
inline datamap_t *CBaseEntity_GetDataDescMap(CBaseEntity *pEntity)
faluco@682
   118
{
faluco@682
   119
	int offset;
faluco@682
   120
faluco@682
   121
	if (!g_pGameConf->GetOffset("GetDataDescMap", &offset) || !offset)
faluco@682
   122
	{
faluco@682
   123
		return NULL;
faluco@682
   124
	}
faluco@682
   125
faluco@682
   126
	return VGetDataDescMap(pEntity, offset);
faluco@682
   127
}
faluco@682
   128
dvander@965
   129
/* :TODO: Move this! */
dvander@965
   130
datamap_t *CHalfLife2::GetDataMap(CBaseEntity *pEntity)
dvander@965
   131
{
dvander@965
   132
	return CBaseEntity_GetDataDescMap(pEntity);
dvander@965
   133
}
dvander@965
   134
dvander@555
   135
static cell_t GetMaxEntities(IPluginContext *pContext, const cell_t *params)
dvander@555
   136
{
dvander@555
   137
	return gpGlobals->maxEntities;
dvander@555
   138
}
dvander@555
   139
dvander@555
   140
static cell_t CreateEdict(IPluginContext *pContext, const cell_t *params)
dvander@555
   141
{
dvander@555
   142
	edict_t *pEdict = engine->CreateEdict();
dvander@555
   143
dvander@555
   144
	if (!pEdict)
dvander@555
   145
	{
dvander@555
   146
		return 0;
dvander@555
   147
	}
dvander@555
   148
dvander@555
   149
	return engine->IndexOfEdict(pEdict);
dvander@555
   150
}
dvander@555
   151
dvander@555
   152
static cell_t RemoveEdict(IPluginContext *pContext, const cell_t *params)
dvander@555
   153
{
dvander@555
   154
	edict_t *pEdict = engine->PEntityOfEntIndex(params[1]);
dvander@555
   155
dvander@555
   156
	if (!pEdict)
dvander@555
   157
	{
dvander@555
   158
		return pContext->ThrowNativeError("Edict %d is not a valid edict", params[1]);
dvander@555
   159
	}
dvander@555
   160
dvander@555
   161
	engine->RemoveEdict(pEdict);
dvander@555
   162
dvander@555
   163
	return 1;
dvander@555
   164
}
dvander@555
   165
dvander@555
   166
static cell_t IsValidEdict(IPluginContext *pContext, const cell_t *params)
dvander@555
   167
{
dvander@556
   168
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   169
dvander@555
   170
	if (!pEdict)
dvander@555
   171
	{
dvander@555
   172
		return 0;
dvander@555
   173
	}
dvander@555
   174
dvander@555
   175
	/* Shouldn't be necessary... not sure though */
dvander@555
   176
	return pEdict->IsFree() ? 0 : 1;
dvander@555
   177
}
dvander@555
   178
dvander@555
   179
static cell_t IsValidEntity(IPluginContext *pContext, const cell_t *params)
dvander@555
   180
{
dvander@556
   181
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   182
dvander@556
   183
	if (!pEdict)
dvander@555
   184
	{
dvander@555
   185
		return 0;
dvander@555
   186
	}
dvander@555
   187
dvander@555
   188
	IServerUnknown *pUnknown = pEdict->GetUnknown();
dvander@555
   189
	if (!pUnknown)
dvander@555
   190
	{
dvander@555
   191
		return 0;
dvander@555
   192
	}
dvander@555
   193
dvander@555
   194
	CBaseEntity *pEntity = pUnknown->GetBaseEntity();
dvander@555
   195
	return (pEntity != NULL) ? 1 : 0;
dvander@555
   196
}
dvander@555
   197
dvander@555
   198
static cell_t IsEntNetworkable(IPluginContext *pContext, const cell_t *params)
dvander@555
   199
{
dvander@556
   200
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   201
dvander@556
   202
	if (!pEdict)
dvander@555
   203
	{
dvander@555
   204
		return 0;
dvander@555
   205
	}
dvander@555
   206
dvander@555
   207
	return (pEdict->GetNetworkable() != NULL) ? 1 : 0;
dvander@555
   208
}
dvander@555
   209
dvander@555
   210
static cell_t GetEntityCount(IPluginContext *pContext, const cell_t *params)
dvander@555
   211
{
dvander@555
   212
	return engine->GetEntityCount();
dvander@555
   213
}
dvander@555
   214
dvander@555
   215
static cell_t GetEdictFlags(IPluginContext *pContext, const cell_t *params)
dvander@555
   216
{
dvander@555
   217
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   218
dvander@555
   219
	if (!pEdict)
dvander@555
   220
	{
dvander@555
   221
		return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
dvander@555
   222
	}
dvander@555
   223
dvander@555
   224
	return pEdict->m_fStateFlags;
dvander@555
   225
}
dvander@555
   226
dvander@555
   227
static cell_t SetEdictFlags(IPluginContext *pContext, const cell_t *params)
dvander@555
   228
{
dvander@555
   229
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   230
dvander@555
   231
	if (!pEdict)
dvander@555
   232
	{
dvander@555
   233
		return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
dvander@555
   234
	}
dvander@555
   235
dvander@555
   236
	pEdict->m_fStateFlags = params[2];
dvander@555
   237
dvander@555
   238
	return 1;
dvander@555
   239
}
dvander@555
   240
dvander@556
   241
static cell_t GetEdictClassname(IPluginContext *pContext, const cell_t *params)
dvander@556
   242
{
dvander@556
   243
	edict_t *pEdict = GetEdict(params[1]);
dvander@556
   244
dvander@556
   245
	if (!pEdict)
dvander@556
   246
	{
dvander@556
   247
		return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
dvander@556
   248
	}
dvander@556
   249
dvander@556
   250
	const char *cls = pEdict->GetClassName();
dvander@556
   251
dvander@556
   252
	if (!cls || cls[0] == '\0')
dvander@556
   253
	{
dvander@556
   254
		return 0;
dvander@556
   255
	}
dvander@556
   256
dvander@556
   257
	pContext->StringToLocal(params[2], params[3], cls);
dvander@556
   258
dvander@556
   259
	return 1;
dvander@556
   260
}
dvander@556
   261
dvander@556
   262
static cell_t GetEntityNetClass(IPluginContext *pContext, const cell_t *params)
dvander@556
   263
{
dvander@556
   264
	edict_t *pEdict = GetEdict(params[1]);
dvander@556
   265
dvander@556
   266
	if (!pEdict)
dvander@556
   267
	{
dvander@556
   268
		return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
dvander@556
   269
	}
dvander@556
   270
dvander@556
   271
	IServerNetworkable *pNet = pEdict->GetNetworkable();
dvander@556
   272
	if (!pNet)
dvander@556
   273
	{
dvander@556
   274
		return 0;
dvander@556
   275
	}
dvander@556
   276
dvander@556
   277
	ServerClass *pClass = pNet->GetServerClass();
dvander@556
   278
dvander@556
   279
	pContext->StringToLocal(params[2], params[3], pClass->GetName());
dvander@556
   280
dvander@556
   281
	return 1;
dvander@556
   282
}
dvander@556
   283
dvander@557
   284
static cell_t GetEntData(IPluginContext *pContext, const cell_t *params)
dvander@557
   285
{
dvander@557
   286
	CBaseEntity *pEntity;
dvander@557
   287
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   288
dvander@557
   289
	if (!pEdict || !pEntity)
dvander@557
   290
	{
dvander@557
   291
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   292
	}
dvander@557
   293
dvander@557
   294
	int offset = params[2];
dvander@557
   295
	if (offset < 0 || offset > 32768)
dvander@557
   296
	{
dvander@557
   297
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   298
	}
dvander@557
   299
dvander@557
   300
	switch (params[3])
dvander@557
   301
	{
dvander@557
   302
	case 4:
dvander@557
   303
		return *(int *)((uint8_t *)pEntity + offset);
dvander@557
   304
	case 2:
dvander@557
   305
		return *(short *)((uint8_t *)pEntity + offset);
dvander@557
   306
	case 1:
dvander@557
   307
		return *((uint8_t *)pEntity + offset);
dvander@557
   308
	default:
dvander@557
   309
		return pContext->ThrowNativeError("Integer size %d is invalid", params[3]);
dvander@557
   310
	}
dvander@557
   311
}
dvander@557
   312
dvander@557
   313
static cell_t SetEntData(IPluginContext *pContext, const cell_t *params)
dvander@557
   314
{
dvander@557
   315
	CBaseEntity *pEntity;
dvander@557
   316
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   317
dvander@557
   318
	if (!pEdict || !pEntity)
dvander@557
   319
	{
dvander@557
   320
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   321
	}
dvander@557
   322
dvander@557
   323
	int offset = params[2];
dvander@557
   324
	if (offset < 0 || offset > 32768)
dvander@557
   325
	{
dvander@557
   326
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   327
	}
dvander@557
   328
dvander@561
   329
	if (params[5])
dvander@561
   330
	{
dvander@685
   331
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   332
	}
dvander@561
   333
dvander@557
   334
	switch (params[4])
dvander@557
   335
	{
dvander@557
   336
	case 4:
dvander@557
   337
		{
dvander@557
   338
			*(int *)((uint8_t *)pEntity + offset) = params[3];
dvander@557
   339
			break;
dvander@557
   340
		}
dvander@557
   341
	case 2:
dvander@557
   342
		{
dvander@557
   343
			*(short *)((uint8_t *)pEntity + offset) = params[3];
dvander@557
   344
			break;
dvander@557
   345
		}
dvander@557
   346
	case 1:
dvander@557
   347
		{
dvander@557
   348
			*((uint8_t *)pEntity + offset) = params[3];
dvander@557
   349
			break;
dvander@557
   350
		}
dvander@557
   351
	default:
dvander@557
   352
		return pContext->ThrowNativeError("Integer size %d is invalid", params[4]);
dvander@557
   353
	}
dvander@557
   354
dvander@557
   355
	return 1;
dvander@557
   356
}
dvander@557
   357
dvander@557
   358
static cell_t GetEntDataFloat(IPluginContext *pContext, const cell_t *params)
dvander@557
   359
{
dvander@557
   360
	CBaseEntity *pEntity;
dvander@557
   361
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   362
dvander@557
   363
	if (!pEdict || !pEntity)
dvander@557
   364
	{
dvander@557
   365
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   366
	}
dvander@557
   367
dvander@557
   368
	int offset = params[2];
dvander@557
   369
	if (offset < 0 || offset > 32768)
dvander@557
   370
	{
dvander@557
   371
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   372
	}
dvander@557
   373
dvander@557
   374
	float f = *(float *)((uint8_t *)pEntity + offset);
dvander@557
   375
dvander@557
   376
	return sp_ftoc(f);
dvander@557
   377
}
dvander@557
   378
dvander@557
   379
static cell_t SetEntDataFloat(IPluginContext *pContext, const cell_t *params)
dvander@557
   380
{
dvander@557
   381
	CBaseEntity *pEntity;
dvander@557
   382
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   383
dvander@557
   384
	if (!pEdict || !pEntity)
dvander@557
   385
	{
dvander@557
   386
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   387
	}
dvander@557
   388
dvander@557
   389
	int offset = params[2];
dvander@557
   390
	if (offset < 0 || offset > 32768)
dvander@557
   391
	{
dvander@557
   392
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   393
	}
dvander@557
   394
dvander@557
   395
	*(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[3]);
dvander@557
   396
dvander@561
   397
	if (params[4])
dvander@561
   398
	{
dvander@685
   399
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   400
	}
dvander@561
   401
dvander@557
   402
	return 1;
dvander@557
   403
}
dvander@557
   404
dvander@557
   405
static cell_t GetEntDataVector(IPluginContext *pContext, const cell_t *params)
dvander@557
   406
{
dvander@557
   407
	CBaseEntity *pEntity;
dvander@557
   408
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   409
dvander@557
   410
	if (!pEdict || !pEntity)
dvander@557
   411
	{
dvander@557
   412
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   413
	}
dvander@557
   414
dvander@557
   415
	int offset = params[2];
dvander@557
   416
	if (offset < 0 || offset > 32768)
dvander@557
   417
	{
dvander@557
   418
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   419
	}
dvander@557
   420
dvander@557
   421
	Vector *v = (Vector *)((uint8_t *)pEntity + offset);
dvander@557
   422
dvander@557
   423
	cell_t *vec;
dvander@557
   424
	pContext->LocalToPhysAddr(params[3], &vec);
dvander@557
   425
faluco@597
   426
	vec[0] = sp_ftoc(v->x);
faluco@597
   427
	vec[1] = sp_ftoc(v->y);
faluco@597
   428
	vec[2] = sp_ftoc(v->z);
dvander@557
   429
dvander@557
   430
	return 1;
dvander@557
   431
}
dvander@557
   432
dvander@557
   433
static cell_t SetEntDataVector(IPluginContext *pContext, const cell_t *params)
dvander@557
   434
{
dvander@557
   435
	CBaseEntity *pEntity;
dvander@557
   436
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   437
dvander@557
   438
	if (!pEdict || !pEntity)
dvander@557
   439
	{
dvander@557
   440
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   441
	}
dvander@557
   442
dvander@557
   443
	int offset = params[2];
dvander@557
   444
	if (offset < 0 || offset > 32768)
dvander@557
   445
	{
dvander@557
   446
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   447
	}
dvander@557
   448
dvander@557
   449
	Vector *v = (Vector *)((uint8_t *)pEntity + offset);
dvander@557
   450
dvander@557
   451
	cell_t *vec;
dvander@557
   452
	pContext->LocalToPhysAddr(params[3], &vec);
dvander@557
   453
faluco@597
   454
	v->x = sp_ctof(vec[0]);
faluco@597
   455
	v->y = sp_ctof(vec[1]);
faluco@597
   456
	v->z = sp_ctof(vec[2]);
dvander@557
   457
dvander@561
   458
	if (params[4])
dvander@561
   459
	{
dvander@685
   460
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   461
	}
dvander@561
   462
dvander@557
   463
	return 1;
dvander@557
   464
}
dvander@557
   465
dvander@557
   466
static cell_t GetEntDataEnt(IPluginContext *pContext, const cell_t *params)
dvander@557
   467
{
dvander@557
   468
	CBaseEntity *pEntity;
dvander@557
   469
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   470
dvander@557
   471
	if (!pEdict || !pEntity)
dvander@557
   472
	{
dvander@557
   473
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   474
	}
dvander@557
   475
dvander@557
   476
	int offset = params[2];
dvander@557
   477
	if (offset < 0 || offset > 32768)
dvander@557
   478
	{
dvander@557
   479
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   480
	}
dvander@557
   481
dvander@557
   482
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
dvander@557
   483
dvander@557
   484
	if (!hndl.IsValid())
dvander@557
   485
	{
dvander@557
   486
		return 0;
dvander@557
   487
	}
dvander@557
   488
dvander@557
   489
	/* :TODO: check serial no.? */
dvander@557
   490
dvander@557
   491
	return hndl.GetEntryIndex();
dvander@557
   492
}
dvander@557
   493
dvander@557
   494
static cell_t SetEntDataEnt(IPluginContext *pContext, const cell_t *params)
dvander@557
   495
{
dvander@557
   496
	CBaseEntity *pEntity;
dvander@557
   497
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   498
dvander@557
   499
	if (!pEdict || !pEntity)
dvander@557
   500
	{
dvander@557
   501
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   502
	}
dvander@557
   503
dvander@557
   504
	int offset = params[2];
dvander@557
   505
	if (offset < 0 || offset > 32768)
dvander@557
   506
	{
dvander@557
   507
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   508
	}
dvander@557
   509
dvander@557
   510
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
dvander@557
   511
dvander@557
   512
	if (params[3] == 0)
dvander@557
   513
	{
dvander@557
   514
		hndl.Set(NULL);
dvander@557
   515
	} else {
dvander@557
   516
		edict_t *pEdict = GetEdict(params[3]);
dvander@557
   517
		if (!pEdict)
dvander@557
   518
		{
dvander@557
   519
			return pContext->ThrowNativeError("Entity %d is invalid", params[3]);
dvander@557
   520
		}
dvander@557
   521
		IServerEntity *pEntOther = pEdict->GetIServerEntity();
dvander@557
   522
		hndl.Set(pEntOther);
dvander@557
   523
	}
dvander@557
   524
dvander@561
   525
	if (params[4])
dvander@561
   526
	{
dvander@685
   527
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   528
	}
dvander@561
   529
dvander@557
   530
	return 1;
dvander@557
   531
}
dvander@557
   532
dvander@558
   533
static cell_t ChangeEdictState(IPluginContext *pContext, const cell_t *params)
dvander@558
   534
{
dvander@558
   535
	edict_t *pEdict = GetEdict(params[1]);
dvander@558
   536
dvander@558
   537
	if (!pEdict)
dvander@558
   538
	{
dvander@558
   539
		return pContext->ThrowNativeError("Edict %d is invalid", params[1]);
dvander@558
   540
	}
dvander@558
   541
dvander@685
   542
	g_HL2.SetEdictStateChanged(pEdict, params[2]);
dvander@558
   543
dvander@558
   544
	return 1;
dvander@558
   545
}
dvander@558
   546
dvander@561
   547
static cell_t FindSendPropOffs(IPluginContext *pContext, const cell_t *params)
dvander@561
   548
{
dvander@561
   549
	char *cls, *prop;
dvander@561
   550
	pContext->LocalToString(params[1], &cls);
dvander@561
   551
	pContext->LocalToString(params[2], &prop);
dvander@561
   552
dvander@561
   553
	SendProp *pSend = g_HL2.FindInSendTable(cls, prop);
dvander@561
   554
dvander@561
   555
	if (!pSend)
dvander@561
   556
	{
dvander@561
   557
		return -1;
dvander@561
   558
	}
dvander@561
   559
dvander@561
   560
	return pSend->GetOffset();
dvander@561
   561
}
dvander@561
   562
faluco@682
   563
static cell_t FindDataMapOffs(IPluginContext *pContext, const cell_t *params)
faluco@682
   564
{
faluco@682
   565
	CBaseEntity *pEntity;
faluco@682
   566
	datamap_t *pMap;
faluco@682
   567
	typedescription_t *td;
faluco@682
   568
	char *offset;
faluco@682
   569
	edict_t *pEdict = GetEntity(params[1], &pEntity);
faluco@682
   570
faluco@682
   571
	if (!pEdict || !pEntity)
faluco@682
   572
	{
faluco@682
   573
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
faluco@682
   574
	}
faluco@682
   575
faluco@682
   576
	if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
faluco@682
   577
	{
faluco@682
   578
		return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
faluco@682
   579
	}
faluco@682
   580
faluco@682
   581
	pContext->LocalToString(params[2], &offset);
faluco@682
   582
	if ((td=g_HL2.FindInDataMap(pMap, offset)) == NULL)
faluco@682
   583
	{
faluco@682
   584
		return -1;
faluco@682
   585
	}
faluco@682
   586
faluco@682
   587
	return td->fieldOffset[TD_OFFSET_NORMAL];
faluco@682
   588
}
faluco@682
   589
faluco@694
   590
static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params)
faluco@694
   591
{
faluco@694
   592
	CBaseEntity *pEntity;
faluco@694
   593
	edict_t *pEdict = GetEntity(params[1], &pEntity);
faluco@694
   594
faluco@694
   595
	if (!pEdict || !pEntity)
faluco@694
   596
	{
faluco@694
   597
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
faluco@694
   598
	}
faluco@694
   599
faluco@694
   600
	int offset = params[2];
faluco@694
   601
	if (offset < 0 || offset > 32768)
faluco@694
   602
	{
faluco@694
   603
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
faluco@694
   604
	}
faluco@694
   605
faluco@694
   606
	size_t len;
faluco@694
   607
	char *src = (char *)((uint8_t *)pEntity + offset);
faluco@694
   608
	pContext->StringToLocalUTF8(params[3], params[4], src, &len);
faluco@694
   609
faluco@694
   610
	return len;
faluco@694
   611
}
faluco@694
   612
faluco@694
   613
static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params)
faluco@694
   614
{
faluco@694
   615
	CBaseEntity *pEntity;
faluco@694
   616
	edict_t *pEdict = GetEntity(params[1], &pEntity);
faluco@694
   617
faluco@694
   618
	if (!pEdict || !pEntity)
faluco@694
   619
	{
faluco@694
   620
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
faluco@694
   621
	}
faluco@694
   622
faluco@694
   623
	int offset = params[2];
faluco@694
   624
	if (offset < 0 || offset > 32768)
faluco@694
   625
	{
faluco@694
   626
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
faluco@694
   627
	}
faluco@694
   628
faluco@694
   629
	char *src;
faluco@694
   630
	char *dest = (char *)((uint8_t *)pEntity + offset);
faluco@694
   631
faluco@694
   632
	pContext->LocalToString(params[3], &src);
faluco@694
   633
	size_t len = strncopy(dest, src, params[4]);
faluco@694
   634
faluco@694
   635
	if (params[5])
faluco@694
   636
	{
faluco@694
   637
		g_HL2.SetEdictStateChanged(pEdict, offset);
faluco@694
   638
	}
faluco@694
   639
faluco@694
   640
	return len;
faluco@694
   641
}
faluco@694
   642
faluco@694
   643
static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params)
faluco@694
   644
{
faluco@694
   645
	CBaseEntity *pEntity;
faluco@694
   646
	char *prop;
faluco@694
   647
	int offset;
faluco@694
   648
	edict_t *pEdict = GetEntity(params[1], &pEntity);
faluco@694
   649
faluco@694
   650
	if (!pEdict || !pEntity)
faluco@694
   651
	{
faluco@694
   652
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
faluco@694
   653
	}
faluco@694
   654
faluco@694
   655
	switch (params[2])
faluco@694
   656
	{
faluco@694
   657
	case Prop_Data:
faluco@694
   658
		{
faluco@694
   659
			datamap_t *pMap;
faluco@694
   660
			typedescription_t *td;
faluco@694
   661
			if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
faluco@694
   662
			{
faluco@694
   663
				return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
faluco@694
   664
			}
faluco@694
   665
			pContext->LocalToString(params[3], &prop);
faluco@694
   666
			if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
faluco@694
   667
			{
faluco@694
   668
				return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
faluco@694
   669
			}
faluco@694
   670
			if (td->fieldType != FIELD_CHARACTER)
faluco@694
   671
			{
faluco@694
   672
				return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
faluco@694
   673
			}
faluco@694
   674
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
faluco@694
   675
			break;
faluco@694
   676
		}
faluco@694
   677
	case Prop_Send:
faluco@694
   678
		{
faluco@694
   679
			char *prop;
faluco@694
   680
			IServerNetworkable *pNet = pEdict->GetNetworkable();
faluco@694
   681
			if (!pNet)
faluco@694
   682
			{
faluco@694
   683
				return pContext->ThrowNativeError("The edict is not networkable");
faluco@694
   684
			}
faluco@694
   685
			pContext->LocalToString(params[3], &prop);
faluco@694
   686
			SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
faluco@694
   687
			if (!pSend)
faluco@694
   688
			{
faluco@694
   689
				return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
faluco@694
   690
			}
faluco@694
   691
			if (pSend->GetType() != DPT_String)
faluco@694
   692
			{
faluco@694
   693
				return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
faluco@694
   694
			}
faluco@694
   695
			offset = pSend->GetOffset();
faluco@694
   696
			break;
faluco@694
   697
		}
faluco@694
   698
	default:
faluco@694
   699
		{
faluco@694
   700
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
faluco@694
   701
		}
faluco@694
   702
	}
faluco@694
   703
faluco@694
   704
	size_t len;
faluco@694
   705
	char *src = (char *)((uint8_t *)pEntity + offset);
faluco@694
   706
	pContext->StringToLocalUTF8(params[4], params[5], src, &len);
faluco@694
   707
faluco@694
   708
	return len;
faluco@694
   709
}
faluco@694
   710
faluco@694
   711
static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params)
faluco@694
   712
{
faluco@694
   713
	CBaseEntity *pEntity;
faluco@694
   714
	char *prop;
faluco@694
   715
	int offset;
faluco@694
   716
	int maxlen;
faluco@694
   717
	bool is_sendprop = false;
faluco@694
   718
	edict_t *pEdict = GetEntity(params[1], &pEntity);
faluco@694
   719
faluco@694
   720
	if (!pEdict || !pEntity)
faluco@694
   721
	{
faluco@694
   722
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
faluco@694
   723
	}
faluco@694
   724
faluco@694
   725
	switch (params[2])
faluco@694
   726
	{
faluco@694
   727
	case Prop_Data:
faluco@694
   728
		{
faluco@694
   729
			datamap_t *pMap;
faluco@694
   730
			typedescription_t *td;
faluco@694
   731
			if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
faluco@694
   732
			{
faluco@694
   733
				return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
faluco@694
   734
			}
faluco@694
   735
			pContext->LocalToString(params[3], &prop);
faluco@694
   736
			if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
faluco@694
   737
			{
faluco@694
   738
				return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
faluco@694
   739
			}
faluco@694
   740
			if (td->fieldType != FIELD_CHARACTER)
faluco@694
   741
			{
faluco@694
   742
				return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
faluco@694
   743
			}
faluco@694
   744
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
faluco@694
   745
			maxlen = td->fieldSize;
faluco@694
   746
			break;
faluco@694
   747
		}
faluco@694
   748
	case Prop_Send:
faluco@694
   749
		{
faluco@694
   750
			char *prop;
faluco@694
   751
			IServerNetworkable *pNet = pEdict->GetNetworkable();
faluco@694
   752
			if (!pNet)
faluco@694
   753
			{
faluco@694
   754
				return pContext->ThrowNativeError("The edict is not networkable");
faluco@694
   755
			}
faluco@694
   756
			pContext->LocalToString(params[3], &prop);
faluco@694
   757
			SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
faluco@694
   758
			if (!pSend)
faluco@694
   759
			{
faluco@694
   760
				return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
faluco@694
   761
			}
faluco@694
   762
			if (pSend->GetType() != DPT_String)
faluco@694
   763
			{
faluco@694
   764
				return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
faluco@694
   765
			}
faluco@694
   766
			offset = pSend->GetOffset();
faluco@694
   767
			maxlen = DT_MAX_STRING_BUFFERSIZE;
faluco@694
   768
			is_sendprop = true;
faluco@694
   769
			break;
faluco@694
   770
		}
faluco@694
   771
	default:
faluco@694
   772
		{
faluco@694
   773
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
faluco@694
   774
		}
faluco@694
   775
	}
faluco@694
   776
faluco@694
   777
	char *src;
faluco@694
   778
	char *dest = (char *)((uint8_t *)pEntity + offset);
faluco@694
   779
faluco@694
   780
	pContext->LocalToString(params[4], &src);
faluco@694
   781
	size_t len = strncopy(dest, src, maxlen);
faluco@694
   782
faluco@694
   783
	if (is_sendprop)
faluco@694
   784
	{
faluco@694
   785
		g_HL2.SetEdictStateChanged(pEdict, offset);
faluco@694
   786
	}
faluco@694
   787
faluco@694
   788
	return len;
faluco@694
   789
}
faluco@694
   790
dvander@555
   791
REGISTER_NATIVES(entityNatives)
dvander@555
   792
{
dvander@558
   793
	{"ChangeEdictState",		ChangeEdictState},
dvander@555
   794
	{"CreateEdict",				CreateEdict},
dvander@561
   795
	{"FindSendPropOffs",		FindSendPropOffs},
dvander@556
   796
	{"GetEdictClassname",		GetEdictClassname},
dvander@555
   797
	{"GetEdictFlags",			GetEdictFlags},
dvander@557
   798
	{"GetEntData",				GetEntData},
dvander@557
   799
	{"GetEntDataEnt",			GetEntDataEnt},
dvander@557
   800
	{"GetEntDataFloat",			GetEntDataFloat},
dvander@557
   801
	{"GetEntDataVector",		GetEntDataVector},
dvander@603
   802
	{"GetEntityCount",			GetEntityCount},
dvander@556
   803
	{"GetEntityNetClass",		GetEntityNetClass},
dvander@555
   804
	{"GetMaxEntities",			GetMaxEntities},
dvander@555
   805
	{"IsEntNetworkable",		IsEntNetworkable},
dvander@555
   806
	{"IsValidEdict",			IsValidEdict},
dvander@555
   807
	{"IsValidEntity",			IsValidEntity},
dvander@555
   808
	{"RemoveEdict",				RemoveEdict},
dvander@555
   809
	{"SetEdictFlags",			SetEdictFlags},
dvander@557
   810
	{"SetEntData",				SetEntData},
dvander@557
   811
	{"SetEntDataEnt",			SetEntDataEnt},
dvander@557
   812
	{"SetEntDataFloat",			SetEntDataFloat},
dvander@557
   813
	{"SetEntDataVector",		SetEntDataVector},
faluco@682
   814
	{"FindDataMapOffs",			FindDataMapOffs},
faluco@694
   815
	{"GetEntDataString",		GetEntDataString},
faluco@694
   816
	{"SetEntDataString",		SetEntDataString},
faluco@694
   817
	{"GetEntPropString",		GetEntPropString},
faluco@694
   818
	{"SetEntPropString",		SetEntPropString},
faluco@588
   819
	{NULL,						NULL}
dvander@555
   820
};