diff --git a/MCServer/Plugins/APIDump/Hooks/OnExecuteCommand.lua b/MCServer/Plugins/APIDump/Hooks/OnExecuteCommand.lua index d920a83ba..79b7bb055 100644 --- a/MCServer/Plugins/APIDump/Hooks/OnExecuteCommand.lua +++ b/MCServer/Plugins/APIDump/Hooks/OnExecuteCommand.lua @@ -28,9 +28,11 @@ return { Name = "EntireCommand", Type = "string", Notes = "The entire command as a single string" }, }, Returns = [[ - If the plugin returns true, the command will be blocked and none of the remaining hook handlers will - be called. If the plugin returns false, MCServer calls all the remaining hook handlers and finally - the command will be executed. + If the plugin returns false, MCServer calls all the remaining hook handlers and finally the command + will be executed. If the plugin returns true, the none of the remaining hook handlers will be called. + In this case the plugin can return a second value, specifying whether what the command result should + be set to, one of the {{cPluginManager#CommandResult|CommandResult}} constants. If not + provided, the value defaults to crBlocked. ]], }, -- HOOK_EXECUTE_COMMAND } diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index c96ab083a..fb02569c9 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -958,6 +958,18 @@ void cLuaState::GetStackValue(int a_StackPos, bool & a_ReturnedVal) +void cLuaState::GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result) +{ + if (lua_isnumber(m_LuaState, a_StackPos)) + { + a_Result = static_cast(static_cast((tolua_tonumber(m_LuaState, a_StackPos, a_Result)))); + } +} + + + + + void cLuaState::GetStackValue(int a_StackPos, cRef & a_Ref) { a_Ref.RefStack(*this, a_StackPos); diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index 4377ed5d0..959a62bb8 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -32,6 +32,7 @@ extern "C" #include "../Vector3.h" #include "../Defines.h" +#include "PluginManager.h" @@ -57,7 +58,6 @@ class cPickup; class cPlayer; class cPlugin; class cPluginLua; -class cPluginManager; class cProjectileEntity; class cRoot; class cScoreboard; @@ -249,6 +249,7 @@ public: void GetStackValue(int a_StackPos, AString & a_Value); void GetStackValue(int a_StackPos, BLOCKTYPE & a_Value); void GetStackValue(int a_StackPos, bool & a_Value); + void GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result); void GetStackValue(int a_StackPos, cRef & a_Ref); void GetStackValue(int a_StackPos, double & a_Value); void GetStackValue(int a_StackPos, float & a_ReturnedVal); diff --git a/src/Bindings/Plugin.h b/src/Bindings/Plugin.h index 6b6a00ba6..d0c2bcefa 100644 --- a/src/Bindings/Plugin.h +++ b/src/Bindings/Plugin.h @@ -56,7 +56,7 @@ public: virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) = 0; virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) = 0; virtual bool OnEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) = 0; - virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand) = 0; + virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) = 0; virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0; virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0; virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) = 0; diff --git a/src/Bindings/PluginLua.cpp b/src/Bindings/PluginLua.cpp index 4cdc5e667..76d3557a4 100644 --- a/src/Bindings/PluginLua.cpp +++ b/src/Bindings/PluginLua.cpp @@ -534,7 +534,7 @@ bool cPluginLua::OnEntityAddEffect(cEntity & a_Entity, int a_EffectType, int a_E -bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand) +bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) { cCSLock Lock(m_CriticalSection); if (!m_LuaState.IsValid()) @@ -545,7 +545,7 @@ bool cPluginLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector & a_Sp cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_EXECUTE_COMMAND]; for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr) { - m_LuaState.Call((int)(**itr), a_Player, a_Split, a_EntireCommand, cLuaState::Return, res); + m_LuaState.Call((int)(**itr), a_Player, a_Split, a_EntireCommand, cLuaState::Return, res, a_Result); if (res) { return true; diff --git a/src/Bindings/PluginLua.h b/src/Bindings/PluginLua.h index 5c5fabec2..524c249b0 100644 --- a/src/Bindings/PluginLua.h +++ b/src/Bindings/PluginLua.h @@ -115,7 +115,7 @@ public: virtual bool OnCraftingNoRecipe (cPlayer & a_Player, cCraftingGrid & a_Grid, cCraftingRecipe & a_Recipe) override; virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) override; virtual bool OnEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier) override; - virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand) override; + virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, cPluginManager::CommandResult & a_Result) override; virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override; virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override; virtual bool OnHandshake (cClientHandle & a_Client, const AString & a_Username) override; diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp index 7384f43bd..15bea22bd 100644 --- a/src/Bindings/PluginManager.cpp +++ b/src/Bindings/PluginManager.cpp @@ -525,14 +525,14 @@ bool cPluginManager::CallHookEntityTeleport(cEntity & a_Entity, const Vector3d & -bool cPluginManager::CallHookExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand) +bool cPluginManager::CallHookExecuteCommand(cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result) { FIND_HOOK(HOOK_EXECUTE_COMMAND); VERIFY_HOOK; for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr) { - if ((*itr)->OnExecuteCommand(a_Player, a_Split, a_EntireCommand)) + if ((*itr)->OnExecuteCommand(a_Player, a_Split, a_EntireCommand, a_Result)) { return true; } @@ -1449,10 +1449,14 @@ cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer & a_Player, } // Ask plugins first if a command is okay to execute the command: - if (CallHookExecuteCommand(&a_Player, Split, a_Command)) + CommandResult Result = crBlocked; + if (CallHookExecuteCommand(&a_Player, Split, a_Command, Result)) { - LOGINFO("Player %s tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player.GetName().c_str(), Split[0].c_str()); - return crBlocked; + if (Result == crBlocked) + { + LOGINFO("Player %s tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player.GetName().c_str(), Split[0].c_str()); + } + return Result; } if ( @@ -1750,9 +1754,10 @@ bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cComma if (cmd == m_ConsoleCommands.end()) { // Command not found - // Still notify the plugins (so that plugins such as Aliases can intercept unknown commands): - CallHookExecuteCommand(nullptr, a_Split, a_Command); - return false; + // Still notify the plugins (so that plugins such as Aliases can intercept unknown commands). + CommandResult res = crBlocked; + CallHookExecuteCommand(nullptr, a_Split, a_Command, res); + return (res == crExecuted); } if (cmd->second.m_Plugin == nullptr) @@ -1762,10 +1767,10 @@ bool cPluginManager::ExecuteConsoleCommand(const AStringVector & a_Split, cComma } // Ask plugins first if a command is okay to execute the console command: - if (CallHookExecuteCommand(nullptr, a_Split, a_Command)) + CommandResult res = crBlocked; + if (CallHookExecuteCommand(nullptr, a_Split, a_Command, res)) { - a_Output.Out("Command \"%s\" was stopped by the HOOK_EXECUTE_COMMAND hook", a_Split[0].c_str()); - return false; + return (res == crExecuted); } return cmd->second.m_Plugin->HandleConsoleCommand(a_Split, a_Output, a_Command); diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h index 6fad98434..d8c886b62 100644 --- a/src/Bindings/PluginManager.h +++ b/src/Bindings/PluginManager.h @@ -200,7 +200,7 @@ public: bool CallHookDisconnect (cClientHandle & a_Client, const AString & a_Reason); bool CallHookEntityAddEffect (cEntity & a_Entity, int a_EffectType, int a_EffectDurationTicks, int a_EffectIntensity, double a_DistanceModifier); bool CallHookEntityTeleport (cEntity & a_Entity, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition); - bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand); // If a_Player == nullptr, it is a console cmd + bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split, const AString & a_EntireCommand, CommandResult & a_Result); // If a_Player == nullptr, it is a console cmd bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData); bool CallHookExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData); bool CallHookHandshake (cClientHandle & a_ClientHandle, const AString & a_Username);