From e724b48766f944cdb9dee2d5f7cea24337fab99f Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Wed, 24 Sep 2025 12:33:22 +0100 Subject: [PATCH 1/8] changes --- .../kotlin/com/lambda/config/Configurable.kt | 3 +- .../config/settings/complex/KeybindSetting.kt | 97 ++++++++++++++----- .../kotlin/com/lambda/module/HudModule.kt | 4 +- src/main/kotlin/com/lambda/module/Module.kt | 28 ++++-- .../com/lambda/module/hud/ModuleList.kt | 2 +- .../module/modules/player/InventoryMove.kt | 2 +- .../lambda/module/modules/player/Scaffold.kt | 2 +- .../util/{KeyboardUtils.kt => InputUtils.kt} | 10 +- 8 files changed, 106 insertions(+), 42 deletions(-) rename src/main/kotlin/com/lambda/util/{KeyboardUtils.kt => InputUtils.kt} (73%) diff --git a/src/main/kotlin/com/lambda/config/Configurable.kt b/src/main/kotlin/com/lambda/config/Configurable.kt index 8f63a7183..836c2cb1f 100644 --- a/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/src/main/kotlin/com/lambda/config/Configurable.kt @@ -30,6 +30,7 @@ import com.lambda.config.settings.collections.MapSetting import com.lambda.config.settings.collections.SetSetting import com.lambda.config.settings.comparable.BooleanSetting import com.lambda.config.settings.comparable.EnumSetting +import com.lambda.config.settings.complex.Bind import com.lambda.config.settings.complex.BlockPosSetting import com.lambda.config.settings.complex.BlockSetting import com.lambda.config.settings.complex.ColorSetting @@ -381,7 +382,7 @@ abstract class Configurable( */ fun setting( name: String, - defaultValue: KeyCode, + defaultValue: Bind, description: String = "", visibility: () -> Boolean = { true }, ) = KeybindSetting(name, defaultValue, description, visibility).register() 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 4dddcc01a..dd1b3ca1c 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt @@ -18,14 +18,20 @@ package com.lambda.config.settings.complex import com.google.gson.reflect.TypeToken +import com.lambda.brigadier.CommandResult.Companion.failure +import com.lambda.brigadier.CommandResult.Companion.success +import com.lambda.brigadier.argument.boolean import com.lambda.brigadier.argument.value import com.lambda.brigadier.argument.word -import com.lambda.brigadier.execute +import com.lambda.brigadier.executeWithResult +import com.lambda.brigadier.optional import com.lambda.brigadier.required import com.lambda.config.AbstractSetting +import com.lambda.config.settings.complex.Bind.Companion.mouseBind import com.lambda.gui.dsl.ImGuiBuilder +import com.lambda.util.InputUtils import com.lambda.util.KeyCode -import com.lambda.util.KeyboardUtils +import com.lambda.util.Mouse import com.lambda.util.StringUtils.capitalize import com.lambda.util.extension.CommandBuilder import imgui.ImGui.isMouseClicked @@ -37,22 +43,23 @@ import org.lwjgl.glfw.GLFW class KeybindSetting( override val name: String, - defaultValue: KeyCode, + defaultValue: Bind, description: String, visibility: () -> Boolean, -) : AbstractSetting( +) : AbstractSetting( defaultValue, - TypeToken.get(KeyCode::class.java).type, + TypeToken.get(Bind::class.java).type, description, visibility ) { private var listening = false override fun ImGuiBuilder.buildLayout() { - val key = value - val scancode = if (key == KeyCode.UNBOUND) -69 else GLFW.glfwGetKeyScancode(key.code) - val translated = if (key == KeyCode.UNBOUND) key else KeyCode.virtualMapUS(key.code, scancode) - val preview = if (listening) "$name: Press any key…" else "$name: $translated" + val bind = value + val scancode = if (bind.code == KeyCode.UNBOUND.code) -69 else GLFW.glfwGetKeyScancode(bind.code) + val translated = if (bind.keyCode == KeyCode.UNBOUND) bind.keyCode else KeyCode.virtualMapUS(bind.code, scancode) + val preview = if (listening) "$name: Press any key…" + else if (bind.isMouseButton) "Mouse ${bind.code}" else "$name: $translated" if (listening) { withStyleColor(ImGuiCol.Button, 0.20f, 0.50f, 1.00f, 1.00f) { @@ -75,7 +82,7 @@ class KeybindSetting( } onItemClick(ImGuiMouseButton.Right) { - value = KeyCode.UNBOUND + value = Bind.EMPTY listening = false } @@ -85,38 +92,78 @@ class KeybindSetting( sameLine() smallButton("Unbind") { - value = KeyCode.UNBOUND + value = Bind.EMPTY listening = false } onItemHover(ImGuiHoveredFlags.Stationary) { lambdaTooltip("Clear binding") } - val poll = KeyboardUtils.lastEvent - if (listening && poll.isPressed) { - when (val key = poll.translated) { - KeyCode.ESCAPE -> listening = false - KeyCode.BACKSPACE, KeyCode.DELETE -> { - value = KeyCode.UNBOUND - listening = false - } - else -> { - value = key - listening = false + val keyboardPoll = InputUtils.lastKeyboardEvent + val mousePoll = InputUtils.lastMouseEvent + if (listening) { + if (keyboardPoll.isPressed) { + when (val key = keyboardPoll.translated) { + KeyCode.ESCAPE -> {} + KeyCode.BACKSPACE, KeyCode.DELETE -> value = Bind.EMPTY + else -> value = Bind(key) } + listening = false + } else if (mousePoll.action == Mouse.Action.Click.ordinal) { + value = mouseBind(mousePoll.button) + listening = false } } } override fun CommandBuilder.buildCommand(registry: CommandRegistryAccess) { - required(word(name)) { parameter -> + required(word(name)) { name -> suggests { _, builder -> KeyCode.entries.forEach { builder.suggest(it.name.capitalize()) } + (1..10).forEach { builder.suggest(it) } builder.buildFuture() } - execute { - trySetValue(KeyCode.valueOf(parameter().value())) + optional(boolean("mouse button")) { isMouseButton -> + executeWithResult { + val isMouse = if (isMouseButton != null) isMouseButton().value() else false + var bind = Bind.EMPTY + if (isMouse) { + val num = try { + name().value().toInt() + } catch(_: NumberFormatException) { + return@executeWithResult failure("${name().value()} doesn't match with a mouse button") + } + bind = mouseBind(num) + } else { + bind = try { + Bind(KeyCode.valueOf(name().value())) + } catch(_: IllegalArgumentException) { + return@executeWithResult failure("${name().value()} doesn't match with a bind") + } + } + + trySetValue(bind) + return@executeWithResult success() + } } } } } + +data class Bind( + val keyCode: KeyCode = KeyCode.UNBOUND, + val code: Int = keyCode.code, + val isMouseButton: Boolean = false +) { + val name: String + get() = if (isMouseButton) "Mouse $code" else keyCode.name + + override fun toString() = + "Key Code: $keyCode, Code: $code, Mouse Button: $isMouseButton" + + companion object { + val EMPTY = Bind() + + fun mouseBind(code: Int) = Bind(code = code, isMouseButton = true) + } +} diff --git a/src/main/kotlin/com/lambda/module/HudModule.kt b/src/main/kotlin/com/lambda/module/HudModule.kt index c84b379b8..5c26f37cd 100644 --- a/src/main/kotlin/com/lambda/module/HudModule.kt +++ b/src/main/kotlin/com/lambda/module/HudModule.kt @@ -17,9 +17,9 @@ package com.lambda.module +import com.lambda.config.settings.complex.Bind import com.lambda.gui.Layout import com.lambda.module.tag.ModuleTag -import com.lambda.util.KeyCode import java.awt.Color abstract class HudModule( @@ -29,7 +29,7 @@ abstract class HudModule( val customWindow: Boolean = false, alwaysListening: Boolean = false, enabledByDefault: Boolean = false, - defaultKeybind: KeyCode = KeyCode.UNBOUND, + defaultKeybind: Bind = Bind.EMPTY, ) : Module(name, description, tag, alwaysListening, enabledByDefault, defaultKeybind), Layout { val backgroundColor by setting("Background Color", Color(0, 0, 0, 0)) val outline by setting("Show Outline", false) diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index fe69536df..9da8176b8 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -17,16 +17,19 @@ package com.lambda.module +import com.lambda.Lambda.mc import com.lambda.command.LambdaCommand import com.lambda.config.AbstractSetting import com.lambda.config.Configurable import com.lambda.config.Configuration import com.lambda.config.configurations.ModuleConfig +import com.lambda.config.settings.complex.Bind 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 @@ -35,6 +38,7 @@ import com.lambda.module.tag.ModuleTag import com.lambda.sound.LambdaSound import com.lambda.sound.SoundManager.play import com.lambda.util.KeyCode +import com.lambda.util.Mouse import com.lambda.util.Nameable /** @@ -111,7 +115,7 @@ abstract class Module( val tag: ModuleTag, private val alwaysListening: Boolean = false, enabledByDefault: Boolean = false, - defaultKeybind: KeyCode = KeyCode.UNBOUND, + defaultKeybind: Bind = Bind.EMPTY, autoDisable: Boolean = false ) : Nameable, Muteable, Configurable(ModuleConfig) { private val isEnabledSetting = setting("Enabled", enabledByDefault) { false } @@ -122,20 +126,20 @@ abstract class Module( var isEnabled by isEnabledSetting val isDisabled get() = !isEnabled - val keybind by keybindSetting + var keybind by keybindSetting override val isMuted: Boolean get() = !isEnabled && !alwaysListening init { listen(alwaysListen = true) { event -> - if (mc.options.commandKey.isPressed) return@listen - if (!event.isPressed) return@listen - if (keybind == KeyCode.UNBOUND) return@listen - if (event.translated != keybind) return@listen - if (mc.currentScreen != null) return@listen + if (event.isPressed) + onButtonPress(event.keyCode) + } - toggle() + listen(alwaysListen = true) { event -> + if (event.action == Mouse.Action.Click.ordinal) + onButtonPress(event.button) } onEnable { LambdaSound.MODULE_ON.play() } @@ -149,6 +153,14 @@ abstract class Module( listen { if (autoDisable) disable() } } + private fun onButtonPress(code: Int, mouseButton: Boolean = false) { + if (mc.options.commandKey.isPressed) return + if (mc.currentScreen != null) return + if (keybind.code == KeyCode.UNBOUND.code) return + if (code != keybind.code) return + toggle() + } + fun enable() { isEnabled = true } diff --git a/src/main/kotlin/com/lambda/module/hud/ModuleList.kt b/src/main/kotlin/com/lambda/module/hud/ModuleList.kt index 587087c50..6c9db4065 100644 --- a/src/main/kotlin/com/lambda/module/hud/ModuleList.kt +++ b/src/main/kotlin/com/lambda/module/hud/ModuleList.kt @@ -39,7 +39,7 @@ object ModuleList : HudModule( enabled.forEach { text(it.name); sameLine() - val color = if (it.keybind == KeyCode.UNBOUND) Color.RED else Color.GREEN + val color = if (it.keybind.code == KeyCode.UNBOUND.code) Color.RED else Color.GREEN withStyleColor(ImGuiCol.Text, color) { text(" [${it.keybind.name}]") } } diff --git a/src/main/kotlin/com/lambda/module/modules/player/InventoryMove.kt b/src/main/kotlin/com/lambda/module/modules/player/InventoryMove.kt index ff2841811..5e2afd407 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/InventoryMove.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/InventoryMove.kt @@ -27,7 +27,7 @@ import com.lambda.interaction.request.rotating.RotationMode import com.lambda.interaction.request.rotating.visibilty.lookAt import com.lambda.module.Module import com.lambda.module.tag.ModuleTag -import com.lambda.util.KeyboardUtils.isKeyPressed +import com.lambda.util.InputUtils.isKeyPressed import com.lambda.util.math.MathUtils.toFloatSign import net.minecraft.client.gui.screen.ChatScreen import net.minecraft.client.gui.screen.Screen 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 9b6544e37..c03a7260f 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/Scaffold.kt @@ -38,7 +38,7 @@ import com.lambda.module.tag.ModuleTag import com.lambda.util.BlockUtils.blockPos import com.lambda.util.BlockUtils.blockState import com.lambda.util.KeyCode -import com.lambda.util.KeyboardUtils.isKeyPressed +import com.lambda.util.InputUtils.isKeyPressed import com.lambda.util.NamedEnum import com.lambda.util.math.distSq import com.lambda.util.world.raycast.InteractionMask diff --git a/src/main/kotlin/com/lambda/util/KeyboardUtils.kt b/src/main/kotlin/com/lambda/util/InputUtils.kt similarity index 73% rename from src/main/kotlin/com/lambda/util/KeyboardUtils.kt rename to src/main/kotlin/com/lambda/util/InputUtils.kt index e2f02ac60..c272f5102 100644 --- a/src/main/kotlin/com/lambda/util/KeyboardUtils.kt +++ b/src/main/kotlin/com/lambda/util/InputUtils.kt @@ -20,11 +20,14 @@ package com.lambda.util 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.listener.UnsafeListener.Companion.listenUnsafe +import com.lambda.util.math.Vec2d import net.minecraft.client.util.InputUtil -object KeyboardUtils : Loadable { - var lastEvent: KeyboardEvent.Press = KeyboardEvent.Press(0, 0, -1, 0) +object InputUtils : Loadable { + var lastKeyboardEvent: KeyboardEvent.Press = KeyboardEvent.Press(0, 0, -1, 0); private set + var lastMouseEvent: MouseEvent.Click = MouseEvent.Click(Mouse.Button.Left, Mouse.Action.Click, 0, Vec2d(0, 0)); private set /** * Returns whether any of the key-codes (not scan-codes) are being pressed @@ -34,6 +37,7 @@ object KeyboardUtils : Loadable { init { // hacking imgui jni lib rn because it's missing a lot of native functions including i/o stuff - listenUnsafe { lastEvent = it } + listenUnsafe { lastKeyboardEvent = it } + listenUnsafe { lastMouseEvent = it } } } From 668b5406a83c401180d07ae73e1fd7a940c07376 Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Sun, 28 Sep 2025 16:18:56 +0100 Subject: [PATCH 2/8] merge fixes --- src/main/kotlin/com/lambda/module/Module.kt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index 42496e725..0ee2d539a 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -18,7 +18,6 @@ package com.lambda.module import com.lambda.Lambda.mc -import com.lambda.Lambda import com.lambda.command.LambdaCommand import com.lambda.config.AbstractSetting import com.lambda.config.Configurable @@ -41,7 +40,6 @@ import com.lambda.sound.SoundManager.play import com.lambda.util.KeyCode import com.lambda.util.Mouse import com.lambda.util.Nameable -import javax.swing.ActionMap /** * A [Module] is a feature or tool for the utility mod. @@ -143,7 +141,7 @@ abstract class Module( listen(alwaysListen = true) { event -> val pressed = event.action == Mouse.Action.Click.ordinal val released = event.action == Mouse.Action.Release.ordinal - onButtonPress(event.button, pressed, released, mouseButton = true) + onButtonPress(event.button, pressed, released) } onEnable { LambdaSound.MODULE_ON.play() } @@ -157,12 +155,12 @@ abstract class Module( listen { if (autoDisable) disable() } } - private fun onButtonPress(code: Int, pressed: Boolean, released: Boolean, mouseButton: Boolean = false) { + private fun onButtonPress(code: Int, pressed: Boolean, released: Boolean) { if (mc.options.commandKey.isPressed) return if (mc.currentScreen != null) return - if (keybind.code == KeyCode.UNBOUND.code) return if (code != keybind.code) return - toggle() + if (pressed) toggle() + else if (released && disableOnRelease) disable() } fun enable() { From cc19dbf6b012a265f16242a7bbb0ee16a114a644 Mon Sep 17 00:00:00 2001 From: Edouard127 <46357922+Edouard127@users.noreply.github.com> Date: Fri, 3 Oct 2025 16:39:09 -0400 Subject: [PATCH 3/8] Added multi key and mouse binds --- .../config/settings/complex/KeybindSetting.kt | 66 +++++++++++++------ .../com/lambda/event/events/KeyboardEvent.kt | 3 + .../com/lambda/event/events/MouseEvent.kt | 3 + src/main/kotlin/com/lambda/module/Module.kt | 25 +++---- .../com/lambda/module/hud/ModuleList.kt | 2 +- .../kotlin/com/lambda/util/Communication.kt | 4 +- src/main/kotlin/com/lambda/util/InputUtils.kt | 4 +- 7 files changed, 71 insertions(+), 36 deletions(-) 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 dd1b3ca1c..2b9ed28bc 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt @@ -39,7 +39,14 @@ import imgui.flag.ImGuiCol import imgui.flag.ImGuiHoveredFlags import imgui.flag.ImGuiMouseButton import net.minecraft.command.CommandRegistryAccess -import org.lwjgl.glfw.GLFW +import org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SHIFT +import org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT_SUPER +import org.lwjgl.glfw.GLFW.GLFW_MOD_ALT +import org.lwjgl.glfw.GLFW.GLFW_MOD_CAPS_LOCK +import org.lwjgl.glfw.GLFW.GLFW_MOD_CONTROL +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( override val name: String, @@ -56,10 +63,9 @@ class KeybindSetting( override fun ImGuiBuilder.buildLayout() { val bind = value - val scancode = if (bind.code == KeyCode.UNBOUND.code) -69 else GLFW.glfwGetKeyScancode(bind.code) - val translated = if (bind.keyCode == KeyCode.UNBOUND) bind.keyCode else KeyCode.virtualMapUS(bind.code, scancode) - val preview = if (listening) "$name: Press any key…" - else if (bind.isMouseButton) "Mouse ${bind.code}" else "$name: $translated" + val preview = + if (listening) "$name: Press any key…" + else bind.name if (listening) { withStyleColor(ImGuiCol.Button, 0.20f, 0.50f, 1.00f, 1.00f) { @@ -99,18 +105,23 @@ class KeybindSetting( lambdaTooltip("Clear binding") } - val keyboardPoll = InputUtils.lastKeyboardEvent - val mousePoll = InputUtils.lastMouseEvent + val keypoll = InputUtils.lastKeyboardEvent ?: return + val mousepoll = InputUtils.lastMouseEvent ?: return + if (listening) { - if (keyboardPoll.isPressed) { - when (val key = keyboardPoll.translated) { + val isModKey = keypoll.keyCode in GLFW_KEY_LEFT_SHIFT..GLFW_KEY_RIGHT_SUPER + + if ((keypoll.isPressed && !isModKey) + || (keypoll.isReleased && isModKey) + ) { + when (keypoll.translated) { KeyCode.ESCAPE -> {} KeyCode.BACKSPACE, KeyCode.DELETE -> value = Bind.EMPTY - else -> value = Bind(key) + else -> value = Bind(keypoll.keyCode, keypoll.modifiers, -1) } listening = false - } else if (mousePoll.action == Mouse.Action.Click.ordinal) { - value = mouseBind(mousePoll.button) + } else if (mousepoll.action == Mouse.Action.Click.ordinal) { + value = Bind(0, mousepoll.modifiers, mousepoll.button) listening = false } } @@ -136,7 +147,7 @@ class KeybindSetting( bind = mouseBind(num) } else { bind = try { - Bind(KeyCode.valueOf(name().value())) + Bind(KeyCode.valueOf(name().value()).code, 0) } catch(_: IllegalArgumentException) { return@executeWithResult failure("${name().value()} doesn't match with a bind") } @@ -151,19 +162,34 @@ class KeybindSetting( } data class Bind( - val keyCode: KeyCode = KeyCode.UNBOUND, - val code: Int = keyCode.code, - val isMouseButton: Boolean = false + val key: Int, + val modifiers: Int, + val mouse: Int = -1, ) { + val truemods = buildList { + if (modifiers and GLFW_MOD_SHIFT != 0) add(KeyCode.LEFT_SHIFT) + if (modifiers and GLFW_MOD_CONTROL != 0) add(KeyCode.LEFT_CONTROL) + if (modifiers and GLFW_MOD_ALT != 0) add(KeyCode.LEFT_ALT) + if (modifiers and GLFW_MOD_SUPER != 0) add(KeyCode.LEFT_SUPER) + if (modifiers and GLFW_MOD_CAPS_LOCK != 0) add(KeyCode.CAPS_LOCK) + if (modifiers and GLFW_MOD_NUM_LOCK != 0) add(KeyCode.NUM_LOCK) + } + val name: String - get() = if (isMouseButton) "Mouse $code" else keyCode.name + get() = buildString { + if (mouse >= 0) append("${Mouse.Button.fromMouseCode(mouse)} + ") + if (modifiers > 0) append("${truemods.joinToString(separator = "+") { it.name }} +") + if (key > 0) append(KeyCode.fromKeyCode(key)) + + if (mouse < 0 && modifiers <= 0 && key <= 0) append("Unbound") + } override fun toString() = - "Key Code: $keyCode, Code: $code, Mouse Button: $isMouseButton" + "Key Code: $key" companion object { - val EMPTY = Bind() + val EMPTY = Bind(0, 0) - fun mouseBind(code: Int) = Bind(code = code, isMouseButton = true) + fun mouseBind(code: Int) = Bind(0, 0, code) } } diff --git a/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt b/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt index 146305a9f..491bbc97d 100644 --- a/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt +++ b/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt @@ -17,6 +17,7 @@ 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_MOD_ALT @@ -54,6 +55,8 @@ sealed class KeyboardEvent { val isPressed = action == GLFW_PRESS val isReleased = action == GLFW_RELEASE + fun satisfies(bind: Bind) = bind.key == keyCode && bind.modifiers == modifiers + val hasShift = modifiers and GLFW_MOD_SHIFT != 0 val hasControl = modifiers and GLFW_MOD_CONTROL != 0 val hasAlt = modifiers and GLFW_MOD_ALT != 0 diff --git a/src/main/kotlin/com/lambda/event/events/MouseEvent.kt b/src/main/kotlin/com/lambda/event/events/MouseEvent.kt index f732c7db9..6c6daff2b 100644 --- a/src/main/kotlin/com/lambda/event/events/MouseEvent.kt +++ b/src/main/kotlin/com/lambda/event/events/MouseEvent.kt @@ -17,6 +17,7 @@ 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.Mouse @@ -50,6 +51,8 @@ sealed class MouseEvent { position ) + fun satisfies(bind: Bind) = bind.modifiers == modifiers && bind.mouse == button + val isMainButton = button <= 2 val isSideButton = button > 2 val isLeftButton = button == 0 diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index 0ee2d539a..70b2f35c5 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -17,7 +17,7 @@ package com.lambda.module -import com.lambda.Lambda.mc +import com.lambda.Lambda import com.lambda.command.LambdaCommand import com.lambda.config.AbstractSetting import com.lambda.config.Configurable @@ -135,13 +135,24 @@ abstract class Module( init { listen(alwaysListen = true) { event -> - onButtonPress(event.keyCode, event.isPressed, event.isReleased) + if (Lambda.mc.options.commandKey.isPressed + || Lambda.mc.currentScreen != null + || !event.satisfies(keybind)) return@listen + + if (event.isPressed) toggle() + else if (event.isReleased && disableOnRelease) disable() } listen(alwaysListen = true) { event -> val pressed = event.action == Mouse.Action.Click.ordinal val released = event.action == Mouse.Action.Release.ordinal - onButtonPress(event.button, pressed, released) + + if (mc.options.commandKey.isPressed + || mc.currentScreen != null + || !event.satisfies(keybind)) return@listen + + if (pressed) toggle() + else if (released && disableOnRelease) disable() } onEnable { LambdaSound.MODULE_ON.play() } @@ -155,14 +166,6 @@ abstract class Module( listen { if (autoDisable) disable() } } - private fun onButtonPress(code: Int, pressed: Boolean, released: Boolean) { - if (mc.options.commandKey.isPressed) return - if (mc.currentScreen != null) return - if (code != keybind.code) return - if (pressed) toggle() - else if (released && disableOnRelease) disable() - } - fun enable() { isEnabled = true } diff --git a/src/main/kotlin/com/lambda/module/hud/ModuleList.kt b/src/main/kotlin/com/lambda/module/hud/ModuleList.kt index 6c9db4065..d0522dddb 100644 --- a/src/main/kotlin/com/lambda/module/hud/ModuleList.kt +++ b/src/main/kotlin/com/lambda/module/hud/ModuleList.kt @@ -39,7 +39,7 @@ object ModuleList : HudModule( enabled.forEach { text(it.name); sameLine() - val color = if (it.keybind.code == KeyCode.UNBOUND.code) Color.RED else Color.GREEN + val color = if (it.keybind.key == 0 && it.keybind.mouse == -1) Color.RED else Color.GREEN withStyleColor(ImGuiCol.Text, color) { text(" [${it.keybind.name}]") } } diff --git a/src/main/kotlin/com/lambda/util/Communication.kt b/src/main/kotlin/com/lambda/util/Communication.kt index 81ea3d0cc..9da68ad56 100644 --- a/src/main/kotlin/com/lambda/util/Communication.kt +++ b/src/main/kotlin/com/lambda/util/Communication.kt @@ -179,8 +179,8 @@ object Communication { } literal("Keybind: ") color(ClickGuiLayout.primaryColor) { - if (module.keybind.code != -1) { - literal(module.keybind.code.toString()) + if (module.keybind.key != 0 || module.keybind.mouse > -1) { + literal(module.keybind.name) } else { literal("Unbound") } diff --git a/src/main/kotlin/com/lambda/util/InputUtils.kt b/src/main/kotlin/com/lambda/util/InputUtils.kt index c272f5102..f76fb8e41 100644 --- a/src/main/kotlin/com/lambda/util/InputUtils.kt +++ b/src/main/kotlin/com/lambda/util/InputUtils.kt @@ -26,8 +26,8 @@ import com.lambda.util.math.Vec2d import net.minecraft.client.util.InputUtil object InputUtils : Loadable { - var lastKeyboardEvent: KeyboardEvent.Press = KeyboardEvent.Press(0, 0, -1, 0); private set - var lastMouseEvent: MouseEvent.Click = MouseEvent.Click(Mouse.Button.Left, Mouse.Action.Click, 0, Vec2d(0, 0)); private set + var lastKeyboardEvent: KeyboardEvent.Press? = null; private set + var lastMouseEvent: MouseEvent.Click? = null; private set /** * Returns whether any of the key-codes (not scan-codes) are being pressed From b758103c2898ea6b0c71c8a927ea7e00d63f255e Mon Sep 17 00:00:00 2001 From: Edouard127 <46357922+Edouard127@users.noreply.github.com> Date: Sun, 19 Oct 2025 09:09:43 -0400 Subject: [PATCH 4/8] Added mouse click pressed/released --- src/main/kotlin/com/lambda/event/events/MouseEvent.kt | 3 +++ src/main/kotlin/com/lambda/module/Module.kt | 9 +++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/com/lambda/event/events/MouseEvent.kt b/src/main/kotlin/com/lambda/event/events/MouseEvent.kt index 6c6daff2b..22ea7c899 100644 --- a/src/main/kotlin/com/lambda/event/events/MouseEvent.kt +++ b/src/main/kotlin/com/lambda/event/events/MouseEvent.kt @@ -53,6 +53,9 @@ sealed class MouseEvent { fun satisfies(bind: Bind) = bind.modifiers == modifiers && bind.mouse == button + val isReleased = action == 0 + val isPressed = action == 1 + val isMainButton = button <= 2 val isSideButton = button > 2 val isLeftButton = button == 0 diff --git a/src/main/kotlin/com/lambda/module/Module.kt b/src/main/kotlin/com/lambda/module/Module.kt index c6eb7b05a..fc9d16525 100644 --- a/src/main/kotlin/com/lambda/module/Module.kt +++ b/src/main/kotlin/com/lambda/module/Module.kt @@ -137,7 +137,7 @@ abstract class Module( init { listen(alwaysListen = true) { event -> - if (Lambda.mc.options.commandKey.isPressed + if (mc.options.commandKey.isPressed || Lambda.mc.currentScreen != null || !event.satisfies(keybind)) return@listen @@ -146,15 +146,12 @@ abstract class Module( } listen(alwaysListen = true) { event -> - val pressed = event.action == Mouse.Action.Click.ordinal - val released = event.action == Mouse.Action.Release.ordinal - if (mc.options.commandKey.isPressed || mc.currentScreen != null || !event.satisfies(keybind)) return@listen - if (pressed) toggle() - else if (released && disableOnRelease) disable() + if (event.isPressed) toggle() + else if (event.isReleased && disableOnRelease) disable() } onEnable { LambdaSound.MODULE_ON.play() } From 82bbb73bc015f7e90587794bf2397cd577193426 Mon Sep 17 00:00:00 2001 From: Edouard127 <46357922+Edouard127@users.noreply.github.com> Date: Sun, 19 Oct 2025 11:05:19 -0400 Subject: [PATCH 5/8] Fixed bind logic --- .../config/settings/complex/KeybindSetting.kt | 68 ++++++++--------- .../com/lambda/event/events/KeyboardEvent.kt | 9 +-- .../com/lambda/event/events/MouseEvent.kt | 24 +----- src/main/kotlin/com/lambda/util/InputUtils.kt | 74 ++++++++++++++++--- src/main/kotlin/com/lambda/util/Mouse.kt | 55 +++----------- 5 files changed, 110 insertions(+), 120 deletions(-) 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 6ea88c42a..a4b232031 100644 --- a/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/complex/KeybindSetting.kt @@ -81,16 +81,8 @@ class KeybindSetting( } lambdaTooltip { - if (!listening) { - description.ifBlank { "Click to set. Right-click to unbind. Esc cancels. Backspace/Delete unbinds." } - } else { - "Listening… Press a key to bind. Esc to cancel. Backspace/Delete to unbind." - } - } - - onItemClick(ImGuiMouseButton.Right) { - value = Bind.EMPTY - listening = false + if (!listening) description.ifBlank { "Click to set. Esc cancels. Backspace/Delete unbinds." } + else "Listening… Press a key to bind. Esc to cancel. Backspace/Delete to unbind." } if (listening && !isAnyItemHovered && isMouseClicked(ImGuiMouseButton.Left)) { @@ -106,25 +98,31 @@ class KeybindSetting( lambdaTooltip("Clear binding") } - val keypoll = InputUtils.lastKeyboardEvent ?: return - val mousepoll = InputUtils.lastMouseEvent ?: return - if (listening) { - val isModKey = keypoll.keyCode in GLFW_KEY_LEFT_SHIFT..GLFW_KEY_RIGHT_SUPER - - if ((keypoll.isPressed && !isModKey) - || (keypoll.isReleased && isModKey) - ) { - when (keypoll.translated) { - KeyCode.ESCAPE -> {} - KeyCode.BACKSPACE, KeyCode.DELETE -> value = Bind.EMPTY - else -> value = Bind(keypoll.keyCode, keypoll.modifiers, -1) + InputUtils.newMouseEvent() + ?.let { + value = Bind(0, it.modifiers, it.button) + listening = false + return + } + + InputUtils.newKeyboardEvent() + ?.let { + val isModKey = it.keyCode in GLFW_KEY_LEFT_SHIFT..GLFW_KEY_RIGHT_SUPER + + // If a mod key is pressed first ignore it unless it was released without any other keys + if ((it.isPressed && !isModKey) || (it.isReleased && isModKey)) { + when (it.translated) { + KeyCode.ESCAPE -> {} + KeyCode.BACKSPACE, KeyCode.DELETE -> value = Bind.EMPTY + else -> value = Bind(it.keyCode, it.modifiers, -1) + } + + listening = false + } + + return } - listening = false - } else if (mousepoll.action == Mouse.Action.Click.ordinal) { - value = Bind(0, mousepoll.modifiers, mousepoll.button) - listening = false - } } } @@ -177,16 +175,20 @@ data class Bind( } val name: String - get() = buildString { - if (mouse >= 0) append("${Mouse.Button.fromMouseCode(mouse)} + ") - if (modifiers > 0) append("${truemods.joinToString(separator = "+") { it.name }} +") - if (key > 0) append(KeyCode.fromKeyCode(key)) + get() { + if (mouse < 0 && modifiers <= 0 && key <= 0) return "Unbound" + + val list = mutableListOf() + + if (mouse >= 0) list.add(Mouse.entries[mouse]) + if (modifiers > 0) list.add(truemods.joinToString(separator = "+") { it.name }) + if (key > 0) list.add(KeyCode.fromKeyCode(key)) - if (mouse < 0 && modifiers <= 0 && key <= 0) append("Unbound") + return list.joinToString(separator = "+") { it.toString() } } override fun toString() = - "Key Code: $key" + "Key Code: $key, Modifiers: ${truemods.joinToString(separator = "+") { it.name }}, Mouse Button: ${Mouse.entries.getOrNull(mouse) ?: "None"}" companion object { val EMPTY = Bind(0, 0) diff --git a/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt b/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt index 491bbc97d..487737e77 100644 --- a/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt +++ b/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt @@ -52,17 +52,10 @@ sealed class KeyboardEvent { val translated: KeyCode get() = KeyCode.virtualMapUS(keyCode, scanCode) - val isPressed = action == GLFW_PRESS + val isPressed = action >= GLFW_PRESS val isReleased = action == GLFW_RELEASE fun satisfies(bind: Bind) = bind.key == keyCode && bind.modifiers == modifiers - - val hasShift = modifiers and GLFW_MOD_SHIFT != 0 - val hasControl = modifiers and GLFW_MOD_CONTROL != 0 - val hasAlt = modifiers and GLFW_MOD_ALT != 0 - val hasSuper = modifiers and GLFW_MOD_SUPER != 0 - val hasCapsLock = modifiers and GLFW_MOD_CAPS_LOCK != 0 - val hasNumLock = modifiers and GLFW_MOD_NUM_LOCK != 0 } /** diff --git a/src/main/kotlin/com/lambda/event/events/MouseEvent.kt b/src/main/kotlin/com/lambda/event/events/MouseEvent.kt index 22ea7c899..605c292a4 100644 --- a/src/main/kotlin/com/lambda/event/events/MouseEvent.kt +++ b/src/main/kotlin/com/lambda/event/events/MouseEvent.kt @@ -36,38 +36,16 @@ sealed class MouseEvent { * @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 - * @property position The x and y position of the mouse on the screen */ data class Click( val button: Int, val action: Int, val modifiers: Int, - val position: Vec2d, ) : ICancellable by Cancellable() { - constructor(button: Mouse.Button, action: Mouse.Action, modifiers: Int, position: Vec2d) : this( - button.ordinal, - action.ordinal, - modifiers, - position - ) - - fun satisfies(bind: Bind) = bind.modifiers == modifiers && bind.mouse == button - val isReleased = action == 0 val isPressed = action == 1 - val isMainButton = button <= 2 - val isSideButton = button > 2 - val isLeftButton = button == 0 - val isRightButton = button == 1 - val isMiddleButton = button == 2 - - val hasShift = hasModifier(GLFW_MOD_SHIFT) - val hasControl = hasModifier(GLFW_MOD_CONTROL) - val hasAlt = hasModifier(GLFW_MOD_ALT) - val hasSuper = hasModifier(GLFW_MOD_SUPER) - val hasCapsLock = hasModifier(GLFW_MOD_CAPS_LOCK) - val hasNumLock = hasModifier(GLFW_MOD_NUM_LOCK) + fun satisfies(bind: Bind) = bind.modifiers == modifiers && bind.mouse == button fun hasModifier(mod: Int) = modifiers and mod == mod } diff --git a/src/main/kotlin/com/lambda/util/InputUtils.kt b/src/main/kotlin/com/lambda/util/InputUtils.kt index f76fb8e41..c5f6d7e41 100644 --- a/src/main/kotlin/com/lambda/util/InputUtils.kt +++ b/src/main/kotlin/com/lambda/util/InputUtils.kt @@ -17,27 +17,81 @@ package com.lambda.util +import com.lambda.Lambda.mc 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.listener.UnsafeListener.Companion.listenUnsafe -import com.lambda.util.math.Vec2d -import net.minecraft.client.util.InputUtil +import org.lwjgl.glfw.GLFW +import org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_ALT +import org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_CONTROL +import org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SHIFT +import org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SUPER +import org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT_ALT +import org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT_CONTROL +import org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT_SHIFT +import org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT_SUPER +import org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_1 +import org.lwjgl.glfw.GLFW.GLFW_MOUSE_BUTTON_8 +import org.lwjgl.glfw.GLFW.GLFW_PRESS +import org.lwjgl.glfw.GLFW.glfwGetKey +import org.lwjgl.glfw.GLFW.glfwGetMouseButton object InputUtils : Loadable { - var lastKeyboardEvent: KeyboardEvent.Press? = null; private set - var lastMouseEvent: MouseEvent.Click? = null; private set + private val keys = KeyCode.entries.map { it.code } + private val scancodes = keys.associateWith { GLFW.glfwGetKeyScancode(it) } + + private val mouses = GLFW_MOUSE_BUTTON_1..GLFW_MOUSE_BUTTON_8 + + private val modMap = mapOf( + GLFW_KEY_LEFT_SHIFT to 0x1, + GLFW_KEY_RIGHT_SHIFT to 0x1, + GLFW_KEY_LEFT_CONTROL to 0x2, + GLFW_KEY_RIGHT_CONTROL to 0x2, + GLFW_KEY_LEFT_ALT to 0x4, + GLFW_KEY_RIGHT_ALT to 0x4, + GLFW_KEY_LEFT_SUPER to 0x8, + GLFW_KEY_RIGHT_SUPER to 0x8, + ) /** * Returns whether any of the key-codes (not scan-codes) are being pressed */ fun SafeContext.isKeyPressed(vararg keys: Int) = - keys.any { InputUtil.isKeyPressed(mc.window.handle, it) } + keys.any { glfwGetKey(mc.window.handle, it) >= GLFW_PRESS } + + /** + * Creates a new event from the currently pressed keys + */ + fun newKeyboardEvent(): KeyboardEvent.Press? { + val pressedKeys = keys + .associateWith { glfwGetKey(mc.window.handle, it) } + .filter { (_, state) -> state >= GLFW_PRESS } + + val mods = pressedKeys.keys + .filter { it in GLFW_KEY_LEFT_SHIFT..GLFW_KEY_RIGHT_SUPER } + .foldRight(0) { v, acc -> acc or modMap.getValue(v) } + + val key = pressedKeys + .firstNotNullOfOrNull { (key, state) -> key to state } ?: return null + + val scancode = scancodes.getValue(key.first) + + return KeyboardEvent.Press(key.first, scancode, key.second, mods) + } + + /** + * Creates a new mouse event from the current glfw states. + */ + fun newMouseEvent(): MouseEvent.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) } + + val mouse = mouses + .firstOrNull { glfwGetMouseButton(mc.window.handle, it) == GLFW_PRESS } + ?: return null - init { - // hacking imgui jni lib rn because it's missing a lot of native functions including i/o stuff - listenUnsafe { lastKeyboardEvent = it } - listenUnsafe { lastMouseEvent = it } + return MouseEvent.Click(mouse, GLFW_PRESS, mods) } } diff --git a/src/main/kotlin/com/lambda/util/Mouse.kt b/src/main/kotlin/com/lambda/util/Mouse.kt index 5a93735ba..e82054fbd 100644 --- a/src/main/kotlin/com/lambda/util/Mouse.kt +++ b/src/main/kotlin/com/lambda/util/Mouse.kt @@ -17,50 +17,13 @@ package com.lambda.util -import org.lwjgl.glfw.GLFW - -class Mouse { - enum class Button { - Left, - Right, - Middle, - Button4, - Button5, - Button6, - Button7, - Button8; - - val isMainButton get() = ordinal == GLFW.GLFW_MOUSE_BUTTON_LEFT || ordinal == GLFW.GLFW_MOUSE_BUTTON_RIGHT - - companion object { - private val mouseCodeMap = entries.associateBy { it.ordinal } - private val nameMap = entries.associateBy { it.name.lowercase() } - - @Throws(IllegalArgumentException::class) - fun fromMouseCode(code: Int) = - mouseCodeMap[code] ?: throw IllegalArgumentException("Mouse code $code not found in mouseCodeMap.") - - @Throws(IllegalArgumentException::class) - fun fromMouseName(name: String) = - nameMap[name.lowercase()] ?: throw IllegalArgumentException("Mouse name '$name' not found in nameMap.") - } - } - - enum class Action { - Release, - Click; - - companion object { - private val mouseActionMap = entries.associateBy { it.ordinal } - private val nameMap = entries.associateBy { it.name.lowercase() } - - @Throws(IllegalArgumentException::class) - fun fromActionCode(code: Int) = - mouseActionMap[code] ?: throw IllegalArgumentException("Action code $code not found in mouseActionMap.") - - @Throws(IllegalArgumentException::class) - fun fromActionName(name: String) = - nameMap[name.lowercase()] ?: throw IllegalArgumentException("Action name '$name' not found in nameMap.") - } - } +enum class Mouse { + Left, + Right, + Middle, + Button4, + Button5, + Button6, + Button7, + Button8; } From 6790b29a76ce37a719c60f05f1a43d2024c76b95 Mon Sep 17 00:00:00 2001 From: Edouard127 <46357922+Edouard127@users.noreply.github.com> Date: Sun, 19 Oct 2025 11:05:29 -0400 Subject: [PATCH 6/8] Added proper key binds for click friend --- .../module/modules/player/ClickFriend.kt | 34 +++++-------------- 1 file changed, 9 insertions(+), 25 deletions(-) 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 9a5a16f24..34805829b 100644 --- a/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt +++ b/src/main/kotlin/com/lambda/module/modules/player/ClickFriend.kt @@ -17,6 +17,7 @@ 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.friend.FriendManager @@ -26,49 +27,32 @@ 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.Mouse import com.lambda.util.world.raycast.RayCastUtils.entityResult import net.minecraft.client.network.OtherClientPlayerEntity -import org.lwjgl.glfw.GLFW.GLFW_MOD_ALT -import org.lwjgl.glfw.GLFW.GLFW_MOD_CAPS_LOCK -import org.lwjgl.glfw.GLFW.GLFW_MOD_CONTROL -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 +import org.lwjgl.glfw.GLFW object ClickFriend : Module( name = "ClickFriend", description = "Add or remove friends with a single click", tag = ModuleTag.PLAYER, ) { - private val friendButton by setting("Friend Button", Mouse.Button.Middle, description = "Button to press to befriend a player") - private val friendAction by setting("Action", Mouse.Action.Release, description = "What mouse action should add or remove the player") - private val comboUnfriend by setting("Combo Unfriend", false, description = "Press a key and right click a player to unfriend") - private val modUnfriend by setting("Combo Key", MouseMod.Shift, description = "The key to press to activate the unfriend combo") { comboUnfriend } + 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", friendBind, "Bind to press to unfriend a player") init { listen { if (mc.currentScreen != null) return@listen - if (it.button != friendButton.ordinal || it.action != friendAction.ordinal) return@listen val target = mc.crosshairTarget?.entityResult?.entity as? OtherClientPlayerEntity ?: return@listen - if (!it.hasModifier(modUnfriend.modifiers) && comboUnfriend && target.isFriend) return@listen - when { - target.isFriend && target.unfriend() -> info(FriendManager.unfriendedText(target.name)) - !target.isFriend && target.befriend() -> info(FriendManager.befriendedText(target.name)) + it.satisfies(friendBind) && !target.isFriend && target.befriend() -> + info(FriendManager.befriendedText(target.name)) + + it.satisfies(unfriendBind) && target.isFriend && target.unfriend() -> + info(FriendManager.unfriendedText(target.name)) } } } - - private enum class MouseMod(val modifiers: Int) { - Shift(GLFW_MOD_SHIFT), - Control(GLFW_MOD_CONTROL), - Alt(GLFW_MOD_ALT), - Super(GLFW_MOD_SUPER), - Caps(GLFW_MOD_CAPS_LOCK), - NumLock(GLFW_MOD_NUM_LOCK); - } } From 1e8b1df3a15b0dc77e5df40832f6bc0e976b2525 Mon Sep 17 00:00:00 2001 From: Edouard127 <46357922+Edouard127@users.noreply.github.com> Date: Sun, 19 Oct 2025 11:05:47 -0400 Subject: [PATCH 7/8] Changed some mixins injections --- .../com/lambda/mixin/input/KeyboardMixin.java | 16 +++++---- .../com/lambda/mixin/input/MouseMixin.java | 33 ++++++++----------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/lambda/mixin/input/KeyboardMixin.java b/src/main/java/com/lambda/mixin/input/KeyboardMixin.java index ffa136983..3c2368116 100644 --- a/src/main/java/com/lambda/mixin/input/KeyboardMixin.java +++ b/src/main/java/com/lambda/mixin/input/KeyboardMixin.java @@ -20,6 +20,8 @@ import com.lambda.event.EventFlow; import com.lambda.event.events.KeyboardEvent; import com.lambda.module.modules.player.InventoryMove; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import net.minecraft.client.Keyboard; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; @@ -30,9 +32,10 @@ @Mixin(Keyboard.class) public class KeyboardMixin { - @Inject(method = "onKey", at = @At("HEAD")) - private void onKey(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) { + @WrapMethod(method = "onKey") + private void onKey(long window, int key, int scancode, int action, int modifiers, Operation original) { EventFlow.post(new KeyboardEvent.Press(key, scancode, action, modifiers)); + original.call(window, key, scancode, action, modifiers); } @Inject(method = "onKey", at = @At("RETURN")) @@ -42,12 +45,13 @@ private void onKeyTail(long window, int key, int scancode, int action, int modif KeyBinding.setKeyPressed(fromCode, action != 0); } - @Inject(method = "onChar", at = @At("HEAD")) - private void onChar(long window, int codePoint, int modifiers, CallbackInfo ci) { + @WrapMethod(method = "onChar") + private void onChar(long window, int codePoint, int modifiers, Operation original) { char[] chars = Character.toChars(codePoint); - for (char c : chars) { + for (char c : chars) EventFlow.post(new KeyboardEvent.Char(c)); - } + + original.call(window, codePoint, modifiers); } } diff --git a/src/main/java/com/lambda/mixin/input/MouseMixin.java b/src/main/java/com/lambda/mixin/input/MouseMixin.java index 9802da2de..f72f697b3 100644 --- a/src/main/java/com/lambda/mixin/input/MouseMixin.java +++ b/src/main/java/com/lambda/mixin/input/MouseMixin.java @@ -21,15 +21,15 @@ import com.lambda.event.events.MouseEvent; import com.lambda.module.modules.render.Zoom; import com.lambda.util.math.Vec2d; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import net.minecraft.client.Mouse; import net.minecraft.client.option.GameOptions; 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; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Mouse.class) public class MouseMixin { @@ -37,33 +37,28 @@ public class MouseMixin { @Shadow private double y; - @Inject(method = "onMouseButton(JIII)V", at = @At("HEAD"), cancellable = true) - private void onMouseButton(long window, int button, int action, int mods, CallbackInfo ci) { - Vec2d position = new Vec2d(x, y); - - if (EventFlow.post(new MouseEvent.Click(button, action, mods, position)).isCanceled()) { - ci.cancel(); - } + @WrapMethod(method = "onMouseButton(JIII)V") + private void onMouseButton(long window, int button, int action, int mods, Operation original) { + if (!EventFlow.post(new MouseEvent.Click(button, action, mods)).isCanceled()) + original.call(window, button, action, mods); } - @Inject(method = "onMouseScroll(JDD)V", at = @At("HEAD"), cancellable = true) - private void onMouseScroll(long window, double horizontal, double vertical, CallbackInfo ci) { + @WrapMethod(method = "onMouseScroll(JDD)V") + 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()) { - ci.cancel(); - } + if (!EventFlow.post(new MouseEvent.Scroll(delta)).isCanceled()) + original.call(window, horizontal, vertical); } - @Inject(method = "onCursorPos(JDD)V", at = @At("HEAD"), cancellable = true) - private void onCursorPos(long window, double x, double y, CallbackInfo ci) { + @WrapMethod(method = "onCursorPos(JDD)V") + private void onCursorPos(long window, double x, double y, Operation original) { if (x + y == this.x + this.y) return; Vec2d position = new Vec2d(x, y); - if (EventFlow.post(new MouseEvent.Move(position)).isCanceled()) { - ci.cancel(); - } + if (!EventFlow.post(new MouseEvent.Move(position)).isCanceled()) + original.call(window, x, y); } @Redirect(method = "updateMouse", at = @At(value = "FIELD", target = "Lnet/minecraft/client/option/GameOptions;smoothCameraEnabled:Z")) From ac4089917436c022d29832cdfa7ef25268b5b6de Mon Sep 17 00:00:00 2001 From: beanbag44 Date: Sun, 19 Oct 2025 16:59:58 +0100 Subject: [PATCH 8/8] only care if the specified modifiers are pressed while ignoring extras --- .../kotlin/com/lambda/event/events/KeyboardEvent.kt | 8 +------- src/main/kotlin/com/lambda/event/events/MouseEvent.kt | 11 +---------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt b/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt index 487737e77..e14e971b5 100644 --- a/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt +++ b/src/main/kotlin/com/lambda/event/events/KeyboardEvent.kt @@ -20,12 +20,6 @@ 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_MOD_ALT -import org.lwjgl.glfw.GLFW.GLFW_MOD_CAPS_LOCK -import org.lwjgl.glfw.GLFW.GLFW_MOD_CONTROL -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 import org.lwjgl.glfw.GLFW.GLFW_PRESS import org.lwjgl.glfw.GLFW.GLFW_RELEASE @@ -55,7 +49,7 @@ sealed class KeyboardEvent { val isPressed = action >= GLFW_PRESS val isReleased = action == GLFW_RELEASE - fun satisfies(bind: Bind) = bind.key == keyCode && bind.modifiers == modifiers + fun satisfies(bind: Bind) = bind.key == keyCode && bind.modifiers and modifiers == bind.modifiers } /** diff --git a/src/main/kotlin/com/lambda/event/events/MouseEvent.kt b/src/main/kotlin/com/lambda/event/events/MouseEvent.kt index 605c292a4..427969e39 100644 --- a/src/main/kotlin/com/lambda/event/events/MouseEvent.kt +++ b/src/main/kotlin/com/lambda/event/events/MouseEvent.kt @@ -20,14 +20,7 @@ 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.Mouse import com.lambda.util.math.Vec2d -import org.lwjgl.glfw.GLFW.GLFW_MOD_ALT -import org.lwjgl.glfw.GLFW.GLFW_MOD_CAPS_LOCK -import org.lwjgl.glfw.GLFW.GLFW_MOD_CONTROL -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 sealed class MouseEvent { /** @@ -45,9 +38,7 @@ sealed class MouseEvent { val isReleased = action == 0 val isPressed = action == 1 - fun satisfies(bind: Bind) = bind.modifiers == modifiers && bind.mouse == button - - fun hasModifier(mod: Int) = modifiers and mod == mod + fun satisfies(bind: Bind) = bind.modifiers and modifiers == bind.modifiers && bind.mouse == button } /**