From 203fd6cdb6d835c600ff00cad5c1b23665bd74f0 Mon Sep 17 00:00:00 2001 From: Motschen Date: Sun, 18 Sep 2022 20:20:10 +0200 Subject: [PATCH] First 1.6.0 changes Way too many changes & fixes to list here, still got some work to do, but this is coming along great already --- build.gradle | 7 ++ gradle.properties | 21 +++--- .../midnightcontrols/MidnightControls.java | 1 + .../client/MidnightControlsClient.java | 27 +++++--- .../client/MidnightControlsConfig.java | 24 ++++--- .../client/MidnightInput.java | 66 ++++++++++++++----- .../client/compat/EMICompat.java | 6 +- .../client/compat/EmotecraftCompat.java | 29 ++++++++ .../client/compat/InventoryTabsCompat.java | 33 ++++++++++ .../client/compat/MidnightControlsCompat.java | 16 +++++ .../client/controller/ButtonBinding.java | 52 +++++++++++++-- .../client/controller/InputHandlers.java | 61 +++++++++++------ .../client/controller/InputManager.java | 24 +++++++ .../client/gui/MidnightControlsHud.java | 11 ++-- .../client/gui/RingScreen.java | 39 ++++++++++- .../client/mixin/HandledScreenMixin.java | 7 +- .../client/mixin/MinecraftClientMixin.java | 32 ++------- .../client/mixin/WorldRendererMixin.java | 20 ++++-- ...tion.java => ButtonBindingRingAction.java} | 30 +++++---- .../client/ring/DummyRingAction.java | 36 ---------- .../client/ring/MidnightRing.java | 64 +++++++++++++++--- .../client/ring/RingAction.java | 8 +-- .../client/ring/RingPage.java | 58 ++++++---------- .../assets/midnightcontrols/lang/en_us.json | 3 +- 24 files changed, 463 insertions(+), 212 deletions(-) create mode 100644 src/main/java/eu/midnightdust/midnightcontrols/client/compat/EmotecraftCompat.java create mode 100644 src/main/java/eu/midnightdust/midnightcontrols/client/compat/InventoryTabsCompat.java rename src/main/java/eu/midnightdust/midnightcontrols/client/ring/{KeyBindingRingAction.java => ButtonBindingRingAction.java} (55%) delete mode 100644 src/main/java/eu/midnightdust/midnightcontrols/client/ring/DummyRingAction.java diff --git a/build.gradle b/build.gradle index f33e346..264e344 100644 --- a/build.gradle +++ b/build.gradle @@ -73,6 +73,7 @@ repositories { } maven { url "https://maven.terraformersmc.com/releases/" } maven { url 'https://maven.kosmx.dev' } + maven { url 'https://maven.isxander.dev/releases' } maven { url 'https://maven.shedaniel.me/' } maven { url 'https://jitpack.io' } maven { url "https://api.modrinth.com/maven" } @@ -115,6 +116,12 @@ dependencies { modImplementation("maven.modrinth:emi:${project.emi_version}") modImplementation "maven.modrinth:emotecraft:${project.emotecraft_version}" modImplementation "io.github.kosmx:bendy-lib:${project.bendylib_version}" + modImplementation "dev.isxander:yet-another-config-lib:${project.yacl_version}" + modImplementation "maven.modrinth:inventory-tabs-updated:${project.inventorytabs_version}" + // Required for Inventory Tabs + modApi("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") { + exclude(group: "net.fabricmc.fabric-api") + } modImplementation "maven.modrinth:midnightlib:${project.midnightlib_version}" include "maven.modrinth:midnightlib:${project.midnightlib_version}" diff --git a/gradle.properties b/gradle.properties index 3791d9d..41202f6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,27 +3,30 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use -minecraft_version=1.19 -yarn_mappings=1.19+build.1 -loader_version=0.14.7 +minecraft_version=1.19.2 +yarn_mappings=1.19.2+build.9 +loader_version=0.14.9 # Mod Properties -mod_version = 1.5.0 +mod_version = 1.6.0 maven_group = eu.midnightdust archives_base_name = midnightcontrols modrinth_id=bXX9h73M # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api -fabric_version=0.55.2+1.19 -sodium_version=mc1.19-0.4.2 +fabric_version=0.60.0+1.19.2 +sodium_version=mc1.19.2-0.4.4 spruceui_version=4.0.0+1.19 -midnightlib_version=0.5.2 -modmenu_version=4.0.0 +midnightlib_version=0.6.0 +modmenu_version=4.0.6 emotecraft_version=2.1.3-SNAPSHOT-build.29-MC1.19-fabric bendylib_version=2.0.+ -emi_version=0.2.0+1.19 +emi_version=0.4.0+1.19 libgui_version=6.0.0+1.19 +inventorytabs_version=inventorytabs-0.9.beta-1.19.x +clothconfig_version=7.0.72 +yacl_version=0.1.2 # Ok Zoomer and LibZoomer are temporarily disabled for the time being, as we are currently using Reflection at runtime instead in OkZoomerCompat due to there being two major, completely incompatible API versions. # ok_zoomer_version=5.0.0-beta.3+1.17.1 diff --git a/src/main/java/eu/midnightdust/midnightcontrols/MidnightControls.java b/src/main/java/eu/midnightdust/midnightcontrols/MidnightControls.java index f7a0824..312fae5 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/MidnightControls.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/MidnightControls.java @@ -9,6 +9,7 @@ package eu.midnightdust.midnightcontrols; +import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.event.PlayerChangeControlsModeCallback; import io.netty.buffer.Unpooled; import net.fabricmc.api.ModInitializer; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java index 2da3a9f..7bb4d91 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java @@ -20,9 +20,10 @@ import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory; import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.InputManager; import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsHud; +import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay; import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingRegistryImplAccessor; -import eu.midnightdust.midnightcontrols.client.ring.KeyBindingRingAction; +import eu.midnightdust.midnightcontrols.client.ring.ButtonBindingRingAction; import eu.midnightdust.midnightcontrols.client.ring.MidnightRing; import dev.lambdaurora.spruceui.hud.HudManager; import net.fabricmc.api.ClientModInitializer; @@ -44,6 +45,8 @@ import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFW; import java.io.File; +import java.util.Timer; +import java.util.TimerTask; /** * Represents the midnightcontrols client mod. @@ -83,10 +86,9 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo KeyBindingHelper.registerKeyBinding(BINDING_LOOK_RIGHT); KeyBindingHelper.registerKeyBinding(BINDING_LOOK_DOWN); KeyBindingHelper.registerKeyBinding(BINDING_LOOK_LEFT); - //KeyBindingHelper.registerKeyBinding(BINDING_RING); + KeyBindingHelper.registerKeyBinding(BINDING_RING); - this.ring.registerAction("keybinding", KeyBindingRingAction.FACTORY); - this.ring.load(); + this.ring.registerAction("buttonbinding", ButtonBindingRingAction.FACTORY); ClientPlayNetworking.registerGlobalReceiver(CONTROLS_MODE_CHANNEL, (client, handler, buf, responseSender) -> responseSender.sendPacket(CONTROLS_MODE_CHANNEL, this.makeControlsModeBuffer(MidnightControlsConfig.controlsMode))); @@ -123,6 +125,14 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","bedrock"), modContainer, ResourcePackActivationType.NORMAL); ResourceManagerHelper.registerBuiltinResourcePack(new Identifier("midnightcontrols","legacy"), modContainer, ResourcePackActivationType.NORMAL); }); + int delay = 0; // delay for 0 sec. + int period = 1; // repeat every 0.001 sec. (100 times a second) + Timer timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { + public void run() { + input.updateCamera(MinecraftClient.getInstance()); + } + }, delay, period); } /** @@ -189,9 +199,10 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput)) this.input.tickController(client); -// if (BINDING_RING.wasPressed()) { -// client.setScreen(new RingScreen()); -// } + if (BINDING_RING.wasPressed()) { + ring.loadFromUnbound(); + client.setScreen(new RingScreen()); + } if (client.world != null && MidnightControlsConfig.enableHints && !MidnightControlsConfig.autoSwitchMode && MidnightControlsConfig.controlsMode == ControlsMode.DEFAULT && MidnightControlsConfig.getController().isGamepad()) { client.getToastManager().add(SystemToast.create(client, SystemToast.Type.PERIODIC_NOTIFICATION, Text.translatable("midnightcontrols.controller.tutorial.title"), Text.translatable("midnightcontrols.controller.tutorial.description", Text.translatable("options.title"), Text.translatable("controls.title"), @@ -201,7 +212,7 @@ public class MidnightControlsClient extends MidnightControls implements ClientMo } } public void onRender(MinecraftClient client) { - this.input.onRender(client); + //this.input.onRender(client); } /** diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java index d884bdd..0b21567 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java @@ -31,6 +31,7 @@ import static org.lwjgl.glfw.GLFW.*; */ public class MidnightControlsConfig extends MidnightConfig { public static boolean isEditing = false; + @Hidden @Entry public static int configVersion = 1; // General @Entry(name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT; @Entry(name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true; @@ -47,12 +48,13 @@ public class MidnightControlsConfig extends MidnightConfig { @Entry(name = "midnightcontrols.menu.reacharound.horizontal") public static boolean horizontalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. @Entry(name = "midnightcontrols.menu.reacharound.vertical") public static boolean verticalReacharound = false; // Disabled by default as this behaviour can be considered cheating on multiplayer servers. @Entry(name = "Reacharound Outline") public static boolean shouldRenderReacharoundOutline = true; - @Entry(name = "Reacharound Outline Color") public static int[] reacharoundOutlineColor = new int[]{255, 255, 255, 102}; + @Entry(name = "Reacharound Outline Color (WIP)", isColor = true) public static String reacharoundOutlineColorHex = "#ffffff"; + @Entry(name = "Reacharound Outline Alpha", min = 0, max = 255) public static int reacharoundOutlineColorAlpha = 102; @Entry(name = "midnightcontrols.menu.right_dead_zone") public static double rightDeadZone = 0.25; @Entry(name = "midnightcontrols.menu.left_dead_zone") public static double leftDeadZone = 0.25; @Entry(name = "midnightcontrols.menu.invert_right_y_axis") public static boolean invertRightYAxis = false; @Entry(name = "midnightcontrols.menu.invert_right_x_axis") public static boolean invertRightXAxis = false; - @Entry(name = "midnightcontrols.menu.rotation_speed") public static double rotationSpeed = 40.0; //used for x axis, name kept for compatability + @Entry(name = "midnightcontrols.menu.rotation_speed") public static double rotationSpeed = 30.0; //used for x axis, name kept for compatability @Entry(name = "midnightcontrols.menu.y_axis_rotation_speed") public static double yAxisRotationSpeed = rotationSpeed; @Entry(name = "midnightcontrols.menu.mouse_speed") public static double mouseSpeed = 25.0; @Entry(name = "midnightcontrols.menu.unfocused_input") public static boolean unfocusedInput = false; @@ -64,15 +66,16 @@ public class MidnightControlsConfig extends MidnightConfig { @Entry(name = "Mouse screens") public static List mouseScreens = Lists.newArrayList("me.jellysquid.mods.sodium.client.gui", "net.coderbot.iris.gui", "net.minecraft.client.gui.screen.advancement", "net.minecraft.client.gui.screen.pack.PackScreen", "net.minecraft.class_5375", "net.minecraft.class_457", "net.minecraft.class_408", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen", - "hardcorequesting.client.interfaces.GuiQuestBook", "hardcorequesting.client.interfaces.GuiReward", "hardcorequesting.client.interfaces.EditTrackerScreen", - "io.github.kosmx.emotes.arch.gui.screen.ingame.FastChosseScreen"); + "hardcorequesting.client.interfaces.GuiQuestBook", "hardcorequesting.client.interfaces.GuiReward", "hardcorequesting.client.interfaces.EditTrackerScreen"); @Entry(name = "Keybindings") public static Map BINDINGS = new HashMap<>(); private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?"); @Entry(name = "Max analog values") public static double[] maxAnalogValues = new double[]{1, 1, 1, 1}; @Entry(name = "Trigger button fix") public static boolean triggerFix = true; @Entry(name = "Enable Hints") public static boolean enableHints = true; - @Entry(name = "Command Keybinds") public static List commandKeybinds = Lists.newArrayList(); + @Entry(name = "Enable Shortcut in Controls Options") public static boolean shortcutInControls = true; + @Entry(name = "Ring Bindings (WIP)") public static List ringBindings = new ArrayList<>(); + @Entry(name = "Ignored Unbound Keys") public static List ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab"); /** * Loads the configuration @@ -82,7 +85,6 @@ public class MidnightControlsConfig extends MidnightConfig { MidnightControlsClient.get().log("Configuration loaded."); // Controller controls. InputManager.loadButtonBindings(); - //this.mod.ring.load(this.config); } /** @@ -286,12 +288,13 @@ public class MidnightControlsConfig extends MidnightConfig { horizontalReacharound = false; verticalReacharound = false; shouldRenderReacharoundOutline = true; - reacharoundOutlineColor = new int[]{255, 255, 255, 102}; + reacharoundOutlineColorHex = "#ffffff"; + reacharoundOutlineColorAlpha = 102; rightDeadZone = 0.25; leftDeadZone = 0.25; invertRightYAxis = false; invertRightXAxis = false; - rotationSpeed = 40.0; + rotationSpeed = 30.0; yAxisRotationSpeed = rotationSpeed; mouseSpeed = 25.0; unfocusedInput = false; @@ -303,6 +306,11 @@ public class MidnightControlsConfig extends MidnightConfig { mouseScreens = Lists.newArrayList("me.jellysquid.mods.sodium.client.gui", "net.coderbot.iris.gui", "net.minecraft.client.gui.screen.advancement", "net.minecraft.client.gui.screen.pack.PackScreen", "net.minecraft.class_5375", "net.minecraft.class_457", "net.minecraft.class_408", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen"); BINDINGS = new HashMap<>(); maxAnalogValues = new double[]{1, 1, 1, 1}; + triggerFix = true; + enableHints = true; + shortcutInControls = true; + ringBindings = new ArrayList<>(); + ignoredUnboundKeys = Lists.newArrayList("inventorytabs.key.next_tab"); } /** diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java index bf0d749..458cbf8 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java @@ -13,15 +13,18 @@ import com.google.common.collect.ImmutableSet; import dev.lambdaurora.spruceui.widget.AbstractSpruceWidget; import dev.lambdaurora.spruceui.widget.container.SpruceEntryListWidget; import eu.midnightdust.midnightcontrols.MidnightControls; +import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat; import eu.midnightdust.midnightcontrols.client.compat.LibGuiCompat; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.compat.SodiumCompat; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.InputManager; +import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay; import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget; import eu.midnightdust.midnightcontrols.client.mixin.*; +import eu.midnightdust.midnightcontrols.client.ring.RingPage; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; import eu.midnightdust.midnightcontrols.client.util.MouseAccessor; import dev.lambdaurora.spruceui.navigation.NavigationDirection; @@ -41,11 +44,13 @@ import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.MerchantScreen; +import net.minecraft.client.gui.screen.ingame.StonecutterScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget; import net.minecraft.client.gui.screen.world.WorldListWidget; import net.minecraft.client.gui.widget.*; import net.minecraft.screen.slot.Slot; +import net.minecraft.text.TranslatableTextContent; import net.minecraft.util.math.MathHelper; import org.aperlambda.lambdacommon.utils.Pair; import org.jetbrains.annotations.NotNull; @@ -171,11 +176,11 @@ public class MidnightInput { } /** - * This method is called when Minecraft renders. + * This method is called to update the camera * * @param client the client instance */ - public void onRender(@NotNull MinecraftClient client) { + public void updateCamera(@NotNull MinecraftClient client) { if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay)) return; @@ -184,8 +189,10 @@ public class MidnightInput { return; if (this.targetYaw != 0.f || this.targetPitch != 0.f) { - float rotationYaw = (float) (player.prevYaw + (this.targetYaw / 0.10) * client.getTickDelta()); - float rotationPitch = (float) (player.prevPitch + (this.targetPitch / 0.10) * client.getTickDelta()); + float rotationYaw = (float) (client.player.prevYaw + (this.targetYaw * 0.2)); + float rotationPitch = (float) (client.player.prevPitch + (this.targetPitch * 0.2)); + client.player.prevYaw = rotationYaw; + client.player.prevPitch = MathHelper.clamp(rotationPitch, -90.f, 90.f); client.player.setYaw(rotationYaw); client.player.setPitch(MathHelper.clamp(rotationPitch, -90.f, 90.f)); if (client.player.isRiding() && client.player.getVehicle() != null) { @@ -257,7 +264,30 @@ public class MidnightInput { value *= -1.0F; int state = value > MidnightControlsConfig.rightDeadZone ? 1 : (value < -MidnightControlsConfig.rightDeadZone ? 2 : 0); - this.handleAxe(client, axis, value, absValue, state); + if (!(client.currentScreen instanceof RingScreen || (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)))) this.handleAxe(client, axis, value, absValue, state); + } + if (client.currentScreen instanceof RingScreen || (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen))) { + float x = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X)) > MidnightControlsConfig.leftDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X) : 0; + float y = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y)) > MidnightControlsConfig.leftDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y) : 0; + if (x == 0 && y == 0) { + x = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_X)) > MidnightControlsConfig.rightDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_X) : 0; + y = Math.abs(buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y)) > MidnightControlsConfig.rightDeadZone ? buffer.get(GLFW_GAMEPAD_AXIS_RIGHT_Y) : 0; + } + int index = -1; + if (x < 0) { + if (y < 0) index = 0; + if (y == 0) index = 3; + if (y > 0) index = 5; + } else if (x == 0) { + if (y < 0) index = 1; + if (y > 0) index = 6; + } else if (x > 0) { + if (y < 0) index = 2; + if (y == 0) index = 4; + if (y > 0) index = 7; + } + if (client.currentScreen instanceof RingScreen && index > -1) RingPage.selected = index; + if (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)) EmotecraftCompat.handleEmoteSelector(index); } } @@ -304,15 +334,6 @@ public class MidnightInput { else if (FabricLoader.getInstance().isModLoaded("libgui")) LibGuiCompat.handlePress(client.currentScreen); } } - - if (button == GLFW.GLFW_GAMEPAD_BUTTON_B) { - if (client.currentScreen != null && client.currentScreen.getClass() != TitleScreen.class) { - if (!MidnightControlsCompat.handleMenuBack(client, client.currentScreen)) - if (!this.tryGoBack(client.currentScreen)) - client.currentScreen.close(); - return; - } - } } if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) @@ -346,13 +367,16 @@ public class MidnightInput { */ public boolean tryGoBack(@NotNull Screen screen) { var set = ImmutableSet.of("gui.back", "gui.done", "gui.cancel", "gui.toTitle", "gui.toMenu"); + return screen.children().stream().filter(element -> element instanceof PressableWidget) .map(element -> (PressableWidget) element) .filter(element -> element.getMessage() != null && element.getMessage().getContent() != null) .anyMatch(element -> { - if (set.stream().anyMatch(key -> element.getMessage().getContent().toString().equals(key))) { - element.onPress(); - return true; + if (element.getMessage().getContent() instanceof TranslatableTextContent translatableText) { + if (set.stream().anyMatch(key -> translatableText.getKey().equals(key))) { + element.onPress(); + return true; + } } return false; }); @@ -460,6 +484,14 @@ public class MidnightInput { } return; } + } else if (client.currentScreen instanceof StonecutterScreen stonecutterScreen) { + if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) { + // @TODO allow rebinding to left stick + if (absValue >= deadZone) { + stonecutterScreen.mouseScrolled(0.0, 0.0, -(value * 1.5f)); + } + return; + } } else if (client.currentScreen instanceof AdvancementsScreen advancementsScreen) { if (axis == GLFW_GAMEPAD_AXIS_RIGHT_X || axis == GLFW_GAMEPAD_AXIS_RIGHT_Y) { var accessor = (AdvancementsScreenAccessor) advancementsScreen; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EMICompat.java b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EMICompat.java index cf9706f..aadcd29 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EMICompat.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EMICompat.java @@ -1,5 +1,6 @@ package eu.midnightdust.midnightcontrols.client.compat; +import dev.emi.emi.EmiConfig; import dev.emi.emi.screen.EmiScreen; import dev.emi.emi.screen.EmiScreenManager; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; @@ -13,7 +14,7 @@ import org.lwjgl.glfw.GLFW; public class EMICompat implements CompatHandler { public static boolean handleTabs(boolean direction) { - if (MidnightControlsClient.get().input.actionGuiCooldown == 0 &&EmiScreenManager.searchLeft != null && EmiScreenManager.searchRight != null) { + if (isEMIEnabled() && MidnightControlsClient.get().input.actionGuiCooldown == 0 && EmiScreenManager.searchLeft != null && EmiScreenManager.searchRight != null) { if (direction) EmiScreenManager.searchRight.onPress(); else EmiScreenManager.searchLeft.onPress(); MidnightControlsClient.get().input.actionGuiCooldown = 5; @@ -38,4 +39,7 @@ public class EMICompat implements CompatHandler { .filter(((client, buttonBinding) -> client.currentScreen instanceof HandledScreen || client.currentScreen instanceof EmiScreen)) .register(); } + public static boolean isEMIEnabled() { + return EmiConfig.enabled; + } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EmotecraftCompat.java b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EmotecraftCompat.java new file mode 100644 index 0000000..74af0f5 --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EmotecraftCompat.java @@ -0,0 +1,29 @@ +package eu.midnightdust.midnightcontrols.client.compat; + +import eu.midnightdust.midnightcontrols.client.controller.InputManager; +import io.github.kosmx.emotes.arch.gui.screen.ingame.FastChosseScreen; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; + +public class EmotecraftCompat { + public static boolean isEmotecraftScreen(Screen screen) { + return screen instanceof FastChosseScreen; + } + public static void handleEmoteSelector(int index) { + MinecraftClient client = MinecraftClient.getInstance(); + if (client.currentScreen instanceof FastChosseScreen) { + int x = client.getWindow().getWidth() / 2; + int y = client.getWindow().getHeight() / 2; + if (index == 0) InputManager.queueMousePosition(x-200, y-200); + if (index == 1) InputManager.queueMousePosition(x, y-200); + if (index == 2) InputManager.queueMousePosition(x+200, y-200); + if (index == 3) InputManager.queueMousePosition(x-200, y); + if (index == 4) InputManager.queueMousePosition(x+200, y); + if (index == 5) InputManager.queueMousePosition(x-200, y+200); + if (index == 6) InputManager.queueMousePosition(x, y+200); + if (index == 7) InputManager.queueMousePosition(x+200, y+200); + + InputManager.INPUT_MANAGER.updateMousePosition(client); + } + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/InventoryTabsCompat.java b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/InventoryTabsCompat.java new file mode 100644 index 0000000..8dfc285 --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/InventoryTabsCompat.java @@ -0,0 +1,33 @@ +package eu.midnightdust.midnightcontrols.client.compat; + +import com.kqp.inventorytabs.tabs.TabManager; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; +import net.minecraft.client.gui.screen.ingame.HandledScreen; + +public class InventoryTabsCompat { + + public static void handleInventoryTabs(Screen screen, boolean next) { + if (screen instanceof HandledScreen && !(screen instanceof CreativeInventoryScreen)) { + TabManager tabManager = TabManager.getInstance(); + int tabIndex = tabManager.tabs.indexOf(tabManager.currentTab); + if (next) { + if (tabIndex < tabManager.tabs.size() - 1) tabManager.onTabClick(tabManager.tabs.get(tabIndex + 1)); + else tabManager.onTabClick(tabManager.tabs.get(0)); + } else { + if (tabIndex > 0) tabManager.onTabClick(tabManager.tabs.get(tabIndex - 1)); + else tabManager.onTabClick(tabManager.tabs.get(tabManager.tabs.size() - 1)); + } + } + } + public static void handleInventoryPage(Screen screen, boolean next) { + if (screen instanceof HandledScreen && !(screen instanceof CreativeInventoryScreen)) { + TabManager tabManager = TabManager.getInstance(); + if (next) { + if (tabManager.canGoForwardAPage()) tabManager.setCurrentPage(tabManager.currentPage + 1); + } else { + if (tabManager.canGoBackAPage()) tabManager.setCurrentPage(tabManager.currentPage - 1); + } + } + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/MidnightControlsCompat.java b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/MidnightControlsCompat.java index caf70a8..5b8883b 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/MidnightControlsCompat.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/MidnightControlsCompat.java @@ -167,4 +167,20 @@ public class MidnightControlsCompat { public static boolean isEMIPresent() { return FabricLoader.getInstance().isModLoaded("emi"); } + /** + * Returns whether InventoryTabs is present. + * + * @return true if InventoryTabs is present, else false + */ + public static boolean isInventoryTabsPresent() { + return FabricLoader.getInstance().isModLoaded("inventorytabs"); + } + /** + * Returns whether Emotecraft is present. + * + * @return true if Emotecraft is present, else false + */ + public static boolean isEmotecraftPresent() { + return FabricLoader.getInstance().isModLoaded("emotecraft"); + } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java index 9dfe509..17ecacd 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java @@ -10,6 +10,8 @@ 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; @@ -44,6 +46,15 @@ public class ButtonBinding { 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(); @@ -52,6 +63,8 @@ public class ButtonBinding { 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(); @@ -73,7 +86,6 @@ public class ButtonBinding { .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 SMOOTH_CAMERA = new Builder("toggle_smooth_camera").onlyInGame().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).onlyInGame().register(); @@ -83,9 +95,9 @@ public class ButtonBinding { 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().register(); + .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().register(); + .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) @@ -103,6 +115,7 @@ public class ButtonBinding { protected PairPredicate filter; private final List actions = new ArrayList<>(Collections.singletonList(PressAction.DEFAULT_ACTION)); private boolean hasCooldown; + private int cooldownLength = 5; private int cooldown = 0; boolean pressed = false; @@ -114,10 +127,22 @@ public class ButtonBinding { this.actions.addAll(actions); this.hasCooldown = hasCooldown; } + public ButtonBinding(String key, int[] defaultButton, List actions, PairPredicate 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. @@ -234,7 +259,7 @@ public class ButtonBinding { if (state == ButtonState.REPEAT && this.hasCooldown && this.cooldown != 0) return; if (this.hasCooldown && state.isPressed()) { - this.cooldown = 5; + this.cooldown = cooldownLength; } for (int i = this.actions.size() - 1; i >= 0; i--) { if (this.actions.get(i).press(client, this, value, state)) @@ -320,7 +345,6 @@ public class ButtonBinding { PLAYER_LIST.mcKeyBinding = options.playerListKey; RIGHT.mcKeyBinding = options.rightKey; SCREENSHOT.mcKeyBinding = options.screenshotKey; - SMOOTH_CAMERA.mcKeyBinding = options.smoothCameraKey; SNEAK.mcKeyBinding = options.sneakKey; SPRINT.mcKeyBinding = options.sprintKey; SWAP_HANDS.mcKeyBinding = options.swapHandsKey; @@ -385,6 +409,7 @@ public class ButtonBinding { ButtonBinding.USE )); INVENTORY_CATEGORY = InputManager.registerDefaultCategory("key.categories.inventory", category -> category.registerAllBindings( + ButtonBinding.EXIT, ButtonBinding.DROP_ITEM, ButtonBinding.HOTBAR_LEFT, ButtonBinding.HOTBAR_RIGHT, @@ -409,7 +434,8 @@ public class ButtonBinding { ButtonBinding.TOGGLE_PERSPECTIVE, ButtonBinding.PAUSE_GAME, //SMOOTH_CAMERA, - ButtonBinding.DEBUG_SCREEN + ButtonBinding.DEBUG_SCREEN, + ButtonBinding.CONTROLS_RING )); } @@ -438,6 +464,7 @@ public class ButtonBinding { private final List actions = new ArrayList<>(); private PairPredicate filter = Predicates.pairAlwaysTrue(); private boolean cooldown = false; + private int cooldownLength = 5; private ButtonCategory category = null; private KeyBinding mcBinding = null; @@ -540,6 +567,17 @@ public class ButtonBinding { 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}. @@ -579,7 +617,7 @@ public class ButtonBinding { * @return the built {@link ButtonBinding} */ public ButtonBinding build() { - var binding = new ButtonBinding(this.key, this.buttons, this.actions, this.filter, this.cooldown); + 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) diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java index 37aced4..51ab043 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java @@ -9,31 +9,27 @@ package eu.midnightdust.midnightcontrols.client.controller; -import com.google.common.collect.ImmutableSet; import eu.midnightdust.midnightcontrols.client.ButtonState; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightInput; -import eu.midnightdust.midnightcontrols.client.compat.EMICompat; +import eu.midnightdust.midnightcontrols.client.compat.InventoryTabsCompat; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.compat.SodiumCompat; +import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor; import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor; import eu.midnightdust.midnightcontrols.client.mixin.RecipeBookWidgetAccessor; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; import eu.midnightdust.midnightcontrols.client.util.MouseAccessor; -import net.fabricmc.fabric.impl.item.group.CreativeGuiExtensions; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gl.Framebuffer; -import net.minecraft.client.gui.hud.DebugHud; +import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; -import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.client.gui.screen.ingame.*; +import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; import net.minecraft.client.gui.widget.PressableWidget; import net.minecraft.client.util.ScreenshotRecorder; import net.minecraft.item.ItemGroup; -import net.minecraft.item.Items; import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.SlotActionType; import org.aperlambda.lambdacommon.utils.Pair; @@ -67,10 +63,12 @@ public class InputHandlers { // When ingame if (client.currentScreen == null && client.player != null) { if (next) - client.player.getInventory().scrollInHotbar(1.0); - else client.player.getInventory().scrollInHotbar(-1.0); + else + client.player.getInventory().scrollInHotbar(1.0); return true; + } else if (client.currentScreen instanceof RingScreen) { + MidnightControlsClient.get().ring.cyclePage(next); } else if (client.currentScreen instanceof CreativeInventoryScreenAccessor inventory) { int currentTab = CreativeInventoryScreenAccessor.getSelectedTab(); int nextTab = currentTab + (next ? 1 : -1); @@ -80,21 +78,27 @@ public class InputHandlers { nextTab = 0; inventory.midnightcontrols$setSelectedTab(ItemGroup.GROUPS[nextTab]); return true; - } else if (client.currentScreen instanceof InventoryScreen inventoryScreen) { - var recipeBook = (RecipeBookWidgetAccessor) inventoryScreen.getRecipeBookWidget(); - var tabs = recipeBook.getTabButtons(); - var currentTab = recipeBook.getCurrentTab(); - if (currentTab == null) + } else if (client.currentScreen instanceof InventoryScreen || client.currentScreen instanceof CraftingScreen || client.currentScreen instanceof AbstractFurnaceScreen) { + RecipeBookWidget recipeBook; + if (client.currentScreen instanceof InventoryScreen inventoryScreen) recipeBook = inventoryScreen.getRecipeBookWidget(); + else if (client.currentScreen instanceof CraftingScreen craftingScreen) recipeBook = craftingScreen.getRecipeBookWidget(); + else recipeBook = ((AbstractFurnaceScreen)client.currentScreen).getRecipeBookWidget(); + var recipeBookAccessor = (RecipeBookWidgetAccessor) recipeBook; + var tabs = recipeBookAccessor.getTabButtons(); + var currentTab = recipeBookAccessor.getCurrentTab(); + if (currentTab == null || !recipeBook.isOpen()) { + if (MidnightControlsCompat.isInventoryTabsPresent()) InventoryTabsCompat.handleInventoryTabs(client.currentScreen, next); return false; + } int nextTab = tabs.indexOf(currentTab) + (next ? 1 : -1); if (nextTab < 0) nextTab = tabs.size() - 1; else if (nextTab >= tabs.size()) nextTab = 0; currentTab.setToggled(false); - recipeBook.setCurrentTab(currentTab = tabs.get(nextTab)); + recipeBookAccessor.setCurrentTab(currentTab = tabs.get(nextTab)); currentTab.setToggled(true); - recipeBook.midnightcontrols$refreshResults(true); + recipeBookAccessor.midnightcontrols$refreshResults(true); return true; } else if (client.currentScreen instanceof AdvancementsScreenAccessor screen) { var tabs = screen.getTabs().values().stream().distinct().collect(Collectors.toList()); @@ -113,7 +117,10 @@ public class InputHandlers { } } return true; - } else if (FabricLoader.getInstance().isModLoaded("sodium")) SodiumCompat.handleTabs(client.currentScreen, next); + } else { + if (FabricLoader.getInstance().isModLoaded("sodium")) SodiumCompat.handleTabs(client.currentScreen, next); + } + if (MidnightControlsCompat.isInventoryTabsPresent()) InventoryTabsCompat.handleInventoryTabs(client.currentScreen, next); return false; }; } @@ -147,6 +154,18 @@ public class InputHandlers { } } catch (Exception ignored) {} } + if (MidnightControlsCompat.isInventoryTabsPresent()) InventoryTabsCompat.handleInventoryPage(client.currentScreen, next); + return false; + }; + } + public static PressAction handleExit() { + return (client, button, value, action) -> { + if (client.currentScreen != null && client.currentScreen.getClass() != TitleScreen.class) { + if (!MidnightControlsCompat.handleMenuBack(client, client.currentScreen)) + if (!MidnightControlsClient.get().input.tryGoBack(client.currentScreen)) + client.currentScreen.close(); + return true; + } return false; }; } @@ -205,7 +224,7 @@ public class InputHandlers { public static boolean handlePauseGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding, float value, @NotNull ButtonState action) { if (action == ButtonState.PRESS) { // If in game, then pause the game. - if (client.currentScreen == null) + if (client.currentScreen == null || client.currentScreen instanceof RingScreen) client.openPauseMenu(false); else if (client.currentScreen instanceof HandledScreen && client.player != null) // If the current screen is a container then close it. client.player.closeHandledScreen(); @@ -328,7 +347,7 @@ public class InputHandlers { * @return true if the client is in game, else false */ public static boolean inGame(@NotNull MinecraftClient client, @NotNull ButtonBinding binding) { - return client.currentScreen == null && MidnightControlsClient.get().input.screenCloseCooldown <= 0; + return (client.currentScreen == null && MidnightControlsClient.get().input.screenCloseCooldown <= 0) || client.currentScreen instanceof RingScreen; } /** diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java index 0acfbbc..3288f2b 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java @@ -17,6 +17,7 @@ import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.client.MinecraftClient; import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.resource.language.I18n; import net.minecraft.client.util.InputUtil; import net.minecraft.util.math.MathHelper; import org.aperlambda.lambdacommon.Identifier; @@ -128,6 +129,29 @@ public class InputManager { public static boolean hasBinding(@NotNull Identifier identifier) { return hasBinding(identifier.getNamespace() + "." + identifier.getName()); } + private static ButtonBinding tempBinding; + /** + * Returns the binding matching the given string. + * + * @param name the name of the binding to get + * @return true if the binding is registered, else false + */ + public static ButtonBinding getBinding(@NotNull String name) { + if (BINDINGS.parallelStream().map(ButtonBinding::getName).anyMatch(binding -> binding.equalsIgnoreCase(name))) + BINDINGS.forEach(binding -> { + if (binding.getName().equalsIgnoreCase(name)) InputManager.tempBinding = binding; + }); + return tempBinding; + } + private static List unboundBindings; + public static List getUnboundBindings() { + unboundBindings = new ArrayList<>(); + BINDINGS.forEach(binding -> { + if (binding.isNotBound() && !MidnightControlsConfig.ignoredUnboundKeys.contains(binding.getTranslationKey())) unboundBindings.add(binding); + }); + unboundBindings.sort(Comparator.comparing(s -> I18n.translate(s.getTranslationKey()))); + return unboundBindings; + } /** * Registers a button binding. diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java index b7cb104..e4945bd 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java @@ -14,7 +14,6 @@ import eu.midnightdust.midnightcontrols.MidnightControlsConstants; import eu.midnightdust.midnightcontrols.client.HudSide; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; -import eu.midnightdust.midnightcontrols.client.MidnightInput; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import dev.lambdaurora.spruceui.hud.Hud; @@ -72,7 +71,7 @@ public class MidnightControlsHud extends Hud { this.dropItemButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.DROP_ITEM); this.attackButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.ATTACK); this.useButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.USE); - if (client.options.getGuiScale().getValue() >= 4) { + if (client.getWindow().getScaleFactor() >= 4) { scale = 0.75f; } else scale = 1f; } @@ -119,7 +118,7 @@ public class MidnightControlsHud extends Hud { currentX += -offset; } else { currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x : x - this.dropItemButtonWidth; - y -= 24; + y -= 20; } this.drawButton(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty()); } @@ -136,7 +135,7 @@ public class MidnightControlsHud extends Hud { currentX -= offset; } else { currentX = x; - y -= 24; + y -= 20; } } @@ -155,7 +154,7 @@ public class MidnightControlsHud extends Hud { if (this.client.options.getShowSubtitles().getValue() && MidnightControlsConfig.hudSide == HudSide.RIGHT) { currentX += -this.dropItemWidth - 2 - this.dropItemButtonWidth - 4; } else { - y -= 24; + y -= 20; currentX = MidnightControlsConfig.hudSide == HudSide.LEFT ? x + this.dropItemButtonWidth + 2 : x - this.dropItemButtonWidth - 2 - this.dropItemWidth; } this.drawTip(matrices, currentX, y, ButtonBinding.DROP_ITEM, !this.client.player.getMainHandStack().isEmpty()); @@ -173,7 +172,7 @@ public class MidnightControlsHud extends Hud { currentX -= 4; } else { currentX = x; - y -= 24; + y -= 20; } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/RingScreen.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/RingScreen.java index 5491e58..6ca31ed 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/RingScreen.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/RingScreen.java @@ -10,8 +10,11 @@ package eu.midnightdust.midnightcontrols.client.gui; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; +import eu.midnightdust.midnightcontrols.client.ring.MidnightRing; +import eu.midnightdust.midnightcontrols.client.ring.RingButtonMode; import eu.midnightdust.midnightcontrols.client.ring.RingPage; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.Text; @@ -30,6 +33,15 @@ public class RingScreen extends Screen { this.mod = MidnightControlsClient.get(); } + @Override + protected void init() { + super.init(); + if (mod.ring.getMaxPages() > 1) { + this.addDrawableChild(new ButtonWidget(5, 5, 20, 20, Text.of("◀"), button -> this.mod.ring.cyclePage(false))); + this.addDrawableChild(new ButtonWidget(width - 25, 5, 20, 20, Text.of("▶"), button -> this.mod.ring.cyclePage(true))); + } + } + @Override public boolean shouldPause() { return false; @@ -40,13 +52,36 @@ public class RingScreen extends Screen { super.render(matrices, mouseX, mouseY, delta); RingPage page = this.mod.ring.getCurrentPage(); - page.render(matrices, this.textRenderer, this.width, this.height, mouseX, mouseY, delta); } + @Override + public void close() { + super.close(); + assert client != null; + client.currentScreen = null; + RingPage page = this.mod.ring.getCurrentPage(); + if (RingPage.selected >= 0 && page.actions[RingPage.selected] != null) + page.actions[RingPage.selected].activate(RingButtonMode.PRESS); + RingPage.selected = -1; + this.removed(); + } + @Override + public boolean changeFocus(boolean lookForwards) { + if (lookForwards) { + if (RingPage.selected < 7) ++RingPage.selected; + else RingPage.selected = -1; + } + else { + if (RingPage.selected > -1) --RingPage.selected; + else RingPage.selected = 7; + } + return true; + } + @Override public boolean mouseReleased(double mouseX, double mouseY, int button) { - if (mod.ring.getCurrentPage().onClick(client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight(), (int) mouseX, (int) mouseY)) { + if (mod.ring.getCurrentPage().onClick(width, height, (int) mouseX, (int) mouseY)) { this.close(); return true; } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/HandledScreenMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/HandledScreenMixin.java index 8a034ff..29d1337 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/HandledScreenMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/HandledScreenMixin.java @@ -12,6 +12,7 @@ package eu.midnightdust.midnightcontrols.client.mixin; import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightInput; +import eu.midnightdust.midnightcontrols.client.compat.EMICompat; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsRenderer; @@ -59,13 +60,13 @@ public abstract class HandledScreenMixin implements HandledScreenAccessor { public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) { if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) { var client = MinecraftClient.getInstance(); - if (client.options.getGuiScale().getValue() >= 4) { + if (client.getWindow().getScaleFactor() >= 4) { scale = 0.75f; } else scale = 1f; matrices.push(); if (scale != 1f) matrices.scale(scale,scale,scale); int x = 2, y = (int) (client.getWindow().getScaledHeight() * (1 / scale) - 2 - MidnightControlsRenderer.ICON_SIZE); - if (MidnightControlsCompat.isEMIPresent()) { + if (MidnightControlsCompat.isEMIPresent() && EMICompat.isEMIEnabled()) { x += 40 * (1 / scale); } x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_A}, "midnightcontrols.action.pickup_all", true, client) + 2; @@ -74,7 +75,7 @@ public abstract class HandledScreenMixin implements HandledScreenAccessor { x = 2; y -= 24; } - if (MidnightControlsCompat.isEMIPresent()) { + if (MidnightControlsCompat.isEMIPresent() && EMICompat.isEMIEnabled()) { x = (int) (client.getWindow().getScaledWidth() * (1 / scale) - 55 - client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.pickup")) * (1 / scale) - client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.quick_move")) - MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.TAKE) - MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.QUICK_MOVE)); diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java index 068d199..666ff58 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java @@ -100,37 +100,19 @@ public abstract class MinecraftClientMixin { this.midnightcontrols$lastTargetSide = side; } // Removed front placing sprinting as way too cheaty. - else if (this.player.isSprinting()) { - hitResult = MidnightControlsClient.get().reacharound.getLastReacharoundResult(); - if (hitResult != null) { - if (cooldown > 0) - this.itemUseCooldown = 0; - } - } +// else if (this.player.isSprinting()) { +// hitResult = MidnightControlsClient.get().reacharound.getLastReacharoundResult(); +// if (hitResult != null) { +// if (cooldown > 0) +// this.itemUseCooldown = 0; +// } +// } this.midnightcontrols$lastPos = this.player.getPos(); } - // Applied multiple times for smooth camera turning even on low FPS - @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;startTick()V", shift = At.Shift.BEFORE)) - private void onPrePreRender(CallbackInfo ci) { - MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this)); - } - @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Recorder;startTick()V", shift = At.Shift.AFTER)) - private void onPreRender(CallbackInfo ci) { - MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this)); - } @Inject(method = "render", at = @At("HEAD")) private void onRender(CallbackInfo ci) { MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this)); } - @Inject(method = "render", at = @At("TAIL")) - private void onPostRender(CallbackInfo ci) { - MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this)); - } - @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;endTick()V", shift = At.Shift.AFTER)) - private void onPostPostRender(CallbackInfo ci) { - MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this)); - } - @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V", shift = At.Shift.AFTER)) private void renderVirtualCursor(boolean fullRender, CallbackInfo ci) { MidnightControlsRenderer.renderVirtualCursor(new MatrixStack(), (MinecraftClient) (Object) this); diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/WorldRendererMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/WorldRendererMixin.java index 0f262e1..b8e5cfc 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/WorldRendererMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/WorldRendererMixin.java @@ -9,6 +9,8 @@ package eu.midnightdust.midnightcontrols.client.mixin; +import com.mojang.blaze3d.systems.RenderSystem; +import eu.midnightdust.lib.util.MidnightColorUtil; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import net.minecraft.block.ShapeContext; @@ -30,6 +32,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.awt.*; + /** * Represents a mixin to WorldRenderer. *

@@ -49,7 +53,7 @@ public abstract class WorldRendererMixin { private BufferBuilderStorage bufferBuilders; @Shadow - private static void drawShapeOutline(MatrixStack matrixStack, VertexConsumer vertexConsumer, VoxelShape voxelShape, double d, double e, double f, float g, float h, float i, float j) { + public static void drawShapeOutline(MatrixStack matrixStack, VertexConsumer vertexConsumer, VoxelShape voxelShape, double d, double e, double f, float g, float h, float i, float j) { } @Inject( @@ -86,12 +90,20 @@ public abstract class WorldRendererMixin { var pos = camera.getPos(); var outlineShape = placementState.getOutlineShape(this.client.world, blockPos, ShapeContext.of(camera.getFocusedEntity())); - int[] color = MidnightControlsConfig.reacharoundOutlineColor; + Color rgb = MidnightColorUtil.hex2Rgb(MidnightControlsConfig.reacharoundOutlineColorHex); + if (MidnightControlsConfig.reacharoundOutlineColorHex.isEmpty()) rgb = MidnightColorUtil.radialRainbow(1,1); - var vertexConsumer = this.bufferBuilders.getEntityVertexConsumers().getBuffer(RenderLayer.getLines()); + RenderSystem.defaultBlendFunc(); + RenderSystem.disableTexture(); + RenderSystem.disableBlend(); + RenderSystem.setShader(GameRenderer::getPositionColorShader); + RenderSystem.setShaderColor(rgb.getRed(), rgb.getGreen(), rgb.getBlue(), MidnightControlsConfig.reacharoundOutlineColorAlpha); + matrices.push(); + var vertexConsumer = this.bufferBuilders.getOutlineVertexConsumers().getBuffer(RenderLayer.getLines()); drawShapeOutline(matrices, vertexConsumer, outlineShape, (double) blockPos.getX() - pos.getX(), (double) blockPos.getY() - pos.getY(), (double) blockPos.getZ() - pos.getZ(), - color[0] / 255.f, color[1] / 255.f, color[2] / 255.f, color[3] / 255.f); + rgb.getRed() / 255.f, rgb.getGreen() / 255.f, rgb.getBlue() / 255.f, MidnightControlsConfig.reacharoundOutlineColorAlpha / 255.f); + matrices.pop(); } } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/KeyBindingRingAction.java b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/ButtonBindingRingAction.java similarity index 55% rename from src/main/java/eu/midnightdust/midnightcontrols/client/ring/KeyBindingRingAction.java rename to src/main/java/eu/midnightdust/midnightcontrols/client/ring/ButtonBindingRingAction.java index cf34e18..fd1baaf 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/KeyBindingRingAction.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/ButtonBindingRingAction.java @@ -10,23 +10,29 @@ package eu.midnightdust.midnightcontrols.client.ring; import com.electronwill.nightconfig.core.Config; +import eu.midnightdust.midnightcontrols.client.ButtonState; +import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.util.KeyBindingAccessor; +import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.option.StickyKeyBinding; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.OrderedText; import net.minecraft.text.Text; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.function.Supplier; -public class KeyBindingRingAction extends RingAction { +public class ButtonBindingRingAction extends RingAction { public static final Factory FACTORY = new Factory(); - public final KeyBinding binding; + public final ButtonBinding binding; - public KeyBindingRingAction(@NotNull Config config, @NotNull KeyBinding binding) { - super(config); + public ButtonBindingRingAction(@NotNull ButtonBinding binding) { + super(); this.binding = binding; } @@ -37,19 +43,19 @@ public class KeyBindingRingAction extends RingAction { @Override public void onAction(@NotNull RingButtonMode mode) { - KeyBindingAccessor accessor = (KeyBindingAccessor) this.binding; - switch (mode) { - case PRESS, HOLD -> accessor.midnightcontrols$handlePressState(this.activated); - case TOGGLE -> { - accessor.midnightcontrols$handlePressState(!this.binding.isPressed()); - this.activated = !this.binding.isPressed(); - } + binding.handle(MinecraftClient.getInstance(), 1.0f, ButtonState.PRESS); + if (binding.asKeyBinding().isPresent()) { + binding.asKeyBinding().get().setPressed(true); + ((KeyBindingAccessor)binding.asKeyBinding().get()).midnightcontrols$press(); } } @Override public void drawIcon(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) { - drawCenteredText(matrices, textRenderer, Text.translatable(this.getName()), x + 25, y + 25 - textRenderer.fontHeight / 2, 0xffffff); + List lines = textRenderer.wrapLines(Text.translatable(this.getName()), MidnightRing.ELEMENT_SIZE); + for (int i = 0; i < lines.size(); ++i) { + drawCenteredTextWithShadow(matrices, textRenderer, lines.get(i), x + MidnightRing.ELEMENT_SIZE / 2, y + MidnightRing.ELEMENT_SIZE / 2 - textRenderer.fontHeight / 2 * (lines.size()-1) - textRenderer.fontHeight / 2 + textRenderer.fontHeight * i, 0xffffff); + } } protected static class Factory implements RingAction.Factory { diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/DummyRingAction.java b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/DummyRingAction.java deleted file mode 100644 index feb4f6d..0000000 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/DummyRingAction.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright © 2021 LambdAurora - * - * This file is part of midnightcontrols. - * - * Licensed under the MIT license. For more information, - * see the LICENSE file. - */ - -package eu.midnightdust.midnightcontrols.client.ring; - -import com.electronwill.nightconfig.core.Config; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.util.math.MatrixStack; -import org.jetbrains.annotations.NotNull; - -public class DummyRingAction extends RingAction { - public DummyRingAction(@NotNull Config config) { - super(config); - } - - @Override - public @NotNull String getName() { - return "dummy"; - } - - @Override - public void onAction(@NotNull RingButtonMode mode) { - - } - - @Override - public void drawIcon(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) { - drawCenteredText(matrices, textRenderer, this.getName(), x + 25, y + 25 - textRenderer.fontHeight / 2, 0xffffff); - } -} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/MidnightRing.java b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/MidnightRing.java index 48b4057..fcd9b7c 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/MidnightRing.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/MidnightRing.java @@ -9,10 +9,12 @@ package eu.midnightdust.midnightcontrols.client.ring; -import com.electronwill.nightconfig.core.Config; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; +import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; +import eu.midnightdust.midnightcontrols.client.controller.InputManager; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.util.math.MathHelper; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -28,7 +30,7 @@ import java.util.Map; * @since 1.4.0 */ public final class MidnightRing { - public static final int ELEMENT_SIZE = 50; + public static final int ELEMENT_SIZE = 75; private final Map actionFactories = new Object2ObjectOpenHashMap<>(); private final List pages = new ArrayList<>(Collections.singletonList(RingPage.DEFAULT)); @@ -41,7 +43,7 @@ public final class MidnightRing { public void registerAction(@NotNull String name, @NotNull RingAction.Factory factory) { if (this.actionFactories.containsKey(name)) { - this.mod.warn("Tried to register twice a ring action: \"" + name + "\"."); + this.mod.warn("Tried to register a ring action twice: \"" + name + "\"."); return; } this.actionFactories.put(name, factory); @@ -50,18 +52,55 @@ public final class MidnightRing { /** * Loads the ring from configuration. */ - public void load() { - List configPages = null; - if (configPages != null) { + public void loadFromConfig() { + List configBindings = MidnightControlsConfig.ringBindings; + if (configBindings != null) { this.pages.clear(); - for (var configPage : configPages) { - RingPage.parseRingPage(configPage).ifPresent(this.pages::add); + int bindingIndex = 0; + for (int i = 0; i < MathHelper.ceil(configBindings.size() / 8f); ++i) { + this.pages.add(new RingPage(i+1 + " / " + MathHelper.ceil(configBindings.size() / 8f))); + } + + for (String binding : configBindings) { + ButtonBinding buttonBinding = InputManager.getBinding(binding); + if (buttonBinding != null) { + RingPage page = this.pages.get(MathHelper.fastFloor(bindingIndex / 8f)); + page.actions[bindingIndex - 8 * (MathHelper.fastFloor(bindingIndex / 8f))] = (new ButtonBindingRingAction(buttonBinding)); + ++bindingIndex; + } } } if (this.pages.isEmpty()) { this.pages.add(RingPage.DEFAULT); } } + /** + * Loads the ring from all unbound keys. + */ + public void loadFromUnbound() { + List unboundBindings = InputManager.getUnboundBindings(); + if (unboundBindings != null) { + this.pages.clear(); + int bindingIndex = 0; + for (int i = 0; i < MathHelper.ceil(unboundBindings.size() / 8f); ++i) { + this.pages.add(new RingPage(i+1 + " / " + MathHelper.ceil(unboundBindings.size() / 8f))); + } + + for (ButtonBinding buttonBinding : unboundBindings) { + if (buttonBinding != null) { + RingPage page = this.pages.get(MathHelper.fastFloor(bindingIndex / 8f)); + page.actions[bindingIndex - 8 * (MathHelper.fastFloor(bindingIndex / 8f))] = (new ButtonBindingRingAction(buttonBinding)); + ++bindingIndex; + } + } + } + if (this.pages.isEmpty()) { + this.pages.add(RingPage.DEFAULT); + } + } + public int getMaxPages() { + return this.pages.size(); + } public @NotNull RingPage getCurrentPage() { if (this.currentPage >= this.pages.size()) @@ -70,4 +109,13 @@ public final class MidnightRing { this.currentPage = 0; return this.pages.get(this.currentPage); } + public void cyclePage(boolean forwards) { + if (forwards) { + if (currentPage < pages.size()-1) ++currentPage; + else currentPage = 0; + } else { + if (currentPage > 0) --currentPage; + else currentPage = pages.size(); + } + } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/RingAction.java b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/RingAction.java index 1062b26..f5a9bc8 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/RingAction.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/RingAction.java @@ -29,11 +29,9 @@ import java.util.function.Supplier; * @since 1.4.0 */ public abstract class RingAction extends DrawableHelper implements Nameable { - protected Config config; protected boolean activated = false; - public RingAction(@NotNull Config config) { - this.config = config; + public RingAction() { } /** @@ -62,8 +60,8 @@ public abstract class RingAction extends DrawableHelper implements Nameable { public abstract void onAction(@NotNull RingButtonMode mode); - public void render(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered) { - fill(matrices, x, y, x + MidnightRing.ELEMENT_SIZE, y + MidnightRing.ELEMENT_SIZE, hovered ? 0xbb777777 : 0xbb000000); + public void render(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int x, int y, boolean hovered, int index) { + fill(matrices, x, y, x + MidnightRing.ELEMENT_SIZE, y + MidnightRing.ELEMENT_SIZE, hovered || RingPage.selected == index ? 0xbb777777 : 0xbb000000); drawIcon(matrices, textRenderer, x, y, hovered); } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/RingPage.java b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/RingPage.java index 91ddba8..75f9698 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/ring/RingPage.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/ring/RingPage.java @@ -11,6 +11,8 @@ package eu.midnightdust.midnightcontrols.client.ring; import com.electronwill.nightconfig.core.Config; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; +import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; +import eu.midnightdust.midnightcontrols.client.controller.InputManager; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawableHelper; @@ -33,18 +35,14 @@ public class RingPage extends DrawableHelper { public static final RingPage DEFAULT = new RingPage("Default"); public final String name; - private RingAction[] actions = new RingAction[8]; + public static int selected = -1; + public RingAction[] actions = new RingAction[8]; public RingPage(@NotNull String name) { this.name = name; for (int i = 0; i < 8; i++) { this.actions[i] = null; } - this.actions[0] = new DummyRingAction(null); - this.actions[1] = new KeyBindingRingAction(null, MidnightControlsClient.BINDING_LOOK_UP); - this.actions[2] = new KeyBindingRingAction(null, MidnightControlsClient.BINDING_LOOK_LEFT); - this.actions[3] = new KeyBindingRingAction(null, MidnightControlsClient.BINDING_LOOK_RIGHT); - this.actions[4] = new KeyBindingRingAction(null, MidnightControlsClient.BINDING_LOOK_DOWN); } /** @@ -60,6 +58,7 @@ public class RingPage extends DrawableHelper { public void render(@NotNull MatrixStack matrices, @NotNull TextRenderer textRenderer, int width, int height, int mouseX, int mouseY, float tickDelta) { int centerX = width / 2; int centerY = height / 2; + if (MidnightControlsClient.get().ring.getMaxPages() > 1) drawCenteredText(matrices, textRenderer, name, centerX, 5, 0xffffff); int offset = MidnightRing.ELEMENT_SIZE + (MidnightRing.ELEMENT_SIZE / 2) + 5; @@ -68,29 +67,29 @@ public class RingPage extends DrawableHelper { for (int i = 0; i < 3; i++) { var ringAction = this.actions[i]; if (ringAction != null) - ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY)); - x += 55; + ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i); + x += MidnightRing.ELEMENT_SIZE + 5; } - y += 55; + y += MidnightRing.ELEMENT_SIZE + 5; x = centerX - offset; for (int i = 3; i < 5; i++) { var ringAction = this.actions[i]; if (ringAction != null) - ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY)); - x += 55 * 2; + ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i); + x += (MidnightRing.ELEMENT_SIZE + 5) * 2; } - y += 55; + y += MidnightRing.ELEMENT_SIZE + 5; x = centerX - offset; for (int i = 5; i < 8; i++) { var ringAction = this.actions[i]; if (ringAction != null) - ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY)); - x += 55; + ringAction.render(matrices, textRenderer, x, y, isHovered(x, y, mouseX, mouseY), i); + x += MidnightRing.ELEMENT_SIZE + 5; } } private static boolean isHovered(int x, int y, int mouseX, int mouseY) { - return mouseX >= x && mouseY >= y && mouseX <= x + MidnightRing.ELEMENT_SIZE && mouseY <= y + MidnightRing.ELEMENT_SIZE; + return mouseX >= x && mouseY >= y && mouseX <= x + MidnightRing.ELEMENT_SIZE && mouseY <= y + MidnightRing.ELEMENT_SIZE && selected < 0; } /** * Renders the ring page. @@ -114,9 +113,9 @@ public class RingPage extends DrawableHelper { ringAction.activate(RingButtonMode.PRESS); return true; } - x += 55; + x += MidnightRing.ELEMENT_SIZE + 5; } - y += 55; + y += MidnightRing.ELEMENT_SIZE + 5; x = centerX - offset; for (int i = 3; i < 5; i++) { var ringAction = this.actions[i]; @@ -124,9 +123,9 @@ public class RingPage extends DrawableHelper { ringAction.activate(RingButtonMode.PRESS); return true; } - x += 55 * 2; + x += (MidnightRing.ELEMENT_SIZE + 5) * 2; } - y += 55; + y += MidnightRing.ELEMENT_SIZE + 5; x = centerX - offset; for (int i = 5; i < 8; i++) { var ringAction = this.actions[i]; @@ -134,27 +133,8 @@ public class RingPage extends DrawableHelper { ringAction.activate(RingButtonMode.PRESS); return true; } - x += 55; + x += MidnightRing.ELEMENT_SIZE + 5; } return false; } - - /** - * Tries to parse a ring page configuration. - * - * @param config the configuration - * @return an optional ring page - */ - public static @NotNull Optional parseRingPage(@NotNull Config config) { - String name = config.get("name"); - if (name == null) - return Optional.empty(); - - var page = new RingPage(name); - - List actionConfigs = config.get("actions"); - - - return Optional.of(page); - } } diff --git a/src/main/resources/assets/midnightcontrols/lang/en_us.json b/src/main/resources/assets/midnightcontrols/lang/en_us.json index 1e96be5..845f27f 100644 --- a/src/main/resources/assets/midnightcontrols/lang/en_us.json +++ b/src/main/resources/assets/midnightcontrols/lang/en_us.json @@ -8,9 +8,10 @@ "midnightcontrols.action.attack": "Attack", "midnightcontrols.action.back": "Back", "midnightcontrols.action.chat": "Open Chat", + "midnightcontrols.action.controls_ring": "Open Unbound Keybind Ring", "midnightcontrols.action.debug_screen": "Open Debug HUD (F3)", "midnightcontrols.action.drop_item": "Drop Item", - "midnightcontrols.action.exit": "Exit", + "midnightcontrols.action.exit": "Exit Screen", "midnightcontrols.action.forward": "Forward", "midnightcontrols.action.hit": "Hit", "midnightcontrols.action.hotbar_left": "Hotbar left",