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;