Iron Chest 方块(IronChest:BlockIronChest)
基本信息
| 属性 | 值 |
|---|---|
| 注册名 | IronChest:BlockIronChest(GameRegistry.registerBlock(ironChestBlock, ItemIronChest.class, "BlockIronChest")) |
| 源码类 | cpw.mods.ironchest.BlockIronChest(extends BlockContainer) |
| 材质 | Material.iron |
| 硬度 | 3.0F(构造函数里唯一的数值设置:setHardness(3.0F)) |
| 爆炸抗性 | 无 setResistance() 调用;改由 getExplosionResistance() 覆写按 TileEntity 类型动态返回,见下 |
| 碰撞箱 | setBlockBounds(0.0625F, 0F, 0.0625F, 0.9375F, 0.875F, 0.9375F) |
| 创造栏 | CreativeTabs.tabDecorations |
| 渲染类型 | getRenderType() = 22(方块模型,物品形态另走 ItemIronChest) |
| 变体数 | 1 个注册方块 + 11 个 metadata 变体(不是 11 个方块) |
[!IMPORTANT] 整个 mod 只注册了 1 个方块。11 种箱子是同一个
BlockIronChest的 metadata 变体,metadata 值就是IronChestType枚举的ordinal()。
metadata 如何选择箱子类型
调用链只有一层,createTileEntity 直接把 metadata 丢给枚举工厂:
// BlockIronChest.java:84
public TileEntity createTileEntity(World world, int metadata) {
return IronChestType.makeEntity(metadata);
}
// IronChestType.java:146
public static TileEntityIronChest makeEntity(int metadata) {
int chesttype = validateMeta(metadata); // 越界 / size<=0 一律回落到 0
if (chesttype == metadata) {
return VALUES[chesttype].clazz.newInstance(); // 用枚举里登记的 TileEntity 类反射实例化
}
return null;
}
validateMeta(int i)(IronChestType.java:286):
if (i < VALUES.length && VALUES[i].size > 0) return i;
else return 0; // 非法 metadata 一律当作 IRON
因此合法 metadata 恰好是 ordinal() ∈ [0, 10];第 12 个常量 WOOD(ordinal() == 11)的 size == 0,被判为非法,getIcon/getSubBlocks 都跳过它,isValidForCreativeMode() 也返回 false。WOOD 是哨兵常量,不存在对应箱子——它只是给"原版木箱子"这个升级来源一个占位身份(见 Wood to Iron Chest Upgrade)。
metadata 分配表
| metadata | ordinal() 常量 |
显示名 | 容量 |
|---|---|---|---|
| 0 | IRON |
Iron Chest | 54 |
| 1 | GOLD |
Gold Chest | 81 |
| 2 | DIAMOND |
Diamond Chest | 108 |
| 3 | COPPER |
Copper Chest | 45 |
| 4 | STEEL |
Steel Chest | 72 |
| 5 | CRYSTAL |
Crystal Chest | 108 |
| 6 | OBSIDIAN |
Obsidian Chest | 108 |
| 7 | DIRTCHEST9000 |
Dirt Chest 9000 | 1 |
| 8 | NETHERITE |
Netherite Chest | 135 |
| 9 | DARKSTEEL |
Dark Steel Chest | 135 |
| 10 | SILVER |
Silver Chest | 72 |
| 11 | WOOD |
(无,不注册) | 0 |
数值属性(逐变体)
| 属性 | 值 | 来源 |
|---|---|---|
| 硬度 | 全部 11 个变体都是 3.0F | 构造函数只调一次 setHardness(3.0F),没有任何按 metadata 分化的硬度 |
| 爆炸抗性 | 抗爆型(OBSIDIAN、NETHERITE)返回 10000.0F;其余沿用 Material.iron 的原版值 |
getExplosionResistance() 覆写 |
| 亮度 | 无(全仓库没有 setLightLevel) |
— |
| 脚步/破坏音效 | 未覆写,走 Material.iron 默认 |
— |
爆炸抗性的判定是按 TileEntity 而非按 metadata:
// BlockIronChest.java:235
public float getExplosionResistance(Entity e, World world, int x, int y, int z,
double ex, double ey, double ez) {
TileEntity te = world.getTileEntity(x, y, z);
if (te instanceof TileEntityIronChest) {
if (((TileEntityIronChest) te).getType().isExplosionResistant()) {
return 10000f;
}
}
return super.getExplosionResistance(e, world, x, y, z, ex, ey, ez);
}
isExplosionResistant() = resistance >= 1,resistance 是 IronChestType 构造函数的最后一个参数(不是 metadata,也不是爆炸抗性数值本身,只是个 0/1 标志)。全枚举只有 OBSIDIAN(resistance = 1)和 NETHERITE(resistance = 1)为 1,其余全为 0。ironchest:blocks/obsidian_*.tooltip 里那句红色 §4Blast Proof 只有 Obsidian 箱子带。
交互
| 触发 | 行为 | 源码 |
|---|---|---|
| 右键方块 | 打开箱子 GUI:player.openGui(IronChest.instance, te.getType().ordinal(), world, x, y, z),GUI ID 即 ordinal() |
BlockIronChest.java:108 |
| 右键(上方被实心方块压住) | 直接 return true,不开 GUI(world.isSideSolid(x, y+1, z, DOWN)) |
BlockIronChest.java:116 |
| 右键(上方有坐下的猫) | return true 但不开 GUI(受配置 ocelotsBlockChests 控制) |
BlockIronChest.java:124 |
客户端(world.isRemote) |
return true,GUI 由 ClientProxy.getClientGuiElement 侧构建 |
BlockIronChest.java:120 |
| 破坏 | breakBlock 先 removeAdornments()(泥土箱会删掉说明书)再把全部内容物 dropContent(0, ...) 散落 |
BlockIronChest.java:171 |
| 创造模式物品栏 | getSubBlocks 遍历 VALUES,跳过 !isValidForCreativeMode() 与 !isEnabled() 的类型 |
BlockIronChest.java:222 |
| 掉落 | getDrops 恒为 1 个 new ItemStack(this, 1, metadata),再调 adornItemDrop(只有泥土箱会打 NBT 标记) |
BlockIronChest.java:99 |
| 红石比较器 | hasComparatorInputOverride() = true + Container.calcRedstoneFromInventory(te),读物品栏填充率 |
BlockIronChest.java:248 |
| 旋转(Forge wrench) | getValidRotations 只允许 UP/DOWN,rotateBlock 调 TileEntityIronChest.rotateAround(axis) |
BlockIronChest.java:272 |
摆放与朝向
onBlockPlacedBy(BlockIronChest.java:141)按玩家 yaw 取 facing = floor(yaw*4/360 + 0.5) & 3,再映射成箱子 metadata 风格的朝向值:
玩家朝向 facing |
写入 teic.setFacing() |
|---|---|
| 0 | 2 |
| 1 | 5 |
| 2 | 3 |
| 3 | 4 |
随后调 teic.wasPlaced(entityliving, itemStack)(泥土箱在此插入说明书),并 world.markBlockForUpdate。
朝向值本身存在 TileEntity 的 NBT 字段 facing 里(不是方块 metadata;方块 metadata 始终是箱子类型 ordinal())。
掉落物内容散落算法
dropContent(int newSize, IInventory chest, ...)(BlockIronChest.java:186)从 newSize 开始逐格取出:
- 每格物品按
random.nextInt(21) + 10(10~30 个)随机拆分成多个EntityItem抛出,抛物线初速0.05F随机 +0.2F向上。 - 物品的 NBT 会被
copy()后写回掉落物实体。 - 正常破坏时
newSize = 0,全部内容散落;箱子升级时由TileEntityIronChest.applyUpgradeItem传入newSize = 新箱子容量,即超出新容量的部分散落在地上,且 Y 坐标+1(避免卡在原箱子方块内)。
渲染
| 事项 | 值 |
|---|---|
| 方块图标 | getIcon(int side, int meta) → IronChestType.VALUES[meta].getIcon(side);makeIcons 为每个类型注册 3 张 ironchest:<name>_{top,front,side},按 sideMapping = {0,0,2,1,2,2,2} 映射 6 个方块朝向 |
STEEL 特例 |
图标注册时 name().equalsIgnoreCase("steel") 被特判成 ironchest:silver_%s(钢箱子复用银箱子贴图) |
| TileEntity 渲染器 | TileEntityIronChestRenderer,模型贴图取 textures/model/<modelTexture>(即 getModelTexture());ModelChest 盖子角度来自 prevLidAngle/lidAngle |
| 物品栏渲染 | IronChestRenderHelper extends TileEntityRendererChestHelper,为每个 ordinal() 预建一个空 TE,让物品形态用同一套渲染器画 |
| 透明内容渲染 | 仅 CRYSTAL(isTransparent())在 TRANSPARENT_RENDER_INSIDE 开启且距离 < TRANSPARENT_RENDER_DISTANCE 时,把 topStacks 里 8 个最多堆叠的物品悬浮旋转显示(关光照,RenderItem 动画关闭)。若 topStacks[1] == null 则放大到 0.85 并整体下移 |
猫与箱子
mod 通过 OcelotsSitOnChestsHandler(LivingUpdateEvent,仅在 OCELOTS_SITONCHESTS 开启时注册)把原版 EntityAIOcelotSit(priority == 6)替换为 IronChestAIOcelotSit(ocelot, 1.33D),并覆写 func_151486_a(isSittableBlock,由 META-INF/IronChest_at.cfg 映射)使任何 IronChest:BlockIronChest 元数据都可坐,且只在 getNumUsingPlayers() == 0(没人开着 GUI)时允许。
相关条目
- ItemIronChest - 箱子在物品栏中的形态,
getMetadata()走同一套validateMeta - Iron Chest · Copper Chest · Steel Chest · Silver Chest · Gold Chest · Diamond Chest · Crystal Chest · Obsidian Chest · Netherite Chest · Dark Steel Chest · Dirt Chest 9000 - 11 个 metadata 变体
- 箱子类型开关 - 四个
enable*Chests配置项决定哪些变体存在 - 升级黑名单 -
blocklistUpgrades可禁止任意一组升级器与配方