diff --git a/MinecraftClient/Inventory/Container.cs b/MinecraftClient/Inventory/Container.cs
index 85f3e9a8..b39892b6 100644
--- a/MinecraftClient/Inventory/Container.cs
+++ b/MinecraftClient/Inventory/Container.cs
@@ -25,6 +25,11 @@ namespace MinecraftClient.Inventory
///
public string Title;
+ ///
+ /// state of container
+ ///
+ public int StateID;
+
///
/// Container Items
///
diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs
index 94eda171..9d0fbf7c 100644
--- a/MinecraftClient/McClient.cs
+++ b/MinecraftClient/McClient.cs
@@ -1066,7 +1066,7 @@ namespace MinecraftClient
/// How long to wait until the path is evaluated (default: 5 seconds)
/// When location is unreachable, computation will reach timeout, then optionally fallback to a close location within maxOffset
/// True if a path has been found
- public bool MoveTo(Location location, bool allowUnsafe = false, bool allowDirectTeleport = false, int maxOffset = 0, int minOffset = 0, TimeSpan? timeout=null)
+ public bool MoveTo(Location location, bool allowUnsafe = false, bool allowDirectTeleport = false, int maxOffset = 0, int minOffset = 0, TimeSpan? timeout = null)
{
lock (locationLock)
{
@@ -1244,7 +1244,7 @@ namespace MinecraftClient
item = inventories[windowId].Items[slotId];
// Inventory update must be after sending packet
- bool result = handler.SendWindowAction(windowId, slotId, action, item);
+ bool result = handler.SendWindowAction(windowId, slotId, action, item, inventories[windowId].Items, inventories[windowId].StateID);
// Update our inventory base on action type
var inventory = GetInventory(windowId);
@@ -1707,7 +1707,7 @@ namespace MinecraftClient
/// Teleporting to other entityies is NOT implemented yet
public bool Spectate(Entity entity)
{
- if(entity.Type == EntityType.Player)
+ if (entity.Type == EntityType.Player)
{
return SpectateByUUID(entity.UUID);
}
@@ -1723,9 +1723,9 @@ namespace MinecraftClient
/// UUID of player/entity to teleport to
public bool SpectateByUUID(Guid UUID)
{
- if(GetGamemode() == 3)
+ if (GetGamemode() == 3)
{
- if(InvokeRequired)
+ if (InvokeRequired)
return InvokeOnMainThread(() => SpectateByUUID(UUID));
return handler.SendSpectate(UUID);
}
@@ -1855,7 +1855,7 @@ namespace MinecraftClient
/// Check if the client is currently processing a Movement.
///
/// true if a movement is currently handled
- public bool ClientIsMoving()
+ public bool ClientIsMoving()
{
return terrainAndMovementsEnabled && locationReceived && ((steps != null && steps.Count > 0) || (path != null && path.Count > 0));
}
@@ -2030,11 +2030,12 @@ namespace MinecraftClient
///
/// Inventory ID
/// Item list, key = slot ID, value = Item information
- public void OnWindowItems(byte inventoryID, Dictionary itemList)
+ public void OnWindowItems(byte inventoryID, Dictionary itemList, int stateId)
{
if (inventories.ContainsKey(inventoryID))
{
inventories[inventoryID].Items = itemList;
+ inventories[inventoryID].StateID = stateId;
DispatchBotEvent(bot => bot.OnInventoryUpdate(inventoryID));
}
}
diff --git a/MinecraftClient/Protocol/Handlers/DataTypes.cs b/MinecraftClient/Protocol/Handlers/DataTypes.cs
index 93c6562e..3bcacf7b 100644
--- a/MinecraftClient/Protocol/Handlers/DataTypes.cs
+++ b/MinecraftClient/Protocol/Handlers/DataTypes.cs
@@ -401,7 +401,7 @@ namespace MinecraftClient.Protocol.Handlers
{
entityType = entityPalette.FromId(ReadNextByte(cache), living);
}
-
+
Double entityX = ReadNextDouble(cache);
Double entityY = ReadNextDouble(cache);
Double entityZ = ReadNextDouble(cache);
@@ -1028,6 +1028,23 @@ namespace MinecraftClient.Protocol.Handlers
return slotData.ToArray();
}
+ public string ByteArrayToString(byte[] ba)
+ {
+ return BitConverter.ToString(ba).Replace("-", " ");
+ }
+
+ public byte[] GetSlotsArray(Dictionary items, ItemPalette itemPalette)
+ {
+ byte[] slotsArray = new byte[items.Count];
+
+ foreach (KeyValuePair item in items)
+ {
+ slotsArray = ConcatBytes(slotsArray, GetShort((short)item.Key), GetItemSlot(item.Value, itemPalette));
+ }
+
+ return slotsArray;
+ }
+
///
/// Get protocol block face from Direction
///
diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs
index c0b04c33..c7e0b9ef 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol16.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs
@@ -94,7 +94,8 @@ namespace MinecraftClient.Protocol.Handlers
int nbr = 0;
switch (id)
{
- case 0x00: byte[] keepalive = new byte[5] { 0, 0, 0, 0, 0 };
+ case 0x00:
+ byte[] keepalive = new byte[5] { 0, 0, 0, 0, 0 };
Receive(keepalive, 1, 4, SocketFlags.None);
handler.OnServerKeepAlive();
Send(keepalive); break;
@@ -183,11 +184,13 @@ namespace MinecraftClient.Protocol.Handlers
case 0xCF: if (protocolversion > 51) { readNextString(); readData(1); readNextString(); } readData(4); break;
case 0xD0: if (protocolversion > 51) { readData(1); readNextString(); } break;
case 0xD1: if (protocolversion > 51) { readNextTeamData(); } break;
- case 0xFA: string channel = readNextString();
+ case 0xFA:
+ string channel = readNextString();
byte[] payload = readNextByteArray();
handler.OnPluginChannelMessage(channel, payload);
break;
- case 0xFF: string reason = readNextString();
+ case 0xFF:
+ string reason = readNextString();
handler.OnConnectionLost(ChatBot.DisconnectReason.InGameKick, reason); break;
default: return false; //unknown packet!
}
@@ -666,12 +669,12 @@ namespace MinecraftClient.Protocol.Handlers
}
catch (SocketException) { return false; }
}
-
+
public bool SendUpdateSign(Location location, string line1, string line2, string line3, string line4)
{
return false; //Currently not implemented
}
-
+
public bool SendBrandInfo(string brandInfo)
{
return false; //Only supported since MC 1.7
@@ -701,23 +704,23 @@ namespace MinecraftClient.Protocol.Handlers
{
return false; //Currently not implemented
}
-
+
public bool SendInteractEntity(int EntityID, int type, int hand)
{
return false; //Currently not implemented
}
-
+
public bool UpdateCommandBlock(Location location, string command, CommandBlockMode mode, CommandBlockFlags flags)
{
return false; //Currently not implemented
}
-
+
public bool SendUseItem(int hand)
{
return false; //Currently not implemented
}
- public bool SendWindowAction(int windowId, int slotId, WindowActionType action, Item item)
+ public bool SendWindowAction(int windowId, int slotId, WindowActionType action, Item item, Dictionary Items, int stateId)
{
return false; //Currently not implemented
}
@@ -759,7 +762,8 @@ namespace MinecraftClient.Protocol.Handlers
/// packet Data
public bool SendPluginChannelPacket(string channel, byte[] data)
{
- try {
+ try
+ {
byte[] channelLength = BitConverter.GetBytes((short)channel.Length);
Array.Reverse(channelLength);
diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs
index 81aae204..aa51647f 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol18.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs
@@ -850,7 +850,7 @@ namespace MinecraftClient.Protocol.Handlers
if (item != null)
inventorySlots[slotId] = item;
}
- handler.OnWindowItems(windowId, inventorySlots);
+ handler.OnWindowItems(windowId, inventorySlots, stateId);
}
break;
case PacketTypesIn.SetSlot:
@@ -1895,7 +1895,7 @@ namespace MinecraftClient.Protocol.Handlers
catch (ObjectDisposedException) { return false; }
}
- public bool SendWindowAction(int windowId, int slotId, WindowActionType action, Item item)
+ public bool SendWindowAction(int windowId, int slotId, WindowActionType action, Item item, Dictionary items, int stateId)
{
try
{
@@ -1931,14 +1931,51 @@ namespace MinecraftClient.Protocol.Handlers
}
List packet = new List();
+
+ log.Info("Window id: " + windowId + " - State id: " + stateId + " - Slot id: " + slotId + " - Mode: " + mode);
+ log.Info("Bytes > " + (byte)windowId + " - State id: " + dataTypes.ByteArrayToString(dataTypes.GetVarInt(stateId)) + " - Slot id: " + dataTypes.ByteArrayToString(dataTypes.GetVarInt(slotId)) + " - Mode: " + dataTypes.ByteArrayToString(dataTypes.GetVarInt(mode)));
+
packet.Add((byte)windowId);
- packet.AddRange(dataTypes.GetShort((short)slotId));
+
+ // 1.18+
+ if (protocolversion > MC1171Version)
+ {
+ packet.AddRange(dataTypes.GetVarInt(stateId));
+ packet.AddRange(dataTypes.GetShort((short)slotId));
+ }
+ // 1.17.1
+ else if (protocolversion == MC1171Version)
+ {
+ packet.AddRange(dataTypes.GetShort((short)slotId));
+ packet.AddRange(dataTypes.GetVarInt(stateId));
+ }
+ // Older
+ else
+ {
+ packet.AddRange(dataTypes.GetShort((short)slotId));
+ }
+
packet.Add(button);
if (protocolversion < MC117Version) packet.AddRange(dataTypes.GetShort(actionNumber));
- if (protocolversion >= MC19Version)
+ if (protocolversion >= MC1165Version)
packet.AddRange(dataTypes.GetVarInt(mode));
- else packet.Add(mode);
+
+ // 1.17+
+ if (protocolversion >= MC117Version)
+ {
+ byte[] arrayOfSlots = dataTypes.GetSlotsArray(items, itemPalette);
+
+ log.Info("Length: " + sizeof(byte) * arrayOfSlots.Length);
+ log.Info("Array: " + dataTypes.ByteArrayToString(arrayOfSlots));
+
+ packet.AddRange(dataTypes.GetVarInt(sizeof(byte) * arrayOfSlots.Length));
+ packet.AddRange(arrayOfSlots);
+ }
+
packet.AddRange(dataTypes.GetItemSlot(item, itemPalette));
+
+ log.Info("Packet data: " + dataTypes.ByteArrayToString(packet.ToArray()));
+
SendPacket(PacketTypesOut.ClickWindow, packet);
return true;
}
diff --git a/MinecraftClient/Protocol/IMinecraftCom.cs b/MinecraftClient/Protocol/IMinecraftCom.cs
index 54d19e77..97aaca35 100644
--- a/MinecraftClient/Protocol/IMinecraftCom.cs
+++ b/MinecraftClient/Protocol/IMinecraftCom.cs
@@ -94,7 +94,7 @@ namespace MinecraftClient.Protocol
/// packet Data
/// True if message was successfully sent
bool SendPluginChannelPacket(string channel, byte[] data);
-
+
///
/// Send Entity Action packet to the server.
///
@@ -102,7 +102,7 @@ namespace MinecraftClient.Protocol
/// Type of packet to send
/// True if packet was successfully sent
bool SendEntityAction(int EntityID, int type);
-
+
///
/// Send a held item change packet to the server.
///
@@ -140,7 +140,7 @@ namespace MinecraftClient.Protocol
/// Z coordinate for "interact at"
/// True if packet was successfully sent
bool SendInteractEntity(int EntityID, int type, float X, float Y, float Z);
-
+
///
/// Send an entity interaction packet to the server.
///
@@ -165,7 +165,7 @@ namespace MinecraftClient.Protocol
/// Action to perform
/// Item in the clicked slot
/// True if packet was successfully sent
- bool SendWindowAction(int windowId, int slotId, WindowActionType action, Item item);
+ bool SendWindowAction(int windowId, int slotId, WindowActionType action, Item item, Dictionary Items, int stateId);
///
/// Request Creative Mode item creation into regular/survival Player Inventory
@@ -220,7 +220,7 @@ namespace MinecraftClient.Protocol
/// New line 4
/// True if packet was succcessfully sent
bool SendUpdateSign(Location location, string line1, string line2, string line3, string line4);
-
+
///
/// Update command block
///
diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs
index 107875c0..2b63d5e7 100644
--- a/MinecraftClient/Protocol/IMinecraftComHandler.cs
+++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs
@@ -263,7 +263,8 @@ namespace MinecraftClient.Protocol
///
/// Inventory ID
/// Item list
- void OnWindowItems(byte inventoryID, Dictionary itemList);
+ /// State ID
+ void OnWindowItems(byte inventoryID, Dictionary itemList, int stateId);
///
/// Called when a single slot has been updated inside an inventory