Files
MidnightControls/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java
Motschen 8d08fdedf4 MidnightControls 1.7.0 - Fixes & Controller Profiles
- Fix diagonal movement speed (PR #113, thanks @dogtopus, closes #42)
- Toggle Sprint and Toggle Sneak can now be enabled separately just for controllers (closes #102)
- Added button binding profile support (closes #107)
- Fix button binding tooltips intersecting with chat on large GUI scales (closes #106)
- Add assets for non-licensed (numbered) PlayStation controllers (closes #110)
- Fix reacharound outline color
- Fix pixel error in legacy icons (closes #84)
- Fix creative flight being slow with Bedrockify installed (just disables the "disableFlyingMomentum" option on launch)
2022-10-16 15:53:03 +02:00

640 lines
27 KiB
Java

/*
* Copyright © 2021 LambdAurora <aurora42lambda@gmail.com>
*
* This file is part of midnightcontrols.
*
* Licensed under the MIT license. For more information,
* see the LICENSE file.
*/
package eu.midnightdust.midnightcontrols.client.controller;
import eu.midnightdust.midnightcontrols.client.ButtonState;
import eu.midnightdust.midnightcontrols.client.MidnightControlsClient;
import eu.midnightdust.midnightcontrols.client.gui.RingScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.GameOptions;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import org.aperlambda.lambdacommon.utils.function.PairPredicate;
import org.aperlambda.lambdacommon.utils.function.Predicates;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.stream.Collectors;
import static org.lwjgl.glfw.GLFW.*;
/**
* Represents a button binding.
*
* @author LambdAurora
* @version 1.7.0
* @since 1.0.0
*/
public class ButtonBinding {
public static final ButtonCategory MOVEMENT_CATEGORY;
public static final ButtonCategory GAMEPLAY_CATEGORY;
public static final ButtonCategory INVENTORY_CATEGORY;
public static final ButtonCategory MULTIPLAYER_CATEGORY;
public static final ButtonCategory MISC_CATEGORY;
public static final ButtonBinding ATTACK = new Builder("attack").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true)).onlyInGame().register();
public static final ButtonBinding BACK = new Builder("back").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, false))
.action(MovementHandler.HANDLER).onlyInGame().register();
public static final ButtonBinding CHAT = new Builder("chat").buttons(GLFW_GAMEPAD_BUTTON_DPAD_RIGHT).onlyInGame().cooldown().register();
public static final ButtonBinding CONTROLS_RING = new Builder("controls_ring").buttons(GLFW_GAMEPAD_BUTTON_GUIDE).onlyInGame().cooldown()
.action((client, button1, value, action) -> {
if (action.isPressed()) {
MidnightControlsClient.get().ring.loadFromUnbound();
client.setScreen(new RingScreen());
}
if (action.isUnpressed() && client.currentScreen != null) client.currentScreen.close();
return true;
}).register();
public static final ButtonBinding DROP_ITEM = new Builder("drop_item").buttons(GLFW_GAMEPAD_BUTTON_B).onlyInGame().cooldown().register();
public static final ButtonBinding FORWARD = new Builder("forward").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_Y, true))
.action(MovementHandler.HANDLER).onlyInGame().register();
public static final ButtonBinding HOTBAR_LEFT = new Builder("hotbar_left").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
.action(InputHandlers.handleHotbar(false)).onlyInGame().cooldown().register();
public static final ButtonBinding HOTBAR_RIGHT = new Builder("hotbar_right").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
.action(InputHandlers.handleHotbar(true)).onlyInGame().cooldown().register();
public static final ButtonBinding INVENTORY = new Builder("inventory").buttons(GLFW_GAMEPAD_BUTTON_Y).onlyInGame().cooldown().register();
public static final ButtonBinding EXIT = new Builder("exit").buttons(GLFW_GAMEPAD_BUTTON_B).filter((client, buttonBinding) -> client.currentScreen != null && buttonBinding.cooldown == 0 && INVENTORY.cooldown == 0)
.action(InputHandlers.handleExit()).cooldown().register();
public static final ButtonBinding JUMP = new Builder("jump").buttons(GLFW_GAMEPAD_BUTTON_A).onlyInGame().register();
public static final ButtonBinding LEFT = new Builder("left").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, false))
.action(MovementHandler.HANDLER).onlyInGame().register();
public static final ButtonBinding PAUSE_GAME = new Builder("pause_game").buttons(GLFW_GAMEPAD_BUTTON_START).action(InputHandlers::handlePauseGame).cooldown().register();
public static final ButtonBinding PICK_BLOCK = new Builder("pick_block").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT).onlyInGame().cooldown().register();
public static final ButtonBinding PLAYER_LIST = new Builder("player_list").buttons(GLFW_GAMEPAD_BUTTON_BACK).onlyInGame().register();
public static final ButtonBinding RIGHT = new Builder("right").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_X, true))
.action(MovementHandler.HANDLER).onlyInGame().register();
public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A)
.action(InputHandlers::handleScreenshot).cooldown().register();
public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B)
.action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.options.debugEnabled = !client.options.debugEnabled; return true;}).cooldown().register();
public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN)
.action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register();
public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT)
.action(InputHandlers.handleInventorySlotPad(3)).onlyInInventory().cooldown().register();
public static final ButtonBinding SLOT_RIGHT = new Builder("slot_right").buttons(GLFW_GAMEPAD_BUTTON_DPAD_RIGHT)
.action(InputHandlers.handleInventorySlotPad(2)).onlyInInventory().cooldown().register();
public static final ButtonBinding SLOT_UP = new Builder("slot_up").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP)
.action(InputHandlers.handleInventorySlotPad(0)).onlyInInventory().cooldown().register();
public static final ButtonBinding SNEAK = new Builder("sneak").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_THUMB)
.actions(InputHandlers::handleToggleSneak).onlyInGame().cooldown().register();
public static final ButtonBinding SPRINT = new Builder("sprint").buttons(GLFW_GAMEPAD_BUTTON_LEFT_THUMB)
.actions(InputHandlers::handleToggleSprint).onlyInGame().register();
public static final ButtonBinding SWAP_HANDS = new Builder("swap_hands").buttons(GLFW_GAMEPAD_BUTTON_X).onlyInGame().cooldown().register();
public static final ButtonBinding TAB_LEFT = new Builder("tab_back").buttons(GLFW_GAMEPAD_BUTTON_LEFT_BUMPER)
.action(InputHandlers.handleHotbar(false)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((client, binding) -> client.currentScreen != null && client.currentScreen.getClass().toString().contains("sodium"))).cooldown().register();
public static final ButtonBinding TAB_RIGHT = new Builder("tab_next").buttons(GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER)
.action(InputHandlers.handleHotbar(true)).filter(Predicates.or(InputHandlers::inInventory, InputHandlers::inAdvancements).or((client, binding) -> client.currentScreen != null && client.currentScreen.getClass().toString().contains("sodium"))).cooldown().register();
public static final ButtonBinding PAGE_LEFT = new Builder("page_back").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true))
.action(InputHandlers.handlePage(false)).filter(InputHandlers::inInventory).cooldown(30).register();
public static final ButtonBinding PAGE_RIGHT = new Builder("page_next").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true))
.action(InputHandlers.handlePage(true)).filter(InputHandlers::inInventory).cooldown(30).register();
public static final ButtonBinding TAKE = new Builder("take").buttons(GLFW_GAMEPAD_BUTTON_X)
.action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register();
public static final ButtonBinding TAKE_ALL = new Builder("take_all").buttons(GLFW_GAMEPAD_BUTTON_A)
.action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register();
public static final ButtonBinding QUICK_MOVE = new Builder("quick_move").buttons(GLFW_GAMEPAD_BUTTON_Y)
.action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register();
public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").filter(InputHandlers::inGame).buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown().register();
public static final ButtonBinding USE = new Builder("use").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)).register();
private int[] button;
private final int[] defaultButton;
private final String key;
private final Text text;
private KeyBinding mcKeyBinding = null;
protected PairPredicate<MinecraftClient, ButtonBinding> filter;
private final List<PressAction> actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION));
private boolean hasCooldown;
private int cooldownLength = 5;
private int cooldown = 0;
boolean pressed = false;
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown) {
this.setButton(this.defaultButton = defaultButton);
this.key = key;
this.text = Text.translatable(this.key);
this.filter = filter;
this.actions.addAll(actions);
this.hasCooldown = hasCooldown;
}
public ButtonBinding(String key, int[] defaultButton, List<PressAction> actions, PairPredicate<MinecraftClient, ButtonBinding> filter, boolean hasCooldown, int cooldownLength) {
this.setButton(this.defaultButton = defaultButton);
this.key = key;
this.text = Text.translatable(this.key);
this.filter = filter;
this.actions.addAll(actions);
this.hasCooldown = hasCooldown;
this.cooldownLength = cooldownLength;
}
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown) {
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown);
}
public ButtonBinding(String key, int[] defaultButton, boolean hasCooldown, int cooldownLength) {
this(key, defaultButton, Collections.emptyList(), Predicates.pairAlwaysTrue(), hasCooldown, cooldownLength);
}
/**
* Returns the button bound.
*
* @return the bound button
*/
public int[] getButton() {
return this.button;
}
/**
* Sets the bound button.
*
* @param button the bound button
*/
public void setButton(int[] button) {
this.button = button;
if (InputManager.hasBinding(this))
InputManager.sortBindings();
}
/**
* Returns whether the bound button is the specified button or not.
*
* @param button the button to check
* @return true if the bound button is the specified button, else false
*/
public boolean isButton(int[] button) {
return InputManager.areButtonsEquivalent(button, this.button);
}
/**
* Returns whether this button is down or not.
*
* @return true if the button is down, else false
*/
public boolean isButtonDown() {
return this.pressed;
}
/**
* Returns whether this button binding is bound or not.
*
* @return true if this button binding is bound, else false
*/
public boolean isNotBound() {
return this.button.length == 0 || this.button[0] == -1;
}
/**
* Gets the default button assigned to this binding.
*
* @return the default button
*/
public int[] getDefaultButton() {
return this.defaultButton;
}
/**
* Returns whether the assigned button is the default button.
*
* @return true if the assigned button is the default button, else false
*/
public boolean isDefault() {
return this.button.length == this.defaultButton.length && InputManager.areButtonsEquivalent(this.button, this.defaultButton);
}
/**
* Returns the button code.
*
* @return the button code
*/
public String getButtonCode() {
return Arrays.stream(this.button)
.mapToObj(btn -> Integer.valueOf(btn).toString())
.collect(Collectors.joining("+"));
}
/**
* Sets the key binding to emulate with this button binding.
*
* @param keyBinding the optional key binding
*/
public void setKeyBinding(@Nullable KeyBinding keyBinding) {
this.mcKeyBinding = keyBinding;
}
/**
* Returns whether the button binding is available in the current context.
*
* @param client the client instance
* @return true if the button binding is available, else false
*/
public boolean isAvailable(@NotNull MinecraftClient client) {
return this.filter.test(client, this);
}
/**
* Updates the button binding cooldown.
*/
public void update() {
if (this.hasCooldown && this.cooldown > 0)
this.cooldown--;
}
/**
* Handles the button binding.
*
* @param client the client instance
* @param state the state
*/
public void handle(@NotNull MinecraftClient client, float value, @NotNull ButtonState state) {
if (state == ButtonState.REPEAT && this.hasCooldown && this.cooldown != 0)
return;
if (this.hasCooldown && state.isPressed()) {
this.cooldown = cooldownLength;
}
for (int i = this.actions.size() - 1; i >= 0; i--) {
if (this.actions.get(i).press(client, this, value, state))
break;
}
}
public @NotNull String getName() {
return this.key;
}
/**
* Returns the translation key of this button binding.
*
* @return the translation key
*/
public @NotNull String getTranslationKey() {
return I18n.hasTranslation("midnightcontrols.action." + this.getName()) ? "midnightcontrols.action." + this.getName() : this.getName();
}
public @NotNull Text getText() {
return this.text;
}
/**
* Returns the key binding equivalent of this button binding.
*
* @return the key binding equivalent
*/
public @NotNull Optional<KeyBinding> asKeyBinding() {
return Optional.ofNullable(this.mcKeyBinding);
}
@Override
public String toString() {
return "ButtonBinding{id=\"" + this.key + "\","
+ "hasCooldown=" + this.hasCooldown
+ "}";
}
/**
* Returns the specified axis as a button.
*
* @param axis the axis
* @param positive true if the axis part is positive, else false
* @return the axis as a button
*/
public static int axisAsButton(int axis, boolean positive) {
return positive ? 100 + axis : 200 + axis;
}
/**
* Returns whether the specified button is an axis or not.
*
* @param button the button
* @return true if the button is an axis, else false
*/
public static boolean isAxis(int button) {
button %= 500;
return button >= 100;
}
/**
* Returns the second Joycon's specified button code.
*
* @param button the raw button code
* @return the second Joycon's button code
*/
public static int controller2Button(int button) {
return 500 + button;
}
public static void init(@NotNull GameOptions options) {
ATTACK.mcKeyBinding = options.attackKey;
BACK.mcKeyBinding = options.backKey;
CHAT.mcKeyBinding = options.chatKey;
DROP_ITEM.mcKeyBinding = options.dropKey;
FORWARD.mcKeyBinding = options.forwardKey;
INVENTORY.mcKeyBinding = options.inventoryKey;
JUMP.mcKeyBinding = options.jumpKey;
LEFT.mcKeyBinding = options.leftKey;
PICK_BLOCK.mcKeyBinding = options.pickItemKey;
PLAYER_LIST.mcKeyBinding = options.playerListKey;
RIGHT.mcKeyBinding = options.rightKey;
SCREENSHOT.mcKeyBinding = options.screenshotKey;
SNEAK.mcKeyBinding = options.sneakKey;
SPRINT.mcKeyBinding = options.sprintKey;
SWAP_HANDS.mcKeyBinding = options.swapHandsKey;
TOGGLE_PERSPECTIVE.mcKeyBinding = options.togglePerspectiveKey;
USE.mcKeyBinding = options.useKey;
}
/**
* Returns the localized name of the specified button.
*
* @param button the button
* @return the localized name of the button
*/
public static @NotNull Text getLocalizedButtonName(int button) {
return switch (button % 500) {
case -1 -> Text.translatable("key.keyboard.unknown");
case GLFW_GAMEPAD_BUTTON_A -> Text.translatable("midnightcontrols.button.a");
case GLFW_GAMEPAD_BUTTON_B -> Text.translatable("midnightcontrols.button.b");
case GLFW_GAMEPAD_BUTTON_X -> Text.translatable("midnightcontrols.button.x");
case GLFW_GAMEPAD_BUTTON_Y -> Text.translatable("midnightcontrols.button.y");
case GLFW_GAMEPAD_BUTTON_LEFT_BUMPER -> Text.translatable("midnightcontrols.button.left_bumper");
case GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER -> Text.translatable("midnightcontrols.button.right_bumper");
case GLFW_GAMEPAD_BUTTON_BACK -> Text.translatable("midnightcontrols.button.back");
case GLFW_GAMEPAD_BUTTON_START -> Text.translatable("midnightcontrols.button.start");
case GLFW_GAMEPAD_BUTTON_GUIDE -> Text.translatable("midnightcontrols.button.guide");
case GLFW_GAMEPAD_BUTTON_LEFT_THUMB -> Text.translatable("midnightcontrols.button.left_thumb");
case GLFW_GAMEPAD_BUTTON_RIGHT_THUMB -> Text.translatable("midnightcontrols.button.right_thumb");
case GLFW_GAMEPAD_BUTTON_DPAD_UP -> Text.translatable("midnightcontrols.button.dpad_up");
case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> Text.translatable("midnightcontrols.button.dpad_right");
case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> Text.translatable("midnightcontrols.button.dpad_down");
case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> Text.translatable("midnightcontrols.button.dpad_left");
case 100 -> Text.translatable("midnightcontrols.axis.left_x+");
case 101 -> Text.translatable("midnightcontrols.axis.left_y+");
case 102 -> Text.translatable("midnightcontrols.axis.right_x+");
case 103 -> Text.translatable("midnightcontrols.axis.right_y+");
case 104 -> Text.translatable("midnightcontrols.axis.left_trigger");
case 105 -> Text.translatable("midnightcontrols.axis.right_trigger");
case 200 -> Text.translatable("midnightcontrols.axis.left_x-");
case 201 -> Text.translatable("midnightcontrols.axis.left_y-");
case 202 -> Text.translatable("midnightcontrols.axis.right_x-");
case 203 -> Text.translatable("midnightcontrols.axis.right_y-");
case 15 -> Text.translatable("midnightcontrols.button.l4");
case 16 -> Text.translatable("midnightcontrols.button.l5");
case 17 -> Text.translatable("midnightcontrols.button.r4");
case 18 -> Text.translatable("midnightcontrols.button.r5");
default -> Text.translatable("midnightcontrols.button.unknown", button);
};
}
static {
MOVEMENT_CATEGORY = InputManager.registerDefaultCategory("key.categories.movement", category -> category.registerAllBindings(
ButtonBinding.FORWARD,
ButtonBinding.BACK,
ButtonBinding.LEFT,
ButtonBinding.RIGHT,
ButtonBinding.JUMP,
ButtonBinding.SNEAK,
ButtonBinding.SPRINT));
GAMEPLAY_CATEGORY = InputManager.registerDefaultCategory("key.categories.gameplay", category -> category.registerAllBindings(
ButtonBinding.ATTACK,
ButtonBinding.PICK_BLOCK,
ButtonBinding.USE
));
INVENTORY_CATEGORY = InputManager.registerDefaultCategory("key.categories.inventory", category -> category.registerAllBindings(
ButtonBinding.EXIT,
ButtonBinding.DROP_ITEM,
ButtonBinding.HOTBAR_LEFT,
ButtonBinding.HOTBAR_RIGHT,
ButtonBinding.INVENTORY,
ButtonBinding.SWAP_HANDS,
ButtonBinding.TAB_LEFT,
ButtonBinding.TAB_RIGHT,
ButtonBinding.PAGE_LEFT,
ButtonBinding.PAGE_RIGHT,
ButtonBinding.TAKE,
ButtonBinding.TAKE_ALL,
ButtonBinding.QUICK_MOVE,
ButtonBinding.SLOT_UP,
ButtonBinding.SLOT_DOWN,
ButtonBinding.SLOT_LEFT,
ButtonBinding.SLOT_RIGHT
));
MULTIPLAYER_CATEGORY = InputManager.registerDefaultCategory("key.categories.multiplayer",
category -> category.registerAllBindings(ButtonBinding.CHAT, ButtonBinding.PLAYER_LIST));
MISC_CATEGORY = InputManager.registerDefaultCategory("key.categories.misc", category -> category.registerAllBindings(
ButtonBinding.SCREENSHOT,
ButtonBinding.TOGGLE_PERSPECTIVE,
ButtonBinding.PAUSE_GAME,
//SMOOTH_CAMERA,
ButtonBinding.DEBUG_SCREEN,
ButtonBinding.CONTROLS_RING
));
}
/**
* Returns a builder instance.
*
* @param identifier the identifier of the button binding
* @return the builder instance
* @since 1.5.0
*/
public static Builder builder(@NotNull Identifier identifier) {
return new Builder(identifier);
}
/**
* Represents a quick {@link ButtonBinding} builder.
*
* @author LambdAurora
* @version 1.5.0
* @since 1.1.0
*/
public static class Builder {
private final String key;
private int[] buttons = new int[0];
private final List<PressAction> actions = new ArrayList<>();
private PairPredicate<MinecraftClient, ButtonBinding> filter = Predicates.pairAlwaysTrue();
private boolean cooldown = false;
private int cooldownLength = 5;
private ButtonCategory category = null;
private KeyBinding mcBinding = null;
/**
* This constructor shouldn't be used for other mods.
*
* @param key the key with format {@code "<namespace>.<name>"}
*/
public Builder(@NotNull String key) {
this.key = key;
this.unbound();
}
public Builder(@NotNull Identifier identifier) {
this(identifier.getNamespace() + "." + identifier.getPath());
}
/**
* Defines the default buttons of the {@link ButtonBinding}.
*
* @param buttons the default buttons
* @return the builder instance
*/
public Builder buttons(int... buttons) {
this.buttons = buttons;
return this;
}
/**
* Sets the {@link ButtonBinding} to unbound.
*
* @return the builder instance
*/
public Builder unbound() {
return this.buttons(-1);
}
/**
* Adds the actions to the {@link ButtonBinding}.
*
* @param actions the actions to add
* @return the builder instance
*/
public Builder actions(@NotNull PressAction... actions) {
this.actions.addAll(Arrays.asList(actions));
return this;
}
/**
* Adds an action to the {@link ButtonBinding}.
*
* @param action the action to add
* @return the builder instance
*/
public Builder action(@NotNull PressAction action) {
this.actions.add(action);
return this;
}
/**
* Sets a filter for the {@link ButtonBinding}.
*
* @param filter the filter
* @return the builder instance
*/
public Builder filter(@NotNull PairPredicate<MinecraftClient, ButtonBinding> filter) {
this.filter = filter;
return this;
}
/**
* Sets the filter of {@link ButtonBinding} to only in game.
*
* @return the builder instance
* @see #filter(PairPredicate)
* @see InputHandlers#inGame(MinecraftClient, ButtonBinding)
*/
public Builder onlyInGame() {
return this.filter(InputHandlers::inGame);
}
/**
* Sets the filter of {@link ButtonBinding} to only in inventory.
*
* @return the builder instance
* @see #filter(PairPredicate)
* @see InputHandlers#inInventory(MinecraftClient, ButtonBinding)
*/
public Builder onlyInInventory() {
return this.filter(InputHandlers::inInventory);
}
/**
* Sets whether the {@link ButtonBinding} has a cooldown or not.
*
* @param cooldown true if the {@link ButtonBinding} has a cooldown, else false
* @return the builder instance
*/
public Builder cooldown(boolean cooldown) {
this.cooldown = cooldown;
return this;
}
/**
* Sets the cooldown enabled with a custom duration for {@link ButtonBinding}.
*
* @param cooldownLength duration of {@link ButtonBinding} cooldown
* @return the builder instance
*/
public Builder cooldown(int cooldownLength) {
this.cooldownLength = cooldownLength;
this.cooldown = true;
return this;
}
/**
* Puts a cooldown on the {@link ButtonBinding}.
*
* @return the builder instance
* @since 1.5.0
*/
public Builder cooldown() {
return this.cooldown(true);
}
/**
* Sets the category of the {@link ButtonBinding}.
*
* @param category the category
* @return the builder instance
*/
public Builder category(@Nullable ButtonCategory category) {
this.category = category;
return this;
}
/**
* Sets the keybinding linked to the {@link ButtonBinding}.
*
* @param binding the keybinding to link
* @return the builder instance
*/
public Builder linkKeybind(@Nullable KeyBinding binding) {
this.mcBinding = binding;
return this;
}
/**
* Builds the {@link ButtonBinding}.
*
* @return the built {@link ButtonBinding}
*/
public ButtonBinding build() {
var binding = new ButtonBinding(this.key, this.buttons, this.actions, this.filter, this.cooldown, this.cooldownLength);
if (this.category != null)
this.category.registerBinding(binding);
if (this.mcBinding != null)
binding.setKeyBinding(this.mcBinding);
return binding;
}
/**
* Builds and registers the {@link ButtonBinding}.
*
* @return the built {@link ButtonBinding}
* @see #build()
*/
public ButtonBinding register() {
return InputManager.registerBinding(this.build());
}
}
}