mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Wire up 1.20.6 structured components to Item and fix GetItemSlot serialization
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
This commit is contained in:
parent
bb18399523
commit
8eac21b4a4
5 changed files with 135 additions and 32 deletions
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
|
@ -450,15 +450,11 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
|
||||
for (var i = 0; i < numberofComponentsToRemove; i++)
|
||||
{
|
||||
// TODO: Check what this does exactly
|
||||
ReadNextVarInt(cache); // The type of component to remove
|
||||
}
|
||||
|
||||
// TODO: Wire up the strctured components in the Item class (extract info, update fields, etc..)
|
||||
// Use strcturedComponentsToAdd
|
||||
// Look at: https://wiki.vg/index.php?title=Slot_Data&oldid=19350#Structured_components
|
||||
|
||||
ReadNextVarInt(cache);
|
||||
|
||||
if (strcturedComponentsToAdd.Count > 0)
|
||||
item.Components = strcturedComponentsToAdd;
|
||||
|
||||
return item;
|
||||
case >= Protocol18Handler.MC_1_13_Version:
|
||||
{
|
||||
|
|
@ -1561,17 +1557,44 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
/// <returns>Item slot representation</returns>
|
||||
public byte[] GetItemSlot(Item? item, ItemPalette itemPalette)
|
||||
{
|
||||
// TODO: Wire up Structured components for 1.20.6
|
||||
|
||||
List<byte> slotData = new();
|
||||
if (protocolversion > Protocol18Handler.MC_1_13_Version)
|
||||
|
||||
if (protocolversion >= Protocol18Handler.MC_1_20_6_Version)
|
||||
{
|
||||
// MC 1.13 and greater
|
||||
if (item == null || item.IsEmpty)
|
||||
slotData.AddRange(GetBool(false)); // No item
|
||||
{
|
||||
slotData.AddRange(GetVarInt(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
slotData.AddRange(GetBool(true)); // Item is present
|
||||
slotData.AddRange(GetVarInt(item.Count));
|
||||
slotData.AddRange(GetVarInt(itemPalette.ToId(item.Type)));
|
||||
|
||||
if (item.Components != null && item.Components.Count > 0)
|
||||
{
|
||||
slotData.AddRange(GetVarInt(item.Components.Count));
|
||||
slotData.AddRange(GetVarInt(0)); // components to remove
|
||||
foreach (var component in item.Components)
|
||||
{
|
||||
slotData.AddRange(GetVarInt(component.TypeId));
|
||||
var serialized = component.Serialize();
|
||||
slotData.AddRange(serialized);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
slotData.AddRange(GetVarInt(0)); // no components to add
|
||||
slotData.AddRange(GetVarInt(0)); // no components to remove
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (protocolversion > Protocol18Handler.MC_1_13_Version)
|
||||
{
|
||||
if (item == null || item.IsEmpty)
|
||||
slotData.AddRange(GetBool(false));
|
||||
else
|
||||
{
|
||||
slotData.AddRange(GetBool(true));
|
||||
slotData.AddRange(GetVarInt(itemPalette.ToId(item.Type)));
|
||||
slotData.Add((byte)item.Count);
|
||||
slotData.AddRange(GetNbt(item.NBT));
|
||||
|
|
@ -1579,13 +1602,10 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
else
|
||||
{
|
||||
// MC 1.12.2 and lower
|
||||
if (item == null || item.IsEmpty)
|
||||
slotData.AddRange(GetShort(-1));
|
||||
else
|
||||
{
|
||||
// For 1.8 - 1.12.2 we combine Item Id and Item Data to a single value using: (id << 16) | data
|
||||
// Thus to get an ID we do a right shift by 16 bits
|
||||
slotData.AddRange(GetShort((short)(itemPalette.ToId(item.Type) >> 16)));
|
||||
slotData.Add((byte)item.Count);
|
||||
slotData.Add((byte)item.Data);
|
||||
|
|
|
|||
|
|
@ -8,7 +8,12 @@ public abstract class StructuredComponent(DataTypes dataTypes, ItemPalette itemP
|
|||
protected DataTypes DataTypes { get; private set; } = dataTypes;
|
||||
protected SubComponentRegistry SubComponentRegistry { get; private set; } = subComponentRegistry;
|
||||
protected ItemPalette ItemPalette { get; private set; } = itemPalette;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The registry type ID assigned during parsing, used for round-trip serialization.
|
||||
/// </summary>
|
||||
public int TypeId { get; set; } = -1;
|
||||
|
||||
public abstract void Parse(Queue<byte> data);
|
||||
public abstract Queue<byte> Serialize();
|
||||
}
|
||||
|
|
@ -35,7 +35,8 @@ public abstract class StructuredComponentRegistry(DataTypes dataTypes, ItemPalet
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue