From 03dc5ea60bce44d8d889223bb83698517e5dc6bc Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Sun, 17 May 2026 22:56:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A7=A6=E5=8F=91=E5=99=A8=E6=94=B6?= =?UTF-8?q?=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages-user/data-state/src/core.ts | 90 ++++++++------ .../data-system/src/trigger/collection.ts | 2 +- .../data-system/src/trigger/collector.ts | 112 ++++++++++++++++++ .../data-system/src/trigger/index.ts | 3 +- packages-user/data-system/src/types.ts | 5 + packages/common/src/logger.json | 6 +- 6 files changed, 176 insertions(+), 42 deletions(-) create mode 100644 packages-user/data-system/src/trigger/collector.ts diff --git a/packages-user/data-state/src/core.ts b/packages-user/data-state/src/core.ts index 0bba55c..6d497d2 100644 --- a/packages-user/data-state/src/core.ts +++ b/packages-user/data-state/src/core.ts @@ -33,7 +33,11 @@ import { DamageSystem, EnemyContext, IEnemyContext, - MapDamage + ITriggerCollector, + ITriggerRegistry, + MapDamage, + TriggerCollector, + TriggerRegistry } from '@user/data-system'; import { CommonAuraConverter, @@ -78,6 +82,8 @@ export class CoreState implements ICoreState { // Layer 2 内容 readonly enemyContext: IEnemyContext; + readonly triggerRegistry: ITriggerRegistry; + readonly triggerCollector: ITriggerCollector; // 用户层内容 readonly loadProgress: ILoadProgressTotal; @@ -95,26 +101,43 @@ export class CoreState implements ICoreState { > = new Map(); constructor() { + //#region L0 初始化 + + // 朝向 + this.roleFace = new RoleFaceBinder(); + this.faceManager = new FaceManager(); + const dir4 = new Dir4FaceHandler(); + const dir8 = new Dir8FaceHandler(); + this.faceManager.register(FaceGroup.Dir4, dir4); + this.faceManager.registerById('dir4', dir4); + this.faceManager.register(FaceGroup.Dir8, dir8); + this.faceManager.registerById('dir8', dir8); + + // 图块 const tileStore = new TileStore(); tileStore.attachLegacyConverter(new TileLegacyBridge()); this.tileStore = tileStore; + + //#endregion + + //#region L1 初始化 + + // Flag 系统 + this.flags = new FlagSystem(); + + // 地图 this.maps = new MapStore(tileStore, this); - this.loadProgress = new LoadProgressTotal(); - this.dataLoader = new MotaDataLoader(this.loadProgress); - - //#region 勇士初始化 - + // 勇士 const heroMover = new HeroMover(); const heroAttribute = new HeroAttribute(HERO_DEFAULT_ATTRIBUTE); const heroState = new HeroState(heroMover, heroAttribute); this.hero = heroState; - //#endregion + this.loadProgress = new LoadProgressTotal(); + this.dataLoader = new MotaDataLoader(this.loadProgress); - //#region 怪物初始化 - - // 怪物管理器初始化 + // 怪物管理器 const comparer = new MainEnemyComparer(); const enemyManager = new EnemyManager(new EnemyLegacyBridge()); enemyManager.attachEnemyComparer(comparer); @@ -126,7 +149,12 @@ export class CoreState implements ICoreState { enemyManager.setAttributeDefaults('point', 0); registerSpecials(enemyManager); this.enemyManager = enemyManager; - // 怪物上下文初始化 + + //#endregion + + //#region L2 初始化 + + // 怪物上下文 const enemyContext = new EnemyContext(this); const damageSystem = new DamageSystem(enemyContext); const mapDamage = new MapDamage(enemyContext); @@ -142,10 +170,18 @@ export class CoreState implements ICoreState { enemyContext.bindHero(heroAttribute); this.enemyContext = enemyContext; + // 触发器注册与收集器 + const triggerRegistry = new TriggerRegistry(); + const triggerCollector = new TriggerCollector(); + triggerCollector.attachRegistry(triggerRegistry); + this.triggerRegistry = triggerRegistry; + this.triggerCollector = triggerCollector; + //#endregion - //#region 存档系统 + //#region 顶层初始化 + // 存档系统 this.saveSystem = new SaveSystem(); // 配置存档系统,一般情况下不建议动,除非你知道你在干什么 this.saveSystem.config({ @@ -155,29 +191,16 @@ export class CoreState implements ICoreState { saveTimeTolerance: 100, autosaveStackSize: 20 }); - + this.addSaveableContent('@system/hero', this.hero); + this.addSaveableContent('@system/flags', this.flags); + this.addSaveableContent('@system/maps', this.maps); + this.addSaveableContent('@system/enemy', this.enemyManager); // 初始化存档数据库,不要动 loading.once('coreInit', () => { this.saveSystem.init(`@game/${core.firstData.name}`); }); - //#endregion - - //#region 其他初始化 - - // 朝向 - this.roleFace = new RoleFaceBinder(); - this.faceManager = new FaceManager(); - const dir4 = new Dir4FaceHandler(); - const dir8 = new Dir8FaceHandler(); - this.faceManager.register(FaceGroup.Dir4, dir4); - this.faceManager.registerById('dir4', dir4); - this.faceManager.register(FaceGroup.Dir8, dir8); - this.faceManager.registerById('dir8', dir8); - - this.flags = new FlagSystem(); - - // 加载先使用兼容层实现 + // 加载初始化,先使用兼容层实现 loading.once('loaded', () => { this.initTileStore(core.maps.blocksInfo); this.initEnemyManager(enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80); @@ -186,13 +209,6 @@ export class CoreState implements ICoreState { core.floors as Record ); }); - - this.addSaveableContent('@system/hero', this.hero); - this.addSaveableContent('@system/flags', this.flags); - this.addSaveableContent('@system/maps', this.maps); - this.addSaveableContent('@system/enemy', this.enemyManager); - - //#endregion } /** diff --git a/packages-user/data-system/src/trigger/collection.ts b/packages-user/data-system/src/trigger/collection.ts index e76f69a..590e753 100644 --- a/packages-user/data-system/src/trigger/collection.ts +++ b/packages-user/data-system/src/trigger/collection.ts @@ -5,7 +5,7 @@ export class TriggerCollection implements ITriggerCollection { private readonly triggerList: ITrigger[]; constructor(triggers: Iterable) { - this.triggerList = Array.from(triggers); + this.triggerList = [...triggers]; } count(): number { diff --git a/packages-user/data-system/src/trigger/collector.ts b/packages-user/data-system/src/trigger/collector.ts new file mode 100644 index 0000000..94b13e6 --- /dev/null +++ b/packages-user/data-system/src/trigger/collector.ts @@ -0,0 +1,112 @@ +import { IMapLayer } from '@user/data-base'; +import { + ITrigger, + ITriggerCollection, + ITriggerCollector, + ITriggerRegistry +} from './types'; +import { logger } from '@motajs/common'; +import { TriggerCollection } from './collection'; + +export class TriggerCollector implements ITriggerCollector { + /** 当前收集器使用的注册对象 */ + private registry: ITriggerRegistry | null = null; + + collect(x: number, y: number, layer: IMapLayer): ITriggerCollection { + if (!this.registry) { + logger.warn(135); + return new TriggerCollection([]); + } + const staticType = layer.getTriggerType(x, y); + const staticTrigger = this.registry.create(staticType); + const dynamics = [...layer.dynamicLayer.getDynamicTilesAt(x, y)]; + + if (dynamics.length === 0) { + // 没有动态图块 + if (staticTrigger) { + return new TriggerCollection([staticTrigger]); + } else { + return new TriggerCollection([]); + } + } else if (dynamics.length === 1) { + // 一个动态图块,只需要进行一次额外判断即可 + const dynamic = dynamics[0]; + const dynamicTrigger = this.registry.create(dynamic.triggerType); + // 直接穷举所有可能情况 + if (!staticTrigger && !dynamicTrigger) { + return new TriggerCollection([]); + } else if (staticTrigger && !dynamicTrigger) { + return new TriggerCollection([staticTrigger]); + } else if (!staticTrigger && dynamicTrigger) { + return new TriggerCollection([dynamicTrigger]); + } else { + // 静态动态都有,则需要额外判断优先级,动态图层在前,因此包含等号 + if (dynamicTrigger!.priority >= staticTrigger!.priority) { + const arr = [dynamicTrigger!, staticTrigger!]; + return new TriggerCollection(arr); + } else { + const arr = [staticTrigger!, dynamicTrigger!]; + return new TriggerCollection(arr); + } + } + } else { + // 动态图块大于两个,使用通用方案,记录重复触发器并抛出警告 + const usedPriority = new Set(); + const duplicate = new Set(); + if (staticTrigger) { + // 有静态触发器 + const lessTriggers: ITrigger[] = []; + const greaterTriggers: ITrigger[] = []; + // 先收集所有的触发器,并记录重复情况 + for (const tile of layer.dynamicLayer.getDynamicTilesAt(x, y)) { + const trigger = this.registry.create(tile.triggerType); + if (trigger) { + if (usedPriority.has(trigger.priority)) { + duplicate.add(trigger.priority); + } + usedPriority.add(trigger.priority); + + // 同优先级下动态在前,因此包含等号 + if (trigger.priority >= staticTrigger.priority) { + greaterTriggers.push(trigger); + } else { + lessTriggers.push(trigger); + } + } + } + if (duplicate.size > 0) { + logger.warn(136, [...duplicate].join(',')); + } + const arr = [ + ...greaterTriggers.sort((a, b) => b.priority - a.priority), + staticTrigger, + ...lessTriggers.sort((a, b) => b.priority - a.priority) + ]; + return new TriggerCollection(arr); + } else { + // 没有静态触发器 + const triggers: ITrigger[] = []; + for (const tile of layer.dynamicLayer.getDynamicTilesAt(x, y)) { + const trigger = this.registry.create(tile.triggerType); + if (trigger) { + if (usedPriority.has(trigger.priority)) { + duplicate.add(trigger.priority); + } + usedPriority.add(trigger.priority); + triggers.push(trigger); + } + } + if (duplicate.size > 0) { + logger.warn(136, [...duplicate].join(',')); + } + return new TriggerCollection( + triggers.sort((a, b) => b.priority - a.priority) + ); + } + } + } + + attachRegistry(registry: ITriggerRegistry | null): void { + this.registry = registry; + } +} diff --git a/packages-user/data-system/src/trigger/index.ts b/packages-user/data-system/src/trigger/index.ts index 02077b8..c5307a9 100644 --- a/packages-user/data-system/src/trigger/index.ts +++ b/packages-user/data-system/src/trigger/index.ts @@ -1,3 +1,4 @@ -export * from './types'; export * from './collection'; +export * from './collector'; export * from './registry'; +export * from './types'; diff --git a/packages-user/data-system/src/types.ts b/packages-user/data-system/src/types.ts index f08ee0b..7160a98 100644 --- a/packages-user/data-system/src/types.ts +++ b/packages-user/data-system/src/types.ts @@ -1,9 +1,14 @@ import { IStateBase } from '@user/data-base'; import { IEnemyContext } from './combat'; +import { ITriggerCollector, ITriggerRegistry } from './trigger'; export interface IStateSystem extends IStateBase { /** 怪物上下文 */ readonly enemyContext: IEnemyContext; + /** 触发器注册 */ + readonly triggerRegistry: ITriggerRegistry; + /** 触发器收集器 */ + readonly triggerCollector: ITriggerCollector; } export interface IStateSystemExtended { diff --git a/packages/common/src/logger.json b/packages/common/src/logger.json index 731b04c..520470b 100644 --- a/packages/common/src/logger.json +++ b/packages/common/src/logger.json @@ -55,8 +55,7 @@ "53": "Expected serializable value set as enemy's default attribute.", "54": "Legacy '$1' API has been removed, consider using new APIs: '$2'.", "55": "Cannot load MapStore state: reference data (compareWith) has not been set.", - "56": "Cannot convert legacy tile data since no tile legacy converter is attached to TileStore.", - "1201": "Floor-damage extension needs 'floor-binder' extension as dependency." + "56": "Cannot convert legacy tile data since no tile legacy converter is attached to TileStore." }, "warn": { "1": "Resource with type of 'none' is loaded.", @@ -193,6 +192,7 @@ "132": "Trigger registry entry of $1 '$2' already exists, new factory will override old factory.", "133": "TileStore.addTile: tile number $1 already exists (id: '$2'), old tile data will be overridden.", "134": "TileStore.addTile: tile id '$1' already maps to number $2, old tile data will be overridden.", - "1001": "Item-detail extension needs 'floor-binder' and 'floor-damage' extension as dependency." + "135": "Expected a trigger registry attched before collect triggers.", + "136": "Unexpected duplicate trigger priority $1, which may cause trigger executed in an unexpected order." } }