按键映射
按键映射(也称按键绑定)将某项操作与鼠标点击、按键等输入关联起来。只要客户端可以接收输入,就能检查映射定义的操作。此外,每个映射都可通过控制设置菜单重新绑定到任意输入。
注册 KeyMapping
仅在物理客户端监听 Mod 事件总线上的 RegisterKeyMappingsEvent,并调用 #register:
// In some physical client only class
// Key mapping is lazily initialized so it doesn't exist until it is registered
public static final Lazy<KeyMapping> EXAMPLE_MAPPING = Lazy.of(() -> /*...*/);
@SubscribeEvent // on the mod event bus only on the physical client
public static void registerBindings(RegisterKeyMappingsEvent event) {
event.register(EXAMPLE_MAPPING.get());
}
创建 KeyMapping
通过构造函数创建 KeyMapping,参数包含定义映射名称的翻译键、默认输入,以及定义其在控制设置菜单中所属类别的翻译键。
建议 提供原版没有使用的类别翻译键,即可添加到自定义类别。自定义类别翻译键应包含 Mod ID,例如
key.categories.examplemod.examplecategory。
默认输入
每个按键映射都关联一个默认输入,由 InputConstants.Key 提供。输入由表示设备的 InputConstants.Type 和表示该设备上输入标识符的整数构成。
原版提供三种类型:KEYSYM 使用 GLFW 按键标记表示键盘输入;SCANCODE 使用平台相关扫描码表示键盘输入;MOUSE 表示鼠标。
提示 键盘强烈建议使用
KEYSYM而非SCANCODE,因为 GLFW 按键标记不依赖特定系统。更多信息见 GLFW 文档。
整数的含义取决于输入类型。所有输入代码定义在 GLFW 中,KEYSYM 标记以 GLFW_KEY_* 开头,MOUSE 代码以 GLFW_MOUSE_* 开头。
new KeyMapping(
"key.examplemod.example1", // Will be localized using this translation key
InputConstants.Type.KEYSYM, // Default mapping is on the keyboard
GLFW.GLFW_KEY_P, // Default key is P
"key.categories.misc" // Mapping will be in the misc category
)
提示 如果映射不应有默认绑定,应将输入设为
InputConstants#UNKNOWN。原版构造函数要求通过InputConstants$Key#getValue提取输入代码,NeoForge 构造函数则可直接接受输入字段。
IKeyConflictContext
并非所有映射都用于所有场景。有些只用于 GUI,另一些只用于游戏内。为防止相同按键在不同场景使用时产生冲突,可以为映射指定 IKeyConflictContext。
冲突上下文包含两个方法:#isActive 判断当前游戏状态是否可使用该映射;#conflicts 判断映射是否与相同或不同冲突上下文中的按键冲突。
NeoForge 通过 KeyConflictContext 定义三种基本上下文:默认的 UNIVERSAL 可在所有场景使用;GUI 仅在打开 Screen 时使用;IN_GAME 仅在没有打开 Screen 时使用。也可实现 IKeyConflictContext 创建自定义上下文。
new KeyMapping(
"key.examplemod.example2",
KeyConflictContext.GUI, // Mapping can only be used when a screen is open
InputConstants.Type.MOUSE, // Default mapping is on the mouse
GLFW.GLFW_MOUSE_BUTTON_LEFT, // Default mouse input is the left mouse button
"key.categories.examplemod.examplecategory" // Mapping will be in the new example category
)
KeyModifier
开发者可能希望按住修饰键时,同一按键具有不同行为,例如 G 与 Ctrl+G。NeoForge 为构造函数增加了 KeyModifier 参数,可添加 Ctrl(KeyModifier#CONTROL)、Shift(KeyModifier#SHIFT)或 Alt(KeyModifier#ALT)修饰。默认值 KeyModifier#NONE 不添加修饰键。
在控制设置菜单中同时按住修饰键和目标输入,也可以添加修饰键。
new KeyMapping(
"key.examplemod.example3",
KeyConflictContext.UNIVERSAL,
KeyModifier.SHIFT, // Default mapping requires shift to be held down
InputConstants.Type.KEYSYM, // Default mapping is on the keyboard
GLFW.GLFW_KEY_G, // Default key is G
"key.categories.misc"
)
检查 KeyMapping
可以检查映射是否被触发,并在适当时机用条件分支执行关联逻辑。
游戏内
在游戏内,应监听事件总线上的 ClientTickEvent.Post,并在 while 循环中调用 KeyMapping#consumeClick。它仅会按尚未处理的输入次数返回 true,不会无限循环阻塞游戏。
@SubscribeEvent // on the game event bus only on the physical client
public static void onClientTick(ClientTickEvent.Post event) {
while (EXAMPLE_MAPPING.get().consumeClick()) {
// Execute logic to perform on click here
}
}
注意 不要用
InputEvent代替ClientTickEvent.Post。输入事件仅分别提供键盘和鼠标事件,不能处理额外输入类型。
GUI 内
在 GUI 中,可以通过 IKeyMappingExtension#isActiveAndMatches 在某个 GuiEventListener 方法内检查映射,最常用的是 #keyPressed 与 #mouseClicked。
#keyPressed 接受 GLFW 按键标记、平台相关扫描码,以及按下的修饰键位字段。使用 InputConstants#getKey 创建输入后即可检查,映射方法本身已负责检查修饰键。
// In some Screen subclass
@Override
public boolean keyPressed(int key, int scancode, int mods) {
if (EXAMPLE_MAPPING.get().isActiveAndMatches(InputConstants.getKey(key, scancode))) {
// Execute logic to perform on key press here
return true;
}
return super.keyPressed(x, y, button);
}
提示 如果需要检查键盘按键但无法修改该界面,可以改为监听事件总线上
ScreenEvent.KeyPressed的 Pre 或 Post 事件。
#mouseClicked 接受鼠标 x、y 坐标和点击的按钮。通过 InputConstants.Type#getOrCreate,使用 MOUSE 类型创建输入即可检查映射。
// In some Screen subclass
@Override
public boolean mouseClicked(double x, double y, int button) {
if (EXAMPLE_MAPPING.get().isActiveAndMatches(InputConstants.TYPE.MOUSE.getOrCreate(button))) {
// Execute logic to perform on mouse click here
return true;
}
return super.mouseClicked(x, y, button);
}
提示 如果需要检查鼠标按键但无法修改该界面,可以改为监听事件总线上
ScreenEvent.MouseButtonPressed的 Pre 或 Post 事件。
来源: NeoForged/Documentation(1.21.1)。中文翻译依据提交
4a680cdd4d15。