From 6ce23e594ce99b5473b53619a2a32574484cc8f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E7=B4=AB=E7=83=9Fowo?= <232029620+jiangziyanowo@users.noreply.github.com> Date: Fri, 24 Oct 2025 09:26:39 +0800 Subject: [PATCH] =?UTF-8?q?AotoTeyvatFoodOneDragon-V1.1=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20(#2221)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改了用户名获取方式方式,改为了设置界面指定用户名(历史记录与历史收益均受到了影响,但避免了后续出现bug的可能性) - 修改了部分不合逻辑的地方(如自动拾取触发时机等) - 修复了一些bug(如坐标比较逻辑中的潜在问题等) - 优化内存使用和资源释放机制 - 添加了用户名验证 - 添加了指定时间结束运行的功能 --- repo/js/AotoTeyvatFoodOneDragon/README.md | 33 +- repo/js/AotoTeyvatFoodOneDragon/main.js | 355 ++++++++++++++---- repo/js/AotoTeyvatFoodOneDragon/manifest.json | 9 +- repo/js/AotoTeyvatFoodOneDragon/settings.json | 11 +- 4 files changed, 308 insertions(+), 100 deletions(-) diff --git a/repo/js/AotoTeyvatFoodOneDragon/README.md b/repo/js/AotoTeyvatFoodOneDragon/README.md index 014b68133..b5bb3dea9 100644 --- a/repo/js/AotoTeyvatFoodOneDragon/README.md +++ b/repo/js/AotoTeyvatFoodOneDragon/README.md @@ -42,6 +42,7 @@ #### 🗓️ 月卡自动领取 - 智能检测领取时间 - 在每日4点自动领取月卡奖励 +- 支持运行到指定时间点停止运行,便于衔接其他任务 #### 👨‍🍳 食材自动加工 - 在运行过程中可自动加工食材(如已勾选) - 智能查找和选择对应食材 @@ -67,27 +68,33 @@ 1. 将脚本添加至调度器。 2. 右键点击脚本以修改 JS 自定义配置。 - 选择采集队伍的名称,未填写队伍名将以当前队伍进行采集,推荐使用迪希雅(行走位&冰雾花&电气水晶)、万叶(吸果子&减少体力损耗)、白术(任意不会击杀晶蝶螃蟹的生存位)、蓝砚or早柚(双风&晶蝶) - - 选择要采集的国家 - - 勾选是否运行过程中进行烹饪/加工 - - 勾选是否需要月卡点击 + - 选择每个国家的运行模式 + - 勾选其他需要的设置(如自定义文件夹,加工,月卡,查询收益等) 3. 点击运行即可 ## ⚠️ 注意事项 -1. 仓库版本经过作者测试,在保证连续3天内无卡脚的情况下上传,且上传后作者仍在每天使用、测试,出现常态问题会跟踪修复。但是不同的队伍、不同的设备,运行相同脚本也有可能产生不同的结果,小概率漏食材或者卡脚属于正常现象。若出现稳定卡脚或漏食材的情况,请在频道发帖并艾特作者作者或直接加入QQ群内反馈【qq群:967950353】 -2. 食材刷新时间为每日0点,螃蟹类刷新时间为采集后12小时,推荐间隔12小时且经过每日0点后运行本脚本; -3. 果树与部分高处的食材刚需万叶,不携带万叶不影响其他部分食用; -4. 无迪希雅的情况,可使用其他大剑行走位代替,依靠钟剑挨揍的盾足以应对本脚本大多数怪堆场景,但有一定概率被电气水晶小卡脚; -5. 运行过程中进行烹饪/加工:在每个国家的任务运行结束后,会按照勾选情况决定是否进行烹饪/加工。支持填写多个料理/食材名称,填写多个时,下方数量要一一对应并且要符号分隔开(支持中英文逗号、中英文分号、空格等符号)。由于食材与料理的页面不同,为避免频繁翻页,建议将料理和食材分开填写。 -6. 加工数量:是每次进行加工时填写的数量,由于加工队列有数量限制,此数量在第二次时会与实际烹饪数量有较大概率出现偏差,无法接受此类情况的用户请移步仓库内食材加工脚本或手动加工。关于统计,目前只支持食材与加工品的统计,暂不支持料理计数 -7. 运行自己的脚本?打开assets文件夹,新建文件夹,命名为需要包含关键字“自定义”,将需要运行的json文件丢进这个文件夹即可。此文件夹会做保护处理,不随更新覆盖。自定义文件夹目前只支持全运行或不运行。在运行时也可针对国家向原有文件夹内放入json文件,但这类文件会随更新被覆盖,此方法请酌情使用。 -8. 本脚本在运行JS脚本【锄地一条龙】后更安全稳定; -9. 本一条龙非效率一条龙而是尽可能全覆盖地图上地区特色食材,需要提高效率或单独某种食材,请自行筛选路线或使用仓库其他作者的食材脚本;(也许《提瓦特食材一条龙极速版》也是个不错的选择?) -10. 想在手机上查看收益详情?打开设置中的js通知并确保bgi全局通知设置下填写了js.custom,这样才能正确收到通知的详情 +1. 兼容性说明:脚本经过多次测试,但不同队伍和设备可能出现不同结果,小概率漏食材或卡脚属于正常现象。如多次卡脚或漏食材,请加入QQ群反馈【qq群:967950353】。 +2. 刷新时间:食材每日0点刷新,螃蟹类采集后12小时刷新,建议间隔12小时且经过每日0点后运行。 +3. 角色需求:果树与高处食材需要万叶;无迪希雅时可用其他大剑角色(如嘉明)代替,但运行效率可能有所下降 +4. 烹饪/加工:支持填写多个料理/食材名称,数量需一一对应并用符号分隔。建议将料理和食材分开填写以避免频繁翻页。 +5. 加工数量:填写的数量可能与实际烹饪数量有偏差,无法接受者请使用专门的食材加工脚本。收益统计暂不支持料理计数。 +6. 自定义脚本:在assets文件夹新建含"自定义"关键字的文件夹存放json文件,此文件夹不会被更新覆盖。 +7. 运行建议:建议在运行【锄地一条龙】后再使用本脚本,更加安全稳定。 +8. 路线选择:本脚本追求全覆盖地区特色食材而非效率,如需提高效率请自行筛选路线或使用其他食材脚本。 +9. 收益通知:想在通知中查看收益详情?需在开启js通知并确认bgi全局通知包含js.custom参数(收益详情在当前版本稳定性欠佳,仅供参考)。 +10. 指定时间结束:在运行过程中,运行完当前脚本会检测时间,若距离目标时间小于十分钟,会停止运行并持续等待至指定时间,便于衔接其他任务。(开启此功能后脚本会以中断的方式结束,故收益查看会受到影响) ----------------------------------------------------------------------------------------------------------------------------- ## 📜 更新日志 +### 1.1(2025.10.23) +- 修改了用户名获取方式方式,改为了设置界面指定用户名(历史记录与历史收益均受到了影响,但避免了后续出现bug的可能性) +- 修改了部分不合逻辑的地方(如自动拾取触发时机等) +- 修复了一些bug(如坐标比较逻辑中的潜在问题等) +- 优化内存使用和资源释放机制 +- 添加了用户名验证 +- 添加了指定时间结束运行的功能 ### 1.0(2025.10.18) 酱酱!“提瓦特食材一条龙 V1.0”闪亮登场!这脚本有什么功能呢?让我们一起卡看吧! - 地图追踪自动化:支持多个地区(蒙德、璃月、稻妻、须弥、枫丹、纳塔、挪德卡莱)的自动采集路径 diff --git a/repo/js/AotoTeyvatFoodOneDragon/main.js b/repo/js/AotoTeyvatFoodOneDragon/main.js index 4c75d18f2..e20dee042 100644 --- a/repo/js/AotoTeyvatFoodOneDragon/main.js +++ b/repo/js/AotoTeyvatFoodOneDragon/main.js @@ -6,7 +6,76 @@ const CaiJiPartyName = settings.CaiJiPartyName || "null"; const ZDYparty = settings.ZDYparty || "null"; - const userName = await getCurrentUsername(); + const userName = settings.userName || "默认账户"; + + // Windows文件名非法字符列表 + const illegalCharacters = /[\\/:*?"<>|]/; + // Windows保留设备名称列表 + const reservedNames = [ + "CON", "PRN", "AUX", "NUL", + "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", + "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" + ]; + + // 检查userName是否为空或只有空格 + if (!userName || userName.trim() === "") { + log.error(`账户名 "${userName}" 不合法,账户名为空或只包含空格。`); + log.error(`将终止程序,请使用合法的名称`); + await sleep(5000); + return; + } + // 检查userName是否以空格开头 + else if (userName.startsWith(" ")) { + log.error(`账户名 "${userName}" 不合法,以空格开头。`); + log.error(`将终止程序,请使用合法的名称`); + await sleep(5000); + return; + } + // 检查userName是否以空格结尾 + else if (userName.endsWith(" ")) { + log.error(`账户名 "${userName}" 不合法,以空格结尾。`); + log.error(`将终止程序,请使用合法的名称`); + await sleep(5000); + return; + } + // 检查userName是否以点号结尾 + else if (userName.endsWith(".")) { + log.error(`账户名 "${userName}" 不合法,以点号结尾。`); + log.error(`将终止程序,请使用合法的名称`); + await sleep(5000); + return; + } + // 检查userName是否包含非法字符 + else if (illegalCharacters.test(userName)) { + log.error(`账户名 "${userName}" 不合法,包含非法字符。`); + log.error(`将终止程序,请使用合法的名称`); + await sleep(5000); + return; + } + // 检查userName是否是保留设备名称 + else if (reservedNames.includes(userName.toUpperCase())) { + log.error(`账户名 "${userName}" 不合法,是保留设备名称。`); + log.error(`将终止程序,请使用合法的名称`); + await sleep(5000); + return; + } + // 检查userName长度是否超过255字符 + else if (userName.length > 255) { + log.error(`账户名 "${userName}" 不合法,账户名过长。`); + log.error(`将终止程序,请使用合法的名称`); + await sleep(5000); + return; + } + // 检查userName长度是否为0 + else if (userName.length === 0) { + log.error(`账户名不合法,账户名为空。`); + log.error(`将终止程序,请使用合法的名称`); + await sleep(5000); + return; + } + else { + log.info(`账户名 "${userName}" 合法。`); + } const cdRecordPath = `record/${userName}_cd.txt`;// 修改CD记录文件路径,包含用户名 @@ -35,7 +104,7 @@ } // 常量定义 - const Pamon = `assets/RecognitionObject/Pamon.png`; + const Pamon = `assets/RecognitionObject/Paimon.png`; const targetFoods = new Set([ "面粉", "兽肉", "鱼肉", "神秘的肉", "黑麦粉", "奶油", "熏禽肉", "黄油", "火腿", "糖", "香辛料", "酸奶油", "蟹黄", "果酱", @@ -56,7 +125,7 @@ // 状态变量 let currentTask = 0; // 当前任务计数器 - let firstScan, secondScan, nowStatus, earning; + let firstScan, secondScan, nowStatus, earning, stovePosition; // ===== 2. 子函数定义部分 ===== @@ -226,7 +295,7 @@ holdY: 750, // 页面滚动距离,控制每次翻页时滑动的距离,数值越小翻页越精细但需要更多次翻页 - pageScrollDistance: 450, + pageScrollDistance: 300, // 图像识别延迟(毫秒),在识别物品时的延迟时间,用于平衡性能和准确性 imageDelay: 20, @@ -606,7 +675,7 @@ const columnWidth = 123; const columnHeight = 680; const maxColumns = 8; - const pageScrollCount = 22; + const pageScrollCount = 35; // 扫描状态 let hasFoundFirstMaterial = false; @@ -935,8 +1004,8 @@ // 计算每个物品的差值 itemsToCheck.forEach(name => { - const count1 = map1[name]; - const count2 = map2[name]; + const count1 = map1[name] || "0"; + const count2 = map2[name] || "0"; // 检查是否有任意一次识别失败 if (count1 === "?" || count2 === "?") { @@ -981,14 +1050,16 @@ const now = new Date(); const formattedDate = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`; - let newRecord = `=== ${formattedDate} ===\n`; + let newRecord = `=== ${formattedDate} ===\n(收益结果受多因素影响,可能会不准确,本结果仅供参考)\n`; let hasChanges = false; Object.keys(diff).forEach(item => { const change = diff[item]; if (change === "识别失败") { - // 不记录识别失败的项目 + // 记录识别失败的项目 + newRecord += `❌ ${item}: 识别失败\n`; + hasChanges = true; // 确保即使只有识别失败的项目也会显示"有变化" } else { if (change !== 0) { newRecord += `✅ ${item}: ${change > 0 ? '+' : ''}${change}\n`; @@ -1298,7 +1369,7 @@ } /** - * 获取JSON文件中最后一个对象的xy坐标(异步版本) + * 获取JSON文件中最后一个对象的xy坐标 * @param {string} filePath - JSON文件路径 * @returns {Object|null} 包含x和y坐标的对象,失败时返回null */ @@ -1306,33 +1377,47 @@ try { // 使用异步文件读取函数 const content = await file.readText(filePath); - const jsonData = JSON.parse(content); - // 检查数据结构 - if (!jsonData || typeof jsonData !== 'object') { - throw new Error('无效的JSON数据结构'); + // 为了减少内存使用,在使用完content后尽快释放 + let positions; + let lastPosition; + let result; + + try { + const jsonData = JSON.parse(content); + + // 检查数据结构 + if (!jsonData || typeof jsonData !== 'object') { + throw new Error('无效的JSON数据结构'); + } + + positions = jsonData.positions; + if (!positions || !Array.isArray(positions) || positions.length === 0) { + throw new Error('positions数组为空或不存在'); + } + + // 获取最后一个点位 + lastPosition = positions[positions.length - 1]; + + // 检查坐标字段 + if (typeof lastPosition.x === 'undefined' || typeof lastPosition.y === 'undefined') { + throw new Error('最后一个点位缺少x或y坐标'); + } + + result = { + x: lastPosition.x, + y: lastPosition.y, + positionId: lastPosition.id || null, + totalPositions: positions.length, + index: positions.length - 1 + }; + } finally { + // 显式清理对象引用,帮助垃圾回收 + positions = null; + lastPosition = null; } - const positions = jsonData.positions; - if (!positions || !Array.isArray(positions) || positions.length === 0) { - throw new Error('positions数组为空或不存在'); - } - - // 获取最后一个点位 - const lastPosition = positions[positions.length - 1]; - - // 检查坐标字段 - if (typeof lastPosition.x === 'undefined' || typeof lastPosition.y === 'undefined') { - throw new Error('最后一个点位缺少x或y坐标'); - } - - return { - x: lastPosition.x, - y: lastPosition.y, - positionId: lastPosition.id || null, - totalPositions: positions.length, - index: positions.length - 1 - }; + return result; } catch (error) { log.error(`处理文件 ${filePath} 时出错:`, error.message); @@ -1340,6 +1425,7 @@ } } + /** * 比较两个坐标是否近似相等 * @param {Object} coord1 - 第一个坐标对象 {x, y} @@ -1433,10 +1519,11 @@ * @param { string[] } files - 要执行的路线文件名数组(含路径) */ async function runFiles(files) { + // 启用自动拾取 + dispatcher.addTimer(new RealtimeTimer("AutoPick")); + for (const fileName of files) { try { - - // 提取路线名称(不含.json后缀) const fName = fileName.split('\\').pop().split('/').pop().replace('.json', ''); @@ -1503,6 +1590,17 @@ await fakeLog(routeName, false, false, 0); + const ifExit = checkExitTime(settings.exitTime); // 检查是否已到退出时间 + if (!ifExit) { + // 计算需要等待的时间 + const waitTime = calculateWaitTime(settings.exitTime); + if (waitTime > 0) { + log.warn(`距离退出时间还有约${Math.floor(waitTime / 1000 / 60)}分${Math.floor((waitTime / 1000) % 60)}秒`); + await genshin.tpToStatueOfTheSeven(); // 回神像等别被肘死了再怪作者…… + await sleep(waitTime + 10000); // 等待时间差+10秒 + } + } + try { // 若启用月卡功能,则点击领取月卡奖励 if (ifMonthcard) { @@ -1513,9 +1611,15 @@ } catch (error) { log.error(`月卡功能发生错误: ${error}`); } + + if (!ifExit) { + log.warn("已到退出时间,将退出程序"); + await genshin.returnMainUi(); + throw new Error("Exit time reached."); // 抛出异常 + } + } catch (e) { - // 修改:继续抛出被取消的任务错误,以便上层处理 - if (e.message == "A task was canceled.") { + if (e.message == "A task was canceled." || e.message == "Exit time reached.") { throw e; // 继续抛出错误 } else { log.error(`处理文件 ${fileName} 时出错: ${e.message},已跳过该路径`); @@ -1524,23 +1628,28 @@ } } + // 关闭自动拾取,防止误触炉子 + dispatcher.ClearAllTriggers(); + // 获取炉子位置坐标并与当前位置比较,决定是否需要执行食材加工 - let position3, position4; + let position4; try { - position3 = await getLastPositionCoords(`assets/${stove}.json`); position4 = genshin.getPositionFromMap(); } catch (error) { position4 = { X: 0, Y: 0 } } - log.debug(`炉子坐标: X=${position3.x}, Y=${position3.y}`); - log.debug(`当前小地图坐标: X=${position4.X}, Y=${position4.Y}`); - const ifDeviation1 = areCoordinatesApproximate(position3, position4, 15); - await sleep(10); + if (stovePosition && ifingredientProcessing) { + log.debug(`炉子坐标: X=${stovePosition.x}, Y=${stovePosition.y}`); + log.debug(`当前小地图坐标: X=${position4.X}, Y=${position4.Y}`); - if (ifDeviation1) { - log.debug("距离上一次加工过近,不执行食材加工"); - return; + const ifDeviation1 = areCoordinatesApproximate(stovePosition, position4, 15); + await sleep(10); + + if (ifDeviation1) { + log.debug("距离上一次加工过近,不执行食材加工"); + return; + } } // 执行食材加工 @@ -1551,28 +1660,122 @@ // 执行地图追踪文件 await runFiles(jsonFilePaths); } catch (e) { - // 修改:继续抛出被取消的任务错误,保持错误传播链 - if (e.message == "A task was canceled.") { - throw e; // 继续抛出错误 + if (e.message == "A task was canceled." || e.message == "Exit time reached.") { + throw e; } log.error(`路径组执行失败: ${e.message}`); } } + /** + * 计算距离退出时间的等待时间 + * @param {string} timeSetting - 时间设置字符串,格式为 "HH:MM" 或 "HH:MM" + * @returns {number} 需要等待的毫秒数 + */ + function calculateWaitTime(timeSetting) { + if (!timeSetting || !/^\d{1,2}[::]\d{2}$/.test(timeSetting)) return 0; + + const now = new Date(); + const currentHour = now.getHours(); + const currentMinute = now.getMinutes(); + const currentSecond = now.getSeconds(); + + // 解析设置的时间(支持中英文冒号) + const [targetHour, targetMinute] = timeSetting.split(/[::]/).map(Number); + + // 验证时间有效性 + if (isNaN(targetHour) || isNaN(targetMinute) || + targetHour < 0 || targetHour > 23 || + targetMinute < 0 || targetMinute > 59) { + return 0; + } + + // 计算当前时间和目标时间的总秒数 + const currentTotalSeconds = currentHour * 3600 + currentMinute * 60 + currentSecond; + const targetTotalSeconds = targetHour * 3600 + targetMinute * 60; + + // 计算需要等待的秒数 + let secondsToWait; + if (currentTotalSeconds < targetTotalSeconds) { + // 同一天内 + secondsToWait = targetTotalSeconds - currentTotalSeconds; + } else { + // 跨天情况(目标时间是第二天) + secondsToWait = (24 * 3600 - currentTotalSeconds) + targetTotalSeconds; + } + + return secondsToWait * 1000; // 转换为毫秒 + } + + /** + * 检查当前时间是否接近禁止运行的时间点(提前10分钟停止) + * @param {string} timeSetting - 时间设置字符串,格式为 "HH:MM" 或 "HH:MM",如 "04:30" 或 "04:30" 表示凌晨4点30分 + * @returns {boolean} 如果当前时间距离禁止运行时间点不足10分钟返回false,否则返回true + */ + function checkExitTime(timeSetting) { + if (!timeSetting || !/^\d{1,2}[::]\d{2}$/.test(timeSetting)) return true; + + const now = new Date(); + const currentHour = now.getHours(); + const currentMinute = now.getMinutes(); + + // 解析设置的时间(支持中英文冒号,会有小笨猪写中文冒号吗?) + const [targetHour, targetMinute] = timeSetting.split(/[::]/).map(Number); + + // 验证时间有效性 + if (isNaN(targetHour) || isNaN(targetMinute) || + targetHour < 0 || targetHour > 23 || + targetMinute < 0 || targetMinute > 59) { + return true; + } + + // 计算当前时间与目标时间的分钟差 + const currentTotalMinutes = currentHour * 60 + currentMinute; + const targetTotalMinutes = targetHour * 60 + targetMinute; + + // 计算距离目标时间的分钟数(考虑跨天情况) + let minutesToTarget; + if (currentTotalMinutes <= targetTotalMinutes) { + // 同一天内 + minutesToTarget = targetTotalMinutes - currentTotalMinutes; + } else { + // 跨天情况(目标时间是第二天) + minutesToTarget = (24 * 60 - currentTotalMinutes) + targetTotalMinutes; + } + + // 如果距离目标时间不足10分钟,返回false表示应该退出 + if (minutesToTarget <= 10 && minutesToTarget >= 0) { + log.warn(`当前时间 ${currentHour}:${currentMinute.toString().padStart(2, '0')} 距离禁止运行时间 ${targetHour}:${targetMinute.toString().padStart(2, '0')} 不足10分钟,脚本将退出`); + return false; + } + + // 如果当前时间正好在目标时间,也退出 + if (currentHour === targetHour && currentMinute === targetMinute) { + log.warn(`当前时间 ${currentHour}:${currentMinute.toString().padStart(2, '0')} 为禁止运行时间,脚本将退出`); + return false; + } + + return true; + } + /** * 逃逸函数 * 通过模拟点击操作来防止被活动捕捉,执行一系列点击动作后返回主界面 * @returns {Promise} 无返回值的异步函数 */ async function preventBeingcaught() { + // 解决剧情弹出页,观景点以及其他奇奇怪怪的页面,理论上都有办法逃出。长剧情无法完全退出时,在运行下一脚本前会触发bgi剧情接管 + // 因为某些问题频繁交互的场景下无法解决 const res1 = await imageRecognitionEnhanced(Pamon, 1.5, 0, 0, 39, 31, 38, 38); if (res1.found) { return; } for (let i = 0; i < 3; i++) { - click(1370, 800); + await click(1370, 800); // 尝试点击剧情对话位置 await sleep(300); - click(1370, 800); + await keyPress("ESCAPE"); // 尝试点击ESC键返回主页面 + await sleep(300); + await click(1370, 800); await sleep(300); } const res2 = await imageRecognitionEnhanced(Pamon, 1.5, 0, 0, 39, 31, 38, 38); @@ -1594,6 +1797,8 @@ async function exponentialBackoffRetry(operation, maxRetries = 5, baseDelay = 500) { for (let i = 0; i < maxRetries; i++) { try { + await click(975, 985); // 点击“复苏”(如果有),先排除全体阵亡的可能性 + await sleep(100); return await operation(); } catch (error) { if (i === maxRetries - 1) throw error; @@ -1621,31 +1826,6 @@ } } - // 获取当前账户id - async function getCurrentUsername() { - let userName; - try { - if (!settings.userName) { - await genshin.returnMainUi(); - const texts = await textOCR("", 0.3, 0, 2, 1750, 1050, 135, 30); - if (texts && texts.found) { - userName = texts.text; - } else { - userName = "默认账户"; - } - } else { - userName = settings.userName; - } - - log.info("当前用户:" + userName); - await genshin.returnMainUi(); - return userName; - } catch (e) { - log.error(`获取用户名失败: ${e.message}`); - return "默认账户"; - } - } - // 寻路函数 async function AutoPath(locationName) { try { @@ -1840,7 +2020,7 @@ await sleep(800); inputText(foodCount[i]); log.info(`尝试制作${Foods[i]} ${foodCount[i]}个`); - log.info("由于受到队列和背包食材数量限制,实际制作数量与上述数量可能不一致!"); + log.warn("由于受到队列和背包食材数量限制,实际制作数量与上述数量可能不一致!"); await sleep(800); click(1190, 755); await sleep(800); @@ -2112,8 +2292,15 @@ await switchPartyIfNeeded(CaiJiPartyName); - // 启用自动拾取 - dispatcher.addTimer(new RealtimeTimer("AutoPick")); + // 获取炉子位置 + if (ifingredientProcessing) { + try { + stovePosition = await getLastPositionCoords(`assets/${stove}.json`); + } catch (error) { + log.warn(`获取炉子坐标失败: ${error.message}`); + stovePosition = null; + } + } const countrys = await executeRegions(); // 筛选要运行的国家 const jsonCount = countJsonFiles(countrys); // 统计JSON文件数 @@ -2166,8 +2353,12 @@ } catch (error) { // 伪造错误结束记录 await fakeLog("AotoTeyvatFoodOneDragon", true, false, 0); - log.error("任务执行失败:" + error.message); - notification.error("任务执行失败:" + error.message); + + if (error.message != "Exit time reached.") { + notification.error("任务中断:" + error.message); + } + + log.error("任务中断:" + error.message); return; } })(); \ No newline at end of file diff --git a/repo/js/AotoTeyvatFoodOneDragon/manifest.json b/repo/js/AotoTeyvatFoodOneDragon/manifest.json index 0e6bc6ffc..0cfc9b651 100644 --- a/repo/js/AotoTeyvatFoodOneDragon/manifest.json +++ b/repo/js/AotoTeyvatFoodOneDragon/manifest.json @@ -1,9 +1,14 @@ { "manifest_version": 1, "name": "提瓦特食材一条龙", - "version": "1.0", + "version": "1.1", "bgi_version": "0.49.0", - "description": "提瓦特食材一条龙,原厨玩家自己的js(bushi)!", + "description": "提瓦特食材一条龙,原厨玩家自己的js(bushi)!请阅读readme后使用!", + "tags": [ + "食材", + "原厨", + "食材加工" + ], "authors": [ { "name": "MissDan", diff --git a/repo/js/AotoTeyvatFoodOneDragon/settings.json b/repo/js/AotoTeyvatFoodOneDragon/settings.json index 6abe9c38d..ad1a58315 100644 --- a/repo/js/AotoTeyvatFoodOneDragon/settings.json +++ b/repo/js/AotoTeyvatFoodOneDragon/settings.json @@ -139,7 +139,7 @@ { "name": "ifCheck", "type": "select", - "label": "是否查询收益\n此功能对性能有一定的要求,并且会增加脚本耗时", + "label": "是否查询收益(测试功能)", "options": [ "不查询收益", "查询所有收益", @@ -148,13 +148,18 @@ "default": "不查询收益" }, { - "name": "userName", + "name": "exitTime", "type": "input-text", - "label": "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n账户名称(选填)" + "label": "不运行的时间\n仅支持单一时间点,支持指定到分钟,请使用24小时制,如:04:00" }, { "name": "notify", "type": "checkbox", "label": "是否发送js通知" + }, + { + "name": "userName", + "type": "input-text", + "label": "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n账户名称(选填)" } ] \ No newline at end of file