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)