虚空方块
[!INFO] 注册真源:
WarpBlocks.initBlocks()(shukaro.warptheory.block.WarpBlocks) ⚠️ 本模组只有 1 个方块,且它不是多方块结构
基本信息
public static BlockVanish blockVanish;
public static void initBlocks() {
blockVanish = new BlockVanish();
GameRegistry.registerBlock(blockVanish, "blockVanish");
GameRegistry.registerTileEntity(TileEntityVanish.class, "tileEntityVanish");
}
| 属性 | 值 |
|---|---|
| 注册名 | blockVanish(驼峰,非下划线) |
| 类 | BlockVanish extends BlockContainer |
| 方块 ID | WarpTheory:blockVanish |
| TileEntity | TileEntityVanish,注册名 tileEntityVanish |
⚠️ 注册名用驼峰 blockVanish / tileEntityVanish,
与 7 个物品的 warptheory.xxx 点号风格不同 ——
全模组命名风格不统一,命令与代码引用时需逐字匹配。
⚠️ 不是多方块
本模组没有任何多方块结构。 全仓 grep 以下模式全部零命中:
| 检索模式 | 命中 |
|---|---|
ForgeMultipart |
0 |
multipart |
0 |
IMultiblock |
0 |
createStructure |
0 |
MultiBlock |
0 |
BlockVanish 的 setBlockBounds(0, 0, 0, 1, 1, 1) 是标准整方块边界,
不是多方块的组成部分。任何关于本模组多方块尺寸、控制器、
可否旋转拆除的描述都与源码不符。
方块属性
BlockVanish 构造器:
super(Material.rock);
this.setBlockUnbreakable();
this.setResistance(6000000.0F);
this.setStepSound(Block.soundTypeGlass);
this.setLightLevel(0.7f);
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
this.setTickRandomly(true);
| 属性 | 值 | 说明 |
|---|---|---|
| 材质 | Material.rock |
|
| 破坏性 | setBlockUnbreakable() |
无法被破坏( Survival 也一样) |
| 抗爆性 | 6000000.0F |
极端值,几乎免疫爆炸 |
| 脚步声 | Block.soundTypeGlass |
⚠️ 材质是 rock 但声音是玻璃 |
| 光照 | 0.7f |
自发光 |
| 随机刻 | setTickRandomly(true) |
触发随机刻更新 |
⚠️ 材质(rock)与脚步声(glass)故意不一致, 配合「不可破坏 + 自发光 + 玻璃声」营造漂浮的诡异方块观感。
机制:临时吞噬并复原方块
TileEntityVanish 的构造器立即快照被覆盖的方块:
public TileEntityVanish(World world, int x, int y, int z, long returnTime) {
this.pair = new NameMetaPair(world.getBlock(x, y, z), world.getBlockMetadata(x, y, z));
if (world.getTileEntity(x, y, z) != null) {
this.tag = new NBTTagCompound();
world.getTileEntity(x, y, z).writeToNBT(this.tag);
}
this.returnTime = returnTime;
}
快照三样东西:
- 方块本身 + metadata(
NameMetaPair,见util/NameMetaPair)—— 不存 ItemStack,靠NameGenerator的名字表反查; - 原 TileEntity 的 NBT(若存在);
- 复原时间戳
returnTime。
复原由 updateEntity() 驱动:
@Override public boolean canUpdate() { return true; }
@Override public void updateEntity() {
if (this.worldObj.getTotalWorldTime() >= this.returnTime) rebuildBlock();
}
即用 getTotalWorldTime()(世界总刻)与 returnTime 比较,
到点后调用 rebuildBlock() 还原。
⚠️ 依赖 setTickRandomly(true) —— 方块必须有随机刻更新,
否则 updateEntity() 不会被调用,方块永久不还原。
为什么用 NameMetaPair 而不是 ItemStack
util/ 下有 NameGenerator + NameMetaPair 两个类,
负责按名字查回方块。WarpTheory.preInit 会从
/assets/warptheory/names/normal.txt 释放一份到
config/warptheory/normal.txt 并构建 NameGenerator:
InputStream in = WarpTheory.class.getResourceAsStream("/assets/warptheory/names/normal.txt");
Files.copy(in, normalFile.getAbsoluteFile().toPath());
normalNames = new NameGenerator(normalFile.getAbsolutePath());
设计意图是:名字表可被玩家/服务器自定义
(normal.txt 放在 config 目录),从而让虚空方块能"记住"
自定义的方块名(用于 GTNH 整合包里的私有方块)。
⚠️ 若释放失败,整个 try 块被 catch (Exception e) { e.printStackTrace(); }
吞掉,normalNames 保持 null —— 之后任何依赖它的复原会 NPE,
但没有任何日志级别的错误输出(只有 printStackTrace)。
无合成配方
GameRegistry.registerBlock(blockVanish, "blockVanish") 之后
没有任何 addRecipe / 雕刻 / 研究条目指向它
(WarpRecipes 中无 blockVanish 字样)。
该方块由曲曲效果在世界中程序化生成, 玩家无法通过正常途径获得 —— 它是效果的产物而非内容。