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