diff --git a/MinecraftClient/Inventory/Enchantment.cs b/MinecraftClient/Inventory/Enchantment.cs new file mode 100644 index 00000000..09b513f9 --- /dev/null +++ b/MinecraftClient/Inventory/Enchantment.cs @@ -0,0 +1,3 @@ +namespace MinecraftClient.Inventory; + +public record Enchantment(Enchantments Type, int Level); \ No newline at end of file diff --git a/MinecraftClient/Inventory/EnchantmentData.cs b/MinecraftClient/Inventory/EnchantmentData.cs index c42dd920..427fe012 100644 --- a/MinecraftClient/Inventory/EnchantmentData.cs +++ b/MinecraftClient/Inventory/EnchantmentData.cs @@ -2,9 +2,9 @@ { public class EnchantmentData { - public Enchantment TopEnchantment { get; set; } - public Enchantment MiddleEnchantment { get; set; } - public Enchantment BottomEnchantment { get; set; } + public Enchantments TopEnchantment { get; set; } + public Enchantments MiddleEnchantment { get; set; } + public Enchantments BottomEnchantment { get; set; } // Seed for rendering Standard Galactic Language (symbols in the enchanting table) (Useful for poeple who use MCC for the protocol) public short Seed { get; set; } diff --git a/MinecraftClient/Inventory/EnchantmentMapping.cs b/MinecraftClient/Inventory/EnchantmentMapping.cs index 1768482e..4f6fca47 100644 --- a/MinecraftClient/Inventory/EnchantmentMapping.cs +++ b/MinecraftClient/Inventory/EnchantmentMapping.cs @@ -10,184 +10,184 @@ namespace MinecraftClient.Inventory { #pragma warning disable format // @formatter:off // 1.14 - 1.15.2 - private static Dictionary enchantmentMappings114 = new() + private static Dictionary enchantmentMappings114 = new() { //id type - { 0, Enchantment.Protection }, - { 1, Enchantment.FireProtection }, - { 2, Enchantment.FeatherFalling }, - { 3, Enchantment.BlastProtection }, - { 4, Enchantment.ProjectileProtection }, - { 5, Enchantment.Respiration }, - { 6, Enchantment.AquaAffinity }, - { 7, Enchantment.Thorns }, - { 8, Enchantment.DepthStrieder }, - { 9, Enchantment.FrostWalker }, - { 10, Enchantment.BindingCurse }, - { 11, Enchantment.Sharpness }, - { 12, Enchantment.Smite }, - { 13, Enchantment.BaneOfArthropods }, - { 14, Enchantment.Knockback }, - { 15, Enchantment.FireAspect }, - { 16, Enchantment.Looting }, - { 17, Enchantment.Sweeping }, - { 18, Enchantment.Efficency }, - { 19, Enchantment.SilkTouch }, - { 20, Enchantment.Unbreaking }, - { 21, Enchantment.Fortune }, - { 22, Enchantment.Power }, - { 23, Enchantment.Punch }, - { 24, Enchantment.Flame }, - { 25, Enchantment.Infinity }, - { 26, Enchantment.LuckOfTheSea }, - { 27, Enchantment.Lure }, - { 28, Enchantment.Loyality }, - { 29, Enchantment.Impaling }, - { 30, Enchantment.Riptide }, - { 31, Enchantment.Channeling }, - { 32, Enchantment.Mending }, - { 33, Enchantment.VanishingCurse } + { 0, Enchantments.Protection }, + { 1, Enchantments.FireProtection }, + { 2, Enchantments.FeatherFalling }, + { 3, Enchantments.BlastProtection }, + { 4, Enchantments.ProjectileProtection }, + { 5, Enchantments.Respiration }, + { 6, Enchantments.AquaAffinity }, + { 7, Enchantments.Thorns }, + { 8, Enchantments.DepthStrieder }, + { 9, Enchantments.FrostWalker }, + { 10, Enchantments.BindingCurse }, + { 11, Enchantments.Sharpness }, + { 12, Enchantments.Smite }, + { 13, Enchantments.BaneOfArthropods }, + { 14, Enchantments.Knockback }, + { 15, Enchantments.FireAspect }, + { 16, Enchantments.Looting }, + { 17, Enchantments.Sweeping }, + { 18, Enchantments.Efficency }, + { 19, Enchantments.SilkTouch }, + { 20, Enchantments.Unbreaking }, + { 21, Enchantments.Fortune }, + { 22, Enchantments.Power }, + { 23, Enchantments.Punch }, + { 24, Enchantments.Flame }, + { 25, Enchantments.Infinity }, + { 26, Enchantments.LuckOfTheSea }, + { 27, Enchantments.Lure }, + { 28, Enchantments.Loyality }, + { 29, Enchantments.Impaling }, + { 30, Enchantments.Riptide }, + { 31, Enchantments.Channeling }, + { 32, Enchantments.Mending }, + { 33, Enchantments.VanishingCurse } }; // 1.16 - 1.18 - private static Dictionary enchantmentMappings116 = new() + private static Dictionary enchantmentMappings116 = new() { //id type - { 0, Enchantment.Protection }, - { 1, Enchantment.FireProtection }, - { 2, Enchantment.FeatherFalling }, - { 3, Enchantment.BlastProtection }, - { 4, Enchantment.ProjectileProtection }, - { 5, Enchantment.Respiration }, - { 6, Enchantment.AquaAffinity }, - { 7, Enchantment.Thorns }, - { 8, Enchantment.DepthStrieder }, - { 9, Enchantment.FrostWalker }, - { 10, Enchantment.BindingCurse }, - { 11, Enchantment.SoulSpeed }, - { 12, Enchantment.Sharpness }, - { 13, Enchantment.Smite }, - { 14, Enchantment.BaneOfArthropods }, - { 15, Enchantment.Knockback }, - { 16, Enchantment.FireAspect }, - { 17, Enchantment.Looting }, - { 18, Enchantment.Sweeping }, - { 19, Enchantment.Efficency }, - { 20, Enchantment.SilkTouch }, - { 21, Enchantment.Unbreaking }, - { 22, Enchantment.Fortune }, - { 23, Enchantment.Power }, - { 24, Enchantment.Punch }, - { 25, Enchantment.Flame }, - { 26, Enchantment.Infinity }, - { 27, Enchantment.LuckOfTheSea }, - { 28, Enchantment.Lure }, - { 29, Enchantment.Loyality }, - { 30, Enchantment.Impaling }, - { 31, Enchantment.Riptide }, - { 32, Enchantment.Channeling }, - { 33, Enchantment.Multishot }, - { 34, Enchantment.QuickCharge }, - { 35, Enchantment.Piercing }, - { 36, Enchantment.Mending }, - { 37, Enchantment.VanishingCurse } + { 0, Enchantments.Protection }, + { 1, Enchantments.FireProtection }, + { 2, Enchantments.FeatherFalling }, + { 3, Enchantments.BlastProtection }, + { 4, Enchantments.ProjectileProtection }, + { 5, Enchantments.Respiration }, + { 6, Enchantments.AquaAffinity }, + { 7, Enchantments.Thorns }, + { 8, Enchantments.DepthStrieder }, + { 9, Enchantments.FrostWalker }, + { 10, Enchantments.BindingCurse }, + { 11, Enchantments.SoulSpeed }, + { 12, Enchantments.Sharpness }, + { 13, Enchantments.Smite }, + { 14, Enchantments.BaneOfArthropods }, + { 15, Enchantments.Knockback }, + { 16, Enchantments.FireAspect }, + { 17, Enchantments.Looting }, + { 18, Enchantments.Sweeping }, + { 19, Enchantments.Efficency }, + { 20, Enchantments.SilkTouch }, + { 21, Enchantments.Unbreaking }, + { 22, Enchantments.Fortune }, + { 23, Enchantments.Power }, + { 24, Enchantments.Punch }, + { 25, Enchantments.Flame }, + { 26, Enchantments.Infinity }, + { 27, Enchantments.LuckOfTheSea }, + { 28, Enchantments.Lure }, + { 29, Enchantments.Loyality }, + { 30, Enchantments.Impaling }, + { 31, Enchantments.Riptide }, + { 32, Enchantments.Channeling }, + { 33, Enchantments.Multishot }, + { 34, Enchantments.QuickCharge }, + { 35, Enchantments.Piercing }, + { 36, Enchantments.Mending }, + { 37, Enchantments.VanishingCurse } }; // 1.19 - 1.20.4 - private static Dictionary enchantmentMappings119 = new() + private static Dictionary enchantmentMappings119 = new() { //id type - { 0, Enchantment.Protection }, - { 1, Enchantment.FireProtection }, - { 2, Enchantment.FeatherFalling }, - { 3, Enchantment.BlastProtection }, - { 4, Enchantment.ProjectileProtection }, - { 5, Enchantment.Respiration }, - { 6, Enchantment.AquaAffinity }, - { 7, Enchantment.Thorns }, - { 8, Enchantment.DepthStrieder }, - { 9, Enchantment.FrostWalker }, - { 10, Enchantment.BindingCurse }, - { 11, Enchantment.SoulSpeed }, - { 12, Enchantment.SwiftSneak }, - { 13, Enchantment.Sharpness }, - { 14, Enchantment.Smite }, - { 15, Enchantment.BaneOfArthropods }, - { 16, Enchantment.Knockback }, - { 17, Enchantment.FireAspect }, - { 18, Enchantment.Looting }, - { 19, Enchantment.Sweeping }, - { 20, Enchantment.Efficency }, - { 21, Enchantment.SilkTouch }, - { 22, Enchantment.Unbreaking }, - { 23, Enchantment.Fortune }, - { 24, Enchantment.Power }, - { 25, Enchantment.Punch }, - { 26, Enchantment.Flame }, - { 27, Enchantment.Infinity }, - { 28, Enchantment.LuckOfTheSea }, - { 29, Enchantment.Lure }, - { 30, Enchantment.Loyality }, - { 31, Enchantment.Impaling }, - { 32, Enchantment.Riptide }, - { 33, Enchantment.Channeling }, - { 34, Enchantment.Multishot }, - { 35, Enchantment.QuickCharge }, - { 36, Enchantment.Piercing }, - { 37, Enchantment.Mending }, - { 38, Enchantment.VanishingCurse } + { 0, Enchantments.Protection }, + { 1, Enchantments.FireProtection }, + { 2, Enchantments.FeatherFalling }, + { 3, Enchantments.BlastProtection }, + { 4, Enchantments.ProjectileProtection }, + { 5, Enchantments.Respiration }, + { 6, Enchantments.AquaAffinity }, + { 7, Enchantments.Thorns }, + { 8, Enchantments.DepthStrieder }, + { 9, Enchantments.FrostWalker }, + { 10, Enchantments.BindingCurse }, + { 11, Enchantments.SoulSpeed }, + { 12, Enchantments.SwiftSneak }, + { 13, Enchantments.Sharpness }, + { 14, Enchantments.Smite }, + { 15, Enchantments.BaneOfArthropods }, + { 16, Enchantments.Knockback }, + { 17, Enchantments.FireAspect }, + { 18, Enchantments.Looting }, + { 19, Enchantments.Sweeping }, + { 20, Enchantments.Efficency }, + { 21, Enchantments.SilkTouch }, + { 22, Enchantments.Unbreaking }, + { 23, Enchantments.Fortune }, + { 24, Enchantments.Power }, + { 25, Enchantments.Punch }, + { 26, Enchantments.Flame }, + { 27, Enchantments.Infinity }, + { 28, Enchantments.LuckOfTheSea }, + { 29, Enchantments.Lure }, + { 30, Enchantments.Loyality }, + { 31, Enchantments.Impaling }, + { 32, Enchantments.Riptide }, + { 33, Enchantments.Channeling }, + { 34, Enchantments.Multishot }, + { 35, Enchantments.QuickCharge }, + { 36, Enchantments.Piercing }, + { 37, Enchantments.Mending }, + { 38, Enchantments.VanishingCurse } }; // 1.20.6+ - private static Dictionary enchantmentMappings = new() + private static Dictionary enchantmentMappings = new() { //id type - { 0, Enchantment.Protection }, - { 1, Enchantment.FireProtection }, - { 2, Enchantment.FeatherFalling }, - { 3, Enchantment.BlastProtection }, - { 4, Enchantment.ProjectileProtection }, - { 5, Enchantment.Respiration }, - { 6, Enchantment.AquaAffinity }, - { 7, Enchantment.Thorns }, - { 8, Enchantment.DepthStrieder }, - { 9, Enchantment.FrostWalker }, - { 10, Enchantment.BindingCurse }, - { 11, Enchantment.SoulSpeed }, - { 12, Enchantment.SwiftSneak }, - { 13, Enchantment.Sharpness }, - { 14, Enchantment.Smite }, - { 15, Enchantment.BaneOfArthropods }, - { 16, Enchantment.Knockback }, - { 17, Enchantment.FireAspect }, - { 18, Enchantment.Looting }, - { 19, Enchantment.Sweeping }, - { 20, Enchantment.Efficency }, - { 21, Enchantment.SilkTouch }, - { 22, Enchantment.Unbreaking }, - { 23, Enchantment.Fortune }, - { 24, Enchantment.Power }, - { 25, Enchantment.Punch }, - { 26, Enchantment.Flame }, - { 27, Enchantment.Infinity }, - { 28, Enchantment.LuckOfTheSea }, - { 29, Enchantment.Lure }, - { 30, Enchantment.Loyality }, - { 31, Enchantment.Impaling }, - { 32, Enchantment.Riptide }, - { 33, Enchantment.Channeling }, - { 34, Enchantment.Multishot }, - { 35, Enchantment.QuickCharge }, - { 36, Enchantment.Piercing }, - { 37, Enchantment.Density }, - { 38, Enchantment.Breach }, - { 39, Enchantment.WindBurst }, - { 40, Enchantment.Mending }, - { 41, Enchantment.VanishingCurse } + { 0, Enchantments.Protection }, + { 1, Enchantments.FireProtection }, + { 2, Enchantments.FeatherFalling }, + { 3, Enchantments.BlastProtection }, + { 4, Enchantments.ProjectileProtection }, + { 5, Enchantments.Respiration }, + { 6, Enchantments.AquaAffinity }, + { 7, Enchantments.Thorns }, + { 8, Enchantments.DepthStrieder }, + { 9, Enchantments.FrostWalker }, + { 10, Enchantments.BindingCurse }, + { 11, Enchantments.SoulSpeed }, + { 12, Enchantments.SwiftSneak }, + { 13, Enchantments.Sharpness }, + { 14, Enchantments.Smite }, + { 15, Enchantments.BaneOfArthropods }, + { 16, Enchantments.Knockback }, + { 17, Enchantments.FireAspect }, + { 18, Enchantments.Looting }, + { 19, Enchantments.Sweeping }, + { 20, Enchantments.Efficency }, + { 21, Enchantments.SilkTouch }, + { 22, Enchantments.Unbreaking }, + { 23, Enchantments.Fortune }, + { 24, Enchantments.Power }, + { 25, Enchantments.Punch }, + { 26, Enchantments.Flame }, + { 27, Enchantments.Infinity }, + { 28, Enchantments.LuckOfTheSea }, + { 29, Enchantments.Lure }, + { 30, Enchantments.Loyality }, + { 31, Enchantments.Impaling }, + { 32, Enchantments.Riptide }, + { 33, Enchantments.Channeling }, + { 34, Enchantments.Multishot }, + { 35, Enchantments.QuickCharge }, + { 36, Enchantments.Piercing }, + { 37, Enchantments.Density }, + { 38, Enchantments.Breach }, + { 39, Enchantments.WindBurst }, + { 40, Enchantments.Mending }, + { 41, Enchantments.VanishingCurse } }; #pragma warning restore format // @formatter:on - public static Enchantment GetEnchantmentById(int protocolVersion, short id) + public static Enchantments GetEnchantmentById(int protocolVersion, short id) { if (protocolVersion < Protocol18Handler.MC_1_14_Version) throw new Exception("Enchantments mappings are not implemented bellow 1.14"); @@ -206,9 +206,9 @@ namespace MinecraftClient.Inventory return value; } - public static string GetEnchantmentName(Enchantment enchantment) + public static string GetEnchantmentName(Enchantments enchantment) { - var translation = ChatParser.TranslateString("enchantment.minecraft." + enchantment.ToString().ToUnderscoreCase()); + var translation = ChatParser.TranslateString("Enchantments.minecraft." + enchantment.ToString().ToUnderscoreCase()); return string.IsNullOrEmpty(translation) ? $"Unknown Enchantment with ID: {(short)enchantment} (Probably not named in the code yet)" : translation; } diff --git a/MinecraftClient/Inventory/Enchantments.cs b/MinecraftClient/Inventory/Enchantments.cs index f1087d51..13fdd595 100644 --- a/MinecraftClient/Inventory/Enchantments.cs +++ b/MinecraftClient/Inventory/Enchantments.cs @@ -1,7 +1,7 @@ namespace MinecraftClient.Inventory { // Not implemented for 1.14 - public enum Enchantment : short + public enum Enchantments : short { AquaAffinity = 0, BaneOfArthropods, diff --git a/MinecraftClient/Inventory/ItemRarity.cs b/MinecraftClient/Inventory/ItemRarity.cs new file mode 100644 index 00000000..a6cc0330 --- /dev/null +++ b/MinecraftClient/Inventory/ItemRarity.cs @@ -0,0 +1,9 @@ +namespace MinecraftClient.Inventory; + +public enum ItemRarity : int +{ + Common = 0, + Uncommon, + Rare, + Epic +} \ No newline at end of file diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index f7775564..50761914 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -2948,27 +2948,27 @@ namespace MinecraftClient // We got the last property for enchantment if (propertyId == 9 && propertyValue != -1) { - short topEnchantmentLevelRequirement = inventory.Properties[0]; - short middleEnchantmentLevelRequirement = inventory.Properties[1]; - short bottomEnchantmentLevelRequirement = inventory.Properties[2]; + var topEnchantmentLevelRequirement = inventory.Properties[0]; + var middleEnchantmentLevelRequirement = inventory.Properties[1]; + var bottomEnchantmentLevelRequirement = inventory.Properties[2]; - Enchantment topEnchantment = EnchantmentMapping.GetEnchantmentById( + var topEnchantment = EnchantmentMapping.GetEnchantmentById( GetProtocolVersion(), inventory.Properties[4]); - Enchantment middleEnchantment = EnchantmentMapping.GetEnchantmentById( + var middleEnchantment = EnchantmentMapping.GetEnchantmentById( GetProtocolVersion(), inventory.Properties[5]); - Enchantment bottomEnchantment = EnchantmentMapping.GetEnchantmentById( + var bottomEnchantment = EnchantmentMapping.GetEnchantmentById( GetProtocolVersion(), inventory.Properties[6]); - short topEnchantmentLevel = inventory.Properties[7]; - short middleEnchantmentLevel = inventory.Properties[8]; - short bottomEnchantmentLevel = inventory.Properties[9]; + var topEnchantmentLevel = inventory.Properties[7]; + var middleEnchantmentLevel = inventory.Properties[8]; + var bottomEnchantmentLevel = inventory.Properties[9]; - StringBuilder sb = new(); + var sb = new StringBuilder(); sb.AppendLine(Translations.Enchantment_enchantments_available + ":"); diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/AttributeModifiersComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/AttributeModifiersComponent1206.cs new file mode 100644 index 00000000..c2eaa2da --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/AttributeModifiersComponent1206.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class AttributeModifiersComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public int NumberOfAttributes { get; set; } + public List Attributes { get; set; } = new(); + public bool ShowInTooltip { get; set; } + + public override void Parse(Queue data) + { + NumberOfAttributes = dataTypes.ReadNextVarInt(data); + + for (var i = 0; i < NumberOfAttributes; i++) + Attributes.Add((AttributeSubComponent1206)subComponentRegistry.ParseSubComponent(SubComponents.Attribute, data)); + + ShowInTooltip = dataTypes.ReadNextBool(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(NumberOfAttributes)); + + if(NumberOfAttributes > 0 && Attributes.Count == 0) + throw new ArgumentNullException($"Can not serialize a AttributeModifiersComponent when the Attributes is empty but NumberOfAttributes is > 0!"); + + foreach (var attribute in Attributes) + data.AddRange(attribute.Serialize()); + + data.AddRange(DataTypes.GetBool(ShowInTooltip)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CanBreakComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CanBreakComponent1206.cs new file mode 100644 index 00000000..24d50cf5 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CanBreakComponent1206.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class CanBreakComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public int NumberOfPredicates { get; set; } + public List BlockPredicates { get; set; } = new(); + public bool ShowInTooltip { get; set; } + + public override void Parse(Queue data) + { + NumberOfPredicates = dataTypes.ReadNextVarInt(data); + + for (var i = 0; i < NumberOfPredicates; i++) + BlockPredicates.Add((BlockPredicateSubcomponent1206)subComponentRegistry.ParseSubComponent(SubComponents.BlockPredicate, data)); + + ShowInTooltip = dataTypes.ReadNextBool(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(NumberOfPredicates)); + + if(NumberOfPredicates > 0 && BlockPredicates.Count == 0) + throw new ArgumentNullException($"Can not serialize a CanBreakComponent when the BlockPredicates is empty but NumberOfPredicates is > 0!"); + + foreach (var blockPredicate in BlockPredicates) + data.AddRange(blockPredicate.Serialize()); + + data.AddRange(DataTypes.GetBool(ShowInTooltip)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CanPlaceOnComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CanPlaceOnComponent1206.cs new file mode 100644 index 00000000..f19211b6 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CanPlaceOnComponent1206.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class CanPlaceOnComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public int NumberOfPredicates { get; set; } + public List BlockPredicates { get; set; } = new(); + public bool ShowInTooltip { get; set; } + + public override void Parse(Queue data) + { + NumberOfPredicates = dataTypes.ReadNextVarInt(data); + + for (var i = 0; i < NumberOfPredicates; i++) + BlockPredicates.Add((BlockPredicateSubcomponent1206)subComponentRegistry.ParseSubComponent(SubComponents.BlockPredicate, data)); + + ShowInTooltip = dataTypes.ReadNextBool(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(NumberOfPredicates)); + + if(NumberOfPredicates > 0 && BlockPredicates.Count == 0) + throw new ArgumentNullException($"Can not serialize a CanPlaceOnComponent when the BlockPredicates is empty but NumberOfPredicates is > 0!"); + + foreach (var blockPredicate in BlockPredicates) + data.AddRange(blockPredicate.Serialize()); + + data.AddRange(DataTypes.GetBool(ShowInTooltip)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CustomDataComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CustomDataComponent1206.cs new file mode 100644 index 00000000..58732f0a --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CustomDataComponent1206.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class CustomDataComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public Dictionary? Nbt { get; set; } = new(); + + public override void Parse(Queue data) + { + Nbt = dataTypes.ReadNextNbt(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetNbt(Nbt)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CustomModelDataComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CustomModelDataComponent1206.cs new file mode 100644 index 00000000..965c4040 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CustomModelDataComponent1206.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class CustomModelDataComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public int Value { get; set; } + + public override void Parse(Queue data) + { + Value = dataTypes.ReadNextVarInt(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(Value)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CustomNameComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CustomNameComponent1206.cs new file mode 100644 index 00000000..71d95001 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/CustomNameComponent1206.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; +using MinecraftClient.Protocol.Message; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class CustomNameComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public string CustomName { get; set; } = string.Empty; + + public override void Parse(Queue data) + { + CustomName = ChatParser.ParseText(dataTypes.ReadNextString(data)); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetString(CustomName)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/DamageComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/DamageComponent1206.cs new file mode 100644 index 00000000..2e6bbadd --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/DamageComponent1206.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class DamageComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public int Damage { get; set; } + + public override void Parse(Queue data) + { + Damage = dataTypes.ReadNextVarInt(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(Damage)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/EnchantmentsComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/EnchantmentsComponent1206.cs new file mode 100644 index 00000000..be5b6e81 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/EnchantmentsComponent1206.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using MinecraftClient.Inventory; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class EnchantmentsComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public int NumberOfEnchantments { get; set; } + public List Enchantments { get; set; } = new(); + public bool ShowTooltip { get; set; } + + public override void Parse(Queue data) + { + NumberOfEnchantments = dataTypes.ReadNextVarInt(data); + + for (var i = 0; i < NumberOfEnchantments; i++) + Enchantments.Add(new Enchantment((Enchantments)dataTypes.ReadNextVarInt(data), dataTypes.ReadNextVarInt(data))); + + ShowTooltip = dataTypes.ReadNextBool(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(Enchantments.Count)); + foreach (var enchantment in Enchantments) + { + data.AddRange(DataTypes.GetVarInt((int)enchantment.Type)); + data.AddRange(DataTypes.GetVarInt(enchantment.Level)); + } + data.AddRange(DataTypes.GetBool(ShowTooltip)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/HideAdditionalTooltipComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/HideAdditionalTooltipComponent1206.cs new file mode 100644 index 00000000..1c3d5f84 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/HideAdditionalTooltipComponent1206.cs @@ -0,0 +1,5 @@ +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class HideAdditionalTooltipComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : EmptyComponent(dataTypes, subComponentRegistry); \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/HideTooltipComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/HideTooltipComponent1206.cs new file mode 100644 index 00000000..c93fa8f9 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/HideTooltipComponent1206.cs @@ -0,0 +1,5 @@ +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class HideTooltipComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : EmptyComponent(dataTypes, subComponentRegistry); \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/ItemNameComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/ItemNameComponent1206.cs new file mode 100644 index 00000000..16107244 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/ItemNameComponent1206.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; +using MinecraftClient.Protocol.Message; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class ItemNameComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public string ItemName { get; set; } = string.Empty; + + public override void Parse(Queue data) + { + ItemName = ChatParser.ParseText(dataTypes.ReadNextString(data)); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetString(ItemName)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/LoreComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/LoreComponent1206.cs new file mode 100644 index 00000000..5a88e04b --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/LoreComponent1206.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; +using MinecraftClient.Protocol.Message; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class LoreNameComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public int NumberOfLines { get; set; } + public List Lines { get; set; } = []; + + public override void Parse(Queue data) + { + NumberOfLines = dataTypes.ReadNextVarInt(data); + + if (NumberOfLines <= 0) return; + + for (var i = 0; i < NumberOfLines; i++) + Lines.Add(ChatParser.ParseText(dataTypes.ReadNextString(data))); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(Lines.Count)); + + if (Lines.Count <= 0) return new Queue(data); + + foreach (var line in Lines) + data.AddRange(DataTypes.GetString(line)); + + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/MaxDamageComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/MaxDamageComponent1206.cs new file mode 100644 index 00000000..c3890dfb --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/MaxDamageComponent1206.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class MaxDamageComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public int MaxDamage { get; set; } + + public override void Parse(Queue data) + { + MaxDamage = dataTypes.ReadNextVarInt(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(MaxDamage)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/MaxStackSizeComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/MaxStackSizeComponent1206.cs new file mode 100644 index 00000000..de210a2b --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/MaxStackSizeComponent1206.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class MaxStackSizeComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public int MaxStackSize { get; set; } + + public override void Parse(Queue data) + { + MaxStackSize = dataTypes.ReadNextVarInt(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(MaxStackSize)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/RarityComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/RarityComponent1206.cs new file mode 100644 index 00000000..f14b6d4d --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/RarityComponent1206.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using MinecraftClient.Inventory; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class RarityComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public ItemRarity Rarity { get; set; } + + public override void Parse(Queue data) + { + Rarity = (ItemRarity)dataTypes.ReadNextVarInt(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt((int)Rarity)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/UnbreakableComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/UnbreakableComponent1206.cs new file mode 100644 index 00000000..a3dfd786 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/1_20_6/UnbreakableComponent1206.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; + +public class UnbrekableComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) +{ + public bool Unbrekable { get; set; } + + public override void Parse(Queue data) + { + Unbrekable = dataTypes.ReadNextBool(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetBool(Unbrekable)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/TestSubComonent.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/EmptyComponent.cs similarity index 54% rename from MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/TestSubComonent.cs rename to MinecraftClient/Protocol/Handlers/StructuredComponents/Components/EmptyComponent.cs index fbed4b70..0cc40762 100644 --- a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/TestSubComonent.cs +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/EmptyComponent.cs @@ -1,19 +1,16 @@ using System.Collections.Generic; using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; -namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents; +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components; -public class TestSubComonent(DataTypes dataTypes) : SubComponent(dataTypes) +public class EmptyComponent(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) { - public int Test { get; set; } - public override void Parse(Queue data) { - Test = DataTypes.ReadNextVarInt(data); } public override Queue Serialize() { - throw new System.NotImplementedException(); + return new Queue(); } } \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/AttributeSubComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/AttributeSubComponent1206.cs new file mode 100644 index 00000000..c7d63dd3 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/AttributeSubComponent1206.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6; + +public class AttributeSubComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : SubComponent(dataTypes, subComponentRegistry) +{ + public int TypeId { get; set; } + public Guid Uuid { get; set; } + public string? Name { get; set; } + public double Value { get; set; } + public int Operation { get; set; } + public int Slot { get; set; } + + protected override void Parse(Queue data) + { + TypeId = dataTypes.ReadNextVarInt(data); + Uuid = dataTypes.ReadNextUUID(data); + Name = dataTypes.ReadNextString(data); + Value = dataTypes.ReadNextDouble(data); + Operation = dataTypes.ReadNextVarInt(data); + Slot = dataTypes.ReadNextVarInt(data); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(TypeId)); + data.AddRange(DataTypes.GetUUID(Uuid)); + + if (string.IsNullOrEmpty(Name?.Trim())) + throw new ArgumentNullException($"Can not serialize AttributeSubComponent due to Name being null or empty!"); + + data.AddRange(DataTypes.GetString(Name)); + data.AddRange(DataTypes.GetDouble(Value)); + data.AddRange(DataTypes.GetVarInt(Operation)); + data.AddRange(DataTypes.GetVarInt(Slot)); + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/BlockPredicateSubcomponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/BlockPredicateSubcomponent1206.cs new file mode 100644 index 00000000..fae29a94 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/BlockPredicateSubcomponent1206.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6; + +public class BlockPredicateSubcomponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : SubComponent(dataTypes, subComponentRegistry) +{ + public bool HasBlocks { get; set; } + public BlockSetSubcomponent1206? BlockSet { get; set; } + public bool HasProperities { get; set; } + public List? Properties { get; set; } + public bool HasNbt { get; set; } + public Dictionary? Nbt { get; set; } + + protected override void Parse(Queue data) + { + HasBlocks = dataTypes.ReadNextBool(data); + + if (HasBlocks) + BlockSet = (BlockSetSubcomponent1206)subComponentRegistry.ParseSubComponent(SubComponents.BlockSet, data); + + HasProperities = dataTypes.ReadNextBool(data); + + if (HasProperities) + { + Properties = new(); + var numberOfProperties = dataTypes.ReadNextVarInt(data); + for (var i = 0; i < numberOfProperties; i++) + Properties.Add((PropertySubComponent1206)subComponentRegistry.ParseSubComponent(SubComponents.Property, data)); + } + + HasNbt = dataTypes.ReadNextBool(data); + + if (HasNbt) + Nbt = dataTypes.ReadNextNbt(data); + } + + public override Queue Serialize() + { + var data = new List(); + + // Block Sets + data.AddRange(DataTypes.GetBool(HasBlocks)); + if (HasBlocks) + { + if(BlockSet == null) + throw new ArgumentNullException($"Can not serialize a BlockPredicate when the BlockSet is empty but HasBlocks is true!"); + + data.AddRange(BlockSet.Serialize()); + } + + // Properites + data.AddRange(DataTypes.GetBool(HasProperities)); + if (HasProperities) + { + if(Properties == null || Properties.Count == 0) + throw new ArgumentNullException($"Can not serialize a BlockPredicate when the Properties is empty but HasProperties is true!"); + + foreach (var property in Properties) + data.AddRange(property.Serialize()); + } + + // NBT + if (HasNbt) + { + if(Nbt == null) + throw new ArgumentNullException($"Can not serialize a BlockPredicate when the Nbt is empty but HasNbt is true!"); + + data.AddRange(DataTypes.GetNbt(Nbt)); + } + + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/BlockSetSubcomponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/BlockSetSubcomponent1206.cs new file mode 100644 index 00000000..a35eeec1 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/BlockSetSubcomponent1206.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6; + +public class BlockSetSubcomponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : SubComponent(dataTypes, subComponentRegistry) +{ + public int Type { get; set; } + public string? TagName { get; set; } + public List? BlockIds { get; set; } + + protected override void Parse(Queue data) + { + Type = DataTypes.ReadNextVarInt(data); + + if (Type == 0) + TagName = dataTypes.ReadNextString(data); + + if (Type == 0) return; + + BlockIds = []; + + for (var i = 0; i < Type - 1; i++) + BlockIds.Add(dataTypes.ReadNextVarInt(data)); + } + + public override Queue Serialize() + { + var data = new List(); + data.AddRange(DataTypes.GetVarInt(Type)); + if (Type == 0) + { + if (string.IsNullOrEmpty(TagName?.Trim())) + throw new ArgumentNullException($"Can not serialize an empty tag name when the Block Set type is 0!"); + + data.AddRange(DataTypes.GetString(TagName)); + } + + if (Type == 0) return new Queue(data); + + if(BlockIds == null || BlockIds.Count == 0) + throw new ArgumentNullException($"Can not serialize an empty list of Block IDs in a Block Set when the type is not 0!"); + + for(var i = 0; i < Type - 1; i++) + data.AddRange(DataTypes.GetVarInt(BlockIds[i])); + + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/PropertySubComponent1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/PropertySubComponent1206.cs new file mode 100644 index 00000000..64742c5f --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/1_20_6/PropertySubComponent1206.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6; + +public class PropertySubComponent1206(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : SubComponent(dataTypes, subComponentRegistry) +{ + public string? Name { get; set; } + public bool IsExactMatch { get; set; } + public string? ExactValue { get; set; } + public string? MinValue { get; set; } + public string? MaxValue { get; set; } + + protected override void Parse(Queue data) + { + Name = dataTypes.ReadNextString(data); + IsExactMatch = dataTypes.ReadNextBool(data); + + if (IsExactMatch) + ExactValue = dataTypes.ReadNextString(data); + else // Ranged Match + { + MinValue = dataTypes.ReadNextString(data); + MaxValue = dataTypes.ReadNextString(data); + } + } + + public override Queue Serialize() + { + var data = new List(); + + if (string.IsNullOrEmpty(Name?.Trim())) + throw new ArgumentNullException($"Can not serialize a Property sub-component if the Name is null or empty!"); + + data.AddRange(DataTypes.GetString(Name)); + data.AddRange(DataTypes.GetBool(IsExactMatch)); + + if (IsExactMatch) + { + if (string.IsNullOrEmpty(ExactValue?.Trim())) + throw new ArgumentNullException($"Can not serialize a Property sub-component if the ExactValue is null or empty when the type is Exact Match!"); + + data.AddRange(DataTypes.GetString(ExactValue)); + } + else + { + if (string.IsNullOrEmpty(MinValue?.Trim()) || string.IsNullOrEmpty(MaxValue?.Trim())) + throw new ArgumentNullException($"Can not serialize a Property sub-component if the MinValue or MaxValue is null or empty when the type is not Exact Match!"); + + data.AddRange(DataTypes.GetString(MinValue)); + data.AddRange(DataTypes.GetString(MaxValue)); + } + + return new Queue(data); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/SubComponents.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/SubComponents.cs new file mode 100644 index 00000000..9de0e9ad --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/Subcomponents/SubComponents.cs @@ -0,0 +1,9 @@ +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents; + +public class SubComponents +{ + public const string BlockPredicate = "BlockPredicate"; + public const string BlockSet = "BlockSet"; + public const string Property = "Property"; + public const string Attribute = "Attribute"; +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/TestComponent.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/TestComponent.cs deleted file mode 100644 index befa1217..00000000 --- a/MinecraftClient/Protocol/Handlers/StructuredComponents/Components/TestComponent.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; -using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents; -using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; - -namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components; - -public class TestComponent(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, subComponentRegistry) -{ - public int TestInt { get; set; } - public string TestString { get; set; } = null!; - - public TestSubComonent TestSubComonent { get; set; } = null!; - - public override void Parse(Queue data) - { - TestInt = dataTypes.ReadNextVarInt(data); - TestString = dataTypes.ReadNextString(data); - TestSubComonent = (SubComponentRegistry.ParseSubComponent("TestSubComponent", data) as TestSubComonent)!; - } - - public override Queue Serialize() - { - var data = new List(); - data.AddRange(DataTypes.GetVarInt(TestInt)); - data.AddRange(DataTypes.GetString(TestString)); - data.AddRange(TestSubComonent.Serialize()); - return new Queue(data); - } -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/SubComponent.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/SubComponent.cs index af63dce8..be235a91 100644 --- a/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/SubComponent.cs +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/SubComponent.cs @@ -2,10 +2,11 @@ using System.Collections.Generic; namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Core; -public abstract class SubComponent(DataTypes dataTypes) +public abstract class SubComponent(DataTypes dataTypes, SubComponentRegistry subComponentRegistry) { protected DataTypes DataTypes { get; private set; } = dataTypes; + protected SubComponentRegistry SubComponentRegistry { get; private set; } = subComponentRegistry; - public abstract void Parse(Queue data); + protected abstract void Parse(Queue data); public abstract Queue Serialize(); } \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/SubComponentRegistry.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/SubComponentRegistry.cs index 844107c1..90123fe6 100644 --- a/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/SubComponentRegistry.cs +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/SubComponentRegistry.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Reflection; namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Core; @@ -20,10 +21,15 @@ public abstract class SubComponentRegistry(DataTypes dataTypes) if(!_subComponentParsers.TryGetValue(name, out var subComponentParserType)) throw new Exception($"Sub component {name} not registered!"); - var instance= Activator.CreateInstance(subComponentParserType, dataTypes) as SubComponent ?? + var instance= Activator.CreateInstance(subComponentParserType, dataTypes, this) as SubComponent ?? throw new InvalidOperationException($"Could not create instance of a sub component parser type: {subComponentParserType.Name}"); - instance.Parse(data); + var parseMethod = instance.GetType().GetMethod("Parse", BindingFlags.Instance | BindingFlags.NonPublic); + + if (parseMethod == null) + throw new InvalidOperationException($"Sub component parser type {subComponentParserType.Name} does not have a Parse method."); + + parseMethod.Invoke(instance, new object[] { data }); return instance; } } \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry1206.cs index d69507ab..da70c454 100644 --- a/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry1206.cs +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry1206.cs @@ -1,4 +1,4 @@ -using MinecraftClient.Protocol.Handlers.StructuredComponents.Components; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6; using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries; @@ -8,6 +8,21 @@ public class StructuredComponentsRegistry1206 : StructuredComponentRegistry public StructuredComponentsRegistry1206(SubComponentRegistry subComponentRegistry, DataTypes dataTypes) : base( subComponentRegistry, dataTypes) { - RegisterComponent(0, "minecraft:test"); + RegisterComponent(0, "minecraft:custom_data"); + RegisterComponent(1, "minecraft:max_stack_size"); + RegisterComponent(2, "minecraft:max_damage"); + RegisterComponent(3, "minecraft:damage"); + RegisterComponent(4, "minecraft:unbreakable"); + RegisterComponent(5, "minecraft:custom_name"); + RegisterComponent(6, "minecraft:item_name"); + RegisterComponent(7, "minecraft:lore"); + RegisterComponent(8, "minecraft:rarity"); + RegisterComponent(9, "minecraft:enchantments"); + RegisterComponent(10, "minecraft:can_place_on"); + RegisterComponent(11, "minecraft:can_break"); + RegisterComponent(12, "minecraft:attribute_modifiers"); + RegisterComponent(13, "minecraft:custom_model_data"); + RegisterComponent(14, "minecraft:hide_additional_tooltip"); + RegisterComponent(15, "minecraft:hide_tooltip"); } } \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/Subcomponents/SubComponentRegistry1206.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/Subcomponents/SubComponentRegistry1206.cs new file mode 100644 index 00000000..b2428185 --- /dev/null +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/Subcomponents/SubComponentRegistry1206.cs @@ -0,0 +1,16 @@ +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_20_6; +using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; + +namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries.Subcomponents; + +public class SubComponentRegistry1206 : SubComponentRegistry +{ + public SubComponentRegistry1206(DataTypes dataTypes) : base(dataTypes) + { + RegisterSubComponent(SubComponents.BlockPredicate); + RegisterSubComponent(SubComponents.BlockSet); + RegisterSubComponent(SubComponents.Property); + RegisterSubComponent(SubComponents.Attribute); + } +} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/Subcomponents/TestSubComponentRegistry.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/Subcomponents/TestSubComponentRegistry.cs deleted file mode 100644 index c10bbc49..00000000 --- a/MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/Subcomponents/TestSubComponentRegistry.cs +++ /dev/null @@ -1,12 +0,0 @@ -using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents; -using MinecraftClient.Protocol.Handlers.StructuredComponents.Core; - -namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries.Subcomponents; - -public class TestSubComponentRegistry : SubComponentRegistry -{ - public TestSubComponentRegistry(DataTypes dataTypes) : base(dataTypes) - { - RegisterSubComponent("TestSubcomponent"); - } -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/StructuredComponentsHandler.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/StructuredComponentsHandler.cs index 6a03e040..f22405b1 100644 --- a/MinecraftClient/Protocol/Handlers/StructuredComponents/StructuredComponentsHandler.cs +++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/StructuredComponentsHandler.cs @@ -18,7 +18,7 @@ public class StructuredComponentsHandler // Get the appropriate subcomponent registry type based on the protocol version and then instantiate it var subcomponentRegistryType = protocolVersion switch { - Protocol18Handler.MC_1_20_6_Version => typeof(TestSubComponentRegistry), + Protocol18Handler.MC_1_20_6_Version => typeof(SubComponentRegistry1206), _ => throw new NotSupportedException($"Protocol version {protocolVersion} is not supported for subcomponent registries!") }; diff --git a/MinecraftClient/Scripting/ChatBot.cs b/MinecraftClient/Scripting/ChatBot.cs index 14ac29d1..eff94a09 100644 --- a/MinecraftClient/Scripting/ChatBot.cs +++ b/MinecraftClient/Scripting/ChatBot.cs @@ -400,9 +400,9 @@ namespace MinecraftClient.Scripting /// Levels required by player for the enchantment in the middle slot /// Levels required by player for the enchantment in the bottom slot public virtual void OnEnchantments( - Enchantment topEnchantment, - Enchantment middleEnchantment, - Enchantment bottomEnchantment, + Enchantments topEnchantment, + Enchantments middleEnchantment, + Enchantments bottomEnchantment, short topEnchantmentLevel, short middleEnchantmentLevel, short bottomEnchantmentLevel,