js:联机团购,锄地一条龙,采集cd管理 (#2991)

* 联机团购

修复放人问题

* 锄地一条龙

1.增加二次识别,默认开启,可禁用
2.增加限定材料识别范围,默认禁用

* 采集cd管理

增加二次识别,默认开启,可禁用
This commit is contained in:
mno
2026-03-14 15:25:30 +08:00
committed by GitHub
parent 906bbfe3e3
commit 022678a55e
8 changed files with 1641 additions and 17 deletions

View File

@@ -648,7 +648,6 @@ async function autoEnter(autoEnterSettings) {
// ===== 状态 =====
let enterCount = 0;
let targetsRo = [];
let checkToEnd = false;
let enteredPlayers = [];
// ===== 初始化 =====
@@ -668,7 +667,7 @@ async function autoEnter(autoEnterSettings) {
// ===== 主循环 =====
const totalTime = timeout * 60 * 1000;
let checkPoints = [false, false, false]; // 使用数组标记检查状态,分别对应30%、50%、70%时间点
let checkPoints = [false, false, false, false, false]; // 使用数组标记检查状态,分别对应20%、40%、60%、80%、90%时间点
while (new Date() - start < totalTime) {
if (enterMode === "进入他人世界") {
const playerSign = await getPlayerSign();
@@ -717,18 +716,18 @@ async function autoEnter(autoEnterSettings) {
// 检查时间点,触发额外检测
const elapsed = new Date() - start;
const timePoints = [0.3, 0.5, 0.7];
const timePoints = [0.2, 0.4, 0.6, 0.8, 0.9];
for (let i = 0; i < timePoints.length; i++) {
const point = timePoints[i];
if (!checkPoints[i] && elapsed >= totalTime * point) {
checkPoints[i] = true;
log.info(`达到超时时间的 ${point * 100}%,额外进行一次检测`);
enterCount = maxEnterCount;
enterCount = maxEnterCount; // 强制触发检测
break;
}
}
if (enterCount >= maxEnterCount) break;
// 继续执行,不在这里结束循环,由统一检查部分处理
if (await isYUI()) keyPress("VK_ESCAPE"); await sleep(500);
await genshin.returnMainUi();
keyPress("Y"); await sleep(250);
@@ -767,8 +766,7 @@ async function autoEnter(autoEnterSettings) {
if (await isYUI()) { keyPress("VK_ESCAPE"); await genshin.returnMainUi(); }
if (enterCount >= maxEnterCount || checkToEnd) {
checkToEnd = true;
if (enterCount >= maxEnterCount) {
await sleep(20000);
if (await findTotalNumber() === maxEnterCount + 1) {
notification.send(`已达到预定人数:${maxEnterCount + 1}`);

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "AAA狗粮联机团购",
"version": "1.14.0",
"version": "1.14.1",
"tags": [
"狗粮"
],

File diff suppressed because it is too large Load Diff

View File

@@ -54,6 +54,7 @@ let pathings;
let localeWorks;
let lastEatBuff = 0;
let currentFood = "";
let monsterInfoObject;
(async function () {
//通用预处理
@@ -278,7 +279,7 @@ async function rotateWarnIfAccountEmpty() {
async function processPathings(groupTags) {
// 读取怪物信息
const monsterInfoContent = await file.readText("assets/monsterInfo.json");
const monsterInfoObject = JSON.parse(monsterInfoContent);
monsterInfoObject = JSON.parse(monsterInfoContent);
// 读取路径文件夹中的所有文件
log.info("开始读取路径文件");
@@ -1031,9 +1032,9 @@ async function runPath(fullPath, map_name, pm, pe) {
}
/* ===== 2. 重排 targetItems当前路线拾取过的提前 ===== */
const history = {};
if (targetItems && currentPathing && currentPathing.items && currentPathing.items.length) {
// 用对象当 Set 做 O(1) 查询
const history = {};
for (let i = 0; i < currentPathing.items.length; i++) {
history[currentPathing.items[i]] = true;
}
@@ -1045,6 +1046,48 @@ async function runPath(fullPath, map_name, pm, pe) {
});
}
/* ===== 2.1 处理 onlyRelatedItems 配置 ===== */
if (settings.onlyRelatedItems && currentPathing && currentPathing.monsterInfo) {
// 首先将所有图片的 enabled 记为 true
for (const it of targetItems) {
it.enabled = true;
}
// 将所有的怪物材料图片的 enabled 记为 false
for (const it of targetItems) {
if (it.isMonsterMaterial) {
it.enabled = false;
}
}
// 根据当前路线包含的怪物类型,找出这些怪物的 item 合并后去重
const monsterItems = new Set();
for (const [monsterName, count] of Object.entries(currentPathing.monsterInfo)) {
const monster = monsterInfoObject.find(m => m.name === monsterName);
if (monster && monster.item && monster.item.length > 0) {
monster.item.forEach(itemName => monsterItems.add(itemName));
}
}
// 将结果数组与图片的 itemName 进行对比,如果纯中文部分相同,则说明需要启用该怪物材料
for (const it of targetItems) {
if (it.isMonsterMaterial) {
const cnPart = it.itemName.replace(/[^\u4e00-\u9fa5]/g, '');
for (const monsterItem of monsterItems) {
const monsterCnPart = monsterItem.replace(/[^\u4e00-\u9fa5]/g, '');
if (cnPart === monsterCnPart) {
it.enabled = true;
break;
}
}
// 特别的,如果在历史中命中过,也视为相关,也改为 true
if (history[it.itemName]) {
it.enabled = true;
}
}
}
}
/* ===== 3. 原逻辑不变 ===== */
state = { running: true, currentPathing: currentPathing };
/* ---------- 主任务 ---------- */
@@ -1280,10 +1323,7 @@ async function recognizeAndInteract() {
let foundTarget = false;
if (pickup_Mode.includes("模板匹配")) {
let time1 = new Date();
itemName = await performTemplateMatch(centerYF);
let time2 = new Date();
//log.info(`调试-本次识别用时${time2 - time1}毫秒`);
}
if (itemName) {
//log.info(`调试-识别到物品${itemName}`);
@@ -1341,16 +1381,34 @@ async function recognizeAndInteract() {
}
try {
let firstMatch = null;
for (const it of targetItems) {
if (!it.enabled) continue;
const cnLen = Math.min(
[...it.itemName].filter(c => c >= '\u4e00' && c <= '\u9fff').length,
5
); // 0-5
if (regions[cnLen].find(it.roi).isExist()) {
return it.itemName;
firstMatch = it;
break;
}
}
if (!firstMatch) return null;
if (!settings.disableSecondCheck) {
const cnLen = Math.min(
[...firstMatch.itemName].filter(c => c >= '\u4e00' && c <= '\u9fff').length,
5
);
if (regions[cnLen].find(firstMatch.roi).isExist()) {
return firstMatch.itemName;
}
return null;
} else {
return firstMatch.itemName;
}
} catch (e) {
log.error(`performTemplateMatch: ${e.message}`);
} finally {
@@ -1969,6 +2027,8 @@ async function loadTargetItems() {
it.template = file.ReadImageMatSync(it.fullPath);
it.itemName = it.fileName.replace(/\.png$/i, '');
it.roi = RecognitionObject.TemplateMatch(it.template);
it.enabled = true;
it.isMonsterMaterial = it.fullPath.includes('怪物掉落材料');
// 新增:解析括号中的阈值
const match = it.fullPath.match(/[(](.*?)[)]/); // 匹配英文或中文括号

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "锄地一条龙",
"version": "2.5.6",
"version": "2.6.0",
"description": "一站式解决自动化锄地支持只拾取狗粮请仔细阅读README.md后使用",
"authors": [
{

View File

@@ -57,6 +57,18 @@
],
"default": "模板匹配拾取,拾取狗粮和怪物材料"
},
{
"name": "onlyRelatedItems",
"type": "checkbox",
"label": "只使用路线相关怪物材料进行识别,提高性能\n仅在选择模板匹配拾取拾取狗粮和怪物材料时生效\n推荐先不勾选运行一段时间获取历史数据后勾选",
"default": false
},
{
"name": "disableSecondCheck",
"type": "checkbox",
"label": "禁用识别到物品后的二次校验,可能增加误捡概率",
"default": false
},
{
"name": "activeDumperMode",
"type": "input-text",

View File

@@ -233,6 +233,7 @@ async function performTemplateMatch(centerYF) {
}
try {
let firstMatch = null;
for (const it of targetItems) {
const cnLen = Math.min(
[...it.itemName].filter(c => c >= '\u4e00' && c <= '\u9fff').length,
@@ -240,9 +241,25 @@ async function performTemplateMatch(centerYF) {
); // 0-5
if (regions[cnLen].find(it.roi).isExist()) {
return it.itemName;
firstMatch = it;
break;
}
}
if (!firstMatch) return null;
if (!settings.disableSecondCheck) {
const cnLen = Math.min(
[...firstMatch.itemName].filter(c => c >= '\u4e00' && c <= '\u9fff').length,
5
);
if (regions[cnLen].find(firstMatch.roi).isExist()) {
return firstMatch.itemName;
}
return null;
} else {
return firstMatch.itemName;
}
} catch (e) {
log.error(`performTemplateMatch: ${e.message}`);
} finally {
@@ -1938,6 +1955,12 @@ async function buildSettingsJson() {
"尽量调为夜晚"
],
"default": "不调节时间"
},
{
"name": "disableSecondCheck",
"type": "checkbox",
"label": "禁用识别到物品后的二次校验,可能增加误捡概率",
"default": false
}
);

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "采集cd管理",
"version": "2.12.1",
"version": "2.13.0",
"bgi_version": "0.44.8",
"description": "仅面对会操作文件和读readme的用户基于文件夹操作自动管理采集路线的cd会按照路径组的顺序依次运行直到指定的时间并会按照给定的cd类型自动跳过未刷新的路线",
"saved_files": [