Json配置表加载支持zip格式,提高多配置表加载速度

This commit is contained in:
dgflash
2025-09-15 16:19:43 +08:00
parent 37900d8219
commit bb29cbf94e
7 changed files with 157 additions and 64 deletions

View File

@@ -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<string, JSZip> = new Map();
/**
* 加载ZIP资源包
* @param url
* @returns
*/
static load(url: string): Promise<JSZip> {
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<any> {
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<SpriteFrame> {
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);
});
}
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "2c6ce5e4-08fd-4ff1-b0b6-8c07d7192263",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -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<string, any> = 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<any> {
return new Promise((resolve, reject) => {
static load(name: string): Promise<any> {
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<boolean> {
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<void> {
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);
}
/** 清理所有数据 */

View File

@@ -44,7 +44,7 @@ export class LanguagePack {
/** 多语言Excel配置表数据 */
private loadTable(lang: string): Promise<void> {
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 资源");

View File

@@ -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 {

View File

@@ -21,7 +21,7 @@ export class CCEntity extends ecs.Entity {
addChildSingleton<T>(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;

View File

@@ -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 {