部件材料 NBT 与 metadata 方案

28 个 ItemTGregPart 实例共用一套"材料即变体"的编码:metadata 存材料 ID,NBT 存材料名。 这是理解本 mod 全部物品行为的基础。

双字段方案

载体 字段 类型 值
ItemStack metadata getItemDamage() int TGregworks.registry.matIDs.get(材料),默认从 1500 起分配
NBT Compound material String GT Materials.mName,如 Iron / Osmiridium

ItemTGregPart.setHasSubtypes(true) 让 metadata 参与区分物品,但这不是 0/1/2… 的定长 subtype, 而是一张最多 16383 项的动态材料 ID 表。

TGregUtils:三个 NBT 助手

vexatos.tgregworks.util.TGregUtils:

方法 行为
getTagCompound(stack) 有则返回,没有就 new 一个并 setTagCompound 写回
getCompoundTag(tag, key) / getCompoundTag(stack, key) 同上,作用在嵌套 Compound 上
getMaterialID(stack) 无 material → 返回 -1;Materials.get(名字) 查不到 → 返回 0;否则返回 matIDs.get(m)
newItemStack(m, p, amount) 造一个 toolParts.get(p) 的 stack,metadata = matIDs.get(m),NBT material = m.mName

getMaterialID 是 ItemTGregPart.getMaterialID(stack) 的实现体,也是 TiC IToolPart 接口要求的方法。 注意它有两个不同的"查不到"返回值:-1(连 NBT 都没有)与 0(NBT 有但材料不存在)。 0 恰好是 getDisplayName 判定"旧存档/无效物品 → 追加 (Deprecated)"的阈值。

onUpdate:自动修复 metadata

ItemTGregPart.onUpdate(stack, world, entity, par4, par5) 在物品每 tick 位于某实体(含玩家背包) 中时调用:

data = getTagCompound(stack)
if (!data.hasKey("material")) return;          // 无 material → 不动
m = Materials.get(data.getString("material"))
matID = TGregworks.registry.matIDs.get(m)
if (matID != null && matID != stack.getItemDamage())
    stack.setItemDamage(matID);                 // 同步 metadata

这条逻辑是旧存档迁移路径:早期版本用 damage = 0 + NBT 区分材料, 后来改成 damage = 材料ID + NBT 冗余。放进背包一次就自动升级。

废弃标记

getItemStackDisplayName(stack):

  1. material 缺失 或 Materials.get(名字) == Materials._NULL → 材料名取本地化键 tgregworks.materials.unknown(zh_CN「未知」);
  2. 否则取 Materials.get(名字).mLocalizedName;
  3. 把语言条目 tgregworks.toolpart.<partname 去空格转小写> 里的 %%material 替换成材料名 ——语言条目本身已经写成 %%material Pickaxe Head 这种形状,替换后得到 铁 Pickaxe Head;
  4. stack.getItemDamage() == 0 时追加 tgregworks.tool.deprecated (en (Deprecated) / zh_CN (不推荐使用))。

getUnlocalizedName(stack) 返回 Materials.get(...).mDefaultLocalName(无本地化, 仅用于 debug/日志),getUnlocalizedName() 无参版返回 type.getPartName()(即 "Pickaxe Head" 这类英文原串)。

getSubItems:创造栏枚举

ItemTGregPart.getSubItems(Item b, CreativeTabs tab, List list) 对每个 toolMaterials 造 new ItemStack(b, 1, matIDs.get(m)) + NBT material, 所以创造栏里 28 个部件各自会列出全部入选材料(数量 = 入选材料数,不是 28)。

颜色

方法 行为
getRGBa(stack)(静态) 无 material 或查不到 → Materials._NULL.mRGBa;否则返回 m.mRGBa(并就地 clamp 到 0–255,会改到 GT 的共享数组)
getColorFromItemStack(stack, pass) 无 material → 交给父类;否则把 RGBa 的前三个分量打包成 int 传给客户端
getIcon / getIconFromDamage / getIconIndex 全部无条件返回 icons[0] —— 每个部件只有一张贴图,颜色全靠上面那条

registerIcons 只建 new IIcon[1],图标 = modTexPrefix + ":" + folder + textureNames[0] = tgregworks:items/parts/<texture>。

⚠️ getRGBa 里的 clamp 是就地写 m.mRGBa[i],会修改 GT Materials 单例共享的数组。 对正常材料(0–255)无影响,但如果某个 mod 注册了溢出的颜色,本 mod 会把它永久改掉。

创造栏

TConstructCreativeTab("tabTGregworks"),本地化 itemGroup.tabTGregworks = Tinkers' Gregworks / zh_CN 匠魂|GT材料。 preInit 结尾往里塞了一个样例:PartTypes.LargeSwordBlade + NBT material = Osmiridium (即"黑铱宽剑刃"),作为 tab 的显示图标。

相关条目