输入方案

基本信息

属性 值
注册的 KeyBinding 数量 0
registerKeyBinding 调用 全仓库 0 处
键盘输入 仅 Keyboard.isKeyDown(KEY_LSHIFT) / (KEY_RSHIFT)
鼠标输入 Mouse.isButtonDown(0)(左键)、Mouse.isButtonDown(1)(右键)、Mouse.getDWheel()(滚轮)
输入轮询时机 TickEvent.RenderTickEvent 且 phase == START
默认按键(键码 0) 不适用——本条目不描述任何 KeyBinding,因此不存在「默认键码」这一属性

结论:本 mod 没有可配置按键

全仓库 17 个 Java 文件中不存在 KeyBinding 类型、不存在 KeyBinding 构造、 不存在 registerKeyBinding、不存在任何 keybinding 注册代码,也没有任何 key.categories / key.mousetweaks.* 语言键。因此:

  • 在「选项 → 按键控制」界面里看不到 Mouse Tweaks 的任何条目;
  • 没有「未绑定(键码 0)」的情况可谈——根本没有绑定对象;
  • 所有行为都只能通过 配置文件 里的 7 个选项开关与枚举来调整。

本条目存在的意义是记录这一事实,避免重复调查,并说明实际的输入来源。

键盘输入

全仓库唯一的键盘读取点,在 ClickHandler.handleSlotChangeAndButtons 中:

boolean shiftIsDown = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
项 值
键 左右 Shift
LWJGL 键码 KEY_LSHIFT(142)/ KEY_RSHIFT(54)
用途 供 左键拖拽(手持物品) 与 左键拖拽(空手 Shift) 判断是否执行 shift-click
是否可配置 否,硬编码
修饰键 无(不支持 Ctrl / Alt 组合)

该值每帧重算一次(跟随鼠标所在的栏位切换),不是「本次拖拽开始时是否按下」的快照—— 因此在拖拽途中按下或松开 Shift 会立即改变后续经过栏位的行为。

鼠标输入

输入 来源 用途
Mouse.isButtonDown(0) 左键 触发 LMBTweakWithItem / LMBTweakWithoutItem
Mouse.isButtonDown(1) 右键 触发 RMBTweak 的拖拽状态机
Mouse.getDWheel() 滚轮 触发 WheelTweak,负值 = 向下
Mouse.getX() / Mouse.getY() 光标位置 经 getRequiredMouseX/Y() 换算为 GUI 缩放坐标,用于定位鼠标下的栏位

光标坐标换算(getRequiredMouseX/Y)

getRequiredMouseX() = (Mouse.getX() * scaledWidth)  / mc.displayWidth
getRequiredMouseY() = scaledHeight - (Mouse.getY() * scaledHeight) / mc.displayHeight - 1

Y 方向额外做了翻转与 -1 修正,使 LWJGL 的「左上原点」坐标对齐 Minecraft GUI 的 「左下原点」坐标。原版 isMouseOverSlot 也是用这套坐标调用的 (该方法经 访问转换器 提升为 public)。

跨界面按键状态机(ClickHandler)

Mouse Tweaks 需要区分「这次拖拽是从本界面开始的」还是「按钮是从上一个界面带过来的」, 为此维护三个状态字段:

字段 作用
waitingForButtonRelease 界面切换后置 true;期间吞掉所有处理,直到左右键都松开才置 false(waitingForButtonRelease = Mouse.isButtonDown(0) || Mouse.isButtonDown(1))
oldSelectedSlot 上一帧鼠标所在的栏位;oldSelectedSlot == selectedSlot 时直接返回(无变化不处理)
firstSlot / firstSlotClicked RMB 拖拽起点及其结算状态(详见 右键拖拽替换)

updateScreen(GuiScreen) 在界面实例变化时一次性复位全部 7 个状态字段 (currentScreen / waitingForButtonRelease / oldSelectedSlot / firstSlot / oldStackOnMouse / firstSlotClicked / shouldClick)。

这样设计的后果:打开新界面时如果还按着鼠标键,第一次点击不会被当成拖拽起点, 必须先松手再点。屏幕关闭(currentScreen == null)时同样会 context.reset() + updateScreen(null) 清空状态。

物品兼容性判定

所有 tweak 共用 DeobfuscationLayer.areStacksCompatible:

(itemStack1 == null) || (itemStack2 == null) || (isItemEqual(a, b) && areItemStackTagsEqual(a, b))

即同类且 NBT 完全相同才算兼容——附魔、耐久、自定义名称、模组写入的自定义标签 都会让两堆被判定为不兼容。判定的两个比较项由源码注释以外的 ItemStack#isItemEqual 与 ItemStack#areItemStackTagsEqual 提供, 在处理前 Runtime 会先对鼠标物品和目标栏位物品各做一次 copy(), 避免处理过程中物品变化导致判定结果漂移。

相关条目