mirror of
https://github.com/motajs/template.git
synced 2026-09-12 17:58:51 +08:00
fix(01-12): repair event phase type fixtures
- Import the existing block event environment contract. - Type focused invocation, raw-event, and map lifecycle fixtures without changing behavior.
This commit is contained in:
parent
ce63966367
commit
15d9f25b44
@ -1,4 +1,9 @@
|
||||
import { beforeAll, describe, expect, it, vi } from 'vitest';
|
||||
import {
|
||||
type IDataCommon,
|
||||
type IMapRawData,
|
||||
type ITileStore
|
||||
} from '@user/data-common';
|
||||
|
||||
interface TestModules {
|
||||
MapState: typeof import('./mapState').MapState;
|
||||
@ -22,7 +27,7 @@ beforeAll(async () => {
|
||||
};
|
||||
});
|
||||
|
||||
function createRaw() {
|
||||
function createRaw(): IMapRawData {
|
||||
return {
|
||||
floorId: 'F1',
|
||||
width: 2,
|
||||
@ -33,8 +38,8 @@ function createRaw() {
|
||||
}
|
||||
|
||||
function createMapState() {
|
||||
const tileStore = new modules.TileStore();
|
||||
const state = {
|
||||
const tileStore: ITileStore = new modules.TileStore() as never;
|
||||
const state: IDataCommon = {
|
||||
tileStore,
|
||||
itemStore: {},
|
||||
mapStore: {},
|
||||
@ -42,7 +47,7 @@ function createMapState() {
|
||||
roleFace: new modules.RoleFaceBinder(),
|
||||
faceManager: {},
|
||||
saveSystem: {}
|
||||
};
|
||||
} as never;
|
||||
return new modules.MapState(tileStore, state);
|
||||
}
|
||||
|
||||
@ -64,7 +69,13 @@ describe('MapState raw event path', () => {
|
||||
});
|
||||
|
||||
describe('MapState malformed raw event structures', () => {
|
||||
const cases = [
|
||||
interface MalformedCase {
|
||||
name: string;
|
||||
mutate(raw: IMapRawData): void;
|
||||
code: number;
|
||||
}
|
||||
|
||||
const cases: MalformedCase[] = [
|
||||
{
|
||||
name: 'missing raw.map container',
|
||||
mutate: raw => Reflect.set(raw, 'map', null),
|
||||
|
||||
@ -1,4 +1,15 @@
|
||||
import { beforeAll, describe, expect, it, vi } from 'vitest';
|
||||
import { type IResizableMapLayer } from './types';
|
||||
import {
|
||||
type IDataCommon,
|
||||
type ITileStore,
|
||||
SaveCompression
|
||||
} from '@user/data-common';
|
||||
|
||||
vi.hoisted(() => {
|
||||
vi.stubGlobal('main', { replayChecking: true });
|
||||
vi.stubGlobal('location', { origin: 'http://localhost' });
|
||||
});
|
||||
|
||||
interface TestModules {
|
||||
MapState: typeof import('./mapState').MapState;
|
||||
@ -6,7 +17,6 @@ interface TestModules {
|
||||
RoleFaceBinder: typeof import('@user/data-common').RoleFaceBinder;
|
||||
FaceManager: typeof import('@user/data-common').FaceManager;
|
||||
Dir8FaceHandler: typeof import('@user/data-common').Dir8FaceHandler;
|
||||
SaveCompression: typeof import('@user/data-common').SaveCompression;
|
||||
}
|
||||
|
||||
let modules: TestModules;
|
||||
@ -21,8 +31,7 @@ beforeAll(async () => {
|
||||
TileStore: commonModule.TileStore,
|
||||
RoleFaceBinder: commonModule.RoleFaceBinder,
|
||||
FaceManager: commonModule.FaceManager,
|
||||
Dir8FaceHandler: commonModule.Dir8FaceHandler,
|
||||
SaveCompression: commonModule.SaveCompression
|
||||
Dir8FaceHandler: commonModule.Dir8FaceHandler
|
||||
};
|
||||
});
|
||||
|
||||
@ -30,7 +39,7 @@ function createMapState(
|
||||
pointEvents: Record<number, Record<number, string>> = {},
|
||||
blocks: number[] = [1, 1, 1, 1]
|
||||
) {
|
||||
const tileStore = new modules.TileStore();
|
||||
const tileStore: ITileStore = new modules.TileStore() as never;
|
||||
tileStore.addTile({
|
||||
num: 1,
|
||||
id: 'base',
|
||||
@ -49,7 +58,7 @@ function createMapState(
|
||||
});
|
||||
const faceManager = new modules.FaceManager();
|
||||
faceManager.register(1, new modules.Dir8FaceHandler());
|
||||
const state = {
|
||||
const state: IDataCommon = {
|
||||
tileStore,
|
||||
itemStore: {},
|
||||
mapStore: {},
|
||||
@ -57,7 +66,7 @@ function createMapState(
|
||||
roleFace: new modules.RoleFaceBinder(),
|
||||
faceManager,
|
||||
saveSystem: {}
|
||||
};
|
||||
} as never;
|
||||
const mapState = new modules.MapState(tileStore, state);
|
||||
const map = mapState.fromRaw({
|
||||
floorId: 'F1',
|
||||
@ -66,7 +75,10 @@ function createMapState(
|
||||
layerAlias: { 0: 'event' },
|
||||
events: { 0: pointEvents }
|
||||
});
|
||||
return { map: map!, layer: map!.getLayerByAlias('event')! };
|
||||
return {
|
||||
map: map!,
|
||||
layer: map!.getLayerByAlias('event')! as IResizableMapLayer
|
||||
};
|
||||
}
|
||||
|
||||
describe('MapLayer tile defaults snapshots conversion and movement', () => {
|
||||
@ -94,20 +106,22 @@ describe('MapLayer tile defaults snapshots conversion and movement', () => {
|
||||
);
|
||||
expect(dynamicTile.tileEvent().dirty()).toBe(false);
|
||||
|
||||
const cleanSave = dynamicTile.saveState();
|
||||
const cleanSave = dynamicTile.saveState(SaveCompression.NoCompression);
|
||||
expect(cleanSave.events).toBeUndefined();
|
||||
dynamicTile.loadState(cleanSave);
|
||||
dynamicTile.loadState(cleanSave, SaveCompression.NoCompression);
|
||||
expect(dynamicTile.tileEvent().get()).toEqual(
|
||||
new Map([[20, 'alternate-event']])
|
||||
);
|
||||
expect(dynamicTile.tileEvent().dirty()).toBe(false);
|
||||
|
||||
dynamicTile.tileEvent().set(30, 'override-event');
|
||||
const overrideSave = dynamicTile.saveState();
|
||||
const overrideSave = dynamicTile.saveState(
|
||||
SaveCompression.NoCompression
|
||||
);
|
||||
const savedEvents = new Map(overrideSave.events!);
|
||||
dynamicTile.tileEvent().set(30, 'changed-after-save');
|
||||
expect(overrideSave.events).toEqual(savedEvents);
|
||||
dynamicTile.loadState(overrideSave);
|
||||
dynamicTile.loadState(overrideSave, SaveCompression.NoCompression);
|
||||
expect(dynamicTile.tileEvent().get()).toEqual(
|
||||
new Map([
|
||||
[20, 'alternate-event'],
|
||||
@ -169,9 +183,9 @@ describe('MapLayer point event lifecycle', () => {
|
||||
expect(point.dirty()).toBe(false);
|
||||
|
||||
const compressionLevels = [
|
||||
modules.SaveCompression.NoCompression,
|
||||
modules.SaveCompression.LowCompression,
|
||||
modules.SaveCompression.HighCompression
|
||||
SaveCompression.NoCompression,
|
||||
SaveCompression.LowCompression,
|
||||
SaveCompression.HighCompression
|
||||
];
|
||||
for (const compression of compressionLevels) {
|
||||
point.set(7, 'saved-point');
|
||||
@ -208,7 +222,7 @@ describe('MapLayer point event lifecycle', () => {
|
||||
height: 2,
|
||||
fullMap: new Uint32Array([1, 1, 1, 1])
|
||||
},
|
||||
modules.SaveCompression.NoCompression
|
||||
SaveCompression.NoCompression
|
||||
);
|
||||
expect(point.get()).toEqual(new Map([[5, 'raw-point']]));
|
||||
expect(point.dirty()).toBe(false);
|
||||
@ -224,8 +238,8 @@ describe('MapLayer point event lifecycle', () => {
|
||||
expect(layer.dirty()).toBe(true);
|
||||
|
||||
const compressionLevels = [
|
||||
modules.SaveCompression.LowCompression,
|
||||
modules.SaveCompression.HighCompression
|
||||
SaveCompression.LowCompression,
|
||||
SaveCompression.HighCompression
|
||||
];
|
||||
for (const compression of compressionLevels) {
|
||||
const save = map.saveState(compression);
|
||||
|
||||
@ -1,17 +1,60 @@
|
||||
import { beforeAll, describe, expect, it, vi } from 'vitest';
|
||||
import {
|
||||
BlockEventType,
|
||||
type IBlockEventEnv,
|
||||
type IGameEventInvocation
|
||||
} from '@user/data-base';
|
||||
import {
|
||||
type IDataCommon,
|
||||
type IGameEventStore,
|
||||
type IReadonlyGameEvent,
|
||||
type ITileStore,
|
||||
EventTrigger
|
||||
} from '@user/data-common';
|
||||
import { type IStateSystem } from '../types';
|
||||
import { EventExecuteMode, EventReduceMode } from './types';
|
||||
import { AnonTokyoInterpreter } from 'anon-tokyo';
|
||||
|
||||
vi.hoisted(() => {
|
||||
vi.stubGlobal('main', { replayChecking: true });
|
||||
vi.stubGlobal('location', { origin: 'http://localhost' });
|
||||
});
|
||||
|
||||
const eventTriggers = {
|
||||
OnEnter: EventTrigger.OnEnter,
|
||||
OnLeave: EventTrigger.OnLeave,
|
||||
OnTouch: EventTrigger.OnTouch
|
||||
} as const;
|
||||
|
||||
const blockEventTypes = {
|
||||
PointEvent: BlockEventType.PointEvent,
|
||||
TileEvent: BlockEventType.TileEvent
|
||||
} as const;
|
||||
|
||||
const eventExecuteModes = {
|
||||
Normal: EventExecuteMode.Normal,
|
||||
CutIfFalsy: EventExecuteMode.CutIfFalsy,
|
||||
CutIfTruthy: EventExecuteMode.CutIfTruthy
|
||||
} as const;
|
||||
|
||||
const eventReduceModes = {
|
||||
NoReduce: EventReduceMode.NoReduce,
|
||||
OrReduce: EventReduceMode.OrReduce,
|
||||
AndReduce: EventReduceMode.AndReduce
|
||||
} as const;
|
||||
|
||||
interface TestModules {
|
||||
EventExecutor: typeof import('./executor').EventExecutor;
|
||||
DefaultHeroMoveTopImpl: typeof import('@user/data-state/hero/moverImpl').DefaultHeroMoveTopImpl;
|
||||
DefaultHeroMoveTopImpl: typeof import('@user/data-state').DefaultHeroMoveTopImpl;
|
||||
MapState: typeof import('@user/data-base').MapState;
|
||||
TileStore: typeof import('@user/data-common').TileStore;
|
||||
RoleFaceBinder: typeof import('@user/data-common').RoleFaceBinder;
|
||||
FaceManager: typeof import('@user/data-common').FaceManager;
|
||||
Dir8FaceHandler: typeof import('@user/data-common').Dir8FaceHandler;
|
||||
EventTrigger: typeof import('@user/data-common').EventTrigger;
|
||||
BlockEventType: typeof import('@user/data-base').BlockEventType;
|
||||
EventExecuteMode: typeof import('./types').EventExecuteMode;
|
||||
EventReduceMode: typeof import('./types').EventReduceMode;
|
||||
EventTrigger: typeof eventTriggers;
|
||||
BlockEventType: typeof blockEventTypes;
|
||||
EventExecuteMode: typeof eventExecuteModes;
|
||||
EventReduceMode: typeof eventReduceModes;
|
||||
}
|
||||
|
||||
interface EventCall {
|
||||
@ -29,22 +72,21 @@ beforeAll(async () => {
|
||||
vi.stubGlobal('main', { replayChecking: true });
|
||||
vi.stubGlobal('location', { origin: 'http://localhost' });
|
||||
const executorModule = await import('./executor');
|
||||
const moverModule = await import('@user/data-state/hero/moverImpl');
|
||||
const stateModule = await import('../../../data-state/src/hero');
|
||||
const baseModule = await import('@user/data-base');
|
||||
const commonModule = await import('@user/data-common');
|
||||
const eventModule = await import('./types');
|
||||
modules = {
|
||||
EventExecutor: executorModule.EventExecutor,
|
||||
DefaultHeroMoveTopImpl: moverModule.DefaultHeroMoveTopImpl,
|
||||
DefaultHeroMoveTopImpl: stateModule.DefaultHeroMoveTopImpl,
|
||||
MapState: baseModule.MapState,
|
||||
TileStore: commonModule.TileStore,
|
||||
RoleFaceBinder: commonModule.RoleFaceBinder,
|
||||
FaceManager: commonModule.FaceManager,
|
||||
Dir8FaceHandler: commonModule.Dir8FaceHandler,
|
||||
EventTrigger: commonModule.EventTrigger,
|
||||
BlockEventType: baseModule.BlockEventType,
|
||||
EventExecuteMode: eventModule.EventExecuteMode,
|
||||
EventReduceMode: eventModule.EventReduceMode
|
||||
EventTrigger: eventTriggers,
|
||||
BlockEventType: blockEventTypes,
|
||||
EventExecuteMode: eventExecuteModes,
|
||||
EventReduceMode: eventReduceModes
|
||||
};
|
||||
});
|
||||
|
||||
@ -53,7 +95,7 @@ function createFixture(
|
||||
staticEvent: string = 'static-enter',
|
||||
dynamicEvent: string = 'dynamic-enter'
|
||||
) {
|
||||
const tileStore = new modules.TileStore();
|
||||
const tileStore: ITileStore = new modules.TileStore() as never;
|
||||
tileStore.addTile({
|
||||
num: 1,
|
||||
id: 'static',
|
||||
@ -72,7 +114,7 @@ function createFixture(
|
||||
});
|
||||
const faceManager = new modules.FaceManager();
|
||||
faceManager.register(1, new modules.Dir8FaceHandler());
|
||||
const commonState = {
|
||||
const commonState: IDataCommon = {
|
||||
tileStore,
|
||||
itemStore: {},
|
||||
mapStore: {},
|
||||
@ -80,7 +122,7 @@ function createFixture(
|
||||
roleFace: new modules.RoleFaceBinder(),
|
||||
faceManager,
|
||||
saveSystem: {}
|
||||
};
|
||||
} as never;
|
||||
const maps = new modules.MapState(tileStore, commonState);
|
||||
const map = maps.fromRaw({
|
||||
floorId: 'F1',
|
||||
@ -93,18 +135,35 @@ function createFixture(
|
||||
const dynamic = layer.createDynamic(2, 1, 0);
|
||||
dynamic.set(2);
|
||||
const events = new Map<string, object>();
|
||||
const store = {
|
||||
getEvent(id: string) {
|
||||
return events.get(id) ?? null;
|
||||
const store: IGameEventStore = {
|
||||
addEvent() {},
|
||||
getEvent<
|
||||
P extends Record<string, any>,
|
||||
E extends Record<string, any>,
|
||||
R = void
|
||||
>(id: string): IReadonlyGameEvent<P, E, R> | null {
|
||||
return events.get(id) as never;
|
||||
}
|
||||
};
|
||||
const executor = new modules.EventExecutor({}, () => store);
|
||||
const executor = new modules.EventExecutor(
|
||||
{} as AnonTokyoInterpreter,
|
||||
() => store
|
||||
);
|
||||
const state = {
|
||||
maps,
|
||||
eventSystem: { executor }
|
||||
};
|
||||
const mover = new modules.DefaultHeroMoveTopImpl(state);
|
||||
return { events, executor, layer, map: map!, dynamic, mover, state };
|
||||
const fixtureState: IStateSystem & IDataCommon = state as never;
|
||||
const mover = new modules.DefaultHeroMoveTopImpl(fixtureState);
|
||||
return {
|
||||
events,
|
||||
executor,
|
||||
layer,
|
||||
map: map!,
|
||||
dynamic,
|
||||
mover,
|
||||
state: fixtureState
|
||||
};
|
||||
}
|
||||
|
||||
function addEvent(
|
||||
@ -139,8 +198,18 @@ function addEvent(
|
||||
});
|
||||
}
|
||||
|
||||
function invocation(id: string, trigger: number) {
|
||||
return { id, env: { trigger } };
|
||||
function invocation(id: string, trigger: EventTrigger): IGameEventInvocation {
|
||||
const env: IBlockEventEnv = {
|
||||
state: {} as IDataCommon,
|
||||
type: BlockEventType.CommonEvent,
|
||||
trigger,
|
||||
heroLocator: { x: 0, y: 0 },
|
||||
triggerLocator: null,
|
||||
tile: null,
|
||||
layer: null,
|
||||
map: null
|
||||
};
|
||||
return { id, env };
|
||||
}
|
||||
|
||||
describe('source-aware matching dispatch', () => {
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import { logger } from '@motajs/common';
|
||||
import { IBlockEventParam, IGameEventInvocation } from '@user/data-base';
|
||||
import {
|
||||
IBlockEventEnv,
|
||||
IBlockEventParam,
|
||||
IGameEventInvocation
|
||||
} from '@user/data-base';
|
||||
import { IGameEventStore } from '@user/data-common';
|
||||
import { AnonTokyoInterpreter } from 'anon-tokyo';
|
||||
import { EventExecuteMode, EventReduceMode, IGameEventExecutor } from './types';
|
||||
|
||||
Loading…
Reference in New Issue
Block a user