Skip to content
Draft
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
11 changes: 7 additions & 4 deletions packages/core/src/actions/create-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { Actions, ActionInitializer, ActionGetter } from './types';

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

export function createActions<T extends Actions>(initializer: ActionInitializer<T>): ActionGetter<T> {
return (world: World): T => {
export function createActions<
T extends Actions,
C extends Record<string, unknown> | undefined = undefined
>(initializer: ActionInitializer<T, C>): ActionGetter<T, C> {
return ((world: World, context?: C): T => {
let worldCache = actionCache.get(world);

if (!worldCache) {
Expand All @@ -15,10 +18,10 @@ export function createActions<T extends Actions>(initializer: ActionInitializer<
let actions = worldCache.get(initializer);

if (!actions) {
actions = initializer(world);
actions = initializer(world, context ?? ({} as C));
worldCache.set(initializer, actions);
}

return actions as T;
};
}) as ActionGetter<T, C>;
}
14 changes: 11 additions & 3 deletions packages/core/src/actions/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { World } from '../world/world';

export type Actions = Record<string, (...args: any[]) => void>;
export type ActionInitializer<T extends Actions> = (world: World) => T;
export type ActionGetter<T extends Actions> = (world: World) => T;
export type Actions = Record<never, (...args: any[]) => void>;

export type ActionInitializer<
T extends Actions,
C extends Record<string, unknown> | undefined = undefined
> = (world: World, context: C) => T;

export type ActionGetter<
T extends Actions,
C extends Record<string, unknown> | undefined = undefined
> = C extends undefined ? (world: World) => T : (world: World, context: C) => T;
23 changes: 23 additions & 0 deletions packages/core/tests/actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,27 @@ describe('Actions', () => {
// Should be different functions
expect(spawnPlayer1).not.toBe(spawnPlayer2);
});

it('should create actions with context', () => {
const actions = createActions((world, context: { count: number }) => ({
addToCount: (amount: number) => {
context.count += amount;
},
resetCount: () => {
context.count = 0;
},
}));

const context = { count: 0 };
const { addToCount, resetCount } = actions(world, context);

addToCount(1);
expect(context.count).toBe(1);

addToCount(2);
expect(context.count).toBe(3);

resetCount();
expect(context.count).toBe(0);
});
});