using System; using System.Collections.Generic; using MinecraftClient.Inventory.ItemPalettes; using MinecraftClient.Protocol.Handlers.StructuredComponents; 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_21_5; /// /// 1.21.5+ uses AdventureModePredicate.STREAM_CODEC: /// list, where each BlockPredicate ends with DataComponentMatchers. /// Tooltip visibility moved to minecraft:tooltip_display. /// public sealed class CanBreakComponent1215(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry) : AdventureModePredicateComponent1215Base(dataTypes, itemPalette, subComponentRegistry); /// /// 1.21.5+ uses AdventureModePredicate.STREAM_CODEC: /// list, where each BlockPredicate ends with DataComponentMatchers. /// Tooltip visibility moved to minecraft:tooltip_display. /// public sealed class CanPlaceOnComponent1215(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry) : AdventureModePredicateComponent1215Base(dataTypes, itemPalette, subComponentRegistry); public abstract class AdventureModePredicateComponent1215Base(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, itemPalette, subComponentRegistry) { public List BlockPredicates { get; set; } = []; public override void Parse(Queue data) { var predicateCount = DataTypes.ReadNextVarInt(data); BlockPredicates = new List(predicateCount); var componentHandler = new StructuredComponentsHandler(DataTypes.ProtocolVersion, DataTypes, ItemPalette); for (var i = 0; i < predicateCount; i++) BlockPredicates.Add(ParseBlockPredicate(data, componentHandler)); } public override Queue Serialize() { var data = new List(); data.AddRange(DataTypes.GetVarInt(BlockPredicates.Count)); foreach (var predicate in BlockPredicates) SerializeBlockPredicate(data, predicate); return new Queue(data); } private AdventureModeBlockPredicate1215 ParseBlockPredicate(Queue data, StructuredComponentsHandler componentHandler) { BlockSetSubcomponent? blockSet = null; if (DataTypes.ReadNextBool(data)) blockSet = (BlockSetSubcomponent)SubComponentRegistry.ParseSubComponent(SubComponents.BlockSet, data); List properties = []; if (DataTypes.ReadNextBool(data)) { var propertyCount = DataTypes.ReadNextVarInt(data); properties = new List(propertyCount); for (var i = 0; i < propertyCount; i++) properties.Add((PropertySubComponent)SubComponentRegistry.ParseSubComponent(SubComponents.Property, data)); } Dictionary? nbt = null; if (DataTypes.ReadNextBool(data)) nbt = DataTypes.ReadNextNbt(data); var exactComponentCount = DataTypes.ReadNextVarInt(data); var exactComponents = new List(exactComponentCount); for (var i = 0; i < exactComponentCount; i++) { var componentTypeId = DataTypes.ReadNextVarInt(data); exactComponents.Add(componentHandler.Parse(componentTypeId, data)); } var partialPredicateCount = DataTypes.ReadNextVarInt(data); var partialPredicates = new List(partialPredicateCount); for (var i = 0; i < partialPredicateCount; i++) { partialPredicates.Add(new DataComponentPredicatePayload1215( DataTypes.ReadNextVarInt(data), DataTypes.ReadNextNbt(data))); } return new AdventureModeBlockPredicate1215(blockSet, properties, nbt, exactComponents, partialPredicates); } private void SerializeBlockPredicate(List data, AdventureModeBlockPredicate1215 predicate) { data.AddRange(DataTypes.GetBool(predicate.BlockSet is not null)); if (predicate.BlockSet is not null) data.AddRange(predicate.BlockSet.Serialize()); data.AddRange(DataTypes.GetBool(predicate.Properties.Count > 0)); if (predicate.Properties.Count > 0) { data.AddRange(DataTypes.GetVarInt(predicate.Properties.Count)); foreach (var property in predicate.Properties) data.AddRange(property.Serialize()); } data.AddRange(DataTypes.GetBool(predicate.Nbt is not null)); if (predicate.Nbt is not null) data.AddRange(DataTypes.GetNbt(predicate.Nbt)); data.AddRange(DataTypes.GetVarInt(predicate.ExactComponents.Count)); foreach (var component in predicate.ExactComponents) { if (component.TypeId < 0) throw new ArgumentException("Exact predicate component is missing its data component type id.", nameof(component)); data.AddRange(DataTypes.GetVarInt(component.TypeId)); data.AddRange(component.Serialize()); } data.AddRange(DataTypes.GetVarInt(predicate.PartialPredicates.Count)); foreach (var predicatePayload in predicate.PartialPredicates) { data.AddRange(DataTypes.GetVarInt(predicatePayload.TypeId)); data.AddRange(DataTypes.GetNbt(predicatePayload.Payload)); } } } public sealed record AdventureModeBlockPredicate1215( BlockSetSubcomponent? BlockSet, List Properties, Dictionary? Nbt, List ExactComponents, List PartialPredicates); public sealed record DataComponentPredicatePayload1215(int TypeId, Dictionary Payload);