JM_KA/assets/Script/Engine/HUD/AssetBundleMamager.ts

456 lines
17 KiB
TypeScript
Raw Normal View History

2022-08-26 16:48:17 +08:00
import BusinessTypeSetting from "../../_BusinessTypeSetting/BusinessTypeSetting";
import LocalStorageData from "../Data/LocalStorageData";
import Enum_Loading from "../HUDV2/Enum_Loading";
import HUDM from "./HUDM";
export default class AssetBundleMamager {
//#region static 屬性
private static _instance: AssetBundleMamager = null;
public static get Instance(): AssetBundleMamager { return AssetBundleMamager._instance; }
//#endregion
//#region public 屬性
public HUGroup: Map<string, HUDM> = new Map<string, HUDM>();
/** 本地VerList */
public LocalVerList: Enum_Loading.VerListObj = null;
/** 遠端VerList */
public RemoteVerList: Enum_Loading.VerListObj = null;
public DownloadList_Preview: Object = {};
/** IsChangeBundleUrl */
public IsChangeBundleUrl: boolean = false;
//#endregion
//#region Lifecycle
constructor() {
AssetBundleMamager._instance = this;
CC_PREVIEW && this._initdownloadList_Preview();
}
//#endregion
//#region Custom Function
/**
* Bundle
* @param {string} BundleName Bundle名稱
* @param {string} Version
* @return {cc.AssetManager.Bundle} Bundle
*/
public *GetBundle(BundleName: string, Version: string = ""): IterableIterator<cc.AssetManager.Bundle> {
let bundle: cc.AssetManager.Bundle = cc.assetManager.getBundle(BundleName);
if (bundle) {
return bundle;
}
// options是可选参数引擎会根据保留字段 进行对应的操作这里添加了version和onFileProgress可用来记录热更资源版本和下载进度
let options: any = null;
let BundleUrl: string = BundleName;
if (cc.sys.isNative && !this.LocalVerList[BundleName].UseLocal) {
BundleUrl = `${(jsb.fileUtils ? jsb.fileUtils.getWritablePath() : "/")}Bundle/${BundleName}/remote/${BundleName}`;
options = {
version: Version
};
}
cc.assetManager.loadBundle(BundleUrl, options, (err: Error, resp: cc.AssetManager.Bundle) => {
if (err) {
cc.error(err);
bundle = null;
}
bundle = resp;
});
while (typeof bundle === "undefined") {
yield null;
}
return bundle;
}
/**
* Bundle
* @param {HUDM} HUDName HUD
*/
public *UpdateBundle(HUDName: HUDM | string, onFileProgress?: (finish: number, total: number, item: string) => void): IterableIterator<any> {
let HUD: HUDM;
if (HUDName instanceof HUDM) {
HUD = HUDName;
} else {
HUD = this.GetHUD(HUDName);
}
let UpdateingData: Enum_Loading.UpdateingDataObj = yield* HUD.HUD(onFileProgress);
if (UpdateingData.IsUpdatecomplete) {
this.LocalVerList[HUD.BundleName] = this.RemoteVerList[HUD.BundleName];
this.LocalVerList[HUD.BundleName]["UseLocal"] = false;
LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
}
return UpdateingData;
}
/**
* Bundle
* @param {HUDM} HUDName HUD
*/
public *RetryUpdateBundle(HUDName: HUDM | string, onFileProgress?: (finish: number, total: number, item: string) => void): IterableIterator<any> {
let HUD: HUDM;
if (HUDName instanceof HUDM) {
HUD = HUDName;
} else {
HUD = this.GetHUD(HUDName);
}
let UpdateingData: Enum_Loading.UpdateingDataObj = yield* HUD.RetryDownLoadFailedAssets();
return UpdateingData;
}
/**
* Bundle取得資源
* @param {cc.AssetManager.Bundle | string} BundleName Bundle名稱
* @param {string} SourceName
* @param {string} type
* @return {any} Source
*/
public *GetBundleSource(BundleName: cc.AssetManager.Bundle | string, SourceName: string, type?: string | Bundle_Source_Type, onFileProgress?: (finish: number, total: number, item: cc.AssetManager.RequestItem) => void): IterableIterator<any> {
let bundle: cc.AssetManager.Bundle;
let source: any;
if (BundleName instanceof cc.AssetManager.Bundle) {
bundle = BundleName;
} else {
bundle = cc.assetManager.getBundle(BundleName);
if (!bundle) {
cc.error(`GetBundleSource Error BundleName: ${BundleName}`);
return null;
}
}
switch (type) {
case Bundle_Source_Type.Scene: {
bundle.loadScene(SourceName, onFileProgress, function (err: Error, scene: cc.SceneAsset): void {
if (err) {
cc.error(err);
return null;
}
// cc.director.runScene(scene);
source = scene;
});
break;
}
case Bundle_Source_Type.Json: {
bundle.load(SourceName, onFileProgress, function (err: Error, json: cc.JsonAsset): void {
if (err) {
cc.error(err);
return null;
}
// source = JSON.parse(json["_nativeAsset"]);
source = json;
});
break;
}
case Bundle_Source_Type.Prefab: {
bundle.load(SourceName, cc.Prefab, onFileProgress, function (err: Error, prefab: cc.Asset): void {
if (err) {
cc.error(err);
return null;
}
// source = JSON.parse(json["_nativeAsset"]);
source = prefab;
});
break;
}
default:
bundle.load(SourceName, function (err: Error, any: any): void {
if (err) {
cc.error(err);
return null;
}
source = any;
});
break;
}
while (typeof source === "undefined") {
yield null;
}
return source;
}
/**
* Bundle
* @param {string} slotID slotID
*/
public *BundleRelease(slotID: number): IterableIterator<any> {
let gameName: string = `Game_${slotID}`;
let sceneName: string = `Slot${slotID}`;
let bundle: cc.AssetManager.Bundle = cc.assetManager.getBundle(gameName);
if (!bundle) {
cc.log(`BundleRelease Error BundleName: ${gameName}`);
return;
}
// let bundles: cc.AssetManager.Cache<cc.AssetManager.Bundle> = cc.assetManager.bundles;
// let cacheDir: string = cc.assetManager.cacheManager.cacheDir;
// let cachedFiles: Object = cc.assetManager.cacheManager.cachedFiles;
yield* this.DelBundleCache(bundle);
yield* this.DelOthersCache(slotID);
bundle.release(sceneName, cc.SceneAsset);
cc.assetManager.removeBundle(bundle);
cc.sys.garbageCollect();
}
/**
* Bundle刪除暫存資源
* @param {string} BundleName Bundle名稱
*/
public *DelBundleCache(BundleName: cc.AssetManager.Bundle | string): IterableIterator<any> {
if (!CC_JSB) {
return;
}
let bundle: cc.AssetManager.Bundle;
let source: any;
if (BundleName instanceof cc.AssetManager.Bundle) {
bundle = BundleName;
} else {
bundle = cc.assetManager.getBundle(BundleName);
if (!bundle) {
// cc.error(`GetBundleSource Error BundleName: ${BundleName}`);
// return;
bundle = yield* AssetBundleMamager.Instance.GetBundle(BundleName, this.RemoteVerList[BundleName].Version);
}
}
let _map: Object = bundle["_config"].assetInfos._map;
for (let map of Object.keys(_map)) {
let path: string = _map[map].path;
if (!path) {
break;
}
source = yield* AssetBundleMamager.Instance.GetBundleSource(bundle, path);
cc.assetManager.cacheManager.removeCache(source.nativeUrl);
bundle.release(path);
// return;
}
}
/**
* cachedFiles刪除暫存資源
* @param {number} slotID slotID
*/
public *DelOthersCache(slotID: number): IterableIterator<any> {
if (!CC_JSB) {
return;
}
let cachedFiles: Object = cc.assetManager.cacheManager.cachedFiles["_map"];
let delcache_group: string[] = [`shared/jsons`, `Slot/Slot${slotID}`, "sounds/Slot/Default", `${BusinessTypeSetting.FolderUrlBundle}project.manifest`, "submit.txt"];
for (let cached of Object.keys(cachedFiles)) {
for (var i: number = 0; i < delcache_group.length; ++i) {
let delcache: string = delcache_group[i];
if (cached.includes(delcache)) {
cc.assetManager.cacheManager.removeCache(cached);
// console.log(`removeCache: ${cached}`);
break;
}
}
}
}
public GetHUD(BundleName: HUDM | string): HUDM {
let HUD: HUDM;
if (BundleName instanceof HUDM) {
HUD = BundleName;
} else {
if (!this.HUGroup.has(BundleName)) {
HUD = new HUDM(BundleName);
this.HUGroup.set(BundleName, HUD);
} else {
HUD = this.HUGroup.get(BundleName);
}
HUD = this.HUGroup.get(BundleName);
}
return HUD;
}
/** 刪除全部暫存資源 */
public ClearAllCache(): void {
cc.assetManager.cacheManager.clearCache();
cc.game.restart();
}
public *CheckBundleNeedHUD(BundleName: HUDM | string): IterableIterator<Enum_Loading.NeedUpdateDataObj> {
let HUD: HUDM;
if (BundleName instanceof HUDM) {
HUD = BundleName;
} else {
HUD = this.GetHUD(BundleName);
}
if (!this.LocalVerList[HUD.BundleName]) {
this.LocalVerList[HUD.BundleName] = new Enum_Loading.BundleDataObj();
let apkVersion: string = this.RemoteVerList[HUD.BundleName].ApkVersion;
if (apkVersion && apkVersion !== "0") {
this.LocalVerList[HUD.BundleName].UseLocal = true;
this.LocalVerList[HUD.BundleName].Version = apkVersion;
}
LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
} else {
if (this.RemoteVerList[HUD.BundleName].Version === this.RemoteVerList[HUD.BundleName].ApkVersion) {
this.LocalVerList[HUD.BundleName] = this.RemoteVerList[HUD.BundleName];
this.LocalVerList[HUD.BundleName].UseLocal = true;
}
}
let UpdateData: Enum_Loading.NeedUpdateDataObj = new Enum_Loading.NeedUpdateDataObj();
if (this.LocalVerList[HUD.BundleName].UseLocal) {
UpdateData.IsNeedUpdate = AssetBundleMamager.Instance.versionCompareHandle(this.LocalVerList[HUD.BundleName].Version, this.RemoteVerList[HUD.BundleName].Version) < 0 ? true : false;
if (UpdateData.IsNeedUpdate) {
UpdateData = yield* HUD.CheckUpdate();
}
} else {
UpdateData = yield* HUD.CheckUpdate();
}
return UpdateData;
}
// public *CheckBundleNeedHUD(BundleName: string): IterableIterator<boolean> {
// if (!this.LocalVerList[BundleName]) {
// this.LocalVerList[BundleName] = new Enum_Loading.BundleDataObj();
// let apkVersion: string = this.RemoteVerList[BundleName].ApkVersion;
// if (apkVersion && apkVersion !== "0") {
// this.LocalVerList[BundleName].UseLocal = true;
// this.LocalVerList[BundleName].Version = apkVersion;
// }
// LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
// }
// let IsUpdate: boolean = AssetBundleMamager.Instance.versionCompareHandle(this.LocalVerList[BundleName].Version, this.RemoteVerList[BundleName].Version) < 0 ? true : false;
// return IsUpdate;
// }
public CheckGameNeedUpdate(GameID: number): boolean {
let IsUpdate: boolean = false;
let bundleName: string = `Game_${GameID}`;
if (!this.RemoteVerList[bundleName]) {
this.RemoteVerList[bundleName] = new Enum_Loading.BundleDataObj();
this.RemoteVerList[bundleName].HasBundle = false;
LocalStorageData.Instance.RemoteVerList = JSON.stringify(this.RemoteVerList);
IsUpdate = true;
}
if (!this.LocalVerList[bundleName]) {
this.LocalVerList[bundleName] = new Enum_Loading.BundleDataObj();
let apkVersion: string = this.RemoteVerList[bundleName].ApkVersion;
if (apkVersion && apkVersion !== "0") {
this.LocalVerList[bundleName].UseLocal = true;
this.LocalVerList[bundleName].Version = apkVersion;
}
LocalStorageData.Instance.LocalVerList = JSON.stringify(this.LocalVerList);
}
if (CC_PREVIEW) {
return this._getIsDownload_Preview(GameID);
}
if (IsUpdate) {
return IsUpdate;
}
IsUpdate = AssetBundleMamager.Instance.versionCompareHandle(this.LocalVerList[bundleName].Version, this.RemoteVerList[bundleName].Version) < 0 ? true : false;
return IsUpdate;
}
/**
* (1.0.02.0.02.0.0退1.0.0)
* >2.0.0退1.0.0
* @param {string} versionA
* @param {string} versionB
* @return {number} num = -1
* @return {number} num = 0
*/
public versionCompareHandle(versionA: string, versionB: string): number {
// console.log("Ver A " + versionA + "VerB " + versionB);
var vA: string[] = versionA.split(".");
var vB: string[] = versionB.split(".");
// 長度不相等,則進行更新
if (vA.length !== vB.length) {
return -1;
}
for (var i: number = 0; i < vA.length; ++i) {
var a: number = +vA[i];
var b: number = +vB[i] || 0;
if (a === b) {
// 數字相同,則跳過
continue;
} else {
// 數字不同,則進行更新
return -1;
}
}
// 長度相等且數字相等,則不更新
return 0;
}
//#endregion
//#region DownloadList_Preview
private _initdownloadList_Preview(): void {
this.DownloadList_Preview = JSON.parse(LocalStorageData.Instance.DownloadList_Preview);
this.DownloadList_Preview = this.DownloadList_Preview ? this.DownloadList_Preview : {};
}
private _getIsDownload_Preview(slotID: number): boolean {
if (!this.DownloadList_Preview[slotID]) {
this.SetIsDownload_Preview(slotID, false);
}
return !this.DownloadList_Preview[slotID];
}
public SetIsDownload_Preview(slotID: number, isDownload: boolean = true): void {
this.DownloadList_Preview[slotID] = isDownload;
LocalStorageData.Instance.DownloadList_Preview = JSON.stringify(this.DownloadList_Preview);
}
//#endregion
}
//#region enum
/** Bundle資源類型 */
export enum Bundle_Source_Type {
/** Json */
Json = "json",
/** Scene */
Scene = "scene",
/** Prefab */
Prefab = "prefab"
}
//#endregion
//#region 廢棄 Function
// /**
// * 從Bundle刪除暫存資源
// * @param {string} BundleName Bundle名稱
// */
// public *DelBundleCache(BundleName: cc.AssetManager.Bundle | string): IterableIterator<any> {
// if (!CC_JSB) {
// return;
// }
// let WritablePath: string = `${jsb.fileUtils.getWritablePath()}gamecaches/${BundleName}`;
// if (jsb.fileUtils.isDirectoryExist(WritablePath)) {
// jsb.fileUtils.removeDirectory(WritablePath);
// }
// }
//#endregion