diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/Interact.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/Interact.kt index 09a192fc7..1f0886991 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/Interact.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/Interact.kt @@ -152,8 +152,7 @@ class Interact( * Continue any suspended, clear any finished or start a new interaction */ private fun launch(event: Interaction<*>): Boolean { - if (character.suspension != null) { - character.resumeSuspension() + if (character.resumeSuspension()) { return true } if (!event.launched && character.emit(event)) { diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/Interaction.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/Interaction.kt index 012dc1bae..c58dba556 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/Interaction.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/Interaction.kt @@ -22,7 +22,7 @@ abstract class Interaction : CancellableEvent(), SuspendableEvent * interaction will have finished and there will be nothing to resume the suspension */ override suspend fun pause(ticks: Int) { - TickSuspension(ticks) + TickSuspension.start(character, ticks) } /** diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/AreaEntered.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/AreaEntered.kt index fc2ac87c7..364fc1082 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/AreaEntered.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/AreaEntered.kt @@ -22,7 +22,7 @@ data class AreaEntered( override val size = 5 override suspend fun pause(ticks: Int) { - TickSuspension(ticks) + TickSuspension.start(character, ticks) } override fun parameter(dispatcher: EventDispatcher, index: Int): Any? = when (index) { diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/AreaExited.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/AreaExited.kt index 660fbb986..c9ffcee5e 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/AreaExited.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/AreaExited.kt @@ -21,7 +21,7 @@ data class AreaExited( override val size = 5 override suspend fun pause(ticks: Int) { - TickSuspension(ticks) + TickSuspension.start(character, ticks) } override fun parameter(dispatcher: EventDispatcher, index: Int): Any? = when (index) { diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/Moved.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/Moved.kt index 024e7f920..a0c4ec7fe 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/Moved.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/mode/move/Moved.kt @@ -24,7 +24,7 @@ data class Moved( override val size = 4 override suspend fun pause(ticks: Int) { - TickSuspension(ticks) + TickSuspension.start(character, ticks) } override fun parameter(dispatcher: EventDispatcher, index: Int): Any? = when (index) { diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/npc/NPC.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/npc/NPC.kt index 5f2f02dbc..498cdae66 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/npc/NPC.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/npc/NPC.kt @@ -36,10 +36,6 @@ data class NPC( override var softTimers: Timers = TimerSlot(this) override var delay: Continuation? = null override var suspension: Suspension? = null - set(value) { - field?.cancel() - field = value - } override var variables: Variables = Variables(this) override val steps: Steps = Steps(this) diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/player/Player.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/player/Player.kt index 6dd1852d3..496391d5e 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/player/Player.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/entity/character/player/Player.kt @@ -65,10 +65,6 @@ class Player( get() = client != null && viewport != null override var suspension: Suspension? = null - set(value) { - field?.cancel() - field = value - } override var delay: Continuation? = null diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/InfiniteSuspension.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/InfiniteSuspension.kt deleted file mode 100644 index 2a20ae3a5..000000000 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/InfiniteSuspension.kt +++ /dev/null @@ -1,17 +0,0 @@ -package world.gregs.voidps.engine.suspend - -import kotlinx.coroutines.suspendCancellableCoroutine - -object InfiniteSuspension : Suspension() { - override val onCancel: (() -> Unit)? = null - - override fun ready(): Boolean { - return false - } - - context(SuspendableContext<*>) suspend operator fun invoke() { - suspendCancellableCoroutine { - character.suspension = InfiniteSuspension - } - } -} \ No newline at end of file diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/PredicateSuspension.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/PredicateSuspension.kt index fcdc77503..15acc9eb3 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/PredicateSuspension.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/PredicateSuspension.kt @@ -1,33 +1,22 @@ package world.gregs.voidps.engine.suspend -import kotlinx.coroutines.CancellableContinuation import kotlinx.coroutines.suspendCancellableCoroutine -import kotlin.coroutines.resume +import world.gregs.voidps.engine.entity.character.Character class PredicateSuspension( private val predicate: () -> Boolean, - override val onCancel: (() -> Unit)?, - private val continuation: CancellableContinuation ) : Suspension() { - var boolean: Boolean? = null - override fun ready(): Boolean { return predicate.invoke() } - override fun resume() { - super.resume() - continuation.resume(Unit) - } - companion object { - context(SuspendableContext<*>) suspend operator fun invoke(predicate: () -> Boolean) { - if (predicate.invoke()) { - return - } + suspend fun start(character: Character, predicate: () -> Boolean) { + val suspension = PredicateSuspension(predicate) suspendCancellableCoroutine { - character.suspension = PredicateSuspension(predicate, onCancel, it) + suspension.continuation = it + character.suspension = suspension } character.suspension = null } diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/Suspend.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/Suspend.kt index 2728626c0..19e5176f9 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/Suspend.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/Suspend.kt @@ -24,19 +24,15 @@ fun Character.resumeSuspension(): Boolean { } suspend fun SuspendableContext.awaitDialogues(): Boolean { - PredicateSuspension { player.dialogue == null } + PredicateSuspension.start(character) { player.dialogue == null } return true } suspend fun SuspendableContext.awaitInterfaces(): Boolean { - PredicateSuspension { player.menu == null } + PredicateSuspension.start(character) { player.menu == null } return true } -suspend fun SuspendableContext<*>.pauseForever() { - InfiniteSuspension() -} - private val logger = InlineLogger() context(SuspendableContext<*>) suspend fun Character.playAnimation(id: String, override: Boolean = false, canInterrupt: Boolean = true) { diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/Suspension.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/Suspension.kt index f65de5cae..76169b286 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/Suspension.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/Suspension.kt @@ -1,14 +1,14 @@ package world.gregs.voidps.engine.suspend +import kotlinx.coroutines.CancellableContinuation +import kotlin.coroutines.resume + abstract class Suspension { - protected abstract val onCancel: (() -> Unit)? + lateinit var continuation: CancellableContinuation abstract fun ready(): Boolean open fun resume() { - } - - open fun cancel() { - onCancel?.invoke() + continuation.resume(Unit) } } \ No newline at end of file diff --git a/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/TickSuspension.kt b/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/TickSuspension.kt index 1c9ca0870..1d2c80136 100644 --- a/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/TickSuspension.kt +++ b/engine/src/main/kotlin/world/gregs/voidps/engine/suspend/TickSuspension.kt @@ -1,32 +1,26 @@ package world.gregs.voidps.engine.suspend -import kotlinx.coroutines.CancellableContinuation import kotlinx.coroutines.suspendCancellableCoroutine import world.gregs.voidps.engine.GameLoop -import kotlin.coroutines.resume +import world.gregs.voidps.engine.entity.character.Character data class TickSuspension( - val tick: Int, - override val onCancel: (() -> Unit)?, - private val continuation: CancellableContinuation + private val tick: Int, ) : Suspension() { override fun ready(): Boolean { return GameLoop.tick >= tick } - override fun resume() { - super.resume() - continuation.resume(Unit) - } - companion object { - context(SuspendableContext<*>) suspend operator fun invoke(ticks: Int) { + suspend fun start(character: Character, ticks: Int) { if (ticks <= 0) { return } + val suspension = TickSuspension(GameLoop.tick + ticks) suspendCancellableCoroutine { - character.suspension = TickSuspension(GameLoop.tick + ticks, onCancel, it) + suspension.continuation = it + character.suspension = suspension } character.suspension = null } diff --git a/engine/src/test/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/InteractTest.kt b/engine/src/test/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/InteractTest.kt index 912301a68..a7973a0c5 100644 --- a/engine/src/test/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/InteractTest.kt +++ b/engine/src/test/kotlin/world/gregs/voidps/engine/entity/character/mode/interact/InteractTest.kt @@ -96,7 +96,7 @@ internal class InteractTest : KoinMock() { if (operate) { Events.handle>("player_operate_npc", "*", "*") { if (suspend) { - TickSuspension(2) + TickSuspension.start(character, 2) } operated = true } @@ -104,7 +104,7 @@ internal class InteractTest : KoinMock() { if (approach) { Events.handle>("player_approach_npc", "*", "*") { if (suspend) { - TickSuspension(2) + TickSuspension.start(character, 2) } approached = true }