feat: integrate platform room entry, UI migration and erqiwang documentation
This commit is contained in:
@@ -6,7 +6,7 @@ This file provides guidance to Codex (Codex.ai/code) when working with code in t
|
||||
|
||||
**任何前端开发都必须完全遵循前后端数据包的协议与数据结构,做到服务器零改动。** 这是本仓库不可逾越的最高准则,优先于一切其它考量:
|
||||
|
||||
- 协议信封、`route`/`rpc` 命名、字段名与类型、`roomtype` 配置数组、`deskinfo` 快照结构等,**必须与现有协议逐字节对齐**(依据 `docs/protocol/`),不得为前端方便而改变格式或新增/重命名字段。
|
||||
- 协议信封、`route`/`rpc` 命名、字段名与类型、`roomtype` 配置编码、`deskinfo` 快照结构等,**必须与现有协议逐字节对齐**(依据 `docs/protocol/`),不得为前端方便而改变格式或新增/重命名字段。
|
||||
- 遇到协议层有疑问时,**先读 `docs/protocol/` 对应章节核对,不要臆测**;宁可前端多做适配,也绝不要求服务器配合改动。
|
||||
- 新的 Cocos 前端(`YouleNexus`)的目标,就是在不改服务器的前提下复刻该协议契约、实现联调兼容。
|
||||
|
||||
@@ -23,12 +23,20 @@ This file provides guidance to Codex (Codex.ai/code) when working with code in t
|
||||
|
||||
## 仓库总览
|
||||
|
||||
这是友乐(Youle)棋牌游戏平台的前端工作区,核心是「**一套前端模板 + 多个子游戏**」的架构,并正在迁移到 Cocos Creator。三个顶层目录:
|
||||
这是友乐(Youle)棋牌游戏平台的前端工作区,核心是「**一套前端模板 + 多个子游戏**」的架构,并正在迁移到 Cocos Creator。主要目录:
|
||||
|
||||
- **`projects/`** —— 旧版 HTML5 前端。`projects/Game_Surface_3` 是**前端模板(平台外壳)**,也是新前端 UI 迁移的**原工程(迁移源)**;其余目录都是**基于该模板扩展出来的子游戏**,平台层几乎不动,只改子游戏层 + 美术数据。分层结构与关键文件见 `projects/AGENTS.md`。
|
||||
- **`docs/protocol/`** —— 前端模板框架与服务器收发包的**协议规范**(权威文档,8 篇)。改动任何网络层代码前**必须先读对应章节**,服务器不可改,前端必须严格对齐协议。
|
||||
- **`cocoscreator_projects/YouleNexus/`** —— 新的 Cocos Creator 3.8+ 前端工程,目标是按 `docs/protocol` 复刻协议契约,做到服务器零改动即可联调。
|
||||
|
||||
### 服务器文档与二七王服务端
|
||||
|
||||
- **`server/development-guide/`**:服务器通用开发文档。查服务端框架、子游戏接入、通信协议和开发约束时,从 [README](server/development-guide/README.md) 开始,按任务阅读对应章节。
|
||||
- **`server/games/erqiwang/`**:二七王当前改动后的服务器代码。核对实际行为时读取这里的实现,不以 `projects/erqiwang` 的旧前端推断当前服务器规则。
|
||||
- 二七王规则设计位于 [design.md](server/games/erqiwang/docs/design/design.md),玩法协议位于 [packet_protocol.md](server/games/erqiwang/docs/protocol/packet_protocol.md)。前端接入时同时核对设计、协议与服务端实现;发现差异应明确记录,不把设计要求冒充已实现行为。
|
||||
- `roomtype` 由目标子游戏定义,可能是数组或字符串;平台通用流程不可擅自转换类型。二七王实际解析以 `class.config.js` 为入口,局数与扣卡检查 `class.export.js`;位索引只在协议文档中维护,不在本文件重复定义。
|
||||
- 查阅服务器源码用于前端适配,不代表授权修改服务器代码;前端开发继续遵守“服务器零改动”。
|
||||
|
||||
### 原工程 `Game_Surface_3` → `YouleNexus` 的 UI 迁移
|
||||
|
||||
`YouleNexus` 的 UI 资源(`assets/framework/ui/prefabs/`)从**原工程 `projects/Game_Surface_3`** 逐层复刻。数据契约与流程规范:
|
||||
@@ -42,7 +50,7 @@ This file provides guidance to Codex (Codex.ai/code) when working with code in t
|
||||
|
||||
`docs/protocol/` 是权威文档,改任何网络层代码前先读对应章节,**不要凭本文件的转述臆测**。
|
||||
|
||||
**两个不可妥协的约束:** ① `roomtype` 房间配置数组结构必须与目标子游戏**逐字节一致**(服务器据此解析规则);② `deskinfo` 对局快照须可序列化/反序列化以支持 `isbattle==1` 时 `Game_Modify.Reconnect(deskinfo)` 断线重连。
|
||||
**两个不可妥协的约束:** ① `roomtype` 房间配置编码的类型与结构必须与目标子游戏**逐字节一致**(服务器据此解析规则);② `deskinfo` 对局快照须可序列化/反序列化以支持 `isbattle==1` 时 `Game_Modify.Reconnect(deskinfo)` 断线重连。
|
||||
|
||||
## 客户端侧适配约束:远程配置 / 原生数据接口 / 原生↔H5 桥接
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
type ClipboardHost=
|
||||
|{kind:'settings';read:()=>unknown}
|
||||
|{kind:'bridge';call:(name:'gamepastetext',data:string,callback:(value:unknown)=>void)=>void}
|
||||
|{kind:'browser';read:()=>Promise<string>};
|
||||
|
||||
/** 05_Func: settings takes no arguments; WVJB takes "" and returns through its callback. */
|
||||
export async function readClipboardText(host:ClipboardHost):Promise<string>{
|
||||
const value=host.kind==='bridge'?await new Promise<unknown>((resolve,reject)=>{
|
||||
const timer=setTimeout(()=>reject(Error('读取剪贴板超时,请手动输入')),10000);
|
||||
try{host.call('gamepastetext','',value=>{clearTimeout(timer);resolve(value);});}
|
||||
catch(error){clearTimeout(timer);reject(error);}
|
||||
}):await host.read();
|
||||
if(typeof value!=='string')throw Error('Invalid clipboard text');
|
||||
return value;
|
||||
}
|
||||
|
||||
export async function readInviteClipboard(host:ClipboardHost):Promise<string>{
|
||||
return (await readClipboardText(host)).replace(/[^0-9]/g,'');
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "4aeb3de8-f982-4246-95be-7dca058bc99d",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import {requireRecord} from '../../protocol/contracts/validation.ts';
|
||||
/** Logic.readRoomList/addRoomToList/removeRoomFromList. This is owner-return history, not recently played rooms. */
|
||||
export class OwnedRoomHistory {
|
||||
private readonly key:string;
|
||||
constructor(private readonly storage:Pick<Storage,'getItem'|'setItem'>,gameid:string|number,agentid:string|number){this.key='tsgame_roomlist_'+gameid+agentid;}
|
||||
read():readonly number[]{
|
||||
const text=this.storage.getItem(this.key);
|
||||
if(!text){this.save([]);return [];}
|
||||
const raw=requireRecord(JSON.parse(text),this.key);
|
||||
if(!Array.isArray(raw.data)||raw.data.some(n=>typeof n!=='number'||!Number.isSafeInteger(n)||n<=0))throw Error('Invalid '+this.key);
|
||||
return Object.freeze([...raw.data]);
|
||||
}
|
||||
private code(value:unknown):number {
|
||||
if(!(typeof value==='string'&&/^[0-9]+$/.test(value)||typeof value==='number'))throw Error('Invalid room history roomcode');
|
||||
const code=Number(value);if(!Number.isSafeInteger(code)||code<=0)throw Error('Invalid room history roomcode');return code;
|
||||
}
|
||||
private save(data:readonly number[]):void{this.storage.setItem(this.key,JSON.stringify({data}));}
|
||||
joined(raw:Readonly<Record<string,unknown>>):void{
|
||||
if(Number(raw.state)===99||Number(raw.state)===0&&Number(raw.isowner)===1){const code=this.code(raw.roomcode);this.save(this.read().filter(n=>n!==code));}
|
||||
}
|
||||
exited(raw:Readonly<Record<string,unknown>>,infinite:number):void{
|
||||
if(Number(raw.isowner)!==1||infinite!==0)return;
|
||||
const code=this.code(raw.roomcode),list=this.read();if(!list.includes(code))this.save([code,...list]);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "ca074aba-afc9-428f-93ea-199d30dba6ef",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ export const BUILD_IDENTITY: ChannelIdentity = {
|
||||
// This game's entry in config_test/update_jsonv2.txt belongs to this agent/channel.
|
||||
agentid: '1B2h0ccl205c390Y28m1Ajdplkuu4wgy',
|
||||
channelid: 'aouv0LotK0pYyQ0Pdrx0CsdcaezfzrcG',
|
||||
// agentid: 'veRa0qrBf0df2K1G4de2tgfmVxB2jxpv',
|
||||
// channelid: 'FtJf073aa0d6rI1xD8J1Y42fINTm0ziK',
|
||||
gameid: 'J9r4022t80pxlb01zOK76DN1WD4QewFl',
|
||||
marketid: 4,
|
||||
version: 1, // 数字 versionCode(联调时改成本地服要求的版本号)
|
||||
|
||||
@@ -2,13 +2,15 @@ import type { RuntimeConfig } from '../config/runtime-config.ts';
|
||||
import { buildFirstSliceEnvelope } from '../protocol/first-slice-routes.ts';
|
||||
import type { OutboundEnvelope } from '../core/types/envelope.ts';
|
||||
import {
|
||||
buildCreateRoomRequest,
|
||||
type CreateRoomEnvironment,
|
||||
buildExitRoomRequest,
|
||||
buildJoinRoomRequest,
|
||||
buildPrepareRequest,
|
||||
type JoinRoomEnvironment,
|
||||
type RoomIdentity,
|
||||
} from '../protocol/contracts/index.ts';
|
||||
import { PlatformStore } from './stores/platform-store.ts';
|
||||
import { cloneAndFreezeRoomtype, PlatformStore } from './stores/platform-store.ts';
|
||||
import type { InsideRoomState, PlatformState } from './stores/platform-types.ts';
|
||||
|
||||
/** The complete-envelope send capability used by platform command adapters. */
|
||||
@@ -23,9 +25,11 @@ export interface PlatformCommandsOptions {
|
||||
}
|
||||
|
||||
export interface JoinRoomCommand extends JoinRoomEnvironment {
|
||||
readonly roomcode: string;
|
||||
readonly roomcode: string | number;
|
||||
}
|
||||
|
||||
export interface CreateRoomCommand extends CreateRoomEnvironment {}
|
||||
|
||||
export class UnsupportedGameHostCommandError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
@@ -37,6 +41,23 @@ export class UnsupportedGameHostCommandError extends Error {
|
||||
export class PlatformCommands {
|
||||
constructor(private readonly options: PlatformCommandsOptions) {}
|
||||
|
||||
getPlayerInvitecode():void {
|
||||
const playerid=this.taskPlayerId(),player=this.options.store.getState().players.entities[playerid];
|
||||
const {openid,unionid}=player;
|
||||
if(typeof openid!=='string'||!(typeof unionid==='string'||typeof unionid==='number'&&Number.isFinite(unionid)))throw Error('Invite query requires login openid and unionid');
|
||||
this.options.send.send(buildFirstSliceEnvelope('get_player_invitecode',{
|
||||
agentid:this.options.runtimeConfig.identity.agentid,playerid,unionid,openid,
|
||||
}));
|
||||
}
|
||||
|
||||
bindInvitecode(invitecode:string):void {
|
||||
const playerid=this.taskPlayerId();
|
||||
if(typeof invitecode!=='string')throw Error('invitecode must be a string');
|
||||
this.options.send.send(buildFirstSliceEnvelope('binding_invitecode',{
|
||||
agentid:this.options.runtimeConfig.identity.agentid,playerid,invitecode,
|
||||
}));
|
||||
}
|
||||
|
||||
getVipRooms(shortcodeList:readonly (string|number)[]):void {
|
||||
this.taskPlayerId();
|
||||
const {agentid,gameid}=this.options.runtimeConfig.identity;
|
||||
@@ -57,6 +78,27 @@ export class PlatformCommands {
|
||||
this.options.send.send(buildFirstSliceEnvelope('get_player_task',{agentid,playerid,gameid}));
|
||||
}
|
||||
|
||||
getVipRankList(limit:number):void {
|
||||
this.taskPlayerId();if(!Number.isInteger(limit)||limit<=0)throw Error('Invalid vipRankLimit');
|
||||
this.options.send.send(buildFirstSliceEnvelope('getVipRankList',{agentid:this.options.runtimeConfig.identity.agentid,limit}));
|
||||
}
|
||||
joinOwnedRoom(roomcode:number,location:unknown):void {
|
||||
const playerid=this.taskPlayerId(),state=this.options.store.getState();
|
||||
if(!Number.isSafeInteger(roomcode)||roomcode<=0)throw Error('Invalid owned roomcode');
|
||||
const ip=state.players.entities[playerid].ip;if(typeof ip!=='string')throw Error('Owned room join requires player login ip');
|
||||
const {agentid,gameid}=this.options.runtimeConfig.identity;
|
||||
this.options.send.send(buildFirstSliceEnvelope('self_join_room',{agentid,playerid,gameid,roomcode,joinmode:1,location,ip}));
|
||||
}
|
||||
getTreasureList():void {
|
||||
this.taskPlayerId();const {agentid,gameid}=this.options.runtimeConfig.identity;
|
||||
this.options.send.send(buildFirstSliceEnvelope('get_treasurelist',{agentid,gameid}));
|
||||
}
|
||||
redeemCard(cardno:string):void {
|
||||
const playerid=this.taskPlayerId();
|
||||
if(typeof cardno!=='string'||cardno===''||/^[ ]+$/.test(cardno))throw Error('Invalid cardno');
|
||||
this.options.send.send(buildFirstSliceEnvelope('topup_card',{agentid:this.options.runtimeConfig.identity.agentid,playerid,cardno}));
|
||||
}
|
||||
|
||||
claimTask(taskid:number|string):void {
|
||||
const playerid=this.taskPlayerId();
|
||||
const task=this.options.store.getState().tasks?.find(task=>String(task.taskid)===String(taskid));
|
||||
@@ -93,6 +135,12 @@ export class PlatformCommands {
|
||||
));
|
||||
}
|
||||
|
||||
createRoom(command: CreateRoomCommand): void {
|
||||
const playerid = this.taskPlayerId();
|
||||
const roomtype = cloneAndFreezeRoomtype(command.roomtype);
|
||||
this.options.send.send(buildCreateRoomRequest(this.options.runtimeConfig, playerid, {...command, roomtype}));
|
||||
}
|
||||
|
||||
joinRoom(command: JoinRoomCommand): void {
|
||||
const state = this.options.store.getState();
|
||||
if (state.room.kind !== 'outside') {
|
||||
|
||||
@@ -4,13 +4,15 @@ import {
|
||||
GameSessionHost,
|
||||
} from '../sdk/runtime/game-session-host.ts';
|
||||
import {
|
||||
parseCreateRoomResponse,
|
||||
parseLoginResponse,
|
||||
parseSelfJoinRoomResponse,
|
||||
type ParsedSelfExitPayload,
|
||||
type ReconnectSnapshot,
|
||||
} from '../protocol/contracts/index.ts';
|
||||
import { PlatformStore } from './stores/platform-store.ts';
|
||||
import { cloneAndFreezeRoomtype, PlatformStore } from './stores/platform-store.ts';
|
||||
import type { PlatformState } from './stores/platform-types.ts';
|
||||
import type {LoginAccountIdentity} from '../protocol/contracts/login-contract.ts';
|
||||
|
||||
export interface GameHostLeasePort {
|
||||
readonly host: GameHost;
|
||||
@@ -21,12 +23,13 @@ export type GameHostLeaseFactory = () => GameHostLeasePort;
|
||||
|
||||
/** A valid nonzero server outcome, delivered without changing canonical state. */
|
||||
export interface ServerDenial {
|
||||
readonly rpc: 'player_login' | 'self_join_room';
|
||||
readonly rpc: 'player_login' | 'self_join_room' | 'create_room';
|
||||
readonly state: number;
|
||||
readonly data: Readonly<Record<string, unknown>>;
|
||||
}
|
||||
|
||||
export interface RuntimeSessionOptions {
|
||||
readonly roomHistory?: import('../adapters/native/owned-room-history.ts').OwnedRoomHistory;
|
||||
readonly store: PlatformStore;
|
||||
readonly gameSession: GameSessionHost;
|
||||
readonly createGameHostLease: GameHostLeaseFactory;
|
||||
@@ -48,6 +51,9 @@ export class RuntimeSessionFault extends Error {
|
||||
/** Coordinates the canonical platform snapshot with the one active game session. */
|
||||
export class RuntimeSession {
|
||||
private loginIsPending = false;
|
||||
private lastJoinedRoomcode: string | null = null;
|
||||
/** Non-device login owns identity in authorization; device login owns it in the response. */
|
||||
private authorizedIdentity:Pick<LoginAccountIdentity,'openid'|'unionid'>|undefined;
|
||||
private wasKicked = false;
|
||||
private terminalFault: RuntimeSessionFault | null = null;
|
||||
private activeLease: GameHostLeasePort | null = null;
|
||||
@@ -65,8 +71,10 @@ export class RuntimeSession {
|
||||
|
||||
get fault(): Error | null { return this.terminalFault; }
|
||||
|
||||
markLoginPending(): void {
|
||||
markLoginPending(identity?:Pick<LoginAccountIdentity,'openid'|'unionid'>|null): void {
|
||||
this.requireOperational();
|
||||
// No argument is a reconnect of the current account; null selects device response identity.
|
||||
if(identity!==undefined)this.authorizedIdentity=identity===null?undefined:identity;
|
||||
this.loginIsPending = true;
|
||||
}
|
||||
|
||||
@@ -78,7 +86,8 @@ export class RuntimeSession {
|
||||
this.options.onServerDenial({ rpc: 'player_login', state: parsed.state, data: parsed.raw });
|
||||
return;
|
||||
}
|
||||
const committed = this.options.store.applyLoginSuccess(parsed);
|
||||
this.lastJoinedRoomcode = null;
|
||||
const committed = this.options.store.applyLoginSuccess(parsed,this.authorizedIdentity);
|
||||
if (parsed.room === null) {
|
||||
this.releaseOrFault('login lobby replacement');
|
||||
return;
|
||||
@@ -86,15 +95,37 @@ export class RuntimeSession {
|
||||
this.openCommittedRoom(committed, parsed.reconnect, 'login room open');
|
||||
}
|
||||
|
||||
handleCreateRoom(data: unknown): void {
|
||||
this.requireOperational();
|
||||
const parsed = parseCreateRoomResponse(data);
|
||||
if (parsed.state !== 0) {
|
||||
this.options.onServerDenial({rpc: 'create_room', state: parsed.state, data: parsed.raw});
|
||||
return;
|
||||
}
|
||||
if (parsed.room === null) throw new Error('create_room missing parsed room');
|
||||
const current = this.options.store.getState().room;
|
||||
if (current.kind === 'inside' && current.roomcode === parsed.room.roomcode
|
||||
&& this.options.gameSession.state === 'active') return;
|
||||
// Subgame code receives an owned immutable value, never the server response graph.
|
||||
const roomtype = cloneAndFreezeRoomtype(parsed.room.roomtype);
|
||||
const count = this.options.gameSession.entry.resolveSeatCount(roomtype);
|
||||
const committed = this.options.store.createRoom(parsed, count);
|
||||
this.openCommittedRoom(committed, {present: false}, 'create room open');
|
||||
}
|
||||
|
||||
handleSelfJoin(data: unknown): void {
|
||||
this.requireOperational();
|
||||
const parsed = parseSelfJoinRoomResponse(data);
|
||||
this.options.roomHistory?.joined(parsed.raw);
|
||||
if (parsed.state !== 0) {
|
||||
this.options.onServerDenial({ rpc: 'self_join_room', state: parsed.state, data: parsed.raw });
|
||||
return;
|
||||
}
|
||||
if (parsed.room !== null && this.lastJoinedRoomcode === parsed.room.roomcode
|
||||
&& this.options.gameSession.state === 'active') return;
|
||||
const committed = this.options.store.replaceRoom(parsed);
|
||||
this.openCommittedRoom(committed, parsed.reconnect, 'self join room open');
|
||||
this.lastJoinedRoomcode = parsed.room!.roomcode;
|
||||
}
|
||||
|
||||
handleSelfExit(parsed: ParsedSelfExitPayload): void {
|
||||
@@ -122,6 +153,7 @@ export class RuntimeSession {
|
||||
}
|
||||
|
||||
try {
|
||||
this.options.roomHistory?.exited(parsed.raw,state.room.infinite);
|
||||
this.options.store.clearRoom();
|
||||
} catch (error) {
|
||||
this.throwFault('self exit state commit', [error, ...this.releaseGame()]);
|
||||
@@ -208,6 +240,7 @@ export class RuntimeSession {
|
||||
}
|
||||
|
||||
private releaseGame(): unknown[] {
|
||||
this.lastJoinedRoomcode = null;
|
||||
const errors: unknown[] = [];
|
||||
const lease = this.activeLease;
|
||||
this.activeLease = null;
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Router } from '../protocol/router.ts';
|
||||
import { isLoginResponse } from '../protocol/first-slice-routes.ts';
|
||||
import type { GameEntry, GameHost } from '../sdk/contracts/index.ts';
|
||||
import { GameSessionHost } from '../sdk/runtime/game-session-host.ts';
|
||||
import { PlatformCommands, type JoinRoomCommand } from './commands.ts';
|
||||
import { PlatformCommands, type JoinRoomCommand, type CreateRoomCommand } from './commands.ts';
|
||||
import type { ConnectionIntent } from './connection-intent.ts';
|
||||
import {
|
||||
createGameHostAdapter,
|
||||
@@ -39,6 +39,7 @@ export interface PlatformRuntimeOptions {
|
||||
readonly loadResources: () => Promise<void>;
|
||||
readonly waitForMinimumDisplay: () => Promise<void>;
|
||||
readonly getLoginDeviceSnapshot: () => LoginDeviceSnapshot;
|
||||
readonly roomHistory?: import('../adapters/native/owned-room-history.ts').OwnedRoomHistory;
|
||||
readonly clock?: Clock;
|
||||
}
|
||||
|
||||
@@ -233,6 +234,7 @@ export class PlatformRuntime {
|
||||
send,
|
||||
});
|
||||
const session = new RuntimeSession({
|
||||
roomHistory:this.options.roomHistory,
|
||||
store: this.store,
|
||||
gameSession,
|
||||
createGameHostLease: () => this.createGameHostLease(commands, send),
|
||||
@@ -290,19 +292,24 @@ export class PlatformRuntime {
|
||||
const config = this.requireConfig();
|
||||
const wire = this.requireOpenWire();
|
||||
const session = this.requireSession();
|
||||
const device=this.options.getLoginDeviceSnapshot();
|
||||
const envelope = buildLoginRequest(
|
||||
config,
|
||||
account,
|
||||
this.options.getLoginDeviceSnapshot(),
|
||||
device,
|
||||
);
|
||||
|
||||
wire.send(envelope);
|
||||
this.loginEnvelope = envelope;
|
||||
this.connectionIntent = { type: 'login', envelope };
|
||||
session.markLoginPending();
|
||||
session.markLoginPending(device.deviceLogin.enabled?null:Object.freeze({openid:envelope.data.openid,unionid:envelope.data.unionid}));
|
||||
this.startLoginGuard();
|
||||
}
|
||||
|
||||
createRoom(command: CreateRoomCommand): void {
|
||||
this.requireCommands().createRoom(command);
|
||||
}
|
||||
|
||||
joinRoom(command: JoinRoomCommand): void {
|
||||
this.requireCommands().joinRoom(command);
|
||||
}
|
||||
@@ -312,8 +319,14 @@ export class PlatformRuntime {
|
||||
}
|
||||
|
||||
getVipRooms(codes:readonly (string|number)[]):void {this.requireCommands().getVipRooms(codes);}
|
||||
getVipRankList(limit:number):void {this.requireCommands().getVipRankList(limit);}
|
||||
joinOwnedRoom(code:number,location:unknown):void {this.requireCommands().joinOwnedRoom(code,location);}
|
||||
getTreasureList():void {this.requireCommands().getTreasureList();}
|
||||
redeemCard(cardno:string):void {this.requireCommands().redeemCard(cardno);}
|
||||
joinVipRoom(code:string|number,location:unknown):void {this.requireCommands().joinVipRoom(code,location);}
|
||||
getPlayerTasks():void {this.requireCommands().getPlayerTasks();}
|
||||
getPlayerInvitecode():void {this.requireCommands().getPlayerInvitecode();}
|
||||
bindInvitecode(code:string):void {this.requireCommands().bindInvitecode(code);}
|
||||
claimTask(taskid:number|string):void {this.requireCommands().claimTask(taskid);}
|
||||
|
||||
exitRoom(): void {
|
||||
@@ -531,8 +544,8 @@ export class PlatformRuntime {
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (rpc === 'self_join_room') {
|
||||
this.requireGameSession().showRoomAfterOpen();
|
||||
if (rpc === 'self_join_room' || rpc === 'create_room') {
|
||||
if (this.store.getState().room.kind === 'inside') this.requireGameSession().showRoomAfterOpen();
|
||||
return;
|
||||
}
|
||||
if (rpc === 'self_exit_room') this.options.scene.showLobby();
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface ScenePort {
|
||||
showReconnect(): void;
|
||||
showKicked(data: unknown): void;
|
||||
/** Required when the host supports the server's generic message UI. */
|
||||
showTips?(message: string, time: number, source?:'show_message'|'update_roomcard'): void;
|
||||
showTips?(message: string, time: number, source?:'show_message'|'update_roomcard'|'update_bean'|'binding_invitecode'): void;
|
||||
/** Recoverable server result; the consumer interprets the original failure payload. */
|
||||
showServerDenial(outcome: ServerDenial): void;
|
||||
showFatal(error: Error): void;
|
||||
|
||||
+85
-2
@@ -1,6 +1,9 @@
|
||||
import type { Unsubscribe } from '../../core/reactive.ts';
|
||||
import {parseVipRooms} from '../../protocol/contracts/vip-room.ts';
|
||||
import {parseRankList,parseVipRankList} from '../../protocol/contracts/rank-list.ts';
|
||||
import type { TaskData } from '../../core/types/task.ts';
|
||||
import type {LoginAccountIdentity} from '../../protocol/contracts/login-contract.ts';
|
||||
import {requireStringOrFiniteNumber} from '../../protocol/contracts/validation.ts';
|
||||
import {
|
||||
hasOwn,
|
||||
requireArray,
|
||||
@@ -12,6 +15,7 @@ import {
|
||||
type ParsedLoginResponse,
|
||||
type ParsedOnlinePayload,
|
||||
type ParsedRoomResponse,
|
||||
type ParsedCreateRoomResponse,
|
||||
type ParsedSeatPayload,
|
||||
} from '../../protocol/contracts/index.ts';
|
||||
import type {
|
||||
@@ -148,7 +152,7 @@ function verifyRoomtypeSourceGraph(graph: readonly RoomtypeObjectSnapshot[]): vo
|
||||
}
|
||||
}
|
||||
|
||||
function cloneAndFreezeRoomtype(value: readonly unknown[]): readonly unknown[] {
|
||||
export function cloneAndFreezeRoomtype(value: readonly unknown[]): readonly unknown[] {
|
||||
const copies = new WeakMap<object, object>();
|
||||
const active = new WeakSet<object>();
|
||||
const ownedGraph: object[] = [];
|
||||
@@ -509,6 +513,54 @@ export class PlatformStore {
|
||||
applyVipRooms(data:unknown):void {
|
||||
this.commit(Object.freeze({...this.state,vipRooms:parseVipRooms(data)}));
|
||||
}
|
||||
/** Absolute server balances; change-only purchase notices never overwrite money. */
|
||||
applyBeanUpdate(data:unknown):void {
|
||||
const raw=requireRecord(data,'$.data');if(raw.change!==undefined)return;
|
||||
let player=this.taskPlayer();
|
||||
if(raw.seat!==undefined){
|
||||
const seat=requireInteger(raw.seat,'$.data.seat'),room=this.state.room;
|
||||
if(room.kind!=='inside')throw Error('update_bean seat requires a room');
|
||||
const id=room.seatPlayerIds[seat];
|
||||
if(id===undefined||id===null||!this.state.players.entities[id])throw Error('update_bean seat has no player');
|
||||
player=this.state.players.entities[id];
|
||||
}
|
||||
const bean=requireNumber(raw.bean,'$.data.bean');
|
||||
this.commit(Object.freeze({...this.state,players:Object.freeze({...this.state.players,
|
||||
entities:Object.freeze({...this.state.players.entities,[player.playerid]:Object.freeze({...player,bean})})})}));
|
||||
}
|
||||
applyVipRank(data:unknown):void {
|
||||
const raw=requireRecord(data,'$.data');
|
||||
// Desk.getVipRankList ignores a missing/falsy list. A receipt still completes this request.
|
||||
this.commit(Object.freeze({...this.state,vipRank:Object.freeze({entries:raw.list?parseVipRankList(raw.list):null})}));
|
||||
}
|
||||
applyTreasureList(data:unknown):void {
|
||||
const raw=requireRecord(data,'$.data');
|
||||
this.commit(Object.freeze({...this.state,treasureList:parseRankList(raw.list)}));
|
||||
}
|
||||
|
||||
applyInvitecode(data:unknown):void {
|
||||
const raw=requireRecord(data,'$.data');
|
||||
const invitecode=raw.invitecode===null?null:requireString(raw.invitecode,'$.data.invitecode');
|
||||
this.commitInvite('query',invitecode);
|
||||
}
|
||||
|
||||
applyInviteBinding(data:unknown):string {
|
||||
const raw=requireRecord(data,'$.data');
|
||||
// Legacy binding_invitecode compares state == 0; the service also sends integer strings.
|
||||
// Normalize at this response boundary, without changing the shared integer validator.
|
||||
const stateValue=typeof raw.state==='string'&&/^[+-]?\d+$/.test(raw.state)?Number(raw.state):raw.state;
|
||||
const state=requireInteger(stateValue,'$.data.state'),error=requireString(raw.error,'$.data.error');
|
||||
const invitecode=state===0?requireString(raw.invitecode,'$.data.invitecode'):this.taskPlayer().invitecode;
|
||||
this.commitInvite('binding',invitecode);
|
||||
return error;
|
||||
}
|
||||
|
||||
private commitInvite(kind:'query'|'binding',invitecode:string|null|undefined):void {
|
||||
const player=this.taskPlayer();
|
||||
this.commit(Object.freeze({...this.state,inviteResponse:Object.freeze({kind}),players:Object.freeze({
|
||||
...this.state.players,entities:Object.freeze({...this.state.players.entities,[player.playerid]:Object.freeze({...player,invitecode})}),
|
||||
})}));
|
||||
}
|
||||
|
||||
private commit(state: PlatformState): PlatformState {
|
||||
if (Object.is(state, this.state)) return state;
|
||||
@@ -540,9 +592,11 @@ export class PlatformStore {
|
||||
return state;
|
||||
}
|
||||
|
||||
applyLoginSuccess(parsed: ParsedLoginResponse): PlatformState {
|
||||
applyLoginSuccess(parsed: ParsedLoginResponse,authorizedIdentity?:Pick<LoginAccountIdentity,'openid'|'unionid'>): PlatformState {
|
||||
const input = requireRecord(parsed, '$.login');
|
||||
const raw = requireRecord(input.raw, '$.login.raw');
|
||||
// Source selection is explicit: authorization for non-device login, response otherwise.
|
||||
const identity=authorizedIdentity===undefined?raw:authorizedIdentity;
|
||||
const state = requireMatchingState(input.state, raw, '$.login');
|
||||
const rawHasRoom = LOGIN_ROOM_FIELDS.some((field) => hasOwn(raw, field));
|
||||
if (input.room === undefined || (input.room !== null) !== rawHasRoom) {
|
||||
@@ -561,6 +615,9 @@ export class PlatformStore {
|
||||
const player: PlatformPlayer = Object.freeze({
|
||||
playerid,
|
||||
nickname: requireString(raw.nickname, '$.login.raw.nickname'),
|
||||
...(hasOwn(identity,'openid')?{openid:requireString(identity.openid,'$.login.identity.openid')}:{}),
|
||||
...(hasOwn(identity,'unionid')?{unionid:requireStringOrFiniteNumber(identity.unionid,'$.login.identity.unionid')}:{}),
|
||||
...(hasOwn(raw,'invitecode')?{invitecode:raw.invitecode===null?null:requireString(raw.invitecode,'$.login.raw.invitecode')}:{}),
|
||||
avatar: requireString(raw.avatar, '$.login.raw.avatar'),
|
||||
sex: requireInteger(raw.sex, '$.login.raw.sex'),
|
||||
bean: requireNumber(raw.bean, '$.login.raw.bean'),
|
||||
@@ -592,6 +649,32 @@ export class PlatformStore {
|
||||
}));
|
||||
}
|
||||
|
||||
createRoom(parsed: ParsedCreateRoomResponse, seatCount: number): PlatformState {
|
||||
if (parsed.state !== 0 || parsed.room === null) throw new Error('createRoom requires success');
|
||||
const count = requirePositiveInteger(seatCount, 'GameEntry.resolveSeatCount');
|
||||
const {roomcode, seat, roomtype} = parsed.room;
|
||||
if (seat < 0 || seat >= count) throw new RangeError('create_room seat outside GameEntry seat count');
|
||||
const previous = this.getState();
|
||||
const selfPlayerId = previous.players.selfPlayerId;
|
||||
if (selfPlayerId === null) throw new Error('create_room requires authenticated player');
|
||||
const selfPlayer = previous.players.entities[selfPlayerId];
|
||||
if (selfPlayer === undefined) throw new Error('create_room missing login player');
|
||||
const seatPlayerIds: (number | null)[] = Array(count).fill(null);
|
||||
seatPlayerIds[seat] = selfPlayerId;
|
||||
// Desk.create_room seats C_Player and resets preparation. No response.players is fabricated.
|
||||
return this.commit(Object.freeze({
|
||||
app: Object.freeze({phase: 'logged-in'}),
|
||||
players: Object.freeze({selfPlayerId, entities: Object.freeze({
|
||||
[selfPlayerId]: Object.freeze({...selfPlayer, isprepare: 0, onstate: 0}),
|
||||
})}),
|
||||
room: Object.freeze({kind: 'inside', roomcode, selfSeat: seat,
|
||||
seatPlayerIds: Object.freeze(seatPlayerIds), readySeats: Object.freeze([]),
|
||||
offlineSeats: Object.freeze([]), roomtype: cloneAndFreezeRoomtype(roomtype),
|
||||
stage: 0, needprepare: parsed.needprepare, infinite: parsed.infinite,
|
||||
}),
|
||||
}));
|
||||
}
|
||||
|
||||
replaceRoom(parsed: ParsedRoomResponse): PlatformState {
|
||||
const input = requireRecord(parsed, '$.response');
|
||||
const raw = requireRecord(input.raw, '$.response.raw');
|
||||
|
||||
@@ -18,6 +18,9 @@ export interface PlatformPlayer {
|
||||
readonly bean: number;
|
||||
/** Account-only fields are absent on other room players; never default them in views. */
|
||||
readonly roomcard?: number;
|
||||
readonly openid?: string;
|
||||
readonly unionid?: string | number;
|
||||
readonly invitecode?: string | null;
|
||||
readonly taskstate?: number;
|
||||
readonly advanced?: number;
|
||||
readonly score?: number;
|
||||
@@ -52,6 +55,10 @@ export interface InsideRoomState {
|
||||
export type RoomState = OutsideRoomState | InsideRoomState;
|
||||
|
||||
export interface PlatformState {
|
||||
readonly vipRank?:{readonly entries:readonly import('../../protocol/contracts/rank-list.ts').RankEntry[]|null};
|
||||
readonly treasureList?:readonly import('../../protocol/contracts/rank-list.ts').RankEntry[];
|
||||
/** Receipt identity allows repeated queries with an unchanged code to open the view. */
|
||||
readonly inviteResponse?: {readonly kind:'query'|'binding'};
|
||||
readonly vipRooms?: readonly import('../../core/types/vip-room.ts').VipRoom[];
|
||||
/** Absent until a task list response arrives; cleared by login replacement. */
|
||||
readonly tasks?: readonly TaskData[];
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/** Game_Surface_3 Logic.InputRoomCode/pasteRoomCode and GameUI Spirit602. */
|
||||
export class JoinRoomInput {
|
||||
private value='';
|
||||
private busy=false;
|
||||
constructor(private readonly submit:(code:number)=>void){}
|
||||
get code():string{return this.value;}
|
||||
setBusy(value:boolean):void{this.busy=value;}
|
||||
prefill(value:string):void{
|
||||
if(!/^\d{0,6}$/.test(value))throw Error('Invalid saved room shortcode');
|
||||
this.value=value;
|
||||
}
|
||||
digit(value:number):void{
|
||||
if(!Number.isInteger(value)||value<0||value>9)throw Error('Invalid room digit');
|
||||
if(this.busy)return;
|
||||
if(this.value.length<6)this.value+=value;
|
||||
if(this.value.length===6)this.submit(Number(this.value));
|
||||
}
|
||||
remove():void{if(!this.busy)this.value=this.value.slice(0,-1);}
|
||||
clear():void{if(!this.busy)this.value='';}
|
||||
paste(value:string):void{
|
||||
if(this.busy)return;this.value=value.replace(/[^0-9]/g,'').slice(0,6);
|
||||
if(this.value.length===6)this.submit(Number(this.value));
|
||||
}
|
||||
confirm():void{if(!this.busy&&Number(this.value)>0)this.submit(Number(this.value));}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "9301c0f4-8779-44f8-8d19-5f540b499e82",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
+2
File diff suppressed because one or more lines are too long
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "a834856f-7a53-445b-b517-6588ad346e59",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -8,8 +8,8 @@ export const LOBBY_TEMPLATE:Readonly<LobbyTemplate>=Object.freeze({
|
||||
isGameHall:false,mainMenuButton:false,hideNotice:false,vipInfinite:false,
|
||||
});
|
||||
export interface LobbyContext {versionState:0|1;launchMode:0|1;}
|
||||
const HALL_DEFAULTS=Object.freeze({androidPay:0,rankList:0 as number|string,storeUrl:'',bagUrl:'',actData:0 as unknown,worldRoomList:0 as number|string,wareHouse:0 as number|string});
|
||||
const SYS_DEFAULTS=Object.freeze({hideTaskBtn:0 as number|string,hideWxShare:0 as number|string,miniPro:0 as number|string,hideRoomCard:1,cdKey:1,
|
||||
const HALL_DEFAULTS=Object.freeze({androidPay:0,rankList:0 as number|string,isReSetOwnerNote:0 as number|string,storeUrl:'',bagUrl:'',actData:0 as unknown,worldRoomList:0 as number|string,wareHouse:0 as number|string});
|
||||
const SYS_DEFAULTS=Object.freeze({vipRankLimit:10,hideTaskBtn:0 as number|string,hideWxShare:0 as number|string,miniPro:0 as number|string,hideRoomCard:1,cdKey:1,
|
||||
ofcShortCode:null as unknown,hideSpid:null as unknown});
|
||||
function object(value:unknown,name:string):Record<string,unknown>{
|
||||
if(value===null||typeof value!=='object'||Array.isArray(value))throw Error(`Invalid ${name}: expected object`);
|
||||
@@ -34,6 +34,8 @@ export function resolveLobbyMenuConfig(remote:RemoteConfig,template:Readonly<Lob
|
||||
for(const key of Object.keys(SYS_DEFAULTS) as (keyof typeof SYS_DEFAULTS)[]){
|
||||
const value=remote.getValue(key);if(value!=null)Object.assign(sys,{[key]:value});
|
||||
}
|
||||
if(!Number.isInteger(Number(sys.vipRankLimit))||Number(sys.vipRankLimit)<=0)throw Error('Invalid vipRankLimit');
|
||||
sys.vipRankLimit=Number(sys.vipRankLimit);
|
||||
for(const key of ['hideTaskBtn','hideWxShare','miniPro','hideRoomCard','cdKey'] as const){
|
||||
if(!Number.isFinite(Number(sys[key])))throw Error(`Invalid ${key}`);
|
||||
if(key==='hideRoomCard'||key==='cdKey')sys[key]=Number(sys[key]);
|
||||
@@ -42,9 +44,18 @@ export function resolveLobbyMenuConfig(remote:RemoteConfig,template:Readonly<Lob
|
||||
const rawAgent=remote.getValue('agentmode');
|
||||
const agentmode=rawAgent==null?1:Number(rawAgent);
|
||||
if(![1,2,3].includes(agentmode))throw Error('Invalid agentmode');
|
||||
return Object.freeze({agentmode,hall:Object.freeze(hall),sys:Object.freeze(sys),template});
|
||||
// Original GameUI draw cases 568/483/3139: missing vipConfig means unopened;
|
||||
// the earlier matchhtml condition is commented out in the source.
|
||||
const vipConfig=remote.getValue('vipConfig');
|
||||
const locked=Object.freeze({568:!hall.worldRoomList,483:!vipConfig,3139:!sys.ofcShortCode});
|
||||
return Object.freeze({agentmode,hall:Object.freeze(hall),sys:Object.freeze(sys),template,locked});
|
||||
}
|
||||
export type LobbyMenuConfig=ReturnType<typeof resolveLobbyMenuConfig>;
|
||||
/** Original click messages intentionally use different comma characters. */
|
||||
export function lobbyLockedTip(config:LobbyMenuConfig,action:'world-rooms'|'match'|'official-rooms'):string|null{
|
||||
if(action==='world-rooms')return config.locked[568]?'暂未开放,敬请期待':null;
|
||||
return config.locked[action==='match'?483:3139]?'暂未开放,敬请期待':null;
|
||||
}
|
||||
export interface LobbyMenuState {visible:Record<number,boolean>;left:Record<number,number>;top:Record<number,number>;}
|
||||
|
||||
/** Ordered projection of JumpMenuScene. Unmentioned nodes retain their authored state. */
|
||||
@@ -111,11 +122,10 @@ export const LOBBY_MENU_ACTIONS=Object.freeze({
|
||||
export type LobbyAction=typeof LOBBY_MENU_ACTIONS[keyof typeof LOBBY_MENU_ACTIONS];
|
||||
export const LOBBY_UNAVAILABLE:Readonly<Partial<Record<LobbyAction,string>>>=Object.freeze({
|
||||
'create-room':'创建房间:尚未接入目标子游戏规则','records':'战绩:尚未接入子游戏战绩模块',
|
||||
'buy-roomcard':'购买房卡:尚未接入支付模块','buy-bean':'购买星星:尚未接入支付模块',
|
||||
match:'比赛:尚未接入比赛模块','world-rooms':'星星场:尚未接入房间列表',store:'商城:尚未接入商城身份参数与原生接口',
|
||||
activity:'活动:尚未接入活动身份参数与原生接口','my-rooms':'我的房间:尚未接入房间记录与进房',qrcode:'二维码:尚未接入分享模块',
|
||||
activity:'活动:尚未接入活动身份参数与原生接口',
|
||||
'official-rooms':'官方试玩:尚未接入微房号列表','more-games':'更多游戏:尚未接入返回大厅与下载入口',
|
||||
rank:'排行:尚未接入排行榜', 'vip-rank':'VIP 排行:尚未接入排行榜','bind-phone':'绑定手机:尚未接入绑定流程',
|
||||
cdkey:'兑换码:尚未接入兑换请求',bag:'背包:尚未接入背包身份参数与原生接口',agent:'代理:尚未接入代理入口',
|
||||
'bind-phone':'绑定手机:尚未接入绑定流程',
|
||||
bag:'背包:尚未接入背包身份参数与原生接口',agent:'代理:尚未接入代理入口',
|
||||
warehouse:'保险箱:尚未接入仓库模块',feedback:'反馈:尚未接入意见提交',
|
||||
});
|
||||
|
||||
@@ -19,6 +19,14 @@ export function selectLobbyModel(state:PlatformState) {
|
||||
});
|
||||
}
|
||||
export type LobbyModel=ReturnType<typeof selectLobbyModel>;
|
||||
/** Game_Config.Notice: speed 0.1 px/ms, 15 px per gblen byte. */
|
||||
export function announcementMotion(text:string,width:number,elapsedSeconds:number){
|
||||
if(!Number.isFinite(width)||width<=0)throw Error('Invalid announcement width');
|
||||
if(!Number.isFinite(elapsedSeconds)||elapsedSeconds<0)throw Error('Invalid announcement elapsed time');
|
||||
const textWidth=text.replace(/[^\x00-\xff]/g,'**').length*15;
|
||||
const duration=(width+textWidth)/100;
|
||||
return {visible:text.length>0,textWidth,duration,left:width-(elapsedSeconds%duration)*100};
|
||||
}
|
||||
export interface Notice {type:0|1; text:string; image:string; url:string; height:number;}
|
||||
export interface LobbyPolicy {noticeHours:number; notices:readonly Notice[]; scroll:string;
|
||||
starName:string; roomCardName:string; contacts:readonly {label:string;value:string}[];}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import {LEGACY_AUTH_DISTRICTS} from './legacy-auth-districts.ts';
|
||||
|
||||
/** Game_Surface_3 05_Func.IDValidator + 11_GameUI cases 484/493.
|
||||
* Local format validation only. Deliberately retain the source's 15-digit,
|
||||
* parent-district and month/day range semantics; this is not server identity proof.
|
||||
*/
|
||||
export function validateProfileAuth(name:string,id:string):'name'|'id'|null {
|
||||
if(name.length<=1)return 'name';
|
||||
const code=id.toUpperCase();
|
||||
if(code.length!==15&&code.length!==18)return 'id';
|
||||
const body=code.length===18?code.slice(0,17):code;
|
||||
const address=body.slice(0,6);
|
||||
const hasAddress=(key:string)=>Object.prototype.hasOwnProperty.call(LEGACY_AUTH_DISTRICTS,key);
|
||||
if(!hasAddress(address)&&!hasAddress(address.slice(0,4)+'00')&&!hasAddress(address.slice(0,2)+'0000'))return 'id';
|
||||
const birth=code.length===18?body.slice(6,14):body.slice(6,12);
|
||||
const month=parseInt(birth.slice(-4,-2),10),day=parseInt(birth.slice(-2),10);
|
||||
if(month>12||month===0||day>31||day===0)return 'id';
|
||||
if(code.length===15)return null;
|
||||
let sum=0;
|
||||
for(let index=0;index<body.length;index++)sum+=parseInt(body[index],10)*(Math.pow(2,17-index)%11);
|
||||
const value=12-sum%11;
|
||||
const check=value===10?'X':String(value>10?value%11:value);
|
||||
return check===code.slice(-1)?null:'id';
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "11f5830e-5f4b-46fb-9e06-b2b65edbed89",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
export type LoadingRpc='get_player_task'|'get_task_award'|'getVipRankList';
|
||||
/** Wire receipt, rather than a successful model update, completes request loading. */
|
||||
export class RequestLoading {
|
||||
private readonly pending=new Set<LoadingRpc>();
|
||||
constructor(private readonly show:(visible:boolean)=>void){}
|
||||
begin(rpc:LoadingRpc):void{const empty=this.pending.size===0;this.pending.add(rpc);if(empty)this.show(true);}
|
||||
cancel(rpc:LoadingRpc):void{if(this.pending.delete(rpc)&&this.pending.size===0)this.show(false);}
|
||||
received(message:{route:string;rpc:string;data?:unknown}):void{
|
||||
if(message.route!=='agent')return;
|
||||
if(message.rpc==='show_message'){this.clear();return;}
|
||||
if(message.rpc==='get_player_task'||message.rpc==='get_task_award'||message.rpc==='getVipRankList')this.cancel(message.rpc);
|
||||
}
|
||||
clear():void{if(this.pending.size){this.pending.clear();this.show(false);}}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "8bb6a294-bfcf-4126-98f1-0845b58c72db",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -1,4 +1,12 @@
|
||||
import type { RuntimeConfig } from '../config/runtime-config.ts';
|
||||
/** Open_ewm uses this exact config key; absent configuration intentionally does nothing. */
|
||||
export function resolveQrCodePolicy(config:RuntimeConfig){
|
||||
const url=config.remoteConfig.getValue('WechatPublicNo_ewm');
|
||||
if(!url)return null;
|
||||
if(typeof url!=='string')throw Error('Invalid WechatPublicNo_ewm');
|
||||
const policy=resolveSharePolicy(config);
|
||||
return {url,share:{sharefriend:1,type:3,webpageUrl:url,title:policy.title+policy.description,description:undefined,sharetype:0}};
|
||||
}
|
||||
/** Source: 12_Logic.getConfig_Succ then 05_Func.sharefriend. */
|
||||
export function resolveSharePolicy(config:RuntimeConfig){
|
||||
const remote=config.remoteConfig,raw=remote.getValue('hall_config');
|
||||
|
||||
@@ -22,6 +22,10 @@ export {
|
||||
type ParsedLoginResponse,
|
||||
} from './login-contract.ts';
|
||||
export {
|
||||
buildCreateRoomRequest,
|
||||
parseCreateRoomResponse,
|
||||
type ParsedCreateRoomResponse,
|
||||
type CreateRoomEnvironment,
|
||||
buildExitRoomRequest,
|
||||
buildJoinRoomRequest,
|
||||
buildPrepareRequest,
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import {requireArray,requireRecord,requireString,requireStringOrFiniteNumber} from './validation.ts';
|
||||
export interface RankEntry {readonly name:string;readonly headimg:string;readonly playerid:string|number;readonly star:string|number;readonly signature:string;readonly notice?:string;readonly destwo?:string;}
|
||||
/** Server rank entries are consumed as sent. Only rankList1 config replaces # line breaks. */
|
||||
export function parseRankList(value:unknown,fromConfig=false):readonly RankEntry[]{
|
||||
return Object.freeze(requireArray(value,'rank list').map((item,index)=>{
|
||||
const p=`rank list[${index}]`,r=requireRecord(item,p);
|
||||
const name=requireString(r.name,p+'.name'),signature=r.signature?requireString(r.signature,p+'.signature'):'';
|
||||
return Object.freeze({name:fromConfig?configRankName(name):name,headimg:requireString(r.headimg,p+'.headimg'),playerid:requireStringOrFiniteNumber(r.playerid,p+'.playerid'),
|
||||
star:requireStringOrFiniteNumber(r.star,p+'.star'),signature:fromConfig?signature.replace(/#/g,'\n'):signature});
|
||||
}));
|
||||
}
|
||||
|
||||
/** Func.subString(name,16,true): Latin-1 counts one, other UTF-16 units two. */
|
||||
function configRankName(name:string):string {
|
||||
let length=0;
|
||||
for(let i=0;i<name.length;i++){
|
||||
length+=name.charCodeAt(i)>255?2:1;
|
||||
if(length>16)return name.slice(0,i)+'...';
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
export function parseVipRankList(value:unknown):readonly RankEntry[]{
|
||||
const raw=requireArray(value,'VIP rank list'),entries=parseRankList(raw);
|
||||
return Object.freeze(entries.map((entry,i)=>{const item=requireRecord(raw[i],'VIP rank entry');
|
||||
return Object.freeze({...entry,notice:item.notice?requireString(item.notice,'notice'):'',destwo:item.destwo?requireString(item.destwo,'destwo'):''});}));
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "744452fb-2d7e-4a0e-9c49-2e6994f5df84",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
+62
-3
@@ -98,7 +98,8 @@ export interface JoinRoomEnvironment {
|
||||
readonly match_id?: string | number;
|
||||
}
|
||||
|
||||
export interface JoinRoomPayload extends RoomActionPayload {
|
||||
export interface JoinRoomPayload extends Omit<RoomActionPayload, 'roomcode'> {
|
||||
readonly roomcode: string | number;
|
||||
readonly location: unknown;
|
||||
readonly ip: string;
|
||||
readonly vipMatch?: 1;
|
||||
@@ -107,7 +108,7 @@ export interface JoinRoomPayload extends RoomActionPayload {
|
||||
|
||||
export function buildJoinRoomRequest(
|
||||
runtimeConfig: FirstSliceRuntimeConfig,
|
||||
room: RoomIdentity,
|
||||
room: { readonly playerid: number; readonly roomcode: string | number },
|
||||
environment: JoinRoomEnvironment,
|
||||
): FirstSliceEnvelope<'self_join_room', JoinRoomPayload> {
|
||||
const environmentRecord = requireRecord(environment, '$.environment');
|
||||
@@ -118,7 +119,8 @@ export function buildJoinRoomRequest(
|
||||
requireRecord(environmentRecord.location, '$.environment.location');
|
||||
}
|
||||
const data: Record<string, unknown> = {
|
||||
...baseRoomAction(runtimeConfig, room),
|
||||
...baseRoomAction(runtimeConfig, {playerid: room.playerid, roomcode: String(room.roomcode)}),
|
||||
roomcode: requireStringOrFiniteNumber(room.roomcode, '$.room.roomcode'),
|
||||
location: environmentRecord.location,
|
||||
ip: requireString(environmentRecord.ip, '$.environment.ip'),
|
||||
};
|
||||
@@ -241,3 +243,60 @@ export function parseKickServerPayload(value: unknown): ParsedKickPayload {
|
||||
const raw = requireRecord(value, '$.data');
|
||||
return { msg: requireString(raw.msg, '$.data.msg'), raw };
|
||||
}
|
||||
|
||||
|
||||
export interface CreateRoomEnvironment {
|
||||
readonly roomtype: readonly unknown[];
|
||||
readonly location: unknown;
|
||||
readonly ip: string;
|
||||
}
|
||||
|
||||
/** Transport contract only: roomtype contents belong to the subgame. */
|
||||
export function buildCreateRoomRequest(
|
||||
runtimeConfig: FirstSliceRuntimeConfig,
|
||||
playerid: number,
|
||||
command: CreateRoomEnvironment,
|
||||
): FirstSliceEnvelope<'create_room', Readonly<Record<string, unknown>>> {
|
||||
const identity = requireRecord(runtimeConfig.identity, '$.runtimeConfig.identity');
|
||||
const raw = requireRecord(command, '$.command');
|
||||
if (!hasOwn(raw, 'location') || raw.location === undefined) {
|
||||
throw new TypeError('$.command.location: expected present field');
|
||||
}
|
||||
if (raw.location !== null) requireRecord(raw.location, '$.command.location');
|
||||
return buildFirstSliceEnvelope('create_room', {
|
||||
agentid: requireStringOrFiniteNumber(identity.agentid, '$.identity.agentid'),
|
||||
playerid: requireInteger(playerid, '$.playerid'),
|
||||
gameid: requireStringOrFiniteNumber(identity.gameid, '$.identity.gameid'),
|
||||
roomtype: requireArray(raw.roomtype, '$.command.roomtype'),
|
||||
ip: requireString(raw.ip, '$.command.ip'),
|
||||
location: raw.location,
|
||||
});
|
||||
}
|
||||
|
||||
export interface ParsedCreateRoomResponse {
|
||||
readonly state: number;
|
||||
readonly room: { readonly roomcode: string; readonly seat: number; readonly roomtype: readonly unknown[] } | null;
|
||||
readonly needprepare: number;
|
||||
readonly infinite: number;
|
||||
readonly raw: JsonRecord;
|
||||
}
|
||||
|
||||
export function parseCreateRoomResponse(value: unknown): ParsedCreateRoomResponse {
|
||||
const raw = requireRecord(value, '$.data');
|
||||
const state = requireInteger(raw.state, '$.data.state');
|
||||
if (state !== 0) return {state, room: null, needprepare: 0, infinite: 0, raw};
|
||||
// Desk.Init initializes these flags to zero; create_room overrides only when provided.
|
||||
const flag = (key: string): number => {
|
||||
if (!hasOwn(raw, key)) return 0;
|
||||
const value = requireInteger(raw[key], `$.data.${key}`);
|
||||
if (value !== 0 && value !== 1) throw new RangeError(`$.data.${key}: expected protocol flag`);
|
||||
return value;
|
||||
};
|
||||
return {
|
||||
state,
|
||||
room: {roomcode: requireString(raw.roomcode, '$.data.roomcode'),
|
||||
seat: requireInteger(raw.seat, '$.data.seat'),
|
||||
roomtype: requireArray(raw.roomtype, '$.data.roomtype')},
|
||||
needprepare: flag('needprepare'), infinite: flag('infinite'), raw,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,12 +7,19 @@ export function isLoginResponse(message:{route:string;rpc:string}):boolean{
|
||||
}
|
||||
|
||||
export type FirstSliceRpc =
|
||||
| 'getVipRankList'
|
||||
| 'get_treasurelist'
|
||||
| 'topup_card'
|
||||
| 'get_player_invitecode'
|
||||
| 'binding_invitecode'
|
||||
| 'getInfoByShortCode'
|
||||
| 'get_player_task'
|
||||
| 'get_task_award'
|
||||
| 'update_bean'
|
||||
| 'update_roomcard'
|
||||
| 'player_finish_task'
|
||||
| 'player_login'
|
||||
| 'create_room'
|
||||
| 'self_join_room'
|
||||
| 'player_prepare'
|
||||
| 'self_exit_room'
|
||||
@@ -30,12 +37,19 @@ export type FirstSliceRoute = 'platform' | 'agent' | 'room';
|
||||
|
||||
/** 第一纵向切片 rpc → route 的唯一权威映射。 */
|
||||
export const FIRST_SLICE_RPC_ROUTE = {
|
||||
getVipRankList: 'agent',
|
||||
get_treasurelist: 'agent',
|
||||
topup_card: 'agent',
|
||||
get_player_invitecode: 'agent',
|
||||
binding_invitecode: 'agent',
|
||||
getInfoByShortCode: 'agent',
|
||||
get_player_task: 'agent',
|
||||
get_task_award: 'agent',
|
||||
update_bean: 'agent',
|
||||
update_roomcard: 'agent',
|
||||
player_finish_task: 'agent',
|
||||
player_login: 'agent',
|
||||
create_room: 'agent',
|
||||
self_join_room: 'agent',
|
||||
player_prepare: 'room',
|
||||
self_exit_room: 'room',
|
||||
|
||||
@@ -28,7 +28,7 @@ export interface PlatformHandlersOptions {
|
||||
readonly gameSession: GameSessionHost;
|
||||
readonly session: RuntimeSession;
|
||||
readonly connection: ConnectionControlPort;
|
||||
readonly showMessage?: (message:string,time:number,source:'show_message'|'update_roomcard')=>void;
|
||||
readonly showMessage?: (message:string,time:number,source:'show_message'|'update_roomcard'|'update_bean'|'binding_invitecode')=>void;
|
||||
}
|
||||
|
||||
export type PlatformDispatchResult = 'handled-platform';
|
||||
@@ -50,14 +50,33 @@ export class PlatformHandlers {
|
||||
}
|
||||
const rpc = message.rpc as FirstSliceRpc;
|
||||
const expectedRoute = routeForFirstSlice(rpc);
|
||||
if (message.route !== expectedRoute && !isLoginResponse(message)) {
|
||||
if (message.route !== expectedRoute && !isLoginResponse(message) && !(rpc==='update_bean'&&message.route==='room')) {
|
||||
throw new Error(
|
||||
`Platform rpc route mismatch: rpc=${rpc} expected=${expectedRoute} received=${message.route}`,
|
||||
);
|
||||
}
|
||||
|
||||
switch (rpc) {
|
||||
case 'getVipRankList':this.options.store.applyVipRank(message.data);break;
|
||||
case 'get_treasurelist':this.options.store.applyTreasureList(message.data);break;
|
||||
case 'topup_card':break; // Original response is empty; updates arrive separately.
|
||||
case 'get_player_invitecode':this.options.store.applyInvitecode(message.data);break;
|
||||
case 'binding_invitecode':{
|
||||
if(!this.options.showMessage)throw Error('binding_invitecode requires a message UI');
|
||||
const text=this.options.store.applyInviteBinding(message.data);
|
||||
this.options.showMessage(text,3000,'binding_invitecode');break;
|
||||
}
|
||||
case 'getInfoByShortCode':this.options.store.applyVipRooms(message.data);break;
|
||||
case 'update_bean': {
|
||||
const raw=requireRecord(message.data,'$.data');
|
||||
const text=raw.text?requireString(raw.text,'$.data.text'):null;
|
||||
this.options.store.applyBeanUpdate(raw);
|
||||
if(raw.change===undefined&&raw.seat===undefined&&text){
|
||||
if(!this.options.showMessage)throw Error('update_bean requires a message UI');
|
||||
this.options.showMessage(text,0,'update_bean');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'update_roomcard': {
|
||||
const raw=requireRecord(message.data,'$.data');
|
||||
const text=raw.text?requireString(raw.text,'$.data.text'):null;
|
||||
@@ -74,6 +93,9 @@ export class PlatformHandlers {
|
||||
case 'player_login':
|
||||
this.options.session.handleLogin(message.data);
|
||||
break;
|
||||
case 'create_room':
|
||||
this.options.session.handleCreateRoom(message.data);
|
||||
break;
|
||||
case 'self_join_room':
|
||||
this.options.session.handleSelfJoin(message.data);
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/** Pre-room capability: a game owns its page and validated, opaque wire configuration. */
|
||||
export interface CreateRoomPageContext {
|
||||
readonly previousRoomtype:unknown;
|
||||
submit(roomtype:readonly unknown[]):void;
|
||||
cancel():void;
|
||||
reportError(message:string):void;
|
||||
}
|
||||
export interface CreateRoomPagePort {
|
||||
open(context:CreateRoomPageContext):void;
|
||||
setBusy(busy:boolean):void;
|
||||
close():void;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "fd4c9495-d6d5-49da-8476-a510df24f1c4",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from './game-entry.ts';
|
||||
export * from './create-room-page.ts';
|
||||
export * from './game-host.ts';
|
||||
export * from './game-module.ts';
|
||||
export * from './game-seat-mapper.ts';
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.AnimationClip",
|
||||
"_name": "AnnouncementHorn",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
"sample": 2,
|
||||
"speed": 1,
|
||||
"wrapMode": 2,
|
||||
"enableTrsBlending": false,
|
||||
"_duration": 2,
|
||||
"_hash": 0,
|
||||
"_tracks": [
|
||||
{
|
||||
"__id__": 1
|
||||
}
|
||||
],
|
||||
"_exoticAnimation": null,
|
||||
"_events": [],
|
||||
"_embeddedPlayers": [],
|
||||
"_additiveSettings": {
|
||||
"__id__": 6
|
||||
},
|
||||
"_auxiliaryCurveEntries": []
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.ObjectTrack",
|
||||
"_binding": {
|
||||
"__type__": "cc.animation.TrackBinding",
|
||||
"path": {
|
||||
"__id__": 2
|
||||
},
|
||||
"proxy": null
|
||||
},
|
||||
"_channel": {
|
||||
"__id__": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.TrackPath",
|
||||
"_paths": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
"spriteFrame"
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.ComponentPath",
|
||||
"component": "cc.Sprite"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.ObjectCurve",
|
||||
"_times": [
|
||||
0,
|
||||
0.5,
|
||||
1,
|
||||
1.5
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__uuid__": "151439f3-c9bd-4fb2-97b5-5afc295d76e8@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "5647b603-4a35-4bd8-b955-a8ceca2a3f43@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "151439f3-c9bd-4fb2-97b5-5afc295d76e8@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "151439f3-c9bd-4fb2-97b5-5afc295d76e8@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.AnimationClipAdditiveSettings",
|
||||
"enabled": false,
|
||||
"refClip": null
|
||||
}
|
||||
]
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "2.0.4",
|
||||
"importer": "animation-clip",
|
||||
"imported": true,
|
||||
"uuid": "aed03d13-bce1-42a0-9d23-ebd829d9ee55",
|
||||
"files": [
|
||||
".bin"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"name": "AnnouncementHorn"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.AnimationClip",
|
||||
"_name": "RequestLoading",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
"sample": 60,
|
||||
"speed": 1,
|
||||
"wrapMode": 2,
|
||||
"enableTrsBlending": false,
|
||||
"_duration": 1,
|
||||
"_hash": 0,
|
||||
"_tracks": [
|
||||
{
|
||||
"__id__": 1
|
||||
}
|
||||
],
|
||||
"_exoticAnimation": null,
|
||||
"_events": [],
|
||||
"_embeddedPlayers": [],
|
||||
"_additiveSettings": {
|
||||
"__id__": 5
|
||||
},
|
||||
"_auxiliaryCurveEntries": []
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.RealTrack",
|
||||
"_binding": {
|
||||
"__type__": "cc.animation.TrackBinding",
|
||||
"path": {
|
||||
"__id__": 2
|
||||
},
|
||||
"proxy": null
|
||||
},
|
||||
"_channel": {
|
||||
"__id__": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.TrackPath",
|
||||
"_paths": [
|
||||
"angle"
|
||||
]
|
||||
},
|
||||
{
|
||||
"__type__": "cc.animation.Channel",
|
||||
"_curve": {
|
||||
"__id__": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealCurve",
|
||||
"_times": [
|
||||
0,
|
||||
1
|
||||
],
|
||||
"_values": [
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": 0,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 0,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 0,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.RealKeyframeValue",
|
||||
"interpolationMode": 0,
|
||||
"tangentWeightMode": 0,
|
||||
"value": -360,
|
||||
"rightTangent": 0,
|
||||
"rightTangentWeight": 0,
|
||||
"leftTangent": 0,
|
||||
"leftTangentWeight": 0,
|
||||
"easingMethod": 0,
|
||||
"__editorExtras__": null
|
||||
}
|
||||
],
|
||||
"preExtrapolation": 1,
|
||||
"postExtrapolation": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.AnimationClipAdditiveSettings",
|
||||
"enabled": false,
|
||||
"refClip": null
|
||||
}
|
||||
]
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "2.0.4",
|
||||
"importer": "animation-clip",
|
||||
"imported": true,
|
||||
"uuid": "987771c5-7f29-487a-b61a-476981cc9216",
|
||||
"files": [
|
||||
".bin"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"name": "RequestLoading"
|
||||
}
|
||||
}
|
||||
@@ -49,10 +49,10 @@
|
||||
"height": 98,
|
||||
"rawWidth": 108,
|
||||
"rawHeight": 98,
|
||||
"borderTop": 48,
|
||||
"borderBottom": 48,
|
||||
"borderLeft": 53,
|
||||
"borderRight": 53,
|
||||
"borderTop": 26,
|
||||
"borderBottom": 34,
|
||||
"borderLeft": 30,
|
||||
"borderRight": 31,
|
||||
"packable": true,
|
||||
"pixelsToUnit": 100,
|
||||
"pivotX": 0.5,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.2 MiB |
@@ -45,9 +45,9 @@
|
||||
"offsetY": 0,
|
||||
"trimX": 0,
|
||||
"trimY": 0,
|
||||
"width": 1600,
|
||||
"width": 1280,
|
||||
"height": 720,
|
||||
"rawWidth": 1600,
|
||||
"rawWidth": 1280,
|
||||
"rawHeight": 720,
|
||||
"borderTop": 0,
|
||||
"borderBottom": 0,
|
||||
@@ -60,16 +60,16 @@
|
||||
"meshType": 0,
|
||||
"vertices": {
|
||||
"rawPosition": [
|
||||
-800,
|
||||
-640,
|
||||
-360,
|
||||
0,
|
||||
800,
|
||||
640,
|
||||
-360,
|
||||
0,
|
||||
-800,
|
||||
-640,
|
||||
360,
|
||||
0,
|
||||
800,
|
||||
640,
|
||||
360,
|
||||
0
|
||||
],
|
||||
@@ -84,11 +84,11 @@
|
||||
"uv": [
|
||||
0,
|
||||
720,
|
||||
1600,
|
||||
1280,
|
||||
720,
|
||||
0,
|
||||
0,
|
||||
1600,
|
||||
1280,
|
||||
0
|
||||
],
|
||||
"nuv": [
|
||||
@@ -102,12 +102,12 @@
|
||||
1
|
||||
],
|
||||
"minPos": [
|
||||
-800,
|
||||
-640,
|
||||
-360,
|
||||
0
|
||||
],
|
||||
"maxPos": [
|
||||
800,
|
||||
640,
|
||||
360,
|
||||
0
|
||||
]
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "ad5e871f-b5d8-439a-852b-53d4d1d9f61b",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
+538
@@ -0,0 +1,538 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.Prefab",
|
||||
"_name": "OwnerRoomItem",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
"data": {
|
||||
"__id__": 1
|
||||
},
|
||||
"optimizationPolicy": 0,
|
||||
"persistent": false
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "OwnerRoomItem",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": null,
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 2
|
||||
},
|
||||
{
|
||||
"__id__": 8
|
||||
},
|
||||
{
|
||||
"__id__": 14
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 20
|
||||
},
|
||||
{
|
||||
"__id__": 22
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 24
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 33554432,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": "5dxzP/UG5Fea3nNr557ORP"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "Spirit100",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 3
|
||||
},
|
||||
{
|
||||
"__id__": 5
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 7
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 33554432,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": "9blwBxZBxC4LDYs+VIpNy1"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 4
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 264,
|
||||
"height": 80
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": "90IWdamq1CaK2+fcIY8I4G"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "l3ocOicG3kovqa6+Yow7SQ"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Sprite",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 6
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
"_dstBlendFactor": 4,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 255,
|
||||
"g": 255,
|
||||
"b": 255,
|
||||
"a": 255
|
||||
},
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "5f783910-7fd0-4482-a206-8dcb57238c74@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"_type": 0,
|
||||
"_fillType": 0,
|
||||
"_sizeMode": 0,
|
||||
"_fillCenter": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_fillStart": 0,
|
||||
"_fillRange": 0,
|
||||
"_isTrimmedMode": true,
|
||||
"_useGrayscale": false,
|
||||
"_atlas": null,
|
||||
"_id": "e2Q9Z8vy1NVpG+xdDhdD9s"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "VMQNp5XtZ86iR1Z+hSYFOg"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "0lhvW5OWHIVi/ncFScuMKQ",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "Spirit102",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 9
|
||||
},
|
||||
{
|
||||
"__id__": 11
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 13
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 39,
|
||||
"y": 2.5,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 33554432,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": "89d19HpytGVox/SvGWJFDr"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 8
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 10
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 14,
|
||||
"height": 19
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": "50k3QzjPhHhJYWzNgtUGBk"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "1sIXmawSIfDNdF9tSIh6ig"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Sprite",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 8
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 12
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
"_dstBlendFactor": 4,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 255,
|
||||
"g": 255,
|
||||
"b": 255,
|
||||
"a": 255
|
||||
},
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "9d49bb70-608e-46d2-8672-5afb78bbd8d7@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"_type": 0,
|
||||
"_fillType": 0,
|
||||
"_sizeMode": 0,
|
||||
"_fillCenter": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_fillStart": 0,
|
||||
"_fillRange": 0,
|
||||
"_isTrimmedMode": true,
|
||||
"_useGrayscale": false,
|
||||
"_atlas": null,
|
||||
"_id": "32xJfAFBFPL57FrZT1Njpw"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "dYeagt3oXF7LLcLyBNmxcQ"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "xOj6F8iDH5ro1bLGRx3c5g",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "Digits",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 15
|
||||
},
|
||||
{
|
||||
"__id__": 17
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 19
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 32,
|
||||
"y": 2.5,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 33554432,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": "85eISb6stE0oj1mZHpP6zK"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 14
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 16
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 14,
|
||||
"height": 19
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": "44soAEXzBJSaDlfZI1MuoB"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "41Li0cKhzYiSg6SbbaoAGg"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Layout",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 14
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 18
|
||||
},
|
||||
"_resizeMode": 1,
|
||||
"_layoutType": 1,
|
||||
"_cellSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 40,
|
||||
"height": 40
|
||||
},
|
||||
"_startAxis": 0,
|
||||
"_paddingLeft": 0,
|
||||
"_paddingRight": 0,
|
||||
"_paddingTop": 0,
|
||||
"_paddingBottom": 0,
|
||||
"_spacingX": 0,
|
||||
"_spacingY": 0,
|
||||
"_verticalDirection": 1,
|
||||
"_horizontalDirection": 0,
|
||||
"_constraint": 0,
|
||||
"_constraintNum": 2,
|
||||
"_affectedByScale": false,
|
||||
"_isAlign": false,
|
||||
"_id": "53I4gVRnlCNo+Wqps6VeDy"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "k0owfG3taNqw+EIUHZ8V9g"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "lC5WHe9437aSbTecw6lUiQ",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 21
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 264,
|
||||
"height": 80
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": "77ZqoCi+xJ/7Bjxxb0o4bl"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "KLcB/F2HEtr5tYEndV8qbg"
|
||||
},
|
||||
{
|
||||
"__type__": "e40a5gQKgNA6a/yNIkJZlsD",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 23
|
||||
},
|
||||
"digitTemplate": {
|
||||
"__id__": 11
|
||||
},
|
||||
"digitsRoot": {
|
||||
"__id__": 14
|
||||
},
|
||||
"_id": "306fBHxpJHuLQI/kcAnGQS"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "RCmOaA1Wm5nUHFrcVQJpOw"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "0oOd9F3D7yWBfO1u4tL3BA",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
}
|
||||
]
|
||||
+2
-2
@@ -2,12 +2,12 @@
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "b13f487a-451e-41ce-a810-1fab0d52248f",
|
||||
"uuid": "67117675-9f6d-4def-a67c-db0e9fb19b98",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "Layer9_Feedback"
|
||||
"syncNodeName": "OwnerRoomItem"
|
||||
}
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.Prefab",
|
||||
"_name": "PlayerInfoTextItem",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
"data": {
|
||||
"__id__": 1
|
||||
},
|
||||
"optimizationPolicy": 0,
|
||||
"persistent": false
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "PlayerInfoTextItem",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": null,
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 2
|
||||
},
|
||||
{
|
||||
"__id__": 4
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 6
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 10,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 33554432,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 3
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 371,
|
||||
"height": 22.680000000000003
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "JYB5ndvc0hWZFdTsDPujQg"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Label",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 5
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
"_dstBlendFactor": 4,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 0,
|
||||
"g": 0,
|
||||
"b": 0,
|
||||
"a": 255
|
||||
},
|
||||
"_string": "资料文字",
|
||||
"_horizontalAlign": 0,
|
||||
"_verticalAlign": 0,
|
||||
"_actualFontSize": 18.975,
|
||||
"_fontSize": 18,
|
||||
"_fontFamily": "Arial",
|
||||
"_lineHeight": 18,
|
||||
"_overflow": 3,
|
||||
"_enableWrapText": true,
|
||||
"_font": null,
|
||||
"_isSystemFontUsed": true,
|
||||
"_spacingX": 0,
|
||||
"_isItalic": false,
|
||||
"_isBold": false,
|
||||
"_isUnderline": false,
|
||||
"_underlineHeight": 2,
|
||||
"_cacheMode": 0,
|
||||
"_enableOutline": false,
|
||||
"_outlineColor": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 0,
|
||||
"g": 0,
|
||||
"b": 0,
|
||||
"a": 255
|
||||
},
|
||||
"_outlineWidth": 2,
|
||||
"_enableShadow": false,
|
||||
"_shadowColor": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 0,
|
||||
"g": 0,
|
||||
"b": 0,
|
||||
"a": 255
|
||||
},
|
||||
"_shadowOffset": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 2,
|
||||
"y": 2
|
||||
},
|
||||
"_shadowBlur": 2,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "wX+Ww4pBz/TnLcrPEXSuAA"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "Pn6tcB1uaJ1EOUf2nLgpzw",
|
||||
"instance": null,
|
||||
"targetOverrides": null
|
||||
}
|
||||
]
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "9e6dbfc6-26c5-4eac-9cc8-8060a677d5ee",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "PlayerInfoTextItem"
|
||||
}
|
||||
}
|
||||
+1216
File diff suppressed because it is too large
Load Diff
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "5925d1d2-f4b2-44c1-a37a-fb2bcdcf664e",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "VipRankItem"
|
||||
}
|
||||
}
|
||||
+1887
-673
File diff suppressed because it is too large
Load Diff
+691
-124
File diff suppressed because it is too large
Load Diff
+472
-1583
File diff suppressed because it is too large
Load Diff
+1028
-501
File diff suppressed because it is too large
Load Diff
+862
-1603
File diff suppressed because it is too large
Load Diff
+2083
-1200
File diff suppressed because it is too large
Load Diff
+201
-202
File diff suppressed because it is too large
Load Diff
+376
-187
File diff suppressed because it is too large
Load Diff
+41
-11
@@ -25,14 +25,14 @@
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 24
|
||||
"__id__": 25
|
||||
},
|
||||
{
|
||||
"__id__": 26
|
||||
"__id__": 27
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 28
|
||||
"__id__": 29
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
@@ -82,14 +82,14 @@
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 19
|
||||
"__id__": 20
|
||||
},
|
||||
{
|
||||
"__id__": 21
|
||||
"__id__": 22
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 23
|
||||
"__id__": 24
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
@@ -186,6 +186,7 @@
|
||||
"__id__": 5
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 1600,
|
||||
"height": 720
|
||||
},
|
||||
@@ -313,10 +314,13 @@
|
||||
},
|
||||
{
|
||||
"__id__": 16
|
||||
},
|
||||
{
|
||||
"__id__": 18
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 18
|
||||
"__id__": 19
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
@@ -360,6 +364,7 @@
|
||||
"__id__": 13
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 150,
|
||||
"height": 150
|
||||
},
|
||||
@@ -455,6 +460,29 @@
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "3wlBO4ciKrxeTYsQdlQvBg"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Animation",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 11
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": null,
|
||||
"playOnLoad": false,
|
||||
"_clips": [
|
||||
{
|
||||
"__uuid__": "987771c5-7f29-487a-b61a-476981cc9216",
|
||||
"__expectedType__": "cc.AnimationClip"
|
||||
}
|
||||
],
|
||||
"_defaultClip": {
|
||||
"__uuid__": "987771c5-7f29-487a-b61a-476981cc9216",
|
||||
"__expectedType__": "cc.AnimationClip"
|
||||
},
|
||||
"_id": "1b3VMKLpRFPKzD9o608yTZ"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
@@ -478,9 +506,10 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 20
|
||||
"__id__": 21
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 1600,
|
||||
"height": 720
|
||||
},
|
||||
@@ -505,7 +534,7 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 22
|
||||
"__id__": 23
|
||||
},
|
||||
"_alignFlags": 45,
|
||||
"_target": null,
|
||||
@@ -554,9 +583,10 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 25
|
||||
"__id__": 26
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 1600,
|
||||
"height": 720
|
||||
},
|
||||
@@ -581,7 +611,7 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 27
|
||||
"__id__": 28
|
||||
},
|
||||
"_alignFlags": 45,
|
||||
"_target": null,
|
||||
|
||||
+445
-129
File diff suppressed because it is too large
Load Diff
-6762
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,7 +1,7 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.Prefab",
|
||||
"_name": "Login_Layer",
|
||||
"_name": "Login",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
@@ -13,7 +13,7 @@
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "Login_Layer",
|
||||
"_name": "Login",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": null,
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "Login_Layer",
|
||||
"syncNodeName": "Login",
|
||||
"hasIcon": false
|
||||
}
|
||||
}
|
||||
+3649
-2492
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -8,6 +8,6 @@
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "Layer4_MainMenu"
|
||||
"syncNodeName": "MainMenu"
|
||||
}
|
||||
}
|
||||
+3793
File diff suppressed because it is too large
Load Diff
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "e7a05100-7de4-4935-896e-a59061377b87",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "NoticeBoard"
|
||||
}
|
||||
}
|
||||
+1002
File diff suppressed because it is too large
Load Diff
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "260ea2dc-696c-4a65-a2fd-109dd794bb45",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "OwnedRoomList"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "95ee9b79-8c30-4f54-a2cf-19d02083cd28",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "QrCode"
|
||||
}
|
||||
}
|
||||
+1540
File diff suppressed because it is too large
Load Diff
+13
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "ada34847-93c7-48f2-bb0a-5c1db4b112f6",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "RedeemCode"
|
||||
}
|
||||
}
|
||||
+3
-241
@@ -1,7 +1,7 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.Prefab",
|
||||
"_name": "Layer1_Logo",
|
||||
"_name": "ResourceLoading",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
@@ -13,22 +13,19 @@
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "Layer1_Logo",
|
||||
"_name": "ResourceLoading",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": null,
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 2
|
||||
},
|
||||
{
|
||||
"__id__": 50
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [],
|
||||
"_prefab": {
|
||||
"__id__": 60
|
||||
"__id__": 50
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
@@ -1130,241 +1127,6 @@
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "group-32",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 51
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [],
|
||||
"_prefab": {
|
||||
"__id__": 59
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 33554432,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "Spirit221",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 50
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 52
|
||||
},
|
||||
{
|
||||
"__id__": 54
|
||||
},
|
||||
{
|
||||
"__id__": 56
|
||||
}
|
||||
],
|
||||
"_prefab": {
|
||||
"__id__": 58
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": -1612.5,
|
||||
"y": 1099.952,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 33554432,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 51
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 53
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 63,
|
||||
"height": 63
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "Y8tq/cDuhVvttPn+x9+bww"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Sprite",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 51
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 55
|
||||
},
|
||||
"_customMaterial": null,
|
||||
"_srcBlendFactor": 2,
|
||||
"_dstBlendFactor": 4,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 255,
|
||||
"g": 255,
|
||||
"b": 255,
|
||||
"a": 255
|
||||
},
|
||||
"_spriteFrame": {
|
||||
"__uuid__": "974bf7e8-69fd-49ff-95fa-ed7ddb8d6a14@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"_type": 0,
|
||||
"_fillType": 0,
|
||||
"_sizeMode": 0,
|
||||
"_fillCenter": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"_fillStart": 0,
|
||||
"_fillRange": 0,
|
||||
"_isTrimmedMode": true,
|
||||
"_useGrayscale": false,
|
||||
"_atlas": null,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "t+vRkZQc/kDtmwdvT1STKA"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Widget",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 51
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": {
|
||||
"__id__": 57
|
||||
},
|
||||
"_alignFlags": 16,
|
||||
"_target": null,
|
||||
"_left": 0,
|
||||
"_right": 0,
|
||||
"_top": 0,
|
||||
"_bottom": 0,
|
||||
"_horizontalCenter": -1612.5,
|
||||
"_verticalCenter": 0,
|
||||
"_isAbsLeft": true,
|
||||
"_isAbsRight": true,
|
||||
"_isAbsTop": true,
|
||||
"_isAbsBottom": true,
|
||||
"_isAbsHorizontalCenter": true,
|
||||
"_isAbsVerticalCenter": true,
|
||||
"_originalWidth": 0,
|
||||
"_originalHeight": 0,
|
||||
"_alignMode": 2,
|
||||
"_lockFlags": 0,
|
||||
"_id": ""
|
||||
},
|
||||
{
|
||||
"__type__": "cc.CompPrefabInfo",
|
||||
"fileId": "K2+PudUKVOrBYR09Lp3sAA"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "J1IKV6k3EB5NkpQVaZVxiA",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
"__id__": 1
|
||||
},
|
||||
"asset": {
|
||||
"__id__": 0
|
||||
},
|
||||
"fileId": "JccA+NmPM7lVqq5kAuMdjQ",
|
||||
"instance": null,
|
||||
"targetOverrides": null,
|
||||
"nestedPrefabInstanceRoots": null
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PrefabInfo",
|
||||
"root": {
|
||||
+1
-1
@@ -8,6 +8,6 @@
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "Layer1_Logo"
|
||||
"syncNodeName": "ResourceLoading"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "bfaf200b-f8f5-4fcb-b9e3-7e4e831177ce",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "c593ddf6-0173-48e8-96cb-dab1273e43d8",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import {_decorator,Button,Label,Toggle,ToggleContainer} from 'cc';
|
||||
import {CreateRoomPage} from '../../scripts/platform-login/CreateRoomPage.ts';
|
||||
import type {CreateRoomPageContext} from '../../framework/sdk/contracts/create-room-page.ts';
|
||||
import {TemplateRoomRules} from './template-room-rules.ts';
|
||||
const {ccclass,property}=_decorator;
|
||||
@ccclass('TemplateCreateRoomView')
|
||||
export class TemplateCreateRoomView extends CreateRoomPage {
|
||||
@property([ToggleContainer]) groups:ToggleContainer[]=[];
|
||||
@property([Toggle]) options:Toggle[]=[];
|
||||
@property([Label]) optionLabels:Label[]=[];
|
||||
@property(Button) submitButton:Button|null=null;
|
||||
@property([Button]) cancelButtons:Button[]=[];
|
||||
private readonly rules=new TemplateRoomRules();
|
||||
private context:CreateRoomPageContext|null=null;
|
||||
private busy=false;
|
||||
private releases:Array<()=>void>=[];
|
||||
open(context:CreateRoomPageContext):void{
|
||||
this.close();
|
||||
if(this.groups.length!==2||this.options.length!==4||this.optionLabels.length!==4||!this.submitButton||this.cancelButtons.length!==2)throw Error('TemplateCreateRoomView requires serialized controls');
|
||||
this.rules.open(context.previousRoomtype);this.context=context;
|
||||
// A saved source index may have no matching option; initialize that state explicitly.
|
||||
this.groups.forEach(group=>group.allowSwitchOff=true);
|
||||
this.optionLabels.forEach((label,i)=>label.string=this.rules.labels[i]);
|
||||
this.options.forEach((toggle,i)=>{
|
||||
toggle.isChecked=this.rules.selection[Math.floor(i/2)]===i%2;
|
||||
const changed=()=>{if(!this.busy&&toggle.isChecked)this.rules.select(Math.floor(i/2) as 0|1,i%2);};
|
||||
toggle.node.on(Toggle.EventType.TOGGLE,changed);this.releases.push(()=>toggle.node.off(Toggle.EventType.TOGGLE,changed));
|
||||
});
|
||||
this.groups.forEach(group=>group.allowSwitchOff=false);
|
||||
const bind=(button:Button,action:()=>void)=>{const fn=()=>{if(!this.busy&&this.context)try{action();}catch(error){context.reportError(error instanceof Error?error.message:String(error));}};
|
||||
button.node.on(Button.EventType.CLICK,fn);this.releases.push(()=>button.node.off(Button.EventType.CLICK,fn));};
|
||||
bind(this.submitButton,()=>context.submit(this.rules.build()));
|
||||
this.cancelButtons.forEach(button=>{const cancel=()=>context.cancel();button.node.on(Button.EventType.CLICK,cancel);this.releases.push(()=>button.node.off(Button.EventType.CLICK,cancel));});this.setBusy(false);
|
||||
}
|
||||
setBusy(busy:boolean):void{this.busy=busy;this.options.forEach(toggle=>toggle.interactable=!busy);if(this.submitButton)this.submitButton.interactable=!busy;}
|
||||
close():void{for(const release of this.releases.splice(0))release();this.context=null;}
|
||||
onDestroy():void{this.close();}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "ebbef7d9-7bda-4c61-9b0a-1ee56e7817fb",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "prefab",
|
||||
"imported": true,
|
||||
"uuid": "f4582832-23e2-4981-be26-08dfe832aa96",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"syncNodeName": "TemplateRoom"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
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();}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "e0dc1f88-a719-4b19-9827-2cf9e4452be9",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import type {GameEntry,GameHost,GameModule,PlatformGameSnapshot} from '../../framework/sdk/contracts/index.ts';
|
||||
import {TemplateRoomRules} from './template-room-rules.ts';
|
||||
export interface TemplateRoomActions {prepare():void;exit():void;}
|
||||
export interface TemplateRoomPresentation {render(snapshot:PlatformGameSnapshot,actions:TemplateRoomActions):void;close():void;}
|
||||
/** Template hooks are intentionally empty, matching 02_SubGame_Input.js. No gameplay is inferred. */
|
||||
export function createTemplateGame(gameId:string|number){
|
||||
let active:TemplateModule|null=null;
|
||||
class TemplateModule implements GameModule {
|
||||
private host:GameHost|null=null;
|
||||
private unsubscribe:(()=>void)|null=null;
|
||||
private view:TemplateRoomPresentation|null=null;
|
||||
restored:unknown=null;
|
||||
attach(host:GameHost):void{
|
||||
if(this.host||active)throw Error('Template module already attached');
|
||||
this.host=host;active=this;this.unsubscribe=host.subscribe(()=>this.render());
|
||||
}
|
||||
mount(view:TemplateRoomPresentation):void{this.view?.close();this.view=view;this.render();}
|
||||
private requireHost():GameHost{if(!this.host)throw Error('Template room session disposed');return this.host;}
|
||||
private render():void{this.view?.render(this.requireHost().getSnapshot(),{prepare:()=>this.requireHost().execute({type:'room.prepare'}),exit:()=>this.requireHost().execute({type:'room.exit'})});}
|
||||
handlePlatformEvent():void{this.render();}
|
||||
handleGameMessage():void{/* Original template _ReceiveData hook is empty. */}
|
||||
restore(deskinfo:unknown):void{this.requireHost();this.restored=deskinfo;}
|
||||
dispose():void{this.unsubscribe?.();this.unsubscribe=null;this.view?.close();this.view=null;this.host=null;this.restored=null;if(active===this)active=null;}
|
||||
}
|
||||
const rules=new TemplateRoomRules();
|
||||
const entry:GameEntry={key:'Game_Surface_3',gameId,route:'Game_Surface_3',resolveSeatCount:roomtype=>rules.seatCount(roomtype),createModule:()=>new TemplateModule()};
|
||||
return {entry,mount(view:TemplateRoomPresentation){if(!active)throw Error('Template room not attached');active.mount(view);},
|
||||
get restoredSnapshot():unknown{return active?.restored;}};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "c6a24a57-c9c3-4eda-9f82-73f1990703fb",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/** Source: 01_SubGame_modify.js. Options are presentation state, not a rule-array encoder. */
|
||||
export class TemplateRoomRules {
|
||||
readonly labels=['10局(房卡X1)','20局(房卡X2)','房主扣卡','每人扣卡'] as const;
|
||||
private selected:[number,number]=[0,0];
|
||||
get selection():readonly number[]{return [...this.selected];}
|
||||
open(previous:unknown=null):void{
|
||||
if(previous===null){this.selected=[0,0];return;}
|
||||
if(!Array.isArray(previous)||!Number.isInteger(previous[0])||!Number.isInteger(previous[1]))throw Error('Invalid template saved roomtype');
|
||||
this.selected=[previous[0]-1,previous[1]-1];
|
||||
}
|
||||
select(group:0|1,index:number):void{
|
||||
if(!Number.isInteger(index)||index<0||index>1)throw Error('Invalid template option');
|
||||
this.selected[group]=index;
|
||||
}
|
||||
build():unknown[]{return [1,4,1,2,2,[1,1,[1,2000,10],null,null,1],[1,0,5]];}
|
||||
seatCount(roomtype:readonly unknown[]):number{
|
||||
if(!Array.isArray(roomtype))throw Error('Template roomtype must be an array');
|
||||
// Desk.Create uses Game_Config.Max.PlayerCnt because the template defines no getMaxPlayerCount hook.
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "0cad77f9-c126-4532-9ffb-70e650008a34",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -1249,7 +1249,7 @@
|
||||
"shareh5desc": "一起来嗨~",
|
||||
"gameNoticeShow": 0,
|
||||
"shareType":1,
|
||||
"showVisitor":1,
|
||||
"showVisitor":0,
|
||||
"shareImgUrl":"https://tsgames.daoqi88.cn/image/match.png",
|
||||
"hallNoticeShow": 0,
|
||||
"gameHallConfig": {
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
},
|
||||
"autoReleaseAssets": false,
|
||||
"_globals": {
|
||||
"__id__": 5
|
||||
"__id__": 6
|
||||
},
|
||||
"_id": "1c10c2ee-adc2-496f-9005-d3e0e6ebbb56"
|
||||
},
|
||||
@@ -72,6 +72,9 @@
|
||||
},
|
||||
{
|
||||
"__id__": 4
|
||||
},
|
||||
{
|
||||
"__id__": 5
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@@ -182,8 +185,24 @@
|
||||
"__uuid__": "e1b53f04-3e2f-4127-9a3f-f629bed6905e",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"notices": {
|
||||
"__uuid__": "b13f487a-451e-41ce-a810-1fab0d52248f",
|
||||
"redeemCode": {
|
||||
"__uuid__": "ada34847-93c7-48f2-bb0a-5c1db4b112f6",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"qrCode": {
|
||||
"__uuid__": "95ee9b79-8c30-4f54-a2cf-19d02083cd28",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"noticeBoard": {
|
||||
"__uuid__": "e7a05100-7de4-4935-896e-a59061377b87",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"ownedRoomList": {
|
||||
"__uuid__": "260ea2dc-696c-4a65-a2fd-109dd794bb45",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"invite": {
|
||||
"__uuid__": "a3db6daa-a98e-4a73-b0f7-cd122bdb11c5",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"profile": {
|
||||
@@ -206,6 +225,100 @@
|
||||
"__uuid__": "f4af0cc2-2514-4bd5-a0de-7a3dbb32438b",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"rank": {
|
||||
"__uuid__": "3eafe9c2-475b-4c81-b71a-37ffa2717c71",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"rankItem": {
|
||||
"__uuid__": "5925d1d2-f4b2-44c1-a37a-fb2bcdcf664e",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"rankMedals": [
|
||||
{
|
||||
"__uuid__": "fb86ab44-8140-4d8e-82f1-84ae4b8f3216@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "10653735-f46a-4e0f-906f-dacb093dad23@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "87749e95-72aa-435e-93bb-1f41553922f0@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
}
|
||||
],
|
||||
"rankTitle": {
|
||||
"__uuid__": "ecb18612-2066-42d2-8fa0-c0161124cf1e@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"vipRankTitle": {
|
||||
"__uuid__": "97b4bd7f-8716-497f-a375-d9c841cf34e9@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
"ownedRoomDigits": [
|
||||
{
|
||||
"__uuid__": "9d49bb70-608e-46d2-8672-5afb78bbd8d7@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "e71157d8-1261-4917-bac1-1b48ab5b6ab9@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "bade804f-d16a-46b6-8746-600ff6b93cce@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "dae7297a-cb1a-49d7-98a9-a3008a8afc7a@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "f1365825-aa47-4efe-936c-81284b0d5e1f@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "b4d68ae8-0799-47c1-8b30-26b2daed2d59@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "be16e577-8add-4c32-a56b-948a52e0180b@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2fd355d7-493d-474c-b753-676c7ee9e50d@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "3c1709f3-a24f-4a9e-814c-04bc1441da55@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "4dd36de5-fadb-4852-8334-e9b5834a3957@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
}
|
||||
],
|
||||
"rankSymbols": [
|
||||
{
|
||||
"__uuid__": "6b9ad554-bf4a-4493-82dd-92b4328cb8a4@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "2f1e97ec-1bad-4731-9563-d90ae5b93111@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "a1016858-72af-4a2c-8d8e-7098eb82a310@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "a6986c72-2bef-4f50-b215-86d4de943b68@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
},
|
||||
{
|
||||
"__uuid__": "df99cc0a-0b2a-4fdd-b271-7932b2bea237@f9941",
|
||||
"__expectedType__": "cc.SpriteFrame"
|
||||
}
|
||||
],
|
||||
"digits": [
|
||||
{
|
||||
"__uuid__": "fc6e9a8e-0a6d-4555-bc3e-88fd427b9f3a@f9941",
|
||||
@@ -272,32 +385,56 @@
|
||||
],
|
||||
"_id": "abZXhqPblEq57+36N2j8xH"
|
||||
},
|
||||
{
|
||||
"__type__": "ec19eRwzzZA6LQg5DFOX78H",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": null,
|
||||
"createRoom": {
|
||||
"__uuid__": "584dbb85-4acc-4bea-9d9b-e0cbeb8741da",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"room": {
|
||||
"__uuid__": "f4582832-23e2-4981-be26-08dfe832aa96",
|
||||
"__expectedType__": "cc.Prefab"
|
||||
},
|
||||
"roomScene": {
|
||||
"__uuid__": "18f06ada-9d36-485c-9f44-556d6980ca7a",
|
||||
"__expectedType__": "cc.SceneAsset"
|
||||
},
|
||||
"_id": "c2sXHnthJJQoYDj00RAeBa"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.SceneGlobals",
|
||||
"ambient": {
|
||||
"__id__": 6
|
||||
},
|
||||
"shadows": {
|
||||
"__id__": 7
|
||||
},
|
||||
"_skybox": {
|
||||
"shadows": {
|
||||
"__id__": 8
|
||||
},
|
||||
"fog": {
|
||||
"_skybox": {
|
||||
"__id__": 9
|
||||
},
|
||||
"octree": {
|
||||
"fog": {
|
||||
"__id__": 10
|
||||
},
|
||||
"skin": {
|
||||
"octree": {
|
||||
"__id__": 11
|
||||
},
|
||||
"lightProbeInfo": {
|
||||
"skin": {
|
||||
"__id__": 12
|
||||
},
|
||||
"postSettings": {
|
||||
"lightProbeInfo": {
|
||||
"__id__": 13
|
||||
},
|
||||
"postSettings": {
|
||||
"__id__": 14
|
||||
},
|
||||
"bakedWithStationaryMainLight": false,
|
||||
"bakedWithHighpLightmap": false
|
||||
},
|
||||
|
||||
@@ -0,0 +1,449 @@
|
||||
[
|
||||
{
|
||||
"__type__": "cc.SceneAsset",
|
||||
"_name": "TemplateRoom",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_native": "",
|
||||
"scene": {
|
||||
"__id__": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Scene",
|
||||
"_name": "TemplateRoom",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": null,
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 2
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [],
|
||||
"_prefab": null,
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 1073741824,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"autoReleaseAssets": false,
|
||||
"_globals": {
|
||||
"__id__": 8
|
||||
},
|
||||
"_id": "18f06ada-9d36-485c-9f44-556d6980ca7a"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "Canvas",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 1
|
||||
},
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 3
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 5
|
||||
},
|
||||
{
|
||||
"__id__": 6
|
||||
},
|
||||
{
|
||||
"__id__": 7
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 800,
|
||||
"y": 360.00000000000006,
|
||||
"z": 0
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 33554432,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": "1cgbnsENBDoLhHJwvyJnKB"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Node",
|
||||
"_name": "Camera",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"_parent": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 4
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 1000
|
||||
},
|
||||
"_lrot": {
|
||||
"__type__": "cc.Quat",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0,
|
||||
"w": 1
|
||||
},
|
||||
"_lscale": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1,
|
||||
"y": 1,
|
||||
"z": 1
|
||||
},
|
||||
"_mobility": 0,
|
||||
"_layer": 1073741824,
|
||||
"_euler": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"z": 0
|
||||
},
|
||||
"_id": "9atEuWMGdBq70ouQQ4tRnO"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Camera",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 3
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": null,
|
||||
"_projection": 0,
|
||||
"_priority": 0,
|
||||
"_fov": 45,
|
||||
"_fovAxis": 0,
|
||||
"_orthoHeight": 360,
|
||||
"_near": 0,
|
||||
"_far": 2000,
|
||||
"_color": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 0,
|
||||
"g": 0,
|
||||
"b": 0,
|
||||
"a": 255
|
||||
},
|
||||
"_depth": 1,
|
||||
"_stencil": 0,
|
||||
"_clearFlags": 7,
|
||||
"_rect": {
|
||||
"__type__": "cc.Rect",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 1,
|
||||
"height": 1
|
||||
},
|
||||
"_aperture": 19,
|
||||
"_shutter": 7,
|
||||
"_iso": 0,
|
||||
"_screenScale": 1,
|
||||
"_visibility": 1108344832,
|
||||
"_targetTexture": null,
|
||||
"_postProcess": null,
|
||||
"_usePostProcess": false,
|
||||
"_cameraType": -1,
|
||||
"_trackingType": 0,
|
||||
"_id": "4780+rx15BKqkTCexT+Fi8"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.UITransform",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": null,
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 1600,
|
||||
"height": 720
|
||||
},
|
||||
"_anchorPoint": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 0.5,
|
||||
"y": 0.5
|
||||
},
|
||||
"_id": "9cHcVMc5JHVJoaZqnwhdaW"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Canvas",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": null,
|
||||
"_cameraComponent": {
|
||||
"__id__": 4
|
||||
},
|
||||
"_alignCanvasWithScreen": true,
|
||||
"_id": "f7IXBbP6ZNjqIM4Q5/I3dI"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.Widget",
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"__editorExtras__": {},
|
||||
"node": {
|
||||
"__id__": 2
|
||||
},
|
||||
"_enabled": true,
|
||||
"__prefab": null,
|
||||
"_alignFlags": 45,
|
||||
"_target": null,
|
||||
"_left": 0,
|
||||
"_right": 0,
|
||||
"_top": 5.684341886080802e-14,
|
||||
"_bottom": 5.684341886080802e-14,
|
||||
"_horizontalCenter": 0,
|
||||
"_verticalCenter": 0,
|
||||
"_isAbsLeft": true,
|
||||
"_isAbsRight": true,
|
||||
"_isAbsTop": true,
|
||||
"_isAbsBottom": true,
|
||||
"_isAbsHorizontalCenter": true,
|
||||
"_isAbsVerticalCenter": true,
|
||||
"_originalWidth": 0,
|
||||
"_originalHeight": 0,
|
||||
"_alignMode": 2,
|
||||
"_lockFlags": 0,
|
||||
"_id": "9fI6665VZLG5Uuoch5UpgC"
|
||||
},
|
||||
{
|
||||
"__type__": "cc.SceneGlobals",
|
||||
"ambient": {
|
||||
"__id__": 9
|
||||
},
|
||||
"shadows": {
|
||||
"__id__": 10
|
||||
},
|
||||
"_skybox": {
|
||||
"__id__": 11
|
||||
},
|
||||
"fog": {
|
||||
"__id__": 12
|
||||
},
|
||||
"octree": {
|
||||
"__id__": 13
|
||||
},
|
||||
"skin": {
|
||||
"__id__": 14
|
||||
},
|
||||
"lightProbeInfo": {
|
||||
"__id__": 15
|
||||
},
|
||||
"postSettings": {
|
||||
"__id__": 16
|
||||
},
|
||||
"bakedWithStationaryMainLight": false,
|
||||
"bakedWithHighpLightmap": false
|
||||
},
|
||||
{
|
||||
"__type__": "cc.AmbientInfo",
|
||||
"_skyColorHDR": {
|
||||
"__type__": "cc.Vec4",
|
||||
"x": 0.2,
|
||||
"y": 0.5,
|
||||
"z": 0.8,
|
||||
"w": 1
|
||||
},
|
||||
"_skyColor": {
|
||||
"__type__": "cc.Vec4",
|
||||
"x": 0.2,
|
||||
"y": 0.5,
|
||||
"z": 0.8,
|
||||
"w": 1
|
||||
},
|
||||
"_skyIllumHDR": 20000,
|
||||
"_skyIllum": 20000,
|
||||
"_groundAlbedoHDR": {
|
||||
"__type__": "cc.Vec4",
|
||||
"x": 0.2,
|
||||
"y": 0.2,
|
||||
"z": 0.2,
|
||||
"w": 1
|
||||
},
|
||||
"_groundAlbedo": {
|
||||
"__type__": "cc.Vec4",
|
||||
"x": 0.2,
|
||||
"y": 0.2,
|
||||
"z": 0.2,
|
||||
"w": 1
|
||||
},
|
||||
"_skyColorLDR": {
|
||||
"__type__": "cc.Vec4",
|
||||
"x": 0.2,
|
||||
"y": 0.5,
|
||||
"z": 0.8,
|
||||
"w": 1
|
||||
},
|
||||
"_skyIllumLDR": 20000,
|
||||
"_groundAlbedoLDR": {
|
||||
"__type__": "cc.Vec4",
|
||||
"x": 0.2,
|
||||
"y": 0.2,
|
||||
"z": 0.2,
|
||||
"w": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.ShadowsInfo",
|
||||
"_enabled": false,
|
||||
"_type": 0,
|
||||
"_normal": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 0,
|
||||
"y": 1,
|
||||
"z": 0
|
||||
},
|
||||
"_distance": 0,
|
||||
"_planeBias": 1,
|
||||
"_shadowColor": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 0,
|
||||
"g": 0,
|
||||
"b": 0,
|
||||
"a": 76
|
||||
},
|
||||
"_maxReceived": 4,
|
||||
"_size": {
|
||||
"__type__": "cc.Vec2",
|
||||
"x": 1024,
|
||||
"y": 1024
|
||||
}
|
||||
},
|
||||
{
|
||||
"__type__": "cc.SkyboxInfo",
|
||||
"_envLightingType": 0,
|
||||
"_envmapHDR": null,
|
||||
"_envmap": null,
|
||||
"_envmapLDR": null,
|
||||
"_diffuseMapHDR": null,
|
||||
"_diffuseMapLDR": null,
|
||||
"_enabled": false,
|
||||
"_useHDR": true,
|
||||
"_editableMaterial": null,
|
||||
"_reflectionHDR": null,
|
||||
"_reflectionLDR": null,
|
||||
"_rotationAngle": 0
|
||||
},
|
||||
{
|
||||
"__type__": "cc.FogInfo",
|
||||
"_type": 0,
|
||||
"_fogColor": {
|
||||
"__type__": "cc.Color",
|
||||
"r": 200,
|
||||
"g": 200,
|
||||
"b": 200,
|
||||
"a": 255
|
||||
},
|
||||
"_enabled": false,
|
||||
"_fogDensity": 0.3,
|
||||
"_fogStart": 0.5,
|
||||
"_fogEnd": 300,
|
||||
"_fogAtten": 5,
|
||||
"_fogTop": 1.5,
|
||||
"_fogRange": 1.2,
|
||||
"_accurate": false
|
||||
},
|
||||
{
|
||||
"__type__": "cc.OctreeInfo",
|
||||
"_enabled": false,
|
||||
"_minPos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": -1024,
|
||||
"y": -1024,
|
||||
"z": -1024
|
||||
},
|
||||
"_maxPos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 1024,
|
||||
"y": 1024,
|
||||
"z": 1024
|
||||
},
|
||||
"_depth": 8
|
||||
},
|
||||
{
|
||||
"__type__": "cc.SkinInfo",
|
||||
"_enabled": true,
|
||||
"_blurRadius": 0.01,
|
||||
"_sssIntensity": 3
|
||||
},
|
||||
{
|
||||
"__type__": "cc.LightProbeInfo",
|
||||
"_giScale": 1,
|
||||
"_giSamples": 1024,
|
||||
"_bounces": 2,
|
||||
"_reduceRinging": 0,
|
||||
"_showProbe": true,
|
||||
"_showWireframe": true,
|
||||
"_showConvex": false,
|
||||
"_data": null,
|
||||
"_lightProbeSphereVolume": 1
|
||||
},
|
||||
{
|
||||
"__type__": "cc.PostSettingsInfo",
|
||||
"_toneMappingType": 0
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "1.1.50",
|
||||
"importer": "scene",
|
||||
"imported": true,
|
||||
"uuid": "18f06ada-9d36-485c-9f44-556d6980ca7a",
|
||||
"files": [
|
||||
".json"
|
||||
],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { _decorator, Component, Label, Mask, Node, UITransform, Widget } from 'cc';
|
||||
import { announcementMotion } from '../../framework/presentation/lobby-model.ts';
|
||||
import { requireNode } from './node-bindings.ts';
|
||||
const {ccclass}=_decorator;
|
||||
function required<T>(value:T|null,name:string):T {if(value===null)throw Error(`Announcement missing ${name}`);return value;}
|
||||
|
||||
/** Native clipping and movement of the authored Announcement children. */
|
||||
@ccclass('AnnouncementView')
|
||||
export class AnnouncementView extends Component {
|
||||
private background:Node|null=null;
|
||||
private textNode:Node|null=null;
|
||||
private viewport:Node|null=null;
|
||||
private message='';
|
||||
private elapsed=0;
|
||||
private textY=0;
|
||||
|
||||
show(message:string):void {
|
||||
if(!this.viewport){
|
||||
const bg=requireNode(this.node,'Spirit219'),text=requireNode(this.node,'Spirit220');
|
||||
const bgUI=required(bg.getComponent(UITransform),'Spirit219 UITransform');
|
||||
// The text is animated; an authored Widget must not reset its X every frame.
|
||||
const widget=text.getComponent(Widget);if(widget)widget.enabled=false;
|
||||
const viewport=new Node('AnnouncementClip');viewport.layer=this.node.layer;viewport.parent=bg;
|
||||
const clipUI=viewport.addComponent(UITransform);clipUI.setAnchorPoint(0,0);
|
||||
clipUI.setContentSize(bgUI.contentSize);
|
||||
viewport.setPosition(-bgUI.width*bgUI.anchorX,-bgUI.height*bgUI.anchorY,0);
|
||||
viewport.addComponent(Mask);
|
||||
this.textY=text.position.y-bg.position.y+bgUI.height*bgUI.anchorY;
|
||||
text.parent=viewport;
|
||||
const textUI=required(text.getComponent(UITransform),'Spirit220 UITransform');
|
||||
textUI.setAnchorPoint(0,textUI.anchorY);
|
||||
const label=required(text.getComponent(Label),'Spirit220 Label');
|
||||
label.enableWrapText=false;label.overflow=Label.Overflow.NONE;label.horizontalAlign=Label.HorizontalAlign.LEFT;
|
||||
this.background=bg;this.textNode=text;this.viewport=viewport;
|
||||
}
|
||||
this.message=message;this.elapsed=0;
|
||||
required(required(this.textNode,'text').getComponent(Label),'label').string=message;
|
||||
this.draw();
|
||||
}
|
||||
|
||||
update(dt:number):void {if(this.viewport){this.elapsed+=dt;this.draw();}}
|
||||
|
||||
private draw():void {
|
||||
const text=required(this.textNode,'text'),bg=required(this.background,'background');
|
||||
const width=required(bg.getComponent(UITransform),'background UITransform').width;
|
||||
const state=announcementMotion(this.message,width,this.elapsed);
|
||||
bg.active=state.visible;text.active=state.visible;
|
||||
text.setPosition(state.left,this.textY,0);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "4b4591ab-307a-4061-9690-7102b996a3ae",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import {_decorator,Component} from 'cc';
|
||||
import type {CreateRoomPageContext,CreateRoomPagePort} from '../../framework/sdk/contracts/create-room-page.ts';
|
||||
const {ccclass}=_decorator;
|
||||
/** Inherit this component on the subgame prefab root. Platform never inspects its children. */
|
||||
@ccclass('CreateRoomPage')
|
||||
export class CreateRoomPage extends Component implements CreateRoomPagePort {
|
||||
open(_context:CreateRoomPageContext):void{throw Error('Subgame must implement CreateRoomPage.open');}
|
||||
setBusy(_busy:boolean):void{throw Error('Subgame must implement CreateRoomPage.setBusy');}
|
||||
close():void{throw Error('Subgame must implement CreateRoomPage.close');}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "956dedf9-3650-418b-af8a-a755a26d991c",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import {_decorator,Button,Component,Label} from 'cc';
|
||||
import {JoinRoomInput} from '../../framework/presentation/join-room-input.ts';
|
||||
const {ccclass,property}=_decorator;
|
||||
export interface JoinRoomViewContext {initialCode:string;submit(code:number):void;cancel():void;paste():Promise<string>;reportError(message:string):void;}
|
||||
@ccclass('JoinRoomView')
|
||||
export class JoinRoomView extends Component {
|
||||
@property([Button]) digitButtons:Button[]=[];
|
||||
@property([Label]) slots:Label[]=[];
|
||||
@property(Button) clearButton:Button|null=null;
|
||||
@property(Button) deleteButton:Button|null=null;
|
||||
@property(Button) pasteButton:Button|null=null;
|
||||
@property(Button) submitButton:Button|null=null;
|
||||
@property([Button]) cancelButtons:Button[]=[];
|
||||
private input:JoinRoomInput|null=null;
|
||||
private releases:Array<()=>void>=[];
|
||||
private generation=0;
|
||||
private busy=false;
|
||||
private pasting=false;
|
||||
open(context:JoinRoomViewContext):void{
|
||||
this.close();const generation=this.generation;
|
||||
if(this.digitButtons.length!==10||this.slots.length!==6||!this.clearButton||!this.deleteButton||!this.pasteButton||!this.submitButton||this.cancelButtons.length!==2)throw Error('JoinRoomView requires serialized controls');
|
||||
const input=this.input=new JoinRoomInput(code=>context.submit(code));input.prefill(context.initialCode);
|
||||
const bind=(button:Button,action:()=>void)=>{const fn=()=>{if(this.busy||this.pasting)return;try{action();}catch(error){context.reportError(error instanceof Error?error.message:String(error));}finally{this.render();}};
|
||||
button.node.on(Button.EventType.CLICK,fn);this.releases.push(()=>button.node.off(Button.EventType.CLICK,fn));};
|
||||
this.digitButtons.forEach((button,digit)=>bind(button,()=>input.digit(digit)));
|
||||
bind(this.clearButton,()=>input.clear());bind(this.deleteButton,()=>input.remove());bind(this.submitButton,()=>input.confirm());
|
||||
bind(this.pasteButton,()=>{this.pasting=true;void context.paste().then(text=>{if(this.generation===generation){input.paste(text);this.render();}})
|
||||
.catch(error=>{if(this.generation===generation)context.reportError(error instanceof Error?error.message:String(error));})
|
||||
.finally(()=>{if(this.generation===generation)this.pasting=false;});});
|
||||
this.cancelButtons.forEach(button=>{const fn=()=>context.cancel();button.node.on(Button.EventType.CLICK,fn);this.releases.push(()=>button.node.off(Button.EventType.CLICK,fn));});
|
||||
this.setBusy(false);this.render();
|
||||
}
|
||||
setBusy(busy:boolean):void{this.busy=busy;this.input?.setBusy(busy);for(const b of [...this.digitButtons,this.clearButton,this.deleteButton,this.submitButton,this.pasteButton])if(b)b.interactable=!busy;}
|
||||
private render():void{const code=this.input?.code;if(code===undefined)return;this.slots.forEach((slot,i)=>{slot.node.active=i<code.length;slot.string=code[i]??'';});}
|
||||
close():void{this.generation++;this.pasting=false;for(const release of this.releases.splice(0))release();this.input=null;}
|
||||
onDestroy():void{this.close();}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "033ab9dd-e1a1-48fb-9fd6-5474c1a45eb2",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -6,12 +6,23 @@ export class LobbyAssets extends Component {
|
||||
@property(Prefab) menu:Prefab|null=null;
|
||||
@property(Prefab) header:Prefab|null=null;
|
||||
@property(Prefab) noticeMenu:Prefab|null=null;
|
||||
@property(Prefab) notices:Prefab|null=null;
|
||||
@property(Prefab) redeemCode:Prefab|null=null;
|
||||
@property(Prefab) qrCode:Prefab|null=null;
|
||||
@property(Prefab) noticeBoard:Prefab|null=null;
|
||||
@property(Prefab) ownedRoomList:Prefab|null=null;
|
||||
@property(Prefab) invite:Prefab|null=null;
|
||||
@property(Prefab) profile:Prefab|null=null;
|
||||
@property(Prefab) settings:Prefab|null=null;
|
||||
@property(Prefab) join:Prefab|null=null;
|
||||
@property(Prefab) tasks:Prefab|null=null;
|
||||
@property(Prefab) share:Prefab|null=null;
|
||||
@property(Prefab) rank:Prefab|null=null;
|
||||
@property(Prefab) rankItem:Prefab|null=null;
|
||||
@property([SpriteFrame]) rankMedals:SpriteFrame[]=[];
|
||||
@property(SpriteFrame) rankTitle:SpriteFrame|null=null;
|
||||
@property(SpriteFrame) vipRankTitle:SpriteFrame|null=null;
|
||||
@property([SpriteFrame]) ownedRoomDigits:SpriteFrame[]=[];
|
||||
@property([SpriteFrame]) rankSymbols:SpriteFrame[]=[];
|
||||
@property([SpriteFrame]) digits:SpriteFrame[]=[];
|
||||
@property([SpriteFrame]) switches:SpriteFrame[]=[];
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user