import { trackEvent } from '@scripts/tracking/TrackEvents'; import { AppKernel } from '../../app/AppKernel'; import { APP_SERVER } from '../../define/Define'; import { ColyseusRoomClient } from '../../network/colyseus/ColyseusRoomClient'; const CASH_BASE = 100; export interface HallMessage { cmd?: string; data?: Record; [key: string]: unknown; } export interface HallPayFinishMessage extends HallMessage { cmd: 'pay_finish'; data?: { Golds?: number | string; PayNum?: number | string; event?: string; params?: unknown; [key: string]: unknown; }; } export interface HallCallClientMessage extends HallMessage { cmd: 'call_client'; data?: { type?: 'track' | 'refresh_mail' | 'start_change' | string; Golds?: number | string; event?: string; params?: unknown; [key: string]: unknown; }; } class HallClient { private client: ColyseusRoomClient | null = null; private serverUrl = ''; async connect(serverUrl?: string): Promise { const mainStore = AppKernel.stores.mainStore; if (!mainStore.isLogin || mainStore.userID <= 0) return false; const nextUrl = serverUrl || mainStore.hallServerUrl || APP_SERVER.SERVER_URL; console.log('[HallClient] endpoint:', JSON.stringify(nextUrl)); if (!nextUrl) { console.warn('[HallClient] Hall server URL is empty'); return false; } if (!this.client || this.serverUrl !== nextUrl) { if (this.client) await this.client.disconnect(); this.serverUrl = nextUrl; this.client = this.createClient(nextUrl); } return this.client.connect(); } async disconnect(): Promise { const client = this.client; this.client = null; this.serverUrl = ''; if (client) await client.disconnect(); } sendChat(message: unknown): boolean { return this.send('chat', message); } sendRegistration(): boolean { const user = AppKernel.stores.mainStore.userInfo; if (!user) return false; const { UserID, GlobalUID, FaceID, NickName } = user; return this.send('id', { UserID, GlobalUID, FaceID, NickName }); } sendState(): boolean { return this.send('state', { in_game: AppKernel.stores.gameStore.gameID }); } private createClient(serverUrl: string): ColyseusRoomClient { return new ColyseusRoomClient(APP_SERVER.ROOM_HALL, serverUrl, { onConnected: () => { AppKernel.stores.mainStore.setServerKick(false); AppKernel.events.emit('hall:connected'); this.sendRegistration(); }, onDisconnected: (code) => AppKernel.events.emit('hall:disconnected', { code }), onTimeout: () => AppKernel.events.emit('hall:timeout'), onMessage: (type, message) => this.onMessage(type, message), }); } private send(type: string, message: unknown = ''): boolean { return this.client?.send(type, message) ?? false; } private onMessage(type: string, rawMessage: unknown): void { const message = this.asMessage(rawMessage); AppKernel.events.emit('hall:message', { type, message }); switch (type) { case 'operate': this.handleOperate(message); break; case 'roger': this.handleRoger(message); break; } } private handleOperate(message: HallMessage): void { switch (message.cmd) { case 'id': this.sendState(); break; case 'kick': AppKernel.stores.mainStore.setServerKick(true); AppKernel.events.emit('hall:kicked', message); break; } } private handleRoger(message: HallMessage): void { switch (message.cmd) { case 'pay_finish': { // const payMessage = message as HallPayFinishMessage; AppKernel.appLobby.onPaymentFinished(); break; } case 'call_client': { const callMessage = message as HallCallClientMessage; if (!!callMessage.data && !!callMessage.data.type) { const { data } = callMessage; switch (data.type) { case 'track': trackEvent(data.event, data.params); break; case 'refresh_mail': break; case 'start_change': break; } } break; } } } private asMessage(message: unknown): HallMessage { if (message && typeof message === 'object') return message as HallMessage; return { data: { value: message } }; } } export const hallClient = new HallClient();