Inventory handling

This commit is contained in:
ReinforceZwei 2020-03-26 15:01:42 +08:00 committed by ORelio
parent c870f080f2
commit bc449b404e
20 changed files with 538 additions and 44 deletions

View file

@ -5,6 +5,7 @@ using System.Text;
using System.IO;
using System.Threading;
using System.Text.RegularExpressions;
using MinecraftClient.Inventory;
namespace MinecraftClient
{
@ -620,6 +621,11 @@ namespace MinecraftClient
return Handler.GetEntityHandlingEnabled();
}
public bool GetInventoryEnabled()
{
return Handler.GetInventoryEnabled();
}
/// <summary>
/// Get the current Minecraft World
/// </summary>
@ -806,5 +812,11 @@ namespace MinecraftClient
{
return Handler.UseItemOnHand();
}
protected Container GetPlayerInventory()
{
Container container = Handler.GetPlayerInventory();
return new Container(container.ID,container.Type,container.Title,container.Items);
}
}
}

View file

@ -14,6 +14,7 @@ namespace MinecraftClient.ChatBots
private Double fishingHookThreshold = 0.2;
private Location LastPos = new Location();
private DateTime CaughtTime = DateTime.Now;
private bool inventoryEnabled;
public override void Initialize()
{
@ -23,11 +24,12 @@ namespace MinecraftClient.ChatBots
ConsoleIO.WriteLine("[AutoFishing] This bot will be unloaded.");
UnloadBot();
}
inventoryEnabled = GetInventoryEnabled();
}
public override void OnEntitySpawn(Entity entity)
{
if (entity.Type == 102)
if (entity.TypeID == 102)
{
ConsoleIO.WriteLine("Threw a fishing rod");
fishingRod.Add(entity.ID, entity);
@ -69,15 +71,36 @@ namespace MinecraftClient.ChatBots
ConsoleIO.WriteLine("Caught a fish!");
// retract fishing rod
UseItemOnHand();
if (inventoryEnabled)
{
if (!hasFishingRod())
{
ConsoleIO.WriteLine("No Fishing Rod on hand. Maybe broken?");
return;
}
}
// non-blocking delay
Task.Factory.StartNew(delegate
{
// retract fishing rod need some time
Thread.Sleep(500);
Thread.Sleep(800);
// throw again
// TODO: to check if hand have fishing rod
UseItemOnHand();
});
}
public bool hasFishingRod()
{
if (!inventoryEnabled) return false;
int start = 36;
int end = 44;
Inventory.Container container = GetPlayerInventory();
foreach(KeyValuePair<int,Inventory.Item> a in container.Items)
{
if (a.Key < start || a.Key > end) continue;
if (a.Value.ID == 622) return true;
}
return false;
}
}
}

View file

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.Commands
{
class ChangeSlot : Command
{
public override string CMDName { get { return "changeslot"; } }
public override string CMDDesc { get { return "changeslot <1-9>: Change hotbar"; } }
public override string Run(McTcpClient handler, string command)
{
if (!handler.GetInventoryEnabled()) return "Please enable InventoryHandling in the config file first.";
if (hasArg(command))
{
short slot;
try
{
slot = Convert.ToInt16(getArg(command));
}
catch (FormatException)
{
return "Could not change slot: Not a Number";
}
if (slot >= 1 && slot <= 9)
{
if (handler.ChangeSlot(slot-=1))
{
return "Changed to slot " + (slot+=1);
}
else
{
return "Could not change slot";
}
}
}
return CMDDesc;
}
}
}

View file

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MinecraftClient.Inventory;
namespace MinecraftClient.Commands
{
class GetInventory : Command
{
public override string CMDName { get { return "getinventory"; } }
public override string CMDDesc { get { return "getinventory: Show your inventory."; } }
public override string Run(McTcpClient handler, string command)
{
Dictionary<int,Item> items = handler.GetPlayerInventory().Items;
foreach(KeyValuePair<int,Item> a in items)
{
ConsoleIO.WriteLine("Slot: "+a.Key+" ItemID: " + a.Value.ID + ", Count: " + a.Value.Count);
}
return "";
}
}
}

View file

@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.Inventory
{
public class Container
{
public int ID;
public ContainerType Type;
public string Title;
public Dictionary<int, Item> Items;
public Container() { }
public Container(int id, ContainerType type, string title)
{
ID = id;
Type = type;
Title = title;
}
public Container(int id, ContainerType type, string title,Dictionary<int,Item> items)
{
ID = id;
Type = type;
Title = title;
Items = items;
}
public Container(int id, Protocol.InventoryType type, string title)
{
ID = id;
Title = title;
}
public Container(int id, int typeID, string title)
{
ID = id;
Type = GetContainerType(typeID);
Title = title;
}
// for player inventory because they dont have ID and title
public Container(ContainerType type)
{
Type = type;
}
public Container(ContainerType type, Dictionary<int, Item> items)
{
Type = type;
Items = items;
}
public static ContainerType GetContainerType(int typeID)
{
// https://wiki.vg/Inventory didn't state the inventory ID, assume that list start with 0
switch (typeID)
{
case 0: return ContainerType.Generic_9x1;
case 1: return ContainerType.Generic_9x2;
case 2: return ContainerType.Generic_9x3;
case 3: return ContainerType.Generic_9x4;
case 4: return ContainerType.Generic_9x5;
case 5: return ContainerType.Generic_9x6;
case 6: return ContainerType.Generic_3x3;
case 7: return ContainerType.Anvil;
case 8: return ContainerType.Beacon;
case 9: return ContainerType.BlastFurnace;
case 10: return ContainerType.BrewingStand;
case 11: return ContainerType.Crafting;
case 12: return ContainerType.Enchantment;
case 13: return ContainerType.Furnace;
case 14: return ContainerType.Grindstone;
case 15: return ContainerType.Hopper;
case 16: return ContainerType.Lectern;
case 17: return ContainerType.Loom;
case 18: return ContainerType.Merchant;
case 19: return ContainerType.ShulkerBox;
case 20: return ContainerType.Smoker;
case 21: return ContainerType.Cartography;
case 22: return ContainerType.Stonecutter;
default: return ContainerType.Unknown;
}
}
}
}

View file

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.Inventory
{
// For MC 1.14 after ONLY
public enum ContainerType
{
Generic_9x1,
Generic_9x2,
Generic_9x3, // chest, ender chest, minecart with chest, barrel
Generic_9x4,
Generic_9x5,
Generic_9x6,
Generic_3x3,
Anvil,
Beacon,
BlastFurnace,
BrewingStand,
Crafting,
Enchantment,
Furnace,
Grindstone,
Hopper,
Lectern,
Loom,
Merchant,
ShulkerBox,
Smoker,
Cartography,
Stonecutter,
// not in the list
PlayerInventory,
Unknown
}
}

View file

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.Inventory
{
public class Item
{
public int ID;
public int Count;
public int SlotID = -1; // which slot is this item at, -1 = not specified
public Dictionary<string, object> NBT;
public Item(int ID,int Count,int SlotID, Dictionary<string,object> NBT)
{
this.ID = ID;
this.Count = Count;
this.SlotID = SlotID;
this.NBT = NBT;
}
public Item(int ID, int Count, int SlotID)
{
this.ID = ID;
this.Count = Count;
this.SlotID = SlotID;
}
public Item(int ID, int Count)
{
this.ID = ID;
this.Count = Count;
}
}
}

View file

@ -8,7 +8,8 @@ namespace MinecraftClient.Mapping
public class Entity
{
public int ID;
public int Type;
public int TypeID;
public EntityType Type;
public string Name;
public Location Location;
public Entity(int ID, Location location)
@ -16,17 +17,31 @@ namespace MinecraftClient.Mapping
this.ID = ID;
this.Location = location;
}
public Entity(int ID, int Type, Location location)
public Entity(int ID, int TypeID, Location location)
{
this.ID = ID;
this.Type = Type;
this.Name = GetMobName(Type);
this.TypeID = TypeID;
this.Name = GetMobName(TypeID);
this.Location = location;
}
public Entity(int ID, int Type, string Name, Location location)
public Entity(int ID, int TypeID, EntityType type, Location location)
{
this.ID = ID;
this.Type = Type;
this.TypeID = TypeID;
this.Type = type;
this.Name = GetMobName(TypeID);
this.Location = location;
}
public Entity(int ID, EntityType type, Location location)
{
this.ID = ID;
this.Type = type;
this.Location = location;
}
public Entity(int ID, int TypeID, string Name, Location location)
{
this.ID = ID;
this.TypeID = TypeID;
this.Name = Name;
this.Location = location;
}
@ -80,7 +95,7 @@ namespace MinecraftClient.Mapping
}
public string GetMobName()
{
return GetMobName(Type);
return GetMobName(TypeID);
}
}
}

View file

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.Mapping
{
public enum EntityType
{
MobAndAnimal,
Player,
NonLivingThings,
}
}

View file

@ -10,6 +10,7 @@ using MinecraftClient.Protocol;
using MinecraftClient.Proxy;
using MinecraftClient.Protocol.Handlers.Forge;
using MinecraftClient.Mapping;
using MinecraftClient.Inventory;
namespace MinecraftClient
{
@ -26,7 +27,7 @@ namespace MinecraftClient
private readonly List<ChatBot> bots = new List<ChatBot>();
private static readonly List<ChatBot> botsOnHold = new List<ChatBot>();
private static List<Inventory> inventories = new List<Inventory>();
private static List<Container> inventories = new List<Container>();
private readonly Dictionary<string, List<ChatBot>> registeredBotPluginChannels = new Dictionary<string, List<ChatBot>>();
private readonly List<string> registeredServerPluginChannels = new List<String>();
@ -52,14 +53,14 @@ namespace MinecraftClient
private string username;
private string uuid;
private string sessionid;
private Inventory playerInventory;
private Container playerInventory = new Container(ContainerType.PlayerInventory);
private DateTime lastKeepAlive;
private object lastKeepAliveLock = new object();
private int playerEntityID;
// not really understand the Inventory Class
// so I use a Dict instead for player inventory
private Dictionary<int, Item> playerItems;
//private Dictionary<int, Inventory.Item> playerItems;
// Entity handling
private Dictionary<int, Entity> entities = new Dictionary<int, Entity>();
@ -567,9 +568,9 @@ namespace MinecraftClient
/// Get client player's inventory items
/// </summary>
/// <returns> Item Dictionary indexed by Slot ID (Check wiki.vg for slot ID)</returns>
public Dictionary<int, Item> GetPlayerInventory()
public Container GetPlayerInventory()
{
return playerItems;
return playerInventory;
}
// TODO: add command for displaying player inventory
@ -737,13 +738,14 @@ namespace MinecraftClient
/// When an inventory is opened
/// </summary>
/// <param name="inventory">Location to reach</param>
public void OnInventoryOpen(Inventory inventory)
public void OnInventoryOpen(Container inventory)
{
//TODO: Handle Inventory
if (!inventories.Contains(inventory))
{
inventories.Add(inventory);
}
ConsoleIO.WriteLine(inventory.Type.ToString());
}
/// <summary>
@ -754,9 +756,9 @@ namespace MinecraftClient
{
for (int i = 0; i < inventories.Count; i++)
{
Inventory inventory = inventories[i];
Container inventory = inventories[i];
if (inventory == null) continue;
if (inventory.id == inventoryID)
if (inventory.Type == Container.GetContainerType(inventoryID))
{
inventories.Remove(inventory);
return;
@ -769,11 +771,27 @@ namespace MinecraftClient
/// </summary>
/// <param name="type"></param>
/// <param name="itemList"></param>
public void OnWindowItems(int type, Dictionary<int, Item> itemList)
public void OnWindowItems(int type, Dictionary<int, Inventory.Item> itemList)
{
// 0 is player inventory
if (type == 0)
playerItems = itemList;
playerInventory.Items = itemList;
}
public void OnSetSlot(byte WindowID, short SlotID, bool Present)
{
if(WindowID == 0)
{
if (playerInventory.Items.ContainsKey(SlotID))
playerInventory.Items.Remove(SlotID);
}
}
public void OnSetSlot(byte WindowID, short SlotID, bool Present, int ItemID, byte Count, Dictionary<string, object> NBT)
{
if (WindowID == 0)
{
playerInventory.Items[SlotID] = new Inventory.Item(ItemID, Count, SlotID, NBT);
}
}
/// <summary>
@ -1081,12 +1099,12 @@ namespace MinecraftClient
/// Called when a non-living entity spawned (fishing hook, minecart, etc)
/// </summary>
/// <param name="EntityID"></param>
/// <param name="EntityType"></param>
/// <param name="TypeID"></param>
/// <param name="UUID"></param>
/// <param name="location"></param>
public void OnSpawnEntity(int EntityID, int EntityType, Guid UUID, Location location)
public void OnSpawnEntity(int EntityID, int TypeID, Guid UUID, Location location)
{
Entity entity = new Entity(EntityID, EntityType, location);
Entity entity = new Entity(EntityID, TypeID, EntityType.NonLivingThings, location);
entities.Add(EntityID, entity);
foreach (ChatBot bot in bots.ToArray())
bot.OnEntitySpawn(entity);
@ -1096,12 +1114,29 @@ namespace MinecraftClient
/// Called when an Entity was created/spawned.
/// </summary>
/// <param name="EntityID"></param>
/// <param name="EntityType"></param>
/// <param name="TypeID"></param>
/// <param name="UUID"></param>
/// <param name="location"></param>
public void OnSpawnLivingEntity(int EntityID, int EntityType, Guid UUID, Location location)
/// <remarks>Cannot determine is a Mob or a Cuty Animal</remarks>
public void OnSpawnLivingEntity(int EntityID, int TypeID, Guid UUID, Location location)
{
Entity entity = new Entity(EntityID, EntityType, location);
Entity entity = new Entity(EntityID, TypeID, EntityType.MobAndAnimal, location);
entities.Add(EntityID, entity);
foreach (ChatBot bot in bots.ToArray())
bot.OnEntitySpawn(entity);
}
/// <summary>
/// Called when a player was spawned/in the render distance
/// </summary>
/// <param name="EntityID"></param>
/// <param name="UUID"></param>
/// <param name="location"></param>
/// <param name="Yaw"></param>
/// <param name="Pitch"></param>
public void OnSpawnPlayer(int EntityID, Guid UUID, Location location, byte Yaw, byte Pitch)
{
Entity entity = new Entity(EntityID, EntityType.Player, location);
entities.Add(EntityID, entity);
foreach (ChatBot bot in bots.ToArray())
bot.OnEntitySpawn(entity);
@ -1118,7 +1153,7 @@ namespace MinecraftClient
if (entities.ContainsKey(a))
{
foreach (ChatBot bot in bots.ToArray())
bot.OnEntityDespawn(new Entity(entities[a].ID, entities[a].Type, entities[a].Location));
bot.OnEntityDespawn(new Entity(entities[a].ID, entities[a].TypeID, entities[a].Type, entities[a].Location));
entities.Remove(a);
}
}
@ -1143,7 +1178,7 @@ namespace MinecraftClient
entities[EntityID].Location = L;
foreach (ChatBot bot in bots.ToArray())
bot.OnEntityMove(new Entity(entities[EntityID].ID, entities[EntityID].Type, entities[EntityID].Location));
bot.OnEntityMove(new Entity(entities[EntityID].ID, entities[EntityID].TypeID, entities[EntityID].Type, entities[EntityID].Location));
}
}
@ -1163,7 +1198,7 @@ namespace MinecraftClient
entities[EntityID].Location = location;
foreach (ChatBot bot in bots.ToArray())
bot.OnEntityMove(new Entity(entities[EntityID].ID, entities[EntityID].Type, entities[EntityID].Location));
bot.OnEntityMove(new Entity(entities[EntityID].ID, entities[EntityID].TypeID, entities[EntityID].Type, entities[EntityID].Location));
}
}
@ -1236,5 +1271,23 @@ namespace MinecraftClient
{
return handler.SendInteractEntityPacket(EntityID, type);
}
// not work :(
public bool PlaceBlock(Location location)
{
ConsoleIO.WriteLine(location.ToString());
return handler.SendPlayerBlockPlacement(0, location, 1, 0.5f, 0.5f, 0.5f, false);
}
public bool ChangeSlot(short slot)
{
if (slot >= 0 && slot <= 8)
{
return handler.SendHeldItemChange(slot);
}
else
{
return false;
}
}
}
}

View file

@ -88,8 +88,10 @@
<Compile Include="ChatBots\TestBot.cs" />
<Compile Include="ChatBot.cs" />
<Compile Include="Command.cs" />
<Compile Include="Commands\ChangeSlot.cs" />
<Compile Include="Commands\Connect.cs" />
<Compile Include="Commands\Debug.cs" />
<Compile Include="Commands\GetInventory.cs" />
<Compile Include="Commands\Look.cs" />
<Compile Include="Commands\Move.cs" />
<Compile Include="Commands\Exit.cs" />
@ -100,6 +102,9 @@
<Compile Include="Commands\Send.cs" />
<Compile Include="Commands\Set.cs" />
<Compile Include="Commands\UseItem.cs" />
<Compile Include="Inventory\Container.cs" />
<Compile Include="Inventory\ContainerType.cs" />
<Compile Include="Inventory\Item.cs" />
<Compile Include="Mapping\BlockPalettes\Palette112.cs" />
<Compile Include="Mapping\BlockPalettes\Palette113.cs" />
<Compile Include="Mapping\BlockPalettes\Palette114.cs" />
@ -107,6 +112,7 @@
<Compile Include="Mapping\BlockPalettes\PaletteGenerator.cs" />
<Compile Include="Mapping\BlockPalettes\PaletteMapping.cs" />
<Compile Include="Mapping\Entity.cs" />
<Compile Include="Mapping\EntityType.cs" />
<Compile Include="Mapping\MaterialExtensions.cs" />
<Compile Include="Protocol\Handlers\DataTypes.cs" />
<Compile Include="Protocol\Handlers\PacketIncomingType.cs" />
@ -286,6 +292,7 @@
<Content Include="Protocol\Dns\Records\totla.txt" />
<Content Include="Resources\AppIcon.ico" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<StartArguments>TestBot - localhost</StartArguments>
<StartArguments>test - 192.168.1.29</StartArguments>
</PropertyGroup>
<PropertyGroup>
<PublishUrlHistory>publish\</PublishUrlHistory>

View file

@ -10,9 +10,6 @@ namespace MinecraftClient.Protocol.Handlers
/// </summary>
enum PacketIncomingType
{
// modified by reinforce
SpawnEntity,
SpawnLivingEntity,
KeepAlive,
JoinGame,
ChatMessage,
@ -33,6 +30,9 @@ namespace MinecraftClient.Protocol.Handlers
OpenWindow,
WindowItems,
SetSlot,
SpawnEntity,
SpawnLivingEntity,
SpawnPlayer,
DestroyEntities,
SetCooldown,
EntityPosition,

View file

@ -22,6 +22,7 @@ namespace MinecraftClient.Protocol.Handlers
TeleportConfirm,
HeldItemChange,
InteractEntity,
UseItem
UseItem,
PlayerBlockPlacement
}
}

View file

@ -658,6 +658,14 @@ namespace MinecraftClient.Protocol.Handlers
{
return false;
}
public bool SendPlayerBlockPlacement(int hand, Location location, int face, float CursorX, float CursorY, float CursorZ, bool insideBlock)
{
return false;
}
public bool SendHeldItemChange(short slot)
{
return false;
}
/// <summary>
/// Send a plugin channel packet to the server.

View file

@ -497,7 +497,18 @@ namespace MinecraftClient.Protocol.Handlers
InventoryType inventoryType = (InventoryType)Enum.Parse(typeof(InventoryType), type);
string title = dataTypes.ReadNextString(packetData);
byte slots = dataTypes.ReadNextByte(packetData);
Inventory inventory = new Inventory(windowID, inventoryType, title, slots);
// TODO:
MinecraftClient.Inventory.Container inventory = new MinecraftClient.Inventory.Container(windowID, inventoryType, title);
handler.OnInventoryOpen(inventory);
}
else
{
int WindowID = dataTypes.ReadNextVarInt(packetData);
int WindowType = dataTypes.ReadNextVarInt(packetData);
string title = dataTypes.ReadNextString(packetData);
MinecraftClient.Inventory.Container inventory = new MinecraftClient.Inventory.Container(WindowID, WindowType, title);
handler.OnInventoryOpen(inventory);
}
@ -536,7 +547,7 @@ namespace MinecraftClient.Protocol.Handlers
*/
byte id = dataTypes.ReadNextByte(packetData);
short elements = dataTypes.ReadNextShort(packetData);
Dictionary<int, Item> itemsList = new Dictionary<int, Item>(); // index is SlotID
Dictionary<int, MinecraftClient.Inventory.Item> itemsList = new Dictionary<int, MinecraftClient.Inventory.Item>(); // index is SlotID
for(int i = 0; i < elements; i++)
{
bool haveItem = dataTypes.ReadNextBool(packetData);
@ -546,13 +557,32 @@ namespace MinecraftClient.Protocol.Handlers
byte itemCount = dataTypes.ReadNextByte(packetData);
dataTypes.ReadNextNbt(packetData);
Item item = new Item(itemID, itemCount);
MinecraftClient.Inventory.Item item = new MinecraftClient.Inventory.Item(itemID, itemCount);
itemsList.Add(i, item);
}
}
handler.OnWindowItems(id, itemsList);
}
break;
case PacketIncomingType.SetSlot:
if(handler.GetInventoryEnabled())
{
byte WindowID = dataTypes.ReadNextByte(packetData);
short SlotID = dataTypes.ReadNextShort(packetData);
bool Present = dataTypes.ReadNextBool(packetData);
if (Present)
{
int ItemID = dataTypes.ReadNextVarInt(packetData);
byte Count = dataTypes.ReadNextByte(packetData);
Dictionary<string, object> NBT = dataTypes.ReadNextNbt(packetData);
handler.OnSetSlot(WindowID, SlotID, Present, ItemID, Count, NBT);
}
else
{
handler.OnSetSlot(WindowID, SlotID, Present);
}
}
break;
case PacketIncomingType.ResourcePackSend:
string url = dataTypes.ReadNextString(packetData);
string hash = dataTypes.ReadNextString(packetData);
@ -606,6 +636,22 @@ namespace MinecraftClient.Protocol.Handlers
handler.OnSpawnLivingEntity(EntityID, EntityType, EntityUUID, EntityLocation);
}
break;
case PacketIncomingType.SpawnPlayer:
if (handler.GetEntityHandlingEnabled())
{
int EntityID = dataTypes.ReadNextVarInt(packetData);
Guid UUID = dataTypes.ReadNextUUID(packetData);
double X = dataTypes.ReadNextDouble(packetData);
double Y = dataTypes.ReadNextDouble(packetData);
double Z = dataTypes.ReadNextDouble(packetData);
byte Yaw = dataTypes.ReadNextByte(packetData);
byte Pitch = dataTypes.ReadNextByte(packetData);
Location EntityLocation = new Location(X, Y, Z);
handler.OnSpawnPlayer(EntityID, UUID, EntityLocation, Yaw, Pitch);
}
break;
case PacketIncomingType.DestroyEntities:
if (handler.GetEntityHandlingEnabled())
{
@ -1186,7 +1232,6 @@ namespace MinecraftClient.Protocol.Handlers
return false;
}
// reinforce
/// <summary>
/// Send an Interact Entity Packet to server
/// </summary>
@ -1207,10 +1252,24 @@ namespace MinecraftClient.Protocol.Handlers
catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { return false; }
}
// TODO: Interact at block location (e.g. chest)
// TODO: Interact at block location (e.g. chest minecart)
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand)
{
return false;
try
{
List<byte> fields = new List<byte>();
fields.AddRange(dataTypes.GetVarInt(EntityID));
fields.AddRange(dataTypes.GetVarInt(type));
fields.AddRange(dataTypes.GetFloat(X));
fields.AddRange(dataTypes.GetFloat(Y));
fields.AddRange(dataTypes.GetFloat(Z));
fields.AddRange(dataTypes.GetVarInt(hand));
SendPacket(PacketOutgoingType.InteractEntity, fields);
return true;
}
catch (SocketException) { return false; }
catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { return false; }
}
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z)
{
@ -1230,5 +1289,42 @@ namespace MinecraftClient.Protocol.Handlers
catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { return false; }
}
public bool SendPlayerBlockPlacement(int hand, Location location, int face, float CursorX, float CursorY, float CursorZ, bool insideBlock)
{
try
{
List<byte> packet = new List<byte>();
packet.AddRange(dataTypes.GetVarInt(hand));
packet.AddRange(dataTypes.GetLocation(location));
packet.AddRange(dataTypes.GetVarInt(face));
packet.AddRange(dataTypes.GetFloat(CursorX));
packet.AddRange(dataTypes.GetFloat(CursorY));
packet.AddRange(dataTypes.GetFloat(CursorZ));
packet.Add(Convert.ToByte(insideBlock ? 1 : 0));
SendPacket(PacketOutgoingType.PlayerBlockPlacement, packet);
return true;
}
catch (SocketException) { return false; }
catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { return false; }
}
public bool SendHeldItemChange(short slot)
{
try
{
List<byte> packet = new List<byte>();
// short to byte (?
byte[] b = BitConverter.GetBytes(slot);
Array.Reverse(b);
packet.AddRange(b);
SendPacket(PacketOutgoingType.HeldItemChange, packet);
return true;
}
catch (SocketException) { return false; }
catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { return false; }
}
}
}

View file

@ -48,6 +48,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling
case 0x0E: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x0F: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x13: return PacketIncomingType.DestroyEntities;
case 0x15: return PacketIncomingType.EntityPosition;
case 0x17: return PacketIncomingType.EntityPositionAndRotation;
@ -86,6 +87,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x30: return PacketIncomingType.DestroyEntities;
case 0x25: return PacketIncomingType.EntityPosition;
case 0x26: return PacketIncomingType.EntityPositionAndRotation;
@ -122,6 +124,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x31: return PacketIncomingType.DestroyEntities;
case 0x26: return PacketIncomingType.EntityPosition;
case 0x27: return PacketIncomingType.EntityPositionAndRotation;
@ -158,6 +161,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x32: return PacketIncomingType.DestroyEntities;
case 0x26: return PacketIncomingType.EntityPosition;
case 0x27: return PacketIncomingType.EntityPositionAndRotation;
@ -194,6 +198,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x35: return PacketIncomingType.DestroyEntities;
case 0x28: return PacketIncomingType.EntityPosition;
case 0x29: return PacketIncomingType.EntityPositionAndRotation;
@ -229,6 +234,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x37: return PacketIncomingType.DestroyEntities;
case 0x28: return PacketIncomingType.EntityPosition;
case 0x29: return PacketIncomingType.EntityPositionAndRotation;
@ -264,6 +270,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x38: return PacketIncomingType.DestroyEntities;
case 0x29: return PacketIncomingType.EntityPosition;
case 0x2A: return PacketIncomingType.EntityPositionAndRotation;
@ -296,6 +303,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.TabComplete: return 0x14;
case PacketOutgoingType.PlayerPosition: return 0x04;
case PacketOutgoingType.PlayerPositionAndLook: return 0x06;
case PacketOutgoingType.HeldItemChange: return 0x17;
case PacketOutgoingType.InteractEntity: return 0x02;
case PacketOutgoingType.TeleportConfirm: throw new InvalidOperationException("Teleport confirm is not supported in protocol " + protocol);
}
@ -314,6 +322,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.PlayerPosition: return 0x0C;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0D;
case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x17;
case PacketOutgoingType.InteractEntity: return 0x0A;
}
}
@ -331,6 +340,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.PlayerPosition: return 0x0E;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0F;
case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x1A;
case PacketOutgoingType.InteractEntity: return 0x0B;
}
}
@ -348,6 +358,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.PlayerPosition: return 0x0D;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0E;
case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x1F;
case PacketOutgoingType.InteractEntity: return 0x0A;
}
}
@ -365,6 +376,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.PlayerPosition: return 0x10;
case PacketOutgoingType.PlayerPositionAndLook: return 0x11;
case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x21;
case PacketOutgoingType.InteractEntity: return 0x0D;
}
}
@ -385,6 +397,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.HeldItemChange: return 0x23;
case PacketOutgoingType.InteractEntity: return 0x0E;
case PacketOutgoingType.UseItem: return 0x2D;
case PacketOutgoingType.PlayerBlockPlacement: return 0x2C;
}
}

View file

@ -85,10 +85,14 @@ namespace MinecraftClient.Protocol
/// <returns>True if message was successfully sent</returns>
bool SendPluginChannelPacket(string channel, byte[] data);
bool SendHeldItemChange(short slot);
bool SendInteractEntityPacket(int EntityID, int type);
bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand);
bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z);
bool SendUseItemPacket(int hand);
bool SendPlayerBlockPlacement(int hand, Location location, int face, float CursorX, float CursorY, float CursorZ, bool insideBlock);
}
}

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using MinecraftClient.Mapping;
using MinecraftClient.Inventory;
namespace MinecraftClient.Protocol
{
@ -52,7 +53,7 @@ namespace MinecraftClient.Protocol
/// <summary>
/// Called when an inventory is opened
/// </summary>
void OnInventoryOpen(Inventory inventory);
void OnInventoryOpen(Container inventory);
/// <summary>
/// Called when an inventory is closed
@ -131,6 +132,8 @@ namespace MinecraftClient.Protocol
void OnSpawnLivingEntity(int EntityID, int EntityType, Guid UUID, Location location);
void OnSpawnPlayer(int EntityID, Guid UUID, Location location, byte Yaw, byte Pitch);
void OnDestroyEntities(int[] EntityID);
void OnEntityPosition(int EntityID, Double Dx, Double Dy, Double Dz,bool onGround);
@ -141,7 +144,10 @@ namespace MinecraftClient.Protocol
void OnEntityTeleport(int EntityID, Double X, Double Y, Double Z, bool onGround);
void OnWindowItems(int type, Dictionary<int, Item> itemList);
void OnWindowItems(int type, Dictionary<int, MinecraftClient.Inventory.Item> itemList);
void OnSetSlot(byte WindowID, short SlotID, bool Present);
void OnSetSlot(byte WindowID, short SlotID, bool Present, int ItemID, byte Count, Dictionary<string, object> NBT);
void SetPlayerEntityID(int EntityID);
}

View file

@ -230,6 +230,27 @@ The AutoRespond bot allows you to automatically react on specific chat messages
You can use either a string to detect in chat messages, or an advanced regular expression.
For more information about how to define match rules, please refer to sample-matches.ini
Using the Auto Attack
------
The AutoAttack bot allows you to automatically attack mobs around you (precisely within radius of 4).
To use this bot, you will need to enable **Entity Handling** in the config file first.
Using the Auto Fishing
------
The AutoFish bot can automatically fish for you.
To use this bot, you will need to enable **Entity Handling** in the config file first.
If you want to get an alert message when the fishing rod was broken, enable **Inventory Handling** in the config file.
A fishing rod with **Mending enchantment** is strongly recommended.
Steps for using this bot:
1. Hold a fishing rod and aim towards the sea before login with MCC
2. Make sure AutoFish is enabled in config file
3. Login with MCC
4. Do /useitem and you should see "threw a fishing rod"
5. To stop fishing, do /useitem again right after the message "threw a fishing rod"
Disclaimer
------