跳转至内容
  • 欢迎
  • 版块
  • 最新
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(不使用皮肤)
  • 不使用皮肤
折叠
品牌标识

Hellclient 社区

  1. 主页
  2. Script脚本
  3. 深入浅出制作全自动Mud机器人-预期管理

深入浅出制作全自动Mud机器人-预期管理

已定时 已固定 已锁定 已移动 Script脚本
机器人全自动代码范例
1 帖子 1 发布者 7 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • jarlyynJ 离线
    jarlyynJ 离线
    jarlyyn
    写于 最后由 jarlyyn 编辑
    #1

    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,会直接失效,不会在下次连接时继续触发。

    1 条回复 最后回复
    • jarlyynJ jarlyyn 在 引用了 此主题
    回复
    • 在新帖中回复
    登录后回复
    • 从旧到新
    • 从新到旧
    • 最多赞同


    • 登录

    • 没有帐号? 注册

    • 登录或注册以进行搜索。
    Powered by Herbrhythm.
    • 第一个帖子
      最后一个帖子
    0
    • 欢迎
    • 版块
    • 最新
    • 标签
    • 热门
    • 用户
    • 群组