Files
cocos/assets/scripts/level/LevelConfigMerge.ts
2026-07-14 16:02:20 +08:00

71 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Node } from 'cc';
import { LevelConfig, SpawnConfig } from './LevelTypes';
import { LevelMapData } from './LevelMapData';
function hasKeys(rec?: Record<string, unknown>): boolean {
return !!rec && Object.keys(rec).length > 0;
}
/** 地图是否覆盖玩家/道具/载具 spawn 格(旧预制体常残留错误横向砖块) */
function groundCoversSpawns(ground: Record<string, unknown> | undefined, spawns: SpawnConfig[]): boolean {
if (!ground || !spawns.length) return false;
for (const s of spawns) {
if (s.kind !== 'player' && s.kind !== 'prop' && s.kind !== 'vehicle') continue;
if (!ground[`${s.x},${s.y}`]) return false;
}
return true;
}
/** Cocos 预制体 LevelMapData 优先DB 仅作 spawns 载体时的回退 */
function pickGround(
fromPrefab: LevelConfig['ground'],
fromDb: LevelConfig['ground'],
spawns: SpawnConfig[],
): LevelConfig['ground'] {
if (groundCoversSpawns(fromPrefab, spawns)) return fromPrefab;
if (groundCoversSpawns(fromDb, spawns)) return fromDb;
if (hasKeys(fromPrefab)) return fromPrefab;
return fromDb;
}
function parseJsonRecord(json: string): Record<string, unknown> | undefined {
try {
const o = JSON.parse(json || '{}') as unknown;
if (o && typeof o === 'object' && !Array.isArray(o)) {
return o as Record<string, unknown>;
}
} catch {
/* ignore */
}
return undefined;
}
/**
* Cocos 预制体 LevelMapData 为地图/主题权威levels-database 主要提供 spawns。
*/
export function mergeLevelConfigWithMapData(config: LevelConfig, levelRoot: Node): LevelConfig {
if (!levelRoot?.isValid) return config;
const md = levelRoot.getComponent(LevelMapData);
if (!md) return config;
const prefabGround = parseJsonRecord(md.groundJson) as LevelConfig['ground'];
const prefabBorder = parseJsonRecord(md.borderJson) as LevelConfig['border'];
const prefabTheme = md.theme?.trim();
const border = hasKeys(prefabBorder as Record<string, unknown>)
? prefabBorder
: config.border;
return {
...config,
// DB 主题优先(主站批次权威);预制体仅作缺省回退
theme: config.theme?.trim() || prefabTheme || 'silu',
ground: pickGround(
prefabGround as LevelConfig['ground'],
config.ground,
config.spawns ?? [],
),
border,
};
}