实现子游戏按需下载,修复点子游戏白屏(§11.1 路径A)
根因:整包 gamehall.zip 顶层只含 gamehall,子游戏需按需单独下载;原 switchGame 直接 loadUrl 不存在的目录 → ArkWeb invalidFileUrl → 白屏。 对齐 Android NewwebviewActivity 的 updategamezip: - ConfigManager.resolveGame(remote, gameid):以 gamedownloadurl 为 gameid 经 agent→game→channel→market 分层解析子游戏 game_zip/game_version(复用 VersionResolver)。 - ResourceManager.updateSubgame:下载→暂存解压→校验 <dir>/index.html→原子换入 urlpath/<dir>。 另加 subgameInstalled/subgameLocalVersion/subgameLocalGameId。 - BridgeGameContainer.switchGame 改 async + prepareSubgame:目录缺失先下载、已装比对远程 版本更高才更新;下载期复用启动页同款金色进度条;远程配置 10 分钟缓存(对齐 gameconfigtime)。 - SwitchGamePayload 增 gameId(gamedownloadurl)。 真机验证:点三个老K → 下载 sangelaok.zip(9.4M) → 解压加载,子游戏正常渲染 (V1.155 与配置 game_version=155 一致);日志不再 invalidFileUrl。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e75f567948
commit
de5b950d9b
@@ -102,6 +102,63 @@ export class ResourceManager {
|
||||
return this.readVersionXml().gameId;
|
||||
}
|
||||
|
||||
// ── 子游戏(§11.1 路径 A 按需下载)─────────────────────────────────────────
|
||||
|
||||
/** 子游戏入口路径 `<urlpath>/<dir>/index.html`。 */
|
||||
subgameIndexPath(dir: string): string {
|
||||
return `${this.cachedPaths.urlpath}/${dir}/index.html`;
|
||||
}
|
||||
|
||||
/** 子游戏资源是否就绪(index.html 存在)。 */
|
||||
subgameInstalled(dir: string): boolean {
|
||||
return FileSystem.exists(this.subgameIndexPath(dir));
|
||||
}
|
||||
|
||||
/** 子游戏本地 version.xml 信息(缺失 → 空信息)。 */
|
||||
private subgameVersionXml(dir: string): VersionXmlInfo {
|
||||
const p: string = `${this.cachedPaths.urlpath}/${dir}/version.xml`;
|
||||
return FileSystem.exists(p) ? VersionXml.parse(FileSystem.readText(p)) : { version: 0, gameName: '', gameId: '' };
|
||||
}
|
||||
|
||||
/** 子游戏本地版本号(缺失 0)。 */
|
||||
subgameLocalVersion(dir: string): number {
|
||||
return this.subgameVersionXml(dir).version;
|
||||
}
|
||||
|
||||
/** 子游戏本地 version.xml 的 game id(查更新时优先用它解析远程版本;缺失 '')。 */
|
||||
subgameLocalGameId(dir: string): string {
|
||||
return this.subgameVersionXml(dir).gameId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载并安装子游戏 zip 到 `urlpath`(复刻 Android runzip:删旧目录 → 解压到 urlpath)。
|
||||
* zip 顶层即 `<dir>/`,解压后得 `urlpath/<dir>/...`。**原子化**:下载→解压暂存→校验
|
||||
* `<dir>/index.html`→删旧换入,任一步失败旧资源保持不动。
|
||||
*/
|
||||
async updateSubgame(dir: string, downloadUrl: string, onProgress?: ProgressCallback): Promise<void> {
|
||||
const url: string = downloadUrl.includes('?') ? downloadUrl : `${downloadUrl}?a=${Date.now()}`;
|
||||
const zipPath: string = `${this.cachedPaths.upurlpath}/dowlod_zip/${Date.now()}_${dir}.zip`;
|
||||
const staging: string = `${this.cachedPaths.urlpath}/.staging_${dir}_${Date.now()}`;
|
||||
const target: string = `${this.cachedPaths.urlpath}/${dir}`;
|
||||
try {
|
||||
await Downloader.download(url, zipPath, onProgress);
|
||||
FileSystem.rmrf(staging);
|
||||
FileSystem.ensureDir(staging);
|
||||
await Unzipper.unzip(zipPath, staging);
|
||||
const staged: string = `${staging}/${dir}`;
|
||||
if (!FileSystem.exists(`${staged}/index.html`)) {
|
||||
throw new Error(`subgame package missing ${dir}/index.html`);
|
||||
}
|
||||
FileSystem.rmrf(target);
|
||||
FileSystem.ensureDir(this.cachedPaths.urlpath);
|
||||
FileSystem.rename(staged, target);
|
||||
ResourceManager.log.i(`subgame ${dir} updated from ${url}`);
|
||||
} finally {
|
||||
FileSystem.rmrf(zipPath);
|
||||
FileSystem.rmrf(staging);
|
||||
}
|
||||
}
|
||||
|
||||
/** 持久化路径到 KvStore(供容器/重启读取)。 */
|
||||
async persistPaths(): Promise<void> {
|
||||
this.kv.putString(KEY_URLPATH, this.cachedPaths.urlpath);
|
||||
|
||||
Reference in New Issue
Block a user