Crystal Chest(水晶箱子)
基本信息
| 属性 | 值 |
|---|---|
| 注册名 | IronChest:BlockIronChest @ metadata 5 |
| metadata 来源 | IronChestType.CRYSTAL.ordinal() |
| 显示名 | tile.ironchest:CRYSTAL.name = Crystal Chest |
| 枚举常量 | CRYSTAL |
| TileEntity | cpw.mods.ironchest.TileEntityCrystalChest(唯一实现 super(IronChestType.CRYSTAL)) |
| 硬度 | 3.0F |
| 爆炸抗性 | 否(resistance = 0) |
| 容量 | 108(size = 108) |
| 槽位形状 | 108 / 12 = 9 行 × 12 列 |
| 物品栏堆叠上限 | 64 |
| GUI 尺寸 | 238 × 256(GUIChest.GUI.CRYSTAL),贴图 ironchest:textures/gui/diamondcontainer.png(借用钻石箱子的) |
| 箱子等级 | tier = 5 |
| 材质 | blockGlass |
| 物品过滤 | 无 |
| 是否配置可关 | 否(isEnabled() 恒 true) |
全 mod 唯一的透明箱子
IronChestType.isTransparent() 是无参返回 this == CRYSTAL 的一行判断,全 mod 只有水晶箱子为 true。它触发三处独有行为:
1. sortTopStacks() 内容压缩
TileEntityIronChest.sortTopStacks() 开头就是:
if (!type.isTransparent() || (worldObj != null && worldObj.isRemote)) return;
非透明箱子直接返回,完全不计算。所以水晶箱子是唯一会维护 topStacks(长度 8 的 ItemStack[])的箱子。它的算法:
- 遍历全部 108 格,把
isItemEqual()的物品合并堆叠数(不是合并格子)。 - 复制一份数组,用
Comparator按stackSize降序排序(o2.stackSize - o1.stackSize,null 排最后)。 - 取前 8 个非空堆叠填入
topStacks。 - 若箱内从有东西变成空(
!hasStuff && hadStuff),清空topStacks并markBlockForUpdate。 - 调
worldObj.markBlockForUpdate通知客户端重渲染。
markDirty() 被覆写为 super.markDirty(); sortTopStacks();,getStackInSlot() 也会置 inventoryTouched = true(在 updateEntity() 里服务端每 tick 检查并重算)。
2. 悬浮物品渲染
TileEntityIronChestRenderer.render(TileEntityIronChestRenderer.java:133):
if (TRANSPARENT_RENDER_INSIDE && type.isTransparent()
&& tile.getDistanceFrom(mc.theWorld, mc.thePlayer) < TRANSPARENT_RENDER_DISTANCE) { ... }
渲染最多 8 个 topStacks 物品:每个挂在一个固定偏移点(shifts 9 个三维偏移数组)上,关光照(glDisable(2896))绕 Y 轴用 timeD 旋转,缩放 blockScale = 0.70F;若 topStacks[1] == null(即只有 1 种物品)则放大到 0.85 并整体下移。用一个共享的 EntityItem + 覆写的 RenderItem(getMiniBlockCount / getMiniItemCount 按 stackSize/32 封顶 15/7,shouldBob/shouldSpreadItems 返回 false)绘制。
3. 独立的网络同步
buildItemStackDataList() 只在 type.isTransparent() 时返回 8 个 topStacks,否则返回 null。PacketHandler 的 IronChestCodec 因此对水晶箱子多写一个 boolean + 8 个 ItemStack(判别字只有 0,通道名 IronChest;type 与 facing 压在一个 byte 里:低 4 位 type、高 4 位 facing)。客户端 handlePacketData 同样只对 VALUES[typeData].isTransparent() 生效。
配置项 透明箱子渲染 控制这两项。
配方
| 字段 | 值 | 实际生成的配方 |
|---|---|---|
recipeDirect |
"mmmmPmmmm" → mmm/mPm/mmm |
getRegistredChestsByTier(CRYSTAL, 5, -1) 返回 tier 5 的 3 个箱子(钻石/水晶/黑曜石),跳过自身后剩 2 条:8 玻璃围 1 钻石箱子 / 8 玻璃围 1 黑曜石箱子 |
recipeUpgradeOneTier |
null |
无 |
recipeUpgradeTwoTiers |
null |
无 |
水晶箱子的 recipeDirect 中 'm' 是 blockGlass(它的材质),与 'G'(固定玻璃)是同一个东西,所以配方实际就是 8 玻璃 + 1 个同级箱子。
升级关系
来源:
| 来源 | 形态 |
|---|---|
| Diamond to Crystal Chest Upgrade | GGG/GOG/GGG |
配方 recipeDirect |
8 玻璃围钻石箱子 或 8 玻璃围黑曜石箱子 |
去向:
| 升级器 | 目标 | 配方 |
|---|---|---|
| Crystal to Dark Steel Chest Upgrade | Dark Steel Chest | OOO/msm/OOO(108 → 135) |
水晶箱子是唯一不能直接升级到下界合金箱子的 tier 5 箱子——ChestChangerType 里 OBSIDIANNETHERITE 的 source 是 OBSIDIAN,不是 CRYSTAL。
语言文件里另有两条没有对应枚举常量的残留键:item.ironchest:DIAMONDNETHERITE.name(Diamond to Netherite Chest Upgrade)和 item.ironchest:CRYSTALNETHERITE.name(Crystal to Netherite Chest Upgrade)。它们在 ChestChangerType 中不存在,属于上游 mod 移除这两个升级器后遗留的未使用本地化键。
NBT 字段
Items(TAG_Compound 列表,每项含 Slot byte)、facing(byte)。TileEntityCrystalChest 无任何覆写。
[!NOTE]
topStacks是纯内存字段,从不写进 NBT。水晶箱子重新加载世界后,服务端readFromNBT末尾会调一次sortTopStacks()重建,但客户端必须等下一次描述包(getDescriptionPacket)才会看到悬浮物品。
渲染
| 事项 | 值 |
|---|---|
| 方块图标 | ironchest:crystal_top / crystal_front / crystal_side |
| 模型贴图 | ironchest:textures/model/crystalchest.png |
| GUI 贴图 | ironchest:textures/gui/diamondcontainer.png(借用) |
| 悬浮物品 | 8 个 topStacks,受 transparentRenderInside / transparentRenderDistance 控制 |
相关条目
- Iron Chest 方块 - metadata 与抗爆机制
- ItemIronChest - 物品形态
- 透明箱子渲染 - 两个控制悬浮物品显示的配置项
- Crystal to Dark Steel Chest Upgrade · Diamond to Crystal Chest Upgrade