diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinCommandHandler.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinCommandHandler.kt index a939e44c..4509eaa2 100644 --- a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinCommandHandler.kt +++ b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinCommandHandler.kt @@ -13,17 +13,29 @@ class KotlinCommandHandler( val world: World, val command: String, privileges: PrivilegeLevel -) : KotlinPlayerHandlerProxyTrait, CommandListener(privileges) { +) : CommandListener(privileges) { - override var callback: Command.(Player) -> Unit = {} - override var predicate: Command.() -> Boolean = { true } + var callback: Command.(Player) -> Unit = {} + var predicate: Command.() -> Boolean = { true } override fun execute(player: Player, command: Command) { - handleProxy(player, command) + if (command.predicate()) { + command.callback(player) + } } - override fun register() { + fun register() { world.commandDispatcher.register(command, this) } + fun where(predicate: Command.() -> Boolean): KotlinCommandHandler { + this.predicate = predicate + return this + } + + fun then(callback: Command.(Player) -> Unit) { + this.callback = callback + this.register() + } + } \ No newline at end of file diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinMessageHandler.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinMessageHandler.kt index f6e1ec4c..6882cc2e 100644 --- a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinMessageHandler.kt +++ b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinMessageHandler.kt @@ -7,15 +7,15 @@ import org.apollo.game.plugin.PluginContext import org.apollo.net.message.Message import kotlin.reflect.KClass -class KotlinMessageHandler( +class KotlinMessageHandler( world: World, - private val listenable: MessageListenable, + private val listenable: MessageListenable, private val callback: T.() -> Unit ) : MessageHandler(world) { override fun handle(player: Player, message: F) { - val context = listenable.from(player, message) - context.callback() + val context = listenable.createContext(player, message) + context?.callback() } } diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinPluginScript.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinPluginScript.kt index 51cfbd12..cadd4629 100644 --- a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinPluginScript.kt +++ b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/KotlinPluginScript.kt @@ -20,34 +20,34 @@ abstract class KotlinPluginScript(var world: World, val context: PluginContext) private var stopListener: (World) -> Unit = { _ -> } - fun on(listenable: Listenable, callback: T.() -> Unit) { + fun on(listenable: Listenable, callback: C.() -> Unit) { // Smart-casting/type-inference is completely broken in this function in intelliJ, so assign to otherwise // pointless `l` values for now. return when (listenable) { is MessageListenable -> { @Suppress("UNCHECKED_CAST") - val l = listenable as MessageListenable + val l = listenable as MessageListenable val handler = KotlinMessageHandler(world, l, callback) context.addMessageHandler(l.type.java, handler) } is PlayerEventListenable -> { @Suppress("UNCHECKED_CAST") - val l = listenable as PlayerEventListenable + val l = listenable as PlayerEventListenable world.listenFor(l.type.java) { event -> - val context = l.from(event) - context.callback() + val context = l.createContext(event) + context?.callback() } } is EventListenable -> { @Suppress("UNCHECKED_CAST") - val l = listenable as EventListenable + val l = listenable as EventListenable world.listenFor(l.type.java) { event -> - val context = l.from(event) - context.callback() + val context = l.createContext(event) + context?.callback() } } } diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/Listenable.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/Listenable.kt index 17cef5a0..14e9efbe 100644 --- a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/Listenable.kt +++ b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/Listenable.kt @@ -9,24 +9,24 @@ import kotlin.reflect.KClass /** * A game occurrence that can be listened to. */ -sealed class Listenable { - abstract val type: KClass +sealed class Listenable { + abstract val type: KClass } -abstract class EventListenable : Listenable() { - abstract fun from(event: F): T +abstract class EventListenable : Listenable() { + abstract fun createContext(event: T): C? } -abstract class MessageListenable : Listenable() { - abstract fun from(player: Player, message: F): T +abstract class MessageListenable : Listenable() { + abstract fun createContext(player: Player, message: T): C? } -abstract class PlayerEventListenable : EventListenable() { +abstract class PlayerEventListenable : EventListenable() { - abstract fun from(player: Player, event: F): T + abstract fun createContext(player: Player, event: T): C? - override fun from(event: F): T { - return from(event.player, event) + final override fun createContext(event: T): C? { + return createContext(event.player, event) } } \ No newline at end of file diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/ListenableContext.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/ListenableContext.kt index 02ae45a3..5f5fef95 100644 --- a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/ListenableContext.kt +++ b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/ListenableContext.kt @@ -1,6 +1,15 @@ package org.apollo.game.plugin.kotlin +import org.apollo.game.model.entity.Player + /** - * Contains contextual information for a [Listenable]. + * Contextual information for a [Listenable]. */ interface ListenableContext + +/** + * Contextual information for a [Listenable] involving a specific [Player]. + */ +interface PlayerContext : ListenableContext { + val player: Player +} \ No newline at end of file diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/ObjectAction.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/ObjectAction.kt deleted file mode 100644 index 4533d20a..00000000 --- a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/ObjectAction.kt +++ /dev/null @@ -1,53 +0,0 @@ -package org.apollo.game.plugin.kotlin.action.obj - -import org.apollo.cache.def.ObjectDefinition -import org.apollo.game.message.impl.ObjectActionMessage -import org.apollo.game.model.entity.EntityType -import org.apollo.game.model.entity.Player -import org.apollo.game.model.entity.obj.GameObject -import org.apollo.game.plugin.kotlin.action.ActionListenableContext - -/** - * An interaction between a [Player] and an [interactive] [GameObject]. - */ -class ObjectAction( - override val option: String, - override val player: Player, - val target: GameObject, - val interactive: T -) : ActionListenableContext { - - companion object : ObjectActionListenable() { - - override fun from(player: Player, message: ObjectActionMessage): ObjectAction<*> { - val def = ObjectDefinition.lookup(message.id) - val selectedAction = def.menuActions[message.option] - - val obj = player.world.regionRepository - .fromPosition(message.position) - .getEntities(message.position, EntityType.DYNAMIC_OBJECT, EntityType.STATIC_OBJECT) - .first { it.definition == def } - - return ObjectAction(selectedAction, player, obj, null) - } - - override val type = ObjectActionMessage::class - - override fun from( - player: Player, - other: ObjectActionMessage, - objects: List - ): ObjectAction { - val def = ObjectDefinition.lookup(other.id) - val selectedAction = def.menuActions[other.option] - - val obj = player.world.regionRepository - .fromPosition(other.position) - .getEntities(other.position, EntityType.DYNAMIC_OBJECT, EntityType.STATIC_OBJECT) - .first { it.definition == def } - - return ObjectAction(selectedAction, player, obj, objects.first { it.instanceOf(obj) }) - } - } - -} diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/ActionListenableContext.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/ActionContext.kt similarity index 62% rename from game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/ActionListenableContext.kt rename to game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/ActionContext.kt index d362b716..95863ddd 100644 --- a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/ActionListenableContext.kt +++ b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/ActionContext.kt @@ -1,9 +1,8 @@ -package org.apollo.game.plugin.kotlin.action +package org.apollo.game.plugin.kotlin.message.action -import org.apollo.game.model.entity.Player import org.apollo.game.plugin.kotlin.KotlinPluginScript -import org.apollo.game.plugin.kotlin.ListenableContext import org.apollo.game.plugin.kotlin.MessageListenable +import org.apollo.game.plugin.kotlin.PlayerContext import org.apollo.net.message.Message /** @@ -15,8 +14,8 @@ import org.apollo.net.message.Message * } * ``` */ -inline fun KotlinPluginScript.on( - listenable: MessageListenable, +inline fun KotlinPluginScript.on( + listenable: MessageListenable, option: String, crossinline callback: T.() -> Unit ) { @@ -27,7 +26,6 @@ inline fun KotlinPluginScript } } -interface ActionListenableContext : ListenableContext { +interface ActionContext : PlayerContext { val option: String - val player: Player } diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/InteractiveObject.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/InteractiveObject.kt similarity index 79% rename from game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/InteractiveObject.kt rename to game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/InteractiveObject.kt index fe903ce5..85e2c695 100644 --- a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/InteractiveObject.kt +++ b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/InteractiveObject.kt @@ -1,4 +1,4 @@ -package org.apollo.game.plugin.kotlin.action.obj +package org.apollo.game.plugin.kotlin.message.action.obj import org.apollo.game.model.entity.obj.GameObject diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/ObjectAction.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/ObjectAction.kt new file mode 100644 index 00000000..db4bab0d --- /dev/null +++ b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/ObjectAction.kt @@ -0,0 +1,60 @@ +package org.apollo.game.plugin.kotlin.message.action.obj + +import org.apollo.cache.def.ObjectDefinition +import org.apollo.game.message.impl.ObjectActionMessage +import org.apollo.game.model.entity.EntityType +import org.apollo.game.model.entity.Player +import org.apollo.game.model.entity.obj.GameObject +import org.apollo.game.plugin.kotlin.message.action.ActionContext + +/** + * An interaction between a [Player] and an [interactive] [GameObject]. + */ +class ObjectAction( // TODO split into two classes, one with T and one without? + override val player: Player, + override val option: String, + val target: GameObject, + val interactive: T +) : ActionContext { + + companion object : ObjectActionListenable() { + + override val type = ObjectActionMessage::class + + override fun createContext(player: Player, message: ObjectActionMessage): ObjectAction<*>? { + return create(player, message, objects = null) + } + + override fun createContext( + player: Player, + other: ObjectActionMessage, + objects: List + ): ObjectAction? { + @Suppress("UNCHECKED_CAST") + return create(player, other, objects) as ObjectAction + } + + private fun create( + player: Player, + other: ObjectActionMessage, + objects: List? + ): ObjectAction<*>? { + val def = ObjectDefinition.lookup(other.id) + val selectedAction = def.menuActions[other.option] + + val obj = player.world.regionRepository + .fromPosition(other.position) + .getEntities(other.position, EntityType.DYNAMIC_OBJECT, EntityType.STATIC_OBJECT) + .find { it.definition == def } + ?: return null + + if (objects == null) { + return ObjectAction(player, selectedAction, obj, null) + } else { + val interactive = objects.find { it.instanceOf(obj) } ?: return null + return ObjectAction(player, selectedAction, obj, interactive) + } + } + } + +} diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/ObjectActionListenable.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/ObjectActionListenable.kt similarity index 67% rename from game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/ObjectActionListenable.kt rename to game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/ObjectActionListenable.kt index fc37d559..bf9bfbf6 100644 --- a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/ObjectActionListenable.kt +++ b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/ObjectActionListenable.kt @@ -1,17 +1,17 @@ -package org.apollo.game.plugin.kotlin.action.obj +package org.apollo.game.plugin.kotlin.message.action.obj import org.apollo.game.message.impl.ObjectActionMessage import org.apollo.game.model.entity.Player import org.apollo.game.plugin.kotlin.MessageListenable -abstract class ObjectActionListenable : MessageListenable, ObjectActionMessage>() { +abstract class ObjectActionListenable : MessageListenable>() { override val type = ObjectActionMessage::class - abstract fun from( + abstract fun createContext( player: Player, other: ObjectActionMessage, objects: List - ): ObjectAction + ): ObjectAction? } \ No newline at end of file diff --git a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/ListenableDsl.kt b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/ObjectActionMessageHandler.kt similarity index 74% rename from game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/ListenableDsl.kt rename to game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/ObjectActionMessageHandler.kt index 2ed023c7..fa3e5de7 100644 --- a/game/src/main/kotlin/org/apollo/game/plugin/kotlin/action/obj/ListenableDsl.kt +++ b/game/src/main/kotlin/org/apollo/game/plugin/kotlin/message/action/obj/ObjectActionMessageHandler.kt @@ -1,4 +1,4 @@ -package org.apollo.game.plugin.kotlin.action.obj +package org.apollo.game.plugin.kotlin.message.action.obj import org.apollo.cache.def.ObjectDefinition import org.apollo.game.message.handler.MessageHandler @@ -8,18 +8,6 @@ import org.apollo.game.model.entity.EntityType import org.apollo.game.model.entity.Player import org.apollo.game.model.entity.obj.GameObject import org.apollo.game.plugin.kotlin.KotlinPluginScript -import org.apollo.game.plugin.kotlin.action.on - -@Deprecated("example function, remove") -fun KotlinPluginScript.x() { - on(ObjectAction, option = "Trade", objects = listOf()) { - - } - - on(ObjectAction, option = "Trade") { - - } -} /** * Registers a listener for [ObjectActionMessage]s that occur on any of the given [InteractiveObject]s using the @@ -27,7 +15,7 @@ fun KotlinPluginScript.x() { * * ``` * on(ObjectAction, option = "Open", objects = DOORS.toList()) { - * player.sendMessage("You open the door") + * player.sendMessage("You open the door.") * } * ``` */ @@ -39,10 +27,8 @@ fun KotlinPluginScript.on( ) { if (objects.isEmpty()) { on(listenable) { - if (this.option.equals(option, ignoreCase = true)) { - @Suppress("UNCHECKED_CAST") (this as ObjectAction) - callback() - } + @Suppress("UNCHECKED_CAST") (callback as ObjectAction<*>.() -> Unit) + callback(this) } } else { val handler = ObjectActionMessageHandler(world, listenable, objects, option, callback) @@ -50,9 +36,6 @@ fun KotlinPluginScript.on( } } -/** - * A [MessageHandler] - */ class ObjectActionMessageHandler( world: World, private val listenable: ObjectActionListenable, @@ -71,8 +54,8 @@ class ObjectActionMessageHandler( .first { it.definition == def } if (option.equals(selectedAction, ignoreCase = true) && objects.any { it.instanceOf(obj) }) { - val context = listenable.from(player, message, objects) - context.callback() + val context = listenable.createContext(player, message, objects) + context?.callback() } }