feat(event): complete phase one event system

This commit is contained in:
AncTe committed 2026-09-09 12:01:21 +08:00
1 parent b9213ddf22
commit a297311ea6
51 files changed
+3261 -1114

No files matched your search

@@ -0,0 +1,54 @@
import {
AnonTokyoInterpreter,
AnonTokyoExecutable,
Statement
} from 'anon-tokyo';
import { EventTrigger, IGameEvent } from './types';
export class GameEvent<
P extends Record<string, any>,
E extends Record<string, any>,
R = void
> implements IGameEvent<P, E, R> {
trigger: EventTrigger = EventTrigger.None;
rawEvent: Statement[];
compiled: AnonTokyoExecutable | null = null;
constructor(
readonly interpreter: AnonTokyoInterpreter,
raw: Statement[]
) {
this.rawEvent = raw;
}
compile(): AnonTokyoExecutable | null {
this.compiled = this.interpreter.compile(this.rawEvent);
return this.compiled;
}
execute(param: P, env: Record<string, any>): Promise<R> {
if (this.compiled) {
return this.compiled.exec(param, env) as Promise<R>;
} else {
const compiled = this.compile();
if (compiled) {
return compiled.exec(param, env) as Promise<R>;
} else {
return this.interpreter.exec(
this.rawEvent,
param,
env
) as Promise<R>;
}
}
}
setRaw(raw: Statement[]): void {
this.rawEvent = raw;
this.compiled = null;
}
setTrigger(trigger: EventTrigger): void {
this.trigger = trigger;
}
}
@@ -0,0 +1,2 @@
export * from './event';
export * from './types';
@@ -0,0 +1,74 @@
import {
AnonTokyoExecutable,
AnonTokyoInterpreter,
Statement
} from 'anon-tokyo';
export const enum EventTrigger {
/** 无触发器,事件需要手动执行 */
None,
/** 当玩家触碰指定图块时触发,如果直接走入则不触发 */
OnTouch,
/** 当玩家进入指定图块时触发 */
OnEnter,
/** 当玩家离开指定图块时触发 */
OnLeave,
/** 当玩家与指定怪物战斗前触发,返回值表示是否与怪物战斗 */
OnBeforeBattle,
/** 当玩家与指定怪物战斗后触发 */
OnAfterBattle,
/** 当玩家开启指定门之前触发,返回值表示是否能够成功开启门 */
OnBeforeOpenDoor,
/** 当玩家开启指定门之后触发 */
OnAfterOpenDoor,
/** 当玩家成功拾取指定道具时触发 */
OnAfterGetItem,
/** 当玩家使用指定位置或图块触发楼层切换前触发,返回值表示是否执行切换操作 */
OnBeforeChangeFloor,
/** 当玩家使用指定位置或图块触发楼层切换后触发 */
OnAfterChangeFloor
}
export interface IReadonlyGameEvent<
P extends Record<string, any>,
E extends Record<string, any>,
R = void
> {
/** 事件解释器 */
readonly interpreter: AnonTokyoInterpreter;
/** 事件触发器类型,由什么触发器触发 */
readonly trigger: EventTrigger;
/** 原始事件数据 */
readonly rawEvent: Statement[];
/** 已编译事件数据,可直接执行 */
readonly compiled: AnonTokyoExecutable | null;
/**
* 编译此事件
*/
compile(): AnonTokyoExecutable | null;
/**
* 执行此游戏事件
* @param param 事件参数
*/
execute(param: P, env: E): Promise<R>;
}
export interface IGameEvent<
P extends Record<string, any>,
E extends Record<string, any>,
R = void
> extends IReadonlyGameEvent<P, E, R> {
/**
* 设置此事件的触发器
* @param trigger 触发器类型
*/
setTrigger(trigger: EventTrigger): void;
/**
* 设置事件的原始数据
* @param raw 事件原始数据
*/
setRaw(raw: Statement[]): void;
}
+1
View File
@@ -1,4 +1,5 @@
export * from './common';
export * from './event';
export * from './replay';
export * from './save';
export * from './store';
@@ -0,0 +1,28 @@
import { logger } from '@motajs/common';
import { IReadonlyGameEvent } from '../event';
import { IGameEventStore } from './types';
export class GameEventStore implements IGameEventStore {
private readonly store: Map<
string,
IReadonlyGameEvent<Record<string, any>, Record<string, any>, any>
> = new Map();
addEvent(
id: string,
event: IReadonlyGameEvent<Record<string, any>, Record<string, any>, any>
): void {
if (this.store.has(id)) {
logger.warn(170, id);
}
this.store.set(id, event);
}
getEvent<
P extends Record<string, any>,
E extends Record<string, any>,
R = void
>(id: string): IReadonlyGameEvent<P, E, R> | null {
return this.store.get(id) ?? null;
}
}
@@ -1,3 +1,5 @@
export * from './eventStore';
export * from './itemStore';
export * from './mapStore';
export * from './tileStore';
export * from './types';
+36 -14
View File
@@ -1,6 +1,7 @@
//#region tile
import { IFacedTileLocator } from '@motajs/common';
import { IReadonlyGameEvent } from '../event';
//#region tile
export const enum TileType {
/** 未知或尚未归类的图块 */
@@ -48,8 +49,8 @@ export interface ITileRawData {
readonly num: number;
/** 图块字符串 id */
readonly id: string;
/** 默认触发器类型 */
readonly trigger: number;
/** 默认事件,键表示优先级,值表示事件 id */
readonly events: Record<number, string>;
/** 图块逻辑类型 */
readonly type: TileType;
/** 图块的通行性对象 */
@@ -81,7 +82,7 @@ export interface ITileStore<TLegacy = unknown> {
* 获取指定图块数字对应的默认触发器类型
* @param num 图块数字
*/
getTrigger(num: number): number;
getTrigger(num: number): number[];
/**
* 获取指定图块数字对应的图块类型
@@ -296,13 +297,6 @@ export interface IChangeFloorData {
readonly relatedPos?: ChangeFloorPos;
}
export interface IMapBlockRawData {
/** 此点的静态触发器类型(仅对该点生效,不会跟随任何图块移动) */
readonly trigger?: number;
/** 楼层切换信息 */
readonly changeFloor?: IChangeFloorData;
}
export interface IMapRawData {
/** 楼层 id */
readonly floorId: string;
@@ -312,8 +306,8 @@ export interface IMapRawData {
readonly map: Record<number, number[]>;
/** 每个地图图层的字符串别名 */
readonly layerAlias: Record<number, string>;
/** 每个地图图层中,指定位置图块的额外数据,外层 key 为图层 zIndex,内层 key 为图块位置索引 */
readonly blockData: Record<number, Record<number, IMapBlockRawData>>;
/** 每个地图图层中,指定位置图块的事件数据,外层键为图层纵深,中层键为图块位置索引,内层键为事件优先级 */
readonly events: Record<number, Record<number, Record<number, string>>>;
}
export interface IMapStore {
@@ -331,3 +325,31 @@ export interface IMapStore {
}
//#endregion
//#region event
export interface IGameEventStore {
/**
* 添加事件实例
* @param id 事件 id
* @param event 事件内容
*/
addEvent(
id: string,
event: IReadonlyGameEvent<Record<string, any>, Record<string, any>, any>
): void;
/**
* 根据事件 id 获取事件实例
* @param id 事件 id
*/
getEvent<
P extends Record<string, any>,
E extends Record<string, any>,
R = void
>(
id: string
): IReadonlyGameEvent<P, E, R> | null;
}
//#endregion
+3 -1
View File
@@ -1,6 +1,6 @@
import { ITileLocator } from '@motajs/common';
import { IFaceManager, IRoleFaceBinder } from './common';
import { IItemStore, IMapStore, ITileStore } from './store';
import { IGameEventStore, IItemStore, IMapStore, ITileStore } from './store';
import { ISaveSystem } from './save';
export interface IEnemyAttr {
@@ -50,6 +50,8 @@ export interface IDataCommon {
readonly itemStore: IItemStore<IHeroAttr, Item<AllIdsOf<'items'>>>;
/** 地图定义存储 */
readonly mapStore: IMapStore;
/** 游戏事件存储 */
readonly eventStore: IGameEventStore;
/** 朝向绑定 */
readonly roleFace: IRoleFaceBinder;
/** 朝向管理 */