core/smn_keyvalues.cpp
author Phong Dang <teame06@gmail.com>
Wed Aug 01 07:29:40 2007 +0000 (2007-08-01)
changeset 1241 2e8046793bc9
parent 1231 17badaf66ce4
child 1330 ab94316bb52b
permissions -rw-r--r--
Added check to make sure player are alive to perform sm_slap, sm_burn, sm_slay.
     1 /**
     2  * vim: set ts=4 :
     3  * ================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
     6  * ================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or 
     9  * modify it under the terms of the GNU General Public License, 
    10  * version 3.0, as published by the Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  * GNU General Public License for more details.
    16  *
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to 
    21  * link the code of this program (as well as its derivative works) to 
    22  * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
    23  * Game MODs that run on software by the Valve Corporation.  You must 
    24  * obey the GNU General Public License in all respects for all other 
    25  * code used. Additionally, AlliedModders LLC grants this exception 
    26  * to all derivative works. AlliedModders LLC defines further 
    27  * exceptions, found in LICENSE.txt (as of this writing, version 
    28  * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
    29  *
    30  * Version: $Id$
    31  */
    32 
    33 #include "sourcemod.h"
    34 #include "sourcemm_api.h"
    35 #include "sm_stringutil.h"
    36 #include "HandleSys.h"
    37 #include <KeyValues.h>
    38 
    39 HandleType_t g_KeyValueType;
    40 
    41 struct KeyValueStack 
    42 {
    43 	KeyValues *pBase;
    44 	CStack<KeyValues *> pCurRoot;
    45 };
    46 
    47 class KeyValueNatives : 
    48 	public SMGlobalClass,
    49 	public IHandleTypeDispatch
    50 {
    51 public:
    52 	void OnSourceModAllInitialized()
    53 	{
    54 		g_KeyValueType = g_HandleSys.CreateType("KeyValues", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    55 	}
    56 	void OnSourceModShutdown()
    57 	{
    58 		g_HandleSys.RemoveType(g_KeyValueType, g_pCoreIdent);
    59 		g_KeyValueType = 0;
    60 	}
    61 	void OnHandleDestroy(HandleType_t type, void *object)
    62 	{
    63 		KeyValueStack *pStk = reinterpret_cast<KeyValueStack *>(object);
    64 		pStk->pBase->deleteThis();
    65 		delete pStk;
    66 	}
    67 };
    68 
    69 KeyValues *SourceModBase::ReadKeyValuesHandle(Handle_t hndl, HandleError *err, bool root)
    70 {
    71 	HandleError herr;
    72 	HandleSecurity sec;
    73 	KeyValueStack *pStk;
    74 
    75 	sec.pOwner = NULL;
    76 	sec.pIdentity = g_pCoreIdent;
    77 
    78 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
    79 		!= HandleError_None)
    80 	{
    81 		if (err)
    82 		{
    83 			*err = herr;
    84 		}
    85 		return NULL;
    86 	}
    87 
    88 	if (err)
    89 	{
    90 		*err = HandleError_None;
    91 	}
    92 
    93 	return (root) ? pStk->pBase : pStk->pCurRoot.front();
    94 }
    95 
    96 static cell_t smn_KvSetString(IPluginContext *pCtx, const cell_t *params)
    97 {
    98 	Handle_t hndl = static_cast<Handle_t>(params[1]);
    99 	HandleError herr;
   100 	HandleSecurity sec;
   101 	KeyValueStack *pStk;
   102 
   103 	sec.pOwner = NULL;
   104 	sec.pIdentity = g_pCoreIdent;
   105 
   106 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   107 		!= HandleError_None)
   108 	{
   109 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   110 	}
   111 
   112 	char *key, *value;
   113 	pCtx->LocalToStringNULL(params[2], &key);
   114 	pCtx->LocalToString(params[3], &value);
   115 
   116 	pStk->pCurRoot.front()->SetString(key, value);
   117 
   118 	return 1;
   119 }
   120 
   121 static cell_t smn_KvSetNum(IPluginContext *pCtx, const cell_t *params)
   122 {
   123 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   124 	HandleError herr;
   125 	HandleSecurity sec;
   126 	KeyValueStack *pStk;
   127 
   128 	sec.pOwner = NULL;
   129 	sec.pIdentity = g_pCoreIdent;
   130 
   131 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   132 		!= HandleError_None)
   133 	{
   134 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   135 	}
   136 
   137 	char *key;
   138 	pCtx->LocalToStringNULL(params[2], &key);
   139 
   140 	pStk->pCurRoot.front()->SetInt(key, params[3]);
   141 
   142 	return 1;
   143 }
   144 
   145 static cell_t smn_KvSetUInt64(IPluginContext *pCtx, const cell_t *params)
   146 {
   147 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   148 	HandleError herr;
   149 	HandleSecurity sec;
   150 	KeyValueStack *pStk;
   151 
   152 	sec.pOwner = NULL;
   153 	sec.pIdentity = g_pCoreIdent;
   154 
   155 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   156 		!= HandleError_None)
   157 	{
   158 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   159 	}
   160 
   161 	char *key;
   162 	cell_t *addr;
   163 	uint64 value;
   164 	pCtx->LocalToStringNULL(params[2], &key);
   165 	pCtx->LocalToPhysAddr(params[3], &addr);
   166 
   167 	value = static_cast<uint64>(*addr);
   168 	pStk->pCurRoot.front()->SetUint64(key, value);
   169 
   170 	return 1;
   171 }
   172 
   173 static cell_t smn_KvSetFloat(IPluginContext *pCtx, const cell_t *params)
   174 {
   175 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   176 	HandleError herr;
   177 	HandleSecurity sec;
   178 	KeyValueStack *pStk;
   179 
   180 	sec.pOwner = NULL;
   181 	sec.pIdentity = g_pCoreIdent;
   182 
   183 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   184 		!= HandleError_None)
   185 	{
   186 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   187 	}
   188 
   189 	char *key;
   190 	pCtx->LocalToStringNULL(params[2], &key);
   191 
   192 	pStk->pCurRoot.front()->SetFloat(key, sp_ctof(params[3]));
   193 
   194 	return 1;
   195 }
   196 
   197 static cell_t smn_KvSetColor(IPluginContext *pCtx, const cell_t *params)
   198 {
   199 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   200 	HandleError herr;
   201 	HandleSecurity sec;
   202 	KeyValueStack *pStk;
   203 
   204 	sec.pOwner = NULL;
   205 	sec.pIdentity = g_pCoreIdent;
   206 
   207 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   208 		!= HandleError_None)
   209 	{
   210 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   211 	}
   212 
   213 	char *key;
   214 	pCtx->LocalToStringNULL(params[2], &key);
   215 
   216 	Color color(params[3], params[4], params[5], params[6]);
   217 	pStk->pCurRoot.front()->SetColor(key, color);
   218 
   219 	return 1;
   220 }
   221 
   222 static cell_t smn_KvGetString(IPluginContext *pCtx, const cell_t *params)
   223 {
   224 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   225 	HandleError herr;
   226 	HandleSecurity sec;
   227 	KeyValueStack *pStk;
   228 
   229 	sec.pOwner = NULL;
   230 	sec.pIdentity = g_pCoreIdent;
   231 
   232 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   233 		!= HandleError_None)
   234 	{
   235 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   236 	}
   237 
   238 	const char *value;
   239 	char *key, *defvalue;
   240 	pCtx->LocalToStringNULL(params[2], &key);
   241 	pCtx->LocalToString(params[5], &defvalue);
   242 
   243 	value = pStk->pCurRoot.front()->GetString(key, defvalue);
   244 	pCtx->StringToLocalUTF8(params[3], params[4], value, NULL);
   245 
   246 	return 1;
   247 }
   248 
   249 static cell_t smn_KvGetNum(IPluginContext *pCtx, const cell_t *params)
   250 {
   251 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   252 	HandleError herr;
   253 	HandleSecurity sec;
   254 	KeyValueStack *pStk;
   255 
   256 	sec.pOwner = NULL;
   257 	sec.pIdentity = g_pCoreIdent;
   258 
   259 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   260 		!= HandleError_None)
   261 	{
   262 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   263 	}
   264 
   265 	int value;
   266 	char *key;
   267 	pCtx->LocalToStringNULL(params[2], &key);
   268 
   269 	value = pStk->pCurRoot.front()->GetInt(key, params[3]);
   270 
   271 	return value;
   272 }
   273 
   274 static cell_t smn_KvGetFloat(IPluginContext *pCtx, const cell_t *params)
   275 {
   276 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   277 	HandleError herr;
   278 	HandleSecurity sec;
   279 	KeyValueStack *pStk;
   280 
   281 	sec.pOwner = NULL;
   282 	sec.pIdentity = g_pCoreIdent;
   283 
   284 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   285 		!= HandleError_None)
   286 	{
   287 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   288 	}
   289 
   290 	float value;
   291 	char *key;
   292 	pCtx->LocalToStringNULL(params[2], &key);
   293 
   294 	value = pStk->pCurRoot.front()->GetFloat(key, sp_ctof(params[3]));
   295 
   296 	return sp_ftoc(value);
   297 }
   298 
   299 static cell_t smn_KvGetColor(IPluginContext *pCtx, const cell_t *params)
   300 {
   301 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   302 	HandleError herr;
   303 	HandleSecurity sec;
   304 	KeyValueStack *pStk;
   305 
   306 	sec.pOwner = NULL;
   307 	sec.pIdentity = g_pCoreIdent;
   308 
   309 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   310 		!= HandleError_None)
   311 	{
   312 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   313 	}
   314 
   315 	Color color;
   316 	char *key;
   317 	cell_t *r, *g, *b, *a;
   318 	pCtx->LocalToStringNULL(params[2], &key);
   319 	pCtx->LocalToPhysAddr(params[3], &r);
   320 	pCtx->LocalToPhysAddr(params[4], &g);
   321 	pCtx->LocalToPhysAddr(params[5], &b);
   322 	pCtx->LocalToPhysAddr(params[6], &a);
   323 
   324 	color = pStk->pCurRoot.front()->GetColor(key);
   325 	*r = color.r();
   326 	*g = color.g();
   327 	*b = color.b();
   328 	*a = color.a();
   329 
   330 	return 1;
   331 }
   332 
   333 static cell_t smn_KvGetUInt64(IPluginContext *pCtx, const cell_t *params)
   334 {
   335 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   336 	HandleError herr;
   337 	HandleSecurity sec;
   338 	KeyValueStack *pStk;
   339 
   340 	sec.pOwner = NULL;
   341 	sec.pIdentity = g_pCoreIdent;
   342 
   343 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   344 		!= HandleError_None)
   345 	{
   346 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   347 	}
   348 
   349 	char *key;
   350 	cell_t *addr, *defvalue;
   351 	uint64 value;
   352 	pCtx->LocalToStringNULL(params[2], &key);
   353 	pCtx->LocalToPhysAddr(params[3], &addr);
   354 	pCtx->LocalToPhysAddr(params[4], &defvalue);
   355 
   356 	value = pStk->pCurRoot.front()->GetUint64(key, static_cast<uint64>(*defvalue));
   357 	*reinterpret_cast<uint64 *>(addr) = value;
   358 
   359 	return 1;
   360 }
   361 
   362 static cell_t smn_CreateKeyValues(IPluginContext *pCtx, const cell_t *params)
   363 {
   364 	KeyValueStack *pStk;
   365 	char *name, *firstkey, *firstvalue;
   366 	bool is_empty;
   367 
   368 	pCtx->LocalToString(params[1], &name);
   369 	pCtx->LocalToString(params[2], &firstkey);
   370 	pCtx->LocalToString(params[3], &firstvalue);
   371 
   372 	is_empty = (firstkey[0] == '\0');
   373 	pStk = new KeyValueStack;
   374 	pStk->pBase = new KeyValues(name, is_empty ? NULL : firstkey, (is_empty||(firstvalue[0]=='\0')) ? NULL : firstvalue);
   375 	pStk->pCurRoot.push(pStk->pBase);
   376 
   377 	return g_HandleSys.CreateHandle(g_KeyValueType, pStk, pCtx->GetIdentity(), g_pCoreIdent, NULL);
   378 }
   379 
   380 static cell_t smn_KvJumpToKey(IPluginContext *pCtx, const cell_t *params)
   381 {
   382 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   383 	HandleError herr;
   384 	HandleSecurity sec;
   385 	char *name;	
   386 	KeyValueStack *pStk;
   387 
   388 	sec.pOwner = NULL;
   389 	sec.pIdentity = g_pCoreIdent;
   390 
   391 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   392 		!= HandleError_None)
   393 	{
   394 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   395 	}
   396 
   397 	pCtx->LocalToString(params[2], &name);
   398 
   399 	KeyValues *pSubKey = pStk->pCurRoot.front();
   400 	pSubKey = pSubKey->FindKey(name, (params[3]) ? true : false);
   401 	if (!pSubKey)
   402 	{
   403 		return 0;
   404 	}
   405 	pStk->pCurRoot.push(pSubKey);
   406 
   407 	return 1;
   408 }
   409 
   410 static cell_t smn_KvGotoFirstSubKey(IPluginContext *pCtx, const cell_t *params)
   411 {
   412 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   413 	HandleError herr;
   414 	HandleSecurity sec;
   415 	KeyValueStack *pStk;
   416 
   417 	sec.pOwner = NULL;
   418 	sec.pIdentity = g_pCoreIdent;
   419 
   420 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   421 		!= HandleError_None)
   422 	{
   423 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   424 	}
   425 
   426 	KeyValues *pSubKey = pStk->pCurRoot.front();
   427 	KeyValues *pFirstSubKey;
   428 	if (params[2])
   429 	{
   430 		pFirstSubKey = pSubKey->GetFirstTrueSubKey();
   431 	} else {
   432 		pFirstSubKey = pSubKey->GetFirstSubKey();
   433 	}
   434 
   435 	if (!pFirstSubKey)
   436 	{
   437 		return 0;
   438 	}
   439 	pStk->pCurRoot.push(pFirstSubKey);
   440 
   441 	return 1;
   442 }
   443 
   444 static cell_t smn_KvGotoNextKey(IPluginContext *pCtx, const cell_t *params)
   445 {
   446 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   447 	HandleError herr;
   448 	HandleSecurity sec;
   449 	KeyValueStack *pStk;
   450 
   451 	sec.pOwner = NULL;
   452 	sec.pIdentity = g_pCoreIdent;
   453 
   454 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   455 		!= HandleError_None)
   456 	{
   457 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   458 	}
   459 
   460 	KeyValues *pSubKey = pStk->pCurRoot.front();
   461 	if (params[2])
   462 	{
   463 		pSubKey = pSubKey->GetNextTrueSubKey();
   464 	} else {
   465 		pSubKey = pSubKey->GetNextKey();
   466 	}
   467 	if (!pSubKey)
   468 	{
   469 		return 0;
   470 	}
   471 	pStk->pCurRoot.pop();
   472 	pStk->pCurRoot.push(pSubKey);
   473 
   474 	return 1;	
   475 }
   476 
   477 static cell_t smn_KvJumpNextSubKey(IPluginContext *pCtx, const cell_t *params)
   478 {
   479 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   480 	HandleError herr;
   481 	HandleSecurity sec;
   482 	KeyValueStack *pStk;
   483 
   484 	sec.pOwner = NULL;
   485 	sec.pIdentity = g_pCoreIdent;
   486 
   487 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   488 		!= HandleError_None)
   489 	{
   490 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   491 	}
   492 
   493 	KeyValues *pSubKey = pStk->pCurRoot.front();
   494 	KeyValues *pNextKey = pSubKey->GetNextKey();
   495 	if (!pNextKey)
   496 	{
   497 		return 0;
   498 	}
   499 	pStk->pCurRoot.push(pNextKey);
   500 
   501 	return 1;	
   502 }
   503 
   504 static cell_t smn_KvGoBack(IPluginContext *pCtx, const cell_t *params)
   505 {
   506 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   507 	HandleError herr;
   508 	HandleSecurity sec;
   509 	KeyValueStack *pStk;
   510 
   511 	sec.pOwner = NULL;
   512 	sec.pIdentity = g_pCoreIdent;
   513 
   514 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   515 		!= HandleError_None)
   516 	{
   517 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   518 	}
   519 
   520 	if (pStk->pCurRoot.size() == 1)
   521 	{
   522 		return 0;
   523 	}
   524 	pStk->pCurRoot.pop();
   525 
   526 	return 1;
   527 }
   528 
   529 static cell_t smn_KvRewind(IPluginContext *pCtx, const cell_t *params)
   530 {
   531 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   532 	HandleError herr;
   533 	HandleSecurity sec;
   534 	KeyValueStack *pStk;
   535 
   536 	sec.pOwner = NULL;
   537 	sec.pIdentity = g_pCoreIdent;
   538 
   539 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   540 		!= HandleError_None)
   541 	{
   542 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   543 	}
   544 
   545 	while (pStk->pCurRoot.size() > 1)
   546 	{
   547 		pStk->pCurRoot.pop();
   548 	}
   549 
   550 	return 1;
   551 }
   552 
   553 static cell_t smn_KvGetSectionName(IPluginContext *pCtx, const cell_t *params)
   554 {
   555 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   556 	HandleError herr;
   557 	HandleSecurity sec;
   558 	KeyValueStack *pStk;
   559 
   560 	sec.pOwner = NULL;
   561 	sec.pIdentity = g_pCoreIdent;
   562 
   563 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   564 		!= HandleError_None)
   565 	{
   566 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   567 	}
   568 
   569 	KeyValues *pSection = pStk->pCurRoot.front();
   570 	const char *name = pSection->GetName();
   571 	if (!name)
   572 	{
   573 		return 0;
   574 	}
   575 	pCtx->StringToLocalUTF8(params[2], params[3], name, NULL);
   576 
   577 	return 1;
   578 }
   579 
   580 static cell_t smn_KvSetSectionName(IPluginContext *pCtx, const cell_t *params)
   581 {
   582 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   583 	HandleError herr;
   584 	HandleSecurity sec;
   585 	char *name;
   586 	KeyValueStack *pStk;
   587 
   588 	sec.pOwner = NULL;
   589 	sec.pIdentity = g_pCoreIdent;
   590 
   591 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   592 		!= HandleError_None)
   593 	{
   594 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   595 	}
   596 
   597 	pCtx->LocalToString(params[2], &name);
   598 
   599 	KeyValues *pSection = pStk->pCurRoot.front();
   600 	pSection->SetName(name);
   601 
   602 	return 1;
   603 }
   604 
   605 static cell_t smn_KvGetDataType(IPluginContext *pCtx, const cell_t *params)
   606 {
   607 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   608 	HandleError herr;
   609 	HandleSecurity sec;
   610 	char *name;
   611 	KeyValueStack *pStk;
   612 
   613 	sec.pOwner = NULL;
   614 	sec.pIdentity = g_pCoreIdent;
   615 
   616 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   617 		!= HandleError_None)
   618 	{
   619 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   620 	}
   621 
   622 	pCtx->LocalToString(params[2], &name);
   623 
   624 	return pStk->pCurRoot.front()->GetDataType(name);
   625 }
   626 
   627 static cell_t smn_KeyValuesToFile(IPluginContext *pCtx, const cell_t *params)
   628 {
   629 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   630 	HandleError herr;
   631 	HandleSecurity sec;
   632 	char *path;
   633 	KeyValueStack *pStk;
   634 
   635 	sec.pOwner = NULL;
   636 	sec.pIdentity = g_pCoreIdent;
   637 
   638 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   639 		!= HandleError_None)
   640 	{
   641 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   642 	}
   643 
   644 	pCtx->LocalToString(params[2], &path);
   645 
   646 	char realpath[PLATFORM_MAX_PATH];
   647 	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path);
   648 
   649 	return pStk->pCurRoot.front()->SaveToFile(basefilesystem, realpath);
   650 }
   651 
   652 static cell_t smn_FileToKeyValues(IPluginContext *pCtx, const cell_t *params)
   653 {
   654 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   655 	HandleError herr;
   656 	HandleSecurity sec;
   657 	char *path;
   658 	KeyValueStack *pStk;
   659 
   660 	sec.pOwner = NULL;
   661 	sec.pIdentity = g_pCoreIdent;
   662 
   663 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   664 		!= HandleError_None)
   665 	{
   666 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   667 	}
   668 
   669 	pCtx->LocalToString(params[2], &path);
   670 
   671 	char realpath[PLATFORM_MAX_PATH];
   672 	g_SourceMod.BuildPath(Path_Game, realpath, sizeof(realpath), "%s", path);
   673 
   674 	return pStk->pCurRoot.front()->LoadFromFile(basefilesystem, realpath);
   675 }
   676 
   677 static cell_t smn_KvSetEscapeSequences(IPluginContext *pCtx, const cell_t *params)
   678 {
   679 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   680 	HandleError herr;
   681 	HandleSecurity sec;
   682 	KeyValueStack *pStk;
   683 
   684 	sec.pOwner = NULL;
   685 	sec.pIdentity = g_pCoreIdent;
   686 
   687 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   688 		!= HandleError_None)
   689 	{
   690 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   691 	}
   692 
   693 	pStk->pCurRoot.front()->UsesEscapeSequences(params[2] ? true : false);
   694 
   695 	return 1;
   696 }
   697 
   698 static cell_t smn_KvNodesInStack(IPluginContext *pCtx, const cell_t *params)
   699 {
   700 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   701 	HandleError herr;
   702 	HandleSecurity sec;
   703 	KeyValueStack *pStk;
   704 
   705 	sec.pOwner = NULL;
   706 	sec.pIdentity = g_pCoreIdent;
   707 
   708 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   709 		!= HandleError_None)
   710 	{
   711 		return pCtx->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   712 	}
   713 
   714 	return pStk->pCurRoot.size() - 1;
   715 }
   716 
   717 static cell_t smn_KvDeleteThis(IPluginContext *pContext, const cell_t *params)
   718 {
   719 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   720 	HandleError herr;
   721 	HandleSecurity sec;
   722 	KeyValueStack *pStk;
   723 
   724 	sec.pOwner = NULL;
   725 	sec.pIdentity = g_pCoreIdent;
   726 
   727 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   728 		!= HandleError_None)
   729 	{
   730 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   731 	}
   732 
   733 	if (pStk->pCurRoot.size() < 2)
   734 	{
   735 		return 0;
   736 	}
   737 
   738 	KeyValues *pValues = pStk->pCurRoot.front();
   739 	pStk->pCurRoot.pop();
   740 	KeyValues *pRoot = pStk->pCurRoot.front();
   741 
   742 	/* We have to manually verify this since Valve sucks
   743 	 * :TODO: make our own KeyValues.h file and make
   744 	 * the sub stuff private so we can do this ourselves!
   745  	 */
   746 	KeyValues *sub = pRoot->GetFirstSubKey();
   747 	while (sub)
   748 	{
   749 		if (sub == pValues)
   750 		{
   751 			KeyValues *pNext = pValues->GetNextKey();
   752 			pRoot->RemoveSubKey(pValues);
   753 			pValues->deleteThis();
   754 			if (pNext)
   755 			{
   756 				pStk->pCurRoot.push(pNext);
   757 				return 1;
   758 			} else {
   759 				return -1;
   760 			}
   761 		}
   762 		sub = sub->GetNextKey();
   763 	}
   764 
   765 	/* Push this back on :( */
   766 	pStk->pCurRoot.push(pValues);
   767 
   768 	return 0;
   769 }
   770 
   771 static cell_t smn_KvDeleteKey(IPluginContext *pContext, const cell_t *params)
   772 {
   773 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   774 	HandleError herr;
   775 	HandleSecurity sec;
   776 	KeyValueStack *pStk;
   777 
   778 	sec.pOwner = NULL;
   779 	sec.pIdentity = g_pCoreIdent;
   780 
   781 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   782 		!= HandleError_None)
   783 	{
   784 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   785 	}
   786 
   787 	if (pStk->pCurRoot.size() < 2)
   788 	{
   789 		return 0;
   790 	}
   791 
   792 	char *keyName;
   793 	pContext->LocalToString(params[2], &keyName);
   794 
   795 	KeyValues *pRoot = pStk->pCurRoot.front();
   796 	KeyValues *pValues = pRoot->FindKey(keyName);
   797 	if (!pValues)
   798 	{
   799 		return 0;
   800 	}
   801 
   802 	pRoot->RemoveSubKey(pValues);
   803 	pValues->deleteThis();
   804 
   805 	return 1;
   806 }
   807 
   808 static cell_t smn_KvSavePosition(IPluginContext *pContext, const cell_t *params)
   809 {
   810 	Handle_t hndl = static_cast<Handle_t>(params[1]);
   811 	HandleError herr;
   812 	HandleSecurity sec;
   813 	KeyValueStack *pStk;
   814 
   815 	sec.pOwner = NULL;
   816 	sec.pIdentity = g_pCoreIdent;
   817 
   818 	if ((herr=g_HandleSys.ReadHandle(hndl, g_KeyValueType, &sec, (void **)&pStk))
   819 		!= HandleError_None)
   820 	{
   821 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   822 	}
   823 
   824 	if (pStk->pCurRoot.size() < 2)
   825 	{
   826 		return 0;
   827 	}
   828 
   829 	KeyValues *pValues = pStk->pCurRoot.front();
   830 	pStk->pCurRoot.push(pValues);
   831 
   832 	return 1;
   833 }
   834 
   835 static KeyValueNatives s_KeyValueNatives;
   836 
   837 REGISTER_NATIVES(keyvaluenatives)
   838 {
   839 	{"KvSetString",				smn_KvSetString},
   840 	{"KvSetNum",				smn_KvSetNum},
   841 	{"KvSetUInt64",				smn_KvSetUInt64},
   842 	{"KvSetFloat",				smn_KvSetFloat},
   843 	{"KvSetColor",				smn_KvSetColor},
   844 	{"KvGetString",				smn_KvGetString},
   845 	{"KvGetNum",				smn_KvGetNum},
   846 	{"KvGetFloat",				smn_KvGetFloat},
   847 	{"KvGetColor",				smn_KvGetColor},
   848 	{"KvGetUInt64",				smn_KvGetUInt64},
   849 	{"CreateKeyValues",			smn_CreateKeyValues},
   850 	{"KvJumpToKey",				smn_KvJumpToKey},
   851 	{"KvGotoNextKey",			smn_KvGotoNextKey},
   852 	{"KvJumpFirstSubKey",		smn_KvGotoFirstSubKey},		/* BACKWARDS COMPAT SHIM */
   853 	{"KvGotoFirstSubKey",		smn_KvGotoFirstSubKey},
   854 	{"KvJumpNextSubKey",		smn_KvJumpNextSubKey},		/* BACKWARDS COMPAT SHIM */
   855 	{"KvGoBack",				smn_KvGoBack},
   856 	{"KvRewind",				smn_KvRewind},
   857 	{"KvGetSectionName",		smn_KvGetSectionName},
   858 	{"KvSetSectionName",		smn_KvSetSectionName},
   859 	{"KvGetDataType",			smn_KvGetDataType},
   860 	{"KeyValuesToFile",			smn_KeyValuesToFile},
   861 	{"FileToKeyValues",			smn_FileToKeyValues},
   862 	{"KvSetEscapeSequences",	smn_KvSetEscapeSequences},
   863 	{"KvDeleteThis",			smn_KvDeleteThis},
   864 	{"KvDeleteKey",				smn_KvDeleteKey},
   865 	{"KvNodesInStack",			smn_KvNodesInStack},
   866 	{"KvSavePosition",			smn_KvSavePosition},
   867 	{NULL,						NULL}
   868 };