11package com.lambda.module.modules.player
22
33import com.google.gson.*
4- import com.google.gson.annotations.SerializedName
54import com.lambda.config.RotationSettings
65import com.lambda.context.SafeContext
76import com.lambda.core.TimerManager
87import com.lambda.event.EventFlow.lambdaScope
8+ import com.lambda.event.events.InteractionEvent
99import com.lambda.event.events.KeyPressEvent
1010import com.lambda.event.events.MovementEvent
1111import com.lambda.event.events.RotationEvent
1212import com.lambda.event.listener.SafeListener.Companion.listener
13- import com.lambda.gui.impl.clickgui.LambdaClickGui
1413import com.lambda.interaction.rotation.Rotation
1514import com.lambda.interaction.rotation.RotationContext
1615import com.lambda.interaction.rotation.RotationMode
@@ -22,8 +21,10 @@ import com.lambda.util.Communication.info
2221import com.lambda.util.Communication.logError
2322import com.lambda.util.Communication.warn
2423import com.lambda.util.FolderRegister
24+ import com.lambda.util.FolderRegister.locationBoundDirectory
2525import com.lambda.util.Formatting.asString
2626import com.lambda.util.KeyCode
27+ import com.lambda.util.StringUtils.sanitizeForFilename
2728import com.lambda.util.primitives.extension.rotation
2829import com.lambda.util.text.buildText
2930import com.lambda.util.text.color
@@ -32,12 +33,11 @@ import kotlinx.coroutines.Dispatchers
3233import kotlinx.coroutines.launch
3334import net.minecraft.client.input.Input
3435import net.minecraft.client.sound.PositionedSoundInstance
35- import net.minecraft.client.sound.SoundInstance
3636import net.minecraft.sound.SoundEvents
3737import net.minecraft.util.math.Vec3d
38- import java.awt.Color
3938import java.io.File
4039import java.lang.reflect.Type
40+ import java.time.Instant
4141import kotlin.time.Duration
4242import kotlin.time.DurationUnit
4343import 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
0 commit comments