refactor: TileStore

This commit is contained in:
AncTe committed 2026-05-17 16:31:08 +08:00
1 parent 501a598de0
commit 13fc4e1b7c
12 files changed
+588 -64

No files matched your search

+1
View File
@@ -4,6 +4,7 @@ export * from './flag';
export * from './hero';
export * from './load';
export * from './map';
export * from './store';
export * from './game';
export * from './types';
@@ -0,0 +1,2 @@
export * from './tileStore';
export * from './types';
@@ -0,0 +1,86 @@
import { isNil } from 'lodash-es';
import { logger } from '@motajs/common';
import {
ITileLegacyConverter,
ITileRawData,
ITileStore,
TileType
} from './types';
export class TileStore<TLegacy = unknown> implements ITileStore<TLegacy> {
/** 以图块数字为键的原始图块定义表 */
private readonly dataMap: Map<number, ITileRawData> = new Map();
/** 由图块 id 反查图块数字的映射表 */
private readonly idMap: Map<string, number> = new Map();
/** 由图块数字反查图块 id 的映射表 */
private readonly numMap: Map<number, string> = new Map();
/** 当前挂载的旧样板图块转换器 */
private legacyConverter: ITileLegacyConverter<TLegacy> | null = null;
getData(num: number): ITileRawData | null {
return this.dataMap.get(num) ?? null;
}
getTrigger(num: number): number {
return this.dataMap.get(num)?.trigger ?? -1;
}
getType(num: number): TileType {
return this.dataMap.get(num)?.type ?? TileType.Unknown;
}
addTile(data: ITileRawData): void {
const oldData = this.dataMap.get(data.num);
const oldNum = this.idMap.get(data.id);
if (oldData) {
logger.warn(133, data.num.toString(), oldData.id);
this.deleteBy(oldData.num, oldData.id);
}
if (!isNil(oldNum) && oldNum !== data.num) {
logger.warn(134, data.id, oldNum.toString());
const oldIdData = this.dataMap.get(oldNum);
if (oldIdData) {
this.deleteBy(oldIdData.num, oldIdData.id);
} else {
this.idMap.delete(data.id);
this.numMap.delete(oldNum);
}
}
this.dataMap.set(data.num, data);
this.idMap.set(data.id, data.num);
this.numMap.set(data.num, data.id);
}
idToNumber(id: string): number | null {
return this.idMap.get(id) ?? null;
}
numberToId(num: number): string | null {
return this.numMap.get(num) ?? null;
}
attachLegacyConverter(converter: ITileLegacyConverter<TLegacy>): 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);
this.idMap.delete(id);
this.numMap.delete(num);
}
}
@@ -0,0 +1,91 @@
export const enum TileType {
/** 未知或尚未归类的图块 */
Unknown,
/** 空白图块 */
None,
/** 地形类图块 */
Terrain,
/** 动画类图块 */
Animate,
/** 道具类图块 */
Item,
/** 怪物类图块 */
Enemy,
/** NPC 类图块 */
Npc,
/** 自动元件 */
Autotile,
/** Tileset 切片图块 */
Tileset
}
export interface ITileRawData {
/** 图块数字 */
readonly num: number;
/** 图块字符串 id */
readonly id: string;
/** 默认触发器类型 */
readonly trigger: number;
/** 图块逻辑类型 */
readonly type: TileType;
}
export interface ITileLegacyConverter<TLegacy> {
/**
* 将旧样板图块定义转换为新的图块原始数据
* @param num 图块数字
* @param legacy 旧样板图块定义
*/
fromLegacy(num: number, legacy: TLegacy): ITileRawData;
}
export interface ITileStore<TLegacy = unknown> {
/**
* 获取指定图块数字对应的完整原始定义
* @param num 图块数字
*/
getData(num: number): ITileRawData | null;
/**
* 获取指定图块数字对应的默认触发器类型
* @param num 图块数字
*/
getTrigger(num: number): number;
/**
* 获取指定图块数字对应的图块类型
* @param num 图块数字
*/
getType(num: number): TileType;
/**
* 添加一个图块定义;若 `num` 或 `id` 冲突则警告并覆盖
* @param data 图块原始定义
*/
addTile(data: ITileRawData): void;
/**
* 根据图块 id 查询对应图块数字
* @param id 图块 id
*/
idToNumber(id: string): number | null;
/**
* 根据图块数字查询对应图块 id
* @param num 图块数字
*/
numberToId(num: number): string | null;
/**
* 挂载一个旧样板转换器
* @param converter 旧样板转换器
*/
attachLegacyConverter(converter: ITileLegacyConverter<TLegacy>): void;
/**
* 使用当前转换器转换并写入一个旧样板图块定义
* @param num 图块数字
* @param legacy 旧样板图块定义
*/
fromLegacy(num: number, legacy: TLegacy): ITileRawData;
}
+3 -4
View File
@@ -3,6 +3,7 @@ import { IEnemyManager } from './enemy';
import { IFlagSystem } from './flag';
import { IFaceManager, IRoleFaceBinder, ISaveableContent } from './common';
import { IMapStore } from './map';
import { ITileStore } from './store';
export interface IStateSaveData {
/** 跟随者列表 */
@@ -14,10 +15,8 @@ export interface IStateBase<TEnemy, THero> {
readonly roleFace: IRoleFaceBinder;
/** 朝向管理 */
readonly faceManager: IFaceManager;
/** id 到图块数字的映射 */
readonly idNumberMap: Map<string, number>;
/** 图块数字到 id 的映射 */
readonly numberIdMap: Map<number, string>;
/** 图块定义存储 */
readonly tileStore: ITileStore;
/** 地图状态 */
readonly maps: IMapStore;