diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs index b767cdc2..61cf5be1 100644 --- a/MinecraftClient/ChatBots/AutoFishing.cs +++ b/MinecraftClient/ChatBots/AutoFishing.cs @@ -54,29 +54,6 @@ namespace MinecraftClient.ChatBots LogToConsoleTranslated("bot.autoFish.no_inv_handle"); } - /// - /// Update settings when reloaded - /// - public /* override */ void OnSettingsReload() - { - if (Settings.AutoFishing_Enabled) - { - if (!GetEntityHandlingEnabled()) - { - LogToConsoleTranslated("extra.entity_required"); - state = FishingState.WaitJoinGame; - } - inventoryEnabled = GetInventoryEnabled(); - if (!inventoryEnabled) - LogToConsoleTranslated("bot.autoFish.no_inv_handle"); - } - else - { - UnloadBot(); - return; - } - } - private void StartFishing() { isFishing = false; @@ -262,7 +239,7 @@ namespace MinecraftClient.ChatBots if (Settings.AutoFishing_LogFishingBobber) LogToConsole(string.Format("FishingBobber {0} Dx={1:0.000000} Dy={2:0.000000} Dz={3:0.000000}", Pos, Dx, Math.Abs(Dy), Dz)); - if (Math.Abs(Dx) < Math.Abs(Settings.AutoFishing_StationaryThreshold) && + if (Math.Abs(Dx) < Math.Abs(Settings.AutoFishing_StationaryThreshold) && Math.Abs(Dz) < Math.Abs(Settings.AutoFishing_StationaryThreshold) && Math.Abs(Dy) > Math.Abs(Settings.AutoFishing_HookThreshold)) { diff --git a/MinecraftClient/ChatBots/BotsCommand.cs b/MinecraftClient/ChatBots/BotsCommand.cs new file mode 100644 index 00000000..309e3e0c --- /dev/null +++ b/MinecraftClient/ChatBots/BotsCommand.cs @@ -0,0 +1,76 @@ +using MinecraftClient.Mapping; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MinecraftClient.Commands +{ + class BotsCommand : Command + { + public override string CmdName { get { return "bots"; } } + public override string CmdUsage { get { return "bots [list|unload ]"; } } + public override string CmdDesc { get { return "cmd.bots.desc"; } } + + public override string Run(McClient handler, string command, Dictionary localVars) + { + if (hasArg(command)) + { + string[] args = getArgs(command); + + if (args.Length == 1) + { + if (args[0].Equals("list", StringComparison.OrdinalIgnoreCase)) + { + StringBuilder sb = new(); + + int length = handler.GetLoadedChatBots().Count; + + if (length == 0) + return Translations.TryGet("cmd.bots.noloaded"); + + for (int i = 0; i < length; i++) + { + sb.Append(handler.GetLoadedChatBots()[i].GetType().Name); + + if (i != length - 1) + sb.Append(" ,"); + + } + + return Translations.Get("cmd.bots.list") + ": " + sb.ToString(); + } + + } + else if (args.Length == 2) + { + if (args[0].Equals("unload", StringComparison.OrdinalIgnoreCase)) + { + string botName = args[1].Trim(); + + if (botName.ToLower().Equals("all", StringComparison.OrdinalIgnoreCase)) + { + if (handler.GetLoadedChatBots().Count == 0) + return Translations.TryGet("cmd.bots.noloaded"); + + handler.UnloadAllBots(); + return Translations.TryGet("cmd.bots.unloaded_all"); + } + else + { + ChatBot? bot = handler.GetLoadedChatBots().Find(bot => bot.GetType().Name.ToLower() == botName.ToLower()); + + if (bot == null) + return Translations.TryGet("cmd.bots.notfound", botName); + + handler.BotUnLoad(bot); + return Translations.TryGet("cmd.bots.unloaded", botName); + } + } + } + } + + return GetCmdDescTranslated(); + } + } +} diff --git a/MinecraftClient/ChatBots/Reload.cs b/MinecraftClient/ChatBots/Reload.cs new file mode 100644 index 00000000..83a92a29 --- /dev/null +++ b/MinecraftClient/ChatBots/Reload.cs @@ -0,0 +1,27 @@ +using MinecraftClient.Mapping; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace MinecraftClient.Commands +{ + class Reload : Command + { + public override string CmdName { get { return "reload"; } } + public override string CmdUsage { get { return "reload"; } } + public override string CmdDesc { get { return "cmd.reload.desc"; } } + + public override string Run(McClient handler, string command, Dictionary localVars) + { + handler.Log.Info(Translations.TryGet("cmd.reload.started")); + handler.ReloadSettings(); + handler.Log.Warn(Translations.TryGet("cmd.reload.warning1")); + handler.Log.Warn(Translations.TryGet("cmd.reload.warning2")); + handler.Log.Warn(Translations.TryGet("cmd.reload.warning3")); + handler.Log.Warn(Translations.TryGet("cmd.reload.warning4")); + + return Translations.TryGet("cmd.reload.finished"); + } + } +} diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index b2bf629d..168a08f0 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -178,28 +178,7 @@ namespace MinecraftClient LoadCommands(); if (botsOnHold.Count == 0) - { - if (Settings.AntiAFK_Enabled) { BotLoad(new ChatBots.AntiAFK(Settings.AntiAFK_Delay)); } - if (Settings.Hangman_Enabled) { BotLoad(new ChatBots.HangmanGame(Settings.Hangman_English)); } - if (Settings.Alerts_Enabled) { BotLoad(new ChatBots.Alerts()); } - if (Settings.ChatLog_Enabled) { BotLoad(new ChatBots.ChatLog(Settings.ExpandVars(Settings.ChatLog_File), Settings.ChatLog_Filter, Settings.ChatLog_DateTime)); } - if (Settings.PlayerLog_Enabled) { BotLoad(new ChatBots.PlayerListLogger(Settings.PlayerLog_Delay, Settings.ExpandVars(Settings.PlayerLog_File))); } - if (Settings.AutoRelog_Enabled) { BotLoad(new ChatBots.AutoRelog(Settings.AutoRelog_Delay_Min, Settings.AutoRelog_Delay_Max, Settings.AutoRelog_Retries)); } - if (Settings.ScriptScheduler_Enabled) { BotLoad(new ChatBots.ScriptScheduler(Settings.ExpandVars(Settings.ScriptScheduler_TasksFile))); } - if (Settings.RemoteCtrl_Enabled) { BotLoad(new ChatBots.RemoteControl()); } - if (Settings.AutoRespond_Enabled) { BotLoad(new ChatBots.AutoRespond(Settings.AutoRespond_Matches, Settings.AutoRespond_MatchColors)); } - if (Settings.AutoAttack_Enabled) { BotLoad(new ChatBots.AutoAttack(Settings.AutoAttack_Mode, Settings.AutoAttack_Priority, Settings.AutoAttack_OverrideAttackSpeed, Settings.AutoAttack_CooldownSeconds, Settings.AutoAttack_Interaction)); } - if (Settings.AutoFishing_Enabled) { BotLoad(new ChatBots.AutoFishing()); } - if (Settings.AutoEat_Enabled) { BotLoad(new ChatBots.AutoEat(Settings.AutoEat_hungerThreshold)); } - if (Settings.Mailer_Enabled) { BotLoad(new ChatBots.Mailer()); } - if (Settings.AutoCraft_Enabled) { BotLoad(new AutoCraft(Settings.AutoCraft_configFile)); } - if (Settings.AutoDrop_Enabled) { BotLoad(new AutoDrop(Settings.AutoDrop_Mode, Settings.AutoDrop_items)); } - if (Settings.ReplayMod_Enabled) { BotLoad(new ReplayCapture(Settings.ReplayMod_BackupInterval)); } - if (Settings.FollowPlayer_Enabled) { BotLoad(new FollowPlayer(Settings.FollowPlayer_UpdateLimit, Settings.FollowPlayer_UpdateLimit)); } - - //Add your ChatBot here by uncommenting and adapting - //BotLoad(new ChatBots.YourBot()); - } + RegisterBots(); } try @@ -287,6 +266,32 @@ namespace MinecraftClient } } + /// + /// Register bots + /// + private void RegisterBots(bool reload = false) + { + if (Settings.AntiAFK_Enabled) { BotLoad(new AntiAFK(Settings.AntiAFK_Delay)); } + if (Settings.Hangman_Enabled) { BotLoad(new HangmanGame(Settings.Hangman_English)); } + if (Settings.Alerts_Enabled) { BotLoad(new Alerts()); } + if (Settings.ChatLog_Enabled) { BotLoad(new ChatLog(Settings.ExpandVars(Settings.ChatLog_File), Settings.ChatLog_Filter, Settings.ChatLog_DateTime)); } + if (Settings.PlayerLog_Enabled) { BotLoad(new PlayerListLogger(Settings.PlayerLog_Delay, Settings.ExpandVars(Settings.PlayerLog_File))); } + if (Settings.AutoRelog_Enabled) { BotLoad(new AutoRelog(Settings.AutoRelog_Delay_Min, Settings.AutoRelog_Delay_Max, Settings.AutoRelog_Retries)); } + if (Settings.ScriptScheduler_Enabled) { BotLoad(new ScriptScheduler(Settings.ExpandVars(Settings.ScriptScheduler_TasksFile))); } + if (Settings.RemoteCtrl_Enabled) { BotLoad(new RemoteControl()); } + if (Settings.AutoRespond_Enabled) { BotLoad(new AutoRespond(Settings.AutoRespond_Matches, Settings.AutoRespond_MatchColors)); } + if (Settings.AutoAttack_Enabled) { BotLoad(new AutoAttack(Settings.AutoAttack_Mode, Settings.AutoAttack_Priority, Settings.AutoAttack_OverrideAttackSpeed, Settings.AutoAttack_CooldownSeconds, Settings.AutoAttack_Interaction)); } + if (Settings.AutoFishing_Enabled) { BotLoad(new AutoFishing()); } + if (Settings.AutoEat_Enabled) { BotLoad(new AutoEat(Settings.AutoEat_hungerThreshold)); } + if (Settings.Mailer_Enabled) { BotLoad(new Mailer()); } + if (Settings.AutoCraft_Enabled) { BotLoad(new AutoCraft(Settings.AutoCraft_configFile)); } + if (Settings.AutoDrop_Enabled) { BotLoad(new AutoDrop(Settings.AutoDrop_Mode, Settings.AutoDrop_items)); } + if (Settings.ReplayMod_Enabled && reload) { BotLoad(new ReplayCapture(Settings.ReplayMod_BackupInterval)); } + + //Add your ChatBot here by uncommenting and adapting + //BotLoad(new ChatBots.YourBot()); + } + /// /// Retrieve messages from the queue and send. /// Note: requires external locking. @@ -714,6 +719,37 @@ namespace MinecraftClient } } + /// + /// Reload settings and bots + /// + /// Marks if bots need to be hard reloaded + public void ReloadSettings() + { + Program.ReloadSettings(); + ReloadBots(); + } + + /// + /// Reload loaded bots (Only builtin bots) + /// + public void ReloadBots() + { + UnloadAllBots(); + RegisterBots(true); + + if (client.Client.Connected) + bots.ForEach(bot => bot.AfterGameJoined()); + } + + /// + /// Unload All Bots + /// + public void UnloadAllBots() + { + foreach (ChatBot bot in GetLoadedChatBots()) + BotUnLoad(bot); + } + #endregion #region Thread-Invoke: Cross-thread method calls @@ -823,6 +859,7 @@ namespace MinecraftClient return; } + b.OnUnload(); bots.RemoveAll(item => object.ReferenceEquals(item, b)); // ToList is needed to avoid an InvalidOperationException from modfiying the list while it's being iterated upon. diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 1facb07b..14281da5 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -46,6 +46,7 @@ namespace MinecraftClient private static Tuple? offlinePrompt = null; private static bool useMcVersionOnce = false; + private static string? settingsIniPath = null; /// /// The main entry point of Minecraft Console Client @@ -104,10 +105,13 @@ namespace MinecraftClient ConsoleIO.DebugReadInput(); } + settingsIniPath = "MinecraftClient.ini"; + //Process ini configuration file if (args.Length >= 1 && System.IO.File.Exists(args[0]) && Settings.ToLowerIfNeed(Path.GetExtension(args[0])) == ".ini") { Settings.LoadFile(args[0]); + settingsIniPath = args[0]; //remove ini configuration file from arguments array List args_tmp = args.ToList(); @@ -529,6 +533,15 @@ namespace MinecraftClient } } + /// + /// Reloads settings + /// + public static void ReloadSettings() + { + if (settingsIniPath != null) + Settings.LoadFile(settingsIniPath); + } + /// /// Disconnect the current client from the server and restart it /// diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index e27e1ca9..119bf5a2 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -223,6 +223,14 @@ general.available_cmd=Available commands: {0} # Animation cmd.animation.desc=Swing your arm. +# Bots +cmd.bots.desc=List bots, unload a bot or all bots. +cmd.bots.list=Loaded bots +cmd.bots.notfound=Bot {0} is not loaded, check if you have made a typo! +cmd.bots.noloaded=No bots loaded! +cmd.bots.unloaded=Successfully unloaded bot: {0} +cmd.bots.unloaded_all=Successfully unloaded all bots! + # ChangeSlot cmd.changeSlot.desc=Change slot in hotbar cmd.changeSlot.nan=Could not change slot: Not a Number @@ -365,6 +373,15 @@ cmd.move.chunk_not_loaded=The chunk where the target location resides has not ye # Reco cmd.reco.desc=restart and reconnect to the server. +# Reload +cmd.reload.started=Reloading settings... +cmd.reload.warning1=This command will NOT affect certain settings which are used before connecting to a server! +cmd.reload.warning2=Some settings passed through the command line parameters might get overriden! +cmd.reload.warning3=You also might need to reconnect for some settings to take effect. +cmd.reload.warning4=Replay Chat Bot will not be hard reloaded due to technical limitations! +cmd.reload.finished=Reloaded Settings! +cmd.reload.desc=Reloads MCC settings. + # Respawn cmd.respawn.desc=Use this to respawn if you are dead. cmd.respawn.done=You have respawned. diff --git a/MinecraftClient/Scripting/ChatBot.cs b/MinecraftClient/Scripting/ChatBot.cs index 848370f1..80d0da3f 100644 --- a/MinecraftClient/Scripting/ChatBot.cs +++ b/MinecraftClient/Scripting/ChatBot.cs @@ -101,6 +101,11 @@ namespace MinecraftClient /// public virtual void Initialize() { } + /// + /// This method is called when the bot is being unloaded, you can use it to free up resources like DB connections + /// + public virtual void OnUnload() { } + /// /// Called after the server has been joined successfully and chat messages are able to be sent. /// This method is called again after reconnecting to the server, whereas Initialize() is called only once.