Skip to content

Commit 3f64a91

Browse files
authored
bugfix: Fixed Structured Components on 26.1 causing crashing with Shulkers
2 parents 6673b39 + 6331478 commit 3f64a91

7 files changed

Lines changed: 205 additions & 13 deletions

File tree

MinecraftClient/Protocol/Handlers/DataTypes.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,12 @@ public Dictionary<string, object> ReadNextNbt(Queue<byte> cache)
411411
return ReadNextNbt(cache, true);
412412
}
413413

414+
public object? ReadNextNbtTag(Queue<byte> cache)
415+
{
416+
var tagType = ReadNextByte(cache);
417+
return tagType == 0 ? null : ReadNbtField(cache, tagType);
418+
}
419+
414420
/// <summary>
415421
/// Read an ItemStackTemplate (26.1+) from a cache of bytes.
416422
/// Unlike ItemStack, this uses item-first encoding: item_id, count, DataComponentPatch.
@@ -1441,6 +1447,17 @@ public byte[] GetNbt(Dictionary<string, object>? nbt)
14411447
return GetNbt(nbt, true);
14421448
}
14431449

1450+
public byte[] GetNbtTag(object? tag)
1451+
{
1452+
if (tag is null)
1453+
return [0];
1454+
1455+
var tagData = GetNbtField(tag, out var tagType);
1456+
var data = new List<byte> { tagType };
1457+
data.AddRange(tagData);
1458+
return data.ToArray();
1459+
}
1460+
14441461
/// <summary>
14451462
/// Build an uncompressed Named Binary Tag blob for sending over the network (internal)
14461463
/// </summary>
@@ -1892,6 +1909,39 @@ public byte[] GetItemSlot(Item? item, ItemPalette itemPalette)
18921909
return slotData.ToArray();
18931910
}
18941911

1912+
/// <summary>
1913+
/// Get a byte array representing the given item as a non-empty ItemStackTemplate.
1914+
/// </summary>
1915+
/// <param name="item">Item</param>
1916+
/// <param name="itemPalette">Item Palette</param>
1917+
/// <returns>ItemStackTemplate representation</returns>
1918+
public byte[] GetItemStackTemplate(Item item, ItemPalette itemPalette)
1919+
{
1920+
List<byte> slotData = new();
1921+
1922+
slotData.AddRange(GetVarInt(itemPalette.ToId(item.Type)));
1923+
slotData.AddRange(GetVarInt(item.Count));
1924+
1925+
if (item.Components is not null && item.Components.Count > 0)
1926+
{
1927+
slotData.AddRange(GetVarInt(item.Components.Count));
1928+
slotData.AddRange(GetVarInt(0)); // components to remove
1929+
foreach (var component in item.Components)
1930+
{
1931+
slotData.AddRange(GetVarInt(component.TypeId));
1932+
var serialized = component.Serialize();
1933+
slotData.AddRange(serialized);
1934+
}
1935+
}
1936+
else
1937+
{
1938+
slotData.AddRange(GetVarInt(0)); // no components to add
1939+
slotData.AddRange(GetVarInt(0)); // no components to remove
1940+
}
1941+
1942+
return slotData.ToArray();
1943+
}
1944+
18951945
/// <summary>
18961946
/// Get a byte array representing an array of item slots
18971947
/// </summary>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.Collections.Generic;
2+
using MinecraftClient.Inventory;
3+
using MinecraftClient.Inventory.ItemPalettes;
4+
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
5+
6+
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._26_1;
7+
8+
public class ContainerComponent261(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
9+
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
10+
{
11+
public List<Item?> Items { get; set; } = [];
12+
13+
public override void Parse(Queue<byte> data)
14+
{
15+
var count = DataTypes.ReadNextVarInt(data);
16+
for (var i = 0; i < count; i++)
17+
Items.Add(DataTypes.ReadNextBool(data) ? DataTypes.ReadNextItemStackTemplate(data, ItemPalette) : null);
18+
}
19+
20+
public override Queue<byte> Serialize()
21+
{
22+
var data = new List<byte>();
23+
data.AddRange(DataTypes.GetVarInt(Items.Count));
24+
foreach (var item in Items)
25+
{
26+
var hasItem = item is not null && !item.IsEmpty;
27+
data.AddRange(DataTypes.GetBool(hasItem));
28+
if (hasItem)
29+
data.AddRange(DataTypes.GetItemStackTemplate(item!, ItemPalette));
30+
}
31+
32+
return new Queue<byte>(data);
33+
}
34+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Collections.Generic;
2+
using MinecraftClient.Inventory;
3+
using MinecraftClient.Inventory.ItemPalettes;
4+
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
5+
6+
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._26_1;
7+
8+
public class ItemStackTemplateListComponent261(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
9+
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
10+
{
11+
public List<Item> Items { get; set; } = [];
12+
13+
public override void Parse(Queue<byte> data)
14+
{
15+
var count = DataTypes.ReadNextVarInt(data);
16+
17+
for (var i = 0; i < count; i++)
18+
Items.Add(DataTypes.ReadNextItemStackTemplate(data, ItemPalette));
19+
}
20+
21+
public override Queue<byte> Serialize()
22+
{
23+
var data = new List<byte>();
24+
data.AddRange(DataTypes.GetVarInt(Items.Count));
25+
26+
foreach (var item in Items)
27+
data.AddRange(DataTypes.GetItemStackTemplate(item, ItemPalette));
28+
29+
return new Queue<byte>(data);
30+
}
31+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Collections.Generic;
2+
using MinecraftClient.Inventory.ItemPalettes;
3+
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
4+
5+
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._26_1;
6+
7+
public class NbtTagComponent261(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
8+
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
9+
{
10+
public object? Tag { get; set; }
11+
12+
public override void Parse(Queue<byte> data)
13+
{
14+
Tag = DataTypes.ReadNextNbtTag(data);
15+
}
16+
17+
public override Queue<byte> Serialize()
18+
{
19+
return new Queue<byte>(DataTypes.GetNbtTag(Tag));
20+
}
21+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Collections.Generic;
2+
using MinecraftClient.Inventory.ItemPalettes;
3+
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
4+
5+
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._26_1;
6+
7+
public class TypedEntityDataComponent261(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
8+
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
9+
{
10+
public int EntityTypeId { get; set; }
11+
public Dictionary<string, object>? Nbt { get; set; }
12+
13+
public override void Parse(Queue<byte> data)
14+
{
15+
EntityTypeId = DataTypes.ReadNextVarInt(data);
16+
Nbt = DataTypes.ReadNextNbt(data);
17+
}
18+
19+
public override Queue<byte> Serialize()
20+
{
21+
var data = new List<byte>();
22+
data.AddRange(DataTypes.GetVarInt(EntityTypeId));
23+
data.AddRange(DataTypes.GetNbt(Nbt));
24+
return new Queue<byte>(data);
25+
}
26+
}
27+
28+
public class BlockEntityDataComponent261(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
29+
: TypedEntityDataComponent261(dataTypes, itemPalette, subComponentRegistry) {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System.Collections.Generic;
2+
using MinecraftClient.Inventory;
3+
using MinecraftClient.Inventory.ItemPalettes;
4+
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
5+
6+
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Components._26_1;
7+
8+
public class UseRemainderComponent261(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
9+
: StructuredComponent(dataTypes, itemPalette, subComponentRegistry)
10+
{
11+
public Item? ConvertInto { get; set; }
12+
13+
public override void Parse(Queue<byte> data)
14+
{
15+
ConvertInto = DataTypes.ReadNextItemStackTemplate(data, ItemPalette);
16+
}
17+
18+
public override Queue<byte> Serialize()
19+
{
20+
var data = new List<byte>();
21+
if (ConvertInto is not null && !ConvertInto.IsEmpty)
22+
data.AddRange(DataTypes.GetItemStackTemplate(ConvertInto, ItemPalette));
23+
return new Queue<byte>(data);
24+
}
25+
}

MinecraftClient/Protocol/Handlers/StructuredComponents/Registries/StructuredComponentsRegistry261.cs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21;
55
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_2;
66
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_5;
7+
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_8;
8+
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_9;
79
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._1_21_11;
810
using MinecraftClient.Protocol.Handlers.StructuredComponents.Components._26_1;
911
using MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
@@ -31,7 +33,7 @@ public StructuredComponentsRegistry261(DataTypes dataTypes, ItemPalette itemPale
3133
RegisterComponent<EnchantmentsComponent1215>(13, "minecraft:enchantments");
3234
RegisterComponent<CanPlaceOnComponent1215>(14, "minecraft:can_place_on");
3335
RegisterComponent<CanBreakComponent1215>(15, "minecraft:can_break");
34-
RegisterComponent<AttributeModifiersComponent>(16, "minecraft:attribute_modifiers");
36+
RegisterComponent<AttributeModifiersComponent1218>(16, "minecraft:attribute_modifiers");
3537
RegisterComponent<CustomModelDataComponent>(17, "minecraft:custom_model_data");
3638
RegisterComponent<TooltipDisplayComponent>(18, "minecraft:tooltip_display");
3739
RegisterComponent<RepairCostComponent>(19, "minecraft:repair_cost");
@@ -40,14 +42,14 @@ public StructuredComponentsRegistry261(DataTypes dataTypes, ItemPalette itemPale
4042
RegisterComponent<IntangibleProjectileComponent>(22, "minecraft:intangible_projectile");
4143
RegisterComponent<FoodComponent1212>(23, "minecraft:food");
4244
RegisterComponent<ConsumableComponent>(24, "minecraft:consumable");
43-
RegisterComponent<UseRemainderComponent>(25, "minecraft:use_remainder");
45+
RegisterComponent<UseRemainderComponent261>(25, "minecraft:use_remainder");
4446
RegisterComponent<UseCooldownComponent>(26, "minecraft:use_cooldown");
4547
RegisterComponent<HolderSetComponent261>(27, "minecraft:damage_resistant");
46-
RegisterComponent<ToolComponent>(28, "minecraft:tool");
48+
RegisterComponent<ToolComponent1215>(28, "minecraft:tool");
4749
RegisterComponent<WeaponComponent>(29, "minecraft:weapon");
4850
RegisterComponent<AttackRangeComponent>(30, "minecraft:attack_range");
4951
RegisterComponent<EnchantableComponent>(31, "minecraft:enchantable");
50-
RegisterComponent<EquippableComponent>(32, "minecraft:equippable");
52+
RegisterComponent<EquippableComponent1218>(32, "minecraft:equippable");
5153
RegisterComponent<RepairableComponent>(33, "minecraft:repairable");
5254
RegisterComponent<GliderComponent>(34, "minecraft:glider");
5355
RegisterComponent<TooltipStyleComponent>(35, "minecraft:tooltip_style");
@@ -64,24 +66,24 @@ public StructuredComponentsRegistry261(DataTypes dataTypes, ItemPalette itemPale
6466
RegisterComponent<MapIdComponent>(46, "minecraft:map_id");
6567
RegisterComponent<MapDecorationsComponent>(47, "minecraft:map_decorations");
6668
RegisterComponent<MapPostProcessingComponent>(48, "minecraft:map_post_processing");
67-
RegisterComponent<ChargedProjectilesComponent>(49, "minecraft:charged_projectiles");
68-
RegisterComponent<BundleContentsComponent>(50, "minecraft:bundle_contents");
69-
RegisterComponent<PotionContentsComponent>(51, "minecraft:potion_contents");
69+
RegisterComponent<ItemStackTemplateListComponent261>(49, "minecraft:charged_projectiles");
70+
RegisterComponent<ItemStackTemplateListComponent261>(50, "minecraft:bundle_contents");
71+
RegisterComponent<PotionContentsComponent1212>(51, "minecraft:potion_contents");
7072
RegisterComponent<PotionDurationScaleComponent>(52, "minecraft:potion_duration_scale");
7173
RegisterComponent<SuspiciousStewEffectsComponent>(53, "minecraft:suspicious_stew_effects");
7274
RegisterComponent<WritableBlookContentComponent>(54, "minecraft:writable_book_content");
7375
RegisterComponent<WrittenBlookContentComponent>(55, "minecraft:written_book_content");
7476
RegisterComponent<TrimComponent1215>(56, "minecraft:trim");
7577
RegisterComponent<DebugStickStateComponent>(57, "minecraft:debug_stick_state");
76-
RegisterComponent<EntityDataComponent>(58, "minecraft:entity_data");
78+
RegisterComponent<TypedEntityDataComponent261>(58, "minecraft:entity_data");
7779
RegisterComponent<BucketEntityDataComponent>(59, "minecraft:bucket_entity_data");
78-
RegisterComponent<BlockEntityDataComponent>(60, "minecraft:block_entity_data");
80+
RegisterComponent<BlockEntityDataComponent261>(60, "minecraft:block_entity_data");
7981
RegisterComponent<InstrumentComponent261>(61, "minecraft:instrument");
8082
RegisterComponent<ProvidesTrimMaterialComponent261>(62, "minecraft:provides_trim_material");
8183
RegisterComponent<OmniousBottleAmplifierComponent>(63, "minecraft:ominous_bottle_amplifier");
82-
RegisterComponent<JukeBoxPlayableComponent>(64, "minecraft:jukebox_playable");
84+
RegisterComponent<JukeBoxPlayableComponent1215>(64, "minecraft:jukebox_playable");
8385
RegisterComponent<HolderSetComponent261>(65, "minecraft:provides_banner_patterns");
84-
RegisterComponent<RecipesComponent>(66, "minecraft:recipes");
86+
RegisterComponent<NbtTagComponent261>(66, "minecraft:recipes");
8587
RegisterComponent<LodestoneTrackerComponent>(67, "minecraft:lodestone_tracker");
8688
RegisterComponent<FireworkExplosionComponent>(68, "minecraft:firework_explosion");
8789
RegisterComponent<FireworksComponent>(69, "minecraft:fireworks");
@@ -90,9 +92,9 @@ public StructuredComponentsRegistry261(DataTypes dataTypes, ItemPalette itemPale
9092
RegisterComponent<BannerPatternsComponent>(72, "minecraft:banner_patterns");
9193
RegisterComponent<BaseColorComponent>(73, "minecraft:base_color");
9294
RegisterComponent<PotDecorationsComponent>(74, "minecraft:pot_decorations");
93-
RegisterComponent<ContainerComponent>(75, "minecraft:container");
95+
RegisterComponent<ContainerComponent261>(75, "minecraft:container");
9496
RegisterComponent<BlockStateComponent>(76, "minecraft:block_state");
95-
RegisterComponent<BeesComponent>(77, "minecraft:bees");
97+
RegisterComponent<BeesComponent1219>(77, "minecraft:bees");
9698
RegisterComponent<LockComponent>(78, "minecraft:lock");
9799
RegisterComponent<ContainerLootComponent>(79, "minecraft:container_loot");
98100

0 commit comments

Comments
 (0)