diff --git a/src-theme/src/integration/events.ts b/src-theme/src/integration/events.ts index 89061c6373b..02e8d9b95e9 100644 --- a/src-theme/src/integration/events.ts +++ b/src-theme/src/integration/events.ts @@ -43,6 +43,17 @@ export interface KeyEvent { mods: number; } +export interface KeyBindingEvent { + key: string; + action: number; + mods: number; +} + +export interface KeyBindingCPSEvent { + key: string; + cps: number; +} + export interface TargetChangeEvent { target: PlayerData | null; } diff --git a/src-theme/src/routes/hud/elements/keystrokes/Key.svelte b/src-theme/src/routes/hud/elements/keystrokes/Key.svelte index 34ae0ea728d..525fbe62427 100644 --- a/src-theme/src/routes/hud/elements/keystrokes/Key.svelte +++ b/src-theme/src/routes/hud/elements/keystrokes/Key.svelte @@ -1,24 +1,43 @@ -
- {key?.key.localized ?? "???"} +
+ {#if showName} + {key?.key.localized ?? "???"} + {/if} + {#if showCPS} + {cps} + {/if}
\ No newline at end of file + .keystrokes { + display: flex; + flex-wrap: wrap; + width: calc(50px * 3 + 5px * 2); + gap: 5px; + } + + .nil { + width: 50px; + } + diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/api/oauth/OAuthClient.kt b/src/main/kotlin/net/ccbluex/liquidbounce/api/oauth/OAuthClient.kt index b0dedc01603..ba76f9430c4 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/api/oauth/OAuthClient.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/api/oauth/OAuthClient.kt @@ -33,7 +33,7 @@ object OAuthClient { private var authCodeContinuation: Continuation? = null fun runWithScope(block: suspend CoroutineScope.() -> Unit) { - scope.launch { block() } + scope.launch(block = block) } suspend fun startAuth(onUrl: (String) -> Unit): ClientAccount { diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/event/EventManager.kt b/src/main/kotlin/net/ccbluex/liquidbounce/event/EventManager.kt index 86197ffa4ac..a40b77c79ea 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/event/EventManager.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/event/EventManager.kt @@ -50,6 +50,8 @@ val ALL_EVENT_CLASSES: Array> = arrayOf( KeyEvent::class, MouseRotationEvent::class, KeybindChangeEvent::class, + KeyBindingEvent::class, + KeyBindingCPSEvent::class, AttackEvent::class, SessionEvent::class, ScreenEvent::class, diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/event/events/GameEvents.kt b/src/main/kotlin/net/ccbluex/liquidbounce/event/events/GameEvents.kt index 0fdc3a5025b..47109de2b91 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/event/events/GameEvents.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/event/events/GameEvents.kt @@ -49,7 +49,15 @@ class MouseRotationEvent(var cursorDeltaX: Double, var cursorDeltaY: Double) : C @Nameable("keybindChange") @WebSocketEvent -class KeybindChangeEvent: Event() +class KeybindChangeEvent : Event() + +@Nameable("keybinding") +@WebSocketEvent +class KeyBindingEvent(val key: InputUtil.Key, val action: Int, val mods: Int) : Event() + +@Nameable("keybindingCPS") +@WebSocketEvent +class KeyBindingCPSEvent(val key: InputUtil.Key, val cps: Int) : Event() @Nameable("useCooldown") class UseCooldownEvent(var cooldown: Int) : Event() diff --git a/src/main/kotlin/net/ccbluex/liquidbounce/utils/input/InputTracker.kt b/src/main/kotlin/net/ccbluex/liquidbounce/utils/input/InputTracker.kt index 5a53a7c2fe8..25b69a134a7 100644 --- a/src/main/kotlin/net/ccbluex/liquidbounce/utils/input/InputTracker.kt +++ b/src/main/kotlin/net/ccbluex/liquidbounce/utils/input/InputTracker.kt @@ -19,12 +19,15 @@ package net.ccbluex.liquidbounce.utils.input +import net.ccbluex.liquidbounce.event.EventManager import net.ccbluex.liquidbounce.event.Listenable -import net.ccbluex.liquidbounce.event.events.MouseButtonEvent +import net.ccbluex.liquidbounce.event.events.* import net.ccbluex.liquidbounce.event.handler import net.ccbluex.liquidbounce.utils.client.mc import net.minecraft.client.option.KeyBinding import net.minecraft.client.util.InputUtil +import net.minecraft.client.util.InputUtil.Type.KEYSYM +import net.minecraft.client.util.InputUtil.Type.MOUSE import org.lwjgl.glfw.GLFW /** @@ -34,8 +37,71 @@ import org.lwjgl.glfw.GLFW */ object InputTracker : Listenable { - // Tracks the state of each mouse button (pressed or not). - private val mouseStates = mutableMapOf() + private val trackers = listOf( + KeyBindingTracker(mc.options.forwardKey), + KeyBindingTracker(mc.options.backKey), + KeyBindingTracker(mc.options.leftKey), + KeyBindingTracker(mc.options.rightKey), + KeyBindingTracker(mc.options.jumpKey), + KeyBindingTracker(mc.options.attackKey), + KeyBindingTracker(mc.options.useKey), + ) + + override fun children(): List = trackers + + // Tracks CPS + class KeyBindingTracker internal constructor(val keyBinding: KeyBinding) : Listenable { + // Records clicks in latest 20 ticks (1 sec) + private val countByTick = IntArray(20) + private var tickIndex = 0 + private var currentCount = 0 + + // Sum of countByTick + var cps = 0 + private set + + var pressed = false + private set(value) { + if (value) { + currentCount++ + } + field = value + } + + @Suppress("NOTHING_TO_INLINE") + private inline fun setPressed(action: Int) { + when (action) { + GLFW.GLFW_RELEASE -> pressed = false + GLFW.GLFW_PRESS -> pressed = true + } + } + + val keyHandler = handler { + if (keyBinding.boundKey.category == KEYSYM && keyBinding.boundKey.code == it.key.code) { + setPressed(it.action) + EventManager.callEvent(KeyBindingEvent(keyBinding.boundKey, it.action, it.mods)) + } + } + + val mouseHandler = handler { + if (keyBinding.boundKey.category == MOUSE && keyBinding.boundKey.code == it.button) { + setPressed(it.action) + EventManager.callEvent(KeyBindingEvent(keyBinding.boundKey, it.action, it.mods)) + } + } + + val tickHandler = handler { + cps -= countByTick[tickIndex] + countByTick[tickIndex] = currentCount + cps += currentCount + currentCount = 0 + tickIndex = (tickIndex + 1) % countByTick.size + EventManager.callEvent(KeyBindingCPSEvent(keyBinding.boundKey, cps)) + } + } + + // Tracks the state of each mouse button. + private val mouseStates = IntArray(32) /** * Extension property that checks if a key binding is pressed on either the keyboard or mouse. @@ -68,7 +134,7 @@ object InputTracker : Listenable { */ @Suppress("unused") private val handleMouseAction = handler { - mouseStates[it.button] = it.action == GLFW.GLFW_PRESS + mouseStates[it.button] = it.action } /** @@ -77,5 +143,5 @@ object InputTracker : Listenable { * @param button The GLFW code of the mouse button. * @return True if the mouse button is pressed, false otherwise. */ - fun isMouseButtonPressed(button: Int): Boolean = mouseStates.getOrDefault(button, false) + fun isMouseButtonPressed(button: Int): Boolean = mouseStates[button] == GLFW.GLFW_PRESS }