diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/StructuredComponent.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/StructuredComponent.cs
index 2c0b66e3..5fa5f82d 100644
--- a/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/StructuredComponent.cs
+++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/StructuredComponent.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Text.Json.Serialization;
using MinecraftClient.Inventory.ItemPalettes;
namespace MinecraftClient.Protocol.Handlers.StructuredComponents.Core;
@@ -12,8 +13,15 @@ public abstract class StructuredComponent(DataTypes dataTypes, ItemPalette itemP
///
/// The registry type ID assigned during parsing, used for round-trip serialization.
///
+ [JsonIgnore]
public int TypeId { get; set; } = -1;
+ ///
+ /// The registry name assigned during parsing (e.g. "minecraft:custom_data"), used for NBT serialization.
+ ///
+ [JsonIgnore]
+ public string ComponentName { get; set; } = string.Empty;
+
public abstract void Parse(Queue data);
public abstract Queue Serialize();
}
\ No newline at end of file
diff --git a/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/StructuredComponentRegistry.cs b/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/StructuredComponentRegistry.cs
index 9ff1f12c..805f2a79 100644
--- a/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/StructuredComponentRegistry.cs
+++ b/MinecraftClient/Protocol/Handlers/StructuredComponents/Core/StructuredComponentRegistry.cs
@@ -37,6 +37,7 @@ public abstract class StructuredComponentRegistry(DataTypes dataTypes, ItemPalet
?? throw new InvalidOperationException($"Could not instantiate a parser for a structured component type {name}");
component.TypeId = id;
+ component.ComponentName = name;
component.Parse(data);
return component;
}
diff --git a/MinecraftClient/Scripting/MccGameApi.cs b/MinecraftClient/Scripting/MccGameApi.cs
index b7c8fbbd..9588691b 100644
--- a/MinecraftClient/Scripting/MccGameApi.cs
+++ b/MinecraftClient/Scripting/MccGameApi.cs
@@ -795,7 +795,8 @@ public sealed class MccGameApi
{
Slot = item.Key,
Type = item.Value.Type.ToString(),
- Count = item.Value.Count
+ Count = item.Value.Count,
+ Nbt = MccGameCommon.BuildNbt(item.Value)
})
.ToArray();
@@ -856,7 +857,8 @@ public sealed class MccGameApi
TypeLabel = pair.Value.GetTypeString(),
Count = pair.Value.Count,
IsPlayerInventory = entry.Key == 0,
- HotbarSlot = isHotbar ? hotbar + 1 : null
+ HotbarSlot = isHotbar ? hotbar + 1 : null,
+ Nbt = MccGameCommon.BuildNbt(pair.Value)
};
});
})
diff --git a/MinecraftClient/Scripting/MccGameCommon.cs b/MinecraftClient/Scripting/MccGameCommon.cs
index 0088dc80..ffca5beb 100644
--- a/MinecraftClient/Scripting/MccGameCommon.cs
+++ b/MinecraftClient/Scripting/MccGameCommon.cs
@@ -35,6 +35,7 @@ public sealed class MccItemStackSnapshot
{
public required string Type { get; init; }
public required int Count { get; init; }
+ public Dictionary? Nbt { get; init; }
}
///
@@ -177,10 +178,26 @@ public static class MccGameCommon
return new MccItemStackSnapshot
{
Type = item.Type.ToString(),
- Count = item.Count
+ Count = item.Count,
+ Nbt = BuildNbt(item)
};
}
+ public static Dictionary? BuildNbt(Item item)
+ {
+ if (item.Components is { Count: > 0 })
+ {
+ return item.Components
+ .Where(c => !string.IsNullOrEmpty(c.ComponentName))
+ .ToDictionary(
+ c => c.ComponentName,
+ c => (object)System.Text.Json.JsonSerializer.SerializeToElement(c, c.GetType())
+ );
+ }
+
+ return item.NBT is { Count: > 0 } ? item.NBT : null;
+ }
+
public static bool TryParseBlockQuery(string? query, out int? blockId, out int? blockMeta)
{
blockId = null;
diff --git a/MinecraftClient/Scripting/MccGameModels.cs b/MinecraftClient/Scripting/MccGameModels.cs
index 0c6b9c52..1eef6476 100644
--- a/MinecraftClient/Scripting/MccGameModels.cs
+++ b/MinecraftClient/Scripting/MccGameModels.cs
@@ -216,6 +216,7 @@ public sealed class MccInventorySnapshotSlot
public required int Slot { get; init; }
public required string Type { get; init; }
public required int Count { get; init; }
+ public Dictionary? Nbt { get; init; }
}
public sealed class MccInventorySnapshotResult
@@ -239,6 +240,7 @@ public sealed class MccInventorySearchMatch
public required int Count { get; init; }
public required bool IsPlayerInventory { get; init; }
public int? HotbarSlot { get; init; }
+ public Dictionary? Nbt { get; init; }
}
public sealed class MccInventorySearchResult