3 * =============================================================================
5 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "PlayerManager.h"
33 #include "ForwardSys.h"
35 #include "AdminCache.h"
36 #include "ConCmdManager.h"
37 #include "MenuStyle_Valve.h"
38 #include "MenuStyle_Radio.h"
39 #include "sm_stringutil.h"
40 #include "CoreConfig.h"
41 #include <inetchannel.h>
44 #include "Translator.h"
46 #include "ChatTriggers.h"
47 #include "HalfLife2.h"
49 PlayerManager g_Players;
50 bool g_OnMapStarted = false;
51 IForward *PreAdminCheck = NULL;
52 IForward *PostAdminCheck = NULL;
53 const unsigned int *g_NumPlayersToAuth = NULL;
55 SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char *, const char *, char *, int);
56 SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, const char *);
57 SH_DECL_HOOK1_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, edict_t *);
58 #if defined ORANGEBOX_BUILD
59 SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &);
61 SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *);
63 SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *);
64 SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int);
66 class KickPlayerTimer : public ITimedEvent
69 ResultType OnTimer(ITimer *pTimer, void *pData)
71 int userid = (int)pData;
72 int client = g_Players.GetClientOfUserId(userid);
75 CPlayer *player = g_Players.GetPlayerByIndex(client);
76 player->Kick("Your name is reserved by SourceMod; set your password to use it.");
80 void OnTimerEnd(ITimer *pTimer, void *pData)
85 PlayerManager::PlayerManager()
90 m_UserIdLookUp = new int[USHRT_MAX+1];
91 memset(m_UserIdLookUp, 0, sizeof(int) * (USHRT_MAX+1));
94 PlayerManager::~PlayerManager()
96 g_NumPlayersToAuth = NULL;
98 delete [] m_AuthQueue;
99 delete [] m_UserIdLookUp;
102 void PlayerManager::OnSourceModAllInitialized()
104 SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect, false);
105 SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect_Post, true);
106 SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &PlayerManager::OnClientPutInServer, true);
107 SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect, false);
108 SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect_Post, true);
109 SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, serverClients, this, &PlayerManager::OnClientCommand, false);
110 SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, serverClients, this, &PlayerManager::OnClientSettingsChanged, true);
111 SH_ADD_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &PlayerManager::OnServerActivate, true);
113 g_ShareSys.AddInterface(NULL, this);
115 ParamType p1[] = {Param_Cell, Param_String, Param_Cell};
116 ParamType p2[] = {Param_Cell};
118 m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_Event, 3, p1);
119 m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2);
120 m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2);
121 m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2);
122 m_clcommand = g_Forwards.CreateForward("OnClientCommand", ET_Hook, 2, NULL, Param_Cell, Param_Cell);
123 m_clinfochanged = g_Forwards.CreateForward("OnClientSettingsChanged", ET_Ignore, 1, p2);
124 m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
125 m_onActivate = g_Forwards.CreateForward("OnServerLoad", ET_Ignore, 0, NULL);
126 m_onActivate2 = g_Forwards.CreateForward("OnMapStart", ET_Ignore, 0, NULL);
128 PreAdminCheck = g_Forwards.CreateForward("OnClientPreAdminCheck", ET_Event, 1, p1);
129 PostAdminCheck = g_Forwards.CreateForward("OnClientPostAdminCheck", ET_Ignore, 1, p1);
132 void PlayerManager::OnSourceModShutdown()
134 SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &PlayerManager::OnClientConnect, false);
135 SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &PlayerManager::OnClientPutInServer, true);
136 SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect, false);
137 SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &PlayerManager::OnClientDisconnect_Post, true);
138 SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientCommand, serverClients, this, &PlayerManager::OnClientCommand, false);
139 SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, serverClients, this, &PlayerManager::OnClientSettingsChanged, true);
140 SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &PlayerManager::OnServerActivate, true);
142 /* Release forwards */
143 g_Forwards.ReleaseForward(m_clconnect);
144 g_Forwards.ReleaseForward(m_clputinserver);
145 g_Forwards.ReleaseForward(m_cldisconnect);
146 g_Forwards.ReleaseForward(m_cldisconnect_post);
147 g_Forwards.ReleaseForward(m_clcommand);
148 g_Forwards.ReleaseForward(m_clinfochanged);
149 g_Forwards.ReleaseForward(m_clauth);
150 g_Forwards.ReleaseForward(m_onActivate);
151 g_Forwards.ReleaseForward(m_onActivate2);
153 g_Forwards.ReleaseForward(PreAdminCheck);
154 g_Forwards.ReleaseForward(PostAdminCheck);
159 ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key,
165 if (strcmp(key, "PassInfoVar") == 0)
167 if (strcmp(value, "_password") != 0)
169 m_PassInfoVar.assign(value);
171 return ConfigResult_Accept;
172 } else if (strcmp(key, "AllowClLanguageVar") == 0) {
173 if (strcasecmp(value, "on") == 0)
176 } else if (strcasecmp(value, "off") == 0) {
179 UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
180 return ConfigResult_Reject;
182 return ConfigResult_Accept;
184 return ConfigResult_Ignore;
187 void PlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
191 /* Initialize all players */
192 m_maxClients = clientMax;
194 m_Players = new CPlayer[m_maxClients + 1];
195 m_AuthQueue = new unsigned int[m_maxClients + 1];
198 memset(m_AuthQueue, 0, sizeof(unsigned int) * (m_maxClients + 1));
200 g_NumPlayersToAuth = &m_AuthQueue[0];
202 m_onActivate->Execute(NULL);
203 m_onActivate2->Execute(NULL);
205 List<IClientListener *>::iterator iter;
206 for (iter = m_hooks.begin(); iter != m_hooks.end(); iter++)
208 if ((*iter)->GetClientListenerVersion() >= 5)
210 (*iter)->OnServerActivated(clientMax);
214 g_OnMapStarted = true;
216 SM_ExecuteAllConfigs();
219 bool PlayerManager::IsServerActivated()
224 bool PlayerManager::CheckSetAdmin(int index, CPlayer *pPlayer, AdminId id)
226 const char *password = g_Admins.GetAdminPassword(id);
227 if (password != NULL)
229 if (m_PassInfoVar.size() < 1)
234 /* Whoa... the user needs a password! */
235 const char *given = engine->GetClientConVarValue(index, m_PassInfoVar.c_str());
236 if (!given || strcmp(given, password) != 0)
242 pPlayer->SetAdminId(id, false);
247 bool PlayerManager::CheckSetAdminName(int index, CPlayer *pPlayer, AdminId id)
249 const char *password = g_Admins.GetAdminPassword(id);
250 if (password == NULL)
255 if (m_PassInfoVar.size() < 1)
260 /* Whoa... the user needs a password! */
261 const char *given = engine->GetClientConVarValue(index, m_PassInfoVar.c_str());
262 if (!given || strcmp(given, password) != 0)
267 pPlayer->SetAdminId(id, false);
272 void PlayerManager::RunAuthChecks()
276 unsigned int removed = 0;
277 for (unsigned int i=1; i<=m_AuthQueue[0]; i++)
279 pPlayer = GetPlayerByIndex(m_AuthQueue[i]);
280 authstr = engine->GetPlayerNetworkIDString(pPlayer->m_pEdict);
281 if (authstr && authstr[0] != '\0'
282 && (strcmp(authstr, "STEAM_ID_PENDING") != 0))
284 /* Set authorization */
285 pPlayer->Authorize(authstr);
287 /* Mark as removed from queue */
288 unsigned int client = m_AuthQueue[i];
292 /* Send to extensions */
293 List<IClientListener *>::iterator iter;
294 IClientListener *pListener;
295 for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
298 pListener->OnClientAuthorized(client, authstr);
299 if (!pPlayer->IsConnected())
305 /* Send to plugins if player is still connected */
306 if (pPlayer->IsConnected() && m_clauth->GetFunctionCount())
308 /* :TODO: handle the case of a player disconnecting in the middle */
309 m_clauth->PushCell(client);
310 m_clauth->PushString(authstr);
311 m_clauth->Execute(NULL);
314 if (pPlayer->IsConnected())
316 pPlayer->Authorize_Post();
321 /* Clean up the queue */
324 /* We don't have to compact the list if it's empty */
325 if (removed != m_AuthQueue[0])
327 unsigned int diff = 0;
328 for (unsigned int i=1; i<=m_AuthQueue[0]; i++)
330 /* If this member is removed... */
331 if (m_AuthQueue[i] == 0)
333 /* Increase the differential */
336 /* diff cannot increase faster than i+1 */
338 assert(i - diff >= 1);
339 /* move this index down */
340 m_AuthQueue[i - diff] = m_AuthQueue[i];
343 m_AuthQueue[0] -= removed;
350 bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen)
352 int client = engine->IndexOfEdict(pEntity);
354 List<IClientListener *>::iterator iter;
355 IClientListener *pListener = NULL;
356 for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
359 if (!pListener->InterceptClientConnect(client, reject, maxrejectlen))
367 m_Players[client].Initialize(pszName, pszAddress, pEntity);
368 m_clconnect->PushCell(client);
369 m_clconnect->PushStringEx(reject, maxrejectlen, SM_PARAM_STRING_UTF8, SM_PARAM_COPYBACK);
370 m_clconnect->PushCell(maxrejectlen);
371 m_clconnect->Execute(&res, NULL);
375 if (!m_Players[client].IsAuthorized())
377 m_AuthQueue[++m_AuthQueue[0]] = client;
380 RETURN_META_VALUE(MRES_SUPERCEDE, false);
383 m_UserIdLookUp[engine->GetPlayerUserId(pEntity)] = client;
388 bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen)
390 int client = engine->IndexOfEdict(pEntity);
391 bool orig_value = META_RESULT_ORIG_RET(bool);
392 CPlayer *pPlayer = GetPlayerByIndex(client);
396 List<IClientListener *>::iterator iter;
397 IClientListener *pListener = NULL;
398 for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
401 pListener->OnClientConnected(client);
402 if (!pPlayer->IsConnected())
412 void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername)
415 int client = engine->IndexOfEdict(pEntity);
417 CPlayer *pPlayer = GetPlayerByIndex(client);
418 /* If they're not connected, they're a bot */
419 if (!pPlayer->IsConnected())
421 /* Run manual connection routines */
423 const char *authid = engine->GetPlayerNetworkIDString(pEntity);
424 pPlayer->Authorize(authid);
425 if (!OnClientConnect(pEntity, playername, "127.0.0.1", error, sizeof(error)))
427 /* :TODO: kick the bot if it's rejected */
430 List<IClientListener *>::iterator iter;
431 IClientListener *pListener = NULL;
432 for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
435 pListener->OnClientConnected(client);
436 /* See if bot was kicked */
437 if (!pPlayer->IsConnected())
442 /* Now do authorization */
443 for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
446 pListener->OnClientAuthorized(client, authid);
448 /* Finally, tell plugins */
449 if (m_clauth->GetFunctionCount())
451 m_clauth->PushCell(client);
452 m_clauth->PushString(authid);
453 m_clauth->Execute(NULL);
455 pPlayer->Authorize_Post();
460 pPlayer->m_Info = playerinfo->GetPlayerInfo(pEntity);
463 /* Get the client's language */
467 if (!pPlayer->IsFakeClient() && (name=engine->GetClientConVarValue(client, "cl_language")))
470 pPlayer->m_LangId = (g_Translator.GetLanguageByName(name, &langid)) ? langid : g_Translator.GetServerLanguage();
472 pPlayer->m_LangId = g_Translator.GetServerLanguage();
476 m_Players[client].Connect();
479 List<IClientListener *>::iterator iter;
480 IClientListener *pListener = NULL;
481 for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
484 pListener->OnClientPutInServer(client);
487 m_clputinserver->PushCell(client);
488 m_clputinserver->Execute(&res, NULL);
491 void PlayerManager::OnSourceModLevelEnd()
493 /* Disconnect all bots still in game */
494 for (int i=1; i<=m_maxClients; i++)
496 if (m_Players[i].IsConnected())
498 OnClientDisconnect(m_Players[i].GetEdict());
504 void PlayerManager::OnClientDisconnect(edict_t *pEntity)
507 int client = engine->IndexOfEdict(pEntity);
509 if (m_Players[client].IsConnected())
511 m_cldisconnect->PushCell(client);
512 m_cldisconnect->Execute(&res, NULL);
514 /* We don't care, prevent a double call */
518 if (m_Players[client].WasCountedAsInGame())
523 List<IClientListener *>::iterator iter;
524 IClientListener *pListener = NULL;
525 for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
528 pListener->OnClientDisconnecting(client);
532 * Remove client from auth queue if necessary
534 if (!m_Players[client].IsAuthorized())
536 for (unsigned int i=1; i<=m_AuthQueue[0]; i++)
538 if (m_AuthQueue[i] == (unsigned)client)
540 /* Move everything ahead of us back by one */
541 for (unsigned int j=i+1; j<=m_AuthQueue[0]; j++)
543 m_AuthQueue[j-1] = m_AuthQueue[j];
545 /* Remove us and break */
552 m_Players[client].Disconnect();
553 m_UserIdLookUp[engine->GetPlayerUserId(pEntity)] = 0;
556 void PlayerManager::OnClientDisconnect_Post(edict_t *pEntity)
559 int client = engine->IndexOfEdict(pEntity);
561 m_cldisconnect_post->PushCell(client);
562 m_cldisconnect_post->Execute(&res, NULL);
564 List<IClientListener *>::iterator iter;
565 IClientListener *pListener = NULL;
566 for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++)
569 pListener->OnClientDisconnected(client);
573 #if defined ORANGEBOX_BUILD
574 void PlayerManager::OnClientCommand(edict_t *pEntity, const CCommand &args)
577 void PlayerManager::OnClientCommand(edict_t *pEntity)
581 int client = engine->IndexOfEdict(pEntity);
582 cell_t res = Pl_Continue;
584 CPlayer *pPlayer = GetPlayerByIndex(client);
585 if (!pPlayer || !pPlayer->IsConnected())
590 g_HL2.PushCommandStack(&args);
592 int argcount = args.ArgC() - 1;
593 const char *cmd = g_HL2.CurrentCommandName();
595 bool result = g_ValveMenuStyle.OnClientCommand(client, cmd, args);
600 result = g_RadioMenuStyle.OnClientCommand(client, cmd, args);
607 cell_t res2 = Pl_Continue;
608 m_clcommand->PushCell(client);
609 m_clcommand->PushCell(argcount);
610 m_clcommand->Execute(&res2, NULL);
619 g_HL2.PopCommandStack();
620 RETURN_META(MRES_SUPERCEDE);
623 res = g_ConCmds.DispatchClientCommand(client, cmd, argcount, (ResultType)res);
625 g_HL2.PopCommandStack();
627 if (res >= Pl_Handled)
629 RETURN_META(MRES_SUPERCEDE);
633 void PlayerManager::OnClientSettingsChanged(edict_t *pEntity)
636 int client = engine->IndexOfEdict(pEntity);
638 if (!m_Players[client].IsConnected())
643 m_clinfochanged->PushCell(engine->IndexOfEdict(pEntity));
644 m_clinfochanged->Execute(&res, NULL);
646 IPlayerInfo *info = m_Players[client].GetPlayerInfo();
647 const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name");
648 const char *old_name = m_Players[client].m_Name.c_str();
650 if (strcmp(old_name, new_name) != 0)
652 AdminId id = g_Admins.FindAdminByIdentity("name", new_name);
653 if (id != INVALID_ADMIN_ID && m_Players[client].GetAdminId() != id)
655 if (!CheckSetAdminName(client, &m_Players[client], id))
657 m_Players[client].Kick("Your name is reserved by SourceMod; set your password to use it.");
658 RETURN_META(MRES_IGNORED);
660 } else if ((id = g_Admins.FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) {
661 if (id == m_Players[client].GetAdminId())
663 /* This player is changing their name; force them to drop admin privileges! */
664 m_Players[client].SetAdminId(INVALID_ADMIN_ID, false);
667 m_Players[client].SetName(new_name);
670 if (m_PassInfoVar.size() > 0)
672 /* Try for a password change */
673 const char *old_pass = m_Players[client].m_LastPassword.c_str();
674 const char *new_pass = engine->GetClientConVarValue(client, m_PassInfoVar.c_str());
675 if (strcmp(old_pass, new_pass) != 0)
677 m_Players[client].m_LastPassword.assign(new_pass);
678 if (m_Players[client].IsInGame() && m_Players[client].IsAuthorized())
680 /* If there is already an admin id assigned, this will just bail out. */
681 m_Players[client].DoBasicAdminChecks();
687 int PlayerManager::GetMaxClients()
692 CPlayer *PlayerManager::GetPlayerByIndex(int client) const
694 if (client > m_maxClients || client < 1)
698 return &m_Players[client];
701 int PlayerManager::GetNumPlayers()
703 return m_PlayerCount;
706 int PlayerManager::GetClientOfUserId(int userid)
708 if (userid < 0 || userid > USHRT_MAX)
713 int client = m_UserIdLookUp[userid];
715 /* Verify the userid. The cache can get messed up with older
716 * Valve engines. :TODO: If this gets fixed, do an old engine
717 * check before invoking this backwards compat code.
721 CPlayer *player = GetPlayerByIndex(client);
722 if (player && player->IsConnected())
724 int realUserId = engine->GetPlayerUserId(player->GetEdict());
725 if (realUserId == userid)
732 /* If we can't verify the userid, we have to do a manual loop */
734 for (int i = 1; i <= m_maxClients; i++)
736 player = GetPlayerByIndex(i);
737 if (!player || !player->IsConnected())
741 if (engine->GetPlayerUserId(player->GetEdict()) == userid)
743 m_UserIdLookUp[userid] = i;
751 void PlayerManager::AddClientListener(IClientListener *listener)
753 m_hooks.push_back(listener);
756 void PlayerManager::RemoveClientListener(IClientListener *listener)
758 m_hooks.remove(listener);
761 IGamePlayer *PlayerManager::GetGamePlayer(edict_t *pEdict)
763 int index = engine->IndexOfEdict(pEdict);
764 return GetGamePlayer(index);
767 IGamePlayer *PlayerManager::GetGamePlayer(int client)
769 return GetPlayerByIndex(client);
772 void PlayerManager::ClearAdminId(AdminId id)
774 for (int i=1; i<=m_maxClients; i++)
776 if (m_Players[i].m_Admin == id)
778 m_Players[i].DumpAdmin(true);
783 void PlayerManager::ClearAllAdmins()
785 for (int i=1; i<=m_maxClients; i++)
787 m_Players[i].DumpAdmin(true);
791 const char *PlayerManager::GetPassInfoVar()
793 return m_PassInfoVar.c_str();
796 void PlayerManager::RecheckAnyAdmins()
798 for (int i=1; i<=m_maxClients; i++)
800 if (m_Players[i].IsInGame() && m_Players[i].IsAuthorized())
802 m_Players[i].DoBasicAdminChecks();
807 unsigned int PlayerManager::GetReplyTo()
809 return g_ChatTriggers.GetReplyTo();
812 unsigned int PlayerManager::SetReplyTo(unsigned int reply)
814 return g_ChatTriggers.SetReplyTo(reply);
823 m_IsConnected = false;
825 m_IsAuthorized = false;
827 m_Admin = INVALID_ADMIN_ID;
830 m_bAdminCheckSignalled = false;
831 m_bIsInKickQueue = false;
832 m_LastPassword.clear();
833 m_LangId = LANGUAGE_ENGLISH;
836 void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
838 m_IsConnected = true;
842 m_iIndex = engine->IndexOfEdict(pEntity);
843 m_LangId = g_Translator.GetServerLanguage();
846 strncopy(ip2, ip, sizeof(ip2));
847 if ((ptr = strchr(ip2, ':')) != NULL)
851 m_IpNoPort.assign(ip2);
854 void CPlayer::Connect()
863 const char *var = g_Players.GetPassInfoVar();
864 int client = engine->IndexOfEdict(m_pEdict);
867 const char *pass = engine->GetClientConVarValue(client, var);
868 m_LastPassword.assign(pass ? pass : "");
870 m_LastPassword.assign("");
875 DoPostConnectAuthorization();
879 void CPlayer::Authorize(const char *steamid)
886 m_IsAuthorized = true;
887 m_AuthID.assign(steamid);
890 void CPlayer::Disconnect()
893 m_IsConnected = false;
895 m_IsAuthorized = false;
901 m_bAdminCheckSignalled = false;
903 m_bIsInKickQueue = false;
906 void CPlayer::SetName(const char *name)
911 const char *CPlayer::GetName()
913 if (m_Info && m_pEdict->GetUnknown())
915 return m_Info->GetName();
918 return m_Name.c_str();
921 const char *CPlayer::GetIPAddress()
926 const char *CPlayer::GetAuthString()
928 return m_AuthID.c_str();
931 edict_t *CPlayer::GetEdict()
936 bool CPlayer::IsInGame()
938 return m_IsInGame && (m_pEdict->GetUnknown() != NULL);
941 bool CPlayer::WasCountedAsInGame()
946 bool CPlayer::IsConnected()
948 return m_IsConnected;
951 bool CPlayer::IsAuthorized()
953 return m_IsAuthorized;
956 IPlayerInfo *CPlayer::GetPlayerInfo()
958 if (m_pEdict->GetUnknown())
966 bool CPlayer::IsFakeClient()
968 return (strcmp(m_AuthID.c_str(), "BOT") == 0);
971 void CPlayer::SetAdminId(AdminId id, bool temporary)
981 m_TempAdmin = temporary;
984 AdminId CPlayer::GetAdminId()
989 void CPlayer::DumpAdmin(bool deleting)
991 if (m_Admin != INVALID_ADMIN_ID)
993 if (m_TempAdmin && !deleting)
995 g_Admins.InvalidateAdmin(m_Admin);
997 m_Admin = INVALID_ADMIN_ID;
1002 void CPlayer::Kick(const char *str)
1004 INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(m_iIndex));
1005 IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
1006 pClient->Disconnect("%s", str);
1009 void CPlayer::Authorize_Post()
1013 DoPostConnectAuthorization();
1017 void CPlayer::DoPostConnectAuthorization()
1020 PreAdminCheck->PushCell(m_iIndex);
1021 PreAdminCheck->Execute(&result);
1023 /* Defer, for better or worse */
1024 if ((ResultType)result >= Pl_Handled)
1035 /* Otherwise, go ahead and do admin checks */
1036 DoBasicAdminChecks();
1038 /* Send the notification out */
1039 NotifyPostAdminChecks();
1042 void CPlayer::NotifyPostAdminChecks()
1044 if (m_bAdminCheckSignalled)
1049 /* Block beforehand so they can't double-call */
1050 m_bAdminCheckSignalled = true;
1052 PostAdminCheck->PushCell(m_iIndex);
1053 PostAdminCheck->Execute(NULL);
1056 void CPlayer::DoBasicAdminChecks()
1058 if (GetAdminId() != INVALID_ADMIN_ID)
1063 /* First check the name */
1065 int client = engine->IndexOfEdict(m_pEdict);
1067 if ((id = g_Admins.FindAdminByIdentity("name", GetName())) != INVALID_ADMIN_ID)
1069 if (!g_Players.CheckSetAdminName(client, this, id))
1071 int userid = engine->GetPlayerUserId(m_pEdict);
1072 g_Timers.CreateTimer(&s_KickPlayerTimer, 0.1f, (void *)userid, 0);
1078 if ((id = g_Admins.FindAdminByIdentity("ip", m_IpNoPort.c_str())) != INVALID_ADMIN_ID)
1080 if (g_Players.CheckSetAdmin(client, this, id))
1086 /* Check IP address */
1087 if ((id = g_Admins.FindAdminByIdentity("steam", m_AuthID.c_str())) != INVALID_ADMIN_ID)
1089 if (g_Players.CheckSetAdmin(client, this, id))
1096 unsigned int CPlayer::GetLanguageId()
1101 int CPlayer::GetUserId()
1105 m_UserId = engine->GetPlayerUserId(GetEdict());
1111 bool CPlayer::IsInKickQueue()
1113 return m_bIsInKickQueue;
1116 void CPlayer::MarkAsBeingKicked()
1118 m_bIsInKickQueue = true;