Skip to content

Commit

Permalink
🐛 core: multiple actions per world work again
Browse files Browse the repository at this point in the history
  • Loading branch information
krispya committed Nov 29, 2024
1 parent b7440ed commit 7c59c05
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
12 changes: 9 additions & 3 deletions packages/core/src/actions/create-actions.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { World } from '../world/world';

const actionCache = new WeakMap<World, any>();
const actionCache = new WeakMap<World, Map<Function, any>>();

export function createActions<T extends Record<string, (...args: any[]) => any>>(
actionSet: (world: World) => T
): (world: World) => T {
return (world: World): T => {
let actions = actionCache.get(world);
let worldCache = actionCache.get(world);
if (!worldCache) {
worldCache = new Map();
actionCache.set(world, worldCache);
}

let actions = worldCache.get(actionSet);
if (!actions) {
actions = actionSet(world);
actionCache.set(world, actions);
worldCache.set(actionSet, actions);
}
return actions;
};
Expand Down
27 changes: 24 additions & 3 deletions packages/core/tests/actions.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { createActions } from '../src/actions/create-actions';
import { createWorld } from '../src';
import { trait } from '../src';
import { beforeEach, describe, expect, it } from 'vitest';
import { createWorld, trait } from '../src';
import { createActions } from '../src/actions/create-actions';

const IsPlayer = trait();

Expand Down Expand Up @@ -30,4 +29,26 @@ describe('Actions', () => {
// Should be the same function
expect(spawnPlayer2).toBe(spawnPlayer);
});

it('should create multiple memoized actions per world', () => {
const actions1 = createActions((world) => ({
spawnPlayer: () => world.spawn(IsPlayer),
destroyPlayers: () => {
world.query(IsPlayer).forEach((e) => e.destroy());
},
}));

const actions2 = createActions((world) => ({
spawnPlayer: () => world.spawn(IsPlayer),
destroyPlayers: () => {
world.query(IsPlayer).forEach((e) => e.destroy());
},
}));

const { spawnPlayer: spawnPlayer1 } = actions1(world);
const { spawnPlayer: spawnPlayer2 } = actions2(world);

// Should be different functions
expect(spawnPlayer1).not.toBe(spawnPlayer2);
});
});

0 comments on commit 7c59c05

Please sign in to comment.