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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|