refactor: codecs
This commit is contained in:
parent
a98049fe07
commit
145e4cfdb8
20
README.md
20
README.md
|
@ -16,4 +16,22 @@ This is a library.
|
|||
|
||||
## Serialization
|
||||
|
||||
`ecstc` uses [`crunches`](https://github.com/cha0s/crunches) for binary serialization.
|
||||
`ecstc` works with [`crunches`](https://github.com/cha0s/crunches) for binary serialization:
|
||||
|
||||
```js
|
||||
import {Codecs} from 'crunches';
|
||||
import {Ecs, registerCodecs} from 'ecstc';
|
||||
|
||||
registerCodecs(Codecs);
|
||||
|
||||
const ecs = new Ecs({Components: {}, Systems: {}});
|
||||
ecs.create(); // now has entity ID: 1 with no components
|
||||
|
||||
const schema = new Schema({ecs, type: 'ecstc-ecs'});
|
||||
const view = schema.allocate(ecs.entities);
|
||||
schema.encode(ecs.entities, view);
|
||||
console.log(schema.decode(view)) // Map(1) { 1 => {} }
|
||||
// or,
|
||||
schema.encode(ecs.diff(), view);
|
||||
console.log(schema.decode(view)) // Map(1) { 1 => {} }
|
||||
```
|
||||
|
|
5
package-lock.json
generated
5
package-lock.json
generated
|
@ -8,11 +8,9 @@
|
|||
"name": "ecstc",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"crunches": "^1.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitest/coverage-v8": "^1.6.0",
|
||||
"crunches": "^1.5.1",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
|
@ -1587,6 +1585,7 @@
|
|||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/crunches/-/crunches-1.5.1.tgz",
|
||||
"integrity": "sha512-6UllN4wALPo8kLbDINFI8FkxPBmRplWcwrQIdrAV4SD0viGF4YytR+Ku3Mv4e8VU42apEgCkbsnn5xv+oUcbdQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
{
|
||||
"author": "cha0s",
|
||||
"dependencies": {
|
||||
"crunches": "^1.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitest/coverage-v8": "^1.6.0",
|
||||
"crunches": "^1.5.1",
|
||||
"eslint": "^8.38.0",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
|
|
160
src/codecs.js
160
src/codecs.js
|
@ -1,92 +1,94 @@
|
|||
import {Codecs} from 'crunches';
|
||||
function registerCodecs(Codecs) {
|
||||
class MaybeDeletion extends Codecs.object {
|
||||
|
||||
class MaybeDeletion extends Codecs.object {
|
||||
|
||||
constructor(blueprint) {
|
||||
super(blueprint);
|
||||
this.$$isDeletion = new Codecs.bool();
|
||||
}
|
||||
|
||||
decode(view, target) {
|
||||
const isDeletion = this.$$isDeletion.decode(view, target);
|
||||
if (isDeletion) {
|
||||
return false;
|
||||
constructor(blueprint) {
|
||||
super(blueprint);
|
||||
this.$$isDeletion = new Codecs.bool();
|
||||
}
|
||||
return super.decode(view, target);
|
||||
}
|
||||
|
||||
encode(value, view, byteOffset) {
|
||||
let written = 0;
|
||||
written += this.$$isDeletion.encode(false === value, view, byteOffset);
|
||||
if (value) {
|
||||
written += super.encode(value, view, byteOffset + written);
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
size(value) {
|
||||
let size = this.$$isDeletion.size();
|
||||
if (value) {
|
||||
size += super.size(value);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function convertPropertiesToOptional(blueprint) {
|
||||
if ('properties' in blueprint) {
|
||||
const newBlueprint = {properties: {}, type: blueprint.type}
|
||||
for (const key in blueprint.properties) {
|
||||
newBlueprint.properties[key] = {
|
||||
...convertPropertiesToOptional(blueprint.properties[key]),
|
||||
optional: true,
|
||||
decode(view, target) {
|
||||
const isDeletion = this.$$isDeletion.decode(view, target);
|
||||
if (isDeletion) {
|
||||
return false;
|
||||
}
|
||||
return super.decode(view, target);
|
||||
}
|
||||
return newBlueprint;
|
||||
}
|
||||
else {
|
||||
return blueprint;
|
||||
}
|
||||
}
|
||||
|
||||
class Component extends MaybeDeletion {
|
||||
|
||||
constructor(blueprint) {
|
||||
super(convertPropertiesToOptional(blueprint));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Entity extends MaybeDeletion {
|
||||
|
||||
constructor(blueprint) {
|
||||
const {ecs} = blueprint;
|
||||
const properties = {};
|
||||
for (const componentName in ecs.Components) {
|
||||
const Component = ecs.Components[componentName];
|
||||
properties[componentName] = {
|
||||
optional: true,
|
||||
type: 'ecstc-component',
|
||||
properties: Component.constructor.properties,
|
||||
};
|
||||
encode(value, view, byteOffset) {
|
||||
let written = 0;
|
||||
written += this.$$isDeletion.encode(false === value, view, byteOffset);
|
||||
if (value) {
|
||||
written += super.encode(value, view, byteOffset + written);
|
||||
}
|
||||
return written;
|
||||
}
|
||||
super({properties});
|
||||
|
||||
size(value) {
|
||||
let size = this.$$isDeletion.size();
|
||||
if (value) {
|
||||
size += super.size(value);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Ecs extends Codecs.map {
|
||||
|
||||
constructor(blueprint) {
|
||||
super({
|
||||
key: {type: 'varuint'},
|
||||
value: {type: 'ecstc-entity', ecs: blueprint.ecs},
|
||||
});
|
||||
function convertPropertiesToOptional(blueprint) {
|
||||
if ('properties' in blueprint) {
|
||||
const newBlueprint = {properties: {}, type: blueprint.type}
|
||||
for (const key in blueprint.properties) {
|
||||
newBlueprint.properties[key] = {
|
||||
...convertPropertiesToOptional(blueprint.properties[key]),
|
||||
optional: true,
|
||||
}
|
||||
}
|
||||
return newBlueprint;
|
||||
}
|
||||
else {
|
||||
return blueprint;
|
||||
}
|
||||
}
|
||||
|
||||
class Component extends MaybeDeletion {
|
||||
|
||||
constructor(blueprint) {
|
||||
super(convertPropertiesToOptional(blueprint));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Entity extends MaybeDeletion {
|
||||
|
||||
constructor(blueprint) {
|
||||
const {ecs} = blueprint;
|
||||
const properties = {};
|
||||
for (const componentName in ecs.Components) {
|
||||
const Component = ecs.Components[componentName];
|
||||
properties[componentName] = {
|
||||
optional: true,
|
||||
type: 'ecstc-component',
|
||||
properties: Component.constructor.properties,
|
||||
};
|
||||
}
|
||||
super({properties});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Ecs extends Codecs.map {
|
||||
|
||||
constructor(blueprint) {
|
||||
super({
|
||||
key: {type: 'varuint'},
|
||||
value: {type: 'ecstc-entity', ecs: blueprint.ecs},
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Codecs['ecstc-ecs'] = Ecs;
|
||||
Codecs['ecstc-entity'] = Entity;
|
||||
Codecs['ecstc-component'] = Component;
|
||||
}
|
||||
|
||||
Codecs['ecstc-ecs'] = Ecs;
|
||||
Codecs['ecstc-entity'] = Entity;
|
||||
Codecs['ecstc-component'] = Component;
|
||||
export default registerCodecs;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {Schema} from 'crunches';
|
||||
import {Codecs, Schema} from 'crunches';
|
||||
import {expect, test} from 'vitest';
|
||||
|
||||
import registerCodecs from './codecs.js';
|
||||
import Ecs from './ecs.js';
|
||||
import System from './system.js';
|
||||
import {fakeEnvironment} from './test-helper.js';
|
||||
|
@ -89,7 +90,7 @@ test('indexing', () => {
|
|||
});
|
||||
|
||||
test('serialization', async () => {
|
||||
await import('./codecs.js');
|
||||
registerCodecs(Codecs);
|
||||
const ecs = new Ecs({Components: {D}, Systems: {}});
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
ecs.create((i & 1) ? {} : {D: {d: 1 / (i + 1)}});
|
||||
|
|
|
@ -23,4 +23,4 @@ delete Properties.number;
|
|||
|
||||
export {definitions, Properties};
|
||||
|
||||
export * as Codecs from './codecs.js';
|
||||
export {default as registerCodecs} from './codecs.js';
|
||||
|
|
|
@ -8,14 +8,6 @@ export default defineConfig({
|
|||
fileName: 'index',
|
||||
name: 'ecstc',
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ['crunches'],
|
||||
output: {
|
||||
globals: {
|
||||
crunches: 'crunches',
|
||||
},
|
||||
},
|
||||
},
|
||||
sourcemap: true,
|
||||
target: 'esnext',
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue
Block a user