From b596e103040109947c571c8775655c8fde1f5265 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 5 Feb 2007 20:32:34 +0000 Subject: [PATCH] heavily cleaned up the player API exposed player API as an interface added client event listeners to API --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40441 --- core/CPlayer.cpp | 57 -------- core/CPlayer.h | 93 ------------- core/CPlayerManager.cpp | 201 +++++++++++++++++++++++++++-- core/CPlayerManager.h | 79 ++++++++---- core/msvc8/sourcemod_mm.vcproj | 12 +- core/smn_player.cpp | 36 +++--- public/IPlayerHelpers.h | 229 +++++++++++++++++++++++++++++++++ 7 files changed, 499 insertions(+), 208 deletions(-) delete mode 100644 core/CPlayer.cpp delete mode 100644 core/CPlayer.h create mode 100644 public/IPlayerHelpers.h diff --git a/core/CPlayer.cpp b/core/CPlayer.cpp deleted file mode 100644 index 1dc5de8c..00000000 --- a/core/CPlayer.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/** - * =============================================================== - * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. - * =============================================================== - * - * This file is not open source and may not be copied without explicit - * written permission of AlliedModders LLC. This file may not be redistributed - * in whole or significant part. - * For information, see LICENSE.txt or http://www.sourcemod.net/license.php - * - * Version: $Id$ - */ - -#include "CPlayer.h" - -CPlayer::CPlayer() -{ - m_IsConnected = false; - m_IsInGame = false; - m_IsAuthorized = false; - m_PlayerEdict = NULL; -} - -void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity) -{ - m_IsConnected = true; - m_Name.assign(name); - m_Ip.assign(ip); - m_PlayerEdict = pEntity; -} - -void CPlayer::Connect() -{ - m_IsInGame = true; -} - -void CPlayer::Authorize(const char *steamid) -{ - m_IsAuthorized = true; - m_AuthID.assign(steamid); -} - -void CPlayer::Disconnect() -{ - m_IsConnected = false; - m_IsInGame = false; - m_IsAuthorized = false; - m_Name.clear(); - m_Ip.clear(); - m_AuthID.clear(); - m_PlayerEdict = NULL; -} - -void CPlayer::SetName(const char *name) -{ - m_Name.assign(name); -} diff --git a/core/CPlayer.h b/core/CPlayer.h deleted file mode 100644 index 4324ad30..00000000 --- a/core/CPlayer.h +++ /dev/null @@ -1,93 +0,0 @@ -/** - * =============================================================== - * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. - * =============================================================== - * - * This file is not open source and may not be copied without explicit - * written permission of AlliedModders LLC. This file may not be redistributed - * in whole or significant part. - * For information, see LICENSE.txt or http://www.sourcemod.net/license.php - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_SOURCEMOD_CPLAYER_H_ -#define _INCLUDE_SOURCEMOD_CPLAYER_H_ - -#include -#include - -using namespace SourceHook; - -class CPlayer -{ - friend class CPlayerManager; -public: - CPlayer(); -public: - const char *PlayerName() const; - const char *PlayerIP() const; - const char *PlayerAuthString() const; - edict_t *GetPlayerEdict() const; - bool IsPlayerInGame() const; - bool IsPlayerConnected() const; - bool IsPlayerAuthorized() const; - bool IsPlayerFakeClient() const; - //:TODO: is user alive function -private: - void Initialize(const char *name, const char *ip, edict_t *pEntity); - void Connect(); - void Authorize(const char *steamid); - void Disconnect(); - void SetName(const char *name); -private: - bool m_IsConnected; - bool m_IsInGame; - bool m_IsAuthorized; - String m_Name; - String m_Ip; - String m_AuthID; - edict_t *m_PlayerEdict; -}; - -inline const char *CPlayer::PlayerName() const -{ - return m_Name.c_str(); -} - -inline const char *CPlayer::PlayerIP() const -{ - return m_Ip.c_str(); -} - -inline const char *CPlayer::PlayerAuthString() const -{ - return m_AuthID.c_str(); -} - -inline edict_t *CPlayer::GetPlayerEdict() const -{ - return m_PlayerEdict; -} - -inline bool CPlayer::IsPlayerInGame() const -{ - return m_IsInGame; -} - -inline bool CPlayer::IsPlayerConnected() const -{ - return m_IsConnected; -} - -inline bool CPlayer::IsPlayerAuthorized() const -{ - return m_IsAuthorized; -} - -inline bool CPlayer::IsPlayerFakeClient() const -{ - return (strcmp(m_AuthID.c_str(), "BOT") == 0); -} - -#endif // _INCLUDE_SOURCEMOD_CPLAYER_H_ diff --git a/core/CPlayerManager.cpp b/core/CPlayerManager.cpp index c242ff5a..65bc9083 100644 --- a/core/CPlayerManager.cpp +++ b/core/CPlayerManager.cpp @@ -13,6 +13,7 @@ #include "CPlayerManager.h" #include "ForwardSys.h" +#include "ShareSys.h" CPlayerManager g_PlayerManager; @@ -26,6 +27,7 @@ SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, in void CPlayerManager::OnSourceModAllInitialized() { SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &CPlayerManager::OnClientConnect, false); + SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, serverClients, this, &CPlayerManager::OnClientConnect_Post, true); SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, serverClients, this, &CPlayerManager::OnClientPutInServer, true); SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &CPlayerManager::OnClientDisconnect, false); SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, serverClients, this, &CPlayerManager::OnClientDisconnect_Post, true); @@ -33,6 +35,8 @@ void CPlayerManager::OnSourceModAllInitialized() SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, serverClients, this, &CPlayerManager::OnClientSettingsChanged, true); SH_ADD_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &CPlayerManager::OnServerActivate, true); + g_ShareSys.AddInterface(NULL, this); + /* Register OnClientConnect */ ParamType p1[] = {Param_Cell, Param_String, Param_Cell}; m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_Event, 3, p1); @@ -92,9 +96,21 @@ void CPlayerManager::OnServerActivate(edict_t *pEdictList, int edictCount, int c bool CPlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) { - cell_t res = 1; int client = engine->IndexOfEdict(pEntity); + List::iterator iter; + IClientListener *pListener = NULL; + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + pListener = (*iter); + if (!pListener->InterceptClientConnect(client, reject, maxrejectlen)) + { + return false; + } + } + + cell_t res = 1; + m_Players[client].Initialize(pszName, pszAddress, pEntity); m_clconnect->PushCell(client); m_clconnect->PushStringEx(reject, maxrejectlen, SM_PARAM_STRING_UTF8, SM_PARAM_COPYBACK); @@ -104,11 +120,37 @@ bool CPlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, cons return (res) ? true : false; } +bool CPlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) +{ + int client = engine->IndexOfEdict(pEntity); + bool orig_value = META_RESULT_ORIG_RET(bool); + if (orig_value) + { + List::iterator iter; + IClientListener *pListener = NULL; + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + pListener = (*iter); + pListener->OnClientConnected(client); + } + } + + return true; +} + void CPlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername) { cell_t res; int client = engine->IndexOfEdict(pEntity); + List::iterator iter; + IClientListener *pListener = NULL; + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + pListener = (*iter); + pListener->OnClientPutInServer(client); + } + m_Players[client].Connect(); m_PlayerCount++; m_clputinserver->PushCell(client); @@ -125,24 +167,43 @@ void CPlayerManager::OnClientDisconnect(edict_t *pEntity) cell_t res; int client = engine->IndexOfEdict(pEntity); - if (m_Players[client].IsPlayerConnected()) + if (m_Players[client].IsConnected()) { m_cldisconnect->PushCell(client); m_cldisconnect->Execute(&res, NULL); } - if (m_Players[client].IsPlayerInGame()) + + if (m_Players[client].IsInGame()) { m_PlayerCount--; } + + List::iterator iter; + IClientListener *pListener = NULL; + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + pListener = (*iter); + pListener->OnClientDisconnecting(client); + } + m_Players[client].Disconnect(); } void CPlayerManager::OnClientDisconnect_Post(edict_t *pEntity) { cell_t res; + int client = engine->IndexOfEdict(pEntity); - m_cldisconnect_post->PushCell(engine->IndexOfEdict(pEntity)); + m_cldisconnect_post->PushCell(client); m_cldisconnect_post->Execute(&res, NULL); + + List::iterator iter; + IClientListener *pListener = NULL; + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + pListener = (*iter); + pListener->OnClientDisconnected(client); + } } void CPlayerManager::OnClientCommand(edict_t *pEntity) @@ -162,8 +223,132 @@ void CPlayerManager::OnClientSettingsChanged(edict_t *pEntity) m_clinfochanged->PushCell(engine->IndexOfEdict(pEntity)); m_clinfochanged->Execute(&res, NULL); - if (m_Players[client].IsPlayerInGame()) - { - m_Players[client].SetName(engine->GetClientConVarValue(client, "name")); - } + m_Players[client].SetName(engine->GetClientConVarValue(client, "name")); +} + +int CPlayerManager::GetMaxClients() +{ + return m_maxClients; +} + +CPlayer *CPlayerManager::GetPlayerByIndex(int client) const +{ + if (client > m_maxClients || client < 0) + { + return NULL; + } + return &m_Players[client]; +} + +int CPlayerManager::GetNumPlayers() +{ + return m_PlayerCount; +} + +void CPlayerManager::AddClientListener(IClientListener *listener) +{ + m_hooks.push_back(listener); +} + +void CPlayerManager::RemoveClientListener(IClientListener *listener) +{ + m_hooks.remove(listener); +} + +IGamePlayer *CPlayerManager::GetGamePlayer(edict_t *pEdict) +{ + int index = engine->IndexOfEdict(pEdict); + return GetGamePlayer(index); +} + +IGamePlayer *CPlayerManager::GetGamePlayer(int client) +{ + return GetPlayerByIndex(client); +} + +/******************* + *** PLAYER CODE *** + *******************/ + +CPlayer::CPlayer() +{ + m_IsConnected = false; + m_IsInGame = false; + m_IsAuthorized = false; + m_PlayerEdict = NULL; +} + +void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity) +{ + m_IsConnected = true; + m_Name.assign(name); + m_Ip.assign(ip); + m_PlayerEdict = pEntity; +} + +void CPlayer::Connect() +{ + m_IsInGame = true; +} + +void CPlayer::Authorize(const char *steamid) +{ + m_IsAuthorized = true; + m_AuthID.assign(steamid); +} + +void CPlayer::Disconnect() +{ + m_IsConnected = false; + m_IsInGame = false; + m_IsAuthorized = false; + m_Name.clear(); + m_Ip.clear(); + m_AuthID.clear(); + m_PlayerEdict = NULL; +} + +void CPlayer::SetName(const char *name) +{ + m_Name.assign(name); +} + +const char *CPlayer::GetName() const +{ + return m_Name.c_str(); +} + +const char *CPlayer::GetIPAddress() const +{ + return m_Ip.c_str(); +} + +const char *CPlayer::GetAuthString() const +{ + return m_AuthID.c_str(); +} + +edict_t *CPlayer::GetEdict() const +{ + return m_PlayerEdict; +} + +bool CPlayer::IsInGame() const +{ + return m_IsInGame; +} + +bool CPlayer::IsConnected() const +{ + return m_IsConnected; +} + +bool CPlayer::IsAuthorized() const +{ + return m_IsAuthorized; +} + +bool CPlayer::IsFakeClient() const +{ + return (strcmp(m_AuthID.c_str(), "BOT") == 0); } diff --git a/core/CPlayerManager.h b/core/CPlayerManager.h index c2dc1dd7..2a2201d1 100644 --- a/core/CPlayerManager.h +++ b/core/CPlayerManager.h @@ -18,11 +18,45 @@ #include #include "sourcemm_api.h" #include -#include "CPlayer.h" +#include +#include +#include -class CPlayer; +using namespace SourceHook; -class CPlayerManager : public SMGlobalClass +class CPlayer : public IGamePlayer +{ + friend class CPlayerManager; +public: + CPlayer(); +public: + const char *GetName() const; + const char *GetIPAddress() const; + const char *GetAuthString() const; + edict_t *GetEdict() const; + bool IsInGame() const; + bool IsConnected() const; + bool IsAuthorized() const; + bool IsFakeClient() const; +private: + void Initialize(const char *name, const char *ip, edict_t *pEntity); + void Connect(); + void Authorize(const char *steamid); + void Disconnect(); + void SetName(const char *name); +private: + bool m_IsConnected; + bool m_IsInGame; + bool m_IsAuthorized; + String m_Name; + String m_Ip; + String m_AuthID; + edict_t *m_PlayerEdict; +}; + +class CPlayerManager : + public SMGlobalClass, + public IPlayerManager { public: CPlayerManager() : m_FirstPass(true) {} @@ -30,20 +64,36 @@ public: //SMGlobalClass void OnSourceModAllInitialized(); void OnSourceModShutdown(); public: - int GetMaxClients() const; CPlayer *GetPlayerByIndex(int client) const; - int GetPlayerCount() const; public: bool OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); + bool OnClientConnect_Post(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); void OnClientPutInServer(edict_t *pEntity, char const *playername); void OnClientDisconnect(edict_t *pEntity); void OnClientDisconnect_Post(edict_t *pEntity); void OnClientAuthorized(); //:TODO: any args needed? void OnClientCommand(edict_t *pEntity); void OnClientSettingsChanged(edict_t *pEntity); +public: //IPlayerManager + void AddClientListener(IClientListener *listener); + void RemoveClientListener(IClientListener *listener); + IGamePlayer *GetGamePlayer(int client); + IGamePlayer *GetGamePlayer(edict_t *pEdict); + int GetMaxClients(); + int GetNumPlayers(); +public: + inline int MaxClients() + { + return m_maxClients; + } + inline int NumPlayers() + { + return m_PlayerCount; + } private: void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax); private: + List m_hooks; IForward *m_clconnect; IForward *m_cldisconnect; IForward *m_cldisconnect_post; @@ -58,23 +108,4 @@ private: extern CPlayerManager g_PlayerManager; -inline int CPlayerManager::GetMaxClients() const -{ - return m_maxClients; -} - -inline CPlayer *CPlayerManager::GetPlayerByIndex(int client) const -{ - if (client > m_maxClients || client < 0) - { - return NULL; - } - return &m_Players[client]; -} - -inline int CPlayerManager::GetPlayerCount() const -{ - return m_PlayerCount; -} - #endif //_INCLUDE_SOURCEMOD_CPLAYERMANAGER_H_ diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj index 1cfa15ee..0332881a 100644 --- a/core/msvc8/sourcemod_mm.vcproj +++ b/core/msvc8/sourcemod_mm.vcproj @@ -191,10 +191,6 @@ RelativePath="..\CLogger.cpp" > - - @@ -285,10 +281,6 @@ RelativePath="..\CLogger.h" > - - @@ -365,6 +357,10 @@ RelativePath="..\..\public\ILibrarySys.h" > + + diff --git a/core/smn_player.cpp b/core/smn_player.cpp index aaa44932..ac1c8873 100644 --- a/core/smn_player.cpp +++ b/core/smn_player.cpp @@ -18,26 +18,26 @@ static cell_t sm_GetClientCount(IPluginContext *pCtx, const cell_t *params) { if (params[1]) { - return g_PlayerManager.GetPlayerCount(); + return g_PlayerManager.NumPlayers(); } - int maxplayers = g_PlayerManager.GetMaxClients(); + int maxplayers = g_PlayerManager.MaxClients(); int count = 0; for (int i=1; i<=maxplayers; ++i) { CPlayer *pPlayer = g_PlayerManager.GetPlayerByIndex(i); - if ((pPlayer->IsPlayerConnected()) && !(pPlayer->IsPlayerInGame())) + if ((pPlayer->IsConnected()) && !(pPlayer->IsInGame())) { count++; } } - return (g_PlayerManager.GetPlayerCount() + count); + return (g_PlayerManager.NumPlayers() + count); } static cell_t sm_GetMaxClients(IPluginContext *pCtx, const cell_t *params) { - return g_PlayerManager.GetMaxClients(); + return g_PlayerManager.MaxClients(); } static cell_t sm_GetClientName(IPluginContext *pCtx, const cell_t *params) @@ -49,12 +49,12 @@ static cell_t sm_GetClientName(IPluginContext *pCtx, const cell_t *params) } CPlayer *pPlayer = g_PlayerManager.GetPlayerByIndex(index); - if (!pPlayer->IsPlayerConnected()) + if (!pPlayer->IsConnected()) { return pCtx->ThrowNativeError("Client %d is not connected.", index); } - pCtx->StringToLocalUTF8(params[2], static_cast(params[3]), pPlayer->PlayerName(), NULL); + pCtx->StringToLocalUTF8(params[2], static_cast(params[3]), pPlayer->GetName(), NULL); return 1; } @@ -67,13 +67,13 @@ static cell_t sm_GetClientIP(IPluginContext *pCtx, const cell_t *params) } CPlayer *pPlayer = g_PlayerManager.GetPlayerByIndex(index); - if (!pPlayer->IsPlayerConnected()) + if (!pPlayer->IsConnected()) { return pCtx->ThrowNativeError("Client %d is not connected.", index); } char buf[64], *ptr; - strcpy(buf, pPlayer->PlayerIP()); + strcpy(buf, pPlayer->GetIPAddress()); if (params[4] && (ptr = strchr(buf, ':'))) { @@ -93,12 +93,12 @@ static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params) } CPlayer *pPlayer = g_PlayerManager.GetPlayerByIndex(index); - if (!pPlayer->IsPlayerConnected()) + if (!pPlayer->IsConnected()) { return pCtx->ThrowNativeError("Client %d is not connected.", index); } - pCtx->StringToLocal(params[2], static_cast(params[3]), pPlayer->PlayerAuthString()); + pCtx->StringToLocal(params[2], static_cast(params[3]), pPlayer->GetAuthString()); return 1; } @@ -110,7 +110,7 @@ static cell_t sm_IsPlayerConnected(IPluginContext *pCtx, const cell_t *params) return pCtx->ThrowNativeError("Invalid client index %d.", index); } - return (g_PlayerManager.GetPlayerByIndex(index)->IsPlayerConnected()) ? 1 : 0; + return (g_PlayerManager.GetPlayerByIndex(index)->IsConnected()) ? 1 : 0; } static cell_t sm_IsPlayerIngame(IPluginContext *pCtx, const cell_t *params) @@ -121,7 +121,7 @@ static cell_t sm_IsPlayerIngame(IPluginContext *pCtx, const cell_t *params) return pCtx->ThrowNativeError("Invalid client index %d.", index); } - return (g_PlayerManager.GetPlayerByIndex(index)->IsPlayerInGame()) ? 1 : 0; + return (g_PlayerManager.GetPlayerByIndex(index)->IsInGame()) ? 1 : 0; } static cell_t sm_IsPlayerAuthorized(IPluginContext *pCtx, const cell_t *params) @@ -132,7 +132,7 @@ static cell_t sm_IsPlayerAuthorized(IPluginContext *pCtx, const cell_t *params) return pCtx->ThrowNativeError("Invalid client index %d.", index); } - return (g_PlayerManager.GetPlayerByIndex(index)->IsPlayerAuthorized()) ? 1 : 0; + return (g_PlayerManager.GetPlayerByIndex(index)->IsAuthorized()) ? 1 : 0; } static cell_t sm_IsPlayerFakeClient(IPluginContext *pCtx, const cell_t *params) @@ -144,12 +144,12 @@ static cell_t sm_IsPlayerFakeClient(IPluginContext *pCtx, const cell_t *params) } CPlayer *pPlayer = g_PlayerManager.GetPlayerByIndex(index); - if (!pPlayer->IsPlayerConnected()) + if (!pPlayer->IsConnected()) { return pCtx->ThrowNativeError("Client %d is not connected.", index); } - return (pPlayer->IsPlayerFakeClient()) ? 1 : 0; + return (pPlayer->IsFakeClient()) ? 1 : 0; } static cell_t sm_PrintToServer(IPluginContext *pCtx, const cell_t *params) @@ -178,7 +178,7 @@ static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params) } CPlayer *pPlayer = g_PlayerManager.GetPlayerByIndex(index); - if (!pPlayer->IsPlayerInGame()) + if (!pPlayer->IsInGame()) { return pCtx->ThrowNativeError("Client %d is not in game.", index); } @@ -193,7 +193,7 @@ static cell_t sm_PrintToConsole(IPluginContext *pCtx, const cell_t *params) buffer[res++] = '\n'; buffer[res] = '\0'; - engine->ClientPrintf(pPlayer->GetPlayerEdict(), buffer); + engine->ClientPrintf(pPlayer->GetEdict(), buffer); return 1; } diff --git a/public/IPlayerHelpers.h b/public/IPlayerHelpers.h new file mode 100644 index 00000000..5a4b9ded --- /dev/null +++ b/public/IPlayerHelpers.h @@ -0,0 +1,229 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod, Copyright (C) 2004-2007 AlliedModders LLC. + * All rights reserved. + * =============================================================== + * + * This file is part of the SourceMod/SourcePawn SDK. This file may only be + * used or modified under the Terms and Conditions of its License Agreement, + * which is found in public/licenses/LICENSE.txt. As of this notice, derivative + * works must be licensed under the GNU General Public License (version 2 or + * greater). A copy of the GPL is included under public/licenses/GPL.txt. + * + * To view the latest information, see: http://www.sourcemod.net/license.php + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_INTERFACE_IPLAYERHELPERS_H_ +#define _INCLUDE_SOURCEMOD_INTERFACE_IPLAYERHELPERS_H_ + +#include + +#define SMINTERFACE_PLAYERMANAGER_NAME "IPlayerManager" +#define SMINTERFACE_PLAYERMANAGER_VERSION 1 + +struct edict_t; + +/** + * @file IPlayerHelpers.h + * @brief Defines basic helper functions for Half-Life 2 clients + */ +namespace SourceMod +{ + /** + * @brief Abstracts some Half-Life 2 and SourceMod properties about clients. + */ + class IGamePlayer + { + public: + /** + * @brief Returns the player's name. + * + * @return String containing the player's name, + * or NULL if unavailable. + */ + virtual const char *GetName() const =0; + + /** + * @brief Returns the player's IP address. + * + * @return String containing the player's IP address, + * or NULL if unavailable. + */ + virtual const char *GetIPAddress() const =0; + + /** + * @brief Returns the player's authentication string. + * + * @return String containing the player's auth string. + * May be NULL if unavailable. + */ + virtual const char *GetAuthString() const =0; + + /** + * @brief Returns the player's edict_t structure. + * + * @return edict_t pointer, or NULL if unavailable. + */ + virtual edict_t *GetEdict() const =0; + + /** + * @brief Returns whether the player is in game (putinserver). + * + * @return True if in game, false otherwise. + */ + virtual bool IsInGame() const =0; + + /** + * @brief Returns whether the player is connected. + * + * Note: If this returns true, all above functions except for + * GetAuthString() should return non-NULL results. + * + * @return True if connected, false otherwise. + */ + virtual bool IsConnected() const =0; + + /** + * @brief Returns whether the player is a fake client. + * + * @return True if a fake client, false otherwise. + */ + virtual bool IsFakeClient() const =0; + }; + + /** + * @brief Provides callbacks for important client events. + */ + class IClientListener + { + public: + virtual unsigned int GetInterfaceVersion() + { + return SMINTERFACE_PLAYERMANAGER_VERSION; + } + public: + /** + * @brief Called when a client requests connection. + * + * @param client Index of the client. + * @param error Error buffer for a disconnect reason. + * @param maxlength Maximum length of error buffer. + * @return True to allow client, false to reject. + */ + virtual bool InterceptClientConnect(int client, char *error, size_t maxlength) + { + return true; + } + + /** + * @brief Called when a client has connected. + * + * @param client Index of the client. + */ + virtual void OnClientConnected(int client) + { + } + + /** + * @brief Called when a client is put in server. + * + * @param client Index of the client. + */ + virtual void OnClientPutInServer(int client) + { + } + + /** + * @brief Called when a client is disconnecting (not fully disconnected yet). + * + * @param client Index of the client. + */ + virtual void OnClientDisconnecting(int client) + { + } + + /** + * @brief Called when a client has fully disconnected. + * + * @param client Index of the client. + */ + virtual void OnClientDisconnected(int client) + { + } + + /** + * @brief Called when a client has recieved authorization. + * + * @param client Index of the client. + * @param authstring Authorization string. + */ + virtual void OnClientAuthorized(int client, const char *authstring) + { + } + }; + + class IPlayerManager : public SMInterface + { + public: + const char *GetInterfaceName() + { + return SMINTERFACE_PLAYERMANAGER_NAME; + } + unsigned int GetInterfaceVersion() + { + return SMINTERFACE_PLAYERMANAGER_VERSION; + } + public: + /** + * @brief Adds a client listener. + * + * @param listener Pointer to an IClientListener. + */ + virtual void AddClientListener(IClientListener *listener) =0; + + /** + * @brief Removes a client listener. + * + * @param listener Pointer to an IClientListener. + */ + virtual void RemoveClientListener(IClientListener *listener) =0; + + /** + * @brief Retrieves an IGamePlayer object by its client index. + * + * Note: This will return a valid object for any player, connected or not. + * Note: Client indexes start at 1, not 0. + * + * @param client Index of the client. + * @return An IGamePlayer pointer, or NULL if out of range. + */ + virtual IGamePlayer *GetGamePlayer(int client) =0; + + /** + * @brief Retrieves an IGamePlayer object by its edict_t pointer. + * + * @param pEdict Index of the client + * @return An IGamePlayer pointer, or NULL if out of range. + */ + virtual IGamePlayer *GetGamePlayer(edict_t *pEdict) =0; + + /** + * @brief Returns the maximum number of clients. + * + * @return Maximum number of clients. + */ + virtual int GetMaxClients() =0; + + /** + * @brief Returns the number of players currently connected. + * + * @return Current number of connected clients. + */ + virtual int GetNumPlayers() =0; + }; +} + +#endif //_INCLUDE_SOURCEMOD_INTERFACE_IPLAYERHELPERS_H_