Refactor asynchronous actions to avoid thread usage

Adds custom coroutines specifically for use within Actions.  This
implements all features of the previous system, however, does not rely
on a separate executor to wake up continuations.

Note: since Actions are still ran by an executor and a small chance of
overlap exists the ActionCoroutine implementation uses atomic counters
and references.
This commit is contained in:
Gary Tierney
2017-09-19 01:52:10 +01:00
parent 169d89ffc0
commit 76dd8ba192
9 changed files with 220 additions and 122 deletions
@@ -1,3 +1,4 @@
import org.apollo.game.action.ActionBlock
import org.apollo.game.action.AsyncAction
import org.apollo.game.message.impl.ItemOptionMessage
import org.apollo.game.model.Animation
@@ -27,7 +28,7 @@ class ConsumeAction(val consumable: Consumable, player: Player, val slot: Int) :
}
}
suspend override fun executeActionAsync() {
override fun action(): ActionBlock = {
consumable.consume(mob, slot)
mob.playAnimation(Animation(CONSUME_ANIMATION_ID))
wait(consumable.delay)
+3 -4
View File
@@ -1,6 +1,7 @@
import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.selects.select
import org.apollo.game.action.ActionBlock
import org.apollo.game.action.AsyncDistancedAction
import org.apollo.game.action.DistancedAction
import org.apollo.game.message.impl.ObjectActionMessage
@@ -53,9 +54,9 @@ class DummyAction(val player: Player, position: Position) : AsyncDistancedAction
}
override suspend fun executeActionAsync() {
override fun action(): ActionBlock = {
mob.sendMessage("You hit the dummy.")
mob.turnTo(this.position)
mob.turnTo(position)
mob.playAnimation(PUNCH_ANIMATION)
wait()
@@ -66,8 +67,6 @@ class DummyAction(val player: Player, position: Position) : AsyncDistancedAction
} else {
skills.addExperience(Skill.ATTACK, EXP_PER_HIT)
}
stop()
}
}
@@ -1,3 +1,4 @@
import org.apollo.game.action.ActionBlock
import org.apollo.game.action.AsyncDistancedAction
import org.apollo.game.action.DistancedAction
import org.apollo.game.message.impl.ObjectActionMessage
@@ -68,18 +69,15 @@ class MiningAction(player: Player, val tool: Pickaxe, val target: MiningTarget)
}
}
override fun start() {
override fun action() : ActionBlock = {
mob.turnTo(position)
val level = mob.skills.mining.currentLevel
if (level < target.ore.level) {
mob.sendMessage("You do not have the required level to mine this rock.")
stop()
}
}
override suspend fun executeActionAsync() {
mob.sendMessage("You swing your pick at the rock.")
mob.playAnimation(tool.animation)
@@ -88,14 +86,12 @@ class MiningAction(player: Player, val tool: Pickaxe, val target: MiningTarget)
val obj = target.getObject(mob.world)
if (!obj.isPresent) {
stop()
return
}
if (target.isSuccessful(mob)) {
if (mob.inventory.freeSlots() == 0) {
mob.inventory.forceCapacityExceeded()
stop()
return
}
if (mob.inventory.add(target.ore.id)) {
@@ -105,7 +101,6 @@ class MiningAction(player: Player, val tool: Pickaxe, val target: MiningTarget)
mob.skills.addExperience(Skill.MINING, target.ore.exp)
mob.world.expireObject(obj.get(), target.ore.objects[target.objectId]!!, target.ore.respawn)
stop()
return
}
}
}
@@ -142,7 +137,7 @@ class ProspectingAction(val m: Player, val p: Position, val ore: Ore) : AsyncDis
}
}
suspend override fun executeActionAsync() {
override fun action() : ActionBlock = {
mob.sendMessage("You examine the rock for ores...")
mob.turnTo(position)