extensions/sdktools/vdecoder.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 20 08:03:43 2007 +0000 (2007-06-20)
changeset 987 242d2382cc41
parent 976 6f9046162acb
child 1031 d9cf44ddcd9c
permissions -rw-r--r--
fixed a very serious flaw where Vectors being passed as pointers would corrupt the vector object values. this caused TeleportEntity() to have very weird effects
dvander@950
     1
#include "smsdk_ext.h"
dvander@950
     2
#include "extension.h"
dvander@950
     3
#include "vdecoder.h"
dvander@987
     4
#include "vcallbuilder.h"
dvander@950
     5
dvander@950
     6
using namespace SourceMod;
dvander@950
     7
using namespace SourcePawn;
dvander@950
     8
dvander@950
     9
/**
dvander@950
    10
 * For object pointers, the data looks like this instead:
dvander@987
    11
 * 4 bytes: POINTER TO LATER
dvander@950
    12
 * + bytes: Object internal data
dvander@950
    13
 *
dvander@950
    14
 * We use the virtual stack as extra fake stack space and create a temp object.
dvander@950
    15
 * If these objects had destructors, we'd need to fake destroy toom of course.
dvander@950
    16
 * Of course, BinTools only reads the first four bytes and passes the pointer.
dvander@950
    17
 */
dvander@950
    18
dvander@950
    19
size_t ValveParamToBinParam(ValveType type, 
dvander@950
    20
						  PassType pass,
dvander@950
    21
						  unsigned int flags,
dvander@987
    22
						  PassInfo *info,
dvander@987
    23
						  bool &needs_extra)
dvander@950
    24
{
dvander@987
    25
	needs_extra = false;
dvander@950
    26
	switch (type)
dvander@950
    27
	{
dvander@950
    28
	case Valve_Vector:
dvander@950
    29
		{
dvander@950
    30
			size_t mySize = sizeof(Vector *);
dvander@950
    31
			if (pass == PassType_Basic)
dvander@950
    32
			{
dvander@976
    33
				if (flags & PASSFLAG_BYREF)
dvander@950
    34
				{
dvander@950
    35
					return 0;
dvander@950
    36
				}
dvander@950
    37
				info->type = PassType_Basic;
dvander@950
    38
				info->flags = flags;
dvander@950
    39
				info->size = sizeof(Vector *);
dvander@987
    40
				mySize = sizeof(Vector);
dvander@987
    41
				needs_extra = true;
dvander@950
    42
			} else if (pass == PassType_Object) {
dvander@950
    43
				info->type = PassType_Object;
dvander@950
    44
				info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR;
dvander@950
    45
				info->size = sizeof(Vector);
dvander@950
    46
			} else {
dvander@950
    47
				return 0;
dvander@950
    48
			}
dvander@950
    49
			return mySize;
dvander@950
    50
		}
dvander@950
    51
	case Valve_QAngle:
dvander@950
    52
		{
dvander@950
    53
			size_t mySize = sizeof(QAngle *);
dvander@950
    54
			if (pass == PassType_Basic)
dvander@950
    55
			{
dvander@976
    56
				if (flags & PASSFLAG_BYREF)
dvander@950
    57
				{
dvander@950
    58
					return 0;
dvander@950
    59
				}
dvander@950
    60
				info->type = PassType_Basic;
dvander@950
    61
				info->flags = flags;
dvander@950
    62
				info->size = sizeof(QAngle *);
dvander@987
    63
				mySize = sizeof(QAngle);
dvander@987
    64
				needs_extra = true;
dvander@950
    65
			} else if (pass == PassType_Object) {
dvander@950
    66
				info->type = PassType_Object;
dvander@950
    67
				info->flags = flags | PASSFLAG_OASSIGNOP | PASSFLAG_OCTOR;
dvander@950
    68
				info->size = sizeof(QAngle);
dvander@950
    69
			} else {
dvander@950
    70
				return 0;
dvander@950
    71
			}
dvander@950
    72
			return mySize;
dvander@950
    73
		}
dvander@950
    74
	case Valve_CBaseEntity:
dvander@950
    75
	case Valve_CBasePlayer:
dvander@950
    76
	case Valve_Edict:
dvander@950
    77
	case Valve_String:
dvander@950
    78
		{
dvander@976
    79
			if (pass != PassType_Basic || (flags & PASSFLAG_BYREF))
dvander@950
    80
			{
dvander@950
    81
				return 0;
dvander@950
    82
			}
dvander@950
    83
			info->type = PassType_Basic;
dvander@950
    84
			info->flags = flags;
dvander@950
    85
			info->size = sizeof(void *);
dvander@950
    86
			return sizeof(void *);
dvander@950
    87
		}
dvander@954
    88
	case Valve_POD:
dvander@954
    89
		{
dvander@954
    90
			info->type = PassType_Basic;
dvander@954
    91
			info->flags = flags;
dvander@954
    92
			if (flags & PASSFLAG_ASPOINTER)
dvander@954
    93
			{
dvander@954
    94
				info->size = sizeof(int *);
dvander@954
    95
				return sizeof(int *) + sizeof(int);
dvander@954
    96
			} else {
dvander@954
    97
				info->size = sizeof(int);
dvander@954
    98
				return sizeof(int);
dvander@954
    99
			}
dvander@954
   100
		}
dvander@954
   101
	case Valve_Bool:
dvander@954
   102
		{
dvander@954
   103
			info->type = PassType_Basic;
dvander@954
   104
			info->flags = flags;
dvander@954
   105
			if (flags & PASSFLAG_ASPOINTER)
dvander@954
   106
			{
dvander@954
   107
				info->size = sizeof(bool *);
dvander@954
   108
				return sizeof(bool *) + sizeof(bool);
dvander@954
   109
			} else {
dvander@954
   110
				info->size = sizeof(bool);
dvander@954
   111
				return sizeof(bool);
dvander@954
   112
			}
dvander@954
   113
		}
dvander@950
   114
	case Valve_Float:
dvander@950
   115
		{
dvander@950
   116
			info->type = PassType_Float;
dvander@950
   117
			info->flags = flags;
dvander@954
   118
			if (flags & PASSFLAG_ASPOINTER)
dvander@954
   119
			{
dvander@954
   120
				info->size = sizeof(float *);
dvander@954
   121
				return sizeof(float *) + sizeof(float);
dvander@954
   122
			} else {
dvander@954
   123
				info->size = sizeof(float);
dvander@954
   124
				return sizeof(float);
dvander@954
   125
			}
dvander@950
   126
		}
dvander@950
   127
	}
dvander@950
   128
dvander@950
   129
	return 0;
dvander@950
   130
}
dvander@950
   131
dvander@950
   132
DataStatus EncodeValveParam(IPluginContext *pContext,
dvander@950
   133
							cell_t param, 
dvander@987
   134
							const ValveCall *pCall,
dvander@954
   135
							const ValvePassInfo *data,
dvander@987
   136
							const void *_buffer)
dvander@950
   137
{
dvander@987
   138
	const void *buffer = (const unsigned char *)_buffer + data->offset;
dvander@954
   139
	switch (data->vtype)
dvander@950
   140
	{
dvander@950
   141
	case Valve_Vector:
dvander@950
   142
		{
dvander@950
   143
			Vector *v = NULL;
dvander@950
   144
dvander@954
   145
			if (data->type == PassType_Basic)
dvander@950
   146
			{
dvander@950
   147
				v = *(Vector **)((unsigned char *)buffer + sizeof(Vector *));
dvander@954
   148
			} else if (data->type == PassType_Object) {
dvander@950
   149
				v = (Vector *)buffer;
dvander@950
   150
			}
dvander@950
   151
dvander@950
   152
			cell_t *addr;
dvander@950
   153
			pContext->LocalToPhysAddr(param, &addr);
dvander@950
   154
dvander@956
   155
			addr[0] = sp_ftoc(v->x);
dvander@956
   156
			addr[1] = sp_ftoc(v->y);
dvander@956
   157
			addr[2] = sp_ftoc(v->z);
dvander@950
   158
dvander@950
   159
			return Data_Okay;
dvander@950
   160
		}
dvander@950
   161
	case Valve_QAngle:
dvander@950
   162
		{
dvander@950
   163
			QAngle *q = NULL;
dvander@950
   164
dvander@954
   165
			if (data->type == PassType_Basic)
dvander@950
   166
			{
dvander@950
   167
				q = *(QAngle **)((unsigned char *)buffer + sizeof(QAngle *));
dvander@954
   168
			} else if (data->type == PassType_Object) {
dvander@950
   169
				q = (QAngle *)buffer;
dvander@950
   170
			}
dvander@950
   171
dvander@950
   172
			cell_t *addr;
dvander@950
   173
			pContext->LocalToPhysAddr(param, &addr);
dvander@950
   174
dvander@956
   175
			addr[0] = sp_ftoc(q->x);
dvander@956
   176
			addr[1] = sp_ftoc(q->y);
dvander@956
   177
			addr[2] = sp_ftoc(q->z);
dvander@950
   178
dvander@950
   179
			return Data_Okay;
dvander@950
   180
		}
dvander@950
   181
	case Valve_CBaseEntity:
dvander@950
   182
	case Valve_CBasePlayer:
dvander@950
   183
		{
dvander@950
   184
			cell_t *addr;
dvander@950
   185
			pContext->LocalToPhysAddr(param, &addr);
dvander@950
   186
dvander@950
   187
			CBaseEntity *pEntity = *(CBaseEntity **)buffer;
dvander@950
   188
			if (pEntity)
dvander@950
   189
			{
dvander@950
   190
				edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
dvander@950
   191
				*addr = engine->IndexOfEdict(pEdict);
dvander@950
   192
			} else {
dvander@950
   193
				*addr = -1;
dvander@950
   194
			}
dvander@950
   195
dvander@950
   196
			return Data_Okay;
dvander@950
   197
		}
dvander@950
   198
	case Valve_Edict:
dvander@950
   199
		{
dvander@950
   200
			cell_t *addr;
dvander@950
   201
			pContext->LocalToPhysAddr(param, &addr);
dvander@950
   202
dvander@950
   203
			edict_t *pEdict = *(edict_t **)buffer;
dvander@950
   204
			if (pEdict)
dvander@950
   205
			{
dvander@950
   206
				*addr = engine->IndexOfEdict(pEdict);
dvander@950
   207
			} else {
dvander@950
   208
				*addr = -1;
dvander@950
   209
			}
dvander@950
   210
dvander@950
   211
			return Data_Okay;
dvander@950
   212
		}
dvander@950
   213
	case Valve_POD:
dvander@950
   214
	case Valve_Float:
dvander@950
   215
		{
dvander@950
   216
			cell_t *addr;
dvander@950
   217
			pContext->LocalToPhysAddr(param, &addr);
dvander@950
   218
dvander@954
   219
			if (data->flags & PASSFLAG_ASPOINTER)
dvander@954
   220
			{
dvander@954
   221
				buffer = (char *)buffer + sizeof(void *);
dvander@954
   222
			}
dvander@954
   223
dvander@950
   224
			*addr = *(cell_t *)buffer;
dvander@950
   225
dvander@950
   226
			return Data_Okay;
dvander@950
   227
		}
dvander@954
   228
	case Valve_Bool:
dvander@954
   229
		{
dvander@954
   230
			cell_t *addr;
dvander@954
   231
			pContext->LocalToPhysAddr(param, &addr);
dvander@954
   232
dvander@954
   233
			if (data->flags & PASSFLAG_ASPOINTER)
dvander@954
   234
			{
dvander@954
   235
				buffer = (char *)buffer + sizeof(bool *);
dvander@954
   236
			}
dvander@954
   237
dvander@954
   238
			*addr = *(bool *)buffer ? 1 : 0;
dvander@954
   239
dvander@954
   240
			return Data_Okay;
dvander@954
   241
		}
dvander@950
   242
	}
dvander@950
   243
dvander@950
   244
	return Data_Fail;
dvander@950
   245
}
dvander@950
   246
dvander@950
   247
DataStatus DecodeValveParam(IPluginContext *pContext,
dvander@950
   248
					  cell_t param,
dvander@987
   249
					  const ValveCall *pCall,
dvander@954
   250
					  const ValvePassInfo *data,
dvander@987
   251
					  void *_buffer)
dvander@950
   252
{
dvander@987
   253
	void *buffer = (unsigned char *)_buffer + data->offset;
dvander@954
   254
	switch (data->vtype)
dvander@950
   255
	{
dvander@950
   256
	case Valve_Vector:
dvander@950
   257
		{
dvander@950
   258
			cell_t *addr;
dvander@950
   259
			int err;
dvander@950
   260
			err = pContext->LocalToPhysAddr(param, &addr);
dvander@950
   261
dvander@950
   262
			unsigned char *mem = (unsigned char *)buffer;
dvander@954
   263
			if (data->type == PassType_Basic)
dvander@950
   264
			{
dvander@950
   265
				/* Store the object in the next N bytes, and store
dvander@950
   266
				 * a pointer to that object right beforehand.
dvander@950
   267
				 */
dvander@950
   268
				Vector **realPtr = (Vector **)buffer;
dvander@950
   269
dvander@950
   270
				if (addr == pContext->GetNullRef(SP_NULL_VECTOR))
dvander@950
   271
				{
dvander@954
   272
					if (data->decflags & VDECODE_FLAG_ALLOWNULL)
dvander@950
   273
					{
dvander@950
   274
						*realPtr = NULL;
dvander@950
   275
						return Data_Okay;
dvander@950
   276
					} else {
dvander@950
   277
						pContext->ThrowNativeError("NULL not allowed");
dvander@950
   278
						return Data_Fail;
dvander@950
   279
					}
dvander@950
   280
				} else {
dvander@987
   281
					mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
dvander@950
   282
					*realPtr = (Vector *)mem;
dvander@950
   283
				}
dvander@950
   284
			}
dvander@950
   285
dvander@950
   286
			if (err != SP_ERROR_NONE)
dvander@950
   287
			{
dvander@950
   288
				pContext->ThrowNativeErrorEx(err, "Could not read plugin data");
dvander@950
   289
				return Data_Fail;
dvander@950
   290
			}
dvander@950
   291
dvander@950
   292
			/* Use placement new to initialize the object cleanly
dvander@950
   293
			 * This has no destructor so we don't need to do 
dvander@950
   294
			 * DestroyValveParam() or something :]
dvander@950
   295
			 */
dvander@950
   296
			Vector *v = new (mem) Vector(
dvander@950
   297
				sp_ctof(addr[0]),
dvander@950
   298
				sp_ctof(addr[1]),
dvander@950
   299
				sp_ctof(addr[2]));
dvander@950
   300
dvander@950
   301
			return Data_Okay;
dvander@950
   302
		}
dvander@950
   303
	case Valve_QAngle:
dvander@950
   304
		{
dvander@950
   305
			cell_t *addr;
dvander@950
   306
			int err;
dvander@950
   307
			err = pContext->LocalToPhysAddr(param, &addr);
dvander@950
   308
dvander@950
   309
			unsigned char *mem = (unsigned char *)buffer;
dvander@954
   310
			if (data->type == PassType_Basic)
dvander@950
   311
			{
dvander@950
   312
				/* Store the object in the next N bytes, and store
dvander@953
   313
				 * a pointer to that object right beforehand.
dvander@953
   314
				 */
dvander@950
   315
				QAngle **realPtr = (QAngle **)buffer;
dvander@950
   316
dvander@950
   317
				if (addr == pContext->GetNullRef(SP_NULL_VECTOR))
dvander@950
   318
				{
dvander@954
   319
					if (!(data->decflags & VDECODE_FLAG_ALLOWNULL))
dvander@950
   320
					{
dvander@950
   321
						pContext->ThrowNativeError("NULL not allowed");
dvander@950
   322
						return Data_Fail;
dvander@950
   323
					} else {
dvander@950
   324
						*realPtr = NULL;
dvander@950
   325
						return Data_Okay;
dvander@950
   326
					}
dvander@950
   327
				} else {
dvander@987
   328
					mem = (unsigned char *)_buffer + pCall->stackEnd + data->obj_offset;
dvander@950
   329
					*realPtr = (QAngle *)mem;
dvander@950
   330
				}
dvander@950
   331
			}
dvander@950
   332
dvander@950
   333
			if (err != SP_ERROR_NONE)
dvander@950
   334
			{
dvander@950
   335
				pContext->ThrowNativeErrorEx(err, "Could not read plugin data");
dvander@950
   336
				return Data_Fail;
dvander@950
   337
			}
dvander@950
   338
dvander@950
   339
			/* Use placement new to initialize the object cleanly
dvander@953
   340
			 * This has no destructor so we don't need to do 
dvander@953
   341
			 * DestroyValveParam() or something :]
dvander@953
   342
			 */
dvander@950
   343
			QAngle *v = new (mem) QAngle(
dvander@950
   344
				sp_ctof(addr[0]),
dvander@950
   345
				sp_ctof(addr[1]),
dvander@950
   346
				sp_ctof(addr[2]));
dvander@950
   347
dvander@950
   348
			return Data_Okay;
dvander@950
   349
		}
dvander@950
   350
	case Valve_CBasePlayer:
dvander@950
   351
		{
dvander@950
   352
			edict_t *pEdict;
dvander@954
   353
			if (data->decflags & VDECODE_FLAG_BYREF)
dvander@950
   354
			{
dvander@950
   355
				cell_t *addr;
dvander@950
   356
				pContext->LocalToPhysAddr(param, &addr);
dvander@950
   357
				param = *addr;
dvander@950
   358
			}
dvander@950
   359
			if (param >= 1 && param <= playerhelpers->GetMaxClients())
dvander@950
   360
			{
dvander@950
   361
				IGamePlayer *player = playerhelpers->GetGamePlayer(param);
dvander@954
   362
				if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
dvander@950
   363
					&& !player->IsConnected())
dvander@950
   364
				{
dvander@950
   365
					pContext->ThrowNativeError("Client %d is not connected", param);
dvander@950
   366
					return Data_Fail;
dvander@950
   367
				} else if (!player->IsInGame()) {
dvander@950
   368
					pContext->ThrowNativeError("Client %d is not in game", param);
dvander@950
   369
					return Data_Fail;
dvander@950
   370
				}
dvander@950
   371
				pEdict = player->GetEdict();
dvander@950
   372
			} else if (param == -1) {
dvander@954
   373
				if (data->decflags & VDECODE_FLAG_ALLOWNULL)
dvander@950
   374
				{
dvander@950
   375
					pEdict = NULL;
dvander@950
   376
				} else {
dvander@950
   377
					pContext->ThrowNativeError("NULL not allowed");
dvander@950
   378
					return Data_Fail;
dvander@950
   379
				}
dvander@950
   380
			} else if (param == 0) {
dvander@954
   381
				if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
dvander@950
   382
				{
dvander@950
   383
					pEdict = engine->PEntityOfEntIndex(0);
dvander@950
   384
				} else {
dvander@950
   385
					pContext->ThrowNativeError("World not allowed");
dvander@950
   386
					return Data_Fail;
dvander@950
   387
				}
dvander@950
   388
			} else {
dvander@950
   389
				pContext->ThrowNativeError("Entity index %d is not a valid client", param);
dvander@950
   390
				return Data_Fail;
dvander@950
   391
			}
dvander@956
   392
			CBaseEntity *pEntity = NULL;
dvander@950
   393
			if (pEdict)
dvander@950
   394
			{
dvander@950
   395
				IServerUnknown *pUnknown = pEdict->GetUnknown();
dvander@950
   396
				if (!pUnknown)
dvander@950
   397
				{
dvander@950
   398
					pContext->ThrowNativeError("Entity %d is a not an IServerUnknown");
dvander@950
   399
					return Data_Fail;
dvander@950
   400
				}
dvander@950
   401
				pEntity = pUnknown->GetBaseEntity();
dvander@950
   402
				if (!pEntity)
dvander@950
   403
				{
dvander@950
   404
					pContext->ThrowNativeError("Entity %d is not a CBaseEntity");
dvander@950
   405
					return Data_Fail;
dvander@950
   406
				}
dvander@950
   407
			}
dvander@950
   408
dvander@950
   409
			CBaseEntity **ebuf = (CBaseEntity **)buffer;
dvander@950
   410
			*ebuf = pEntity;
dvander@950
   411
dvander@950
   412
			return Data_Okay;
dvander@950
   413
		}
dvander@950
   414
	case Valve_CBaseEntity:
dvander@950
   415
		{
dvander@950
   416
			edict_t *pEdict;
dvander@954
   417
			if (data->decflags & VDECODE_FLAG_BYREF)
dvander@950
   418
			{
dvander@950
   419
				cell_t *addr;
dvander@950
   420
				pContext->LocalToPhysAddr(param, &addr);
dvander@950
   421
				param = *addr;
dvander@950
   422
			}
dvander@950
   423
			if (param >= 1 && param <= playerhelpers->GetMaxClients())
dvander@950
   424
			{
dvander@950
   425
				IGamePlayer *player = playerhelpers->GetGamePlayer(param);
dvander@954
   426
				if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
dvander@950
   427
					&& !player->IsConnected())
dvander@950
   428
				{
dvander@950
   429
					pContext->ThrowNativeError("Client %d is not connected", param);
dvander@950
   430
					return Data_Fail;
dvander@950
   431
				} else if (!player->IsInGame()) {
dvander@950
   432
					pContext->ThrowNativeError("Client %d is not in game", param);
dvander@950
   433
					return Data_Fail;
dvander@950
   434
				}
dvander@950
   435
				pEdict = player->GetEdict();
dvander@950
   436
			} else if (param == -1) {
dvander@954
   437
				if (data->decflags & VDECODE_FLAG_ALLOWNULL)
dvander@950
   438
				{
dvander@950
   439
					pEdict = NULL;
dvander@950
   440
				} else {
dvander@950
   441
					pContext->ThrowNativeError("NULL not allowed");
dvander@950
   442
					return Data_Fail;
dvander@950
   443
				}
dvander@950
   444
			} else if (param == 0) {
dvander@954
   445
				if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
dvander@950
   446
				{
dvander@950
   447
					pEdict = engine->PEntityOfEntIndex(0);
dvander@950
   448
				} else {
dvander@950
   449
					pContext->ThrowNativeError("World not allowed");
dvander@950
   450
					return Data_Fail;
dvander@950
   451
				}
dvander@950
   452
			} else {
dvander@950
   453
				pEdict = engine->PEntityOfEntIndex(param);
dvander@950
   454
				if (!pEdict || pEdict->IsFree())
dvander@950
   455
				{
dvander@950
   456
					pContext->ThrowNativeError("Entity %d is not valid or is freed", param);
dvander@950
   457
					return Data_Fail;
dvander@950
   458
				}
dvander@950
   459
			}
dvander@956
   460
			CBaseEntity *pEntity = NULL;
dvander@950
   461
			if (pEdict)
dvander@950
   462
			{
dvander@950
   463
				IServerUnknown *pUnknown = pEdict->GetUnknown();
dvander@950
   464
				if (!pUnknown)
dvander@950
   465
				{
dvander@950
   466
					pContext->ThrowNativeError("Entity %d is a not an IServerUnknown");
dvander@950
   467
					return Data_Fail;
dvander@950
   468
				}
dvander@950
   469
				pEntity = pUnknown->GetBaseEntity();
dvander@950
   470
				if (!pEntity)
dvander@950
   471
				{
dvander@950
   472
					pContext->ThrowNativeError("Entity %d is not a CBaseEntity");
dvander@950
   473
					return Data_Fail;
dvander@950
   474
				}
dvander@950
   475
			}
dvander@950
   476
dvander@950
   477
			CBaseEntity **ebuf = (CBaseEntity **)buffer;
dvander@950
   478
			*ebuf = pEntity;
dvander@950
   479
dvander@950
   480
			return Data_Okay;
dvander@950
   481
		}
dvander@950
   482
	case Valve_Edict:
dvander@950
   483
		{
dvander@950
   484
			edict_t *pEdict;
dvander@954
   485
			if (data->decflags & VDECODE_FLAG_BYREF)
dvander@950
   486
			{
dvander@950
   487
				cell_t *addr;
dvander@950
   488
				pContext->LocalToPhysAddr(param, &addr);
dvander@950
   489
				param = *addr;
dvander@950
   490
			}
dvander@950
   491
			if (param >= 1 && param <= playerhelpers->GetMaxClients())
dvander@950
   492
			{
dvander@950
   493
				IGamePlayer *player = playerhelpers->GetGamePlayer(param);
dvander@954
   494
				if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
dvander@950
   495
					&& !player->IsConnected())
dvander@950
   496
				{
dvander@950
   497
					pContext->ThrowNativeError("Client %d is not connected", param);
dvander@950
   498
					return Data_Fail;
dvander@950
   499
				} else if (!player->IsInGame()) {
dvander@950
   500
					pContext->ThrowNativeError("Client %d is not in game", param);
dvander@950
   501
					return Data_Fail;
dvander@950
   502
				}
dvander@950
   503
				pEdict = player->GetEdict();
dvander@950
   504
			} else if (param == -1) {
dvander@954
   505
				if (data->decflags & VDECODE_FLAG_ALLOWNULL)
dvander@950
   506
				{
dvander@950
   507
					pEdict = NULL;
dvander@950
   508
				} else {
dvander@950
   509
					pContext->ThrowNativeError("NULL not allowed");
dvander@950
   510
					return Data_Fail;
dvander@950
   511
				}
dvander@950
   512
			} else if (param == 0) {
dvander@954
   513
				if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
dvander@950
   514
				{
dvander@950
   515
					pEdict = engine->PEntityOfEntIndex(0);
dvander@950
   516
				} else {
dvander@950
   517
					pContext->ThrowNativeError("World not allowed");
dvander@950
   518
					return Data_Fail;
dvander@950
   519
				}
dvander@950
   520
			} else {
dvander@950
   521
				pEdict = engine->PEntityOfEntIndex(param);
dvander@950
   522
				if (!pEdict || pEdict->IsFree())
dvander@950
   523
				{
dvander@950
   524
					pContext->ThrowNativeError("Entity %d is not valid or is freed", param);
dvander@950
   525
					return Data_Fail;
dvander@950
   526
				}
dvander@950
   527
			}
dvander@950
   528
dvander@950
   529
			edict_t **ebuf = (edict_t **)buffer;
dvander@950
   530
			*ebuf = pEdict;
dvander@950
   531
dvander@950
   532
			return Data_Okay;
dvander@950
   533
		}
dvander@950
   534
	case Valve_POD:
dvander@950
   535
	case Valve_Float:
dvander@950
   536
		{
dvander@954
   537
			if (data->decflags & VDECODE_FLAG_BYREF)
dvander@950
   538
			{
dvander@950
   539
				cell_t *addr;
dvander@950
   540
				pContext->LocalToPhysAddr(param, &addr);
dvander@950
   541
				param = *addr;
dvander@950
   542
			}
dvander@954
   543
			if (data->flags & PASSFLAG_ASPOINTER)
dvander@954
   544
			{
dvander@954
   545
				*(void **)buffer = (char *)buffer + sizeof(void *);
dvander@954
   546
				buffer = *(void **)buffer;
dvander@954
   547
			}
dvander@950
   548
			*(cell_t *)buffer = param;
dvander@950
   549
			return Data_Okay;
dvander@950
   550
		}
dvander@954
   551
	case Valve_Bool:
dvander@954
   552
		{
dvander@954
   553
			if (data->decflags & VDECODE_FLAG_BYREF)
dvander@954
   554
			{
dvander@954
   555
				cell_t *addr;
dvander@954
   556
				pContext->LocalToPhysAddr(param, &addr);
dvander@954
   557
				param = *addr;
dvander@954
   558
			}
dvander@954
   559
			if (data->flags & PASSFLAG_ASPOINTER)
dvander@954
   560
			{
dvander@954
   561
				*(bool **)buffer = (bool *)((char *)buffer + sizeof(bool *));
dvander@954
   562
				buffer = *(bool **)buffer;
dvander@954
   563
			}
dvander@954
   564
			*(bool *)buffer = param ? true : false;
dvander@954
   565
			return Data_Okay;
dvander@954
   566
		}
dvander@950
   567
	case Valve_String:
dvander@950
   568
		{
dvander@950
   569
			char *addr;
dvander@950
   570
			pContext->LocalToString(param, &addr);
dvander@950
   571
			*(char **)buffer = addr;
dvander@950
   572
			return Data_Okay;
dvander@950
   573
		}
dvander@950
   574
	}
dvander@950
   575
dvander@950
   576
	return Data_Fail;
dvander@950
   577
}