import type { BattleSession } from 'db://assets/mx/module/battle'; import { TransformComp } from 'db://assets/mx/module/battle/ecs/Components'; import type { ComposedUnit } from 'db://assets/mx/module/merge'; import type { EntityId } from 'db://assets/mx/module/ecs'; import type { MapManager } from '../map/legacy/MapManager'; import { composeKey } from './ComposeUnitKey'; /** 部署查询只需合成与已部署列表 */ export interface IDeployOwner { /** Merge 合成单位 */ readonly compositions: readonly ComposedUnit[]; /** 已部署实体 */ readonly deployedUnits: readonly EntityId[]; } /** 部署信息 DTO(由 Merge.compositions 查询时现算) */ export interface DeployedTowerInfo { /** Hero.id */ weapon1Id: number; /** 合成等级 */ level: number; /** 合成键 */ composeKey: string; /** 占地格 */ gridIndices: readonly number[]; /** 朝向 */ direction: ComposedUnit['direction']; } /** ECS 实体 → 地图格 index(TransformComp + MapManager,不读 DeploySync 缓存) */ export function findGridIndexByEntity( entityId: EntityId, session: BattleSession, map: MapManager, ): number | null { const world = session.world; if (!world.isAlive(entityId)) return null; const tf = world.getComponent(entityId, TransformComp); if (!tf) return null; const mg = map.getMapGrid(tf.row, tf.col); return mg?.Index ?? null; } /** 地图格 → 与 TransformComp 格坐标精确匹配的已部署实体 */ function findEntityIdAtMapGrid( gridIndex: number, session: BattleSession, map: MapManager, player?: IDeployOwner | null, ): EntityId | null { const g = map.getMapGridByIndex(gridIndex); if (!g) return null; const world = session.world; const deployed = player?.deployedUnits ?? session.players[0]?.deployedUnits ?? []; for (const entityId of deployed) { if (!world.isAlive(entityId)) continue; const tf = world.getComponent(entityId, TransformComp); if (tf && tf.row === g.Row && tf.col === g.Col) return entityId; } return null; } /** * 地图格 index → ECS 实体。 * 多格合成体只在 gridIndices[0] 落 Transform,其余格通过 composition 回查同一实体。 */ export function findEntityIdByGridIndex( gridIndex: number, session: BattleSession, map: MapManager, player?: IDeployOwner | null, ): EntityId | null { const direct = findEntityIdAtMapGrid(gridIndex, session, map, player); if (direct != null) return direct; // 多格合成:实体只挂在一格,其余格经 composition 回查 const comp = player?.compositions.find(c => c.gridIndices.includes(gridIndex)) ?? null; if (!comp) return null; for (const idx of comp.gridIndices) { if (idx === gridIndex) continue; const entityId = findEntityIdAtMapGrid(idx, session, map, player); if (entityId != null) return entityId; } return null; } /** * 实体 → 地图格 index。 * 多格合成体 Transform 只落在锚点格;锚点格对不上时,沿 composition 其它格回查。 */ export function findGridIndexForEntity( entityId: EntityId, player: IDeployOwner, session: BattleSession, map: MapManager, ): number | null { const direct = findGridIndexByEntity(entityId, session, map); if (direct != null) return direct; for (const comp of player.compositions) { for (const idx of comp.gridIndices) { if (findEntityIdByGridIndex(idx, session, map, player) === entityId) { return idx; } } } return null; } /** MergeSession.compositions 中查找实体所属合成单位(唯一合成态来源) */ export function findCompositionForEntity( entityId: EntityId, player: IDeployOwner, session: BattleSession, map: MapManager, ): ComposedUnit | null { const gridIndex = findGridIndexForEntity(entityId, player, session, map); if (gridIndex == null) return null; return player.compositions.find(c => c.gridIndices.includes(gridIndex)) ?? null; } /** 由 Merge 合成单位构建部署信息 DTO(查询时现算,不缓存) */ export function buildDeployedTowerInfo(comp: ComposedUnit): DeployedTowerInfo { return { weapon1Id: comp.weapon1Id, level: comp.level, composeKey: composeKey(comp), gridIndices: comp.gridIndices, direction: comp.direction, }; }