You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.5 KiB
140 lines
4.5 KiB
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<number, MapCellSnapshot>();
|
|
private _tiles = new Map<number, MapTileRecord>();
|
|
|
|
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<number, number> {
|
|
const layout = new Map<number, number>();
|
|
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);
|
|
}
|
|
}
|
|
|