jarlyyn
发表于 2021-9-6 10:19:49
在完善了基本信息的收集后,我们的接下去要做什么功能呢?
[*]数据发送
[*]当前位置判断
[*]忙判断
[*]路径行走
在这些问题都接完之后,才能让我那饿了几个月的id吃上热乎的饭菜。
jarlyyn
发表于 2021-9-6 10:45:13
先让我们解决发送的问题。
mush里最简单的发送自然是world.Send里,填什么发什么,这不是很简单么?
当然没那么简单,发送要解决4个问题
[*]速率控制
[*]全局控制(如回显)
[*]命令标准化
[*]自定义功能
速率控制比较重要,单独开一个回复
全局控制很容易理解,是为了能同意的管理发送的表现。如果你要给所有的发送命令的地方价格命令统计,不全局控制是要改死人的。这是一个工程化的问题
命令标准化呢,略微复杂点
比如一个e,我可以直接发送e,也可以发送>e,也可以发送?e,最后实际发送到mud的可能都是e。
这个主要是用在路径里的。直接向东走可以直接发e,走过去有busy的可能发个e然后等busy结束,等等。
最后一个自定义功能么,很简单,有些控制性的变量可能不直接发送到mud,比如zmud经典的#wa 2000,又比如有些命令可能会进行展开,比如#study,通过变量和设置展开为 study fu zi literate
jarlyyn
发表于 2021-9-6 11:12:19
然后是速率控制
正常mud都有速率控制的,不然就是比岁网速好,每秒能发更多的命令了。
超过限制往往会发生让人很痛苦的事,比如我玩的mud可能是被雷P,北侠据我测试似乎是吞命令。
那么怎么控制速率呢?
熟悉mush的人立刻会说,用Speedwalk。
您很聪明,学会了防御式开发的防呆式开发,可以跳过这个回复向后看了。
那么,如果不聪明的方式,应该怎么办?
或者说,speedwalk有什么问题吗?
主要是mud,至少侠客行类的mud是通过心跳来计算命令限制的。
在这个模式下,speedwalk其实只有三个问题
[*]在非均匀发送时的效率问题。(这个是小问题,主要在等>发送一堆命令>等的状态下效率看着没那么高)
[*]发送的两个命令的间隔时间的问题。(先open再行走容易遇到被门关住,对npc下kill后容易因为延时被npc先下pfm)
[*]DiscardQueue后部分重要命令被吞的问题(切换技能,练技能,切换回来,结果刚切换过去就被团了,造成无法使用正常的技能)
要解决speedwalk的问题,我们需要自己接管命令的发送。
我先是在mush的机器里做了一个实现,然后在我的客户端引入了一个节拍器的概念
节拍器的逻辑很简单,设置一个周期和命令数
[*]维护一个待发送队列,储存需要发送的命令组(多个命令)列表
[*]支持按组发送命令,在要么一起发送,要么等下一个心跳一起发送
[*]维护一个类似令牌桶的已发送的历史,所以被发送内容的发送时间会放在里面
[*]设置一个高频计时器(mush支持0.1的timer),在发送和计时器触发时,先清理令牌桶里的过期令牌(超过周期),再看令牌桶的剩余空间(命令数-剩余令牌)。如果空间够,发送当前命令组。否则将令牌桶填满,等待下次清理后发送
[*]加入锁定命令,可以锁定当前队列里的所有命令,只有强制Discard才会清理,保证部分命令必定执行。
go语言的版本代码为
https://github.com/jarlyyn/hellclient/blob/master/src/vendor/modules/world/component/metronome/metronome.go
lua版本为
https://github.com/hellclient-scripts/helllua/blob/walk/script/mods/queue.lua
js版本的代码为
https://github.com/hellclient-scripts/zsz-self.jvs/blob/7c325dfa64362c542295ea3ddf8f26f88c5c2d53/script/queue.js
中被注释的部分。
我还写过一个mush机器人的 js 补丁,作为附件上传了
windygreen
发表于 2021-9-6 15:06:45
几点建议
房间除了名字,还要给一个unique number id,因为有非常多的重名。
出口除了方向,还要加上该方向的room id,这样便于将来的遍历
jarlyyn
发表于 2021-9-6 15:55:59
windygreen 发表于 2021-9-6 03:06 PM
几点建议
房间除了名字,还要给一个unique number id,因为有非常多的重名。
出口除了方向,还要加上该方向 ...
谢谢你的建议。
因为北侠不支持全自动机器人
所以这次我并不准备做mapper信息。
mrzhe
发表于 2021-9-6 16:50:21
包神威武
yxdaoer
发表于 2021-9-6 22:33:27
高手风范
jarlyyn
发表于 2021-9-7 01:01:09
制作发送模块
因为是比较核心的模块,适当的加了备注。
主要提供3个功能
[*]发送命令,参数为分号分割的命令,和是否强制按组发送
[*]注册命令,可以将回调(重要部分,之后的回复会解释)注册为命令
[*]组合命令,将分号分割的命令转化为&&分割的命令
命令的特殊语法为
[*]英文句号[.] 和上标号[^]开头的,当作标志(命令),发送时去掉前置的标志位发送
[*]&&分割的当作分组发送(必须一起发送)
[*]井号[#]开头的作为命令,如果将#和第一个空格之间的文字作为指令,第一个空格后的文字作为数据调用指令
[*]#号开头的命令强制分割分组
[*]如果#之后是数字,正数,而且没注册,将数据作为重复发送的命令(zmud的 #5 e)
发送的代码为
https://github.com/hellclient-scripts/pkuxkx.noob/blob/c45bb9de2c31b456c2f01e523208eb9c91ad9677/script/core/send.js
然后在游戏里进行测试
首先
/App.Send("#30 l")
会发现先发送 20个l(我设置的每秒发送限制),然后再断断续续的发送10个l
再测试分组
/App.Send("#15 l\;l&&l&&l&&l&&l&&l&&l&&l&&l&&l&&l&&l&&l&&l&&l")
发现命令分两次发送
第一次连续发送15个
等1秒
第二次还是连续发送15个
完成目标
jarlyyn
发表于 2021-9-7 01:16:02
本帖最后由 jarlyyn 于 2021-9-8 04:10 PM 编辑
接下来看回调。
回调是什么
回调的用途是定义一个函数,在需要的时候进行执行
如发送命令,进入房间,不忙等。
我这里的特殊点是,所有的回调必须先用字符串形式注册到全局(App内),在使用的地方仅使用字符串
无他,方便debug。
比如你设置了进入房间调用的函数,如果是个字符串, 你至少还能打印出来,这个事件帮顶了多少回调。
如果是函数,完全无法debug。
回调通过App.RegisterCallback注册到App.Callbacks里
同时,我还建立了简单的 App.Bind和App.Rasie函数
实现了简单的事件机制
具体代码见
https://github.com/hellclient-sc ... d9677/script/app.js
很明显,通过/Bound()可以打印出所有监听的时间和对应回调
比如我现在就是
{
"OnRoomObj": [
"info.room.objlocate"
],
"OnRoomExits": [
"info.room.namelocate"
]
}很简单清晰
jarlyyn
发表于 2021-9-7 01:34:01
今天还把 i2(道具),skills(技能),jifa(激发) 三个数据的也处理好了
https://github.com/hellclient-scripts/pkuxkx.noob/blob/c45bb9de2c31b456c2f01e523208eb9c91ad9677/script/core/player.js
具体的也没啥好说的,都是基本功
所以,现在只要/App.Send("l;score;hp;i2;cha;jifa")
就能 得到 mud中的所有基本信息了
通过/Debug() 命令打印如下
{
"Room": {
"ID": "yzkd",
"Name": "客店",
"Desc": "",
"Tags": "[大宋国] [城市] [存盘点]",
"Objs": [
{
"ID": "Board",
"Name": "客店留言板"
},
{
"ID": "Tianshen suicong",
"Name": "节日使者 天神随从"
},
{
"ID": "Song shengyi",
"Name": "日月神教 引路人 宋生亦"
},
{
"ID": "Xiao er",
"Name": "店小二"
},
{
"ID": "Xxsmallthree",
"Name": "少林罗汉堂弟子 慧无"
},
{
"ID": "Marsh",
"Name": "武学大家 莫小贝"
},
{
"ID": "Xzg",
"Name": "武学大师 全真派 人仙 小猪哥"
},
{
"ID": "Dome",
"Name": "天眷者 金陵镖局总镖头「面面俱到╰._.╯牛气冲天」渡我"
},
{
"ID": "Azerob",
"Name": "天地会 堂主 无所谓"
},
{
"ID": "Bber",
"Name": "明教 教众 无忧"
},
{
"ID": "Shendu",
"Name": "天龙寺第十五代弟子 本慎"
},
{
"ID": "Jxyu",
"Name": "日月神教 香主 还是潇洒"
},
{
"ID": "Zues",
"Name": "叶绿风"
},
{
"ID": "Luzuo",
"Name": "五毒教山门弟子「有请金蚕蛊大人现身」陆左"
},
{
"ID": "Huke",
"Name": "五毒教山门弟子「四门馆在读学士大唐子爵大人」虎克"
},
{
"ID": "Sip",
"Name": "少林达摩院弟子 澄思"
},
{
"ID": "Ldyz",
"Name": "丐帮二袋弟子 雷迪亚兹"
},
{
"ID": "Shanzhaifuyi",
"Name": "丐帮一袋弟子 芐莒"
},
{
"ID": "Grobot",
"Name": "普通百姓「华丽转身」大高手"
},
{
"ID": "Turnleft",
"Name": "日月神教 香主 向左转"
},
{
"ID": "Phoenix",
"Name": "灵鹫宫首领 凤"
},
{
"ID": "Endless",
"Name": "绝情谷入室弟子 无尽"
},
{
"ID": "Dream",
"Name": "普通百姓 梦"
},
{
"ID": "Dragon",
"Name": "天地会 护法 龙"
},
{
"ID": "Veyron",
"Name": "大宋 忠武将军 威龙"
},
{
"ID": "Kickb",
"Name": "天龙寺第十五代弟子 本鬼"
},
{
"ID": "Raider",
"Name": "少林达摩院弟子 渡鬼"
},
{
"ID": "Walnut",
"Name": "明教 教众 核桃"
},
{
"ID": "Jsysj",
"Name": "普通百姓 宋江"
},
{
"ID": "Yqlljy",
"Name": "普通百姓 卢俊义"
},
{
"ID": "Luyoujiao",
"Name": "丐帮一袋弟子「请君试问东流水,别意与之谁短长!」鲁有角"
},
{
"ID": "Shotone",
"Name": "大宋 昭武校尉 一品"
},
{
"ID": "Lixchh",
"Name": "武当派真人「1743」眼前又黑"
}
],
"Exits": [
"up",
"west"
]
},
"HP": {
"eff_jing": 112,
"jing": 142,
"per_jing": 100,
"eff_jingli": 100,
"jingli": 100,
"jiajing": 0,
"eff_zhenqi": 0,
"zhengqi": 330,
"eff_jingqi": null,
"jingqi": 3475,
"eff_drink": 0,
"drink": 330,
"drink_status": "饥渴",
"exp": 131,
"status": "受伤"
},
"Score": {
"rank": "武当派第四代弟子",
"name": "杰林修",
"id": "Jarlyyn",
"bl": 23,
"wx": 17,
"gg": 21,
"sf": 19,
"fy": 15,
"rm": 18,
"lx": 30,
"ds": "?",
"country": "无国籍",
"family": "武当派",
"age": 16,
"teacher": "谷虚道长",
"gender": "男性",
"loyalty": 0,
"birthday": "戊子年十一月二十一日子时七刻",
"chushi": "无",
"marry": "未婚",
"panshi": "无",
"kill": 0,
"job": "未入职",
"saving": 0,
"killed": 0,
"morality": 0,
"wuxuepoint": 0,
"deaths": 1,
"reputation": 0,
"guojiapoint": 0,
"shaqi": "正常",
"wish": 0,
"shizhan": 0
},
"Skills": {
"All": []
},
"Jifa": [],
"Items": [
{
"ID": "Jiudai",
"Name": "牛皮酒袋"
},
{
"ID": "Gan liang",
"Name": "四块干粮"
},
{
"ID": "Silver",
"Name": "九两白银"
},
{
"ID": "Ma xie",
"Name": "麻鞋"
},
{
"ID": "Pao",
"Name": "青色道袍"
},
{
"ID": "Jin nang",
"Name": "锦囊"
}
],
"Equipments": [
{
"ID": "Ma xie",
"Name": "麻鞋"
},
{
"ID": "Pao",
"Name": "青色道袍"
},
{
"ID": "Jin nang",
"Name": "锦囊"
}
],
"Load": 9,
"Weapon": "",
"WeaponID": ""
}
主动获取内容部分告一段落