jarlyyn
发表于 2025-4-7 20:03:18
应该是的
记得正确设置后进mud会有提示
but
发表于 2025-4-7 20:05:19
jarlyyn 发表于 2025-4-7 08:03 PM
应该是的
记得正确设置后进mud会有提示
data/attachment/forum/cf9e9e833dbc2dedb154248a5483852f.png ok,应该可以了。
icer
发表于 2025-4-7 20:20:00
but 发表于 2025-4-7 08:05 PM
ok,应该可以了。
对,这样就可以统计了。后面可以加版本号或者平台标记以便你分析使用情况,不过要等到你的客户端从左侧“其他”类里独立出来成为一个单独的分类之后,才可以双击查看客户端组成,类似paotin或者mudlet
but
发表于 2025-4-9 07:37:14
使用js很大的好处是可以利用 AI 写不少代码,你看以下的函数大部分都是利用cursor来实现的
// 基础插件,可以参考,请不用修改
let api;
module.exports = {
init: function (apiInstance) {
api = apiInstance;
api.action('您要将另一个连线中的相同人物赶出去', 'y');
//实现对fullme命令的解析,解析图片显示在主界面的右边,@开头的指令是私有指令
api.action(/http:\/\/fullme\.pkuxkx\.net\/robot\.php\?filename=(.*)/, '@fullme $1');
},
/**
* 用xy替代@go ,实现同步到达目标地点,并执行回调函数或命令
* await sys.xy('晋阳', 'sw;w;w;w;s');//到达晋阳后执行sw;w;w;w;s
* @param {string} target 目标地点
* @param {function|string} callback 回调函数或命令
* @param {number} timeout 超时时间
* @returns
*/
xy: async function (target, callback, timeout = 30) {
await this.sync('@go ' + target, '你到达了' + target, timeout);
if (!callback) return;
if (typeof callback === 'function') {
callback();
} else if (typeof callback === 'string') {
api.send(callback);
}
},
delay: function (time, cmd) {
setTimeout(() => {
api.send(cmd);
}, time * 1000);
},
tick: function (time, cmd) {
return setInterval(() => {
api.send(cmd);
}, time * 1000);
},
untick: function (id) {
clearInterval(id);
},
// 睡眠 await sys.sleep(2);等待2秒
sleep: function (time) {
return new Promise((resolve) => {
setTimeout(resolve, time * 1000);
});
},
/**
* 异步转同步,执行命令后,会等待successAction触发才判断结束,才可以继续执行下一条指令
* await sys.sync('@go 晋阳', '你到达了晋阳',30);//到晋阳之后执行其它命令,判断的标准就是屏幕出现了"你到达了晋阳"
* @param {string} cmd 命令
* @param {string} successAction 成功后执行的命令
* @param {number} timeout 超时时间
* @returns
*/
sync: function (cmd, successAction, timeout = 5) {
return new Promise((resolve) => {
this.busywait = true;
// 监听成功事件
const successHandler = () => {
api.unaction(successAction);
this.busywait = false;
clearTimeout(timeoutid);
resolve();
};
// 注册一次性触发器
api.action(successAction, successHandler);
api.send(cmd);
// 设置超时,防止无限等待
const timeoutid = setTimeout(() => {
this.busywait = false;
resolve();
}, timeout * 1000); // 超时
});
},
/**
* 批量执行命令,每条命令之间延迟delaySeconds秒
* await sys.batch(['ask hao about 帮助', 'give hao zi', 'ask hao about 交个朋友', 'ask hao about 独门秘方', 'ask hao about 木桶'], 2);
* @param {string[]} commands 命令列表
* @param {number} delaySeconds 延迟时间
*/
async batch(commands, delaySeconds) {
for (const command of commands) {
try {
api.send(command);
await this.sleep(delaySeconds);
} catch (error) {
api.echo(`命令 "${command}" 执行失败: ${error.message}`, true);
}
}
},
/**
* 反转路径字符串
* reversePath('sw;w;#3 w;s') 返回 'n;#3 e;e;ne'
* @param {string} pathString 路径字符串,例如 'sw;w;w;w;s' 或 '#4 w;s'
* @returns {string} 反转后的路径字符串
*/
reversePath(pathString) {
if (!pathString) {
return '';
}
const oppositeDirections = {
'n': 's',
's': 'n',
'e': 'w',
'w': 'e',
'ne': 'sw',
'nw': 'se',
'se': 'nw',
'sw': 'ne',
'nu': 'sd', // northup -> southdown
'nd': 'su', // northdown -> southup
'eu': 'wd', // eastup -> westdown
'ed': 'wu', // eastdown -> westup
'su': 'nd', // southup -> northdown
'sd': 'nu', // southdown -> northup
'wu': 'ed', // westup -> eastdown
'wd': 'eu', // westdown -> eastup
'u': 'd', // up -> down
'd': 'u', // down -> up
'enter': 'out', // 假设 enter/out 互为反向
'out': 'enter'
// 可以根据需要添加其他特殊移动指令的反向
};
const commands = pathString.split(';');
const reversedCommands = commands.reverse();
const processedCommands = reversedCommands.map(cmd => {
cmd = cmd.trim();
if (!cmd) return ''; // 处理可能的空字符串
// 匹配指令,例如 "#3 w" 或 "ne"
const match = cmd.match(/^(#\d+\s+)?(+)$/i);
if (match) {
const prefix = match || ''; // 前缀,例如 "#3 " 或空字符串
const direction = match; // 方向,例如 "w" 或 "ne"
const opposite = oppositeDirections;
if (opposite) {
return prefix + opposite;
} else {
// 如果找不到反向,可能是不支持的方向或特殊指令,原样返回
return cmd;
}
} else {
// 如果不匹配模式(可能是特殊指令),原样返回
return cmd;
}
});
// 过滤掉处理过程中可能产生的空字符串
return processedCommands.filter(cmd => cmd).join(';');
}
}
利用上面的工具函数,实现药浴任务的一些代码
yaoyu: function () {
api.alias('yaoyu.buy', async () => {
await sys.batch(['buy im_212', 'buy im_212', 'buy im_700', 'buy im_947', 'buy im_768'], 3);
})
api.alias('yaoyu.gomutong', async () => {
await sys.xy('晋阳', 'sw;w;w;w;s');
})
api.alias('yaoyu.backmutong', async () => {
let backpath = sys.reversePath('sw;w;w;w;s');
await sys.batch(, 2);
})
api.alias('yaoyu.askmutong', async () => {
await sys.batch(['ask hao about 帮助', 'give hao zi', 'ask hao about 交个朋友', 'ask hao about 独门秘方', 'ask hao about 木桶'], 2);
})
}后续逐渐更新到wiki上
jarlyyn
发表于 2025-4-9 10:15:04
but 发表于 2025-4-9 07:37 AM
使用js很大的好处是可以利用 AI 写不少代码,你看以下的函数大部分都是利用cursor来实现的
利用上面的工具 ...
实际上每个指令都会有失败,比如ask和购买的失败处理。
最好还是注册标准指令后处理。
我以前的洗澡代码大概是这样的
(function (App) {
App.Quest.Common.Bath = {}
App.Quest.Common.Bath.Data = {}
App.Quest.Common.Bath.Start = function (param) {
if (!param) {
throw "洗澡的房间不能为空"
}
App.Quest.Common.Bath.Data = {
Home: param,
}
App.Quest.Common.Bath.Main()
}
App.Quest.Common.Bath.Finish = function () {
App.Core.Quest.Cooldown("bath", 60 * 60 * 1000)
App.Next()
}
App.Quest.Common.Bath.Main = function () {
App.Core.Sell.SetNoSell("gouqi")
App.Core.Sell.SetNoSell("digu pi")
App.Core.Sell.SetNoSell("shechuang zi")
App.Core.Sell.SetNoSell("gancao")
App.Core.Sell.SetNoSell("sheng gancao")
App.Commands([
App.NewCommand('prepare', App.PrapareFull),
App.NewCommand('function', App.Quest.Common.Bath.Next)
]).Push()
App.Next()
}
App.Quest.Common.Bath.Next = function () {
if (App.GetItemByName("地骨皮", true) == null) {
if (App.GetItemByName("枸杞", true) == null) {
App.Commands([
App.NewCommand("to", App.Options.NewWalk("lingzhou-jiuguan")),
App.NewCommand('do', "buy gouqi;i2"),
App.NewCommand('nobusy'),
App.NewCommand('function', App.Quest.Common.Bath.Main),
]).Push()
App.Next()
return
} else {
App.Commands([
App.NewCommand('do', "xiao gouqi;i2"),
App.NewCommand('nobusy'),
App.NewCommand('function', App.Quest.Common.Bath.Main),
]).Push()
App.Next()
return
}
}
if (App.GetItemByName("生甘草", true) == null) {
if (App.GetItemByName("甘草", true) == null) {
App.Commands([
App.NewCommand("to", App.Options.NewWalk("yzdp")),
App.NewCommand('do', "buy im_190;i2"),
App.NewCommand('nobusy'),
App.NewCommand('function', App.Quest.Common.Bath.Main),
]).Push()
App.Next()
return
} else {
App.Commands([
App.NewCommand('do', "bo gancao;i2"),
App.NewCommand('nobusy'),
App.NewCommand('function', App.Quest.Common.Bath.Main),
]).Push()
App.Next()
return
}
}
if (App.GetItemObj("Pot", true) == null) {
App.Commands([
App.NewCommand("to", App.Options.NewWalk("yz-zhp")),
App.NewCommand('do', "buy pot;i2"),
App.NewCommand('nobusy'),
App.NewCommand('function', App.Quest.Common.Bath.Main),
]).Push()
App.Next()
return
}
if (App.GetItemByName("蛇床子", true) == null) {
App.Commands([
App.NewCommand("to", App.Options.NewWalk("suzhoudp")),
App.NewCommand('do', "buy im_226;i2"),
App.NewCommand('nobusy'),
App.NewCommand('function', App.Quest.Common.Bath.Main),
]).Push()
App.Next()
return
}
if (App.GetItemByName("大木桶", true) == null) {
App.Commands([
App.NewCommand("to", App.Options.NewWalk("jinyangyp")),
App.NewCommand('ask', App.Options.NewQuestion("hao ba", "帮助")),
App.NewCommand('nobusy'),
App.NewCommand('do', "give shechuang zi to hao ba"),
App.NewCommand('nobusy'),
App.NewCommand('ask', App.Options.NewQuestion("hao ba", "交个朋友")),
App.NewCommand('nobusy'),
App.NewCommand('ask', App.Options.NewQuestion("hao ba", "独门秘方")),
App.NewCommand('nobusy'),
App.NewCommand('ask', App.Options.NewQuestion("hao ba", "木桶")),
App.NewCommand('nobusy'),
App.NewCommand('do', "i2"),
App.NewCommand('function', App.Quest.Common.Bath.Main),
]).Push()
App.Next()
return
}
App.Commands([
App.NewCommand("to", App.Options.NewWalk("xinyang-tqc")),
App.NewCommand('do', "fill pot;i2"),
App.NewCommand('nobusy'),
App.NewCommand("to", App.Options.NewWalk("yz-sczh")),
App.NewCommand("move", App.Options.NewPath("enter " + App.Quest.Common.Bath.Data.Home)),
App.NewCommand("do", "add shechuang zi;add digu pi;add sheng gancao;pour tong;pour tong;pour tong;bath"),
App.NewCommand("delay", 120),
App.NewCommand("nobusy"),
App.NewCommand('function', App.Quest.Common.Bath.Finish),
]).Push()
App.Next()
}
})(App)