Port Area plugin to Kotlin

This commit is contained in:
Major
2017-09-24 18:42:06 +01:00
parent cb9e6f353d
commit ce1bcba893
4 changed files with 141 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
plugin {
name = "Area listeners"
description = "Enables plugins to listen on mobs entering, moving inside of, or leaving a rectangular area."
authors = ["Major"]
dependencies = ["api"]
}
+18
View File
@@ -0,0 +1,18 @@
package org.apollo.game.plugins.area
/**
* Defines an area action using the DSL.
*/
fun action(@Suppress("UNUSED_PARAMETER") name: String, builder: ActionBuilder.() -> Unit) {
val listener = ActionBuilder()
builder(listener)
actions.add(listener.build())
}
/**
* The [Set] of ([Area], [AreaAction]) [Pair]s.
*/
val actions = mutableSetOf<Pair<Area, AreaAction>>()
class AreaAction(val entrance: AreaListener, val inside: AreaListener, val exit: AreaListener)
+94
View File
@@ -0,0 +1,94 @@
package org.apollo.game.plugins.area
import org.apollo.game.model.Position
import org.apollo.game.model.entity.Player
import org.apollo.game.plugins.api.component1
import org.apollo.game.plugins.api.component2
import org.apollo.game.plugins.api.component3
/**
* An area in the game world.
*/
interface Area {
/**
* Returns whether or not the specified [Position] is inside this [Area].
*/
operator fun contains(position: Position): Boolean
}
private class RectangularArea(val x: IntRange, val y: IntRange, val height: Int) : Area {
override operator fun contains(position: Position): Boolean {
val (x, y, z) = position
return x in this.x && y in this.y && z == height
}
}
/**
* A typealias for a function that is invoked when a player enters, moves inside of, or exits an [Area].
*/
internal typealias AreaListener = Player.(Position) -> Unit
/**
* A builder for ([Area], [AreaAction]) [Pair]s.
*/
class ActionBuilder {
private var area: Area? = null
private var entrance: AreaListener = { }
private var inside: AreaListener = { }
private var exit: AreaListener = { }
/**
* Places the contents of this builder into an ([Area], [AreaAction]) [Pair].
*/
fun build(): Pair<Area, AreaAction> {
val area = area ?: throw UnsupportedOperationException("Area must be specified.")
return Pair(area, AreaAction(entrance, inside, exit))
}
/**
* Sets the [Area] to listen for movement in.
*/
fun area(contains: (Position) -> Boolean) {
this.area = object : Area {
override fun contains(position: Position): Boolean = contains.invoke(position)
}
}
/**
* Sets the [Area] to listen for movement in. Note that [IntRange]s are (inclusive, _exclusive_), i.e. the upper
* bound is exclusive.
*/
fun area(x: IntRange, y: IntRange, height: Int = 0) {
this.area = RectangularArea(x, y, height)
}
/**
* Executes the specified [listener] when a player enters the related [Area].
*/
fun entrance(listener: AreaListener) {
this.entrance = listener
}
/**
* Executes the specified [listener] when a player moves around inside the related [Area].
*/
fun inside(listener: AreaListener) {
this.inside = listener
}
/**
* Executes the specified [listener] when a player moves exits the related [Area].
*/
fun exit(listener: AreaListener) {
this.exit = listener
}
}
+23
View File
@@ -0,0 +1,23 @@
import org.apollo.game.model.entity.Player
import org.apollo.game.model.event.impl.MobPositionUpdateEvent
import org.apollo.game.plugins.area.actions
/**
* Intercepts the [MobPositionUpdateEvent] and invokes area actions if necessary.
*/
on_event { MobPositionUpdateEvent::class }
.where { mob is Player }
.then {
for ((area, action) in actions) {
if (mob.position in area) {
if (next in area) {
action.inside(mob as Player, next)
} else {
action.exit(mob as Player, next)
}
} else if (next in area) {
action.entrance(mob as Player, next)
}
}
}