mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-02 16:49:12 +00:00
Create raw handlers in plugin listener overloads
This commit is contained in:
@@ -7,19 +7,6 @@ import org.apollo.game.plugin.PluginContext
|
||||
import org.apollo.net.message.Message
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class KotlinMessageHandler<F : Message, T : ListenableContext>(
|
||||
world: World,
|
||||
private val listenable: MessageListenable<F, T>,
|
||||
private val callback: T.() -> Unit
|
||||
) : MessageHandler<F>(world) {
|
||||
|
||||
override fun handle(player: Player, message: F) {
|
||||
val context = listenable.createContext(player, message)
|
||||
context?.callback()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A handler for [Message]s.
|
||||
*/
|
||||
|
||||
@@ -20,35 +20,35 @@ abstract class KotlinPluginScript(var world: World, val context: PluginContext)
|
||||
|
||||
private var stopListener: (World) -> Unit = { _ -> }
|
||||
|
||||
fun <T : Any, C : ListenableContext> on(listenable: Listenable<T, C>, callback: C.() -> Unit) {
|
||||
fun <T : Any, C : ListenableContext, I : PredicateContext> on(
|
||||
listenable: Listenable<T, C, I>,
|
||||
callback: C.() -> Unit
|
||||
) {
|
||||
registerListener(listenable, null, callback)
|
||||
}
|
||||
|
||||
internal fun <T : Any, C : ListenableContext, I : PredicateContext> registerListener(
|
||||
listenable: Listenable<T, C, I>,
|
||||
predicateContext: I?,
|
||||
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<Message, C>
|
||||
val l = listenable as MessageListenable<Message, C, I>
|
||||
|
||||
val handler = KotlinMessageHandler(world, l, callback)
|
||||
val handler = l.createHandler(world, predicateContext, callback)
|
||||
context.addMessageHandler(l.type.java, handler)
|
||||
}
|
||||
is PlayerEventListenable -> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val l = listenable as PlayerEventListenable<PlayerEvent, C>
|
||||
|
||||
world.listenFor(l.type.java) { event ->
|
||||
val context = l.createContext(event)
|
||||
context?.callback()
|
||||
}
|
||||
}
|
||||
is EventListenable -> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val l = listenable as EventListenable<Event, C>
|
||||
val l = listenable as EventListenable<Event, C, I>
|
||||
|
||||
world.listenFor(l.type.java) { event ->
|
||||
val context = l.createContext(event)
|
||||
context?.callback()
|
||||
}
|
||||
val handler = l.createHandler(world, predicateContext, callback)
|
||||
world.listenFor(l.type.java, handler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,27 @@
|
||||
package org.apollo.game.plugin.kotlin
|
||||
|
||||
import org.apollo.game.model.entity.Player
|
||||
import org.apollo.game.message.handler.MessageHandler
|
||||
import org.apollo.game.model.World
|
||||
import org.apollo.game.model.event.Event
|
||||
import org.apollo.game.model.event.PlayerEvent
|
||||
import org.apollo.game.model.event.EventListener
|
||||
import org.apollo.net.message.Message
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* A game occurrence that can be listened to.
|
||||
*/
|
||||
sealed class Listenable<T : Any, C : ListenableContext> {
|
||||
sealed class Listenable<T : Any, C : ListenableContext, P : PredicateContext> {
|
||||
abstract val type: KClass<T>
|
||||
}
|
||||
|
||||
abstract class EventListenable<T : Event, C : ListenableContext> : Listenable<T, C>() {
|
||||
abstract fun createContext(event: T): C?
|
||||
abstract class EventListenable<T : Event, C : ListenableContext, P : PredicateContext> : Listenable<T, C, P>() {
|
||||
|
||||
abstract fun createHandler(world: World, predicateContext: P?, callback: C.() -> Unit): EventListener<T>
|
||||
|
||||
}
|
||||
|
||||
abstract class MessageListenable<T : Message, C : ListenableContext> : Listenable<T, C>() {
|
||||
abstract fun createContext(player: Player, message: T): C?
|
||||
abstract class MessageListenable<T : Message, C : ListenableContext, P : PredicateContext> : Listenable<T, C, P>() {
|
||||
|
||||
abstract fun createHandler(world: World, predicateContext: P?, callback: C.() -> Unit): MessageHandler<T>
|
||||
|
||||
}
|
||||
|
||||
abstract class PlayerEventListenable<T : PlayerEvent, C : ListenableContext> : EventListenable<T, C>() {
|
||||
|
||||
abstract fun createContext(player: Player, event: T): C?
|
||||
|
||||
final override fun createContext(event: T): C? {
|
||||
return createContext(event.player, event)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,4 +12,6 @@ interface ListenableContext
|
||||
*/
|
||||
interface PlayerContext : ListenableContext {
|
||||
val player: Player
|
||||
}
|
||||
}
|
||||
|
||||
interface PredicateContext
|
||||
@@ -1,10 +1,13 @@
|
||||
package org.apollo.game.plugin.kotlin.message
|
||||
|
||||
import org.apollo.game.message.handler.MessageHandler
|
||||
import org.apollo.game.message.impl.ButtonMessage
|
||||
import org.apollo.game.model.World
|
||||
import org.apollo.game.model.entity.Player
|
||||
import org.apollo.game.plugin.kotlin.KotlinPluginScript
|
||||
import org.apollo.game.plugin.kotlin.MessageListenable
|
||||
import org.apollo.game.plugin.kotlin.PlayerContext
|
||||
import org.apollo.game.plugin.kotlin.PredicateContext
|
||||
|
||||
/**
|
||||
* Registers a listener for [ButtonMessage]s that occur on the given [button] id.
|
||||
@@ -20,21 +23,34 @@ fun KotlinPluginScript.on(
|
||||
button: Int,
|
||||
callback: ButtonClick.() -> Unit
|
||||
) {
|
||||
on(listenable) {
|
||||
if (this.button == button) {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
registerListener(listenable, ButtonPredicateContext(button), callback)
|
||||
}
|
||||
|
||||
class ButtonClick(override val player: Player, val button: Int) : PlayerContext {
|
||||
|
||||
companion object : MessageListenable<ButtonMessage, ButtonClick>() {
|
||||
override val type = ButtonMessage::class
|
||||
companion object : MessageListenable<ButtonMessage, ButtonClick, ButtonPredicateContext>() {
|
||||
|
||||
override fun createContext(player: Player, message: ButtonMessage): ButtonClick {
|
||||
return ButtonClick(player, message.widgetId)
|
||||
override val type = ButtonMessage::class
|
||||
|
||||
override fun createHandler(
|
||||
world: World,
|
||||
predicateContext: ButtonPredicateContext?,
|
||||
callback: ButtonClick.() -> Unit
|
||||
): MessageHandler<ButtonMessage> {
|
||||
return object : MessageHandler<ButtonMessage>(world) {
|
||||
|
||||
override fun handle(player: Player, message: ButtonMessage) {
|
||||
if (predicateContext == null || predicateContext.button == message.widgetId) {
|
||||
val context = ButtonClick(player, message.widgetId)
|
||||
context.callback()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ButtonPredicateContext(val button: Int) : PredicateContext
|
||||
@@ -3,6 +3,7 @@ package org.apollo.game.plugin.kotlin.message.action
|
||||
import org.apollo.game.plugin.kotlin.KotlinPluginScript
|
||||
import org.apollo.game.plugin.kotlin.MessageListenable
|
||||
import org.apollo.game.plugin.kotlin.PlayerContext
|
||||
import org.apollo.game.plugin.kotlin.PredicateContext
|
||||
import org.apollo.net.message.Message
|
||||
|
||||
/**
|
||||
@@ -14,18 +15,16 @@ import org.apollo.net.message.Message
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
inline fun <T : ActionContext, reified F : Message> KotlinPluginScript.on(
|
||||
listenable: MessageListenable<F, T>,
|
||||
fun <T : ActionContext, F : Message> KotlinPluginScript.on(
|
||||
listenable: MessageListenable<F, T, ActionPredicateContext>,
|
||||
option: String,
|
||||
crossinline callback: T.() -> Unit
|
||||
callback: T.() -> Unit
|
||||
) {
|
||||
on(listenable) {
|
||||
if (this.option.equals(option, ignoreCase = true)) {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
registerListener(listenable, ActionPredicateContext(option), callback)
|
||||
}
|
||||
|
||||
interface ActionContext : PlayerContext {
|
||||
val option: String
|
||||
}
|
||||
|
||||
open class ActionPredicateContext(open val option: String) : PredicateContext
|
||||
+77
-29
@@ -1,12 +1,60 @@
|
||||
package org.apollo.game.plugin.kotlin.message.action.obj
|
||||
|
||||
import org.apollo.cache.def.ObjectDefinition
|
||||
import org.apollo.game.message.handler.MessageHandler
|
||||
import org.apollo.game.message.impl.ObjectActionMessage
|
||||
import org.apollo.game.model.World
|
||||
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.MessageListenable
|
||||
import org.apollo.game.plugin.kotlin.message.action.ActionContext
|
||||
|
||||
/**
|
||||
* Registers a listener for [ObjectActionMessage]s that occur on any of the given [InteractiveObject]s using the
|
||||
* given [option] (case-insensitive).
|
||||
*
|
||||
* ```
|
||||
* on(ObjectAction, option = "Open", objects = DOORS.toList()) {
|
||||
* player.sendMessage("You open the door.")
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
fun <T : InteractiveObject> KotlinPluginScript.on(
|
||||
listenable: ObjectAction.Companion,
|
||||
option: String,
|
||||
objects: List<T>,
|
||||
callback: ObjectAction<T>.() -> Unit
|
||||
) {
|
||||
@Suppress("UNCHECKED_CAST") (callback as ObjectAction<*>.() -> Unit)
|
||||
registerListener(listenable, ObjectActionPredicateContext(option, objects), callback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener for [ObjectActionMessage]s that occur on any of the given [InteractiveObject]s using the
|
||||
* given [option] (case-insensitive).
|
||||
*
|
||||
* ```
|
||||
* on(ObjectAction, option = "Open", objects = DOORS.toList()) {
|
||||
* player.sendMessage("You open the door.")
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
fun KotlinPluginScript.on(
|
||||
listenable: ObjectAction.Companion,
|
||||
option: String,
|
||||
callback: ObjectAction<*>.() -> Unit
|
||||
) {
|
||||
registerListener(listenable, ObjectActionPredicateContext(option, emptyList()), callback)
|
||||
}
|
||||
|
||||
fun KotlinPluginScript.x() {
|
||||
on(ObjectAction, "walk") {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An interaction between a [Player] and an [interactive] [GameObject].
|
||||
*/
|
||||
@@ -17,44 +65,44 @@ class ObjectAction<T : InteractiveObject?>( // TODO split into two classes, one
|
||||
val interactive: T
|
||||
) : ActionContext {
|
||||
|
||||
companion object : ObjectActionListenable() {
|
||||
companion object : MessageListenable<ObjectActionMessage, ObjectAction<*>, ObjectActionPredicateContext<*>>() {
|
||||
|
||||
override val type = ObjectActionMessage::class
|
||||
|
||||
override fun createContext(player: Player, message: ObjectActionMessage): ObjectAction<*>? {
|
||||
return create<InteractiveObject>(player, message, objects = null)
|
||||
}
|
||||
override fun createHandler(
|
||||
world: World,
|
||||
predicateContext: ObjectActionPredicateContext<*>?,
|
||||
callback: ObjectAction<*>.() -> Unit
|
||||
): MessageHandler<ObjectActionMessage> {
|
||||
return object : MessageHandler<ObjectActionMessage>(world) {
|
||||
|
||||
override fun <T : InteractiveObject> createContext(
|
||||
player: Player,
|
||||
other: ObjectActionMessage,
|
||||
objects: List<T>
|
||||
): ObjectAction<T>? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return create(player, other, objects) as ObjectAction<T>
|
||||
}
|
||||
override fun handle(player: Player, message: ObjectActionMessage) {
|
||||
val def = ObjectDefinition.lookup(message.id)
|
||||
val option = def.menuActions[message.option]
|
||||
|
||||
private fun <T : InteractiveObject> create(
|
||||
player: Player,
|
||||
other: ObjectActionMessage,
|
||||
objects: List<T>?
|
||||
): ObjectAction<*>? {
|
||||
val def = ObjectDefinition.lookup(other.id)
|
||||
val selectedAction = def.menuActions[other.option]
|
||||
val target = world.regionRepository
|
||||
.fromPosition(message.position)
|
||||
.getEntities<GameObject>(message.position, EntityType.DYNAMIC_OBJECT, EntityType.STATIC_OBJECT)
|
||||
.find { it.definition == def }
|
||||
?: return // Could happen if object was despawned this tick, before calling this handle function
|
||||
|
||||
val obj = player.world.regionRepository
|
||||
.fromPosition(other.position)
|
||||
.getEntities<GameObject>(other.position, EntityType.DYNAMIC_OBJECT, EntityType.STATIC_OBJECT)
|
||||
.find { it.definition == def }
|
||||
?: return null
|
||||
val context = when { // Evaluation-order matters here.
|
||||
predicateContext == null -> ObjectAction<InteractiveObject?>(player, option, target, null)
|
||||
!predicateContext.option.equals(option, ignoreCase = true) -> return
|
||||
predicateContext.objects.isEmpty() -> ObjectAction(player, option, target, null)
|
||||
predicateContext.objects.any { it.instanceOf(target) } -> {
|
||||
val interactive = predicateContext.objects.find { it.instanceOf(target) } ?: return
|
||||
ObjectAction(player, option, target, interactive)
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
|
||||
context.callback()
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
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, ObjectAction<*>>() {
|
||||
|
||||
override val type = ObjectActionMessage::class
|
||||
|
||||
abstract fun <T : InteractiveObject> createContext(
|
||||
player: Player,
|
||||
other: ObjectActionMessage,
|
||||
objects: List<T>
|
||||
): ObjectAction<T>?
|
||||
|
||||
}
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
package org.apollo.game.plugin.kotlin.message.action.obj
|
||||
|
||||
import org.apollo.cache.def.ObjectDefinition
|
||||
import org.apollo.game.message.handler.MessageHandler
|
||||
import org.apollo.game.message.impl.ObjectActionMessage
|
||||
import org.apollo.game.model.World
|
||||
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
|
||||
|
||||
/**
|
||||
* Registers a listener for [ObjectActionMessage]s that occur on any of the given [InteractiveObject]s using the
|
||||
* given [option] (case-insensitive).
|
||||
*
|
||||
* ```
|
||||
* on(ObjectAction, option = "Open", objects = DOORS.toList()) {
|
||||
* player.sendMessage("You open the door.")
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
fun <T : InteractiveObject> KotlinPluginScript.on(
|
||||
listenable: ObjectActionListenable,
|
||||
option: String,
|
||||
objects: List<T>,
|
||||
callback: ObjectAction<T>.() -> Unit
|
||||
) {
|
||||
if (objects.isEmpty()) {
|
||||
on(listenable) {
|
||||
@Suppress("UNCHECKED_CAST") (callback as ObjectAction<*>.() -> Unit)
|
||||
callback(this)
|
||||
}
|
||||
} else {
|
||||
val handler = ObjectActionMessageHandler(world, listenable, objects, option, callback)
|
||||
context.addMessageHandler(listenable.type.java, handler)
|
||||
}
|
||||
}
|
||||
|
||||
class ObjectActionMessageHandler<T : InteractiveObject>(
|
||||
world: World,
|
||||
private val listenable: ObjectActionListenable,
|
||||
private val objects: List<T>,
|
||||
private val option: String,
|
||||
private val callback: ObjectAction<T>.() -> Unit
|
||||
) : MessageHandler<ObjectActionMessage>(world) {
|
||||
|
||||
override fun handle(player: Player, message: ObjectActionMessage) {
|
||||
val def = ObjectDefinition.lookup(message.id)
|
||||
val selectedAction = def.menuActions[message.option]
|
||||
|
||||
val obj = player.world.regionRepository
|
||||
.fromPosition(message.position)
|
||||
.getEntities<GameObject>(message.position, EntityType.DYNAMIC_OBJECT, EntityType.STATIC_OBJECT)
|
||||
.first { it.definition == def }
|
||||
|
||||
if (option.equals(selectedAction, ignoreCase = true) && objects.any { it.instanceOf(obj) }) {
|
||||
val context = listenable.createContext(player, message, objects)
|
||||
context?.callback()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package org.apollo.game.plugin.kotlin.message.action.obj
|
||||
|
||||
import org.apollo.game.plugin.kotlin.message.action.ActionPredicateContext
|
||||
|
||||
data class ObjectActionPredicateContext<T : InteractiveObject>(
|
||||
override val option: String,
|
||||
val objects: List<T>
|
||||
) : ActionPredicateContext(option)
|
||||
Reference in New Issue
Block a user