跳到主要内容

控制器

本文只介绍控制器 API 的使用方式,对于控制器的详细说明,请参考 技术文档 中的控制器部分。

实现

随便走走 为例,下文将演示如何实现一个简单的控制器:

import ink.ptms.adyeshach.core.entity.EntityInstance
import ink.ptms.adyeshach.core.entity.controller.Controller
import ink.ptms.adyeshach.core.entity.path.PathFinderHandler
import ink.ptms.adyeshach.core.entity.path.Request
import ink.ptms.adyeshach.core.entity.path.ResultRandomPosition

class ControllerRandomStrollLand(entity: EntityInstance) : Controller(entity) {

override fun id(): String {
return "RANDOM_STROLL_LAND"
}

override fun group(): String {
return "WALK"
}

override fun shouldExecute(): Boolean {
// 当满足概率时触发控制器
return entity != null && entity!!.random().nextDouble() < 0.001;
}

override fun continueExecute(): Boolean {
// 不会继续执行
return false
}

override fun start() {
if (entity != null) {
// 请求一个随机位置
PathFinderHandler.request(entity!!.getLocation(), request = Request.RANDOM_POSITION) {
// 移动到随机位置
entity!!.controllerMoveTo((it as ResultRandomPosition).random.toLocation(entity!!.world))
}
}
}
}

在这之后,我们便可以直接将该控制器添加到单位身上:

entity.registerController(ControllerRandomStrollLand(entity))

或是移除:

// 使用序号移除
entity.unregisterController("RANDOM_STROLL_LAND")
// 使用类移除
entity.unregisterController(ControllerRandomStrollLand::class.java)

尽管此时这个控制器已经可以使用,但是它还不能借助 脚本 或是 编辑页面 来添加到单位身上。

注册

想要使控制器可以被 脚本编辑页面 访问,还需要借助控制器注册接口。

// 获取控制器注册接口
val registry = Adyeshach.api().getEntityControllerRegistry()
// 创建控制器生成器
val generator = ControllerGenerator(ControllerRandomStrollLand::class.java) { ControllerRandomStrollLand(it) }
// 注册控制器
registry.registerControllerGenerator("RANDOM_STROLL_LAND", generator)

此时这个控制器就可以被 脚本编辑页面 访问了,但它还不够完善。

参数 & 持久化

对于需要使用额外参数的控制器,就没有那么简单了。现在,我们要为上面的演示控制器添加一个参数:probability,表示执行概率。

...
import com.google.gson.annotations.Expose

class ControllerRandomStrollLand(entity: EntityInstance, @Expose val probability: Double) : Controller(entity) {

constructor(entity: EntityInstance) : this(entity, 0.01)

...

override fun shouldExecute(): Boolean {
// 当满足概率时触发控制器
return entity != null && entity!!.random().nextDouble() < probability;
}

...

override fun toString(): String {
return "${id()}:${"%.2f".format(probability)}"
}
}

同时,这个参数需要被持久化,否则会在重载时丢失。我们需要为其添加一个 @Expose 注解。并且,我们还要修改它的 toString 方法,使其能够被 编辑页面 在相同控制器的不同参数中鉴别。

两个及以上的参数之间使用 , 进行分割,例如:RANDOM_STROLL_LAND:0.01,0.5

警告

对于浮点数必须保留两位小数,否则会因精度丢失导致 编辑页面 无法正常识别。

自定义序列化

对于特殊的需求,Adyeshach 支持控制器的自定义序列化方式。

...

class ControllerRandomStrollLand(entity: EntityInstance, val probability: Double) : Controller(entity), CustomSerializable {

...

override fun serialize(): JsonObject {
return JsonObject().also { it.addProperty("probability", probability) }
}

companion object {

@JvmStatic
fun deserialize(data: JsonObject): ControllerGenerator {
val probability = data["probability"].asDouble
return ControllerGenerator(ControllerRandomStrollLand::class.java) { ControllerRandomStrollLand(it, probability) }
}
}
}

使用自定义序列化的控制器,必须在类中声明一个静态方法 deserialize