跳转至内容
  • 欢迎
  • 版块
  • 最新
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • 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 发布者 8 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • jarlyynJ 离线
    jarlyynJ 离线
    jarlyyn
    编写于 最后由 编辑
    #1

    虽然很多客户端和教程介绍机器时,都是用触发来驱动机器。

    但是,要做一个稳定,功能强大的机器,被动的靠出发来驱动明显不可行,必须要依靠全面详尽的数据来运行。

    在Mud中,有很多指令会对应获取更新数据。常见比如"hp","score","i","skills"等。

    我们一般都会根据这些指令的结果来更新数据。

    但是,Mud又是动态的,这些数据往往又容易失效。

    做任何动作之前猛刷一通指令明显不科学,浪费服务器资源,还干扰用户使用。在这个情况下,我们肯定是要面对有时效性的数据来进行编码。

    也就是说,我们在收集数据时,不光光面对是一个采集的问题。还要把数据是做缓存,处理一个缓存失效的问题。

    那以缓存的角度来看看到数据的话,实际是要实现以下几个地方

    • 数据的有效期(ttl)
    • 数据回源(发现过期后主动更新数据)
    • 数据的强制更新(更新数据后更新数据和有效期)
    • 数据强制失效

    实现的方法其实有很多,我这里说说我的实现方法。

    以我的代码为例

    在处理数据时,我使用了这么一个结构

        let DefaultExecute = function (check) {
            return check.Command
        }
        class Check {
            constructor(id) {
                this.#id = id
            }
            #id = ""
            Interval = 0
            #last = 0
            Execute = DefaultExecute
            Command = null
            WithExecute(fn) {
                this.Execute = fn ? fn : DefaultExecute
            }
            ID() {
                return this.#id
            }
            WithCommand(cmd) {
                if (typeof (cmd) != "function") {
                    this.Command = function () { App.Send(cmd) }
                } else {
                    this.Command = cmd
                }
                return this
            }
            WithInterval(interval) {
                interval = interval - 0
                if (isNaN(interval)) {
                    interval = 0
                }
                this.Interval = interval
                return this
            }
            InCooldown() {
                return (new Date()).getTime() - this.Interval < this.#last
            }
            Reset() {
                this.#last = (new Date()).getTime()
            }
            Force() {
                this.#last = 0
            }
        }
    

    这个机构很明显。

    • #last 最后一次更新时间
    • Interval 重新获取数据的间隔(ttl)
    • Execute,Command 更新数据的函数和指令
    • #id 缓存的 id,可以制定id进行更新

    在使用时,我会以这样的形式来注册一个数据检查(更新)器

        let checkerSkills = App.Checker.Register("skills", "skills", 300000)
    

    这是注册一个 id为skills,指令为skills,数据有效期为300秒的检查器。

    在匹配skill最后的代码最后调用一下Reset

            function (result) {
                            checkerSkills.Reset()
                        })
    

    就能按一定的有效期来保存数据了。

    然后由于这个是获取技能数据的,所以我绑定了技能提升的触发事件,在技能重置时强制这个缓存数据失效

        //技能升级时重置相关的checker
        App.BindEvent("core.skillimproved", function () {
            checkerHPM.Force()
            checkerSkills.Force()
            checkerJifa.Force()
        })
    

    就能比较有效的处理缓存数据了。

    在可能需要处理状态的地方,我加入了检查所有预设检查器的代码

        //检查的函数
        App.Check = () => {
            App.RaiseEvent(eventBeforeCheck)//触发检查发送指令
            let checks = App.Checker.Check()//获取需要执行的检查
            if (checks.length == 0) {//无需检查
                App.Next()
                return
            }
            App.PushCommands(//一次性执行所有检查
                App.Commands.NewFunctionCommand(function () {
                    checks.forEach(check => {
                        check()
                    });
                    App.Next()
                }),
                App.NewSyncCommand(),
            )
            App.Next()
        }
        //准备函数,第一个函数时准备id,第二个时准备的上下文(环境变量)
        App.Prepare = function (id, context) {
            App.RaiseEvent(eventBeforeCheck)
            let checks = App.Checker.Check()
            if (checks.length == 0) {
                AfterCheck(id, context)
                return
            }
            App.PushCommands(
                App.Commands.NewFunctionCommand(function () {
                    checks.forEach(check => {
                        check()
                    });
                    App.Next()
                }),
                App.NewSyncCommand(),
                App.Commands.NewFunctionCommand(function () {
                    AfterCheck(id, context)
                }),
            )
            App.Next()
        }
    

    这样就能确保每次在需要数据进行决策(准备)时,使用的是最新的有效的数据。

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


    • 登录

    • 没有帐号? 注册

    • 登录或注册以进行搜索。
    由Herbrhythm提供技术支持
    • 第一个帖子
      最后一个帖子
    0
    • 欢迎
    • 版块
    • 最新
    • 标签
    • 热门
    • 用户
    • 群组