跳转至内容
  • 0 赞同
    1 帖子
    8 浏览
    jarlyynJ
    虽然很多客户端和教程介绍机器时,都是用触发来驱动机器。 但是,要做一个稳定,功能强大的机器,被动的靠出发来驱动明显不可行,必须要依靠全面详尽的数据来运行。 在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() } 这样就能确保每次在需要数据进行决策(准备)时,使用的是最新的有效的数据。