feat: wire lobby task and VIP prefab flows and sync UI assets
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import {requireArray,requireRecord,requireString} from './validation.ts';
|
||||
import type {VipCode,VipRoom} from '../../core/types/vip-room.ts';
|
||||
export function vipCode(value:unknown,path:string):VipCode {
|
||||
if(typeof value==='string'&&value.length>0)return value;
|
||||
if(typeof value==='number'&&Number.isFinite(value))return value;
|
||||
throw TypeError(`${path}: expected non-empty string or finite number`);
|
||||
}
|
||||
/** Defaults here are the original GameUI source semantics, not view repairs. */
|
||||
export function parseVipRooms(payload:unknown):readonly VipRoom[]{
|
||||
const data=requireRecord(payload,'$.data');
|
||||
return Object.freeze(requireArray(data.roomInfo,'$.data.roomInfo').map((value,index)=>{
|
||||
const p=`$.data.roomInfo[${index}]`,r=requireRecord(value,p);
|
||||
const playerList=requireArray(r.playerList,p+'.playerList').map((v,i)=>Object.freeze([...requireArray(v,`${p}.playerList[${i}]`)]));
|
||||
const codes=r.roomcodes?requireRecord(r.roomcodes,p+'.roomcodes'):null;
|
||||
const roomcodes=codes?Object.freeze({roomtype:Object.freeze([...requireArray(codes.roomtype,p+'.roomcodes.roomtype')]),roomlist:Object.freeze(requireArray(codes.roomlist,p+'.roomcodes.roomlist').map((v,i)=>vipCode(v,`${p}.roomcodes.roomlist[${i}]`)))}):null;
|
||||
const deskState=roomcodes?requireArray(r.deskState,p+'.deskState'):[];
|
||||
const seatCount=roomcodes?requireArray(r.seatCount,p+'.seatCount').map((v,i)=>vipCode(v,`${p}.seatCount[${i}]`)):[];
|
||||
if(roomcodes&&[roomcodes.roomlist.length,deskState.length,seatCount.length].some(n=>n!==playerList.length))throw TypeError(p+': desk arrays must have matching lengths');
|
||||
const owner=typeof r.owner==='string'?r.owner:String(vipCode(r.owner,p+'.owner'));
|
||||
return Object.freeze({shortCode:vipCode(r.shortCode,p+'.shortCode'),title:r.destwo?requireString(r.destwo,p+'.destwo'):'vip房间',owner,roomcodes,playerList:Object.freeze(playerList),deskState:Object.freeze([...deskState]),seatCount:Object.freeze(seatCount),forbidSelect:!!r.forbidSelect});
|
||||
}));
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "413720a7-c6a9-4364-bb42-3c9c6f4fb907",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -7,6 +7,11 @@ export function isLoginResponse(message:{route:string;rpc:string}):boolean{
|
||||
}
|
||||
|
||||
export type FirstSliceRpc =
|
||||
| 'getInfoByShortCode'
|
||||
| 'get_player_task'
|
||||
| 'get_task_award'
|
||||
| 'update_roomcard'
|
||||
| 'player_finish_task'
|
||||
| 'player_login'
|
||||
| 'self_join_room'
|
||||
| 'player_prepare'
|
||||
@@ -25,6 +30,11 @@ export type FirstSliceRoute = 'platform' | 'agent' | 'room';
|
||||
|
||||
/** 第一纵向切片 rpc → route 的唯一权威映射。 */
|
||||
export const FIRST_SLICE_RPC_ROUTE = {
|
||||
getInfoByShortCode: 'agent',
|
||||
get_player_task: 'agent',
|
||||
get_task_award: 'agent',
|
||||
update_roomcard: 'agent',
|
||||
player_finish_task: 'agent',
|
||||
player_login: 'agent',
|
||||
self_join_room: 'agent',
|
||||
player_prepare: 'room',
|
||||
|
||||
@@ -28,7 +28,7 @@ export interface PlatformHandlersOptions {
|
||||
readonly gameSession: GameSessionHost;
|
||||
readonly session: RuntimeSession;
|
||||
readonly connection: ConnectionControlPort;
|
||||
readonly showMessage?: (message:string,time:number)=>void;
|
||||
readonly showMessage?: (message:string,time:number,source:'show_message'|'update_roomcard')=>void;
|
||||
}
|
||||
|
||||
export type PlatformDispatchResult = 'handled-platform';
|
||||
@@ -57,6 +57,20 @@ export class PlatformHandlers {
|
||||
}
|
||||
|
||||
switch (rpc) {
|
||||
case 'getInfoByShortCode':this.options.store.applyVipRooms(message.data);break;
|
||||
case 'update_roomcard': {
|
||||
const raw=requireRecord(message.data,'$.data');
|
||||
const text=raw.text?requireString(raw.text,'$.data.text'):null;
|
||||
this.options.store.applyRoomcardUpdate(raw);
|
||||
if(raw.change===undefined&&text){
|
||||
if(!this.options.showMessage)throw Error('update_roomcard requires a message UI');
|
||||
this.options.showMessage(text,0,'update_roomcard');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'get_player_task':this.options.store.applyTaskList(message.data);break;
|
||||
case 'get_task_award':this.options.store.applyTaskAward(message.data);break;
|
||||
case 'player_finish_task':this.options.store.applyTaskFinished(message.data);break;
|
||||
case 'player_login':
|
||||
this.options.session.handleLogin(message.data);
|
||||
break;
|
||||
@@ -127,7 +141,7 @@ export class PlatformHandlers {
|
||||
// Desk.show_message converts the original time with Number; only >0 auto-closes.
|
||||
const time=Number(data.time);
|
||||
if(!this.options.showMessage)throw Error('show_message requires a message UI');
|
||||
this.options.showMessage(text,time);
|
||||
this.options.showMessage(text,time,'show_message');
|
||||
break;
|
||||
}
|
||||
case 'kick_offline': {
|
||||
|
||||
Reference in New Issue
Block a user