From 59cc4cea7c8a094afc46f9c80d7de9398d680739 Mon Sep 17 00:00:00 2001 From: Milutinke Date: Sun, 11 Sep 2022 17:06:23 +0200 Subject: [PATCH 1/3] Added a way to execute multiple commands with a single command --- MinecraftClient/Commands/ExecMulti.cs | 43 +++++++++++++++++++++++++++ MinecraftClient/Resources/lang/en.ini | 6 ++++ 2 files changed, 49 insertions(+) create mode 100644 MinecraftClient/Commands/ExecMulti.cs diff --git a/MinecraftClient/Commands/ExecMulti.cs b/MinecraftClient/Commands/ExecMulti.cs new file mode 100644 index 00000000..dc303c8a --- /dev/null +++ b/MinecraftClient/Commands/ExecMulti.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MinecraftClient.Commands +{ + class ExecMulti : Command + { + public override string CmdName { get { return "execmulti"; } } + public override string CmdUsage { get { return "execmulti -> -> -> ..."; } } + public override string CmdDesc { get { return "cmd.execmulti.desc"; } } + + public override string Run(McClient handler, string command, Dictionary localVars) + { + if (hasArg(command)) + { + string commandsString = getArg(command); + IEnumerable commands = commandsString.Split("->") + .ToList() + .ConvertAll(command => command.Trim()) + .FindAll(command => !string.IsNullOrEmpty(command) || command.StartsWith("execmulti", StringComparison.OrdinalIgnoreCase)); + + foreach (string cmd in commands) + { + string output = ""; + handler.PerformInternalCommand(cmd, ref output); + + string log = Translations.TryGet( + "cmd.execmulti.executed", cmd, + string.IsNullOrEmpty(output) ? Translations.TryGet("cmd.execmulti.no_result") : Translations.TryGet("cmd.execmulti.result", output)); + + if (output.Contains("unknown command", StringComparison.OrdinalIgnoreCase)) + handler.Log.Error(log); + else handler.Log.Info(log); + } + + return ""; + } + + return GetCmdDescTranslated(); + } + } +} diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 1d0cc4ad..403363ce 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -271,6 +271,12 @@ cmd.entityCmd.distance=Distance cmd.entityCmd.location=Location cmd.entityCmd.type=Type +# Exec Multi +cmd.execmulti.desc=Execute multiple commands one after another +cmd.execmulti.executed=Executed the command '{0}' with {1} +cmd.execmulti.result=result '{0}'! +cmd.execmulti.no_result=no result! + # Exit cmd.exit.desc=disconnect from the server. From 77da611411834200f1c57790102b1cf6c5e95272 Mon Sep 17 00:00:00 2001 From: Milutinke Date: Sun, 11 Sep 2022 22:35:26 +0200 Subject: [PATCH 2/3] Added a command that executes other command if a condition is met. --- MinecraftClient/Commands/ExecIf.cs | 98 ++++++++++++++++++++++++++ MinecraftClient/Commands/ExecMulti.cs | 9 ++- MinecraftClient/McClient.cs | 9 +-- MinecraftClient/MinecraftClient.csproj | 1 + MinecraftClient/Resources/lang/en.ini | 7 ++ MinecraftClient/Settings.cs | 9 +++ 6 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 MinecraftClient/Commands/ExecIf.cs diff --git a/MinecraftClient/Commands/ExecIf.cs b/MinecraftClient/Commands/ExecIf.cs new file mode 100644 index 00000000..8ea68e0f --- /dev/null +++ b/MinecraftClient/Commands/ExecIf.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using DynamicExpresso; + +namespace MinecraftClient.Commands +{ + class ExecIf : Command + { + public override string CmdName { get { return "execif"; } } + public override string CmdUsage { get { return "execif ---> "; } } + public override string CmdDesc { get { return "cmd.execif.desc"; } } + + public override string Run(McClient handler, string command, Dictionary localVars) + { + if (hasArg(command)) + { + string commandsString = getArg(command); + + if (!commandsString.Contains("--->")) + return GetCmdDescTranslated(); + + string[] parts = commandsString.Split("--->", StringSplitOptions.TrimEntries) + .ToList() + .ConvertAll(command => command.Trim()) + .ToArray(); + + if (parts.Length == 0) + return GetCmdDescTranslated(); + + string expressionText = parts[0]; + string resultCommand = parts[1]; + + try + { + var interpreter = new Interpreter(); + interpreter.SetVariable("MCC", handler); + + foreach (KeyValuePair entry in Settings.GetVariables()) + interpreter.SetVariable(entry.Key, entry.Value); + + Lambda parsedExpression = interpreter.Parse(expressionText); + var result = parsedExpression.Invoke(); + + if (result != null) + { + bool shouldExec = false; + + if (result is bool) + shouldExec = (bool)result; + else if (result is string) + shouldExec = !string.IsNullOrEmpty((string)result) && ((string)result).Trim().Contains("true", StringComparison.OrdinalIgnoreCase); + else if (result is int) + shouldExec = (int)result > 0; + else if (result is double) + shouldExec = (double)result > 0; + else if (result is float) + shouldExec = (float)result > 0; + else if (result is Int16) + shouldExec = (Int16)result > 0; + else if (result is Int32) + shouldExec = (Int32)result > 0; + else if (result is Int64) + shouldExec = (Int64)result > 0; + + handler.Log.Debug("[Execif] Result Type: " + result.GetType().Name); + + if (shouldExec) + { + string output = ""; + handler.PerformInternalCommand(resultCommand, ref output); + + if (string.IsNullOrEmpty(output)) + handler.Log.Debug(Translations.TryGet("cmd.execif.executed_no_output", expressionText, resultCommand)); + else handler.Log.Debug(Translations.TryGet("cmd.execif.executed", expressionText, resultCommand, output)); + + return ""; + } + + return ""; + } + } + catch (Exception e) + { + handler.Log.Error(Translations.TryGet("cmd.execif.error_occured", command)); + handler.Log.Error(Translations.TryGet("cmd.execif.error", e.Message)); + return ""; + } + + return GetCmdDescTranslated(); + } + + return GetCmdDescTranslated(); + } + + + } +} diff --git a/MinecraftClient/Commands/ExecMulti.cs b/MinecraftClient/Commands/ExecMulti.cs index dc303c8a..a7ad217f 100644 --- a/MinecraftClient/Commands/ExecMulti.cs +++ b/MinecraftClient/Commands/ExecMulti.cs @@ -15,10 +15,13 @@ namespace MinecraftClient.Commands if (hasArg(command)) { string commandsString = getArg(command); - IEnumerable commands = commandsString.Split("->") + + if (commandsString.Contains("execmulti", StringComparison.OrdinalIgnoreCase) || commandsString.Contains("execif", StringComparison.OrdinalIgnoreCase)) + return Translations.TryGet("cmd.execmulti.prevent"); + + IEnumerable commands = commandsString.Split("->", StringSplitOptions.TrimEntries) .ToList() - .ConvertAll(command => command.Trim()) - .FindAll(command => !string.IsNullOrEmpty(command) || command.StartsWith("execmulti", StringComparison.OrdinalIgnoreCase)); + .FindAll(command => !string.IsNullOrEmpty(command)); foreach (string cmd in commands) { diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index 3ef7fbf1..049f68b2 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -316,7 +316,7 @@ namespace MinecraftClient { if (e is not ThreadAbortException) Log.Warn("Update: Got error from " + bot.ToString() + ": " + e.ToString()); - else + else throw; //ThreadAbortException should not be caught } } @@ -570,7 +570,7 @@ namespace MinecraftClient { string response_msg = ""; string command = Settings.internalCmdChar == ' ' ? text : text.Substring(1); - if (!PerformInternalCommand(Settings.ExpandVars(command), ref response_msg) && Settings.internalCmdChar == '/') + if (!PerformInternalCommand(Settings.ExpandVars(command), ref response_msg, Settings.GetVariables()) && Settings.internalCmdChar == '/') { SendText(text); } @@ -658,6 +658,7 @@ namespace MinecraftClient else if (cmds.ContainsKey(command_name)) { response_msg = cmds[command_name].Run(this, command, localVars); + foreach (ChatBot bot in bots.ToArray()) { try @@ -1658,8 +1659,8 @@ namespace MinecraftClient upper2backpack = true; lowerStartSlot = 1; } - else if (item != null && item.Count == 1 && (item.Type == ItemType.NetheriteIngot || - item.Type == ItemType.Emerald || item.Type == ItemType.Diamond || item.Type == ItemType.GoldIngot || + else if (item != null && item.Count == 1 && (item.Type == ItemType.NetheriteIngot || + item.Type == ItemType.Emerald || item.Type == ItemType.Diamond || item.Type == ItemType.GoldIngot || item.Type == ItemType.IronIngot) && !inventory.Items.ContainsKey(0)) { lower2upper = true; diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index 1d99f102..794364ff 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -29,6 +29,7 @@ + diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 403363ce..3867dde5 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -271,6 +271,13 @@ cmd.entityCmd.distance=Distance cmd.entityCmd.location=Location cmd.entityCmd.type=Type +# Exec If +cmd.execif.desc=Allows you to execute a command if a condition is met. (You can use variables from MinecraftClient.ini and /set command, as well as CSharp expressions) +cmd.execif.executed=The condition '{0}' was met, executed command '{1}' with result '{2}'. +cmd.execif.executed_no_output=The condition '{0}' was met, executed command '{1}', no result was returned. +cmd.execif.error_occured=An error has occured while executing the command: {0} +cmd.execif.error=Error: {0} + # Exec Multi cmd.execmulti.desc=Execute multiple commands one after another cmd.execmulti.executed=Executed the command '{0}' with {1} diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index db493953..349072ae 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -1005,6 +1005,15 @@ namespace MinecraftClient return null; } + /// + /// Get a dictionary containing variables (names and value) + /// + /// A IDictionary containing a name and a vlaue key pairs of variables + public static Dictionary GetVariables() + { + return AppVars; + } + /// /// Replace %variables% with their value from global AppVars /// From a0f0c634ff8050e2a894d03d05bafedb5090e34b Mon Sep 17 00:00:00 2001 From: Milutinke Date: Tue, 13 Sep 2022 13:49:59 +0200 Subject: [PATCH 3/3] Made the /execif return boolean as expression evaluation result --- MinecraftClient/Commands/ExecIf.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MinecraftClient/Commands/ExecIf.cs b/MinecraftClient/Commands/ExecIf.cs index 8ea68e0f..df2c9e37 100644 --- a/MinecraftClient/Commands/ExecIf.cs +++ b/MinecraftClient/Commands/ExecIf.cs @@ -39,14 +39,13 @@ namespace MinecraftClient.Commands foreach (KeyValuePair entry in Settings.GetVariables()) interpreter.SetVariable(entry.Key, entry.Value); - Lambda parsedExpression = interpreter.Parse(expressionText); - var result = parsedExpression.Invoke(); + var result = interpreter.Eval(expressionText); if (result != null) { - bool shouldExec = false; + bool shouldExec = result; - if (result is bool) + /*if (result is bool) shouldExec = (bool)result; else if (result is string) shouldExec = !string.IsNullOrEmpty((string)result) && ((string)result).Trim().Contains("true", StringComparison.OrdinalIgnoreCase); @@ -62,6 +61,7 @@ namespace MinecraftClient.Commands shouldExec = (Int32)result > 0; else if (result is Int64) shouldExec = (Int64)result > 0; + */ handler.Log.Debug("[Execif] Result Type: " + result.GetType().Name);