This commit is contained in:
COMPUTER\EDY
2026-08-28 22:59:13 +08:00
parent a9c2c0301c
commit f8ef17bd56
121 changed files with 9634 additions and 12271 deletions
+5 -46
View File
@@ -71,56 +71,15 @@ export class GameConfig {
private static levelLoadRequest = 0;
private static sceneLoadRequest = 0;
private static cancelBlockLoading: () => void = null;
private static preparedBlocks: any[] = null;
private static preparedNextLevel = 0;
private static nextBlocksLoading: Promise<any[]> = null;
/** 只读取下一关配置,不调用 LEVEL_INFO_init,也不改玩家进度。 */
/** 只准备当前关图片,不预读或加载下一关图片。 */
static prepareBlockWindow(onRemoteRequired?: () => void, stage = "进关"): Promise<boolean> {
const blocks = this.BLOCK_INFO && this.BLOCK_INFO[0];
if (!blocks || !this.loadedLevelNumber) return Promise.reject(new Error("关卡配置尚未就绪"));
const currentLevel = this.loadedLevelNumber;
let nextLevel = currentLevel + 1;
if (!this.GM_INFO.otherLevel && (this.GM_INFO.GameplayType === 1
|| this.loadedLevelNumber >= GameTool.MAX_NORMAL_LEVEL)) {
// 预选无尽模式本地随机的下一关,通关时 getNextLevel 复用同一个结果。
if (!this.nextEndlessLevel) {
this.nextEndlessLevel = GameTool.getPurelyRandom(GameTool.MAX_NORMAL_LEVEL);
}
nextLevel = this.nextEndlessLevel;
} else {
this.nextEndlessLevel = 0;
}
if (this.preparedBlocks !== blocks || this.preparedNextLevel !== nextLevel || !this.nextBlocksLoading) {
this.preparedBlocks = blocks;
this.preparedNextLevel = nextLevel;
const loadNext = new Promise<any[]>((resolve, reject) => {
cc.assetManager.loadBundle("custom", (err, bundle) => {
if (err) return reject(err);
const path = "Json/level" + nextLevel;
if (!bundle.getInfoWithPath(path, cc.JsonAsset)) return resolve([]);
bundle.load(path, cc.JsonAsset, (error, asset: cc.JsonAsset) => {
if (error) return reject(error);
if (!asset || !asset.json || !Array.isArray(asset.json.BLOCK_INFO)
|| !Array.isArray(asset.json.BLOCK_INFO[0])) {
return reject(new Error("下一关配置无效: " + path));
}
resolve(asset.json.BLOCK_INFO[0]);
});
});
}).catch(error => {
if (this.nextBlocksLoading === loadNext) this.nextBlocksLoading = null;
throw error;
});
this.nextBlocksLoading = loadNext;
}
// 只复用下一关 JSON;每次进关都检查图片来源,不能复用已完成 Promise 跳过日志/重试通知。
return this.nextBlocksLoading.then(next => {
if (this.BLOCK_INFO[0] !== blocks) return false;
return BlockAssetManager.instance.prepareWindow(blocks, next,
{ onRemoteRequired, currentLevel, nextLevel, stage }).then(ready =>
ready && this.BLOCK_INFO[0] === blocks);
});
return BlockAssetManager.instance.prepareWindow(blocks,
{ onRemoteRequired, currentLevel, stage }).then(ready =>
ready && this.BLOCK_INFO[0] === blocks);
}
/** 创建时不显示;仅远程图片调用 open。失效请求不能打开或关闭后续请求的 Loading。 */
@@ -150,7 +109,7 @@ export class GameConfig {
};
}
/** 所有正式进关入口都在两关图片就绪后才切换 GameScene。 */
/** 所有正式进关入口都在当前关图片就绪后才切换 GameScene。 */
static enterGameSceneWhenReady(time = 0): void {
const id = ++this.sceneLoadRequest;
const scene = cc.director.getScene();
+24 -11
View File
@@ -8,7 +8,6 @@ type ImageSource = "内存复用" | "本地缓存" | "临时缓存" | "远程下
interface BlockWindowOptions {
onRemoteRequired?: () => void;
currentLevel?: number;
nextLevel?: number;
stage?: string;
}
@@ -53,6 +52,9 @@ export default class BlockAssetManager {
private committedPaths = new Set<string>();
private activePaths = new Set<string>();
private requestId = 0;
private windowRequestId = 0;
private committedRequestId = 0;
private activeRequestId = 0;
private foregroundLoads = 0;
private backgroundRunning = false;
private backgroundTimer: any = null;
@@ -144,31 +146,28 @@ export default class BlockAssetManager {
} catch (error) { return {}; }
}
/** 当前场景还在显示时保留它的图片,切场景销毁后再释放旧关独占资源。 */
async prepareWindow(current: any[], next: any[], options: BlockWindowOptions = {}): Promise<boolean> {
/** 只准备当前关;当前场景仍在显示时保留它的图片。 */
async prepareWindow(current: any[], options: BlockWindowOptions = {}): Promise<boolean> {
const currentPaths = collectBlockTexturePaths(current);
const nextPaths = collectBlockTexturePaths(next);
const paths = new Set(currentPaths.concat(nextPaths));
const paths = new Set(currentPaths);
const id = ++this.requestId;
const stage = options.stage || "进关";
const currentLabel = "当前关" + (options.currentLevel || "");
const nextLabel = "下一关" + (options.nextLevel || "");
// 同时存在多个进关请求时,只通知最新窗口;共享加载失败后的远程重试也走这里。
this.reportSource = (path, source) => {
if (id !== this.requestId || !paths.has(path)) return;
const levels = [currentPaths.indexOf(path) >= 0 ? currentLabel : "",
nextPaths.indexOf(path) >= 0 ? nextLabel : ""].filter(Boolean).join(" / ");
// console.log(`[Block图片][${stage}来源] ${levels} ${path}.png -> ${source},版本=${this.version}`);
// console.log(`[Block图片][${stage}来源] ${currentLabel} ${path}.png -> ${source},版本=${this.version}`);
if (source === "远程下载" && options.onRemoteRequired) options.onRemoteRequired();
};
this.windowPaths = paths;
this.windowRequestId = id;
this.foregroundLoads++;
this.releaseUnused();
try {
await this.initialize();
if (id !== this.requestId) return false;
this.ensureUserCacheFolder();
// console.log(`[Block图片][${stage}检查] ${currentLabel} / ${nextLabel},版本=${this.version},共${paths.size}张`);
// console.log(`[Block图片][${stage}检查] ${currentLabel},版本=${this.version},共${paths.size}张`);
const names = Array.from(paths);
// 限制前台并发,后台队列在此期间让出下载机会。
for (let i = 0; i < names.length; i += 4) {
@@ -180,10 +179,12 @@ export default class BlockAssetManager {
}
if (id !== this.requestId) return false;
this.committedPaths = paths;
this.committedRequestId = id;
return true;
} catch (error) {
if (id !== this.requestId) return false;
this.windowPaths = this.committedPaths;
this.windowRequestId = this.committedRequestId;
throw error;
} finally {
if (id === this.requestId) this.reportSource = null;
@@ -197,11 +198,23 @@ export default class BlockAssetManager {
const paths = collectBlockTexturePaths(blocks);
paths.forEach(path => this.getFrame(path));
this.activePaths = new Set(paths);
this.activeRequestId = this.committedRequestId;
this.releaseUnused();
}
releaseScene(): void {
const releasedRequestId = this.activeRequestId;
this.activePaths.clear();
this.activeRequestId = 0;
// 若下一关或重开关卡已准备完成,即使图片集合相同,也不能被旧场景销毁流程释放。
if (releasedRequestId && this.windowRequestId === releasedRequestId) {
this.windowPaths = new Set<string>();
this.windowRequestId = 0;
}
if (releasedRequestId && this.committedRequestId === releasedRequestId) {
this.committedPaths = new Set<string>();
this.committedRequestId = 0;
}
this.releaseUnused();
}
@@ -211,7 +224,7 @@ export default class BlockAssetManager {
return frame;
}
/** 调试时可核对是否只有当前关、下一关,以及尚未销毁的旧场景资源。 */
/** 调试时可核对是否只有当前关,以及转场期间尚未销毁的旧场景资源。 */
getLoadedPaths(): string[] {
return Array.from(this.frames.keys()).sort();
}