mirror of
https://github.com/motajs/template.git
synced 2026-09-12 09:30:19 +08:00
feat(03-07): wire serialized event loading boundary
- Register validated serialized events through the CoreState load seam - Bind raw map event ids with MapState.fromRaw before replay execution
This commit is contained in:
parent
8f3f5cad7d
commit
a111b8dcd4
@ -21,7 +21,8 @@ import {
|
||||
ItemStore,
|
||||
IMapStore,
|
||||
MapStore,
|
||||
IReplaySystem
|
||||
IReplaySystem,
|
||||
IMapRawData
|
||||
} from '@user/data-common';
|
||||
import {
|
||||
EnemyManager,
|
||||
@ -70,8 +71,11 @@ import {
|
||||
} from './shared';
|
||||
import {
|
||||
createLegacyDependencies,
|
||||
ILegacyLoadData
|
||||
ILegacyLoadData,
|
||||
ILegacySerializedLoadData,
|
||||
LOAD_SERIALIZED_DATA
|
||||
} from './legacy/dependencies';
|
||||
import { registerSerializedEvents } from './legacy/events';
|
||||
import { ILoadProgressTotal, LoadProgressTotal } from '@motajs/loader';
|
||||
import { isNil } from 'lodash-es';
|
||||
import { DirectionMapper, IDirectionMapper, logger } from '@motajs/common';
|
||||
@ -163,7 +167,6 @@ export class CoreState implements ICoreState {
|
||||
const eventStore = new GameEventStore();
|
||||
this.eventStore = eventStore;
|
||||
this.directionMapper = new DirectionMapper();
|
||||
// TODO: 后续在此初始化路径注册外部序列化事件定义与地图事件 id 绑定。
|
||||
|
||||
//#endregion
|
||||
|
||||
@ -261,7 +264,21 @@ export class CoreState implements ICoreState {
|
||||
this.initTileStore(data.tiles);
|
||||
this.initItemStore(data.items);
|
||||
this.initEnemyManager(data.enemies);
|
||||
this.initMapState(data.floors, data.maps);
|
||||
if (data.serialized) {
|
||||
this[LOAD_SERIALIZED_DATA](data.serialized);
|
||||
} else {
|
||||
this.initMapState(data.floors, data.maps);
|
||||
}
|
||||
}
|
||||
|
||||
/** 经内部加载边界注册序列化事件并绑定原始地图事件 id */
|
||||
[LOAD_SERIALIZED_DATA](data: ILegacySerializedLoadData): void {
|
||||
registerSerializedEvents(
|
||||
this.eventStore,
|
||||
this.eventSystem.executor.interpreter,
|
||||
data.events
|
||||
);
|
||||
this.initRawMapState(data.maps);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -421,6 +438,20 @@ export class CoreState implements ICoreState {
|
||||
this.maps.compareWith(reference);
|
||||
}
|
||||
|
||||
private initRawMapState(data: readonly IMapRawData[]): void {
|
||||
const reference = new Map<string, Map<number, Uint32Array>>();
|
||||
for (const raw of data) {
|
||||
const state = this.maps.fromRaw(raw);
|
||||
if (!state) continue;
|
||||
const ref = new Map<number, Uint32Array>();
|
||||
for (const [zIndex, map] of Object.entries(raw.map)) {
|
||||
ref.set(Number(zIndex), new Uint32Array(map));
|
||||
}
|
||||
reference.set(raw.floorId, ref);
|
||||
}
|
||||
this.maps.compareWith(reference);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 存档方法
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
IEnemyAttr,
|
||||
ISaveSystem,
|
||||
ITileLegacyConverter,
|
||||
IMapRawData,
|
||||
MemorySaveSystem,
|
||||
SaveSystem
|
||||
} from '@user/data-common';
|
||||
@ -12,6 +13,16 @@ import { IStateSystem } from '@user/data-system';
|
||||
import { EnemyLegacyBridge } from '../enemy/legacy';
|
||||
import { ItemLegacyBridge, LegacyItemData } from './item';
|
||||
import { LegacyTileData, TileLegacyBridge } from './tile';
|
||||
import { ISerializedEventDefinitions } from './events';
|
||||
|
||||
/** CoreState 内部显式数据加载所需的序列化事件与原始地图 */
|
||||
export interface ILegacySerializedLoadData {
|
||||
readonly events: ISerializedEventDefinitions;
|
||||
readonly maps: readonly IMapRawData[];
|
||||
}
|
||||
|
||||
/** 仅供 CoreState 与 legacy 数据源之间使用的加载方法标识 */
|
||||
export const LOAD_SERIALIZED_DATA = Symbol('loadSerializedData');
|
||||
|
||||
export interface ILegacyLoadData {
|
||||
readonly tiles: typeof core.maps.blocksInfo;
|
||||
@ -19,6 +30,7 @@ export interface ILegacyLoadData {
|
||||
readonly enemies: Record<EnemyIds, Enemy>;
|
||||
readonly floors: FloorIds[];
|
||||
readonly maps: Record<FloorIds, ResolvedFloor>;
|
||||
readonly serialized?: ILegacySerializedLoadData;
|
||||
}
|
||||
|
||||
export interface ILegacyDependencies {
|
||||
|
||||
64
packages-user/data-state/src/legacy/events.ts
Normal file
64
packages-user/data-state/src/legacy/events.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { EventTrigger, GameEvent, IGameEventStore } from '@user/data-common';
|
||||
import { AnonTokyoInterpreter, Statement } from 'anon-tokyo';
|
||||
|
||||
/** 旧样板内部加载边界使用的序列化事件定义 */
|
||||
export interface ISerializedEventData {
|
||||
readonly trigger: EventTrigger;
|
||||
readonly rawEvent: Statement[];
|
||||
}
|
||||
|
||||
/** 事件 id 到序列化事件定义的映射 */
|
||||
export interface ISerializedEventDefinitions {
|
||||
readonly [id: string]: ISerializedEventData;
|
||||
}
|
||||
|
||||
interface IRuntimeStatement {
|
||||
readonly type?: unknown;
|
||||
}
|
||||
|
||||
function isStatement(value: unknown): value is Statement {
|
||||
if (!value || typeof value !== 'object') return false;
|
||||
const statement = value as IRuntimeStatement;
|
||||
return (
|
||||
typeof statement.type === 'number' &&
|
||||
Number.isInteger(statement.type) &&
|
||||
statement.type >= 0 &&
|
||||
statement.type <= 10
|
||||
);
|
||||
}
|
||||
|
||||
function isEventTrigger(value: unknown): value is EventTrigger {
|
||||
return (
|
||||
typeof value === 'number' &&
|
||||
Number.isInteger(value) &&
|
||||
value >= EventTrigger.None &&
|
||||
value <= EventTrigger.OnAfterChangeFloor
|
||||
);
|
||||
}
|
||||
|
||||
function isSerializedEventData(value: unknown): value is ISerializedEventData {
|
||||
if (!value || typeof value !== 'object') return false;
|
||||
const data = value as ISerializedEventData;
|
||||
return isEventTrigger(data.trigger) && Array.isArray(data.rawEvent)
|
||||
? data.rawEvent.every(isStatement)
|
||||
: false;
|
||||
}
|
||||
|
||||
/** 将内部序列化事件定义转换为带有统一解释器的游戏事件实例 */
|
||||
export function registerSerializedEvents(
|
||||
store: IGameEventStore,
|
||||
interpreter: AnonTokyoInterpreter,
|
||||
definitions: ISerializedEventDefinitions
|
||||
): void {
|
||||
if (!definitions || typeof definitions !== 'object') return;
|
||||
for (const [id, data] of Object.entries(definitions)) {
|
||||
if (!id || !isSerializedEventData(data)) continue;
|
||||
const event = new GameEvent<
|
||||
Record<string, any>,
|
||||
Record<string, any>,
|
||||
any
|
||||
>(interpreter, data.rawEvent);
|
||||
event.setTrigger(data.trigger);
|
||||
store.addEvent(id, event);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user