diff --git a/docs/Asset.md b/docs/Asset.md index 17e0dbc..42c37da 100644 --- a/docs/Asset.md +++ b/docs/Asset.md @@ -78,7 +78,7 @@ public static getByUUID(uuid: string): T public static releasePath(path: string, bundlename: string = "resources"): void /** 按 bundle 和 文件夹释放资源 */ -public static async releaseDir(dir: string, bundlename: string = "resources", asset: typeof Asset): Promise +public static releaseDir(dir: string, bundlename: string = "resources", asset: typeof Asset): Promise /** 按 uuid 释放资源 */ public static releaseUUID(uuid: string): void diff --git a/docs/UI.md b/docs/UI.md index 23bd820..434ff24 100644 --- a/docs/UI.md +++ b/docs/UI.md @@ -199,7 +199,7 @@ export interface IPackageConfigRes { /** * 异步打开一个窗口 (如果UI包的资源未加载, 会自动加载 配合 WindowManager.initPackageConfig一起使用) */ - public static async showWindow(windowName: string, userdata?: any): Promise + public static showWindow(windowName: string, userdata?: any): Promise /** * 打开一个窗口 (用于已加载过资源的窗口) diff --git a/src/asset/AssetLoader.ts b/src/asset/AssetLoader.ts index e0f66bb..12d3f37 100644 --- a/src/asset/AssetLoader.ts +++ b/src/asset/AssetLoader.ts @@ -250,21 +250,27 @@ export class AssetLoader { * 加载资源 * @internal */ - private async loadItem(index: number): Promise { + private loadItem(index: number): void { let item = this._items[index]; item.status = StateType.Loading; this._parallel++; - - let bundle = null; if (item.bundle == "resources") { - bundle = resources; + if (item.isFile) { + this.loadFile(index, resources); + } else { + this.loadDir(index, resources); + } } else { - bundle = await AssetUtils.loadBundle(item.bundle); - } - if (item.isFile) { - this.loadFile(index, bundle); - } else { - this.loadDir(index, bundle); + AssetUtils.loadBundle(item.bundle).then((bundle: AssetManager.Bundle) => { + if (item.isFile) { + this.loadFile(index, bundle); + } else { + this.loadDir(index, bundle); + } + }).catch((err: Error) => { + log(`load bundle error, bundle:${item.bundle}, filename:${item.path}`); + item.status = StateType.Error; + }); } } diff --git a/src/asset/AssetPool.ts b/src/asset/AssetPool.ts index 6c3fb41..f2ab82a 100644 --- a/src/asset/AssetPool.ts +++ b/src/asset/AssetPool.ts @@ -75,17 +75,26 @@ export class AssetPool { } /** 按 bundle 和 文件夹释放资源 */ - public static async releaseDir(dir: string, bundlename: string = "resources", asset: typeof Asset): Promise { - let bundle = null; - if (bundlename == "resources") { - bundle = resources; - } else { - bundle = await AssetUtils.loadBundle(bundlename); - } - let uuids = AssetUtils.getUUIDs(dir, asset, bundle); - for (const uuid of uuids) { - this.releaseUUID(uuid); - } + public static releaseDir(dir: string, bundlename: string = "resources", asset: typeof Asset): Promise { + return new Promise((resolve, reject) => { + if (bundlename == "resources") { + let uuids = AssetUtils.getUUIDs(dir, asset, resources); + for (const uuid of uuids) { + this.releaseUUID(uuid); + } + resolve(true); + } else { + AssetUtils.loadBundle(bundlename).then((bundle: AssetManager.Bundle) => { + let uuids = AssetUtils.getUUIDs(dir, asset, bundle); + for (const uuid of uuids) { + this.releaseUUID(uuid); + } + resolve(true); + }).catch((err: Error) => { + reject(false); + }); + } + }); } /** 按 uuid 释放资源 */ diff --git a/src/asset/AssetUtils.ts b/src/asset/AssetUtils.ts index 4eb705a..040be2e 100644 --- a/src/asset/AssetUtils.ts +++ b/src/asset/AssetUtils.ts @@ -33,7 +33,7 @@ export class AssetUtils { } /** 加载 bundle */ - public static async loadBundle(bundlename: string): Promise { + public static loadBundle(bundlename: string): Promise { return new Promise((resolve, reject) => { let bundle = assetManager.getBundle(bundlename); if (bundle) { diff --git a/src/tool/Binary.ts b/src/tool/Binary.ts index 94cee74..a89be77 100644 --- a/src/tool/Binary.ts +++ b/src/tool/Binary.ts @@ -133,7 +133,7 @@ export class Binary { const strLen = view.getUint32(offset, true); offset += 4; const strBytes = new Uint8Array(view.buffer, offset, strLen); - return new TextDecoder().decode(strBytes); + return this.utf8ArrayToString(strBytes); } case 3: // boolean return view.getUint8(offset) === 1; @@ -185,8 +185,7 @@ export class Binary { break; } case 'string': { - const encoder = new TextEncoder(); - const strBytes = encoder.encode(value); + const strBytes = this.stringToUtf8Array(value); const strLen = strBytes.length; const strBuf = new Uint8Array(5 + strLen); strBuf[0] = 2; @@ -268,4 +267,84 @@ export class Binary { throw new Error(`未知的类型: ${type}`); } } + + /** @internal */ + private static utf8ArrayToString(array: Uint8Array): string { + if (!array || array.length === 0) { + return ''; + } + let out = ''; + let i = 0; + try { + while (i < array.length) { + let c = array[i++]; + if (c > 127) { + if (c > 191 && c < 224) { + if (i >= array.length) break; + c = ((c & 31) << 6) | (array[i++] & 63); + } else if (c > 223 && c < 240) { + if (i + 1 >= array.length) break; + c = ((c & 15) << 12) | ((array[i++] & 63) << 6) | (array[i++] & 63); + } else if (c > 239 && c < 248) { + if (i + 2 >= array.length) break; + c = ((c & 7) << 18) | ((array[i++] & 63) << 12) | ((array[i++] & 63) << 6) | (array[i++] & 63); + } else { + // 无效的 UTF-8 序列 + continue; + } + } + if (c <= 0xffff) { + out += String.fromCharCode(c); + } else if (c <= 0x10ffff) { + c -= 0x10000; + out += String.fromCharCode((c >> 10) | 0xd800); + out += String.fromCharCode((c & 0x3FF) | 0xdc00); + } + } + } catch (error) { + console.error('UTF-8 解码错误:', error); + return ''; + } + return out; + } + + /** @internal */ + private static stringToUtf8Array(str: string): Uint8Array { + if (!str || str.length === 0) { + return new Uint8Array(0); + } + const arr: number[] = []; + try { + for (let i = 0; i < str.length; i++) { + let charcode = str.charCodeAt(i); + if (charcode < 0x80) { + arr.push(charcode); + } else if (charcode < 0x800) { + arr.push(0xc0 | (charcode >> 6)); + arr.push(0x80 | (charcode & 0x3f)); + } else if (charcode < 0xd800 || charcode >= 0xe000) { + arr.push(0xe0 | (charcode >> 12)); + arr.push(0x80 | ((charcode >> 6) & 0x3f)); + arr.push(0x80 | (charcode & 0x3f)); + } else { + // surrogate pair + if (i + 1 >= str.length) { + // 不完整的代理对 + break; + } + i++; + charcode = ((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff); + charcode += 0x10000; + arr.push(0xf0 | (charcode >> 18)); + arr.push(0x80 | ((charcode >> 12) & 0x3f)); + arr.push(0x80 | ((charcode >> 6) & 0x3f)); + arr.push(0x80 | (charcode & 0x3f)); + } + } + } catch (error) { + console.error('UTF-8 编码错误:', error); + return new Uint8Array(0); + } + return new Uint8Array(arr); + } } \ No newline at end of file diff --git a/src/ui/WindowManager.ts b/src/ui/WindowManager.ts index 2a671c0..8159975 100644 --- a/src/ui/WindowManager.ts +++ b/src/ui/WindowManager.ts @@ -32,7 +32,7 @@ export class WindowManager { * @param windowName 窗口名 * @param userdata 用户数据 */ - public static async showWindow(windowName: string, userdata?: any): Promise { + public static showWindow(windowName: string, userdata?: any): Promise { return new Promise((resolve, reject) => { this._resPool.loadWindowRes(windowName, { complete: () => {