feat: add packet palette, data components, and protocol fixes for MC 1.21.2

Packet Palette (Phase 2.1):
- Create PacketPalette1212.cs with complete ID mapping for protocol 768
  (131 clientbound + 60 serverbound play packets, plus config packets)
- Add new PacketTypesIn enum values: EntityPositionSync, MoveMinecartAlongTrack,
  PlayerRotation, RecipeBookAdd/Remove/Settings, SetCursorItem, SetHeldSlot,
  SetPlayerInventory
- Add new PacketTypesOut enum values: BundleItemSelected, ClientTickEnd
- Update PacketType18Handler routing for 1.21.2

Data Components (Phase 1.4):
- Create StructuredComponentsRegistry1212 with 67 components (was 57 in 1.21)
  reflecting the new 1.21.2 DataComponents ordering
- Implement 11 new component parsers: ConsumableComponent, UseRemainderComponent,
  UseCooldownComponent, DamageResistantComponent, EnchantableComponent,
  EquippableComponent, RepairableComponent, GliderComponent, TooltipStyleComponent,
  DeathProtectionComponent, ItemModelComponent
- Create FoodComponent1212 (simplified: nutrition/saturation/canAlwaysEat only;
  eatSeconds/effects/usingConvertsTo moved to consumable/use_remainder)
- Create SubComponentRegistry1212 and route in StructuredComponentsHandler

Protocol Fixes:
- Fix PlayerPositionAndLook packet for 1.21.2 (new format: teleportId first,
  added deltaMovement Vec3, flags as Int instead of Byte)
- Fix login success packet (remove strictErrorHandling read for >= 1.21.2)
- Fix ClientSettings/ClientInformation packet (add particleStatus VarInt)
- Add SetHeldSlot as alias for HeldItemChange in packet handler

Verified: MCC connects to 1.21.2 vanilla server, stays connected, chat works.
Made-with: Cursor
This commit is contained in:
BruceChen 2026-03-20 03:25:20 +08:00
parent df833ae2a8
commit 57a0dedb33
20 changed files with 953 additions and 33 deletions

View file

@ -0,0 +1,129 @@
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_2;
public class ConsumableComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public float ConsumeSeconds { get; set; }
public int Animation { get; set; }
public SoundEventSubComponent? Sound { get; set; }
public bool HasConsumeParticles { get; set; }
public List<ConsumeEffectData> Effects { get; set; } = new();
public override void Parse(Queue<byte> data)
{
ConsumeSeconds = dataTypes.ReadNextFloat(data);
Animation = dataTypes.ReadNextVarInt(data);
Sound = (SoundEventSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
HasConsumeParticles = dataTypes.ReadNextBool(data);
var effectCount = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < effectCount; i++)
{
var effectTypeId = dataTypes.ReadNextVarInt(data);
var effectData = ReadConsumeEffectPayload(effectTypeId, data);
Effects.Add(new ConsumeEffectData(effectTypeId, effectData));
}
}
private byte[] ReadConsumeEffectPayload(int effectTypeId, Queue<byte> data)
{
var payload = new List<byte>();
switch (effectTypeId)
{
case 0: // apply_effects: List<MobEffectInstance> + probability(float)
var effectCount = dataTypes.ReadNextVarInt(data);
payload.AddRange(DataTypes.GetVarInt(effectCount));
for (var i = 0; i < effectCount; i++)
payload.AddRange(ReadMobEffectInstance(data));
payload.AddRange(DataTypes.GetFloat(dataTypes.ReadNextFloat(data)));
break;
case 1: // remove_effects: HolderSet<MobEffect>
payload.AddRange(ReadHolderSet(data));
break;
case 2: // clear_all_effects: empty
break;
case 3: // teleport_randomly: float diameter
payload.AddRange(DataTypes.GetFloat(dataTypes.ReadNextFloat(data)));
break;
case 4: // play_sound: Holder<SoundEvent>
var sound = (SoundEventSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
payload.AddRange(sound.Serialize());
break;
}
return payload.ToArray();
}
private byte[] ReadMobEffectInstance(Queue<byte> data)
{
var result = new List<byte>();
var effectId = dataTypes.ReadNextVarInt(data);
result.AddRange(DataTypes.GetVarInt(effectId));
result.AddRange(ReadMobEffectDetails(data));
return result.ToArray();
}
private byte[] ReadMobEffectDetails(Queue<byte> data)
{
var result = new List<byte>();
var amplifier = dataTypes.ReadNextVarInt(data);
result.AddRange(DataTypes.GetVarInt(amplifier));
var duration = dataTypes.ReadNextVarInt(data);
result.AddRange(DataTypes.GetVarInt(duration));
var ambient = dataTypes.ReadNextBool(data);
result.AddRange(DataTypes.GetBool(ambient));
var showParticles = dataTypes.ReadNextBool(data);
result.AddRange(DataTypes.GetBool(showParticles));
var showIcon = dataTypes.ReadNextBool(data);
result.AddRange(DataTypes.GetBool(showIcon));
var hasHiddenEffect = dataTypes.ReadNextBool(data);
result.AddRange(DataTypes.GetBool(hasHiddenEffect));
if (hasHiddenEffect)
result.AddRange(ReadMobEffectDetails(data));
return result.ToArray();
}
private byte[] ReadHolderSet(Queue<byte> data)
{
var result = new List<byte>();
var type = dataTypes.ReadNextVarInt(data);
result.AddRange(DataTypes.GetVarInt(type));
if (type == 0)
{
var tagName = dataTypes.ReadNextString(data);
result.AddRange(DataTypes.GetString(tagName));
}
else
{
for (var i = 0; i < type - 1; i++)
{
var id = dataTypes.ReadNextVarInt(data);
result.AddRange(DataTypes.GetVarInt(id));
}
}
return result.ToArray();
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetFloat(ConsumeSeconds));
data.AddRange(DataTypes.GetVarInt(Animation));
if (Sound != null) data.AddRange(Sound.Serialize());
data.AddRange(DataTypes.GetBool(HasConsumeParticles));
data.AddRange(DataTypes.GetVarInt(Effects.Count));
foreach (var effect in Effects)
{
data.AddRange(DataTypes.GetVarInt(effect.EffectTypeId));
data.AddRange(effect.Payload);
}
return new Queue<byte>(data);
}
public record ConsumeEffectData(int EffectTypeId, byte[] Payload);
}

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
public class DamageResistantComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public string Types { get; set; } = null!;
public override void Parse(Queue<byte> data)
{
Types = dataTypes.ReadNextString(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetString(Types));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,106 @@
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_2;
public class DeathProtectionComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public List<ConsumeEffectData> DeathEffects { get; set; } = new();
public override void Parse(Queue<byte> data)
{
var effectCount = dataTypes.ReadNextVarInt(data);
for (var i = 0; i < effectCount; i++)
{
var effectTypeId = dataTypes.ReadNextVarInt(data);
var effectData = ReadConsumeEffectPayload(effectTypeId, data);
DeathEffects.Add(new ConsumeEffectData(effectTypeId, effectData));
}
}
private byte[] ReadConsumeEffectPayload(int effectTypeId, Queue<byte> data)
{
var payload = new List<byte>();
switch (effectTypeId)
{
case 0: // apply_effects
var effectCount = dataTypes.ReadNextVarInt(data);
payload.AddRange(DataTypes.GetVarInt(effectCount));
for (var i = 0; i < effectCount; i++)
payload.AddRange(ReadMobEffectInstance(data));
payload.AddRange(DataTypes.GetFloat(dataTypes.ReadNextFloat(data)));
break;
case 1: // remove_effects
payload.AddRange(ReadHolderSet(data));
break;
case 2: // clear_all_effects
break;
case 3: // teleport_randomly
payload.AddRange(DataTypes.GetFloat(dataTypes.ReadNextFloat(data)));
break;
case 4: // play_sound
var sound = (SoundEventSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
payload.AddRange(sound.Serialize());
break;
}
return payload.ToArray();
}
private byte[] ReadMobEffectInstance(Queue<byte> data)
{
var result = new List<byte>();
result.AddRange(DataTypes.GetVarInt(dataTypes.ReadNextVarInt(data)));
result.AddRange(ReadMobEffectDetails(data));
return result.ToArray();
}
private byte[] ReadMobEffectDetails(Queue<byte> data)
{
var result = new List<byte>();
result.AddRange(DataTypes.GetVarInt(dataTypes.ReadNextVarInt(data)));
result.AddRange(DataTypes.GetVarInt(dataTypes.ReadNextVarInt(data)));
result.AddRange(DataTypes.GetBool(dataTypes.ReadNextBool(data)));
result.AddRange(DataTypes.GetBool(dataTypes.ReadNextBool(data)));
result.AddRange(DataTypes.GetBool(dataTypes.ReadNextBool(data)));
var hasHidden = dataTypes.ReadNextBool(data);
result.AddRange(DataTypes.GetBool(hasHidden));
if (hasHidden)
result.AddRange(ReadMobEffectDetails(data));
return result.ToArray();
}
private byte[] ReadHolderSet(Queue<byte> data)
{
var result = new List<byte>();
var type = dataTypes.ReadNextVarInt(data);
result.AddRange(DataTypes.GetVarInt(type));
if (type == 0)
{
result.AddRange(DataTypes.GetString(dataTypes.ReadNextString(data)));
}
else
{
for (var i = 0; i < type - 1; i++)
result.AddRange(DataTypes.GetVarInt(dataTypes.ReadNextVarInt(data)));
}
return result.ToArray();
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(DeathEffects.Count));
foreach (var effect in DeathEffects)
{
data.AddRange(DataTypes.GetVarInt(effect.EffectTypeId));
data.AddRange(effect.Payload);
}
return new Queue<byte>(data);
}
public record ConsumeEffectData(int EffectTypeId, byte[] Payload);
}

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
public class EnchantableComponent(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()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Value));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,94 @@
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_2;
public class EquippableComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Slot { get; set; }
public SoundEventSubComponent? EquipSound { get; set; }
public bool HasModel { get; set; }
public string? Model { 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 override void Parse(Queue<byte> data)
{
Slot = dataTypes.ReadNextVarInt(data);
EquipSound = (SoundEventSubComponent)subComponentRegistry.ParseSubComponent(SubComponents.SoundEvent, data);
HasModel = dataTypes.ReadNextBool(data);
if (HasModel)
Model = 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);
}
else
{
AllowedEntitiesIds = new List<int>();
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);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Slot));
if (EquipSound != null) data.AddRange(EquipSound.Serialize());
data.AddRange(DataTypes.GetBool(HasModel));
if (HasModel && Model != null)
data.AddRange(DataTypes.GetString(Model));
data.AddRange(DataTypes.GetBool(HasCameraOverlay));
if (HasCameraOverlay && CameraOverlay != null)
data.AddRange(DataTypes.GetString(CameraOverlay));
data.AddRange(DataTypes.GetBool(HasAllowedEntities));
if (HasAllowedEntities)
{
data.AddRange(DataTypes.GetVarInt(AllowedEntitiesType));
if (AllowedEntitiesType == 0 && AllowedEntitiesTag != null)
{
data.AddRange(DataTypes.GetString(AllowedEntitiesTag));
}
else if (AllowedEntitiesIds != 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));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,29 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
public class FoodComponent1212(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Nutrition { get; set; }
public float Saturation { get; set; }
public bool CanAlwaysEat { get; set; }
public override void Parse(Queue<byte> data)
{
Nutrition = dataTypes.ReadNextVarInt(data);
Saturation = dataTypes.ReadNextFloat(data);
CanAlwaysEat = dataTypes.ReadNextBool(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Nutrition));
data.AddRange(DataTypes.GetFloat(Saturation));
data.AddRange(DataTypes.GetBool(CanAlwaysEat));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,8 @@
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
public class GliderComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: EmptyComponent(dataTypes, itemPalette, subComponentRegistry);

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
public class ItemModelComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public string Identifier { get; set; } = null!;
public override void Parse(Queue<byte> data)
{
Identifier = dataTypes.ReadNextString(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetString(Identifier));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,44 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
public class RepairableComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public int Type { get; set; }
public string? TagName { get; set; }
public List<int>? ItemIds { get; set; }
public override void Parse(Queue<byte> data)
{
Type = dataTypes.ReadNextVarInt(data);
if (Type == 0)
{
TagName = dataTypes.ReadNextString(data);
}
else
{
ItemIds = new List<int>();
for (var i = 0; i < Type - 1; i++)
ItemIds.Add(dataTypes.ReadNextVarInt(data));
}
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetVarInt(Type));
if (Type == 0 && TagName != null)
{
data.AddRange(DataTypes.GetString(TagName));
}
else if (ItemIds != null)
{
foreach (var id in ItemIds)
data.AddRange(DataTypes.GetVarInt(id));
}
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
public class TooltipStyleComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public string Identifier { get; set; } = null!;
public override void Parse(Queue<byte> data)
{
Identifier = dataTypes.ReadNextString(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetString(Identifier));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,31 @@
using System.Collections.Generic;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
public class UseCooldownComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public float Seconds { get; set; }
public bool HasCooldownGroup { get; set; }
public string? CooldownGroup { get; set; }
public override void Parse(Queue<byte> data)
{
Seconds = dataTypes.ReadNextFloat(data);
HasCooldownGroup = dataTypes.ReadNextBool(data);
if (HasCooldownGroup)
CooldownGroup = dataTypes.ReadNextString(data);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(DataTypes.GetFloat(Seconds));
data.AddRange(DataTypes.GetBool(HasCooldownGroup));
if (HasCooldownGroup && CooldownGroup != null)
data.AddRange(DataTypes.GetString(CooldownGroup));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,24 @@
using System.Collections.Generic;
using MinecraftClient.Inventory;
using MinecraftClient.Inventory.ItemPalettes;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
public class UseRemainderComponent(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
{
public Item? ConvertInto { get; set; }
public override void Parse(Queue<byte> data)
{
ConvertInto = dataTypes.ReadNextItemSlot(data, ItemPalette);
}
public override Queue<byte> Serialize()
{
var data = new List<byte>();
data.AddRange(dataTypes.GetItemSlot(ConvertInto, ItemPalette));
return new Queue<byte>(data);
}
}

View file

@ -0,0 +1,82 @@
using MinecraftClient.Inventory.ItemPalettes;
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.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries;
public class StructuredComponentsRegistry1212 : StructuredComponentRegistry
{
public StructuredComponentsRegistry1212(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
: base(dataTypes, itemPalette, subComponentRegistry)
{
RegisterComponent<CustomDataComponent>(0, "minecraft:custom_data");
RegisterComponent<MaxStackSizeComponent>(1, "minecraft:max_stack_size");
RegisterComponent<MaxDamageComponent>(2, "minecraft:max_damage");
RegisterComponent<DamageComponent>(3, "minecraft:damage");
RegisterComponent<UnbrekableComponent1206>(4, "minecraft:unbreakable");
RegisterComponent<CustomNameComponent>(5, "minecraft:custom_name");
RegisterComponent<ItemNameComponent>(6, "minecraft:item_name");
RegisterComponent<ItemModelComponent>(7, "minecraft:item_model");
RegisterComponent<LoreNameComponent1206>(8, "minecraft:lore");
RegisterComponent<RarityComponent>(9, "minecraft:rarity");
RegisterComponent<EnchantmentsComponent>(10, "minecraft:enchantments");
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<HideAdditionalTooltipComponent>(15, "minecraft:hide_additional_tooltip");
RegisterComponent<HideTooltipComponent>(16, "minecraft:hide_tooltip");
RegisterComponent<RepairCostComponent>(17, "minecraft:repair_cost");
RegisterComponent<CreativeSlotLockComponent>(18, "minecraft:creative_slot_lock");
RegisterComponent<EnchantmentGlintOverrideComponent>(19, "minecraft:enchantment_glint_override");
RegisterComponent<IntangibleProjectileComponent>(20, "minecraft:intangible_projectile");
RegisterComponent<FoodComponent1212>(21, "minecraft:food");
RegisterComponent<ConsumableComponent>(22, "minecraft:consumable");
RegisterComponent<UseRemainderComponent>(23, "minecraft:use_remainder");
RegisterComponent<UseCooldownComponent>(24, "minecraft:use_cooldown");
RegisterComponent<DamageResistantComponent>(25, "minecraft:damage_resistant");
RegisterComponent<ToolComponent>(26, "minecraft:tool");
RegisterComponent<EnchantableComponent>(27, "minecraft:enchantable");
RegisterComponent<EquippableComponent>(28, "minecraft:equippable");
RegisterComponent<RepairableComponent>(29, "minecraft:repairable");
RegisterComponent<GliderComponent>(30, "minecraft:glider");
RegisterComponent<TooltipStyleComponent>(31, "minecraft:tooltip_style");
RegisterComponent<DeathProtectionComponent>(32, "minecraft:death_protection");
RegisterComponent<StoredEnchantmentsComponent>(33, "minecraft:stored_enchantments");
RegisterComponent<DyeColorComponent>(34, "minecraft:dyed_color");
RegisterComponent<MapColorComponent>(35, "minecraft:map_color");
RegisterComponent<MapIdComponent>(36, "minecraft:map_id");
RegisterComponent<MapDecorationsComponent>(37, "minecraft:map_decorations");
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<SuspiciousStewEffectsComponent>(42, "minecraft:suspicious_stew_effects");
RegisterComponent<WritableBlookContentComponent>(43, "minecraft:writable_book_content");
RegisterComponent<WrittenBlookContentComponent>(44, "minecraft:written_book_content");
RegisterComponent<TrimComponent>(45, "minecraft:trim");
RegisterComponent<DebugStickStateComponent>(46, "minecraft:debug_stick_state");
RegisterComponent<EntityDataComponent>(47, "minecraft:entity_data");
RegisterComponent<BucketEntityDataComponent>(48, "minecraft:bucket_entity_data");
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<RecipesComponent>(53, "minecraft:recipes");
RegisterComponent<LodestoneTrackerComponent>(54, "minecraft:lodestone_tracker");
RegisterComponent<FireworkExplosionComponent>(55, "minecraft:firework_explosion");
RegisterComponent<FireworksComponent>(56, "minecraft:fireworks");
RegisterComponent<ProfileComponent>(57, "minecraft:profile");
RegisterComponent<NoteBlockSoundComponent>(58, "minecraft:note_block_sound");
RegisterComponent<BannerPatternsComponent>(59, "minecraft:banner_patterns");
RegisterComponent<BaseColorComponent>(60, "minecraft:base_color");
RegisterComponent<PotDecorationsComponent>(61, "minecraft:pot_decorations");
RegisterComponent<ContainerComponent>(62, "minecraft:container");
RegisterComponent<BlockStateComponent>(63, "minecraft:block_state");
RegisterComponent<BeesComponent>(64, "minecraft:bees");
RegisterComponent<LockComponent>(65, "minecraft:lock");
RegisterComponent<ContainerLootComponent>(66, "minecraft:container_loot");
}
}

View file

@ -0,0 +1,11 @@
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components.Subcomponents._1_21;
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Registries.Subcomponents;
public class SubComponentRegistry1212 : SubComponentRegistry121
{
public SubComponentRegistry1212(DataTypes dataTypes) : base(dataTypes)
{
}
}

View file

@ -21,6 +21,7 @@ public class StructuredComponentsHandler
{
Protocol18Handler.MC_1_20_6_Version => typeof(SubComponentRegistry1206),
Protocol18Handler.MC_1_21_Version => typeof(SubComponentRegistry121),
>= Protocol18Handler.MC_1_21_2_Version => typeof(SubComponentRegistry1212),
_ => throw new NotSupportedException($"Protocol version {protocolVersion} is not supported for subcomponent registries!")
};
@ -32,6 +33,7 @@ public class StructuredComponentsHandler
{
Protocol18Handler.MC_1_20_6_Version => typeof(StructuredComponentsRegistry1206),
Protocol18Handler.MC_1_21_Version => typeof(StructuredComponentsRegistry121),
>= Protocol18Handler.MC_1_21_2_Version => typeof(StructuredComponentsRegistry1212),
_ => throw new NotSupportedException($"Protocol version {protocolVersion} is not supported for structured component registries!")
};