From ceb142f1653ef36d2a9c4ed6773f27a9faedcc6a Mon Sep 17 00:00:00 2001 From: Constructor Date: Mon, 13 Jan 2025 02:04:27 +0100 Subject: [PATCH 1/5] Fixed rate timer based TickEvent --- .../main/kotlin/com/lambda/event/EventFlow.kt | 13 +++++ .../com/lambda/event/events/ClientEvent.kt | 2 + .../com/lambda/event/listener/SafeListener.kt | 3 +- .../lambda/module/modules/debug/TimerTest.kt | 48 +++++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 common/src/main/kotlin/com/lambda/module/modules/debug/TimerTest.kt diff --git a/common/src/main/kotlin/com/lambda/event/EventFlow.kt b/common/src/main/kotlin/com/lambda/event/EventFlow.kt index 894b6795c..4b059840c 100644 --- a/common/src/main/kotlin/com/lambda/event/EventFlow.kt +++ b/common/src/main/kotlin/com/lambda/event/EventFlow.kt @@ -19,12 +19,14 @@ package com.lambda.event import com.lambda.context.SafeContext import com.lambda.event.callback.ICancellable +import com.lambda.event.events.ClientEvent import com.lambda.event.listener.Listener import com.lambda.threading.runConcurrent import com.lambda.threading.runSafe import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.* +import kotlin.concurrent.fixedRateTimer /** @@ -76,6 +78,17 @@ object EventFlow { */ val concurrentListeners = Subscriber() + init { + fixedRateTimer( + daemon = true, + name = "Scheduler-Lambda-Tick", + initialDelay = 50L, + period = 50L + ) { + ClientEvent.FixedTick().post() + } + } + fun Any.unsubscribe() { syncListeners.unsubscribe(this) concurrentListeners.unsubscribe(this) diff --git a/common/src/main/kotlin/com/lambda/event/events/ClientEvent.kt b/common/src/main/kotlin/com/lambda/event/events/ClientEvent.kt index 1468ff092..5557f86d6 100644 --- a/common/src/main/kotlin/com/lambda/event/events/ClientEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/ClientEvent.kt @@ -44,4 +44,6 @@ sealed class ClientEvent { * Triggered before playing a sound */ data class Sound(val sound: SoundInstance) : ICancellable by Cancellable() + + class FixedTick : Event } diff --git a/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt b/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt index 847d6ee1d..f1cf5942e 100644 --- a/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt +++ b/common/src/main/kotlin/com/lambda/event/listener/SafeListener.kt @@ -22,6 +22,7 @@ import com.lambda.event.Event import com.lambda.event.EventFlow import com.lambda.event.Muteable import com.lambda.threading.runConcurrent +import com.lambda.threading.runGameScheduled import com.lambda.threading.runSafe import com.lambda.util.Pointer import com.lambda.util.selfReference @@ -121,7 +122,7 @@ class SafeListener( noinline function: SafeContext.(T) -> Unit = {}, ): SafeListener { val listener = SafeListener(priority, this, alwaysListen) { event -> - function(event) + runGameScheduled { function(event) } } EventFlow.syncListeners.subscribe(listener) diff --git a/common/src/main/kotlin/com/lambda/module/modules/debug/TimerTest.kt b/common/src/main/kotlin/com/lambda/module/modules/debug/TimerTest.kt new file mode 100644 index 000000000..cfbd81e45 --- /dev/null +++ b/common/src/main/kotlin/com/lambda/module/modules/debug/TimerTest.kt @@ -0,0 +1,48 @@ +/* + * 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.module.modules.debug + +import com.lambda.event.events.ClientEvent +import com.lambda.event.listener.SafeListener.Companion.listen +import com.lambda.event.listener.SafeListener.Companion.listenConcurrently +import com.lambda.module.Module +import com.lambda.module.tag.ModuleTag +import com.lambda.util.Communication.info +import com.lambda.util.KeyCode +import net.minecraft.block.Blocks +import net.minecraft.util.math.BlockPos +import java.awt.Color + +object TimerTest : Module( + name = "TimerTest", + defaultTags = setOf(ModuleTag.DEBUG) +) { + private var last = 0L + + init { + listen { + val now = System.currentTimeMillis() + info("${now - last} - Fixed Tick on game thread") + last = now + } + + listenConcurrently { +// info("${System.currentTimeMillis()} - Fixed Tick Concurrently (but not on mc game thread)") + } + } +} \ No newline at end of file From 531b325de8eaf72a64b46fe3b850fb52458d19c7 Mon Sep 17 00:00:00 2001 From: Constructor Date: Mon, 13 Jan 2025 03:16:57 +0100 Subject: [PATCH 2/5] Make GUI ticking fixed rate --- .../kotlin/com/lambda/core/TimerManager.kt | 24 ++++++++++++++++++- .../main/kotlin/com/lambda/event/EventFlow.kt | 14 +---------- .../com/lambda/event/events/ClientEvent.kt | 14 +++++++++-- .../lambda/graphics/animation/Animation.kt | 5 ++-- .../graphics/renderer/esp/impl/ESPRenderer.kt | 3 ++- .../kotlin/com/lambda/gui/api/LambdaGui.kt | 4 ++-- .../lambda/module/modules/movement/Speed.kt | 2 +- .../module/modules/movement/TickShift.kt | 2 +- .../lambda/module/modules/movement/Timer.kt | 2 +- 9 files changed, 45 insertions(+), 25 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/core/TimerManager.kt b/common/src/main/kotlin/com/lambda/core/TimerManager.kt index d370f0f79..4b10ba084 100644 --- a/common/src/main/kotlin/com/lambda/core/TimerManager.kt +++ b/common/src/main/kotlin/com/lambda/core/TimerManager.kt @@ -19,16 +19,38 @@ package com.lambda.core import com.lambda.event.EventFlow.post import com.lambda.event.events.ClientEvent +import com.lambda.event.events.TickEvent +import com.lambda.event.listener.SafeListener.Companion.listenOnce +import java.util.* +import kotlin.concurrent.fixedRateTimer object TimerManager : Loadable { var lastTickLength: Float = 50f override fun load() = "Loaded Timer Manager" + private const val TICK_DELAY = 50L + private var start = 0L + val fixedTickDelta get() = (System.currentTimeMillis() - start).mod(TICK_DELAY).toDouble() / TICK_DELAY + + init { + listenOnce { + start = System.currentTimeMillis() + fixedRateTimer( + daemon = true, + name = "Scheduler-Lambda-Tick", + initialDelay = TICK_DELAY, + period = TICK_DELAY + ) { + ClientEvent.FixedTick(this).post() + } + } + } + fun getLength(): Float { var length = 50f - ClientEvent.Timer(1.0).post { + ClientEvent.TimerUpdate(1.0).post { length /= speed.toFloat() } diff --git a/common/src/main/kotlin/com/lambda/event/EventFlow.kt b/common/src/main/kotlin/com/lambda/event/EventFlow.kt index 4b059840c..5ee430de6 100644 --- a/common/src/main/kotlin/com/lambda/event/EventFlow.kt +++ b/common/src/main/kotlin/com/lambda/event/EventFlow.kt @@ -19,14 +19,13 @@ package com.lambda.event import com.lambda.context.SafeContext import com.lambda.event.callback.ICancellable -import com.lambda.event.events.ClientEvent import com.lambda.event.listener.Listener import com.lambda.threading.runConcurrent import com.lambda.threading.runSafe import kotlinx.coroutines.* import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.* -import kotlin.concurrent.fixedRateTimer +import java.util.* /** @@ -78,17 +77,6 @@ object EventFlow { */ val concurrentListeners = Subscriber() - init { - fixedRateTimer( - daemon = true, - name = "Scheduler-Lambda-Tick", - initialDelay = 50L, - period = 50L - ) { - ClientEvent.FixedTick().post() - } - } - fun Any.unsubscribe() { syncListeners.unsubscribe(this) concurrentListeners.unsubscribe(this) diff --git a/common/src/main/kotlin/com/lambda/event/events/ClientEvent.kt b/common/src/main/kotlin/com/lambda/event/events/ClientEvent.kt index 5557f86d6..74047294f 100644 --- a/common/src/main/kotlin/com/lambda/event/events/ClientEvent.kt +++ b/common/src/main/kotlin/com/lambda/event/events/ClientEvent.kt @@ -18,9 +18,11 @@ package com.lambda.event.events import com.lambda.event.Event +import com.lambda.event.EventFlow import com.lambda.event.callback.Cancellable import com.lambda.event.callback.ICancellable import net.minecraft.client.sound.SoundInstance +import java.util.TimerTask sealed class ClientEvent { /** @@ -38,12 +40,20 @@ sealed class ClientEvent { * * @property speed The speed of the timer. */ - data class Timer(var speed: Double) : Event + data class TimerUpdate(var speed: Double) : Event /** * Triggered before playing a sound */ data class Sound(val sound: SoundInstance) : ICancellable by Cancellable() - class FixedTick : Event + /** + * Represents a fixed tick event in the application. + * + * A fixed tick can be used to execute a specific task consistently at regular intervals, based on the provided + * timer task. This event is part of the event system and can be subscribed to for handling the specified timer task. + * + * @property timerTask The task that is executed during this fixed tick event. + */ + data class FixedTick(val timerTask: TimerTask) : Event } diff --git a/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt b/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt index f9a13eea9..b334a24ee 100644 --- a/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt +++ b/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt @@ -17,8 +17,7 @@ package com.lambda.graphics.animation -import com.lambda.Lambda.mc -import com.lambda.util.extension.partialTicks +import com.lambda.core.TimerManager import com.lambda.util.math.lerp import kotlin.math.abs import kotlin.reflect.KProperty @@ -28,7 +27,7 @@ class Animation(initialValue: Double, val update: (Double) -> Double) { private var currValue = initialValue operator fun getValue(thisRef: Any?, property: KProperty<*>) = - lerp(mc.partialTicks, prevValue, currValue) + lerp(TimerManager.fixedTickDelta, prevValue, currValue) operator fun setValue(thisRef: Any?, property: KProperty<*>, valueIn: Double) = setValue(valueIn) diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/ESPRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/ESPRenderer.kt index f8eba5060..32898cc8c 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/ESPRenderer.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/ESPRenderer.kt @@ -18,6 +18,7 @@ package com.lambda.graphics.renderer.esp.impl import com.lambda.Lambda.mc +import com.lambda.core.TimerManager import com.lambda.graphics.buffer.VertexPipeline import com.lambda.graphics.buffer.vertex.attributes.VertexAttrib import com.lambda.graphics.buffer.vertex.attributes.VertexMode @@ -47,7 +48,7 @@ abstract class ESPRenderer(tickedMode: Boolean) { fun render() { shader.use() - shader["u_TickDelta"] = mc.partialTicks + shader["u_TickDelta"] = TimerManager.fixedTickDelta shader["u_CameraPosition"] = mc.gameRenderer.camera.pos withFaceCulling(faces::render) diff --git a/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt b/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt index e8f71a52d..41059dfbc 100644 --- a/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt +++ b/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt @@ -19,8 +19,8 @@ package com.lambda.gui.api import com.lambda.Lambda.mc import com.lambda.event.Muteable +import com.lambda.event.events.ClientEvent import com.lambda.event.events.RenderEvent -import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.graphics.animation.AnimationTicker import com.lambda.gui.api.component.core.IComponent @@ -56,7 +56,7 @@ abstract class LambdaGui( onEvent(GuiEvent.Render()) } - listen { + listen { animation.tick() onEvent(GuiEvent.Tick()) } diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt index ac7d10121..d08644129 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Speed.kt @@ -113,7 +113,7 @@ object Speed : Module( lastDistance = player.moveDelta } - listen { + listen { if (mode != Mode.NCP_STRAFE) return@listen if (!shouldWork() || !isInputting) return@listen it.speed = ncpTimerBoost diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt index 873d89616..ea9b301bc 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/TickShift.kt @@ -101,7 +101,7 @@ object TickShift : Module( } } - listen { + listen { if (!isActive) { poolPackets() return@listen diff --git a/common/src/main/kotlin/com/lambda/module/modules/movement/Timer.kt b/common/src/main/kotlin/com/lambda/module/modules/movement/Timer.kt index abbd113f1..f71e5f6ff 100644 --- a/common/src/main/kotlin/com/lambda/module/modules/movement/Timer.kt +++ b/common/src/main/kotlin/com/lambda/module/modules/movement/Timer.kt @@ -30,7 +30,7 @@ object Timer : Module( private val timer by setting("Timer", 1.0, 0.0..10.0, 0.01) init { - listen { + listen { it.speed = timer.coerceAtLeast(0.05) } } From 12359536e87693ed5b997c9a03a855ad9026f11a Mon Sep 17 00:00:00 2001 From: Constructor Date: Mon, 13 Jan 2025 03:31:40 +0100 Subject: [PATCH 3/5] Try nanos (changes nothing) --- .../kotlin/com/lambda/core/TimerManager.kt | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/core/TimerManager.kt b/common/src/main/kotlin/com/lambda/core/TimerManager.kt index 4b10ba084..1f2f8fe5c 100644 --- a/common/src/main/kotlin/com/lambda/core/TimerManager.kt +++ b/common/src/main/kotlin/com/lambda/core/TimerManager.kt @@ -19,9 +19,6 @@ package com.lambda.core import com.lambda.event.EventFlow.post import com.lambda.event.events.ClientEvent -import com.lambda.event.events.TickEvent -import com.lambda.event.listener.SafeListener.Companion.listenOnce -import java.util.* import kotlin.concurrent.fixedRateTimer object TimerManager : Loadable { @@ -30,20 +27,19 @@ object TimerManager : Loadable { override fun load() = "Loaded Timer Manager" private const val TICK_DELAY = 50L + private const val TICK_DELAY_NANOS = TICK_DELAY * 1_000_000L private var start = 0L - val fixedTickDelta get() = (System.currentTimeMillis() - start).mod(TICK_DELAY).toDouble() / TICK_DELAY + val fixedTickDelta get() = (System.nanoTime() - start).mod(TICK_DELAY_NANOS).toDouble() / TICK_DELAY_NANOS init { - listenOnce { - start = System.currentTimeMillis() - fixedRateTimer( - daemon = true, - name = "Scheduler-Lambda-Tick", - initialDelay = TICK_DELAY, - period = TICK_DELAY - ) { - ClientEvent.FixedTick(this).post() - } + start = System.nanoTime() + fixedRateTimer( + daemon = true, + name = "Scheduler-Lambda-Tick", + initialDelay = TICK_DELAY, + period = TICK_DELAY + ) { + ClientEvent.FixedTick(this).post() } } From d106b6e616ce8d78430d318d1affc54553a71ead Mon Sep 17 00:00:00 2001 From: Constructor Date: Mon, 13 Jan 2025 03:34:56 +0100 Subject: [PATCH 4/5] Change start --- common/src/main/kotlin/com/lambda/core/TimerManager.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/core/TimerManager.kt b/common/src/main/kotlin/com/lambda/core/TimerManager.kt index 1f2f8fe5c..78a2d4916 100644 --- a/common/src/main/kotlin/com/lambda/core/TimerManager.kt +++ b/common/src/main/kotlin/com/lambda/core/TimerManager.kt @@ -32,13 +32,13 @@ object TimerManager : Loadable { val fixedTickDelta get() = (System.nanoTime() - start).mod(TICK_DELAY_NANOS).toDouble() / TICK_DELAY_NANOS init { - start = System.nanoTime() fixedRateTimer( daemon = true, name = "Scheduler-Lambda-Tick", - initialDelay = TICK_DELAY, + initialDelay = 0, period = TICK_DELAY ) { + if (start == 0L) start = System.nanoTime() ClientEvent.FixedTick(this).post() } } From 1f443503bd67bb298ce4d596a41863fc7b81b8d2 Mon Sep 17 00:00:00 2001 From: Constructor Date: Thu, 16 Jan 2025 22:50:10 +0100 Subject: [PATCH 5/5] Revert to ms and not gui event --- common/src/main/kotlin/com/lambda/core/TimerManager.kt | 5 ++--- .../main/kotlin/com/lambda/graphics/animation/Animation.kt | 5 +++-- .../com/lambda/graphics/renderer/esp/impl/ESPRenderer.kt | 3 +-- common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt | 3 ++- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/common/src/main/kotlin/com/lambda/core/TimerManager.kt b/common/src/main/kotlin/com/lambda/core/TimerManager.kt index 78a2d4916..ce68852f3 100644 --- a/common/src/main/kotlin/com/lambda/core/TimerManager.kt +++ b/common/src/main/kotlin/com/lambda/core/TimerManager.kt @@ -27,9 +27,8 @@ object TimerManager : Loadable { override fun load() = "Loaded Timer Manager" private const val TICK_DELAY = 50L - private const val TICK_DELAY_NANOS = TICK_DELAY * 1_000_000L private var start = 0L - val fixedTickDelta get() = (System.nanoTime() - start).mod(TICK_DELAY_NANOS).toDouble() / TICK_DELAY_NANOS + val fixedTickDelta get() = (System.currentTimeMillis() - start).mod(TICK_DELAY).toDouble() / TICK_DELAY init { fixedRateTimer( @@ -38,7 +37,7 @@ object TimerManager : Loadable { initialDelay = 0, period = TICK_DELAY ) { - if (start == 0L) start = System.nanoTime() + if (start == 0L) start = System.currentTimeMillis() ClientEvent.FixedTick(this).post() } } diff --git a/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt b/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt index b334a24ee..f9a13eea9 100644 --- a/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt +++ b/common/src/main/kotlin/com/lambda/graphics/animation/Animation.kt @@ -17,7 +17,8 @@ package com.lambda.graphics.animation -import com.lambda.core.TimerManager +import com.lambda.Lambda.mc +import com.lambda.util.extension.partialTicks import com.lambda.util.math.lerp import kotlin.math.abs import kotlin.reflect.KProperty @@ -27,7 +28,7 @@ class Animation(initialValue: Double, val update: (Double) -> Double) { private var currValue = initialValue operator fun getValue(thisRef: Any?, property: KProperty<*>) = - lerp(TimerManager.fixedTickDelta, prevValue, currValue) + lerp(mc.partialTicks, prevValue, currValue) operator fun setValue(thisRef: Any?, property: KProperty<*>, valueIn: Double) = setValue(valueIn) diff --git a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/ESPRenderer.kt b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/ESPRenderer.kt index 32898cc8c..f8eba5060 100644 --- a/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/ESPRenderer.kt +++ b/common/src/main/kotlin/com/lambda/graphics/renderer/esp/impl/ESPRenderer.kt @@ -18,7 +18,6 @@ package com.lambda.graphics.renderer.esp.impl import com.lambda.Lambda.mc -import com.lambda.core.TimerManager import com.lambda.graphics.buffer.VertexPipeline import com.lambda.graphics.buffer.vertex.attributes.VertexAttrib import com.lambda.graphics.buffer.vertex.attributes.VertexMode @@ -48,7 +47,7 @@ abstract class ESPRenderer(tickedMode: Boolean) { fun render() { shader.use() - shader["u_TickDelta"] = TimerManager.fixedTickDelta + shader["u_TickDelta"] = mc.partialTicks shader["u_CameraPosition"] = mc.gameRenderer.camera.pos withFaceCulling(faces::render) diff --git a/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt b/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt index 41059dfbc..21b421cce 100644 --- a/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt +++ b/common/src/main/kotlin/com/lambda/gui/api/LambdaGui.kt @@ -21,6 +21,7 @@ import com.lambda.Lambda.mc import com.lambda.event.Muteable import com.lambda.event.events.ClientEvent import com.lambda.event.events.RenderEvent +import com.lambda.event.events.TickEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.graphics.animation.AnimationTicker import com.lambda.gui.api.component.core.IComponent @@ -56,7 +57,7 @@ abstract class LambdaGui( onEvent(GuiEvent.Render()) } - listen { + listen { animation.tick() onEvent(GuiEvent.Tick()) }