extensions/sdktools/vdecoder.cpp
author Scott Ehlert <ds@alliedmods.net>
Wed Aug 15 06:19:30 2007 +0000 (2007-08-15)
changeset 1330 ab94316bb52b
parent 1233 e9cfc03b9bb8
child 1498 e7eb59f70ff6
permissions -rw-r--r--
Updated license headers on virtually all files with extremely minor changes in the name of some sort of strange consistency.
All plugin and include file headers also have been changed to say about GPL3 instead of GPL2.

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