Fix legacy Farmer placement support

This commit is contained in:
Anon 2026-05-03 15:46:16 +02:00
parent 5279609561
commit c282f2783c
6 changed files with 62 additions and 14 deletions

View file

@ -149,6 +149,10 @@ namespace MinecraftClient.ChatBots
if (running) if (running)
return r.SetAndReturn(CmdResult.Status.Fail, Translations.bot_farmer_already_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; var movementLock = BotMovementLock.Instance;
if (movementLock is { IsLocked: true }) if (movementLock is { IsLocked: true })
return r.SetAndReturn(CmdResult.Status.Fail, return r.SetAndReturn(CmdResult.Status.Fail,
@ -369,11 +373,11 @@ namespace MinecraftClient.ChatBots
break; 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)); Math.Floor(location.Z));
LogDebug("Sending placeblock to: " + loc); LogDebug("Sending placeblock to: " + loc);
SendPlaceBlock(loc, Direction.Up); SendPlaceBlock(loc, Direction.Up, lookAtBlock: true);
Thread.Sleep(300); Thread.Sleep(300);
} }
else LogDebug("Can't move to: " + location2); 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 // 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) // 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); 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<Location> FindEmptyFarmland(int radius) private List<Location> FindEmptyFarmland(int radius)
{ {
return GetWorld() return GetWorld()

View file

@ -211,6 +211,7 @@ namespace MinecraftClient.Protocol.Handlers
>= MC_1_14_Version => new EntityPalette114(), >= MC_1_14_Version => new EntityPalette114(),
>= MC_1_13_Version => new EntityPalette113(), >= MC_1_13_Version => new EntityPalette113(),
>= MC_1_12_Version => new EntityPalette112(), >= MC_1_12_Version => new EntityPalette112(),
>= MC_1_11_Version => new EntityPalette112(),
_ => new EntityPalette18() _ => new EntityPalette18()
}; };
@ -2968,7 +2969,9 @@ namespace MinecraftClient.Protocol.Handlers
double y = dataTypes.ReadNextInt(packetData) / 8.0D; double y = dataTypes.ReadNextInt(packetData) / 8.0D;
double z = dataTypes.ReadNextInt(packetData) / 8.0D; double z = dataTypes.ReadNextInt(packetData) / 8.0D;
float volume = dataTypes.ReadNextFloat(packetData); 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); handler.OnSoundEffect(soundName, new Location(x, y, z), category, volume, pitch, null);
break; break;
@ -2989,7 +2992,9 @@ namespace MinecraftClient.Protocol.Handlers
double y = dataTypes.ReadNextInt(packetData) / 8.0D; double y = dataTypes.ReadNextInt(packetData) / 8.0D;
double z = dataTypes.ReadNextInt(packetData) / 8.0D; double z = dataTypes.ReadNextInt(packetData) / 8.0D;
float volume = dataTypes.ReadNextFloat(packetData); 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) if (protocolVersion >= MC_1_19_Version)
dataTypes.ReadNextLong(packetData); // Seed dataTypes.ReadNextLong(packetData); // Seed
@ -5502,9 +5507,7 @@ namespace MinecraftClient.Protocol.Handlers
playerInventory.Items.TryGetValue(slotWindowIds[currentSlot], out var item); playerInventory.Items.TryGetValue(slotWindowIds[currentSlot], out var item);
packet.AddRange(dataTypes.GetItemSlot(item, itemPalette)); packet.AddRange(dataTypes.GetItemSlot(item, itemPalette));
packet.Add(0); // cursorX AddLegacyBlockPlacementCursor(packet, cursorX, cursorY, cursorZ);
packet.Add(0); // cursorY
packet.Add(0); // cursorZ
SendPacket(PacketTypesOut.PlayerBlockPlacement, packet); SendPacket(PacketTypesOut.PlayerBlockPlacement, packet);
return true; return true;
@ -5520,9 +5523,14 @@ namespace MinecraftClient.Protocol.Handlers
break; break;
} }
packet.AddRange(dataTypes.GetFloat(cursorX)); // cursorX if (protocolVersion < MC_1_11_Version)
packet.AddRange(dataTypes.GetFloat(cursorY)); // cursorY AddLegacyBlockPlacementCursor(packet, cursorX, cursorY, cursorZ);
packet.AddRange(dataTypes.GetFloat(cursorZ)); // 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) if (protocolVersion >= MC_1_14_Version)
packet.Add(0); // insideBlock = false packet.Add(0); // insideBlock = false
@ -5561,6 +5569,18 @@ namespace MinecraftClient.Protocol.Handlers
_ => (0.5f, 0.5f, 0.5f), _ => (0.5f, 0.5f, 0.5f),
}; };
private static void AddLegacyBlockPlacementCursor(List<byte> 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) public bool SendHeldItemChange(short slot)
{ {
try try

View file

@ -1221,6 +1221,15 @@ namespace MinecraftClient {
} }
} }
/// <summary>
/// Looks up a localized string similar to {0} is only available in Minecraft {1} and newer!.
/// </summary>
internal static string bot_farmer_crop_unavailable {
get {
return ResourceManager.GetString("bot.farmer.crop_unavailable", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Farming bot. /// Looks up a localized string similar to Farming bot.
/// </summary> /// </summary>
@ -1267,7 +1276,7 @@ namespace MinecraftClient {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Not implemented bellow 1.13!. /// Looks up a localized string similar to Not implemented below 1.8!.
/// </summary> /// </summary>
internal static string bot_farmer_not_implemented { internal static string bot_farmer_not_implemented {
get { get {

View file

@ -505,6 +505,9 @@ cooldown: {6}</value>
<data name="bot.farmer.crop_type" xml:space="preserve"> <data name="bot.farmer.crop_type" xml:space="preserve">
<value>Crop type</value> <value>Crop type</value>
</data> </data>
<data name="bot.farmer.crop_unavailable" xml:space="preserve">
<value>{0} is only available in Minecraft {1} and newer!</value>
</data>
<data name="bot.farmer.desc" xml:space="preserve"> <data name="bot.farmer.desc" xml:space="preserve">
<value>Farming bot</value> <value>Farming bot</value>
</data> </data>

View file

@ -1562,10 +1562,11 @@ namespace MinecraftClient.Scripting
/// <param name="location">Location to place block to</param> /// <param name="location">Location to place block to</param>
/// <param name="blockFace">Block face (e.g. Direction.Down when clicking on the block below to place this block)</param> /// <param name="blockFace">Block face (e.g. Direction.Down when clicking on the block below to place this block)</param>
/// <param name="hand">Hand.MainHand or Hand.OffHand</param> /// <param name="hand">Hand.MainHand or Hand.OffHand</param>
/// <param name="lookAtBlock">Also look at the block before interacting</param>
/// <returns>TRUE if successfully placed</returns> /// <returns>TRUE if successfully placed</returns>
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);
} }
/// <summary> /// <summary>

View file

@ -1976,6 +1976,8 @@ redirectFrom:
- Potato - Potato
- Wheat - Wheat
Beetroot farming requires Minecraft `1.9+`.
**Current list of issues:** **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) - 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)