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.IO;
using System.Threading; using System.Threading;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using MinecraftClient.Inventory;
namespace MinecraftClient namespace MinecraftClient
{ {
@ -620,6 +621,11 @@ namespace MinecraftClient
return Handler.GetEntityHandlingEnabled(); return Handler.GetEntityHandlingEnabled();
} }
public bool GetInventoryEnabled()
{
return Handler.GetInventoryEnabled();
}
/// <summary> /// <summary>
/// Get the current Minecraft World /// Get the current Minecraft World
/// </summary> /// </summary>
@ -806,5 +812,11 @@ namespace MinecraftClient
{ {
return Handler.UseItemOnHand(); 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 Double fishingHookThreshold = 0.2;
private Location LastPos = new Location(); private Location LastPos = new Location();
private DateTime CaughtTime = DateTime.Now; private DateTime CaughtTime = DateTime.Now;
private bool inventoryEnabled;
public override void Initialize() public override void Initialize()
{ {
@ -23,11 +24,12 @@ namespace MinecraftClient.ChatBots
ConsoleIO.WriteLine("[AutoFishing] This bot will be unloaded."); ConsoleIO.WriteLine("[AutoFishing] This bot will be unloaded.");
UnloadBot(); UnloadBot();
} }
inventoryEnabled = GetInventoryEnabled();
} }
public override void OnEntitySpawn(Entity entity) public override void OnEntitySpawn(Entity entity)
{ {
if (entity.Type == 102) if (entity.TypeID == 102)
{ {
ConsoleIO.WriteLine("Threw a fishing rod"); ConsoleIO.WriteLine("Threw a fishing rod");
fishingRod.Add(entity.ID, entity); fishingRod.Add(entity.ID, entity);
@ -69,15 +71,36 @@ namespace MinecraftClient.ChatBots
ConsoleIO.WriteLine("Caught a fish!"); ConsoleIO.WriteLine("Caught a fish!");
// retract fishing rod // retract fishing rod
UseItemOnHand(); UseItemOnHand();
if (inventoryEnabled)
{
if (!hasFishingRod())
{
ConsoleIO.WriteLine("No Fishing Rod on hand. Maybe broken?");
return;
}
}
// non-blocking delay // non-blocking delay
Task.Factory.StartNew(delegate Task.Factory.StartNew(delegate
{ {
// retract fishing rod need some time // retract fishing rod need some time
Thread.Sleep(500); Thread.Sleep(800);
// throw again // throw again
// TODO: to check if hand have fishing rod
UseItemOnHand(); 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 class Entity
{ {
public int ID; public int ID;
public int Type; public int TypeID;
public EntityType Type;
public string Name; public string Name;
public Location Location; public Location Location;
public Entity(int ID, Location location) public Entity(int ID, Location location)
@ -16,17 +17,31 @@ namespace MinecraftClient.Mapping
this.ID = ID; this.ID = ID;
this.Location = location; this.Location = location;
} }
public Entity(int ID, int Type, Location location) public Entity(int ID, int TypeID, Location location)
{ {
this.ID = ID; this.ID = ID;
this.Type = Type; this.TypeID = TypeID;
this.Name = GetMobName(Type); this.Name = GetMobName(TypeID);
this.Location = location; 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.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.Name = Name;
this.Location = location; this.Location = location;
} }
@ -80,7 +95,7 @@ namespace MinecraftClient.Mapping
} }
public string GetMobName() 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.Proxy;
using MinecraftClient.Protocol.Handlers.Forge; using MinecraftClient.Protocol.Handlers.Forge;
using MinecraftClient.Mapping; using MinecraftClient.Mapping;
using MinecraftClient.Inventory;
namespace MinecraftClient namespace MinecraftClient
{ {
@ -26,7 +27,7 @@ namespace MinecraftClient
private readonly List<ChatBot> bots = new List<ChatBot>(); private readonly List<ChatBot> bots = new List<ChatBot>();
private static readonly List<ChatBot> botsOnHold = 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 Dictionary<string, List<ChatBot>> registeredBotPluginChannels = new Dictionary<string, List<ChatBot>>();
private readonly List<string> registeredServerPluginChannels = new List<String>(); private readonly List<string> registeredServerPluginChannels = new List<String>();
@ -52,14 +53,14 @@ namespace MinecraftClient
private string username; private string username;
private string uuid; private string uuid;
private string sessionid; private string sessionid;
private Inventory playerInventory; private Container playerInventory = new Container(ContainerType.PlayerInventory);
private DateTime lastKeepAlive; private DateTime lastKeepAlive;
private object lastKeepAliveLock = new object(); private object lastKeepAliveLock = new object();
private int playerEntityID; private int playerEntityID;
// not really understand the Inventory Class // not really understand the Inventory Class
// so I use a Dict instead for player inventory // so I use a Dict instead for player inventory
private Dictionary<int, Item> playerItems; //private Dictionary<int, Inventory.Item> playerItems;
// Entity handling // Entity handling
private Dictionary<int, Entity> entities = new Dictionary<int, Entity>(); private Dictionary<int, Entity> entities = new Dictionary<int, Entity>();
@ -567,9 +568,9 @@ namespace MinecraftClient
/// Get client player's inventory items /// Get client player's inventory items
/// </summary> /// </summary>
/// <returns> Item Dictionary indexed by Slot ID (Check wiki.vg for slot ID)</returns> /// <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 // TODO: add command for displaying player inventory
@ -737,13 +738,14 @@ namespace MinecraftClient
/// When an inventory is opened /// When an inventory is opened
/// </summary> /// </summary>
/// <param name="inventory">Location to reach</param> /// <param name="inventory">Location to reach</param>
public void OnInventoryOpen(Inventory inventory) public void OnInventoryOpen(Container inventory)
{ {
//TODO: Handle Inventory //TODO: Handle Inventory
if (!inventories.Contains(inventory)) if (!inventories.Contains(inventory))
{ {
inventories.Add(inventory); inventories.Add(inventory);
} }
ConsoleIO.WriteLine(inventory.Type.ToString());
} }
/// <summary> /// <summary>
@ -754,9 +756,9 @@ namespace MinecraftClient
{ {
for (int i = 0; i < inventories.Count; i++) for (int i = 0; i < inventories.Count; i++)
{ {
Inventory inventory = inventories[i]; Container inventory = inventories[i];
if (inventory == null) continue; if (inventory == null) continue;
if (inventory.id == inventoryID) if (inventory.Type == Container.GetContainerType(inventoryID))
{ {
inventories.Remove(inventory); inventories.Remove(inventory);
return; return;
@ -769,11 +771,27 @@ namespace MinecraftClient
/// </summary> /// </summary>
/// <param name="type"></param> /// <param name="type"></param>
/// <param name="itemList"></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 // 0 is player inventory
if (type == 0) 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> /// <summary>
@ -1081,12 +1099,12 @@ namespace MinecraftClient
/// Called when a non-living entity spawned (fishing hook, minecart, etc) /// Called when a non-living entity spawned (fishing hook, minecart, etc)
/// </summary> /// </summary>
/// <param name="EntityID"></param> /// <param name="EntityID"></param>
/// <param name="EntityType"></param> /// <param name="TypeID"></param>
/// <param name="UUID"></param> /// <param name="UUID"></param>
/// <param name="location"></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); entities.Add(EntityID, entity);
foreach (ChatBot bot in bots.ToArray()) foreach (ChatBot bot in bots.ToArray())
bot.OnEntitySpawn(entity); bot.OnEntitySpawn(entity);
@ -1096,12 +1114,29 @@ namespace MinecraftClient
/// Called when an Entity was created/spawned. /// Called when an Entity was created/spawned.
/// </summary> /// </summary>
/// <param name="EntityID"></param> /// <param name="EntityID"></param>
/// <param name="EntityType"></param> /// <param name="TypeID"></param>
/// <param name="UUID"></param> /// <param name="UUID"></param>
/// <param name="location"></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); entities.Add(EntityID, entity);
foreach (ChatBot bot in bots.ToArray()) foreach (ChatBot bot in bots.ToArray())
bot.OnEntitySpawn(entity); bot.OnEntitySpawn(entity);
@ -1118,7 +1153,7 @@ namespace MinecraftClient
if (entities.ContainsKey(a)) if (entities.ContainsKey(a))
{ {
foreach (ChatBot bot in bots.ToArray()) 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); entities.Remove(a);
} }
} }
@ -1143,7 +1178,7 @@ namespace MinecraftClient
entities[EntityID].Location = L; entities[EntityID].Location = L;
foreach (ChatBot bot in bots.ToArray()) 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; entities[EntityID].Location = location;
foreach (ChatBot bot in bots.ToArray()) 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); 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="ChatBots\TestBot.cs" />
<Compile Include="ChatBot.cs" /> <Compile Include="ChatBot.cs" />
<Compile Include="Command.cs" /> <Compile Include="Command.cs" />
<Compile Include="Commands\ChangeSlot.cs" />
<Compile Include="Commands\Connect.cs" /> <Compile Include="Commands\Connect.cs" />
<Compile Include="Commands\Debug.cs" /> <Compile Include="Commands\Debug.cs" />
<Compile Include="Commands\GetInventory.cs" />
<Compile Include="Commands\Look.cs" /> <Compile Include="Commands\Look.cs" />
<Compile Include="Commands\Move.cs" /> <Compile Include="Commands\Move.cs" />
<Compile Include="Commands\Exit.cs" /> <Compile Include="Commands\Exit.cs" />
@ -100,6 +102,9 @@
<Compile Include="Commands\Send.cs" /> <Compile Include="Commands\Send.cs" />
<Compile Include="Commands\Set.cs" /> <Compile Include="Commands\Set.cs" />
<Compile Include="Commands\UseItem.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\Palette112.cs" />
<Compile Include="Mapping\BlockPalettes\Palette113.cs" /> <Compile Include="Mapping\BlockPalettes\Palette113.cs" />
<Compile Include="Mapping\BlockPalettes\Palette114.cs" /> <Compile Include="Mapping\BlockPalettes\Palette114.cs" />
@ -107,6 +112,7 @@
<Compile Include="Mapping\BlockPalettes\PaletteGenerator.cs" /> <Compile Include="Mapping\BlockPalettes\PaletteGenerator.cs" />
<Compile Include="Mapping\BlockPalettes\PaletteMapping.cs" /> <Compile Include="Mapping\BlockPalettes\PaletteMapping.cs" />
<Compile Include="Mapping\Entity.cs" /> <Compile Include="Mapping\Entity.cs" />
<Compile Include="Mapping\EntityType.cs" />
<Compile Include="Mapping\MaterialExtensions.cs" /> <Compile Include="Mapping\MaterialExtensions.cs" />
<Compile Include="Protocol\Handlers\DataTypes.cs" /> <Compile Include="Protocol\Handlers\DataTypes.cs" />
<Compile Include="Protocol\Handlers\PacketIncomingType.cs" /> <Compile Include="Protocol\Handlers\PacketIncomingType.cs" />
@ -286,6 +292,7 @@
<Content Include="Protocol\Dns\Records\totla.txt" /> <Content Include="Protocol\Dns\Records\totla.txt" />
<Content Include="Resources\AppIcon.ico" /> <Content Include="Resources\AppIcon.ico" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- 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. Other similar extension points exist, see Microsoft.Common.targets.

View file

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

View file

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

View file

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

View file

@ -658,6 +658,14 @@ namespace MinecraftClient.Protocol.Handlers
{ {
return false; 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> /// <summary>
/// Send a plugin channel packet to the server. /// 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); InventoryType inventoryType = (InventoryType)Enum.Parse(typeof(InventoryType), type);
string title = dataTypes.ReadNextString(packetData); string title = dataTypes.ReadNextString(packetData);
byte slots = dataTypes.ReadNextByte(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); handler.OnInventoryOpen(inventory);
} }
@ -536,7 +547,7 @@ namespace MinecraftClient.Protocol.Handlers
*/ */
byte id = dataTypes.ReadNextByte(packetData); byte id = dataTypes.ReadNextByte(packetData);
short elements = dataTypes.ReadNextShort(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++) for(int i = 0; i < elements; i++)
{ {
bool haveItem = dataTypes.ReadNextBool(packetData); bool haveItem = dataTypes.ReadNextBool(packetData);
@ -546,13 +557,32 @@ namespace MinecraftClient.Protocol.Handlers
byte itemCount = dataTypes.ReadNextByte(packetData); byte itemCount = dataTypes.ReadNextByte(packetData);
dataTypes.ReadNextNbt(packetData); dataTypes.ReadNextNbt(packetData);
Item item = new Item(itemID, itemCount); MinecraftClient.Inventory.Item item = new MinecraftClient.Inventory.Item(itemID, itemCount);
itemsList.Add(i, item); itemsList.Add(i, item);
} }
} }
handler.OnWindowItems(id, itemsList); handler.OnWindowItems(id, itemsList);
} }
break; 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: case PacketIncomingType.ResourcePackSend:
string url = dataTypes.ReadNextString(packetData); string url = dataTypes.ReadNextString(packetData);
string hash = dataTypes.ReadNextString(packetData); string hash = dataTypes.ReadNextString(packetData);
@ -606,6 +636,22 @@ namespace MinecraftClient.Protocol.Handlers
handler.OnSpawnLivingEntity(EntityID, EntityType, EntityUUID, EntityLocation); handler.OnSpawnLivingEntity(EntityID, EntityType, EntityUUID, EntityLocation);
} }
break; 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: case PacketIncomingType.DestroyEntities:
if (handler.GetEntityHandlingEnabled()) if (handler.GetEntityHandlingEnabled())
{ {
@ -1185,8 +1231,7 @@ namespace MinecraftClient.Protocol.Handlers
} }
return false; return false;
} }
// reinforce
/// <summary> /// <summary>
/// Send an Interact Entity Packet to server /// Send an Interact Entity Packet to server
/// </summary> /// </summary>
@ -1207,10 +1252,24 @@ namespace MinecraftClient.Protocol.Handlers
catch (System.IO.IOException) { return false; } catch (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { 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) 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) 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 (System.IO.IOException) { return false; }
catch (ObjectDisposedException) { 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 // Entity handling
case 0x0E: return PacketIncomingType.SpawnEntity; // for non-living entity case 0x0E: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x0F: return PacketIncomingType.SpawnLivingEntity; // for living entity case 0x0F: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x13: return PacketIncomingType.DestroyEntities; case 0x13: return PacketIncomingType.DestroyEntities;
case 0x15: return PacketIncomingType.EntityPosition; case 0x15: return PacketIncomingType.EntityPosition;
case 0x17: return PacketIncomingType.EntityPositionAndRotation; case 0x17: return PacketIncomingType.EntityPositionAndRotation;
@ -86,6 +87,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling // Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x30: return PacketIncomingType.DestroyEntities; case 0x30: return PacketIncomingType.DestroyEntities;
case 0x25: return PacketIncomingType.EntityPosition; case 0x25: return PacketIncomingType.EntityPosition;
case 0x26: return PacketIncomingType.EntityPositionAndRotation; case 0x26: return PacketIncomingType.EntityPositionAndRotation;
@ -122,6 +124,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling // Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x31: return PacketIncomingType.DestroyEntities; case 0x31: return PacketIncomingType.DestroyEntities;
case 0x26: return PacketIncomingType.EntityPosition; case 0x26: return PacketIncomingType.EntityPosition;
case 0x27: return PacketIncomingType.EntityPositionAndRotation; case 0x27: return PacketIncomingType.EntityPositionAndRotation;
@ -158,6 +161,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling // Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x32: return PacketIncomingType.DestroyEntities; case 0x32: return PacketIncomingType.DestroyEntities;
case 0x26: return PacketIncomingType.EntityPosition; case 0x26: return PacketIncomingType.EntityPosition;
case 0x27: return PacketIncomingType.EntityPositionAndRotation; case 0x27: return PacketIncomingType.EntityPositionAndRotation;
@ -194,6 +198,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling // Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x35: return PacketIncomingType.DestroyEntities; case 0x35: return PacketIncomingType.DestroyEntities;
case 0x28: return PacketIncomingType.EntityPosition; case 0x28: return PacketIncomingType.EntityPosition;
case 0x29: return PacketIncomingType.EntityPositionAndRotation; case 0x29: return PacketIncomingType.EntityPositionAndRotation;
@ -229,6 +234,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling // Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x37: return PacketIncomingType.DestroyEntities; case 0x37: return PacketIncomingType.DestroyEntities;
case 0x28: return PacketIncomingType.EntityPosition; case 0x28: return PacketIncomingType.EntityPosition;
case 0x29: return PacketIncomingType.EntityPositionAndRotation; case 0x29: return PacketIncomingType.EntityPositionAndRotation;
@ -264,6 +270,7 @@ namespace MinecraftClient.Protocol.Handlers
// Entity handling // Entity handling
case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity case 0x00: return PacketIncomingType.SpawnEntity; // for non-living entity
case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity case 0x03: return PacketIncomingType.SpawnLivingEntity; // for living entity
case 0x05: return PacketIncomingType.SpawnPlayer;
case 0x38: return PacketIncomingType.DestroyEntities; case 0x38: return PacketIncomingType.DestroyEntities;
case 0x29: return PacketIncomingType.EntityPosition; case 0x29: return PacketIncomingType.EntityPosition;
case 0x2A: return PacketIncomingType.EntityPositionAndRotation; case 0x2A: return PacketIncomingType.EntityPositionAndRotation;
@ -296,6 +303,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.TabComplete: return 0x14; case PacketOutgoingType.TabComplete: return 0x14;
case PacketOutgoingType.PlayerPosition: return 0x04; case PacketOutgoingType.PlayerPosition: return 0x04;
case PacketOutgoingType.PlayerPositionAndLook: return 0x06; case PacketOutgoingType.PlayerPositionAndLook: return 0x06;
case PacketOutgoingType.HeldItemChange: return 0x17;
case PacketOutgoingType.InteractEntity: return 0x02; case PacketOutgoingType.InteractEntity: return 0x02;
case PacketOutgoingType.TeleportConfirm: throw new InvalidOperationException("Teleport confirm is not supported in protocol " + protocol); 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.PlayerPosition: return 0x0C;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0D; case PacketOutgoingType.PlayerPositionAndLook: return 0x0D;
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x17;
case PacketOutgoingType.InteractEntity: return 0x0A; case PacketOutgoingType.InteractEntity: return 0x0A;
} }
} }
@ -331,6 +340,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.PlayerPosition: return 0x0E; case PacketOutgoingType.PlayerPosition: return 0x0E;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0F; case PacketOutgoingType.PlayerPositionAndLook: return 0x0F;
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x1A;
case PacketOutgoingType.InteractEntity: return 0x0B; case PacketOutgoingType.InteractEntity: return 0x0B;
} }
} }
@ -348,6 +358,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.PlayerPosition: return 0x0D; case PacketOutgoingType.PlayerPosition: return 0x0D;
case PacketOutgoingType.PlayerPositionAndLook: return 0x0E; case PacketOutgoingType.PlayerPositionAndLook: return 0x0E;
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x1F;
case PacketOutgoingType.InteractEntity: return 0x0A; case PacketOutgoingType.InteractEntity: return 0x0A;
} }
} }
@ -365,6 +376,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.PlayerPosition: return 0x10; case PacketOutgoingType.PlayerPosition: return 0x10;
case PacketOutgoingType.PlayerPositionAndLook: return 0x11; case PacketOutgoingType.PlayerPositionAndLook: return 0x11;
case PacketOutgoingType.TeleportConfirm: return 0x00; case PacketOutgoingType.TeleportConfirm: return 0x00;
case PacketOutgoingType.HeldItemChange: return 0x21;
case PacketOutgoingType.InteractEntity: return 0x0D; case PacketOutgoingType.InteractEntity: return 0x0D;
} }
} }
@ -385,6 +397,7 @@ namespace MinecraftClient.Protocol.Handlers
case PacketOutgoingType.HeldItemChange: return 0x23; case PacketOutgoingType.HeldItemChange: return 0x23;
case PacketOutgoingType.InteractEntity: return 0x0E; case PacketOutgoingType.InteractEntity: return 0x0E;
case PacketOutgoingType.UseItem: return 0x2D; case PacketOutgoingType.UseItem: return 0x2D;
case PacketOutgoingType.PlayerBlockPlacement: return 0x2C;
} }
} }

View file

@ -84,11 +84,15 @@ namespace MinecraftClient.Protocol
/// <param name="data">packet Data</param> /// <param name="data">packet Data</param>
/// <returns>True if message was successfully sent</returns> /// <returns>True if message was successfully sent</returns>
bool SendPluginChannelPacket(string channel, byte[] data); bool SendPluginChannelPacket(string channel, byte[] data);
bool SendHeldItemChange(short slot);
bool SendInteractEntityPacket(int EntityID, int type); 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, int hand);
bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z); bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z);
bool SendUseItemPacket(int hand); 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.Linq;
using System.Text; using System.Text;
using MinecraftClient.Mapping; using MinecraftClient.Mapping;
using MinecraftClient.Inventory;
namespace MinecraftClient.Protocol namespace MinecraftClient.Protocol
{ {
@ -52,7 +53,7 @@ namespace MinecraftClient.Protocol
/// <summary> /// <summary>
/// Called when an inventory is opened /// Called when an inventory is opened
/// </summary> /// </summary>
void OnInventoryOpen(Inventory inventory); void OnInventoryOpen(Container inventory);
/// <summary> /// <summary>
/// Called when an inventory is closed /// Called when an inventory is closed
@ -131,6 +132,8 @@ namespace MinecraftClient.Protocol
void OnSpawnLivingEntity(int EntityID, int EntityType, Guid UUID, Location location); 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 OnDestroyEntities(int[] EntityID);
void OnEntityPosition(int EntityID, Double Dx, Double Dy, Double Dz,bool onGround); 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 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); 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. 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 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 Disclaimer
------ ------