跳到主要内容

宿主状态、常量及错误码

1. 宿主状态 RuntimeState​

宿主在运行过程中会经历不同的状态,可以通过 gameHandle.getGameState() 获取当前状态。

状态枚举​

状态值说明
UNAVAILABLEunavailable不可用状态,宿主尚未初始化
WAITINGwaiting等待状态,已初始化但未启动游戏
RUNNINGrunning运行状态,游戏正在加载
PLAYINGplaying播放状态,游戏正在运行

状态转换图​

UNAVAILABLE
↓ (initialize)
WAITING
↓ (start)
RUNNING
↓ (play)
PLAYING
↓ (stop/destroy)
WAITING/UNAVAILABLE

代码示例​

const { RuntimeState } = require('webglhost-runtime-pc');

// Get current game state
const state = gameHandle.getGameState();
console.log('Current game state:', state);

// Check state
if (state === RuntimeState.PLAYING) {
console.log('Game is playing');
} else if (state === RuntimeState.RUNNING) {
console.log('Game is running');
}

// State constants
console.log('Available states:');
console.log('UNAVAILABLE:', RuntimeState.UNAVAILABLE);
console.log('WAITING:', RuntimeState.WAITING);
console.log('RUNNING:', RuntimeState.RUNNING);
console.log('PLAYING:', RuntimeState.PLAYING);

2. 常量定义 TJConstants​

TJConstants 包含游戏启动参数的常量定义,使用这些常量可以避免硬编码字符串。

游戏启动参数常量​

const { TJConstants } = require('webglhost-runtime-pc');

// Commonly used constants
TJConstants.LAUNCH_KEY // 'launchKey'
TJConstants.USER_ID // 'userId'
TJConstants.GAME_ID // 'gameId'
TJConstants.ACCESS_TOKEN // 'accessToken'

// Debug and inspector
TJConstants.ENABLE_VCONSOLE // 'enableVConsole'
TJConstants.ENABLE_INSPECTOR // 'enableInspector'
TJConstants.INSPECTOR_WAIT_FOR_INSPECT // 'waitForInspect'

// UI configuration
TJConstants.SHOW_MENU_LAYOUT // 'showMenuLayout'
TJConstants.SHOW_MENU_EXPLORE_BTN // 'showMenuExploreBtn'
TJConstants.SPLASH_ICON_URL // 'splashIconUrl'
TJConstants.SPLASH_GAME_TITLE // 'splashGameTitle'

// Custom scripts
TJConstants.CUSTOM_SCRIPT_FILES // 'customScriptFiles'
TJConstants.CUSTOM_SCRIPT_CONTENTS // 'customScriptContents'

// Domain whitelist
TJConstants.ENABLE_DOMAIN_WHITELIST // 'enableDomainWhiteList'
TJConstants.DOMAIN_WHITELIST_REQUEST // 'domainWhiteListRequest'
TJConstants.DOMAIN_WHITELIST_SOCKET // 'domainWhiteListSocket'
TJConstants.DOMAIN_WHITELIST_UDP // 'domainWhiteListUDP'
TJConstants.DOMAIN_WHITELIST_TCP // 'domainWhiteListTCP'
TJConstants.DOMAIN_WHITELIST_UPLOAD_FILE // 'domainWhiteListUploadFile'
TJConstants.DOMAIN_WHITELIST_DOWNLOAD_FILE // 'domainWhiteListDownloadFile'

// Audio and visual
TJConstants.ENABLE_MUTE_ALL_AUDIO // 'enableMuteAllAudio'
TJConstants.ENABLE_TRANSPARENT_MODE // 'enableTransparentMode'

使用示例​

const { TJConstants } = require('webglhost-runtime-pc');

const options = {
[TJConstants.LAUNCH_KEY]: 'my-launch-key',
[TJConstants.USER_ID]: 'user-123',
[TJConstants.ENABLE_VCONSOLE]: true,
[TJConstants.SHOW_MENU_LAYOUT]: true,
[TJConstants.CUSTOM_SCRIPT_FILES]: ['./script1.js', './script2.js'],
[TJConstants.DOMAIN_WHITELIST_REQUEST]: [
'https://api.example.com',
'https://cdn.example.com'
]
};

await gameHandle.setGameStartOptions(options);

3. 错误码 HostRuntimeError​

错误类定义​

const { HostRuntimeError } = require('webglhost-runtime-pc');

// All errors are instances of HostRuntimeError class
class HostRuntimeError extends Error {
constructor(code, message) {
super(message);
this.code = code;
this.name = 'HostRuntimeError';
}
}

核心错误码​

错误码含义错误处理建议
SDK_INITIALIZATION_FAILEDSDK 初始化失败检查 SDK 密钥
GAME_ID_NOT_SET游戏 ID 未设置提供有效的游戏 ID
LAUNCH_KEY_NOT_SET启动密钥未设置提供启动密钥
USER_NOT_AVAILABLE用户不可用检查用户 ID
GAME_NOT_FOUND游戏未找到检查游戏 ID 和密钥
GAME_QR_SESSION_EXPIRED游戏二维码会话已过期重新扫码
SERVER_RESPONSE_ERROR服务器响应错误检查网络和服务状态
GAME_HANDLE_UNINITIALIZED游戏句柄未初始化先初始化游戏句柄
NETWORK_ERROR网络错误检查网络连接
FILE_SYSTEM_ERROR文件系统错误检查文件路径和权限
AUDIO_ERROR音频错误检查音频设备
PERMISSION_ERROR权限错误检查系统权限

错误处理示例​

const { TJHostHandle, HostRuntimeError } = require('webglhost-runtime-pc');

// Example 1: Handling initialization error
TJHostHandle.initialize('sdk-key', 'sdk-secret', (hostHandle, error) => {
if (error) {
if (error.code === 'SDK_INITIALIZATION_FAILED') {
console.error('SDK initialization failed:', error.message);
console.error('Please check your SDK credentials');
} else {
console.error('Initialization error:', error.code, error.message);
}
return;
}

console.log('SDK initialized successfully');
});

// Example 2: Handling game start error
async function startGame(gameHandle, options) {
try {
await gameHandle.setGameStartOptions(options);
await gameHandle.start();
} catch (error) {
if (error instanceof HostRuntimeError) {
switch (error.code) {
case 'LAUNCH_KEY_NOT_SET':
console.error('Launch key is required');
break;
case 'USER_NOT_AVAILABLE':
console.error('User ID is required');
break;
case 'GAME_NOT_FOUND':
console.error('Game not found, check your game ID');
break;
case 'NETWORK_ERROR':
console.error('Network error, please check your connection');
break;
default:
console.error('Game start error:', error.code, error.message);
}
} else {
console.error('Unexpected error:', error);
}
}
}

// Example 3: Creating custom errors
const customError = HostRuntimeError.create('CUSTOM_ERROR', 'Custom error message');
throw customError;

// Example 4: Converting network errors
try {
// Network operation
} catch (networkError) {
const runtimeError = HostRuntimeError.fromNetworkError(networkError);
console.error('Runtime error:', runtimeError.code, runtimeError.message);
}

错误处理最佳实践​

class ErrorHandler {
constructor() {
this.errorListeners = [];
}

onError(listener) {
this.errorListeners.push(listener);
}

handleError(error) {
console.error('[ErrorHandler] Error occurred:', error);

// Notify all listeners
for (const listener of this.errorListeners) {
try {
listener(error);
} catch (e) {
console.error('[ErrorHandler] Listener error:', e);
}
}

// Handle specific error types
if (error instanceof HostRuntimeError) {
return this.handleHostRuntimeError(error);
}

return this.handleGenericError(error);
}

handleHostRuntimeError(error) {
const errorHandlers = {
'SDK_INITIALIZATION_FAILED': () => {
return {
title: 'Initialization Failed',
message: 'Failed to initialize SDK. Please check your credentials.',
recoverable: false
};
},
'LAUNCH_KEY_NOT_SET': () => {
return {
title: 'Configuration Error',
message: 'Game launch key is missing.',
recoverable: false
};
},
'NETWORK_ERROR': () => {
return {
title: 'Network Error',
message: 'Please check your internet connection and try again.',
recoverable: true
};
},
'GAME_NOT_FOUND': () => {
return {
title: 'Game Not Found',
message: 'The requested game could not be found.',
recoverable: false
};
}
};

const handler = errorHandlers[error.code];
if (handler) {
return handler();
}

return {
title: 'Error',
message: error.message || 'An unknown error occurred',
recoverable: false
};
}

handleGenericError(error) {
return {
title: 'Unexpected Error',
message: error.message || 'An unexpected error occurred',
recoverable: false
};
}
}

// Usage
const errorHandler = new ErrorHandler();

errorHandler.onError((error) => {
console.log('Error occurred:', error);
// Show error dialog, send to analytics, etc.
});

// When an error occurs
try {
await gameHandle.start();
} catch (error) {
const errorInfo = errorHandler.handleError(error);
console.log('Error info:', errorInfo);

// Show error UI
if (errorInfo.recoverable) {
// Show retry button
} else {
// Show error message and exit
}
}

完整示例​

const {
TJHostHandle,
RuntimeState,
TJConstants,
HostRuntimeError
} = require('webglhost-runtime-pc');

class GameManager {
constructor() {
this.hostHandle = null;
this.gameHandle = null;
this.currentState = RuntimeState.UNAVAILABLE;
}

async initialize(sdkKey, sdkSecret) {
return new Promise((resolve, reject) => {
TJHostHandle.initialize(sdkKey, sdkSecret, (hostHandle, error) => {
if (error) {
this.handleError(error);
reject(error);
return;
}

this.hostHandle = hostHandle;
this.currentState = RuntimeState.WAITING;
resolve();
});
});
}

async createGame() {
try {
this.gameHandle = await this.hostHandle.createGameHandle();
this.setupStateTracking();
console.log('Game handle created');
} catch (error) {
this.handleError(error);
throw error;
}
}

setupStateTracking() {
// Monitor state changes
const checkState = () => {
const newState = this.gameHandle.getGameState();
if (newState !== this.currentState) {
console.log(`State changed: ${this.currentState} -> ${newState}`);
this.currentState = newState;
this.onStateChanged(newState);
}
};

// Check state periodically
setInterval(checkState, 1000);
}

onStateChanged(newState) {
console.log(`Current state: ${newState}`);

switch (newState) {
case RuntimeState.UNAVAILABLE:
console.log('Game is unavailable');
break;
case RuntimeState.WAITING:
console.log('Ready to start game');
break;
case RuntimeState.RUNNING:
console.log('Game is loading');
break;
case RuntimeState.PLAYING:
console.log('Game is playing');
break;
}
}

async startGame(launchKey, userId) {
try {
const options = {
[TJConstants.LAUNCH_KEY]: launchKey,
[TJConstants.USER_ID]: userId,
[TJConstants.ENABLE_VCONSOLE]: false,
[TJConstants.SHOW_MENU_LAYOUT]: true
};

await this.gameHandle.setGameStartOptions(options);
await this.gameHandle.start();
this.gameHandle.play();

console.log('Game started successfully');
} catch (error) {
this.handleError(error);
throw error;
}
}

handleError(error) {
if (error instanceof HostRuntimeError) {
console.error(`[${error.code}] ${error.message}`);

// Handle specific errors
switch (error.code) {
case 'SDK_INITIALIZATION_FAILED':
console.error('Please verify your SDK credentials');
break;
case 'LAUNCH_KEY_NOT_SET':
console.error('Launch key is required to start the game');
break;
case 'NETWORK_ERROR':
console.error('Network connection failed, please check your internet');
break;
default:
console.error('An error occurred:', error.message);
}
} else {
console.error('Unexpected error:', error);
}
}

getState() {
return this.currentState;
}

isPlaying() {
return this.currentState === RuntimeState.PLAYING;
}

isPaused() {
return this.currentState === RuntimeState.PAUSED;
}

canStart() {
return this.currentState === RuntimeState.WAITING;
}
}

// Usage
async function main() {
const manager = new GameManager();

try {
// Initialize
await manager.initialize('sdk-key', 'sdk-secret');
console.log('Manager initialized, state:', manager.getState());

// Create game
await manager.createGame();
console.log('Game created, state:', manager.getState());

// Start game
await manager.startGame('launch-key', 'user-123');
console.log('Game started, state:', manager.getState());

// Check state
if (manager.isPlaying()) {
console.log('Game is now playing');
}

} catch (error) {
console.error('Failed to start game:', error);
}
}

main();

状态和错误码参考速查​

快速状态检查​

// Check if game can be started
if (gameHandle.getGameState() === RuntimeState.WAITING) {
await gameHandle.start();
}

// Check if game is playing
if (gameHandle.getGameState() === RuntimeState.PLAYING) {
console.log('Game is currently playing');
}

// Check if game is running
if (gameHandle.getGameState() === RuntimeState.RUNNING) {
console.log('Game is loading/running');
}

快速错误处理​

try {
// Game operations
} catch (error) {
if (error.code === 'NETWORK_ERROR') {
// Retry logic
} else if (error.code === 'SDK_INITIALIZATION_FAILED') {
// Show error and exit
}
}