diff --git a/MinecraftClient/ChatBots/AntiAFK.cs b/MinecraftClient/ChatBots/AntiAFK.cs index a54e8bcc..63eac4ba 100644 --- a/MinecraftClient/ChatBots/AntiAFK.cs +++ b/MinecraftClient/ChatBots/AntiAFK.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using MinecraftClient.Mapping; namespace MinecraftClient.ChatBots { @@ -12,28 +10,150 @@ namespace MinecraftClient.ChatBots public class AntiAFK : ChatBot { private int count; - private int timeping; + private string pingparam; + private int timeping = 600; + private int timepingMax = -1; + private bool useTerrainHandling = false; + private bool previousSneakState = false; + private int walkRange = 5; + private int walkRetries = 10; + private Random random = new Random(); /// /// This bot sends a /ping command every X seconds in order to stay non-afk. /// - /// Time amount between each ping (10 = 1s, 600 = 1 minute, etc.) + /// Time amount between each ping (10 = 1s, 600 = 1 minute, etc.) Can be a range of numbers eg. 10-600 - public AntiAFK(int pingparam) + public AntiAFK(string pingparam, bool useTerrainHandling, int walkRange, int walkRetries) { count = 0; - timeping = pingparam; + this.pingparam = pingparam; + this.useTerrainHandling = useTerrainHandling; + this.walkRange = walkRange; + this.walkRetries = walkRetries; + } + + public override void Initialize() + { + if (useTerrainHandling) + { + if (!GetTerrainEnabled()) + { + useTerrainHandling = false; + LogToConsole(Translations.TryGet("bot.antiafk.not_using_terrain_handling")); + } + } + + if (string.IsNullOrEmpty(pingparam)) + LogToConsole(Translations.TryGet("bot.antiafk.invalid_time")); + else + { + // Handle the random range + if (pingparam.Contains("-")) + { + string[] parts = pingparam.Split("-"); + + if (parts.Length == 2) + { + if (int.TryParse(parts[0].Trim(), out int firstTime)) + { + timeping = firstTime; + + if (int.TryParse(parts[1].Trim(), out int secondTime)) + timepingMax = secondTime; + else LogToConsole(Translations.TryGet("bot.antiafk.invalid_range_partial", timeping)); + } + else LogToConsole(Translations.TryGet("bot.antiafk.invalid_range")); + } + else LogToConsole(Translations.TryGet("bot.antiafk.invalid_range")); + } + else + { + if (int.TryParse(pingparam.Trim(), out int value)) + timeping = value; + else LogToConsole(Translations.TryGet("bot.antiafk.invalid_value")); + } + } + + if (timepingMax != -1 && timeping > timepingMax) + { + int temporary = timepingMax; + timepingMax = timeping; + timeping = temporary; + + LogToConsole(Translations.TryGet("bot.antiafk.swapping")); + } + if (timeping < 10) { timeping = 10; } //To avoid flooding } public override void Update() { count++; - if (count == timeping) + + if ((timepingMax != -1 && count == random.Next(timeping, timepingMax)) || count == timeping) { - SendText(Settings.AntiAFK_Command); + DoAntiAfkStuff(); count = 0; } + + } + + private void DoAntiAfkStuff() + { + if (useTerrainHandling) + { + Location currentLocation = GetCurrentLocation(); + Location goal; + + bool moved = false; + bool useAlternativeMethod = false; + int triesCounter = 0; + + while (!moved) + { + if (triesCounter++ >= walkRetries) + { + useAlternativeMethod = true; + break; + } + + goal = GetRandomLocationWithinRangeXZ(currentLocation, walkRange); + + // Prevent getting the same location + while ((currentLocation.X == goal.X) && (currentLocation.Y == goal.Y) && (currentLocation.Z == goal.Z)) + { + LogToConsole("Same location!, generating new one"); + goal = GetRandomLocationWithinRangeXZ(currentLocation, walkRange); + } + + if (!Movement.CheckChunkLoading(GetWorld(), currentLocation, goal)) + { + useAlternativeMethod = true; + break; + } + else moved = MoveToLocation(goal, allowUnsafe: false, allowDirectTeleport: false); + } + + if (!useAlternativeMethod) + { + // Solve the case when the bot was closed in 1x2, was sneaking, but then he was freed, this will make him not sneak anymore + previousSneakState = false; + Sneak(false); + + return; + } + } + + SendText(Settings.AntiAFK_Command); + Sneak(previousSneakState); + previousSneakState = !previousSneakState; + count = 0; + } + + private Location GetRandomLocationWithinRangeXZ(Location currentLocation, int range) + { + return new Location(currentLocation.X + random.Next(range * -1, range), currentLocation.Y, currentLocation.Z + random.Next(range * -1, range)); } } } diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index f5305d2e..89809d3f 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -271,7 +271,7 @@ namespace MinecraftClient /// private void RegisterBots(bool reload = false) { - if (Settings.AntiAFK_Enabled) { BotLoad(new AntiAFK(Settings.AntiAFK_Delay)); } + if (Settings.AntiAFK_Enabled) { BotLoad(new AntiAFK(Settings.AntiAFK_Delay, Settings.AntiAFK_UseTerrain_Handling, Settings.AntiAFK_Walk_Range, Settings.AntiAFK_Walk_Retries)); } 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)); } diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini index 55562ea7..6c45739a 100644 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ b/MinecraftClient/Resources/config/MinecraftClient.ini @@ -138,11 +138,15 @@ logtofile=false # Log alerts info a file logfile=alerts-log.txt # The name of a file where alers logs will be written [AntiAFK] -# Send a command on a regular basis to avoid automatic AFK disconnection +# Send a command on a regular basis or make the bot walk around randomly to avoid automatic AFK disconnection # /!\ Make sure your server rules do not forbid anti-AFK mechanisms! +# /!\ Make sure you keep the bot in an enclosure to prevent it wandering off if you're using terrain handling! enabled=false -delay=600 #10 = 1s -command=/ping +delay=600 # 10 = 1s (Can also be a random number between 2 numbers, example: 50-600) (Default: 600) +command=/ping # Command to send to the server +use_terrain_handling=false # Use terrain handling to enable the bot to move around +walk_range=5 # The range the bot can move around randomly +walk_retries=20 # How many timec can the bot fail trying to move before using the command method [AutoRelog] # Automatically relog when disconnected by server, for example because the server is restating diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 4b80c088..6962f7bb 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -427,6 +427,13 @@ cmd.useitem.use=Used an item [bot] # ChatBots. Naming style: bot.. +# Anti AFK +bot.antiafk.not_using_terrain_handling=The terrain handling is not enabled in the settings of the client, enable it if you want to use it with this bot. Using alternative (command) method. +bot.antiafk.invalid_range_partial=Invalid time range provided, using the first part of the range {0} as the time! +bot.antiafk.invalid_range=Invalid time range provided, using default time of 600! +bot.antiafk.invalid_value=Invalid time provided, using default time of 600! +bot.antiafk.swapping=The time range begins with a bigger value, swapped them around. + # AutoAttack bot.autoAttack.mode=Unknown attack mode: {0}. Using single mode as default. bot.autoAttack.priority=Unknown priority: {0}. Using distance priority as default. diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index 29011834..35389826 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -141,8 +141,11 @@ namespace MinecraftClient //AntiAFK Settings public static bool AntiAFK_Enabled = false; - public static int AntiAFK_Delay = 600; + public static string AntiAFK_Delay = "600"; public static string AntiAFK_Command = "/ping"; + public static bool AntiAFK_UseTerrain_Handling = false; + public static int AntiAFK_Walk_Range = 5; + public static int AntiAFK_Walk_Retries = 20; //Hangman Settings public static bool Hangman_Enabled = false; @@ -598,8 +601,11 @@ namespace MinecraftClient switch (ToLowerIfNeed(argName)) { case "enabled": AntiAFK_Enabled = str2bool(argValue); return true; - case "delay": AntiAFK_Delay = str2int(argValue); return true; + case "delay": AntiAFK_Delay = argValue; return true; case "command": AntiAFK_Command = argValue == "" ? "/ping" : argValue; return true; + case "use_terrain_handling": AntiAFK_UseTerrain_Handling = str2bool(argValue); return true; + case "walk_range": AntiAFK_Walk_Range = str2int(argValue); return true; + case "walk_retries": AntiAFK_Walk_Retries = str2int(argValue); return true; } break;