import { MapCellKind, type MapTileRecord } from '../types/MergeTypes'; export interface MapCellSnapshot { kind: MapCellKind; /** 地图编辑时即为可放置且初始无字块 */ builtinPut: boolean; /** 编辑器标记:该可走格是否允许放置 type3 扩展格子 */ canPutGrid: boolean; /** 本轮备战 type3 扩展格:仅改格状态,不挂字块节点 */ prepType3?: boolean; /** type3 落子时刻(Date.now),用于限时可拖 */ prepType3PlacedAtMs?: number; } /** 地图字块棋盘(纯数据,格索引 = MapGrid.Index) */ export class MapTileBoard { private _cells = new Map(); private _tiles = new Map(); initCell(gridIndex: number, snapshot: MapCellSnapshot): void { this._cells.set(gridIndex, { ...snapshot }); } getCellKind(gridIndex: number): MapCellKind | null { return this._cells.get(gridIndex)?.kind ?? null; } isBuiltinPut(gridIndex: number): boolean { return this._cells.get(gridIndex)?.builtinPut ?? false; } isPrepType3(gridIndex: number): boolean { return this._cells.get(gridIndex)?.prepType3 ?? false; } /** type3 落子时刻;非 prepType3 时为 null */ getPrepType3PlacedAtMs(gridIndex: number): number | null { const cell = this._cells.get(gridIndex); if (!cell?.prepType3) return null; return cell.prepType3PlacedAtMs ?? null; } canPutGrid(gridIndex: number): boolean { return this._cells.get(gridIndex)?.canPutGrid ?? false; } setPrepType3(gridIndex: number, value: boolean): void { const cell = this._cells.get(gridIndex); if (!cell) return; cell.prepType3 = value; if (value) { cell.prepType3PlacedAtMs = Date.now(); } else { cell.prepType3PlacedAtMs = undefined; } } hasTile(gridIndex: number): boolean { return this._tiles.has(gridIndex); } getTile(gridIndex: number): MapTileRecord | null { return this._tiles.get(gridIndex) ?? null; } setCellKind(gridIndex: number, kind: MapCellKind): void { const cell = this._cells.get(gridIndex); if (!cell) return; cell.kind = kind; } /** 铲等效果:格变为可放置(与原生 Put 格一致) */ markCellAsPut(gridIndex: number): void { const cell = this._cells.get(gridIndex); if (!cell) return; cell.kind = MapCellKind.Put; cell.builtinPut = true; } /** 蟠桃树落到空 Put:格变为可开挖、不可放置 */ markCellAsDig(gridIndex: number): void { const cell = this._cells.get(gridIndex); if (!cell) return; cell.kind = MapCellKind.Dig; cell.builtinPut = false; } placeTile(gridIndex: number, tile: MapTileRecord): void { this._tiles.set(gridIndex, { ...tile }); } removeTile(gridIndex: number): MapTileRecord | null { const t = this._tiles.get(gridIndex) ?? null; this._tiles.delete(gridIndex); return t; } /** gridIndex → weapon2Id(供组合扫描;不含 type3 格状态) */ getWeapon2Layout(): Map { const layout = new Map(); this._tiles.forEach((tile, idx) => layout.set(idx, tile.weapon2Id)); return layout; } forEachTile(fn: (gridIndex: number, tile: MapTileRecord) => void): void { this._tiles.forEach((tile, idx) => fn(idx, { ...tile })); } get gridIndices(): number[] { const out: number[] = []; this._cells.forEach((_cell, idx) => out.push(idx)); return out; } exportCell(gridIndex: number): MapCellSnapshot | null { const cell = this._cells.get(gridIndex); return cell ? { ...cell } : null; } clearTiles(): void { this._tiles.clear(); } restoreBoard( cells: ReadonlyArray<{ gridIndex: number; cell: MapCellSnapshot }>, tiles: ReadonlyArray<{ gridIndex: number; tile: MapTileRecord }>, ): void { for (const { gridIndex, cell } of cells) { this._cells.set(gridIndex, { ...cell }); } this._tiles.clear(); for (const { gridIndex, tile } of tiles) { this._tiles.set(gridIndex, { ...tile }); } } getTileWeapon2IdsByIndices(indices: number[]): number[] { return indices.map((i) => this._tiles.get(i)?.weapon2Id).filter((id): id is number => id != null); } }