jarlyyn
发表于 2021-9-28 17:23:53
加入授权一览和注销功能
jarlyyn
发表于 2021-9-29 10:37:17
然后是验证码输入功能。
首先是抓取验证码URL并记录,这个简单,加一行出发就行
^(http:\/\/fullme\.pkuxkx\.net\/robot\.php\?filename=\d+)$
然后需要获取php文件内容,里面的验证码地址。
这里我使用了一个异步操作。创建请求,异步发起,指明回调地址。然后代码继续向下走。
请求完成后,回调根据传入的请求是否成功的参数,获取请求的实际数据。
在机器人脚本的场景下,同步请求太坑,利用协程之类还要解决数据竞争问题,和浏览器里JS一样单线程+回调是我觉得比较合适的放案
具体代码为
app.API.Fullme=function(callback){
let url=app.Core.FullmeUrl
if (url){
app.Data.FullmeCallback=callback?callback:""
app.Core.FullmeReq=HTTP.New("GET",url)
app.Core.FullmeReq.AsyncExecute("App.Core.OnFullme")
}
}
app.Core.OnFullme=function(name,id,code,data){
if (code!=0){
throw data
}
if (code==0){
let result=imgsrcre.exec(app.Core.FullmeReq.ResponseBody())
if (result==null){
throw "无法匹配图片地址"
}
let url="http://fullme.pkuxkx.net"+result
app.API.ShowFullme(url)
}
}
获取到后,我偷了个懒,用正则匹配,获取实际图片地址
然后做了个可视化识别输入的组件,弹出输入框让用户填写验证码。
app.API.ShowFullme=function(url){
let vp=Userinput.newvisualprompt("验证码","忽略红色字符,如果是方向性文字,每对中括号内文字为一组",url)
vp.setrefreshcallback("App.Core.OnFullmeRefresh")
vp.publish("App.Core.OnFullmeSubmit")
}
具体代码见
https://github.com/hellclient-scripts/pkuxkx.noob/blob/2c1ecad25027adf7bff810e047075dff6669098b/script/core/fullme.js
jarlyyn
发表于 2021-9-29 10:44:16
让我们试一下实际效果
先收工输入fullme
然后输入
/App.Fullme()
弹窗出来了,然后,嗯,认不出,北侠的验证码早晚只有程序才能全认出来。点上方的刷新图标,多刷了几次
这是啥?手挠?继续刷新。
这回看出来,手扶……还拖拉机呢……
填写 手扶 两个字进输入框,提交,机器将我填写的内容发送到mud,fullme成功。
好了,这个功能完成了。
其实北侠要针对别人破解fullme很容易,凡是成功高且快的,一定不是真人……
jarlyyn
发表于 2021-10-5 00:28:35
节后机器暂时停止更新。
由于我玩的mud节前有大幅度修改,会以这套框架重做部分机器。
届时会有部分代码回馈到这个框架里。
jarlyyn
发表于 2021-10-9 01:50:01
为机器人加入载具模式。
所谓载具,就是行走的工具。
默认的载具是run,快速移动,可以多步移动,直接发送命令。
一个额外的载具是go,就是在发送命令前加入go,比如 go west,会过滤命令,不会多步移动。
另外引入一个赶车的载具cart,在发送命令前加入gan che to,比如gan che to west,会过滤命令,不会多步移动。
过滤命令是有一个替换列表,具体为
(function(){
return {
"east": "%1east",
"south": "%1south",
"west": "%1west",
"north": "%1north",
"southeast": "%1southeast",
"southwest": "%1southwest",
"northeast": "%1northeast",
"northwest": "%1northwest",
"eastup": "%1eastup",
"eastdown": "%1eastdown",
"southup": "%1southup",
"southdown": "%1southdown",
"westup": "%1westup",
"westdownwd": "%1westdown",
"northup": "%1northup",
"northdown": "%1northdown",
"up": "%1up",
"down": "%1down",
"e": "%1east",
"s": "%1south",
"w": "%1west",
"n": "%1north",
"se": "%1southeast",
"sw": "%1southwest",
"ne": "%1northeast",
"nw": "%1northwest",
"eu": "%1eastup",
"ed": "%1eastdown",
"su": "%1southup",
"sd": "%1southdown",
"wu": "%1westup",
"wd": "%1westdown",
"nu": "%1northup",
"nd": "%1northdown",
"u": "%1up",
"d": "%1down",
"enter": "%1enter",
"out": "%1out",
"e·": "%1east",
"s·": "%1south",
"w·": "%1west",
"n·": "%1north",
"se·": "%1southeast",
"sw·": "%1southwest",
"ne·": "%1northeast",
"nw·": "%1northwest",
"eu·": "%1eastup",
"ed·": "%1eastdown",
"su·": "%1southup",
"sd·": "%1southdown",
"wu·": "%1westup",
"wd·": "%1westdown",
"nu·": "%1northup",
"nd·": "%1northdown",
"u·": "%1up",
"d·": "%1down",
"enter·": "%1enter",
"out·": "%1out",
"yell boat。":"yell boat",
"#wait":"#wait"
}
})()
载具的基础类是
(function(app){
let _drivepath=Include("include/drivepath.js")
let Vehicle=function(){
this.TagDrive=false
this.MultiStep=false
this.ID=""
this.RetryInterval=0.5
this.Fly=false
this.Sender=function(cmd){
app.Send(cmd)
}
}
Vehicle.prototype.Send=function(cmd){
this.Sender(cmd)
}
Vehicle.prototype.ConvertDrivePath=function(cmd,path){
let p=_drivepath
if (!p){
throw "无效的drivepath"+path
}
p=p.replace("%1",cmd)
return p
}
return Vehicle
})(App)
默认的run
(function (app) {
let Vehicle = Include("core/vehicle/vehicle.js")
let Run = function () {
Vehicle.call(this)
this.ID="run"
this.MultiStep=true
this.Fly=true
}
Run.prototype = Object.create(Vehicle.prototype)
return Run
})(App)额外的go
(function (app) {
let Vehicle = Include("core/vehicle/vehicle.js")
let Go = function () {
Vehicle.call(this)
this.ID="go"
this.TagDrive=true
this.Sender=function(cmd){
app.Send(this.ConvertDrivePath("go ",cmd))
}
}
Go.prototype = Object.create(Vehicle.prototype)
return Go
})(App)
额外的cart
(function (app) {
let Vehicle = Include("core/vehicle/vehicle.js")
let Cart = function () {
Vehicle.call(this)
this.TagDrive=true
this.ID="cart"
this.Sender=function(cmd){
app.Send(this.ConvertDrivePath("gan che to ",cmd))
}
}
Cart.prototype = Object.create(Vehicle.prototype)
return Cart
})(App)全局引入 Drive方法切换载具,go方法发送前进命令
let cart = Include("core/vehicle/cart.js")
app.Vehicle=null
app.Vehicles={
Run:new run(),
Go:new go(),
Cart:new cart(),
}
app.Vehicle=app.Vehicles.Run
app.Drive=function(id){
if(id){
for (let key in app.Vehicles) {
if (app.Vehicles.ID == id){
app.Vehicle=app.Vehicles
return
}
}
throw "未知的载具 " +id
}else{
app.Vehicle=app.Vehicles.Run
}
}
app.RegisterCallback("core.vehicle.inittags",function(){
Mapper.settag("drive",app.Vehicle.TagDrive)
})
app.Bind("PathInit","core.vehicle.inittags")
app.Go=function(cmd){
app.Vehicle.Send(cmd)
}
并在移动模块里做相应调整。
同时#to命令支持设置载具
比如#to yzkd,#to go yzgc,#to cart yzyp
更新较多
详细内容见
https://github.com/hellclient-scripts/pkuxkx.noob/commit/de44c7966aae9c2e5cf8b7b48c313484bf9816fa
jarlyyn
发表于 2021-10-9 01:56:24
让我们看看实际效果
先是#to yzyp,很明显,多步前进
然后是#to go qfsm,单步前进,带go 的前缀
最后 #to cart ly,嗯,没有车,只是发了个带gan che to的命令……
xlyh
发表于 2021-10-11 22:47:08
写的不错 期待客户端有win版的
jarlyyn
发表于 2021-10-12 17:35:49
下一步要做的模块是道具和NPC。
根据我的经验,侠客行类游戏有很大一块的内容是围绕道具和NPC。
获取XXX道具
将XXX道具给NPC
找到XXXNPC
杀死XXXNPC
依次找到XXX,XXX,XXX NPC等。
所以,这块可以认为是另一个重要部分
jarlyyn
发表于 2021-10-12 17:41:46
本帖最后由 jarlyyn 于 2021-10-12 06:58 PM 编辑
先让我们给道具做一个抽象。
道具是什么?
道具是Mud里可以获取并携带在身上的一种对象。
最基本的,
一个道具有 Name(英文名)和Label(标签)两种属性,理论上还可以有数量。
出于管理需要,我们还可能加上一个独一无二的ID,避免有重名不同属性的,以及显示用的备注
在实际使用中,道具还有一些额外的属性,比如
获取方式(购买,捡取,杀人夺宝)
获取命令(buy或者get)
获取目标(比如购买的位置,所在的NPC等)
获取间隔(可能要等刷新才能获取)
所以,一个基本的道具的代码可能是这样的
(function(app){
let Item=function(){
this.ID=""
this.Name=""
this.Label=""
this.Type=""
this.Comment=""
this.Interval=0
this.Command=""
this.Location=""
}
return Item
})(App)
很明显。这个标志化的格式可以用来保存为文本文件进行管理
jarlyyn
发表于 2021-10-12 17:43:21
本帖最后由 jarlyyn 于 2021-10-12 06:39 PM 编辑
然后在整理一下道具获取的形式,大概有这么几种基础类型
[*]货物(固定点获取,前往路径后执行指定命令)
[*]资源(固定区域获取,遍历路径,找到目标后执行制定命令)
[*]战利品(战斗胜利后获取,与NPC联动,寻找NPC,找到目标后进行战斗,胜利后执行指定命令)
[*]回执(找到NPC后获取,与NPC联动,寻找NPC.找到后执行指定命令获取)
[*]工艺品(通过其他物品制作,与其他物品联动,依次获取必备道具,最后在指定位置执行命令获取)
[*]其他
在明确了Type后,这些道具的Location对应的值也很明显了
[*]goods:获取的地址
[*]resource:路径的ID
[*]trophy:Npc的id
[*]receipt:Npc的id
[*]crafts:需要的道具id和数量的列表
这里特别要注意的就是牵涉到了id,必然会有固定数据和临时数据的id两种
然后,很明显,我们需要一个生产(Produce)方法
用来根据传入的道具ID,成功和失败ID生成一个任务
任务执行后就会去尝试获取对应道具