Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/ecs/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
SRC = wasm/SparseArray.cpp\
wasm/Entity.cpp\
wasm/Utils.cpp\
wasm/Zipper.cpp\
wasm/IndexedZipper.cpp\
wasm/Registry.cpp

NAME := libecs
Expand All @@ -12,7 +14,7 @@ WASM_NAME = $(OUT_DIR)/$(NAME).wasm
TS_NAME = $(NAME).d.ts

CFLAGS = -std=c++20
LDFLAGS = -O3 --no-entry --bind
LDFLAGS = -O3 --no-entry --bind -sNO_DISABLE_EXCEPTION_CATCHING -sEXPORT_EXCEPTION_HANDLING_HELPERS

CC = em++

Expand Down
135 changes: 135 additions & 0 deletions packages/ecs/test/wasm/IndexedZipper.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import Module from "../../public/libecs";

class Velocity {
x: number;
y: number;

constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}

class Position {
x: number;
y: number;

constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}

describe("IndexedZipper", () => {
test("basic instantation", async () => {
const m = await Module();
const v = new m.MapStringSparseArray();

const zip = new m.IndexedZipper(v);

expect(zip).toBeDefined();
expect(zip.getValue()).toBeUndefined();
});

test("single simple sparse array instantation", async () => {
const m = await Module();
const r = new m.Registry();
expect(r).toBeDefined();

for (let i = 0; i < 5; i++) {
const e = r.spawnEntity();
r.addComponent(e, new Velocity(i, i));
}

const zip = r.getIndexedZipper([Velocity]);
expect(zip).toBeDefined();

for (let i = 0; i < 5; i++, zip.next()) {
expect(zip.getValue()).toStrictEqual({ entity: i, Velocity: new Velocity(i, i) });
}
expect(zip.getValue()).toBeUndefined();
});

test("single complex sparse array instantation", async () => {
const m = await Module();
const r = new m.Registry();
expect(r).toBeDefined();

for (let i = 0; i < 5; i++) {
const e = new m.Entity(i * 5);
r.addComponent(e, new Velocity(i, i));
}

const zip = r.getIndexedZipper([Velocity]);
expect(zip).toBeDefined();

for (let i = 0; i < 5; i++) {
expect(zip.getValue()).toStrictEqual({ entity: i * 5, Velocity: new Velocity(i, i) });
zip.next();
}
expect(zip.getValue()).toBeUndefined();
});

test("multiple complex sparse array instantation", async () => {
const m = await Module();
const r = new m.Registry();
expect(r).toBeDefined();

for (let i = 0; i < 20; i++) {
const e = r.spawnEntity(i);
if (i % 5 === 0) r.addComponent(e, new Velocity(0, i));
if (i % 3 === 0) r.addComponent(e, new Position(i, 0));
}

const zip = r.getIndexedZipper([Velocity, Position]);
expect(zip).toBeDefined();

for (let i = 0; i < 20; i++) {
if (i % 3 === 0 && i % 5 === 0) {
expect(zip.getValue()).toStrictEqual({
entity: i,
Velocity: new Velocity(0, i),
Position: new Position(i, 0),
});
zip.next();
}
}
expect(zip.getValue()).toBeUndefined();
});

test("simple indexed zipper modification", async () => {
const m = await Module();
const r = new m.Registry();
expect(r).toBeDefined();

for (let i = 0; i < 20; i++) {
const e = r.spawnEntity(i);
if (i % 5 === 0) {
r.addComponent(e, new Velocity(0, i));
}
}

let zip = r.getIndexedZipper([Velocity]);
expect(zip).toBeDefined();

for (let i = 0; i < 20; i++) {
if (i % 5 === 0) {
const vel = zip.getValue()["Velocity"];
vel.y *= 2;
zip.next();
}
}

zip = r.getIndexedZipper([Velocity]);
for (let i = 0; i < 20; i++) {
if (i % 5 === 0) {
expect(zip.getValue()).toStrictEqual({
entity: i,
Velocity: new Velocity(0, i * 2),
});
zip.next();
}
}
expect(zip.getValue()).toBeUndefined();
});
});
132 changes: 75 additions & 57 deletions packages/ecs/test/wasm/Registry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,17 @@ describe("Registry", () => {
const vel = new Velocity(1, 2);
const pos = new Position(4, 5);

const e = r.spawn_entity();
expect(e.get_id()).toBe(0);
const e = r.spawnEntity();
expect(e.getId()).toBe(0);

r.add_component(e, vel);
r.add_component(e, pos);
r.addComponent(e, vel);
r.addComponent(e, pos);

const velocities = r.get_components(Velocity);
const positions = r.get_components(Position);
const velocities = r.getComponents(Velocity);
const positions = r.getComponents(Position);

expect(velocities.get(e.get_id())).toStrictEqual(new Velocity(1, 2));
expect(positions.get(e.get_id())).toStrictEqual(new Position(4, 5));
expect(velocities.get(e.getId())).toStrictEqual(new Velocity(1, 2));
expect(positions.get(e.getId())).toStrictEqual(new Position(4, 5));
});

test("override components", async () => {
Expand All @@ -49,28 +49,28 @@ describe("Registry", () => {
const vel = new Velocity(1, 2);
const vel2 = new Velocity(4, 5);

const e = r.spawn_entity();
const e = r.spawnEntity();

r.add_component(e, vel);
expect(r.get_components(Velocity).get(e.get_id())).toStrictEqual(new Velocity(1, 2));
r.addComponent(e, vel);
expect(r.getComponents(Velocity).get(e.getId())).toStrictEqual(new Velocity(1, 2));

r.add_component(e, vel2);
expect(r.get_components(Velocity).get(e.get_id())).toStrictEqual(new Velocity(4, 5));
r.addComponent(e, vel2);
expect(r.getComponents(Velocity).get(e.getId())).toStrictEqual(new Velocity(4, 5));
});

test("basic remove", async () => {
const m = await Module();
const r = new m.Registry();

const vel = new Velocity(1, 2);
const e = r.spawn_entity();
const e = r.spawnEntity();

r.add_component(e, vel);
expect(r.get_components(Velocity).get(e.get_id())).toStrictEqual(new Velocity(1, 2));
r.addComponent(e, vel);
expect(r.getComponents(Velocity).get(e.getId())).toStrictEqual(new Velocity(1, 2));

r.remove_component(e, Velocity);
expect(r.get_components(Velocity).size()).toEqual(1);
expect(r.get_components(Velocity).get(e.get_id())).toBeUndefined();
r.removeComponent(e, Velocity);
expect(r.getComponents(Velocity).size()).toEqual(1);
expect(r.getComponents(Velocity).get(e.getId())).toBeUndefined();
});

test("basic kill", async () => {
Expand All @@ -81,23 +81,23 @@ describe("Registry", () => {
const vel = new Velocity(1, 2);
const pos = new Position(4, 5);

r.spawn_entity();
const e = r.spawn_entity();
expect(e.get_id()).toBe(1);
r.spawnEntity();
const e = r.spawnEntity();
expect(e.getId()).toBe(1);

r.add_component(e, vel);
r.add_component(e, pos);
r.addComponent(e, vel);
r.addComponent(e, pos);

const velocities = r.get_components(Velocity);
const positions = r.get_components(Position);
const velocities = r.getComponents(Velocity);
const positions = r.getComponents(Position);

expect(positions.size()).toEqual(2);
expect(velocities.get(e.get_id())).toStrictEqual(new Velocity(1, 2));
expect(positions.get(e.get_id())).toStrictEqual(new Position(4, 5));
expect(velocities.get(e.getId())).toStrictEqual(new Velocity(1, 2));
expect(positions.get(e.getId())).toStrictEqual(new Position(4, 5));

r.kill_entity(e);
expect(r.get_components(Velocity).get(e.get_id())).toBeUndefined();
expect(r.get_components(Position).get(e.get_id())).toBeUndefined();
r.killEntity(e);
expect(r.getComponents(Velocity).get(e.getId())).toBeUndefined();
expect(r.getComponents(Position).get(e.getId())).toBeUndefined();
});

test("system incrementing a variable", async () => {
Expand All @@ -106,13 +106,13 @@ describe("Registry", () => {

let counter = 0;

r.add_system(() => {
r.addSystem(() => {
counter += 1;
});

for (let i = 0; i <= 15; i++) {
expect(counter).toBe(i);
r.run_systems();
r.runSystems();
}
expect(counter).toBe(16);
});
Expand All @@ -122,22 +122,22 @@ describe("Registry", () => {
const r = new m.Registry();
expect(r).toBeDefined();

const e = r.spawn_entity();
const e2 = r.spawn_entity();
expect(e2.get_id()).toBe(1);
const e3 = r.spawn_entity();
const e = r.spawnEntity();
const e2 = r.spawnEntity();
expect(e2.getId()).toBe(1);
const e3 = r.spawnEntity();

r.add_component(e, new Velocity(1, 1));
r.add_component(e, new Position(-2, -2));
r.addComponent(e, new Velocity(1, 1));
r.addComponent(e, new Position(-2, -2));

r.add_component(e2, new Velocity(-1, -1));
r.add_component(e2, new Position(2, 2));
r.addComponent(e2, new Velocity(-1, -1));
r.addComponent(e2, new Position(2, 2));

r.add_component(e3, new Position(0, 0));
r.addComponent(e3, new Position(0, 0));

r.add_system(() => {
const velocities = r.get_components(Velocity);
const positions = r.get_components(Position);
r.addSystem(() => {
const velocities = r.getComponents(Velocity);
const positions = r.getComponents(Position);
for (let i = 0; i < velocities.size() && i < positions.size(); i++) {
if (velocities.get(i) === undefined || positions.get(i) === undefined) {
continue;
Expand All @@ -147,20 +147,38 @@ describe("Registry", () => {
}
});

expect(r.get_components(Position).size()).toEqual(3);
expect(r.getComponents(Position).size()).toEqual(3);

expect(r.get_components(Position).get(e.get_id())).toStrictEqual(new Position(-2, -2));
expect(r.get_components(Position).get(e2.get_id())).toStrictEqual(new Position(2, 2));
expect(r.get_components(Position).get(e3.get_id())).toStrictEqual(new Position(0, 0));
r.run_systems();
expect(r.getComponents(Position).get(e.getId())).toStrictEqual(new Position(-2, -2));
expect(r.getComponents(Position).get(e2.getId())).toStrictEqual(new Position(2, 2));
expect(r.getComponents(Position).get(e3.getId())).toStrictEqual(new Position(0, 0));
r.runSystems();

expect(r.get_components(Position).get(e.get_id())).toStrictEqual(new Position(-1, -1));
expect(r.get_components(Position).get(e2.get_id())).toStrictEqual(new Position(1, 1));
expect(r.get_components(Position).get(e3.get_id())).toStrictEqual(new Position(0, 0));
r.run_systems();
expect(r.getComponents(Position).get(e.getId())).toStrictEqual(new Position(-1, -1));
expect(r.getComponents(Position).get(e2.getId())).toStrictEqual(new Position(1, 1));
expect(r.getComponents(Position).get(e3.getId())).toStrictEqual(new Position(0, 0));
r.runSystems();

expect(r.get_components(Position).get(e.get_id())).toStrictEqual(new Position(0, 0));
expect(r.get_components(Position).get(e2.get_id())).toStrictEqual(new Position(0, 0));
expect(r.get_components(Position).get(e3.get_id())).toStrictEqual(new Position(0, 0));
expect(r.getComponents(Position).get(e.getId())).toStrictEqual(new Position(0, 0));
expect(r.getComponents(Position).get(e2.getId())).toStrictEqual(new Position(0, 0));
expect(r.getComponents(Position).get(e3.getId())).toStrictEqual(new Position(0, 0));
});

test("Try unallowed component name", async () => {
const m = await Module();
const r = new m.Registry();
expect(r).toBeDefined();

const entityComp = { name: "entity" };

const e = r.spawnEntity();
expect(e.getId()).toBe(0);

try {
r.addComponent(e, entityComp);
fail();
} catch (e) {
expect(m.getExceptionMessage(e)[1].toString()).toBeDefined();
}
});
});
2 changes: 1 addition & 1 deletion packages/ecs/test/wasm/SparseArray.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe("SparseArray", () => {
expect(sa.get(0)).toBe(undefined);
});

test("basic iteration", async () => {
test("basic iteration with get and size", async () => {
const m = await Module();
const sa = new m.SparseArray();
sa.set(0, 1);
Expand Down
Loading
Loading