refactor(core): 使用fflate替换msgpack以兼容小游戏环境

This commit is contained in:
YHH
2025-10-28 14:08:34 +08:00
parent 4e81fc7eba
commit 683203919f
7 changed files with 59 additions and 33 deletions

17
package-lock.json generated
View File

@@ -4929,15 +4929,6 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/@msgpack/msgpack": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.2.tgz",
"integrity": "sha512-JEW4DEtBzfe8HvUYecLU9e6+XJnKDlUAIve8FvPzF3Kzs6Xo/KuZkZJsDH0wJXl/qEZbeeE7edxDNY3kMs39hQ==",
"license": "ISC",
"engines": {
"node": ">= 18"
}
},
"node_modules/@napi-rs/wasm-runtime": { "node_modules/@napi-rs/wasm-runtime": {
"version": "0.2.4", "version": "0.2.4",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz",
@@ -12793,6 +12784,12 @@
} }
} }
}, },
"node_modules/fflate": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
"license": "MIT"
},
"node_modules/figures": { "node_modules/figures": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
@@ -26310,7 +26307,7 @@
"version": "2.2.9", "version": "2.2.9",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@msgpack/msgpack": "^3.0.0", "fflate": "^0.8.2",
"tslib": "^2.8.1" "tslib": "^2.8.1"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -72,7 +72,7 @@
"directory": "packages/core" "directory": "packages/core"
}, },
"dependencies": { "dependencies": {
"@msgpack/msgpack": "^3.0.0", "fflate": "^0.8.2",
"tslib": "^2.8.1" "tslib": "^2.8.1"
} }
} }

View File

@@ -17,7 +17,17 @@ const banner = `/**
const external = []; const external = [];
const commonPlugins = [ const modernPlugins = [
resolve({
browser: true,
preferBuiltins: false
}),
commonjs({
include: /node_modules/
})
];
const legacyPlugins = [
resolve({ resolve({
browser: true, browser: true,
preferBuiltins: false preferBuiltins: false
@@ -44,7 +54,7 @@ module.exports = [
exports: 'named' exports: 'named'
}, },
plugins: [ plugins: [
...commonPlugins, ...modernPlugins,
terser({ terser({
format: { format: {
comments: /^!/ comments: /^!/
@@ -65,7 +75,7 @@ module.exports = [
unknownGlobalSideEffects: false unknownGlobalSideEffects: false
} }
}, },
// CommonJS构建 // CommonJS构建
{ {
input: 'bin/index.js', input: 'bin/index.js',
@@ -77,7 +87,7 @@ module.exports = [
exports: 'named' exports: 'named'
}, },
plugins: [ plugins: [
...commonPlugins, ...modernPlugins,
terser({ terser({
format: { format: {
comments: /^!/ comments: /^!/
@@ -96,7 +106,7 @@ module.exports = [
} }
}, },
// UMD构建 - 用于CDN和浏览器直接使用 // UMD构建
{ {
input: 'bin/index.js', input: 'bin/index.js',
output: { output: {
@@ -108,7 +118,7 @@ module.exports = [
exports: 'named' exports: 'named'
}, },
plugins: [ plugins: [
...commonPlugins, ...legacyPlugins,
terser({ terser({
format: { format: {
comments: /^!/ comments: /^!/

View File

@@ -11,7 +11,7 @@ import { Component } from '../Component';
import { ComponentSerializer, SerializedComponent } from './ComponentSerializer'; import { ComponentSerializer, SerializedComponent } from './ComponentSerializer';
import { SerializedEntity } from './EntitySerializer'; import { SerializedEntity } from './EntitySerializer';
import { ComponentType } from '../Core/ComponentStorage'; import { ComponentType } from '../Core/ComponentStorage';
import { encode, decode } from '@msgpack/msgpack'; import { BinarySerializer } from '../../Utils/BinarySerializer';
/** /**
* 变更操作类型 * 变更操作类型
@@ -147,8 +147,8 @@ export interface IncrementalSerializationOptions {
/** /**
* 序列化格式 * 序列化格式
* - 'json': JSON格式(可读性好,方便调试) * - 'json': JSON格式
* - 'binary': MessagePack二进制格式体积小性能高 * - 'binary': 二进制格式
* 默认 'json' * 默认 'json'
*/ */
format?: IncrementalSerializationFormat; format?: IncrementalSerializationFormat;
@@ -639,7 +639,7 @@ export class IncrementalSerializer {
}; };
if (opts.format === 'binary') { if (opts.format === 'binary') {
return encode(incremental); return BinarySerializer.encode(incremental);
} else { } else {
return opts.pretty return opts.pretty
? JSON.stringify(incremental, null, 2) ? JSON.stringify(incremental, null, 2)
@@ -664,11 +664,9 @@ export class IncrementalSerializer {
*/ */
public static deserializeIncremental(data: string | Uint8Array): IncrementalSnapshot { public static deserializeIncremental(data: string | Uint8Array): IncrementalSnapshot {
if (typeof data === 'string') { if (typeof data === 'string') {
// JSON格式
return JSON.parse(data); return JSON.parse(data);
} else { } else {
// 二进制格式MessagePack return BinarySerializer.decode(data) as IncrementalSnapshot;
return decode(data) as IncrementalSnapshot;
} }
} }

View File

@@ -11,7 +11,7 @@ import { ComponentType, ComponentRegistry } from '../Core/ComponentStorage';
import { EntitySerializer, SerializedEntity } from './EntitySerializer'; import { EntitySerializer, SerializedEntity } from './EntitySerializer';
import { getComponentTypeName } from '../Decorators'; import { getComponentTypeName } from '../Decorators';
import { getSerializationMetadata } from './SerializationDecorators'; import { getSerializationMetadata } from './SerializationDecorators';
import { encode, decode } from '@msgpack/msgpack'; import { BinarySerializer } from '../../Utils/BinarySerializer';
/** /**
* 场景序列化格式 * 场景序列化格式
@@ -200,14 +200,12 @@ export class SceneSerializer {
}; };
} }
// 根据格式返回数据
if (opts.format === 'json') { if (opts.format === 'json') {
return opts.pretty return opts.pretty
? JSON.stringify(serializedScene, null, 2) ? JSON.stringify(serializedScene, null, 2)
: JSON.stringify(serializedScene); : JSON.stringify(serializedScene);
} else { } else {
// 二进制格式(使用 MessagePack return BinarySerializer.encode(serializedScene);
return encode(serializedScene);
} }
} }
@@ -229,15 +227,12 @@ export class SceneSerializer {
...options ...options
}; };
// 解析数据
let serializedScene: SerializedScene; let serializedScene: SerializedScene;
try { try {
if (typeof saveData === 'string') { if (typeof saveData === 'string') {
// JSON格式
serializedScene = JSON.parse(saveData); serializedScene = JSON.parse(saveData);
} else { } else {
// 二进制格式MessagePack serializedScene = BinarySerializer.decode(saveData) as SerializedScene;
serializedScene = decode(saveData) as SerializedScene;
} }
} catch (error) { } catch (error) {
throw new Error(`Failed to parse save data: ${error}`); throw new Error(`Failed to parse save data: ${error}`);

View File

@@ -0,0 +1,25 @@
import { strToU8, strFromU8, zlibSync, unzlibSync } from 'fflate';
/**
* 二进制序列化器
* 使用zlib压缩JSON数据
*/
export class BinarySerializer {
/**
* 将对象编码为压缩的二进制数据
*/
public static encode(value: any): Uint8Array {
const jsonString = JSON.stringify(value);
const utf8Bytes = strToU8(jsonString);
return zlibSync(utf8Bytes);
}
/**
* 将压缩的二进制数据解码为对象
*/
public static decode(bytes: Uint8Array): any {
const decompressed = unzlibSync(bytes);
const jsonString = strFromU8(decompressed);
return JSON.parse(jsonString);
}
}

View File

@@ -5,4 +5,5 @@ export * from './GlobalManager';
export * from './PerformanceMonitor'; export * from './PerformanceMonitor';
export { Time } from './Time'; export { Time } from './Time';
export * from './Debug'; export * from './Debug';
export * from './Logger'; export * from './Logger';
export * from './BinarySerializer';