219 lines
6.5 KiB
TypeScript
219 lines
6.5 KiB
TypeScript
import { _decorator, Component, Enum, Node } from 'cc';
|
||
import { PinballBootConfig, PinballBootMode, PinballBootResult, PinballBootstrap } from '../Modules/Pinball/Boot';
|
||
import { PinballManager } from '../Modules/Pinball/PinballManager';
|
||
const { ccclass, property } = _decorator;
|
||
|
||
// 定义模式枚举
|
||
export enum RunMode {
|
||
STANDALONE = 0,
|
||
CLIENT_MULTIPLAYER = 1,
|
||
SERVER_MULTIPLAYER = 2
|
||
}
|
||
|
||
// 将枚举注册到Cocos Creator
|
||
Enum(RunMode);
|
||
|
||
// RunMode 到字符串的映射
|
||
const RunModeStrings = {
|
||
[RunMode.STANDALONE]: 'standalone',
|
||
[RunMode.CLIENT_MULTIPLAYER]: 'client-multiplayer',
|
||
[RunMode.SERVER_MULTIPLAYER]: 'server-multiplayer'
|
||
} as const;
|
||
|
||
// RunMode 到 PinballBootMode 的映射
|
||
const RunModeToPinballBootMode = {
|
||
[RunMode.STANDALONE]: PinballBootMode.STANDALONE,
|
||
[RunMode.CLIENT_MULTIPLAYER]: PinballBootMode.CLIENT_MULTIPLAYER,
|
||
[RunMode.SERVER_MULTIPLAYER]: PinballBootMode.SERVER_MULTIPLAYER
|
||
} as const;
|
||
|
||
@ccclass('ClientRunner')
|
||
export class ClientRunner extends Component {
|
||
|
||
@property({
|
||
type: Enum(RunMode),
|
||
displayName: "运行模式",
|
||
tooltip: '选择运行模式:单机/客户端多人/服务器多人'
|
||
})
|
||
public mode: RunMode = RunMode.STANDALONE;
|
||
|
||
@property({
|
||
type: Node,
|
||
displayName: "主相机节点",
|
||
tooltip: '主相机节点,用于渲染游戏画面'
|
||
})
|
||
public cameraNode: Node = null;
|
||
|
||
@property({
|
||
type: Node,
|
||
displayName: "渲染容器",
|
||
tooltip: '渲染容器节点,所有游戏对象将在此节点下渲染'
|
||
})
|
||
public renderContainer: Node = null;
|
||
|
||
@property({
|
||
type: Node,
|
||
displayName: "UI容器",
|
||
tooltip: 'UI容器节点,用于显示游戏UI界面'
|
||
})
|
||
public uiContainer: Node = null;
|
||
|
||
private pinballManager: PinballManager = null;
|
||
private bootResult: PinballBootResult = null;
|
||
|
||
async start() {
|
||
console.log(`[ClientRunner] 开始启动,运行模式: ${this.getModeString()}`);
|
||
|
||
// 使用 Bootstrap 启动游戏
|
||
await this.bootWithBootstrap();
|
||
}
|
||
|
||
/**
|
||
* 使用 Bootstrap 启动游戏
|
||
*/
|
||
private async bootWithBootstrap(): Promise<void> {
|
||
try {
|
||
// 创建启动配置
|
||
const config = this.createBootConfig();
|
||
|
||
// 使用 Bootstrap 启动
|
||
const bootstrap = PinballBootstrap.getInstance();
|
||
this.bootResult = await bootstrap.boot(this, config);
|
||
|
||
if (this.bootResult.success) {
|
||
this.pinballManager = this.bootResult.pinballManager;
|
||
console.log(`[ClientRunner] 使用 Bootstrap 启动成功: ${this.bootResult.mode}`);
|
||
} else {
|
||
console.error(`[ClientRunner] Bootstrap 启动失败: ${this.bootResult.error}`);
|
||
this.handleBootFailure(this.bootResult);
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('[ClientRunner] Bootstrap 启动异常:', error);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建启动配置
|
||
*/
|
||
private createBootConfig(): PinballBootConfig {
|
||
// 将 RunMode 转换为 PinballBootMode
|
||
const bootMode = this.convertRunModeToPinballBootMode(this.mode);
|
||
|
||
// 使用默认配置并设置节点引用
|
||
const config = PinballBootstrap.createDefaultConfig(bootMode);
|
||
config.cameraNode = this.cameraNode;
|
||
config.renderContainer = this.renderContainer;
|
||
config.uiContainer = this.uiContainer;
|
||
|
||
// 根据模式添加特定配置
|
||
if (bootMode === PinballBootMode.CLIENT_MULTIPLAYER ||
|
||
bootMode === PinballBootMode.SERVER_MULTIPLAYER) {
|
||
config.multiplayerConfig = {
|
||
serverAddress: 'localhost:3000', // 默认服务器地址
|
||
playerName: 'Player1',
|
||
roomId: 'default'
|
||
};
|
||
}
|
||
|
||
return config;
|
||
}
|
||
|
||
/**
|
||
* 转换 RunMode 到 PinballBootMode
|
||
*/
|
||
private convertRunModeToPinballBootMode(runMode: RunMode): PinballBootMode {
|
||
return RunModeToPinballBootMode[runMode] ?? PinballBootMode.STANDALONE;
|
||
}
|
||
|
||
/**
|
||
* 处理启动失败
|
||
*/
|
||
private handleBootFailure(result: PinballBootResult): void {
|
||
console.error(`[ClientRunner] 启动失败 - 模式: ${result.mode}, 错误: ${result.error}`);
|
||
|
||
// 可以在这里添加错误恢复逻辑,比如回退到 Standalone 模式
|
||
if (result.mode !== PinballBootMode.STANDALONE) {
|
||
console.log('[ClientRunner] 尝试回退到 Standalone 模式...');
|
||
setTimeout(async () => {
|
||
this.mode = RunMode.STANDALONE;
|
||
await this.bootWithBootstrap();
|
||
}, 1000);
|
||
}
|
||
}
|
||
|
||
update(deltaTime: number) {
|
||
|
||
}
|
||
|
||
onDestroy() {
|
||
// 清理 PinballManager
|
||
if (this.pinballManager) {
|
||
this.pinballManager = null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取 PinballManager 实例
|
||
*/
|
||
public getPinballManager(): PinballManager | null {
|
||
return this.pinballManager;
|
||
}
|
||
|
||
/**
|
||
* 重启当前模式
|
||
*/
|
||
public async restart(): Promise<void> {
|
||
console.log('[ClientRunner] 重启游戏...');
|
||
|
||
if (this.pinballManager) {
|
||
await this.pinballManager.restartGame();
|
||
} else {
|
||
// 如果没有 PinballManager,重新执行启动流程
|
||
await this.bootWithBootstrap();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 切换模式并重启
|
||
*/
|
||
public async switchMode(newMode: RunMode): Promise<void> {
|
||
console.log(`[ClientRunner] 切换模式从 ${this.getModeString()} 到 ${this.getModeStringForMode(newMode)}`);
|
||
|
||
// 停止当前游戏
|
||
if (this.pinballManager) {
|
||
await this.pinballManager.stopCurrentGame();
|
||
}
|
||
|
||
// 设置新模式
|
||
this.mode = newMode;
|
||
|
||
// 重新启动
|
||
await this.bootWithBootstrap();
|
||
}
|
||
|
||
/**
|
||
* 获取启动结果
|
||
*/
|
||
public getBootResult(): PinballBootResult | null {
|
||
return this.bootResult;
|
||
}
|
||
|
||
/**
|
||
* 获取指定模式的字符串值
|
||
*/
|
||
private getModeStringForMode(mode: RunMode): string {
|
||
return RunModeStrings[mode] ?? 'standalone';
|
||
}
|
||
|
||
/**
|
||
* 获取当前模式的字符串值
|
||
* @returns 模式字符串
|
||
*/
|
||
public getModeString(): string {
|
||
return this.getModeStringForMode(this.mode);
|
||
}
|
||
}
|
||
|
||
|