mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
In 1.20.6+, items use structured components instead of NBT for metadata. Previously, ReadNextItemSlot parsed the components but never stored them on the Item instance, leaving DisplayName/Lores/Damage/Enchantments all empty. GetItemSlot also still used the pre-1.20.6 format (bool + VarInt + byte + NBT), causing the server to reject any item operation packets. Changes: Item.cs: - Add List<StructuredComponent>? Components field to hold the raw component list for round-trip serialization - DisplayName property: read from CustomNameComponent (with ItemNameComponent as fallback) when Components is present - Lores property: read from LoreNameComponent1206 when Components is present - Damage property: read from DamageComponent when Components is present - Add EnchantmentList property: read from EnchantmentsComponent (covers both normal and StoredEnchantmentsComponent for enchanted books) - ToFullString(): use EnchantmentList with EnchantmentMapping for display when available, fall back to NBT path for older versions - Add CloneWithCount() method that preserves both NBT and Components DataTypes.cs - ReadNextItemSlot: - Assign parsed strcturedComponentsToAdd to item.Components DataTypes.cs - GetItemSlot: - Add 1.20.6+ branch: write VarInt(count) + VarInt(itemId) + component counts + serialized components (using each component's TypeId and Serialize() method) - Empty slot sends VarInt(0) per the 1.20.6 protocol spec StructuredComponent.cs: - Add int TypeId property (default -1) to store the registry type ID assigned during parsing, enabling round-trip serialization StructuredComponentRegistry.cs: - Set component.TypeId = id after instantiation in ParseComponent() McClient.cs: - Replace manual Item constructor calls (new Item(type, count, nbt)) with Item.CloneWithCount() to preserve Components during inventory operations like slot moves, stack splits, and right-click placement Made-with: Cursor
65 lines
No EOL
2.4 KiB
C#
65 lines
No EOL
2.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using MinecraftClient.Inventory.ItemPalettes;
|
|
|
|
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
|
|
|
|
public abstract class StructuredComponentRegistry(DataTypes dataTypes, ItemPalette itemPalette, SubComponentRegistry subComponentRegistry)
|
|
{
|
|
private Dictionary<string, Type> ComponentParsers { get; } = new();
|
|
private Dictionary<int, string> IdToComponent { get; } = new();
|
|
private Dictionary<string, int> ComponentToId { get; } = new();
|
|
|
|
protected void RegisterComponent<T>(int id, string name) where T : StructuredComponent
|
|
{
|
|
if (string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(name))
|
|
throw new ArgumentNullException(nameof(name));
|
|
|
|
name = name.ToLower();
|
|
|
|
if (ComponentParsers.ContainsKey(name) || IdToComponent.ContainsValue(name)
|
|
|| ComponentToId.ContainsKey(name) || IdToComponent.ContainsKey(id))
|
|
throw new InvalidOperationException($"A component with name '{name}' or id '{id}' is already registered.");
|
|
|
|
ComponentParsers[name] = typeof(T);
|
|
IdToComponent[id] = name;
|
|
ComponentToId[name] = id;
|
|
}
|
|
|
|
public StructuredComponent ParseComponent(int id, Queue<byte> data)
|
|
{
|
|
if (IdToComponent.TryGetValue(id, out var name))
|
|
{
|
|
if (ComponentParsers.TryGetValue(name, out var type))
|
|
{
|
|
var component =
|
|
Activator.CreateInstance(type, dataTypes, itemPalette, subComponentRegistry) as StructuredComponent
|
|
?? throw new InvalidOperationException($"Could not instantiate a parser for a structured component type {name}");
|
|
|
|
component.TypeId = id;
|
|
component.Parse(data);
|
|
return component;
|
|
}
|
|
}
|
|
|
|
throw new Exception($"No parser found for component with ID {id}");
|
|
}
|
|
|
|
public string GetComponentNameById(int id)
|
|
{
|
|
if (IdToComponent.TryGetValue(id, out var value))
|
|
return value;
|
|
|
|
throw new Exception($"No component found for ID {id}");
|
|
}
|
|
|
|
public int GetComponentIdByName(string name)
|
|
{
|
|
name = name.ToLower();
|
|
|
|
if (ComponentToId.TryGetValue(name, out var value))
|
|
return value;
|
|
|
|
throw new Exception($"No ID found for component {name}");
|
|
}
|
|
} |