深入浅出制作全自动Mud机器人-预期管理
Script脚本
1
帖子
1
发布者
7
浏览
-
Mud机器人有一种很常见的开发方式,就是 我预期 未来服务器可能会返回N种回复,根据不同的回复执行不同的代码。
以mush为例,最基本的就是设置一组触发器,预期进行时,开启触发组,有任何一个触发命中时,关闭本组,继续执行。
这种模式下主要的课题是失效管理,也就是什么场景下,会结束预期。
我在newhelljs中引入了 一个叫做Task/Plan的概念,对这种操作进行优化
具体来说,我定义的预期是这样的。
在某种状态下,一定时间内,预期有N种触发或者事件可能会发生。
触发后默认预期会结束,除非显示的保活。
首先,我定义了一个预期的有效范围。
根据我的恶趣味,我起了个很蛋疼的名字叫Committee(委员会)
委员会里有很多个职位(Position)
每个职位会有Term任期。
所有的预期(task/plan)是挂在任期Term上的。
任期是一个抽象概念,比如连接,房间,任务,战斗。
当有新的连接/进入新房间/开始新人物/进入或离开战斗后,任期就会自动结束。
这样保证了预期不会泄漏长期存在。
比如我在我战斗模块的开始和结束战斗的代码
Start(id, data) { this.Position.StartNewTerm() this.Data = data this.Target = id ? id : "" this.StartAt = (new Date()).getTime() this.Position.AddTimer(this.Interval, () => { this.Ticker(this) }) this.Ticker(this) this.Plan.Execute() this.Combating = true return this } Stop(reason) { if (!this.Combating) { return } let onstop = this.OnStop this.Position.StartNewTerm() onstop(this, reason) this.Target = "" this.Combating = false this.Data = null }会使用this.Position.StartNewTerm()来更新任期(所有相关的触发/计时器失效)
当计时器失效时,会Task的结算函数,把Task结束的原因TaskResult传入,这样就能根据不同的结果进行判断了。
至于Plan,其实就是一个Task的工厂函数,调用Plan就能常见一个新的Task。
以代码为例
let matcherEnter = /^你连线进入.+。$/ let matcherReenter = /重新连线完毕。$/ let matcherTooFast = /你距上一次退出时间只有.+秒钟,请稍候再登录。$/ let matcherTooFast2 = /你不能在.+秒钟之内连续重新连线。$/ //登录的计划 var PlanOnConnected = new App.Plan(App.Positions.Connect, function (task) { task.AddTrigger(matcherEnter).WithName("enter") task.AddTrigger(matcherReenter).WithName("reenter") task.AddTrigger(matcherTooFast).WithName("toofast") task.AddTrigger(matcherTooFast2).WithName("toofast2") task.AddTimer(5000).WithName("timeout") }, function (result) { switch (result.Type) { case "trigger": switch (result.Name) { case "enter": App.RaiseEvent(new App.Event("core.entermud", false).WithType("system")) App.RaiseEvent(new App.Event("core.relogin", false).WithType("system")) break case "reenter": App.RaiseEvent(new App.Event("core.entermud", true).WithType("system")) App.RaiseEvent(new App.Event("core.reconnect", false).WithType("system")) break case "toofast": case "toofast2": if (App.Core.Connect.Callback) { App.Core.Connect.Next = (new Date()).getTime() + 10000 Note("10秒后重试") } break } break case "timer": if (App.Core.Connect.Callback) { App.Core.Connect.Next = (new Date()).getTime() + 10000 Note("10秒后重试") } break } })就是一个很明显的,高内聚的,预期的组合
- 当前连接有效
- 有个不同Name的文字出发
- 有5秒的timeout
结束函数里通过switch语句,对不同类型的结果进行处理,抛出时间或者进行重连。
如果在这当中意外断线,由于有Connect的Position,会直接失效,不会在下次连接时继续触发。
-
J jarlyyn 在 引用了 此主题