mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-03 00:38:21 +00:00
Add unit tests for areas plugin
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
package org.apollo.game.plugins.area
|
||||
|
||||
import org.apollo.game.model.Position
|
||||
import org.apollo.game.plugins.api.Position.component1
|
||||
import org.apollo.game.plugins.api.Position.component2
|
||||
import org.apollo.game.plugins.api.Position.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
|
||||
|
||||
}
|
||||
|
||||
internal class RectangularArea(private val x: IntRange, private val y: IntRange, private 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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.apollo.game.plugins.area
|
||||
|
||||
import org.apollo.game.model.Position
|
||||
import org.apollo.game.model.entity.Player
|
||||
|
||||
/**
|
||||
* A set of actions to execute when a player enters, moves inside, or exits a specific area of the world.
|
||||
*/
|
||||
internal class AreaAction(val entrance: AreaListener, val inside: AreaListener, val exit: AreaListener)
|
||||
|
||||
/**
|
||||
* A function that is invoked when a player enters, moves inside of, or exits an [Area].
|
||||
*/
|
||||
typealias AreaListener = Player.(Position) -> Unit
|
||||
|
||||
/**
|
||||
* Registers an [AreaAction] for the specified [Area] using the builder.
|
||||
*/
|
||||
fun action(name: String, area: Area, builder: AreaActionBuilder.() -> Unit) {
|
||||
actions += AreaActionBuilder(name, area).apply(builder).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an [AreaAction] for the specified [Area] using the builder.
|
||||
*
|
||||
* @param predicate The predicate that determines whether or not the given [Position] is inside the [Area].
|
||||
*/
|
||||
fun action(name: String, predicate: (Position) -> Boolean, builder: AreaActionBuilder.() -> Unit) {
|
||||
val area = object : Area {
|
||||
override fun contains(position: Position): Boolean = predicate(position)
|
||||
}
|
||||
|
||||
action(name, area, builder)
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an [AreaAction] for the specified [Area] using the builder.
|
||||
*
|
||||
* @param x The `x` coordinate range, both ends inclusive.
|
||||
* @param y The `y` coordinate range, both ends inclusive.
|
||||
*/
|
||||
fun action(name: String, x: IntRange, y: IntRange, height: Int = 0, builder: AreaActionBuilder.() -> Unit) {
|
||||
val area = RectangularArea(x, y, height)
|
||||
|
||||
action(name, area, builder)
|
||||
}
|
||||
|
||||
/**
|
||||
* The [Set] of ([Area], [AreaAction]) [Pair]s.
|
||||
*/
|
||||
internal val actions = mutableSetOf<Pair<Area, AreaAction>>()
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.apollo.game.plugins.area
|
||||
|
||||
/**
|
||||
* A builder for ([Area], [AreaAction]) [Pair]s.
|
||||
*/
|
||||
class AreaActionBuilder internal constructor(val name: String, val area: Area) {
|
||||
|
||||
private var entrance: AreaListener = { }
|
||||
|
||||
private var inside: AreaListener = { }
|
||||
|
||||
private var exit: AreaListener = { }
|
||||
|
||||
/**
|
||||
* Places the contents of this builder into an ([Area], [AreaAction]) [Pair].
|
||||
*/
|
||||
internal fun build(): Pair<Area, AreaAction> {
|
||||
return Pair(area, AreaAction(entrance, inside, exit))
|
||||
}
|
||||
|
||||
/**
|
||||
* The [listener] to execute when a player enters the associated [Area].
|
||||
*/
|
||||
fun entrance(listener: AreaListener) {
|
||||
this.entrance = listener
|
||||
}
|
||||
|
||||
/**
|
||||
* The [listener] to execute when a player moves around inside the associated [Area].
|
||||
*/
|
||||
fun inside(listener: AreaListener) {
|
||||
this.inside = listener
|
||||
}
|
||||
|
||||
/**
|
||||
* The [listener] to execute when a player moves exits the associated [Area].
|
||||
*/
|
||||
fun exit(listener: AreaListener) {
|
||||
this.exit = listener
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
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)
|
||||
@@ -1,94 +0,0 @@
|
||||
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.Position.component1
|
||||
import org.apollo.game.plugins.api.Position.component2
|
||||
import org.apollo.game.plugins.api.Position.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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import org.apollo.game.model.Position
|
||||
import org.apollo.game.model.entity.Player
|
||||
import org.apollo.game.plugin.testing.junit.ApolloTestingExtension
|
||||
import org.apollo.game.plugin.testing.junit.api.annotations.TestMock
|
||||
import org.apollo.game.plugins.area.action
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
|
||||
@ExtendWith(ApolloTestingExtension::class)
|
||||
class AreaActionTests {
|
||||
|
||||
@TestMock
|
||||
lateinit var player: Player
|
||||
|
||||
@Test
|
||||
fun `entrance action is triggered when a player enters the area`() {
|
||||
var triggered = false
|
||||
val position = Position(3222, 3222)
|
||||
|
||||
action("entrance_test_action", predicate = { it == player.position }) {
|
||||
triggered = true
|
||||
}
|
||||
|
||||
player.position = position
|
||||
|
||||
assertTrue(triggered) { "entrance_test_action was not triggered." }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `inside action is triggered when a player moves inside an area`() {
|
||||
player.position = Position(3222, 3222)
|
||||
var triggered = false
|
||||
|
||||
action("inside_test_action", x = 3220..3224, y = 3220..3224) {
|
||||
triggered = true
|
||||
}
|
||||
|
||||
player.position = Position(3223, 3222)
|
||||
|
||||
assertTrue(triggered) { "inside_test_action was not triggered." }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `exit action is triggered when a player exits the area`() {
|
||||
player.position = Position(3222, 3222)
|
||||
|
||||
var triggered = false
|
||||
|
||||
action("exit_test_action", predicate = { it == player.position }) {
|
||||
triggered = true
|
||||
}
|
||||
|
||||
player.position = Position(3221, 3221)
|
||||
|
||||
assertTrue(triggered) { "exit_test_action was not triggered." }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user