From cad2cdb4b28a0b83da5af540cddb50c4931ee50a Mon Sep 17 00:00:00 2001 From: beanbag44 <107891830+beanbag44@users.noreply.github.com> Date: Fri, 9 Jan 2026 11:16:41 +0000 Subject: [PATCH 1/3] move listeners into the bind setting cores themselves to avoid duplicate code / consistency issues --- .../com/lambda/mixin/input/KeyboardMixin.java | 6 +- .../com/lambda/mixin/input/MouseMixin.java | 9 +- .../kotlin/com/lambda/config/Configurable.kt | 9 +- .../config/settings/complex/KeybindSetting.kt | 53 ++++++++- src/main/kotlin/com/lambda/event/EventFlow.kt | 8 +- .../com/lambda/event/events/ButtonEvent.kt | 110 ++++++++++++++++++ .../com/lambda/event/events/KeyboardEvent.kt | 65 ----------- .../com/lambda/event/events/MouseEvent.kt | 62 ---------- src/main/kotlin/com/lambda/gui/MenuBar.kt | 4 +- .../lambda/gui/components/ClickGuiLayout.kt | 19 ++- .../com/lambda/gui/components/QuickSearch.kt | 6 +- src/main/kotlin/com/lambda/module/Module.kt | 27 +---- .../lambda/module/modules/debug/StateInfo.kt | 17 +-- .../module/modules/movement/BetterFirework.kt | 62 ++-------- .../lambda/module/modules/player/AirPlace.kt | 4 +- .../lambda/module/modules/player/AutoArmor.kt | 8 +- .../module/modules/player/ClickFriend.kt | 30 +++-- .../lambda/module/modules/player/Replay.kt | 19 +-- .../lambda/module/modules/player/Scaffold.kt | 4 +- .../lambda/module/modules/render/ViewModel.kt | 7 +- .../com/lambda/module/modules/render/Zoom.kt | 4 +- src/main/kotlin/com/lambda/util/InputUtils.kt | 15 +-- 22 files changed, 244 insertions(+), 304 deletions(-) create mode 100644 src/main/kotlin/com/lambda/event/events/ButtonEvent.kt delete mode 100644 src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt delete mode 100644 src/main/kotlin/com/lambda/event/events/MouseEvent.kt diff --git a/src/main/java/com/lambda/mixin/input/KeyboardMixin.java b/src/main/java/com/lambda/mixin/input/KeyboardMixin.java index 027a3edea..8e913469d 100644 --- a/src/main/java/com/lambda/mixin/input/KeyboardMixin.java +++ b/src/main/java/com/lambda/mixin/input/KeyboardMixin.java @@ -18,7 +18,7 @@ package com.lambda.mixin.input; import com.lambda.event.EventFlow; -import com.lambda.event.events.KeyboardEvent; +import com.lambda.event.events.ButtonEvent; import com.lambda.module.modules.player.InventoryMove; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; @@ -43,7 +43,7 @@ public class KeyboardMixin { @WrapMethod(method = "onKey") private void onKey(long window, int action, KeyInput input, Operation original) { - EventFlow.post(new KeyboardEvent.Press(input.key(), input.scancode(), action, input.modifiers())); + EventFlow.post(new ButtonEvent.Keyboard.Press(input.key(), input.scancode(), action, input.modifiers())); original.call(window, action, input); } @@ -60,7 +60,7 @@ private void onChar(long window, CharInput input, Operation original) { char[] chars = Character.toChars(input.codepoint()); for (char c : chars) - EventFlow.post(new KeyboardEvent.Char(c)); + EventFlow.post(new ButtonEvent.Keyboard.Char(c)); original.call(window, input); } diff --git a/src/main/java/com/lambda/mixin/input/MouseMixin.java b/src/main/java/com/lambda/mixin/input/MouseMixin.java index f025bc838..c78c2aa73 100644 --- a/src/main/java/com/lambda/mixin/input/MouseMixin.java +++ b/src/main/java/com/lambda/mixin/input/MouseMixin.java @@ -18,7 +18,7 @@ package com.lambda.mixin.input; import com.lambda.event.EventFlow; -import com.lambda.event.events.MouseEvent; +import com.lambda.event.events.ButtonEvent; import com.lambda.module.modules.render.Zoom; import com.lambda.util.math.Vec2d; import com.llamalad7.mixinextras.injector.ModifyExpressionValue; @@ -26,7 +26,6 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import net.minecraft.client.Mouse; import net.minecraft.client.input.MouseInput; -import net.minecraft.client.option.SimpleOption; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -39,7 +38,7 @@ public class MouseMixin { @WrapMethod(method = "onMouseButton") private void onMouseButton(long window, MouseInput input, int action, Operation original) { - if (!EventFlow.post(new MouseEvent.Click(input.button(), action, input.modifiers())).isCanceled()) + if (!EventFlow.post(new ButtonEvent.Mouse.Click(input.button(), action, input.modifiers())).isCanceled()) original.call(window, input, action); } @@ -47,7 +46,7 @@ private void onMouseButton(long window, MouseInput input, int action, Operation< private void onMouseScroll(long window, double horizontal, double vertical, Operation original) { Vec2d delta = new Vec2d(horizontal, vertical); - if (!EventFlow.post(new MouseEvent.Scroll(delta)).isCanceled()) + if (!EventFlow.post(new ButtonEvent.Mouse.Scroll(delta)).isCanceled()) original.call(window, horizontal, vertical); } @@ -57,7 +56,7 @@ private void onCursorPos(long window, double x, double y, Operation origin Vec2d position = new Vec2d(x, y); - if (!EventFlow.post(new MouseEvent.Move(position)).isCanceled()) + if (!EventFlow.post(new ButtonEvent.Mouse.Move(position)).isCanceled()) original.call(window, x, y); } diff --git a/src/main/kotlin/com/lambda/config/Configurable.kt b/src/main/kotlin/com/lambda/config/Configurable.kt index e044162c8..fce94e2a2 100644 --- a/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/src/main/kotlin/com/lambda/config/Configurable.kt @@ -42,6 +42,7 @@ import com.lambda.config.settings.numeric.DoubleSetting import com.lambda.config.settings.numeric.FloatSetting import com.lambda.config.settings.numeric.IntegerSetting import com.lambda.config.settings.numeric.LongSetting +import com.lambda.event.Muteable import com.lambda.util.Communication.logError import com.lambda.util.KeyCode import com.lambda.util.Nameable @@ -228,15 +229,19 @@ abstract class Configurable( name: String, defaultValue: Bind, description: String = "", + alwaysListen: Boolean = false, + screenCheck: Boolean = true, visibility: () -> Boolean = { true }, - ) = Setting(name, description, KeybindSetting(defaultValue), this, visibility).register() + ) = Setting(name, description, KeybindSetting(defaultValue, this as? Muteable, alwaysListen, screenCheck), this, visibility).register() fun setting( name: String, defaultValue: KeyCode, description: String = "", + alwaysListen: Boolean = false, + screenCheck: Boolean = true, visibility: () -> Boolean = { true }, - ) = Setting(name, description, KeybindSetting(defaultValue), this, visibility).register() + ) = Setting(name, description, KeybindSetting(defaultValue, this as? Muteable, alwaysListen, screenCheck), this, visibility).register() fun setting( name: String, diff --git a/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt b/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt index 0d31ee129..dd5e9663e 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt @@ -28,6 +28,10 @@ import com.lambda.brigadier.optional import com.lambda.brigadier.required import com.lambda.config.Setting import com.lambda.config.SettingCore +import com.lambda.context.SafeContext +import com.lambda.event.Muteable +import com.lambda.event.events.ButtonEvent +import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.gui.dsl.ImGuiBuilder import com.lambda.util.InputUtils import com.lambda.util.KeyCode @@ -48,14 +52,43 @@ import org.lwjgl.glfw.GLFW.GLFW_MOD_NUM_LOCK import org.lwjgl.glfw.GLFW.GLFW_MOD_SHIFT import org.lwjgl.glfw.GLFW.GLFW_MOD_SUPER -class KeybindSetting(defaultValue: Bind) : SettingCore( +class KeybindSetting( + defaultValue: Bind, + private val muteable: Muteable?, + private val alwaysListening: Boolean, + private val screenCheck: Boolean +) : SettingCore( defaultValue, TypeToken.get(Bind::class.java).type -) { - constructor(defaultValue: KeyCode) : this(Bind(defaultValue.code, 0, -1)) +), Muteable { + constructor(defaultValue: KeyCode, muteable: Muteable?, alwaysListen: Boolean, screenCheck: Boolean) + : this(Bind(defaultValue.code, 0, -1), muteable, alwaysListen, screenCheck) + + private val pressListeners = mutableListOf Unit>() + private val repeatListeners = mutableListOf Unit>() + private val releaseListeners = mutableListOf Unit>() private var listening = false + override val isMuted + get() = muteable?.isMuted == true && !alwaysListening + + init { + listen { event -> onButtonEvent(event) } + listen { event -> onButtonEvent(event) } + } + + private fun SafeContext.onButtonEvent(event: ButtonEvent) { + if (mc.options.commandKey.isPressed || + (screenCheck && mc.currentScreen != null) || + !event.satisfies(value)) return + + if (event.isPressed) { + if (event.isRepeated) repeatListeners.forEach { it(event) } + else pressListeners.forEach { it(event) } + } else if (event.isReleased) releaseListeners.forEach { it(event) } + } + context(setting: Setting<*, Bind>) override fun ImGuiBuilder.buildLayout() { text(setting.name) @@ -161,6 +194,20 @@ class KeybindSetting(defaultValue: Bind) : SettingCore( } } } + + companion object { + fun Setting.onPress(block: SafeContext.(ButtonEvent) -> Unit) = apply { + core.pressListeners.add(block) + } + + fun Setting.onRepeat(block: SafeContext.(ButtonEvent) -> Unit) = apply { + core.repeatListeners.add(block) + } + + fun Setting.onRelease(block: SafeContext.(ButtonEvent) -> Unit) = apply { + core.releaseListeners.add(block) + } + } } data class Bind( diff --git a/src/main/kotlin/com/lambda/event/EventFlow.kt b/src/main/kotlin/com/lambda/event/EventFlow.kt index 5fbdabbcd..ef18705cd 100644 --- a/src/main/kotlin/com/lambda/event/EventFlow.kt +++ b/src/main/kotlin/com/lambda/event/EventFlow.kt @@ -290,8 +290,8 @@ object EventFlow { * @return `true` if the listener should not be notified, `false` otherwise. */ private fun shouldNotNotify(listener: Listener, event: Event) = - listener.owner is Muteable - && (listener.owner as Muteable).isMuted - && !listener.alwaysListen - || event is ICancellable && event.isCanceled() + (listener.owner is Muteable && + (listener.owner as Muteable).isMuted && + !listener.alwaysListen) || + (event is ICancellable && event.isCanceled()) } diff --git a/src/main/kotlin/com/lambda/event/events/ButtonEvent.kt b/src/main/kotlin/com/lambda/event/events/ButtonEvent.kt new file mode 100644 index 000000000..034de460c --- /dev/null +++ b/src/main/kotlin/com/lambda/event/events/ButtonEvent.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2026 Lambda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lambda.event.events + +import com.lambda.config.settings.complex.Bind +import com.lambda.event.Event +import com.lambda.event.callback.Cancellable +import com.lambda.event.callback.ICancellable +import com.lambda.util.KeyCode +import com.lambda.util.math.Vec2d +import org.lwjgl.glfw.GLFW.GLFW_PRESS +import org.lwjgl.glfw.GLFW.GLFW_RELEASE +import org.lwjgl.glfw.GLFW.GLFW_REPEAT + +sealed class ButtonEvent : ICancellable by Cancellable() { + abstract val action: Int + abstract val modifiers: Int + + val isPressed get() = action >= GLFW_PRESS + val isReleased get() = action == GLFW_RELEASE + val isRepeated get() = action == GLFW_REPEAT + + abstract fun satisfies(bind: Bind): Boolean + + sealed class Mouse { + /** + * Represents a mouse click event + * + * @property button The button that was clicked + * @property action The action performed (e.g., press or release) + * @property modifiers An integer representing any modifiers (e.g., shift or ctrl) active during the event + */ + data class Click( + val button: Int, + override val action: Int, + override val modifiers: Int, + ) : ButtonEvent() { + override fun satisfies(bind: Bind) = bind.modifiers and modifiers == bind.modifiers && bind.mouse == button + } + + /** + * Represents a mouse scroll event + * + * @property delta The amount of scrolling in the x and y directions + */ + data class Scroll( + val delta: Vec2d, + ) : ICancellable by Cancellable() + + /** + * Represents a mouse move event. + * + * @property position The x and y position of the mouse on the screen. + */ + data class Move( + val position: Vec2d, + ) : ICancellable by Cancellable() + } + + sealed class Keyboard { + /** + * Represents a key press + * + * @property keyCode The key code of the key that was pressed + * @property scanCode The scan code of the key that was pressed + * @property action The action that was performed on the key (Pressed, Released) + * @property modifiers The modifiers that were active when the key was pressed + * + * @see About Keyboards + */ + data class Press( + val keyCode: Int, + val scanCode: Int, + override val action: Int, + override val modifiers: Int, + ) : ButtonEvent() { + val bind: Bind + get() = Bind(translated.code, modifiers, -1) + + val translated: KeyCode + get() = KeyCode.virtualMapUS(keyCode, scanCode) + + override fun satisfies(bind: Bind) = bind.key == translated.code && bind.modifiers and modifiers == bind.modifiers + } + + /** + * Represents glfwSetCharCallback events + * + * Keys and characters do not map 1:1. + * A single key press may produce several characters, and a single + * character may require several keys to produce + */ + data class Char(val char: kotlin.Char) : Event + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt b/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt deleted file mode 100644 index d496c3fc0..000000000 --- a/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2025 Lambda - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lambda.event.events - -import com.lambda.config.settings.complex.Bind -import com.lambda.event.Event -import com.lambda.util.KeyCode -import org.lwjgl.glfw.GLFW.GLFW_PRESS -import org.lwjgl.glfw.GLFW.GLFW_RELEASE -import org.lwjgl.glfw.GLFW.GLFW_REPEAT - -sealed class KeyboardEvent { - /** - * Represents a key press - * - * @property keyCode The key code of the key that was pressed - * @property scanCode The scan code of the key that was pressed - * @property action The action that was performed on the key (Pressed, Released) - * @property modifiers The modifiers that were active when the key was pressed - * - * @see About Keyboards - */ - data class Press( - val keyCode: Int, - val scanCode: Int, - val action: Int, - val modifiers: Int, - ) : Event { - val bind: Bind - get() = Bind(translated.code, modifiers, -1) - - val translated: KeyCode - get() = KeyCode.virtualMapUS(keyCode, scanCode) - - val isPressed = action >= GLFW_PRESS - val isReleased = action == GLFW_RELEASE - val isRepeated = action == GLFW_REPEAT - - fun satisfies(bind: Bind) = bind.key == translated.code && bind.modifiers and modifiers == bind.modifiers - } - - /** - * Represents glfwSetCharCallback events - * - * Keys and characters do not map 1:1. - * A single key press may produce several characters, and a single - * character may require several keys to produce - */ - data class Char(val char: kotlin.Char) : Event -} diff --git a/src/main/kotlin/com/lambda/event/events/MouseEvent.kt b/src/main/kotlin/com/lambda/event/events/MouseEvent.kt deleted file mode 100644 index 3fcb9d3f7..000000000 --- a/src/main/kotlin/com/lambda/event/events/MouseEvent.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2025 Lambda - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lambda.event.events - -import com.lambda.config.settings.complex.Bind -import com.lambda.event.callback.Cancellable -import com.lambda.event.callback.ICancellable -import com.lambda.util.math.Vec2d -import net.minecraft.client.input.MouseInput - -sealed class MouseEvent { - /** - * Represents a mouse click event - * - * @property button The button that was clicked - * @property action The action performed (e.g., press or release) - * @property modifiers An integer representing any modifiers (e.g., shift or ctrl) active during the event - */ - data class Click( - val button: Int, - val action: Int, - val modifiers: Int, - ) : ICancellable by Cancellable() { - val isReleased = action == 0 - val isPressed = action == 1 - - fun satisfies(bind: Bind) = bind.modifiers and modifiers == bind.modifiers && bind.mouse == button - } - - /** - * Represents a mouse scroll event - * - * @property delta The amount of scrolling in the x and y directions - */ - data class Scroll( - val delta: Vec2d, - ) : ICancellable by Cancellable() - - /** - * Represents a mouse move event. - * - * @property position The x and y position of the mouse on the screen. - */ - data class Move( - val position: Vec2d, - ) : ICancellable by Cancellable() -} diff --git a/src/main/kotlin/com/lambda/gui/MenuBar.kt b/src/main/kotlin/com/lambda/gui/MenuBar.kt index bfef5ac0f..539f04904 100644 --- a/src/main/kotlin/com/lambda/gui/MenuBar.kt +++ b/src/main/kotlin/com/lambda/gui/MenuBar.kt @@ -52,9 +52,7 @@ import imgui.flag.ImGuiCol import imgui.flag.ImGuiStyleVar import imgui.flag.ImGuiWindowFlags import net.fabricmc.loader.api.FabricLoader -import net.minecraft.client.gui.hud.debug.DebugHudEntries import net.minecraft.client.gui.screen.DebugOptionsScreen -import net.minecraft.command.permission.Permission import net.minecraft.network.packet.c2s.play.ChangeGameModeC2SPacket import net.minecraft.server.command.GameModeCommand import net.minecraft.util.Util @@ -279,7 +277,7 @@ object MenuBar { .filter { it.tag == tag } .forEach { module -> menuItem(module.name, selected = module.isEnabled) { - if (module.isEnabled) module.disable() else module.enable() + module.toggle() } // Optionally, offer a "Settings..." item to focus this module’s details UI. } diff --git a/src/main/kotlin/com/lambda/gui/components/ClickGuiLayout.kt b/src/main/kotlin/com/lambda/gui/components/ClickGuiLayout.kt index 89729a4e3..2ff52d576 100644 --- a/src/main/kotlin/com/lambda/gui/components/ClickGuiLayout.kt +++ b/src/main/kotlin/com/lambda/gui/components/ClickGuiLayout.kt @@ -20,9 +20,9 @@ package com.lambda.gui.components import com.lambda.Lambda.mc import com.lambda.config.Configurable import com.lambda.config.configurations.GuiConfig +import com.lambda.config.settings.complex.KeybindSetting.Companion.onPress import com.lambda.core.Loadable import com.lambda.event.events.GuiEvent -import com.lambda.event.events.KeyboardEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.gui.DearImGui import com.lambda.gui.LambdaScreen @@ -63,7 +63,12 @@ object ClickGuiLayout : Loadable, Configurable(GuiConfig) { override val name = "GUI" var open = false var developerMode = false - val keybind by setting("Keybind", KeyCode.Y) + val keybind by setting("Keybind", KeyCode.Y, screenCheck = false) + .onPress { + if (!open && mc.currentScreen != null) return@onPress + if (DearImGui.io.wantTextInput) return@onPress + toggle() + } private var initialLayoutComplete = false private var frameCount = 0 private var activeDragWindowName: String? = null @@ -343,16 +348,6 @@ object ClickGuiLayout : Loadable, Configurable(GuiConfig) { } } } - - listen(alwaysListen = true) { event -> - if (!event.isPressed) return@listen - if (mc.options.commandKey.isPressed) return@listen - if (!event.satisfies(keybind)) return@listen - if (!open && mc.currentScreen != null) return@listen - if (open && DearImGui.io.wantTextInput) return@listen - - toggle() - } } val Screen?.hasInput: Boolean diff --git a/src/main/kotlin/com/lambda/gui/components/QuickSearch.kt b/src/main/kotlin/com/lambda/gui/components/QuickSearch.kt index f4815152b..a92fb7ca2 100644 --- a/src/main/kotlin/com/lambda/gui/components/QuickSearch.kt +++ b/src/main/kotlin/com/lambda/gui/components/QuickSearch.kt @@ -23,7 +23,7 @@ import com.lambda.command.LambdaCommand import com.lambda.config.Configurable import com.lambda.config.Configuration import com.lambda.config.Setting -import com.lambda.event.events.KeyboardEvent +import com.lambda.event.events.ButtonEvent import com.lambda.event.listener.UnsafeListener.Companion.listenUnsafe import com.lambda.gui.LambdaScreen import com.lambda.gui.Layout @@ -62,7 +62,7 @@ object QuickSearch { ImGuiWindowFlags.NoScrollWithMouse init { - listenUnsafe { event -> + listenUnsafe { event -> if (mc.currentScreen !is LambdaScreen) return@listenUnsafe handleKeyPress(event) } @@ -302,7 +302,7 @@ object QuickSearch { return "$configurableName » $group" } - private fun handleKeyPress(event: KeyboardEvent.Press) { + private fun handleKeyPress(event: ButtonEvent.Keyboard.Press) { if ((!event.isPressed || event.isRepeated) || !(event.keyCode == KeyCode.LeftShift.code || event.keyCode == KeyCode.RightShift.code)) return diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index 2ba08c91b..bf845b341 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -17,7 +17,6 @@ package com.lambda.module -import com.lambda.Lambda import com.lambda.command.LambdaCommand import com.lambda.config.Configurable import com.lambda.config.Configuration @@ -26,12 +25,12 @@ import com.lambda.config.MutableAutomationConfigImpl import com.lambda.config.SettingCore import com.lambda.config.configurations.ModuleConfigs import com.lambda.config.settings.complex.Bind +import com.lambda.config.settings.complex.KeybindSetting.Companion.onPress +import com.lambda.config.settings.complex.KeybindSetting.Companion.onRelease import com.lambda.context.SafeContext import com.lambda.event.Muteable import com.lambda.event.events.ClientEvent import com.lambda.event.events.ConnectionEvent -import com.lambda.event.events.KeyboardEvent -import com.lambda.event.events.MouseEvent import com.lambda.event.listener.Listener import com.lambda.event.listener.SafeListener import com.lambda.event.listener.SafeListener.Companion.listen @@ -122,7 +121,9 @@ abstract class Module( autoDisable: Boolean = false ) : Nameable, Muteable, Configurable(ModuleConfigs), MutableAutomationConfig by MutableAutomationConfigImpl() { private val isEnabledSetting = setting("Enabled", enabledByDefault) { false } - val keybindSetting = setting("Keybind", defaultKeybind) { false } + val keybindSetting = setting("Keybind", defaultKeybind, alwaysListen = true) { false } + .onPress { toggle() } + .onRelease { if (disableOnRelease) disable() } val disableOnReleaseSetting = setting("Disable On Release", false) { false } val drawSetting = setting("Draw", true, "Draws the module in the module list hud element") @@ -137,24 +138,6 @@ abstract class Module( get() = !isEnabled && !alwaysListening init { - listen(alwaysListen = true) { event -> - if (mc.options.commandKey.isPressed - || Lambda.mc.currentScreen != null - || !event.satisfies(keybind)) return@listen - - if (event.isPressed && !event.isRepeated) toggle() - else if (event.isReleased && disableOnRelease) disable() - } - - listen(alwaysListen = true) { event -> - if (mc.options.commandKey.isPressed - || mc.currentScreen != null - || !event.satisfies(keybind)) return@listen - - if (event.isPressed) toggle() - else if (event.isReleased && disableOnRelease) disable() - } - onEnable { LambdaSound.ModuleOn.play() } onDisable { LambdaSound.ModuleOff.play() } diff --git a/src/main/kotlin/com/lambda/module/modules/debug/StateInfo.kt b/src/main/kotlin/com/lambda/module/modules/debug/StateInfo.kt index d835e623b..2ddc49190 100644 --- a/src/main/kotlin/com/lambda/module/modules/debug/StateInfo.kt +++ b/src/main/kotlin/com/lambda/module/modules/debug/StateInfo.kt @@ -17,8 +17,7 @@ package com.lambda.module.modules.debug -import com.lambda.event.events.KeyboardEvent -import com.lambda.event.listener.SafeListener.Companion.listen +import com.lambda.config.settings.complex.KeybindSetting.Companion.onPress import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.util.BlockUtils.blockState @@ -35,6 +34,11 @@ object StateInfo : Module( tag = ModuleTag.DEBUG, ) { private val printBind by setting("Print", KeyCode.Unbound, "The bind used to print the info to chat") + .onPress { + val crosshair = mc.crosshairTarget ?: return@onPress + if (crosshair !is BlockHitResult) return@onPress + info(blockState(crosshair.blockPos).betterToString()) + } val propertyFields = Properties::class.java.declaredFields .filter { Property::class.java.isAssignableFrom(it.type) } @@ -46,15 +50,6 @@ object StateInfo : Module( if (crosshair !is BlockHitResult) return@onEnable info(blockState(crosshair.blockPos).betterToString()) } - - listen { event -> - if (!event.isPressed || - !event.satisfies(printBind)) return@listen - - val crosshair = mc.crosshairTarget ?: return@listen - if (crosshair !is BlockHitResult) return@listen - info(blockState(crosshair.blockPos).betterToString()) - } } private fun BlockState.betterToString(): String { diff --git a/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt b/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt index 99443f902..7661ea406 100644 --- a/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt +++ b/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt @@ -20,9 +20,8 @@ package com.lambda.module.modules.movement import com.lambda.config.AutomationConfig.Companion.setDefaultAutomationConfig import com.lambda.config.applyEdits import com.lambda.config.settings.complex.Bind +import com.lambda.config.settings.complex.KeybindSetting.Companion.onPress import com.lambda.context.SafeContext -import com.lambda.event.events.KeyboardEvent -import com.lambda.event.events.MouseEvent import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.managers.hotbar.HotbarRequest @@ -49,7 +48,14 @@ object BetterFirework : Module( tag = ModuleTag.MOVEMENT, ) { private var activateButton by setting("Activate Key", Bind(0, 0, Mouse.Middle.ordinal), "Button to activate Firework") + .onPress { + if (takeoffState != TakeoffState.None) return@onPress // Prevent using multiple times + // If already gliding use another firework + if (player.canOpenElytra || player.isGliding) takeoffState = TakeoffState.StartFlying + else if (player.canTakeoff) takeoffState = TakeoffState.Jumping + } private var midFlightActivationKey by setting("Mid-Flight Activation Key", Bind(0, 0), "Firework use key for mid flight activation") + .onPress { if (player.isGliding) takeoffState = TakeoffState.StartFlying } private var middleClickCancel by setting("Middle Click Cancel", false, description = "Cancel pick block action on middle mouse click") { activateButton.key != KeyCode.Unbound.code } private var fireworkInteract by setting("Right Click Fly", true, "Automatically start flying when right clicking fireworks") private var fireworkInteractCancel by setting("Right Click Cancel", false, "Cancel block interactions while holding fireworks") { fireworkInteract } @@ -93,58 +99,6 @@ object BetterFirework : Module( } } } - listen { - if (!it.isPressed) { - return@listen - } - if (it.satisfies(activateButton)) { - if (activateButton.mouse == mc.options.pickItemKey.boundKey.code) { - return@listen - } - runSafe { - if (takeoffState != TakeoffState.None) { - return@listen // Prevent using multiple times - } - if (player.canOpenElytra || player.isGliding) { - // If already gliding use another firework - takeoffState = TakeoffState.StartFlying - } else if (player.canTakeoff) { - takeoffState = TakeoffState.Jumping - } - } - } - if (it.satisfies(midFlightActivationKey)) { - runSafe { - if (player.isGliding) - takeoffState = TakeoffState.StartFlying - } - } - } - listen { - if (!it.isPressed) { - return@listen - } - if (it.satisfies(activateButton)) { - if (activateButton.key != mc.options.pickItemKey.boundKey.code) { - runSafe { - if (takeoffState == TakeoffState.None) { - if (player.canOpenElytra || player.isGliding) { - // If already gliding use another firework - takeoffState = TakeoffState.StartFlying - } else if (player.canTakeoff) { - takeoffState = TakeoffState.Jumping - } - } - } - } - } - if (it.satisfies(midFlightActivationKey)) { - runSafe { - if (player.isGliding) - takeoffState = TakeoffState.StartFlying - } - } - } } /** diff --git a/src/main/kotlin/com/lambda/module/modules/player/AirPlace.kt b/src/main/kotlin/com/lambda/module/modules/player/AirPlace.kt index 2a0858f3e..c5b3b0b1b 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/AirPlace.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/AirPlace.kt @@ -21,7 +21,7 @@ import com.lambda.config.AutomationConfig.Companion.setDefaultAutomationConfig import com.lambda.config.applyEdits import com.lambda.config.settings.complex.Bind import com.lambda.context.SafeContext -import com.lambda.event.events.MouseEvent +import com.lambda.event.events.ButtonEvent import com.lambda.event.events.PlayerEvent import com.lambda.event.events.TickEvent import com.lambda.event.events.onStaticRender @@ -118,7 +118,7 @@ object AirPlace : Module( } } - listen { event -> + listen { event -> if (!scrollBind.isSatisfied()) return@listen event.cancel() distance += event.delta.y diff --git a/src/main/kotlin/com/lambda/module/modules/player/AutoArmor.kt b/src/main/kotlin/com/lambda/module/modules/player/AutoArmor.kt index 0de3ef751..b9532899a 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/AutoArmor.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/AutoArmor.kt @@ -20,16 +20,14 @@ package com.lambda.module.modules.player import com.lambda.config.AutomationConfig.Companion.setDefaultAutomationConfig import com.lambda.config.applyEdits import com.lambda.config.settings.complex.Bind +import com.lambda.config.settings.complex.KeybindSetting.Companion.onPress import com.lambda.context.SafeContext -import com.lambda.event.events.KeyboardEvent -import com.lambda.event.events.MouseEvent import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.interaction.managers.inventory.InventoryRequest.Companion.inventoryRequest import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.util.EnchantmentUtils.getEnchantment -import com.lambda.util.InputUtils.isSatisfied import com.lambda.util.player.SlotUtils.armorSlots import com.lambda.util.player.SlotUtils.hotbarAndInventorySlots import net.minecraft.component.DataComponentTypes @@ -49,6 +47,7 @@ object AutoArmor : Module( ) { private var elytraPriority by setting("Elytra Priority", true, "Prioritizes elytra's over other armor pieces in the chest slot") private val toggleElytraPriority by setting("Toggle Elytra Priority", Bind.EMPTY) + .onPress { elytraPriority = !elytraPriority } private val minDurabilityPercentage by setting("Min Durability", 5, 0..100, 1, "Minimum durability percentage before being swapped for a new piece", "%") private val headProtection by setting("Preferred Head Protection", Protection.Protection) private val chestProtection by setting("Preferred Chest Protection", Protection.Protection) @@ -128,9 +127,6 @@ object AutoArmor : Module( } }.submit() } - - listen { if (toggleElytraPriority.isSatisfied()) elytraPriority = !elytraPriority } - listen { if (toggleElytraPriority.isSatisfied()) elytraPriority = !elytraPriority } } context(safeContext: SafeContext) diff --git a/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt b/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt index a23e6e779..abe148410 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt @@ -18,8 +18,8 @@ package com.lambda.module.modules.player import com.lambda.config.settings.complex.Bind -import com.lambda.event.events.MouseEvent -import com.lambda.event.listener.SafeListener.Companion.listen +import com.lambda.config.settings.complex.KeybindSetting.Companion.onPress +import com.lambda.context.SafeContext import com.lambda.friend.FriendManager import com.lambda.friend.FriendManager.befriend import com.lambda.friend.FriendManager.isFriend @@ -27,6 +27,7 @@ import com.lambda.friend.FriendManager.unfriend import com.lambda.module.Module import com.lambda.module.tag.ModuleTag import com.lambda.util.Communication.info +import com.lambda.util.InputUtils.isSatisfied import com.lambda.util.world.raycast.RayCastUtils.entityResult import net.minecraft.client.network.OtherClientPlayerEntity import org.lwjgl.glfw.GLFW @@ -37,23 +38,20 @@ object ClickFriend : Module( description = "Add or remove friends with a single click", tag = ModuleTag.PLAYER, ) { - private val friendBind by setting("Friend Bind", Bind(0, 0, GLFW.GLFW_MOUSE_BUTTON_MIDDLE), "Bind to press to befriend a player") - private val unfriendBind by setting("Unfriend Bind", Bind(0, GLFW_MOD_SHIFT, GLFW.GLFW_MOUSE_BUTTON_MIDDLE), "Bind to press to unfriend a player") + private val friendBind = setting("Friend Bind", Bind(0, 0, GLFW.GLFW_MOUSE_BUTTON_MIDDLE), "Bind to press to befriend a player") + private val unfriendBind = setting("Unfriend Bind", Bind(0, GLFW_MOD_SHIFT, GLFW.GLFW_MOUSE_BUTTON_MIDDLE), "Bind to press to unfriend a player") init { - listen { - if (mc.currentScreen != null) return@listen - - val target = mc.crosshairTarget?.entityResult?.entity as? OtherClientPlayerEntity - ?: return@listen + // onPress listeners applied here to avoid recursion warning + friendBind.onPress { if (!unfriendBind.value.isSatisfied()) checkSetFriend(true) } + unfriendBind.onPress { if (!friendBind.value.isSatisfied()) checkSetFriend(false) } + } - when { - it.satisfies(friendBind) && !target.isFriend && target.befriend() -> - info(FriendManager.befriendedText(target.name)) + private fun SafeContext.checkSetFriend(friend: Boolean) { + val target = mc.crosshairTarget?.entityResult?.entity as? OtherClientPlayerEntity + ?: return - it.satisfies(unfriendBind) && target.isFriend && target.unfriend() -> - info(FriendManager.unfriendedText(target.name)) - } - } + if (friend && !target.isFriend && target.befriend()) info(FriendManager.befriendedText(target.name)) + else if (!friend && target.isFriend && target.unfriend()) info(FriendManager.unfriendedText(target.name)) } } diff --git a/src/main/kotlin/com/lambda/module/modules/player/Replay.kt b/src/main/kotlin/com/lambda/module/modules/player/Replay.kt index 7550c6955..e6345aa1b 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Replay.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Replay.kt @@ -26,10 +26,10 @@ import com.google.gson.JsonNull import com.google.gson.JsonSerializationContext import com.google.gson.JsonSerializer import com.lambda.brigadier.CommandResult +import com.lambda.config.settings.complex.KeybindSetting.Companion.onPress import com.lambda.context.SafeContext import com.lambda.core.TimerManager import com.lambda.event.EventFlow.lambdaScope -import com.lambda.event.events.KeyboardEvent import com.lambda.event.events.MovementEvent import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen @@ -88,9 +88,13 @@ object Replay : Module( autoDisable = true ) { private val record by setting("Record", KeyCode.R) + .onPress { handleRecord() } private val play by setting("Play / Stop", KeyCode.C) + .onPress { handlePlay() } private val cycle by setting("Cycle Play Mode", KeyCode.B, description = "REPLAY: Replay the recording once. CONTINUE: Replay the recording and continue recording. LOOP: Loop the recording.") + .onPress { handlePlayModeCycle() } private val check by setting("Set Checkpoint", KeyCode.V, description = "Create a checkpoint while recording.") + .onPress { handleCheckpoint() } private val loops by setting("Loops", -1, -1..10, 1, description = "Number of times to loop the replay. -1 for infinite.", unit = " repeats") private val velocityCheck by setting("Velocity check", true, description = "Check if the player is moving before starting a recording.") @@ -130,19 +134,6 @@ object Replay : Module( .create() init { - listen { - if (!it.isPressed) return@listen - if (mc.currentScreen != null && !mc.options.commandKey.isPressed) return@listen - - when (it.bind) { - record -> handleRecord() - play -> handlePlay() - cycle -> handlePlayModeCycle() - check -> handleCheckpoint() - else -> {} - } - } - listen { event -> when (state) { State.Recording -> { diff --git a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt index c5c1c4ea7..618c6da83 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt @@ -32,7 +32,7 @@ import com.lambda.module.tag.ModuleTag import com.lambda.threading.runSafeAutomated import com.lambda.util.BlockUtils.blockPos import com.lambda.util.BlockUtils.blockState -import com.lambda.util.InputUtils.isKeyPressed +import com.lambda.util.InputUtils.isSatisfied import com.lambda.util.KeyCode import net.minecraft.util.math.BlockPos import java.util.concurrent.ConcurrentLinkedQueue @@ -85,7 +85,7 @@ object Scaffold : Module( val playerSupport = player.blockPos.down() val alreadySupported = blockState(playerSupport).hasSolidTopSurface(world, playerSupport, player) if (alreadySupported) return@listen - val offset = if (isKeyPressed(descend.key)) descendAmount else 0 + val offset = if (descend.isSatisfied()) descendAmount else 0 val beneath = playerSupport.down(offset) runSafeAutomated { scaffoldPositions(beneath) diff --git a/src/main/kotlin/com/lambda/module/modules/render/ViewModel.kt b/src/main/kotlin/com/lambda/module/modules/render/ViewModel.kt index 6a2a67594..f6799e220 100644 --- a/src/main/kotlin/com/lambda/module/modules/render/ViewModel.kt +++ b/src/main/kotlin/com/lambda/module/modules/render/ViewModel.kt @@ -18,8 +18,7 @@ package com.lambda.module.modules.render import com.lambda.Lambda.mc -import com.lambda.event.events.KeyboardEvent -import com.lambda.event.events.MouseEvent +import com.lambda.event.events.ButtonEvent import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.module.Module @@ -109,12 +108,12 @@ object ViewModel : Module( private var attackKeyTicksPressed = -1 init { - listen { event -> + listen { event -> if (event.button == mc.options.attackKey.boundKey.code) attackKeyTicksPressed = if (event.action == 0) -1 else 0 } - listen { event -> + listen { event -> if (event.keyCode == mc.options.attackKey.boundKey.code) { if (event.isPressed) attackKeyTicksPressed = 0 else if (event.isReleased) attackKeyTicksPressed = -1 diff --git a/src/main/kotlin/com/lambda/module/modules/render/Zoom.kt b/src/main/kotlin/com/lambda/module/modules/render/Zoom.kt index 25e3cdc39..e8b9d82db 100644 --- a/src/main/kotlin/com/lambda/module/modules/render/Zoom.kt +++ b/src/main/kotlin/com/lambda/module/modules/render/Zoom.kt @@ -17,7 +17,7 @@ package com.lambda.module.modules.render -import com.lambda.event.events.MouseEvent +import com.lambda.event.events.ButtonEvent import com.lambda.event.events.RenderEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.module.Module @@ -52,7 +52,7 @@ object Zoom : Module( get() = clamp((System.currentTimeMillis() - lastZoomTime) / (if (isEnabled) animationDuration else disableDuration).toDouble(), 0.0, 1.0).toFloat() init { - listen { event -> + listen { event -> val yDelta = event.delta.y.toFloat() val delta = (yDelta * sensitivity) + (((zoom + extraZoom) * sensitivity) * yDelta) if (persistentScroll) zoom += delta diff --git a/src/main/kotlin/com/lambda/util/InputUtils.kt b/src/main/kotlin/com/lambda/util/InputUtils.kt index ed97f8e3a..a738391af 100644 --- a/src/main/kotlin/com/lambda/util/InputUtils.kt +++ b/src/main/kotlin/com/lambda/util/InputUtils.kt @@ -21,8 +21,7 @@ import com.lambda.Lambda.mc import com.lambda.config.settings.complex.Bind import com.lambda.context.SafeContext import com.lambda.core.Loadable -import com.lambda.event.events.KeyboardEvent -import com.lambda.event.events.MouseEvent +import com.lambda.event.events.ButtonEvent import it.unimi.dsi.fastutil.ints.Int2IntArrayMap import org.lwjgl.glfw.GLFW import org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_ALT @@ -53,7 +52,7 @@ object InputUtils : Loadable { * Note: This function is extremely expensive to execute, it is recommended to not use * it unless you absolutely need to. Additionally, you might screw with the key cache. */ - fun newKeyboardEvent(): KeyboardEvent.Press? { + fun newKeyboardEvent(): ButtonEvent.Keyboard.Press? { val pressedKeys = keys .associateWith { glfwGetKey(mc.window.handle, it) } .filter { (key, state) -> state >= GLFW_PRESS || lastPressedKeys[key] >= GLFW_PRESS } @@ -76,13 +75,13 @@ object InputUtils : Loadable { val scancode = scancodes.getOrElse(key.first) { 0 } - return KeyboardEvent.Press(key.first, scancode, key.second, mods) + return ButtonEvent.Keyboard.Press(key.first, scancode, key.second, mods) } /** * Creates a new mouse event from the current glfw states. */ - fun newMouseEvent(): MouseEvent.Click? { + fun newMouseEvent(): ButtonEvent.Mouse.Click? { val mods = (GLFW_KEY_LEFT_SHIFT..GLFW_KEY_RIGHT_SUPER) .filter { glfwGetKey(mc.window.handle, it) >= GLFW_PRESS } .foldRight(0) { v, acc -> acc or modMap.getValue(v) } @@ -91,15 +90,13 @@ object InputUtils : Loadable { .firstOrNull { glfwGetMouseButton(mc.window.handle, it) == GLFW_PRESS } ?: return null - return MouseEvent.Click(mouse, GLFW_PRESS, mods) + return ButtonEvent.Mouse.Click(mouse, GLFW_PRESS, mods) } fun Bind.isSatisfied(): Boolean = (key == -1 || glfwGetKey(mc.window.handle, key).pressedOrRepeated) && (mouse == -1 || glfwGetMouseButton(mc.window.handle, mouse).pressedOrRepeated) && - truemods.all { - glfwGetKey(mc.window.handle, it.code).pressedOrRepeated - } + truemods.all { glfwGetKey(mc.window.handle, it.code).pressedOrRepeated } private val Int.pressedOrRepeated get() = this == 1 || this == 2 From c56ff2dac9fcd6cefc92c7e0b8cdf2ffc4c08142 Mon Sep 17 00:00:00 2001 From: beanbag44 <107891830+beanbag44@users.noreply.github.com> Date: Fri, 9 Jan 2026 11:30:05 +0000 Subject: [PATCH 2/3] "alwaysListening" over "alwaysListen" to keep parity with modules --- src/main/kotlin/com/lambda/config/Configurable.kt | 8 ++++---- src/main/kotlin/com/lambda/module/Module.kt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/lambda/config/Configurable.kt b/src/main/kotlin/com/lambda/config/Configurable.kt index fce94e2a2..310fad314 100644 --- a/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/src/main/kotlin/com/lambda/config/Configurable.kt @@ -229,19 +229,19 @@ abstract class Configurable( name: String, defaultValue: Bind, description: String = "", - alwaysListen: Boolean = false, + alwaysListening: Boolean = false, screenCheck: Boolean = true, visibility: () -> Boolean = { true }, - ) = Setting(name, description, KeybindSetting(defaultValue, this as? Muteable, alwaysListen, screenCheck), this, visibility).register() + ) = Setting(name, description, KeybindSetting(defaultValue, this as? Muteable, alwaysListening, screenCheck), this, visibility).register() fun setting( name: String, defaultValue: KeyCode, description: String = "", - alwaysListen: Boolean = false, + alwaysListening: Boolean = false, screenCheck: Boolean = true, visibility: () -> Boolean = { true }, - ) = Setting(name, description, KeybindSetting(defaultValue, this as? Muteable, alwaysListen, screenCheck), this, visibility).register() + ) = Setting(name, description, KeybindSetting(defaultValue, this as? Muteable, alwaysListening, screenCheck), this, visibility).register() fun setting( name: String, diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index bf845b341..0066648b3 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -121,7 +121,7 @@ abstract class Module( autoDisable: Boolean = false ) : Nameable, Muteable, Configurable(ModuleConfigs), MutableAutomationConfig by MutableAutomationConfigImpl() { private val isEnabledSetting = setting("Enabled", enabledByDefault) { false } - val keybindSetting = setting("Keybind", defaultKeybind, alwaysListen = true) { false } + val keybindSetting = setting("Keybind", defaultKeybind, alwaysListening = true) { false } .onPress { toggle() } .onRelease { if (disableOnRelease) disable() } val disableOnReleaseSetting = setting("Disable On Release", false) { false } From a597a9b9ff4391e632ef23f674f49158db7f79f1 Mon Sep 17 00:00:00 2001 From: beanbag44 <107891830+beanbag44@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:34:43 +0000 Subject: [PATCH 3/3] fix better firework using two fireworks --- .../module/modules/movement/BetterFirework.kt | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt b/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt index 7661ea406..cdfb26208 100644 --- a/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt +++ b/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt @@ -54,7 +54,7 @@ object BetterFirework : Module( if (player.canOpenElytra || player.isGliding) takeoffState = TakeoffState.StartFlying else if (player.canTakeoff) takeoffState = TakeoffState.Jumping } - private var midFlightActivationKey by setting("Mid-Flight Activation Key", Bind(0, 0), "Firework use key for mid flight activation") + private var midFlightActivationKey by setting("Mid-Flight Activation Key", Bind.EMPTY, "Firework use key for mid flight activation") .onPress { if (player.isGliding) takeoffState = TakeoffState.StartFlying } private var middleClickCancel by setting("Middle Click Cancel", false, description = "Cancel pick block action on middle mouse click") { activateButton.key != KeyCode.Unbound.code } private var fireworkInteract by setting("Right Click Fly", true, "Automatically start flying when right clicking fireworks") @@ -133,17 +133,9 @@ object BetterFirework : Module( runSafe { when { (mc.crosshairTarget?.type == HitResult.Type.BLOCK && !middleClickCancel) || - (!activateButton.isMouseBind || activateButton.mouse != mc.options.pickItemKey.boundKey.code) || + activateButton.mouse != mc.options.pickItemKey.boundKey.code || takeoffState != TakeoffState.None -> false // Prevent using multiple times - else -> { - if (player.canOpenElytra || player.isGliding) { - // If already gliding use another firework - takeoffState = TakeoffState.StartFlying - } else if (player.canTakeoff) { - takeoffState = TakeoffState.Jumping - } - middleClickCancel - } + else -> middleClickCancel } } ?: false