Skip to content

Commit

Permalink
Mouse bindings (#379)
Browse files Browse the repository at this point in the history
* Mouse bindings

* Allow mid click bindings and use button name numbers instead of index

Human-readable mouse names start with 1. Using this scheme aligns with what you'd see in RusherHack for example. To accomplish this, any raw mouse input that comes as an index we simply increment by 1.

I'm planning on PR'ing a hud module that shows all bindings, again like in Rusherhack. So this would trigger my OCD having those bind names not align between clients.

* fix comment and comparisons for clarity

* clarify what min index means

* Cleanup and cast safety

* More null safety (!! can throw an exception)

also mousekey is concurrent and may change after first null check.

Co-authored-by: Constructor <fractalminds@protonmail.com>
  • Loading branch information
rfresh2 and Avanatiker authored Sep 30, 2022
1 parent 3dcbc8a commit 9b36ff4
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 19 deletions.
13 changes: 8 additions & 5 deletions src/main/kotlin/com/lambda/client/event/ForgeEventProcessor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import net.minecraftforge.fml.common.gameevent.InputEvent
import net.minecraftforge.fml.common.gameevent.TickEvent
import net.minecraftforge.fml.common.network.FMLNetworkEvent
import org.lwjgl.input.Keyboard
import org.lwjgl.input.Mouse

internal object ForgeEventProcessor {
private val mc = Wrapper.minecraft
Expand Down Expand Up @@ -82,6 +83,13 @@ internal object ForgeEventProcessor {
ModuleManager.onBind(Keyboard.getEventKey())
}

@SubscribeEvent
fun onEventMouse(event: InputEvent.MouseInputEvent) {
LambdaEventBus.post(event)
if (!Mouse.getEventButtonState()) return
ModuleManager.onMouseBind(Mouse.getEventButton() + 1)
}

@SubscribeEvent(priority = EventPriority.HIGHEST)
fun onChatSent(event: ClientChatEvent) {
MessageDetection.Command.BARITONE.removedOrNull(event.message)?.let {
Expand All @@ -94,11 +102,6 @@ internal object ForgeEventProcessor {
}
}

@SubscribeEvent
fun onEventMouse(event: InputEvent.MouseInputEvent) {
LambdaEventBus.post(event)
}

/**
* Includes events of subclasses like ChunkEvent and GetCollisionBoxesEvent
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.lambda.client.module.modules.client.ClickGUI
import com.lambda.client.module.modules.client.CustomFont
import com.lambda.client.module.modules.client.GuiColors
import com.lambda.client.setting.settings.impl.other.BindSetting
import com.lambda.client.util.Bind.Companion.minMouseIndex
import com.lambda.client.util.graphics.VertexHelper
import com.lambda.client.util.graphics.font.FontRenderAdapter
import com.lambda.client.util.math.Vec2f
Expand All @@ -20,6 +21,11 @@ class BindButton(

override fun onRelease(mousePos: Vec2f, buttonId: Int) {
super.onRelease(mousePos, buttonId)
if (listening && buttonId >= minMouseIndex) {
setting.value.apply {
setMouseBind(buttonId + 1)
}
}
listening = !listening
}

Expand Down
12 changes: 9 additions & 3 deletions src/main/kotlin/com/lambda/client/module/ModuleManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,15 @@ object ModuleManager : AsyncLoader<List<Class<out AbstractModule>>> {

internal fun onBind(eventKey: Int) {
if (Keyboard.isKeyDown(Keyboard.KEY_F3)) return // if key is the 'none' key (stuff like mod key in i3 might return 0)
for (module in modules) {
if (module.bind.value.isDown(eventKey)) module.toggle()
}
modules.filter {
it.bind.value.isDown(eventKey)
}.forEach { it.toggle() }
}

internal fun onMouseBind(eventMouse: Int) {
modules.filter {
it.bind.value.isMouseDown(eventMouse)
}.forEach { it.toggle() }
}

fun getModuleOrNull(moduleName: String?) = moduleName?.let { moduleSet[it] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class BindSetting(
description: String = ""
) : ImmutableSetting<Bind>(name, value, visibility, { _, input -> input }, description, unit = "") {

override val defaultValue: Bind = Bind(TreeSet(value.modifierKeys), value.key)
override val defaultValue: Bind = Bind(TreeSet(value.modifierKeys), value.key, null)

override fun resetValue() {
value.setBind(defaultValue.modifierKeys, defaultValue.key)
Expand All @@ -25,6 +25,12 @@ class BindSetting(
value.clear()
return
}
if (valueIn.startsWith("Mouse", ignoreCase = true)) {
valueIn.split("Mouse").lastOrNull()?.toIntOrNull()?.let {
value.setMouseBind(it)
}
return
}

val splitNames = valueIn.split('+')
val lastKey = KeyboardUtils.getKey(splitNames.last())
Expand Down
45 changes: 36 additions & 9 deletions src/main/kotlin/com/lambda/client/util/Bind.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@ import java.util.*

class Bind(
modifierKeysIn: TreeSet<Int>,
keyIn: Int
keyIn: Int,
mouseIn: Int?
) {

constructor() : this(0)

constructor(key: Int) : this(TreeSet(keyComparator), key)
constructor(key: Int) : this(TreeSet(keyComparator), key, null)

constructor(vararg modifierKeys: Int, key: Int) : this(TreeSet(keyComparator).apply { modifierKeys.forEach { add(it) } }, key)
constructor(vararg modifierKeys: Int, key: Int) : this(TreeSet(keyComparator).apply { modifierKeys.forEach { add(it) } }, key, null)

val modifierKeys = modifierKeysIn
var key = keyIn; private set
var mouseKey = mouseIn; private set

private var cachedName = getName()

val isEmpty get() = key !in 1..255
val isEmpty get() = key !in 1..255 && compareValues(mouseKey, minMouseIndex) < 0

fun isDown(eventKey: Int): Boolean {
return eventKey != 0
Expand All @@ -27,6 +30,12 @@ class Bind(
&& synchronized(this) { modifierKeys.all { isModifierKeyDown(eventKey, it) } }
}

fun isMouseDown(eventKey: Int): Boolean {
return eventKey > minMouseIndex
&& !isEmpty
&& mouseKey == (eventKey)
}

private fun isModifierKeyDown(eventKey: Int, modifierKey: Int) =
eventKey != modifierKey
&& when (modifierKey) {
Expand Down Expand Up @@ -62,11 +71,21 @@ class Bind(
setBind(cache, keyIn)
}

fun setMouseBind(mouseIn: Int) {
synchronized(this) {
modifierKeys.clear()
key = 0
mouseKey = mouseIn
cachedName = getName()
}
}

fun setBind(modifierKeysIn: Collection<Int>, keyIn: Int) {
synchronized(this) {
modifierKeys.clear()
modifierKeys.addAll(modifierKeysIn)
key = keyIn
mouseKey = null
cachedName = getName()
}
}
Expand All @@ -75,6 +94,7 @@ class Bind(
synchronized(this) {
modifierKeys.clear()
key = 0
mouseKey = null
cachedName = getName()
}
}
Expand All @@ -88,18 +108,25 @@ class Bind(
"None"
} else {
StringBuilder().run {
for (key in modifierKeys) {
val name = modifierName[key] ?: KeyboardUtils.getDisplayName(key) ?: continue
append(name)
append('+')
mouseKey?.let {
if (it > minMouseIndex) append("Mouse$mouseKey")
} ?: run {
for (key in modifierKeys) {
val name = modifierName[key] ?: KeyboardUtils.getDisplayName(key) ?: continue
append(name)
append('+')
}
append(KeyboardUtils.getDisplayName(key))
}
append(KeyboardUtils.getDisplayName(key))

toString()
}
}
}

companion object {
const val minMouseIndex: Int = 2 // middle click button index. Button number = index + 1.

private val modifierName: Map<Int, String> = hashMapOf(
Keyboard.KEY_LCONTROL to "Ctrl",
Keyboard.KEY_RCONTROL to "Ctrl",
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/lambda/client/util/KeyboardUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ object KeyboardUtils {
fun sendUnknownKeyError(bind: String) {
MessageSendHelper.sendErrorMessage("Unknown key [${formatValue(bind)}]! " +
"Right shift is ${formatValue("rshift")}, " +
"left Control is ${formatValue("lcontrol")}, " +
"left control is ${formatValue("lcontrol")}, " +
"and ` is ${formatValue("grave")}. " +
"You cannot bind the ${formatValue("meta")} key."
)
Expand Down

0 comments on commit 9b36ff4

Please sign in to comment.