Files
esengine/packages/platform-wechat/src/WeChatAdapter.ts
YHH a768b890fd feat: 集成Rust WASM渲染引擎与TypeScript ECS框架 (#228)
* feat: 集成Rust WASM渲染引擎与TypeScript ECS框架

* feat: 增强编辑器UI功能与跨平台支持

* fix: 修复CI测试和类型检查问题

* fix: 修复CI问题并提高测试覆盖率

* fix: 修复CI问题并提高测试覆盖率
2025-11-21 10:03:18 +08:00

290 lines
8.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 微信小游戏平台适配器
*/
import type {
IPlatformAdapter,
PlatformWorker,
WorkerCreationOptions,
PlatformConfig
} from '@esengine/ecs-framework';
import type { SystemInfo } from '@esengine/platform-common';
import { WeChatCanvasSubsystem } from './subsystems/WeChatCanvasSubsystem';
import { WeChatAudioSubsystem } from './subsystems/WeChatAudioSubsystem';
import { WeChatStorageSubsystem } from './subsystems/WeChatStorageSubsystem';
import { WeChatNetworkSubsystem } from './subsystems/WeChatNetworkSubsystem';
import { WeChatInputSubsystem } from './subsystems/WeChatInputSubsystem';
import { WeChatFileSubsystem } from './subsystems/WeChatFileSubsystem';
import { WeChatWASMSubsystem } from './subsystems/WeChatWASMSubsystem';
import { getWx, isWeChatMiniGame } from './utils';
/**
* 微信小游戏 Worker 包装
*/
class WeChatWorker implements PlatformWorker {
private _worker: WechatMinigame.Worker;
private _state: 'running' | 'terminated' = 'running';
constructor(worker: WechatMinigame.Worker) {
this._worker = worker;
}
get state(): 'running' | 'terminated' {
return this._state;
}
postMessage(message: any, _transfer?: Transferable[]): void {
this._worker.postMessage(message);
}
onMessage(handler: (event: { data: any }) => void): void {
this._worker.onMessage((res) => {
handler({ data: res });
});
}
onError(handler: (error: ErrorEvent) => void): void {
this._worker.onError((error) => {
handler(error as unknown as ErrorEvent);
});
}
terminate(): void {
this._worker.terminate();
this._state = 'terminated';
}
}
/**
* 微信小游戏平台适配器
*/
export class WeChatAdapter implements IPlatformAdapter {
readonly name = 'wechat-minigame';
readonly version: string;
// 子系统实例
private _canvas: WeChatCanvasSubsystem | null = null;
private _audio: WeChatAudioSubsystem | null = null;
private _storage: WeChatStorageSubsystem | null = null;
private _network: WeChatNetworkSubsystem | null = null;
private _input: WeChatInputSubsystem | null = null;
private _file: WeChatFileSubsystem | null = null;
private _wasm: WeChatWASMSubsystem | null = null;
private _deviceInfo: WechatMinigame.DeviceInfo | null = null;
private _windowInfo: WechatMinigame.WindowInfo | null = null;
private _appBaseInfo: WechatMinigame.AppBaseInfo | null = null;
constructor() {
if (!isWeChatMiniGame()) {
throw new Error('当前环境不是微信小游戏环境');
}
// 使用新的分离 API 获取系统信息
const wxApi = getWx();
this._deviceInfo = wxApi.getDeviceInfo();
this._windowInfo = wxApi.getWindowInfo();
this._appBaseInfo = wxApi.getAppBaseInfo();
this.version = this._appBaseInfo.SDKVersion;
}
// ========================================================================
// IPlatformAdapter 基础实现
// ========================================================================
isWorkerSupported(): boolean {
// 微信小游戏支持 Worker但有限制
return typeof getWx().createWorker === 'function';
}
isSharedArrayBufferSupported(): boolean {
// 微信小游戏不支持 SharedArrayBuffer
return false;
}
getHardwareConcurrency(): number {
// 微信小游戏无法获取真实核心数,返回保守值
return 2;
}
createWorker(script: string, options?: WorkerCreationOptions): PlatformWorker {
// 微信小游戏 Worker 需要指定文件路径,不支持内联脚本
// script 参数应该是 worker 文件的路径
const worker = getWx().createWorker(script, {
useExperimentalWorker: true
});
return new WeChatWorker(worker);
}
createSharedArrayBuffer(_length: number): SharedArrayBuffer | null {
// 微信小游戏不支持 SharedArrayBuffer
return null;
}
getHighResTimestamp(): number {
return Date.now();
}
getPlatformConfig(): PlatformConfig {
return {
maxWorkerCount: 1,
supportsModuleWorker: false,
supportsTransferableObjects: true,
maxSharedArrayBufferSize: 0,
workerScriptPrefix: '',
limitations: {
noEval: true,
requiresWorkerInit: true,
memoryLimit: this._deviceInfo?.memorySize
? parseInt(String(this._deviceInfo.memorySize)) * 1024 * 1024
: 256 * 1024 * 1024,
workerNotSupported: false,
workerLimitations: [
'Worker 必须使用独立文件,不支持内联脚本',
'仅支持 1 个 Worker 实例',
'不支持 SharedArrayBuffer',
'Worker 文件需要在 game.json 中配置'
]
},
extensions: {
platform: 'wechat-minigame',
sdkVersion: this._appBaseInfo?.SDKVersion
}
};
}
async getPlatformConfigAsync(): Promise<PlatformConfig> {
return this.getPlatformConfig();
}
// ========================================================================
// 子系统访问器
// ========================================================================
/**
* 获取 Canvas 子系统
*/
get canvas(): WeChatCanvasSubsystem {
if (!this._canvas) {
this._canvas = new WeChatCanvasSubsystem();
}
return this._canvas;
}
/**
* 获取音频子系统
*/
get audio(): WeChatAudioSubsystem {
if (!this._audio) {
this._audio = new WeChatAudioSubsystem();
}
return this._audio;
}
/**
* 获取存储子系统
*/
get storage(): WeChatStorageSubsystem {
if (!this._storage) {
this._storage = new WeChatStorageSubsystem();
}
return this._storage;
}
/**
* 获取网络子系统
*/
get network(): WeChatNetworkSubsystem {
if (!this._network) {
this._network = new WeChatNetworkSubsystem();
}
return this._network;
}
/**
* 获取输入子系统
*/
get input(): WeChatInputSubsystem {
if (!this._input) {
this._input = new WeChatInputSubsystem();
}
return this._input;
}
/**
* 获取文件系统子系统
*/
get file(): WeChatFileSubsystem {
if (!this._file) {
this._file = new WeChatFileSubsystem();
}
return this._file;
}
/**
* 获取 WASM 子系统
*/
get wasm(): WeChatWASMSubsystem {
if (!this._wasm) {
this._wasm = new WeChatWASMSubsystem();
}
return this._wasm;
}
// ========================================================================
// 系统信息
// ========================================================================
/**
* 获取系统信息
*/
getSystemInfo(): SystemInfo {
const device = this._deviceInfo!;
const window = this._windowInfo!;
const app = this._appBaseInfo!;
return {
brand: device.brand,
model: device.model,
pixelRatio: window.pixelRatio,
screenWidth: window.screenWidth,
screenHeight: window.screenHeight,
windowWidth: window.windowWidth,
windowHeight: window.windowHeight,
statusBarHeight: window.statusBarHeight || 0,
system: device.system,
platform: device.platform as SystemInfo['platform'],
SDKVersion: app.SDKVersion,
benchmarkLevel: device.benchmarkLevel || 0,
memorySize: device.memorySize ? parseInt(String(device.memorySize)) : undefined
};
}
/**
* 比较基础库版本
*/
compareVersion(v1: string, v2: string): number {
const a1 = v1.split('.').map(Number);
const a2 = v2.split('.').map(Number);
const len = Math.max(a1.length, a2.length);
for (let i = 0; i < len; i++) {
const n1 = a1[i] || 0;
const n2 = a2[i] || 0;
if (n1 > n2) return 1;
if (n1 < n2) return -1;
}
return 0;
}
/**
* 检查是否支持某个 API
*/
canIUse(schema: string): boolean {
return getWx().canIUse(schema);
}
}