控制面板交互动作

[!INFO] 源码: src/main/scala/gcewing/projectblue/ControlPanelPart.java

控制面板部件的每一次点击都走 activateCell(int i, EntityPlayer, ItemStack)。手持物决定动作;空手(或不匹配的手持物)则触发控件本身。

动作分发表

activateCell 按顺序判定,命中即 return:

顺序 条件 动作 消耗
1 手持 SprayCanItem 设置该格通道色;颜色 16 时改为「按格号自动」 喷漆罐转 durability
2 手持 Items.dye 设置该格通道色 = 15 - meta 扣 1 个(非创造)
3 手持 Project Red ItemScrewdriver 且潜行 切换 flush / surface 安装方式 不消耗
4 手持 ItemScrewdriver(不潜行)且该格有控件 移除控件并掉落 不消耗
5 手持 ItemScrewdriver(不潜行)且该格为空 旋转面板(rot = (rot+1)&0x3) 不消耗
6 手持木炭(Items.coal meta 1) 打开文字编辑 GUI 不消耗
7 该格为空 + 手持 miniatureLever 放入 LEVER 扣 1 个
8 该格为空 + 手持 miniatureButton 放入 BUTTON 扣 1 个
9 该格为空 + 手持 miniatureLamp 放入 LAMP 扣 1 个
10 该格为空 + 手持 miniatureCover 且其 NBT mat == 面板基材名 放入 BLANK 扣 1 个
11 以上都不满足 activateControl(i) — 拨动拉杆 / 按下按钮 不消耗

LEVER / BUTTON 放入时把手持物的 meta 存为该格的通道色(setControlMeta(i, meta))。

控件行为

控件 行为 细节
LEVER 状态异或 1(开关) 播放 random.click 音,pitch 0.6(开)/ 0.5(关)
BUTTON 置 1 并计时 20 tick(1 秒)后自动回 0 buttonDownTime = 20;scheduleTick 自我重排
LAMP 无输出,仅作为显示 状态由外部输入决定,见下
BLANK 无功能,纯装饰/填充 拆下时掉落带 mat NBT 的 miniatureCover

LAMP 格子在 getInputs() 中被外部信号驱动:setControlState(i, sig[ch] != 0 ? 1 : 0),其中 ch = getChannelColor(i)。

特殊交互

  • 潜行 + 螺丝刀点击(click() 而非 activate())→ 破坏并掉落整个面板(harvest)。与普通破坏不同,这条路径直接调 tile().dropItems(getDrops()) + remPart,绕过工具。
  • 同一 tick 只处理一次:activate 用静态 lastActivateTime 去重(源码注释说明手持物非空时会被调用两次)。
  • 改通道色后会 FaceUtils.notifyAllNeighbors(this, side) 并播放 step.snow 音效。

坐标 → 格子映射

activate 用命中点反算格子:

i = floor((p.z + 0.5) * gridSize)   // 行(局部 Z 轴)
j = floor((-p.x + 0.5) * gridSize)  // 列(局部 X 轴取反)
cell = i * gridSize + j

p 是命中点经 localToGlobalTransformation 变换到部件局部坐标后的结果。

信号方向

面板是 IBundledEmitter:getBundledSignal(side) 遍历活跃格子,把状态 > 0 的 LEVER/BUTTON 按其通道色置 signal[channel] = 255。

相关