跳转至内容
  • 欢迎
  • 版块
  • 最新
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • 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 社区

administrators

私有

帖子


  • 深入浅出制作全自动Mud机器人-整体架构
    jarlyynJ jarlyyn

    以最靠近Mud服务器到最靠近用户排序

    适配器层

    做机器人的第一步就是在机器和MUD实际的交互中加一层适配器层,机器人只与适配器层交互,避免与客户端/Mud的过度耦合。适配器层包括两个组件

    • 事件系统。将所有的Mud的回显/断线连线封装成行事件。这样遇到需要修正Mud信息,应对Mud更新时只需要修正相应的事件就行,也提供在事件中加入额外处理的加入空间
    • 发送队列。绝大部分发送的内容压入队列,并在队列里进行解析/别名注册管理,使得机器不需要考虑发送的细节

    信息配置管理层

    配置使用基本统一的格式,由默认值/变量/数据文件一次覆盖获得最终结果,使得配置模块与业务逻辑独立,业务逻辑之需要注册新的参数,由具体的UI/变量负责加载和解析

    驱动模式层

    我整个机器是使用的 类似 Promise的Command队列进行管理,并提供必须的队列控制指令,比如Flush,Insert,Append,Snapshot,Rollback,提供统一的驱动引擎

    工作编排系统

    提供了#start+quest变量,以及#do的用户指令队列两种形式,使得用户能在不修改代码的情况下,尽可能的进行自定义流程管控。配合信息配置层的设置,尽量在变量和输入层面就能取代大部分代码工作

    用户交互

    通过助理按钮和别名系统,提供尽可能方便的设置功能,便于用户使用机器,以及在手机上进行操作。

    Script脚本

  • 深入浅出制作全自动Mud机器人-图形任务
    jarlyynJ jarlyyn

    有一小部分Mud会有试图用字符图形化传达信息的任务。

    这种任务,如果少量,算挺有情趣。如果出现大量,那就基本是一个纯机器向的MUD给机器制作者分级的机制了。

    图形任务,有各种各样的形式,难以做一个统一的介绍,但可以整理下思路。

    一般来说,图形任务的生成是走以下流程

    1. 生成随机任务信息
    2. 加入干扰元素
    3. 渲染

    所以,对于图形化任务的处理,基本上也是按这个顺序倒过来依次处理。

    1. 提取信息。利用问与答章节中的方法,提取到代表图形的多行文本,并从多行string转换为2维数组。
    2. 标准信息化,将渲染后的信息,替换和维护2维数组,有效信息用自己的个固定符号(token)替换
    3. 去干扰。根据不同的任务形式会有不同。可能是对比,可能是可行读判断等等。
    4. 解析出任务信息。开始任务。

    对于图形任务,已经脱离了对手动/体验型玩家的基本尊重了,很容易成为服务器LPC对抗VPS的脚本对拼,个人建议,不要投入太大精力。毕竟做机器只是为了游戏本身的乐趣或者体验变成的快乐,而不是对抗某个后者某群WIZ的自我满足感。所以,建议点到为止即可。

    Script脚本

  • HellMapManager 2026.05.11发布
    jarlyynJ jarlyyn

    升级Avalonia版本,提升界面性能

    下载地址

    HellMapManager地图编辑器

  • 深入浅出制作全自动Mud机器人-延时响应
    jarlyynJ jarlyyn

    延时响应是Mud解密中很常见的一个状态。

    指当你发出指令后,游戏中的NPC或者场景会在一定时间后,或者断断续续的做出响应。

    一般来说,延迟响应为了考虑到玩家的体验,服务器的响应需要进行特别复杂的处理,使用简单的匹配和Mode标记就可以处理。

    之所以单独作为一个课题讨论,是因为延时响应的核心处理点是 失效管理。

    普通解密,触发器一般是即用即关的,不需要考虑太多的意外状态,通过触发组就能很好的解决了。

    而延时解密,因为要考虑到可能会有终止/意外/并行的情况,需要手动的对出发考虑失效和重复生效、计时器延时等状况,触发器组就很捉襟见肘了,一般需要更多的代码工具去进行管理。

    我这里是通过自己的Task/Plan模块,将所有的触发/计时器/事件处理封装在一个Task对象内,并强制使用一个作用范围强制失效来解决这个问题的。

    参考代码:

        let baohuwait = 28 * 1000
        let matcherKill = /^你对(.+)的(黑衣人|邪派高手|绝世高手)喝道:大胆狂徒,竟敢在这撒野!!/
        //等待NPC出现的计划
        let PlanProtect = new App.Plan(
            App.Positions["Quest"],
            (task) => {
                task.AddTrigger(matcherKill, (tri, result) => {
                    if (result[1] != App.Data.Player.Score.名字) {
                        return true;
                    }
                    App.Send("halt")
                    let id
                    switch (result[2]) {
                        case "黑衣人":
                            id = "heiyi ren"
                            break
                        case "邪派高手":
                            id = "xiepai gaoshou"
                            break
                        case "绝世高手":
                            id = "jueshi gaoshou"
                            break
                    }
                    Baohu.Data.ID = id
                    Baohu.Data.Type = result[2]
                }).WithName("ok")
                let wait = Baohu.Data.Start + baohuwait - $.Now()
                if (wait > 0) {
                    task.AddTimer(wait, (timer) => {
                        Note("准备迎敌")
                        App.Send("halt")
                        App.Core.Heal.TryTouch()
                        $.RaiseStage("prepare")
                        $.RaiseStage("baohu-ready")
                        return true
                    }).WithNoRepeat(true)
                }
                task.AddTimer(1100, () => {
                    if (App.Core.Weapon.Touch) {
                        if (($.Now() - Baohu.Data.Start) < baohuwait) {
                            App.Send("halt")
                            App.Core.Heal.TryTouch()
                            $.RaiseStage("pause")
                            $.RaiseStage("wait")
                        }
                    }
                    return true
                })
                task.AddTimer(3000, () => {
                    let d = (($.Now() - Baohu.Data.Start) / 1000).toFixed(0)
                    Note(`保护开始${d}秒`)
                    return true
                })
                task.AddTimer(60000, () => {
                    App.Log("保护等待超时")
                    return false
                }).WithName("timeout")
                $.RaiseStage("wait")
            },
            (result) => {
                if (result.Name == "ok") {
                    $.PushCommands(
                        $.CounterAttack(`${GetVariable("id")}'s ${Baohu.Data.ID}`, App.NewCombat("baohu").WithTags(`baohu-${Baohu.Data.Type}`).WithPlan(PlanCombat)),
                        $.Function(Baohu.Finish),
                    )
                    $.Next()
                    return
                }
                App.Send("halt")
                App.Log(`保护NPC${Baohu.Data.NPC.ID}失败`)
                Baohu.Fail()
            }
        )
    
    

    代码地址

    可以看到,我使用了一个叫做PlanProtect的计划(task工厂),创建了一个基于Quest的封装,所有的触发和计时器都绑定在这个Task封装上,并在Quest发生变化时强制失效。

    预期管理工具Plan/Task的详细介绍

    由于我一直认为Mud机器人是一个工程问题,难点在于可维护性和代码失控。所以,我认为,选用或者开发一个触发失效工具,是十分重要的,也应该是整个机器人的核心驱动逻辑之一。

    Script脚本 全自动

  • 深入浅出制作全自动Mud机器人-随机迷宫地图
    jarlyynJ jarlyyn

    随机迷宫以及地图是很多Mud引入的新任务类型。

    比如下面就是一个典型的迷宫地图

    ┌─┬─┬─┬─┬─┬─┬─┬─┐
    │★│     │       │
    ├ ┼─┼ ┼─┼ ┼─┼─┼ ┤
    │ │ │   │     │ │
    ├ ┼ ┼─┼ ┼ ┼─┼─┼ ┤
    │ │         │ │ │
    ├ ┼─┼ ┼─┼ ┼─┼ ┼ ┤
    │   │ │     │   │
    ├─┼ ┼ ┼─┼─┼─┼ ┼ ┤
    │ │   │ │ │ │ │ │
    ├ ┼ ┼ ┼ ┼ ┼ ┼ ┼─┤
    │ │ │     │ │ │ │
    ├ ┼ ┼─┼─┼─┼ ┼ ┼ ┤
    │   │         │ │
    ├─┼─┼ ┼─┼ ┼─┼ ┼ ┤
    │     │     │   │
    └─┴─┴─┴─┴─┴─┴─┴─┘
    

    这种地图本质就是在服务器创建了一系列的虚拟房间,并建立了房间中之间的联系,最后将这些方向和关系再打印成文字图案。

    那么,处理方式也比较直接。

    先将文字图标准化,化成比较简单的单字节图,然后再遍历建立临时房间和出口信息就可以。

    参考HellMapManager.Dll的范例代码

    local hmmlib=require('hmm')
    local hmm=hmmlib.new()
    hmm.DllEncoding=0 --0 for utf-8, 1 for gbk
    local json=require('json')
    local file=assert(io.open("hongchen.hmm","r"))
    local data=file:read("*a")
    file:close();
    hmm:call("import",data)
    local extrooms={}
    local extpaths={}
    local function buildMyRoom(entry,roomid,roomname)
        local myroom1=hmmlib.Room.new()
        myroom1.Key="myroom-entry"
        myroom1.Name=roomname.."大厅"
        local myroomexit1=hmmlib.Exit.new()
        myroomexit1.Command="open gate;n"
        myroomexit1.To="myroom-home"
        local myroomexit2=hmmlib.Exit.new()
        myroomexit2.Command="out"
        myroomexit2.To=entry
        myroom1.Exits={myroomexit1,myroomexit2}
        local myroom2=hmmlib.Room.new()
        myroom2.Key="myroom-home"
        myroom2.Name=roomname.."卧室"
        local myroomexit3=hmmlib.Exit.new()
        myroomexit3.Command="open gate;s"
        myroomexit3.To="myroom-entry"
        myroom2.Exits={myroomexit3}
        table.insert(extrooms, myroom1)
        table.insert(extrooms, myroom2)
        local entrypath=hmmlib.Path.new()
        entrypath.From=entry
        entrypath.Command="go "..roomid
        entrypath.To="myroom-entry"
        table.insert(extpaths, entrypath)
    end
    
    buildMyRoom("2440","myhouse","大别野")
    
    local mazemaptxt=[[
    ┌─┬─┬─┬─┬─┬─┬─┬─┐
    │             │ │
    ├─┼ ┼─┼─┼─┼─┼ ┼ ┤
    │ │   │     │ │ │
    ├ ┼ ┼─┼ ┼ ┼─┼ ┼ ┤
    │  ♚  │ │ │   │ │
    ├─┼ ┼ ┼ ┼ ┼─┼ ┼ ┤
    │   │   │ │     │
    ├─┼ ┼─┼ ┼─┼─┼ ┼─┤
    │ │ │   │     │ │
    ├ ┼ ┼─┼─┼ ┼ ┼─┼ ┤
    │ │   │   │   │ │
    ├ ┼ ┼─┼─┼ ┼ ┼ ┼ ┤
    │ │ │     │ │   │
    ├ ┼ ┼─┼ ┼ ┼ ┼ ┼─┤
    │   │   │ │ │  ★│
    └─┴─┴─┴─┴─┴─┴─┴─┘
    ]]
    --♚为当前位置,★为出口
    
    local Maze={}
    Maze.__index=Maze
    Maze.new=function()
        local self=setmetatable({},Maze)
            self.RoomPrefix="maze-"
            self.RoomKeys={}
            self.Rooms={}
            self.Paths={}
            self.EntryRoom=""
            self.ExitRooms={}
        return self
    end
    function Maze:buildRoomKey(x,y)
        return self.RoomPrefix..tostring(x).."-"..tostring(y)
    end
    function Maze:buildExit(room,tokey,command)
        local exit1=hmmlib.Exit.new()
        exit1.Command=command
        exit1.To=tokey
        table.insert(room.Exits, exit1)
    end
    function Maze:readmap(maptxt)
        local maplines={}
        for line in string.gmatch(maptxt, "[^\r\n]+") do
            if #line>0 then
            --因为utf8不定长,进行处理
            line = string.gsub(line," "," ")
            line = string.gsub(line,"│","+")
            line = string.gsub(line,"─","+")
            line = string.gsub(line,"├","+")
            line = string.gsub(line,"┤","+")
            line = string.gsub(line,"┴","+")
            line = string.gsub(line,"┬","+")
            line = string.gsub(line,"└","+")
            line = string.gsub(line,"┘","+")
            line = string.gsub(line,"┌","+")
            line = string.gsub(line,"┐","+")
            line = string.gsub(line,"┼","+")
            line = string.gsub(line,"♚","I")
            line = string.gsub(line,"★","O")
            table.insert(maplines, line)
            end
        end
        local roomwidth=(#maplines[1]-1)/2
        local roomheight=(#maplines-1)/2
        local currentY=1
        --按行处理
        while currentY<=roomheight do
            local currentX=1
            --处理每个房间
                while currentX<=roomwidth do
                    local roomkey=self:buildRoomKey(currentX-1, currentY-1)
                    table.insert(self.RoomKeys, roomkey)
                    local room=hmmlib.Room.new()
                    room.Key=roomkey
                    if maplines[currentY*2]:sub(currentX*2, currentX*2)=="I" then
                        self.EntryRoom=roomkey
                    end
                    if maplines[currentY*2]:sub(currentX*2, currentX*2)=="O" then
                        table.insert(self.ExitRooms, roomkey)
                    end
                    if maplines[currentY*2]:sub(currentX*2+1, currentX*2+1)==" " then
                        self:buildExit(room,self:buildRoomKey(currentX,currentY-1),"e")
                    end
                    if maplines[currentY*2]:sub(currentX*2-1, currentX*2-1)==" " then
                        self:buildExit(room,self:buildRoomKey(currentX-2,currentY-1),"w")                    
                    end
                    if maplines[currentY*2+1]:sub(currentX*2, currentX*2)==" " then
                        self:buildExit(room,self:buildRoomKey(currentX-1,currentY),"s")
                    end
                    if maplines[currentY*2-1]:sub(currentX*2, currentX*2)==" " then
                        self:buildExit(room,self:buildRoomKey(currentX-1,currentY-2),"n")                    
                    end
                    table.insert(self.Rooms, room)
                    currentX=currentX+1
                end
            currentY=currentY+1
        end
    end
    function Maze:applyTo(environment)
        for _, room in ipairs(self.Rooms) do
            table.insert(environment.Rooms, room)
        end
        for _, path in ipairs(self.Paths) do
            table.insert(environment.Paths, path)
        end
    end
    
    local mymaze=Maze.new()
    mymaze:readmap(mazemaptxt)
    local query=hmmlib.QueryPathAny.new()
    query.From={"2522"}
    query.Target={"myroom-home"}
    query.Environment=hmmlib.Environment.new()
    query.Environment.Rooms=extrooms
    query.Environment.Paths=extpaths
    local result=json.decode(hmm:call("querypathany", json.encode(query)))
    if (result==nil) then
        print("No home path found")
    else
        print("Home path found:")
        print(json.encode(result))
    end
    
    -- 遍历迷宫后离开
    local queryall=hmmlib.QueryPath.new()
    queryall.Start=mymaze.EntryRoom
    queryall.Target=mymaze.RoomKeys
    queryall.Environment=hmmlib.Environment.new()
    
    mymaze:applyTo(queryall.Environment)
    result=json.decode(hmm:call("querypathall", json.encode(queryall)))
    if (result==nil) then
        print("No full maze path found")
    else
        print("Full maze path found:")
        print(json.encode(result))
    end
    --遍历完成,离开路径
    query=hmmlib.QueryPathAny.new()
    query.From={result["To"]}
    query.Target=mymaze.ExitRooms
    query.Environment=hmmlib.Environment.new()
    mymaze:applyTo(query.Environment)
    result=json.decode(hmm:call("querypathany", json.encode(query)))
    if (result==nil) then
        print("No maze path found")
    else
        print("Maze path found:")
        print(json.encode(result))
    end
    

    在处理动态地图时,核心还是不要想的太复杂,直接找出Room的对应元素,以及相应的Exit,然后根据需要遍历或者导航即可。

    Script脚本 全自动

  • 深入浅出制作全自动Mud机器人-问与答
    jarlyynJ jarlyyn

    问与答是一个最为典型简单的Mud解密,是大部分Mud任务的基础与核心,可以作为我们研究Mud解密的入口。

    对于一个标准的问答对话来说,一般是

    • 主动发起ask
    • 游戏提示 你向XXXX打听关于XXXX的事情
    • 可能有部分干扰,没听清之类
    • 紧跟着你打听的内容,NPC会进行回复。同时NPC也会恢复其他玩家的问题,这时可能对你有所干扰。

    这时,很多老玩家可能会向你介绍多行匹配这一神器。

    但很可惜,这只是试图逃避正确解决问答问题的逃课行为。

    多行匹配完全不适合问答解密上。因为多行匹配无法进行逻辑处理,无法引入状态。也无法标准化处理。

    因此,多行匹配在问答问题上,只能算是一个补丁。如果你的机器建立在大量补丁上,很快就会带来难以解决的架构问题。

    那么,怎么来进行一个标准化的问答呢?

    很简单,对NPC的回答进行录制。

    在ask npc时,同时发送你的ask指令和同步指令。对应的,你会预期两个服务器的回复

    • 你想XXX大厅关于XXX的事情:开始录制,把这行之后的每一行都追加到一个数组里
    • 你的同步响应:结束录制,ask结束,进行下一步处理。

    这样,就把问答问题,转换为对一个字符串数组的按行分析。

    再配合简单的状态机形式,一般就是一个局部的Mode变量,就行解决大部分的问题了。

    以hongchenjs的长安任务为例,需要向梁兴禄发起ask 任务,处理的代码如下

        Changan.Check = function () {
            if (App.Data.Ask.Answers.length) {
                if (App.Data.Ask.Answers[0].Line == "梁兴禄对你说道:本府不是已经给你派发了差事,完不成的话就先跟我取消。") {
                    Changan.Fail();
                    return;
                }
                if (App.Data.Ask.Answers[0].Line == "梁兴禄对你说道:你的江湖经验已经很高了,再在衙门里也混不出个名堂了。") {
                    Quest.Cooldown(10 * 60 * 60 * 1000)
                    App.Next();
                    return
    
                }
                if (App.Data.Ask.Answers[0].Line == "梁兴禄盯着你看了看,说道:“你刚取消过一次任务,过一分钟再来吧。”") {
                    Quest.Cooldown(60 * 1000)
                    // App.Core.Timeslice.Change("")
                    App.Next();
                    return
                }
                if (App.Data.Ask.Answers[0].Line.match(matcherTooMany)) {
                    Quest.Cooldown(4 * 3600 * 1000)
                    // App.Core.Timeslice.Change("")
                    App.Next();
                    return
                }
                if (App.Data.Ask.Answers[0].Line == "梁兴禄对你说道:嗯,既然你有心为衙门出力,我便给你个差事。") {
                    Changan.All++;
                    App.Send("changanjob")
                    if (App.Data.Ask.Answers[1].Line == "梁兴禄说着便拿出一份公函交给你。") {
                        Changan.Gonghan()
                        return
                    }
                    Changan.Check2()
                    return
                }
            }
            App.Fail()
        }
        Changan.Check2 = function () {
            let result = App.Data.Ask.Answers[1].Line.match(matcherCode)
            if (result) {
                Changan.Data.Name = result[2];
                for (var i = 3; i < App.Data.Ask.Answers.length; i++) {
                    let token = App.Data.Ask.Answers[i].Line.match(matcherCodeToken)
                    if (token) {
                        Changan.Data.Code += token[1].trim()
                    } else {
                        break
                    }
                }
                Changan.Data.Type = "code"
                Changan.DoCode()
                return
            } else {
                App.Log("未知的长安任务对话")
                Changan.Fail()
                return
            }
        }
    
    

    代码地址

    能很好的看出怎么用标准录制的问答信息,来解决复杂谜题。

    Script脚本 全自动

  • 深入浅出制作全自动Mud机器人-解密系统
    jarlyynJ jarlyyn

    解密系统在mud机器人中,属于比较高层的应用层。

    整个解密系统的本质就是:发出指令,期待响应,从响应中解析出系统状态,进入合适的模块。

    一般而言,mud的解析会分为以下几种:

    1. 单行格式化信息
    2. 多行复杂信息
    3. 延迟信息
    4. 图形化信息
    5. 多重交互流

    其中单行格式化信息和多行复杂信息,是比较正常的信息交互模式。

    而延迟信息,图形化信息,多重交互信息,就大概率是巫师为机器人设置的障碍了。

    在开始深入解析解密系统之前,我们先要确认一点,解密系统的基础。

    所有的解密,本质来说都是从两步开始的。

    1. 确认信息同步
    2. 记录调阅多行信息

    确认信息同步,是为了跟信息一个明确的结束状态。一般会准备一个平时不怎么使用的指令,用来做信息结束的确认。只有看到这个指令回复出现,才进入下一步的动作。之前的所有的出发,不直接执行指令,只改变状态/属性/变量,最后才进行决策。同时,这也与mud机器的同步问题有关。

    同步参考

    而记录和调阅多行信息,是模拟人对mud信息的处理。机器对mud是按行进行匹配的,但人对mud是根据历史多行进行阅读的。所以,在准备解密时,必须把所有可能有用的信息记录在行数组里。再根据确定的触发,匹配合适的上下文,分析数据。

    对于机器人,我的观点是

    Mud应该是为人设计的。如果完全不适合人玩,那这机器也没有做的意义。

    这也是我的解密模块的理论基础。

    Script脚本 全自动 架构

  • HellMapManager嵌入脚本Dll发布
    jarlyynJ jarlyyn

    HMM嵌入脚本Dll是将HMM程序本地编译为AOT版本,在dll里引用。

    本质是将http api接口替换为c api,通过文本进行调用的接口。

    优点:

    • 跨客户端,跨语言。可以在mush/mudlet/ls等客户端,通过lua/python的方式使用,也可以独立的使用nodejs/lua/python进行调用
    • 毫秒级别的路径查询(取决于地图大小/路径长度/CPU性能)
    • 完全开源。基于Mit协议的宽松开源协议,你可以自由的扩展/改写/利用代码。
    • 有Hell和红尘两款Mud的机器深度使用本库的算法
    • 地图文件也可以通过 hmm.ts项目,在原生的javascript/lua中使用
    • 有跨平台(windows/macos/linux)的编辑软件支持,编辑软件支持版本分差对比。
    • 完善的文档/单元测试
    • 支持多点对多点寻路(querypathany)规划路线
    • 支持模拟移动逼近的方式动态生成便利路径(quarypathall)规划路线
    • 支持按顺序进入房间的形式(querypathordered)规划路线
    • 支持标签,支持带值的标签,以动态的决定某个出口只能被符合某个条件,或技能不低于某个值的情况下才启用/禁用。
    • 支持房间黑/白名单,移动指令的黑/白名单来的形式动态规划路线
    • 支持地图膨胀,一般配合模拟逼近的形式,遍历出生于目标区域会随机移动的NPC可以到达的房间
    • 支持临时禁用出口,应对npc拦路/技能不符无法通行的情况
    • 支持临时房间和路径,用以解决随机迷宫,自建房屋等问题
    • 支持 直达捷径,用于实现flyto/rideto/miss等功能
    • 支持对房间的可变信息保留多个版本的快照,并在快照内进行搜索
    • 支持转码,可以支持utf-8以及gbk编码

    限制:

    作为作者,个人对用用只有以下三个希望

    • 希望不要以Mud owner禁止的方式使用本库
    • 希望不要在不欢迎本库的Mud宣传本库
    • 希望不要在禁止或者不欢迎公开传播地图文件的mud 传播本库生成的地图文件

    API:
    API文档

    代码范例

    预览版本下载链接:

    https://github.com/hellclient-scripts/hellmapmanager/releases/tag/embedding.2026.04.22

    HellMapManager地图编辑器

  • [开发]hellmanager.ts lua版本放弃性能优化声明
    jarlyynJ jarlyyn

    简单的benchmark:
    gowrk+httpapi: 0.5ms/req
    nodejs:1ms/req
    dll+lua:3ms/req
    lua5.1/luajit:10ms/req

    HellMapManager地图编辑器

  • [开发]hellmanager.ts lua版本放弃性能优化声明
    jarlyynJ jarlyyn

    这次优化了下寻路算法,就正常寻路优化到了10ms左右

    但是由于这是同一优化,api/node/dll模式也得到了极大的提升,所以差距还是等比例的。

    因为,虽然寻路优化到了可用的范围(10ms)

    但在追求性能的场合,依然无法提供性能保证。

    HellMapManager地图编辑器

成员列表

jarlyynJ jarlyyn
  • 登录

  • 没有帐号? 注册

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