1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/PlayerManager.cpp Sun Jul 06 04:49:55 2008 +0000
1.3 @@ -0,0 +1,1579 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include "PlayerManager.h"
1.36 +#include "ForwardSys.h"
1.37 +#include "ShareSys.h"
1.38 +#include "AdminCache.h"
1.39 +#include "ConCmdManager.h"
1.40 +#include "MenuStyle_Valve.h"
1.41 +#include "MenuStyle_Radio.h"
1.42 +#include "sm_stringutil.h"
1.43 +#include "CoreConfig.h"
1.44 +#include "TimerSys.h"
1.45 +#include "Translator.h"
1.46 +#include "Logger.h"
1.47 +#include "ChatTriggers.h"
1.48 +#include "HalfLife2.h"
1.49 +#include <inetchannel.h>
1.50 +#include <iclient.h>
1.51 +#include "GameConfigs.h"
1.52 +#include "systems/ExtensionSys.h"
1.53 +
1.54 +PlayerManager g_Players;
1.55 +bool g_OnMapStarted = false;
1.56 +IForward *PreAdminCheck = NULL;
1.57 +IForward *PostAdminCheck = NULL;
1.58 +IForward *PostAdminFilter = NULL;
1.59 +const unsigned int *g_NumPlayersToAuth = NULL;
1.60 +int lifestate_offset = -1;
1.61 +List<ICommandTargetProcessor *> target_processors;
1.62 +
1.63 +SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int);
1.64 +SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *);
1.65 +SH_DECL_HOOK1_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, edict_t *);
1.66 +#if defined ORANGEBOX_BUILD
1.67 +SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &);
1.68 +#else
1.69 +SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *);
1.70 +#endif
1.71 +SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *);
1.72 +SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int);
1.73 +
1.74 +class KickPlayerTimer : public ITimedEvent
1.75 +{
1.76 +public:
1.77 + ResultType OnTimer(ITimer *pTimer, void *pData)
1.78 + {
1.79 + int userid = (int)pData;
1.80 + int client = g_Players.GetClientOfUserId(userid);
1.81 + if (client)
1.82 + {
1.83 + CPlayer *player = g_Players.GetPlayerByIndex(client);
1.84 + player->Kick("Your name is reserved by SourceMod; set your password to use it.");
1.85 + }
1.86 + return Pl_Stop;
1.87 + }
1.88 + void OnTimerEnd(ITimer *pTimer, void *pData)
1.89 + {
1.90 + }
1.91 +} s_KickPlayerTimer;
1.92 +
1.93 +PlayerManager::PlayerManager()
1.94 +{
1.95 + m_AuthQueue = NULL;
1.96 + m_FirstPass = false;
1.97 + m_maxClients = 0;
1.98 +
1.99 + m_UserIdLookUp = new int[USHRT_MAX+1];
1.100 + memset(m_UserIdLookUp, 0, sizeof(int) * (USHRT_MAX+1));
1.101 +}
1.102 +
1.103 +PlayerManager::~PlayerManager()
1.104 +{
1.105 + g_NumPlayersToAuth = NULL;
1.106 +
1.107 + delete [] m_AuthQueue;
1.108 + delete [] m_UserIdLookUp;
1.109 +}
1.110 +
1.111 +void PlayerManager::OnSourceModAllInitialized()
1.112 +{
1.113 + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect, false);
1.114 + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect_Post, true);
1.115 + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &PlayerManager::OnClientPutInServer, true);
1.116 + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect, false);
1.117 + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect_Post, true);
1.118 + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, serverClients, this, &PlayerManager::OnClientCommand, false);
1.119 + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, serverClients, this, &PlayerManager::OnClientSettingsChanged, true);
1.120 + SH_ADD_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &PlayerManager::OnServerActivate, true);
1.121 +
1.122 + g_ShareSys.AddInterface(NULL, this);
1.123 +
1.124 + ParamType p1[] = {Param_Cell, Param_String, Param_Cell};
1.125 + ParamType p2[] = {Param_Cell};
1.126 +
1.127 + m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_Event, 3, p1);
1.128 + m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2);
1.129 + m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2);
1.130 + m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2);
1.131 + m_clcommand = g_Forwards.CreateForward("OnClientCommand", ET_Hook, 2, NULL, Param_Cell, Param_Cell);
1.132 + m_clinfochanged = g_Forwards.CreateForward("OnClientSettingsChanged", ET_Ignore, 1, p2);
1.133 + m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
1.134 + m_onActivate = g_Forwards.CreateForward("OnServerLoad", ET_Ignore, 0, NULL);
1.135 + m_onActivate2 = g_Forwards.CreateForward("OnMapStart", ET_Ignore, 0, NULL);
1.136 +
1.137 + PreAdminCheck = g_Forwards.CreateForward("OnClientPreAdminCheck", ET_Event, 1, p1);
1.138 + PostAdminCheck = g_Forwards.CreateForward("OnClientPostAdminCheck", ET_Ignore, 1, p1);
1.139 + PostAdminFilter = g_Forwards.CreateForward("OnClientPostAdminFilter", ET_Ignore, 1, p1);
1.140 +
1.141 + m_bIsListenServer = !engine->IsDedicatedServer();
1.142 + m_ListenClient = 0;
1.143 +}
1.144 +
1.145 +void PlayerManager::OnSourceModShutdown()
1.146 +{
1.147 + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect, false);
1.148 + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &PlayerManager::OnClientPutInServer, true);
1.149 + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect, false);
1.150 + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect_Post, true);
1.151 + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientCommand, serverClients, this, &PlayerManager::OnClientCommand, false);
1.152 + SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, serverClients, this, &PlayerManager::OnClientSettingsChanged, true);
1.153 + SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &PlayerManager::OnServerActivate, true);
1.154 +
1.155 + /* Release forwards */
1.156 + g_Forwards.ReleaseForward(m_clconnect);
1.157 + g_Forwards.ReleaseForward(m_clputinserver);
1.158 + g_Forwards.ReleaseForward(m_cldisconnect);
1.159 + g_Forwards.ReleaseForward(m_cldisconnect_post);
1.160 + g_Forwards.ReleaseForward(m_clcommand);
1.161 + g_Forwards.ReleaseForward(m_clinfochanged);
1.162 + g_Forwards.ReleaseForward(m_clauth);
1.163 + g_Forwards.ReleaseForward(m_onActivate);
1.164 + g_Forwards.ReleaseForward(m_onActivate2);
1.165 +
1.166 + g_Forwards.ReleaseForward(PreAdminCheck);
1.167 + g_Forwards.ReleaseForward(PostAdminCheck);
1.168 + g_Forwards.ReleaseForward(PostAdminFilter);
1.169 +
1.170 + delete [] m_Players;
1.171 +}
1.172 +
1.173 +ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
1.174 + const char *value,
1.175 + ConfigSource source,
1.176 + char *error,
1.177 + size_t maxlength)
1.178 +{
1.179 + if (strcmp(key, "PassInfoVar") == 0)
1.180 + {
1.181 + if (strcmp(value, "_password") != 0)
1.182 + {
1.183 + m_PassInfoVar.assign(value);
1.184 + }
1.185 + return ConfigResult_Accept;
1.186 + } else if (strcmp(key, "AllowClLanguageVar") == 0) {
1.187 + if (strcasecmp(value, "on") == 0)
1.188 + {
1.189 + m_QueryLang = true;
1.190 + } else if (strcasecmp(value, "off") == 0) {
1.191 + m_QueryLang = false;
1.192 + } else {
1.193 + UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
1.194 + return ConfigResult_Reject;
1.195 + }
1.196 + return ConfigResult_Accept;
1.197 + }
1.198 + return ConfigResult_Ignore;
1.199 +}
1.200 +
1.201 +void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
1.202 +{
1.203 + if (!m_FirstPass)
1.204 + {
1.205 + /* Initialize all players */
1.206 + m_maxClients = clientMax;
1.207 + m_PlayerCount = 0;
1.208 + m_Players = new CPlayer[m_maxClients + 1];
1.209 + m_AuthQueue = new unsigned int[m_maxClients + 1];
1.210 + m_FirstPass = true;
1.211 +
1.212 + memset(m_AuthQueue, 0, sizeof(unsigned int) * (m_maxClients + 1));
1.213 +
1.214 + g_NumPlayersToAuth = &m_AuthQueue[0];
1.215 + }
1.216 + g_Extensions.CallOnCoreMapStart(pEdictList, edictCount, clientMax);
1.217 + m_onActivate->Execute(NULL);
1.218 + m_onActivate2->Execute(NULL);
1.219 +
1.220 + List<IClientListener *>::iterator iter;
1.221 + for (iter = m_hooks.begin(); iter != m_hooks.end(); iter++)
1.222 + {
1.223 + if ((*iter)->GetClientListenerVersion() >= 5)
1.224 + {
1.225 + (*iter)->OnServerActivated(clientMax);
1.226 + }
1.227 + }
1.228 +
1.229 + g_OnMapStarted = true;
1.230 +
1.231 + SM_ExecuteAllConfigs();
1.232 +}
1.233 +
1.234 +bool PlayerManager::IsServerActivated()
1.235 +{
1.236 + return m_FirstPass;
1.237 +}
1.238 +
1.239 +bool PlayerManager::CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id)
1.240 +{
1.241 + const char *password = g_Admins.GetAdminPassword(id);
1.242 + if (password != NULL)
1.243 + {
1.244 + if (m_PassInfoVar.size() < 1)
1.245 + {
1.246 + return false;
1.247 + }
1.248 +
1.249 + /* Whoa... the user needs a password! */
1.250 + const char *given = engine->GetClientConVarValue(index, m_PassInfoVar.c_str());
1.251 + if (!given || strcmp(given, password) != 0)
1.252 + {
1.253 + return false;
1.254 + }
1.255 + }
1.256 +
1.257 + pPlayer->SetAdminId(id, false);
1.258 +
1.259 + return true;
1.260 +}
1.261 +
1.262 +bool PlayerManager::CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id)
1.263 +{
1.264 + const char *password = g_Admins.GetAdminPassword(id);
1.265 + if (password == NULL)
1.266 + {
1.267 + return false;
1.268 + }
1.269 +
1.270 + if (m_PassInfoVar.size() < 1)
1.271 + {
1.272 + return false;
1.273 + }
1.274 +
1.275 + /* Whoa... the user needs a password! */
1.276 + const char *given = engine->GetClientConVarValue(index, m_PassInfoVar.c_str());
1.277 + if (!given || strcmp(given, password) != 0)
1.278 + {
1.279 + return false;
1.280 + }
1.281 +
1.282 + pPlayer->SetAdminId(id, false);
1.283 +
1.284 + return true;
1.285 +}
1.286 +
1.287 +void PlayerManager::RunAuthChecks()
1.288 +{
1.289 + CPlayer *pPlayer;
1.290 + const char *authstr;
1.291 + unsigned int removed = 0;
1.292 + for (unsigned int i=1; i<=m_AuthQueue[0]; i++)
1.293 + {
1.294 + pPlayer = GetPlayerByIndex(m_AuthQueue[i]);
1.295 + authstr = engine->GetPlayerNetworkIDString(pPlayer->m_pEdict);
1.296 + if (authstr && authstr[0] != '\0'
1.297 + && (strcmp(authstr, "STEAM_ID_PENDING") != 0))
1.298 + {
1.299 + /* Set authorization */
1.300 + pPlayer->Authorize(authstr);
1.301 +
1.302 + /* Mark as removed from queue */
1.303 + unsigned int client = m_AuthQueue[i];
1.304 + m_AuthQueue[i] = 0;
1.305 + removed++;
1.306 +
1.307 + /* Send to extensions */
1.308 + List<IClientListener *>::iterator iter;
1.309 + IClientListener *pListener;
1.310 + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
1.311 + {
1.312 + pListener = (*iter);
1.313 + pListener->OnClientAuthorized(client, authstr);
1.314 + if (!pPlayer->IsConnected())
1.315 + {
1.316 + break;
1.317 + }
1.318 + }
1.319 +
1.320 + /* Send to plugins if player is still connected */
1.321 + if (pPlayer->IsConnected() && m_clauth->GetFunctionCount())
1.322 + {
1.323 + /* :TODO: handle the case of a player disconnecting in the middle */
1.324 + m_clauth->PushCell(client);
1.325 + m_clauth->PushString(authstr);
1.326 + m_clauth->Execute(NULL);
1.327 + }
1.328 +
1.329 + if (pPlayer->IsConnected())
1.330 + {
1.331 + pPlayer->Authorize_Post();
1.332 + }
1.333 + }
1.334 + }
1.335 +
1.336 + /* Clean up the queue */
1.337 + if (removed)
1.338 + {
1.339 + /* We don't have to compact the list if it's empty */
1.340 + if (removed != m_AuthQueue[0])
1.341 + {
1.342 + unsigned int diff = 0;
1.343 + for (unsigned int i=1; i<=m_AuthQueue[0]; i++)
1.344 + {
1.345 + /* If this member is removed... */
1.346 + if (m_AuthQueue[i] == 0)
1.347 + {
1.348 + /* Increase the differential */
1.349 + diff++;
1.350 + } else {
1.351 + /* diff cannot increase faster than i+1 */
1.352 + assert(i > diff);
1.353 + assert(i - diff >= 1);
1.354 + /* move this index down */
1.355 + m_AuthQueue[i - diff] = m_AuthQueue[i];
1.356 + }
1.357 + }
1.358 + m_AuthQueue[0] -= removed;
1.359 + } else {
1.360 + m_AuthQueue[0] = 0;
1.361 + }
1.362 + }
1.363 +}
1.364 +
1.365 +bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen)
1.366 +{
1.367 + int client = engine->IndexOfEdict(pEntity);
1.368 +
1.369 + List<IClientListener *>::iterator iter;
1.370 + IClientListener *pListener = NULL;
1.371 + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
1.372 + {
1.373 + pListener = (*iter);
1.374 + if (!pListener->InterceptClientConnect(client, reject, maxrejectlen))
1.375 + {
1.376 + return false;
1.377 + }
1.378 + }
1.379 +
1.380 + cell_t res = 1;
1.381 +
1.382 + m_Players[client].Initialize(pszName, pszAddress, pEntity);
1.383 + m_clconnect->PushCell(client);
1.384 + m_clconnect->PushStringEx(reject, maxrejectlen, SM_PARAM_STRING_UTF8, SM_PARAM_COPYBACK);
1.385 + m_clconnect->PushCell(maxrejectlen);
1.386 + m_clconnect->Execute(&res, NULL);
1.387 +
1.388 + if (res)
1.389 + {
1.390 + if (!m_Players[client].IsAuthorized())
1.391 + {
1.392 + m_AuthQueue[++m_AuthQueue[0]] = client;
1.393 + }
1.394 + }
1.395 + else
1.396 + {
1.397 + RETURN_META_VALUE(MRES_SUPERCEDE, false);
1.398 + }
1.399 +
1.400 + m_UserIdLookUp[engine->GetPlayerUserId(pEntity)] = client;
1.401 +
1.402 + return true;
1.403 +}
1.404 +
1.405 +bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen)
1.406 +{
1.407 + int client = engine->IndexOfEdict(pEntity);
1.408 + bool orig_value = META_RESULT_ORIG_RET(bool);
1.409 + CPlayer *pPlayer = GetPlayerByIndex(client);
1.410 +
1.411 + if (orig_value)
1.412 + {
1.413 + List<IClientListener *>::iterator iter;
1.414 + IClientListener *pListener = NULL;
1.415 + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
1.416 + {
1.417 + pListener = (*iter);
1.418 + pListener->OnClientConnected(client);
1.419 + if (!pPlayer->IsConnected())
1.420 + {
1.421 + break;
1.422 + }
1.423 + }
1.424 + }
1.425 +
1.426 + if (!pPlayer->IsFakeClient()
1.427 + && m_bIsListenServer
1.428 + && strncmp(pszAddress, "127.0.0.1", 9) == 0)
1.429 + {
1.430 + m_ListenClient = client;
1.431 + }
1.432 +
1.433 + return true;
1.434 +}
1.435 +
1.436 +void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername)
1.437 +{
1.438 + cell_t res;
1.439 + int client = engine->IndexOfEdict(pEntity);
1.440 +
1.441 + CPlayer *pPlayer = GetPlayerByIndex(client);
1.442 + /* If they're not connected, they're a bot */
1.443 + if (!pPlayer->IsConnected())
1.444 + {
1.445 + /* Run manual connection routines */
1.446 + char error[255];
1.447 + const char *authid = engine->GetPlayerNetworkIDString(pEntity);
1.448 + pPlayer->Authorize(authid);
1.449 + if (!OnClientConnect(pEntity, playername, "127.0.0.1", error, sizeof(error)))
1.450 + {
1.451 + /* :TODO: kick the bot if it's rejected */
1.452 + return;
1.453 + }
1.454 + List<IClientListener *>::iterator iter;
1.455 + IClientListener *pListener = NULL;
1.456 + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
1.457 + {
1.458 + pListener = (*iter);
1.459 + pListener->OnClientConnected(client);
1.460 + /* See if bot was kicked */
1.461 + if (!pPlayer->IsConnected())
1.462 + {
1.463 + return;
1.464 + }
1.465 + }
1.466 + /* Now do authorization */
1.467 + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
1.468 + {
1.469 + pListener = (*iter);
1.470 + pListener->OnClientAuthorized(client, authid);
1.471 + }
1.472 + /* Finally, tell plugins */
1.473 + if (m_clauth->GetFunctionCount())
1.474 + {
1.475 + m_clauth->PushCell(client);
1.476 + m_clauth->PushString(authid);
1.477 + m_clauth->Execute(NULL);
1.478 + }
1.479 + pPlayer->Authorize_Post();
1.480 + }
1.481 +
1.482 + if (playerinfo)
1.483 + {
1.484 + pPlayer->m_Info = playerinfo->GetPlayerInfo(pEntity);
1.485 + }
1.486 +
1.487 + /* Get the client's language */
1.488 + if (m_QueryLang)
1.489 + {
1.490 + const char *name;
1.491 + if (!pPlayer->IsFakeClient() && (name=engine->GetClientConVarValue(client, "cl_language")))
1.492 + {
1.493 + unsigned int langid;
1.494 + pPlayer->m_LangId = (g_Translator.GetLanguageByName(name, &langid)) ? langid : g_Translator.GetServerLanguage();
1.495 + } else {
1.496 + pPlayer->m_LangId = g_Translator.GetServerLanguage();
1.497 + }
1.498 + }
1.499 +
1.500 + m_Players[client].Connect();
1.501 + m_PlayerCount++;
1.502 +
1.503 + List<IClientListener *>::iterator iter;
1.504 + IClientListener *pListener = NULL;
1.505 + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
1.506 + {
1.507 + pListener = (*iter);
1.508 + pListener->OnClientPutInServer(client);
1.509 + }
1.510 +
1.511 + m_clputinserver->PushCell(client);
1.512 + m_clputinserver->Execute(&res, NULL);
1.513 +
1.514 + if (m_Players[client].IsAuthorized())
1.515 + {
1.516 + m_Players[client].DoPostConnectAuthorization();
1.517 + }
1.518 +}
1.519 +
1.520 +void PlayerManager::OnSourceModLevelEnd()
1.521 +{
1.522 + /* Disconnect all bots still in game */
1.523 + for (int i=1; i<=m_maxClients; i++)
1.524 + {
1.525 + if (m_Players[i].IsConnected())
1.526 + {
1.527 + OnClientDisconnect(m_Players[i].GetEdict());
1.528 + }
1.529 + }
1.530 + m_PlayerCount = 0;
1.531 +}
1.532 +
1.533 +void PlayerManager::OnClientDisconnect(edict_t *pEntity)
1.534 +{
1.535 + cell_t res;
1.536 + int client = engine->IndexOfEdict(pEntity);
1.537 +
1.538 + if (m_Players[client].IsConnected())
1.539 + {
1.540 + m_cldisconnect->PushCell(client);
1.541 + m_cldisconnect->Execute(&res, NULL);
1.542 + }
1.543 + else
1.544 + {
1.545 + /* We don't care, prevent a double call */
1.546 + return;
1.547 + }
1.548 +
1.549 + if (m_Players[client].WasCountedAsInGame())
1.550 + {
1.551 + m_PlayerCount--;
1.552 + }
1.553 +
1.554 + List<IClientListener *>::iterator iter;
1.555 + IClientListener *pListener = NULL;
1.556 + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
1.557 + {
1.558 + pListener = (*iter);
1.559 + pListener->OnClientDisconnecting(client);
1.560 + }
1.561 +
1.562 + /**
1.563 + * Remove client from auth queue if necessary
1.564 + */
1.565 + if (!m_Players[client].IsAuthorized())
1.566 + {
1.567 + for (unsigned int i=1; i<=m_AuthQueue[0]; i++)
1.568 + {
1.569 + if (m_AuthQueue[i] == (unsigned)client)
1.570 + {
1.571 + /* Move everything ahead of us back by one */
1.572 + for (unsigned int j=i+1; j<=m_AuthQueue[0]; j++)
1.573 + {
1.574 + m_AuthQueue[j-1] = m_AuthQueue[j];
1.575 + }
1.576 + /* Remove us and break */
1.577 + m_AuthQueue[0]--;
1.578 + break;
1.579 + }
1.580 + }
1.581 + }
1.582 +
1.583 + m_Players[client].Disconnect();
1.584 + m_UserIdLookUp[engine->GetPlayerUserId(pEntity)] = 0;
1.585 +
1.586 + if (m_ListenClient == client)
1.587 + {
1.588 + m_ListenClient = 0;
1.589 + }
1.590 +}
1.591 +
1.592 +void PlayerManager::OnClientDisconnect_Post(edict_t *pEntity)
1.593 +{
1.594 + cell_t res;
1.595 + int client = engine->IndexOfEdict(pEntity);
1.596 +
1.597 + m_cldisconnect_post->PushCell(client);
1.598 + m_cldisconnect_post->Execute(&res, NULL);
1.599 +
1.600 + List<IClientListener *>::iterator iter;
1.601 + IClientListener *pListener = NULL;
1.602 + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
1.603 + {
1.604 + pListener = (*iter);
1.605 + pListener->OnClientDisconnected(client);
1.606 + }
1.607 +}
1.608 +
1.609 +#if defined ORANGEBOX_BUILD
1.610 +void PlayerManager::OnClientCommand(edict_t *pEntity, const CCommand &args)
1.611 +{
1.612 +#else
1.613 +void PlayerManager::OnClientCommand(edict_t *pEntity)
1.614 +{
1.615 + CCommand args;
1.616 +#endif
1.617 + int client = engine->IndexOfEdict(pEntity);
1.618 + cell_t res = Pl_Continue;
1.619 +
1.620 + CPlayer *pPlayer = GetPlayerByIndex(client);
1.621 + if (!pPlayer || !pPlayer->IsConnected())
1.622 + {
1.623 + return;
1.624 + }
1.625 +
1.626 + g_HL2.PushCommandStack(&args);
1.627 +
1.628 + int argcount = args.ArgC() - 1;
1.629 + const char *cmd = g_HL2.CurrentCommandName();
1.630 +
1.631 + bool result = g_ValveMenuStyle.OnClientCommand(client, cmd, args);
1.632 + if (result)
1.633 + {
1.634 + res = Pl_Handled;
1.635 + } else {
1.636 + result = g_RadioMenuStyle.OnClientCommand(client, cmd, args);
1.637 + if (result)
1.638 + {
1.639 + res = Pl_Handled;
1.640 + }
1.641 + }
1.642 +
1.643 + cell_t res2 = Pl_Continue;
1.644 + m_clcommand->PushCell(client);
1.645 + m_clcommand->PushCell(argcount);
1.646 + m_clcommand->Execute(&res2, NULL);
1.647 +
1.648 + if (res2 > res)
1.649 + {
1.650 + res = res2;
1.651 + }
1.652 +
1.653 + if (res >= Pl_Stop)
1.654 + {
1.655 + g_HL2.PopCommandStack();
1.656 + RETURN_META(MRES_SUPERCEDE);
1.657 + }
1.658 +
1.659 + res = g_ConCmds.DispatchClientCommand(client, cmd, argcount, (ResultType)res);
1.660 +
1.661 + g_HL2.PopCommandStack();
1.662 +
1.663 + if (res >= Pl_Handled)
1.664 + {
1.665 + RETURN_META(MRES_SUPERCEDE);
1.666 + }
1.667 +}
1.668 +
1.669 +void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
1.670 +{
1.671 + cell_t res;
1.672 + int client = engine->IndexOfEdict(pEntity);
1.673 +
1.674 + if (!m_Players[client].IsConnected())
1.675 + {
1.676 + return;
1.677 + }
1.678 +
1.679 + m_clinfochanged->PushCell(engine->IndexOfEdict(pEntity));
1.680 + m_clinfochanged->Execute(&res, NULL);
1.681 +
1.682 + IPlayerInfo *info = m_Players[client].GetPlayerInfo();
1.683 + const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name");
1.684 + const char *old_name = m_Players[client].m_Name.c_str();
1.685 +
1.686 + if (strcmp(old_name, new_name) != 0)
1.687 + {
1.688 + AdminId id = g_Admins.FindAdminByIdentity("name", new_name);
1.689 + if (id != INVALID_ADMIN_ID && m_Players[client].GetAdminId() != id)
1.690 + {
1.691 + if (!CheckSetAdminName(client, &m_Players[client], id))
1.692 + {
1.693 + m_Players[client].Kick("Your name is reserved by SourceMod; set your password to use it.");
1.694 + RETURN_META(MRES_IGNORED);
1.695 + }
1.696 + } else if ((id = g_Admins.FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) {
1.697 + if (id == m_Players[client].GetAdminId())
1.698 + {
1.699 + /* This player is changing their name; force them to drop admin privileges! */
1.700 + m_Players[client].SetAdminId(INVALID_ADMIN_ID, false);
1.701 + }
1.702 + }
1.703 + m_Players[client].SetName(new_name);
1.704 + }
1.705 +
1.706 + if (m_PassInfoVar.size() > 0)
1.707 + {
1.708 + /* Try for a password change */
1.709 + const char *old_pass = m_Players[client].m_LastPassword.c_str();
1.710 + const char *new_pass = engine->GetClientConVarValue(client, m_PassInfoVar.c_str());
1.711 + if (strcmp(old_pass, new_pass) != 0)
1.712 + {
1.713 + m_Players[client].m_LastPassword.assign(new_pass);
1.714 + if (m_Players[client].IsInGame() && m_Players[client].IsAuthorized())
1.715 + {
1.716 + /* If there is already an admin id assigned, this will just bail out. */
1.717 + m_Players[client].DoBasicAdminChecks();
1.718 + }
1.719 + }
1.720 + }
1.721 +}
1.722 +
1.723 +int PlayerManager::GetMaxClients()
1.724 +{
1.725 + return m_maxClients;
1.726 +}
1.727 +
1.728 +CPlayer *PlayerManager::GetPlayerByIndex(int client) const
1.729 +{
1.730 + if (client > m_maxClients || client < 1)
1.731 + {
1.732 + return NULL;
1.733 + }
1.734 + return &m_Players[client];
1.735 +}
1.736 +
1.737 +int PlayerManager::GetNumPlayers()
1.738 +{
1.739 + return m_PlayerCount;
1.740 +}
1.741 +
1.742 +int PlayerManager::GetClientOfUserId(int userid)
1.743 +{
1.744 + if (userid < 0 || userid > USHRT_MAX)
1.745 + {
1.746 + return 0;
1.747 + }
1.748 +
1.749 + int client = m_UserIdLookUp[userid];
1.750 +
1.751 + /* Verify the userid. The cache can get messed up with older
1.752 + * Valve engines. :TODO: If this gets fixed, do an old engine
1.753 + * check before invoking this backwards compat code.
1.754 + */
1.755 + if (client)
1.756 + {
1.757 + CPlayer *player = GetPlayerByIndex(client);
1.758 + if (player && player->IsConnected())
1.759 + {
1.760 + int realUserId = engine->GetPlayerUserId(player->GetEdict());
1.761 + if (realUserId == userid)
1.762 + {
1.763 + return client;
1.764 + }
1.765 + }
1.766 + }
1.767 +
1.768 + /* If we can't verify the userid, we have to do a manual loop */
1.769 + CPlayer *player;
1.770 + for (int i = 1; i <= m_maxClients; i++)
1.771 + {
1.772 + player = GetPlayerByIndex(i);
1.773 + if (!player || !player->IsConnected())
1.774 + {
1.775 + continue;
1.776 + }
1.777 + if (engine->GetPlayerUserId(player->GetEdict()) == userid)
1.778 + {
1.779 + m_UserIdLookUp[userid] = i;
1.780 + return i;
1.781 + }
1.782 + }
1.783 +
1.784 + return 0;
1.785 +}
1.786 +
1.787 +void PlayerManager::AddClientListener(IClientListener *listener)
1.788 +{
1.789 + m_hooks.push_back(listener);
1.790 +}
1.791 +
1.792 +void PlayerManager::RemoveClientListener(IClientListener *listener)
1.793 +{
1.794 + m_hooks.remove(listener);
1.795 +}
1.796 +
1.797 +IGamePlayer *PlayerManager::GetGamePlayer(edict_t *pEdict)
1.798 +{
1.799 + int index = engine->IndexOfEdict(pEdict);
1.800 + return GetGamePlayer(index);
1.801 +}
1.802 +
1.803 +IGamePlayer *PlayerManager::GetGamePlayer(int client)
1.804 +{
1.805 + return GetPlayerByIndex(client);
1.806 +}
1.807 +
1.808 +void PlayerManager::ClearAdminId(AdminId id)
1.809 +{
1.810 + for (int i=1; i<=m_maxClients; i++)
1.811 + {
1.812 + if (m_Players[i].m_Admin == id)
1.813 + {
1.814 + m_Players[i].DumpAdmin(true);
1.815 + }
1.816 + }
1.817 +}
1.818 +
1.819 +void PlayerManager::ClearAllAdmins()
1.820 +{
1.821 + for (int i=1; i<=m_maxClients; i++)
1.822 + {
1.823 + m_Players[i].DumpAdmin(true);
1.824 + }
1.825 +}
1.826 +
1.827 +const char *PlayerManager::GetPassInfoVar()
1.828 +{
1.829 + return m_PassInfoVar.c_str();
1.830 +}
1.831 +
1.832 +void PlayerManager::RecheckAnyAdmins()
1.833 +{
1.834 + for (int i=1; i<=m_maxClients; i++)
1.835 + {
1.836 + if (m_Players[i].IsInGame() && m_Players[i].IsAuthorized())
1.837 + {
1.838 + m_Players[i].DoBasicAdminChecks();
1.839 + }
1.840 + }
1.841 +}
1.842 +
1.843 +unsigned int PlayerManager::GetReplyTo()
1.844 +{
1.845 + return g_ChatTriggers.GetReplyTo();
1.846 +}
1.847 +
1.848 +unsigned int PlayerManager::SetReplyTo(unsigned int reply)
1.849 +{
1.850 + return g_ChatTriggers.SetReplyTo(reply);
1.851 +}
1.852 +
1.853 +int PlayerManager::FilterCommandTarget(IGamePlayer *pAdmin, IGamePlayer *pTarget, int flags)
1.854 +{
1.855 + return InternalFilterCommandTarget((CPlayer *)pAdmin, (CPlayer *)pTarget, flags);
1.856 +}
1.857 +
1.858 +void PlayerManager::RegisterCommandTargetProcessor(ICommandTargetProcessor *pHandler)
1.859 +{
1.860 + target_processors.push_back(pHandler);
1.861 +}
1.862 +
1.863 +void PlayerManager::UnregisterCommandTargetProcessor(ICommandTargetProcessor *pHandler)
1.864 +{
1.865 + target_processors.remove(pHandler);
1.866 +}
1.867 +
1.868 +int PlayerManager::InternalFilterCommandTarget(CPlayer *pAdmin, CPlayer *pTarget, int flags)
1.869 +{
1.870 + if ((flags & COMMAND_FILTER_CONNECTED) == COMMAND_FILTER_CONNECTED
1.871 + && !pTarget->IsConnected())
1.872 + {
1.873 + return COMMAND_TARGET_NONE;
1.874 + }
1.875 + else if ((flags & COMMAND_FILTER_CONNECTED) != COMMAND_FILTER_CONNECTED &&
1.876 + !pTarget->IsInGame())
1.877 + {
1.878 + return COMMAND_TARGET_NOT_IN_GAME;
1.879 + }
1.880 +
1.881 + if ((flags & COMMAND_FILTER_NO_BOTS) == COMMAND_FILTER_NO_BOTS
1.882 + && pTarget->IsFakeClient())
1.883 + {
1.884 + return COMMAND_TARGET_NOT_HUMAN;
1.885 + }
1.886 +
1.887 + if (pAdmin != NULL)
1.888 + {
1.889 + if ((flags & COMMAND_FILTER_NO_IMMUNITY) != COMMAND_FILTER_NO_IMMUNITY
1.890 + && !g_Admins.CanAdminTarget(pAdmin->GetAdminId(), pTarget->GetAdminId()))
1.891 + {
1.892 + return COMMAND_TARGET_IMMUNE;
1.893 + }
1.894 + }
1.895 +
1.896 + if ((flags & COMMAND_FILTER_ALIVE) == COMMAND_FILTER_ALIVE
1.897 + && pTarget->GetLifeState() != PLAYER_LIFE_ALIVE)
1.898 + {
1.899 + return COMMAND_TARGET_NOT_ALIVE;
1.900 + }
1.901 +
1.902 + if ((flags & COMMAND_FILTER_DEAD) == COMMAND_FILTER_DEAD
1.903 + && pTarget->GetLifeState() != PLAYER_LIFE_DEAD)
1.904 + {
1.905 + return COMMAND_TARGET_NOT_DEAD;
1.906 + }
1.907 +
1.908 + return COMMAND_TARGET_VALID;
1.909 +}
1.910 +
1.911 +void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info)
1.912 +{
1.913 + CPlayer *pTarget, *pAdmin;
1.914 + int max_clients, total = 0;
1.915 +
1.916 + max_clients = GetMaxClients();
1.917 +
1.918 + if (info->max_targets < 1)
1.919 + {
1.920 + info->reason = COMMAND_TARGET_NONE;
1.921 + info->num_targets = 0;
1.922 + }
1.923 +
1.924 + if (info->admin == 0)
1.925 + {
1.926 + pAdmin = NULL;
1.927 + }
1.928 + else
1.929 + {
1.930 + pAdmin = GetPlayerByIndex(info->admin);
1.931 + }
1.932 +
1.933 + if (info->pattern[0] == '#')
1.934 + {
1.935 + int userid = atoi(&info->pattern[1]);
1.936 + int client = GetClientOfUserId(userid);
1.937 +
1.938 + /* See if a valid userid matched */
1.939 + if (client > 0)
1.940 + {
1.941 + IGamePlayer *pTarget = GetPlayerByIndex(client);
1.942 + if (pTarget != NULL)
1.943 + {
1.944 + if ((info->reason = FilterCommandTarget(pAdmin, pTarget, info->flags)) == COMMAND_TARGET_VALID)
1.945 + {
1.946 + info->targets[0] = client;
1.947 + info->num_targets = 1;
1.948 + strncopy(info->target_name, pTarget->GetName(), info->target_name_maxlength);
1.949 + info->target_name_style = COMMAND_TARGETNAME_RAW;
1.950 + }
1.951 + else
1.952 + {
1.953 + info->num_targets = 0;
1.954 + }
1.955 + return;
1.956 + }
1.957 + }
1.958 +
1.959 + /* Do we need to look for a steam id? */
1.960 + if (strncmp(&info->pattern[1], "STEAM_", 6) == 0)
1.961 + {
1.962 + size_t p, len;
1.963 + char new_pattern[256];
1.964 +
1.965 + strcpy(new_pattern, "STEAM_");
1.966 + len = strlen(&info->pattern[7]);
1.967 + for (p = 0; p < len; p++)
1.968 + {
1.969 + new_pattern[6 + p] = info->pattern[7 + p];
1.970 + if (new_pattern[6 + p] == '_')
1.971 + {
1.972 + new_pattern[6 + p] = ':';
1.973 + }
1.974 + }
1.975 + new_pattern[6 + p] = '\0';
1.976 +
1.977 + for (int i = 1; i <= max_clients; i++)
1.978 + {
1.979 + if ((pTarget = GetPlayerByIndex(i)) == NULL)
1.980 + {
1.981 + continue;
1.982 + }
1.983 + if (!pTarget->IsConnected() || !pTarget->IsAuthorized())
1.984 + {
1.985 + continue;
1.986 + }
1.987 + if (strcmp(pTarget->GetAuthString(), new_pattern) == 0)
1.988 + {
1.989 + if ((info->reason = FilterCommandTarget(pAdmin, pTarget, info->flags))
1.990 + == COMMAND_TARGET_VALID)
1.991 + {
1.992 + info->targets[0] = i;
1.993 + info->num_targets = 1;
1.994 + strncopy(info->target_name, pTarget->GetName(), info->target_name_maxlength);
1.995 + info->target_name_style = COMMAND_TARGETNAME_RAW;
1.996 + }
1.997 + else
1.998 + {
1.999 + info->num_targets = 0;
1.1000 + }
1.1001 + return;
1.1002 + }
1.1003 + }
1.1004 + }
1.1005 +
1.1006 + /* See if an exact name matches */
1.1007 + for (int i = 1; i <= max_clients; i++)
1.1008 + {
1.1009 + if ((pTarget = GetPlayerByIndex(i)) == NULL)
1.1010 + {
1.1011 + continue;
1.1012 + }
1.1013 + if (!pTarget->IsConnected())
1.1014 + {
1.1015 + continue;
1.1016 + }
1.1017 + if (strcmp(pTarget->GetName(), &info->pattern[1]) == 0)
1.1018 + {
1.1019 + if ((info->reason = FilterCommandTarget(pAdmin, pTarget, info->flags))
1.1020 + == COMMAND_TARGET_VALID)
1.1021 + {
1.1022 + info->targets[0] = i;
1.1023 + info->num_targets = 1;
1.1024 + strncopy(info->target_name, pTarget->GetName(), info->target_name_maxlength);
1.1025 + info->target_name_style = COMMAND_TARGETNAME_RAW;
1.1026 + }
1.1027 + else
1.1028 + {
1.1029 + info->num_targets = 0;
1.1030 + }
1.1031 + return;
1.1032 + }
1.1033 + }
1.1034 + }
1.1035 +
1.1036 + if (strcmp(info->pattern, "@me") == 0 && info->admin != 0)
1.1037 + {
1.1038 + info->targets[0] = info->admin;
1.1039 + info->num_targets = 1;
1.1040 + strncopy(info->target_name, pAdmin->GetName(), info->target_name_maxlength);
1.1041 + info->target_name_style = COMMAND_TARGETNAME_RAW;
1.1042 + return;
1.1043 + }
1.1044 +
1.1045 + if ((info->flags & COMMAND_FILTER_NO_MULTI) != COMMAND_FILTER_NO_MULTI)
1.1046 + {
1.1047 + bool is_multi = false;
1.1048 + bool bots_only = false;
1.1049 + int skip_client = -1;
1.1050 +
1.1051 + if (strcmp(info->pattern, "@all") == 0)
1.1052 + {
1.1053 + is_multi = true;
1.1054 + strncopy(info->target_name, "all players", info->target_name_maxlength);
1.1055 + info->target_name_style = COMMAND_TARGETNAME_ML;
1.1056 + }
1.1057 + else if (strcmp(info->pattern, "@dead") == 0)
1.1058 + {
1.1059 + is_multi = true;
1.1060 + if ((info->flags & COMMAND_FILTER_ALIVE) == COMMAND_FILTER_ALIVE)
1.1061 + {
1.1062 + info->num_targets = 0;
1.1063 + info->reason = COMMAND_TARGET_NOT_ALIVE;
1.1064 + return;
1.1065 + }
1.1066 + info->flags |= COMMAND_FILTER_DEAD;
1.1067 + strncopy(info->target_name, "all dead players", info->target_name_maxlength);
1.1068 + info->target_name_style = COMMAND_TARGETNAME_ML;
1.1069 + }
1.1070 + else if (strcmp(info->pattern, "@alive") == 0)
1.1071 + {
1.1072 + is_multi = true;
1.1073 + if ((info->flags & COMMAND_FILTER_DEAD) == COMMAND_FILTER_DEAD)
1.1074 + {
1.1075 + info->num_targets = 0;
1.1076 + info->reason = COMMAND_TARGET_NOT_DEAD;
1.1077 + return;
1.1078 + }
1.1079 + strncopy(info->target_name, "all alive players", info->target_name_maxlength);
1.1080 + info->target_name_style = COMMAND_TARGETNAME_ML;
1.1081 + info->flags |= COMMAND_FILTER_ALIVE;
1.1082 + }
1.1083 + else if (strcmp(info->pattern, "@bots") == 0)
1.1084 + {
1.1085 + is_multi = true;
1.1086 + if ((info->flags & COMMAND_FILTER_NO_BOTS) == COMMAND_FILTER_NO_BOTS)
1.1087 + {
1.1088 + info->num_targets = 0;
1.1089 + info->reason = COMMAND_FILTER_NO_BOTS;
1.1090 + return;
1.1091 + }
1.1092 + strncopy(info->target_name, "all bots", info->target_name_maxlength);
1.1093 + info->target_name_style = COMMAND_TARGETNAME_ML;
1.1094 + bots_only = true;
1.1095 + }
1.1096 + else if (strcmp(info->pattern, "@humans") == 0)
1.1097 + {
1.1098 + is_multi = true;
1.1099 + strncopy(info->target_name, "all humans", info->target_name_maxlength);
1.1100 + info->target_name_style = COMMAND_TARGETNAME_ML;
1.1101 + info->flags |= COMMAND_FILTER_NO_BOTS;
1.1102 + }
1.1103 + else if (strcmp(info->pattern, "@!me") == 0)
1.1104 + {
1.1105 + is_multi = true;
1.1106 + strncopy(info->target_name, "all players", info->target_name_maxlength);
1.1107 + info->target_name_style = COMMAND_TARGETNAME_ML;
1.1108 + skip_client = info->admin;
1.1109 + }
1.1110 +
1.1111 + if (is_multi)
1.1112 + {
1.1113 + for (int i = 1; i <= max_clients && total < info->max_targets; i++)
1.1114 + {
1.1115 + if ((pTarget = GetPlayerByIndex(i)) == NULL)
1.1116 + {
1.1117 + continue;
1.1118 + }
1.1119 + if (FilterCommandTarget(pAdmin, pTarget, info->flags) > 0)
1.1120 + {
1.1121 + if ((!bots_only || pTarget->IsFakeClient())
1.1122 + && skip_client != i)
1.1123 + {
1.1124 + info->targets[total++] = i;
1.1125 + }
1.1126 + }
1.1127 + }
1.1128 +
1.1129 + info->num_targets = total;
1.1130 + info->reason = (info->num_targets) ? COMMAND_TARGET_VALID : COMMAND_TARGET_EMPTY_FILTER;
1.1131 + return;
1.1132 + }
1.1133 + }
1.1134 +
1.1135 + List<ICommandTargetProcessor *>::iterator iter;
1.1136 + for (iter = target_processors.begin(); iter != target_processors.end(); iter++)
1.1137 + {
1.1138 + ICommandTargetProcessor *pProcessor = (*iter);
1.1139 + if (pProcessor->ProcessCommandTarget(info))
1.1140 + {
1.1141 + return;
1.1142 + }
1.1143 + }
1.1144 +
1.1145 + /* Check partial names */
1.1146 + int found_client = 0;
1.1147 + CPlayer *pFoundClient = NULL;
1.1148 + for (int i = 1; i <= max_clients; i++)
1.1149 + {
1.1150 + if ((pTarget = GetPlayerByIndex(i)) == NULL)
1.1151 + {
1.1152 + continue;
1.1153 + }
1.1154 +
1.1155 + if (stristr(pTarget->GetName(), info->pattern) != NULL)
1.1156 + {
1.1157 + if (found_client)
1.1158 + {
1.1159 + info->num_targets = 0;
1.1160 + info->reason = COMMAND_TARGET_AMBIGUOUS;
1.1161 + return;
1.1162 + }
1.1163 + else
1.1164 + {
1.1165 + found_client = i;
1.1166 + pFoundClient = pTarget;
1.1167 + }
1.1168 + }
1.1169 + }
1.1170 +
1.1171 + if (found_client)
1.1172 + {
1.1173 + if ((info->reason = FilterCommandTarget(pAdmin, pFoundClient, info->flags))
1.1174 + == COMMAND_TARGET_VALID)
1.1175 + {
1.1176 + info->targets[0] = found_client;
1.1177 + info->num_targets = 1;
1.1178 + strncopy(info->target_name, pFoundClient->GetName(), info->target_name_maxlength);
1.1179 + info->target_name_style = COMMAND_TARGETNAME_RAW;
1.1180 + }
1.1181 + else
1.1182 + {
1.1183 + info->num_targets = 0;
1.1184 + }
1.1185 + }
1.1186 + else
1.1187 + {
1.1188 + info->num_targets = 0;
1.1189 + info->reason = COMMAND_TARGET_NONE;
1.1190 + }
1.1191 +}
1.1192 +
1.1193 +/*******************
1.1194 + *** PLAYER CODE ***
1.1195 + *******************/
1.1196 +
1.1197 +CPlayer::CPlayer()
1.1198 +{
1.1199 + m_IsConnected = false;
1.1200 + m_IsInGame = false;
1.1201 + m_IsAuthorized = false;
1.1202 + m_pEdict = NULL;
1.1203 + m_Admin = INVALID_ADMIN_ID;
1.1204 + m_TempAdmin = false;
1.1205 + m_Info = NULL;
1.1206 + m_bAdminCheckSignalled = false;
1.1207 + m_bIsInKickQueue = false;
1.1208 + m_LastPassword.clear();
1.1209 + m_LangId = SOURCEMOD_LANGUAGE_ENGLISH;
1.1210 +}
1.1211 +
1.1212 +void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
1.1213 +{
1.1214 + m_IsConnected = true;
1.1215 + m_Name.assign(name);
1.1216 + m_Ip.assign(ip);
1.1217 + m_pEdict = pEntity;
1.1218 + m_iIndex = engine->IndexOfEdict(pEntity);
1.1219 + m_LangId = g_Translator.GetServerLanguage();
1.1220 +
1.1221 + char ip2[24], *ptr;
1.1222 + strncopy(ip2, ip, sizeof(ip2));
1.1223 + if ((ptr = strchr(ip2, ':')) != NULL)
1.1224 + {
1.1225 + *ptr = '\0';
1.1226 + }
1.1227 + m_IpNoPort.assign(ip2);
1.1228 +}
1.1229 +
1.1230 +void CPlayer::Connect()
1.1231 +{
1.1232 + if (m_IsInGame)
1.1233 + {
1.1234 + return;
1.1235 + }
1.1236 +
1.1237 + m_IsInGame = true;
1.1238 +
1.1239 + const char *var = g_Players.GetPassInfoVar();
1.1240 + int client = engine->IndexOfEdict(m_pEdict);
1.1241 + if (var[0] != '\0')
1.1242 + {
1.1243 + const char *pass = engine->GetClientConVarValue(client, var);
1.1244 + m_LastPassword.assign(pass ? pass : "");
1.1245 + }
1.1246 + else
1.1247 + {
1.1248 + m_LastPassword.assign("");
1.1249 + }
1.1250 +}
1.1251 +
1.1252 +void CPlayer::Authorize(const char *steamid)
1.1253 +{
1.1254 + if (m_IsAuthorized)
1.1255 + {
1.1256 + return;
1.1257 + }
1.1258 +
1.1259 + m_IsAuthorized = true;
1.1260 + m_AuthID.assign(steamid);
1.1261 +}
1.1262 +
1.1263 +void CPlayer::Disconnect()
1.1264 +{
1.1265 + DumpAdmin(false);
1.1266 + m_IsConnected = false;
1.1267 + m_IsInGame = false;
1.1268 + m_IsAuthorized = false;
1.1269 + m_Name.clear();
1.1270 + m_Ip.clear();
1.1271 + m_AuthID.clear();
1.1272 + m_pEdict = NULL;
1.1273 + m_Info = NULL;
1.1274 + m_bAdminCheckSignalled = false;
1.1275 + m_UserId = -1;
1.1276 + m_bIsInKickQueue = false;
1.1277 +}
1.1278 +
1.1279 +void CPlayer::SetName(const char *name)
1.1280 +{
1.1281 + m_Name.assign(name);
1.1282 +}
1.1283 +
1.1284 +const char *CPlayer::GetName()
1.1285 +{
1.1286 + if (m_Info && m_pEdict->GetUnknown())
1.1287 + {
1.1288 + return m_Info->GetName();
1.1289 + }
1.1290 +
1.1291 + return m_Name.c_str();
1.1292 +}
1.1293 +
1.1294 +const char *CPlayer::GetIPAddress()
1.1295 +{
1.1296 + return m_Ip.c_str();
1.1297 +}
1.1298 +
1.1299 +const char *CPlayer::GetAuthString()
1.1300 +{
1.1301 + return m_AuthID.c_str();
1.1302 +}
1.1303 +
1.1304 +edict_t *CPlayer::GetEdict()
1.1305 +{
1.1306 + return m_pEdict;
1.1307 +}
1.1308 +
1.1309 +bool CPlayer::IsInGame()
1.1310 +{
1.1311 + return m_IsInGame && (m_pEdict->GetUnknown() != NULL);
1.1312 +}
1.1313 +
1.1314 +bool CPlayer::WasCountedAsInGame()
1.1315 +{
1.1316 + return m_IsInGame;
1.1317 +}
1.1318 +
1.1319 +bool CPlayer::IsConnected()
1.1320 +{
1.1321 + return m_IsConnected;
1.1322 +}
1.1323 +
1.1324 +bool CPlayer::IsAuthorized()
1.1325 +{
1.1326 + return m_IsAuthorized;
1.1327 +}
1.1328 +
1.1329 +IPlayerInfo *CPlayer::GetPlayerInfo()
1.1330 +{
1.1331 + if (m_pEdict->GetUnknown())
1.1332 + {
1.1333 + return m_Info;
1.1334 + }
1.1335 +
1.1336 + return NULL;
1.1337 +}
1.1338 +
1.1339 +bool CPlayer::IsFakeClient()
1.1340 +{
1.1341 + return (strncasecmp(m_AuthID.c_str(), "BOT", 3) == 0);
1.1342 +}
1.1343 +
1.1344 +void CPlayer::SetAdminId(AdminId id, bool temporary)
1.1345 +{
1.1346 + if (!m_IsConnected)
1.1347 + {
1.1348 + return;
1.1349 + }
1.1350 +
1.1351 + DumpAdmin(false);
1.1352 +
1.1353 + m_Admin = id;
1.1354 + m_TempAdmin = temporary;
1.1355 +}
1.1356 +
1.1357 +AdminId CPlayer::GetAdminId()
1.1358 +{
1.1359 + return m_Admin;
1.1360 +}
1.1361 +
1.1362 +void CPlayer::DumpAdmin(bool deleting)
1.1363 +{
1.1364 + if (m_Admin != INVALID_ADMIN_ID)
1.1365 + {
1.1366 + if (m_TempAdmin && !deleting)
1.1367 + {
1.1368 + g_Admins.InvalidateAdmin(m_Admin);
1.1369 + }
1.1370 + m_Admin = INVALID_ADMIN_ID;
1.1371 + m_TempAdmin = false;
1.1372 + }
1.1373 +}
1.1374 +
1.1375 +void CPlayer::Kick(const char *str)
1.1376 +{
1.1377 + MarkAsBeingKicked();
1.1378 + INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(m_iIndex));
1.1379 + IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
1.1380 + pClient->Disconnect("%s", str);
1.1381 +}
1.1382 +
1.1383 +void CPlayer::Authorize_Post()
1.1384 +{
1.1385 + if (m_IsInGame)
1.1386 + {
1.1387 + DoPostConnectAuthorization();
1.1388 + }
1.1389 +}
1.1390 +
1.1391 +void CPlayer::DoPostConnectAuthorization()
1.1392 +{
1.1393 + bool delay = false;
1.1394 +
1.1395 + List<IClientListener *>::iterator iter;
1.1396 + for (iter = g_Players.m_hooks.begin();
1.1397 + iter != g_Players.m_hooks.end();
1.1398 + iter++)
1.1399 + {
1.1400 + IClientListener *pListener = (*iter);
1.1401 +#if defined MIN_API_FOR_ADMINCALLS
1.1402 + if (pListener->GetClientListenerVersion() < MIN_API_FOR_ADMINCALLS)
1.1403 + {
1.1404 + continue;
1.1405 + }
1.1406 +#endif
1.1407 + if (!pListener->OnClientPreAdminCheck(m_iIndex))
1.1408 + {
1.1409 + delay = true;
1.1410 + }
1.1411 + }
1.1412 +
1.1413 + cell_t result = 0;
1.1414 + PreAdminCheck->PushCell(m_iIndex);
1.1415 + PreAdminCheck->Execute(&result);
1.1416 +
1.1417 + /* Defer, for better or worse */
1.1418 + if (delay || (ResultType)result >= Pl_Handled)
1.1419 + {
1.1420 + return;
1.1421 + }
1.1422 +
1.1423 + /* Sanity check */
1.1424 + if (!IsConnected())
1.1425 + {
1.1426 + return;
1.1427 + }
1.1428 +
1.1429 + /* Otherwise, go ahead and do admin checks */
1.1430 + DoBasicAdminChecks();
1.1431 +
1.1432 + /* Send the notification out */
1.1433 + NotifyPostAdminChecks();
1.1434 +}
1.1435 +
1.1436 +bool CPlayer::RunAdminCacheChecks()
1.1437 +{
1.1438 + AdminId old_id = GetAdminId();
1.1439 +
1.1440 + DoBasicAdminChecks();
1.1441 +
1.1442 + return (GetAdminId() != old_id);
1.1443 +}
1.1444 +
1.1445 +void CPlayer::NotifyPostAdminChecks()
1.1446 +{
1.1447 + if (m_bAdminCheckSignalled)
1.1448 + {
1.1449 + return;
1.1450 + }
1.1451 +
1.1452 + /* Block beforehand so they can't double-call */
1.1453 + m_bAdminCheckSignalled = true;
1.1454 +
1.1455 + List<IClientListener *>::iterator iter;
1.1456 + for (iter = g_Players.m_hooks.begin();
1.1457 + iter != g_Players.m_hooks.end();
1.1458 + iter++)
1.1459 + {
1.1460 + IClientListener *pListener = (*iter);
1.1461 +#if defined MIN_API_FOR_ADMINCALLS
1.1462 + if (pListener->GetClientListenerVersion() < MIN_API_FOR_ADMINCALLS)
1.1463 + {
1.1464 + continue;
1.1465 + }
1.1466 +#endif
1.1467 + pListener->OnClientPostAdminCheck(m_iIndex);
1.1468 + }
1.1469 +
1.1470 + PostAdminFilter->PushCell(m_iIndex);
1.1471 + PostAdminFilter->Execute(NULL);
1.1472 +
1.1473 + PostAdminCheck->PushCell(m_iIndex);
1.1474 + PostAdminCheck->Execute(NULL);
1.1475 +}
1.1476 +
1.1477 +void CPlayer::DoBasicAdminChecks()
1.1478 +{
1.1479 + if (GetAdminId() != INVALID_ADMIN_ID)
1.1480 + {
1.1481 + return;
1.1482 + }
1.1483 +
1.1484 + /* First check the name */
1.1485 + AdminId id;
1.1486 + int client = engine->IndexOfEdict(m_pEdict);
1.1487 +
1.1488 + if ((id = g_Admins.FindAdminByIdentity("name", GetName())) != INVALID_ADMIN_ID)
1.1489 + {
1.1490 + if (!g_Players.CheckSetAdminName(client, this, id))
1.1491 + {
1.1492 + int userid = engine->GetPlayerUserId(m_pEdict);
1.1493 + g_Timers.CreateTimer(&s_KickPlayerTimer, 0.1f, (void *)userid, 0);
1.1494 + }
1.1495 + return;
1.1496 + }
1.1497 +
1.1498 + /* Check IP */
1.1499 + if ((id = g_Admins.FindAdminByIdentity("ip", m_IpNoPort.c_str())) != INVALID_ADMIN_ID)
1.1500 + {
1.1501 + if (g_Players.CheckSetAdmin(client, this, id))
1.1502 + {
1.1503 + return;
1.1504 + }
1.1505 + }
1.1506 +
1.1507 + /* Check IP address */
1.1508 + if ((id = g_Admins.FindAdminByIdentity("steam", m_AuthID.c_str())) != INVALID_ADMIN_ID)
1.1509 + {
1.1510 + if (g_Players.CheckSetAdmin(client, this, id))
1.1511 + {
1.1512 + return;
1.1513 + }
1.1514 + }
1.1515 +}
1.1516 +
1.1517 +unsigned int CPlayer::GetLanguageId()
1.1518 +{
1.1519 + return m_LangId;
1.1520 +}
1.1521 +
1.1522 +int CPlayer::GetUserId()
1.1523 +{
1.1524 + if (m_UserId == -1)
1.1525 + {
1.1526 + m_UserId = engine->GetPlayerUserId(GetEdict());
1.1527 + }
1.1528 +
1.1529 + return m_UserId;
1.1530 +}
1.1531 +
1.1532 +bool CPlayer::IsInKickQueue()
1.1533 +{
1.1534 + return m_bIsInKickQueue;
1.1535 +}
1.1536 +
1.1537 +void CPlayer::MarkAsBeingKicked()
1.1538 +{
1.1539 + m_bIsInKickQueue = true;
1.1540 +}
1.1541 +
1.1542 +int CPlayer::GetLifeState()
1.1543 +{
1.1544 + if (lifestate_offset == -1)
1.1545 + {
1.1546 + if (!g_pGameConf->GetOffset("m_lifeState", &lifestate_offset))
1.1547 + {
1.1548 + lifestate_offset = -2;
1.1549 + }
1.1550 + }
1.1551 +
1.1552 + if (lifestate_offset < 0)
1.1553 + {
1.1554 + IPlayerInfo *info = GetPlayerInfo();
1.1555 + if (info == NULL)
1.1556 + {
1.1557 + return PLAYER_LIFE_UNKNOWN;
1.1558 + }
1.1559 + return info->IsDead() ? PLAYER_LIFE_DEAD : PLAYER_LIFE_ALIVE;
1.1560 + }
1.1561 +
1.1562 + if (m_pEdict == NULL)
1.1563 + {
1.1564 + return PLAYER_LIFE_UNKNOWN;
1.1565 + }
1.1566 +
1.1567 + CBaseEntity *pEntity;
1.1568 + IServerUnknown *pUnknown = m_pEdict->GetUnknown();
1.1569 + if (pUnknown == NULL || (pEntity = pUnknown->GetBaseEntity()) == NULL)
1.1570 + {
1.1571 + return PLAYER_LIFE_UNKNOWN;
1.1572 + }
1.1573 +
1.1574 + if (*((uint8_t *)pEntity + lifestate_offset) == LIFE_ALIVE)
1.1575 + {
1.1576 + return PLAYER_LIFE_ALIVE;
1.1577 + }
1.1578 + else
1.1579 + {
1.1580 + return PLAYER_LIFE_DEAD;
1.1581 + }
1.1582 +}