Skip to content

Commit bca4441

Browse files
committed
Better file structure, logging and less strict checkpoint setting
1 parent c3c30a9 commit bca4441

File tree

8 files changed

+122
-54
lines changed

8 files changed

+122
-54
lines changed

common/src/main/kotlin/com/lambda/command/commands/ReplayCommand.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.lambda.command.CommandManager.register
1010
import com.lambda.command.LambdaCommand
1111
import com.lambda.module.modules.player.Replay
1212
import com.lambda.util.FolderRegister
13+
import com.lambda.util.FolderRegister.listRecursive
1314

1415
object ReplayCommand : LambdaCommand {
1516
override val name = "replay"
@@ -25,16 +26,15 @@ object ReplayCommand : LambdaCommand {
2526
// 7. Set replay speed
2627
required(string("replay name")) { replayName ->
2728
suggests { _, builder ->
28-
FolderRegister.replay.listFiles()?.map {
29-
it.nameWithoutExtension
30-
}?.forEach {
31-
builder.suggest(it)
32-
}
29+
val dir = FolderRegister.replay
30+
dir.listRecursive().forEach {
31+
builder.suggest(it.relativeTo(dir).path)
32+
}
3333
builder.buildFuture()
3434
}
3535

3636
executeWithResult {
37-
val replayFile = FolderRegister.replay.resolve("${this[replayName].value()}.json")
37+
val replayFile = FolderRegister.replay.resolve(this[replayName].value())
3838

3939
if (!replayFile.exists()) {
4040
return@executeWithResult CommandResult.failure("Replay file does not exist")

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package com.lambda.config
22

33
import com.lambda.interaction.rotation.IRotationConfig
44
import com.lambda.interaction.rotation.RotationMode
5+
import kotlin.math.max
6+
import kotlin.math.min
57
import kotlin.random.Random
68

79
class RotationSettings(
@@ -12,10 +14,10 @@ class RotationSettings(
1214
override val keepTicks by c.setting("Keep Rotation", 3, 1..10, 1, "Ticks to keep rotation", "", vis)
1315
override val resetTicks by c.setting("Reset Rotation", 3, 1..10, 1, "Ticks before rotation is reset", "", vis)
1416

15-
private val r1 by c.setting("Turn Speed 1", 70.0, 1.0..180.0, 0.1, "Rotation Speed 1", "", vis)
16-
private val r2 by c.setting("Turn Speed 2", 110.0, 1.0..180.0, 0.1, "Rotation Speed 2", "", vis)
17+
var r1 by c.setting("Turn Speed 1", 70.0, 1.0..180.0, 0.1, "Rotation Speed 1", "", vis)
18+
var r2 by c.setting("Turn Speed 2", 110.0, 1.0..180.0, 0.1, "Rotation Speed 2", "", vis)
1719

18-
override val turnSpeed get() = Random.nextDouble(r1, r2)
20+
override val turnSpeed get() = Random.nextDouble(min(r1, r2), max(r1, r2) + 0.01)
1921

2022
var speedMultiplier = 1.0
2123

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ object GuiSettings : Module(
1515
private val scaleSetting by setting("Scale", 1.0, 0.5..3.0, 0.01, visibility = { page == Page.General })
1616

1717
// Colors
18-
private val primaryColor by setting("Primary Color", Color(130, 200, 255), visibility = { page == Page.Colors })
19-
private val secondaryColor by setting("Secondary Color", Color(225, 130, 225), visibility = { page == Page.Colors && shade })
18+
val primaryColor by setting("Primary Color", Color(130, 200, 255), visibility = { page == Page.Colors })
19+
val secondaryColor by setting("Secondary Color", Color(225, 130, 225), visibility = { page == Page.Colors && shade })
2020
val backgroundColor by setting("Background Color", Color(0, 0, 0, 80), visibility = { page == Page.Colors })
2121
val glow by setting("Glow", true, visibility = { page == Page.Colors })
2222
val shade by setting("Shade Color", true, visibility = { page == Page.Colors })

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ object PacketLogger : Module(
7979

8080
onEnableUnsafe {
8181
val fileName = "packet-log-${getTime(fileFormatter)}.txt"
82+
83+
// ToDo: Organize files with FolderRegister.worldBoundDirectory
8284
file = FolderRegister.packetLogs.resolve(fileName).apply {
8385
if (!parentFile.exists()) {
8486
parentFile.mkdirs()

common/src/main/kotlin/com/lambda/module/modules/player/Replay.kt

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package com.lambda.module.modules.player
22

33
import com.google.gson.*
4-
import com.google.gson.annotations.SerializedName
54
import com.lambda.config.RotationSettings
65
import com.lambda.context.SafeContext
76
import com.lambda.core.TimerManager
87
import com.lambda.event.EventFlow.lambdaScope
8+
import com.lambda.event.events.InteractionEvent
99
import com.lambda.event.events.KeyPressEvent
1010
import com.lambda.event.events.MovementEvent
1111
import com.lambda.event.events.RotationEvent
1212
import com.lambda.event.listener.SafeListener.Companion.listener
13-
import com.lambda.gui.impl.clickgui.LambdaClickGui
1413
import com.lambda.interaction.rotation.Rotation
1514
import com.lambda.interaction.rotation.RotationContext
1615
import com.lambda.interaction.rotation.RotationMode
@@ -22,8 +21,10 @@ import com.lambda.util.Communication.info
2221
import com.lambda.util.Communication.logError
2322
import com.lambda.util.Communication.warn
2423
import com.lambda.util.FolderRegister
24+
import com.lambda.util.FolderRegister.locationBoundDirectory
2525
import com.lambda.util.Formatting.asString
2626
import com.lambda.util.KeyCode
27+
import com.lambda.util.StringUtils.sanitizeForFilename
2728
import com.lambda.util.primitives.extension.rotation
2829
import com.lambda.util.text.buildText
2930
import com.lambda.util.text.color
@@ -32,12 +33,11 @@ import kotlinx.coroutines.Dispatchers
3233
import kotlinx.coroutines.launch
3334
import net.minecraft.client.input.Input
3435
import net.minecraft.client.sound.PositionedSoundInstance
35-
import net.minecraft.client.sound.SoundInstance
3636
import net.minecraft.sound.SoundEvents
3737
import net.minecraft.util.math.Vec3d
38-
import java.awt.Color
3938
import java.io.File
4039
import java.lang.reflect.Type
40+
import java.time.Instant
4141
import kotlin.time.Duration
4242
import kotlin.time.DurationUnit
4343
import kotlin.time.toDuration
@@ -55,24 +55,27 @@ object Replay : Module(
5555
private val record by setting("Record", KeyCode.R)
5656
private val play by setting("Play / Pause", KeyCode.C)
5757
private val stop by setting("Stop", KeyCode.X)
58-
private val check by setting("Checkpoint", KeyCode.V, description = "Create a checkpoint while recording.")
59-
private val playCheck by setting("Play until checkpoint", KeyCode.B, description = "Replays until the last set checkpoint.")
58+
private val check by setting("Set Checkpoint", KeyCode.V, description = "Create a checkpoint while recording.")
59+
private val playCheck by setting("Play Checkpoint", KeyCode.B, description = "Replays until the last set checkpoint.")
6060
private val loop by setting("Loop", false)
6161
private val loops by setting("Loops", -1, -1..10, 1, description = "Number of times to loop the replay. -1 for infinite.", unit = "repeats") { loop }
6262
private val cancelOnDeviation by setting("Cancel on deviation", true)
6363
private val deviationThreshold by setting("Deviation threshold", 0.1, 0.1..5.0, 0.1, description = "The threshold for the deviation to cancel the replay.") { cancelOnDeviation }
6464

6565
private val rotationConfig = RotationSettings(this).apply {
6666
rotationMode = RotationMode.LOCK
67+
r1 = 1000.0
68+
r2 = 1001.0
6769
}
6870

6971
enum class State {
7072
INACTIVE,
7173
RECORDING,
7274
PAUSED_RECORDING,
7375
PLAYING,
76+
PAUSED_REPLAY,
7477
PLAYING_CHECKPOINTS,
75-
PAUSED_REPLAY
78+
PAUSED_CHECKPOINTS
7679
}
7780

7881
private var state = State.INACTIVE
@@ -82,6 +85,7 @@ object Replay : Module(
8285
private var recording: Recording? = null
8386
private var replay: Recording? = null
8487
private var repeats = 0
88+
private val still = Vec3d(0.0, -0.0784000015258789, 0.0)
8589

8690
private val gsonCompact = GsonBuilder()
8791
.registerTypeAdapter(Recording::class.java, Recording())
@@ -92,9 +96,9 @@ object Replay : Module(
9296

9397
info(buildText {
9498
literal("Recording ")
95-
color(Color.GRAY) { literal(file.nameWithoutExtension) }
99+
color(GuiSettings.primaryColor) { literal(file.nameWithoutExtension) }
96100
literal(" loaded. Duration: ")
97-
color(Color.GRAY) { literal(recording?.duration.toString()) }
101+
color(GuiSettings.primaryColor) { literal(recording?.duration.toString()) }
98102
})
99103
}
100104

@@ -178,13 +182,16 @@ object Replay : Module(
178182
if (loop && repeats < loops) {
179183
if (repeats >= 0) repeats++
180184
replay = recording?.duplicate()
181-
this@Replay.info("Replay looped. $repeats / $loops")
185+
this@Replay.info(buildText {
186+
color(GuiSettings.primaryColor) { literal("[$repeats / $loops]") }
187+
literal(" Replay looped.")
188+
})
182189
} else {
183190
if (state != State.PLAYING_CHECKPOINTS) {
184191
state = State.INACTIVE
185192
this@Replay.info(buildText {
186193
literal("Replay finished after ")
187-
color(Color.GRAY) { literal(it.duration.toString()) }
194+
color(GuiSettings.primaryColor) { literal(recording?.duration.toString()) }
188195
literal(".")
189196
})
190197
return@listener
@@ -212,40 +219,52 @@ object Replay : Module(
212219
recording?.let {
213220
state = State.PLAYING
214221
replay = it.duplicate()
215-
this@Replay.info("Replay started. Duration: ${it.duration}.")
222+
info(buildText {
223+
literal("Replay started. Duration: ")
224+
color(GuiSettings.primaryColor) { literal(it.duration.toString()) }
225+
})
216226
} ?: run {
217227
this@Replay.warn("No recording to replay.")
218228
}
219229
}
220230
State.RECORDING -> {
221231
state = State.PAUSED_RECORDING
222-
this@Replay.info("Recording paused.")
232+
info("Recording paused.")
223233
}
224234
State.PAUSED_RECORDING -> {
225235
state = State.RECORDING
226-
this@Replay.info("Recording resumed.")
236+
info("Recording resumed.")
227237
}
228-
State.PLAYING, State.PLAYING_CHECKPOINTS -> { // ToDo: More general pausing for all states
238+
State.PLAYING -> { // ToDo: More general pausing for all states
229239
state = State.PAUSED_REPLAY
230-
this@Replay.info("Replay paused.")
240+
info("Replay paused.")
231241
}
232242
State.PAUSED_REPLAY -> {
233243
state = State.PLAYING
234-
this@Replay.info("Replay resumed.")
244+
info("Replay resumed.")
245+
}
246+
State.PLAYING_CHECKPOINTS -> {
247+
state = State.PAUSED_CHECKPOINTS
248+
info("Checkpoint replay paused.")
249+
}
250+
State.PAUSED_CHECKPOINTS -> {
251+
state = State.PLAYING_CHECKPOINTS
252+
info("Checkpoint replay resumed.")
235253
}
236254
}
237255
}
238256

239257
private fun SafeContext.handleRecord() {
240258
when (state) {
241259
State.RECORDING -> {
242-
state = State.INACTIVE
243-
recording?.let {
244-
save(it, "recording")
245-
}
246-
this@Replay.info("Recording stopped. Recorded for ${recording?.duration}.")
260+
stopRecording()
247261
}
248262
State.INACTIVE -> {
263+
if (player.velocity != still) {
264+
this@Replay.logError("Cannot start recording while moving. Slow down and try again!")
265+
return
266+
}
267+
249268
recording = Recording()
250269
state = State.RECORDING
251270
this@Replay.info("Recording started.")
@@ -257,11 +276,7 @@ object Replay : Module(
257276
private fun SafeContext.handleStop() {
258277
when (state) {
259278
State.RECORDING, State.PAUSED_RECORDING -> {
260-
state = State.INACTIVE
261-
recording?.let {
262-
save(it, "recording")
263-
}
264-
this@Replay.info("Recording stopped. Recorded for ${recording?.duration}.")
279+
stopRecording()
265280
}
266281
State.PLAYING, State.PAUSED_REPLAY, State.PLAYING_CHECKPOINTS -> {
267282
state = State.INACTIVE
@@ -271,19 +286,26 @@ object Replay : Module(
271286
}
272287
}
273288

289+
private fun SafeContext.stopRecording() {
290+
state = State.INACTIVE
291+
recording?.let {
292+
save(it, "recording")
293+
this@Replay.info(buildText {
294+
literal("Recording stopped. Recorded for ")
295+
color(GuiSettings.primaryColor) { literal(it.duration.toString()) }
296+
literal(".")
297+
})
298+
}
299+
}
300+
274301
private fun SafeContext.handleCheckpoint() {
275302
when (state) {
276303
State.RECORDING -> {
277-
if (player.velocity != Vec3d(0.0, -0.0784000015258789, 0.0)) {
278-
this@Replay.logError("Cannot create checkpoint while moving. Try again!")
279-
return
280-
}
281-
282304
checkpoint = recording?.duplicate()
283305
checkpoint?.let {
284306
save(it, "checkpoint")
307+
this@Replay.info("Checkpoint created.")
285308
}
286-
this@Replay.info("Checkpoint created.")
287309
}
288310
else -> {}
289311
}
@@ -294,22 +316,20 @@ object Replay : Module(
294316
State.INACTIVE -> {
295317
state = State.PLAYING_CHECKPOINTS
296318
replay = checkpoint?.duplicate()
297-
this@Replay.info("Replaying until last set checkpoint. Duration: ${checkpoint?.duration}")
319+
info(buildText {
320+
literal("Replaying until last set checkpoint. Duration: ")
321+
color(GuiSettings.primaryColor) { literal(checkpoint?.duration.toString()) }
322+
})
298323
}
299324
else -> {}
300325
}
301326
}
302327

303328
private fun SafeContext.save(recording: Recording, name: String) {
304329
lambdaScope.launch(Dispatchers.IO) {
305-
FolderRegister.replay.mkdirs()
306-
FolderRegister.replay.resolve("$name-${
307-
mc.currentServerEntry?.address?.replace(":", "_")
308-
}-${
309-
world.dimensionKey?.value?.path?.replace("/", "_")
310-
}-${
311-
System.currentTimeMillis()
312-
}.json").writeText(gsonCompact.toJson(recording))
330+
locationBoundDirectory(FolderRegister.replay).resolve("${
331+
Instant.now().toString().sanitizeForFilename()
332+
}-$name.json").writeText(gsonCompact.toJson(recording))
313333
}
314334
}
315335

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package com.lambda.util
22

33
import com.lambda.Lambda.mc
4+
import com.lambda.context.SafeContext
45
import com.lambda.util.FolderRegister.config
56
import com.lambda.util.FolderRegister.lambda
67
import com.lambda.util.FolderRegister.minecraft
8+
import com.lambda.util.StringUtils.sanitizeForFilename
79
import java.io.File
10+
import java.net.InetSocketAddress
811

912
/**
1013
* The [FolderRegister] object is responsible for managing the directory structure of the application.
@@ -19,4 +22,21 @@ object FolderRegister {
1922
val config: File = File(lambda, "config")
2023
val packetLogs: File = File(lambda, "packet-log")
2124
val replay: File = File(lambda, "replay")
25+
26+
fun File.createIfNotExists() {
27+
if (!exists()) { mkdirs() }
28+
}
29+
30+
fun File.listRecursive() = walk().filter { it.isFile }
31+
32+
fun SafeContext.locationBoundDirectory(file: File): File {
33+
val hostName = (connection.connection.address as? InetSocketAddress)?.hostName ?: "singleplayer"
34+
val path = file.resolve(
35+
hostName.sanitizeForFilename()
36+
).resolve(
37+
world.dimensionKey?.value?.path?.sanitizeForFilename() ?: "unknown"
38+
)
39+
path.createIfNotExists()
40+
return path
41+
}
2242
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import java.time.format.DateTimeFormatter
88

99
object Formatting {
1010
val Vec3d.asString: String
11-
get() = "(%.2f, %.2f, %.2f)".format(x, y, z)
11+
get() = asString()
1212

1313
fun Vec3d.asString(decimals: Int = 2): String {
1414
val format = "%.${decimals}f"

0 commit comments

Comments
 (0)