mirror of
https://github.com/motajs/template.git
synced 2026-11-01 22:24:31 +08:00
feat(event): complete phase one event system
This commit is contained in:
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,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';
|
||||
@@ -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
|
||||
@@ -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;
|
||||
/** 朝向管理 */
|
||||
|
||||
Reference in new issue
Block a user