diff --git a/packages-user/client-modules/src/action/move.ts b/packages-user/client-modules/src/action/move.ts index f539be5..976bd94 100644 --- a/packages-user/client-modules/src/action/move.ts +++ b/packages-user/client-modules/src/action/move.ts @@ -1,5 +1,6 @@ import { KeyCode } from '@motajs/client-base'; import { Hotkey, HotkeyData } from '@motajs/system'; +// @ts-expect-error 需要重构 import { HeroMover, IMoveController } from '@user/data-state'; import { Ticker } from 'mutate-animate'; import { mainScope } from './hotkey'; diff --git a/packages-user/client-modules/src/render/ui/main.tsx b/packages-user/client-modules/src/render/ui/main.tsx index 4d6e392..571320a 100644 --- a/packages-user/client-modules/src/render/ui/main.tsx +++ b/packages-user/client-modules/src/render/ui/main.tsx @@ -25,6 +25,7 @@ import { RightStatusBar } from './statusBar'; import { ReplayingStatus } from './toolbar'; +// @ts-expect-error 需要重构 import { getHeroStatusOn, state } from '@user/data-state'; import { hook } from '@user/data-base'; import { mainUIController } from './controller'; diff --git a/packages-user/data-base/src/hero/equipment.test.ts b/packages-user/data-base/src/hero/equipment.test.ts index 144a2f7..06dad0c 100644 --- a/packages-user/data-base/src/hero/equipment.test.ts +++ b/packages-user/data-base/src/hero/equipment.test.ts @@ -145,7 +145,7 @@ function createItem( /** 构造一个装配勇士装备对象的测试环境 */ function createEnv(): TestEnv { const tileStore = new TileStore(); - const itemStore = new ItemStore(); + const itemStore = new ItemStore(); // 录像系统桩,用于满足装备/卸下时的 route.add 记录与临时禁用录像 const replaySystem = createReplaySystem(); const state = { tileStore, itemStore, replaySystem } as never; diff --git a/packages-user/data-base/src/hero/items.test.ts b/packages-user/data-base/src/hero/items.test.ts index 60e77ff..580d22d 100644 --- a/packages-user/data-base/src/hero/items.test.ts +++ b/packages-user/data-base/src/hero/items.test.ts @@ -57,7 +57,7 @@ interface ItemFixture { /** 构造一个装配勇士道具对象的测试环境 */ function createEnv(): TestEnv { const tileStore = new TileStore(); - const itemStore = new ItemStore(); + const itemStore = new ItemStore(); // 录像系统桩,仅用于满足道具使用时的 route.add 记录 const replaySystem = { route: { add: vi.fn() } }; const state = { tileStore, itemStore, replaySystem } as never; diff --git a/packages-user/data-base/src/hero/saveLoad.test.ts b/packages-user/data-base/src/hero/saveLoad.test.ts index 6c3160f..3cca927 100644 --- a/packages-user/data-base/src/hero/saveLoad.test.ts +++ b/packages-user/data-base/src/hero/saveLoad.test.ts @@ -74,7 +74,7 @@ interface EquipEnv { /** 极E��一个含图块、E��具存储与假录像系统的公共层假对象 */ function createState(): IDataCommon { const tileStore = new TileStore(); - const itemStore = new ItemStore(); + const itemStore = new ItemStore(); const route = { add: vi.fn() }; return { tileStore, diff --git a/packages-user/data-common/src/store/itemStore.ts b/packages-user/data-common/src/store/itemStore.ts index 0a53cb2..312bd22 100644 --- a/packages-user/data-common/src/store/itemStore.ts +++ b/packages-user/data-common/src/store/itemStore.ts @@ -1,18 +1,9 @@ -import { logger } from '@motajs/common'; -import { - IItemLegacyConverter, - IItemRawData, - IItemStore, - ItemCategory -} from './types'; +import { IItemRawData, IItemStore, ItemCategory } from './types'; -export class ItemStore implements IItemStore { +export class ItemStore implements IItemStore { /** 以道具图块数字为键的原始道具定义表 */ private readonly dataMap: Map> = new Map(); - /** 当前挂载的旧样板道具转换器 */ - private converter: IItemLegacyConverter | null = null; - getData(num: number): IItemRawData | null { return this.dataMap.get(num) ?? null; } @@ -24,21 +15,4 @@ export class ItemStore implements IItemStore { addItem(data: IItemRawData): void { this.dataMap.set(data.num, data); } - - attachLegacyConverter( - converter: IItemLegacyConverter - ): void { - this.converter = converter; - } - - fromLegacy(num: number, legacy: TLegacy): IItemRawData { - const converter = this.converter; - if (!converter) { - logger.error(57); - throw new Error('Expected a item legacy converter.'); - } - const data = converter.fromLegacy(num, legacy); - this.addItem(data); - return data; - } } diff --git a/packages-user/data-common/src/store/tileStore.ts b/packages-user/data-common/src/store/tileStore.ts index 66fc24e..915dc9d 100644 --- a/packages-user/data-common/src/store/tileStore.ts +++ b/packages-user/data-common/src/store/tileStore.ts @@ -1,13 +1,8 @@ import { isNil } from 'lodash-es'; import { logger } from '@motajs/common'; -import { - ITileLegacyConverter, - ITileRawData, - ITileStore, - TileType -} from './types'; +import { ITileRawData, ITileStore, TileType } from './types'; -export class TileStore implements ITileStore { +export class TileStore implements ITileStore { /** 以图块数字为键的原始图块定义表 */ private readonly dataMap: Map = new Map(); @@ -20,9 +15,6 @@ export class TileStore implements ITileStore { /** 由图块数字保存的默认事件映射 */ private readonly eventMap: Map> = new Map(); - /** 当前挂载的旧样板图块转换器 */ - private legacyConverter: ITileLegacyConverter | null = null; - getData(num: number): ITileRawData | null { return this.dataMap.get(num) ?? null; } @@ -83,21 +75,6 @@ export class TileStore implements ITileStore { } } - attachLegacyConverter(converter: ITileLegacyConverter): void { - this.legacyConverter = converter; - } - - fromLegacy(num: number, legacy: TLegacy): ITileRawData { - const converter = this.legacyConverter; - if (!converter) { - logger.error(56); - throw new Error('Expected a tile legacy converter.'); - } - const data = converter.fromLegacy(num, legacy); - this.addTile(data); - return data; - } - /** 删除一组旧的图块定义及其双向索引 */ private deleteBy(num: number, id: string): void { this.dataMap.delete(num); diff --git a/packages-user/data-common/src/store/types.ts b/packages-user/data-common/src/store/types.ts index 8d530fc..b40c9a6 100644 --- a/packages-user/data-common/src/store/types.ts +++ b/packages-user/data-common/src/store/types.ts @@ -62,16 +62,7 @@ export interface ITileRawData { readonly eventPass: boolean; } -export interface ITileLegacyConverter { - /** - * 将旧样板图块定义转换为新的图块原始数据 - * @param num 图块数字 - * @param legacy 旧样板图块定义 - */ - fromLegacy(num: number, legacy: TLegacy): ITileRawData; -} - -export interface ITileStore { +export interface ITileStore { /** * 获取指定图块数字对应的完整原始定义 * @param num 图块数字 @@ -119,19 +110,6 @@ export interface ITileStore { * @param token 图块数字或 id */ id(token: number | string): string | undefined; - - /** - * 挂载一个旧样板转换器 - * @param converter 旧样板转换器 - */ - attachLegacyConverter(converter: ITileLegacyConverter): void; - - /** - * 使用当前转换器转换并写入一个旧样板图块定义 - * @param num 图块数字 - * @param legacy 旧样板图块定义 - */ - fromLegacy(num: number, legacy: TLegacy): ITileRawData; } //#endregion @@ -208,16 +186,7 @@ export interface IItemRawData { readonly equip: IItemEquipData; } -export interface IItemLegacyConverter { - /** - * 将旧样板道具定义转换为新的道具原始数据 - * @param num 道具图块数字 - * @param legacy 旧样板道具定义 - */ - fromLegacy(num: number, legacy: TLegacy): IItemRawData; -} - -export interface IItemStore { +export interface IItemStore { /** * 获取指定图块数字对应的道具原始数据 * @param num 道具图块数字 @@ -235,21 +204,6 @@ export interface IItemStore { * @param data 道具原始数据 */ addItem(data: IItemRawData): void; - - /** - * 挂载一个旧样板转换器 - * @param converter 旧样板转换器 - */ - attachLegacyConverter( - converter: IItemLegacyConverter - ): void; - - /** - * 使用当前转换器转换并写入一个旧样板道具定义 - * @param num 道具图块数字 - * @param legacy 旧样板道具定义 - */ - fromLegacy(num: number, legacy: TLegacy): IItemRawData; } //#endregion diff --git a/packages-user/data-common/src/types.ts b/packages-user/data-common/src/types.ts index 42bf066..e31b975 100644 --- a/packages-user/data-common/src/types.ts +++ b/packages-user/data-common/src/types.ts @@ -45,9 +45,9 @@ export interface IHeroAttr { export interface IDataCommon { /** 图块定义存储 */ - readonly tileStore: ITileStore>; + readonly tileStore: ITileStore; /** 道具定义存储 */ - readonly itemStore: IItemStore>>; + readonly itemStore: IItemStore; /** 地图定义存储 */ readonly mapStore: IMapStore; /** 游戏事件存储 */ diff --git a/packages-user/data-state/src/core.ts b/packages-user/data-state/src/core.ts index 7d95d8b..c4df8bb 100644 --- a/packages-user/data-state/src/core.ts +++ b/packages-user/data-state/src/core.ts @@ -35,8 +35,6 @@ import { FlagSystem, IMotaDataLoader, MotaDataLoader, - loading, - IReadonlyEnemy, IMapState, MapState } from '@user/data-base'; @@ -62,23 +60,7 @@ import { registerSpecials, MainEnemyComparer } from './enemy'; -import { - BG2_ZINDEX, - BG_ZINDEX, - EVENT_ZINDEX, - FG2_ZINDEX, - FG_ZINDEX, - HERO_DEFAULT_ATTRIBUTE, - TILE_HEIGHT, - TILE_WIDTH -} from './shared'; -import { - ItemLegacyBridge, - LegacyItemData, - LegacyTileData, - TileLegacyBridge -} from './legacy'; -import { isNil } from 'lodash-es'; +import { HERO_DEFAULT_ATTRIBUTE, TILE_HEIGHT, TILE_WIDTH } from './shared'; import { DefaultHeroMoveTopImpl, DefaultPassPredicateImpl } from './hero'; import { createEventRegistrations } from './event/registrations'; import { @@ -93,8 +75,8 @@ export class CoreState implements ICoreState { // Layer 0 公共层,最底层的接口,不会依赖任何其他内容,一般是工具性接口及不需要存档的数据 readonly roleFace: IRoleFaceBinder; readonly faceManager: IFaceManager; - readonly tileStore: ITileStore; - readonly itemStore: IItemStore; + readonly tileStore: ITileStore; + readonly itemStore: IItemStore; readonly mapStore: IMapStore; readonly eventStore: IGameEventStore; readonly directionMapper: IDirectionMapper; @@ -139,19 +121,13 @@ export class CoreState implements ICoreState { this.faceManager.registerById('dir8', dir8); // 图块 - const tileStore = new TileStore(); - tileStore.attachLegacyConverter(new TileLegacyBridge()); - this.tileStore = tileStore; + this.tileStore = new TileStore(); // 道具 - const itemStore = new ItemStore(); - itemStore.attachLegacyConverter(new ItemLegacyBridge(this)); - this.itemStore = itemStore; + this.itemStore = new ItemStore(); // 地图 - const mapStore = new MapStore(); - this.mapStore = mapStore; + this.mapStore = new MapStore(); // 游戏事件 - const eventStore = new GameEventStore(); - this.eventStore = eventStore; + this.eventStore = new GameEventStore(); this.directionMapper = new DirectionMapper(); //#endregion @@ -162,7 +138,7 @@ export class CoreState implements ICoreState { this.flags = new FlagSystem(); // 地图 - this.maps = new MapState(tileStore, this); + this.maps = new MapState(this.tileStore, this); // 勇士 const heroAttribute = new HeroAttribute(HERO_DEFAULT_ATTRIBUTE); @@ -237,17 +213,6 @@ export class CoreState implements ICoreState { this.addSaveableContent('@system/enemy', this.enemyManager); this.addSaveableContent('@system/replay', this.replaySystem); - // 加载初始化,先使用兼容层实现 - loading.once('loaded', () => { - this.initTileStore(core.maps.blocksInfo); - this.initItemStore(core.items.items); - this.initEnemyManager(enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80); - this.initMapState( - core.floorIds, - core.floors as Record - ); - }); - // 勇士顶层初始化 const heroMoveTopImpl = new DefaultHeroMoveTopImpl(this); this.hero.location.mover.useTopImplementation(heroMoveTopImpl); @@ -285,168 +250,6 @@ export class CoreState implements ICoreState { replay.registerCommand(ReplayCode.Unequip, unequip); } - /** - * 初始化图块存储对象 - * @param data 旧样板图块定义对象 - */ - private initTileStore(data: typeof core.maps.blocksInfo) { - const entries = Object.entries(data); - for (const [key, block] of entries) { - this.tileStore.fromLegacy(Number(key), block); - } - - for (const [key, block] of entries) { - if (!block.faceIds) continue; - const { down, up, left, right } = block.faceIds; - const downNum = this.tileStore.idToNumber(down); - if (downNum !== Number(key)) continue; - const upNum = this.tileStore.idToNumber(up); - const leftNum = this.tileStore.idToNumber(left); - const rightNum = this.tileStore.idToNumber(right); - this.roleFace.malloc(downNum, FaceDirection.Down); - if (!isNil(upNum)) { - this.roleFace.bind(upNum, downNum, FaceDirection.Up); - } - if (!isNil(leftNum)) { - this.roleFace.bind(leftNum, downNum, FaceDirection.Left); - } - if (!isNil(rightNum)) { - this.roleFace.bind(rightNum, downNum, FaceDirection.Right); - } - } - } - - /** - * 初始化道具存储对象 - * @param data 旧样板道具定义对象 - */ - private initItemStore(data: typeof core.items.items) { - const entries = Object.entries(data); - for (const [id, legacy] of entries) { - const num = this.tileStore.idToNumber(id); - if (isNil(num)) { - logger.warn(145, id); - continue; - } - this.itemStore.fromLegacy(num, legacy); - } - } - - /** - * 初始化怪物管理器对象 - * @param data 旧样板怪物存储对象 - */ - private initEnemyManager(data: Record) { - const manager = this.enemyManager; - const reference = new Map>(); - for (const [id, enemy] of Object.entries(structuredClone(data))) { - const num = this.tileStore.idToNumber(id); - if (isNil(num)) continue; - if (enemy.faceIds) { - // 有 faceId 的要把其他的也映射到当前怪物 - const { left, up, right, down } = enemy.faceIds; - const leftCode = this.tileStore.idToNumber(left)!; - const upCode = this.tileStore.idToNumber(up)!; - const rightCode = this.tileStore.idToNumber(right)!; - const downCode = this.tileStore.idToNumber(down)!; - const prefab = manager.fromLegacyEnemy(downCode, enemy); - reference.set(downCode, prefab); - manager.addPrefab(prefab); - this.roleFace.malloc(downCode, FaceDirection.Down); - this.roleFace.bind(leftCode, downCode, FaceDirection.Left); - this.roleFace.bind(upCode, downCode, FaceDirection.Up); - this.roleFace.bind(rightCode, downCode, FaceDirection.Down); - manager.reusePrefab(num, leftCode, left); - manager.reusePrefab(num, upCode, up); - manager.reusePrefab(num, rightCode, right); - } else { - const prefab = manager.fromLegacyEnemy(num, enemy); - reference.set(num, prefab); - manager.addPrefab(prefab); - } - } - manager.compareWith(reference); - } - - /** - * 初始化地图状态 - * @param floors 楼层列表 - * @param data 每个楼层对应的旧版地图信息 - */ - private initMapState( - floors: FloorIds[], - data: Record - ) { - const reference = new Map>(); - for (const id of floors) { - const floor = data[id]; - const state = this.maps.createMap(id, floor.width, floor.height); - const bg = state.addLayer(); - const bg2 = state.addLayer(); - const event = state.addLayer(); - const fg = state.addLayer(); - const fg2 = state.addLayer(); - bg.setZIndex(BG_ZINDEX); - bg2.setZIndex(BG2_ZINDEX); - event.setZIndex(EVENT_ZINDEX); - fg.setZIndex(FG_ZINDEX); - fg2.setZIndex(FG2_ZINDEX); - state.setLayerAlias(bg, 'bg'); - state.setLayerAlias(bg2, 'bg2'); - state.setLayerAlias(event, 'event'); - state.setEventLayer(event); - state.setLayerAlias(fg, 'fg'); - state.setLayerAlias(fg2, 'fg2'); - state.setActiveStatus(false); - - const size = floor.width * floor.height; - const ref = new Map(); - - if (floor.bgmap && floor.bgmap.length > 0) { - const arr = new Uint32Array(floor.bgmap.flat()); - bg.setMapRef(arr); - ref.set(BG_ZINDEX, new Uint32Array(arr)); - } else { - ref.set(BG_ZINDEX, new Uint32Array(size)); - } - - if (floor.bg2map && floor.bg2map.length > 0) { - const arr = new Uint32Array(floor.bg2map.flat()); - bg2.setMapRef(arr); - ref.set(BG2_ZINDEX, new Uint32Array(arr)); - } else { - ref.set(BG2_ZINDEX, new Uint32Array(size)); - } - - if (floor.map && floor.map.length > 0) { - const arr = new Uint32Array(floor.map.flat()); - event.setMapRef(arr); - ref.set(EVENT_ZINDEX, new Uint32Array(arr)); - } else { - ref.set(EVENT_ZINDEX, new Uint32Array(size)); - } - - if (floor.fgmap && floor.fgmap.length > 0) { - const arr = new Uint32Array(floor.fgmap.flat()); - fg.setMapRef(arr); - ref.set(FG_ZINDEX, new Uint32Array(arr)); - } else { - ref.set(FG_ZINDEX, new Uint32Array(size)); - } - - if (floor.fg2map && floor.fg2map.length > 0) { - const arr = new Uint32Array(floor.fg2map.flat()); - fg2.setMapRef(arr); - ref.set(FG2_ZINDEX, new Uint32Array(arr)); - } else { - ref.set(FG2_ZINDEX, new Uint32Array(size)); - } - - reference.set(id, ref); - } - this.maps.compareWith(reference); - } - //#endregion //#region 存档方法 diff --git a/packages-user/data-state/src/enemy/special.ts b/packages-user/data-state/src/enemy/special.ts index f477e4c..6cedd69 100644 --- a/packages-user/data-state/src/enemy/special.ts +++ b/packages-user/data-state/src/enemy/special.ts @@ -3,7 +3,6 @@ import { defineNonePropertySpecial, IEnemyManager } from '@user/data-base'; -import { getHeroStatusOn } from '../legacy/hero'; import { IEnemyAttr } from '@user/data-common'; //#region 复合属性值类型 @@ -176,6 +175,7 @@ export function registerSpecials(manager: IEnemyManager): void { const { vampire, add } = special.value; return ( `战斗前,怪物首先吸取角色的${vampire}%生命` + + // @ts-expect-error 需要重构 `(约${Math.floor((vampire / 100) * getHeroStatusOn('hp'))}点)作为伤害` + (add ? `,并把伤害数值加到自身生命上。` : `。`) ); diff --git a/packages-user/data-state/src/index.ts b/packages-user/data-state/src/index.ts index 5fcda61..eb2c5f6 100644 --- a/packages-user/data-state/src/index.ts +++ b/packages-user/data-state/src/index.ts @@ -1,7 +1,6 @@ export * from './enemy'; export * from './event'; export * from './hero'; -export * from './legacy'; export * from './replay'; export * from './core'; diff --git a/packages-user/data-state/src/legacy/hero.ts b/packages-user/data-state/src/legacy/hero.ts deleted file mode 100644 index b238993..0000000 --- a/packages-user/data-state/src/legacy/hero.ts +++ /dev/null @@ -1,115 +0,0 @@ -/** - * 获取勇士在某一点的属性 - * @param name 要获取的勇士属性 - * @param floorId 勇士所在楼层 - */ -export function getHeroStatusOn(name: 'all', floorId?: FloorIds): HeroStatus; -export function getHeroStatusOn( - name: (keyof HeroStatus)[], - floorId?: FloorIds -): Partial; -export function getHeroStatusOn( - name: K, - floorId?: FloorIds -): HeroStatus[K]; -export function getHeroStatusOn( - name: keyof HeroStatus | 'all' | (keyof HeroStatus)[], - floorId?: FloorIds -) { - // @ts-expect-error 暂时无法推导 - return getHeroStatusOf(core.status.hero, name, floorId); -} - -/** - * 获取一定状态下的勇士在某一点的属性 - * @param status 勇士的状态 - * @param name 要获取的勇士属性 - * @param floorId 勇士所在楼层 - */ -export function getHeroStatusOf( - status: Partial, - name: 'all', - floorId?: FloorIds -): HeroStatus; -export function getHeroStatusOf( - status: Partial, - name: (keyof HeroStatus)[], - floorId?: FloorIds -): Partial; -export function getHeroStatusOf( - status: Partial, - name: K, - floorId?: FloorIds -): HeroStatus[K]; -export function getHeroStatusOf( - status: DeepPartial, - name: keyof HeroStatus | 'all' | (keyof HeroStatus)[], - floorId?: FloorIds -) { - return getRealStatus(status, name, floorId); -} - -function getRealStatus( - status: DeepPartial, - name: keyof HeroStatus | 'all' | (keyof HeroStatus)[], - floorId: FloorIds = core.status.floorId -): any { - if (name instanceof Array) { - const res: any = {}; - name.forEach(v => { - res[v] = getRealStatus(status, v, floorId); - }); - return res; - } - - if (name === 'all') { - const res: any = {}; - for (const [key, value] of Object.entries(core.status.hero)) { - if (typeof value === 'number') { - res[key] = getRealStatus( - status, - key as keyof HeroStatus, - floorId - ); - } else { - res[key] = value; - } - } - - return res; - } - - let s = (status[name] ?? core.status.hero[name]) as number; - if (s === null || s === void 0) { - throw new ReferenceError( - `Wrong hero status property name is delivered: ${name}` - ); - } - - if (typeof s !== 'number') return s; - - // buff - s *= core.status.hero.buff[name] ?? 1; - s = Math.floor(s); - - // 衰弱效果 - if ((name === 'atk' || name === 'def') && flags.weak) { - const weak = core.values.weakValue; - if (weak < 1) { - // 百分比衰弱 - s *= 1 - weak; - } else { - s -= weak; - } - } - - return s; -} - -// 下面的内容暂时无用 - -export interface IHeroStatusDefault { - atk: number; - def: number; - hp: number; -} diff --git a/packages-user/data-state/src/legacy/index.ts b/packages-user/data-state/src/legacy/index.ts deleted file mode 100644 index 548eb20..0000000 --- a/packages-user/data-state/src/legacy/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './hero'; -export * from './interface'; -export * from './item'; -export * from './move'; -export * from './tile'; -export * from './utils'; diff --git a/packages-user/data-state/src/legacy/interface.ts b/packages-user/data-state/src/legacy/interface.ts deleted file mode 100644 index 2c9b741..0000000 --- a/packages-user/data-state/src/legacy/interface.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface IStateDamageable { - /** 生命值 */ - hp: number; -} diff --git a/packages-user/data-state/src/legacy/item.ts b/packages-user/data-state/src/legacy/item.ts deleted file mode 100644 index ef98299..0000000 --- a/packages-user/data-state/src/legacy/item.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { - IHeroAttr, - IItemEffect, - IItemEquipData, - IItemLegacyConverter, - IItemRawData, - ItemCategory -} from '@user/data-common'; -import { IStateSystem } from '@user/data-system'; - -export type LegacyItemData = Item>; - -type LegacyItemEffectFn = ( - state: IStateSystem, - item: IItemRawData -) => void; -type LegacyItemCanUseFn = ( - state: IStateSystem, - item: IItemRawData -) => boolean; - -class LegacyItemEffect implements IItemEffect { - pickEvent: unknown; - useEvent: unknown; - - /** 道具使用效果 */ - private readonly useFn: LegacyItemEffectFn | null = null; - /** 是否能够使用道具 */ - private readonly canUseFn: LegacyItemCanUseFn | null = null; - /** 全局状态对象 */ - private readonly state: IStateSystem; - - constructor(legacy: LegacyItemData, state: IStateSystem) { - this.state = state; - this.pickEvent = undefined; - this.useEvent = legacy.useItemEvent; - - if (legacy.cls === 'items') { - if (legacy.itemEffect) { - this.useFn = new Function( - 'state', - 'item', - legacy.itemEffect - ) as LegacyItemEffectFn; - } - } else if (legacy.cls === 'constants' || legacy.cls === 'tools') { - if (legacy.useItemEffect) { - this.useFn = new Function( - 'state', - 'item', - legacy.useItemEffect - ) as LegacyItemEffectFn; - } - if (typeof legacy.canUseItemEffect === 'string') { - this.canUseFn = new Function( - 'state', - 'item', - legacy.canUseItemEffect - ) as LegacyItemCanUseFn; - } else { - this.canUseFn = () => !!legacy.canUseItemEffect; - } - } - } - - useEffect(item: IItemRawData): void { - this.useFn?.(this.state, item); - } - - canUse(item: IItemRawData): boolean { - if (!this.canUseFn) return true; - else return this.canUseFn(this.state, item); - } -} - -export class ItemLegacyBridge implements IItemLegacyConverter< - IHeroAttr, - LegacyItemData -> { - constructor(private readonly state: IStateSystem) {} - - fromLegacy(num: number, legacy: LegacyItemData): IItemRawData { - const effect = new LegacyItemEffect(legacy, this.state); - return { - num, - id: legacy.id, - category: this.mapCategory(legacy.cls), - name: legacy.name, - text: legacy.text ?? '', - hideInToolbox: legacy.hideInToolBox, - effect, - equip: this.convertEquip(legacy.equip) - }; - } - - /** - * 将旧样板装备信息转换为新样板接口 - * @param legacy 旧样板格式的装备信息 - */ - private convertEquip(legacy: Equip): IItemEquipData { - const valueMap = new Map, number>(); - const perMap = new Map, number>(); - - for (const [key, value] of Object.entries(legacy.value)) { - valueMap.set(key as SelectKey, value); - } - for (const [key, value] of Object.entries(legacy.percentage)) { - perMap.set(key as SelectKey, value); - } - - return { - slots: [legacy.type], - animate: legacy.animate, - value: valueMap, - percentage: perMap, - loadEvent: legacy.equipEvent, - unloadEvent: legacy.unequipEvent - }; - } - - /** - * 从旧样板道具类型获取新接口对应的类型 - * @param cls 旧样板道具类型 - */ - private mapCategory(cls: ItemCls): ItemCategory { - switch (cls) { - case 'constants': - return ItemCategory.Constant; - case 'tools': - return ItemCategory.Consumable; - case 'equips': - return ItemCategory.Equipment; - case 'items': - return ItemCategory.Pick; - default: - return ItemCategory.Unknown; - } - } -} diff --git a/packages-user/data-state/src/legacy/move.ts b/packages-user/data-state/src/legacy/move.ts deleted file mode 100644 index d1beadc..0000000 --- a/packages-user/data-state/src/legacy/move.ts +++ /dev/null @@ -1,523 +0,0 @@ -import EventEmitter from 'eventemitter3'; -import { backDir, toDir } from './utils'; -import { loading } from '@user/data-base'; -import type { HeroKeyMover } from '@user/client-modules'; -import { sleep } from '@motajs/common'; -import { fromDirectionString } from '@user/data-common'; - -function getDataStateMover() { - if (typeof Mota === 'undefined') return null; - return Mota.require('@user/data-state').state.hero.location.mover; -} - -// todo: 转身功能 - -interface MoveStepDir { - type: 'dir'; - value: Move2; -} - -interface MoveStepSpeed { - type: 'speed'; - value: number; -} - -export type MoveStep = MoveStepDir | MoveStepSpeed; - -export interface IMoveController { - /** 本次移动是否完成 */ - done: boolean; - /** 当前移动队列 */ - queue: MoveStep[]; - /** 当本次移动完成时兑现 */ - onEnd: Promise; - - /** - * 停止本次移动,停止后将不再能继续移动 - */ - stop(): Promise; - - /** - * 向队列末尾添加移动信息 - * @param step 移动信息 - */ - push(...step: MoveStep[]): void; -} - -interface EObjectMovingEvent { - stepEnd: [step: MoveStep]; - moveEnd: []; - moveStart: [queue: MoveStep[]]; -} - -export abstract class ObjectMoverBase extends EventEmitter { - /** 移动队列 */ - private moveQueue: MoveStep[] = []; - - /** 当前的移动速度 */ - moveSpeed: number = 100; - /** 当前的移动方向 */ - moveDir: Dir2 = 'down'; - /** 当前是否正在移动 */ - moving: boolean = false; - /** 面朝方向 */ - faceDir: Dir2 = 'down'; - - /** 当前的控制对象 */ - controller?: IMoveController; - - /** - * 当本次移动开始时执行的函数 - * @param controller 本次移动的控制对象 - */ - protected abstract onMoveStart(controller: IMoveController): Promise; - - /** - * 当本次移动结束时执行的函数 - * @param controller 本次移动的控制对象 - */ - protected abstract onMoveEnd(controller: IMoveController): Promise; - - /** - * 当这一步开始移动时执行的函数,可以用来播放移动动画等 - * @param step 这一步的移动信息 - * @param controller 本次移动的控制对象 - * @returns 一个Promise,其值表示本次移动的代码,并将其值传入这一步移动后的操作,即{@link onStepEnd} - */ - protected abstract onStepStart( - step: MoveStepDir, - controller: IMoveController - ): Promise; - - /** - * 当这一步移动结束后执行的函数(即{@link onStepStart}成功兑现后),可以用于设置物体坐标等 - * @param step 这一步的移动信息 - * @param code 本步移动的代码,即onMoveStart的返回值 - * @param controller 本次移动的控制对象 - * @returns 一个Promise,当其兑现时,本步移动全部完成,将会开始下一步的移动 - */ - protected abstract onStepEnd( - step: MoveStepDir, - code: number, - controller: IMoveController - ): Promise; - - /** - * 当移动速度被设置时执行的函数 - * @param speed 设置为的移动速度 - * @param controller 本次移动的控制对象 - */ - protected abstract onSetMoveSpeed( - speed: number, - controller: IMoveController - ): void; - - private getMoveDir(move: Move2): Dir2 { - if (move === 'forward') return this.moveDir; - if (move === 'backward') return backDir(this.faceDir); - return move; - } - - private getFaceDir(move: Move2): Dir2 { - if (move === 'forward' || move === 'backward') return this.faceDir; - return move; - } - - /** - * 设置当前面朝方向,移动中设置无效 - * @param dir 面朝方向 - */ - setFaceDir(dir: Dir2) { - if (!this.moving) this.faceDir = dir; - } - - /** - * 设置当前移动方向,移动中设置无效 - * @param dir 移动方向 - */ - setMoveDir(dir: Dir2) { - if (!this.moving) this.moveDir = dir; - } - - /** - * 开始移动,这个操作后,本次移动将不能通过{@link insertMove}添加移动步骤, - * 只能通过{@link IMoveController.push}添加,而通过前者添加的移动步骤会在下次移动生效 - */ - startMove(): IMoveController | null { - if (this.moving) return null; - const queue = this.moveQueue.slice(); - this.clearMoveQueue(); - - this.moving = true; - let stopMove = false; - - const start = async () => { - // 等待宏任务执行完成,不然controller会在首次调用中未定义 - await new Promise(res => res()); - await this.onMoveStart(controller); - this.emit('moveStart', queue); - while (queue.length > 0) { - if (stopMove || !this.moving) break; - const step = queue.shift(); - if (!step) break; - if (step.type === 'dir') { - this.moveDir = this.getMoveDir(step.value); - this.faceDir = this.getFaceDir(step.value); - const code = await this.onStepStart(step, controller); - await this.onStepEnd(step, code, controller); - } else { - const speed = step.value; - this.moveSpeed = speed; - this.onSetMoveSpeed(speed, controller); - } - this.emit('stepEnd', step); - } - this.moving = false; - this.emit('moveEnd'); - - await this.onMoveEnd(controller); - }; - - const onEnd = start().then(() => { - this.controller = void 0; - controller.done = true; - }); - const controller: IMoveController = { - done: false, - onEnd, - queue, - push(...step) { - queue.push(...step); - }, - stop() { - stopMove = true; - return onEnd; - } - }; - this.controller = controller; - - return controller; - } - - /** - * 向移动队列末尾插入移动实例 - * @param move 移动实例 - */ - insertMove(...move: MoveStep[]) { - this.moveQueue.push(...move); - } - - /** - * 清空移动队列 - */ - clearMoveQueue() { - this.moveQueue = []; - } - - /** - * 向移动队列末尾插入一个移动操作 - * @param step 移动方向 - */ - oneStep(step: Move2) { - this.moveQueue.push({ type: 'dir', value: step }); - } - - /** - * 按照传入的数组移动物体,插入至移动队列末尾 - * @param steps 移动步骤 - */ - moveAs(steps: MoveStep[]) { - this.moveQueue.push(...steps); - } -} - -// todo: refactor - -interface CanMoveStatus { - /** 由CannotIn和CannotOut计算出的信息,不可移动时不会触发触发器 */ - canMove: boolean; - /** 由图块的noPass计算出的信息,不可移动时会触发触发器 */ - noPass: boolean; -} - -const enum HeroMoveCode { - Step, - Stop, - /** 不能移动,并撞击前面一格的图块,触发其触发器 */ - Hit, - /** 不能移动,同时当前格有CannotOut,或目标格有CannotIn,不会触发前面一格的触发器 */ - CannotMove -} - -export class HeroMover extends ObjectMoverBase { - /** 当前移动是否忽略地形 */ - private ignoreTerrain: boolean = false; - /** 当前移动是否不计入录像 */ - private noRoute: boolean = false; - /** 当前移动是否是在lockControl条件下开始的 */ - private inLockControl: boolean = false; - /** 是否会在特殊时刻进行自动存档 */ - private autoSave: boolean = false; - - /** 本次移动开始时的移动速度 */ - private beforeMoveSpeed: number = 100; - - override startMove( - ignoreTerrain: boolean = false, - noRoute: boolean = false, - inLockControl: boolean = false, - autoSave: boolean = false - ): IMoveController | null { - if (this.moving) return null; - this.ignoreTerrain = ignoreTerrain; - this.noRoute = noRoute; - this.inLockControl = inLockControl; - this.autoSave = autoSave; - return super.startMove(); - } - - private checkAutoSave(_x: number, _y: number, _nx: number, _ny: number) { - // const index = `${x},${y}`; - // const nIndex = `${nx},${ny}`; - // const map = core.status.thisMap.enemy.mapDamage; - // const dam = map[index]; - // const nextDam = map[nIndex]; - // if (!dam || !nextDam) return; - // 可以在这里判断地图伤害,并进行自动存档,例如在进入或离开地图伤害时存档 - // if (dam.damage > 0 || nextDam.damage > 0) { - // core.autosave() - // } - } - - protected async onMoveStart(controller: IMoveController): Promise { - this.beforeMoveSpeed = this.moveSpeed; - if (!core.isReplaying() || core.status.replay.speed <= 12) { - getDataStateMover()?.start(); - } - // 这里要检查前面那一格能不能走,不能走则不触发平滑视角,以避免撞墙上视角卡住 - if (!this.ignoreTerrain) { - const { x, y } = core.status.hero.loc; - const firstDir = controller.queue.find( - v => v.type === 'dir' - )?.value; - if (firstDir && firstDir !== 'backward' && firstDir !== 'forward') { - const data = this.checkCanMove(x, y, toDir(firstDir as Dir)); - if (data.canMove && !data.noPass) { - // viewport.sync('startMove'); - } - } - } else { - // viewport.sync('startMove'); - } - } - - protected async onMoveEnd(controller: IMoveController): Promise { - this.moveSpeed = this.beforeMoveSpeed; - this.onSetMoveSpeed(this.moveSpeed, controller); - // viewport.sync('endMove'); - core.clearContinueAutomaticRoute(); - core.stopAutomaticRoute(); - } - - protected async onStepStart( - _step: MoveStepDir, - controller: IMoveController - ): Promise { - const showDir = toDir(this.faceDir); - const dir4Move = toDir(this.moveDir); - core.setHeroLoc('direction', showDir); - - const { x, y } = core.status.hero.loc; - const { x: nx, y: ny } = this.nextLoc(x, y, this.moveDir); - - if (this.autoSave && !this.ignoreTerrain) { - this.checkAutoSave(x, y, nx, ny); - } - - if (!this.inLockControl && core.status.lockControl) { - controller.stop(); - return HeroMoveCode.Stop; - } - - if (!this.ignoreTerrain || !this.noRoute) { - this.moveDir = dir4Move; - } - - const dir = this.moveDir; - if (!this.ignoreTerrain) { - const { noPass, canMove } = this.checkCanMove(x, y, dir4Move); - - if (!canMove) { - return HeroMoveCode.CannotMove; - } - // 不能移动 - if (noPass) { - return HeroMoveCode.Hit; - } - } - - // 可以移动,显示移动动画 - - await this.moveAnimate(nx, ny, showDir, dir); - - return HeroMoveCode.Step; - } - - protected async onStepEnd( - _step: MoveStepDir, - code: HeroMoveCode, - controller: IMoveController - ): Promise { - const { x, y } = core.status.hero.loc; - const { x: nx, y: ny } = this.nextLoc(x, y, this.moveDir); - const showDir = toDir(this.faceDir); - - // 前方不能移动 - if (code === HeroMoveCode.CannotMove || code === HeroMoveCode.Hit) { - controller.stop(); - this.onCannotMove(showDir); - if (code === HeroMoveCode.Hit) { - core.trigger(nx, ny); - } - core.checkRouteFolding(); - return; - } - - // 本次移动停止 - if (code === HeroMoveCode.Stop) { - core.clearContinueAutomaticRoute(); - core.stopAutomaticRoute(); - controller.stop(); - return; - } - - // 本次移动正常完成 - if (code === HeroMoveCode.Step) { - core.setHeroLoc('x', nx, true); - core.setHeroLoc('y', ny, true); - - if (!this.ignoreTerrain) { - const direction = core.getHeroLoc('direction'); - core.control._moveAction_popAutomaticRoute(); - if (!this.noRoute) core.status.route.push(direction); - - // 中毒处理 - if (core.hasFlag('poison')) { - core.status.hero.hp -= core.values.poisonDamage; - if (core.status.hero.hp <= 0) { - core.status.hero.hp = 0; - core.events.lose(); - } - core.updateStatusBar(); - } - - core.moveOneStep(); - core.checkRouteFolding(); - } - } - } - - protected onSetMoveSpeed( - speed: number, - _controller: IMoveController - ): void { - this.moveSpeed = speed; - } - - /** - * 移动动画 - * @param x 目标横坐标 - * @param y 目标纵坐标 - * @param _showDir 显示方向 - * @param moveDir 移动方向 - */ - private async moveAnimate( - x: number, - y: number, - _showDir: Dir, - moveDir: Dir2 - ) { - // const viewport = HeroMover.viewport; - // if (!viewport) return; - const replay = core.status.replay.speed; - const speed = replay === 24 ? 1 : this.moveSpeed / replay; - // viewport.all('moveTo', x, y, speed * 1.6); - const replaying = core.isReplaying(); - if (replaying) { - if (core.status.replay.speed > 12) { - await sleep(speed); - getDataStateMover()?.setPos(x, y); - } else { - const mover = getDataStateMover(); - mover?.step(fromDirectionString(moveDir)); - await mover?.start()?.onEnd; - } - } else { - const mover = getDataStateMover(); - mover?.step(fromDirectionString(moveDir)); - await mover?.start()?.onEnd; - } - } - - /** - * 当前方一格不能走时,执行的函数 - * @param dir 移动方向 - */ - private onCannotMove(dir: Dir) { - if (!this.noRoute) core.status.route.push(dir); - core.status.automaticRoute.moveStepBeforeStop = []; - core.status.automaticRoute.lastDirection = dir; - - if (core.status.automaticRoute.moveStepBeforeStop.length === 0) { - core.clearContinueAutomaticRoute(); - core.stopAutomaticRoute(); - } - } - - /** - * 检查前方是否可以移动 - * @param x 当前横坐标 - * @param y 当前纵坐标 - * @param dir 移动方向 - */ - private checkCanMove(x: number, y: number, dir: Dir): CanMoveStatus { - // 如果是循环式地图 - const { x: nx, y: ny } = this.nextLoc(x, y, dir); - const noPass = core.noPass(nx, ny); - const canMove = core.canMoveHero(x, y, dir); - return { noPass, canMove }; - } - - /** - * 获取前方一格的坐标 - * @param x 当前横坐标 - * @param y 当前纵坐标 - * @param dir 移动方向 - */ - private nextLoc(x: number, y: number, dir: Dir2): Loc { - const { x: dx, y: dy } = core.utils.scan2[dir]; - const nx = x + dx; - const ny = y + dy; - return { x: nx, y: ny }; - } -} - -interface HeroMoveCollection { - mover: HeroMover; - keyMover?: HeroKeyMover; -} - -// 初始化基础勇士移动实例 -const heroMover = new HeroMover(); -export const heroMoveCollection: HeroMoveCollection = { - mover: heroMover -}; -loading.once('coreInit', () => { - // 注册按键操作 - Mota.r(() => { - const { HeroKeyMover } = Mota.require('@user/client-modules'); - const { gameKey } = Mota.require('@motajs/system'); - const keyMover = new HeroKeyMover(gameKey, heroMover); - heroMoveCollection.keyMover = keyMover; - }); -}); diff --git a/packages-user/data-state/src/legacy/tile.ts b/packages-user/data-state/src/legacy/tile.ts deleted file mode 100644 index 3f9d61f..0000000 --- a/packages-user/data-state/src/legacy/tile.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { - ITileLegacyConverter, - ITilePassData, - ITileRawData, - PassBit, - TileType -} from '@user/data-common'; - -interface ILegacyTileEventData { - /** 旧样板图块携带的默认事件映射 */ - readonly events?: Record; -} - -export type LegacyTileData = MapDataOf & ILegacyTileEventData; - -export class TileLegacyBridge implements ITileLegacyConverter { - private getTileType(num: number, legacy: LegacyTileData): TileType { - if (num === 0) return TileType.None; - switch (legacy.cls) { - case 'terrains': - return TileType.Terrain; - case 'autotile': - return TileType.Autotile; - case 'animates': - return TileType.Animate; - case 'items': - return TileType.Item; - case 'enemys': - case 'enemy48': - return TileType.Enemy; - case 'npcs': - case 'npc48': - return TileType.Npc; - // @ts-expect-error 动态类型声明导致的错误,忽略即可 - case 'tileset': - return TileType.Tileset; - default: - return TileType.Unknown; - } - } - - private getPass(num: number, legacy: LegacyTileData): ITilePassData { - if (num === 0) { - // 空图块 - return { - onlyEvents: true, - inPass: 0b1111, - outPass: 0b1111 - }; - } else if (num === 17) { - // 空气墙 - return { - onlyEvents: false, - inPass: 0b0000, - outPass: 0b0000 - }; - } else { - // 正常图块 - if (legacy.cannotIn && legacy.cannotOut) { - let inPass = 0b1111; - let outPass = 0b1111; - if (legacy.cannotIn.includes('up')) { - inPass &= ~PassBit.Up; - } - if (legacy.cannotIn.includes('right')) { - inPass &= ~PassBit.Right; - } - if (legacy.cannotIn.includes('down')) { - inPass &= ~PassBit.Down; - } - if (legacy.cannotIn.includes('left')) { - inPass &= ~PassBit.Left; - } - if (legacy.cannotOut.includes('up')) { - outPass &= ~PassBit.Up; - } - if (legacy.cannotOut.includes('right')) { - outPass &= ~PassBit.Right; - } - if (legacy.cannotOut.includes('down')) { - outPass &= ~PassBit.Down; - } - if (legacy.cannotOut.includes('left')) { - outPass &= ~PassBit.Left; - } - return { - onlyEvents: false, - inPass, - outPass - }; - } else { - return { - onlyEvents: true, - inPass: 0b1111, - outPass: 0b1111 - }; - } - } - } - - /** 将旧样板事件输入复制为新的默认事件对象 */ - private getEvents(legacy: LegacyTileData): Record { - const events: Record = {}; - for (const [priority, event] of Object.entries(legacy.events ?? {})) { - const priorityNum = Number(priority); - if (Number.isInteger(priorityNum) && typeof event === 'string') { - events[priorityNum] = event; - } - } - return events; - } - - fromLegacy(num: number, legacy: LegacyTileData): ITileRawData { - return { - num, - id: legacy.id, - events: this.getEvents(legacy), - type: this.getTileType(num, legacy), - pass: this.getPass(num, legacy), - eventPass: !legacy.noPass - }; - } -} diff --git a/packages-user/data-state/src/legacy/utils.ts b/packages-user/data-state/src/legacy/utils.ts deleted file mode 100644 index e2ce87b..0000000 --- a/packages-user/data-state/src/legacy/utils.ts +++ /dev/null @@ -1,107 +0,0 @@ -const dirMap: Record = { - down: 'down', - left: 'left', - leftdown: 'left', - leftup: 'left', - right: 'right', - rightdown: 'right', - rightup: 'right', - up: 'up' -}; - -/** - * 将八方向转换为四方向,一般用于斜角移动时的方向显示 - * @param dir 八方向 - */ -export function toDir(dir: Dir2): Dir { - return dirMap[dir]; -} - -const backDirMap: Record = { - up: 'down', - down: 'up', - left: 'right', - right: 'left', - leftup: 'rightdown', - rightup: 'leftdown', - leftdown: 'rightup', - rightdown: 'leftup' -}; - -export function backDir(dir: Dir): Dir; -export function backDir(dir: Dir2): Dir2; -export function backDir(dir: Dir2): Dir2 { - return backDirMap[dir]; -} - -export function locInMap(x: number, y: number, floorId: FloorIds) { - const { width, height } = core.status.maps[floorId]; - return x >= 0 && y >= 0 && x < width && y < height; -} - -/** - * 广义检查能否移动,指定两个点以及行走方向,返回能否执行上述移动。 - * 可以传入地图之外的点,视为可以随意移动。仅检查 cannotIn 和 cannotOut,不检查 noPass - * @param fx 出点横坐标 - * @param fy 出点纵坐标 - * @param tx 入点横坐标 - * @param ty 入点纵坐标 - * @param dir 行走方向 - * @param fromFloorId 出点楼层id - * @param toFloorId 入点楼层id - */ -export function checkCanMoveExtended( - fx: number, - fy: number, - tx: number, - ty: number, - dir: Dir, - fromFloorId: FloorIds = core.status.floorId, - toFloorId: FloorIds = core.status.floorId -) { - const fromInMap = locInMap(fx, fy, fromFloorId); - const toInMap = locInMap(tx, ty, toFloorId); - const map = maps_90f36752_8815_4be8_b32b_d7fad1d0542e; - - if (fromInMap) { - const cannotMove = core.floors[fromFloorId].cannotMove; - const fromIndex: LocString = `${fx},${fy}`; - // 检查当前点是否有不可出 - if (cannotMove[fromIndex]?.includes(dir)) return false; - const blocks = getBlockForLoc(fx, fy, fromFloorId); - const can = blocks.some(v => { - if (v === 0) return false; - const out = map[v as Exclude]?.cannotOut; - return out?.includes(dir); - }); - if (can) return false; - } - if (toInMap) { - const cannotMoveIn = core.floors[toFloorId].cannotMoveIn; - const toIndex: LocString = `${tx},${ty}`; - const back = backDir(dir); - // 检查目标点是否有不可入 - if (cannotMoveIn[toIndex]?.includes(back)) return false; - const blocks = getBlockForLoc(tx, ty, toFloorId); - const can = blocks.some(v => { - if (v === 0) return false; - const out = map[v as Exclude]?.cannotIn; - return out?.includes(back); - }); - if (can) return false; - } - - return true; -} - -function getBlockForLoc(x: number, y: number, floorId: FloorIds) { - const map = core.status.maps[floorId]; - const floor = core.floors[floorId]; - return [ - floor.bgmap[y][x], - floor.bg2map[y][x], - map.map[y][x], - floor.bgmap[y][x], - floor.bg2map[y][x] - ]; -} diff --git a/packages-user/data-state/test/tileLegacy.test.ts b/packages-user/data-state/test/tileLegacy.test.ts deleted file mode 100644 index 0d301bb..0000000 --- a/packages-user/data-state/test/tileLegacy.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { TileStore } from '@user/data-common'; -import { LegacyTileData, TileLegacyBridge } from '../src/legacy/tile'; - -describe('TileLegacyBridge events-map contract', () => { - // 验证旧样板事件对象会转换为 TileStore 可消费的默认事件映射 - it('converts legacy events into the TileStore event map', () => { - const bridge = new TileLegacyBridge(); - const store = new TileStore(); - store.attachLegacyConverter(bridge); - const legacy: LegacyTileData = { - id: 'yellowWall', - cls: 'terrains', - events: { 10: 'onEnter', 20: 'onTouch' }, - noPass: true - }; - - const converted = store.fromLegacy(1, legacy); - - expect(converted.events).toEqual({ 10: 'onEnter', 20: 'onTouch' }); - expect(store.getEvent(1)).toEqual( - new Map([ - [10, 'onEnter'], - [20, 'onTouch'] - ]) - ); - expect(converted.eventPass).toBe(false); - expect(converted).not.toHaveProperty('trigger'); - }); - - // 验证旧样板缺少事件输入时仍生成合法的空事件映射 - it('uses an empty events map when legacy input has no events', () => { - const bridge = new TileLegacyBridge(); - const legacy: LegacyTileData = { - id: 'whiteWall', - cls: 'terrains' - }; - - const converted = bridge.fromLegacy(2, legacy); - - expect(converted.events).toEqual({}); - expect(converted).not.toHaveProperty('trigger'); - }); -}); diff --git a/packages/legacy-ui/src/tools/equipbox.tsx b/packages/legacy-ui/src/tools/equipbox.tsx index 6e7e879..3ca9f76 100644 --- a/packages/legacy-ui/src/tools/equipbox.tsx +++ b/packages/legacy-ui/src/tools/equipbox.tsx @@ -62,6 +62,7 @@ export function getNowStatus(nowEquip?: Equip, onCol: boolean = false) { 'hpmax', 'money' ] as (keyof SelectType)[]; + // @ts-expect-error 需要重构 const { getHeroStatusOn } = Mota.require('@user/data-state'); return (