Fixed the component system from 1.20.6 - 1.21.11

This commit is contained in:
Anon 2026-03-25 01:08:27 +01:00
parent 6f30f9b79a
commit 17808bb652
17 changed files with 749 additions and 25 deletions

View file

@ -6,17 +6,47 @@ namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_2
public class CustomModelDataComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry) : StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Value { get; set; }
public List<float> Floats { get; set; } = [];
public List<bool> Flags { get; set; } = [];
public List<string> Strings { get; set; } = [];
public List<int> Colors { get; set; } = [];
public override void Parse(Queue<byte> data)
{
Value = DataTypes.ReadNextVarInt(data);
Floats = ReadList(data, static (dataTypes, componentData) => dataTypes.ReadNextFloat(componentData));
Flags = ReadList(data, static (dataTypes, componentData) => dataTypes.ReadNextBool(componentData));
Strings = ReadList(data, static (dataTypes, componentData) => dataTypes.ReadNextString(componentData));
Colors = ReadList(data, static (dataTypes, componentData) => dataTypes.ReadNextInt(componentData));
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Value));
WriteList(data, Floats, static (dataTypes, value) => dataTypes.GetFloat(value));
WriteList(data, Flags, static (dataTypes, value) => dataTypes.GetBool(value));
WriteList(data, Strings, static (dataTypes, value) => dataTypes.GetString(value));
WriteList(data, Colors, static (_, value) => DataTypes.GetInt(value));
return new Queue<byte>(data);
}
}
private List<T> ReadList<T>(Queue<byte> data, ReadDelegate<T> read)
{
var count = DataTypes.ReadNextVarInt(data);
var values = new List<T>(count);
for (var i = 0; i < count; i++)
values.Add(read(DataTypes, data));
return values;
}
private void WriteList<T>(List<byte> data, List<T> values, WriteDelegate<T> write)
{
data.AddRange(DataTypes.GetVarInt(values.Count));
foreach (var value in values)
data.AddRange(write(DataTypes, value));
}
private delegate T ReadDelegate<out T>(DataTypes dataTypes, Queue<byte> data);
private delegate byte[] WriteDelegate<in T>(DataTypes dataTypes, T value);
}

View file

@ -0,0 +1,21 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
public class CustomModelDataComponent1206(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Value { get; set; }
public override void Parse(Queue<byte> data)
{
Value = DataTypes.ReadNextVarInt(data);
}
public override Queue<byte> Serialize()
{
return new Queue<byte>(DataTypes.GetVarInt(Value));
}
}

View file

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_21;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
using MinecraftClient.Protocol.Message;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21;
public class JukeBoxPlayableComponent121(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public bool IsHolder { get; set; }
public int HolderId { get; set; }
public string? ResourceKey { get; set; }
public SoundEventSubComponent? SoundEvent { get; set; }
public Dictionary<string, object>? DescriptionNbt { get; set; }
public string Description { get; set; } = string.Empty;
public float Duration { get; set; }
public int ComparatorOutput { get; set; }
public bool ShowTooltip { get; set; }
public override void Parse(Queue<byte> data)
{
IsHolder = DataTypes.ReadNextBool(data);
if (IsHolder)
{
HolderId = DataTypes.ReadNextVarInt(data);
if (HolderId == 0)
{
SoundEvent = (SoundEventSubComponent)SubComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
DescriptionNbt = DataTypes.ReadNextNbt(data);
Description = ChatParser.ParseText(DescriptionNbt);
Duration = DataTypes.ReadNextFloat(data);
ComparatorOutput = DataTypes.ReadNextVarInt(data);
}
}
else
{
ResourceKey = DataTypes.ReadNextString(data);
}
ShowTooltip = DataTypes.ReadNextBool(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetBool(IsHolder));
if (IsHolder)
{
data.AddRange(DataTypes.GetVarInt(HolderId));
if (HolderId == 0)
{
if (SoundEvent is null)
throw new ArgumentNullException(nameof(SoundEvent), "Inline jukebox song requires a sound event.");
if (DescriptionNbt is null)
throw new ArgumentNullException(nameof(DescriptionNbt), "Inline jukebox song requires a description.");
data.AddRange(SoundEvent.Serialize());
data.AddRange(DataTypes.GetNbt(DescriptionNbt));
data.AddRange(DataTypes.GetFloat(Duration));
data.AddRange(DataTypes.GetVarInt(ComparatorOutput));
}
}
else
{
if (string.IsNullOrEmpty(ResourceKey))
throw new ArgumentNullException(nameof(ResourceKey), "Resource key is required for key-backed jukebox songs.");
data.AddRange(DataTypes.GetString(ResourceKey));
}
data.AddRange(DataTypes.GetBool(ShowTooltip));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,61 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
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_2;
public class PotionContentsComponent1212(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public bool HasPotionId { get; set; }
public int PotionId { get; set; }
public bool HasCustomColor { get; set; }
public int CustomColor { get; set; }
public List<PotionEffectSubComponent> Effects { get; set; } = [];
public bool HasCustomName { get; set; }
public string? CustomName { get; set; }
public override void Parse(Queue<byte> data)
{
HasPotionId = DataTypes.ReadNextBool(data);
if (HasPotionId)
PotionId = DataTypes.ReadNextVarInt(data);
HasCustomColor = DataTypes.ReadNextBool(data);
if (HasCustomColor)
CustomColor = DataTypes.ReadNextInt(data);
var numberOfEffects = DataTypes.ReadNextVarInt(data);
Effects = new List<PotionEffectSubComponent>(numberOfEffects);
for (var i = 0; i < numberOfEffects; i++)
Effects.Add((PotionEffectSubComponent)SubComponentRegistry.ParseSubComponent(SubComponents.PotionEffect, data));
HasCustomName = DataTypes.ReadNextBool(data);
if (HasCustomName)
CustomName = DataTypes.ReadNextString(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetBool(HasPotionId));
if (HasPotionId)
data.AddRange(DataTypes.GetVarInt(PotionId));
data.AddRange(DataTypes.GetBool(HasCustomColor));
if (HasCustomColor)
data.AddRange(DataTypes.GetInt(CustomColor));
data.AddRange(DataTypes.GetVarInt(Effects.Count));
foreach (var effect in Effects)
data.AddRange(effect.Serialize());
data.AddRange(DataTypes.GetBool(HasCustomName));
if (HasCustomName && CustomName is not null)
data.AddRange(DataTypes.GetString(CustomName));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_5;
public class AttributeModifiersComponent1215(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int NumberOfAttributes { get; set; }
public List<SubComponent> Attributes { get; set; } = [];
public override void Parse(Queue<byte> data)
{
NumberOfAttributes = DataTypes.ReadNextVarInt(data);
Attributes = new List<SubComponent>(NumberOfAttributes);
for (var i = 0; i < NumberOfAttributes; i++)
Attributes.Add(SubComponentRegistry.ParseSubComponent(SubComponents.Attribute, data));
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(NumberOfAttributes));
if (Attributes.Count != NumberOfAttributes)
throw new ArgumentNullException(nameof(Attributes), "Attributes count must match NumberOfAttributes.");
foreach (var attribute in Attributes)
data.AddRange(attribute.Serialize());
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_21;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_5;
public class EquippableComponent1215(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Slot { get; set; }
public SoundEventSubComponent? EquipSound { get; set; }
public bool HasAssetId { get; set; }
public string? AssetId { get; set; }
public bool HasCameraOverlay { get; set; }
public string? CameraOverlay { get; set; }
public bool HasAllowedEntities { get; set; }
public int AllowedEntitiesType { get; set; }
public string? AllowedEntitiesTag { get; set; }
public List<int>? AllowedEntitiesIds { get; set; }
public bool Dispensable { get; set; }
public bool Swappable { get; set; }
public bool DamageOnHurt { get; set; }
public bool EquipOnInteract { get; set; }
public override void Parse(Queue<byte> data)
{
Slot = DataTypes.ReadNextVarInt(data);
EquipSound = (SoundEventSubComponent)SubComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
HasAssetId = DataTypes.ReadNextBool(data);
if (HasAssetId)
AssetId = DataTypes.ReadNextString(data);
HasCameraOverlay = DataTypes.ReadNextBool(data);
if (HasCameraOverlay)
CameraOverlay = DataTypes.ReadNextString(data);
HasAllowedEntities = DataTypes.ReadNextBool(data);
if (HasAllowedEntities)
{
AllowedEntitiesType = DataTypes.ReadNextVarInt(data);
if (AllowedEntitiesType == 0)
{
AllowedEntitiesTag = DataTypes.ReadNextString(data);
AllowedEntitiesIds = null;
}
else
{
AllowedEntitiesTag = null;
AllowedEntitiesIds = new List<int>(Math.Max(AllowedEntitiesType - 1, 0));
for (var i = 0; i < AllowedEntitiesType - 1; i++)
AllowedEntitiesIds.Add(DataTypes.ReadNextVarInt(data));
}
}
Dispensable = DataTypes.ReadNextBool(data);
Swappable = DataTypes.ReadNextBool(data);
DamageOnHurt = DataTypes.ReadNextBool(data);
EquipOnInteract = DataTypes.ReadNextBool(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Slot));
if (EquipSound is null)
throw new ArgumentNullException(nameof(EquipSound), "EquipSound is required.");
data.AddRange(EquipSound.Serialize());
data.AddRange(DataTypes.GetBool(HasAssetId));
if (HasAssetId && AssetId is not null)
data.AddRange(DataTypes.GetString(AssetId));
data.AddRange(DataTypes.GetBool(HasCameraOverlay));
if (HasCameraOverlay && CameraOverlay is not null)
data.AddRange(DataTypes.GetString(CameraOverlay));
data.AddRange(DataTypes.GetBool(HasAllowedEntities));
if (HasAllowedEntities)
{
data.AddRange(DataTypes.GetVarInt(AllowedEntitiesType));
if (AllowedEntitiesType == 0 && AllowedEntitiesTag is not null)
{
data.AddRange(DataTypes.GetString(AllowedEntitiesTag));
}
else if (AllowedEntitiesIds is not null)
{
foreach (var id in AllowedEntitiesIds)
data.AddRange(DataTypes.GetVarInt(id));
}
}
data.AddRange(DataTypes.GetBool(Dispensable));
data.AddRange(DataTypes.GetBool(Swappable));
data.AddRange(DataTypes.GetBool(DamageOnHurt));
data.AddRange(DataTypes.GetBool(EquipOnInteract));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_21;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
using MinecraftClient.Protocol.Message;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_5;
public class JukeBoxPlayableComponent1215(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public bool IsHolder { get; set; }
public int HolderId { get; set; }
public string? ResourceKey { get; set; }
public SoundEventSubComponent? SoundEvent { get; set; }
public Dictionary<string, object>? DescriptionNbt { get; set; }
public string Description { get; set; } = string.Empty;
public float Duration { get; set; }
public int ComparatorOutput { get; set; }
public override void Parse(Queue<byte> data)
{
IsHolder = DataTypes.ReadNextBool(data);
if (IsHolder)
{
HolderId = DataTypes.ReadNextVarInt(data);
if (HolderId == 0)
{
SoundEvent = (SoundEventSubComponent)SubComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
DescriptionNbt = DataTypes.ReadNextNbt(data);
Description = ChatParser.ParseText(DescriptionNbt);
Duration = DataTypes.ReadNextFloat(data);
ComparatorOutput = DataTypes.ReadNextVarInt(data);
}
}
else
{
ResourceKey = DataTypes.ReadNextString(data);
}
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetBool(IsHolder));
if (IsHolder)
{
data.AddRange(DataTypes.GetVarInt(HolderId));
if (HolderId == 0)
{
if (SoundEvent is null)
throw new ArgumentNullException(nameof(SoundEvent), "Inline jukebox song requires a sound event.");
if (DescriptionNbt is null)
throw new ArgumentNullException(nameof(DescriptionNbt), "Inline jukebox song requires a description.");
data.AddRange(SoundEvent.Serialize());
data.AddRange(DataTypes.GetNbt(DescriptionNbt));
data.AddRange(DataTypes.GetFloat(Duration));
data.AddRange(DataTypes.GetVarInt(ComparatorOutput));
}
}
else
{
if (string.IsNullOrEmpty(ResourceKey))
throw new ArgumentNullException(nameof(ResourceKey), "Resource key is required for key-backed jukebox songs.");
data.AddRange(DataTypes.GetString(ResourceKey));
}
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
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;
public class ToolComponent1215(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int NumberOfRules { get; set; }
public List<RuleSubComponent> Rules { get; set; } = [];
public float DefaultMiningSpeed { get; set; }
public int DamagePerBlock { get; set; }
public bool CanDestroyBlocksInCreative { get; set; }
public override void Parse(Queue<byte> data)
{
NumberOfRules = DataTypes.ReadNextVarInt(data);
Rules = new List<RuleSubComponent>(NumberOfRules);
for (var i = 0; i < NumberOfRules; i++)
Rules.Add((RuleSubComponent)SubComponentRegistry.ParseSubComponent(SubComponents.Rule, data));
DefaultMiningSpeed = DataTypes.ReadNextFloat(data);
DamagePerBlock = DataTypes.ReadNextVarInt(data);
CanDestroyBlocksInCreative = DataTypes.ReadNextBool(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(NumberOfRules));
if (Rules.Count != NumberOfRules)
throw new ArgumentNullException(nameof(Rules), "Rules count must match NumberOfRules.");
foreach (var rule in Rules)
data.AddRange(rule.Serialize());
data.AddRange(DataTypes.GetFloat(DefaultMiningSpeed));
data.AddRange(DataTypes.GetVarInt(DamagePerBlock));
data.AddRange(DataTypes.GetBool(CanDestroyBlocksInCreative));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.IO;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
using MinecraftClient.Protocol.Message;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_8;
public class AttributeModifiersComponent1218(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int NumberOfAttributes { get; set; }
public List<SubComponent> Attributes { get; set; } = [];
public List<AttributeModifierDisplay> Displays { get; set; } = [];
public override void Parse(Queue<byte> data)
{
NumberOfAttributes = DataTypes.ReadNextVarInt(data);
Attributes = new List<SubComponent>(NumberOfAttributes);
Displays = new List<AttributeModifierDisplay>(NumberOfAttributes);
for (var i = 0; i < NumberOfAttributes; i++)
{
Attributes.Add(SubComponentRegistry.ParseSubComponent(SubComponents.Attribute, data));
Displays.Add(ReadDisplay(data));
}
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(NumberOfAttributes));
if (Attributes.Count != NumberOfAttributes)
throw new ArgumentNullException(nameof(Attributes), "Attributes count must match NumberOfAttributes.");
if (Displays.Count != NumberOfAttributes)
throw new ArgumentNullException(nameof(Displays), "Displays count must match NumberOfAttributes.");
for (var i = 0; i < NumberOfAttributes; i++)
{
data.AddRange(Attributes[i].Serialize());
data.AddRange(SerializeDisplay(Displays[i]));
}
return new Queue<byte>(data);
}
private AttributeModifierDisplay ReadDisplay(Queue<byte> data)
{
var displayType = DataTypes.ReadNextVarInt(data);
return displayType switch
{
0 => new AttributeModifierDisplay(AttributeModifierDisplayType.Default),
1 => new AttributeModifierDisplay(AttributeModifierDisplayType.Hidden),
2 => ReadOverrideDisplay(data),
_ => throw new InvalidDataException($"Unknown attribute modifier display type: {displayType}")
};
}
private AttributeModifierDisplay ReadOverrideDisplay(Queue<byte> data)
{
var overrideTextNbt = DataTypes.ReadNextNbt(data);
var overrideText = ChatParser.ParseText(overrideTextNbt);
return new AttributeModifierDisplay(AttributeModifierDisplayType.Override, overrideTextNbt, overrideText);
}
private Queue<byte> SerializeDisplay(AttributeModifierDisplay display)
{
var data = new List<byte>
{
};
data.AddRange(DataTypes.GetVarInt((int)display.Type));
if (display.Type == AttributeModifierDisplayType.Override)
{
if (display.OverrideTextNbt is null)
throw new ArgumentNullException(nameof(display.OverrideTextNbt), "Override display requires component NBT.");
data.AddRange(DataTypes.GetNbt(display.OverrideTextNbt));
}
return new Queue<byte>(data);
}
}
public sealed record AttributeModifierDisplay(
AttributeModifierDisplayType Type,
Dictionary<string, object>? OverrideTextNbt = null,
string? OverrideText = null);
public enum AttributeModifierDisplayType
{
Default = 0,
Hidden = 1,
Override = 2
}

View file

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_21;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_8;
public class EquippableComponent1218(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Slot { get; set; }
public SoundEventSubComponent? EquipSound { get; set; }
public bool HasAssetId { get; set; }
public string? AssetId { get; set; }
public bool HasCameraOverlay { get; set; }
public string? CameraOverlay { get; set; }
public bool HasAllowedEntities { get; set; }
public int AllowedEntitiesType { get; set; }
public string? AllowedEntitiesTag { get; set; }
public List<int>? AllowedEntitiesIds { get; set; }
public bool Dispensable { get; set; }
public bool Swappable { get; set; }
public bool DamageOnHurt { get; set; }
public bool EquipOnInteract { get; set; }
public bool CanBeSheared { get; set; }
public SoundEventSubComponent? ShearingSound { get; set; }
public override void Parse(Queue<byte> data)
{
Slot = DataTypes.ReadNextVarInt(data);
EquipSound = (SoundEventSubComponent)SubComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
HasAssetId = DataTypes.ReadNextBool(data);
if (HasAssetId)
AssetId = DataTypes.ReadNextString(data);
HasCameraOverlay = DataTypes.ReadNextBool(data);
if (HasCameraOverlay)
CameraOverlay = DataTypes.ReadNextString(data);
HasAllowedEntities = DataTypes.ReadNextBool(data);
if (HasAllowedEntities)
{
AllowedEntitiesType = DataTypes.ReadNextVarInt(data);
if (AllowedEntitiesType == 0)
{
AllowedEntitiesTag = DataTypes.ReadNextString(data);
AllowedEntitiesIds = null;
}
else
{
AllowedEntitiesTag = null;
AllowedEntitiesIds = new List<int>(Math.Max(AllowedEntitiesType - 1, 0));
for (var i = 0; i < AllowedEntitiesType - 1; i++)
AllowedEntitiesIds.Add(DataTypes.ReadNextVarInt(data));
}
}
Dispensable = DataTypes.ReadNextBool(data);
Swappable = DataTypes.ReadNextBool(data);
DamageOnHurt = DataTypes.ReadNextBool(data);
EquipOnInteract = DataTypes.ReadNextBool(data);
CanBeSheared = DataTypes.ReadNextBool(data);
ShearingSound = (SoundEventSubComponent)SubComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Slot));
if (EquipSound is null)
throw new ArgumentNullException(nameof(EquipSound), "EquipSound is required.");
if (ShearingSound is null)
throw new ArgumentNullException(nameof(ShearingSound), "ShearingSound is required.");
data.AddRange(EquipSound.Serialize());
data.AddRange(DataTypes.GetBool(HasAssetId));
if (HasAssetId && AssetId is not null)
data.AddRange(DataTypes.GetString(AssetId));
data.AddRange(DataTypes.GetBool(HasCameraOverlay));
if (HasCameraOverlay && CameraOverlay is not null)
data.AddRange(DataTypes.GetString(CameraOverlay));
data.AddRange(DataTypes.GetBool(HasAllowedEntities));
if (HasAllowedEntities)
{
data.AddRange(DataTypes.GetVarInt(AllowedEntitiesType));
if (AllowedEntitiesType == 0 && AllowedEntitiesTag is not null)
{
data.AddRange(DataTypes.GetString(AllowedEntitiesTag));
}
else if (AllowedEntitiesIds is not null)
{
foreach (var id in AllowedEntitiesIds)
data.AddRange(DataTypes.GetVarInt(id));
}
}
data.AddRange(DataTypes.GetBool(Dispensable));
data.AddRange(DataTypes.GetBool(Swappable));
data.AddRange(DataTypes.GetBool(DamageOnHurt));
data.AddRange(DataTypes.GetBool(EquipOnInteract));
data.AddRange(DataTypes.GetBool(CanBeSheared));
data.AddRange(ShearingSound.Serialize());
return new Queue<byte>(data);
}
}

View file

@ -22,7 +22,7 @@ public class StructuredComponentsRegistry1206 : StructuredComponentRegistry
RegisterComponent<CanPlaceOnComponent>(10, "minecraft:can_place_on");
RegisterComponent<CanBreakComponent>(11, "minecraft:can_break");
RegisterComponent<AttributeModifiersComponent>(12, "minecraft:attribute_modifiers");
RegisterComponent<CustomModelDataComponent>(13, "minecraft:custom_model_data");
RegisterComponent<CustomModelDataComponent1206>(13, "minecraft:custom_model_data");
RegisterComponent<HideAdditionalTooltipComponent>(14, "minecraft:hide_additional_tooltip");
RegisterComponent<HideTooltipComponent>(15, "minecraft:hide_tooltip");
RegisterComponent<RepairCostComponent>(16, "minecraft:repair_cost");
@ -66,4 +66,4 @@ public class StructuredComponentsRegistry1206 : StructuredComponentRegistry
RegisterComponent<LockComponent>(54, "minecraft:lock");
RegisterComponent<ContainerLootComponent>(55, "minecraft:container_loot");
}
}
}

View file

@ -23,7 +23,7 @@ public class StructuredComponentsRegistry121 : StructuredComponentRegistry
RegisterComponent<CanPlaceOnComponent>(10, "minecraft:can_place_on");
RegisterComponent<CanBreakComponent>(11, "minecraft:can_break");
RegisterComponent<AttributeModifiersComponent>(12, "minecraft:attribute_modifiers");
RegisterComponent<CustomModelDataComponent>(13, "minecraft:custom_model_data");
RegisterComponent<CustomModelDataComponent1206>(13, "minecraft:custom_model_data");
RegisterComponent<HideAdditionalTooltipComponent>(14, "minecraft:hide_additional_tooltip");
RegisterComponent<HideTooltipComponent>(15, "minecraft:hide_tooltip");
RegisterComponent<RepairCostComponent>(16, "minecraft:repair_cost");
@ -52,7 +52,7 @@ public class StructuredComponentsRegistry121 : StructuredComponentRegistry
RegisterComponent<BlockEntityDataComponent>(39, "minecraft:block_entity_data");
RegisterComponent<InstrumentComponent>(40, "minecraft:instrument");
RegisterComponent<OmniousBottleAmplifierComponent>(41, "minecraft:ominous_bottle_amplifier");
RegisterComponent<JukeBoxPlayableComponent>(42, "minecraft:jukebox_playable");
RegisterComponent<JukeBoxPlayableComponent121>(42, "minecraft:jukebox_playable");
RegisterComponent<RecipesComponent>(43, "minecraft:recipes");
RegisterComponent<LodestoneTrackerComponent>(44, "minecraft:lodestone_tracker");
RegisterComponent<FireworkExplosionComponent>(45, "minecraft:firework_explosion");
@ -68,4 +68,4 @@ public class StructuredComponentsRegistry121 : StructuredComponentRegistry
RegisterComponent<LockComponent>(55, "minecraft:lock");
RegisterComponent<ContainerLootComponent>(56, "minecraft:container_loot");
}
}
}

View file

@ -4,6 +4,7 @@ using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_5;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_8;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_11;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
@ -30,7 +31,7 @@ public class StructuredComponentsRegistry12111 : StructuredComponentRegistry
RegisterComponent<EnchantmentsComponent1215>(13, "minecraft:enchantments");
RegisterComponent<CanPlaceOnComponent>(14, "minecraft:can_place_on");
RegisterComponent<CanBreakComponent>(15, "minecraft:can_break");
RegisterComponent<AttributeModifiersComponent>(16, "minecraft:attribute_modifiers");
RegisterComponent<AttributeModifiersComponent1218>(16, "minecraft:attribute_modifiers");
RegisterComponent<CustomModelDataComponent>(17, "minecraft:custom_model_data");
RegisterComponent<TooltipDisplayComponent>(18, "minecraft:tooltip_display");
RegisterComponent<RepairCostComponent>(19, "minecraft:repair_cost");
@ -42,11 +43,11 @@ public class StructuredComponentsRegistry12111 : StructuredComponentRegistry
RegisterComponent<UseRemainderComponent>(25, "minecraft:use_remainder");
RegisterComponent<UseCooldownComponent>(26, "minecraft:use_cooldown");
RegisterComponent<DamageResistantComponent>(27, "minecraft:damage_resistant");
RegisterComponent<ToolComponent>(28, "minecraft:tool");
RegisterComponent<ToolComponent1215>(28, "minecraft:tool");
RegisterComponent<WeaponComponent>(29, "minecraft:weapon");
RegisterComponent<AttackRangeComponent>(30, "minecraft:attack_range");
RegisterComponent<EnchantableComponent>(31, "minecraft:enchantable");
RegisterComponent<EquippableComponent>(32, "minecraft:equippable");
RegisterComponent<EquippableComponent1218>(32, "minecraft:equippable");
RegisterComponent<RepairableComponent>(33, "minecraft:repairable");
RegisterComponent<GliderComponent>(34, "minecraft:glider");
RegisterComponent<TooltipStyleComponent>(35, "minecraft:tooltip_style");
@ -63,7 +64,7 @@ public class StructuredComponentsRegistry12111 : StructuredComponentRegistry
RegisterComponent<MapPostProcessingComponent>(46, "minecraft:map_post_processing");
RegisterComponent<ChargedProjectilesComponent>(47, "minecraft:charged_projectiles");
RegisterComponent<BundleContentsComponent>(48, "minecraft:bundle_contents");
RegisterComponent<PotionContentsComponent>(49, "minecraft:potion_contents");
RegisterComponent<PotionContentsComponent1212>(49, "minecraft:potion_contents");
RegisterComponent<PotionDurationScaleComponent>(50, "minecraft:potion_duration_scale");
RegisterComponent<SuspiciousStewEffectsComponent>(51, "minecraft:suspicious_stew_effects");
RegisterComponent<WritableBlookContentComponent>(52, "minecraft:writable_book_content");
@ -76,7 +77,7 @@ public class StructuredComponentsRegistry12111 : StructuredComponentRegistry
RegisterComponent<InstrumentComponent1215>(59, "minecraft:instrument");
RegisterComponent<ProvidesTrimMaterialComponent>(60, "minecraft:provides_trim_material");
RegisterComponent<OmniousBottleAmplifierComponent>(61, "minecraft:ominous_bottle_amplifier");
RegisterComponent<JukeBoxPlayableComponent>(62, "minecraft:jukebox_playable");
RegisterComponent<JukeBoxPlayableComponent1215>(62, "minecraft:jukebox_playable");
RegisterComponent<ProvidesBannerPatternsComponent>(63, "minecraft:provides_banner_patterns");
RegisterComponent<RecipesComponent>(64, "minecraft:recipes");
RegisterComponent<LodestoneTrackerComponent>(65, "minecraft:lodestone_tracker");

View file

@ -25,7 +25,7 @@ public class StructuredComponentsRegistry1212 : StructuredComponentRegistry
RegisterComponent<CanPlaceOnComponent>(11, "minecraft:can_place_on");
RegisterComponent<CanBreakComponent>(12, "minecraft:can_break");
RegisterComponent<AttributeModifiersComponent>(13, "minecraft:attribute_modifiers");
RegisterComponent<CustomModelDataComponent>(14, "minecraft:custom_model_data");
RegisterComponent<CustomModelDataComponent1206>(14, "minecraft:custom_model_data");
RegisterComponent<HideAdditionalTooltipComponent>(15, "minecraft:hide_additional_tooltip");
RegisterComponent<HideTooltipComponent>(16, "minecraft:hide_tooltip");
RegisterComponent<RepairCostComponent>(17, "minecraft:repair_cost");
@ -52,7 +52,7 @@ public class StructuredComponentsRegistry1212 : StructuredComponentRegistry
RegisterComponent<MapPostProcessingComponent>(38, "minecraft:map_post_processing");
RegisterComponent<ChargedProjectilesComponent>(39, "minecraft:charged_projectiles");
RegisterComponent<BundleContentsComponent>(40, "minecraft:bundle_contents");
RegisterComponent<PotionContentsComponent>(41, "minecraft:potion_contents");
RegisterComponent<PotionContentsComponent1212>(41, "minecraft:potion_contents");
RegisterComponent<SuspiciousStewEffectsComponent>(42, "minecraft:suspicious_stew_effects");
RegisterComponent<WritableBlookContentComponent>(43, "minecraft:writable_book_content");
RegisterComponent<WrittenBlookContentComponent>(44, "minecraft:written_book_content");
@ -63,7 +63,7 @@ public class StructuredComponentsRegistry1212 : StructuredComponentRegistry
RegisterComponent<BlockEntityDataComponent>(49, "minecraft:block_entity_data");
RegisterComponent<InstrumentComponent>(50, "minecraft:instrument");
RegisterComponent<OmniousBottleAmplifierComponent>(51, "minecraft:ominous_bottle_amplifier");
RegisterComponent<JukeBoxPlayableComponent>(52, "minecraft:jukebox_playable");
RegisterComponent<JukeBoxPlayableComponent121>(52, "minecraft:jukebox_playable");
RegisterComponent<RecipesComponent>(53, "minecraft:recipes");
RegisterComponent<LodestoneTrackerComponent>(54, "minecraft:lodestone_tracker");
RegisterComponent<FireworkExplosionComponent>(55, "minecraft:firework_explosion");

View file

@ -4,6 +4,7 @@ using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_20_6;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_5;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_8;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries;
@ -26,7 +27,7 @@ public class StructuredComponentsRegistry1215 : StructuredComponentRegistry
RegisterComponent<EnchantmentsComponent1215>(10, "minecraft:enchantments");
RegisterComponent<CanPlaceOnComponent>(11, "minecraft:can_place_on");
RegisterComponent<CanBreakComponent>(12, "minecraft:can_break");
RegisterComponent<AttributeModifiersComponent>(13, "minecraft:attribute_modifiers");
RegisterComponent<AttributeModifiersComponent1215>(13, "minecraft:attribute_modifiers");
RegisterComponent<CustomModelDataComponent>(14, "minecraft:custom_model_data");
// 15: tooltip_display (NEW, replaces hide_additional_tooltip + hide_tooltip)
RegisterComponent<TooltipDisplayComponent>(15, "minecraft:tooltip_display");
@ -39,10 +40,10 @@ public class StructuredComponentsRegistry1215 : StructuredComponentRegistry
RegisterComponent<UseRemainderComponent>(22, "minecraft:use_remainder");
RegisterComponent<UseCooldownComponent>(23, "minecraft:use_cooldown");
RegisterComponent<DamageResistantComponent>(24, "minecraft:damage_resistant");
RegisterComponent<ToolComponent>(25, "minecraft:tool");
RegisterComponent<ToolComponent1215>(25, "minecraft:tool");
RegisterComponent<WeaponComponent>(26, "minecraft:weapon"); // NEW
RegisterComponent<EnchantableComponent>(27, "minecraft:enchantable");
RegisterComponent<EquippableComponent>(28, "minecraft:equippable");
RegisterComponent<EquippableComponent1215>(28, "minecraft:equippable");
RegisterComponent<RepairableComponent>(29, "minecraft:repairable");
RegisterComponent<GliderComponent>(30, "minecraft:glider");
RegisterComponent<TooltipStyleComponent>(31, "minecraft:tooltip_style");
@ -56,7 +57,7 @@ public class StructuredComponentsRegistry1215 : StructuredComponentRegistry
RegisterComponent<MapPostProcessingComponent>(39, "minecraft:map_post_processing");
RegisterComponent<ChargedProjectilesComponent>(40, "minecraft:charged_projectiles");
RegisterComponent<BundleContentsComponent>(41, "minecraft:bundle_contents");
RegisterComponent<PotionContentsComponent>(42, "minecraft:potion_contents");
RegisterComponent<PotionContentsComponent1212>(42, "minecraft:potion_contents");
RegisterComponent<PotionDurationScaleComponent>(43, "minecraft:potion_duration_scale"); // NEW
RegisterComponent<SuspiciousStewEffectsComponent>(44, "minecraft:suspicious_stew_effects");
RegisterComponent<WritableBlookContentComponent>(45, "minecraft:writable_book_content");
@ -69,7 +70,7 @@ public class StructuredComponentsRegistry1215 : StructuredComponentRegistry
RegisterComponent<InstrumentComponent1215>(52, "minecraft:instrument"); // Changed to EitherHolder<Instrument> in 1.21.5
RegisterComponent<ProvidesTrimMaterialComponent>(53, "minecraft:provides_trim_material"); // NEW
RegisterComponent<OmniousBottleAmplifierComponent>(54, "minecraft:ominous_bottle_amplifier");
RegisterComponent<JukeBoxPlayableComponent>(55, "minecraft:jukebox_playable");
RegisterComponent<JukeBoxPlayableComponent1215>(55, "minecraft:jukebox_playable");
RegisterComponent<ProvidesBannerPatternsComponent>(56, "minecraft:provides_banner_patterns"); // NEW
RegisterComponent<RecipesComponent>(57, "minecraft:recipes");
RegisterComponent<LodestoneTrackerComponent>(58, "minecraft:lodestone_tracker");

View file

@ -48,4 +48,16 @@ public class StructuredComponentsHandler
{
return ComponentRegistry.ParseComponent(componentId, data);
}
}
public string GetComponentName(int componentId)
{
try
{
return ComponentRegistry.GetComponentNameById(componentId);
}
catch
{
return "<unknown>";
}
}
}