mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Interact with inventories
The /inventory command allow listing inventory and clicking on items Should be enough for operating GUI menus such as Server chooser/teleporter
This commit is contained in:
parent
bc3d6aba00
commit
e04f06cece
13 changed files with 574 additions and 217 deletions
BIN
DebugTools/MinecraftClientProxy.suo
Normal file
BIN
DebugTools/MinecraftClientProxy.suo
Normal file
Binary file not shown.
|
|
@ -149,6 +149,22 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
g = readNextBool(ref packetData);
|
||||
Console.WriteLine("[C -> S] Location: " + x + ", " + y + ", " + z + ", (look)" + ", " + g);
|
||||
break;
|
||||
case 0x09:
|
||||
byte window = readNextByte(ref packetData);
|
||||
short slot = readNextShort(ref packetData);
|
||||
byte button = readNextByte(ref packetData);
|
||||
short action = readNextShort(ref packetData);
|
||||
int mode = readNextVarInt(ref packetData);
|
||||
bool slotPresent = readNextBool(ref packetData);
|
||||
int itemId = -1;
|
||||
byte itemCount = 0;
|
||||
if (slotPresent)
|
||||
{
|
||||
itemId = readNextVarInt(ref packetData);
|
||||
itemCount = readNextByte(ref packetData);
|
||||
}
|
||||
Console.WriteLine("[C -> S] Window #" + window + " click: #" + slot + " button " + button + " action " + action + " mode " + mode + " item " + itemId + " x" + itemCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -209,6 +225,19 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return rawValue[0] != 0;
|
||||
}
|
||||
|
||||
private byte readNextByte(ref byte[] cache)
|
||||
{
|
||||
byte[] rawValue = readData(1, ref cache);
|
||||
return rawValue[0];
|
||||
}
|
||||
|
||||
private short readNextShort(ref byte[] cache)
|
||||
{
|
||||
byte[] rawValue = readData(2, ref cache);
|
||||
Array.Reverse(rawValue); //Endianness
|
||||
return BitConverter.ToInt16(rawValue, 0);
|
||||
}
|
||||
|
||||
private double readNextDouble(ref byte[] cache)
|
||||
{
|
||||
byte[] rawValue = readData(8, ref cache);
|
||||
|
|
|
|||
|
|
@ -6,23 +6,63 @@ using MinecraftClient.Inventory;
|
|||
|
||||
namespace MinecraftClient.Commands
|
||||
{
|
||||
class GetInventory : Command
|
||||
class Inventory : Command
|
||||
{
|
||||
public override string CMDName { get { return "inventory"; } }
|
||||
public override string CMDDesc { get { return "inventory: Show your inventory."; } }
|
||||
public override string CMDDesc { get { return "inventory <id> <list|close|click <slot>>: Interact with inventories"; } }
|
||||
|
||||
public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
|
||||
{
|
||||
List<string> response = new List<string>();
|
||||
|
||||
response.Add("Inventory slots:");
|
||||
|
||||
foreach (KeyValuePair<int, Item> item in handler.GetPlayerInventory().Items)
|
||||
if (handler.GetInventoryEnabled())
|
||||
{
|
||||
string[] args = getArgs(command);
|
||||
if (args.Length >= 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
int inventoryId = int.Parse(args[0]);
|
||||
string action = args.Length > 1
|
||||
? args[1].ToLower()
|
||||
: "list";
|
||||
switch (action)
|
||||
{
|
||||
case "close":
|
||||
if (handler.CloseInventory(inventoryId))
|
||||
return "Closing Inventoy #" + inventoryId;
|
||||
else return "Failed to close Inventory #" + inventoryId;
|
||||
case "list":
|
||||
Container inventory = handler.GetInventory(inventoryId);
|
||||
List<string> response = new List<string>();
|
||||
response.Add("Inventory #" + inventoryId + " - " + inventory.Title + "§8");
|
||||
foreach (KeyValuePair<int, Item> item in inventory.Items)
|
||||
response.Add(String.Format(" #{0}: {1} x{2}", item.Key, item.Value.Type, item.Value.Count));
|
||||
}
|
||||
|
||||
return String.Join("\n", response.ToArray());
|
||||
case "click":
|
||||
if (args.Length == 3)
|
||||
{
|
||||
int slot = int.Parse(args[2]);
|
||||
handler.ClickWindowSlot(inventoryId, slot);
|
||||
return "Clicking slot " + slot + " in window #" + inventoryId;
|
||||
}
|
||||
else return CMDDesc;
|
||||
default:
|
||||
return CMDDesc;
|
||||
}
|
||||
}
|
||||
catch (FormatException) { return CMDDesc; }
|
||||
}
|
||||
else
|
||||
{
|
||||
Dictionary<int, Container> inventories = handler.GetInventories();
|
||||
List<string> response = new List<string>();
|
||||
response.Add("Inventories:");
|
||||
foreach (var inventory in inventories)
|
||||
response.Add(String.Format(" #{0}: {1}", inventory.Key, inventory.Value.Title + "§8"));
|
||||
response.Add(CMDDesc);
|
||||
return String.Join("\n", response);
|
||||
}
|
||||
}
|
||||
else return "Please enable inventoryhandling in config to use this command.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,13 @@ namespace MinecraftClient.Commands
|
|||
public override string CMDDesc { get { return "useitem: Use (left click) an item on the hand"; } }
|
||||
|
||||
public override string Run(McTcpClient handler, string command, Dictionary<string, object> localVars)
|
||||
{
|
||||
if (handler.GetInventoryEnabled())
|
||||
{
|
||||
handler.UseItemOnHand();
|
||||
return "Use an item";
|
||||
return "Used an item";
|
||||
}
|
||||
else return "Please enable inventoryhandling in config to use this command.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,44 +20,34 @@ namespace MinecraftClient.Inventory
|
|||
/// </summary>
|
||||
public int Count;
|
||||
|
||||
/// <summary>
|
||||
/// Slot ID in the parent inventory
|
||||
/// </summary>
|
||||
/// <remarks>-1 means currently being dragged by mouse</remarks>
|
||||
public int SlotID;
|
||||
|
||||
/// <summary>
|
||||
/// Item Metadata
|
||||
/// </summary>
|
||||
public Dictionary<string, object> NBT;
|
||||
|
||||
/// <summary>
|
||||
/// Create an item with Type ID, Count and Slot ID
|
||||
/// Create an item with Type ID, Count and Metadata
|
||||
/// </summary>
|
||||
/// <param name="ID">Item Type ID</param>
|
||||
/// <param name="Count">Item Count</param>
|
||||
/// <param name="SlotID">Item Slot ID in parent inventory</param>
|
||||
public Item(int id, int count, int slotID)
|
||||
/// <param name="NBT">Item Metadata</param>
|
||||
public Item(int id, int count, Dictionary<string, object> nbt)
|
||||
{
|
||||
this.Type = (ItemType)id;
|
||||
this.Count = count;
|
||||
this.SlotID = slotID;
|
||||
this.NBT = new Dictionary<string, object>();
|
||||
this.NBT = nbt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an item with Type ID, Count, Slot ID and Metadata
|
||||
/// Check if the item slot is empty
|
||||
/// </summary>
|
||||
/// <param name="ID">Item Type ID</param>
|
||||
/// <param name="Count">Item Count</param>
|
||||
/// <param name="SlotID">Item Slot ID in parent inventory</param>
|
||||
/// <param name="NBT">Item Metadata</param>
|
||||
public Item(int id, int count, int slotID, Dictionary<string, object> nbt)
|
||||
/// <returns>TRUE if the item is empty</returns>
|
||||
public bool IsEmpty
|
||||
{
|
||||
this.Type = (ItemType)id;
|
||||
this.Count = count;
|
||||
this.SlotID = slotID;
|
||||
this.NBT = nbt;
|
||||
get
|
||||
{
|
||||
return Type == ItemType.Air || Count == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,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<Container> inventories = new List<Container>();
|
||||
private static Dictionary<int, Container> inventories = new Dictionary<int, Container>();
|
||||
|
||||
private readonly Dictionary<string, List<ChatBot>> registeredBotPluginChannels = new Dictionary<string, List<ChatBot>>();
|
||||
private readonly List<string> registeredServerPluginChannels = new List<String>();
|
||||
|
|
@ -53,7 +53,6 @@ namespace MinecraftClient
|
|||
private string username;
|
||||
private string uuid;
|
||||
private string sessionid;
|
||||
private Container playerInventory = new Container(ContainerType.PlayerInventory);
|
||||
private DateTime lastKeepAlive;
|
||||
private object lastKeepAliveLock = new object();
|
||||
|
||||
|
|
@ -136,6 +135,12 @@ namespace MinecraftClient
|
|||
inventoryHandlingEnabled = Settings.InventoryHandling;
|
||||
entityHandlingEnabled = Settings.EntityHandling;
|
||||
|
||||
if (inventoryHandlingEnabled)
|
||||
{
|
||||
inventories.Clear();
|
||||
inventories[0] = new Container(0, ContainerType.PlayerInventory, "Player Inventory");
|
||||
}
|
||||
|
||||
bool retry = false;
|
||||
this.sessionid = sessionID;
|
||||
this.uuid = uuid;
|
||||
|
|
@ -550,7 +555,6 @@ namespace MinecraftClient
|
|||
inventoryHandlingEnabled = false;
|
||||
inventoryHandlingRequested = false;
|
||||
inventories.Clear();
|
||||
playerInventory = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -592,13 +596,34 @@ namespace MinecraftClient
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all inventories. ID 0 is the player inventory.
|
||||
/// </summary>
|
||||
/// <returns>All inventories</returns>
|
||||
public Dictionary<int, Container> GetInventories()
|
||||
{
|
||||
return inventories;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get client player's inventory items
|
||||
/// </summary>
|
||||
/// <param name="inventoryID">Window ID of the requested inventory</param>
|
||||
/// <returns> Item Dictionary indexed by Slot ID (Check wiki.vg for slot ID)</returns>
|
||||
public Container GetInventory(int inventoryID)
|
||||
{
|
||||
if (inventories.ContainsKey(inventoryID))
|
||||
return inventories[inventoryID];
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get client player's inventory items
|
||||
/// </summary>
|
||||
/// <returns> Item Dictionary indexed by Slot ID (Check wiki.vg for slot ID)</returns>
|
||||
public Container GetPlayerInventory()
|
||||
{
|
||||
return playerInventory;
|
||||
return GetInventory(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -765,19 +790,14 @@ namespace MinecraftClient
|
|||
/// When an inventory is opened
|
||||
/// </summary>
|
||||
/// <param name="inventory">Location to reach</param>
|
||||
public void OnInventoryOpen(Container inventory)
|
||||
public void OnInventoryOpen(int inventoryID, Container inventory)
|
||||
{
|
||||
//TODO: Handle Inventory
|
||||
if (!inventories.Contains(inventory))
|
||||
{
|
||||
inventories.Add(inventory);
|
||||
}
|
||||
inventories[inventoryID] = inventory;
|
||||
|
||||
if (Settings.DebugMessages)
|
||||
if (inventoryID != 0)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§8An Inventory opened: " + inventory.Type + " - " + inventory.Title);
|
||||
foreach (var item in inventory.Items)
|
||||
ConsoleIO.WriteLineFormatted("§8 - Slot " + item.Key + ": " + item.Value.Type + " x" + item.Value.Count);
|
||||
ConsoleIO.WriteLogLine("Inventory # " + inventoryID + " opened: " + inventory.Title);
|
||||
ConsoleIO.WriteLogLine("Use /inventory to interact with it.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -785,64 +805,42 @@ namespace MinecraftClient
|
|||
/// When an inventory is close
|
||||
/// </summary>
|
||||
/// <param name="inventoryID">Location to reach</param>
|
||||
public void OnInventoryClose(byte inventoryID)
|
||||
public void OnInventoryClose(int inventoryID)
|
||||
{
|
||||
for (int i = 0; i < inventories.Count; i++)
|
||||
{
|
||||
Container inventory = inventories[i];
|
||||
if (inventory == null) continue;
|
||||
if (inventory.Type == Container.GetContainerType(inventoryID))
|
||||
{
|
||||
inventories.Remove(inventory);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (inventories.ContainsKey(inventoryID))
|
||||
inventories.Remove(inventoryID);
|
||||
|
||||
if (inventoryID != 0)
|
||||
ConsoleIO.WriteLogLine("Inventory # " + inventoryID + " closed.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When received window items from server.
|
||||
/// </summary>
|
||||
/// <param name="type">Inventory type</param>
|
||||
/// <param name="inventoryID">Inventory ID</param>
|
||||
/// <param name="itemList">Item list, key = slot ID, value = Item information</param>
|
||||
public void OnWindowItems(int type, Dictionary<int, Inventory.Item> itemList)
|
||||
public void OnWindowItems(byte inventoryID, Dictionary<int, Inventory.Item> itemList)
|
||||
{
|
||||
// 0 is player inventory
|
||||
if (type == 0)
|
||||
playerInventory.Items = itemList;
|
||||
if (Settings.DebugMessages)
|
||||
{
|
||||
ConsoleIO.WriteLineFormatted("§8Received Window of type " + type);
|
||||
foreach (var item in itemList)
|
||||
ConsoleIO.WriteLineFormatted("§8 - Slot " + item.Key + ": " + item.Value.Type + " x" + item.Value.Count);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When a slot is cleared inside window items
|
||||
/// </summary>
|
||||
/// <param name="WindowID">Window ID</param>
|
||||
/// <param name="SlotID">Slot ID</param>
|
||||
public void OnSlotClear(byte WindowID, short SlotID)
|
||||
{
|
||||
if (WindowID == 0 && playerInventory.Items.ContainsKey(SlotID))
|
||||
{
|
||||
playerInventory.Items.Remove(SlotID);
|
||||
}
|
||||
if (inventories.ContainsKey(inventoryID))
|
||||
inventories[inventoryID].Items = itemList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When a slot is set inside window items
|
||||
/// </summary>
|
||||
/// <param name="WindowID">Window ID</param>
|
||||
/// <param name="SlotID">Slot ID</param>
|
||||
/// <param name="ItemID">Item ID</param>
|
||||
/// <param name="Count">Item Count</param>
|
||||
/// <param name="NBT">Item Metadata</param>
|
||||
public void OnSetSlot(byte WindowID, short SlotID, int ItemID, byte Count, Dictionary<string, object> NBT)
|
||||
/// <param name="inventoryID">Window ID</param>
|
||||
/// <param name="slotID">Slot ID</param>
|
||||
/// <param name="item">Item (may be null for empty slot)</param>
|
||||
public void OnSetSlot(byte inventoryID, short slotID, Item item)
|
||||
{
|
||||
if (WindowID == 0)
|
||||
if (inventories.ContainsKey(inventoryID))
|
||||
{
|
||||
playerInventory.Items[SlotID] = new Inventory.Item(ItemID, Count, SlotID, NBT);
|
||||
if (item == null || item.IsEmpty)
|
||||
{
|
||||
if (inventories[inventoryID].Items.ContainsKey(slotID))
|
||||
inventories[inventoryID].Items.Remove(slotID);
|
||||
}
|
||||
else inventories[inventoryID].Items[slotID] = item;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1312,7 +1310,35 @@ namespace MinecraftClient
|
|||
/// <returns>TRUE if the item was successfully used</returns>
|
||||
public bool UseItemOnHand()
|
||||
{
|
||||
return handler.SendUseItemPacket(0);
|
||||
return handler.SendUseItem(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Click a slot in the specified window
|
||||
/// </summary>
|
||||
/// <returns>TRUE if the slot was successfully clicked</returns>
|
||||
public bool ClickWindowSlot(int windowId, int slotId)
|
||||
{
|
||||
Item item = null;
|
||||
if (inventories.ContainsKey(windowId) && inventories[windowId].Items.ContainsKey(slotId))
|
||||
item = inventories[windowId].Items[slotId];
|
||||
|
||||
return handler.SendClickWindow(windowId, slotId, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the specified inventory window
|
||||
/// </summary>
|
||||
/// <param name="windowId">Window ID</param>
|
||||
/// <returns>TRUE if the window was successfully closed</returns>
|
||||
public bool CloseInventory(int windowId)
|
||||
{
|
||||
if (windowId != 0 && inventories.ContainsKey(windowId))
|
||||
{
|
||||
inventories.Remove(windowId);
|
||||
return handler.SendCloseWindow(windowId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1320,10 +1346,10 @@ namespace MinecraftClient
|
|||
/// </summary>
|
||||
/// <param name="EntityID"></param>
|
||||
/// <param name="type">0: interact, 1: attack, 2: interact at</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>TRUE if interaction succeeded</returns>
|
||||
public bool InteractEntity(int EntityID, int type)
|
||||
{
|
||||
return handler.SendInteractEntityPacket(EntityID, type);
|
||||
return handler.SendInteractEntity(EntityID, type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1342,7 +1368,7 @@ namespace MinecraftClient
|
|||
/// Change active slot in the player inventory
|
||||
/// </summary>
|
||||
/// <param name="slot">Slot to activate (0 to 8)</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>TRUE if the slot was changed</returns>
|
||||
public bool ChangeSlot(short slot)
|
||||
{
|
||||
if (slot >= 0 && slot <= 8)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System.Text;
|
|||
using System.Net.Sockets;
|
||||
using MinecraftClient.Mapping;
|
||||
using MinecraftClient.Crypto;
|
||||
using MinecraftClient.Inventory;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers
|
||||
{
|
||||
|
|
@ -319,6 +320,40 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return ReadNextNbt(cache, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a single item slot from a cache of byte and remove it from the cache
|
||||
/// </summary>
|
||||
/// <param name="item">Item</param>
|
||||
/// <returns>The item that was read or NULL for an empty slot</returns>
|
||||
public Item ReadNextItemSlot(List<byte> cache)
|
||||
{
|
||||
List<byte> slotData = new List<byte>();
|
||||
if (protocolversion > Protocol18Handler.MC113Version)
|
||||
{
|
||||
// MC 1.13 and greater
|
||||
bool itemPresent = ReadNextBool(cache);
|
||||
if (itemPresent)
|
||||
{
|
||||
int itemID = ReadNextVarInt(cache);
|
||||
byte itemCount = ReadNextByte(cache);
|
||||
Dictionary<string, object> NBT = ReadNextNbt(cache);
|
||||
return new Item(itemID, itemCount, NBT);
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// MC 1.12.2 and lower
|
||||
short itemID = ReadNextShort(cache);
|
||||
if (itemID == -1)
|
||||
return null;
|
||||
byte itemCount = ReadNextByte(cache);
|
||||
short itemDamage = ReadNextShort(cache);
|
||||
Dictionary<string, object> NBT = ReadNextNbt(cache);
|
||||
return new Item(itemID, itemCount, NBT);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an uncompressed Named Binary Tag blob and remove it from the cache (internal)
|
||||
/// </summary>
|
||||
|
|
@ -395,6 +430,163 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build an uncompressed Named Binary Tag blob for sending over the network
|
||||
/// </summary>
|
||||
/// <param name="nbt">Dictionary to encode as Nbt</param>
|
||||
/// <returns>Byte array for this NBT tag</returns>
|
||||
public byte[] GetNbt(Dictionary<string, object> nbt)
|
||||
{
|
||||
return GetNbt(nbt, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build an uncompressed Named Binary Tag blob for sending over the network (internal)
|
||||
/// </summary>
|
||||
/// <param name="nbt">Dictionary to encode as Nbt</param>
|
||||
/// <param name="root">TRUE if starting a new NBT tag, FALSE if processing a nested NBT tag</param>
|
||||
/// <returns>Byte array for this NBT tag</returns>
|
||||
private byte[] GetNbt(Dictionary<string, object> nbt, bool root)
|
||||
{
|
||||
if (nbt == null || nbt.Count == 0)
|
||||
return new byte[] { 0 }; // TAG_End
|
||||
|
||||
List<byte> bytes = new List<byte>();
|
||||
|
||||
if (root)
|
||||
{
|
||||
bytes.Add(10); // TAG_Compound
|
||||
}
|
||||
|
||||
foreach (var item in nbt)
|
||||
{
|
||||
byte fieldType;
|
||||
byte[] fieldNameLength = GetUShort((ushort)item.Key.Length);
|
||||
byte[] fieldName = Encoding.ASCII.GetBytes(item.Key);
|
||||
byte[] fieldData = GetNbtField(item.Value, out fieldType);
|
||||
bytes.AddRange(fieldNameLength);
|
||||
bytes.AddRange(fieldName);
|
||||
bytes.Add(fieldType);
|
||||
bytes.AddRange(fieldData);
|
||||
}
|
||||
|
||||
bytes.Add(0); // TAG_End
|
||||
return bytes.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert a single object into its NBT representation (internal)
|
||||
/// </summary>
|
||||
/// <param name="obj">Object to convert</param>
|
||||
/// <param name="fieldType">Field type for the passed object</param>
|
||||
/// <returns>Binary data for the passed object</returns>
|
||||
private byte[] GetNbtField(object obj, out byte fieldType)
|
||||
{
|
||||
if (obj is byte)
|
||||
{
|
||||
fieldType = 1; // TAG_Byte
|
||||
return new[] { (byte)obj };
|
||||
}
|
||||
else if (obj is short)
|
||||
{
|
||||
fieldType = 2; // TAG_Short
|
||||
return GetShort((short)obj);
|
||||
}
|
||||
else if (obj is int)
|
||||
{
|
||||
fieldType = 3; // TAG_Int
|
||||
return GetInt((int)obj);
|
||||
}
|
||||
else if (obj is long)
|
||||
{
|
||||
fieldType = 4; // TAG_Long
|
||||
return GetLong((long)obj);
|
||||
}
|
||||
else if (obj is float)
|
||||
{
|
||||
fieldType = 5; // TAG_Float
|
||||
return GetFloat((float)obj);
|
||||
}
|
||||
else if (obj is double)
|
||||
{
|
||||
fieldType = 6; // TAG_Double
|
||||
return GetDouble((double)obj);
|
||||
}
|
||||
else if (obj is byte[])
|
||||
{
|
||||
fieldType = 7; // TAG_Byte_Array
|
||||
return (byte[])obj;
|
||||
}
|
||||
else if (obj is string)
|
||||
{
|
||||
fieldType = 8; // TAG_String
|
||||
byte[] stringBytes = Encoding.UTF8.GetBytes((string)obj);
|
||||
return ConcatBytes(GetUShort((ushort)stringBytes.Length), stringBytes);
|
||||
}
|
||||
else if (obj is object[])
|
||||
{
|
||||
fieldType = 9; // TAG_List
|
||||
|
||||
List<object> list = new List<object>((object[])obj);
|
||||
int arrayLengthTotal = list.Count;
|
||||
|
||||
// Treat empty list as TAG_Byte, length 0
|
||||
if (arrayLengthTotal == 0)
|
||||
return ConcatBytes(new[] { (byte)1 }, GetInt(0));
|
||||
|
||||
// Encode first list item, retain its type
|
||||
byte firstItemType;
|
||||
string firstItemTypeString = list[0].GetType().Name;
|
||||
byte[] firstItemBytes = GetNbtField(list[0], out firstItemType);
|
||||
list.RemoveAt(0);
|
||||
|
||||
// Encode further list items, check they have the same type
|
||||
byte subsequentItemType;
|
||||
List<byte> subsequentItemsBytes = new List<byte>();
|
||||
foreach (object item in list)
|
||||
{
|
||||
subsequentItemsBytes.AddRange(GetNbtField(item, out subsequentItemType));
|
||||
if (subsequentItemType != firstItemType)
|
||||
throw new System.IO.InvalidDataException(
|
||||
"GetNbt: Cannot encode object[] list with mixed types: " + firstItemTypeString + ", " + item.GetType().Name + " into NBT!");
|
||||
}
|
||||
|
||||
// Build NBT list: type, length, item array
|
||||
return ConcatBytes(new[] { firstItemType }, GetInt(arrayLengthTotal), firstItemBytes, subsequentItemsBytes.ToArray());
|
||||
}
|
||||
else if (obj is Dictionary<string, object>)
|
||||
{
|
||||
fieldType = 10; // TAG_Compound
|
||||
return GetNbt((Dictionary<string, object>)obj, false);
|
||||
}
|
||||
else if (obj is int[])
|
||||
{
|
||||
fieldType = 11; // TAG_Int_Array
|
||||
|
||||
int[] srcIntList = (int[])obj;
|
||||
List<byte> encIntList = new List<byte>();
|
||||
encIntList.AddRange(GetInt(srcIntList.Length));
|
||||
foreach (int item in srcIntList)
|
||||
encIntList.AddRange(GetInt(item));
|
||||
return encIntList.ToArray();
|
||||
}
|
||||
else if (obj is long[])
|
||||
{
|
||||
fieldType = 12; // TAG_Long_Array
|
||||
|
||||
long[] srcLongList = (long[])obj;
|
||||
List<byte> encLongList = new List<byte>();
|
||||
encLongList.AddRange(GetInt(srcLongList.Length));
|
||||
foreach (long item in srcLongList)
|
||||
encLongList.AddRange(GetLong(item));
|
||||
return encLongList.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new System.IO.InvalidDataException("GetNbt: Cannot encode data type " + obj.GetType().Name + " into NBT!");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build an integer for sending over the network
|
||||
/// </summary>
|
||||
|
|
@ -412,6 +604,30 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return bytes.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get byte array representing a long integer
|
||||
/// </summary>
|
||||
/// <param name="number">Long to process</param>
|
||||
/// <returns>Array ready to send</returns>
|
||||
public byte[] GetLong(long number)
|
||||
{
|
||||
byte[] theLong = BitConverter.GetBytes(number);
|
||||
Array.Reverse(theLong);
|
||||
return theLong;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get byte array representing an integer
|
||||
/// </summary>
|
||||
/// <param name="number">Integer to process</param>
|
||||
/// <returns>Array ready to send</returns>
|
||||
public byte[] GetInt(int number)
|
||||
{
|
||||
byte[] theInt = BitConverter.GetBytes(number);
|
||||
Array.Reverse(theInt);
|
||||
return theInt;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get byte array representing a short
|
||||
/// </summary>
|
||||
|
|
@ -424,6 +640,18 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return theShort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get byte array representing an unsigned short
|
||||
/// </summary>
|
||||
/// <param name="number">Short to process</param>
|
||||
/// <returns>Array ready to send</returns>
|
||||
public byte[] GetUShort(ushort number)
|
||||
{
|
||||
byte[] theShort = BitConverter.GetBytes(number);
|
||||
Array.Reverse(theShort);
|
||||
return theShort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get byte array representing a double
|
||||
/// </summary>
|
||||
|
|
@ -448,7 +676,6 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return theFloat;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get byte array with length information prepended to it
|
||||
/// </summary>
|
||||
|
|
@ -473,7 +700,6 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
public byte[] GetString(string text)
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(text);
|
||||
|
||||
return ConcatBytes(GetVarInt(bytes.Length), bytes);
|
||||
}
|
||||
|
||||
|
|
@ -499,6 +725,42 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return locationBytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a byte array representing the given item as an item slot
|
||||
/// </summary>
|
||||
/// <param name="item">Item</param>
|
||||
/// <returns>Item slot representation</returns>
|
||||
public byte[] GetItemSlot(Item item)
|
||||
{
|
||||
List<byte> slotData = new List<byte>();
|
||||
if (protocolversion > Protocol18Handler.MC113Version)
|
||||
{
|
||||
// MC 1.13 and greater
|
||||
if (item == null || item.IsEmpty)
|
||||
slotData.Add(0); // No item
|
||||
else
|
||||
{
|
||||
slotData.Add(1); // Item is present
|
||||
slotData.AddRange(GetVarInt((int)item.Type));
|
||||
slotData.Add((byte)item.Count);
|
||||
slotData.AddRange(GetNbt(item.NBT));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// MC 1.12.2 and lower
|
||||
if (item == null || item.IsEmpty)
|
||||
slotData.AddRange(GetShort(-1));
|
||||
else
|
||||
{
|
||||
slotData.AddRange(GetShort((short)item.Type));
|
||||
slotData.Add((byte)item.Count);
|
||||
slotData.AddRange(GetNbt(item.NBT));
|
||||
}
|
||||
}
|
||||
return slotData.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Easily append several byte arrays
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
HeldItemChange,
|
||||
InteractEntity,
|
||||
UseItem,
|
||||
ClickWindow,
|
||||
CloseWindow,
|
||||
PlayerBlockPlacement
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using MinecraftClient.Crypto;
|
|||
using MinecraftClient.Proxy;
|
||||
using System.Security.Cryptography;
|
||||
using MinecraftClient.Mapping;
|
||||
using MinecraftClient.Inventory;
|
||||
|
||||
namespace MinecraftClient.Protocol.Handlers
|
||||
{
|
||||
|
|
@ -641,22 +642,32 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return false; //Currently not implemented
|
||||
}
|
||||
|
||||
public bool SendInteractEntityPacket(int EntityID, int type)
|
||||
public bool SendInteractEntity(int EntityID, int type)
|
||||
{
|
||||
return false; //Currently not implemented
|
||||
}
|
||||
|
||||
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand)
|
||||
public bool SendInteractEntity(int EntityID, int type, float X, float Y, float Z, int hand)
|
||||
{
|
||||
return false; //Currently not implemented
|
||||
}
|
||||
|
||||
public bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z)
|
||||
public bool SendInteractEntity(int EntityID, int type, float X, float Y, float Z)
|
||||
{
|
||||
return false; //Currently not implemented
|
||||
}
|
||||
|
||||
public bool SendUseItemPacket(int hand)
|
||||
public bool SendUseItem(int hand)
|
||||
{
|
||||
return false; //Currently not implemented
|
||||
}
|
||||
|
||||
public bool SendClickWindow(int windowId, int slotId, Item item)
|
||||
{
|
||||
return false; //Currently not implemented
|
||||
}
|
||||
|
||||
public bool SendCloseWindow(int windowId)
|
||||
{
|
||||
return false; //Currently not implemented
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
private bool autocomplete_received = false;
|
||||
private int autocomplete_transaction_id = 0;
|
||||
private readonly List<string> autocomplete_result = new List<string>();
|
||||
private readonly Dictionary<int, short> window_actions = new Dictionary<int, short>();
|
||||
private bool login_phase = true;
|
||||
private int protocolversion;
|
||||
private int currentDimension;
|
||||
|
|
@ -497,23 +498,27 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
case PacketIncomingType.OpenWindow:
|
||||
if (handler.GetInventoryEnabled())
|
||||
{
|
||||
if (protocolversion < MC114Version) // packet changed at 1.14
|
||||
if (protocolversion < MC114Version)
|
||||
{
|
||||
// MC 1.13 or lower
|
||||
byte windowID = dataTypes.ReadNextByte(packetData);
|
||||
string type = dataTypes.ReadNextString(packetData).Replace("minecraft:", "").ToUpper();
|
||||
ContainerTypeOld inventoryType = (ContainerTypeOld)Enum.Parse(typeof(ContainerTypeOld), type);
|
||||
string title = dataTypes.ReadNextString(packetData);
|
||||
byte slots = dataTypes.ReadNextByte(packetData);
|
||||
Container inventory = new Container(windowID, inventoryType, title);
|
||||
handler.OnInventoryOpen(inventory);
|
||||
Container inventory = new Container(windowID, inventoryType, ChatParser.ParseText(title));
|
||||
window_actions[windowID] = 0;
|
||||
handler.OnInventoryOpen(windowID, inventory);
|
||||
}
|
||||
else
|
||||
{
|
||||
int WindowID = dataTypes.ReadNextVarInt(packetData);
|
||||
int WindowType = dataTypes.ReadNextVarInt(packetData);
|
||||
// MC 1.14 or greater
|
||||
int windowID = dataTypes.ReadNextVarInt(packetData);
|
||||
int windowType = dataTypes.ReadNextVarInt(packetData);
|
||||
string title = dataTypes.ReadNextString(packetData);
|
||||
Container inventory = new Container(WindowID, WindowType, title);
|
||||
handler.OnInventoryOpen(inventory);
|
||||
Container inventory = new Container(windowID, windowType, ChatParser.ParseText(title));
|
||||
window_actions[windowID] = 0;
|
||||
handler.OnInventoryOpen(windowID, inventory);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -521,103 +526,32 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
if (handler.GetInventoryEnabled())
|
||||
{
|
||||
byte windowID = dataTypes.ReadNextByte(packetData);
|
||||
window_actions[windowID] = 0;
|
||||
handler.OnInventoryClose(windowID);
|
||||
}
|
||||
break;
|
||||
case PacketIncomingType.WindowItems:
|
||||
if (handler.GetInventoryEnabled())
|
||||
{
|
||||
// MC 1.12.2 or lower
|
||||
if (protocolversion < MC113Version)
|
||||
{
|
||||
byte id = dataTypes.ReadNextByte(packetData);
|
||||
byte windowId = dataTypes.ReadNextByte(packetData);
|
||||
short elements = dataTypes.ReadNextShort(packetData);
|
||||
Dictionary<int, Item> itemsList = new Dictionary<int, Item>(); // index is SlotID
|
||||
|
||||
for (int i = 0; i < elements; i++)
|
||||
Dictionary<int, Item> inventorySlots = new Dictionary<int, Item>();
|
||||
for (short slotId = 0; slotId < elements; slotId++)
|
||||
{
|
||||
short itemID = dataTypes.ReadNextShort(packetData);
|
||||
if (itemID == -1) continue;
|
||||
byte itemCount = dataTypes.ReadNextByte(packetData);
|
||||
short itemDamage = dataTypes.ReadNextShort(packetData);
|
||||
Dictionary<string, object> NBT = new Dictionary<string, object>();
|
||||
//TODO: Add to the dictionary for the inventory its in using the id
|
||||
if (packetData.ToArray().Count() > 0)
|
||||
{
|
||||
NBT = dataTypes.ReadNextNbt(packetData);
|
||||
}
|
||||
Item item = new Item(itemID, itemCount, itemDamage, NBT);
|
||||
itemsList.Add(i, item);
|
||||
}
|
||||
handler.OnWindowItems(id, itemsList);
|
||||
}
|
||||
else
|
||||
{
|
||||
// MC 1.13 after
|
||||
byte id = dataTypes.ReadNextByte(packetData);
|
||||
short elements = dataTypes.ReadNextShort(packetData);
|
||||
Dictionary<int, Item> itemsList = new Dictionary<int, Item>(); // index is SlotID
|
||||
for (int i = 0; i < elements; i++)
|
||||
{
|
||||
bool haveItem = dataTypes.ReadNextBool(packetData);
|
||||
if (haveItem)
|
||||
{
|
||||
int itemID = dataTypes.ReadNextVarInt(packetData);
|
||||
byte itemCount = dataTypes.ReadNextByte(packetData);
|
||||
dataTypes.ReadNextNbt(packetData);
|
||||
|
||||
Item item = new Item(itemID, itemCount, i);
|
||||
itemsList.Add(i, item);
|
||||
}
|
||||
}
|
||||
handler.OnWindowItems(id, itemsList);
|
||||
Item item = dataTypes.ReadNextItemSlot(packetData);
|
||||
if (item != null)
|
||||
inventorySlots[slotId] = item;
|
||||
}
|
||||
handler.OnWindowItems(windowId, inventorySlots);
|
||||
}
|
||||
break;
|
||||
case PacketIncomingType.SetSlot:
|
||||
if (handler.GetInventoryEnabled())
|
||||
{
|
||||
// MC 1.12.2 or lower
|
||||
if (protocolversion < MC113Version)
|
||||
{
|
||||
byte WindowID = dataTypes.ReadNextByte(packetData);
|
||||
short SlotID = dataTypes.ReadNextShort(packetData);
|
||||
short ItemID = dataTypes.ReadNextShort(packetData);
|
||||
if (ItemID == -1)
|
||||
{
|
||||
handler.OnSlotClear(WindowID, SlotID);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte Count = dataTypes.ReadNextByte(packetData);
|
||||
short itemDamage = dataTypes.ReadNextShort(packetData); // useless so ignored
|
||||
Dictionary<string, object> NBT = new Dictionary<string, object>();
|
||||
//TODO: Add to the dictionary for the inventory its in using the id
|
||||
if (packetData.ToArray().Count() > 0)
|
||||
{
|
||||
NBT = dataTypes.ReadNextNbt(packetData);
|
||||
}
|
||||
handler.OnSetSlot(WindowID, SlotID, ItemID, Count, NBT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// MC 1.13 after
|
||||
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, ItemID, Count, NBT);
|
||||
}
|
||||
else
|
||||
{
|
||||
handler.OnSlotClear(WindowID, SlotID);
|
||||
}
|
||||
}
|
||||
byte windowID = dataTypes.ReadNextByte(packetData);
|
||||
short slotID = dataTypes.ReadNextShort(packetData);
|
||||
Item item = dataTypes.ReadNextItemSlot(packetData);
|
||||
handler.OnSetSlot(windowID, slotID, item);
|
||||
}
|
||||
break;
|
||||
case PacketIncomingType.ResourcePackSend:
|
||||
|
|
@ -1285,7 +1219,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
/// <param name="EntityID"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public bool SendInteractEntityPacket(int EntityID, int type)
|
||||
public bool SendInteractEntity(int EntityID, int type)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -1300,7 +1234,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
catch (ObjectDisposedException) { return false; }
|
||||
}
|
||||
// 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 SendInteractEntity(int EntityID, int type, float X, float Y, float Z, int hand)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -1318,12 +1252,12 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
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 SendInteractEntity(int EntityID, int type, float X, float Y, float Z)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool SendUseItemPacket(int hand)
|
||||
public bool SendUseItem(int hand)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -1370,5 +1304,45 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
catch (System.IO.IOException) { return false; }
|
||||
catch (ObjectDisposedException) { return false; }
|
||||
}
|
||||
|
||||
public bool SendClickWindow(int windowId, int slotId, Item item)
|
||||
{
|
||||
try
|
||||
{
|
||||
short actionNumber = (short)(window_actions[windowId] + 1);
|
||||
window_actions[windowId] = actionNumber;
|
||||
|
||||
List<byte> packet = new List<byte>();
|
||||
packet.Add((byte)windowId);
|
||||
packet.AddRange(dataTypes.GetShort((short)slotId));
|
||||
packet.Add(0); // Left mouse click
|
||||
packet.AddRange(dataTypes.GetShort(actionNumber));
|
||||
|
||||
// Operation mode = 0 (default)
|
||||
if (protocolversion >= MC19Version)
|
||||
packet.AddRange(dataTypes.GetVarInt(0));
|
||||
else packet.Add(0);
|
||||
|
||||
packet.AddRange(dataTypes.GetItemSlot(item));
|
||||
|
||||
SendPacket(PacketOutgoingType.ClickWindow, packet);
|
||||
return true;
|
||||
}
|
||||
catch (SocketException) { return false; }
|
||||
catch (System.IO.IOException) { return false; }
|
||||
catch (ObjectDisposedException) { return false; }
|
||||
}
|
||||
|
||||
public bool SendCloseWindow(int windowId)
|
||||
{
|
||||
try
|
||||
{
|
||||
SendPacket(PacketOutgoingType.CloseWindow, new[] { (byte)windowId });
|
||||
return true;
|
||||
}
|
||||
catch (SocketException) { return false; }
|
||||
catch (System.IO.IOException) { return false; }
|
||||
catch (ObjectDisposedException) { return false; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,6 +306,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
case PacketOutgoingType.HeldItemChange: return 0x17;
|
||||
case PacketOutgoingType.InteractEntity: return 0x02;
|
||||
case PacketOutgoingType.TeleportConfirm: throw new InvalidOperationException("Teleport confirm is not supported in protocol " + protocol);
|
||||
case PacketOutgoingType.ClickWindow: return 0x0E;
|
||||
case PacketOutgoingType.CloseWindow: return 0x0D;
|
||||
}
|
||||
}
|
||||
else if (protocol <= Protocol18Handler.MC1112Version) // MC 1.9, 1,10 and 1.11
|
||||
|
|
@ -324,6 +326,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
case PacketOutgoingType.TeleportConfirm: return 0x00;
|
||||
case PacketOutgoingType.HeldItemChange: return 0x17;
|
||||
case PacketOutgoingType.InteractEntity: return 0x0A;
|
||||
case PacketOutgoingType.ClickWindow: return 0x07;
|
||||
case PacketOutgoingType.CloseWindow: return 0x08;
|
||||
}
|
||||
}
|
||||
else if (protocol <= Protocol18Handler.MC112Version) // MC 1.12
|
||||
|
|
@ -342,6 +346,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
case PacketOutgoingType.TeleportConfirm: return 0x00;
|
||||
case PacketOutgoingType.HeldItemChange: return 0x1A;
|
||||
case PacketOutgoingType.InteractEntity: return 0x0B;
|
||||
case PacketOutgoingType.ClickWindow: return 0x07;
|
||||
case PacketOutgoingType.CloseWindow: return 0x08;
|
||||
}
|
||||
}
|
||||
else if (protocol <= Protocol18Handler.MC1122Version) // 1.12.2
|
||||
|
|
@ -360,6 +366,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
case PacketOutgoingType.TeleportConfirm: return 0x00;
|
||||
case PacketOutgoingType.HeldItemChange: return 0x1F;
|
||||
case PacketOutgoingType.InteractEntity: return 0x0A;
|
||||
case PacketOutgoingType.ClickWindow: return 0x07;
|
||||
case PacketOutgoingType.CloseWindow: return 0x08;
|
||||
}
|
||||
}
|
||||
else if (protocol < Protocol18Handler.MC114Version) // MC 1.13 to 1.13.2
|
||||
|
|
@ -378,6 +386,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
case PacketOutgoingType.TeleportConfirm: return 0x00;
|
||||
case PacketOutgoingType.HeldItemChange: return 0x21;
|
||||
case PacketOutgoingType.InteractEntity: return 0x0D;
|
||||
case PacketOutgoingType.ClickWindow: return 0x08;
|
||||
case PacketOutgoingType.CloseWindow: return 0x09;
|
||||
}
|
||||
}
|
||||
else // MC 1.14 to 1.15
|
||||
|
|
@ -398,6 +408,8 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
case PacketOutgoingType.InteractEntity: return 0x0E;
|
||||
case PacketOutgoingType.UseItem: return 0x2D;
|
||||
case PacketOutgoingType.PlayerBlockPlacement: return 0x2C;
|
||||
case PacketOutgoingType.ClickWindow: return 0x09;
|
||||
case PacketOutgoingType.CloseWindow: return 0x0A;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using MinecraftClient.Crypto;
|
||||
using MinecraftClient.Mapping;
|
||||
using MinecraftClient.Inventory;
|
||||
|
||||
namespace MinecraftClient.Protocol
|
||||
{
|
||||
|
|
@ -98,7 +99,7 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="EntityID">Entity ID to interact with</param>
|
||||
/// <param name="type">Type of interaction (0: interact, 1: attack, 2: interact at)</param>
|
||||
/// <returns>True if packet was successfully sent</returns>
|
||||
bool SendInteractEntityPacket(int EntityID, int type);
|
||||
bool SendInteractEntity(int EntityID, int type);
|
||||
|
||||
/// <summary>
|
||||
/// Send an entity interaction packet to the server.
|
||||
|
|
@ -110,7 +111,7 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="Z">Z coordinate for "interact at"</param>
|
||||
/// <param name="hand">Player hand (0: main hand, 1: off hand)</param>
|
||||
/// <returns>True if packet was successfully sent</returns>
|
||||
bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z, int hand);
|
||||
bool SendInteractEntity(int EntityID, int type, float X, float Y, float Z, int hand);
|
||||
|
||||
/// <summary>
|
||||
/// Send an entity interaction packet to the server.
|
||||
|
|
@ -121,14 +122,29 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="Y">Y coordinate for "interact at"</param>
|
||||
/// <param name="Z">Z coordinate for "interact at"</param>
|
||||
/// <returns>True if packet was successfully sent</returns>
|
||||
bool SendInteractEntityPacket(int EntityID, int type, float X, float Y, float Z);
|
||||
bool SendInteractEntity(int EntityID, int type, float X, float Y, float Z);
|
||||
|
||||
/// <summary>
|
||||
/// Send a use item packet to the server
|
||||
/// </summary>
|
||||
/// <param name="hand">0: main hand, 1: off hand</param>
|
||||
/// <returns>True if packet was successfully sent</returns>
|
||||
bool SendUseItemPacket(int hand);
|
||||
bool SendUseItem(int hand);
|
||||
|
||||
/// <summary>
|
||||
/// Send a click window slot packet to the server
|
||||
/// </summary>
|
||||
/// <param name="windowId">Id of the window being clicked</param>
|
||||
/// <param name="slotId">Id of the clicked slot</param>
|
||||
/// <param name="item">Item in the clicked slot</param>
|
||||
/// <returns>True if packet was successfully sent</returns>
|
||||
bool SendClickWindow(int windowId, int slotId, Item item);
|
||||
|
||||
/// <summary>
|
||||
/// Send a close window packet to the server
|
||||
/// </summary>
|
||||
/// <param name="windowId">Id of the window being closed</param>
|
||||
bool SendCloseWindow(int windowId);
|
||||
|
||||
/// <summary>
|
||||
/// Send player block placement packet to the server
|
||||
|
|
|
|||
|
|
@ -53,12 +53,12 @@ namespace MinecraftClient.Protocol
|
|||
/// <summary>
|
||||
/// Called when an inventory is opened
|
||||
/// </summary>
|
||||
void OnInventoryOpen(Container inventory);
|
||||
void OnInventoryOpen(int inventoryID, Container inventory);
|
||||
|
||||
/// <summary>
|
||||
/// Called when an inventory is closed
|
||||
/// </summary>
|
||||
void OnInventoryClose(byte inventoryID);
|
||||
void OnInventoryClose(int inventoryID);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the player respawns, which happens on login, respawn and world change.
|
||||
|
|
@ -199,26 +199,17 @@ namespace MinecraftClient.Protocol
|
|||
/// <summary>
|
||||
/// Called when inventory items have been received
|
||||
/// </summary>
|
||||
/// <param name="type">Inventory type</param>
|
||||
/// <param name="inventoryID">Inventory ID</param>
|
||||
/// <param name="itemList">Item list</param>
|
||||
void OnWindowItems(int type, Dictionary<int, MinecraftClient.Inventory.Item> itemList);
|
||||
|
||||
/// <summary>
|
||||
/// Called when a single slot has been cleared inside an inventory
|
||||
/// </summary>
|
||||
/// <param name="WindowID">Inventory ID</param>
|
||||
/// <param name="SlotID">Slot ID</param>
|
||||
void OnSlotClear(byte WindowID, short SlotID);
|
||||
void OnWindowItems(byte inventoryID, Dictionary<int, MinecraftClient.Inventory.Item> itemList);
|
||||
|
||||
/// <summary>
|
||||
/// Called when a single slot has been updated inside an inventory
|
||||
/// </summary>
|
||||
/// <param name="WindowID">Inventory ID</param>
|
||||
/// <param name="SlotID">Slot ID</param>
|
||||
/// <param name="ItemID">Item ID</param>
|
||||
/// <param name="Count">Item Count</param>
|
||||
/// <param name="NBT">Item Metadata</param>
|
||||
void OnSetSlot(byte WindowID, short SlotID, int ItemID, byte Count, Dictionary<string, object> NBT);
|
||||
/// <param name="inventoryID">Window ID</param>
|
||||
/// <param name="slotID">Slot ID</param>
|
||||
/// <param name="item">Item (may be null for empty slot)</param>
|
||||
void OnSetSlot(byte inventoryID, short slotID, Item item);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the Player entity ID has been received from the server
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue