extensions/structs/natives.cpp
author Asher Baker <asherkin@gmail.com>
Thu Apr 26 16:58:18 2012 +0100 (2012-04-26)
changeset 3488 bee90c8ef6c3
parent 2348 befb05075881
permissions -rw-r--r--
Fixed client serials not being unique on Windows (bug 5285, r=psychonic).
     1 /**
     2 * vim: set ts=4 :
     3 * =============================================================================
     4 * SourceMod Sample Extension
     5 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6 * =============================================================================
     7 *
     8 * This program is free software; you can redistribute it and/or modify it under
     9 * the terms of the GNU General Public License, version 3.0, as published by the
    10 * Free Software Foundation.
    11 * 
    12 * This program is distributed in the hope that it will be useful, but WITHOUT
    13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15 * details.
    16 *
    17 * You should have received a copy of the GNU General Public License along with
    18 * this program.  If not, see <http://www.gnu.org/licenses/>.
    19 *
    20 * As a special exception, AlliedModders LLC gives you permission to link the
    21 * code of this program (as well as its derivative works) to "Half-Life 2," the
    22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23 * by the Valve Corporation.  You must obey the GNU General Public License in
    24 * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25 * this exception to all derivative works.  AlliedModders LLC defines further
    26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27 * or <http://www.sourcemod.net/license.php>.
    28 *
    29 * Version: $Id$
    30 */
    31 
    32 #include "extension.h"
    33 #include "utldict.h"
    34 
    35 class FileWeaponInfo_t;
    36 typedef unsigned short WEAPON_FILE_INFO_HANDLE;
    37 
    38 inline edict_t *GetEdict(cell_t num)
    39 {
    40 	edict_t *pEdict = engine->PEntityOfEntIndex(num);
    41 	if (!pEdict || pEdict->IsFree())
    42 	{
    43 		return NULL;
    44 	}
    45 
    46 	return pEdict;
    47 }
    48 
    49 inline edict_t *GetEntity(cell_t num, CBaseEntity **pData)
    50 {
    51 	edict_t *pEdict = engine->PEntityOfEntIndex(num);
    52 	if (!pEdict || pEdict->IsFree())
    53 	{
    54 		return NULL;
    55 	}
    56 
    57 	IServerUnknown *pUnk;
    58 	if ((pUnk=pEdict->GetUnknown()) == NULL)
    59 	{
    60 		return NULL;
    61 	}
    62 	*pData = pUnk->GetBaseEntity();
    63 	return pEdict;
    64 }
    65 
    66 int CheckBaseHandle(CBaseHandle &hndl)
    67 {
    68 	if (!hndl.IsValid())
    69 	{
    70 		return -1;
    71 	}
    72 
    73 	int index = hndl.GetEntryIndex();
    74 
    75 	edict_t *pStoredEdict;
    76 	CBaseEntity *pStoredEntity;
    77 
    78 	pStoredEdict = GetEntity(index, &pStoredEntity);
    79 
    80 	if (pStoredEdict == NULL || pStoredEntity == NULL)
    81 	{
    82 		return -1;
    83 	}
    84 
    85 	IServerEntity *pSE = pStoredEdict->GetIServerEntity();
    86 
    87 	if (pSE == NULL)
    88 	{
    89 		return -1;
    90 	}
    91 
    92 	if (pSE->GetRefEHandle() != hndl)
    93 	{
    94 		return -1;
    95 	}
    96 
    97 	return index;
    98 }
    99 
   100 //native GetStructInt(Handle:struct, const String:member[]);
   101 static cell_t GetStructInt(IPluginContext *pContext, const cell_t *params)
   102 {
   103 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   104 	HandleError err;
   105 	HandleSecurity sec;
   106 
   107 	sec.pOwner = NULL;
   108 	sec.pIdentity = myself->GetIdentity();
   109 
   110 	StructHandle *pHandle;
   111 	if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle))
   112 		!= HandleError_None)
   113 	{
   114 		return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err);
   115 	}
   116 
   117 	char *member;
   118 	pContext->LocalToString(params[2], &member);
   119 
   120 	int value;
   121 
   122 	if (!pHandle->GetInt(member, &value))
   123 	{
   124 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   125 	}
   126 
   127 	return value;
   128 }
   129 
   130 //native SetStructInt(Handle:struct, const String:member[], value);
   131 static cell_t SetStructInt(IPluginContext *pContext, const cell_t *params)
   132 {
   133 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   134 	HandleError err;
   135 	HandleSecurity sec;
   136 
   137 	sec.pOwner = NULL;
   138 	sec.pIdentity = myself->GetIdentity();
   139 
   140 	StructHandle *pHandle;
   141 	if ((err = handlesys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle))
   142 		!= HandleError_None)
   143 	{
   144 		return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err);
   145 	}
   146 
   147 	char *member;
   148 	pContext->LocalToString(params[2], &member);
   149 
   150 	if (!pHandle->SetInt(member, params[3]))
   151 	{
   152 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   153 	}
   154 
   155 	return 1;
   156 }
   157 
   158 //native GetStructFloat(Handle:struct, const String:member[], &Float:value);
   159 static cell_t GetStructFloat(IPluginContext *pContext, const cell_t *params)
   160 {
   161 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   162 	HandleError err;
   163 	HandleSecurity sec;
   164 
   165 	sec.pOwner = NULL;
   166 	sec.pIdentity = myself->GetIdentity();
   167 
   168 	StructHandle *pHandle;
   169 	if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle))
   170 		!= HandleError_None)
   171 	{
   172 		return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err);
   173 	}
   174 
   175 	char *member;
   176 	pContext->LocalToString(params[2], &member);
   177 
   178 	float value;
   179 
   180 	if (!pHandle->GetFloat(member, &value))
   181 	{
   182 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   183 	}
   184 
   185 	return sp_ftoc(value);
   186 }	
   187 
   188 //native SetStructFloat(Handle:struct, const String:member[], Float:value);
   189 static cell_t SetStructFloat(IPluginContext *pContext, const cell_t *params)
   190 {
   191 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   192 	HandleError err;
   193 	HandleSecurity sec;
   194 
   195 	sec.pOwner = NULL;
   196 	sec.pIdentity = myself->GetIdentity();
   197 
   198 	StructHandle *pHandle;
   199 	if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle))
   200 		!= HandleError_None)
   201 	{
   202 		return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err);
   203 	}
   204 
   205 	char *member;
   206 	pContext->LocalToString(params[2], &member);
   207 
   208 	if (!pHandle->SetFloat(member, sp_ctof(params[3])))
   209 	{
   210 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   211 	}
   212 
   213 	return 1;
   214 }
   215 
   216 //native GetStructVector(Handle:struct, const String:member[], Float:vec[3]);
   217 static cell_t GetStructVector(IPluginContext *pContext, const cell_t *params)
   218 {
   219 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   220 	HandleError err;
   221 	HandleSecurity sec;
   222 
   223 	sec.pOwner = NULL;
   224 	sec.pIdentity = myself->GetIdentity();
   225 
   226 	StructHandle *pHandle;
   227 	if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle))
   228 		!= HandleError_None)
   229 	{
   230 		return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err);
   231 	}
   232 
   233 	char *member;
   234 	pContext->LocalToString(params[2], &member);
   235 
   236 	cell_t *addr;
   237 	pContext->LocalToPhysAddr(params[3], &addr);
   238 
   239 	Vector value;
   240 
   241 	if (!pHandle->GetVector(member, &value))
   242 	{
   243 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   244 	}
   245 
   246 	addr[0] = sp_ftoc(value.x);
   247 	addr[1] = sp_ftoc(value.y);
   248 	addr[2] = sp_ftoc(value.z);
   249 
   250 	return 1;
   251 }
   252 
   253 //native SetStructVector(Handle:struct, const String:member[], Float:vec[3]);
   254 static cell_t SetStructVector(IPluginContext *pContext, const cell_t *params)
   255 {
   256 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   257 	HandleError err;
   258 	HandleSecurity sec;
   259 
   260 	sec.pOwner = NULL;
   261 	sec.pIdentity = myself->GetIdentity();
   262 
   263 	StructHandle *pHandle;
   264 	if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle))
   265 		!= HandleError_None)
   266 	{
   267 		return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err);
   268 	}
   269 
   270 	char *member;
   271 	pContext->LocalToString(params[2], &member);
   272 
   273 	Vector value;
   274 
   275 	cell_t *addr;
   276 	pContext->LocalToPhysAddr(params[3], &addr);
   277 
   278 	value.x = sp_ctof(addr[0]);
   279 	value.y = sp_ctof(addr[1]);
   280 	value.z = sp_ctof(addr[2]);
   281 
   282 	if (!pHandle->SetVector(member, value))
   283 	{
   284 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   285 	}
   286 
   287 	return 1;
   288 }
   289 
   290 //native GetStructString(Handle:struct, const String:member[], String:value[], maxlen);
   291 static cell_t GetStructString(IPluginContext *pContext, const cell_t *params)
   292 {
   293 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   294 	HandleError err;
   295 	HandleSecurity sec;
   296 
   297 	sec.pOwner = NULL;
   298 	sec.pIdentity = myself->GetIdentity();
   299 
   300 	StructHandle *pHandle;
   301 	if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle))
   302 		!= HandleError_None)
   303 	{
   304 		return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err);
   305 	}
   306 
   307 	char *member;
   308 	pContext->LocalToString(params[2], &member);
   309 
   310 	char *string;
   311 	if (!pHandle->GetString(member, &string))
   312 	{
   313 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   314 	}
   315 
   316 	pContext->StringToLocal(params[3], params[4], string);
   317 
   318 	return 1;
   319 }
   320 
   321 //native SetStructString(Handle:struct, const String:member[], String:value[]);
   322 static cell_t SetStructString(IPluginContext *pContext, const cell_t *params)
   323 {
   324 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   325 	HandleError err;
   326 	HandleSecurity sec;
   327 
   328 	sec.pOwner = NULL;
   329 	sec.pIdentity = myself->GetIdentity();
   330 
   331 	StructHandle *pHandle;
   332 	if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle))
   333 		!= HandleError_None)
   334 	{
   335 		return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err);
   336 	}
   337 
   338 	char *member;
   339 	pContext->LocalToString(params[2], &member);
   340 
   341 	char *string;
   342 	pContext->LocalToString(params[3], &string);
   343 
   344 	if (!pHandle->SetString(member, string))
   345 	{
   346 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   347 	}
   348 
   349 	return 1;
   350 }
   351 
   352 //native GetStructEnt(Handle:struct, const String:member[], &ent);
   353 static cell_t GetStructEnt(IPluginContext *pContext, const cell_t *params)
   354 {
   355 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   356 	HandleError err;
   357 	HandleSecurity sec;
   358 
   359 	sec.pOwner = NULL;
   360 	sec.pIdentity = myself->GetIdentity();
   361 
   362 	StructHandle *pHandle;
   363 	if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle))
   364 		!= HandleError_None)
   365 	{
   366 		return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err);
   367 	}
   368 
   369 	char *member;
   370 	pContext->LocalToString(params[2], &member);
   371 
   372 	CBaseHandle *value;
   373 	if (!pHandle->GetEHandle(member, &value))
   374 	{
   375 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   376 	}
   377 
   378 	return CheckBaseHandle(*value);
   379 }
   380 
   381 //native SetStructEnt(Handle:struct, const String:member[], ent);
   382 static cell_t SetStructEnt(IPluginContext *pContext, const cell_t *params)
   383 {
   384 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   385 	HandleError err;
   386 	HandleSecurity sec;
   387 
   388 	sec.pOwner = NULL;
   389 	sec.pIdentity = myself->GetIdentity();
   390 
   391 	StructHandle *pHandle;
   392 	if ((err = g_pHandleSys->ReadHandle(hndl, g_StructHandle, &sec, (void **)&pHandle))
   393 		!= HandleError_None)
   394 	{
   395 		return pContext->ThrowNativeError("Invalid struct handle %x (error %d)", hndl, err);
   396 	}
   397 
   398 	char *member;
   399 	pContext->LocalToString(params[2], &member);
   400 
   401 	CBaseHandle *value;
   402 	if (!pHandle->GetEHandle(member, &value))
   403 	{
   404 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   405 	}
   406 
   407 	edict_t *pEdict = GetEdict(params[3]);
   408 
   409 	if (pEdict == NULL)
   410 	{
   411 		return pContext->ThrowNativeError("Invalid entity %i", params[3]);
   412 	}
   413 
   414 	IServerEntity *pEntOther = pEdict->GetIServerEntity();
   415 	value->Set(pEntOther);
   416 
   417 	if (!pHandle->SetEHandle(member, value))
   418 	{
   419 		return pContext->ThrowNativeError("Invalid member, or incorrect data type");
   420 	}
   421 
   422 	return 1;
   423 }
   424 
   425 static cell_t GetWeaponStruct(IPluginContext *pContext, const cell_t *params)
   426 {
   427 	char *weapon;
   428 	pContext->LocalToString(params[1], &weapon);
   429 
   430 	void **func;
   431 
   432 #if defined WIN32
   433 	void *addr = NULL;
   434 	func = &addr;
   435 #else
   436 	WEAPON_FILE_INFO_HANDLE (*LookupWeaponInfoSlot)(const char *) = NULL;
   437 	func = (void **)&LookupWeaponInfoSlot;
   438 #endif
   439 
   440 	FileWeaponInfo_t *(*GetFileWeaponInfoFromHandle)( WEAPON_FILE_INFO_HANDLE handle ) = NULL;
   441 
   442 	if (!conf->GetMemSig("LookupWeaponInfoSlot", func) || *func == NULL)
   443 	{
   444 		return pContext->ThrowNativeError("Failed to locate signature LookupWeaponInfoSlot");
   445 	}
   446 
   447 	if (!conf->GetMemSig("GetFileWeaponInfoFromHandle", (void **)&GetFileWeaponInfoFromHandle) || GetFileWeaponInfoFromHandle == NULL)
   448 	{
   449 		return pContext->ThrowNativeError("Failed to locate signature GetFileWeaponInfoFromHandle");
   450 	}
   451 
   452 #if defined WIN32
   453 	int offset;
   454 
   455 	if (!conf->GetOffset("m_WeaponInfoDatabase", &offset))
   456 	{
   457 		return pContext->ThrowNativeError("Failed to locate offset m_WeaponInfoDatabase");
   458 	}
   459 
   460 	addr = (unsigned char *)addr + offset;
   461 
   462 	CUtlDict< FileWeaponInfo_t*, unsigned short > *m_WeaponInfoDatabase = *(CUtlDict< FileWeaponInfo_t*, unsigned short > **)addr;
   463 
   464 	WEAPON_FILE_INFO_HANDLE handle = m_WeaponInfoDatabase->Find(weapon);
   465 
   466 	if (handle == -1 || handle == m_WeaponInfoDatabase->InvalidIndex())
   467 	{
   468 		return pContext->ThrowNativeError("Could not find weapon %s", weapon);
   469 	}
   470 #else
   471 	WEAPON_FILE_INFO_HANDLE handle = LookupWeaponInfoSlot(weapon);
   472 #endif
   473 	FileWeaponInfo_t *info = GetFileWeaponInfoFromHandle(handle);
   474 
   475 	//g_pSM->LogMessage(myself, "%i %i %x", handle, GetInvalidWeaponInfoHandle(), info);
   476 
   477 	if (!info)
   478 	{
   479 		return pContext->ThrowNativeError("Weapon does not exist!");
   480 	}
   481 
   482 	/* Offsets! */
   483 	/*
   484 	g_pSM->LogMessage(myself, "Offsets for FileWeaponInfo_t");
   485 	g_pSM->LogMessage(myself, "bParsed: %i", (unsigned char *)&(info->bParsedScript) - (unsigned char *)info);
   486 	g_pSM->LogMessage(myself, "bLoadedHudElements: %i", (unsigned char *)&(info->bLoadedHudElements) - (unsigned char *)info);
   487 	g_pSM->LogMessage(myself, "szClassName: %i", (unsigned char *)&(info->szClassName) - (unsigned char *)info);
   488 	g_pSM->LogMessage(myself, "szPrintName: %i", (unsigned char *)&(info->szPrintName) - (unsigned char *)info);
   489 	g_pSM->LogMessage(myself, "szViewModel: %i", (unsigned char *)&(info->szViewModel) - (unsigned char *)info);
   490 	g_pSM->LogMessage(myself, "szWorldModel: %i", (unsigned char *)&(info->szWorldModel) - (unsigned char *)info);
   491 	g_pSM->LogMessage(myself, "szAnimationPrefix: %i", (unsigned char *)&(info->szAnimationPrefix) - (unsigned char *)info);
   492 	g_pSM->LogMessage(myself, "iSlot: %i", (unsigned char *)&(info->iSlot) - (unsigned char *)info);
   493 	g_pSM->LogMessage(myself, "iPosition: %i", (unsigned char *)&(info->iPosition) - (unsigned char *)info);
   494 	g_pSM->LogMessage(myself, "iMaxClip1: %i", (unsigned char *)&(info->iMaxClip1) - (unsigned char *)info);
   495 	g_pSM->LogMessage(myself, "iMaxClip2: %i", (unsigned char *)&(info->iMaxClip2) - (unsigned char *)info);
   496 	g_pSM->LogMessage(myself, "iDefaultClip1: %i", (unsigned char *)&(info->iDefaultClip1) - (unsigned char *)info);
   497 	g_pSM->LogMessage(myself, "iDefaultClip2: %i", (unsigned char *)&(info->iDefaultClip2) - (unsigned char *)info);
   498 	g_pSM->LogMessage(myself, "iWeight: %i", (unsigned char *)&(info->iWeight) - (unsigned char *)info);
   499 	g_pSM->LogMessage(myself, "iRumbleEffect: %i", (unsigned char *)&(info->iRumbleEffect) - (unsigned char *)info);
   500 	g_pSM->LogMessage(myself, "bAutoSwitchTo: %i", (unsigned char *)&(info->bAutoSwitchTo) - (unsigned char *)info);
   501 	g_pSM->LogMessage(myself, "bAutoSwitchFrom: %i", (unsigned char *)&(info->bAutoSwitchFrom) - (unsigned char *)info);
   502 	g_pSM->LogMessage(myself, "iFlags: %i", (unsigned char *)&(info->iFlags) - (unsigned char *)info);
   503 	g_pSM->LogMessage(myself, "szAmmo1: %i", (unsigned char *)&(info->szAmmo1) - (unsigned char *)info);
   504 	g_pSM->LogMessage(myself, "szAmmo2: %i", (unsigned char *)&(info->szAmmo2) - (unsigned char *)info);
   505 	g_pSM->LogMessage(myself, "aShootSounds: %i", (unsigned char *)&(info->aShootSounds) - (unsigned char *)info);
   506 	g_pSM->LogMessage(myself, "iAmmoType: %i", (unsigned char *)&(info->iAmmoType) - (unsigned char *)info);
   507 	g_pSM->LogMessage(myself, "iAmmo2Type: %i", (unsigned char *)&(info->iAmmo2Type) - (unsigned char *)info);
   508 	g_pSM->LogMessage(myself, "m_bMeleeWeapon: %i", (unsigned char *)&(info->m_bMeleeWeapon) - (unsigned char *)info);
   509 	g_pSM->LogMessage(myself, "m_bBuiltRightHanded: %i", (unsigned char *)&(info->m_bBuiltRightHanded) - (unsigned char *)info);
   510 	g_pSM->LogMessage(myself, "m_bAllowFlipping: %i", (unsigned char *)&(info->m_bAllowFlipping) - (unsigned char *)info);
   511 	*/
   512 	return g_StructManager.CreateStructHandle("FileWeaponInfo_t", info);
   513 };
   514 
   515 const sp_nativeinfo_t MyNatives[] = 
   516 {
   517 	{"GetStructInt",	GetStructInt},
   518 	{"SetStructInt",	SetStructInt},
   519 	{"GetStructFloat",	GetStructFloat},
   520 	{"SetStructFloat",	SetStructFloat},
   521 	{"GetStructVector",	GetStructVector},
   522 	{"SetStructVector",	SetStructVector},
   523 	{"GetStructString",	GetStructString},
   524 	{"SetStructString",	SetStructString},
   525 	{"GetStructEnt",	GetStructEnt},
   526 	{"SetStructEnt",	SetStructEnt},
   527 	{"GetWeaponStruct",	GetWeaponStruct},
   528 	{NULL,				NULL},
   529 };