core/smn_player.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 06 06:27:47 2007 +0000 (2007-06-06)
changeset 884 a5f3239cef1a
parent 784 0ff19a8bd981
child 910 153c052460af
permissions -rw-r--r--
- vote menus now get cancelled properly (and get a new callback with it)
- added api for seeing if a menu is in a VoteDisplay
- fixed another item count bug
- removed some cruft from the vote handler header
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  * This file is not open source and may not be copied without explicit
     8  * written permission of AlliedModders LLC.  This file may not be redistributed 
     9  * in whole or significant part.
    10  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11  *
    12  * Version: $Id$
    13  */
    14 
    15 #include "PlayerManager.h"
    16 #include "AdminCache.h"
    17 #include "sm_stringutil.h"
    18 #include <inetchannelinfo.h>
    19 
    20 static cell_t sm_GetClientCount(IPluginContext *pCtx, const cell_t *params)
    21 {
    22 	if (params[1])
    23 	{
    24 		return g_Players.NumPlayers();
    25 	}
    26 
    27 	int maxplayers = g_Players.MaxClients();
    28 	int count = 0;
    29 	for (int i=1; i<=maxplayers; ++i)
    30 	{
    31 		CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
    32 		if ((pPlayer->IsConnected()) && !(pPlayer->IsInGame()))
    33 		{
    34 			count++;
    35 		}
    36 	}
    37 
    38 	return (g_Players.NumPlayers() + count);
    39 }
    40 
    41 static cell_t sm_GetMaxClients(IPluginContext *pCtx, const cell_t *params)
    42 {
    43 	return g_Players.MaxClients();
    44 }
    45 
    46 static cell_t sm_GetClientName(IPluginContext *pCtx, const cell_t *params)
    47 {
    48 	int index = params[1];
    49 	if ((index < 1) || (index > g_Players.GetMaxClients()))
    50 	{
    51 		return pCtx->ThrowNativeError("Invalid client index %d", index);
    52 	}
    53 
    54 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
    55 	if (!pPlayer->IsConnected())
    56 	{
    57 		return pCtx->ThrowNativeError("Client %d is not connected", index);
    58 	}
    59 
    60 	pCtx->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pPlayer->GetName(), NULL);
    61 	return 1;
    62 }
    63 
    64 static cell_t sm_GetClientIP(IPluginContext *pCtx, const cell_t *params)
    65 {
    66 	int index = params[1];
    67 	if ((index < 1) || (index > g_Players.GetMaxClients()))
    68 	{
    69 		return pCtx->ThrowNativeError("Invalid client index %d", index);
    70 	}
    71 
    72 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
    73 	if (!pPlayer->IsConnected())
    74 	{
    75 		return pCtx->ThrowNativeError("Client %d is not connected", index);
    76 	}
    77 
    78 	char buf[64], *ptr;
    79 	strcpy(buf, pPlayer->GetIPAddress());
    80 
    81 	if (params[4] && (ptr = strchr(buf, ':')))
    82 	{
    83 		*ptr = '\0';
    84 	}
    85 
    86 	pCtx->StringToLocal(params[2], static_cast<size_t>(params[3]), buf);
    87 	return 1;
    88 }
    89 
    90 static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params)
    91 {
    92 	int index = params[1];
    93 	if ((index < 1) || (index > g_Players.GetMaxClients()))
    94 	{
    95 		return pCtx->ThrowNativeError("Invalid client index %d", index);
    96 	}
    97 
    98 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
    99 	if (!pPlayer->IsConnected())
   100 	{
   101 		return pCtx->ThrowNativeError("Client %d is not connected", index);
   102 	}
   103 
   104 	if (!pPlayer->IsAuthorized())
   105 	{
   106 		return 0;
   107 	}
   108 
   109 	pCtx->StringToLocal(params[2], static_cast<size_t>(params[3]), pPlayer->GetAuthString());
   110 
   111 	return 1;
   112 }
   113 
   114 static cell_t sm_IsClientConnected(IPluginContext *pCtx, const cell_t *params)
   115 {
   116 	int index = params[1];
   117 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   118 	{
   119 		return pCtx->ThrowNativeError("Invalid client index %d", index);
   120 	}
   121 
   122 	return (g_Players.GetPlayerByIndex(index)->IsConnected()) ? 1 : 0;
   123 }
   124 
   125 static cell_t sm_IsClientInGame(IPluginContext *pCtx, const cell_t *params)
   126 {
   127 	int index = params[1];
   128 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   129 	{
   130 		return pCtx->ThrowNativeError("Invalid client index %d", index);
   131 	}
   132 
   133 	return (g_Players.GetPlayerByIndex(index)->IsInGame()) ? 1 : 0;
   134 }
   135 
   136 static cell_t sm_IsClientAuthorized(IPluginContext *pCtx, const cell_t *params)
   137 {
   138 	int index = params[1];
   139 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   140 	{
   141 		return pCtx->ThrowNativeError("Invalid client index %d", index);
   142 	}
   143 
   144 	return (g_Players.GetPlayerByIndex(index)->IsAuthorized()) ? 1 : 0;
   145 }
   146 
   147 static cell_t sm_IsClientFakeClient(IPluginContext *pCtx, const cell_t *params)
   148 {
   149 	int index = params[1];
   150 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   151 	{
   152 		return pCtx->ThrowNativeError("Invalid client index %d", index);
   153 	}
   154 
   155 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
   156 	if (!pPlayer->IsConnected())
   157 	{
   158 		return pCtx->ThrowNativeError("Client %d is not connected", index);
   159 	}
   160 
   161 	return (pPlayer->IsFakeClient()) ? 1 : 0;
   162 }
   163 
   164 static cell_t sm_GetClientInfo(IPluginContext *pContext, const cell_t *params)
   165 {
   166 	int client = params[1];
   167 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   168 	if (!pPlayer)
   169 	{
   170 		return pContext->ThrowNativeError("Invalid client index %d", client);
   171 	}
   172 	if (!pPlayer->IsConnected())
   173 	{
   174 		return pContext->ThrowNativeError("Client %d is not connected", client);
   175 	}
   176 
   177 	char *key;
   178 	pContext->LocalToString(params[2], &key);
   179 
   180 	const char *val = engine->GetClientConVarValue(client, key);
   181 	if (!val)
   182 	{
   183 		return false;
   184 	}
   185 
   186 	pContext->StringToLocalUTF8(params[3], params[4], val, NULL);
   187 	return 1;
   188 }
   189 
   190 static cell_t SetUserAdmin(IPluginContext *pContext, const cell_t *params)
   191 {
   192 	int client = params[1];
   193 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   194 	if (!pPlayer)
   195 	{
   196 		return pContext->ThrowNativeError("Invalid client index %d", client);
   197 	}
   198 	if (!pPlayer->IsConnected())
   199 	{
   200 		return pContext->ThrowNativeError("Client %d is not connected", client);
   201 	}
   202 	if (!g_Admins.IsValidAdmin(params[2]))
   203 	{
   204 		return pContext->ThrowNativeError("AdminId %x is not valid", params[2]);
   205 	}
   206 
   207 	pPlayer->SetAdminId(params[2], params[3] ? true : false);
   208 
   209 	return 1;
   210 }
   211 
   212 static cell_t GetUserAdmin(IPluginContext *pContext, const cell_t *params)
   213 {
   214 	int client = params[1];
   215 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   216 	if (!pPlayer)
   217 	{
   218 		return pContext->ThrowNativeError("Invalid client index %d", client);
   219 	}
   220 	if (!pPlayer->IsConnected())
   221 	{
   222 		return pContext->ThrowNativeError("Client %d is not connected", client);
   223 	}
   224 
   225 	return pPlayer->GetAdminId();
   226 }
   227 
   228 static cell_t AddUserFlags(IPluginContext *pContext, const cell_t *params)
   229 {
   230 	int client = params[1];
   231 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   232 	if (!pPlayer)
   233 	{
   234 		return pContext->ThrowNativeError("Invalid client index %d", client);
   235 	}
   236 	if (!pPlayer->IsConnected())
   237 	{
   238 		return pContext->ThrowNativeError("Client %d is not connected", client);
   239 	}
   240 
   241 	AdminId id;
   242 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   243 	{
   244 		id = g_Admins.CreateAdmin(NULL);
   245 		pPlayer->SetAdminId(id, true);
   246 	}
   247 
   248 	cell_t *addr;
   249 	for (int i=2; i<=params[0]; i++)
   250 	{
   251 		pContext->LocalToPhysAddr(params[i], &addr);
   252 		g_Admins.SetAdminFlag(id, (AdminFlag)*addr, true);
   253 	}
   254 
   255 	return 1;
   256 }
   257 
   258 static cell_t RemoveUserFlags(IPluginContext *pContext, const cell_t *params)
   259 {
   260 	int client = params[1];
   261 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   262 	if (!pPlayer)
   263 	{
   264 		return pContext->ThrowNativeError("Invalid client index %d", client);
   265 	}
   266 	if (!pPlayer->IsConnected())
   267 	{
   268 		return pContext->ThrowNativeError("Client %d is not connected", client);
   269 	}
   270 	
   271 	AdminId id;
   272 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   273 	{
   274 		return 0;
   275 	}
   276 
   277 	cell_t *addr;
   278 	for (int i=2; i<=params[0]; i++)
   279 	{
   280 		pContext->LocalToPhysAddr(params[i], &addr);
   281 		g_Admins.SetAdminFlag(id, (AdminFlag)*addr, false);
   282 	}
   283 
   284 	return 1;
   285 }
   286 
   287 static cell_t SetUserFlagBits(IPluginContext *pContext, const cell_t *params)
   288 {
   289 	int client = params[1];
   290 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   291 	if (!pPlayer)
   292 	{
   293 		return pContext->ThrowNativeError("Invalid client index %d", client);
   294 	}
   295 	if (!pPlayer->IsConnected())
   296 	{
   297 		return pContext->ThrowNativeError("Client %d is not connected", client);
   298 	}
   299 
   300 	AdminId id;
   301 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   302 	{
   303 		id = g_Admins.CreateAdmin(NULL);
   304 		pPlayer->SetAdminId(id, true);
   305 	}
   306 
   307 	g_Admins.SetAdminFlags(id, Access_Effective, params[2]);
   308 
   309 	return 1;
   310 }
   311 
   312 static cell_t GetUserFlagBits(IPluginContext *pContext, const cell_t *params)
   313 {
   314 	int client = params[1];
   315 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   316 	if (!pPlayer)
   317 	{
   318 		return pContext->ThrowNativeError("Invalid client index %d", client);
   319 	}
   320 	if (!pPlayer->IsConnected())
   321 	{
   322 		return pContext->ThrowNativeError("Client %d is not connected", client);
   323 	}
   324 
   325 	AdminId id;
   326 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   327 	{
   328 		return 0;
   329 	}
   330 
   331 	return g_Admins.GetAdminFlags(id, Access_Effective);
   332 }
   333 
   334 static cell_t GetClientUserId(IPluginContext *pContext, const cell_t *params)
   335 {
   336 	int client = params[1];
   337 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   338 	if (!pPlayer)
   339 	{
   340 		return pContext->ThrowNativeError("Invalid client index %d", client);
   341 	}
   342 	if (!pPlayer->IsConnected())
   343 	{
   344 		return pContext->ThrowNativeError("Client %d is not connected", client);
   345 	}
   346 
   347 	return engine->GetPlayerUserId(pPlayer->GetEdict());
   348 }
   349 
   350 static cell_t CanUserTarget(IPluginContext *pContext, const cell_t *params)
   351 {
   352 	int client = params[1];
   353 	int target = params[2];
   354 
   355 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   356 	if (!pPlayer)
   357 	{
   358 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   359 	} else if (!pPlayer->IsConnected()) {
   360 		return pContext->ThrowNativeError("Player %d is not connected", client);
   361 	}
   362 
   363 	CPlayer *pTarget = g_Players.GetPlayerByIndex(target);
   364 	if (!pTarget)
   365 	{
   366 		return pContext->ThrowNativeError("Player %d is not a valid client", target);
   367 	} else if (!pTarget->IsConnected()) {
   368 		return pContext->ThrowNativeError("Player %d is not connected", target);
   369 	}
   370 
   371 	return g_Admins.CanAdminTarget(pPlayer->GetAdminId(), pTarget->GetAdminId()) ? 1 : 0;
   372 }
   373 
   374 static cell_t GetClientTeam(IPluginContext *pContext, const cell_t *params)
   375 {
   376 	int client = params[1];
   377 
   378 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   379 	if (!pPlayer)
   380 	{
   381 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   382 	} else if (!pPlayer->IsInGame()) {
   383 		return pContext->ThrowNativeError("Player %d is not in game", client);
   384 	}
   385 
   386 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   387 	if (!pInfo)
   388 	{
   389 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   390 	}
   391 
   392 	return pInfo->GetTeamIndex();
   393 }
   394 
   395 static cell_t GetFragCount(IPluginContext *pContext, const cell_t *params)
   396 {
   397 	int client = params[1];
   398 
   399 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   400 	if (!pPlayer)
   401 	{
   402 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   403 	} else if (!pPlayer->IsInGame()) {
   404 		return pContext->ThrowNativeError("Player %d is not in game", client);
   405 	}
   406 
   407 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   408 	if (!pInfo)
   409 	{
   410 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   411 	}
   412 
   413 	return pInfo->GetFragCount();
   414 }
   415 
   416 static cell_t GetDeathCount(IPluginContext *pContext, const cell_t *params)
   417 {
   418 	int client = params[1];
   419 
   420 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   421 	if (!pPlayer)
   422 	{
   423 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   424 	} else if (!pPlayer->IsInGame()) {
   425 		return pContext->ThrowNativeError("Player %d is not in game", client);
   426 	}
   427 
   428 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   429 	if (!pInfo)
   430 	{
   431 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   432 	}
   433 
   434 	return pInfo->GetDeathCount();
   435 }
   436 
   437 static cell_t GetArmorValue(IPluginContext *pContext, const cell_t *params)
   438 {
   439 	int client = params[1];
   440 
   441 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   442 	if (!pPlayer)
   443 	{
   444 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   445 	} else if (!pPlayer->IsInGame()) {
   446 		return pContext->ThrowNativeError("Player %d is not in game", client);
   447 	}
   448 
   449 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   450 	if (!pInfo)
   451 	{
   452 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   453 	}
   454 
   455 	return pInfo->GetArmorValue();
   456 }
   457 
   458 static cell_t GetAbsOrigin(IPluginContext *pContext, const cell_t *params)
   459 {
   460 	int client = params[1];
   461 
   462 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   463 	if (!pPlayer)
   464 	{
   465 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   466 	} else if (!pPlayer->IsInGame()) {
   467 		return pContext->ThrowNativeError("Player %d is not in game", client);
   468 	}
   469 
   470 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   471 	if (!pInfo)
   472 	{
   473 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   474 	}
   475 
   476 	cell_t *pVec;
   477 	pContext->LocalToPhysAddr(params[2], &pVec);
   478 
   479 	Vector vec = pInfo->GetAbsOrigin();
   480 	pVec[0] = sp_ftoc(vec.x);
   481 	pVec[1] = sp_ftoc(vec.y);
   482 	pVec[2] = sp_ftoc(vec.z);
   483 
   484 	return 1;
   485 }
   486 
   487 static cell_t GetAbsAngles(IPluginContext *pContext, const cell_t *params)
   488 {
   489 	int client = params[1];
   490 
   491 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   492 	if (!pPlayer)
   493 	{
   494 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   495 	} else if (!pPlayer->IsInGame()) {
   496 		return pContext->ThrowNativeError("Player %d is not in game", client);
   497 	}
   498 
   499 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   500 	if (!pInfo)
   501 	{
   502 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   503 	}
   504 
   505 	cell_t *pAng;
   506 	pContext->LocalToPhysAddr(params[2], &pAng);
   507 
   508 	QAngle ang = pInfo->GetAbsAngles();
   509 	pAng[0] = sp_ftoc(ang.x);
   510 	pAng[1] = sp_ftoc(ang.y);
   511 	pAng[2] = sp_ftoc(ang.z);
   512 
   513 	return 1;
   514 }
   515 
   516 static cell_t GetPlayerMins(IPluginContext *pContext, const cell_t *params)
   517 {
   518 	int client = params[1];
   519 
   520 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   521 	if (!pPlayer)
   522 	{
   523 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   524 	} else if (!pPlayer->IsInGame()) {
   525 		return pContext->ThrowNativeError("Player %d is not in game", client);
   526 	}
   527 
   528 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   529 	if (!pInfo)
   530 	{
   531 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   532 	}
   533 
   534 	cell_t *pVec;
   535 	pContext->LocalToPhysAddr(params[2], &pVec);
   536 
   537 	Vector vec = pInfo->GetPlayerMins();
   538 	pVec[0] = sp_ftoc(vec.x);
   539 	pVec[1] = sp_ftoc(vec.y);
   540 	pVec[2] = sp_ftoc(vec.z);
   541 
   542 	return 1;
   543 }
   544 
   545 static cell_t GetPlayerMaxs(IPluginContext *pContext, const cell_t *params)
   546 {
   547 	int client = params[1];
   548 
   549 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   550 	if (!pPlayer)
   551 	{
   552 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   553 	} else if (!pPlayer->IsInGame()) {
   554 		return pContext->ThrowNativeError("Player %d is not in game", client);
   555 	}
   556 
   557 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   558 	if (!pInfo)
   559 	{
   560 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   561 	}
   562 
   563 	cell_t *pVec;
   564 	pContext->LocalToPhysAddr(params[2], &pVec);
   565 
   566 	Vector vec = pInfo->GetPlayerMaxs();
   567 	pVec[0] = sp_ftoc(vec.x);
   568 	pVec[1] = sp_ftoc(vec.y);
   569 	pVec[2] = sp_ftoc(vec.z);
   570 
   571 	return 1;
   572 }
   573 
   574 static cell_t GetWeaponName(IPluginContext *pContext, const cell_t *params)
   575 {
   576 	int client = params[1];
   577 
   578 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   579 	if (!pPlayer)
   580 	{
   581 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   582 	} else if (!pPlayer->IsInGame()) {
   583 		return pContext->ThrowNativeError("Player %d is not in game", client);
   584 	}
   585 
   586 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   587 	if (!pInfo)
   588 	{
   589 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   590 	}
   591 
   592 	const char *weapon = pInfo->GetWeaponName();
   593 	pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), weapon ? weapon : "", NULL);
   594 
   595 	return 1;
   596 }
   597 
   598 static cell_t GetModelName(IPluginContext *pContext, const cell_t *params)
   599 {
   600 	int client = params[1];
   601 
   602 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   603 	if (!pPlayer)
   604 	{
   605 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   606 	} else if (!pPlayer->IsInGame()) {
   607 		return pContext->ThrowNativeError("Player %d is not in game", client);
   608 	}
   609 
   610 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   611 	if (!pInfo)
   612 	{
   613 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   614 	}
   615 
   616 	const char *model = pInfo->GetModelName();
   617 	pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), model ? model : "", NULL);
   618 
   619 	return 1;
   620 }
   621 
   622 static cell_t GetHealth(IPluginContext *pContext, const cell_t *params)
   623 {
   624 	int client = params[1];
   625 
   626 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   627 	if (!pPlayer)
   628 	{
   629 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   630 	} else if (!pPlayer->IsInGame()) {
   631 		return pContext->ThrowNativeError("Player %d is not in game", client);
   632 	}
   633 
   634 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   635 	if (!pInfo)
   636 	{
   637 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   638 	}
   639 
   640 	return pInfo->GetHealth();
   641 }
   642 
   643 static cell_t GetTimeConnected(IPluginContext *pContext, const cell_t *params)
   644 {
   645 	int client = params[1];
   646 
   647 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   648 	if (!pPlayer)
   649 	{
   650 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   651 	} else if (!pPlayer->IsInGame()) {
   652 		return pContext->ThrowNativeError("Player %d is not in game", client);
   653 	} else if (pPlayer->IsFakeClient()) {
   654 		return pContext->ThrowNativeError("Player %d is a bot", client);
   655 	}
   656 
   657 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   658 
   659 	return sp_ftoc(pInfo->GetTimeConnected());
   660 }
   661 
   662 static cell_t GetDataRate(IPluginContext *pContext, const cell_t *params)
   663 {
   664 	int client = params[1];
   665 
   666 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   667 	if (!pPlayer)
   668 	{
   669 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   670 	} else if (!pPlayer->IsInGame()) {
   671 		return pContext->ThrowNativeError("Player %d is not in game", client);
   672 	} else if (pPlayer->IsFakeClient()) {
   673 		return pContext->ThrowNativeError("Player %d is a bot", client);
   674 	}
   675 
   676 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   677 
   678 	return pInfo->GetDataRate();
   679 }
   680 
   681 static cell_t IsTimingOut(IPluginContext *pContext, const cell_t *params)
   682 {
   683 	int client = params[1];
   684 
   685 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   686 	if (!pPlayer)
   687 	{
   688 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   689 	} else if (!pPlayer->IsInGame()) {
   690 		return pContext->ThrowNativeError("Player %d is not in game", client);
   691 	} else if (pPlayer->IsFakeClient()) {
   692 		return pContext->ThrowNativeError("Player %d is a bot", client);
   693 	}
   694 
   695 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   696 
   697 	return pInfo->IsTimingOut() ? 1 : 0;
   698 }
   699 
   700 static cell_t GetLatency(IPluginContext *pContext, const cell_t *params)
   701 {
   702 	int client = params[1];
   703 
   704 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   705 	if (!pPlayer)
   706 	{
   707 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   708 	} else if (!pPlayer->IsInGame()) {
   709 		return pContext->ThrowNativeError("Player %d is not in game", client);
   710 	} else if (pPlayer->IsFakeClient()) {
   711 		return pContext->ThrowNativeError("Player %d is a bot", client);
   712 	}
   713 
   714 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   715 
   716 	return sp_ftoc(pInfo->GetLatency(params[2]));
   717 }
   718 
   719 static cell_t GetAvgLatency(IPluginContext *pContext, const cell_t *params)
   720 {
   721 	int client = params[1];
   722 
   723 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   724 	if (!pPlayer)
   725 	{
   726 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   727 	} else if (!pPlayer->IsInGame()) {
   728 		return pContext->ThrowNativeError("Player %d is not in game", client);
   729 	} else if (pPlayer->IsFakeClient()) {
   730 		return pContext->ThrowNativeError("Player %d is a bot", client);
   731 	}
   732 
   733 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   734 
   735 	return sp_ftoc(pInfo->GetAvgLatency(params[2]));
   736 }
   737 
   738 static cell_t GetAvgLoss(IPluginContext *pContext, const cell_t *params)
   739 {
   740 	int client = params[1];
   741 
   742 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   743 	if (!pPlayer)
   744 	{
   745 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   746 	} else if (!pPlayer->IsInGame()) {
   747 		return pContext->ThrowNativeError("Player %d is not in game", client);
   748 	} else if (pPlayer->IsFakeClient()) {
   749 		return pContext->ThrowNativeError("Player %d is a bot", client);
   750 	}
   751 
   752 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   753 
   754 	return sp_ftoc(pInfo->GetAvgLoss(params[2]));
   755 }
   756 
   757 static cell_t GetAvgChoke(IPluginContext *pContext, const cell_t *params)
   758 {
   759 	int client = params[1];
   760 
   761 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   762 	if (!pPlayer)
   763 	{
   764 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   765 	} else if (!pPlayer->IsInGame()) {
   766 		return pContext->ThrowNativeError("Player %d is not in game", client);
   767 	} else if (pPlayer->IsFakeClient()) {
   768 		return pContext->ThrowNativeError("Player %d is a bot", client);
   769 	}
   770 
   771 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   772 
   773 	return sp_ftoc(pInfo->GetAvgChoke(params[2]));
   774 }
   775 
   776 static cell_t GetAvgData(IPluginContext *pContext, const cell_t *params)
   777 {
   778 	int client = params[1];
   779 
   780 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   781 	if (!pPlayer)
   782 	{
   783 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   784 	} else if (!pPlayer->IsInGame()) {
   785 		return pContext->ThrowNativeError("Player %d is not in game", client);
   786 	} else if (pPlayer->IsFakeClient()) {
   787 		return pContext->ThrowNativeError("Player %d is a bot", client);
   788 	}
   789 
   790 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   791 
   792 	return sp_ftoc(pInfo->GetAvgData(params[2]));
   793 }
   794 
   795 static cell_t GetAvgPackets(IPluginContext *pContext, const cell_t *params)
   796 {
   797 	int client = params[1];
   798 
   799 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   800 	if (!pPlayer)
   801 	{
   802 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   803 	} else if (!pPlayer->IsInGame()) {
   804 		return pContext->ThrowNativeError("Player %d is not in game", client);
   805 	} else if (pPlayer->IsFakeClient()) {
   806 		return pContext->ThrowNativeError("Player %d is a bot", client);
   807 	}
   808 
   809 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   810 
   811 	return sp_ftoc(pInfo->GetAvgPackets(params[2]));
   812 }
   813 
   814 static cell_t GetClientOfUserId(IPluginContext *pContext, const cell_t *params)
   815 {
   816 	return g_Players.GetClientOfUserId(params[1]);
   817 }
   818 
   819 REGISTER_NATIVES(playernatives)
   820 {
   821 	{"AddUserFlags",			AddUserFlags},
   822 	{"CanUserTarget",			CanUserTarget},
   823 	{"GetClientAuthString",		sm_GetClientAuthStr},
   824 	{"GetClientCount",			sm_GetClientCount},
   825 	{"GetClientInfo",			sm_GetClientInfo},
   826 	{"GetClientIP",				sm_GetClientIP},
   827 	{"GetClientName",			sm_GetClientName},
   828 	{"GetClientTeam",			GetClientTeam},
   829 	{"GetClientUserId",			GetClientUserId},
   830 	{"GetMaxClients",			sm_GetMaxClients},
   831 	{"GetUserAdmin",			GetUserAdmin},
   832 	{"GetUserFlagBits",			GetUserFlagBits},
   833 	{"IsClientAuthorized",		sm_IsClientAuthorized},
   834 	{"IsClientConnected",		sm_IsClientConnected},
   835 	{"IsFakeClient",			sm_IsClientFakeClient},
   836 	{"IsPlayerInGame",			sm_IsClientInGame},			/* Backwards compat shim */
   837 	{"IsClientInGame",			sm_IsClientInGame},
   838 	{"RemoveUserFlags",			RemoveUserFlags},
   839 	{"SetUserAdmin",			SetUserAdmin},
   840 	{"SetUserFlagBits",			SetUserFlagBits},
   841 	{"GetClientDeaths",			GetDeathCount},
   842 	{"GetClientFrags",			GetFragCount},
   843 	{"GetClientArmor",			GetArmorValue},
   844 	{"GetClientAbsOrigin",		GetAbsOrigin},
   845 	{"GetClientAbsAngles",		GetAbsAngles},
   846 	{"GetClientMins",			GetPlayerMins},
   847 	{"GetClientMaxs",			GetPlayerMaxs},
   848 	{"GetClientWeapon",			GetWeaponName},
   849 	{"GetClientModel",			GetModelName},
   850 	{"GetClientHealth",			GetHealth},
   851 	{"GetClientTime",			GetTimeConnected},
   852 	{"GetClientDataRate",		GetDataRate},
   853 	{"IsClentTimingOut",		IsTimingOut},
   854 	{"GetClientLatency",		GetLatency},
   855 	{"GetClientAvgLatency",		GetAvgLatency},
   856 	{"GetClientAvgLoss",		GetAvgLoss},
   857 	{"GetClientAvgChoke",		GetAvgChoke},
   858 	{"GetClientAvgData",		GetAvgData},
   859 	{"GetClientAvgPackets",		GetAvgPackets},
   860 	{"GetClientOfUserId",		GetClientOfUserId},
   861 	{NULL,						NULL}
   862 };