core/smn_entities.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jul 03 20:46:17 2007 +0000 (2007-07-03)
changeset 1036 2a073d5b3454
parent 965 327edbb1357a
child 1231 17badaf66ce4
permissions -rw-r--r--
added amb505
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@965
   112
/* :TODO: Move this! */
dvander@965
   113
datamap_t *CHalfLife2::GetDataMap(CBaseEntity *pEntity)
dvander@965
   114
{
dvander@965
   115
	return CBaseEntity_GetDataDescMap(pEntity);
dvander@965
   116
}
dvander@965
   117
dvander@555
   118
static cell_t GetMaxEntities(IPluginContext *pContext, const cell_t *params)
dvander@555
   119
{
dvander@555
   120
	return gpGlobals->maxEntities;
dvander@555
   121
}
dvander@555
   122
dvander@555
   123
static cell_t CreateEdict(IPluginContext *pContext, const cell_t *params)
dvander@555
   124
{
dvander@555
   125
	edict_t *pEdict = engine->CreateEdict();
dvander@555
   126
dvander@555
   127
	if (!pEdict)
dvander@555
   128
	{
dvander@555
   129
		return 0;
dvander@555
   130
	}
dvander@555
   131
dvander@555
   132
	return engine->IndexOfEdict(pEdict);
dvander@555
   133
}
dvander@555
   134
dvander@555
   135
static cell_t RemoveEdict(IPluginContext *pContext, const cell_t *params)
dvander@555
   136
{
dvander@555
   137
	edict_t *pEdict = engine->PEntityOfEntIndex(params[1]);
dvander@555
   138
dvander@555
   139
	if (!pEdict)
dvander@555
   140
	{
dvander@555
   141
		return pContext->ThrowNativeError("Edict %d is not a valid edict", params[1]);
dvander@555
   142
	}
dvander@555
   143
dvander@555
   144
	engine->RemoveEdict(pEdict);
dvander@555
   145
dvander@555
   146
	return 1;
dvander@555
   147
}
dvander@555
   148
dvander@555
   149
static cell_t IsValidEdict(IPluginContext *pContext, const cell_t *params)
dvander@555
   150
{
dvander@556
   151
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   152
dvander@555
   153
	if (!pEdict)
dvander@555
   154
	{
dvander@555
   155
		return 0;
dvander@555
   156
	}
dvander@555
   157
dvander@555
   158
	/* Shouldn't be necessary... not sure though */
dvander@555
   159
	return pEdict->IsFree() ? 0 : 1;
dvander@555
   160
}
dvander@555
   161
dvander@555
   162
static cell_t IsValidEntity(IPluginContext *pContext, const cell_t *params)
dvander@555
   163
{
dvander@556
   164
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   165
dvander@556
   166
	if (!pEdict)
dvander@555
   167
	{
dvander@555
   168
		return 0;
dvander@555
   169
	}
dvander@555
   170
dvander@555
   171
	IServerUnknown *pUnknown = pEdict->GetUnknown();
dvander@555
   172
	if (!pUnknown)
dvander@555
   173
	{
dvander@555
   174
		return 0;
dvander@555
   175
	}
dvander@555
   176
dvander@555
   177
	CBaseEntity *pEntity = pUnknown->GetBaseEntity();
dvander@555
   178
	return (pEntity != NULL) ? 1 : 0;
dvander@555
   179
}
dvander@555
   180
dvander@555
   181
static cell_t IsEntNetworkable(IPluginContext *pContext, const cell_t *params)
dvander@555
   182
{
dvander@556
   183
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   184
dvander@556
   185
	if (!pEdict)
dvander@555
   186
	{
dvander@555
   187
		return 0;
dvander@555
   188
	}
dvander@555
   189
dvander@555
   190
	return (pEdict->GetNetworkable() != NULL) ? 1 : 0;
dvander@555
   191
}
dvander@555
   192
dvander@555
   193
static cell_t GetEntityCount(IPluginContext *pContext, const cell_t *params)
dvander@555
   194
{
dvander@555
   195
	return engine->GetEntityCount();
dvander@555
   196
}
dvander@555
   197
dvander@555
   198
static cell_t GetEdictFlags(IPluginContext *pContext, const cell_t *params)
dvander@555
   199
{
dvander@555
   200
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   201
dvander@555
   202
	if (!pEdict)
dvander@555
   203
	{
dvander@555
   204
		return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
dvander@555
   205
	}
dvander@555
   206
dvander@555
   207
	return pEdict->m_fStateFlags;
dvander@555
   208
}
dvander@555
   209
dvander@555
   210
static cell_t SetEdictFlags(IPluginContext *pContext, const cell_t *params)
dvander@555
   211
{
dvander@555
   212
	edict_t *pEdict = GetEdict(params[1]);
dvander@555
   213
dvander@555
   214
	if (!pEdict)
dvander@555
   215
	{
dvander@555
   216
		return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
dvander@555
   217
	}
dvander@555
   218
dvander@555
   219
	pEdict->m_fStateFlags = params[2];
dvander@555
   220
dvander@555
   221
	return 1;
dvander@555
   222
}
dvander@555
   223
dvander@556
   224
static cell_t GetEdictClassname(IPluginContext *pContext, const cell_t *params)
dvander@556
   225
{
dvander@556
   226
	edict_t *pEdict = GetEdict(params[1]);
dvander@556
   227
dvander@556
   228
	if (!pEdict)
dvander@556
   229
	{
dvander@556
   230
		return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
dvander@556
   231
	}
dvander@556
   232
dvander@556
   233
	const char *cls = pEdict->GetClassName();
dvander@556
   234
dvander@556
   235
	if (!cls || cls[0] == '\0')
dvander@556
   236
	{
dvander@556
   237
		return 0;
dvander@556
   238
	}
dvander@556
   239
dvander@556
   240
	pContext->StringToLocal(params[2], params[3], cls);
dvander@556
   241
dvander@556
   242
	return 1;
dvander@556
   243
}
dvander@556
   244
dvander@556
   245
static cell_t GetEntityNetClass(IPluginContext *pContext, const cell_t *params)
dvander@556
   246
{
dvander@556
   247
	edict_t *pEdict = GetEdict(params[1]);
dvander@556
   248
dvander@556
   249
	if (!pEdict)
dvander@556
   250
	{
dvander@556
   251
		return pContext->ThrowNativeError("Invalid edict (%d)", params[1]);
dvander@556
   252
	}
dvander@556
   253
dvander@556
   254
	IServerNetworkable *pNet = pEdict->GetNetworkable();
dvander@556
   255
	if (!pNet)
dvander@556
   256
	{
dvander@556
   257
		return 0;
dvander@556
   258
	}
dvander@556
   259
dvander@556
   260
	ServerClass *pClass = pNet->GetServerClass();
dvander@556
   261
dvander@556
   262
	pContext->StringToLocal(params[2], params[3], pClass->GetName());
dvander@556
   263
dvander@556
   264
	return 1;
dvander@556
   265
}
dvander@556
   266
dvander@557
   267
static cell_t GetEntData(IPluginContext *pContext, const cell_t *params)
dvander@557
   268
{
dvander@557
   269
	CBaseEntity *pEntity;
dvander@557
   270
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   271
dvander@557
   272
	if (!pEdict || !pEntity)
dvander@557
   273
	{
dvander@557
   274
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   275
	}
dvander@557
   276
dvander@557
   277
	int offset = params[2];
dvander@557
   278
	if (offset < 0 || offset > 32768)
dvander@557
   279
	{
dvander@557
   280
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   281
	}
dvander@557
   282
dvander@557
   283
	switch (params[3])
dvander@557
   284
	{
dvander@557
   285
	case 4:
dvander@557
   286
		return *(int *)((uint8_t *)pEntity + offset);
dvander@557
   287
	case 2:
dvander@557
   288
		return *(short *)((uint8_t *)pEntity + offset);
dvander@557
   289
	case 1:
dvander@557
   290
		return *((uint8_t *)pEntity + offset);
dvander@557
   291
	default:
dvander@557
   292
		return pContext->ThrowNativeError("Integer size %d is invalid", params[3]);
dvander@557
   293
	}
dvander@557
   294
}
dvander@557
   295
dvander@557
   296
static cell_t SetEntData(IPluginContext *pContext, const cell_t *params)
dvander@557
   297
{
dvander@557
   298
	CBaseEntity *pEntity;
dvander@557
   299
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   300
dvander@557
   301
	if (!pEdict || !pEntity)
dvander@557
   302
	{
dvander@557
   303
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   304
	}
dvander@557
   305
dvander@557
   306
	int offset = params[2];
dvander@557
   307
	if (offset < 0 || offset > 32768)
dvander@557
   308
	{
dvander@557
   309
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   310
	}
dvander@557
   311
dvander@561
   312
	if (params[5])
dvander@561
   313
	{
dvander@685
   314
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   315
	}
dvander@561
   316
dvander@557
   317
	switch (params[4])
dvander@557
   318
	{
dvander@557
   319
	case 4:
dvander@557
   320
		{
dvander@557
   321
			*(int *)((uint8_t *)pEntity + offset) = params[3];
dvander@557
   322
			break;
dvander@557
   323
		}
dvander@557
   324
	case 2:
dvander@557
   325
		{
dvander@557
   326
			*(short *)((uint8_t *)pEntity + offset) = params[3];
dvander@557
   327
			break;
dvander@557
   328
		}
dvander@557
   329
	case 1:
dvander@557
   330
		{
dvander@557
   331
			*((uint8_t *)pEntity + offset) = params[3];
dvander@557
   332
			break;
dvander@557
   333
		}
dvander@557
   334
	default:
dvander@557
   335
		return pContext->ThrowNativeError("Integer size %d is invalid", params[4]);
dvander@557
   336
	}
dvander@557
   337
dvander@557
   338
	return 1;
dvander@557
   339
}
dvander@557
   340
dvander@557
   341
static cell_t GetEntDataFloat(IPluginContext *pContext, const cell_t *params)
dvander@557
   342
{
dvander@557
   343
	CBaseEntity *pEntity;
dvander@557
   344
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   345
dvander@557
   346
	if (!pEdict || !pEntity)
dvander@557
   347
	{
dvander@557
   348
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   349
	}
dvander@557
   350
dvander@557
   351
	int offset = params[2];
dvander@557
   352
	if (offset < 0 || offset > 32768)
dvander@557
   353
	{
dvander@557
   354
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   355
	}
dvander@557
   356
dvander@557
   357
	float f = *(float *)((uint8_t *)pEntity + offset);
dvander@557
   358
dvander@557
   359
	return sp_ftoc(f);
dvander@557
   360
}
dvander@557
   361
dvander@557
   362
static cell_t SetEntDataFloat(IPluginContext *pContext, const cell_t *params)
dvander@557
   363
{
dvander@557
   364
	CBaseEntity *pEntity;
dvander@557
   365
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   366
dvander@557
   367
	if (!pEdict || !pEntity)
dvander@557
   368
	{
dvander@557
   369
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   370
	}
dvander@557
   371
dvander@557
   372
	int offset = params[2];
dvander@557
   373
	if (offset < 0 || offset > 32768)
dvander@557
   374
	{
dvander@557
   375
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   376
	}
dvander@557
   377
dvander@557
   378
	*(float *)((uint8_t *)pEntity + offset) = sp_ctof(params[3]);
dvander@557
   379
dvander@561
   380
	if (params[4])
dvander@561
   381
	{
dvander@685
   382
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   383
	}
dvander@561
   384
dvander@557
   385
	return 1;
dvander@557
   386
}
dvander@557
   387
dvander@557
   388
static cell_t GetEntDataVector(IPluginContext *pContext, const cell_t *params)
dvander@557
   389
{
dvander@557
   390
	CBaseEntity *pEntity;
dvander@557
   391
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   392
dvander@557
   393
	if (!pEdict || !pEntity)
dvander@557
   394
	{
dvander@557
   395
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   396
	}
dvander@557
   397
dvander@557
   398
	int offset = params[2];
dvander@557
   399
	if (offset < 0 || offset > 32768)
dvander@557
   400
	{
dvander@557
   401
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   402
	}
dvander@557
   403
dvander@557
   404
	Vector *v = (Vector *)((uint8_t *)pEntity + offset);
dvander@557
   405
dvander@557
   406
	cell_t *vec;
dvander@557
   407
	pContext->LocalToPhysAddr(params[3], &vec);
dvander@557
   408
faluco@597
   409
	vec[0] = sp_ftoc(v->x);
faluco@597
   410
	vec[1] = sp_ftoc(v->y);
faluco@597
   411
	vec[2] = sp_ftoc(v->z);
dvander@557
   412
dvander@557
   413
	return 1;
dvander@557
   414
}
dvander@557
   415
dvander@557
   416
static cell_t SetEntDataVector(IPluginContext *pContext, const cell_t *params)
dvander@557
   417
{
dvander@557
   418
	CBaseEntity *pEntity;
dvander@557
   419
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   420
dvander@557
   421
	if (!pEdict || !pEntity)
dvander@557
   422
	{
dvander@557
   423
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   424
	}
dvander@557
   425
dvander@557
   426
	int offset = params[2];
dvander@557
   427
	if (offset < 0 || offset > 32768)
dvander@557
   428
	{
dvander@557
   429
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   430
	}
dvander@557
   431
dvander@557
   432
	Vector *v = (Vector *)((uint8_t *)pEntity + offset);
dvander@557
   433
dvander@557
   434
	cell_t *vec;
dvander@557
   435
	pContext->LocalToPhysAddr(params[3], &vec);
dvander@557
   436
faluco@597
   437
	v->x = sp_ctof(vec[0]);
faluco@597
   438
	v->y = sp_ctof(vec[1]);
faluco@597
   439
	v->z = sp_ctof(vec[2]);
dvander@557
   440
dvander@561
   441
	if (params[4])
dvander@561
   442
	{
dvander@685
   443
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   444
	}
dvander@561
   445
dvander@557
   446
	return 1;
dvander@557
   447
}
dvander@557
   448
dvander@557
   449
static cell_t GetEntDataEnt(IPluginContext *pContext, const cell_t *params)
dvander@557
   450
{
dvander@557
   451
	CBaseEntity *pEntity;
dvander@557
   452
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   453
dvander@557
   454
	if (!pEdict || !pEntity)
dvander@557
   455
	{
dvander@557
   456
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   457
	}
dvander@557
   458
dvander@557
   459
	int offset = params[2];
dvander@557
   460
	if (offset < 0 || offset > 32768)
dvander@557
   461
	{
dvander@557
   462
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   463
	}
dvander@557
   464
dvander@557
   465
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
dvander@557
   466
dvander@557
   467
	if (!hndl.IsValid())
dvander@557
   468
	{
dvander@557
   469
		return 0;
dvander@557
   470
	}
dvander@557
   471
dvander@557
   472
	/* :TODO: check serial no.? */
dvander@557
   473
dvander@557
   474
	return hndl.GetEntryIndex();
dvander@557
   475
}
dvander@557
   476
dvander@557
   477
static cell_t SetEntDataEnt(IPluginContext *pContext, const cell_t *params)
dvander@557
   478
{
dvander@557
   479
	CBaseEntity *pEntity;
dvander@557
   480
	edict_t *pEdict = GetEntity(params[1], &pEntity);
dvander@557
   481
dvander@557
   482
	if (!pEdict || !pEntity)
dvander@557
   483
	{
dvander@557
   484
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
dvander@557
   485
	}
dvander@557
   486
dvander@557
   487
	int offset = params[2];
dvander@557
   488
	if (offset < 0 || offset > 32768)
dvander@557
   489
	{
dvander@557
   490
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
dvander@557
   491
	}
dvander@557
   492
dvander@557
   493
	CBaseHandle &hndl = *(CBaseHandle *)((uint8_t *)pEntity + offset);
dvander@557
   494
dvander@557
   495
	if (params[3] == 0)
dvander@557
   496
	{
dvander@557
   497
		hndl.Set(NULL);
dvander@557
   498
	} else {
dvander@557
   499
		edict_t *pEdict = GetEdict(params[3]);
dvander@557
   500
		if (!pEdict)
dvander@557
   501
		{
dvander@557
   502
			return pContext->ThrowNativeError("Entity %d is invalid", params[3]);
dvander@557
   503
		}
dvander@557
   504
		IServerEntity *pEntOther = pEdict->GetIServerEntity();
dvander@557
   505
		hndl.Set(pEntOther);
dvander@557
   506
	}
dvander@557
   507
dvander@561
   508
	if (params[4])
dvander@561
   509
	{
dvander@685
   510
		g_HL2.SetEdictStateChanged(pEdict, offset);
dvander@561
   511
	}
dvander@561
   512
dvander@557
   513
	return 1;
dvander@557
   514
}
dvander@557
   515
dvander@558
   516
static cell_t ChangeEdictState(IPluginContext *pContext, const cell_t *params)
dvander@558
   517
{
dvander@558
   518
	edict_t *pEdict = GetEdict(params[1]);
dvander@558
   519
dvander@558
   520
	if (!pEdict)
dvander@558
   521
	{
dvander@558
   522
		return pContext->ThrowNativeError("Edict %d is invalid", params[1]);
dvander@558
   523
	}
dvander@558
   524
dvander@685
   525
	g_HL2.SetEdictStateChanged(pEdict, params[2]);
dvander@558
   526
dvander@558
   527
	return 1;
dvander@558
   528
}
dvander@558
   529
dvander@561
   530
static cell_t FindSendPropOffs(IPluginContext *pContext, const cell_t *params)
dvander@561
   531
{
dvander@561
   532
	char *cls, *prop;
dvander@561
   533
	pContext->LocalToString(params[1], &cls);
dvander@561
   534
	pContext->LocalToString(params[2], &prop);
dvander@561
   535
dvander@561
   536
	SendProp *pSend = g_HL2.FindInSendTable(cls, prop);
dvander@561
   537
dvander@561
   538
	if (!pSend)
dvander@561
   539
	{
dvander@561
   540
		return -1;
dvander@561
   541
	}
dvander@561
   542
dvander@561
   543
	return pSend->GetOffset();
dvander@561
   544
}
dvander@561
   545
faluco@682
   546
static cell_t FindDataMapOffs(IPluginContext *pContext, const cell_t *params)
faluco@682
   547
{
faluco@682
   548
	CBaseEntity *pEntity;
faluco@682
   549
	datamap_t *pMap;
faluco@682
   550
	typedescription_t *td;
faluco@682
   551
	char *offset;
faluco@682
   552
	edict_t *pEdict = GetEntity(params[1], &pEntity);
faluco@682
   553
faluco@682
   554
	if (!pEdict || !pEntity)
faluco@682
   555
	{
faluco@682
   556
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
faluco@682
   557
	}
faluco@682
   558
faluco@682
   559
	if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
faluco@682
   560
	{
faluco@682
   561
		return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
faluco@682
   562
	}
faluco@682
   563
faluco@682
   564
	pContext->LocalToString(params[2], &offset);
faluco@682
   565
	if ((td=g_HL2.FindInDataMap(pMap, offset)) == NULL)
faluco@682
   566
	{
faluco@682
   567
		return -1;
faluco@682
   568
	}
faluco@682
   569
faluco@682
   570
	return td->fieldOffset[TD_OFFSET_NORMAL];
faluco@682
   571
}
faluco@682
   572
faluco@694
   573
static cell_t GetEntDataString(IPluginContext *pContext, const cell_t *params)
faluco@694
   574
{
faluco@694
   575
	CBaseEntity *pEntity;
faluco@694
   576
	edict_t *pEdict = GetEntity(params[1], &pEntity);
faluco@694
   577
faluco@694
   578
	if (!pEdict || !pEntity)
faluco@694
   579
	{
faluco@694
   580
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
faluco@694
   581
	}
faluco@694
   582
faluco@694
   583
	int offset = params[2];
faluco@694
   584
	if (offset < 0 || offset > 32768)
faluco@694
   585
	{
faluco@694
   586
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
faluco@694
   587
	}
faluco@694
   588
faluco@694
   589
	size_t len;
faluco@694
   590
	char *src = (char *)((uint8_t *)pEntity + offset);
faluco@694
   591
	pContext->StringToLocalUTF8(params[3], params[4], src, &len);
faluco@694
   592
faluco@694
   593
	return len;
faluco@694
   594
}
faluco@694
   595
faluco@694
   596
static cell_t SetEntDataString(IPluginContext *pContext, const cell_t *params)
faluco@694
   597
{
faluco@694
   598
	CBaseEntity *pEntity;
faluco@694
   599
	edict_t *pEdict = GetEntity(params[1], &pEntity);
faluco@694
   600
faluco@694
   601
	if (!pEdict || !pEntity)
faluco@694
   602
	{
faluco@694
   603
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
faluco@694
   604
	}
faluco@694
   605
faluco@694
   606
	int offset = params[2];
faluco@694
   607
	if (offset < 0 || offset > 32768)
faluco@694
   608
	{
faluco@694
   609
		return pContext->ThrowNativeError("Offset %d is invalid", offset);
faluco@694
   610
	}
faluco@694
   611
faluco@694
   612
	char *src;
faluco@694
   613
	char *dest = (char *)((uint8_t *)pEntity + offset);
faluco@694
   614
faluco@694
   615
	pContext->LocalToString(params[3], &src);
faluco@694
   616
	size_t len = strncopy(dest, src, params[4]);
faluco@694
   617
faluco@694
   618
	if (params[5])
faluco@694
   619
	{
faluco@694
   620
		g_HL2.SetEdictStateChanged(pEdict, offset);
faluco@694
   621
	}
faluco@694
   622
faluco@694
   623
	return len;
faluco@694
   624
}
faluco@694
   625
faluco@694
   626
static cell_t GetEntPropString(IPluginContext *pContext, const cell_t *params)
faluco@694
   627
{
faluco@694
   628
	CBaseEntity *pEntity;
faluco@694
   629
	char *prop;
faluco@694
   630
	int offset;
faluco@694
   631
	edict_t *pEdict = GetEntity(params[1], &pEntity);
faluco@694
   632
faluco@694
   633
	if (!pEdict || !pEntity)
faluco@694
   634
	{
faluco@694
   635
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
faluco@694
   636
	}
faluco@694
   637
faluco@694
   638
	switch (params[2])
faluco@694
   639
	{
faluco@694
   640
	case Prop_Data:
faluco@694
   641
		{
faluco@694
   642
			datamap_t *pMap;
faluco@694
   643
			typedescription_t *td;
faluco@694
   644
			if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
faluco@694
   645
			{
faluco@694
   646
				return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
faluco@694
   647
			}
faluco@694
   648
			pContext->LocalToString(params[3], &prop);
faluco@694
   649
			if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
faluco@694
   650
			{
faluco@694
   651
				return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
faluco@694
   652
			}
faluco@694
   653
			if (td->fieldType != FIELD_CHARACTER)
faluco@694
   654
			{
faluco@694
   655
				return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
faluco@694
   656
			}
faluco@694
   657
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
faluco@694
   658
			break;
faluco@694
   659
		}
faluco@694
   660
	case Prop_Send:
faluco@694
   661
		{
faluco@694
   662
			char *prop;
faluco@694
   663
			IServerNetworkable *pNet = pEdict->GetNetworkable();
faluco@694
   664
			if (!pNet)
faluco@694
   665
			{
faluco@694
   666
				return pContext->ThrowNativeError("The edict is not networkable");
faluco@694
   667
			}
faluco@694
   668
			pContext->LocalToString(params[3], &prop);
faluco@694
   669
			SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
faluco@694
   670
			if (!pSend)
faluco@694
   671
			{
faluco@694
   672
				return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
faluco@694
   673
			}
faluco@694
   674
			if (pSend->GetType() != DPT_String)
faluco@694
   675
			{
faluco@694
   676
				return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
faluco@694
   677
			}
faluco@694
   678
			offset = pSend->GetOffset();
faluco@694
   679
			break;
faluco@694
   680
		}
faluco@694
   681
	default:
faluco@694
   682
		{
faluco@694
   683
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
faluco@694
   684
		}
faluco@694
   685
	}
faluco@694
   686
faluco@694
   687
	size_t len;
faluco@694
   688
	char *src = (char *)((uint8_t *)pEntity + offset);
faluco@694
   689
	pContext->StringToLocalUTF8(params[4], params[5], src, &len);
faluco@694
   690
faluco@694
   691
	return len;
faluco@694
   692
}
faluco@694
   693
faluco@694
   694
static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params)
faluco@694
   695
{
faluco@694
   696
	CBaseEntity *pEntity;
faluco@694
   697
	char *prop;
faluco@694
   698
	int offset;
faluco@694
   699
	int maxlen;
faluco@694
   700
	bool is_sendprop = false;
faluco@694
   701
	edict_t *pEdict = GetEntity(params[1], &pEntity);
faluco@694
   702
faluco@694
   703
	if (!pEdict || !pEntity)
faluco@694
   704
	{
faluco@694
   705
		return pContext->ThrowNativeError("Entity %d is invalid", params[1]);
faluco@694
   706
	}
faluco@694
   707
faluco@694
   708
	switch (params[2])
faluco@694
   709
	{
faluco@694
   710
	case Prop_Data:
faluco@694
   711
		{
faluco@694
   712
			datamap_t *pMap;
faluco@694
   713
			typedescription_t *td;
faluco@694
   714
			if ((pMap=CBaseEntity_GetDataDescMap(pEntity)) == NULL)
faluco@694
   715
			{
faluco@694
   716
				return pContext->ThrowNativeError("Unable to retrieve GetDataDescMap offset");
faluco@694
   717
			}
faluco@694
   718
			pContext->LocalToString(params[3], &prop);
faluco@694
   719
			if ((td=g_HL2.FindInDataMap(pMap, prop)) == NULL)
faluco@694
   720
			{
faluco@694
   721
				return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
faluco@694
   722
			}
faluco@694
   723
			if (td->fieldType != FIELD_CHARACTER)
faluco@694
   724
			{
faluco@694
   725
				return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
faluco@694
   726
			}
faluco@694
   727
			offset = td->fieldOffset[TD_OFFSET_NORMAL];
faluco@694
   728
			maxlen = td->fieldSize;
faluco@694
   729
			break;
faluco@694
   730
		}
faluco@694
   731
	case Prop_Send:
faluco@694
   732
		{
faluco@694
   733
			char *prop;
faluco@694
   734
			IServerNetworkable *pNet = pEdict->GetNetworkable();
faluco@694
   735
			if (!pNet)
faluco@694
   736
			{
faluco@694
   737
				return pContext->ThrowNativeError("The edict is not networkable");
faluco@694
   738
			}
faluco@694
   739
			pContext->LocalToString(params[3], &prop);
faluco@694
   740
			SendProp *pSend = g_HL2.FindInSendTable(pNet->GetServerClass()->GetName(), prop);
faluco@694
   741
			if (!pSend)
faluco@694
   742
			{
faluco@694
   743
				return pContext->ThrowNativeError("Property \"%s\" not found for entity %d", prop, params[1]);
faluco@694
   744
			}
faluco@694
   745
			if (pSend->GetType() != DPT_String)
faluco@694
   746
			{
faluco@694
   747
				return pContext->ThrowNativeError("Property \"%s\" is not a valid string", prop);
faluco@694
   748
			}
faluco@694
   749
			offset = pSend->GetOffset();
faluco@694
   750
			maxlen = DT_MAX_STRING_BUFFERSIZE;
faluco@694
   751
			is_sendprop = true;
faluco@694
   752
			break;
faluco@694
   753
		}
faluco@694
   754
	default:
faluco@694
   755
		{
faluco@694
   756
			return pContext->ThrowNativeError("Invalid Property type %d", params[2]);
faluco@694
   757
		}
faluco@694
   758
	}
faluco@694
   759
faluco@694
   760
	char *src;
faluco@694
   761
	char *dest = (char *)((uint8_t *)pEntity + offset);
faluco@694
   762
faluco@694
   763
	pContext->LocalToString(params[4], &src);
faluco@694
   764
	size_t len = strncopy(dest, src, maxlen);
faluco@694
   765
faluco@694
   766
	if (is_sendprop)
faluco@694
   767
	{
faluco@694
   768
		g_HL2.SetEdictStateChanged(pEdict, offset);
faluco@694
   769
	}
faluco@694
   770
faluco@694
   771
	return len;
faluco@694
   772
}
faluco@694
   773
dvander@555
   774
REGISTER_NATIVES(entityNatives)
dvander@555
   775
{
dvander@558
   776
	{"ChangeEdictState",		ChangeEdictState},
dvander@555
   777
	{"CreateEdict",				CreateEdict},
dvander@561
   778
	{"FindSendPropOffs",		FindSendPropOffs},
dvander@556
   779
	{"GetEdictClassname",		GetEdictClassname},
dvander@555
   780
	{"GetEdictFlags",			GetEdictFlags},
dvander@557
   781
	{"GetEntData",				GetEntData},
dvander@557
   782
	{"GetEntDataEnt",			GetEntDataEnt},
dvander@557
   783
	{"GetEntDataFloat",			GetEntDataFloat},
dvander@557
   784
	{"GetEntDataVector",		GetEntDataVector},
dvander@603
   785
	{"GetEntityCount",			GetEntityCount},
dvander@556
   786
	{"GetEntityNetClass",		GetEntityNetClass},
dvander@555
   787
	{"GetMaxEntities",			GetMaxEntities},
dvander@555
   788
	{"IsEntNetworkable",		IsEntNetworkable},
dvander@555
   789
	{"IsValidEdict",			IsValidEdict},
dvander@555
   790
	{"IsValidEntity",			IsValidEntity},
dvander@555
   791
	{"RemoveEdict",				RemoveEdict},
dvander@555
   792
	{"SetEdictFlags",			SetEdictFlags},
dvander@557
   793
	{"SetEntData",				SetEntData},
dvander@557
   794
	{"SetEntDataEnt",			SetEntDataEnt},
dvander@557
   795
	{"SetEntDataFloat",			SetEntDataFloat},
dvander@557
   796
	{"SetEntDataVector",		SetEntDataVector},
faluco@682
   797
	{"FindDataMapOffs",			FindDataMapOffs},
faluco@694
   798
	{"GetEntDataString",		GetEntDataString},
faluco@694
   799
	{"SetEntDataString",		SetEntDataString},
faluco@694
   800
	{"GetEntPropString",		GetEntPropString},
faluco@694
   801
	{"SetEntPropString",		SetEntPropString},
faluco@588
   802
	{NULL,						NULL}
dvander@555
   803
};