Skip to content

Keybind Helpers

Deprecated

This page documents KeybindHelper which is deprecated and will be removed in Amber 10.0.

Use com.iamkaf.amber.api.registry.v1.KeybindHelper instead. See Functions API for the new approach.

Amber provides a utility class for managing keybinds across all mod loaders. The KeybindHelper simplifies the registration of custom keybindings and handles platform differences automatically.

Overview

The keybind helper includes:

  • Cross-platform registration: Works consistently on Fabric, Forge, and NeoForge
  • Client-side only: Automatically handles environment checks
  • Forge compatibility: Manages Forge-specific event timing requirements
  • Centralized management: Keeps track of all registered keybinds

Basic Usage

Registering a Keybind

Use KeybindHelper.register() to register a custom keybind:

java
import com.iamkaf.amber.api.keymapping.KeybindHelper;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.KeyMapping;

public class MyModKeybinds {
    // Create keybind instances using KeyMapping constructors
    public static final KeyMapping ABILITY_KEY = new KeyMapping(
        "key.mymod.ability",           // Translation key
        InputConstants.Type.KEYSYM,    // Input type
        InputConstants.KEY_R,          // Key code
        KeyMapping.Category.MISC       // Category
    );
    
    public static final KeyMapping MENU_KEY = new KeyMapping(
        "key.mymod.menu",
        InputConstants.Type.KEYSYM,
        InputConstants.KEY_M,
        KeyMapping.Category.INVENTORY
    );
    
    // Register keybinds
    public static void registerKeybinds() {
        KeybindHelper.register(ABILITY_KEY);
        KeybindHelper.register(MENU_KEY);
    }
    
    // Check if keybind is pressed
    public static void onClientTick() {
        Minecraft mc = Minecraft.getInstance();
        
        // Check if ability key is pressed
        if (ABILITY_KEY.consumeClick()) {
            activateAbility();
        }
        
        // Check if menu key is pressed
        if (MENU_KEY.consumeClick()) {
            toggleMenu();
        }
    }
    
    private static void activateAbility() {
        // Ability logic
    }
    
    private static void toggleMenu() {
        // Menu toggle logic
    }
}

Client-Side Registration

Register keybinds in your client-side initialization:

java
// For Fabric
@Environment(EnvType.CLIENT)
public class MyModClient implements ClientModInitializer {
    @Override
    public void onInitializeClient() {
        MyModKeybinds.registerKeybinds();
    }
}

// For Forge/NeoForge
@Mod(MyMod.MOD_ID)
public class MyMod {
    public MyMod() {
        // Register on client bus
        FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup);
    }
    
    @OnlyIn(Dist.CLIENT)
    private void clientSetup(final FMLClientSetupEvent event) {
        MyModKeybinds.registerKeybinds();
    }
}

Advanced Usage

Keybind with Modifier Keys

KeyMapping doesn't directly support modifier keys in its constructor, but you can check for them in your keybind handler:

java
public class AdvancedKeybinds {
    public static final KeyMapping DASH_KEY = new KeyMapping(
        "key.mymod.dash",
        InputConstants.Type.KEYSYM,
        InputConstants.KEY_R,
        KeyMapping.Category.MOVEMENT
    );
    
    public static final KeyMapping SPECTATOR_KEY = new KeyMapping(
        "key.mymod.spectator",
        InputConstants.Type.KEYSYM,
        InputConstants.KEY_G,
        KeyMapping.Category.MISC
    );
    
    public static void registerKeybinds() {
        KeybindHelper.register(DASH_KEY);
        KeybindHelper.register(SPECTATOR_KEY);
    }
    
    public static void onClientTick() {
        Minecraft mc = Minecraft.getInstance();
        
        // Check for modifier keys when handling keybind
        if (DASH_KEY.consumeClick()) {
            // Check if Shift is held down
            if (mc.options.keyShift.isDown()) {
                performEnhancedDash();
            } else {
                performDash();
            }
        }
    }
    
    private static void performDash() {
        // Regular dash
    }
    
    private static void performEnhancedDash() {
        // Enhanced dash with Shift
    }
}

Context-Aware Keybinds

Create keybinds that behave differently based on context:

java
public class ContextKeybinds {
    public static final KeyMapping ACTION_KEY = new KeyMapping(
        "key.mymod.action",
        InputConstants.Type.KEYSYM,
        InputConstants.KEY_F,
        KeyMapping.Category.GAMEPLAY
    );
    
    public static void registerKeybinds() {
        KeybindHelper.register(ACTION_KEY);
    }
    
    public static void onClientTick() {
        Minecraft mc = Minecraft.getInstance();
        
        if (ACTION_KEY.consumeClick()) {
            if (mc.player == null) return;
            
            // Different behavior based on context
            if (mc.player.isSpectator()) {
                toggleSpectatorMode();
            } else if (mc.player.isCreative()) {
                openCreativeMenu();
            } else {
                performAbility();
            }
        }
    }
    
    private static void toggleSpectatorMode() {
        // Spectator mode logic
    }
    
    private static void openCreativeMenu() {
        // Creative menu logic
    }
    
    private static void performAbility() {
        // Regular ability logic
    }
}

Keybind with Toggle State

While KeyMapping doesn't have built-in toggle support, you can implement toggle behavior:

java
public class ToggleKeybinds {
    public static final KeyMapping TOGGLE_HUD_KEY = new KeyMapping(
        "key.mymod.toggle_hud",
        InputConstants.Type.KEYSYM,
        InputConstants.KEY_H,
        KeyMapping.Category.MISC
    );
    
    private static boolean hudVisible = true;
    
    public static void registerKeybinds() {
        KeybindHelper.register(TOGGLE_HUD_KEY);
    }
    
    public static void onClientTick() {
        if (TOGGLE_HUD_KEY.consumeClick()) {
            hudVisible = !hudVisible;
            
            // Show feedback
            Minecraft.getInstance().player.sendSystemMessage(
                Component.literal("HUD " + (hudVisible ? "enabled" : "disabled"))
            );
        }
    }
    
    public static boolean isHudVisible() {
        return hudVisible;
    }
}

KeyMapping Categories

KeyMapping includes several predefined categories for organizing keybinds:

java
// Available categories
KeyMapping.Category.MOVEMENT     // Movement controls
KeyMapping.Category.MISC          // Miscellaneous
KeyMapping.Category.MULTIPLAYER   // Multiplayer functions
KeyMapping.Category.GAMEPLAY      // General gameplay
KeyMapping.Category.INVENTORY     // Inventory management
KeyMapping.Category.CREATIVE      // Creative mode
KeyMapping.Category.SPECTATOR     // Spectator mode

Best Practices

1. Translation Keys

Always use translation keys for keybind names:

java
// Good - Uses translation key
public static final KeyMapping ABILITY_KEY = new KeyMapping(
    "key.mymod.ability",           // Translation key
    InputConstants.Type.KEYSYM,    // Input type
    InputConstants.KEY_R,          // Key code
    KeyMapping.Category.MISC       // Category
);

// Bad - Hardcoded strings (not supported by KeyMapping)

2. Unique Key Codes

Choose key codes that don't conflict with vanilla controls:

java
// Good - Less commonly used keys
InputConstants.KEY_R              // Reasonably common
InputConstants.KEY_G              // Less common
InputConstants.KEY_H              // Less common

// Avoid - Commonly used keys
InputConstants.KEY_W              // Movement
InputConstants.KEY_A              // Movement
InputConstants.KEY_S              // Movement
InputConstants.KEY_D              // Movement
InputConstants.KEY_SPACE          // Jump

3. Environment Checks

The KeybindHelper automatically handles client-side checks, but you should still ensure your keybind logic is client-side only:

java
// Good - Client-side only
@OnlyIn(Dist.CLIENT)
public class MyModKeybinds {
    public static void registerKeybinds() {
        KeybindHelper.register(ABILITY_KEY);
    }
}

// Unnecessary - KeybindHelper already checks environment
public class MyModKeybinds {
    public static void registerKeybinds() {
        if (Platform.isClient()) {  // Not needed
            KeybindHelper.register(ABILITY_KEY);
        }
    }
}

4. Keybind Storage

Store keybind references for easy access:

java
// Good - Centralized storage
public class MyModKeybinds {
    public static final KeyMapping ABILITY_KEY = createKeybind("ability", InputConstants.KEY_R);
    public static final KeyMapping MENU_KEY = createKeybind("menu", InputConstants.KEY_M);
    
    private static KeyMapping createKeybind(String name, int key) {
        return new KeyMapping(
            "key.mymod." + name,
            InputConstants.Type.KEYSYM,
            key,
            KeyMapping.Category.MISC
        );
    }
    
    public static void registerKeybinds() {
        KeybindHelper.register(ABILITY_KEY);
        KeybindHelper.register(MENU_KEY);
    }
}

KeyMapping API

The KeyMapping class provides several useful methods:

java
KeyMapping keybind = new KeyMapping("key.test", InputConstants.Type.KEYSYM, InputConstants.KEY_T, KeyMapping.Category.MISC);

// Check if key is currently pressed
boolean isDown = keybind.isDown();

// Consume a click event (returns true if there was a click to consume)
if (keybind.consumeClick()) {
    // Handle keybind press
}

// Get the keybind name
String name = keybind.getName();

// Get the translated key message
Component keyName = keybind.getTranslatedKeyMessage();

// Check if keybind is unbound
boolean isUnbound = keybind.isUnbound();

// Check if keybind uses default key
boolean isDefault = keybind.isDefault();

// Save keybind configuration
String saveString = keybind.saveString();

Migration from Platform-Specific Keybinds

From Fabric KeyBindingRegistry

java
// Old Fabric way
KeyBindingRegistry.registerKeyBinding(new KeyBinding(
    "key.mymod.ability",
    InputUtil.Type.KEYSYM,
    GLFW.GLFW_KEY_R,
    "category.mymod"
));

// New Amber way
public static final KeyMapping ABILITY_KEY = new KeyMapping(
    "key.mymod.ability",
    InputConstants.Type.KEYSYM,
    InputConstants.KEY_R,
    KeyMapping.Category.MISC
);

// In your client initializer
KeybindHelper.register(ABILITY_KEY);

From Forge KeyMapping

java
// Old Forge way
private static final DeferredRegister<KeyMapping> KEY_BINDINGS = 
    DeferredRegister.create(ForgeRegistries.KEY_MAPPINGS, MOD_ID);

public static final RegistryObject<KeyMapping> ABILITY_KEY = KEY_BINDINGS.register(
    "ability_key",
    () -> new KeyMapping("key.mymod.ability", GLFW.GLFW_KEY_R, "category.mymod")
);

// New Amber way (simpler!)
public static final KeyMapping ABILITY_KEY = new KeyMapping(
    "key.mymod.ability",
    InputConstants.Type.KEYSYM,
    InputConstants.KEY_R,
    KeyMapping.Category.MISC
);

// In your client setup
KeybindHelper.register(ABILITY_KEY);

The KeybindHelper abstracts platform differences while providing a simpler API that works across all mod loaders.

Released under the MIT License.