1
0
forked from Clones/Controlify

lots of API docs and fix sources jar

This commit is contained in:
isXander
2023-04-15 13:12:45 +01:00
parent 2c08d5f15c
commit 8eb8510590
16 changed files with 233 additions and 59 deletions

View File

@ -1,4 +1,5 @@
import com.github.breadmoirai.githubreleaseplugin.GithubReleaseTask
import org.gradle.jvm.tasks.Jar
plugins {
java
@ -118,6 +119,11 @@ blossom {
replaceToken("<SDL2_VERSION>", libs.versions.sdl2.jni.get(), sdl2ManagerClass)
}
java {
withSourcesJar()
withJavadocJar()
}
tasks {
processResources {
val modId: String by project
@ -152,6 +158,10 @@ tasks {
archiveClassifier.set("fabric-$minecraftVersion-sources")
}
named<Jar>("javadocJar") {
archiveClassifier.set("fabric-$minecraftVersion-javadoc")
}
register("releaseMod") {
group = "mod"
@ -163,10 +173,6 @@ tasks {
}
}
java {
withSourcesJar()
}
val changelogText = file("changelogs/${project.version}.md").takeIf { it.exists() }?.readText() ?: "No changelog provided."
val modrinthId: String by project
@ -233,6 +239,8 @@ publishing {
artifactId = base.archivesName.get()
from(components["java"])
artifact(tasks["remapSourcesJar"])
artifact(tasks["javadocJar"])
}
}

View File

@ -4,6 +4,7 @@ import com.mojang.blaze3d.Blaze3D;
import com.mojang.logging.LogUtils;
import dev.isxander.controlify.api.ControlifyApi;
import dev.isxander.controlify.api.entrypoint.ControlifyEntrypoint;
import dev.isxander.controlify.config.gui.ControllerBindHandler;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerState;
import dev.isxander.controlify.controller.joystick.CompoundJoystickController;
@ -37,6 +38,7 @@ import org.lwjgl.glfw.GLFW;
import org.slf4j.Logger;
import java.util.ArrayDeque;
import java.util.Optional;
import java.util.Queue;
public class Controlify implements ControlifyApi {
@ -160,6 +162,8 @@ public class Controlify implements ControlifyApi {
controllerHIDService = new ControllerHIDService();
controllerHIDService.start();
ControllerBindHandler.setup();
FabricLoader.getInstance().getEntrypoints("controlify", ControlifyEntrypoint.class).forEach(entrypoint -> {
try {
entrypoint.onControlifyPreInit(this);
@ -187,6 +191,7 @@ public class Controlify implements ControlifyApi {
wrapControllerError(controller::updateState, "Updating controller state", controller);
else
wrapControllerError(controller::clearState, "Clearing controller state", controller);
ControlifyEvents.CONTROLLER_STATE_UPDATE.invoker().onControllerStateUpdate(controller);
}
if (switchableController != null && Blaze3D.getTime() - askSwitchTime <= 10000) {
@ -233,11 +238,11 @@ public class Controlify implements ControlifyApi {
ScreenProcessorProvider.provide(minecraft.screen).onControllerUpdate(controller);
}
if (minecraft.level != null) {
this.inGameInputHandler().inputTick();
this.inGameInputHandler().ifPresent(InGameInputHandler::inputTick);
}
this.virtualMouseHandler().handleControllerInput(controller);
ControlifyEvents.CONTROLLER_STATE_UPDATED.invoker().onControllerStateUpdate(controller);
ControlifyEvents.ACTIVE_CONTROLLER_TICKED.invoker().onControllerStateUpdate(controller);
}
public static void wrapControllerError(Runnable runnable, String errorTitle, Controller<?, ?> controller) {
@ -335,10 +340,12 @@ public class Controlify implements ControlifyApi {
return currentController;
}
public void setCurrentController(Controller<?, ?> controller) {
if (controller == null)
controller = Controller.DUMMY;
@Override
public @NotNull Optional<Controller<?, ?>> getCurrentController() {
return Optional.ofNullable(currentController);
}
public void setCurrentController(Controller<?, ?> controller) {
if (this.currentController == controller) return;
this.currentController = controller;
@ -347,6 +354,15 @@ public class Controlify implements ControlifyApi {
switchableController = null;
}
if (controller == null) {
this.setInputMode(InputMode.KEYBOARD_MOUSE);
this.inGameInputHandler = null;
this.inGameButtonGuide = null;
DebugLog.log("Updated current controller to null");
config().save();
return;
}
DebugLog.log("Updated current controller to {}({})", controller.name(), controller.uid());
if (!config().currentControllerUid().equals(controller.uid())) {
@ -362,12 +378,12 @@ public class Controlify implements ControlifyApi {
calibrationQueue.add(controller);
}
public InGameInputHandler inGameInputHandler() {
return inGameInputHandler;
public Optional<InGameInputHandler> inGameInputHandler() {
return Optional.ofNullable(inGameInputHandler);
}
public InGameButtonGuide inGameButtonGuide() {
return inGameButtonGuide;
public Optional<InGameButtonGuide> inGameButtonGuide() {
return Optional.ofNullable(inGameButtonGuide);
}
public VirtualMouseHandler virtualMouseHandler() {

View File

@ -2,10 +2,11 @@ package dev.isxander.controlify.api;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.api.bind.ControlifyBindingsApi;
import dev.isxander.controlify.controller.Controller;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
/**
* Interface with Controlify in a manner where you don't need to worry about updates
* breaking! This is the recommended way to interact with Controlify.
@ -17,10 +18,14 @@ import org.jetbrains.annotations.NotNull;
*/
public interface ControlifyApi {
/**
* @deprecated Use {@link #getCurrentController()} instead.
* @return the controller currently in use. If disabled, this will return {@link Controller#DUMMY}
*/
@Deprecated
@NotNull Controller<?, ?> currentController();
@NotNull Optional<Controller<?, ?>> getCurrentController();
/**
* Get the current input mode for the game.
*/

View File

@ -5,17 +5,39 @@ import dev.isxander.yacl.api.Option;
import net.minecraft.client.KeyMapping;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import java.util.function.BooleanSupplier;
public interface ControllerBinding {
/**
* @return the current analogue state of the binding.
*/
float state();
/**
* @return the analogue state of the binding last tick.
*/
float prevState();
/**
* @return if the binding is currently held.
*/
boolean held();
/**
* @return if the binding was held last tick.
*/
boolean prevHeld();
/**
* @return if the binding is held this tick but not the previous tick
*/
boolean justPressed();
/**
* @return if the binding is not held this tick but was held last tick
*/
boolean justReleased();
Component name();
@ -24,7 +46,10 @@ public interface ControllerBinding {
ResourceLocation id();
KeyMappingOverride override();
/**
* The vanilla override of the binding. Null if there is no override.
*/
@Nullable KeyMappingOverride override();
void resetBind();
boolean isUnbound();

View File

@ -8,6 +8,8 @@ import net.minecraft.client.gui.screens.Screen;
public interface ButtonGuidePredicate<T extends AbstractButton> {
boolean shouldDisplay(T button);
/** Only display the button guide when the button is focused. */
ButtonGuidePredicate<AbstractButton> FOCUS_ONLY = AbstractWidget::isFocused;
/** Always display the button guide. */
ButtonGuidePredicate<AbstractButton> ALWAYS = btn -> true;
}

View File

@ -21,7 +21,22 @@ public final class ControlifyEvents {
/**
* Triggers every tick when the current controller state has been updated.
*/
public static final Event<ControllerStateUpdate> CONTROLLER_STATE_UPDATED = EventFactory.createArrayBacked(ControllerStateUpdate.class, callbacks -> controller -> {
public static final Event<ControllerStateUpdate> ACTIVE_CONTROLLER_TICKED = EventFactory.createArrayBacked(ControllerStateUpdate.class, callbacks -> controller -> {
for (ControllerStateUpdate callback : callbacks) {
callback.onControllerStateUpdate(controller);
}
});
/**
* @deprecated Use {@link #ACTIVE_CONTROLLER_TICKED} instead.
*/
@Deprecated
public static final Event<ControllerStateUpdate> CONTROLLER_STATE_UPDATED = ACTIVE_CONTROLLER_TICKED;
/**
* Triggers every tick when any connected controller's state has been updated before the active controller is ticked.
*/
public static final Event<ControllerStateUpdate> CONTROLLER_STATE_UPDATE = EventFactory.createArrayBacked(ControllerStateUpdate.class, callbacks -> controller -> {
for (ControllerStateUpdate callback : callbacks) {
callback.onControllerStateUpdate(controller);
}
@ -45,6 +60,10 @@ public final class ControlifyEvents {
}
});
/**
* Allows you to modify the look input before it is applied to the player.
* These modifiers are called before the look input is multiplied by the sensitivity.
*/
public static final Event<LookInputModifier> LOOK_INPUT_MODIFIER = EventFactory.createArrayBacked(LookInputModifier.class, callbacks -> new LookInputModifier() {
@Override
public float modifyX(float x, Controller<?, ?> controller) {

View File

@ -6,6 +6,15 @@ import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.phys.HitResult;
/**
* All information available to a guide entry.
* This may be added over time.
* @param client the minecraft client
* @param player local player
* @param level the current world
* @param hitResult where the player is currently looking
* @param controller the controller for this guide renderer
*/
public record IngameGuideContext(Minecraft client,
LocalPlayer player,
ClientLevel level,

View File

@ -6,15 +6,49 @@ import dev.isxander.controlify.ingame.InGameInputHandler;
import java.util.function.BiFunction;
import java.util.function.BooleanSupplier;
/**
* Allows dependants to modify controller look input.
*
* Implementing classes must provide methods for modifying the x
* and y axis values of the controller's look input.
*/
public interface LookInputModifier {
/**
* Modifies the x axis value of the controller's look input.
*
* @param x the current value of the x axis, typically in the range 0-1 but can be higher from gyro input
* @param controller the current active controller
* @return the modified value of the x axis
*/
float modifyX(float x, Controller<?, ?> controller);
/**
* Modifies the y axis value of the controller's look input.
*
* @param y the current value of the y axis, typically in the range 0-1 but can be higher from gyro input
* @param controller the current active controller
* @return the modified value of the y axis
*/
float modifyY(float y, Controller<?, ?> controller);
/**
* Creates a new LookInputModifier using the given x and y axis modifying functions.
*
* @param x the function for modifying the x axis
* @param y the function for modifying the y axis
* @return the new LookInputModifier object
*/
static LookInputModifier functional(BiFunction<Float, Controller<?, ?>, Float> x, BiFunction<Float, Controller<?, ?>, Float> y) {
return new InGameInputHandler.FunctionalLookInputModifier(x, y);
}
/**
* Creates a new LookInputModifier that sets the x and y axis to zero if the given condition is true.
*
* @param condition the condition that determines whether to set the axis values to zero
* @return the new LookInputModifier object
*/
static LookInputModifier zeroIf(BooleanSupplier condition) {
return functional((x, controller) -> condition.getAsBoolean() ? 0 : x, (y, controller) -> condition.getAsBoolean() ? 0 : y);
}

View File

@ -339,7 +339,7 @@ public class ControllerBindings<T extends ControllerState> {
registerModdedKeybinds();
ControlifyEvents.CONTROLLER_STATE_UPDATED.register(this::onControllerUpdate);
ControlifyEvents.CONTROLLER_STATE_UPDATE.register(this::onControllerUpdate);
ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> KeyMapping.releaseAll());
}

View File

@ -0,0 +1,21 @@
package dev.isxander.controlify.config.gui;
import dev.isxander.controlify.api.event.ControlifyEvents;
public class ControllerBindHandler {
public static ControlifyEvents.ControllerStateUpdate CURRENT_BIND_LISTENER = controller -> {};
public static void setBindListener(ControlifyEvents.ControllerStateUpdate listener) {
CURRENT_BIND_LISTENER = listener;
}
public static void clearBindListener() {
CURRENT_BIND_LISTENER = controller -> {};
}
public static void setup() {
ControlifyEvents.CONTROLLER_STATE_UPDATE.register(controller -> {
CURRENT_BIND_LISTENER.onControllerStateUpdate(controller);
});
}
}

View File

@ -1,6 +1,7 @@
package dev.isxander.controlify.config.gui;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.api.event.ControlifyEvents;
import dev.isxander.controlify.bindings.GamepadBind;
import dev.isxander.controlify.bindings.GamepadBinds;
import dev.isxander.controlify.bindings.IBind;
@ -42,8 +43,9 @@ public class GamepadBindController implements Controller<IBind<GamepadState>> {
return new BindButtonWidget(this, yaclScreen, dimension);
}
public static class BindButtonWidget extends ControllerWidget<GamepadBindController> implements ComponentProcessor {
public static class BindButtonWidget extends ControllerWidget<GamepadBindController> implements ComponentProcessor, ControlifyEvents.ControllerStateUpdate {
private boolean awaitingControllerInput = false;
private boolean justTookInput = false;
private final Component awaitingText = Component.translatable("controlify.gui.bind_input_awaiting").withStyle(ChatFormatting.ITALIC);
public BindButtonWidget(GamepadBindController control, YACLScreen screen, Dimension<Integer> dim) {
@ -64,6 +66,7 @@ public class GamepadBindController implements Controller<IBind<GamepadState>> {
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (isFocused() && keyCode == GLFW.GLFW_KEY_ENTER && !awaitingControllerInput) {
awaitingControllerInput = true;
ControllerBindHandler.setBindListener(this);
return true;
}
@ -74,6 +77,7 @@ public class GamepadBindController implements Controller<IBind<GamepadState>> {
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (getDimension().isPointInside((int)mouseX, (int)mouseY)) {
awaitingControllerInput = true;
ControllerBindHandler.setBindListener(this);
return true;
}
@ -85,10 +89,23 @@ public class GamepadBindController implements Controller<IBind<GamepadState>> {
if (controller != control.controller) return true;
if (controller.bindings().GUI_PRESS.justPressed() && !awaitingControllerInput) {
ControllerBindHandler.setBindListener(this);
return awaitingControllerInput = true;
}
if (!awaitingControllerInput) return false;
if (justTookInput) {
justTookInput = false;
return true;
}
return false;
}
@Override
public void onControllerStateUpdate(dev.isxander.controlify.controller.Controller<?, ?> controller) {
if (controller != control.controller) return;
if (!awaitingControllerInput) return;
var gamepad = control.controller;
@ -97,17 +114,16 @@ public class GamepadBindController implements Controller<IBind<GamepadState>> {
if (bind.held(gamepad.state()) && !bind.held(gamepad.prevState())) {
control.option().requestSet(bind);
awaitingControllerInput = false;
gamepad.consumeButtonState();
return true;
justTookInput = true;
ControllerBindHandler.clearBindListener();
return;
}
}
return false;
}
@Override
public boolean overrideControllerNavigation(ScreenProcessor<?> screen, dev.isxander.controlify.controller.Controller<?, ?> controller) {
return awaitingControllerInput;
return awaitingControllerInput || justTookInput;
}
@Override

View File

@ -1,6 +1,7 @@
package dev.isxander.controlify.config.gui;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.api.event.ControlifyEvents;
import dev.isxander.controlify.bindings.*;
import dev.isxander.controlify.controller.joystick.JoystickController;
import dev.isxander.controlify.controller.joystick.SingleJoystickController;
@ -41,8 +42,9 @@ public class JoystickBindController implements Controller<IBind<JoystickState>>
return new BindButtonWidget(this, yaclScreen, dimension);
}
public static class BindButtonWidget extends ControllerWidget<JoystickBindController> implements ComponentProcessor {
public static class BindButtonWidget extends ControllerWidget<JoystickBindController> implements ComponentProcessor, ControlifyEvents.ControllerStateUpdate {
private boolean awaitingControllerInput = false;
private boolean justTookInput = false;
private final Component awaitingText = Component.translatable("controlify.gui.bind_input_awaiting").withStyle(ChatFormatting.ITALIC);
public BindButtonWidget(JoystickBindController control, YACLScreen screen, Dimension<Integer> dim) {
@ -63,6 +65,7 @@ public class JoystickBindController implements Controller<IBind<JoystickState>>
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (isFocused() && keyCode == GLFW.GLFW_KEY_ENTER && !awaitingControllerInput) {
awaitingControllerInput = true;
ControllerBindHandler.setBindListener(this);
return true;
}
@ -73,6 +76,7 @@ public class JoystickBindController implements Controller<IBind<JoystickState>>
public boolean mouseClicked(double mouseX, double mouseY, int button) {
if (getDimension().isPointInside((int)mouseX, (int)mouseY)) {
awaitingControllerInput = true;
ControllerBindHandler.setBindListener(this);
return true;
}
@ -83,11 +87,25 @@ public class JoystickBindController implements Controller<IBind<JoystickState>>
public boolean overrideControllerButtons(ScreenProcessor<?> screen, dev.isxander.controlify.controller.Controller<?, ?> controller) {
if (controller != control.controller) return true;
if (controller.bindings().GUI_PRESS.justPressed() && !awaitingControllerInput) {
return awaitingControllerInput = true;
if (justTookInput) {
justTookInput = false;
return true;
}
if (!awaitingControllerInput) return false;
if (controller.bindings().GUI_PRESS.justPressed() && !awaitingControllerInput) {
awaitingControllerInput = true;
ControllerBindHandler.setBindListener(this);
return true;
}
return awaitingControllerInput;
}
@Override
public void onControllerStateUpdate(dev.isxander.controlify.controller.Controller<?, ?> controller) {
if (controller != control.controller) return;
if (!awaitingControllerInput) return;
var joystick = control.controller;
@ -98,7 +116,9 @@ public class JoystickBindController implements Controller<IBind<JoystickState>>
if (state.buttons().get(i) && !prevState.buttons().get(i)) {
control.option().requestSet(new JoystickButtonBind(joystick, i));
awaitingControllerInput = false;
return true;
justTookInput = true;
ControllerBindHandler.clearBindListener();
return;
}
}
@ -111,11 +131,15 @@ public class JoystickBindController implements Controller<IBind<JoystickState>>
if (axis > activationThreshold) {
control.option().requestSet(new JoystickAxisBind(joystick, i, JoystickAxisBind.AxisDirection.POSITIVE));
awaitingControllerInput = false;
return true;
justTookInput = true;
ControllerBindHandler.clearBindListener();
return;
} else if (axis < -activationThreshold) {
control.option().requestSet(new JoystickAxisBind(joystick, i, JoystickAxisBind.AxisDirection.NEGATIVE));
awaitingControllerInput = false;
return true;
justTookInput = true;
ControllerBindHandler.clearBindListener();
return;
}
}
}
@ -127,16 +151,16 @@ public class JoystickBindController implements Controller<IBind<JoystickState>>
if (prevHat.isCentered() && !hat.isCentered()) {
control.option().requestSet(new JoystickHatBind(joystick, i, hat));
awaitingControllerInput = false;
return true;
justTookInput = true;
ControllerBindHandler.clearBindListener();
return;
}
}
return false;
}
@Override
public boolean overrideControllerNavigation(ScreenProcessor<?> screen, dev.isxander.controlify.controller.Controller<?, ?> controller) {
return awaitingControllerInput;
return awaitingControllerInput || justTookInput;
}
@Override

View File

@ -73,15 +73,8 @@ public class JoystickState implements ControllerState {
}
public static JoystickState fromJoystick(JoystickController<?> joystick, int joystickId) {
if (DebugProperties.PRINT_JOY_INPUT_COUNT)
Controlify.LOGGER.info("Printing joy input for " + joystick.name());
FloatBuffer axesBuffer = GLFW.glfwGetJoystickAxes(joystickId);
float[] inAxes = new float[axesBuffer.limit()];
if (DebugProperties.PRINT_JOY_INPUT_COUNT)
Controlify.LOGGER.info("Axes count = " + inAxes.length);
{
int i = 0;
while (axesBuffer.hasRemaining()) {
@ -92,10 +85,6 @@ public class JoystickState implements ControllerState {
ByteBuffer buttonBuffer = GLFW.glfwGetJoystickButtons(joystickId);
boolean[] inButtons = new boolean[buttonBuffer.limit()];
if (DebugProperties.PRINT_JOY_INPUT_COUNT)
Controlify.LOGGER.info("Button count = " + inButtons.length);
{
int i = 0;
while (buttonBuffer.hasRemaining()) {
@ -106,10 +95,6 @@ public class JoystickState implements ControllerState {
ByteBuffer hatBuffer = GLFW.glfwGetJoystickHats(joystickId);
HatState[] inHats = new HatState[hatBuffer.limit()];
if (DebugProperties.PRINT_JOY_INPUT_COUNT)
Controlify.LOGGER.info("Hat count = " + inHats.length);
{
int i = 0;
while (hatBuffer.hasRemaining()) {
@ -139,12 +124,22 @@ public class JoystickState implements ControllerState {
var axis = axes[i];
float state = axis.getAxis(data);
rawAxes.add(state);
deadzoneAxes.add(axis.requiresDeadzone() ? ControllerUtils.deadzone(state, i) : state);
deadzoneAxes.add(axis.requiresDeadzone()
? ControllerUtils.deadzone(state, joystick.config().getDeadzone(i))
: state
);
}
List<Boolean> buttons = Arrays.stream(mapping.buttons()).map(button -> button.isPressed(data)).toList();
List<HatState> hats = Arrays.stream(mapping.hats()).map(hat -> hat.getHatState(data)).toList();
if (DebugProperties.PRINT_JOY_STATE) {
Controlify.LOGGER.info("Printing joystick state for controller {}", joystick);
Controlify.LOGGER.info(Arrays.stream(axes).map(axis -> axis.name().getString() + ": " + axis.getAxis(data)).toList().toString());
Controlify.LOGGER.info(Arrays.stream(mapping.buttons()).map(button -> button.name().getString() + ": " + button.isPressed(data)).toList().toString());
Controlify.LOGGER.info(Arrays.stream(mapping.hats()).map(hat -> hat.name().getString() + ": " + hat.getHatState(data)).toList().toString());
}
return new JoystickState(joystick.mapping(), deadzoneAxes, rawAxes, buttons, hats);
}

View File

@ -15,7 +15,7 @@ public class DebugProperties {
/* Forces all gamepads to be treated as a regular joystick */
public static final boolean FORCE_JOYSTICK = boolProp("controlify.debug.force_joystick", false, false);
/* Prints joystick input counts for making joystick mappings */
public static final boolean PRINT_JOY_INPUT_COUNT = boolProp("controlify.debug.print_joy_input_count", false, false);
public static final boolean PRINT_JOY_STATE = boolProp("controlify.debug.print_joy_state", false, false);
/* Print gyro data if supported */
public static final boolean PRINT_GYRO = boolProp("controlify.debug.print_gyro", false, false);

View File

@ -50,7 +50,7 @@ public abstract class MinecraftMixin {
@Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;turnPlayer()V"))
private void doPlayerLook(boolean tick, CallbackInfo ci) {
Controlify.instance().inGameInputHandler().processPlayerLook(getDeltaFrameTime());
Controlify.instance().inGameInputHandler().ifPresent(ih -> ih.processPlayerLook(getDeltaFrameTime()));
}
@Inject(method = "<init>", at = @At("TAIL"))

View File

@ -2,6 +2,8 @@ package dev.isxander.controlify.mixins.feature.guide.ingame;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.ingame.InGameInputHandler;
import dev.isxander.controlify.ingame.guide.InGameButtonGuide;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
import org.spongepowered.asm.mixin.Final;
@ -20,17 +22,15 @@ public class GuiMixin {
@Inject(method = "render", at = @At(value = "CONSTANT", args = "stringValue=chat"))
private void renderButtonGuide(PoseStack matrices, float tickDelta, CallbackInfo ci) {
if (Controlify.instance().inGameButtonGuide() != null) {
Controlify.instance().inGameButtonGuide().ifPresent(guide -> {
minecraft.getProfiler().push("controlify_button_guide");
Controlify.instance().inGameButtonGuide().renderHud(matrices, tickDelta, screenWidth, screenHeight);
guide.renderHud(matrices, tickDelta, screenWidth, screenHeight);
minecraft.getProfiler().pop();
}
});
}
@Inject(method = "tick()V", at = @At("RETURN"))
private void tickButtonGuide(CallbackInfo ci) {
if (Controlify.instance().inGameButtonGuide() != null) {
Controlify.instance().inGameButtonGuide().tick();
}
Controlify.instance().inGameButtonGuide().ifPresent(InGameButtonGuide::tick);
}
}