poi-plugin-kancolle-chs 1.2.0 → 1.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.
@@ -1,6 +1,6 @@
1
1
  /* ========================================================================= *
2
2
  * 砍口垒汉化计划PLUS - POI 原生引擎注入补丁 *
3
- * 编译时间: 2026/9/13 02:05:30 *
3
+ * 编译时间: 2026/9/13 02:23:23 *
4
4
  * 词条条数: 文本 2840 | 正则 357 | 任务 655 *
5
5
  * ========================================================================= */
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poi-plugin-kancolle-chs",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "砍口垒汉化计划PLUS POI 原生独立插件:提供全界面文本替换、正则动态替换、KCSAPI 响应合流、中文字体与贴图魔改、自定义字体适配与官方资源更新",
5
5
  "main": "index.es",
6
6
  "files": [
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.2.0'
18
+ let pkgVersion = '1.3.0'
19
19
  try {
20
20
  const pkg = require('../package.json')
21
21
  if (pkg && pkg.version) pkgVersion = pkg.version
@@ -72,7 +72,7 @@ export const DEFAULT_CONFIG = {
72
72
  enableApiFlavor: true, // 海域进点气象与深海台词 (battle.api_flavor_info.json)
73
73
 
74
74
  // --- 3. 静态魔改资产细分开关 ---
75
- enableFontHack: true, // 优美中文字体魔改 (A-OTF-UDShinGoPro*.hack.woff2)
75
+ enableFontHack: true, // 默认中文字体替换(思源黑体)
76
76
  enableImageHack: true, // 界面贴图与图标魔改 (.hack.png / .hack.jpg)
77
77
 
78
78
  // --- 4. 自定义字体优先适配 ---
@@ -83,13 +83,15 @@ export const DEFAULT_CONFIG = {
83
83
 
84
84
  // --- 5. 官方资源与更新管理 ---
85
85
  autoCheckUpdate: true, // 插件启动时是否在后台自动检查更新
86
+ downloadMirror: 'direct', // 资源下载加速镜像,默认 'direct' (GitHub 官方直连)
86
87
 
87
88
  // --- 6. 游戏运行帧率上限调节 ---
88
89
  fpsLimit: 60, // 游戏帧率上限 (默认 60,可选 60, 120, 165, 240)
89
90
 
90
- // --- 7. 界面自适应与布局排版模式 ---
91
+ // --- 7. 综合设置与界面布局模式 ---
91
92
  layoutDensity: 'auto', // 'auto'(自适应), 'compact'(紧凑模式), 'spacious'(宽屏模式)
92
93
  panelMaxWidth: '100%', // 面板最大宽度: '100%', '880px', '1080px'
94
+ noticeAutoCloseSeconds: 20, // 提示与通知默认自动向上折叠关闭时间 (秒,0 为不自动关闭)
93
95
 
94
96
  // --- 8. 其他魔改功能 (独立路径优先加载第三方魔改资源) ---
95
97
  enableCustomHack: false, // 是否启用其他第三方魔改功能
@@ -116,7 +118,18 @@ export const PRESET_LAYOUT_DENSITY = [
116
118
 
117
119
  // 界面最大宽度预设
118
120
  export const PRESET_MAX_WIDTH = [
119
- { label: '100% 铺满', value: '100%' },
121
+ { label: '500px 窄屏', value: '500px' },
120
122
  { label: '880px 适中', value: '880px' },
121
- { label: '1080px 宽屏', value: '1080px' },
123
+ { label: '1200px 宽屏', value: '1200px' },
124
+ { label: '1600px 超宽', value: '1600px' },
125
+ { label: '100% 铺满', value: '100%' },
126
+ ]
127
+
128
+ // 提示自动折叠关闭时间预设
129
+ export const PRESET_NOTICE_AUTOCLOSE = [
130
+ { label: '5秒 极速', value: 5 },
131
+ { label: '10秒 适中', value: 10 },
132
+ { label: '20秒 默认', value: 20 },
133
+ { label: '30秒 宽裕', value: 30 },
134
+ { label: '从不自动折叠', value: 0 },
122
135
  ]
@@ -16,10 +16,61 @@ class ResourceManager {
16
16
  }
17
17
 
18
18
  /**
19
- * 获取系统中所有可能存在的 POI 缓存目录路径 (包括用户自定义缓存路径、默认 MyCache 与 Downloads 等)
19
+ * 判断指定路径是否位于用户系统的 Downloads (下载) 目录中
20
+ */
21
+ isDownloadsPath(targetPath) {
22
+ if (!targetPath || typeof targetPath !== 'string') return false
23
+ try {
24
+ const home = process.env.HOME || process.env.USERPROFILE || ''
25
+ if (!home) return false
26
+ const downloads = path.resolve(path.join(home, 'Downloads')).toLowerCase()
27
+ const resolved = path.resolve(targetPath.trim()).toLowerCase()
28
+ return resolved === downloads || resolved.startsWith(downloads + path.sep)
29
+ } catch (_) {
30
+ return false
31
+ }
32
+ }
33
+
34
+ /**
35
+ * 自动清理可能错误创建在 Downloads 目录下的 KanColle 临时挂载点
36
+ */
37
+ cleanSpuriousDownloadsKanColle() {
38
+ try {
39
+ const home = process.env.HOME || process.env.USERPROFILE || ''
40
+ if (!home) return
41
+ const dlKc = path.join(home, 'Downloads', 'KanColle')
42
+ if (fs.existsSync(dlKc)) {
43
+ const cleanRec = (dir) => {
44
+ if (!fs.existsSync(dir)) return
45
+ const items = fs.readdirSync(dir)
46
+ for (const item of items) {
47
+ const full = path.join(dir, item)
48
+ try {
49
+ const st = fs.lstatSync(full)
50
+ if (st.isSymbolicLink()) {
51
+ fs.unlinkSync(full)
52
+ } else if (st.isDirectory()) {
53
+ cleanRec(full)
54
+ fs.rmdirSync(full)
55
+ } else {
56
+ fs.unlinkSync(full)
57
+ }
58
+ } catch (_) {}
59
+ }
60
+ }
61
+ cleanRec(dlKc)
62
+ if (fs.existsSync(dlKc)) fs.rmdirSync(dlKc)
63
+ console.log('[KancolleCHS] 已安全清理 Downloads 目录下的 KanColle 临时挂载点')
64
+ }
65
+ } catch (_e) {}
66
+ }
67
+
68
+ /**
69
+ * 获取系统中所有可能存在的 POI 缓存目录路径 (包括用户自定义缓存路径、默认 MyCache 等,严格排除 Downloads)
20
70
  */
21
71
  getAllPoiCacheDirs() {
22
72
  const dirs = new Set()
73
+ this.cleanSpuriousDownloadsKanColle()
23
74
 
24
75
  // 1. 若运行于 POI 渲染进程,优先从 POI 配置读取
25
76
  try {
@@ -35,7 +86,9 @@ class ResourceManager {
35
86
  } catch (_) {}
36
87
  }
37
88
  if (p && typeof p === 'string' && p.trim() && p !== 'null' && p !== 'undefined' && fs.existsSync(p)) {
38
- dirs.add(path.resolve(p))
89
+ if (!this.isDownloadsPath(p)) {
90
+ dirs.add(path.resolve(p))
91
+ }
39
92
  }
40
93
 
41
94
  // 检查 POI 全局默认缓存路径 (POI 源码: global.DEFAULT_CACHE_PATH)
@@ -43,7 +96,9 @@ class ResourceManager {
43
96
  try {
44
97
  const defaultCacheGlobal = window.remote.getGlobal('DEFAULT_CACHE_PATH')
45
98
  if (defaultCacheGlobal && typeof defaultCacheGlobal === 'string' && fs.existsSync(defaultCacheGlobal)) {
46
- dirs.add(path.resolve(defaultCacheGlobal))
99
+ if (!this.isDownloadsPath(defaultCacheGlobal)) {
100
+ dirs.add(path.resolve(defaultCacheGlobal))
101
+ }
47
102
  }
48
103
  } catch (_) {}
49
104
  try {
@@ -75,7 +130,9 @@ class ResourceManager {
75
130
  let cleaned = line.replace(/^\s*path:\s*/, '').trim()
76
131
  cleaned = cleaned.replace(/^['"]|['"]$/g, '').replace(/\\\\/g, '\\').trim()
77
132
  if (cleaned && cleaned !== 'null' && cleaned !== 'undefined' && fs.existsSync(cleaned)) {
78
- dirs.add(path.resolve(cleaned))
133
+ if (!this.isDownloadsPath(cleaned)) {
134
+ dirs.add(path.resolve(cleaned))
135
+ }
79
136
  }
80
137
  break
81
138
  } else if (!line.startsWith(' ') && !line.startsWith('\t')) {
@@ -91,7 +148,10 @@ class ResourceManager {
91
148
  if (fs.existsSync(cacheDir)) dirs.add(path.resolve(cacheDir))
92
149
  }
93
150
 
94
- const list = Array.from(dirs).filter((d) => typeof d === 'string' && d.trim() && d !== 'null' && d !== 'undefined')
151
+ const list = Array.from(dirs)
152
+ .filter((d) => typeof d === 'string' && d.trim() && d !== 'null' && d !== 'undefined')
153
+ .filter((d) => !this.isDownloadsPath(d))
154
+
95
155
  if (list.length === 0) {
96
156
  if (userDataDir) {
97
157
  list.push(path.resolve(path.join(userDataDir, 'MyCache')))
@@ -105,6 +165,12 @@ class ResourceManager {
105
165
  }
106
166
 
107
167
  getPoiCacheDir() {
168
+ this.cleanSpuriousDownloadsKanColle()
169
+ const userDataDir = getPoiUserDataDir()
170
+ const defaultSafePath = userDataDir
171
+ ? path.resolve(path.join(userDataDir, 'MyCache'))
172
+ : path.resolve(path.join(process.env.USERPROFILE || process.env.HOME || '.', '.poi', 'MyCache'))
173
+
108
174
  try {
109
175
  if (typeof window !== 'undefined') {
110
176
  let val = null
@@ -118,6 +184,15 @@ class ResourceManager {
118
184
  } catch (_) {}
119
185
  }
120
186
  if (val && typeof val === 'string' && val.trim() && val !== 'null' && val !== 'undefined') {
187
+ if (this.isDownloadsPath(val)) {
188
+ console.warn('[KancolleCHS] 检测到 POI 缓存路径指向 Downloads,强制重置为 MyCache 以保护下载目录')
189
+ try {
190
+ if (window.config && typeof window.config.set === 'function') {
191
+ window.config.set('poi.misc.cache.path', defaultSafePath)
192
+ }
193
+ } catch (_) {}
194
+ return defaultSafePath
195
+ }
121
196
  return path.resolve(val)
122
197
  }
123
198
 
@@ -125,7 +200,9 @@ class ResourceManager {
125
200
  try {
126
201
  const defaultCacheGlobal = window.remote.getGlobal('DEFAULT_CACHE_PATH')
127
202
  if (defaultCacheGlobal && typeof defaultCacheGlobal === 'string' && defaultCacheGlobal.trim()) {
128
- return path.resolve(defaultCacheGlobal)
203
+ if (!this.isDownloadsPath(defaultCacheGlobal)) {
204
+ return path.resolve(defaultCacheGlobal)
205
+ }
129
206
  }
130
207
  } catch (_) {}
131
208
  try {
@@ -139,19 +216,13 @@ class ResourceManager {
139
216
  } catch (_e) {}
140
217
 
141
218
  const allDirs = this.getAllPoiCacheDirs()
142
- if (allDirs.length > 0 && typeof allDirs[0] === 'string' && allDirs[0].trim()) {
143
- return path.resolve(allDirs[0])
219
+ for (const d of allDirs) {
220
+ if (d && typeof d === 'string' && d.trim() && !this.isDownloadsPath(d)) {
221
+ return path.resolve(d)
222
+ }
144
223
  }
145
224
 
146
- const userDataDir = getPoiUserDataDir()
147
- if (userDataDir) {
148
- return path.resolve(path.join(userDataDir, 'MyCache'))
149
- }
150
- const home = process.env.HOME || process.env.USERPROFILE || ''
151
- if (home) {
152
- return path.resolve(path.join(home, '.poi', 'MyCache'))
153
- }
154
- return path.resolve('.')
225
+ return defaultSafePath
155
226
  }
156
227
 
157
228
  /**
@@ -608,11 +679,40 @@ class ResourceManager {
608
679
  * 清理游戏运行与网络缓存 (安全清除 Electron Webview 缓存与会话数据,复位挂载,防止旧缓存阻碍汉化生效)
609
680
  */
610
681
  async clearGameCache() {
611
- // 1. 清理 Electron 底层 defaultSession 内存与磁盘缓存
682
+ // 1. 全方位深度清理 Electron 底层会话缓存 (涵盖 defaultSession、当前窗口及 Webview 独立会话)
612
683
  try {
613
- if (typeof window !== 'undefined' && window.remote && window.remote.session) {
614
- await window.remote.session.defaultSession.clearCache()
615
- console.log('[KancolleCHS-PLUS] 成功清理 Electron Webview 会话缓存')
684
+ if (typeof window !== 'undefined') {
685
+ const remote = window.remote ||
686
+ (window.require && window.require('@electron/remote')) ||
687
+ (window.require && window.require('electron') && window.require('electron').remote)
688
+
689
+ if (remote) {
690
+ if (remote.session && remote.session.defaultSession && typeof remote.session.defaultSession.clearCache === 'function') {
691
+ await remote.session.defaultSession.clearCache()
692
+ }
693
+ if (typeof remote.getCurrentWebContents === 'function') {
694
+ const curSession = remote.getCurrentWebContents().session
695
+ if (curSession && typeof curSession.clearCache === 'function') {
696
+ await curSession.clearCache()
697
+ }
698
+ }
699
+ if (remote.session && remote.session.defaultSession && typeof remote.session.defaultSession.clearStorageData === 'function') {
700
+ await remote.session.defaultSession.clearStorageData({
701
+ storages: ['cachestorage', 'shadercache']
702
+ }).catch(() => null)
703
+ }
704
+ }
705
+
706
+ const webview = (window.getStore && window.getStore('layout.webview.ref')) ||
707
+ document.querySelector('kan-game webview') ||
708
+ document.querySelector('webview')
709
+ if (webview && typeof webview.getWebContents === 'function') {
710
+ const wc = webview.getWebContents()
711
+ if (wc && wc.session && typeof wc.session.clearCache === 'function') {
712
+ await wc.session.clearCache()
713
+ }
714
+ }
715
+ console.log('[KancolleCHS-PLUS] 成功全方位清理 Electron Webview 与会话缓存')
616
716
  }
617
717
  } catch (e) {
618
718
  console.warn('[KancolleCHS-PLUS] 清理 Electron 会话缓存异常:', e)