一些js更新 (#890)

* 一些js更新

* Update repo/js/自动小怪锄地规划/main.js

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update repo/js/自动精英锄地规划/main.js

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
mno
2025-05-20 23:43:14 +08:00
committed by GitHub
parent 6a5f7b2587
commit 64610ae0eb
11 changed files with 588 additions and 141 deletions

View File

@@ -0,0 +1,114 @@
// fakeLog 函数,使用方法:将本函数放在主函数前,调用时请务必使用await否则可能出现v8白框报错
//在js开头处伪造该js结束运行的日志信息如 await fakeLog("js脚本", true, true, 0);
//在js结尾处伪造该js开始运行的日志信息如 await fakeLog("js脚本", true, false, 2333);
//duration项目仅在伪造结束信息时有效且无实际作用可以任意填写当你需要在日志中输出特定值时才需要单位为毫秒
//在调用地图追踪前伪造该地图追踪开始运行的日志信息,如 await fakeLog(`地图追踪.json`, false, true, 0);
//在调用地图追踪后伪造该地图追踪结束运行的日志信息,如 await fakeLog(`地图追踪.json`, false, false, 0);
//如此便可以在js运行过程中伪造地图追踪的日志信息可以在日志分析等中查看
async function fakeLog(name, isJs, isStart, duration) {
await sleep(10);
const currentTime = Date.now();
// 参数检查
if (typeof name !== 'string') {
log.error("参数 'name' 必须是字符串类型!");
return;
}
if (typeof isJs !== 'boolean') {
log.error("参数 'isJs' 必须是布尔型!");
return;
}
if (typeof isStart !== 'boolean') {
log.error("参数 'isStart' 必须是布尔型!");
return;
}
if (typeof currentTime !== 'number' || !Number.isInteger(currentTime)) {
log.error("参数 'currentTime' 必须是整数!");
return;
}
if (typeof duration !== 'number' || !Number.isInteger(duration)) {
log.error("参数 'duration' 必须是整数!");
return;
}
// 将 currentTime 转换为 Date 对象并格式化为 HH:mm:ss.sss
const date = new Date(currentTime);
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
const milliseconds = String(date.getMilliseconds()).padStart(3, '0');
const formattedTime = `${hours}:${minutes}:${seconds}.${milliseconds}`;
// 将 duration 转换为分钟和秒,并保留三位小数
const durationInSeconds = duration / 1000; // 转换为秒
const durationMinutes = Math.floor(durationInSeconds / 60);
const durationSeconds = (durationInSeconds % 60).toFixed(3); // 保留三位小数
// 使用四个独立的 if 语句处理四种情况
if (isJs && isStart) {
// 处理 isJs = true 且 isStart = true 的情况
const logMessage = `正在伪造js开始的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 开始执行JS脚本: "${name}"`;
log.info(logMessage);
}
if (isJs && !isStart) {
// 处理 isJs = true 且 isStart = false 的情况
const logMessage = `正在伪造js结束的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------`;
log.info(logMessage);
}
if (!isJs && isStart) {
// 处理 isJs = false 且 isStart = true 的情况
const logMessage = `正在伪造地图追踪开始的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 开始执行地图追踪任务: "${name}"`;
log.info(logMessage);
}
if (!isJs && !isStart) {
// 处理 isJs = false 且 isStart = false 的情况
const logMessage = `正在伪造地图追踪结束的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------`;
log.info(logMessage);
}
}
// 主函数,用于示例该函数的使用
async function main() {
// 定义变量
const name1 = "伪造日志测试";
const name2 = "伪造地图追踪.json";
// 调用 fakeLog 函数,输出 JavaScript 的结尾日志,耗时 1.234 秒
const duration1 = 1234; // 1.234 秒
await fakeLog(name1, true, false, duration1);
// 输出地图追踪开始的日志
const duration2 = 0; // 地图追踪开始时,耗时为 0
await fakeLog(name2, false, true, duration2);
// 等待5秒
await sleep(5000);
log.info('模拟地图追踪运行完成')
// 调用 fakeLog 函数,输出地图追踪结束的日志,耗时 5.000 秒
const duration3 = 5000; // 5.000 秒
await fakeLog(name2, false, false, duration3);
// 调用 fakeLog 函数,输出 JavaScript 开始的日志
const duration4 = 0; // JS 开始时,耗时为 0
await fakeLog(name1, true, true, duration4);
}
// 调用主函数
main();

View File

@@ -0,0 +1,14 @@
{
"manifest_version": 1,
"name": "伪造日志测试",
"version": "1.0",
"bgi_version": "0.44.0",
"description": "",
"authors": [
{
"name": "mno"
}
],
"settings_ui": "settings.json",
"main": "main.js"
}

View File

@@ -0,0 +1,59 @@
[
{
"name": "operationType",
"type": "select",
"label": "操作模式(默认:生成路径组文件)",
"options": [
"生成路径组文件",
"执行路径组文件1",
"执行路径组文件2",
"执行路径组文件3",
"输出地图追踪文件"
]
},
{
"name": "excludeTagsForPathGroup1",
"type": "input-text",
"label": "路径组1要排除的标签传奇水免次数盾或高危"
},
{
"name": "selectTagsForPathGroup2",
"type": "input-text",
"label": "路径组2要选择的标签传奇水免次数盾或高危"
},
{
"name": "selectTagsForPathGroup3",
"type": "input-text",
"label": "路径组3要选择的标签传奇水免次数盾或高危"
},
{
"name": "disableAutoPickup",
"type": "checkbox",
"label": "是否禁用自动拾取(默认不禁用)"
},
{
"name": "disableRouteCdCheck",
"type": "checkbox",
"label": "是否禁用路线CD检测默认不禁用"
},
{
"name": "requiredMonsterCount",
"type": "input-text",
"label": "目标怪物数量默认405必须为0以上整数"
},
{
"name": "minSecPerMonster",
"type": "input-text",
"label": "最低秒均(秒均=摩拉/时间默认0.1"
},
{
"name": "excludeTagsForAll",
"type": "input-text",
"label": "全局排除关键词(使用中文分号分隔)"
},
{
"name": "accountName",
"type": "input-text",
"label": "账户名,用于区分不同的账户"
}
]

View File

@@ -1,11 +1,93 @@
// fakeLog 函数,使用方法:将本函数放在主函数前,调用时请务必使用await否则可能出现v8白框报错
//在js开头处伪造该js结束运行的日志信息如 await fakeLog("js脚本", true, true, 0);
//在js结尾处伪造该js开始运行的日志信息如 await fakeLog("js脚本", true, false, 2333);
//duration项目仅在伪造结束信息时有效且无实际作用可以任意填写当你需要在日志中输出特定值时才需要单位为毫秒
//在调用地图追踪前伪造该地图追踪开始运行的日志信息,如 await fakeLog(`地图追踪.json`, false, true, 0);
//在调用地图追踪后伪造该地图追踪结束运行的日志信息,如 await fakeLog(`地图追踪.json`, false, false, 0);
//如此便可以在js运行过程中伪造地图追踪的日志信息可以在日志分析等中查看
async function fakeLog(name, isJs, isStart, duration) {
await sleep(10);
const currentTime = Date.now();
// 参数检查
if (typeof name !== 'string') {
log.error("参数 'name' 必须是字符串类型!");
return;
}
if (typeof isJs !== 'boolean') {
log.error("参数 'isJs' 必须是布尔型!");
return;
}
if (typeof isStart !== 'boolean') {
log.error("参数 'isStart' 必须是布尔型!");
return;
}
if (typeof currentTime !== 'number' || !Number.isInteger(currentTime)) {
log.error("参数 'currentTime' 必须是整数!");
return;
}
if (typeof duration !== 'number' || !Number.isInteger(duration)) {
log.error("参数 'duration' 必须是整数!");
return;
}
// 将 currentTime 转换为 Date 对象并格式化为 HH:mm:ss.sss
const date = new Date(currentTime);
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
const milliseconds = String(date.getMilliseconds()).padStart(3, '0');
const formattedTime = `${hours}:${minutes}:${seconds}.${milliseconds}`;
// 将 duration 转换为分钟和秒,并保留三位小数
const durationInSeconds = duration / 1000; // 转换为秒
const durationMinutes = Math.floor(durationInSeconds / 60);
const durationSeconds = (durationInSeconds % 60).toFixed(3); // 保留三位小数
// 使用四个独立的 if 语句处理四种情况
if (isJs && isStart) {
// 处理 isJs = true 且 isStart = true 的情况
const logMessage = `正在伪造js开始的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 开始执行JS脚本: "${name}"`;
log.info(logMessage);
}
if (isJs && !isStart) {
// 处理 isJs = true 且 isStart = false 的情况
const logMessage = `正在伪造js结束的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------`;
log.info(logMessage);
}
if (!isJs && isStart) {
// 处理 isJs = false 且 isStart = true 的情况
const logMessage = `正在伪造地图追踪开始的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 开始执行地图追踪任务: "${name}"`;
log.info(logMessage);
}
if (!isJs && !isStart) {
// 处理 isJs = false 且 isStart = false 的情况
const logMessage = `正在伪造地图追踪结束的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------`;
log.info(logMessage);
}
}
(async function () {
// 定义六个运行时变量,初始值分别为 2000、1000、0、0、0、0
let runtime1 = 2000;
let runtime2 = 1000;
let runtime3 = 0;
let runtime4 = 0;
let runtime5 = 0;
let runtime6 = 0;
//伪造js结束的日志记录
await fakeLog("消耗复活料理", true, false, 2333);
// 从 settings 中获取最大循环次数,如果未配置则默认为 2000
const maxLoopCount = parseInt(settings.maxLoopCount || 2000, 10);
@@ -35,24 +117,6 @@
const currentHour = now.getHours(); // 获取当前时间的小时数
const currentTime = now.toLocaleString(); // 获取完整的当前时间字符串
// 更新 runtime 变量
runtime6 = runtime5;
runtime5 = runtime4;
runtime4 = runtime3;
runtime3 = runtime2;
runtime2 = runtime1;
runtime1 = now.getTime();
// 检查时间差条件
if ((runtime1 - runtime2) < 500 &&
(runtime2 - runtime3) < 500 &&
(runtime3 - runtime4) < 500 &&
(runtime4 - runtime5) < 500 &&
(runtime5 - runtime6) < 500) {
log.info(`连续五次时间差小于 500 毫秒,循环终止。`);
break; // 如果连续五次时间差小于 500 毫秒,退出循环
}
// 如果当前时间的小时数与排除时间相同,则退出循环
if (currentHour === excludeHour) {
log.info(`当前时间是 ${currentTime},与排除时间小时数相同,将退出循环`);
@@ -62,7 +126,24 @@
// 记录当前时间
log.info(`正在执行循环第 ${i + 1} 次,总共 ${maxLoopCount} 次,当前时间: ${currentTime}`);
await fakeLog(`${i + 1}次信仰之跃.json`, false, true, 0);
// 运行路径追踪任务
await pathingScript.runFile(pathFileName);
await fakeLog(`${i + 1}次信仰之跃.json`, false, false, 0);
//捕获任务结束的信息同时等待95秒用来卡时间
try {
log.info('正在等待复活料理cd')
await sleep(95000);
} catch (error) {
log.error(`发生错误: ${error}`);
break; // 终止循环
}
}
//伪造一个js开始的日志记录
await fakeLog("消耗复活料理", true, true, 0);
})();

View File

@@ -1,8 +1,8 @@
{
"manifest_version": 1,
"name": "消耗复活料理@mno",
"version": "1.0",
"description": "通过信仰之跃消耗放在食品袋中的复活料理,注意,使用前请确保要消耗的复活料理在食品袋中并且装备食品袋小道具,目前存在一个已知的bug导致结束配置组时将花费过长的时间建议直接关闭bgi程序来关闭本配置组",
"name": "消耗复活料理",
"version": "1.1",
"description": "通过信仰之跃消耗放在食品袋中的复活料理,注意,使用前请确保要消耗的复活料理在食品袋中并且装备食品袋小道具,并且不要开启行走位,生存位等配置,也不要开启循环使用小道具",
"authors": [
{
"name": "mno"

View File

@@ -13,29 +13,38 @@
"id": 1,
"x": 508.03515625,
"y": -630.49072265625,
"type": "teleport",
"move_mode": "walk",
"action": "",
"action_params": ""
},
{
"id": 2,
"x": 499.87890625,
"y": -686.18310546875,
"type": "path",
"move_mode": "fly",
"action": "stop_flying",
"action_params": "10000",
"move_mode": "walk",
"action_params": "",
"type": "teleport",
"locked": false
},
{
"id": 2,
"x": 508.03515625,
"y": -630.49072265625,
"action": "combat_script",
"move_mode": "walk",
"action_params": "keypress(1)",
"type": "path"
},
{
"id": 3,
"x": 499.87890625,
"y": -686.18310546875,
"action": "stop_flying",
"move_mode": "fly",
"action_params": "10000",
"type": "path"
},
{
"id": 4,
"x": 501.3095703125,
"y": -683.6240234375,
"type": "path",
"move_mode": "walk",
"action": "combat_script",
"action_params": "keypress(z),wait(5),keypress(1),wait(90)"
"move_mode": "walk",
"action_params": "keypress(z)",
"type": "path"
}
]
}

View File

@@ -1,3 +1,89 @@
// fakeLog 函数,使用方法:将本函数放在主函数前,调用时请务必使用await否则可能出现v8白框报错
//在js开头处伪造该js结束运行的日志信息如 await fakeLog("js脚本", true, true, 0);
//在js结尾处伪造该js开始运行的日志信息如 await fakeLog("js脚本", true, false, 2333);(可以不加)
//duration项目仅在伪造结束信息时有效且无实际作用可以任意填写当你需要在日志中输出特定值时才需要单位为毫秒
//在调用地图追踪前伪造该地图追踪开始运行的日志信息,如 await fakeLog(`地图追踪.json`, false, true, 0);
//在调用地图追踪后伪造该地图追踪结束运行的日志信息,如 await fakeLog(`地图追踪.json`, false, false, 0);
//如此便可以在js运行过程中伪造地图追踪的日志信息可以在日志分析等中查看
async function fakeLog(name, isJs, isStart, duration) {
await sleep(10);
const currentTime = Date.now();
// 参数检查
if (typeof name !== 'string') {
log.error("参数 'name' 必须是字符串类型!");
return;
}
if (typeof isJs !== 'boolean') {
log.error("参数 'isJs' 必须是布尔型!");
return;
}
if (typeof isStart !== 'boolean') {
log.error("参数 'isStart' 必须是布尔型!");
return;
}
if (typeof currentTime !== 'number' || !Number.isInteger(currentTime)) {
log.error("参数 'currentTime' 必须是整数!");
return;
}
if (typeof duration !== 'number' || !Number.isInteger(duration)) {
log.error("参数 'duration' 必须是整数!");
return;
}
// 将 currentTime 转换为 Date 对象并格式化为 HH:mm:ss.sss
const date = new Date(currentTime);
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
const milliseconds = String(date.getMilliseconds()).padStart(3, '0');
const formattedTime = `${hours}:${minutes}:${seconds}.${milliseconds}`;
// 将 duration 转换为分钟和秒,并保留三位小数
const durationInSeconds = duration / 1000; // 转换为秒
const durationMinutes = Math.floor(durationInSeconds / 60);
const durationSeconds = (durationInSeconds % 60).toFixed(3); // 保留三位小数
// 使用四个独立的 if 语句处理四种情况
if (isJs && isStart) {
// 处理 isJs = true 且 isStart = true 的情况
const logMessage = `正在伪造js开始的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 开始执行JS脚本: "${name}"`;
log.info(logMessage);
}
if (isJs && !isStart) {
// 处理 isJs = true 且 isStart = false 的情况
const logMessage = `正在伪造js结束的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------`;
log.info(logMessage);
}
if (!isJs && isStart) {
// 处理 isJs = false 且 isStart = true 的情况
const logMessage = `正在伪造地图追踪开始的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 开始执行地图追踪任务: "${name}"`;
log.info(logMessage);
}
if (!isJs && !isStart) {
// 处理 isJs = false 且 isStart = false 的情况
const logMessage = `正在伪造地图追踪结束的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------`;
log.info(logMessage);
}
}
(async function () {
// 初始化所有用到的参数
const operationMode = settings.operationMode || "生成路径文件"; // 默认值为“生成路径文件”
@@ -11,6 +97,11 @@
const pathingDir = 'pathing/'; // 初始化pathingDir参数
const enableCooldownCheck = !disableCooldownCheck; // 如果 disableCooldownCheck 未设置或为 false则 enableCooldownCheck 为 true
// 初始化全局排除关键词配置
let globalExclusionKeywords = settings.globalExclusionKeywords || "不跑"; // 默认为不跑
const exclusionKeywordsArray = globalExclusionKeywords.split("").map(keyword => keyword.trim()).filter(Boolean); // 使用中文分号分隔,并去除空格和空字符串
// 初始化用于计数的变量
let outputFolderName = accountName; // 初始化为空
let totalMonsterCount = 0; // 筛选出的怪物总数
@@ -19,15 +110,6 @@
let failCount = 0; // 失败复制的文件数量
let routeIndex = 0; // 当前筛选的路线序号
// 定义六个运行时变量,初始值分别为 2000、1000、0、0、0、0
let runtime1 = 2000;
let runtime2 = 1000;
let runtime3 = 0;
let runtime4 = 0;
let runtime5 = 0;
let runtime6 = 0;
// 日志输出配置参数
log.info(
`自动小怪锄地规划 - 配置信息:` +
@@ -41,6 +123,9 @@
`账户名=${accountName}`
);
// 在日志中输出全局排除关键词配置信息
log.info(`全局排除关键词=${globalExclusionKeywords ? exclusionKeywordsArray.join("") : "无"}`);
// 检查是否所有配置都是默认状态
const isDefaultConfig = (
operationMode === "生成路径文件" &&
@@ -82,6 +167,8 @@
// 判断操作模式是否为“执行路径文件”,若是则执行路径文件
if (operationMode === "执行路径文件") {
try {
//伪造js已经结束的记录
await fakeLog("自动小怪锄地规划", true, false, 1);
// 定义路径组文件的路径,使用 outputFolderName
const pathGroupFilePath = `route/${outputFolderName}.txt`;
@@ -90,45 +177,43 @@
for (let i = 0; i < savedRoutes.length; i++) {
const routeWithTimestamp = savedRoutes[i].trim();
const [routeName, routeTimestamp] = routeWithTimestamp.split('::');
log.info(`当前任务为第 ${i + 1}/${savedRoutes.length}`);
log.info(`当前进度:${routeName}为第 ${i + 1}/${savedRoutes.length}`);
const now = new Date(); // 获取开始时间
const startTime = now.toISOString();
// 更新 runtime 变量
runtime6 = runtime5;
runtime5 = runtime4;
runtime4 = runtime3;
runtime3 = runtime2;
runtime2 = runtime1;
runtime1 = now.getTime();
// 检查时间差条件
if ((runtime1 - runtime2) < 500 &&
(runtime2 - runtime3) < 500 &&
(runtime3 - runtime4) < 500 &&
(runtime4 - runtime5) < 500 &&
(runtime5 - runtime6) < 500) {
log.info(`连续五次时间差小于 500 毫秒,循环终止。`);
break; // 如果连续五次时间差小于 500 毫秒,退出循环
}
if (enableCooldownCheck && startTime < routeTimestamp) {
log.info(`当前路线 ${routeName} 未刷新,跳过任务`);
await sleep(500);
await sleep(10);
continue; // 跳过当前循环
}
log.info(`当前路线 ${routeName} 已刷新或未启用CD检测执行任务`);
// 拼接路径文件的完整路径
const pathingFilePath = `pathing/${routeName}.json`;
//伪造地图追踪开始的日志记录
await fakeLog(routeName + ".json", false, true, 0); // 开始时 duration 通常为 0
// 执行路径文件
await pathingScript.runFile(pathingFilePath);
// 如果启用了CD检测获取结束时间并判断时间差
const endTime = new Date(); // 获取结束时间
const timeDiff = endTime - now; // 计算时间差(单位:毫秒)
//伪造地图追踪结束的日志记录
await fakeLog(routeName + ".json", false, false, timeDiff);
//尝试捕获任务取消的错误,捕获后终止循环
try {
await sleep(10);
} catch (error) {
log.error(`发生错误: ${error}`);
return; // 终止循环
}
// 如果启用了CD检测
if (enableCooldownCheck) {
const endTime = new Date(); // 获取结束时间
const timeDiff = endTime - now; // 计算时间差(单位:毫秒)
if (timeDiff > 10000) { // 如果时间差大于10秒10000毫秒
if (timeDiff > 3000) { // 如果时间差大于3秒3000毫秒
// 计算新的时间戳增加12小时
const newTimestamp = new Date(startTime).getTime() + 12 * 60 * 60 * 1000;
const formattedNewTimestamp = new Date(newTimestamp).toISOString();
@@ -148,6 +233,10 @@
} catch (error) {
log.error(`读取或写入路径组文件时出错: ${error}`);
}
//伪造一个js开始的记录实际上没必要
//await fakeLog("自动精英锄地规划", true, true, 0);
return;
}
// 筛选、排序并选取路线
@@ -173,13 +262,14 @@
for (const route of sortedPathingFiles) {
routeIndex++; // 每次循环时递增
const meetsKeywordCondition = exclusionKeywordsArray.every(keyword => !route.name.toLowerCase().includes(keyword));
const meetsWaterFreeCondition = !excludeWaterFree || !route.isWaterFree;
const meetsHighRiskCondition = !excludeHighRisk || !route.isHighRisk;
// 修改后的日志输出,增加当前路线的序号
//log.debug(`筛选路线 ${routeIndex}${route.name}):水免条件 ${meetsWaterFreeCondition},高危条件 ${meetsHighRiskCondition}`);
log.debug(`筛选路线 ${routeIndex}${route.name}):关键词条件 ${meetsKeywordCondition},水免条件 ${meetsWaterFreeCondition},高危条件 ${meetsHighRiskCondition}`);
if (meetsWaterFreeCondition && meetsHighRiskCondition) {
if (meetsKeywordCondition && meetsWaterFreeCondition && meetsHighRiskCondition) {
totalMonsterCount += route.monsterCount;
route.selected = 1;
selectedRoutes.push(route.name);
@@ -187,6 +277,7 @@
}
}
if (totalMonsterCount < requiredMonsterCount) {
log.warn(`数量不足,最多可以包含 ${totalMonsterCount} 只怪物,不满足所需的 ${requiredMonsterCount} 只怪物`);
}

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "自动小怪锄地规划",
"version": "1.0",
"version": "1.1",
"bgi_version": "0.44.0",
"description": "该脚本支持根据用户配置生成路径组文件、运行路径组或输出地图追踪文件。用户可以通过自定义配置设置所需怪物数量、筛选条件如是否排除水免路线或高危路线以及效率计算权重。脚本会根据这些条件自动筛选出符合条件的路线此外支持刷新cd检测启用后未刷新的路线在运行时将被跳过。注意第一次使用时要先生成路径组文件后再执行路径组文件之后的每次运行无需再次生成路径组文件将根据自定义配置中的内容自动寻找对应的路径组文件当你需要强制刷新cd或更改筛选条件时可以重新生成路径组文件",
"authors": [

View File

@@ -43,5 +43,11 @@
"name": "accountName",
"type": "input-text",
"label": "账户名,用于区分不同账号的信息"
},
{
"name": "globalExclusionKeywords",
"type": "input-text",
"label": "全局排除关键词(用于在筛选路线时排除包含指定关键词的路线)\n使用中文分号分隔默认排除不跑",
"default": "不跑"
}
]
]

View File

@@ -1,3 +1,86 @@
// fakeLog 函数,使用方法:将本函数放在主函数前,调用时请务必使用await否则可能出现v8白框报错
//在js开头处伪造该js结束运行的日志信息如 await fakeLog("js脚本", true, true, 0);
//在js结尾处伪造该js开始运行的日志信息如 await fakeLog("js脚本", true, false, 2333);
//duration项目仅在伪造结束信息时有效且无实际作用可以任意填写当你需要在日志中输出特定值时才需要单位为毫秒
//在调用地图追踪前伪造该地图追踪开始运行的日志信息,如 await fakeLog(`地图追踪.json`, false, true, 0);
//在调用地图追踪后伪造该地图追踪结束运行的日志信息,如 await fakeLog(`地图追踪.json`, false, false, 0);
//如此便可以在js运行过程中伪造地图追踪的日志信息可以在日志分析等中查看
async function fakeLog(name, isJs, isStart, duration) {
await sleep(10);
const currentTime = Date.now();
// 参数检查
if (typeof name !== 'string') {
log.error("参数 'name' 必须是字符串类型!");
return;
}
if (typeof isJs !== 'boolean') {
log.error("参数 'isJs' 必须是布尔型!");
return;
}
if (typeof isStart !== 'boolean') {
log.error("参数 'isStart' 必须是布尔型!");
return;
}
// Removed redundant type and integer checks for `currentTime`.
if (typeof duration !== 'number' || !Number.isInteger(duration)) {
log.error("参数 'duration' 必须是整数!");
return;
}
// 将 currentTime 转换为 Date 对象并格式化为 HH:mm:ss.sss
const date = new Date(currentTime);
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
const milliseconds = String(date.getMilliseconds()).padStart(3, '0');
const formattedTime = `${hours}:${minutes}:${seconds}.${milliseconds}`;
// 将 duration 转换为分钟和秒,并保留三位小数
const durationInSeconds = duration / 1000; // 转换为秒
const durationMinutes = Math.floor(durationInSeconds / 60);
const durationSeconds = (durationInSeconds % 60).toFixed(3); // 保留三位小数
// 使用四个独立的 if 语句处理四种情况
if (isJs && isStart) {
// 处理 isJs = true 且 isStart = true 的情况
const logMessage = `正在伪造js开始的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 开始执行JS脚本: "${name}"`;
log.info(logMessage);
}
if (isJs && !isStart) {
// 处理 isJs = true 且 isStart = false 的情况
const logMessage = `正在伪造js结束的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------`;
log.info(logMessage);
}
if (!isJs && isStart) {
// 处理 isJs = false 且 isStart = true 的情况
const logMessage = `正在伪造地图追踪开始的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 开始执行地图追踪任务: "${name}"`;
log.info(logMessage);
}
if (!isJs && !isStart) {
// 处理 isJs = false 且 isStart = false 的情况
const logMessage = `正在伪造地图追踪结束的日志记录\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`→ 脚本执行结束: "${name}", 耗时: ${durationMinutes}${durationSeconds}\n\n` +
`[${formattedTime}] [INF] BetterGenshinImpact.Service.ScriptService\n` +
`------------------------------`;
log.info(logMessage);
}
}
(async function () {
// 初始化配置
const operationType = settings.operationType || "生成路径组文件"; // 操作模式
@@ -24,35 +107,22 @@
// 根据 disableRouteCdCheck 的值设置 enableRouteCdCheck
const enableRouteCdCheck = !disableRouteCdCheck; // 如果 disableRouteCdCheck 为 true则 enableRouteCdCheck 为 false反之亦然
// 新增校验:检查所有配置是否都是默认状态
const defaultSettings = {
operationType: "生成路径组文件",
excludeTagsForPathGroup1: "",
selectTagsForPathGroup2: "",
selectTagsForPathGroup3: "",
disableAutoPickup: false,
disableRouteCdCheck: false,
requiredMonsterCount: 405,
minSecPerMonster: 0.1,
accountName: "一个账户名",
excludeTagsForAll: ""
};
const isAllDefault = Object.entries(defaultSettings).every(([key, defaultValue]) => {
return settings[key] === undefined || settings[key] === defaultValue;
});
if (isAllDefault) {
log.warn("所有配置项均为默认状态请检查是否需要调整配置你没有修改自定义配置请在配置组界面中右键本js以修改自定义配置。");
//当用户所有自定义配置均为默认时警告用户
if (
operationType === "生成路径组文件" &&
excludeTagsForPathGroup1 === "" &&
selectTagsForPathGroup2 === "" &&
selectTagsForPathGroup3 === "" &&
disableAutoPickup === false &&
disableRouteCdCheck === false &&
requiredMonsterCount === 405 &&
minSecPerMonster === 0.1 &&
accountName === "一个账户名" &&
excludeTagsForAll === ""
) {
log.warn("所有配置项均为默认状态请检查是否需要调整配置。你没有修改自定义配置请在配置组界面中右键本js以修改自定义配置。");
}
// 定义六个运行时变量,初始值分别为 2000、1000、0、0、0、0
let runtime1 = 2000;
let runtime2 = 1000;
let runtime3 = 0;
let runtime4 = 0;
let runtime5 = 0;
let runtime6 = 0;
// 初始化文件路径(直接内置生成)
const indexPath = 'index.txt';
@@ -94,6 +164,9 @@
log.warn("自动拾取已禁用");
}
//伪造js结束的记录
await fakeLog("自动精英锄地规划", true, false, 1);
// 根据 executePathGroupMode 获取路径组编号
const pathGroupNumber = executePathGroupMode;
@@ -116,63 +189,60 @@
const now = new Date();
const startTime = now.toISOString(); // 获取开始时间
// 更新 runtime 变量
runtime6 = runtime5;
runtime5 = runtime4;
runtime4 = runtime3;
runtime3 = runtime2;
runtime2 = runtime1;
runtime1 = now.getTime();
// 检查时间差条件
if ((runtime1 - runtime2) < 500 &&
(runtime2 - runtime3) < 500 &&
(runtime3 - runtime4) < 500 &&
(runtime4 - runtime5) < 500 &&
(runtime5 - runtime6) < 500) {
log.info(`连续五次时间差小于 500 毫秒,循环终止。`);
break; // 如果连续五次时间差小于 500 毫秒,退出循环
}
// 如果启用了路线CD检测检查当前时间是否不早于附加时间戳
if (enableRouteCdCheck) {
const pathCDDate = new Date(pathCD); // 将附加时间戳转换为Date对象
if (now < pathCDDate) {
log.info(`当前路线 ${pathName} 为第 ${i + 1}/${pathLines.length} 个,当前路线未刷新,放弃该路径`);
await sleep(500);
await sleep(10);
continue; // 放弃该路径
}
}
log.info(`当前路线 ${pathName} 为第 ${i + 1}/${pathLines.length}当前路线已刷新或未启用cd检测执行路径`);
//伪造地图追踪开始的日志记录
await fakeLog(pathName + ".json", false, true, 0); // 开始时 duration 通常为 0
// 执行路径文件
await pathingScript.runFile(pathFilePath);
//捕获任务取消的错误并跳出循环
try {
await sleep(10);
} catch (error) {
log.error(`发生错误: ${error}`);
break; // 终止循环
}
// 获取结束时间
const endTime = new Date();
const endTimeISO = endTime.toISOString(); // 获取结束时间
// 检查执行时间是否超过10
// 检查执行时间是否超过3
const executionTime = endTime.getTime() - now.getTime();
// 如果启用了CD检测且结束时间与开始时间相差超过10秒则更新附加时间戳为开始时间后的第一个凌晨四点
if (enableRouteCdCheck && executionTime > 10000) {
// 计算开始时间后的第一个晚上八点
const nextEveningEight = new Date(startTime);
nextEveningEight.setHours(4, 0, 0, 0); // 设置时间为凌晨四点0分0秒0毫秒
if (nextEveningEight <= new Date(startTime)) {
// 如果设置的时间小于等于开始时间,说明需要取下一个晚上八
nextEveningEight.setHours(4 + 24, 0, 0, 0); // 设置时间为下一个晚上八点0分0秒0毫秒
//伪造地图追踪结束的记录
await fakeLog(pathName + ".json", false, false, executionTime);
// 如果启用了CD检测且结束时间与开始时间相差超过3秒则更新附加时间戳为开始时间后的第一个凌晨四点
if (enableRouteCdCheck && executionTime > 3000) {
// 计算开始时间后的第一个凌晨四
const nextFourClock = new Date(startTime);
nextFourClock.setHours(4, 0, 0, 0); // 设置时间为凌晨四点
if (nextFourClock <= new Date(startTime)) {
// 如果设置的时间小于等于开始时间,说明需要取下一个凌晨四点
nextFourClock.setHours(4 + 24, 0, 0, 0); // 设置时间为下一个凌晨四点
}
// 转换为北京时间UTC+8
const nextEveningEightBeijing = new Date(nextEveningEight.getTime() + 8 * 3600 * 1000);
const nextEveningEightBeijingFormatted = `${nextEveningEightBeijing.getFullYear()}-${String(nextEveningEightBeijing.getMonth() + 1).padStart(2, '0')}-${String(nextEveningEightBeijing.getDate()).padStart(2, '0')} ${String(nextEveningEightBeijing.getHours()).padStart(2, '0')}:${String(nextEveningEightBeijing.getMinutes()).padStart(2, '0')}:${String(nextEveningEightBeijing.getSeconds()).padStart(2, '0')}`;
const nextFourClockBeijing = new Date(nextFourClock.getTime());
const nextFourClockFormatted = `${nextFourClockBeijing.getFullYear()}-${String(nextFourClockBeijing.getMonth() + 1).padStart(2, '0')}-${String(nextFourClockBeijing.getDate()).padStart(2, '0')} ${String(nextFourClockBeijing.getHours()).padStart(2, '0')}:${String(nextFourClockBeijing.getMinutes()).padStart(2, '0')}:${String(nextFourClockBeijing.getSeconds()).padStart(2, '0')}`;
// 更新路径组文件中的附加时间戳
pathLines[i] = `${pathName}::${nextEveningEight.toISOString()}`;
log.info(`当前路线 ${pathName} 执行完成,下一次可用时间更新为:${nextEveningEightBeijingFormatted}`);
pathLines[i] = `${pathName}::${nextFourClock.toISOString()}`;
log.info(`当前路线 ${pathName} 执行完成,可用时间更新为:${nextFourClockFormatted}`);
// 将更新后的内容写回路径组文件
const updatedPathGroupContent = pathLines.join('\n');
@@ -183,9 +253,12 @@
}
} catch (error) {
log.error(`读取路径组文件失败:${error}`);
process.exit(1); // 退出程序
return;
}
//伪造一个js开始的记录
await fakeLog("自动精英锄地规划", true, true, 0);
// 执行完成后退出程序
return;
}

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "自动精英锄地规划",
"version": "1.0",
"version": "1.1",
"bgi_version": "0.44.0",
"description": "脚本名称:自动精英锄地规划\n该脚本支持根据用户配置生成路径组文件、运行路径组或执行路径文件。用户可以通过配置文件设置所需怪物数量、筛选条件如是否包含传奇路线、水免路线、次数盾路线、高危路线以及最低秒均值。脚本还支持禁用自动拾取功能和启用路线CD检测。脚本会根据这些条件筛选出符合条件的路线并生成路径组文件或直接运行路径文件直到满足所需怪物数量。",
"authors": [