Files
youle_app_ios_v2/ylgamehall/Source/Resource/SubGameDirectoryStore.swift
T
joywayerandClaude Opus 4.7 7be7a2abbc 子游戏 zip 升级链路完整对齐 msext(持久化目录 + advance + 版本比对)
之前新外壳的 SubGameDownloader 只看 index.html 是否存在,缺这两个关键行为:
- gamefilepath 持久化(msext NSUserDefaults["game_name"] → gamefilepath)
- 远端 game_version > 本地 version.xml 时升级 + 目录末尾追加 "1"
  (msext gameController.m:1414 等价 [NSString stringWithFormat:@"%@1", gamefilepath])

本次完整补齐:

1. 新增 SubGameDirectoryStore:UserDefaults 持久化 directory → actualDir 映射
   - current(forKey:) / advance(forKey:) / saveInitialIfNeeded(forKey:)
   - nonisolated 让 actor / MainActor 都能直接调

2. SubGameDownloader 三分支决策(msext gameController.m:1239-1255 + uplevel: 等价):
   - 目录不存在(首装)→ 下载到 currentDir,不 advance
   - 目录存在 + 远端 > 本地 → advance + 下载到新目录
   - 远端 ≤ 本地 → 复用 currentDir
   API 改为按入参(directoryKey / gameStart / remoteVersion / remoteZipURL)调用,
   返回 Outcome.actualDirectory 暴露实际生效目录名。

3. LocalAudioHandler.register 的 assetsRoot 改 @MainActor closure
   srcIsloop 每次调用时取最新值,让子游戏升级(effectiveGameDir 末尾追加 "1")
   后下一次 srcIsloop 自动用新目录路径。

4. SubGameViewController 引入 effectiveGameDir:
   - init 时同步从 SubGameDirectoryStore 读初始值(首次=request.gameDir)
   - boot pipeline 内调 ensureReady,从 outcome 同步升级后的新目录名
   - loadFileURL / AppDataWriter / srcIsloop closure 全部走 effectiveGameDir
   - resolveBoot 返回 (lobbyResolved, subGameResolved) 完整 ResolvedVersion,
     给 ensureReady 用 gameVersion 做版本比对

5. WebContainerViewController 大厅侧 LocalAudioHandler 改 closure 形式(路径不变)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-23 23:04:57 +08:00

45 lines
2.0 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// SubGameDirectoryStore.swift
// ylgamehall
//
// 子游戏目录名持久化映射:H5 传的 Gamedirectory(也是 gameStart 同名)→ 实际沙盒
// 目录名。与 daoqi msext gameController.m:1414 / 2183-2188 等价:
// - 首次安装:actualDir = directory,写入 NSUserDefaults
// - 每次 zip 升级(远端 game_version > 本地 version.xml):actualDir 末尾追加 "1"
// 新版本解压到新目录,旧目录残留在沙盒(msext 同款"追加而非原子替换"策略)
//
// 存储约定:UserDefaults key = "ylgh.subGameDir.<directory>"value = 实际目录名
//
import Foundation
/// UserDefaults 线程安全,所有方法 nonisolated 让 actor / MainActor / 后台线程都能直接调用。
public enum SubGameDirectoryStore {
private static let keyPrefix = "ylgh.subGameDir."
/// 当前实际目录名。已持久化 → 返回持久化值;未持久化 → 返回 directory 本身
/// (对应 msext NSUserDefaults 缺 key 时 gamefilepath = gamename 的默认)。
nonisolated public static func current(forKey directory: String) -> String {
UserDefaults.standard.string(forKey: keyPrefix + directory) ?? directory
}
/// 触发升级:末尾追加 "1",写回 UserDefaults,返回新值。
/// msext gameController.m:1414 等价 `gamefilepath = [NSString stringWithFormat:@"%@1", gamefilepath]`。
@discardableResult
nonisolated public static func advance(forKey directory: String) -> String {
let next = current(forKey: directory) + "1"
UserDefaults.standard.set(next, forKey: keyPrefix + directory)
return next
}
/// 首次访问时把 directory 自身写入(与 msext gameController.m:2187
/// SaveDefaultInfo 等价)。后续 advance 会基于此值追加。
nonisolated public static func saveInitialIfNeeded(forKey directory: String) {
let k = keyPrefix + directory
if UserDefaults.standard.string(forKey: k) == nil {
UserDefaults.standard.set(directory, forKey: k)
}
}
}