diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index 91b921c2..c12c55ae 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -2111,6 +2111,16 @@ namespace MinecraftClient { DispatchBotEvent(bot => bot.OnUpdateScore(entityname, action, objectivename, value)); } + + /// + /// Called when entity metadata added/updated + /// + /// Target entity's ID + /// Metadata + public void OnEntityMetadata(int entityID, Dictionary metadata) + { + + } #endregion } } diff --git a/MinecraftClient/Protocol/Handlers/DataTypes.cs b/MinecraftClient/Protocol/Handlers/DataTypes.cs index c66d3a17..21161d36 100644 --- a/MinecraftClient/Protocol/Handlers/DataTypes.cs +++ b/MinecraftClient/Protocol/Handlers/DataTypes.cs @@ -494,6 +494,126 @@ namespace MinecraftClient.Protocol.Handlers } } + public Dictionary ReadNextMetadata(Queue cache) + { + Dictionary data = new Dictionary(); + byte Key = ReadNextByte(cache); + while (Key != 0xff) + { + int Type = ReadNextVarInt(cache); + // Value's data type is depended on Type + object Value = null; + + // We need to go through every data in order to get all fields in the packet + // Store the value as needed + switch (Type) + { + case 0: // byte + Value = ReadNextByte(cache); + break; + case 1: // VarInt + Value = ReadNextVarInt(cache); + break; + case 2: // Float + Value = ReadNextFloat(cache); + break; + case 3: // String + Value = ReadNextString(cache); + break; + case 4: // Chat + Value = ReadNextString(cache); + break; + case 5: // Optional Chat + if (ReadNextBool(cache)) + { + Value = ReadNextString(cache); + } + break; + case 6: // Slot + Value = ReadNextItemSlot(cache); + break; + case 7: // Boolean + Value = ReadNextBool(cache); + break; + case 8: // Rotation (3x floats) + List t = new List(); + t.Add(ReadNextFloat(cache)); + t.Add(ReadNextFloat(cache)); + t.Add(ReadNextFloat(cache)); + Value = t; + break; + case 9: // Position + Value = ReadNextLocation(cache); + break; + case 10: // Optional Position + if (ReadNextBool(cache)) + { + Value = ReadNextLocation(cache); + } + break; + case 11: // Direction (VarInt) + Value = ReadNextVarInt(cache); + break; + case 12: // Optional UUID + if (ReadNextBool(cache)) + { + Value = ReadNextUUID(cache); + } + break; + case 13: // Optional BlockID (VarInt) + if (ReadNextBool(cache)) + { + Value = ReadNextVarInt(cache); + } + break; + case 14: // NBT + Value = ReadNextNbt(cache); + break; + case 15: // Particle + // Currecutly not handled. Reading data only + int ParticleID = ReadNextVarInt(cache); + switch (ParticleID) + { + case 3: + ReadNextVarInt(cache); + break; + case 14: + ReadNextFloat(cache); + ReadNextFloat(cache); + ReadNextFloat(cache); + ReadNextFloat(cache); + break; + case 23: + ReadNextVarInt(cache); + break; + case 32: + ReadNextItemSlot(cache); + break; + } + break; + case 16: // Villager Data (3x VarInt) + List d = new List(); + d.Add(ReadNextVarInt(cache)); + d.Add(ReadNextVarInt(cache)); + d.Add(ReadNextVarInt(cache)); + Value = d; + break; + case 17: // Optional VarInt + if (ReadNextBool(cache)) + { + Value = ReadNextVarInt(cache); + } + break; + case 18: // Pose + Value = ReadNextVarInt(cache); + break; + } + data.Add(Key, Value); + Key = ReadNextByte(cache); + } + return data; + } + /// /// Build an uncompressed Named Binary Tag blob for sending over the network /// diff --git a/MinecraftClient/Protocol/Handlers/PacketIncomingType.cs b/MinecraftClient/Protocol/Handlers/PacketIncomingType.cs index a612a8f5..03d8da68 100644 --- a/MinecraftClient/Protocol/Handlers/PacketIncomingType.cs +++ b/MinecraftClient/Protocol/Handlers/PacketIncomingType.cs @@ -47,6 +47,7 @@ namespace MinecraftClient.Protocol.Handlers EntityEquipment, EntityVelocity, EntityEffect, + EntityMetadata, TimeUpdate, UpdateHealth, SetExperience, diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index a9f67407..de2f4c04 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -861,6 +861,14 @@ namespace MinecraftClient.Protocol.Handlers handler.OnEntityProperties(EntityID, keys); } break; + case PacketIncomingType.EntityMetadata: + if (handler.GetEntityHandlingEnabled()) + { + int EntityID = dataTypes.ReadNextVarInt(packetData); + Dictionary metadata = dataTypes.ReadNextMetadata(packetData); + handler.OnEntityMetadata(EntityID, metadata); + } + break; case PacketIncomingType.TimeUpdate: long WorldAge = dataTypes.ReadNextLong(packetData); long TimeOfday = dataTypes.ReadNextLong(packetData); diff --git a/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs b/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs index c958dbda..3e3c4ca3 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18PacketTypes.cs @@ -109,6 +109,7 @@ namespace MinecraftClient.Protocol.Handlers case 0x3B: return PacketIncomingType.EntityVelocity; case 0x3C: return PacketIncomingType.EntityEquipment; case 0x4B: return PacketIncomingType.EntityEffect; + case 0x39: return PacketIncomingType.EntityMetadata; case 0x44: return PacketIncomingType.TimeUpdate; case 0x3E: return PacketIncomingType.UpdateHealth; case 0x3D: return PacketIncomingType.SetExperience; @@ -157,6 +158,7 @@ namespace MinecraftClient.Protocol.Handlers case 0x3D: return PacketIncomingType.EntityVelocity; case 0x3E: return PacketIncomingType.EntityEquipment; case 0x4E: return PacketIncomingType.EntityEffect; + case 0x3B: return PacketIncomingType.EntityMetadata; case 0x46: return PacketIncomingType.TimeUpdate; case 0x40: return PacketIncomingType.UpdateHealth; case 0x3F: return PacketIncomingType.SetExperience; @@ -205,6 +207,7 @@ namespace MinecraftClient.Protocol.Handlers case 0x3E: return PacketIncomingType.EntityVelocity; case 0x3F: return PacketIncomingType.EntityEquipment; case 0x4F: return PacketIncomingType.EntityEffect; + case 0x3C: return PacketIncomingType.EntityMetadata; case 0x47: return PacketIncomingType.TimeUpdate; case 0x41: return PacketIncomingType.UpdateHealth; case 0x40: return PacketIncomingType.SetExperience; @@ -253,6 +256,7 @@ namespace MinecraftClient.Protocol.Handlers case 0x41: return PacketIncomingType.EntityVelocity; case 0x42: return PacketIncomingType.EntityEquipment; case 0x53: return PacketIncomingType.EntityEffect; + case 0x3F: return PacketIncomingType.EntityMetadata; case 0x4A: return PacketIncomingType.TimeUpdate; case 0x44: return PacketIncomingType.UpdateHealth; case 0x43: return PacketIncomingType.SetExperience; @@ -301,6 +305,7 @@ namespace MinecraftClient.Protocol.Handlers case 0x41: return PacketIncomingType.EntityVelocity; case 0x46: return PacketIncomingType.EntityEquipment; case 0x59: return PacketIncomingType.EntityEffect; + case 0x43: return PacketIncomingType.EntityMetadata; case 0x4E: return PacketIncomingType.TimeUpdate; case 0x48: return PacketIncomingType.UpdateHealth; case 0x47: return PacketIncomingType.SetExperience; @@ -349,6 +354,7 @@ namespace MinecraftClient.Protocol.Handlers case 0x46: return PacketIncomingType.EntityVelocity; case 0x47: return PacketIncomingType.EntityEquipment; case 0x5A: return PacketIncomingType.EntityEffect; + case 0x44: return PacketIncomingType.EntityMetadata; case 0x4F: return PacketIncomingType.TimeUpdate; case 0x49: return PacketIncomingType.UpdateHealth; case 0x48: return PacketIncomingType.SetExperience; @@ -361,7 +367,7 @@ namespace MinecraftClient.Protocol.Handlers } } else { - switch (packetID) + switch (packetID) // MC 1.16+ { case 0x20: return PacketIncomingType.KeepAlive; case 0x25: return PacketIncomingType.JoinGame; @@ -396,6 +402,7 @@ namespace MinecraftClient.Protocol.Handlers case 0x46: return PacketIncomingType.EntityVelocity; case 0x47: return PacketIncomingType.EntityEquipment; case 0x59: return PacketIncomingType.EntityEffect; + case 0x44: return PacketIncomingType.EntityMetadata; case 0x4E: return PacketIncomingType.TimeUpdate; case 0x49: return PacketIncomingType.UpdateHealth; case 0x48: return PacketIncomingType.SetExperience; diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs index 40ddcf81..64c1dd99 100644 --- a/MinecraftClient/Protocol/IMinecraftComHandler.cs +++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs @@ -192,6 +192,13 @@ namespace MinecraftClient.Protocol /// Dictionary of properties void OnEntityProperties(int entityID, Dictionary prop); + /// + /// Called when entity metadata added/updated + /// + /// Target entity's ID + /// Metadata + void OnEntityMetadata(int entityID, Dictionary metadata); + /// /// Called when the world age has been updated ///