package army.warfare.holo.util.misc import army.warfare.holo.events.UpdateEvent import com.darkmagician6.eventapi.EventManager import com.darkmagician6.eventapi.EventTarget import kotlinx.coroutines.* import kotlin.coroutines.Continuation import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine class SequenceList { private val sequences = mutableListOf() fun add(sequence: Sequence) { sequences.add(sequence) } fun register() { EventManager.register(this) } fun unregister() { EventManager.unregister(this) } @EventTarget fun updateSequences(event: UpdateEvent.Pre) { for (seq in sequences) { val angle = seq.tick() ?: continue if (angle.first != null) { event.yaw = angle.first!! } if (angle.second != null) { event.pitch = angle.second!! } } } } class Sequence(val handler: suspend Sequence.() -> Unit) { private var continuation: Continuation? = null private var remainingTicks: Int = 0 private var coroutine: Job = buildCoroutine() private var rotationYaw: Float? = null private var rotationPitch: Float? = null private fun buildCoroutine(): Job { return GlobalScope.launch(Dispatchers.Unconfined) { sync() while (isActive) { handler() sync() } } } fun reset() { remainingTicks = 0 continuation = null coroutine = buildCoroutine() } fun tick(): Pair? { if (remainingTicks > 0) { remainingTicks-- } else { if (coroutine.isActive) { continuation?.resume(Unit) if (rotationYaw != null || rotationPitch != null) { val angle = Pair(rotationYaw, rotationPitch) rotationYaw = null rotationPitch = null return angle } } } return null } suspend fun wait(ticks: Int) { remainingTicks = ticks suspendCoroutine { continuation = it } } fun rotate(yaw: Float?, pitch: Float?) { rotationYaw = yaw rotationPitch = pitch } suspend fun sync() { wait(0) } }