diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index 3f1edac3..fdbf2a1c 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -196,8 +196,11 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const if (res) { - m_AuthQueue[++m_AuthQueue[0]] = client; - g_SourceMod.SetAuthChecking(true); + if (!m_Players[client].IsAuthorized()) + { + m_AuthQueue[++m_AuthQueue[0]] = client; + g_SourceMod.SetAuthChecking(true); + } } else { RETURN_META_VALUE(MRES_SUPERCEDE, false); } @@ -229,10 +232,13 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername int client = engine->IndexOfEdict(pEntity); CPlayer *pPlayer = GetPlayerByIndex(client); + /* If they're not connected, they're a bot */ if (!pPlayer->IsConnected()) { /* Run manual connection routines */ char error[255]; + const char *authid = engine->GetPlayerNetworkIDString(pEntity); + pPlayer->Authorize(authid); if (!OnClientConnect(pEntity, playername, "127.0.0.1", error, sizeof(error))) { /* :TODO: kick the bot if it's rejected */ @@ -244,7 +250,35 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername { pListener = (*iter); pListener->OnClientConnected(client); + /* See if bot was kicked */ + if (!pPlayer->IsConnected()) + { + return; + } } + /* Now do authorization */ + for (iter=m_hooks.begin(); iter!=m_hooks.end(); iter++) + { + pListener = (*iter); + pListener->OnClientAuthorized(client, authid); + /* See if bot was kicked */ + if (!pPlayer->IsConnected()) + { + return; + } + } + /* Finally, tell plugins */ + if (m_clauth->GetFunctionCount()) + { + m_clauth->PushCell(client); + m_clauth->PushString(authid); + m_clauth->Execute(NULL); + } + } + + if (playerinfo) + { + pPlayer->m_Info = playerinfo->GetPlayerInfo(pEntity); } List::iterator iter; @@ -253,6 +287,11 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername { pListener = (*iter); pListener->OnClientPutInServer(client); + /* See if player was kicked */ + if (!pPlayer->IsConnected()) + { + return; + } } m_Players[client].Connect(); @@ -432,6 +471,7 @@ CPlayer::CPlayer() m_pEdict = NULL; m_Admin = INVALID_ADMIN_ID; m_TempAdmin = false; + m_Info = NULL; } void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity) @@ -463,6 +503,7 @@ void CPlayer::Disconnect() m_Ip.clear(); m_AuthID.clear(); m_pEdict = NULL; + m_Info = NULL; } void CPlayer::SetName(const char *name) @@ -505,6 +546,11 @@ bool CPlayer::IsAuthorized() return m_IsAuthorized; } +IPlayerInfo *CPlayer::GetPlayerInfo() +{ + return m_Info; +} + bool CPlayer::IsFakeClient() { return (strcmp(m_AuthID.c_str(), "BOT") == 0); diff --git a/core/PlayerManager.h b/core/PlayerManager.h index fd8e3e45..a61fb970 100644 --- a/core/PlayerManager.h +++ b/core/PlayerManager.h @@ -42,6 +42,8 @@ public: bool IsFakeClient(); void SetAdminId(AdminId id, bool temporary); AdminId GetAdminId(); +public: + IPlayerInfo *GetPlayerInfo(); private: void Initialize(const char *name, const char *ip, edict_t *pEntity); void Connect(); @@ -59,6 +61,7 @@ private: AdminId m_Admin; bool m_TempAdmin; edict_t *m_pEdict; + IPlayerInfo *m_Info; }; class PlayerManager : diff --git a/core/smn_player.cpp b/core/smn_player.cpp index f7c7190b..de742b3f 100644 --- a/core/smn_player.cpp +++ b/core/smn_player.cpp @@ -369,26 +369,48 @@ static cell_t CanUserTarget(IPluginContext *pContext, const cell_t *params) return g_Admins.CanAdminTarget(pPlayer->GetAdminId(), pTarget->GetAdminId()) ? 1 : 0; } +static cell_t GetClientTeam(IPluginContext *pContext, const cell_t *params) +{ + int client = params[1]; + + CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); + if (!pPlayer) + { + return pContext->ThrowNativeError("Player %d is not a valid client", client); + } else if (!pPlayer->IsInGame()) { + return pContext->ThrowNativeError("Player %d is not in game", client); + } + + IPlayerInfo *pInfo = pPlayer->GetPlayerInfo(); + if (!pInfo) + { + return pContext->ThrowNativeError("IPlayerInfo not supported by game"); + } + + return pInfo->GetTeamIndex(); +} + REGISTER_NATIVES(playernatives) { - {"GetMaxClients", sm_GetMaxClients}, - {"GetClientCount", sm_GetClientCount}, - {"GetClientName", sm_GetClientName}, - {"GetClientIP", sm_GetClientIP}, - {"GetClientAuthString", sm_GetClientAuthStr}, - {"IsClientConnected", sm_IsPlayerConnected}, - {"IsPlayerInGame", sm_IsPlayerIngame}, - {"IsClientAuthorized", sm_IsPlayerAuthorized}, - {"IsFakeClient", sm_IsPlayerFakeClient}, - {"GetClientInfo", sm_GetClientInfo}, - {"SetUserAdmin", SetUserAdmin}, - {"GetUserAdmin", GetUserAdmin}, {"AddUserFlags", AddUserFlags}, - {"RemoveUserFlags", RemoveUserFlags}, - {"SetUserFlagBits", SetUserFlagBits}, - {"GetUserFlagBits", GetUserFlagBits}, - {"GetClientUserId", GetClientUserId}, {"CanUserTarget", CanUserTarget}, + {"GetClientAuthString", sm_GetClientAuthStr}, + {"GetClientCount", sm_GetClientCount}, + {"GetClientInfo", sm_GetClientInfo}, + {"GetClientIP", sm_GetClientIP}, + {"GetClientName", sm_GetClientName}, + {"GetClientTeam", GetClientTeam}, + {"GetClientUserId", GetClientUserId}, + {"GetMaxClients", sm_GetMaxClients}, + {"GetUserAdmin", GetUserAdmin}, + {"GetUserFlagBits", GetUserFlagBits}, + {"IsClientAuthorized", sm_IsPlayerAuthorized}, + {"IsClientConnected", sm_IsPlayerConnected}, + {"IsFakeClient", sm_IsPlayerFakeClient}, + {"IsPlayerInGame", sm_IsPlayerIngame}, + {"RemoveUserFlags", RemoveUserFlags}, + {"SetUserAdmin", SetUserAdmin}, + {"SetUserFlagBits", SetUserFlagBits}, {NULL, NULL} }; diff --git a/core/sourcemm_api.cpp b/core/sourcemm_api.cpp index 1374bba5..c483d489 100644 --- a/core/sourcemm_api.cpp +++ b/core/sourcemm_api.cpp @@ -27,6 +27,7 @@ IGameEventManager2 *gameevents = NULL; IUniformRandomStream *engrandom = NULL; CallClass *enginePatch = NULL; CallClass *gamedllPatch = NULL; +IPlayerInfoManager *playerinfo = NULL; PLUGIN_EXPOSE(SourceMod, g_SourceMod_Core); @@ -41,6 +42,9 @@ bool SourceMod_Core::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen GET_V_IFACE_CURRENT(engineFactory, gameevents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2); GET_V_IFACE_CURRENT(engineFactory, engrandom, IUniformRandomStream, VENGINE_SERVER_RANDOM_INTERFACE_VERSION); + /* :TODO: Make this optional and... make it find earlier versions [?] */ + GET_V_IFACE_CURRENT(serverFactory, playerinfo, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER); + if ((g_pMMPlugins = (ISmmPluginManager *)g_SMAPI->MetaFactory(MMIFACE_PLMANAGER, NULL, NULL)) == NULL) { if (error) diff --git a/core/sourcemm_api.h b/core/sourcemm_api.h index 138b02e1..bc385c92 100644 --- a/core/sourcemm_api.h +++ b/core/sourcemm_api.h @@ -18,6 +18,7 @@ #include #include #include +#include #include /** @@ -54,6 +55,7 @@ extern IGameEventManager2 *gameevents; extern SourceHook::CallClass *enginePatch; extern SourceHook::CallClass *gamedllPatch; extern IUniformRandomStream *engrandom; +extern IPlayerInfoManager *playerinfo; #define ENGINE_CALL(func) SH_CALL(enginePatch, &IVEngineServer::func) #define SERVER_CALL(func) SH_CALL(gamedllPatch, &IServerGameDLL::func) diff --git a/plugins/include/clients.inc b/plugins/include/clients.inc index 771d4a91..7668b0f6 100644 --- a/plugins/include/clients.inc +++ b/plugins/include/clients.inc @@ -181,6 +181,15 @@ native bool:IsFakeClient(client); */ native bool:GetClientInfo(client, const String:key[], String:value[], maxlen); +/** + * Retrieves a client's team index. + * + * @param client Player's index. + * @return Team index the client is on (mod specific). + * @error Invalid client index, client not in game, or no mod support. + */ +native GetClientTeam(client); + /** * Sets a client's AdminId. *