IronChestMinecarts

[!INFO] Git Commit: 7c65075 | Updated: 2026-04-26

Iron Chest Minecarts 为 Iron Chests 模组引入的每一种箱子等级提供一个"箱子矿车",让箱子随矿车在轨道上运输。它本身不注册任何方块、TileEntity、GUI、附魔或指令,核心内容是 8 个矿车物品 + 8 个矿车实体(共享同一个抽象基类)+ 1 个渲染配置项。

本仓库为 GTNH(GregTech: New Horizons)fork(Gradle tag 1.2.1,Minecraft 1.7.10 / Forge 10.13.4.1614),原作者 ganymedes01。

依赖

Reference.DEPENDENCIES:

声明 含义
required-after:Forge@[10.10,) 必须依赖 Forge
required-after:IronChest 必须依赖 Iron Chests
modid 显示名 依赖强度
ironchest Iron Chests 硬依赖(箱子方块、容器、GUI、升级器均来自它)
Railcraft Railcraft 软依赖(@Optional.Interface + @Optional.Method,未安装时相关代码被剥离)

代码结构

只有 15 个 Java 文件,全部内容如下:

文件 职责
IronChestMinecarts.java @Mod 主类;preInit 读配置、注册 GUI handler、注册 3 个原版矿石字典、按类型循环注册物品/矿车实体/矿石字典/渲染器;missingMapping 处理旧存档重映射
lib/Reference.java MOD_ID=ironchestminecarts、MOD_NAME="Iron Chest Minecarts"、依赖串、版本号
gui/GuiHandler.java IGuiHandler 实现,转发给 Iron Chests 的 ContainerIronChest / GUIChest(本模组不自绘 GUI)
minecarts/EntityMinecartIronChestAbstract.java 抽象基类:自建物品栏、NBT 读写、掉落、交互、箱子升级器、Railcraft IItemTransfer;types 包扫描注册
minecarts/types/EntityMinecart{8}Chest.java 8 个各 40 行的实体类,唯一实现是 type() 返回一个 IronChestType 常量
minecarts/ItemMinecartIronChest.java 矿车物品;覆写 onItemUse(在铁轨上放矿车)、Railcraft 显示名
minecarts/ItemMinecartRenderer.java 抽象 IItemRenderer,负责矿车模型 + 各 ItemRenderType 的缩放/位移
minecarts/ItemMinecartChestRenderer.java 上者的实现,用 RenderBlocks 渲染对应等级的铁箱子方块

变体总览(§ 变体穷举)

模组不是注册"一个带 8 个 metadata 的矿车物品",而是注册 8 个独立的 Item 实例;实体侧同理是 8 个独立的实体类。每个变体由一个 IronChestType 枚举常量唯一决定,等级、容量、槽位形状、纹理、矿石字典名、升级链全部随之变化。

等级与容量

变体(IronChestType) 实体 ID / 箱子 meta 箱子等级 矿车物品栏 槽位排布 箱子材料 抗爆 可放入物品
DIRTCHEST9000 泥土 7 -1(不参与升级链) 1 1 行 × 1 dirt 否 仅泥土(itemFilter = Blocks.dirt)
COPPER 铜 3 1 45 5 行 × 9 ingotCopper 否 全部
IRON 铁 0 2 54 6 行 × 9 ingotIron、ingotRefinedIron 否 全部
STEEL 钢 4 3 72 8 行 × 9 ingotSteel 否 全部
GOLD 金 1 4 81 9 行 × 9 ingotGold 否 全部
DIAMOND 钻石 2 5 108 9 行 × 12 gemDiamond 否 全部
OBSIDIAN 黑曜石 6 5 108 9 行 × 12 obsidian 是(resistance=1) 全部
CRYSTAL 水晶 5 5 108 9 行 × 12 blockGlass 否 全部
  • 槽位数 = getSizeInventory() = type().getRowCount() * type().getRowLength(),两者均来自 Iron Chests 的 IronChestType。
  • 唯一形状差异:IRON/GOLD/STEEL/COPPER/DIRTCHEST9000 每行 9 格;DIAMOND/OBSIDIAN/CRYSTAL 每行 12 格。泥土箱子是唯一的 1 格。
  • 108 格有三个并列变体(钻石 / 黑曜石 / 水晶),它们的区别不在容量而在材料、抗爆性和升级链位置。
  • 铜箱子(45 格)比铁箱子(54 格)更小,是唯一"等级与容量倒挂"的一档(等级 1 但只有 5 行)。

注册名 / 纹理 / 矿石字典对照

变体 物品注册名 物品纹理 实体 ID 名 矿石字典名
泥土 minecart_chest_dirtchest9000 minecart_chest_dirtchest9000.png minecart_chest_dirtchest9000 chestDirt
铜 minecart_chest_copper minecart_chest_copper.png minecart_chest_copper chestCopper
铁 minecart_chest_iron minecart_chest_iron.png minecart_chest_iron chestIron
钢 minecart_chest_steel minecart_chest_silver.png minecart_chest_silver chestSteel
金 minecart_chest_gold minecart_chest_gold.png minecart_chest_gold chestGold
钻石 minecart_chest_diamond minecart_chest_diamond.png minecart_chest_diamond chestDiamond
黑曜石 minecart_chest_obsidian minecart_chest_obsidian.png minecart_chest_obsidian chestObsidian
水晶 minecart_chest_crystal minecart_chest_crystal.png minecart_chest_crystal chestCrystal
  • 全部名字由 type.name().toLowerCase() 拼出,钢 是唯一例外:代码对 "steel" 做 .replace("teel", "ilver") → "silver",所以钢的实体 ID 名和纹理名是 silver,物品注册名是 steel。
  • 该不一致由 missingMapping 兜底:旧存档中的 ironchestminecarts:minecart_chest_silver(物品与方块两种类型)被重映射到 minecart_chest_steel。
  • 泥土箱子的物品/实体 ID 里保留了枚举名 dirtchest9000(只有矿石字典被特判成 chestDirt)。

无实体变体的 IronChestType

当前安装的 Iron Chests 枚举有 12 个值,但本模组只扫描 minecarts/types/ 下的 8 个类,且不检查 IronChestType.isEnabled()。因此以下 4 个等级永远没有矿车(即使 Iron Chests 配置文件启用了它们):

IronChestType 箱子容量 说明
NETHERITE 135 GTNH 默认关闭(Iron Chests 配置 !isGTNHLoaded)
DARKSTEEL 135 GTNH 默认开启,但仍无矿车
SILVER 72 与 STEEL 共享纹理,本模组不提供
WOOD 0 占位枚举(size=0),非真实箱子

这直接影响箱子升级器:目标为 SILVER / NETHERITE / DARKSTEEL 的升级器用在本模组矿车上会出问题,见下方"已知问题"。

共享机制

8 个变体的行为差异仅限上表(等级 / 容量 / 槽位 / 材料 / 抗爆 / 过滤器)。以下机制全部实现在抽象基类,8 个变体完全一致 —— 详见 共用机制基类。

机制 行为
物品栏 基类自建 ItemStack[] inventory,不依赖 Dropper TileEntity
放车 onItemUse:目标方块是铁轨(BlockRailBase.func_150051_a)时在方块中心生成矿车,消耗 1 个物品;否则返回 false
打开 右键矿车 → openGui(..., hashCode(), ...),GuiHandler 用该 hash 当实体 ID 取回矿车
升级 手持 Iron Chests 的箱子升级器右键矿车,整车 NBT(含物品栏)迁移到新等级的矿车,消耗 1 个升级器
破坏掉落 killMinecart:掉落 1 个原版 Items.minecart + 1 个对应等级的铁箱子 + 车内全部物品(带随机初速度散落)
NBT 存 Items 列表 + CustomDisplayTile/DisplayTile/DisplayData/DisplayOffset + CustomName
Railcraft 实现 IItemTransfer(offerItem / 3 个 requestItem),卸载器与装料器可直接操作
事件 交互前发布可取消的 MinecartInteractEvent

已知问题(源码可复现)

  1. 箱子升级器会销毁矿车:当升级器目标等级是本模组未注册的 4 个 IronChestType 之一时,interactFirst 先 setDead() 杀掉旧矿车,再对 map.get(newType) 的 null 调用 getConstructor 抛 NPE,被 catch (Exception) 捕获后仅 printStackTrace() —— 矿车和车内物品一起消失,玩家只看到日志。受影响组合:

    升级器 源 → 目标 结果
    copperSilverUpgrade 铜 → 银 矿车消失
    ironSilverUpgrade 铁 → 银 矿车消失
    obsidianNetheriteUpgrade 黑曜石 → 下界合金 矿车消失
    diamondDarkSteelUpgrade 钻石 → 暗钢 矿车消失
    crystalDarkSteelUpgrade 水晶 → 暗钢 矿车消失
    obsidianDarkSteelUpgrade 黑曜石 → 暗钢 矿车消失

    可用组合(源与目标都在 8 个变体内):铁→金、铁→钢、铜→钢、铜→铁、钢→金、金→钻石、钻石→水晶、钻石→黑曜石。

  2. 升级不走 Iron Chests 的升级黑名单:interactFirst 只判断 changer.getType().canUpgrade(type())(即 from == source),没有调用 IronChestType.allowUpgradeFrom,所以 Iron Chests 配置里的 blocklistUpgrades 对矿车不生效。

  3. 本模组不注册任何合成配方:代码中无 addRecipe / ShapedOreRecipe / CraftingManager 调用。矿车物品的配方由 Iron Chests 或 GTNH 配方脚本提供;本模组只贡献 8 个矿石字典名供配方引用。

  4. getCartItem() 与 killMinecart() 各自掉一个车体物品:killMinecart 显式掉落原版 Items.minecart,而 getCartItem() 返回本模组的矿车物品;EntityMinecart.attackEntityFrom 在实体造成伤害时会额外掉落 getCartItem()(该行为属原版 EntityMinecart,本仓库未包含反编译源码,属推断),因此用镐/火焰破坏矿车可能拿到两个车体物品。

物品列表

实体列表

游戏设定列表