40 lines
2.8 KiB
TypeScript
40 lines
2.8 KiB
TypeScript
import {_decorator,Button,Component,Label} from 'cc';
|
|
import type {PlatformGameSnapshot} from '../../framework/sdk/contracts/index.ts';
|
|
import type {TemplateRoomActions,TemplateRoomPresentation} from './template-game.ts';
|
|
const {ccclass,property}=_decorator;
|
|
/** Template lobby-to-room handoff surface; concrete subgames replace this presentation. */
|
|
@ccclass('TemplateRoomView')
|
|
export class TemplateRoomView extends Component implements TemplateRoomPresentation {
|
|
@property(Label) roomLabel:Label|null=null;
|
|
@property(Label) playersLabel:Label|null=null;
|
|
@property(Button) prepareButton:Button|null=null;
|
|
@property(Button) exitButton:Button|null=null;
|
|
private actions:TemplateRoomActions|null=null;
|
|
private bound=false;
|
|
private pending:'prepare'|'exit'|null=null;
|
|
private timer:ReturnType<typeof setTimeout>|null=null;
|
|
private snapshot:PlatformGameSnapshot|null=null;
|
|
private readonly prepare=()=>this.invoke('prepare');
|
|
private readonly exit=()=>this.invoke('exit');
|
|
render(snapshot:PlatformGameSnapshot,actions:TemplateRoomActions):void{
|
|
if(!this.roomLabel||!this.playersLabel||!this.prepareButton||!this.exitButton)throw Error('TemplateRoomView missing controls');
|
|
this.actions=actions;this.snapshot=snapshot;
|
|
if(!this.bound){this.prepareButton.node.on(Button.EventType.CLICK,this.prepare);this.exitButton.node.on(Button.EventType.CLICK,this.exit);this.bound=true;}
|
|
this.roomLabel.string=`房间号:${snapshot.room.roomcode}`;
|
|
this.playersLabel.string=snapshot.seats.map(p=>`${p.seat+1} ${p.nickname}${p.playerId===snapshot.self.playerId?'(我)':''} ${!p.online?'离线':p.ready?'已准备':'未准备'}`).join('\n');
|
|
const self=snapshot.seats.find(p=>p.playerId===snapshot.self.playerId);
|
|
if(self?.ready||snapshot.connection.phase!=='logged-in')this.clearPending();
|
|
this.prepareButton.interactable=this.pending===null&&snapshot.connection.phase==='logged-in'&&snapshot.room.stage===0&&!self?.ready;
|
|
this.exitButton.interactable=this.pending===null&&snapshot.connection.phase==='logged-in';
|
|
}
|
|
private invoke(kind:'prepare'|'exit'):void{
|
|
if(!this.actions||this.pending)return;
|
|
try{this.actions[kind]();this.pending=kind;this.prepareButton!.interactable=false;this.exitButton!.interactable=false;
|
|
this.timer=setTimeout(()=>{this.clearPending();if(this.snapshot&&this.actions)this.render(this.snapshot,this.actions);this.node.emit('room-action-timeout');},15000);
|
|
}catch(error){this.node.emit('room-action-error',error);}
|
|
}
|
|
private clearPending():void{if(this.timer!==null)clearTimeout(this.timer);this.timer=null;this.pending=null;}
|
|
close():void{this.clearPending();if(this.bound){this.prepareButton?.node.off(Button.EventType.CLICK,this.prepare);this.exitButton?.node.off(Button.EventType.CLICK,this.exit);}this.bound=false;this.actions=null;}
|
|
onDestroy():void{this.close();}
|
|
}
|