星门(Stargate)
[!IMPORTANT] 本文所有坐标偏移、方块数量与 metadata 要求均逐行对照
BlockStargateController.runStructureCheck()(源码 81–97 行)与formGate()(102–122 行)得出,偏移方向经StructureUtil.rotate()旋转。
星门是 StargateNH 唯一的玩家自建多方块结构。它是一个 5×5 的拱门:中央竖立一个星门控制器方块作为核心,周围 15 个方块按固定的拱形排布。结构满足后全部方块会被自动替换为不可见的"已成形"方块,由 TESR 渲染出星门模型。玩家再用一个拨号装置为星门设定 7 位地址,即可与其他星门互联传送。
基本信息
| 属性 | 值 |
|---|---|
| 结构名 | Stargate(星门) |
| 核心方块 | 星门控制器方块(stargatenh:<group>_stargate_controller) |
| 必需方块 | 星门雪佛龙方块(meta 1)×7、星门环方块(meta 0)×8 |
| 可选方块 | 无(结构尺寸固定,不可放大或缩小) |
| 结构方块总数 | 16(1 控制器 + 7 雪佛龙 + 8 环) |
| 外形尺寸 | 宽 5 × 高 5 × 厚 1(沿朝向方向厚度为 1) |
| 材质 | 全部为 Material.iron |
| TileEntity | TileStargateController,注册 ID TileEntityStargateControllerNH |
| 能量消耗 | 无。本 mod 不含任何能量系统(详见下节) |
能量与成本模型
本 mod 没有能量、功率或消耗概念。 对全部 Java 源码检索 energy / power / cost / ForgeEnergy / IEnergy / EU 均无任何匹配;TileStargateController 未实现任何 Forge 能量接口,也没有 setHardness / setResistance / setLightLevel 调用。
因此激活一座星门的真实成本只有三项,全部是逻辑性的:
| 成本项 | 说明 | 依据 |
|---|---|---|
| 16 个方块 | 组装结构所需建材 | formGate() |
| 1 个地址 | 该星门被永久占用一个 7 位地址 | TileStargateController.setAddress() |
| 一次性的"被拨"资格 | 一座星门一生只能被别的星门拨通一次 | getDialed() 把 dialed 置 true 后全类再无复位点 |
方块硬度与爆炸抗性本 mod 未设置,继承原版 Block(Material) 构造函数的默认值(硬度 2.0、爆炸抗性 10.0),这是原版行为而非本 mod 的设定。
结构要求
结构是固定尺寸的:没有最小/最大规模之分,偏移表写死 15 个位置。坐标以控制器方块为原点 (0, 0),offsetX 为水平方向(沿门平面),offsetY 为高度方向(rotate() 永不改变 dy,Y 轴恒定向上)。
完整偏移表
下表左侧是逻辑偏移,实际世界坐标由 StructureUtil.rotate(offsetX, offsetY, facing) 决定。
| offsetX | offsetY | 所需方块 | 所需 meta | 角色 |
|---|---|---|---|---|
| 0 | 0 | 控制器方块(自身) | facing(2–5) | 结构核心 / 挂 TileEntity / 拨号发起端 |
| −2 | 0 | 星门方块 | 1(雪佛龙) | 拱脚外侧 |
| −1 | 0 | 星门方块 | 0(环) | 拱脚内侧 |
| +1 | 0 | 星门方块 | 0(环) | 拱脚内侧 |
| +2 | 0 | 星门方块 | 1(雪佛龙) | 拱脚外侧 |
| −2 | 1 | 星门方块 | 0(环) | 左立柱 |
| +2 | 1 | 星门方块 | 0(环) | 右立柱 |
| −2 | 2 | 星门方块 | 1(雪佛龙) | 左立柱雪佛龙 |
| +2 | 2 | 星门方块 | 1(雪佛龙) | 右立柱雪佛龙 |
| −2 | 3 | 星门方块 | 0(环) | 左立柱 |
| +2 | 3 | 星门方块 | 0(环) | 右立柱 |
| −2 | 4 | 星门方块 | 1(雪佛龙) | 拱顶外侧 |
| −1 | 4 | 星门方块 | 0(环) | 拱顶内侧 |
| 0 | 4 | 星门方块 | 1(雪佛龙) | 拱顶正中央也是雪佛龙 |
| +1 | 4 | 星门方块 | 0(环) | 拱顶内侧 |
| +2 | 4 | 星门方块 | 1(雪佛龙) | 拱顶外侧 |
按 meta 汇总:雪佛龙(meta 1)共 7 个,环(meta 0)共 8 个,加控制器 1 个 = 16。
[!TIP] 7 个雪佛龙不是巧合。 雪佛龙数量(7)与地址位数(
StargateAddress的 7 个 sigil)、TileStargateController.CHEVRON_ANGLES数组长度(7)三者严格相等,拨号动画就是让第 i 个雪佛龙依次对准第 i 个符号。
布局示意(facing = 2,正面视角)
y=4 [雪佛龙][环] [雪佛龙] [环][雪佛龙]
y=3 [ 环 ] [ 环 ]
y=2 [ 雪佛龙 ] [ 雪佛龙 ]
y=1 [ 环 ] [ 环 ]
y=0 [雪佛龙][环] [控制器] [环][雪佛龙]
x=-2 x=-1 x=0 x=+1 x=+2
朝向
控制器方块的 metadata 就是朝向,由 onBlockPlacedBy() 依玩家视线写入,只可能是 2 / 3 / 4 / 5(永远不会出现 0 或 1):
| 玩家朝向 | 写入的 meta | 含义 |
|---|---|---|
| 0 | 2 | 北(−Z) |
| 1 | 5 | 东(+X) |
| 2 | 3 | 南(+Z) |
| 3 | 4 | 西(−X) |
StructureUtil.rotate() 的旋转对应关系:
| facing | 方向 | 逻辑 offsetX 映射到 |
|---|---|---|
| 2 | 北(−Z) | 世界 +X |
| 5 | 东(+X) | 世界 −Z |
| 3 | 南(+Z) | 世界 −X |
| 4 | 西(−X) | 世界 +Z |
| 其他 | — | 回退为 (dx, dy, 0) |
即结构只做水平面内的四面旋转,offsetY 永远映射到 dy。
6 种材质组(§2.14 变体穷举)
ModBlocks.StargateBlocks 枚举定义 6 个材质组,每组各自实例化出完整的 3 个方块(雪佛龙/环共用的方块、控制器方块、已成形方块),共 18 个注册方块,加上 dialing_device 共 19 个方块。
| 枚举值 | id |
isLegacy |
显示名后缀(affix.*) |
背景故事 tooltip | 对比 |
|---|---|---|---|---|---|
Default |
default |
false | 无 | 无 | 唯一无后缀、无 tooltip 的组,名称直接是 tile.default_stargate_block.<meta>.name |
SplitOrigin |
split_origin |
true | of Split Origin | The first conquering (2.1.0.0) | 5 个 legacy 组中 tooltip 版本号最低 |
PolychromeContest |
polychrome_contest |
true | of Polychrome Contest | Race for the infinite (2.1.2.3qf) | 唯一版本号含字母后缀 qf |
DimensionalDuplicity |
dimensional_duplicity |
true | of Dimensional Duplicity | Dawn of the new age (2.2.3) | — |
HarmonicBreakthrough |
harmonic_breakthrough |
true | of Harmonic Breakthrough | Universes torn apart (2.3.0) | — |
HeavenlyFire |
heavenly_fire |
true | of Heavenly Fire | Stars forged anew (2.7.0) | tooltip 版本号最高(2.7.0) |
变体之间的核心差异:仅限外观与命名。 isLegacy 字段在全 mod 中只被三个 ItemBlock 内部类读取,用于决定显示名是否拼接 affix 后缀、是否附加 tooltip;它不影响任何玩法逻辑。6 种材质组的结构要求、地址系统、传送行为、碰撞判定完全一致。实际使用场景是按喜好挑选贴图主题。
材质组不可混用
结构检测用的是 rBlock == block 的方块实例相等比较(StructureUtil.checkBlockAndMeta()),而每种材质组各自 new 出独立的 BlockStargate / BlockStargateController / BlockFormedGate 实例。因此一座星门必须完全由同一材质组的方块组成,混用两种材质组无法成形。
形成机制
全自动检测,放下最后一块方块的瞬间即成形。 没有"手持核方块右键装配"这类手动步骤,也没有结构样板物品。
两条触发路径:
- 放下控制器方块 —
BlockStargateController.onPostBlockPlaced()直接调用runStructureCheck()。 - 放下任意一个星门方块(环或雪佛龙) —
BlockStargate.onPostBlockPlaced()调用findController()做一次泛洪搜索:只沿着同种方块(neighbor == this)向上下左右 6 个方向扩散,遇到BlockStargateController就对它执行runStructureCheck()。搜索有硬上限checked.size() > 20即中止(源码注释 “Hard limit so nothing horrible happens”),意味着泛洪最多检查约 20 个方块;同一 group 内彼此直连的 15 个成员不会触发该上限。
formGate() 随即把 15 个成员方块和控制器本身全部 setBlock(..., flag 3) 为对应的 formedGateBlock,控制器位置写入 meta = facing。
成形后的状态(BlockFormedGate)
成形后结构里的每一个位置都变成 stargatenh:<group>_stargate_formed,metadata 完整保留成形前的身份:
| 成形后 meta | 含义 | 是否有 TileEntity | 破坏时掉落 |
|---|---|---|---|
| 0 | 原本是环方块 | 否(hasTileEntity(meta) = meta > 1) |
星门环方块 ×1(damage 0) |
| 1 | 原本是雪佛龙方块 | 否 | 星门雪佛龙方块 ×1(damage 1) |
| 2 / 3 / 4 / 5 | 原本是控制器,meta 即朝向 | 是,TileStargateController |
控制器方块 ×1(damage 0) |
因此拆掉一座成形星门会精确掉回组装它的那 16 个方块,不增不减;getDrops() 完全忽略 fortune 参数,时运对掉落无影响。
渲染上该方块是完全隐形的:getRenderType() 返回 −1、renderAsNormalBlock() 返回 false、isOpaqueCube() 返回 false,实际外观由 RenderStargateTESR 绘制的 models/stargate.obj 提供。选取框按朝向为 5×5×1(getSelectedBoundingBoxFromPool())。
解体机制
拆掉任何一个方块,整座星门立刻解体。 同样有两条路径:
- 拆控制器(meta > 1)—
BlockFormedGate.breakBlock()直接调用deform()。 - 拆其他位置(meta 0/1)— 同样走
findController()泛洪(上限 20)找到控制器后执行runDeformCheck(),只要 15 项检查中任意一项不满足就整体deform()。
deform() 逐个调用 StructureUtil.deformRel(),把每个 BlockFormedGate 换回:meta > 1 → 控制器方块,否则 → 星门方块,metadata 原样保留(所以拆解后的星门方块朝向和类型信息不会丢失,可以直接重新摆放触发成形)。
功能
- 玩家或生物站在门前,碰撞到门内侧的触发区域即被传送到目标星门(
BlockFormedGate.addCollisionBoxesToList()→TileStargateController.doTeleport())。 - 传送不改变维度——只把实体坐标设到目标星门控制器旁
y + 1.5,仍在同一个World内。 - 触发区域按朝向为
(x−1, y+1, z)–(x+2, y+4, z+1)(facing 0 或 2)或(x, y+1, z−1)–(x+1, y+4, z+2)(其余朝向)。只有EntityLivingBase会被传送,掉落物、箭矢等实体直接穿过。 - 拨出目标地址后 7 个雪佛龙依次锁定,锁定过程见 拨号序列。
数值
| 数值 | 值 | 来源 |
|---|---|---|
| 结构方块总数 | 16 | runStructureCheck() |
| 雪佛龙数 / 环方块数 | 7 / 8 | runStructureCheck() |
| 泛洪搜索硬上限 | 20 | findController() |
| 雪佛龙间隔角 | 51.43°(= 360°/7) | CHEVRON_ANGLES 数组 |
| 符号角步进 | 22.5°(= 360°/16) | SYMBOL_STEP |
| 每符号最短锁定时长 | 20 tick(1 秒) | `animTotalTicks = Math.max(20, |
| 每符号固定停顿 | 25 tick | lockTicksRemaining = 25 |
| 最快完成一次拨号 | 315 tick ≈ 15.75 秒 | 7 × (20 + 25) |
限制
- 尺寸固定,无法缩放或扩展,多一格少一格都不会成形。
- 材质组不可混用(见上节)。
- 地址只能设定一次:
setAddress()首行即if (hasAddress) return;,且 GUI 在已有地址时只显示拨号界面。 - 每座星门只能被拨通一次:
getDialed()把dialed置为true后整个类中再无复位,第二次拨入会被dialOut()第一行拒绝。 - 地址冲突时静默失败:
setAddress()先查注册表,若地址已被占用则不注册也不置hasAddress,玩家只能看到地址一直没锁定。GUI 的"地址可用/已被使用"提示(isUnique同步值)是唯一的预检手段。 - 注册表只存在于主世界:
StargateRegistry.RegisterEvent仅在world.provider.dimensionId == 0时加载,见 地址与星门注册表。 - mod 重载 / 区块卸载会丢失"被拨"状态:
dialed字段不写入 NBT,重新加载时回到false。 dialing目标位置不持久化,同样只存在于内存中。
参与方块
- 星门环方块 - 结构中 meta 0 的成员,共 8 个;雪佛龙之间的填充件
- 星门雪佛龙方块 - 结构中 meta 1 的成员,共 7 个;与 7 位地址一一对应
- 星门控制器方块 - 结构核心,朝向来源,拨号发起端
- 已成形星门方块 - 成形后的替代方块,承载碰撞传送与 TESR
- 拨号装置 - 设定地址与发起拨号的唯一交互方块