Adds level prefabs, theme assets, audio, extensions, and deployment scripts for the Unity WebGL migration. Co-authored-by: Cursor <cursoragent@cursor.com>
164 lines
5.3 KiB
TypeScript
164 lines
5.3 KiB
TypeScript
/**
|
||
* 内置回退贴图(themes-database.json 未加载或未配置时使用)
|
||
*/
|
||
import { Direction } from '../core/Define';
|
||
import { getThemeTextureFolder, isThemeDatabaseReady } from '../theme/ThemeRegistry';
|
||
|
||
export interface ThemeEntityTextureSet {
|
||
playerFront: string[];
|
||
playerBack: string[];
|
||
shipNorth: string[];
|
||
shipEast: string[];
|
||
shipSouth: string[];
|
||
shipWest: string[];
|
||
/** @deprecated 等同 shipSouth */
|
||
shipFront: string[];
|
||
/** @deprecated 等同 shipNorth */
|
||
shipBack: string[];
|
||
}
|
||
|
||
const THEME_TEXTURE_FOLDER: Record<string, string> = {
|
||
default: 'default',
|
||
silu: 'silu',
|
||
SILU: 'silu',
|
||
chinese: 'chinese',
|
||
redArmy: 'redArmy',
|
||
redarmy: 'redArmy',
|
||
numMan: 'numMan',
|
||
snow: 'snow',
|
||
sanxing: 'sanxing',
|
||
};
|
||
|
||
const THEME_CANONICAL_KEY: Record<string, string> = {
|
||
default: 'default',
|
||
silu: 'silu',
|
||
SILU: 'silu',
|
||
chinese: 'chinese',
|
||
redArmy: 'redArmy',
|
||
redarmy: 'redArmy',
|
||
numMan: 'numMan',
|
||
snow: 'snow',
|
||
sanxing: 'sanxing',
|
||
};
|
||
|
||
function shipFourWay(folder: string, prefix: string): Pick<
|
||
ThemeEntityTextureSet,
|
||
'shipNorth' | 'shipEast' | 'shipSouth' | 'shipWest' | 'shipFront' | 'shipBack'
|
||
> {
|
||
const base = `textures/${folder}/${prefix}`;
|
||
return {
|
||
shipNorth: [`${base}_N`, `${base}_B`],
|
||
shipEast: [`${base}_E`],
|
||
shipSouth: [`${base}_S`, `${base}_F`],
|
||
shipWest: [`${base}_W`],
|
||
shipFront: [`${base}_S`, `${base}_F`],
|
||
shipBack: [`${base}_N`, `${base}_B`],
|
||
};
|
||
}
|
||
|
||
const SILU_SHIP = shipFourWay('silu', 'siluShip');
|
||
const SILU_FALLBACK: ThemeEntityTextureSet = {
|
||
playerFront: ['textures/silu/skin/待机正面/1'],
|
||
playerBack: ['textures/silu/skin/待机背面/1'],
|
||
...SILU_SHIP,
|
||
};
|
||
|
||
export const THEME_ENTITY_TEXTURES: Record<string, ThemeEntityTextureSet> = {
|
||
default: {
|
||
playerFront: ['textures/default/player_F'],
|
||
playerBack: ['textures/default/player_B'],
|
||
...shipFourWay('default', 'ship'),
|
||
},
|
||
silu: { ...SILU_FALLBACK },
|
||
chinese: {
|
||
playerFront: ['textures/chinese/skin/待机正面/1', 'textures/chinese/chineseShip_F'],
|
||
playerBack: ['textures/chinese/skin/待机背面/1', 'textures/chinese/chineseShip_B'],
|
||
...shipFourWay('chinese', 'chineseShip'),
|
||
},
|
||
redArmy: {
|
||
playerFront: ['textures/redArmy/skin/待机正面/1'],
|
||
playerBack: ['textures/redArmy/skin/待机背面/1'],
|
||
...shipFourWay('redArmy', 'redArmyShip'),
|
||
},
|
||
numMan: {
|
||
playerFront: ['textures/numMan/skin/待机正面/1'],
|
||
playerBack: ['textures/numMan/skin/待机背面/1'],
|
||
...shipFourWay('numMan', 'numManShip'),
|
||
},
|
||
snow: {
|
||
playerFront: ['textures/snow/skin/待机正面/1'],
|
||
playerBack: ['textures/snow/skin/待机背面/1'],
|
||
...shipFourWay('snow', 'snowShip'),
|
||
},
|
||
sanxing: {
|
||
playerFront: ['textures/sanxing/skin/待机正面/1'],
|
||
playerBack: ['textures/sanxing/skin/待机背面/1'],
|
||
...shipFourWay('sanxing', 'sanxingShip'),
|
||
},
|
||
};
|
||
|
||
export function canonicalThemeKey(theme: string | undefined): string {
|
||
if (!theme) return 'silu';
|
||
return THEME_CANONICAL_KEY[theme] ?? theme;
|
||
}
|
||
|
||
export function resolveThemeFolder(theme: string | undefined): string {
|
||
if (!theme) return 'silu';
|
||
if (isThemeDatabaseReady()) return getThemeTextureFolder(theme);
|
||
return THEME_TEXTURE_FOLDER[theme] ?? theme;
|
||
}
|
||
|
||
export function getThemeEntityTextures(theme: string | undefined): ThemeEntityTextureSet {
|
||
const key = canonicalThemeKey(theme);
|
||
return THEME_ENTITY_TEXTURES[key] ?? SILU_FALLBACK;
|
||
}
|
||
|
||
export type VehicleSpriteRole = 'shipNorth' | 'shipEast' | 'shipSouth' | 'shipWest';
|
||
export type EntitySpriteRole = 'playerFront' | 'playerBack' | VehicleSpriteRole | 'shipFront' | 'shipBack';
|
||
|
||
export function vehicleSpriteRoleForDirection(direction: Direction): VehicleSpriteRole {
|
||
switch (direction) {
|
||
case Direction.North: return 'shipNorth';
|
||
case Direction.East: return 'shipEast';
|
||
case Direction.South: return 'shipSouth';
|
||
case Direction.West: return 'shipWest';
|
||
default: return 'shipNorth';
|
||
}
|
||
}
|
||
|
||
export function vehicleThemeFieldForDirection(direction: Direction): keyof import('../theme/ThemeTypes').ThemeEntityConfig {
|
||
switch (direction) {
|
||
case Direction.North: return 'vehicleNorth';
|
||
case Direction.East: return 'vehicleEast';
|
||
case Direction.South: return 'vehicleSouth';
|
||
case Direction.West: return 'vehicleWest';
|
||
default: return 'vehicleNorth';
|
||
}
|
||
}
|
||
|
||
export function entityTextureCandidates(
|
||
theme: string | undefined,
|
||
role: EntitySpriteRole,
|
||
): string[] {
|
||
const set = getThemeEntityTextures(theme);
|
||
const primary = [...(set[role] ?? [])];
|
||
const fb = SILU_FALLBACK[role as keyof ThemeEntityTextureSet];
|
||
if (fb) {
|
||
for (const p of fb) {
|
||
if (!primary.includes(p)) primary.push(p);
|
||
}
|
||
}
|
||
return primary;
|
||
}
|
||
|
||
/** 预加载某主题载具四向贴图主路径 */
|
||
export function allVehicleDirectionTextureCandidates(theme: string | undefined): string[] {
|
||
const out: string[] = [];
|
||
for (let d = Direction.North; d <= Direction.West; d++) {
|
||
for (const p of entityTextureCandidates(theme, vehicleSpriteRoleForDirection(d))) {
|
||
if (!out.includes(p)) out.push(p);
|
||
}
|
||
}
|
||
return out;
|
||
}
|