refactor(core): 使用fflate替换msgpack以兼容小游戏环境
This commit is contained in:
17
package-lock.json
generated
17
package-lock.json
generated
@@ -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": {
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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: /^!/
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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}`);
|
||||||
|
|||||||
25
packages/core/src/Utils/BinarySerializer.ts
Normal file
25
packages/core/src/Utils/BinarySerializer.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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';
|
||||||
|
|||||||
Reference in New Issue
Block a user