chore(js): 更新图片资源适应高分辨率 (#2721)

This commit is contained in:
Bread Grocery
2026-01-18 18:51:44 +08:00
committed by GitHub
parent 2aadd12cd3
commit c484ba8be8
12 changed files with 77 additions and 90 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 847 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 813 B

View File

@@ -1,6 +1,6 @@
import { __name } from "./rolldown-runtime.js";
//#region node_modules/.pnpm/@bettergi+utils@0.1.27/node_modules/@bettergi/utils/dist/workflow.js
//#region node_modules/@bettergi/utils/dist/workflow.js
/** 默认最大重试次数 */
const defaultMaxAttempts = 5;
/** 默认重试间隔(毫秒) */
@@ -61,7 +61,7 @@ const waitForRegionDisappear = async (regionProvider, retryAction, options) => {
};
//#endregion
//#region node_modules/.pnpm/@bettergi+utils@0.1.27/node_modules/@bettergi/utils/dist/asserts.js
//#region node_modules/@bettergi/utils/dist/asserts.js
/**
* 断言某个区域即将出现,否则抛出异常
* @param regionProvider 返回区域的函数
@@ -85,7 +85,7 @@ const assertRegionDisappearing = async (regionProvider, message, retryAction, op
};
//#endregion
//#region node_modules/.pnpm/@bettergi+utils@0.1.27/node_modules/@bettergi/utils/dist/exception.js
//#region node_modules/@bettergi/utils/dist/exception.js
/**
* 获取错误信息字符串
* @param err 异常对象
@@ -104,7 +104,7 @@ const isHostException = (err) => {
};
//#endregion
//#region node_modules/.pnpm/@bettergi+utils@0.1.27/node_modules/@bettergi/utils/dist/mouse.js
//#region node_modules/@bettergi/utils/dist/mouse.js
/** 使用回放脚本模拟滚动 */
const simulateScroll = async (wheelDelta, times) => {
const script = {
@@ -144,7 +144,10 @@ const mouseScrollDownLines = (lines, lineHeight = 175) => {
};
//#endregion
//#region node_modules/.pnpm/@bettergi+utils@0.1.27/node_modules/@bettergi/utils/dist/ocr.js
//#region node_modules/@bettergi/utils/dist/ocr.js
const scaleTo1080P = (n) => {
return genshin.scaleTo1080PRatio <= 1 ? n : Math.floor(n / genshin.scaleTo1080PRatio);
};
/**
* 在指定区域内搜索图片
* @param image 图片路径 或 图片Mat
@@ -223,31 +226,30 @@ const findTextWithinBounds = (text, x, y, w, h, options, config = {}) => {
* @param condition 查找条件
* @param listView 列表视图参数
* @param retryOptions 重试选项
* @param sampling 区域采样函数,通过采样区域画面变化判断列表是否触底(默认:底半区
* @param threshold 采样区域匹配阈值默认0.9
* @param threshold 列表视图变化匹配阈值(默认:0.9
* @returns 如果找到匹配的区域,则返回该区域,否则返回 undefined
*/
const findWithinListView = async (condition, listView, retryOptions, sampling, threshold = 0.9) => {
const findWithinListView = async (condition, listView, retryOptions, threshold = 0.9) => {
const { x, y, w, h, lineHeight, scrollLines = 1, paddingX = 10, paddingY = 10 } = listView;
const { maxAttempts = 99, retryInterval = 1200 } = retryOptions || {};
sampling ??= (r) => r.deriveCrop(1, r.height * 0.5, r.width - 1, r.height * 0.5);
const captureListViewRegion = () => captureGameRegion().deriveCrop(x, y, w, h);
const isReachedBottom = (() => {
let captured;
let lastCaptured;
return () => {
const newRegion = captureListViewRegion();
if (!newRegion?.isExist()) return true;
try {
captured = captureListViewRegion();
if (!lastCaptured) return false;
const oldRegion = sampling(lastCaptured);
if (!oldRegion?.isExist()) return true;
const ro = RecognitionObject.templateMatch(oldRegion.srcMat);
const lc = lastCaptured.deriveCrop(1, 1, lastCaptured.width - 2, lastCaptured.height - 2);
const ro = RecognitionObject.templateMatch(lc.srcMat);
ro.threshold = threshold;
ro.use3Channels = true;
ro.initTemplate();
return newRegion.find(ro)?.isExist();
return captured.find(ro).isExist();
} catch {
return true;
} finally {
lastCaptured = newRegion;
lastCaptured = captured;
}
};
})();
@@ -259,7 +261,7 @@ const findWithinListView = async (condition, listView, retryOptions, sampling, t
},
async () => {
moveMouseTo(x + w - paddingX, y + paddingY);
await sleep(50);
await sleep(200);
await mouseScrollDownLines(scrollLines, lineHeight);
},
{
@@ -269,14 +271,9 @@ const findWithinListView = async (condition, listView, retryOptions, sampling, t
);
if (targetRegion?.isExist()) {
const { item1, item2 } = targetRegion.convertPositionToGameCaptureRegion(0, 0);
const scale = genshin.width / 1920;
const [x$1, y$1] = [
Math.floor(scale <= 1 ? item1 : item1 / scale),
Math.floor(scale <= 1 ? item2 : item2 / scale),
];
Object.assign(targetRegion, {
x: x$1,
y: y$1,
x: scaleTo1080P(item1),
y: scaleTo1080P(item2),
});
return targetRegion;
}
@@ -288,8 +285,7 @@ const findWithinListView = async (condition, listView, retryOptions, sampling, t
* @param matchOptions 搜索选项
* @param retryOptions 重试选项
* @param config 识别对象配置
* @param sampling 区域采样函数,通过采样区域画面变化判断列表是否触底(默认:底半区
* @param threshold 采样区域匹配阈值默认0.9
* @param threshold 列表视图变化匹配阈值(默认:0.9
* @returns 如果找到匹配的文本区域,则返回该区域,否则返回 undefined
*/
const findTextWithinListView = async (
@@ -298,7 +294,6 @@ const findTextWithinListView = async (
matchOptions,
retryOptions,
config = {},
sampling,
threshold = 0.9,
) => {
const ro = RecognitionObject.ocrThis;
@@ -311,13 +306,12 @@ const findTextWithinListView = async (
},
listView,
retryOptions,
sampling,
threshold,
);
};
//#endregion
//#region node_modules/.pnpm/@bettergi+utils@0.1.27/node_modules/@bettergi/utils/dist/misc.js
//#region node_modules/@bettergi/utils/dist/misc.js
/**
* 深度合并多个对象
* @param objects 多个对象
@@ -335,7 +329,7 @@ const deepMerge = (...objects) => {
};
//#endregion
//#region node_modules/.pnpm/@bettergi+utils@0.1.27/node_modules/@bettergi/utils/dist/time.js
//#region node_modules/@bettergi/utils/dist/time.js
/**
* 获取下一个含当日凌晨4点的时间
*/
@@ -393,7 +387,7 @@ const formatDurationAsReadable = (duration) => {
};
//#endregion
//#region node_modules/.pnpm/@bettergi+utils@0.1.27/node_modules/@bettergi/utils/dist/progress.js
//#region node_modules/@bettergi/utils/dist/progress.js
/** 进度追踪器 */
var ProgressTracker = class {
total = 0;
@@ -466,7 +460,7 @@ var ProgressTracker = class {
};
//#endregion
//#region node_modules/.pnpm/@bettergi+utils@0.1.27/node_modules/@bettergi/utils/dist/store.js
//#region node_modules/@bettergi/utils/dist/store.js
/**
* 创建一个持久化存储对象,用于管理应用状态数据
* 该函数会创建一个代理对象对该对象的所有属性的修改都会自动同步到相应的JSON文件脚本的 `store` 目录下)中。
@@ -475,7 +469,7 @@ var ProgressTracker = class {
*/
const useStore = (name) => {
const filePath = `store/${name}.json`;
const obj = (() => {
const storeData = (() => {
try {
if (
![...file.readPathSync("store")].map((path) => path.replace(/\\/g, "/")).includes(filePath)
@@ -487,34 +481,34 @@ const useStore = (name) => {
return {};
}
})();
const createProxy = (target, parentPath = []) => {
if (typeof target !== "object" || target === null) return target;
return new Proxy(target, {
get: (target$1, key) => {
const value = Reflect.get(target$1, key);
const createProxy = (targetObject, parentPath = []) => {
if (typeof targetObject !== "object" || targetObject === null) return targetObject;
return new Proxy(targetObject, {
get: (target, key) => {
const value = Reflect.get(target, key);
return typeof value === "object" && value !== null
? createProxy(value, [...parentPath, key])
: value;
},
set: (target$1, key, value) => {
const success = Reflect.set(target$1, key, value);
set: (target, key, value) => {
const success = Reflect.set(target, key, value);
if (success)
Promise.resolve().then(() => {
file.writeTextSync(filePath, JSON.stringify(obj, null, 2));
file.writeTextSync(filePath, JSON.stringify(storeData, null, 2));
});
return success;
},
deleteProperty: (target$1, key) => {
const success = Reflect.deleteProperty(target$1, key);
deleteProperty: (target, key) => {
const success = Reflect.deleteProperty(target, key);
if (success)
Promise.resolve().then(() => {
file.writeTextSync(filePath, JSON.stringify(obj, null, 2));
file.writeTextSync(filePath, JSON.stringify(storeData, null, 2));
});
return success;
},
});
};
return createProxy(obj);
return createProxy(storeData);
};
/**
* 创建一个带有默认值的持久化存储对象,用于管理应用状态数据

View File

@@ -28,7 +28,7 @@ const findBottomBtnText = (text, contains) => {
const findCloseDialog = () => {
const iro = findImageWithinBounds("assets/UI_BtnIcon_Close.png", 410, 160, 1100, 660, {
useMask: true,
threshold: 0.7,
threshold: 0.8,
});
iro?.drawSelf("group_img");
return iro;
@@ -41,20 +41,11 @@ const clickToContinue = () => {
const findUidText = () => {
return findTextWithinBounds("UID", 1620, 1050, 300, 30, { contains: true });
};
//! 查找元素视野按钮(判断处于大世界条件一
//! 查找元素视野按钮(判断处于大世界)
const findElementViewBtn = () => {
const iro = findImageWithinBounds("assets/UI_BtnIcon_ElementView.png", 0, 0, 500, 80, {
useMask: true,
threshold: 0.85,
});
iro?.drawSelf("group_img");
return iro;
};
//! 查找推荐奇域按钮(判断处于大世界条件二)
const findBeyondRecommendBtn = () => {
const iro = findImageWithinBounds("assets/UI_BtnIcon_Beyond_Recommend.png", 960, 0, 960, 80, {
useMask: true,
threshold: 0.75,
threshold: 0.8,
});
iro?.drawSelf("group_img");
return iro;
@@ -63,7 +54,7 @@ const findBeyondRecommendBtn = () => {
const findBeyondHallBtn = () => {
const iro = findImageWithinBounds("assets/UI_BtnIcon_Beyond_Hall.png", 200, 0, 150, 100, {
useMask: true,
threshold: 0.75,
threshold: 0.8,
});
iro?.drawSelf("group_img");
return iro;
@@ -175,7 +166,8 @@ const findDeleteStageSaveBtn = () => {
//! 关卡:查找关卡退出按钮
const findStageEscBtn = () => {
const iro = findImageWithinBounds("assets/UI_Icon_Leave.png", 0, 0, 100, 100, {
threshold: 0.75,
useMask: true,
threshold: 0.8,
});
iro?.drawSelf("group_img");
return iro;
@@ -216,7 +208,7 @@ const findFetchRewardBtn = () => {
{
useMask: true,
use3Channels: true,
threshold: 0.9,
threshold: 0.8,
},
);
iro?.drawSelf("group_img");
@@ -233,7 +225,6 @@ export {
findBeyondBattlepassPopup,
findBeyondFavoritesBtn,
findBeyondHallBtn,
findBeyondRecommendBtn,
findBottomBtnText,
findClearInputBtn,
findCloseDialog,

View File

@@ -3,7 +3,6 @@ import { assertRegionAppearing, waitForAction } from "../@bettergi+utils.js";
import { userConfig } from "../constants/config.js";
import {
findBeyondHallBtn,
findBeyondRecommendBtn,
findConfirmBtn,
findElementViewBtn,
findGotTeyvatBtn,
@@ -14,9 +13,7 @@ import {
//! 判断是否处于奇域大厅
const isInLobby = () => findBeyondHallBtn() !== void 0;
//! 判断是否处于提瓦特大陆
const isInTeyvat = () => {
return findBeyondRecommendBtn() !== void 0 && findElementViewBtn() !== void 0;
};
const isInTeyvat = () => findElementViewBtn() !== void 0;
//! 退出大厅返回提瓦特大陆
const exitLobbyToTeyvat = async () => {
if (!userConfig.goToTeyvat) return;

View File

@@ -59,10 +59,15 @@ const fetchBattlepassExp = async () => {
async () => {
//! 重复确认,防止误领纪游奖励(部件礼箱会卡流程)而不是经验
if (findHeaderTitle("任务", true)) {
findBottomBtnText("领取", true)?.click();
clickToContinue();
await sleep(1e3);
clickToContinue();
const reward = findBottomBtnText("领取", true);
if (reward) {
reward.click();
await sleep(50);
reward.click();
clickToContinue();
await sleep(1e3);
clickToContinue();
}
}
},
{
@@ -72,16 +77,28 @@ const fetchBattlepassExp = async () => {
);
await genshin.returnMainUi();
};
//! 点击领取奖励按钮
const clickClaimRewardBtn = async () => {
const reward = findFetchRewardBtn();
if (reward) {
reward.click();
await sleep(50);
reward.click();
clickToContinue();
await sleep(1e3);
clickToContinue();
}
};
//! 领取绮衣珍赏奖励
const fetchRaimentCollection = async () => {
//! 打开绮衣珍赏
await assertRegionAppearing(
() => findHeaderTitle("珍赏", true),
() => findHeaderTitle("绮衣", true) || findHeaderTitle("珍赏", true),
"打开绮衣珍赏超时,活动未轮换/已结束",
async () => {
keyPress("VK_F6");
await sleep(2e3);
if (findHeaderTitle("珍赏", true) === void 0) keyPress("VK_Q");
if (!findHeaderTitle("绮衣", true) && !findHeaderTitle("珍赏", true)) keyPress("VK_Q");
},
{
maxAttempts: 5,
@@ -93,13 +110,7 @@ const fetchRaimentCollection = async () => {
findFetchRewardBtn,
"领取绮衣珍赏奖励超时",
async () => {
const reward = findFetchRewardBtn();
if (reward) {
reward.click();
clickToContinue();
await sleep(1e3);
clickToContinue();
}
await clickClaimRewardBtn();
},
{
maxAttempts: 5,
@@ -129,13 +140,7 @@ const fetchInvitationToWonderland = async () => {
findFetchRewardBtn,
"领取妙思觅索奖励超时",
async () => {
const reward = findFetchRewardBtn();
if (reward) {
reward.click();
clickToContinue();
await sleep(1e3);
clickToContinue();
}
await clickClaimRewardBtn();
},
{
maxAttempts: 5,

View File

@@ -67,9 +67,9 @@ const playStage = async (playbacks) => {
};
//! 执行通关回放文件(随机抽取)
const execStagePlayback = async (playbacks) => {
const file$1 = playbacks[Math.floor(Math.random() * playbacks.length)];
log.info("执行通关回放文件: {file}", file$1);
await keyMouseScript.runFile(file$1);
const file = playbacks[Math.floor(Math.random() * playbacks.length)];
log.info("执行通关回放文件: {file}", file);
await keyMouseScript.runFile(file);
};
//! 退出关卡
const exitStage = async () => {

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"name": "千星奇域·每周经验刷取(回放通关版)",
"version": "0.1.9",
"version": "0.1.10",
"bgi_version": "0.54.0",
"description": "千星奇域·每周经验刷取(回放通关版)",
"authors": [
@@ -11,7 +11,7 @@
},
{
"name": "躁动的氨气",
"link": "https://github.com/A-Little-AnQi"
"link": "https://github.com/zaodonganqi"
}
],
"main": "main.js",