refactor: codecs

This commit is contained in:
cha0s 2024-12-02 02:05:10 -06:00
parent a98049fe07
commit 145e4cfdb8
7 changed files with 107 additions and 97 deletions

View File

@ -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
View File

@ -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"

View File

@ -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",

View File

@ -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;

View File

@ -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)}});

View File

@ -23,4 +23,4 @@ delete Properties.number;
export {definitions, Properties};
export * as Codecs from './codecs.js';
export {default as registerCodecs} from './codecs.js';

View File

@ -8,14 +8,6 @@ export default defineConfig({
fileName: 'index',
name: 'ecstc',
},
rollupOptions: {
external: ['crunches'],
output: {
globals: {
crunches: 'crunches',
},
},
},
sourcemap: true,
target: 'esnext',
},