From 3d8c1121591118e00f7777ff345f5657a7b5143d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Milutinovi=C4=87?= Date: Fri, 1 Jul 2022 18:59:58 +0200 Subject: [PATCH] Implemented "Click Window" for 1.18 (now sending the new required fields), formated few files with Visual Studio formatting. PS: left debug for people to see, I'll remove it once everything is working --- MinecraftClient/Inventory/Container.cs | 5 ++ MinecraftClient/McClient.cs | 15 +++--- .../Protocol/Handlers/DataTypes.cs | 19 +++++++- .../Protocol/Handlers/Protocol16.cs | 24 ++++++---- .../Protocol/Handlers/Protocol18.cs | 47 +++++++++++++++++-- MinecraftClient/Protocol/IMinecraftCom.cs | 10 ++-- .../Protocol/IMinecraftComHandler.cs | 3 +- 7 files changed, 94 insertions(+), 29 deletions(-) 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