From 311815be9f95b9660daee2edf1ef67f72bbf2664 Mon Sep 17 00:00:00 2001 From: ReinforceZwei <39955851+ReinforceZwei@users.noreply.github.com> Date: Thu, 26 Mar 2020 19:10:28 +0800 Subject: [PATCH] Fix backwards support for entity, inventory handling Seems AutoAttack not work in 1.12.2 Entity handling currently only support 1.13 or higher --- MinecraftClient/McTcpClient.cs | 24 +++ .../Protocol/Handlers/Protocol18.cs | 137 ++++++++++++------ 2 files changed, 118 insertions(+), 43 deletions(-) diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs index 3b28c704..d5a1d231 100644 --- a/MinecraftClient/McTcpClient.cs +++ b/MinecraftClient/McTcpClient.cs @@ -564,6 +564,27 @@ namespace MinecraftClient return entityHandlingEnabled; } + public bool SetEntityHandlingEnabled(bool enabled) + { + if (!enabled) + { + if (entityHandlingEnabled) + { + entityHandlingEnabled = false; + return true; + } + else + { + return false; + } + } + else + { + // Entity Handling cannot be enabled in runtime (or after joining server) + return false; + } + } + /// /// Get client player's inventory items /// @@ -1104,6 +1125,7 @@ namespace MinecraftClient /// public void OnSpawnEntity(int EntityID, int TypeID, Guid UUID, Location location) { + if (entities.ContainsKey(EntityID)) return; Entity entity = new Entity(EntityID, TypeID, EntityType.NonLivingThings, location); entities.Add(EntityID, entity); foreach (ChatBot bot in bots.ToArray()) @@ -1120,6 +1142,7 @@ namespace MinecraftClient /// Cannot determine is a Mob or a Cuty Animal public void OnSpawnLivingEntity(int EntityID, int TypeID, Guid UUID, Location location) { + if (entities.ContainsKey(EntityID)) return; Entity entity = new Entity(EntityID, TypeID, EntityType.MobAndAnimal, location); entities.Add(EntityID, entity); foreach (ChatBot bot in bots.ToArray()) @@ -1136,6 +1159,7 @@ namespace MinecraftClient /// public void OnSpawnPlayer(int EntityID, Guid UUID, Location location, byte Yaw, byte Pitch) { + if (entities.ContainsKey(EntityID)) return; Entity entity = new Entity(EntityID, EntityType.Player, location); entities.Add(EntityID, entity); foreach (ChatBot bot in bots.ToArray()) diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 38164159..93593985 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -69,12 +69,18 @@ namespace MinecraftClient.Protocol.Handlers handler.SetTerrainEnabled(false); } - if (handler.GetInventoryEnabled() && protocolversion > MC1152Version) + if (handler.GetInventoryEnabled() && (protocolversion > MC1152Version || protocolversion < MC110Version)) { ConsoleIO.WriteLineFormatted("§8Inventories are currently not handled for that MC version."); handler.SetInventoryEnabled(false); } + if(handler.GetEntityHandlingEnabled() && protocolversion < MC1122Version) + { + ConsoleIO.WriteLineFormatted("§8Entities are currently not handled for that MC version."); + handler.SetInventoryEnabled(false); + } + if (protocolversion >= MC113Version) { if (protocolVersion > MC1152Version && handler.GetTerrainEnabled()) @@ -525,61 +531,96 @@ namespace MinecraftClient.Protocol.Handlers case PacketIncomingType.WindowItems: if (handler.GetInventoryEnabled()) { - /* - * Following commented code will crash - * - byte id = dataTypes.ReadNextByte(packetData); - short elements = dataTypes.ReadNextShort(packetData); + // MC 1.12.2 or lower + if (protocolversion < MC113Version) + { + byte id = dataTypes.ReadNextByte(packetData); + short elements = dataTypes.ReadNextShort(packetData); + Dictionary itemsList = new Dictionary(); // index is SlotID - for (int i = 0; i < elements; i++) - { - short itemID = dataTypes.ReadNextShort(packetData); - if (itemID == -1) continue; - byte itemCount = dataTypes.ReadNextByte(packetData); - short itemDamage = dataTypes.ReadNextShort(packetData); - Item item = new Item(itemID, itemCount, itemDamage, 0); - //TODO: Add to the dictionary for the inventory its in using the id - if (packetData.ToArray().Count() > 0) + for (int i = 0; i < elements; i++) { - dataTypes.ReadNextNbt(packetData); - } - } - */ - byte id = dataTypes.ReadNextByte(packetData); - short elements = dataTypes.ReadNextShort(packetData); - Dictionary itemsList = new Dictionary(); // index is SlotID - for(int i = 0; i < elements; i++) - { - bool haveItem = dataTypes.ReadNextBool(packetData); - if (haveItem) - { - int itemID = dataTypes.ReadNextVarInt(packetData); + short itemID = dataTypes.ReadNextShort(packetData); + if (itemID == -1) continue; byte itemCount = dataTypes.ReadNextByte(packetData); - dataTypes.ReadNextNbt(packetData); - - Item item = new Item(itemID, itemCount); + short itemDamage = dataTypes.ReadNextShort(packetData); + Dictionary NBT = new Dictionary(); + //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 itemsList = new Dictionary(); // 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); + itemsList.Add(i, item); + } + } + handler.OnWindowItems(id, itemsList); } - handler.OnWindowItems(id, itemsList); } break; case PacketIncomingType.SetSlot: if(handler.GetInventoryEnabled()) { - byte WindowID = dataTypes.ReadNextByte(packetData); - short SlotID = dataTypes.ReadNextShort(packetData); - bool Present = dataTypes.ReadNextBool(packetData); - if (Present) + // MC 1.12.2 or lower + if (protocolversion < MC113Version) { - int ItemID = dataTypes.ReadNextVarInt(packetData); - byte Count = dataTypes.ReadNextByte(packetData); - Dictionary NBT = dataTypes.ReadNextNbt(packetData); - handler.OnSetSlot(WindowID, SlotID, Present, ItemID, Count, NBT); + byte WindowID = dataTypes.ReadNextByte(packetData); + short SlotID = dataTypes.ReadNextShort(packetData); + short ItemID = dataTypes.ReadNextShort(packetData); + if (ItemID == -1) + { + handler.OnSetSlot(WindowID, SlotID, false); + } + else + { + byte Count = dataTypes.ReadNextByte(packetData); + short itemDamage = dataTypes.ReadNextShort(packetData); // useless so ignored + Dictionary NBT = new Dictionary(); + //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, true, ItemID, Count, NBT); + } } else { - handler.OnSetSlot(WindowID, SlotID, Present); + // 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 NBT = dataTypes.ReadNextNbt(packetData); + handler.OnSetSlot(WindowID, SlotID, Present, ItemID, Count, NBT); + } + else + { + handler.OnSetSlot(WindowID, SlotID, Present); + } } } break; @@ -597,7 +638,11 @@ namespace MinecraftClient.Protocol.Handlers if (handler.GetEntityHandlingEnabled()) { int EntityID = dataTypes.ReadNextVarInt(packetData); - Guid EntityUUID = dataTypes.ReadNextUUID(packetData); + Guid EntityUUID = Guid.Empty; + if (protocolversion > MC18Version) + { + EntityUUID = dataTypes.ReadNextUUID(packetData); + } int EntityType = dataTypes.ReadNextVarInt(packetData); Double X = dataTypes.ReadNextDouble(packetData); Double Y = dataTypes.ReadNextDouble(packetData); @@ -619,7 +664,11 @@ namespace MinecraftClient.Protocol.Handlers if (handler.GetEntityHandlingEnabled()) { int EntityID = dataTypes.ReadNextVarInt(packetData); - Guid EntityUUID = dataTypes.ReadNextUUID(packetData); + Guid EntityUUID = Guid.Empty; + if (protocolversion > MC18Version) + { + EntityUUID = dataTypes.ReadNextUUID(packetData); + } int EntityType = dataTypes.ReadNextVarInt(packetData); Double X = dataTypes.ReadNextDouble(packetData); Double Y = dataTypes.ReadNextDouble(packetData); @@ -631,6 +680,8 @@ namespace MinecraftClient.Protocol.Handlers short VelocityY = dataTypes.ReadNextShort(packetData); short VelocityZ = dataTypes.ReadNextShort(packetData); + // packet before 1.15 has metadata at the end + Location EntityLocation = new Location(X, Y, Z); handler.OnSpawnLivingEntity(EntityID, EntityType, EntityUUID, EntityLocation);