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