poi-plugin-kancolle-chs 1.3.0 → 1.3.8
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/index.es +1 -7
- package/package.json +6 -1
- package/src/config.es +3 -0
- package/src/constants.es +5 -3
- package/src/core/api-merger.es +227 -14
- package/src/core/main-patcher.es +1 -0
- package/src/core/resource-updater.es +3 -2
- package/src/core/text-patcher.es +3 -0
- package/src/loaders/data-loader.es +129 -13
- package/src/views/MainPanel.es +68 -34
package/index.es
CHANGED
|
@@ -31,13 +31,7 @@ export const pluginDidLoad = async () => {
|
|
|
31
31
|
await mainPatcher.buildAndDeploy()
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
// 4.
|
|
35
|
-
if (configManager.get('autoCheckUpdate', true)) {
|
|
36
|
-
import('./src/core/git-manager').then(({ gitManager }) => {
|
|
37
|
-
gitManager.checkForUpdates().catch(() => {})
|
|
38
|
-
}).catch(() => {})
|
|
39
|
-
}
|
|
40
|
-
|
|
34
|
+
// 4. 若开启了启动自动检查更新,由 MainPanel 在渲染时自动检测并在有更新时弹窗提醒
|
|
41
35
|
console.log('[砍口垒汉化计划PLUS] 插件加载完毕,原生汉化模式已生效!')
|
|
42
36
|
} else {
|
|
43
37
|
console.log('[砍口垒汉化计划PLUS] 插件当前处于停用状态,确保环境纯净官方原版...')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poi-plugin-kancolle-chs",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.8",
|
|
4
4
|
"description": "砍口垒汉化计划PLUS POI 原生独立插件:提供全界面文本替换、正则动态替换、KCSAPI 响应合流、中文字体与贴图魔改、自定义字体适配与官方资源更新",
|
|
5
5
|
"main": "index.es",
|
|
6
6
|
"files": [
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
"assets/",
|
|
10
10
|
"generated/"
|
|
11
11
|
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"pub": "node scripts/publish-to-npm.js",
|
|
14
|
+
"publish-plugin": "node scripts/publish-to-npm.js",
|
|
15
|
+
"pub:dry": "node scripts/publish-to-npm.js --dry-run"
|
|
16
|
+
},
|
|
12
17
|
"author": {
|
|
13
18
|
"name": "泉浅漪",
|
|
14
19
|
"link": "https://github.com/asaico",
|
package/src/config.es
CHANGED
|
@@ -93,6 +93,9 @@ class ConfigManager {
|
|
|
93
93
|
|
|
94
94
|
if (saved && typeof saved === 'object') {
|
|
95
95
|
this.config = { ...DEFAULT_CONFIG, ...saved }
|
|
96
|
+
if (saved.autoCheckResourceUpdate === undefined && saved.autoCheckUpdate !== undefined) {
|
|
97
|
+
this.config.autoCheckResourceUpdate = saved.autoCheckUpdate
|
|
98
|
+
}
|
|
96
99
|
} else {
|
|
97
100
|
// 若首次启动且无配置,尝试全平台推荐路径初始化
|
|
98
101
|
for (const candidate of RECOMMENDED_SOURCE_PATHS) {
|
package/src/constants.es
CHANGED
|
@@ -15,7 +15,7 @@ export const OFFICIAL_REPO_GIT = 'https://github.com/asaico/Kancolle_to_CHS.git'
|
|
|
15
15
|
export const OFFICIAL_REPO_RELEASES = 'https://github.com/asaico/Kancolle_to_CHS/releases'
|
|
16
16
|
|
|
17
17
|
// 插件版本与 npm 元信息
|
|
18
|
-
let pkgVersion = '1.3.
|
|
18
|
+
let pkgVersion = '1.3.8'
|
|
19
19
|
try {
|
|
20
20
|
const pkg = require('../package.json')
|
|
21
21
|
if (pkg && pkg.version) pkgVersion = pkg.version
|
|
@@ -70,6 +70,7 @@ export const DEFAULT_CONFIG = {
|
|
|
70
70
|
enableApiMapInfo: true, // 出击海区与作战行动说明 (start2.api_mst_mapinfo.json)
|
|
71
71
|
enableApiPictureBook: true, // 舰船与装备图鉴介绍 (picture_book.ship / slotitem)
|
|
72
72
|
enableApiFlavor: true, // 海域进点气象与深海台词 (battle.api_flavor_info.json)
|
|
73
|
+
enableApiItem: true, // 消耗道具与商城道具汉化 (useitem / payitem.json)
|
|
73
74
|
|
|
74
75
|
// --- 3. 静态魔改资产细分开关 ---
|
|
75
76
|
enableFontHack: true, // 默认中文字体替换(思源黑体)
|
|
@@ -82,8 +83,9 @@ export const DEFAULT_CONFIG = {
|
|
|
82
83
|
customFontPath: '', // 本地字体文件绝对路径 (.woff2 / .ttf / .otf)
|
|
83
84
|
|
|
84
85
|
// --- 5. 官方资源与更新管理 ---
|
|
85
|
-
autoCheckUpdate: true,
|
|
86
|
-
|
|
86
|
+
autoCheckUpdate: true, // 插件启动时是否在后台自动检查更新
|
|
87
|
+
autoCheckResourceUpdate: true, // 启动 POI 时自动检查本地汉化资源更新并在面板提示
|
|
88
|
+
downloadMirror: 'direct', // 资源下载加速镜像,默认 'direct' (GitHub 官方直连)
|
|
87
89
|
|
|
88
90
|
// --- 6. 游戏运行帧率上限调节 ---
|
|
89
91
|
fpsLimit: 60, // 游戏帧率上限 (默认 60,可选 60, 120, 165, 240)
|
package/src/core/api-merger.es
CHANGED
|
@@ -11,6 +11,7 @@ export function generateApiPatcherScript(apiData, options = {}) {
|
|
|
11
11
|
enableApiMapInfo = true,
|
|
12
12
|
enableApiPictureBook = true,
|
|
13
13
|
enableApiFlavor = true,
|
|
14
|
+
enableApiItem = true,
|
|
14
15
|
} = options
|
|
15
16
|
|
|
16
17
|
// 若所有 API 模块均未启用,则不注入 XHR 拦截代码
|
|
@@ -21,7 +22,8 @@ export function generateApiPatcherScript(apiData, options = {}) {
|
|
|
21
22
|
enableApiFurniture ||
|
|
22
23
|
enableApiMapInfo ||
|
|
23
24
|
enableApiPictureBook ||
|
|
24
|
-
enableApiFlavor
|
|
25
|
+
enableApiFlavor ||
|
|
26
|
+
enableApiItem
|
|
25
27
|
|
|
26
28
|
if (!anyApiEnabled) {
|
|
27
29
|
return ''
|
|
@@ -33,6 +35,10 @@ export function generateApiPatcherScript(apiData, options = {}) {
|
|
|
33
35
|
furniture = {},
|
|
34
36
|
mapinfo = {},
|
|
35
37
|
slotitem = {},
|
|
38
|
+
slotitemEquiptype = {},
|
|
39
|
+
stype = {},
|
|
40
|
+
useitem = {},
|
|
41
|
+
payitem = {},
|
|
36
42
|
pictureBookShip = {},
|
|
37
43
|
pictureBookSlot = {},
|
|
38
44
|
questlist = {},
|
|
@@ -45,6 +51,10 @@ export function generateApiPatcherScript(apiData, options = {}) {
|
|
|
45
51
|
const activeFurniture = enableApiFurniture ? furniture : {}
|
|
46
52
|
const activeMapInfo = enableApiMapInfo ? mapinfo : {}
|
|
47
53
|
const activeSlot = enableApiShip ? slotitem : {}
|
|
54
|
+
const activeEquiptype = enableApiShip ? slotitemEquiptype : {}
|
|
55
|
+
const activeStype = enableApiShip ? stype : {}
|
|
56
|
+
const activeUseitem = enableApiItem ? useitem : {}
|
|
57
|
+
const activePayitem = enableApiItem ? payitem : {}
|
|
48
58
|
const activePBShip = enableApiPictureBook ? pictureBookShip : {}
|
|
49
59
|
const activePBSlot = enableApiPictureBook ? pictureBookSlot : {}
|
|
50
60
|
const activeQuest = enableApiQuest ? questlist : {}
|
|
@@ -61,6 +71,7 @@ export function generateApiPatcherScript(apiData, options = {}) {
|
|
|
61
71
|
enableApiMapInfo: ${enableApiMapInfo ? 'true' : 'false'},
|
|
62
72
|
enableApiPictureBook: ${enableApiPictureBook ? 'true' : 'false'},
|
|
63
73
|
enableApiFlavor: ${enableApiFlavor ? 'true' : 'false'},
|
|
74
|
+
enableApiItem: ${enableApiItem ? 'true' : 'false'},
|
|
64
75
|
}, window.__kanchs_api_options || {});
|
|
65
76
|
|
|
66
77
|
window.__kanchs_api_data = Object.assign({
|
|
@@ -69,6 +80,10 @@ export function generateApiPatcherScript(apiData, options = {}) {
|
|
|
69
80
|
furniture: ${JSON.stringify(activeFurniture)},
|
|
70
81
|
mapinfo: ${JSON.stringify(activeMapInfo)},
|
|
71
82
|
slotitem: ${JSON.stringify(activeSlot)},
|
|
83
|
+
slotitemEquiptype: ${JSON.stringify(activeEquiptype)},
|
|
84
|
+
stype: ${JSON.stringify(activeStype)},
|
|
85
|
+
useitem: ${JSON.stringify(activeUseitem)},
|
|
86
|
+
payitem: ${JSON.stringify(activePayitem)},
|
|
72
87
|
pictureBookShip: ${JSON.stringify(activePBShip)},
|
|
73
88
|
pictureBookSlot: ${JSON.stringify(activePBSlot)},
|
|
74
89
|
questlist: ${JSON.stringify(activeQuest)},
|
|
@@ -198,6 +213,105 @@ export function generateApiPatcherScript(apiData, options = {}) {
|
|
|
198
213
|
}
|
|
199
214
|
}
|
|
200
215
|
|
|
216
|
+
// 6. 装备类型分类母表 (start2.api_mst_slotitem_equiptype.json)
|
|
217
|
+
if (getOpt('enableApiShip') && Array.isArray(data.api_mst_slotitem_equiptype)) {
|
|
218
|
+
const EQUIPTYPE_DATA = getData('slotitemEquiptype');
|
|
219
|
+
for (let i = 0; i < data.api_mst_slotitem_equiptype.length; i++) {
|
|
220
|
+
const eq = data.api_mst_slotitem_equiptype[i];
|
|
221
|
+
if (!eq || eq.api_id === undefined) continue;
|
|
222
|
+
const patch = EQUIPTYPE_DATA[eq.api_id] || EQUIPTYPE_DATA[String(eq.api_id)];
|
|
223
|
+
if (patch && patch.api_name) {
|
|
224
|
+
const origName = eq.api_name;
|
|
225
|
+
eq.api_name = patch.api_name;
|
|
226
|
+
if (typeof window !== 'undefined' && window.__kanchs_dynamic_dict && origName) {
|
|
227
|
+
window.__kanchs_dynamic_dict[origName] = patch.api_name;
|
|
228
|
+
}
|
|
229
|
+
modified = true;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 7. 基础舰种母表 (start2.api_mst_stype.json)
|
|
235
|
+
if (getOpt('enableApiShip') && Array.isArray(data.api_mst_stype)) {
|
|
236
|
+
const STYPE_DATA = getData('stype');
|
|
237
|
+
for (let i = 0; i < data.api_mst_stype.length; i++) {
|
|
238
|
+
const st = data.api_mst_stype[i];
|
|
239
|
+
if (!st || st.api_id === undefined) continue;
|
|
240
|
+
const patch = STYPE_DATA[st.api_id] || STYPE_DATA[String(st.api_id)];
|
|
241
|
+
if (patch && patch.api_name) {
|
|
242
|
+
const origName = st.api_name;
|
|
243
|
+
st.api_name = patch.api_name;
|
|
244
|
+
if (typeof window !== 'undefined' && window.__kanchs_dynamic_dict && origName) {
|
|
245
|
+
window.__kanchs_dynamic_dict[origName] = patch.api_name;
|
|
246
|
+
}
|
|
247
|
+
modified = true;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// 8. 消耗道具母表 (start2.api_mst_useitem.json)
|
|
253
|
+
if (getOpt('enableApiItem') && Array.isArray(data.api_mst_useitem)) {
|
|
254
|
+
const USEITEM_DATA = getData('useitem');
|
|
255
|
+
for (let i = 0; i < data.api_mst_useitem.length; i++) {
|
|
256
|
+
const u = data.api_mst_useitem[i];
|
|
257
|
+
if (!u || u.api_id === undefined) continue;
|
|
258
|
+
const patch = USEITEM_DATA[u.api_id] || USEITEM_DATA[String(u.api_id)];
|
|
259
|
+
if (patch) {
|
|
260
|
+
if (patch.api_name) {
|
|
261
|
+
const origName = u.api_name;
|
|
262
|
+
u.api_name = patch.api_name;
|
|
263
|
+
if (typeof window !== 'undefined' && window.__kanchs_dynamic_dict && origName) {
|
|
264
|
+
window.__kanchs_dynamic_dict[origName] = patch.api_name;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (patch.api_description) {
|
|
268
|
+
u.api_description = patch.api_description;
|
|
269
|
+
if (Array.isArray(patch.api_description)) {
|
|
270
|
+
for (let dIdx = 0; dIdx < patch.api_description.length; dIdx++) {
|
|
271
|
+
const line = patch.api_description[dIdx];
|
|
272
|
+
if (typeof line === 'string' && line.trim()) {
|
|
273
|
+
registerBrVariants(line, line);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} else if (typeof patch.api_description === 'string') {
|
|
277
|
+
registerBrVariants(patch.api_description, patch.api_description);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
modified = true;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// 9. 商城与点券道具母表 (start2.api_mst_payitem.json)
|
|
286
|
+
if (getOpt('enableApiItem') && Array.isArray(data.api_mst_payitem)) {
|
|
287
|
+
const PAYITEM_DATA = getData('payitem');
|
|
288
|
+
for (let i = 0; i < data.api_mst_payitem.length; i++) {
|
|
289
|
+
const p = data.api_mst_payitem[i];
|
|
290
|
+
if (!p || p.api_id === undefined) continue;
|
|
291
|
+
const patch = PAYITEM_DATA[p.api_id] || PAYITEM_DATA[String(p.api_id)];
|
|
292
|
+
if (patch) {
|
|
293
|
+
if (patch.api_name) {
|
|
294
|
+
const origName = p.api_name;
|
|
295
|
+
p.api_name = patch.api_name;
|
|
296
|
+
if (typeof window !== 'undefined' && window.__kanchs_dynamic_dict && origName) {
|
|
297
|
+
window.__kanchs_dynamic_dict[origName] = patch.api_name;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (patch.api_description) {
|
|
301
|
+
const origDesc = p.api_description;
|
|
302
|
+
p.api_description = patch.api_description;
|
|
303
|
+
registerBrVariants(origDesc, patch.api_description);
|
|
304
|
+
}
|
|
305
|
+
if (patch.api_shop_description) {
|
|
306
|
+
const origShop = p.api_shop_description;
|
|
307
|
+
p.api_shop_description = patch.api_shop_description;
|
|
308
|
+
registerBrVariants(origShop, patch.api_shop_description);
|
|
309
|
+
}
|
|
310
|
+
modified = true;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
201
315
|
return modified;
|
|
202
316
|
}
|
|
203
317
|
|
|
@@ -298,19 +412,102 @@ export function generateApiPatcherScript(apiData, options = {}) {
|
|
|
298
412
|
}
|
|
299
413
|
|
|
300
414
|
function patchFlavor(data) {
|
|
301
|
-
if (!getOpt('enableApiFlavor') || !data ||
|
|
415
|
+
if (!getOpt('enableApiFlavor') || !data || typeof data !== 'object') return false;
|
|
302
416
|
let modified = false;
|
|
303
417
|
const FLAVOR_DATA = getData('flavorInfo');
|
|
418
|
+
const SHIP_DATA = getData('ship');
|
|
419
|
+
const dynamicDict = window.__kanchs_dynamic_dict || {};
|
|
420
|
+
|
|
421
|
+
// 1. 处理战斗台词与深海入场 (api_flavor_info 数组或单个对象)
|
|
422
|
+
if (data.api_flavor_info) {
|
|
423
|
+
const list = Array.isArray(data.api_flavor_info) ? data.api_flavor_info : [data.api_flavor_info];
|
|
424
|
+
for (let i = 0; i < list.length; i++) {
|
|
425
|
+
const f = list[i];
|
|
426
|
+
if (!f || typeof f !== 'object') continue;
|
|
427
|
+
|
|
428
|
+
// 尝试通过 api_voice_id 或 api_boss_ship_id 匹配汉化补丁
|
|
429
|
+
let patch = null;
|
|
430
|
+
if (f.api_voice_id !== undefined && f.api_voice_id !== null) {
|
|
431
|
+
patch = FLAVOR_DATA[f.api_voice_id] || FLAVOR_DATA[String(f.api_voice_id)];
|
|
432
|
+
}
|
|
433
|
+
if (!patch && f.api_boss_ship_id !== undefined && f.api_boss_ship_id !== null) {
|
|
434
|
+
patch = FLAVOR_DATA['ship_' + f.api_boss_ship_id] || FLAVOR_DATA[f.api_boss_ship_id];
|
|
435
|
+
}
|
|
304
436
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
437
|
+
const origMsg = f.api_message || '';
|
|
438
|
+
const origShip = f.api_ship_name || '';
|
|
439
|
+
const origClass = f.api_class_name || '';
|
|
440
|
+
|
|
441
|
+
if (patch) {
|
|
442
|
+
if (patch.api_message) {
|
|
443
|
+
f.api_message = patch.api_message;
|
|
444
|
+
registerBrVariants(origMsg, patch.api_message);
|
|
445
|
+
modified = true;
|
|
446
|
+
}
|
|
447
|
+
if (patch.api_class_name) {
|
|
448
|
+
f.api_class_name = patch.api_class_name;
|
|
449
|
+
if (origClass) dynamicDict[origClass] = patch.api_class_name;
|
|
450
|
+
modified = true;
|
|
451
|
+
}
|
|
452
|
+
if (patch.api_ship_name) {
|
|
453
|
+
f.api_ship_name = patch.api_ship_name;
|
|
454
|
+
if (origShip) dynamicDict[origShip] = patch.api_ship_name;
|
|
455
|
+
modified = true;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// 兜底 1: 若未由 patch 提供 ship_name 或 class_name,尝试通过舰船表与动态字典补全汉化
|
|
460
|
+
if (f.api_boss_ship_id && SHIP_DATA && SHIP_DATA[f.api_boss_ship_id] && SHIP_DATA[f.api_boss_ship_id].api_name) {
|
|
461
|
+
if (!patch || !patch.api_ship_name) {
|
|
462
|
+
f.api_ship_name = SHIP_DATA[f.api_boss_ship_id].api_name;
|
|
463
|
+
if (origShip) dynamicDict[origShip] = f.api_ship_name;
|
|
464
|
+
modified = true;
|
|
465
|
+
}
|
|
466
|
+
} else if (f.api_ship_name && dynamicDict[f.api_ship_name]) {
|
|
467
|
+
f.api_ship_name = dynamicDict[f.api_ship_name];
|
|
468
|
+
modified = true;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (f.api_class_name && dynamicDict[f.api_class_name]) {
|
|
472
|
+
f.api_class_name = dynamicDict[f.api_class_name];
|
|
473
|
+
modified = true;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// 兜底 2: 若 api_message 未被 voice_id 补丁命中,尝试字典直接替换
|
|
477
|
+
if ((!patch || !patch.api_message) && f.api_message) {
|
|
478
|
+
if (dynamicDict[f.api_message]) {
|
|
479
|
+
f.api_message = dynamicDict[f.api_message];
|
|
480
|
+
registerBrVariants(origMsg, f.api_message);
|
|
481
|
+
modified = true;
|
|
482
|
+
} else {
|
|
483
|
+
const clean = f.api_message.replace(/<br\\s*\\/?>/gi, '');
|
|
484
|
+
if (dynamicDict[clean]) {
|
|
485
|
+
f.api_message = dynamicDict[clean];
|
|
486
|
+
registerBrVariants(origMsg, f.api_message);
|
|
487
|
+
modified = true;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// 2. 处理海图进点气象/剧情提示 (api_cell_flavor 对象)
|
|
495
|
+
if (data.api_cell_flavor && typeof data.api_cell_flavor === 'object') {
|
|
496
|
+
const cf = data.api_cell_flavor;
|
|
497
|
+
if (cf.api_message) {
|
|
498
|
+
const orig = cf.api_message;
|
|
499
|
+
if (dynamicDict[orig]) {
|
|
500
|
+
cf.api_message = dynamicDict[orig];
|
|
501
|
+
registerBrVariants(orig, cf.api_message);
|
|
502
|
+
modified = true;
|
|
503
|
+
} else {
|
|
504
|
+
const clean = orig.replace(/<br\\s*\\/?>/gi, '');
|
|
505
|
+
if (dynamicDict[clean]) {
|
|
506
|
+
cf.api_message = dynamicDict[clean];
|
|
507
|
+
registerBrVariants(orig, cf.api_message);
|
|
508
|
+
modified = true;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
314
511
|
}
|
|
315
512
|
}
|
|
316
513
|
|
|
@@ -327,7 +524,12 @@ export function generateApiPatcherScript(apiData, options = {}) {
|
|
|
327
524
|
return url.indexOf('/api_start2/getData') !== -1 ||
|
|
328
525
|
url.indexOf('/api_get_member/picture_book') !== -1 ||
|
|
329
526
|
url.indexOf('/api_get_member/questlist') !== -1 ||
|
|
330
|
-
url.indexOf('/api_req_map/') !== -1
|
|
527
|
+
url.indexOf('/api_req_map/') !== -1 ||
|
|
528
|
+
url.indexOf('/api_req_sortie/') !== -1 ||
|
|
529
|
+
url.indexOf('/api_req_combined_battle/') !== -1 ||
|
|
530
|
+
url.indexOf('/api_req_battle_midnight/') !== -1 ||
|
|
531
|
+
url.indexOf('/api_req_practice/') !== -1 ||
|
|
532
|
+
url.indexOf('battle') !== -1;
|
|
331
533
|
}
|
|
332
534
|
|
|
333
535
|
function handleIntercept(target) {
|
|
@@ -363,8 +565,19 @@ export function generateApiPatcherScript(apiData, options = {}) {
|
|
|
363
565
|
modified = patchPictureBook(json.api_data, target._kanchs_body);
|
|
364
566
|
} else if (url.includes('/api_get_member/questlist')) {
|
|
365
567
|
modified = patchQuestlist(json.api_data);
|
|
366
|
-
}
|
|
367
|
-
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// 战斗、夜战、联合舰队或海图进点:检查并合流深海台词 (api_flavor_info) 与海况剧情 (api_cell_flavor)
|
|
571
|
+
if (
|
|
572
|
+
url.includes('/api_req_sortie/') ||
|
|
573
|
+
url.includes('/api_req_combined_battle/') ||
|
|
574
|
+
url.includes('/api_req_battle_midnight/') ||
|
|
575
|
+
url.includes('/api_req_practice/') ||
|
|
576
|
+
url.includes('/api_req_map/') ||
|
|
577
|
+
(json.api_data && (json.api_data.api_flavor_info || json.api_data.api_cell_flavor))
|
|
578
|
+
) {
|
|
579
|
+
const flavorModified = patchFlavor(json.api_data);
|
|
580
|
+
modified = modified || flavorModified;
|
|
368
581
|
}
|
|
369
582
|
|
|
370
583
|
if (modified) {
|
package/src/core/main-patcher.es
CHANGED
|
@@ -255,6 +255,7 @@ class MainPatcher {
|
|
|
255
255
|
enableApiMapInfo: configManager.get('enableApiMapInfo', true),
|
|
256
256
|
enableApiPictureBook: configManager.get('enableApiPictureBook', true),
|
|
257
257
|
enableApiFlavor: configManager.get('enableApiFlavor', true),
|
|
258
|
+
enableApiItem: configManager.get('enableApiItem', true),
|
|
258
259
|
}
|
|
259
260
|
const apiScript = generateApiPatcherScript(dataLoader.apiData, apiOptions)
|
|
260
261
|
if (apiScript) {
|
|
@@ -9,6 +9,7 @@ import { configManager } from '../config'
|
|
|
9
9
|
import { dataLoader } from '../loaders/data-loader'
|
|
10
10
|
import { resourceManager } from './resource-manager'
|
|
11
11
|
import { mainPatcher } from './main-patcher'
|
|
12
|
+
import { PLUGIN_VERSION } from '../constants'
|
|
12
13
|
|
|
13
14
|
const execAsync = util.promisify(exec)
|
|
14
15
|
|
|
@@ -264,7 +265,7 @@ class ResourceUpdater {
|
|
|
264
265
|
currentUrl,
|
|
265
266
|
{
|
|
266
267
|
headers: {
|
|
267
|
-
'User-Agent':
|
|
268
|
+
'User-Agent': `poi-plugin-kancolle-chs/${PLUGIN_VERSION}`,
|
|
268
269
|
Accept: '*/*',
|
|
269
270
|
},
|
|
270
271
|
},
|
|
@@ -606,7 +607,7 @@ class ResourceUpdater {
|
|
|
606
607
|
treeUrl,
|
|
607
608
|
{
|
|
608
609
|
headers: {
|
|
609
|
-
'User-Agent':
|
|
610
|
+
'User-Agent': `poi-plugin-kancolle-chs/${PLUGIN_VERSION}`,
|
|
610
611
|
Accept: 'application/vnd.github.v3+json',
|
|
611
612
|
},
|
|
612
613
|
timeout: 15000,
|
package/src/core/text-patcher.es
CHANGED
|
@@ -28,6 +28,9 @@ export function generateTextPatcherScript(textDict = {}, regexRules = [], option
|
|
|
28
28
|
const CUSTOM_FONT_NAME = ${JSON.stringify(customFontName || 'Microsoft YaHei')};
|
|
29
29
|
|
|
30
30
|
const KCT_TLS = ${JSON.stringify(activeDict)};
|
|
31
|
+
try {
|
|
32
|
+
Object.assign(window.__kanchs_dynamic_dict, KCT_TLS);
|
|
33
|
+
} catch(_) {}
|
|
31
34
|
const KCT_RAW_RULES = ${JSON.stringify(activeRegex)};
|
|
32
35
|
const KCT_REPLACEMENTS = [];
|
|
33
36
|
|
|
@@ -15,6 +15,10 @@ class DataLoader {
|
|
|
15
15
|
furniture: {}, // id -> { api_title, api_description }
|
|
16
16
|
mapinfo: {}, // id -> { api_name, api_opetext, api_infotext }
|
|
17
17
|
slotitem: {}, // id -> { api_name }
|
|
18
|
+
slotitemEquiptype: {}, // id -> { api_id, api_name }
|
|
19
|
+
stype: {}, // id -> { api_id, api_name }
|
|
20
|
+
useitem: {}, // id -> { api_id, api_name, api_description }
|
|
21
|
+
payitem: {}, // id -> { api_id, api_name, api_description, api_shop_description }
|
|
18
22
|
pictureBookShip: {}, // index_no -> { api_name, api_info, api_sinfo }
|
|
19
23
|
pictureBookSlot: {}, // index_no -> { api_name, api_info }
|
|
20
24
|
questlist: {}, // no -> { api_title, api_detail }
|
|
@@ -33,6 +37,10 @@ class DataLoader {
|
|
|
33
37
|
furnitureCount: 0,
|
|
34
38
|
mapCount: 0,
|
|
35
39
|
questCount: 0,
|
|
40
|
+
slotitemEquiptypeCount: 0,
|
|
41
|
+
stypeCount: 0,
|
|
42
|
+
useitemCount: 0,
|
|
43
|
+
payitemCount: 0,
|
|
36
44
|
pictureBookShipCount: 0,
|
|
37
45
|
pictureBookSlotCount: 0,
|
|
38
46
|
flavorCount: 0,
|
|
@@ -69,7 +77,7 @@ class DataLoader {
|
|
|
69
77
|
this.stats.isLoaded = true
|
|
70
78
|
this.stats.lastLoadedTime = new Date().toLocaleString()
|
|
71
79
|
console.log(
|
|
72
|
-
`[KancolleCHS] 汉化数据加载成功! 文本: ${this.stats.textCount} 条, 正则: ${this.stats.regexCount} 条, 任务: ${this.stats.questCount} 条, 舰船: ${this.stats.shipCount} 条`
|
|
80
|
+
`[KancolleCHS] 汉化数据加载成功! 文本: ${this.stats.textCount} 条, 正则: ${this.stats.regexCount} 条, 任务: ${this.stats.questCount} 条, 舰船: ${this.stats.shipCount} 条, 舰种: ${this.stats.stypeCount || 0} 条, 装备分类: ${this.stats.slotitemEquiptypeCount || 0} 条, 道具: ${this.stats.useitemCount || 0} 条, 商城: ${this.stats.payitemCount || 0} 条, 进点/深海台词: ${this.stats.flavorCount} 条`
|
|
73
81
|
)
|
|
74
82
|
return true
|
|
75
83
|
} catch (e) {
|
|
@@ -157,6 +165,10 @@ class DataLoader {
|
|
|
157
165
|
furniture: {},
|
|
158
166
|
mapinfo: {},
|
|
159
167
|
slotitem: {},
|
|
168
|
+
slotitemEquiptype: {},
|
|
169
|
+
stype: {},
|
|
170
|
+
useitem: {},
|
|
171
|
+
payitem: {},
|
|
160
172
|
pictureBookShip: {},
|
|
161
173
|
pictureBookSlot: {},
|
|
162
174
|
questlist: {},
|
|
@@ -164,10 +176,22 @@ class DataLoader {
|
|
|
164
176
|
}
|
|
165
177
|
|
|
166
178
|
const readFileSafe = async (fileName) => {
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
179
|
+
const candidates = [
|
|
180
|
+
path.join(apiDir, fileName),
|
|
181
|
+
path.join(sourceDir, 'text', fileName),
|
|
182
|
+
path.join(sourceDir, 'text', 'text', fileName),
|
|
183
|
+
path.join(sourceDir, 'api', fileName),
|
|
184
|
+
]
|
|
185
|
+
for (const p of candidates) {
|
|
186
|
+
if (fs.existsSync(p)) {
|
|
187
|
+
try {
|
|
188
|
+
const txt = await fs.readFile(p, 'utf8')
|
|
189
|
+
const parsed = safeParseJson(txt, null)
|
|
190
|
+
if (parsed) return parsed
|
|
191
|
+
} catch (_) {}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return null
|
|
171
195
|
}
|
|
172
196
|
|
|
173
197
|
// 1. 舰船与入手台词 (start2.api_mst_ship.json)
|
|
@@ -312,6 +336,73 @@ class DataLoader {
|
|
|
312
336
|
}
|
|
313
337
|
}
|
|
314
338
|
|
|
339
|
+
// 5.1 装备类型分类母表 (start2.api_mst_slotitem_equiptype.json)
|
|
340
|
+
const equiptypeList = await readFileSafe('start2.api_mst_slotitem_equiptype.json')
|
|
341
|
+
if (Array.isArray(equiptypeList)) {
|
|
342
|
+
for (const item of equiptypeList) {
|
|
343
|
+
if (item && item.api_id !== undefined) {
|
|
344
|
+
const entry = {
|
|
345
|
+
api_id: item.api_id,
|
|
346
|
+
api_name: item.api_name,
|
|
347
|
+
}
|
|
348
|
+
this.apiData.slotitemEquiptype[item.api_id] = entry
|
|
349
|
+
this.apiData.slotitemEquiptype[String(item.api_id)] = entry
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
this.stats.slotitemEquiptypeCount = Object.keys(this.apiData.slotitemEquiptype).filter((k) => !isNaN(k)).length
|
|
354
|
+
|
|
355
|
+
// 5.2 基础舰种母表 (start2.api_mst_stype.json)
|
|
356
|
+
const stypeList = await readFileSafe('start2.api_mst_stype.json')
|
|
357
|
+
if (Array.isArray(stypeList)) {
|
|
358
|
+
for (const item of stypeList) {
|
|
359
|
+
if (item && item.api_id !== undefined) {
|
|
360
|
+
const entry = {
|
|
361
|
+
api_id: item.api_id,
|
|
362
|
+
api_name: item.api_name,
|
|
363
|
+
}
|
|
364
|
+
this.apiData.stype[item.api_id] = entry
|
|
365
|
+
this.apiData.stype[String(item.api_id)] = entry
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
this.stats.stypeCount = Object.keys(this.apiData.stype).filter((k) => !isNaN(k)).length
|
|
370
|
+
|
|
371
|
+
// 5.3 消耗道具母表 (start2.api_mst_useitem.json)
|
|
372
|
+
const useitemList = await readFileSafe('start2.api_mst_useitem.json')
|
|
373
|
+
if (Array.isArray(useitemList)) {
|
|
374
|
+
for (const item of useitemList) {
|
|
375
|
+
if (item && item.api_id !== undefined) {
|
|
376
|
+
const entry = {
|
|
377
|
+
api_id: item.api_id,
|
|
378
|
+
api_name: item.api_name,
|
|
379
|
+
api_description: item.api_description,
|
|
380
|
+
}
|
|
381
|
+
this.apiData.useitem[item.api_id] = entry
|
|
382
|
+
this.apiData.useitem[String(item.api_id)] = entry
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
this.stats.useitemCount = Object.keys(this.apiData.useitem).filter((k) => !isNaN(k)).length
|
|
387
|
+
|
|
388
|
+
// 5.4 商城与点券道具母表 (start2.api_mst_payitem.json)
|
|
389
|
+
const payitemList = await readFileSafe('start2.api_mst_payitem.json')
|
|
390
|
+
if (Array.isArray(payitemList)) {
|
|
391
|
+
for (const item of payitemList) {
|
|
392
|
+
if (item && item.api_id !== undefined) {
|
|
393
|
+
const entry = {
|
|
394
|
+
api_id: item.api_id,
|
|
395
|
+
api_name: item.api_name,
|
|
396
|
+
api_description: item.api_description,
|
|
397
|
+
api_shop_description: item.api_shop_description,
|
|
398
|
+
}
|
|
399
|
+
this.apiData.payitem[item.api_id] = entry
|
|
400
|
+
this.apiData.payitem[String(item.api_id)] = entry
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
this.stats.payitemCount = Object.keys(this.apiData.payitem).filter((k) => !isNaN(k)).length
|
|
405
|
+
|
|
315
406
|
// 6. 任务数据 (questlist.json)
|
|
316
407
|
let questList = await readFileSafe('questlist.json')
|
|
317
408
|
if (!questList) {
|
|
@@ -372,19 +463,44 @@ class DataLoader {
|
|
|
372
463
|
this.stats.pictureBookSlotCount = Object.keys(this.apiData.pictureBookSlot).length
|
|
373
464
|
|
|
374
465
|
// 9. 进点台词与海况 (battle.api_flavor_info.json)
|
|
375
|
-
|
|
466
|
+
let flavorList = await readFileSafe('battle.api_flavor_info.json')
|
|
467
|
+
if (!flavorList) {
|
|
468
|
+
const altPaths = [
|
|
469
|
+
path.join(sourceDir, 'text', 'battle.api_flavor_info.json'),
|
|
470
|
+
path.join(sourceDir, 'text', 'text', 'battle.api_flavor_info.json'),
|
|
471
|
+
path.join(sourceDir, 'api', 'battle.api_flavor_info.json'),
|
|
472
|
+
]
|
|
473
|
+
for (const ap of altPaths) {
|
|
474
|
+
if (fs.existsSync(ap)) {
|
|
475
|
+
const txt = await fs.readFile(ap, 'utf8')
|
|
476
|
+
flavorList = safeParseJson(txt, null)
|
|
477
|
+
if (flavorList) break
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
376
481
|
if (Array.isArray(flavorList)) {
|
|
377
482
|
for (const item of flavorList) {
|
|
378
|
-
if (item
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
483
|
+
if (!item) continue
|
|
484
|
+
const entry = {
|
|
485
|
+
api_voice_id: item.api_voice_id,
|
|
486
|
+
api_message: item.api_message,
|
|
487
|
+
api_class_name: item.api_class_name,
|
|
488
|
+
api_ship_name: item.api_ship_name,
|
|
489
|
+
api_boss_ship_id: item.api_boss_ship_id,
|
|
490
|
+
}
|
|
491
|
+
if (item.api_voice_id !== undefined && item.api_voice_id !== null) {
|
|
492
|
+
this.apiData.flavorInfo[item.api_voice_id] = entry
|
|
493
|
+
this.apiData.flavorInfo[String(item.api_voice_id)] = entry
|
|
494
|
+
}
|
|
495
|
+
if (item.api_boss_ship_id !== undefined && item.api_boss_ship_id !== null) {
|
|
496
|
+
this.apiData.flavorInfo[`ship_${item.api_boss_ship_id}`] = entry
|
|
497
|
+
}
|
|
498
|
+
if (item.api_message_ja && item.api_message) {
|
|
499
|
+
this.textDict[item.api_message_ja] = item.api_message
|
|
384
500
|
}
|
|
385
501
|
}
|
|
386
502
|
}
|
|
387
|
-
this.stats.flavorCount = Object.keys(this.apiData.flavorInfo).length
|
|
503
|
+
this.stats.flavorCount = Object.keys(this.apiData.flavorInfo).filter((k) => !String(k).startsWith('ship_')).length
|
|
388
504
|
}
|
|
389
505
|
}
|
|
390
506
|
|
package/src/views/MainPanel.es
CHANGED
|
@@ -91,6 +91,7 @@ export class MainPanel extends Component {
|
|
|
91
91
|
toggleMode: 'restart', // 切换执行模式: 'restart'=清缓存并自动重启游戏, 'reload'=清缓存并刷新页面, 'none'=仅启停(不清缓存不刷新)
|
|
92
92
|
showUnconfiguredAlert: false, // 启用汉化时资源包未配置提示弹窗
|
|
93
93
|
showRestartConfirm: false, // 重启 POI 客户端二次确认弹窗
|
|
94
|
+
showResourceUpdateAlert: false, // 启动或检查检测到本地汉化资源有更新提醒弹窗
|
|
94
95
|
logs: [],
|
|
95
96
|
}
|
|
96
97
|
}
|
|
@@ -120,10 +121,14 @@ export class MainPanel extends Component {
|
|
|
120
121
|
}).catch(() => {})
|
|
121
122
|
}
|
|
122
123
|
|
|
123
|
-
//
|
|
124
|
-
|
|
124
|
+
// 启动时自动检查本地汉化资源更新 (支持弹窗提醒)
|
|
125
|
+
const shouldCheckResource = this.state.config.autoCheckResourceUpdate !== undefined
|
|
126
|
+
? this.state.config.autoCheckResourceUpdate
|
|
127
|
+
: this.state.config.autoCheckUpdate
|
|
128
|
+
|
|
129
|
+
if (shouldCheckResource && !this.hasAutoCheckedUpdates) {
|
|
125
130
|
this.hasAutoCheckedUpdates = true
|
|
126
|
-
this.handleCheckIncrementalUpdates().catch(() => {})
|
|
131
|
+
this.handleCheckIncrementalUpdates({ isAutoStartup: true }).catch(() => {})
|
|
127
132
|
}
|
|
128
133
|
|
|
129
134
|
// 自动在后台静默检查插件本体版本更新
|
|
@@ -314,7 +319,7 @@ export class MainPanel extends Component {
|
|
|
314
319
|
|
|
315
320
|
// 1. 重新读取数据
|
|
316
321
|
await dataLoader.loadAll(sourceDir)
|
|
317
|
-
this.addLog(`汉化字典载入完成: 文本 ${dataLoader.stats.textCount} 条, 正则 ${dataLoader.stats.regexCount} 条, 任务 ${dataLoader.stats.questCount} 条`)
|
|
322
|
+
this.addLog(`汉化字典载入完成: 文本 ${dataLoader.stats.textCount} 条, 正则 ${dataLoader.stats.regexCount} 条, 任务 ${dataLoader.stats.questCount} 条, 进点/深海台词 ${dataLoader.stats.flavorCount || 0} 条`)
|
|
318
323
|
|
|
319
324
|
// 2. 细分子模块挂载静态贴图与中文字体
|
|
320
325
|
await resourceManager.mountResources()
|
|
@@ -691,6 +696,7 @@ export class MainPanel extends Component {
|
|
|
691
696
|
enableApiMapInfo: Boolean(cfg.enableApiMapInfo),
|
|
692
697
|
enableApiPictureBook: Boolean(cfg.enableApiPictureBook),
|
|
693
698
|
enableApiFlavor: Boolean(cfg.enableApiFlavor),
|
|
699
|
+
enableApiItem: Boolean(cfg.enableApiItem !== false),
|
|
694
700
|
}
|
|
695
701
|
const js = `
|
|
696
702
|
(function() {
|
|
@@ -815,7 +821,8 @@ export class MainPanel extends Component {
|
|
|
815
821
|
}
|
|
816
822
|
|
|
817
823
|
// 3. 若总开关处于开启状态,且修改了文本或API拦截,自动重新编译部署 main.hack.js
|
|
818
|
-
|
|
824
|
+
const nonPatcherKeys = ['enableFontHack', 'enableImageHack', 'autoCheckUpdate', 'autoCheckResourceUpdate', 'downloadMirror', 'noticeAutoCloseSeconds']
|
|
825
|
+
if (this.state.config.enabled && !nonPatcherKeys.includes(key)) {
|
|
819
826
|
await mainPatcher.buildAndDeploy()
|
|
820
827
|
this.setState({ mainPatcherStatus: { ...mainPatcher.status } })
|
|
821
828
|
}
|
|
@@ -835,6 +842,7 @@ export class MainPanel extends Component {
|
|
|
835
842
|
enableApiMapInfo: true,
|
|
836
843
|
enableApiPictureBook: true,
|
|
837
844
|
enableApiFlavor: true,
|
|
845
|
+
enableApiItem: true,
|
|
838
846
|
enableFontHack: true,
|
|
839
847
|
enableImageHack: true,
|
|
840
848
|
}
|
|
@@ -860,6 +868,7 @@ export class MainPanel extends Component {
|
|
|
860
868
|
enableApiMapInfo: false,
|
|
861
869
|
enableApiPictureBook: false,
|
|
862
870
|
enableApiFlavor: false,
|
|
871
|
+
enableApiItem: false,
|
|
863
872
|
enableFontHack: false,
|
|
864
873
|
enableImageHack: false,
|
|
865
874
|
}
|
|
@@ -885,6 +894,7 @@ export class MainPanel extends Component {
|
|
|
885
894
|
enableApiMapInfo: true,
|
|
886
895
|
enableApiPictureBook: true,
|
|
887
896
|
enableApiFlavor: true,
|
|
897
|
+
enableApiItem: true,
|
|
888
898
|
enableFontHack: true,
|
|
889
899
|
enableImageHack: true,
|
|
890
900
|
}
|
|
@@ -1266,17 +1276,22 @@ export class MainPanel extends Component {
|
|
|
1266
1276
|
}
|
|
1267
1277
|
|
|
1268
1278
|
/**
|
|
1269
|
-
* 轻量化检查远端变动文件 (基于 Git Blob 哈希比对,免 Git
|
|
1279
|
+
* 轻量化检查远端变动文件 (基于 Git Blob 哈希比对,免 Git 环境,支持启动自检与弹窗提醒)
|
|
1270
1280
|
*/
|
|
1271
|
-
handleCheckIncrementalUpdates = async () => {
|
|
1281
|
+
handleCheckIncrementalUpdates = async (options = {}) => {
|
|
1282
|
+
const isAutoStartup = Boolean(options && options.isAutoStartup)
|
|
1272
1283
|
const sourceDir = configManager.resolveSourcePath()
|
|
1273
1284
|
if (!sourceDir) {
|
|
1274
|
-
|
|
1285
|
+
if (!isAutoStartup) {
|
|
1286
|
+
this.setState({ statusMessage: '尚未配置汉化资源包路径,请先指定或下载资源包', statusIntent: Intent.WARNING })
|
|
1287
|
+
}
|
|
1275
1288
|
return
|
|
1276
1289
|
}
|
|
1277
1290
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1291
|
+
if (!isAutoStartup) {
|
|
1292
|
+
this.setState({ isProcessing: true, statusMessage: '正在比对远端文件变动...', statusIntent: Intent.PRIMARY })
|
|
1293
|
+
}
|
|
1294
|
+
this.addLog(isAutoStartup ? '启动自检:正在通过文件哈希比对汉化资源远端更新...' : '正在通过文件哈希比对 GitHub 远端变动文件...')
|
|
1280
1295
|
|
|
1281
1296
|
try {
|
|
1282
1297
|
const res = await resourceUpdater.checkIncrementalUpdates({
|
|
@@ -1285,16 +1300,18 @@ export class MainPanel extends Component {
|
|
|
1285
1300
|
onLog: (msg) => this.addLog(msg),
|
|
1286
1301
|
})
|
|
1287
1302
|
|
|
1288
|
-
if (res.hasUpdate) {
|
|
1303
|
+
if (res.hasUpdate && res.changedFiles && res.changedFiles.length > 0) {
|
|
1289
1304
|
this.setState({
|
|
1290
1305
|
resourceUpdaterStatus: {
|
|
1291
1306
|
...this.state.resourceUpdaterStatus,
|
|
1292
1307
|
hasIncrementalUpdate: true,
|
|
1293
1308
|
changedFiles: res.changedFiles,
|
|
1294
1309
|
},
|
|
1295
|
-
|
|
1296
|
-
|
|
1310
|
+
showResourceUpdateAlert: false,
|
|
1311
|
+
statusMessage: `检测到 ${res.changedFiles.length} 个文件与远端有差异`,
|
|
1312
|
+
statusIntent: Intent.NONE,
|
|
1297
1313
|
})
|
|
1314
|
+
this.addLog(`检测到 ${res.changedFiles.length} 个汉化资源文件与远端有差异(已记录,不弹窗打扰)`)
|
|
1298
1315
|
} else {
|
|
1299
1316
|
this.setState({
|
|
1300
1317
|
resourceUpdaterStatus: {
|
|
@@ -1302,18 +1319,25 @@ export class MainPanel extends Component {
|
|
|
1302
1319
|
hasIncrementalUpdate: false,
|
|
1303
1320
|
changedFiles: [],
|
|
1304
1321
|
},
|
|
1305
|
-
statusMessage: '当前所有汉化文件均为最新,无变动!',
|
|
1306
|
-
statusIntent: Intent.SUCCESS,
|
|
1322
|
+
statusMessage: isAutoStartup ? '' : '当前所有汉化文件均为最新,无变动!',
|
|
1323
|
+
statusIntent: isAutoStartup ? Intent.NONE : Intent.SUCCESS,
|
|
1307
1324
|
})
|
|
1325
|
+
if (isAutoStartup) {
|
|
1326
|
+
this.addLog('启动自检完成:本地汉化资源已是最新版本,无变动文件')
|
|
1327
|
+
}
|
|
1308
1328
|
}
|
|
1309
1329
|
} catch (e) {
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1330
|
+
if (!isAutoStartup) {
|
|
1331
|
+
this.setState({
|
|
1332
|
+
statusMessage: `检查变动失败: ${e.message}`,
|
|
1333
|
+
statusIntent: Intent.DANGER,
|
|
1334
|
+
})
|
|
1335
|
+
}
|
|
1336
|
+
this.addLog(`检查汉化资源变动失败: ${e.message}`)
|
|
1315
1337
|
} finally {
|
|
1316
|
-
|
|
1338
|
+
if (!isAutoStartup) {
|
|
1339
|
+
this.setState({ isProcessing: false })
|
|
1340
|
+
}
|
|
1317
1341
|
}
|
|
1318
1342
|
}
|
|
1319
1343
|
|
|
@@ -1676,6 +1700,7 @@ export class MainPanel extends Component {
|
|
|
1676
1700
|
selectedMirror,
|
|
1677
1701
|
showTimeoutAlert,
|
|
1678
1702
|
showRestartConfirm,
|
|
1703
|
+
showResourceUpdateAlert,
|
|
1679
1704
|
logs,
|
|
1680
1705
|
} = this.state
|
|
1681
1706
|
|
|
@@ -2360,13 +2385,17 @@ export class MainPanel extends Component {
|
|
|
2360
2385
|
marginTop: '8px',
|
|
2361
2386
|
}}
|
|
2362
2387
|
>
|
|
2363
|
-
{resourceUpdaterStatus.changedFiles.map((file, idx) =>
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
<
|
|
2368
|
-
|
|
2369
|
-
|
|
2388
|
+
{resourceUpdaterStatus.changedFiles.map((file, idx) => {
|
|
2389
|
+
const filePath = typeof file === 'object' && file ? (file.path || '') : String(file || '');
|
|
2390
|
+
const fileCategory = typeof file === 'object' && file && file.category ? file.category : '文件';
|
|
2391
|
+
return (
|
|
2392
|
+
<div key={idx} style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '2px 0' }}>
|
|
2393
|
+
<span style={{ color: '#3dcc68', fontWeight: 'bold', minWidth: '40px' }}>[变动]</span>
|
|
2394
|
+
<span style={{ color: '#888', minWidth: '56px' }}>[{fileCategory}]</span>
|
|
2395
|
+
<span style={{ color: '#eee', wordBreak: 'break-all' }}>{filePath}</span>
|
|
2396
|
+
</div>
|
|
2397
|
+
);
|
|
2398
|
+
})}
|
|
2370
2399
|
</div>
|
|
2371
2400
|
</div>
|
|
2372
2401
|
)}
|
|
@@ -2398,9 +2427,9 @@ export class MainPanel extends Component {
|
|
|
2398
2427
|
|
|
2399
2428
|
<div style={{ marginTop: '8px' }}>
|
|
2400
2429
|
<Switch
|
|
2401
|
-
label="启动 POI
|
|
2402
|
-
checked={config.autoCheckUpdate}
|
|
2403
|
-
onChange={() => this.handleToggleOption('
|
|
2430
|
+
label="启动 POI 时自动检查本地汉化资源更新并在面板提示"
|
|
2431
|
+
checked={config.autoCheckResourceUpdate !== undefined ? config.autoCheckResourceUpdate : config.autoCheckUpdate}
|
|
2432
|
+
onChange={() => this.handleToggleOption('autoCheckResourceUpdate')}
|
|
2404
2433
|
/>
|
|
2405
2434
|
</div>
|
|
2406
2435
|
</div>
|
|
@@ -2417,8 +2446,8 @@ export class MainPanel extends Component {
|
|
|
2417
2446
|
<Tag intent={config.enableTextDict || config.enableTextRegex ? Intent.SUCCESS : Intent.NONE} minimal round small>
|
|
2418
2447
|
文字: {config.enableTextDict || config.enableTextRegex ? '开' : '关'}
|
|
2419
2448
|
</Tag>
|
|
2420
|
-
<Tag intent={config.enableApiQuest || config.enableApiShip || config.enableApiMission || config.enableApiFurniture || config.enableApiMapInfo || config.enableApiPictureBook || config.enableApiFlavor ? Intent.SUCCESS : Intent.NONE} minimal round small>
|
|
2421
|
-
数据: {config.enableApiQuest || config.enableApiShip || config.enableApiMission || config.enableApiFurniture || config.enableApiMapInfo || config.enableApiPictureBook || config.enableApiFlavor ? '开' : '关'}
|
|
2449
|
+
<Tag intent={config.enableApiQuest || config.enableApiShip || config.enableApiMission || config.enableApiFurniture || config.enableApiMapInfo || config.enableApiPictureBook || config.enableApiFlavor || config.enableApiItem ? Intent.SUCCESS : Intent.NONE} minimal round small>
|
|
2450
|
+
数据: {config.enableApiQuest || config.enableApiShip || config.enableApiMission || config.enableApiFurniture || config.enableApiMapInfo || config.enableApiPictureBook || config.enableApiFlavor || config.enableApiItem ? '开' : '关'}
|
|
2422
2451
|
</Tag>
|
|
2423
2452
|
<Tag intent={config.enableImageHack || config.enableFontHack || config.enableCustomFont ? Intent.SUCCESS : Intent.NONE} minimal round small>
|
|
2424
2453
|
静态与字体: {config.enableImageHack || config.enableFontHack || config.enableCustomFont ? '开' : '关'}
|
|
@@ -2479,7 +2508,7 @@ export class MainPanel extends Component {
|
|
|
2479
2508
|
onChange={() => this.handleToggleOption('enableApiQuest')}
|
|
2480
2509
|
/>
|
|
2481
2510
|
<Switch
|
|
2482
|
-
label="
|
|
2511
|
+
label="舰娘/舰种/装备与分类汉化"
|
|
2483
2512
|
checked={config.enableApiShip}
|
|
2484
2513
|
onChange={() => this.handleToggleOption('enableApiShip')}
|
|
2485
2514
|
/>
|
|
@@ -2508,6 +2537,11 @@ export class MainPanel extends Component {
|
|
|
2508
2537
|
checked={config.enableApiFlavor}
|
|
2509
2538
|
onChange={() => this.handleToggleOption('enableApiFlavor')}
|
|
2510
2539
|
/>
|
|
2540
|
+
<Switch
|
|
2541
|
+
label="消耗品与道具商城汉化"
|
|
2542
|
+
checked={config.enableApiItem}
|
|
2543
|
+
onChange={() => this.handleToggleOption('enableApiItem')}
|
|
2544
|
+
/>
|
|
2511
2545
|
</div>
|
|
2512
2546
|
</div>
|
|
2513
2547
|
|