Skip to content

Platform Adapter

The ECS framework provides a platform adapter interface that allows users to implement custom platform adapters for different runtime environments.

The core library only provides interface definitions. Platform adapter implementations should be copied from the documentation.

  1. Flexibility: Different projects may have different platform adaptation needs. Copying code allows users to freely modify as needed
  2. Reduce Dependencies: Avoid introducing unnecessary dependency packages, keeping the core framework lean
  3. Customization: Users can customize according to specific runtime environments and requirements

Supports all modern browser environments, including Chrome, Firefox, Safari, Edge, etc.

Feature Support:

  • Worker (Web Worker)
  • SharedArrayBuffer (requires COOP/COEP)
  • Transferable Objects
  • Module Worker (modern browsers)

Use Cases: Web games, Web applications, PWA


Designed specifically for the WeChat Mini Game environment, handling special restrictions and APIs.

Feature Support:

  • Worker (max 1, requires game.json configuration)
  • SharedArrayBuffer (not supported)
  • Transferable Objects (not supported)
  • WeChat Device Info API

Use Cases: WeChat Mini Game development


Provides support for Node.js server environments, suitable for game servers and compute servers.

Feature Support:

  • Worker Threads
  • SharedArrayBuffer
  • Transferable Objects
  • Complete system information

Use Cases: Game servers, compute servers, CLI tools


export interface IPlatformAdapter {
readonly name: string;
readonly version?: string;
isWorkerSupported(): boolean;
isSharedArrayBufferSupported(): boolean;
getHardwareConcurrency(): number;
createWorker(script: string, options?: WorkerCreationOptions): PlatformWorker;
createSharedArrayBuffer(length: number): SharedArrayBuffer | null;
getHighResTimestamp(): number;
getPlatformConfig(): PlatformConfig;
getPlatformConfigAsync?(): Promise<PlatformConfig>;
}
export interface PlatformWorker {
postMessage(message: any, transfer?: Transferable[]): void;
onMessage(handler: (event: { data: any }) => void): void;
onError(handler: (error: ErrorEvent) => void): void;
terminate(): void;
readonly state: 'running' | 'terminated';
}

1. Choose the Appropriate Platform Adapter

Section titled “1. Choose the Appropriate Platform Adapter”

Select the corresponding adapter based on your runtime environment:

import { PlatformManager } from '@esengine/ecs-framework';
// Browser environment
if (typeof window !== 'undefined') {
const { BrowserAdapter } = await import('./platform/BrowserAdapter');
PlatformManager.getInstance().registerAdapter(new BrowserAdapter());
}
// WeChat Mini Game environment
else if (typeof wx !== 'undefined') {
const { WeChatMiniGameAdapter } = await import('./platform/WeChatMiniGameAdapter');
PlatformManager.getInstance().registerAdapter(new WeChatMiniGameAdapter());
}
// Node.js environment
else if (typeof process !== 'undefined' && process.versions?.node) {
const { NodeAdapter } = await import('./platform/NodeAdapter');
PlatformManager.getInstance().registerAdapter(new NodeAdapter());
}
const manager = PlatformManager.getInstance();
// Check if adapter is registered
if (manager.hasAdapter()) {
const adapter = manager.getAdapter();
console.log('Current platform:', adapter.name);
console.log('Platform version:', adapter.version);
// Check feature support
console.log('Worker support:', manager.supportsFeature('worker'));
console.log('SharedArrayBuffer support:', manager.supportsFeature('shared-array-buffer'));
}

If existing platform adapters don’t meet your needs, you can create custom adapters:

import type { IPlatformAdapter, PlatformWorker, WorkerCreationOptions, PlatformConfig } from '@esengine/ecs-framework';
export class CustomAdapter implements IPlatformAdapter {
public readonly name = 'custom';
public readonly version = '1.0.0';
public isWorkerSupported(): boolean {
// Implement your Worker support check logic
return false;
}
public isSharedArrayBufferSupported(): boolean {
// Implement your SharedArrayBuffer support check logic
return false;
}
public getHardwareConcurrency(): number {
// Return your platform's concurrency count
return 1;
}
public createWorker(script: string, options?: WorkerCreationOptions): PlatformWorker {
throw new Error('Worker not supported on this platform');
}
public createSharedArrayBuffer(length: number): SharedArrayBuffer | null {
return null;
}
public getHighResTimestamp(): number {
return Date.now();
}
public getPlatformConfig(): PlatformConfig {
return {
maxWorkerCount: 1,
supportsModuleWorker: false,
supportsTransferableObjects: false,
limitations: {
workerNotSupported: true
}
};
}
}
import { PlatformManager } from '@esengine/ecs-framework';
import { CustomAdapter } from './CustomAdapter';
const customAdapter = new CustomAdapter();
PlatformManager.getInstance().registerAdapter(customAdapter);

Recommend detecting and registering platform adapters in this order:

async function initializePlatform() {
const manager = PlatformManager.getInstance();
try {
// 1. WeChat Mini Game (highest priority, most distinctive environment)
if (typeof wx !== 'undefined' && wx.getSystemInfoSync) {
const { WeChatMiniGameAdapter } = await import('./platform/WeChatMiniGameAdapter');
manager.registerAdapter(new WeChatMiniGameAdapter());
return;
}
// 2. Node.js environment
if (typeof process !== 'undefined' && process.versions?.node) {
const { NodeAdapter } = await import('./platform/NodeAdapter');
manager.registerAdapter(new NodeAdapter());
return;
}
// 3. Browser environment (last check, broadest coverage)
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
const { BrowserAdapter } = await import('./platform/BrowserAdapter');
manager.registerAdapter(new BrowserAdapter());
return;
}
// 4. Unknown environment, use default adapter
console.warn('Unrecognized platform environment, using default adapter');
manager.registerAdapter(new CustomAdapter());
} catch (error) {
console.error('Platform adapter initialization failed:', error);
throw error;
}
}
function createWorkerSystem() {
const manager = PlatformManager.getInstance();
if (!manager.hasAdapter()) {
throw new Error('No platform adapter registered');
}
const config: WorkerSystemConfig = {
enableWorker: manager.supportsFeature('worker'),
workerCount: manager.supportsFeature('worker') ?
manager.getAdapter().getHardwareConcurrency() : 1,
useSharedArrayBuffer: manager.supportsFeature('shared-array-buffer')
};
// If Worker not supported, automatically degrade to synchronous processing
if (!config.enableWorker) {
console.info('Current platform does not support Worker, using synchronous processing mode');
}
return new PhysicsSystem(config);
}
try {
await initializePlatform();
// Validate adapter functionality
const manager = PlatformManager.getInstance();
const adapter = manager.getAdapter();
console.log(`Platform adapter initialized: ${adapter.name} v${adapter.version}`);
} catch (error) {
console.error('Platform initialization failed:', error);
// Provide fallback solution
const fallbackAdapter = new CustomAdapter();
PlatformManager.getInstance().registerAdapter(fallbackAdapter);
console.warn('Using fallback adapter to continue running');
}