diff --git a/assets/core/common/loader/ZipLoader.ts b/assets/core/common/loader/ZipLoader.ts new file mode 100644 index 0000000..219d283 --- /dev/null +++ b/assets/core/common/loader/ZipLoader.ts @@ -0,0 +1,87 @@ +import { BufferAsset, SpriteFrame, Texture2D } from "cc"; +import { oops } from "db://oops-framework/core/Oops"; + +/** + * 加载Zip资源 + * 注: + * 1. 使用此功能需要教程项目中项目资源目录libs/jszip目录拷贝到自己的项目中 + * 2. 选中libs/jszip/jszip文件,属性检查器中勾选导入为插件、允许指点平台加载此库 + * 3. 压缩软件打包的 game.zip 修改为 game.bin 则可在游戏中加载 + */ +export class ZipLoader { + private static zips: Map = new Map(); + + /** + * 加载ZIP资源包 + * @param url + * @returns + */ + static load(url: string): Promise { + return new Promise((resolve, reject) => { + oops.res.load(url, BufferAsset, async (error: Error | null, asset: BufferAsset) => { + if (error) return reject(error); + + var zip = await JSZip.loadAsync(asset.buffer()); + this.zips.set(url, zip); + resolve(zip); + }) + }); + } + + static getJson(zipName: string, path: string): Promise { + return new Promise(async (resolve, reject) => { + var zip = this.zips.get(zipName); + if (zip == null) { + console.error(`名为【${zipName}】的资源包不存在`); + resolve(null); + return; + } + + var file = zip.file(path); + var json = JSON.parse(await file.async("text")); + resolve(json); + }); + } + + static getSpriteFrame(zipName: string, path: string): Promise { + return new Promise(async (resolve, reject) => { + var zip = this.zips.get(zipName); + if (zip == null) { + console.error(`名为【${zipName}】的资源包不存在`); + resolve(null!); + return; + } + + var file = zip.file(path); + var buf = await file.async("base64"); + var img = new Image(); + img.src = 'data:image/png;base64,' + buf; + img.onload = () => { + var texture = new Texture2D(); + texture.reset({ + width: img.width, + height: img.height + }); + texture.uploadData(img, 0, 0); + texture.loaded = true; + + var sf = new SpriteFrame(); + sf.texture = texture; + + resolve(sf); + } + }); + } + + /** 释放Zip资源 */ + static release(url?: string) { + if (url) { + oops.res.release(url); + } + else { + this.zips.forEach((value: JSZip, key: string) => { + oops.res.release(key); + }); + } + } +} \ No newline at end of file diff --git a/assets/core/common/loader/ZipLoader.ts.meta b/assets/core/common/loader/ZipLoader.ts.meta new file mode 100644 index 0000000..0b36f42 --- /dev/null +++ b/assets/core/common/loader/ZipLoader.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "2c6ce5e4-08fd-4ff1-b0b6-8c07d7192263", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/assets/core/utils/JsonUtil.ts b/assets/core/utils/JsonUtil.ts index 03778f9..7671f5f 100644 --- a/assets/core/utils/JsonUtil.ts +++ b/assets/core/utils/JsonUtil.ts @@ -6,91 +6,87 @@ */ import { JsonAsset } from "cc"; +import { ZipLoader } from "db://oops-framework/core/common/loader/ZipLoader"; import { resLoader } from "../common/loader/ResLoader"; /** 资源路径 */ -const path: string = "config/game/"; +const pathJson: string = "config/game/"; +/** 压缩包资源路径 */ +const pathZip: string = "config/game/game"; /** 数据缓存 */ const data: Map = new Map(); /** JSON数据表工具 */ export class JsonUtil { + /** 是否使用压缩包加载配置表 */ + static zip: boolean = false; + /** * 通知资源名从缓存中获取一个Json数据表 * @param name 资源名 */ static get(name: string): any { - if (data.has(name)) - return data.get(name); - } - - /** - * 通知资源名加载Json数据表 - * @param name 资源名 - * @param callback 资源加载完成回调 - */ - static load(name: string, callback: Function): void { - if (data.has(name)) - callback(data.get(name)); - else { - const url = path + name; - resLoader.load(url, JsonAsset, (err: Error | null, content: JsonAsset) => { - if (err) { - console.warn(err.message); - callback(null); - } - else { - data.set(name, content.json); - resLoader.release(url); - callback(content.json); - } - }); - } + if (data.has(name)) return data.get(name); } /** * 异步加载Json数据表 * @param name 资源名 */ - static loadAsync(name: string): Promise { - return new Promise((resolve, reject) => { + static load(name: string): Promise { + return new Promise(async (resolve, reject) => { + let content: any = null; if (data.has(name)) { - resolve(data.get(name)) + resolve(data.get(name)); } else { - const url = path + name; - resLoader.load(url, JsonAsset, (err: Error | null, content: JsonAsset) => { - if (err) { - console.warn(err.message); - resolve(null); - } - else { - data.set(name, content.json); - resLoader.release(url); - resolve(content.json); - } - }); + const url = pathJson + name; + if (this.zip) { + content = await ZipLoader.getJson(pathZip, `${name}.json`); + } + else { + content = await resLoader.loadAsync(url, JsonAsset); + } + + if (content) { + data.set(name, content.json); + resLoader.release(url); + resolve(content.json); + } } }); } - /** 加载所有配置表数据到缓存中 */ - static loadDirAsync(): Promise { - return new Promise((resolve, reject) => { - resLoader.loadDir(path, (err: Error | null, assets: JsonAsset[]) => { - if (err) { - console.warn(err.message); - resolve(false); - } - else { - assets.forEach(asset => { - data.set(asset.name, asset.json); - }); - resLoader.releaseDir(path); - resolve(true); - } - }); + /** + * 加载所有配置表数据到缓存中 + * @param isZip 是否为压缩包 + * @param zipNames 压缩包内的资源名列表 + */ + static loadDir(zipNames?: string[]): Promise { + return new Promise(async (resolve, reject) => { + if (this.zip && zipNames) { + await ZipLoader.load(pathZip); + zipNames.forEach(name => { + data.set(name, ZipLoader.getJson(pathZip, `${name}.json`)); + }); + resolve(); + } + else { + resLoader.loadDir(pathJson, (err: Error | null, assets: JsonAsset[]) => { + if (err) { + console.error(err.message); + resolve(); + } + else { + assets.forEach(asset => { + data.set(asset.name, asset.json); + }); + resLoader.releaseDir(pathJson); + resolve(); + } + }); + } }); } @@ -100,6 +96,7 @@ export class JsonUtil { */ static release(name: string) { data.delete(name); + if (this.zip) ZipLoader.release(pathZip); } /** 清理所有数据 */ diff --git a/assets/libs/gui/language/LanguagePack.ts b/assets/libs/gui/language/LanguagePack.ts index 53bfadf..1d22726 100644 --- a/assets/libs/gui/language/LanguagePack.ts +++ b/assets/libs/gui/language/LanguagePack.ts @@ -44,7 +44,7 @@ export class LanguagePack { /** 多语言Excel配置表数据 */ private loadTable(lang: string): Promise { return new Promise(async (resolve, reject) => { - let json = await JsonUtil.loadAsync("Language"); + let json = await JsonUtil.load("Language"); if (json) { LanguageData.language.set(LanguageDataType.Excel, json); Logger.instance.logConfig("config/game/Language", "下载语言包 table 资源"); diff --git a/assets/module/common/CCComp.ts b/assets/module/common/CCComp.ts index afdcf77..f37a178 100644 --- a/assets/module/common/CCComp.ts +++ b/assets/module/common/CCComp.ts @@ -38,13 +38,13 @@ export abstract class CCComp extends GameComponent implements ecs.IComp { static compName: string; canRecycle!: boolean; - ent!: ecs.Entity; + ent!: CCEntity; tid: number = -1; /** 从父节点移除自己 */ remove() { const cct = ECSModel.compCtors[this.tid]; - if (this.ent && this.ent instanceof CCEntity) { + if (this.ent) { this.ent.removeUi(cct); } else { diff --git a/assets/module/common/CCEntity.ts b/assets/module/common/CCEntity.ts index c0299e8..34ee2f9 100644 --- a/assets/module/common/CCEntity.ts +++ b/assets/module/common/CCEntity.ts @@ -21,7 +21,7 @@ export class CCEntity extends ecs.Entity { addChildSingleton(cls: any): T { if (this.singletons == null) this.singletons = new Map(); - let entity = cls.create() + let entity = cls.create(); this.singletons.set(cls, entity); this.addChild(entity); return entity as T; diff --git a/assets/module/common/CCVMParentComp.ts b/assets/module/common/CCVMParentComp.ts index 7a43c7d..9f6cbf4 100644 --- a/assets/module/common/CCVMParentComp.ts +++ b/assets/module/common/CCVMParentComp.ts @@ -50,13 +50,13 @@ export abstract class CCVMParentComp extends VMParent implements ecs.IComp { static compName: string; canRecycle!: boolean; - ent!: ecs.Entity; + ent!: CCEntity; tid: number = -1; /** 从父节点移除自己 */ remove() { const cct = ECSModel.compCtors[this.tid]; - if (this.ent && this.ent instanceof CCEntity) { + if (this.ent) { this.ent.removeUi(cct); } else {