Complete room UI and protocol integration, move game definitions and resources behind bundle entries, publish authoritative version XML, and document single-game builds. Include all current resource changes and experiment artifacts.
62 lines
3.8 KiB
TypeScript
62 lines
3.8 KiB
TypeScript
import {createBuildIdentity} from './build-identity.ts';
|
|
import {_decorator,Prefab,SceneAsset,Node,assetManager,AssetManager,TextAsset,js} from 'cc';
|
|
import versionManifestParser,{type VersionManifest} from './version-manifest.js';
|
|
import {GameComposition,type CommonRoomView} from '../../scripts/platform-login/GameComposition.ts';
|
|
import {getGameDefinition,gameBundleName,gameResourcePath,type SubgameEntry} from './game-definitions.ts';
|
|
import type {GameDefinition} from '../../framework/sdk/contracts/game-definition.ts';
|
|
const {ccclass,property}=_decorator;
|
|
/** App composition root: each game assigns its own pre-room page, room view and scene. */
|
|
@ccclass('SubgameAssets')
|
|
export class SubgameAssets extends GameComposition {
|
|
@property gameKey:string='';
|
|
private loaded:Readonly<{definition:GameDefinition;createRoom:Prefab;room:Prefab}>|null=null;
|
|
get createRoom(){return this.loaded?.createRoom??null;}
|
|
get room(){return this.loaded?.room??null;}
|
|
@property(SceneAsset) roomScene:SceneAsset|null=null;
|
|
private manifestValue:Readonly<VersionManifest>|null=null;
|
|
get versionManifest(){return this.manifestValue;}
|
|
get displayVersion(){if(!this.manifestValue)throw Error('version.xml has not been loaded');return this.manifestValue.version;}
|
|
async loadBuildIdentity(){
|
|
await this.loadGameAssets();
|
|
const key=this.gameKey,path=this.definition.config.versionResource;
|
|
if(path!==key+'/version')throw Error('Version resource does not match selected game: '+key);
|
|
const bundleName='version-'+key;
|
|
const bundle=await new Promise<AssetManager.Bundle>((resolve,reject)=>assetManager.loadBundle(bundleName,(error,result)=>{
|
|
if(error)reject(Error('Cannot load '+bundleName+': '+error.message));
|
|
else if(!result)reject(Error('Missing '+bundleName));else resolve(result);
|
|
}));
|
|
const asset=await new Promise<TextAsset>((resolve,reject)=>bundle.load(path,TextAsset,(error,result)=>{
|
|
if(error)reject(Error('Cannot load '+path+'.xml: '+error.message));
|
|
else if(!result)reject(Error('Missing '+path+'.xml'));else resolve(result);
|
|
}));
|
|
try {
|
|
if(this.gameKey!==key)throw Error('Game selection changed during version.xml load');
|
|
const manifest=versionManifestParser.parseVersionManifest(asset.text);
|
|
const identity=createBuildIdentity(manifest);
|
|
this.manifestValue=manifest;
|
|
return identity;
|
|
} finally {bundle.release(path,TextAsset);}
|
|
}
|
|
private async loadGameAssets(){
|
|
const key=this.gameKey;
|
|
if(this.loaded){if(this.loaded.definition.key!==key)throw Error('Game selection changed after loading');return;}
|
|
const bundle=await new Promise<AssetManager.Bundle>((resolve,reject)=>assetManager.loadBundle(gameBundleName(key),(error,result)=>{
|
|
if(error)reject(error);else if(!result)reject(Error('Missing game bundle: '+key));else resolve(result);
|
|
}));
|
|
const definition=getGameDefinition(key,name=>js.getClassByName(name) as unknown as SubgameEntry|null);
|
|
const load=(resource:string)=>new Promise<Prefab>((resolve,reject)=>bundle.load(gameResourcePath(definition.config.assetRoot,resource),Prefab,(error,result)=>{
|
|
if(error)reject(error);else if(!result)reject(Error('Missing game prefab: '+resource));else resolve(result);
|
|
}));
|
|
const [createRoom,room]=await Promise.all([load(definition.resources.createRoom),load(definition.resources.room)]);
|
|
if(this.gameKey!==key)throw Error('Game selection changed during asset load');
|
|
this.loaded={definition,createRoom,room};
|
|
}
|
|
get definition(){if(!this.loaded)throw Error('Subgame assets have not been loaded');return this.loaded.definition;}
|
|
resolveRoomView(root:Node):CommonRoomView {
|
|
const name=this.definition.roomViewClass;
|
|
const view=root.getComponent(name) as (CommonRoomView|null);
|
|
if(!view||typeof view.render!=='function'||typeof view.close!=='function'||typeof view.dissolutionReceived!=='function')throw Error(`Room prefab missing valid ${name}`);
|
|
return view;
|
|
}
|
|
}
|