From 5292721f0b9688a60b50d7bdbe835c0c8ef425f3 Mon Sep 17 00:00:00 2001 From: domino_ Date: Mon, 25 Apr 2022 22:00:53 +0100 Subject: [PATCH] Add a OnPlayerRunCmdPre forward (#1760) Adds an OnPlayerRunCmdPre forward in order for plugins to be able to hook OnPlayerRunCmd with the guarantee that none of the parameters have been modified by other plugins. As such, OnPlayerRunCmdPre's parameters cannot be modified and are read-only. Plugins that wish to use OnPlayerRunCmdPre can maintain backwards compatibility with SourceMod 1.10 by falling back to OnPlayerRunCmd if the Pre variant was never fired. --- extensions/sdktools/hooks.cpp | 97 +++++++++++++++++++++--------- extensions/sdktools/hooks.h | 1 + plugins/include/sdktools_hooks.inc | 17 ++++++ 3 files changed, 85 insertions(+), 30 deletions(-) diff --git a/extensions/sdktools/hooks.cpp b/extensions/sdktools/hooks.cpp index ddfa2919..f253406c 100644 --- a/extensions/sdktools/hooks.cpp +++ b/extensions/sdktools/hooks.cpp @@ -69,6 +69,7 @@ CHookManager::CHookManager() : replay_enabled("replay_enabled", false) #endif { + m_usercmdsPreFwd = NULL; m_usercmdsFwd = NULL; m_usercmdsPostFwd = NULL; m_netFileSendFwd = NULL; @@ -97,6 +98,19 @@ void CHookManager::Initialize() plsys->AddPluginsListener(this); sharesys->AddCapabilityProvider(myself, this, FEATURECAP_PLAYERRUNCMD_11PARAMS); + + m_usercmdsPreFwd = forwards->CreateForward("OnPlayerRunCmdPre", ET_Ignore, 11, NULL, + Param_Cell, // int client + Param_Cell, // int buttons + Param_Cell, // int impulse + Param_Array, // float vel[3] + Param_Array, // float angles[3] + Param_Cell, // int weapon + Param_Cell, // int subtype + Param_Cell, // int cmdnum + Param_Cell, // int tickcount + Param_Cell, // int seed + Param_Array); // int mouse[2] m_usercmdsFwd = forwards->CreateForward("OnPlayerRunCmd", ET_Event, 11, NULL, Param_Cell, // client @@ -179,6 +193,7 @@ void CHookManager::Shutdown() } #endif + forwards->ReleaseForward(m_usercmdsPreFwd); forwards->ReleaseForward(m_usercmdsFwd); forwards->ReleaseForward(m_usercmdsPostFwd); forwards->ReleaseForward(m_netFileSendFwd); @@ -283,7 +298,10 @@ void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper) RETURN_META(MRES_IGNORED); } - if (m_usercmdsFwd->GetFunctionCount() == 0) + bool hasUsercmdsPreFwds = (m_usercmdsPreFwd->GetFunctionCount() > 0); + bool hasUsercmdsFwds = (m_usercmdsFwd->GetFunctionCount() > 0); + + if (!hasUsercmdsPreFwds && !hasUsercmdsFwds) { RETURN_META(MRES_IGNORED); } @@ -311,34 +329,53 @@ void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper) cell_t vel[3] = {sp_ftoc(ucmd->forwardmove), sp_ftoc(ucmd->sidemove), sp_ftoc(ucmd->upmove)}; cell_t angles[3] = {sp_ftoc(ucmd->viewangles.x), sp_ftoc(ucmd->viewangles.y), sp_ftoc(ucmd->viewangles.z)}; cell_t mouse[2] = {ucmd->mousedx, ucmd->mousedy}; - - m_usercmdsFwd->PushCell(client); - m_usercmdsFwd->PushCellByRef(&ucmd->buttons); - m_usercmdsFwd->PushCellByRef(&impulse); - m_usercmdsFwd->PushArray(vel, 3, SM_PARAM_COPYBACK); - m_usercmdsFwd->PushArray(angles, 3, SM_PARAM_COPYBACK); - m_usercmdsFwd->PushCellByRef(&ucmd->weaponselect); - m_usercmdsFwd->PushCellByRef(&ucmd->weaponsubtype); - m_usercmdsFwd->PushCellByRef(&ucmd->command_number); - m_usercmdsFwd->PushCellByRef(&ucmd->tick_count); - m_usercmdsFwd->PushCellByRef(&ucmd->random_seed); - m_usercmdsFwd->PushArray(mouse, 2, SM_PARAM_COPYBACK); - m_usercmdsFwd->Execute(&result); - - ucmd->impulse = impulse; - ucmd->forwardmove = sp_ctof(vel[0]); - ucmd->sidemove = sp_ctof(vel[1]); - ucmd->upmove = sp_ctof(vel[2]); - ucmd->viewangles.x = sp_ctof(angles[0]); - ucmd->viewangles.y = sp_ctof(angles[1]); - ucmd->viewangles.z = sp_ctof(angles[2]); - ucmd->mousedx = mouse[0]; - ucmd->mousedy = mouse[1]; - - - if (result == Pl_Handled) + + if (hasUsercmdsPreFwds) { - RETURN_META(MRES_SUPERCEDE); + m_usercmdsPreFwd->PushCell(client); + m_usercmdsPreFwd->PushCell(ucmd->buttons); + m_usercmdsPreFwd->PushCell(ucmd->impulse); + m_usercmdsPreFwd->PushArray(vel, 3); + m_usercmdsPreFwd->PushArray(angles, 3); + m_usercmdsPreFwd->PushCell(ucmd->weaponselect); + m_usercmdsPreFwd->PushCell(ucmd->weaponsubtype); + m_usercmdsPreFwd->PushCell(ucmd->command_number); + m_usercmdsPreFwd->PushCell(ucmd->tick_count); + m_usercmdsPreFwd->PushCell(ucmd->random_seed); + m_usercmdsPreFwd->PushArray(mouse, 2); + m_usercmdsPreFwd->Execute(); + } + + if (hasUsercmdsFwds) + { + m_usercmdsFwd->PushCell(client); + m_usercmdsFwd->PushCellByRef(&ucmd->buttons); + m_usercmdsFwd->PushCellByRef(&impulse); + m_usercmdsFwd->PushArray(vel, 3, SM_PARAM_COPYBACK); + m_usercmdsFwd->PushArray(angles, 3, SM_PARAM_COPYBACK); + m_usercmdsFwd->PushCellByRef(&ucmd->weaponselect); + m_usercmdsFwd->PushCellByRef(&ucmd->weaponsubtype); + m_usercmdsFwd->PushCellByRef(&ucmd->command_number); + m_usercmdsFwd->PushCellByRef(&ucmd->tick_count); + m_usercmdsFwd->PushCellByRef(&ucmd->random_seed); + m_usercmdsFwd->PushArray(mouse, 2, SM_PARAM_COPYBACK); + m_usercmdsFwd->Execute(&result); + + ucmd->impulse = impulse; + ucmd->forwardmove = sp_ctof(vel[0]); + ucmd->sidemove = sp_ctof(vel[1]); + ucmd->upmove = sp_ctof(vel[2]); + ucmd->viewangles.x = sp_ctof(angles[0]); + ucmd->viewangles.y = sp_ctof(angles[1]); + ucmd->viewangles.z = sp_ctof(angles[2]); + ucmd->mousedx = mouse[0]; + ucmd->mousedy = mouse[1]; + + + if (result == Pl_Handled) + { + RETURN_META(MRES_SUPERCEDE); + } } RETURN_META(MRES_IGNORED); @@ -576,7 +613,7 @@ void CHookManager::OnPluginLoaded(IPlugin *plugin) if (PRCH_enabled) { bool changed = false; - if (!PRCH_used && (m_usercmdsFwd->GetFunctionCount() > 0)) + if (!PRCH_used && ((m_usercmdsFwd->GetFunctionCount() > 0) || (m_usercmdsPreFwd->GetFunctionCount() > 0))) { PRCH_used = true; changed = true; @@ -634,7 +671,7 @@ void CHookManager::OnPluginLoaded(IPlugin *plugin) void CHookManager::OnPluginUnloaded(IPlugin *plugin) { - if (PRCH_used && !m_usercmdsFwd->GetFunctionCount()) + if (PRCH_used && (!m_usercmdsFwd->GetFunctionCount() && !m_usercmdsPreFwd->GetFunctionCount())) { for (size_t i = 0; i < m_runUserCmdHooks.size(); ++i) { diff --git a/extensions/sdktools/hooks.h b/extensions/sdktools/hooks.h index b46e3666..80334c8c 100644 --- a/extensions/sdktools/hooks.h +++ b/extensions/sdktools/hooks.h @@ -77,6 +77,7 @@ private: void NetChannelHook(int client); private: + IForward *m_usercmdsPreFwd; IForward *m_usercmdsFwd; IForward *m_usercmdsPostFwd; IForward *m_netFileSendFwd; diff --git a/plugins/include/sdktools_hooks.inc b/plugins/include/sdktools_hooks.inc index cd656eeb..1c20016d 100644 --- a/plugins/include/sdktools_hooks.inc +++ b/plugins/include/sdktools_hooks.inc @@ -37,6 +37,23 @@ #define FEATURECAP_PLAYERRUNCMD_11PARAMS "SDKTools PlayerRunCmd 11Params" +/** + * Called when a clients movement buttons are being processed (Read Only) + * + * @param client Index of the client. + * @param buttons Current commands (as bitflags - see entity_prop_stocks.inc). + * @param impulse Current impulse command. + * @param vel Players desired velocity. + * @param angles Players desired view angles. + * @param weapon Entity index of the new weapon if player switches weapon, 0 otherwise. + * @param subtype Weapon subtype when selected from a menu. + * @param cmdnum Command number. Increments from the first command sent. + * @param tickcount Tick count. A client's prediction based on the server's GetGameTickCount value. + * @param seed Random seed. Used to determine weapon recoil, spread, and other predicted elements. + * @param mouse Mouse direction (x, y). + */ +forward void OnPlayerRunCmdPre(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2]); + /** * Called when a clients movement buttons are being processed *