@windsland52/maafw-live 0.0.0-stage → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +278 -2
- package/bin/maafw-live.mjs +25 -0
- package/docs/daemon-protocol.md +116 -0
- package/docs/keyframe-evidence-contract-v0.md +61 -0
- package/docs/keyframe-retention-contract-v0.md +236 -0
- package/lib/client/daemon.js +234 -0
- package/lib/client/daemon.js.map +1 -0
- package/lib/commands/annotate.js +172 -0
- package/lib/commands/annotate.js.map +1 -0
- package/lib/commands/calibrate.js +61 -0
- package/lib/commands/calibrate.js.map +1 -0
- package/lib/commands/color.js +73 -0
- package/lib/commands/color.js.map +1 -0
- package/lib/commands/crop.js +228 -0
- package/lib/commands/crop.js.map +1 -0
- package/lib/commands/env.js +215 -0
- package/lib/commands/env.js.map +1 -0
- package/lib/commands/index.js +64 -0
- package/lib/commands/index.js.map +1 -0
- package/lib/commands/input.js +219 -0
- package/lib/commands/input.js.map +1 -0
- package/lib/commands/kf.js +131 -0
- package/lib/commands/kf.js.map +1 -0
- package/lib/commands/reco.js +211 -0
- package/lib/commands/reco.js.map +1 -0
- package/lib/commands/repl.js +698 -0
- package/lib/commands/repl.js.map +1 -0
- package/lib/commands/runtime.js +514 -0
- package/lib/commands/runtime.js.map +1 -0
- package/lib/commands/skill.js +169 -0
- package/lib/commands/skill.js.map +1 -0
- package/lib/commands/timing.js +229 -0
- package/lib/commands/timing.js.map +1 -0
- package/lib/commands/version.js +66 -0
- package/lib/commands/version.js.map +1 -0
- package/lib/daemon/framed.mjs +2850 -0
- package/lib/daemon/reco_child.mjs +146 -0
- package/lib/exec.js +96 -0
- package/lib/exec.js.map +1 -0
- package/lib/flags.js +42 -0
- package/lib/flags.js.map +1 -0
- package/lib/image.js +90 -0
- package/lib/image.js.map +1 -0
- package/lib/index.js +139 -0
- package/lib/index.js.map +1 -0
- package/lib/interface/index.js +12 -0
- package/lib/interface/index.js.map +1 -0
- package/lib/interface/jsonc.js +95 -0
- package/lib/interface/jsonc.js.map +1 -0
- package/lib/interface/load.js +307 -0
- package/lib/interface/load.js.map +1 -0
- package/lib/interface/override.js +103 -0
- package/lib/interface/override.js.map +1 -0
- package/lib/interface/plan.js +188 -0
- package/lib/interface/plan.js.map +1 -0
- package/lib/pkg.js +18 -0
- package/lib/pkg.js.map +1 -0
- package/lib/protocol.js +90 -0
- package/lib/protocol.js.map +1 -0
- package/lib/runtime/actions.js +110 -0
- package/lib/runtime/actions.js.map +1 -0
- package/lib/runtime/keyframes.js +73 -0
- package/lib/runtime/keyframes.js.map +1 -0
- package/lib/runtime/session.js +86 -0
- package/lib/runtime/session.js.map +1 -0
- package/lib/types/client/daemon.d.ts +86 -0
- package/lib/types/commands/annotate.d.ts +3 -0
- package/lib/types/commands/calibrate.d.ts +7 -0
- package/lib/types/commands/color.d.ts +9 -0
- package/lib/types/commands/crop.d.ts +3 -0
- package/lib/types/commands/env.d.ts +2 -0
- package/lib/types/commands/index.d.ts +13 -0
- package/lib/types/commands/input.d.ts +17 -0
- package/lib/types/commands/kf.d.ts +10 -0
- package/lib/types/commands/reco.d.ts +23 -0
- package/lib/types/commands/repl.d.ts +2 -0
- package/lib/types/commands/runtime.d.ts +48 -0
- package/lib/types/commands/skill.d.ts +17 -0
- package/lib/types/commands/timing.d.ts +64 -0
- package/lib/types/commands/version.d.ts +3 -0
- package/lib/types/exec.d.ts +31 -0
- package/lib/types/flags.d.ts +58 -0
- package/lib/types/image.d.ts +27 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/interface/index.d.ts +11 -0
- package/lib/types/interface/jsonc.d.ts +9 -0
- package/lib/types/interface/load.d.ts +113 -0
- package/lib/types/interface/override.d.ts +33 -0
- package/lib/types/interface/plan.d.ts +47 -0
- package/lib/types/pkg.d.ts +6 -0
- package/lib/types/protocol.d.ts +108 -0
- package/lib/types/runtime/actions.d.ts +166 -0
- package/lib/types/runtime/keyframes.d.ts +43 -0
- package/lib/types/runtime/session.d.ts +53 -0
- package/lib/types/update-check.d.ts +20 -0
- package/lib/types/usage.d.ts +3 -0
- package/lib/update-check.js +97 -0
- package/lib/update-check.js.map +1 -0
- package/lib/usage.js +50 -0
- package/lib/usage.js.map +1 -0
- package/package.json +81 -4
- package/skills/README.md +51 -0
- package/skills/maafw-live/SKILL.md +263 -0
- package/skills/maafw-live/references/examples.md +238 -0
- package/skills/maafw-live/references/pitfalls.md +118 -0
- package/skills/maafw-live/references/workflows.md +159 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonc.js","sourceRoot":"","sources":["../../src/interface/jsonc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 载入项目 interface.json(ProjectInterface v2)。
|
|
3
|
+
*
|
|
4
|
+
* 只做本工具需要的窄解析:控制器声明(连接规划用)、资源声明(路径解析用)、任务入口
|
|
5
|
+
* (run --project 用)。其余字段(task 参数、option、i18n 等)不属于 CLI 的职责,原样忽略。
|
|
6
|
+
* 全过程不抛异常:问题进 problems[],由调用方决定怎么呈现。
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
9
|
+
import { dirname, join, resolve } from 'node:path';
|
|
10
|
+
import { parseJsonc } from './jsonc.js';
|
|
11
|
+
/** 找 interface.json:项目根优先,其次 assets/(部分项目把声明放资源目录下)。 */
|
|
12
|
+
const REL_CANDIDATES = ['interface.json', 'assets/interface.json'];
|
|
13
|
+
export function findInterfaceFile(dir) {
|
|
14
|
+
const base = resolve(dir);
|
|
15
|
+
for (const rel of REL_CANDIDATES) {
|
|
16
|
+
const p = join(base, rel);
|
|
17
|
+
if (existsSync(p))
|
|
18
|
+
return p;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
function str(v) {
|
|
23
|
+
return typeof v === 'string' && v.trim() ? v : undefined;
|
|
24
|
+
}
|
|
25
|
+
function num(v) {
|
|
26
|
+
return typeof v === 'number' && Number.isFinite(v) ? v : undefined;
|
|
27
|
+
}
|
|
28
|
+
function strList(v) {
|
|
29
|
+
if (typeof v === 'string')
|
|
30
|
+
return [v];
|
|
31
|
+
if (Array.isArray(v))
|
|
32
|
+
return v.filter((x) => typeof x === 'string' && x.length > 0);
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
function obj(v) {
|
|
36
|
+
return v && typeof v === 'object' && !Array.isArray(v) ? v : null;
|
|
37
|
+
}
|
|
38
|
+
export function loadInterface(dir) {
|
|
39
|
+
const file = findInterfaceFile(dir);
|
|
40
|
+
const base = {
|
|
41
|
+
file,
|
|
42
|
+
dir: file ? dirname(file) : null,
|
|
43
|
+
version: null,
|
|
44
|
+
name: null,
|
|
45
|
+
controllers: [],
|
|
46
|
+
resources: [],
|
|
47
|
+
tasks: [],
|
|
48
|
+
options: {},
|
|
49
|
+
presets: [],
|
|
50
|
+
globalOption: [],
|
|
51
|
+
pretask: [],
|
|
52
|
+
agents: [],
|
|
53
|
+
problems: [],
|
|
54
|
+
};
|
|
55
|
+
if (!file) {
|
|
56
|
+
return { ...base, problems: [{ message: '未找到 interface.json(找过 ' + REL_CANDIDATES.join(' / ') + ')' }] };
|
|
57
|
+
}
|
|
58
|
+
let raw;
|
|
59
|
+
try {
|
|
60
|
+
raw = parseJsonc(readFileSync(file, 'utf8'));
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
return { ...base, problems: [{ message: 'interface.json 解析失败:' + String(e.message) }] };
|
|
64
|
+
}
|
|
65
|
+
const o = obj(raw);
|
|
66
|
+
if (!o)
|
|
67
|
+
return { ...base, problems: [{ message: 'interface.json 顶层必须是对象' }] };
|
|
68
|
+
const problems = [];
|
|
69
|
+
const version = num(o.interface_version);
|
|
70
|
+
if (version === undefined)
|
|
71
|
+
problems.push({ message: '缺少 interface_version(ProjectInterface v2 应为 2)' });
|
|
72
|
+
else if (version !== 2)
|
|
73
|
+
problems.push({ message: 'interface_version=' + version + ';本工具按 v2 解析,可能有出入' });
|
|
74
|
+
const controllers = [];
|
|
75
|
+
for (const item of Array.isArray(o.controller) ? o.controller : []) {
|
|
76
|
+
const c = obj(item);
|
|
77
|
+
const name = c ? str(c.name) : undefined;
|
|
78
|
+
const type = c ? str(c.type) : undefined;
|
|
79
|
+
if (!c || !name || !type) {
|
|
80
|
+
problems.push({ message: 'controller 项缺少 name 或 type,已跳过' });
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const display = {};
|
|
84
|
+
const ss = num(c.display_short_side);
|
|
85
|
+
if (ss !== undefined)
|
|
86
|
+
display.shortSide = ss;
|
|
87
|
+
const ls = num(c.display_long_side);
|
|
88
|
+
if (ls !== undefined)
|
|
89
|
+
display.longSide = ls;
|
|
90
|
+
if (c.display_raw === true)
|
|
91
|
+
display.raw = true;
|
|
92
|
+
if (Array.isArray(c.display_expand) && c.display_expand.length === 2) {
|
|
93
|
+
const a = num(c.display_expand[0]);
|
|
94
|
+
const b = num(c.display_expand[1]);
|
|
95
|
+
if (a !== undefined && b !== undefined)
|
|
96
|
+
display.expand = [a, b];
|
|
97
|
+
}
|
|
98
|
+
const w = obj(c.win32);
|
|
99
|
+
const g = obj(c.gamepad);
|
|
100
|
+
controllers.push({
|
|
101
|
+
name,
|
|
102
|
+
type,
|
|
103
|
+
display: Object.keys(display).length ? display : undefined,
|
|
104
|
+
win32: w
|
|
105
|
+
? {
|
|
106
|
+
classRegex: str(w.class_regex),
|
|
107
|
+
windowRegex: str(w.window_regex),
|
|
108
|
+
screencap: str(w.screencap),
|
|
109
|
+
mouse: str(w.mouse),
|
|
110
|
+
keyboard: str(w.keyboard),
|
|
111
|
+
}
|
|
112
|
+
: undefined,
|
|
113
|
+
gamepad: g
|
|
114
|
+
? {
|
|
115
|
+
classRegex: str(g.class_regex),
|
|
116
|
+
windowRegex: str(g.window_regex),
|
|
117
|
+
gamepadType: str(g.gamepad_type),
|
|
118
|
+
screencap: str(g.screencap),
|
|
119
|
+
}
|
|
120
|
+
: undefined,
|
|
121
|
+
attachResourcePath: strList(c.attach_resource_path),
|
|
122
|
+
option: strList(c.option),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (!controllers.length)
|
|
126
|
+
problems.push({ message: 'controller[] 为空:项目没有声明任何控制器' });
|
|
127
|
+
const resources = [];
|
|
128
|
+
for (const item of Array.isArray(o.resource) ? o.resource : []) {
|
|
129
|
+
const r = obj(item);
|
|
130
|
+
const name = r ? str(r.name) : undefined;
|
|
131
|
+
const paths = r ? strList(r.path) : [];
|
|
132
|
+
if (!r || !name || !paths.length) {
|
|
133
|
+
problems.push({ message: 'resource 项缺少 name 或 path,已跳过' });
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
resources.push({ name, paths, controllers: strList(r.controller), option: strList(r.option) });
|
|
137
|
+
}
|
|
138
|
+
const tasks = [];
|
|
139
|
+
const options = {};
|
|
140
|
+
const presets = [];
|
|
141
|
+
const globalOption = [];
|
|
142
|
+
const pretask = [];
|
|
143
|
+
const agents = [];
|
|
144
|
+
const readAgents = (list) => {
|
|
145
|
+
for (const item of Array.isArray(list) ? list : (list !== undefined ? [list] : [])) {
|
|
146
|
+
const a = obj(item);
|
|
147
|
+
const exec = a ? str(a.child_exec) : undefined;
|
|
148
|
+
if (!a || !exec)
|
|
149
|
+
continue;
|
|
150
|
+
agents.push({ exec, args: strList(a.child_args) });
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
const readTasks = (list, src) => {
|
|
154
|
+
for (const item of Array.isArray(list) ? list : []) {
|
|
155
|
+
const t = obj(item);
|
|
156
|
+
const name = t ? str(t.name) : undefined;
|
|
157
|
+
if (!t || !name) {
|
|
158
|
+
problems.push({ message: 'task 项缺少 name,已跳过(' + src + ')' });
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
tasks.push({
|
|
162
|
+
name,
|
|
163
|
+
entry: str(t.entry),
|
|
164
|
+
controller: strList(t.controller),
|
|
165
|
+
resource: strList(t.resource),
|
|
166
|
+
option: strList(t.option),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
const readOptions = (dict, src) => {
|
|
171
|
+
const d = obj(dict);
|
|
172
|
+
if (!d) {
|
|
173
|
+
if (dict !== undefined)
|
|
174
|
+
problems.push({ message: 'option 应为对象(键=配置项名),已忽略(' + src + ')' });
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
for (const [key, val] of Object.entries(d)) {
|
|
178
|
+
const v = obj(val);
|
|
179
|
+
if (!v || !str(v.type)) {
|
|
180
|
+
problems.push({ message: 'option ' + key + ' 缺少 type,已跳过(' + src + ')' });
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
const cases = [];
|
|
184
|
+
for (const cs of Array.isArray(v.cases) ? v.cases : []) {
|
|
185
|
+
const c2 = obj(cs);
|
|
186
|
+
const cname = c2 ? str(c2.name) : undefined;
|
|
187
|
+
if (!c2 || !cname)
|
|
188
|
+
continue;
|
|
189
|
+
const po = obj(c2.pipeline_override);
|
|
190
|
+
cases.push({
|
|
191
|
+
name: cname,
|
|
192
|
+
...(po ? { pipelineOverride: po } : {}),
|
|
193
|
+
option: strList(c2.option),
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
options[key] = {
|
|
197
|
+
name: key,
|
|
198
|
+
type: String(v.type),
|
|
199
|
+
cases,
|
|
200
|
+
...(v.default_case !== undefined ? { defaultCase: v.default_case } : {}),
|
|
201
|
+
controller: strList(v.controller),
|
|
202
|
+
resource: strList(v.resource),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
const readPresets = (list) => {
|
|
207
|
+
for (const item of Array.isArray(list) ? list : []) {
|
|
208
|
+
const p = obj(item);
|
|
209
|
+
const name = p ? str(p.name) : undefined;
|
|
210
|
+
if (!p || !name)
|
|
211
|
+
continue;
|
|
212
|
+
const tlist = [];
|
|
213
|
+
for (const tp of Array.isArray(p.task) ? p.task : []) {
|
|
214
|
+
const t2 = obj(tp);
|
|
215
|
+
const tname = t2 ? str(t2.name) : undefined;
|
|
216
|
+
if (!t2 || !tname)
|
|
217
|
+
continue;
|
|
218
|
+
const pv = obj(t2.option);
|
|
219
|
+
tlist.push({ name: tname, enabled: t2.enabled !== false, ...(pv ? { option: pv } : {}) });
|
|
220
|
+
}
|
|
221
|
+
presets.push({ name, task: tlist });
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
readTasks(o.task, '主文件');
|
|
225
|
+
readOptions(o.option, '主文件');
|
|
226
|
+
readPresets(o.preset);
|
|
227
|
+
readAgents(o.agent);
|
|
228
|
+
for (const g of strList(o.global_option))
|
|
229
|
+
if (!globalOption.includes(g))
|
|
230
|
+
globalOption.push(g);
|
|
231
|
+
const mainPretasks = Array.isArray(o.pretask) ? o.pretask : (o.pretask !== undefined ? [o.pretask] : []);
|
|
232
|
+
for (const pt of mainPretasks) {
|
|
233
|
+
const p2 = obj(pt);
|
|
234
|
+
if (p2)
|
|
235
|
+
pretask.push({ name: str(p2.name), exec: str(p2.exec) });
|
|
236
|
+
}
|
|
237
|
+
/* import 合并(v2.2.0):只合 task/option/preset/global_option/pretask(及 group/setting,本工具不消费)。
|
|
238
|
+
* controller/resource 不可导入——子文件声明了也忽略并记 problems。循环导入用 visited 集合挡住。
|
|
239
|
+
*
|
|
240
|
+
* 上游口径(MaaFW 5.14.2 @ 8061d5b,逐条核过):
|
|
241
|
+
* - 被 import 的文件由 tools/interface_import.schema.json 约束(描述原文:"用于 interface.json 的
|
|
242
|
+
* import 字段引用的文件"),顶层只有 task/option/pretask/global_option/setting/preset,且
|
|
243
|
+
* `additionalProperties: false` → **`import` 不可嵌套**、`agent` 也不在其中;
|
|
244
|
+
* - 协议文档 3.3 的 import 节把 `group` 列进可导入字段(v2.4.0,合并表里也有 group 行),
|
|
245
|
+
* 而 5.14.2 的 import schema 顶层**没有 group** → 文档与 schema 不一致(上游漂移)。
|
|
246
|
+
* **后续:上游已就这条提 PR,结论是"改 schema"**(即 import 文件将来可以合法带 group)。
|
|
247
|
+
* 我们的行为不变——group 本工具不消费,因此既不合并也不报错;真要用到 UI 分组时再说。
|
|
248
|
+
* - `agent` 不在 import schema 里,但本工具**宽容读取**(下面的 readAgents):这是超出协议的扩展,
|
|
249
|
+
* 只影响"文件结构校验收紧的工具"与我们的行为差异,实现上进 candidates 前仍会如实报 problems。 */
|
|
250
|
+
const seen = new Set([file]);
|
|
251
|
+
const imports = strList(o.import);
|
|
252
|
+
for (const rel of imports) {
|
|
253
|
+
const childFile = join(dirname(file), rel);
|
|
254
|
+
if (seen.has(childFile)) {
|
|
255
|
+
problems.push({ message: 'import 循环引用,已跳过:' + rel });
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
seen.add(childFile);
|
|
259
|
+
let child = null;
|
|
260
|
+
try {
|
|
261
|
+
child = obj(parseJsonc(readFileSync(childFile, 'utf8')));
|
|
262
|
+
}
|
|
263
|
+
catch (e) {
|
|
264
|
+
problems.push({ message: 'import 文件读取/解析失败:' + rel + '(' + String(e.message) + ')' });
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
if (!child)
|
|
268
|
+
continue;
|
|
269
|
+
if (child.controller !== undefined || child.resource !== undefined) {
|
|
270
|
+
problems.push({ message: 'import 文件 ' + rel + ' 声明了 controller/resource:协议不可导入,已忽略' });
|
|
271
|
+
}
|
|
272
|
+
/* import 不可嵌套:被引用的文件由 interface_import.schema.json 约束(MaaFW 5.14.2,
|
|
273
|
+
* 顶层只有 task/option/pretask/global_option/setting/preset 且 additionalProperties: false,
|
|
274
|
+
* 文档 3.3 的 import 节也没有嵌套写法)。静默吞掉会让"二级文件"整份消失得无影无踪,
|
|
275
|
+
* 所以这里记一条 problem——它通常意味着拆分方式需要改成平铺。 */
|
|
276
|
+
if (child.import !== undefined) {
|
|
277
|
+
problems.push({ message: 'import 文件 ' + rel + ' 里还有 import:import 不可嵌套(该文件的 schema 顶层没有 import 字段),其引用的文件已忽略' });
|
|
278
|
+
}
|
|
279
|
+
readTasks(child.task, rel);
|
|
280
|
+
readOptions(child.option, rel);
|
|
281
|
+
readPresets(child.preset);
|
|
282
|
+
readAgents(child.agent);
|
|
283
|
+
for (const g of strList(child.global_option))
|
|
284
|
+
if (!globalOption.includes(g))
|
|
285
|
+
globalOption.push(g);
|
|
286
|
+
for (const pt of Array.isArray(child.pretask) ? child.pretask : []) {
|
|
287
|
+
const p2 = obj(pt);
|
|
288
|
+
if (p2)
|
|
289
|
+
pretask.push({ name: str(p2.name), exec: str(p2.exec) });
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
...base,
|
|
294
|
+
version: version ?? null,
|
|
295
|
+
name: str(o.name) ?? null,
|
|
296
|
+
controllers,
|
|
297
|
+
resources,
|
|
298
|
+
tasks,
|
|
299
|
+
options,
|
|
300
|
+
presets,
|
|
301
|
+
globalOption,
|
|
302
|
+
pretask,
|
|
303
|
+
agents,
|
|
304
|
+
problems,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/interface/load.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 把一份 pipeline_override 并入累计结果:同节点字段替换(与协议"不深度合并"一致)。
|
|
3
|
+
*
|
|
4
|
+
* **唯一一份实现**:四级链、`run --override`、`timing --override` 都走这里。这三处曾经各写一份,
|
|
5
|
+
* 代价是同一个参数在不同命令里表现不同。非对象值必须**原样替换、不能展开**:字符串会被摊成
|
|
6
|
+
* `{0:'a',1:'b'}`,`null` / 数字会静默变成空对象——等于把用户写的节点悄悄丢掉。
|
|
7
|
+
*/
|
|
8
|
+
export function mergeOverride(acc, po) {
|
|
9
|
+
for (const [node, fields] of Object.entries(po)) {
|
|
10
|
+
if (fields && typeof fields === 'object' && !Array.isArray(fields)) {
|
|
11
|
+
acc[node] = { ...(acc[node] ?? {}), ...fields };
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
acc[node] = fields;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function computePipelineOverride(input) {
|
|
19
|
+
const { loaded, controllerName, resourceName, taskName, presetName } = input;
|
|
20
|
+
const warns = [];
|
|
21
|
+
const applied = [];
|
|
22
|
+
const acc = {};
|
|
23
|
+
const preset = presetName ? loaded.presets.find((p) => p.name === presetName) : undefined;
|
|
24
|
+
if (presetName && !preset)
|
|
25
|
+
warns.push('preset ' + presetName + ' 不存在(可用:' + loaded.presets.map((p) => p.name).join(' / ') + '或无)');
|
|
26
|
+
const presetTask = preset && taskName ? preset.task.find((t) => t.name === taskName) : undefined;
|
|
27
|
+
const applicable = (o) => {
|
|
28
|
+
if (o.controller?.length && controllerName && !o.controller.includes(controllerName))
|
|
29
|
+
return false;
|
|
30
|
+
if (o.resource?.length && resourceName && !o.resource.includes(resourceName))
|
|
31
|
+
return false;
|
|
32
|
+
return true;
|
|
33
|
+
};
|
|
34
|
+
/** 解析一个 option 的当前取值:preset > default_case;返回 case 名(单个或数组)。 */
|
|
35
|
+
const valueOf = (name) => {
|
|
36
|
+
const o = loaded.options[name];
|
|
37
|
+
if (!o) {
|
|
38
|
+
warns.push('option ' + name + ' 未在 interface 中定义,已跳过');
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const pv = presetTask?.option?.[name];
|
|
42
|
+
if (pv !== undefined) {
|
|
43
|
+
return { cases: Array.isArray(pv) ? pv.map(String) : [String(pv)], via: 'preset' };
|
|
44
|
+
}
|
|
45
|
+
if (o.defaultCase !== undefined) {
|
|
46
|
+
return { cases: Array.isArray(o.defaultCase) ? o.defaultCase.map(String) : [String(o.defaultCase)], via: 'default' };
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
};
|
|
50
|
+
const mergeOption = (name, level, chain = []) => {
|
|
51
|
+
/* 嵌套 option 是"case 里再列 option",A → B → A 这类自引用会让递归停不下来:
|
|
52
|
+
* 记一条警告并跳过,而不是用栈溢出把整条 run 打断。 */
|
|
53
|
+
if (chain.includes(name)) {
|
|
54
|
+
warns.push('option ' + name + ' 出现在自己的嵌套链里(' + [...chain, name].join(' > ') + '),已跳过');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const o = loaded.options[name];
|
|
58
|
+
if (o && !applicable(o))
|
|
59
|
+
return;
|
|
60
|
+
const v = valueOf(name);
|
|
61
|
+
if (!o)
|
|
62
|
+
return;
|
|
63
|
+
if (!v) {
|
|
64
|
+
if (o.type === 'input' || o.type === 'hotkey')
|
|
65
|
+
return; // 输入类不产生 pipeline_override,不算异常
|
|
66
|
+
warns.push('option ' + name + '(' + level + ')无 preset/default_case 取值,跳过其 pipeline_override');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
for (const cname of v.cases) {
|
|
70
|
+
const c = o.cases.find((x) => x.name === cname);
|
|
71
|
+
if (!c) {
|
|
72
|
+
warns.push('option ' + name + ' 的取值 ' + cname + ' 不是已声明的 case,已跳过');
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (c.pipelineOverride && Object.keys(c.pipelineOverride).length) {
|
|
76
|
+
mergeOverride(acc, c.pipelineOverride);
|
|
77
|
+
applied.push(name + '=' + cname + '(' + level + ',via ' + v.via + ')');
|
|
78
|
+
}
|
|
79
|
+
/* 嵌套子 option:父 case 生效后按声明顺序合并(更具体,晚于父级) */
|
|
80
|
+
for (const child of c.option ?? [])
|
|
81
|
+
mergeOption(child, level + ' > ' + name, [...chain, name]);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
for (const name of loaded.globalOption)
|
|
85
|
+
mergeOption(name, 'global_option');
|
|
86
|
+
if (resourceName) {
|
|
87
|
+
const r = loaded.resources.find((x) => x.name === resourceName);
|
|
88
|
+
for (const name of r?.option ?? [])
|
|
89
|
+
mergeOption(name, 'resource.option');
|
|
90
|
+
}
|
|
91
|
+
if (controllerName) {
|
|
92
|
+
const c = loaded.controllers.find((x) => x.name === controllerName);
|
|
93
|
+
for (const name of c?.option ?? [])
|
|
94
|
+
mergeOption(name, 'controller.option');
|
|
95
|
+
}
|
|
96
|
+
if (taskName) {
|
|
97
|
+
const t = loaded.tasks.find((x) => x.name === taskName);
|
|
98
|
+
for (const name of t?.option ?? [])
|
|
99
|
+
mergeOption(name, 'task.option');
|
|
100
|
+
}
|
|
101
|
+
return { override: acc, warns, applied };
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=override.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"override.js","sourceRoot":"","sources":["../../src/interface/override.ts"],"names":[],"mappings":"AA2BA;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,GAA4B,EAAE,EAA2B;IACrF,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;QAChD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAE,GAAG,CAAC,IAAI,CAA6B,IAAI,EAAE,CAAC,EAAE,GAAI,MAAkC,EAAE,CAAA;QAC3G,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,GAAG,MAAM,CAAA;QACpB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAoB;IAC1D,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,KAAK,CAAA;IAC5E,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,MAAM,GAAG,GAA4B,EAAE,CAAA;IACvC,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACzF,IAAI,UAAU,IAAI,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAA;IAClI,MAAM,UAAU,GAAG,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAEhG,MAAM,UAAU,GAAG,CAAC,CAAkB,EAAW,EAAE;QACjD,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,IAAI,cAAc,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC;YAAE,OAAO,KAAK,CAAA;QAClG,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,IAAI,YAAY,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC;YAAE,OAAO,KAAK,CAAA;QAC1F,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,gEAAgE;IAChE,MAAM,OAAO,GAAG,CAAC,IAAY,EAA2C,EAAE;QACxE,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,uBAAuB,CAAC,CAAA;YACtD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,CAAA;QACrC,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAA;QACpF,CAAC;QACD,IAAI,CAAC,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAA;QACtH,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,QAAkB,EAAE,EAAQ,EAAE;QAC9E;yCACiC;QACjC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,cAAc,GAAG,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAA;YACtF,OAAM;QACR,CAAC;QACD,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC9B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAM;QAC/B,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;QACvB,IAAI,CAAC,CAAC;YAAE,OAAM;QACd,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAM,CAAC,gCAAgC;YACtF,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,GAAG,GAAG,KAAK,GAAG,iDAAiD,CAAC,CAAA;YAC9F,OAAM;QACR,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YAC5B,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAA;YAC/C,IAAI,CAAC,CAAC,EAAE,CAAC;gBACP,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,OAAO,GAAG,KAAK,GAAG,kBAAkB,CAAC,CAAA;gBACnE,SAAQ;YACV,CAAC;YACD,IAAI,CAAC,CAAC,gBAAgB,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,MAAM,EAAE,CAAC;gBACjE,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,gBAAgB,CAAC,CAAA;gBACtC,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,GAAG,GAAG,KAAK,GAAG,GAAG,GAAG,KAAK,GAAG,OAAO,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAA;YACxE,CAAC;YACD,4CAA4C;YAC5C,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,MAAM,IAAI,EAAE;gBAAE,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,GAAG,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;QAChG,CAAC;IACH,CAAC,CAAA;IAED,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,YAAY;QAAE,WAAW,CAAC,IAAI,EAAE,eAAe,CAAC,CAAA;IAC1E,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAA;QAC/D,KAAK,MAAM,IAAI,IAAI,CAAC,EAAE,MAAM,IAAI,EAAE;YAAE,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAA;IAC1E,CAAC;IACD,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAA;QACnE,KAAK,MAAM,IAAI,IAAI,CAAC,EAAE,MAAM,IAAI,EAAE;YAAE,WAAW,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAA;IAC5E,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAA;QACvD,KAAK,MAAM,IAAI,IAAI,CAAC,EAAE,MAAM,IAAI,EAAE;YAAE,WAAW,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;IACtE,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;AAC1C,CAAC"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 项目驱动的连接规划:把 interface.json 的控制器声明与枚举到的设备对上,
|
|
3
|
+
* 产出 daemon `connect` 的参数;对不上时给出候选与可操作的原因。
|
|
4
|
+
*
|
|
5
|
+
* 为什么不猜设备:猜错不只是连错窗口,还会把 roi 与模板的坐标系一起猜错。
|
|
6
|
+
*/
|
|
7
|
+
import { resolve } from 'node:path';
|
|
8
|
+
const KIND_BY_TYPE = { Adb: 'adb', Win32: 'win32', Gamepad: 'gamepad', PlayCover: 'playcover', Linux: 'linux' };
|
|
9
|
+
function safeRegExp(pattern) {
|
|
10
|
+
try {
|
|
11
|
+
return new RegExp(pattern);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function fail(c, code, error, candidates, connect, notes) {
|
|
18
|
+
return { ok: false, code, error, controllerName: c.name, connect, candidates, notes };
|
|
19
|
+
}
|
|
20
|
+
export function planController(loaded, overrides, devices) {
|
|
21
|
+
const wanted = overrides.controller;
|
|
22
|
+
const c = wanted ? loaded.controllers.find((x) => x.name === wanted) : loaded.controllers[0];
|
|
23
|
+
if (!c) {
|
|
24
|
+
const names = loaded.controllers.map((x) => x.name).join(' / ');
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
code: wanted ? 'CONTROLLER_NOT_FOUND' : 'NO_CONTROLLER',
|
|
28
|
+
controllerName: null,
|
|
29
|
+
connect: {},
|
|
30
|
+
candidates: [],
|
|
31
|
+
error: wanted
|
|
32
|
+
? 'interface.json 里没有控制器 ' + wanted + (names ? '(可用:' + names + ')' : '')
|
|
33
|
+
: 'interface.json 没有声明任何控制器',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const kind = KIND_BY_TYPE[c.type];
|
|
37
|
+
if (!kind) {
|
|
38
|
+
return {
|
|
39
|
+
ok: false,
|
|
40
|
+
code: 'CONTROLLER_UNSUPPORTED',
|
|
41
|
+
controllerName: c.name,
|
|
42
|
+
connect: {},
|
|
43
|
+
candidates: [],
|
|
44
|
+
error: '控制器 ' + c.name + ' 的类型 ' + c.type + ' 暂不受支持(本 CLI 支持 Adb / Win32 / Gamepad / PlayCover / Linux;MacOS 走手动 --kind macos)',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const notes = ['控制器 ' + c.name + '(来自 interface.json)'];
|
|
48
|
+
const connect = { kind };
|
|
49
|
+
if (c.display?.shortSide !== undefined)
|
|
50
|
+
connect.shortSide = c.display.shortSide;
|
|
51
|
+
if (c.display?.longSide !== undefined)
|
|
52
|
+
connect.longSide = c.display.longSide;
|
|
53
|
+
if (c.display?.raw)
|
|
54
|
+
connect.rawSize = true;
|
|
55
|
+
if (c.display?.expand)
|
|
56
|
+
notes.push('display_expand 暂不生效(daemon 未接入),已忽略');
|
|
57
|
+
if (kind === 'playcover' || kind === 'linux') {
|
|
58
|
+
/* 两类控制器没有可枚举的设备发现:必须显式给 target(playcover=<address>/<uuid>,
|
|
59
|
+
linux=<config JSON>),工具不猜会话形态。 */
|
|
60
|
+
const t = overrides.manualTarget ?? null;
|
|
61
|
+
if (!t) {
|
|
62
|
+
return fail(c, 'TARGET_REQUIRED', kind === 'playcover'
|
|
63
|
+
? 'PlayCover 需要 --target <address>/<uuid>(PlayCover 设置里可见)'
|
|
64
|
+
: 'Linux 需要 --target <config JSON>(含 screencap_method / input_method 等必填字段)', [], connect, notes);
|
|
65
|
+
}
|
|
66
|
+
connect.target = t;
|
|
67
|
+
return { ok: true, controllerName: c.name, connect, notes };
|
|
68
|
+
}
|
|
69
|
+
if (kind === 'adb') {
|
|
70
|
+
const addr = overrides.adb?.address ?? null;
|
|
71
|
+
let hit;
|
|
72
|
+
if (addr)
|
|
73
|
+
hit = devices.find((d) => String(d.id ?? '') === addr);
|
|
74
|
+
if (addr && !hit) {
|
|
75
|
+
return fail(c, 'DEVICE_NOT_FOUND', 'adb 地址 ' + addr + ' 不在已发现设备中(共 ' + devices.length + ' 台)', devices, connect, notes);
|
|
76
|
+
}
|
|
77
|
+
if (!hit && devices.length === 0) {
|
|
78
|
+
return fail(c, 'NO_DEVICES', '没有发现 adb 设备(检查 adb 连接与模拟器)', [], connect, notes);
|
|
79
|
+
}
|
|
80
|
+
if (!hit && devices.length === 1)
|
|
81
|
+
hit = devices[0];
|
|
82
|
+
if (!hit) {
|
|
83
|
+
return fail(c, 'DEVICE_AMBIGUOUS', '发现 ' + devices.length + ' 台 adb 设备,请用 --address 显式指定', devices, connect, notes);
|
|
84
|
+
}
|
|
85
|
+
connect.target = String(hit.id ?? '');
|
|
86
|
+
notes.push('设备:' + (hit.name || hit.id || '?'));
|
|
87
|
+
return { ok: true, controllerName: c.name, connect, notes };
|
|
88
|
+
}
|
|
89
|
+
/* Win32 / Gamepad:窗口类名与标题正则两条都生效(与本体 boost::regex_search 语义一致)。 */
|
|
90
|
+
const decl = kind === 'gamepad' ? { ...(c.gamepad ?? {}) } : { ...(c.win32 ?? {}) };
|
|
91
|
+
const hwnd = (kind === 'gamepad' ? overrides.gamepad?.hwnd : overrides.win32?.hwnd) ?? null;
|
|
92
|
+
let hit;
|
|
93
|
+
if (hwnd) {
|
|
94
|
+
hit =
|
|
95
|
+
devices.find((d) => String(d.id ?? '') === hwnd) ??
|
|
96
|
+
devices.find((d) => String(d.name ?? '').includes(hwnd) || String(d.cls ?? '').includes(hwnd));
|
|
97
|
+
if (!hit) {
|
|
98
|
+
return fail(c, 'WINDOW_NOT_FOUND', '窗口未找到:' + hwnd + '(hwnd 变了或窗口已关闭)', devices, connect, notes);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const clsRe = decl.classRegex ? safeRegExp(decl.classRegex) : null;
|
|
103
|
+
const winRe = decl.windowRegex ? safeRegExp(decl.windowRegex) : null;
|
|
104
|
+
if (decl.classRegex && !clsRe)
|
|
105
|
+
notes.push('class_regex 不是合法正则,已忽略:' + decl.classRegex);
|
|
106
|
+
if (decl.windowRegex && !winRe)
|
|
107
|
+
notes.push('window_regex 不是合法正则,已忽略:' + decl.windowRegex);
|
|
108
|
+
if (clsRe || winRe) {
|
|
109
|
+
const matched = devices.filter((d) => (!clsRe || clsRe.test(String(d.cls ?? ''))) && (!winRe || winRe.test(String(d.name ?? ''))));
|
|
110
|
+
if (matched.length === 1)
|
|
111
|
+
hit = matched[0];
|
|
112
|
+
else if (matched.length === 0) {
|
|
113
|
+
const cond = [
|
|
114
|
+
decl.classRegex && 'class~' + decl.classRegex,
|
|
115
|
+
decl.windowRegex && 'title~' + decl.windowRegex,
|
|
116
|
+
]
|
|
117
|
+
.filter(Boolean)
|
|
118
|
+
.join(' + ');
|
|
119
|
+
return fail(c, 'WINDOW_NOT_FOUND', '没有窗口同时匹配 ' + cond + '(当前 ' + devices.length + ' 个窗口)', devices, connect, notes);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
return fail(c, 'WINDOW_AMBIGUOUS', '有 ' + matched.length + ' 个窗口匹配,请用 --hwnd 显式指定', matched, connect, notes);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else if (devices.length === 1) {
|
|
126
|
+
hit = devices[0];
|
|
127
|
+
notes.push('控制器未声明窗口匹配规则,使用唯一窗口');
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
return fail(c, 'WINDOW_AMBIGUOUS', '控制器未声明窗口匹配规则,且当前有 ' + devices.length + ' 个窗口,请用 --hwnd 指定', devices, connect, notes);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
connect.target = String(hit.id ?? '');
|
|
134
|
+
if (decl.screencap)
|
|
135
|
+
connect.screencap = decl.screencap;
|
|
136
|
+
if (kind === 'win32') {
|
|
137
|
+
if (decl.mouse)
|
|
138
|
+
connect.mouse = decl.mouse;
|
|
139
|
+
if (decl.keyboard)
|
|
140
|
+
connect.keyboard = decl.keyboard;
|
|
141
|
+
}
|
|
142
|
+
else if (decl.gamepadType) {
|
|
143
|
+
connect.gamepadType = decl.gamepadType;
|
|
144
|
+
}
|
|
145
|
+
notes.push('窗口:' + (hit.name || hit.cls || hit.id || '?'));
|
|
146
|
+
return { ok: true, controllerName: c.name, connect, notes };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* 解析资源路径:resource[] 是互斥单选(Client 语义)——不传 override 时取第一个适用于
|
|
150
|
+
* 所选控制器的条目,条目自身多路径按声明顺序叠加(如"B 服"= base + bilibili);
|
|
151
|
+
* attach_resource_path 在选中控制器后追加。override(--resource)先按资源名匹配,
|
|
152
|
+
* 匹配不上再按文件系统路径解释(原有行为)。
|
|
153
|
+
*/
|
|
154
|
+
export function resolveResourcePaths(loaded, controllerName, override) {
|
|
155
|
+
const dir = loaded.dir;
|
|
156
|
+
/**
|
|
157
|
+
* 追加控制器声明的 attach_resource_path(v2.2.0:"在 resource.path 加载完成后,额外加载")。
|
|
158
|
+
* 它是**控制器的属性**,所以 `--resource` 走哪条分支都要追加——曾经两条提前 return 把它丢了。
|
|
159
|
+
*/
|
|
160
|
+
const withAttach = (paths, names, selected) => {
|
|
161
|
+
const out = [...paths];
|
|
162
|
+
if (dir && controllerName) {
|
|
163
|
+
const c = loaded.controllers.find((x) => x.name === controllerName);
|
|
164
|
+
for (const p of c?.attachResourcePath ?? [])
|
|
165
|
+
out.push(resolve(dir, p));
|
|
166
|
+
}
|
|
167
|
+
return { paths: [...new Set(out)], names, selected };
|
|
168
|
+
};
|
|
169
|
+
if (override) {
|
|
170
|
+
const byName = loaded.resources.find((r) => r.name === override);
|
|
171
|
+
if (byName && dir) {
|
|
172
|
+
return withAttach(byName.paths.map((p) => resolve(dir, p)), [byName.name], byName.name);
|
|
173
|
+
}
|
|
174
|
+
return withAttach([resolve(override)], ['(--resource)'], null);
|
|
175
|
+
}
|
|
176
|
+
if (!dir)
|
|
177
|
+
return { paths: [], names: [], selected: null };
|
|
178
|
+
const applicable = loaded.resources.filter((r) => !controllerName || !r.controllers.length || r.controllers.includes(controllerName));
|
|
179
|
+
const paths = [];
|
|
180
|
+
let selected = null;
|
|
181
|
+
if (applicable.length) {
|
|
182
|
+
selected = applicable[0].name;
|
|
183
|
+
for (const p of applicable[0].paths)
|
|
184
|
+
paths.push(resolve(dir, p));
|
|
185
|
+
}
|
|
186
|
+
return withAttach(paths, selected ? [selected] : [], selected);
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=plan.js.map
|