Skip to content

Commit abd6a3f

Browse files
committed
durations
1 parent b5bec2d commit abd6a3f

File tree

13 files changed

+185
-43
lines changed

13 files changed

+185
-43
lines changed

common/src/main/kotlin/com/lambda/config/Configurable.kt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.google.gson.reflect.TypeToken
2323
import com.lambda.Lambda
2424
import com.lambda.Lambda.LOG
2525
import com.lambda.config.settings.CharSetting
26+
import com.lambda.config.settings.DurationSetting
2627
import com.lambda.config.settings.FunctionSetting
2728
import com.lambda.config.settings.StringSetting
2829
import com.lambda.config.settings.collections.ListSetting
@@ -35,10 +36,13 @@ import com.lambda.config.settings.numeric.*
3536
import com.lambda.util.Communication.logError
3637
import com.lambda.util.KeyCode
3738
import com.lambda.util.Nameable
39+
import com.lambda.util.extension.highestUnit
3840
import net.minecraft.block.Block
3941
import net.minecraft.util.math.BlockPos
4042
import net.minecraft.util.math.Vec3d
4143
import java.awt.Color
44+
import kotlin.time.Duration
45+
import kotlin.time.toDuration
4246

4347
/**
4448
* Represents a set of [AbstractSetting]s that are associated with the [name] of the [Configurable].
@@ -354,6 +358,36 @@ abstract class Configurable(
354358
visibility: () -> Boolean = { true },
355359
) = LongSetting(name, defaultValue, range, step, description, visibility, unit).register()
356360

361+
/**
362+
* Creates a [DurationSetting] with the provided parameters and adds it to the [settings].
363+
*
364+
* The value of the setting is coerced into the specified [range] and rounded to the nearest [step].
365+
*
366+
* The unit of the duration is inferred automatically by [Duration.highestUnit]
367+
*
368+
* Example:
369+
* ```kotlin
370+
* val duration by setting("Duration", 10.microseconds, 420.nanoseconds..80.minutes, 69420.microseconds)
371+
* ```
372+
*
373+
* @param name The unique identifier for the setting.
374+
* @param defaultValue The default [Duration] value of the setting.
375+
* @param range The range within which the setting's value must fall.
376+
* @param step The step to which the setting's value is rounded.
377+
* @param description A brief explanation of the setting's purpose and behavior.
378+
* @param visibility A lambda expression that determines the visibility status of the setting.
379+
*
380+
* @return The created [Duration].
381+
*/
382+
fun setting(
383+
name: String,
384+
defaultValue: Duration,
385+
range: ClosedRange<Duration>,
386+
step: Duration = 1.toDuration(defaultValue.highestUnit),
387+
description: String = "",
388+
visibility: () -> Boolean = { true },
389+
) = DurationSetting(name, defaultValue, range, step, description, visibility).register()
390+
357391
/**
358392
* Creates a [KeyBindSetting] with the provided parameters and adds it to the [settings].
359393
*

common/src/main/kotlin/com/lambda/config/groups/BuildSettings.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,5 @@ class BuildSettings(
4949
override val placeConfirmation by c.setting("Place Confirmation", true, "Wait for block placement confirmation") { vis() && page == Page.Place }
5050
override val placementsPerTick by c.setting("Instant Places Per Tick", 1, 1..30, 1, "Maximum instant block places per tick") { vis() && page == Page.Place }
5151

52-
override val interactionTimeout by c.setting("Interaction Timeout", 10, 1..30, 1, "Timeout for block breaks in ticks", unit = " ticks") { vis() && (page == Page.Place && placeConfirmation || page == Page.Break && breakConfirmation) }
52+
override val interactionTimeout by c.setting("Interaction Timeout", 10, 1..30, 1,"Timeout for block breaks in ticks", unit = " ticks") { vis() && (page == Page.Place && placeConfirmation || page == Page.Break && breakConfirmation) }
5353
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.config.settings
19+
20+
import com.lambda.util.extension.highestUnit
21+
import com.lambda.util.extension.symbol
22+
import kotlin.time.Duration
23+
import kotlin.time.DurationUnit
24+
import kotlin.time.toDuration
25+
26+
class DurationSetting(
27+
override val name: String,
28+
private val defaultValue: Duration,
29+
override val range: ClosedRange<Duration>,
30+
override val step: Duration = 1.toDuration(defaultValue.highestUnit), // FixMe: Causes issues if the lower bound of the range is less than the step duration unit
31+
// Ex: 60.microseconds..10.minutes will have a step of 1 minute
32+
// Maybe we should leave this as is for the default behavior
33+
description: String,
34+
visibility: () -> Boolean,
35+
) : NumericSetting<Duration>(
36+
defaultValue,
37+
range,
38+
step,
39+
description,
40+
visibility,
41+
"",
42+
) {
43+
// ToDo:
44+
// Should we determine the unit from the step since this is the in/decrement value within the range so it would make sense to use that for the unit inference
45+
override fun toString() = "${value.toInt(value.highestUnit)} ${value.highestUnit.symbol}"
46+
}

common/src/main/kotlin/com/lambda/config/settings/NumericSetting.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import kotlin.reflect.KProperty
2626
/**
2727
* @see [com.lambda.config.Configurable]
2828
*/
29-
abstract class NumericSetting<T>(
29+
abstract class NumericSetting<T : Comparable<T>>(
3030
value: T,
3131
open val range: ClosedRange<T>,
3232
open val step: T,
@@ -38,7 +38,7 @@ abstract class NumericSetting<T>(
3838
TypeToken.get(value::class.java).type,
3939
description,
4040
visibility
41-
) where T : Number, T : Comparable<T> {
41+
) {
4242
private val formatter = NumberFormat.getNumberInstance(Locale.getDefault())
4343

4444
override fun toString() = "${formatter.format(value)}$unit"

common/src/main/kotlin/com/lambda/module/modules/client/Discord.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,16 @@ import dev.cbyrne.kdiscordipc.KDiscordIPC
3737
import dev.cbyrne.kdiscordipc.core.packet.inbound.impl.AuthenticatePacket
3838
import dev.cbyrne.kdiscordipc.data.activity.*
3939
import kotlinx.coroutines.delay
40+
import kotlin.time.Duration.Companion.milliseconds
41+
import kotlin.time.Duration.Companion.seconds
4042

4143
object Discord : Module(
4244
name = "Discord",
4345
description = "Discord Rich Presence configuration",
4446
defaultTags = setOf(ModuleTag.CLIENT),
4547
//enabledByDefault = true, // ToDo: Bring this back on beta release
4648
) {
47-
private val delay by setting("Update Delay", 5000L, 5000L..30000L, 100L, unit = "ms")
49+
private val delay by setting("Update Delay", 5.seconds, 5.seconds..30.seconds, 100.milliseconds)
4850
private val showTime by setting("Show Time", true, description = "Show how long you have been playing for.")
4951
private val line1Left by setting("Line 1 Left", LineInfo.WORLD)
5052
private val line1Right by setting("Line 1 Right", LineInfo.USERNAME)

common/src/main/kotlin/com/lambda/module/modules/combat/CrystalAura.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ import net.minecraft.util.math.*
6060
import kotlin.concurrent.fixedRateTimer
6161
import kotlin.math.max
6262
import kotlin.time.Duration.Companion.milliseconds
63+
import kotlin.time.Duration.Companion.nanoseconds
64+
import kotlin.time.Duration.Companion.seconds
6365

6466
object CrystalAura : Module(
6567
name = "CrystalAura",
@@ -74,9 +76,9 @@ object CrystalAura : Module(
7476
private val placeDelay by setting("Place Delay", 50L, 0L..1000L, 1L, "Delay between placement attempts", " ms") { page == Page.General }
7577
private val explodeDelay by setting("Explode Delay", 10L, 0L..1000L, 1L, "Delay between explosion attempts", " ms") { page == Page.General }
7678
private val updateMode by setting("Update Mode", UpdateMode.Async) { page == Page.General }
77-
private val updateDelaySetting by setting("Update Delay", 25L, 5L..200L, 5L, unit = " ms") { page == Page.General && updateMode == UpdateMode.Async }
79+
private val updateDelaySetting by setting("Update Delay", 25.milliseconds, 5.milliseconds..200.milliseconds, 5.milliseconds) { page == Page.General && updateMode == UpdateMode.Async }
7880
private val maxUpdatesPerFrame by setting("Max Updates Per Frame", 5, 1..20, 1) { page == Page.General && updateMode == UpdateMode.Async }
79-
private val updateDelay get() = if (updateMode == UpdateMode.Async) updateDelaySetting else 0L
81+
private val updateDelay get() = if (updateMode == UpdateMode.Async) updateDelaySetting else 0.nanoseconds
8082
private val debug by setting("Debug", false) { page == Page.General }
8183

8284
/* Placement */
@@ -119,7 +121,7 @@ object CrystalAura : Module(
119121
private val predictionTimer = Timer()
120122
private var lastEntityId = 0
121123

122-
private val decay = LimitedDecayQueue<Int>(10000, 3000L)
124+
private val decay = LimitedDecayQueue<Int>(10000, 3.seconds)
123125

124126
private val collidingOffsets = mutableListOf<BlockPos>().apply {
125127
for (x in -1..1) {
@@ -293,7 +295,7 @@ object CrystalAura : Module(
293295
}
294296

295297
private fun SafeContext.updateBlueprint(target: LivingEntity) =
296-
updateTimer.runIfPassed(updateDelay.milliseconds) {
298+
updateTimer.runIfPassed(updateDelay) {
297299
resetBlueprint()
298300

299301
// Build damage info

common/src/main/kotlin/com/lambda/module/modules/network/PacketDelay.kt

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ import com.lambda.util.ClientPacket
2929
import com.lambda.util.PacketUtils.handlePacketSilently
3030
import com.lambda.util.PacketUtils.sendPacketSilently
3131
import com.lambda.util.ServerPacket
32+
import com.lambda.util.Timer
3233
import kotlinx.coroutines.delay
33-
import net.minecraft.network.listener.ClientPacketListener
34-
import net.minecraft.network.listener.ServerPacketListener
3534
import net.minecraft.network.packet.Packet
3635
import net.minecraft.network.packet.c2s.common.KeepAliveC2SPacket
3736
import java.util.concurrent.ConcurrentLinkedDeque
37+
import kotlin.time.Duration.Companion.milliseconds
38+
import kotlin.time.Duration.Companion.seconds
3839

3940
object PacketDelay : Module(
4041
name = "PacketDelay",
@@ -44,19 +45,18 @@ object PacketDelay : Module(
4445
private val mode by setting("Mode", Mode.STATIC)
4546
private val networkScope by setting("Network Scope", Direction.BOTH)
4647
private val packetScope by setting("Packet Scope", PacketType.ANY)
47-
private val inboundDelay by setting("Inbound Delay", 250L, 0L..5000L, 10L, unit = "ms") { networkScope != Direction.OUTBOUND }
48-
private val outboundDelay by setting("Outbound Delay", 250L, 0L..5000L, 10L, unit = "ms") { networkScope != Direction.INBOUND }
48+
private val inboundDelay by setting("Inbound Delay", 250.milliseconds, 1.milliseconds..5.seconds, 10.milliseconds) { networkScope != Direction.OUTBOUND }
49+
private val outboundDelay by setting("Outbound Delay", 250.milliseconds, 1.milliseconds..5.seconds, 10.milliseconds) { networkScope != Direction.INBOUND }
4950

5051
private var outboundPool = ConcurrentLinkedDeque<ClientPacket>()
5152
private var inboundPool = ConcurrentLinkedDeque<ServerPacket>()
52-
private var outboundLastUpdate = 0L
53-
private var inboundLastUpdate = 0L
53+
private var outboundLastUpdate = Timer()
54+
private var inboundLastUpdate = Timer()
5455

5556
init {
5657
listen<RenderEvent.World> {
5758
if (mode != Mode.STATIC) return@listen
58-
59-
flushPools(System.currentTimeMillis())
59+
flushPools()
6060
}
6161

6262
listen<PacketEvent.Send.Pre>(Int.MIN_VALUE) { event ->
@@ -104,29 +104,25 @@ object PacketDelay : Module(
104104
}
105105

106106
onDisable {
107-
flushPools(System.currentTimeMillis())
107+
flushPools()
108108
}
109109
}
110110

111-
private fun SafeContext.flushPools(time: Long) {
112-
if (time - outboundLastUpdate >= outboundDelay) {
111+
private fun SafeContext.flushPools() {
112+
outboundLastUpdate.runIfPassed(outboundDelay) {
113113
while (outboundPool.isNotEmpty()) {
114114
outboundPool.poll().let { packet ->
115115
connection.sendPacketSilently(packet)
116116
}
117117
}
118-
119-
outboundLastUpdate = time
120118
}
121119

122-
if (time - inboundLastUpdate >= inboundDelay) {
120+
inboundLastUpdate.runIfPassed(inboundDelay) {
123121
while (inboundPool.isNotEmpty()) {
124122
inboundPool.poll().let { packet ->
125123
connection.handlePacketSilently(packet)
126124
}
127125
}
128-
129-
inboundLastUpdate = time
130126
}
131127
}
132128

common/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,20 @@ import com.lambda.util.collections.LimitedDecayQueue
2626
import net.minecraft.network.packet.c2s.common.CommonPongC2SPacket
2727
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.*
2828
import net.minecraft.network.packet.c2s.play.TeleportConfirmC2SPacket
29+
import kotlin.time.Duration.Companion.milliseconds
30+
import kotlin.time.Duration.Companion.seconds
2931

3032
// ToDo: HUD info
3133
object PacketLimiter : Module(
3234
name = "PacketLimiter",
3335
description = "Limits the amount of packets sent to the server",
3436
defaultTags = setOf(ModuleTag.NETWORK)
3537
) {
36-
private var packetQueue = LimitedDecayQueue<PacketEvent.Send.Pre>(99, 1000)
38+
private var packetQueue = LimitedDecayQueue<PacketEvent.Send.Pre>(99, 1.seconds)
3739
private val limit by setting("Limit", 99, 1..100, 1, "The maximum amount of packets to send per given time interval", unit = " packets")
3840
.onValueChange { _, to -> packetQueue.setSizeLimit(to) }
3941

40-
private val interval by setting("Duration", 4000L, 1L..10000L, 50L, "The interval / duration in milliseconds to limit packets for", unit = " ms")
42+
private val interval by setting("Duration", 4.seconds, 1.milliseconds..10.seconds, 50.milliseconds, "The interval / duration in milliseconds to limit packets for")
4143
.onValueChange { _, to -> packetQueue.setDecayTime(to) }
4244

4345
private val defaultIgnorePackets = setOf(

common/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import com.lambda.util.Formatting.string
5353
import com.lambda.util.collections.LimitedDecayQueue
5454
import com.lambda.util.extension.Structure
5555
import com.lambda.util.extension.inventorySlots
56+
import com.lambda.util.extension.ticks
5657
import com.lambda.util.item.ItemUtils.block
5758
import com.lambda.util.player.SlotUtils.hotbarAndStorage
5859
import net.minecraft.entity.ItemEntity
@@ -70,7 +71,7 @@ class BuildTask @Ta5kBuilder constructor(
7071
override val name: String get() = "Building $blueprint with ${(breaks / (age / 20.0 + 0.001)).string} b/s ${(placements / (age / 20.0 + 0.001)).string} p/s"
7172

7273
private val pendingInteractions = LimitedDecayQueue<BuildContext>(
73-
build.maxPendingInteractions, build.interactionTimeout * 50L
74+
build.maxPendingInteractions, build.interactionTimeout.ticks
7475
) { info("${it::class.simpleName} at ${it.expectedPos.toShortString()} timed out") }
7576
private var currentInteraction: BuildContext? = null
7677
private val instantBreaks = mutableSetOf<BreakContext>()

common/src/main/kotlin/com/lambda/util/ServerTPS.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ import com.lambda.event.events.PacketEvent
2222
import com.lambda.event.listener.SafeListener.Companion.listen
2323
import com.lambda.util.collections.LimitedDecayQueue
2424
import net.minecraft.network.packet.s2c.play.WorldTimeUpdateS2CPacket
25+
import kotlin.time.Duration.Companion.seconds
2526

2627
object ServerTPS {
2728
// Server sends exactly one world time update every 20 server ticks (one per second).
28-
private val updateHistory = LimitedDecayQueue<Long>(61, 60000)
29+
private val updateHistory = LimitedDecayQueue<Long>(61, 60.seconds)
2930
private var lastUpdate = 0L
3031

3132
val averageMSPerTick: Double

0 commit comments

Comments
 (0)