Add AutoEat

#923
This commit is contained in:
ReinforceZwei 2020-04-08 00:28:03 +08:00 committed by ORelio
parent 70e5ae85d7
commit 2e1e79bcef
10 changed files with 128 additions and 11 deletions

View file

@ -850,5 +850,15 @@ namespace MinecraftClient
Container container = Handler.GetPlayerInventory(); Container container = Handler.GetPlayerInventory();
return new Container(container.ID, container.Type, container.Title, container.Items); return new Container(container.ID, container.Type, container.Title, container.Items);
} }
/// <summary>
/// Check if player is eating or not
/// </summary>
/// <remarks>Some bot like AutoAttack need this. We don't want to attack while eating</remarks>
/// <returns>True if is eating</returns>
protected bool GetIsEating()
{
return Handler.GetIsEating();
}
} }
} }

View file

@ -31,6 +31,8 @@ namespace MinecraftClient.ChatBots
} }
public override void Update() public override void Update()
{
if (!GetIsEating())
{ {
if (attackCooldownCounter == 0) if (attackCooldownCounter == 0)
{ {
@ -48,6 +50,7 @@ namespace MinecraftClient.ChatBots
attackCooldownCounter--; attackCooldownCounter--;
} }
} }
}
public override void OnEntitySpawn(Entity entity) public override void OnEntitySpawn(Entity entity)
{ {

View file

@ -43,6 +43,7 @@ namespace MinecraftClient.Commands
response.Add(String.Format(" #{0}: {1} x{2}", item.Key, item.Value.Type, item.Value.Count)); response.Add(String.Format(" #{0}: {1} x{2}", item.Key, item.Value.Type, item.Value.Count));
else response.Add(String.Format(" #{0}: {1} x{2} - {3}§8", item.Key, item.Value.Type, item.Value.Count, displayName)); else response.Add(String.Format(" #{0}: {1} x{2} - {3}§8", item.Key, item.Value.Type, item.Value.Count, displayName));
} }
response.Add("Your selected hotbar is " + (handler.GetCurrentSlot() + 1));
return String.Join("\n", response.ToArray()); return String.Join("\n", response.ToArray());
case "click": case "click":
if (args.Length == 3) if (args.Length == 3)

View file

@ -70,5 +70,24 @@ namespace MinecraftClient.Inventory
return null; return null;
} }
} }
/// <summary>
/// Check item is a food
/// </summary>
/// <returns>True if is a food</returns>
public bool IsFood()
{
// non-poison and stackable food
// remarks: auto eat may works with non-stackable food <- not tested
int[] foods = { 524, 765, 821, 823, 562, 763, 680, 629, 801, 585, 788, 630, 670, 674, 588, 587, 768, 673, 764, 777, 677, 679, 625, 800, 584, 787, 626, 678, 876, 627 };
if (foods.Contains((int)Type))
{
return true;
}
else
{
return false;
}
}
} }
} }

View file

@ -59,8 +59,13 @@ namespace MinecraftClient
private int playerEntityID; private int playerEntityID;
// player health and hunger
private float playerHealth; private float playerHealth;
private int playerFoodSaturation; private int playerFoodSaturation;
private bool Eating = false;
private int HungerThreshold = 6;
private byte CurrentSlot = 0;
private byte LastSlot = 0; // for switch back to origin slot after eating
// Entity handling // Entity handling
private Dictionary<int, Entity> entities = new Dictionary<int, Entity>(); private Dictionary<int, Entity> entities = new Dictionary<int, Entity>();
@ -80,6 +85,8 @@ namespace MinecraftClient
public Double GetServerTPS() { return serverTPS; } public Double GetServerTPS() { return serverTPS; }
public float GetHealth() { return playerHealth; } public float GetHealth() { return playerHealth; }
public int GetSaturation() { return playerFoodSaturation; } public int GetSaturation() { return playerFoodSaturation; }
public byte GetCurrentSlot() { return CurrentSlot; }
public bool GetIsEating() { return Eating; }
// get bots list for unloading them by commands // get bots list for unloading them by commands
public List<ChatBot> GetLoadedChatBots() public List<ChatBot> GetLoadedChatBots()
@ -1530,6 +1537,7 @@ namespace MinecraftClient
{ {
if (slot >= 0 && slot <= 8) if (slot >= 0 && slot <= 8)
{ {
CurrentSlot = Convert.ToByte(slot);
return handler.SendHeldItemChange(slot); return handler.SendHeldItemChange(slot);
} }
else else
@ -1558,6 +1566,61 @@ namespace MinecraftClient
ConsoleIO.WriteLogLine("You are dead. Type /respawn to respawn."); ConsoleIO.WriteLogLine("You are dead. Type /respawn to respawn.");
} }
} }
if (Settings.AutoEat)
{
if (food <= HungerThreshold || (food < 20 && health < 20))
{
Eating = true;
FindFoodAndEat();
}
// keep eating until full
if (food < 20 && Eating)
{
FindFoodAndEat();
}
if (food >= 20 && Eating)
{
Eating = false;
ChangeSlot(LastSlot);
}
}
}
public void OnHeldItemChange(byte slot)
{
CurrentSlot = slot;
}
/// <summary>
/// Try to find food in the hotbar and eat it
/// </summary>
/// <returns>True if found</returns>
public bool FindFoodAndEat()
{
Container inventory = inventories[0];
bool found = false;
if (inventory.Items.ContainsKey(CurrentSlot + 36) && inventory.Items[CurrentSlot + 36].IsFood())
{
// no need to change slot
found = true;
}
else
{
LastSlot = CurrentSlot;
for (int i = 36; i <= 44; i++)
{
if (!inventory.Items.ContainsKey(i)) continue;
if (inventory.Items[i].IsFood())
{
int slot = i - 36;
ChangeSlot((short)slot);
found = true;
break;
}
}
}
if (found) UseItemOnHand();
return found;
} }
} }
} }

View file

@ -42,6 +42,7 @@ namespace MinecraftClient.Protocol.Handlers
EntityTeleport, EntityTeleport,
EntityStatus, EntityStatus,
UpdateHealth, UpdateHealth,
HeldItemChange,
UnknownPacket UnknownPacket
} }
} }

View file

@ -730,6 +730,10 @@ namespace MinecraftClient.Protocol.Handlers
dataTypes.ReadNextFloat(packetData); dataTypes.ReadNextFloat(packetData);
handler.OnUpdateHealth(health, food); handler.OnUpdateHealth(health, food);
break; break;
case PacketIncomingType.HeldItemChange:
byte slot = dataTypes.ReadNextByte(packetData);
handler.OnHeldItemChange(slot);
break;
default: default:
return false; //Ignored packet return false; //Ignored packet
} }

View file

@ -277,7 +277,8 @@ namespace MinecraftClient.Protocol.Handlers
case 0x59: return PacketIncomingType.EntityProperties; case 0x59: return PacketIncomingType.EntityProperties;
case 0x57: return PacketIncomingType.EntityTeleport; case 0x57: return PacketIncomingType.EntityTeleport;
case 0x1C: return PacketIncomingType.EntityStatus; case 0x1C: return PacketIncomingType.EntityStatus;
case 0x49: return PacketIncomingType.UpdateHealth; // TODO: Add backwards support for this packet case 0x49: return PacketIncomingType.UpdateHealth; // TODO: Add backwards support
case 0x40: return PacketIncomingType.HeldItemChange; // TODO: Add backwards support
default: return PacketIncomingType.UnknownPacket; default: return PacketIncomingType.UnknownPacket;
} }
} }

View file

@ -212,8 +212,20 @@ namespace MinecraftClient.Protocol
/// <param name="item">Item (may be null for empty slot)</param> /// <param name="item">Item (may be null for empty slot)</param>
void OnSetSlot(byte inventoryID, short slotID, Item item); void OnSetSlot(byte inventoryID, short slotID, Item item);
/// <summary>
/// Called when player health or hunger changed.
/// </summary>
/// <param name="health"></param>
/// <param name="food"></param>
void OnUpdateHealth(float health, int food); void OnUpdateHealth(float health, int food);
/// <summary>
/// Called when client need to change slot.
/// </summary>
/// <remarks>Used for setting player slot after joining game</remarks>
/// <param name="slot"></param>
void OnHeldItemChange(byte slot);
/// <summary> /// <summary>
/// Called when the Player entity ID has been received from the server /// Called when the Player entity ID has been received from the server
/// </summary> /// </summary>

View file

@ -97,6 +97,7 @@ namespace MinecraftClient
public static bool ResolveSrvRecordsShortTimeout = true; public static bool ResolveSrvRecordsShortTimeout = true;
public static bool EntityHandling = false; public static bool EntityHandling = false;
public static bool AutoRespawn = false; public static bool AutoRespawn = false;
public static bool AutoEat = false;
//AntiAFK Settings //AntiAFK Settings
public static bool AntiAFK_Enabled = false; public static bool AntiAFK_Enabled = false;
@ -244,6 +245,7 @@ namespace MinecraftClient
case "botmessagedelay": botMessageDelay = TimeSpan.FromSeconds(str2int(argValue)); break; case "botmessagedelay": botMessageDelay = TimeSpan.FromSeconds(str2int(argValue)); break;
case "debugmessages": DebugMessages = str2bool(argValue); break; case "debugmessages": DebugMessages = str2bool(argValue); break;
case "autorespawn": AutoRespawn = str2bool(argValue); break; case "autorespawn": AutoRespawn = str2bool(argValue); break;
case "autoeat": AutoEat = str2bool(argValue); break;
case "botowners": case "botowners":
Bots_Owners.Clear(); Bots_Owners.Clear();
@ -589,6 +591,7 @@ namespace MinecraftClient
+ "scriptcache=true # Cache compiled scripts for faster load on low-end devices\r\n" + "scriptcache=true # Cache compiled scripts for faster load on low-end devices\r\n"
+ "timestamps=false # Prepend timestamps to chat messages\r\n" + "timestamps=false # Prepend timestamps to chat messages\r\n"
+ "autorespawn=false # Toggle auto respawn if client player was dead (make sure your spawn point is safe)\r\n" + "autorespawn=false # Toggle auto respawn if client player was dead (make sure your spawn point is safe)\r\n"
+ "autoeat=false # Toggle auto eat when player is hungry\r\n"
+ "\r\n" + "\r\n"
+ "[AppVars]\r\n" + "[AppVars]\r\n"
+ "# yourvar=yourvalue\r\n" + "# yourvar=yourvalue\r\n"