From 9903ad7535e86c4b76150acb35a3ff60652a3521 Mon Sep 17 00:00:00 2001 From: Milutinke Date: Wed, 28 Sep 2022 18:38:57 +0200 Subject: [PATCH 1/9] Updated Anti AFK Chat Bot to use terrain handling, now it can walk around randomly in the given range. Also added random interval support, and the bot now can sneak when using the command (alternative method). --- MinecraftClient/ChatBots/AntiAFK.cs | 138 ++++++++++++++++-- MinecraftClient/McClient.cs | 2 +- .../Resources/config/MinecraftClient.ini | 10 +- MinecraftClient/Resources/lang/en.ini | 7 + MinecraftClient/Settings.cs | 10 +- 5 files changed, 152 insertions(+), 15 deletions(-) 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; From 5d1eabd74ca6d894f819db4d975f28998c5b9a91 Mon Sep 17 00:00:00 2001 From: Milutinke Date: Wed, 28 Sep 2022 18:46:17 +0200 Subject: [PATCH 2/9] Added safeguard for the walk range. --- MinecraftClient/ChatBots/AntiAFK.cs | 8 ++++++++ MinecraftClient/Resources/lang/en.ini | 1 + 2 files changed, 9 insertions(+) diff --git a/MinecraftClient/ChatBots/AntiAFK.cs b/MinecraftClient/ChatBots/AntiAFK.cs index 63eac4ba..d078aae5 100644 --- a/MinecraftClient/ChatBots/AntiAFK.cs +++ b/MinecraftClient/ChatBots/AntiAFK.cs @@ -42,6 +42,14 @@ namespace MinecraftClient.ChatBots useTerrainHandling = false; LogToConsole(Translations.TryGet("bot.antiafk.not_using_terrain_handling")); } + else + { + if (walkRange <= 0) + { + walkRange = 5; + LogToConsole(Translations.TryGet("bot.antiafk.invalid_walk_range")); + } + } } if (string.IsNullOrEmpty(pingparam)) diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 6962f7bb..9e06fb0e 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -433,6 +433,7 @@ bot.antiafk.invalid_range_partial=Invalid time range provided, using the first p 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. +bot.antiafk.invalid_walk_range=Invalid walk range provided, must be a positive integer greater than 0, using default value of 5! # AutoAttack bot.autoAttack.mode=Unknown attack mode: {0}. Using single mode as default. From 6c07415e24b9faa11c8525e727f5393b3c3aac5c Mon Sep 17 00:00:00 2001 From: Milutinke Date: Wed, 28 Sep 2022 18:50:48 +0200 Subject: [PATCH 3/9] Improved some comments in the default ini file. --- MinecraftClient/Resources/config/MinecraftClient.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini index 6c45739a..73e109a3 100644 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ b/MinecraftClient/Resources/config/MinecraftClient.ini @@ -140,12 +140,12 @@ logfile=alerts-log.txt # The name of a file where alers logs will be [AntiAFK] # 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! +# /!\ Make sure you keep the bot in an enclosure to prevent it wandering off if you're using terrain handling! (Recommended size 5x5x5) enabled=false 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_range=5 # The range the bot can move around randomly (Note: the bigger the range, the slower the bot will be) walk_retries=20 # How many timec can the bot fail trying to move before using the command method [AutoRelog] From a6ad163aadf5350ccb6cbe3fe9ec666b53b3228d Mon Sep 17 00:00:00 2001 From: Milutinke Date: Wed, 28 Sep 2022 18:52:57 +0200 Subject: [PATCH 4/9] Fixed some comments in the default ini file. --- MinecraftClient/Resources/config/MinecraftClient.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini index 73e109a3..14b1e034 100644 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ b/MinecraftClient/Resources/config/MinecraftClient.ini @@ -138,7 +138,7 @@ 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 or make the bot walk around randomly to avoid automatic AFK disconnection +# Send a command on a regular or random 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! (Recommended size 5x5x5) enabled=false @@ -299,11 +299,11 @@ log_delay=600 # 10 = 1s [Map] # Allows you to render maps into .jpg images # This is useful for solving captchas which use maps -# NOTE: This is a new feature, we could not find the proper color mappings, but we are continuing with the search -# The colors are not like in minecraft and might look ugly -# This feature is currently only useful for solving captchas, which is it's primary purpose for the time being. +# NOTE: +# This feature is currently only useful for solving captchas which use maps. # If some servers have a very short time for solving captchas, enabe auto_render_on_update and prepare to open the file quickly. # On linux you can use FTP to access generated files. +# In the future it might will be possible to display maps directly in the console with a separate command. enabled=false resize_map=false # Should the map be resized? (Default one is small 128x128) resize_to=256 # The size to resize the map to (Note: the bigger it is, the lower the quallity is) From 3a9c9f3c8eaf1f7834c29386d34e80955549b3ce Mon Sep 17 00:00:00 2001 From: Milutinke Date: Wed, 28 Sep 2022 18:56:12 +0200 Subject: [PATCH 5/9] Improved some more comments. --- MinecraftClient/Resources/config/MinecraftClient.ini | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini index 14b1e034..5ec3aeb8 100644 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ b/MinecraftClient/Resources/config/MinecraftClient.ini @@ -286,6 +286,7 @@ backupinterval=300 # How long should replay file be auto-saved, i # This is due to a slow pathfinding algorithm, we're working on getting a better one # You can tweak the update limit and find what works best for you. (NOTE: Do not but a very low one, because you might achieve the opposite, # this might clog the thread for terain handling) and thus slow the bot even more. +# /!\ Make sure server rules allow an option like this in the rules of the server before using this bot enabled=false update_limit=10 # The rate at which the bot does calculations (10 = 1s) (Default: 5) (You can tweak this if you feel the bot is too slow) stop_at_distance=3 # Do not follow the player if he is in the range of 3 blocks (prevents the bot from pushing a player in an infinite loop) @@ -299,15 +300,17 @@ log_delay=600 # 10 = 1s [Map] # Allows you to render maps into .jpg images # This is useful for solving captchas which use maps +# The maps are rendered into Rendered_Maps folder. # NOTE: # This feature is currently only useful for solving captchas which use maps. # If some servers have a very short time for solving captchas, enabe auto_render_on_update and prepare to open the file quickly. # On linux you can use FTP to access generated files. # In the future it might will be possible to display maps directly in the console with a separate command. +# /!\ Make sure server rules allow bots to be used on the server, or you risk being punished. enabled=false resize_map=false # Should the map be resized? (Default one is small 128x128) resize_to=256 # The size to resize the map to (Note: the bigger it is, the lower the quallity is) auto_render_on_update=false # Automatically render the map once it's received or updated from/by the server -delete_rendered_on_unload=true # Delete all rendered maps on unload or exit +delete_rendered_on_unload=true # Delete all rendered maps on unload/reload (Does not delete the images if you exit the client) notify_on_first_update=false # Get a notification when you have gotten a map from the server for the first time - # Note: Will be printed for each map in vicinity, could cause spam if there are a lot of maps \ No newline at end of file + # Note: Will be printed for each map in vicinity, could cause spam if there are a lot of maps \ No newline at end of file From 6a266c68c33db5e18460af22cc2e08d1ce8dd41a Mon Sep 17 00:00:00 2001 From: Milutinke Date: Wed, 28 Sep 2022 21:39:13 +0200 Subject: [PATCH 6/9] Leave bed command. --- MinecraftClient/Commands/Leavebed.cs | 17 +++++++++++++++++ MinecraftClient/Resources/lang/en.ini | 4 ++++ 2 files changed, 21 insertions(+) create mode 100644 MinecraftClient/Commands/Leavebed.cs diff --git a/MinecraftClient/Commands/Leavebed.cs b/MinecraftClient/Commands/Leavebed.cs new file mode 100644 index 00000000..1ded6aed --- /dev/null +++ b/MinecraftClient/Commands/Leavebed.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace MinecraftClient.Commands +{ + public class leaveBedCommand : Command + { + public override string CmdName { get { return "leavebed"; } } + public override string CmdUsage { get { return "leavebed"; } } + public override string CmdDesc { get { return "cmd.leavebed.desc"; } } + + public override string Run(McClient handler, string command, Dictionary localVars) + { + handler.SendEntityAction(Protocol.EntityActionType.LeaveBed); + return Translations.TryGet("cmd.leavebed.leaving"); + } + } +} \ No newline at end of file diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 4b80c088..ceb42086 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -343,6 +343,10 @@ cmd.inventory.help.unknown=Unknown action. cmd.inventory.found_items=Found items cmd.inventory.no_found_items=Could not find the specified item in any of avaliable Inventories! +# Leave bed +cmd.leavebed.desc=Used to leave a bed. +cmd.leavebed.leaving=Leaving a bed. + # List cmd.list.desc=get the player list. cmd.list.players=PlayerList: {0} From cd3adfa14cdb168994ddad7ec1591bfdcc360bd8 Mon Sep 17 00:00:00 2001 From: Milutinke Date: Wed, 28 Sep 2022 22:43:14 +0200 Subject: [PATCH 7/9] Changed the bed command to be able to sleep. Added relative coordinates to /dig command. --- MinecraftClient/ChatBots/Map.cs | 2 +- MinecraftClient/Commands/Dig.cs | 8 ++- MinecraftClient/Commands/Leavebed.cs | 57 ++++++++++++++++--- MinecraftClient/Mapping/MaterialExtensions.cs | 32 +++++++++++ MinecraftClient/Resources/lang/en.ini | 8 ++- 5 files changed, 94 insertions(+), 13 deletions(-) diff --git a/MinecraftClient/ChatBots/Map.cs b/MinecraftClient/ChatBots/Map.cs index 0969daba..a6793e1f 100644 --- a/MinecraftClient/ChatBots/Map.cs +++ b/MinecraftClient/ChatBots/Map.cs @@ -33,7 +33,7 @@ namespace MinecraftClient.ChatBots deleteAllOnExit = Settings.Map_Delete_All_On_Unload; notifyOnFirstUpdate = Settings.Map_Notify_On_First_Update; - RegisterChatBotCommand("maps", "bot.map.cmd.desc", "maps > | maps >", OnMapCommand); + RegisterChatBotCommand("maps", "bot.map.cmd.desc", "maps list|render or maps l|r ", OnMapCommand); } public override void OnUnload() diff --git a/MinecraftClient/Commands/Dig.cs b/MinecraftClient/Commands/Dig.cs index fc5214fb..9a303561 100644 --- a/MinecraftClient/Commands/Dig.cs +++ b/MinecraftClient/Commands/Dig.cs @@ -24,9 +24,11 @@ namespace MinecraftClient.Commands { try { - int x = int.Parse(args[0]); - int y = int.Parse(args[1]); - int z = int.Parse(args[2]); + Location current = handler.GetCurrentLocation(); + double x = args[0].StartsWith('~') ? current.X + (args[0].Length > 1 ? double.Parse(args[0][1..]) : 0) : double.Parse(args[0]); + double y = args[1].StartsWith('~') ? current.Y + (args[1].Length > 1 ? double.Parse(args[1][1..]) : 0) : double.Parse(args[1]); + double z = args[2].StartsWith('~') ? current.Z + (args[2].Length > 1 ? double.Parse(args[2][1..]) : 0) : double.Parse(args[2]); + Location blockToBreak = new Location(x, y, z); if (blockToBreak.DistanceSquared(handler.GetCurrentLocation().EyesLocation()) > 25) return Translations.Get("cmd.dig.too_far"); diff --git a/MinecraftClient/Commands/Leavebed.cs b/MinecraftClient/Commands/Leavebed.cs index 1ded6aed..cfc0c4ce 100644 --- a/MinecraftClient/Commands/Leavebed.cs +++ b/MinecraftClient/Commands/Leavebed.cs @@ -1,17 +1,60 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MinecraftClient.Mapping; +using PInvoke; namespace MinecraftClient.Commands { - public class leaveBedCommand : Command + public class BedCommand : Command { - public override string CmdName { get { return "leavebed"; } } - public override string CmdUsage { get { return "leavebed"; } } - public override string CmdDesc { get { return "cmd.leavebed.desc"; } } + public override string CmdName { get { return "bed"; } } + public override string CmdUsage { get { return "bed leave|sleep "; } } + public override string CmdDesc { get { return "cmd.bed.desc"; } } public override string Run(McClient handler, string command, Dictionary localVars) { - handler.SendEntityAction(Protocol.EntityActionType.LeaveBed); - return Translations.TryGet("cmd.leavebed.leaving"); + string[] args = getArgs(command); + + if (args.Length >= 1) + { + string subcommand = args[0].ToLower().Trim(); + + if (subcommand.Equals("leave") || subcommand.Equals("l")) + { + handler.SendEntityAction(Protocol.EntityActionType.LeaveBed); + return Translations.TryGet("cmd.bed.leaving"); + } + + if (subcommand.Equals("sleep") || subcommand.Equals("s")) + { + if (args.Length >= 3) + { + Location current = handler.GetCurrentLocation(); + double x = args[1].StartsWith('~') ? current.X + (args[1].Length > 1 ? double.Parse(args[1][1..]) : 0) : double.Parse(args[1]); + double y = args[2].StartsWith('~') ? current.Y + (args[2].Length > 1 ? double.Parse(args[2][1..]) : 0) : double.Parse(args[2]); + double z = args[3].StartsWith('~') ? current.Z + (args[3].Length > 1 ? double.Parse(args[3][1..]) : 0) : double.Parse(args[3]); + + Location block = new Location(x, y, z).ToFloor(), blockCenter = block.ToCenter(); + + if (!handler.GetWorld().GetBlock(block).Type.IsBed()) + return Translations.TryGet("cmd.bed.not_a_bed", blockCenter.X, blockCenter.Y, blockCenter.Z); + + bool res = handler.PlaceBlock(block, Direction.Down); + + return Translations.TryGet( + "cmd.bed.trying_to_use", + blockCenter.X, + blockCenter.Y, + blockCenter.Z, + Translations.TryGet(res ? "cmd.bed.in" : "cmd.bed.not_in") + ); + } + } + } + + return CmdUsage; } } } \ No newline at end of file diff --git a/MinecraftClient/Mapping/MaterialExtensions.cs b/MinecraftClient/Mapping/MaterialExtensions.cs index fafa4894..f1b9129a 100644 --- a/MinecraftClient/Mapping/MaterialExtensions.cs +++ b/MinecraftClient/Mapping/MaterialExtensions.cs @@ -752,6 +752,7 @@ namespace MinecraftClient.Mapping return false; } } + /// /// Check if the provided material is a liquid a player can swim into /// @@ -768,5 +769,36 @@ namespace MinecraftClient.Mapping return false; } } + + /// + /// Check if the provided material is a bed + /// + /// Material to test + /// True if the material is a bed + public static bool IsBed(this Material m) + { + switch (m) + { + case Material.BlackBed: + case Material.BlueBed: + case Material.BrownBed: + case Material.CyanBed: + case Material.GrayBed: + case Material.GreenBed: + case Material.LightBlueBed: + case Material.LightGrayBed: + case Material.LimeBed: + case Material.MagentaBed: + case Material.OrangeBed: + case Material.PinkBed: + case Material.PurpleBed: + case Material.RedBed: + case Material.WhiteBed: + case Material.YellowBed: + return true; + default: + return false; + } + } } } diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index ceb42086..bbcfaddf 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -344,8 +344,12 @@ cmd.inventory.found_items=Found items cmd.inventory.no_found_items=Could not find the specified item in any of avaliable Inventories! # Leave bed -cmd.leavebed.desc=Used to leave a bed. -cmd.leavebed.leaving=Leaving a bed. +cmd.bed.desc=Used to sleep in or leave a bed. +cmd.bed.leaving=Sending a command to leave a bed to the server. +cmd.bed.trying_to_use=Trying to sleep in a bed on location (X: {0:0.0}, Y: {1:0.0}, Z: {2:0.0}). Result: {3} +cmd.bed.in=Succesfully laid in bed! +cmd.bed.not_in=Could not lay in bed. Are you trying to sleep in a bed? (PS: You must use the head block coordinates of the bed) +cmd.bed.not_a_bed=The block on (X: {0:0.0}, Y: {1:0.0}, Z: {2:0.0}) is not a bed! # List cmd.list.desc=get the player list. From a52da095b4f8e4b190c2bc0565c413a52d851b31 Mon Sep 17 00:00:00 2001 From: Milutinke Date: Thu, 29 Sep 2022 19:28:34 +0200 Subject: [PATCH 8/9] Added an option to find a bed and sleep in it. --- MinecraftClient/Commands/Leavebed.cs | 96 ++++++++++++++++++++++++++- MinecraftClient/Resources/lang/en.ini | 6 ++ 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/MinecraftClient/Commands/Leavebed.cs b/MinecraftClient/Commands/Leavebed.cs index cfc0c4ce..89f6c7a7 100644 --- a/MinecraftClient/Commands/Leavebed.cs +++ b/MinecraftClient/Commands/Leavebed.cs @@ -1,16 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; +using System.Threading.Tasks; using MinecraftClient.Mapping; -using PInvoke; namespace MinecraftClient.Commands { public class BedCommand : Command { public override string CmdName { get { return "bed"; } } - public override string CmdUsage { get { return "bed leave|sleep "; } } + public override string CmdUsage { get { return "bed leave|sleep |sleep "; } } public override string CmdDesc { get { return "cmd.bed.desc"; } } public override string Run(McClient handler, string command, Dictionary localVars) @@ -29,6 +28,97 @@ namespace MinecraftClient.Commands if (subcommand.Equals("sleep") || subcommand.Equals("s")) { + if (args.Length == 2) + { + if (!int.TryParse(args[1], out int radius)) + return CmdUsage; + + handler.GetLogger().Info(Translations.TryGet("cmd.bed.searching", radius)); + + Location current = handler.GetCurrentLocation(); + Location bedLocation = current; + + Material[] bedMaterialList = new Material[]{ + Material.BlackBed, + Material.BlueBed, + Material.BrownBed, + Material.CyanBed, + Material.GrayBed, + Material.GreenBed, + Material.LightBlueBed, + Material.LightGrayBed, + Material.LimeBed, + Material.MagentaBed, + Material.OrangeBed, + Material.PinkBed, + Material.PurpleBed, + Material.RedBed, + Material.WhiteBed, + Material.YellowBed + }; + + bool found = false; + foreach (Material material in bedMaterialList) + { + List beds = handler.GetWorld().FindBlock(current, material, radius); + + if (beds.Count > 0) + { + found = true; + bedLocation = beds.First(); + break; + } + } + + if (!found) + return Translations.TryGet("cmd.bed.bed_not_found"); + + handler.Log.Info(Translations.TryGet("cmd.bed.found_a_bed_at", bedLocation.X, bedLocation.Y, bedLocation.Z)); + + if (!Movement.CheckChunkLoading(handler.GetWorld(), current, bedLocation)) + return Translations.Get("cmd.move.chunk_not_loaded", bedLocation.X, bedLocation.Y, bedLocation.Z); + + if (handler.MoveTo(bedLocation)) + { + Task.Factory.StartNew(() => + { + bool atTheLocation = false; + DateTime timeout = DateTime.Now.AddSeconds(60); + + while (DateTime.Now < timeout) + { + if (handler.GetCurrentLocation() == bedLocation || handler.GetCurrentLocation().Distance(bedLocation) <= 2.0) + { + atTheLocation = true; + break; + } + } + + if (!atTheLocation) + { + handler.Log.Info(Translations.TryGet("cmd.bed.failed_to_reach_in_time", bedLocation.X, bedLocation.Y, bedLocation.Z)); + return; + } + + handler.Log.Info(Translations.TryGet("cmd.bed.moving", bedLocation.X, bedLocation.Y, bedLocation.Z)); + + bool res = handler.PlaceBlock(bedLocation, Direction.Down); + + handler.Log.Info(Translations.TryGet( + "cmd.bed.trying_to_use", + bedLocation.X, + bedLocation.Y, + bedLocation.Z, + Translations.TryGet(res ? "cmd.bed.in" : "cmd.bed.not_in") + )); + }); + + return ""; + } + + return Translations.Get("cmd.bed.cant_reach_safely"); + } + if (args.Length >= 3) { Location current = handler.GetCurrentLocation(); diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index bbcfaddf..92f0b614 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -350,6 +350,12 @@ cmd.bed.trying_to_use=Trying to sleep in a bed on location (X: {0:0.0}, Y: {1:0. cmd.bed.in=Succesfully laid in bed! cmd.bed.not_in=Could not lay in bed. Are you trying to sleep in a bed? (PS: You must use the head block coordinates of the bed) cmd.bed.not_a_bed=The block on (X: {0:0.0}, Y: {1:0.0}, Z: {2:0.0}) is not a bed! +cmd.bed.searching=Searching for a bed in radius of {0}... +cmd.bed.bed_not_found=Could not find a bed! +cmd.bed.found_a_bed_at=Found a bet at (X: {0:0.0}, Y: {1:0.0}, Z: {2:0.0}). +cmd.bed.cant_reach_safely=Can not reach the bed safely! +cmd.bed.moving=Moving to (X: {0:0.0}, Y: {1:0.0}, Z: {2:0.0}) where the bed is located. +cmd.bed.failed_to_reach_in_time=Failed to reach the bed position (X: {0:0.0}, Y: {1:0.0}, Z: {2:0.0}) in time (30 seconds). Giving up! # List cmd.list.desc=get the player list. From d66e009979e2fcc2386adbf17f886dd09edc9a2f Mon Sep 17 00:00:00 2001 From: Milutinke Date: Thu, 29 Sep 2022 19:32:02 +0200 Subject: [PATCH 9/9] Removed the old name for the file with bed command. Now using a proper name. --- MinecraftClient/Commands/{Leavebed.cs => Bed.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename MinecraftClient/Commands/{Leavebed.cs => Bed.cs} (100%) diff --git a/MinecraftClient/Commands/Leavebed.cs b/MinecraftClient/Commands/Bed.cs similarity index 100% rename from MinecraftClient/Commands/Leavebed.cs rename to MinecraftClient/Commands/Bed.cs