From 9549743c6d82a44b2e3546c4776f0c92297bb8ca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 07:55:25 +0000 Subject: [PATCH 1/3] Implement legacy Farmer support updates Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/395596c2-cc40-4295-8100-a8408243f45b Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com> --- MinecraftClient/ChatBots/Farmer.cs | 22 +++++++++++++++++-- .../Mapping/BlockPalettes/Palette112.cs | 1 + .../Protocol/Handlers/Protocol18.cs | 1 + .../Resources/Translations/Translations.resx | 2 +- docs/guide/chat-bots.md | 2 +- docs/guide/configuration.md | 2 +- docs/guide/usage.md | 6 ++--- 7 files changed, 28 insertions(+), 8 deletions(-) diff --git a/MinecraftClient/ChatBots/Farmer.cs b/MinecraftClient/ChatBots/Farmer.cs index 7c15791c..8a21ae5c 100644 --- a/MinecraftClient/ChatBots/Farmer.cs +++ b/MinecraftClient/ChatBots/Farmer.cs @@ -73,7 +73,7 @@ namespace MinecraftClient.ChatBots public override void Initialize() { - if (GetProtocolVersion() < Protocol18Handler.MC_1_13_Version) + if (GetProtocolVersion() < Protocol18Handler.MC_1_8_Version) { LogToConsole(Translations.bot_farmer_not_implemented); return; @@ -626,6 +626,9 @@ namespace MinecraftClient.ChatBots { var protocolVersion = GetProtocolVersion(); + if (protocolVersion < Protocol18Handler.MC_1_13_Version) + return IsLegacyCropFullyGrown(block, cropType); + switch (cropType) { case CropType.Beetroot: @@ -781,6 +784,21 @@ namespace MinecraftClient.ChatBots return false; } + private static bool IsLegacyCropFullyGrown(Block block, CropType cropType) + { + return cropType switch + { + CropType.Beetroot => block.BlockId == 207 && block.BlockMeta >= 3, + CropType.Carrot => block.BlockId == 141 && block.BlockMeta >= 7, + CropType.Melon => block.BlockId == 105 && block.BlockMeta >= 7, + CropType.NetherWart => block.BlockId == 115 && block.BlockMeta >= 3, + CropType.Pumpkin => block.BlockId == 104 && block.BlockMeta >= 7, + CropType.Potato => block.BlockId == 142 && block.BlockMeta >= 7, + CropType.Wheat => block.BlockId == 59 && block.BlockMeta >= 7, + _ => false + }; + } + // Yoinked from ReinforceZwei's AutoTree and adapted to search the whole of inventory in additon to the hotbar private bool SwitchToItem(ItemType itemType) { @@ -854,4 +872,4 @@ namespace MinecraftClient.ChatBots else LogDebugToConsole(text); } } -} \ No newline at end of file +} diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette112.cs b/MinecraftClient/Mapping/BlockPalettes/Palette112.cs index cdfd4a53..0a9aa947 100644 --- a/MinecraftClient/Mapping/BlockPalettes/Palette112.cs +++ b/MinecraftClient/Mapping/BlockPalettes/Palette112.cs @@ -183,6 +183,7 @@ namespace MinecraftClient.Mapping.BlockPalettes { 173, Material.CoalBlock }, { 174, Material.PackedIce }, { 175, Material.TallGrass }, // DoublePlant + { 207, Material.Beetroots }, // BeetrootBlock }; protected override Dictionary GetDict() diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 50e7b91a..5c69f037 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -5506,6 +5506,7 @@ namespace MinecraftClient.Protocol.Handlers packet.Add(0); // cursorY packet.Add(0); // cursorZ + SendPacket(PacketTypesOut.PlayerBlockPlacement, packet); return true; case < MC_1_14_Version: packet.AddRange(dataTypes.GetLocation(location)); diff --git a/MinecraftClient/Resources/Translations/Translations.resx b/MinecraftClient/Resources/Translations/Translations.resx index 2e9da34a..cc0333b9 100644 --- a/MinecraftClient/Resources/Translations/Translations.resx +++ b/MinecraftClient/Resources/Translations/Translations.resx @@ -521,7 +521,7 @@ cooldown: {6} The Farmer bot needs Terrain Handling in order to work, please enable it! - Not implemented bellow 1.13! + Not implemented below 1.8! Radius diff --git a/docs/guide/chat-bots.md b/docs/guide/chat-bots.md index 8a5a39eb..d0383717 100644 --- a/docs/guide/chat-bots.md +++ b/docs/guide/chat-bots.md @@ -1957,7 +1957,7 @@ redirectFrom:

Warning

-**This a newly added bot, it is not perfect and was only tested in 1.19.2, there are some minor issues with it and you should treat it as an experimental bot.** +**This bot is still experimental, has some known issues, and should be treated with extra caution on legacy versions.**
diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 715108d3..a21c40e3 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -555,7 +555,7 @@ Coordinate = { x = 145, y = 64, z = 2045 }

Warning

- **This feature is currently not supported in `1.4.6 - 1.9`. But we are working on getting it supported in 1.8 and 1.9.** + **This feature is currently supported on `1.8+` and is unavailable on `1.4.6 - 1.7.10`.**
diff --git a/docs/guide/usage.md b/docs/guide/usage.md index d6dcfaeb..cff5824c 100644 --- a/docs/guide/usage.md +++ b/docs/guide/usage.md @@ -1016,7 +1016,7 @@ In scripts and remote control, no slash is needed to perform the command, eg. `q

Warning

- **The [Inventory Handling](configuration.md#inventoryhandling) is currently not supported in `1.4.6 - 1.9`** + **The [Inventory Handling](configuration.md#inventoryhandling) is currently supported on `1.8+` and is unavailable on `1.4.6 - 1.7.10`.**
@@ -1063,7 +1063,7 @@ In scripts and remote control, no slash is needed to perform the command, eg. `q

Warning

- **The [Inventory Handling](configuration.md#inventoryhandling) is currently not supported in `1.4.6 - 1.9`.** + **The [Inventory Handling](configuration.md#inventoryhandling) is currently supported on `1.8+` and is unavailable on `1.4.6 - 1.7.10`.**
@@ -1298,7 +1298,7 @@ In scripts and remote control, no slash is needed to perform the command, eg. `q

Warning

- **The [Inventory Handling](configuration.md#inventoryhandling) is currently not supported in `1.4.6 - 1.9`.** + **The [Inventory Handling](configuration.md#inventoryhandling) is currently supported on `1.8+` and is unavailable on `1.4.6 - 1.7.10`.**
From 5279609561880d5424b3a383bbd22740941a36d0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 08:00:41 +0000 Subject: [PATCH 2/3] Polish legacy Farmer validation logic Agent-Logs-Url: https://github.com/MCCTeam/Minecraft-Console-Client/sessions/395596c2-cc40-4295-8100-a8408243f45b Co-authored-by: milutinke <441903+milutinke@users.noreply.github.com> --- MinecraftClient/ChatBots/Farmer.cs | 35 +++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/MinecraftClient/ChatBots/Farmer.cs b/MinecraftClient/ChatBots/Farmer.cs index 8a21ae5c..5d50ac55 100644 --- a/MinecraftClient/ChatBots/Farmer.cs +++ b/MinecraftClient/ChatBots/Farmer.cs @@ -616,18 +616,18 @@ namespace MinecraftClient.ChatBots if (fullyGrown && material is Material.Melon or Material.Pumpkin) return true; - var isFullyGrown = IsCropFullyGrown(GetWorld().GetBlock(location), cropType); + var isFullyGrown = IsCropFullyGrown(GetWorld().GetBlock(location), cropType, location); return fullyGrown ? isFullyGrown : !isFullyGrown; }) .ToList(); } - private bool IsCropFullyGrown(Block block, CropType cropType) + private bool IsCropFullyGrown(Block block, CropType cropType, Location? location = null) { var protocolVersion = GetProtocolVersion(); if (protocolVersion < Protocol18Handler.MC_1_13_Version) - return IsLegacyCropFullyGrown(block, cropType); + return IsLegacyCropFullyGrown(block, cropType, location); switch (cropType) { @@ -784,21 +784,44 @@ namespace MinecraftClient.ChatBots return false; } - private static bool IsLegacyCropFullyGrown(Block block, CropType cropType) + private bool IsLegacyCropFullyGrown(Block block, CropType cropType, Location? location) { return cropType switch { CropType.Beetroot => block.BlockId == 207 && block.BlockMeta >= 3, CropType.Carrot => block.BlockId == 141 && block.BlockMeta >= 7, - CropType.Melon => block.BlockId == 105 && block.BlockMeta >= 7, + CropType.Melon => block.BlockId == 105 + && (block.BlockMeta >= 7 || HasAdjacentBlock(location, Material.Melon)), CropType.NetherWart => block.BlockId == 115 && block.BlockMeta >= 3, - CropType.Pumpkin => block.BlockId == 104 && block.BlockMeta >= 7, + CropType.Pumpkin => block.BlockId == 104 + && (block.BlockMeta >= 7 || HasAdjacentBlock(location, Material.Pumpkin)), CropType.Potato => block.BlockId == 142 && block.BlockMeta >= 7, CropType.Wheat => block.BlockId == 59 && block.BlockMeta >= 7, _ => false }; } + private bool HasAdjacentBlock(Location? location, Material material) + { + if (location is not Location stemLocation) + return false; + + var world = GetWorld(); + int x = (int)Math.Floor(stemLocation.X); + int y = (int)Math.Floor(stemLocation.Y); + int z = (int)Math.Floor(stemLocation.Z); + + Location[] adjacentLocations = + [ + new(x + 1, y, z), + new(x - 1, y, z), + new(x, y, z + 1), + new(x, y, z - 1) + ]; + + return adjacentLocations.Any(adjacentLocation => world.GetBlock(adjacentLocation).Type == material); + } + // Yoinked from ReinforceZwei's AutoTree and adapted to search the whole of inventory in additon to the hotbar private bool SwitchToItem(ItemType itemType) { From c282f2783ce9c40367bc702e6fbe04828e0ffaca Mon Sep 17 00:00:00 2001 From: Anon Date: Sun, 3 May 2026 15:46:16 +0200 Subject: [PATCH 3/3] Fix legacy Farmer placement support --- MinecraftClient/ChatBots/Farmer.cs | 19 ++++++++-- .../Protocol/Handlers/Protocol18.cs | 36 ++++++++++++++----- .../Translations/Translations.Designer.cs | 11 +++++- .../Resources/Translations/Translations.resx | 3 ++ MinecraftClient/Scripting/ChatBot.cs | 5 +-- docs/guide/chat-bots.md | 2 ++ 6 files changed, 62 insertions(+), 14 deletions(-) diff --git a/MinecraftClient/ChatBots/Farmer.cs b/MinecraftClient/ChatBots/Farmer.cs index 5d50ac55..fe33176a 100644 --- a/MinecraftClient/ChatBots/Farmer.cs +++ b/MinecraftClient/ChatBots/Farmer.cs @@ -149,6 +149,10 @@ namespace MinecraftClient.ChatBots if (running) return r.SetAndReturn(CmdResult.Status.Fail, Translations.bot_farmer_already_running); + if (!IsCropAvailableForProtocol(whatToFarm, GetProtocolVersion())) + return r.SetAndReturn(CmdResult.Status.Fail, + string.Format(Translations.bot_farmer_crop_unavailable, whatToFarm, "1.9")); + var movementLock = BotMovementLock.Instance; if (movementLock is { IsLocked: true }) return r.SetAndReturn(CmdResult.Status.Fail, @@ -369,11 +373,11 @@ namespace MinecraftClient.ChatBots break; } - var loc = new Location(Math.Floor(location.X), Math.Floor(location2.Y), + var loc = new Location(Math.Floor(location.X), Math.Floor(location.Y), Math.Floor(location.Z)); LogDebug("Sending placeblock to: " + loc); - SendPlaceBlock(loc, Direction.Up); + SendPlaceBlock(loc, Direction.Up, lookAtBlock: true); Thread.Sleep(300); } else LogDebug("Can't move to: " + location2); @@ -496,7 +500,7 @@ namespace MinecraftClient.ChatBots { // TODO: Do a check if the carrot/potato is on the first growth stage // if so, use: new Location(location.X, (double)(location.Y - 1) + (double)0.93750, location.Z) - SendPlaceBlock(location2, Direction.Down); + SendPlaceBlock(location2, Direction.Down, lookAtBlock: true); } Thread.Sleep(100); @@ -591,6 +595,15 @@ namespace MinecraftClient.ChatBots }; } + private static bool IsCropAvailableForProtocol(CropType type, int protocolVersion) + { + return type switch + { + CropType.Beetroot => protocolVersion >= Protocol18Handler.MC_1_9_Version, + _ => true + }; + } + private List FindEmptyFarmland(int radius) { return GetWorld() diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 5c69f037..730507aa 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -211,6 +211,7 @@ namespace MinecraftClient.Protocol.Handlers >= MC_1_14_Version => new EntityPalette114(), >= MC_1_13_Version => new EntityPalette113(), >= MC_1_12_Version => new EntityPalette112(), + >= MC_1_11_Version => new EntityPalette112(), _ => new EntityPalette18() }; @@ -2968,7 +2969,9 @@ namespace MinecraftClient.Protocol.Handlers double y = dataTypes.ReadNextInt(packetData) / 8.0D; double z = dataTypes.ReadNextInt(packetData) / 8.0D; float volume = dataTypes.ReadNextFloat(packetData); - float pitch = dataTypes.ReadNextFloat(packetData); + float pitch = protocolVersion < MC_1_10_Version + ? dataTypes.ReadNextByte(packetData) / 63.0f + : dataTypes.ReadNextFloat(packetData); handler.OnSoundEffect(soundName, new Location(x, y, z), category, volume, pitch, null); break; @@ -2989,7 +2992,9 @@ namespace MinecraftClient.Protocol.Handlers double y = dataTypes.ReadNextInt(packetData) / 8.0D; double z = dataTypes.ReadNextInt(packetData) / 8.0D; float volume = dataTypes.ReadNextFloat(packetData); - float pitch = dataTypes.ReadNextFloat(packetData); + float pitch = protocolVersion < MC_1_10_Version + ? dataTypes.ReadNextByte(packetData) / 63.0f + : dataTypes.ReadNextFloat(packetData); if (protocolVersion >= MC_1_19_Version) dataTypes.ReadNextLong(packetData); // Seed @@ -5502,9 +5507,7 @@ namespace MinecraftClient.Protocol.Handlers playerInventory.Items.TryGetValue(slotWindowIds[currentSlot], out var item); packet.AddRange(dataTypes.GetItemSlot(item, itemPalette)); - packet.Add(0); // cursorX - packet.Add(0); // cursorY - packet.Add(0); // cursorZ + AddLegacyBlockPlacementCursor(packet, cursorX, cursorY, cursorZ); SendPacket(PacketTypesOut.PlayerBlockPlacement, packet); return true; @@ -5520,9 +5523,14 @@ namespace MinecraftClient.Protocol.Handlers break; } - packet.AddRange(dataTypes.GetFloat(cursorX)); // cursorX - packet.AddRange(dataTypes.GetFloat(cursorY)); // cursorY - packet.AddRange(dataTypes.GetFloat(cursorZ)); // cursorZ + if (protocolVersion < MC_1_11_Version) + AddLegacyBlockPlacementCursor(packet, cursorX, cursorY, cursorZ); + else + { + packet.AddRange(dataTypes.GetFloat(cursorX)); // cursorX + packet.AddRange(dataTypes.GetFloat(cursorY)); // cursorY + packet.AddRange(dataTypes.GetFloat(cursorZ)); // cursorZ + } if (protocolVersion >= MC_1_14_Version) packet.Add(0); // insideBlock = false @@ -5561,6 +5569,18 @@ namespace MinecraftClient.Protocol.Handlers _ => (0.5f, 0.5f, 0.5f), }; + private static void AddLegacyBlockPlacementCursor(List packet, float cursorX, float cursorY, float cursorZ) + { + packet.Add(ToLegacyBlockPlacementCursor(cursorX)); + packet.Add(ToLegacyBlockPlacementCursor(cursorY)); + packet.Add(ToLegacyBlockPlacementCursor(cursorZ)); + } + + private static byte ToLegacyBlockPlacementCursor(float cursor) + { + return (byte)Math.Clamp((int)(cursor * 16.0f), 0, byte.MaxValue); + } + public bool SendHeldItemChange(short slot) { try diff --git a/MinecraftClient/Resources/Translations/Translations.Designer.cs b/MinecraftClient/Resources/Translations/Translations.Designer.cs index b6e454cd..5363c658 100644 --- a/MinecraftClient/Resources/Translations/Translations.Designer.cs +++ b/MinecraftClient/Resources/Translations/Translations.Designer.cs @@ -1221,6 +1221,15 @@ namespace MinecraftClient { } } + /// + /// Looks up a localized string similar to {0} is only available in Minecraft {1} and newer!. + /// + internal static string bot_farmer_crop_unavailable { + get { + return ResourceManager.GetString("bot.farmer.crop_unavailable", resourceCulture); + } + } + /// /// Looks up a localized string similar to Farming bot. /// @@ -1267,7 +1276,7 @@ namespace MinecraftClient { } /// - /// Looks up a localized string similar to Not implemented bellow 1.13!. + /// Looks up a localized string similar to Not implemented below 1.8!. /// internal static string bot_farmer_not_implemented { get { diff --git a/MinecraftClient/Resources/Translations/Translations.resx b/MinecraftClient/Resources/Translations/Translations.resx index cc0333b9..e95e2d29 100644 --- a/MinecraftClient/Resources/Translations/Translations.resx +++ b/MinecraftClient/Resources/Translations/Translations.resx @@ -505,6 +505,9 @@ cooldown: {6} Crop type + + {0} is only available in Minecraft {1} and newer! + Farming bot diff --git a/MinecraftClient/Scripting/ChatBot.cs b/MinecraftClient/Scripting/ChatBot.cs index 45236fda..c8d20edb 100644 --- a/MinecraftClient/Scripting/ChatBot.cs +++ b/MinecraftClient/Scripting/ChatBot.cs @@ -1562,10 +1562,11 @@ namespace MinecraftClient.Scripting /// Location to place block to /// Block face (e.g. Direction.Down when clicking on the block below to place this block) /// Hand.MainHand or Hand.OffHand + /// Also look at the block before interacting /// TRUE if successfully placed - public bool SendPlaceBlock(Location location, Direction blockFace, Hand hand = Hand.MainHand) + public bool SendPlaceBlock(Location location, Direction blockFace, Hand hand = Hand.MainHand, bool lookAtBlock = false) { - return Handler.PlaceBlock(location, blockFace, hand); + return Handler.PlaceBlock(location, blockFace, hand, lookAtBlock); } /// diff --git a/docs/guide/chat-bots.md b/docs/guide/chat-bots.md index d0383717..22e09926 100644 --- a/docs/guide/chat-bots.md +++ b/docs/guide/chat-bots.md @@ -1976,6 +1976,8 @@ redirectFrom: - Potato - Wheat + Beetroot farming requires Minecraft `1.9+`. + **Current list of issues:** - Sometimes the bot will not bone meal carrots/potatoes or melon/pumpkin stems (you will see it in a pattern of crops that have not been bonemealed)