diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index 85b5937e..bcf73bde 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -121,7 +121,7 @@ void PlayerManager::OnSourceModAllInitialized() ParamType p1[] = {Param_Cell, Param_String, Param_Cell}; ParamType p2[] = {Param_Cell}; - m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_Event, 3, p1); + m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_LowEvent, 3, p1); m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2); m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2); m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2); @@ -288,7 +288,7 @@ void PlayerManager::RunAuthChecks() unsigned int removed = 0; for (unsigned int i=1; i<=m_AuthQueue[0]; i++) { - pPlayer = GetPlayerByIndex(m_AuthQueue[i]); + pPlayer = &m_Players[m_AuthQueue[i]]; authstr = engine->GetPlayerNetworkIDString(pPlayer->m_pEdict); if (authstr && authstr[0] != '\0' && (strcmp(authstr, "STEAM_ID_PENDING") != 0)) @@ -362,6 +362,7 @@ void PlayerManager::RunAuthChecks() bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) { int client = engine->IndexOfEdict(pEntity); + CPlayer *pPlayer = &m_Players[client]; List::iterator iter; IClientListener *pListener = NULL; @@ -376,26 +377,29 @@ bool PlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, const cell_t res = 1; - m_Players[client].Initialize(pszName, pszAddress, pEntity); + pPlayer->Initialize(pszName, pszAddress, pEntity); m_clconnect->PushCell(client); m_clconnect->PushStringEx(reject, maxrejectlen, SM_PARAM_STRING_UTF8, SM_PARAM_COPYBACK); m_clconnect->PushCell(maxrejectlen); - m_clconnect->Execute(&res, NULL); + m_clconnect->Execute(&res); if (res) { - if (!m_Players[client].IsAuthorized()) + if (!pPlayer->IsAuthorized()) { m_AuthQueue[++m_AuthQueue[0]] = client; } + + m_UserIdLookUp[engine->GetPlayerUserId(pEntity)] = client; } else { - RETURN_META_VALUE(MRES_SUPERCEDE, false); + if (!pPlayer->IsFakeClient()) + { + RETURN_META_VALUE(MRES_SUPERCEDE, false); + } } - m_UserIdLookUp[engine->GetPlayerUserId(pEntity)] = client; - return true; } @@ -403,7 +407,7 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName, { int client = engine->IndexOfEdict(pEntity); bool orig_value = META_RESULT_ORIG_RET(bool); - CPlayer *pPlayer = GetPlayerByIndex(client); + CPlayer *pPlayer = &m_Players[client]; if (orig_value) { @@ -418,13 +422,17 @@ bool PlayerManager::OnClientConnect_Post(edict_t *pEntity, const char *pszName, break; } } - } - if (!pPlayer->IsFakeClient() - && m_bIsListenServer - && strncmp(pszAddress, "127.0.0.1", 9) == 0) + if (!pPlayer->IsFakeClient() + && m_bIsListenServer + && strncmp(pszAddress, "127.0.0.1", 9) == 0) + { + m_ListenClient = client; + } + } + else { - m_ListenClient = client; + InvalidatePlayer(pPlayer); } return true; @@ -434,8 +442,8 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername { cell_t res; int client = engine->IndexOfEdict(pEntity); + CPlayer *pPlayer = &m_Players[client]; - CPlayer *pPlayer = GetPlayerByIndex(client); /* If they're not connected, they're a bot */ if (!pPlayer->IsConnected()) { @@ -494,7 +502,7 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername } } - m_Players[client].Connect(); + pPlayer->Connect(); m_PlayerCount++; List::iterator iter; @@ -508,9 +516,9 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername m_clputinserver->PushCell(client); m_clputinserver->Execute(&res, NULL); - if (m_Players[client].IsAuthorized()) + if (pPlayer->IsAuthorized()) { - m_Players[client].DoPostConnectAuthorization(); + pPlayer->DoPostConnectAuthorization(); } } @@ -531,8 +539,9 @@ void PlayerManager::OnClientDisconnect(edict_t *pEntity) { cell_t res; int client = engine->IndexOfEdict(pEntity); + CPlayer *pPlayer = &m_Players[client]; - if (m_Players[client].IsConnected()) + if (pPlayer->IsConnected()) { m_cldisconnect->PushCell(client); m_cldisconnect->Execute(&res, NULL); @@ -543,7 +552,7 @@ void PlayerManager::OnClientDisconnect(edict_t *pEntity) return; } - if (m_Players[client].WasCountedAsInGame()) + if (pPlayer->WasCountedAsInGame()) { m_PlayerCount--; } @@ -556,29 +565,7 @@ void PlayerManager::OnClientDisconnect(edict_t *pEntity) pListener->OnClientDisconnecting(client); } - /** - * Remove client from auth queue if necessary - */ - if (!m_Players[client].IsAuthorized()) - { - for (unsigned int i=1; i<=m_AuthQueue[0]; i++) - { - if (m_AuthQueue[i] == (unsigned)client) - { - /* Move everything ahead of us back by one */ - for (unsigned int j=i+1; j<=m_AuthQueue[0]; j++) - { - m_AuthQueue[j-1] = m_AuthQueue[j]; - } - /* Remove us and break */ - m_AuthQueue[0]--; - break; - } - } - } - - m_Players[client].Disconnect(); - m_UserIdLookUp[engine->GetPlayerUserId(pEntity)] = 0; + InvalidatePlayer(pPlayer); if (m_ListenClient == client) { @@ -613,9 +600,9 @@ void PlayerManager::OnClientCommand(edict_t *pEntity) #endif int client = engine->IndexOfEdict(pEntity); cell_t res = Pl_Continue; + CPlayer *pPlayer = &m_Players[client]; - CPlayer *pPlayer = GetPlayerByIndex(client); - if (!pPlayer || !pPlayer->IsConnected()) + if (!pPlayer->IsConnected()) { return; } @@ -667,8 +654,9 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) { cell_t res; int client = engine->IndexOfEdict(pEntity); + CPlayer *pPlayer = &m_Players[client]; - if (!m_Players[client].IsConnected()) + if (!pPlayer->IsConnected()) { return; } @@ -676,42 +664,42 @@ void PlayerManager::OnClientSettingsChanged(edict_t *pEntity) m_clinfochanged->PushCell(engine->IndexOfEdict(pEntity)); m_clinfochanged->Execute(&res, NULL); - IPlayerInfo *info = m_Players[client].GetPlayerInfo(); + IPlayerInfo *info = pPlayer->GetPlayerInfo(); const char *new_name = info ? info->GetName() : engine->GetClientConVarValue(client, "name"); - const char *old_name = m_Players[client].m_Name.c_str(); + const char *old_name = pPlayer->m_Name.c_str(); if (strcmp(old_name, new_name) != 0) { AdminId id = g_Admins.FindAdminByIdentity("name", new_name); - if (id != INVALID_ADMIN_ID && m_Players[client].GetAdminId() != id) + if (id != INVALID_ADMIN_ID && pPlayer->GetAdminId() != id) { - if (!CheckSetAdminName(client, &m_Players[client], id)) + if (!CheckSetAdminName(client, pPlayer, id)) { - m_Players[client].Kick("Your name is reserved by SourceMod; set your password to use it."); + pPlayer->Kick("Your name is reserved by SourceMod; set your password to use it."); RETURN_META(MRES_IGNORED); } } else if ((id = g_Admins.FindAdminByIdentity("name", old_name)) != INVALID_ADMIN_ID) { - if (id == m_Players[client].GetAdminId()) + if (id == pPlayer->GetAdminId()) { /* This player is changing their name; force them to drop admin privileges! */ - m_Players[client].SetAdminId(INVALID_ADMIN_ID, false); + pPlayer->SetAdminId(INVALID_ADMIN_ID, false); } } - m_Players[client].SetName(new_name); + pPlayer->SetName(new_name); } if (m_PassInfoVar.size() > 0) { /* Try for a password change */ - const char *old_pass = m_Players[client].m_LastPassword.c_str(); + const char *old_pass = pPlayer->m_LastPassword.c_str(); const char *new_pass = engine->GetClientConVarValue(client, m_PassInfoVar.c_str()); if (strcmp(old_pass, new_pass) != 0) { - m_Players[client].m_LastPassword.assign(new_pass); - if (m_Players[client].IsInGame() && m_Players[client].IsAuthorized()) + pPlayer->m_LastPassword.assign(new_pass); + if (pPlayer->IsInGame() && pPlayer->IsAuthorized()) { /* If there is already an admin id assigned, this will just bail out. */ - m_Players[client].DoBasicAdminChecks(); + pPlayer->DoBasicAdminChecks(); } } } @@ -862,6 +850,33 @@ void PlayerManager::UnregisterCommandTargetProcessor(ICommandTargetProcessor *pH target_processors.remove(pHandler); } +void PlayerManager::InvalidatePlayer(CPlayer *pPlayer) +{ + /** + * Remove client from auth queue if necessary + */ + if (!pPlayer->IsAuthorized()) + { + for (unsigned int i=1; i<=m_AuthQueue[0]; i++) + { + if (m_AuthQueue[i] == (unsigned)pPlayer->m_iIndex) + { + /* Move everything ahead of us back by one */ + for (unsigned int j=i+1; j<=m_AuthQueue[0]; j++) + { + m_AuthQueue[j-1] = m_AuthQueue[j]; + } + /* Remove us and break */ + m_AuthQueue[0]--; + break; + } + } + } + + m_UserIdLookUp[engine->GetPlayerUserId(pPlayer->m_pEdict)] = 0; + pPlayer->Disconnect(); +} + int PlayerManager::InternalFilterCommandTarget(CPlayer *pAdmin, CPlayer *pTarget, int flags) { if ((flags & COMMAND_FILTER_CONNECTED) == COMMAND_FILTER_CONNECTED diff --git a/core/PlayerManager.h b/core/PlayerManager.h index 9d235c49..da67f206 100644 --- a/core/PlayerManager.h +++ b/core/PlayerManager.h @@ -173,6 +173,7 @@ public: unsigned int SetReplyTo(unsigned int reply); private: void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax); + void InvalidatePlayer(CPlayer *pPlayer); private: List m_hooks; IForward *m_clconnect; diff --git a/core/systems/ForwardSys.cpp b/core/systems/ForwardSys.cpp index a3e31fe0..654f158b 100644 --- a/core/systems/ForwardSys.cpp +++ b/core/systems/ForwardSys.cpp @@ -186,11 +186,6 @@ void CForwardManager::ReleaseForward(IForward *forward) void CForwardManager::ForwardFree(CForward *fwd) { - if (fwd == NULL) - { - return; - } - m_FreeForwards.push(fwd); m_managed.remove(fwd); } @@ -288,15 +283,11 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter) return err; } - if (filter) - { - filter->OnExecuteBegin(); - } - FuncIter iter = m_functions.begin(); IPluginFunction *func; cell_t cur_result = 0; cell_t high_result = 0; + cell_t low_result = 0; int err; unsigned int failed=0, success=0; unsigned int num_params = m_curparam; @@ -316,12 +307,16 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter) { int err = SP_ERROR_PARAM; param = &temp_info[i]; + if (i >= m_numparams || m_types[i] == Param_Any) { type = param->pushedas; - } else { + } + else + { type = m_types[i]; } + if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF)) { /* If we're byref or we're vararg, we always push everything by ref. @@ -330,26 +325,30 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter) if (type == Param_String) { err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags); - } else if (type == Param_Float || type == Param_Cell) { + } + else if (type == Param_Float || type == Param_Cell) + { err = func->PushCellByRef(¶m->val); - } else { + } + else + { err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags); assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef); } - } else { + } + else + { /* If we're not byref or not vararg, our job is a bit easier. */ assert(type == Param_Cell || type == Param_Float); err = func->PushCell(param->val); } + if (err != SP_ERROR_NONE) { - if (!filter || !filter->OnErrorReport(this, func, err)) - { - g_DbgReporter.GenerateError(func->GetParentContext(), - func->GetFunctionID(), - err, - "Failed to push parameter while executing forward"); - } + g_DbgReporter.GenerateError(func->GetParentContext(), + func->GetFunctionID(), + err, + "Failed to push parameter while executing forward"); continue; } } @@ -357,12 +356,10 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter) /* Call the function and deal with the return value. */ if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE) { - if (filter) - { - filter->OnErrorReport(this, func, err); - } failed++; - } else { + } + else + { success++; switch (m_ExecType) { @@ -386,14 +383,11 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter) } break; } - case ET_Custom: + case ET_LowEvent: { - if (filter) + if (cur_result < low_result) { - if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop) - { - goto done; - } + low_result = cur_result; } break; } @@ -406,25 +400,39 @@ int CForward::Execute(cell_t *result, IForwardFilter *filter) } done: + if (success) { - if (m_ExecType == ET_Event || m_ExecType == ET_Hook) + switch (m_ExecType) { - cur_result = high_result; - } else if (m_ExecType == ET_Ignore) { - cur_result = 0; + case ET_Ignore: + { + cur_result = 0; + break; + } + case ET_Event: + case ET_Hook: + { + cur_result = high_result; + break; + } + case ET_LowEvent: + { + cur_result = low_result; + break; + } + default: + { + break; + } } + if (result) { *result = cur_result; } } - if (filter) - { - filter->OnExecuteEnd(&cur_result, success, failed); - } - return SP_ERROR_NONE; } diff --git a/core/systems/ForwardSys.h b/core/systems/ForwardSys.h index e3ff7b4d..1d6303a4 100644 --- a/core/systems/ForwardSys.h +++ b/core/systems/ForwardSys.h @@ -43,7 +43,7 @@ using namespace SourceHook; typedef List::iterator FuncIter; -//:TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX +/* :TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX */ #define FORWARDS_NAME_MAX 64 struct ByrefInfo diff --git a/public/IForwardSys.h b/public/IForwardSys.h index 61e4ff5b..cd9bbb19 100644 --- a/public/IForwardSys.h +++ b/public/IForwardSys.h @@ -79,66 +79,11 @@ namespace SourceMod ET_Single = 1, /**< Only return the last exec, ignore all others */ ET_Event = 2, /**< Acts as an event with the ResultTypes above, no mid-Stops allowed, returns highest */ ET_Hook = 3, /**< Acts as a hook with the ResultTypes above, mid-Stops allowed, returns highest */ - ET_Custom = 4, /**< Ignored or handled by an IForwardFilter */ + ET_LowEvent = 4, /**< Same as ET_Event except that it returns the lowest value */ }; class IForward; - - /** - * @brief Allows interception of how the Forward System executes functions. - */ - class IForwardFilter - { - public: - /** - * @brief Called when an error occurs executing a plugin. - * - * @param fwd IForward pointer. - * @param func IPluginFunction pointer to the failed function. - * @param err Error code. - * @return True to handle, false to pass to global error reporter. - */ - virtual bool OnErrorReport(IForward *fwd, - IPluginFunction *func, - int err) - { - return false; - } - - /** - * @brief Called after each function return during execution. - * NOTE: Only used for ET_Custom. - * - * @param fwd IForward pointer. - * @param func IPluginFunction pointer to the executed function. - * @param retval Pointer to current return value (can be modified). - * @return ResultType denoting the next action to take. - */ - virtual ResultType OnFunctionReturn(IForward *fwd, - IPluginFunction *func, - cell_t *retval) - { - return Pl_Continue; - } - - /** - * @brief Called when execution begins. - */ - virtual void OnExecuteBegin() - { - }; - - /** - * @brief Called when execution ends. - * - * @param final_ret Final return value (modifiable). - * @param success Number of successful execs. - * @param failed Number of failed execs. - */ - virtual void OnExecuteEnd(cell_t *final_ret, unsigned int success, unsigned int failed) - { - } - }; + class IForwardFilter; /** * @brief Unmanaged Forward, abstracts calling multiple functions as "forwards," or collections of functions. @@ -180,7 +125,7 @@ namespace SourceMod * @brief Executes the forward. * * @param result Optional pointer to store result in. - * @param filter Optional pointer to an IForwardFilter. + * @param filter Do not use. * @return Error code, if any. */ virtual int Execute(cell_t *result, IForwardFilter *filter=NULL) =0;