From cf0e3331e0fec57169f0fa0a6dd7be110e4e694f Mon Sep 17 00:00:00 2001 From: Gary Tierney Date: Sun, 17 Sep 2017 03:09:47 +0100 Subject: [PATCH] Add API plugin with common functionality --- .../src/org/apollo/game/plugins/api/player.kt | 2 + .../src/org/apollo/game/plugins/api/util.kt | 7 +++ .../src/org/apollo/game/plugins/api/world.kt | 61 +++++++++++++++++++ .../org/apollo/game/model/area/Region.java | 16 ++++- .../apollo/game/action/AsyncActionRunner.kt | 12 ++-- .../apollo/game/action/AsyncActionTrait.kt | 4 +- .../game/action/AsyncDistancedAction.kt | 6 ++ 7 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 game/plugin/api/src/org/apollo/game/plugins/api/util.kt create mode 100644 game/plugin/api/src/org/apollo/game/plugins/api/world.kt diff --git a/game/plugin/api/src/org/apollo/game/plugins/api/player.kt b/game/plugin/api/src/org/apollo/game/plugins/api/player.kt index d6b46151..87881bdd 100644 --- a/game/plugin/api/src/org/apollo/game/plugins/api/player.kt +++ b/game/plugin/api/src/org/apollo/game/plugins/api/player.kt @@ -1,8 +1,10 @@ package org.apollo.game.plugins.api +import org.apollo.game.model.entity.Player import org.apollo.game.model.entity.Skill import org.apollo.game.model.entity.SkillSet +val Player.skills: SkillSet get() = skillSet val SkillSet.attack: Skill get() = getSkill(Skill.ATTACK) val SkillSet.defence: Skill get() = getSkill(Skill.DEFENCE) val SkillSet.strength: Skill get() = getSkill(Skill.STRENGTH) diff --git a/game/plugin/api/src/org/apollo/game/plugins/api/util.kt b/game/plugin/api/src/org/apollo/game/plugins/api/util.kt new file mode 100644 index 00000000..377af6c8 --- /dev/null +++ b/game/plugin/api/src/org/apollo/game/plugins/api/util.kt @@ -0,0 +1,7 @@ +import java.util.* + +val RAND = Random() + +fun rand(bounds: Int): Int { + return RAND.nextInt(bounds) +} \ No newline at end of file diff --git a/game/plugin/api/src/org/apollo/game/plugins/api/world.kt b/game/plugin/api/src/org/apollo/game/plugins/api/world.kt new file mode 100644 index 00000000..5a550879 --- /dev/null +++ b/game/plugin/api/src/org/apollo/game/plugins/api/world.kt @@ -0,0 +1,61 @@ +import org.apollo.game.model.Position +import org.apollo.game.model.World +import org.apollo.game.model.area.Region +import org.apollo.game.model.entity.Entity +import org.apollo.game.model.entity.EntityType +import org.apollo.game.model.entity.EntityType.DYNAMIC_OBJECT +import org.apollo.game.model.entity.EntityType.STATIC_OBJECT +import org.apollo.game.model.entity.obj.DynamicGameObject +import org.apollo.game.model.entity.obj.GameObject +import org.apollo.game.model.entity.obj.StaticGameObject +import org.apollo.game.scheduling.ScheduledTask +import java.lang.IllegalArgumentException +import java.util.* +import java.util.stream.Stream + +fun Region.find(position: Position, pred: (T) -> Boolean, vararg types: EntityType): Stream { + val result = this.getEntities(position, *types) + + return result.stream() + .filter(pred::invoke) +} + +fun Region.findObjects(position: Position, id: Int): Stream { + return find(position, { it.id == id }, DYNAMIC_OBJECT, STATIC_OBJECT) +} + +fun Region.findObject(position: Position, id: Int): Optional { + return find(position, { it.id == id }, DYNAMIC_OBJECT, STATIC_OBJECT) + .findFirst() +} + +class ExpireObjectTask( + val world: World, + val obj: GameObject, + val replacement: GameObject, + val respawnDelay: Int +) : ScheduledTask(0, true) { + + private var respawning: Boolean = false + + override fun execute() { + val region = world.regionRepository.fromPosition(obj.position) + + if (!respawning) { + world.spawn(replacement) + respawning = true + setDelay(respawnDelay) + } else { + region.removeEntity(replacement, false) + world.spawn(obj) + stop() + } + } +} + +fun World.expireObject(obj: GameObject, replacement: Int, respawnDelay: Int) { + val replacementObj = DynamicGameObject.createPublic(this, replacement, obj.position, obj.type, obj.orientation) + val respawnedObj = DynamicGameObject.createPublic(this, obj.id, obj.position, obj.type, obj.orientation) + + schedule(ExpireObjectTask(this, obj, replacementObj, respawnDelay)) +} diff --git a/game/src/main/java/org/apollo/game/model/area/Region.java b/game/src/main/java/org/apollo/game/model/area/Region.java index 7eafb952..e5150d45 100644 --- a/game/src/main/java/org/apollo/game/model/area/Region.java +++ b/game/src/main/java/org/apollo/game/model/area/Region.java @@ -335,12 +335,22 @@ public final class Region { } /** - * Removes an {@link Entity} from this Region. + * Removes an {@link Entity} from this Region and notifies listeners. * * @param entity The Entity. * @throws IllegalArgumentException If the Entity does not belong in this Region, or if it was never added. */ public void removeEntity(Entity entity) { + removeEntity(entity, true); + } + + /** + * Removes an {@link Entity} from this Region. + * + * @param entity The Entity. + * @throws IllegalArgumentException If the Entity does not belong in this Region, or if it was never added. + */ + public void removeEntity(Entity entity, boolean notifyListeners) { EntityType type = entity.getEntityType(); if (type.isTransient()) { throw new IllegalArgumentException("Tried to remove a transient Entity (" + entity + ") from " + @@ -356,7 +366,9 @@ public final class Region { throw new IllegalArgumentException("Entity (" + entity + ") belongs in (" + this + ") but does not exist."); } - notifyListeners(entity, EntityUpdateType.REMOVE); + if (notifyListeners) { + notifyListeners(entity, EntityUpdateType.REMOVE); + } } @Override diff --git a/game/src/main/kotlin/org/apollo/game/action/AsyncActionRunner.kt b/game/src/main/kotlin/org/apollo/game/action/AsyncActionRunner.kt index e4d3ab5f..5288abc2 100644 --- a/game/src/main/kotlin/org/apollo/game/action/AsyncActionRunner.kt +++ b/game/src/main/kotlin/org/apollo/game/action/AsyncActionRunner.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.experimental.CommonPool import kotlinx.coroutines.experimental.Job import kotlinx.coroutines.experimental.channels.Channel import kotlinx.coroutines.experimental.launch -import kotlinx.coroutines.experimental.selects.select +import kotlinx.coroutines.experimental.runBlocking class AsyncActionRunner(val actionSupplier: () -> Action<*>, val callback: suspend () -> Unit) { var job: Job? = null @@ -27,10 +27,10 @@ class AsyncActionRunner(val actionSupplier: () -> Action<*>, val callback: suspe val action = actionSupplier.invoke() job = launch(CommonPool) { - select { - pulseChannel.onReceive { + run { + while (action.isRunning) { + pulseChannel.receive() callback() - action.stop() } } } @@ -45,12 +45,14 @@ class AsyncActionRunner(val actionSupplier: () -> Action<*>, val callback: suspe pulseChannel.close() } - suspend fun wait(pulses: Int = 1) { + suspend fun wait(pulses: Int = 1, pulseCallback: (() -> Unit)? = null) { var remainingPulses = pulses while (remainingPulses > 0) { val numPulses = pulseChannel.receive() remainingPulses -= numPulses + + pulseCallback?.invoke() } } diff --git a/game/src/main/kotlin/org/apollo/game/action/AsyncActionTrait.kt b/game/src/main/kotlin/org/apollo/game/action/AsyncActionTrait.kt index f398c5f9..7ad1a973 100644 --- a/game/src/main/kotlin/org/apollo/game/action/AsyncActionTrait.kt +++ b/game/src/main/kotlin/org/apollo/game/action/AsyncActionTrait.kt @@ -3,7 +3,7 @@ package org.apollo.game.action interface AsyncActionTrait { val runner: AsyncActionRunner - suspend fun wait(pulses: Int = 1) { - runner.wait(pulses) + suspend fun wait(pulses: Int = 1, pulseCallback: (() -> Unit)? = null) { + runner.wait(pulses, pulseCallback) } } \ No newline at end of file diff --git a/game/src/main/kotlin/org/apollo/game/action/AsyncDistancedAction.kt b/game/src/main/kotlin/org/apollo/game/action/AsyncDistancedAction.kt index e947f8e4..343b2fd3 100644 --- a/game/src/main/kotlin/org/apollo/game/action/AsyncDistancedAction.kt +++ b/game/src/main/kotlin/org/apollo/game/action/AsyncDistancedAction.kt @@ -15,12 +15,18 @@ abstract class AsyncDistancedAction : DistancedAction, AsyncActionTr abstract suspend fun executeActionAsync() + open protected fun start() { + + } + override fun stop() { super.stop() runner.stop() } override fun executeAction() { + start() + if (!runner.started()) { runner.start() }