mirror of
https://github.com/motajs/template.git
synced 2026-11-01 22:24:31 +08:00
1 parent
476f735adc
commit
70a58ef4dc
9 files changed
+853
-14
No files matched your search
@@ -10,7 +10,7 @@ import {
|
||||
SpecialCreation,
|
||||
IEnemySaveState
|
||||
} from './types';
|
||||
import { SaveCompression } from '../common/types';
|
||||
import { SaveCompression } from '../common';
|
||||
|
||||
export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
|
||||
/** 特殊属性注册表,code -> 创建函数 */
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './layerState';
|
||||
export * from './mapLayer';
|
||||
export * from './mapStore';
|
||||
export * from './types';
|
||||
@@ -29,6 +29,12 @@ export class LayerState
|
||||
/** 图层钩子映射 */
|
||||
private layerHookMap: Map<IMapLayer, IMapLayerHookController> = new Map();
|
||||
|
||||
/** 楼层是否处于激活状态 */
|
||||
active: boolean = false;
|
||||
|
||||
/** 楼层级脏标记 */
|
||||
private dirty: boolean = false;
|
||||
|
||||
addLayer(width: number, height: number): IMapLayer {
|
||||
const array = new Uint32Array(width * height);
|
||||
const layer = new MapLayer(array, width, height);
|
||||
@@ -106,6 +112,18 @@ export class LayerState
|
||||
return this.backgroundTile;
|
||||
}
|
||||
|
||||
setActiveStatus(active: boolean): void {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
isDirty(): boolean {
|
||||
return this.dirty;
|
||||
}
|
||||
|
||||
setDirty(dirty: boolean): void {
|
||||
this.dirty = dirty;
|
||||
}
|
||||
|
||||
protected createController(
|
||||
hook: Partial<ILayerStateHooks>
|
||||
): IHookController<ILayerStateHooks> {
|
||||
@@ -120,18 +138,21 @@ class StateMapLayerHook implements Partial<IMapLayerHooks> {
|
||||
) {}
|
||||
|
||||
onUpdateArea(x: number, y: number, width: number, height: number): void {
|
||||
this.state.setDirty(true);
|
||||
this.state.forEachHook(hook => {
|
||||
hook.onUpdateLayerArea?.(this.layer, x, y, width, height);
|
||||
});
|
||||
}
|
||||
|
||||
onUpdateBlock(block: number, x: number, y: number): void {
|
||||
this.state.setDirty(true);
|
||||
this.state.forEachHook(hook => {
|
||||
hook.onUpdateLayerBlock?.(this.layer, block, x, y);
|
||||
});
|
||||
}
|
||||
|
||||
onResize(width: number, height: number): void {
|
||||
this.state.setDirty(true);
|
||||
this.state.forEachHook(hook => {
|
||||
hook.onResizeLayer?.(this.layer, width, height);
|
||||
});
|
||||
|
||||
@@ -186,14 +186,12 @@ export class MapLayer
|
||||
}
|
||||
const res = new Uint32Array(width * height);
|
||||
const arr = this.mapArray;
|
||||
const nr = Math.min(r, w);
|
||||
const nb = Math.min(b, h);
|
||||
for (let nx = x; nx < nr; nx++) {
|
||||
for (let ny = y; ny < nb; ny++) {
|
||||
const origin = ny * w + nx;
|
||||
const target = (ny - y) * width + (nx - x);
|
||||
res[target] = arr[origin];
|
||||
}
|
||||
for (let ny = y; ny < nb; ny++) {
|
||||
const lineStart = ny * w + x;
|
||||
const lineEnd = lineStart + width;
|
||||
const dy = ny - y;
|
||||
res.set(arr.subarray(lineStart, lineEnd), dy * width);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -205,6 +203,27 @@ export class MapLayer
|
||||
return this.mapData;
|
||||
}
|
||||
|
||||
setMapRef(array: Uint32Array): void {
|
||||
if (array.length !== this.width * this.height) {
|
||||
logger.warn(
|
||||
123,
|
||||
array.length.toString(),
|
||||
(this.width * this.height).toString()
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.mapData.expired = true;
|
||||
this.mapArray = array;
|
||||
this.mapData = {
|
||||
expired: false,
|
||||
array: this.mapArray
|
||||
};
|
||||
this.empty = !array.some(v => v !== 0);
|
||||
this.forEachHook(hook => {
|
||||
hook.onUpdateArea?.(0, 0, this.width, this.height);
|
||||
});
|
||||
}
|
||||
|
||||
protected createController(
|
||||
hook: Partial<IMapLayerHooks>
|
||||
): IMapLayerHookController {
|
||||
|
||||
@@ -0,0 +1,383 @@
|
||||
import { logger } from '@motajs/common';
|
||||
import { SaveCompression } from '../common';
|
||||
import {
|
||||
ILayerState,
|
||||
ILayerStateSave,
|
||||
IMapLayer,
|
||||
IMapLayerSave,
|
||||
IMapStore,
|
||||
IMapStoreSave
|
||||
} from './types';
|
||||
import { LayerState } from './layerState';
|
||||
|
||||
export class MapStore implements IMapStore {
|
||||
/** 楼层 id 到状态对象的映射 */
|
||||
private readonly mapData: Map<string, LayerState> = new Map();
|
||||
|
||||
/** 所有楼层 id 的只读集合视图 */
|
||||
readonly maps: Set<string> = new Set();
|
||||
|
||||
/** 差分压缩参考基准,首次 compareWith 后设置,之后不再更新 */
|
||||
private refData: Map<string, Map<number, Uint32Array>> | null = null;
|
||||
|
||||
//#region 楼层访问
|
||||
|
||||
getLayerState(id: string): ILayerState | null {
|
||||
return this.mapData.get(id) ?? null;
|
||||
}
|
||||
|
||||
getActiveMap(id: string): ILayerState | null {
|
||||
const state = this.mapData.get(id);
|
||||
if (!state || !state.active) return null;
|
||||
return state;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 楼层管理
|
||||
|
||||
createLayerState(id: string): ILayerState {
|
||||
if (this.mapData.has(id)) {
|
||||
logger.warn(121, id);
|
||||
}
|
||||
const state = new LayerState();
|
||||
// 若 refData 已存在,新楼层直接视为全脏
|
||||
if (this.refData !== null) {
|
||||
state.setDirty(true);
|
||||
}
|
||||
this.mapData.set(id, state);
|
||||
this.maps.add(id);
|
||||
return state;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region active 管理
|
||||
|
||||
isMapActive(id: string): boolean {
|
||||
return this.mapData.get(id)?.active ?? false;
|
||||
}
|
||||
|
||||
setMapActiveStatus(id: string, active: boolean): void {
|
||||
this.mapData.get(id)?.setActiveStatus(active);
|
||||
}
|
||||
|
||||
*iterateActiveMaps(): Iterable<[string, ILayerState]> {
|
||||
for (const [id, state] of this.mapData) {
|
||||
if (state.active) yield [id, state];
|
||||
}
|
||||
}
|
||||
|
||||
*iterateInactiveMaps(): Iterable<[string, ILayerState]> {
|
||||
for (const [id, state] of this.mapData) {
|
||||
if (!state.active) yield [id, state];
|
||||
}
|
||||
}
|
||||
|
||||
iterateAllMaps(): Iterable<[string, ILayerState]> {
|
||||
return this.mapData;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 存档及压缩
|
||||
|
||||
compareWith(ref: Map<string, Map<number, Uint32Array>>): void {
|
||||
if (this.refData !== null) return;
|
||||
this.refData = ref;
|
||||
|
||||
for (const [id, state] of this.mapData) {
|
||||
const refFloor = ref.get(id);
|
||||
if (!refFloor) {
|
||||
state.setDirty(true);
|
||||
continue;
|
||||
}
|
||||
let dirty = false;
|
||||
for (const layer of state.layerList) {
|
||||
const refArray = refFloor.get(layer.zIndex);
|
||||
if (!refArray) {
|
||||
dirty = true;
|
||||
break;
|
||||
}
|
||||
const cur = layer.getMapRef().array;
|
||||
if (cur.length !== refArray.length) {
|
||||
dirty = true;
|
||||
break;
|
||||
}
|
||||
if (cur.some((v, i) => refArray[i] !== v)) {
|
||||
dirty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.setDirty(dirty);
|
||||
}
|
||||
}
|
||||
|
||||
private saveNoCompression(): IMapStoreSave {
|
||||
const floors = new Map<string, ILayerStateSave>();
|
||||
for (const [id, state] of this.mapData) {
|
||||
if (!state.active) continue;
|
||||
floors.set(id, this.saveLayerStateFull(state));
|
||||
}
|
||||
return { floors };
|
||||
}
|
||||
|
||||
private saveLowCompression(): IMapStoreSave {
|
||||
const floors = new Map<string, ILayerStateSave>();
|
||||
for (const [id, state] of this.mapData) {
|
||||
if (!state.active) continue;
|
||||
// 非 dirty 或 dirty 但与参考基准完全一致 → 空 layers(读档时从参考基准恢复)
|
||||
if (
|
||||
!state.isDirty() ||
|
||||
(this.refData && this.isStateEqualToRef(id, state))
|
||||
) {
|
||||
floors.set(id, {
|
||||
background: state.getBackground(),
|
||||
layers: new Map()
|
||||
});
|
||||
} else {
|
||||
floors.set(id, this.saveLayerStateFull(state));
|
||||
}
|
||||
}
|
||||
return { floors };
|
||||
}
|
||||
|
||||
private saveHighCompression(): IMapStoreSave {
|
||||
const floors = new Map<string, ILayerStateSave>();
|
||||
for (const [id, state] of this.mapData) {
|
||||
if (!state.active) continue;
|
||||
if (!state.isDirty()) {
|
||||
floors.set(id, {
|
||||
background: state.getBackground(),
|
||||
layers: new Map()
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const refFloor = this.refData?.get(id);
|
||||
const layersMap = new Map<number, IMapLayerSave>();
|
||||
for (const layer of state.layerList) {
|
||||
const refArray = refFloor?.get(layer.zIndex);
|
||||
const rows = this.diffRows(layer, refArray);
|
||||
if (rows.size === 0 && refArray) continue; // 与参考完全一致
|
||||
layersMap.set(layer.zIndex, {
|
||||
width: layer.width,
|
||||
height: layer.height,
|
||||
rows
|
||||
});
|
||||
}
|
||||
floors.set(id, {
|
||||
background: state.getBackground(),
|
||||
layers: layersMap
|
||||
});
|
||||
}
|
||||
return { floors };
|
||||
}
|
||||
|
||||
/**
|
||||
* NoCompression 读档:每个图层均有 fullMap,直接转移所有权,无需参考基准。
|
||||
*/
|
||||
private loadNoCompression(state: IMapStoreSave): void {
|
||||
for (const [id, cur] of this.mapData) {
|
||||
cur.setActiveStatus(state.floors.has(id));
|
||||
}
|
||||
for (const [id, layerStateSave] of state.floors) {
|
||||
const cur = this.mapData.get(id);
|
||||
if (!cur) {
|
||||
logger.warn(122, id);
|
||||
continue;
|
||||
}
|
||||
cur.setBackground(layerStateSave.background);
|
||||
for (const layer of cur.layerList) {
|
||||
const layerSave = layerStateSave.layers.get(layer.zIndex);
|
||||
if (!layerSave?.fullMap) continue;
|
||||
layer.setMapRef(new Uint32Array(layerSave.fullMap));
|
||||
}
|
||||
cur.setDirty(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LowCompression 读档:
|
||||
* - layers 有数据(dirty 楼层)→ fullMap 直接转移所有权
|
||||
* - layers 为空(非 dirty 楼层)→ 从参考基准恢复
|
||||
*/
|
||||
private loadLowCompression(state: IMapStoreSave): void {
|
||||
if (!this.refData) {
|
||||
logger.error(55);
|
||||
return;
|
||||
}
|
||||
for (const [id, cur] of this.mapData) {
|
||||
cur.setActiveStatus(state.floors.has(id));
|
||||
}
|
||||
for (const [id, layerStateSave] of state.floors) {
|
||||
const cur = this.mapData.get(id);
|
||||
const refFloor = this.refData.get(id);
|
||||
if (!cur) {
|
||||
logger.warn(122, id);
|
||||
continue;
|
||||
}
|
||||
if (!refFloor) {
|
||||
logger.warn(124, id);
|
||||
continue;
|
||||
}
|
||||
cur.setBackground(layerStateSave.background);
|
||||
for (const layer of cur.layerList) {
|
||||
const layerSave = layerStateSave.layers.get(layer.zIndex);
|
||||
if (layerSave?.fullMap) {
|
||||
layer.setMapRef(layerSave.fullMap);
|
||||
} else {
|
||||
const refArray = refFloor?.get(layer.zIndex);
|
||||
if (!refArray) {
|
||||
logger.warn(124, id);
|
||||
return;
|
||||
}
|
||||
layer.setMapRef(new Uint32Array(refArray));
|
||||
}
|
||||
}
|
||||
cur.setDirty(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HighCompression 读档:
|
||||
* - layers 有数据(dirty 楼层)→ 以参考基准为底,叠加差分行
|
||||
* - layers 为空(非 dirty 楼层)或图层无变化(rows 缺失)→ 从参考基准恢复
|
||||
*/
|
||||
private loadHighCompression(state: IMapStoreSave): void {
|
||||
if (!this.refData) {
|
||||
logger.error(55);
|
||||
return;
|
||||
}
|
||||
for (const [id, cur] of this.mapData) {
|
||||
cur.setActiveStatus(state.floors.has(id));
|
||||
}
|
||||
for (const [id, layerStateSave] of state.floors) {
|
||||
const cur = this.mapData.get(id);
|
||||
const refFloor = this.refData.get(id);
|
||||
if (!cur) {
|
||||
logger.warn(122, id);
|
||||
continue;
|
||||
}
|
||||
if (!refFloor) {
|
||||
logger.warn(124, id);
|
||||
continue;
|
||||
}
|
||||
cur.setBackground(layerStateSave.background);
|
||||
let isMapDirty = true;
|
||||
for (const layer of cur.layerList) {
|
||||
const refArray = refFloor.get(layer.zIndex);
|
||||
if (!refArray) {
|
||||
logger.warn(124, id);
|
||||
continue;
|
||||
}
|
||||
const layerSave = layerStateSave.layers.get(layer.zIndex);
|
||||
if (!layerSave?.rows || layerSave.rows.size === 0) {
|
||||
// 图层无变化或非 dirty 楼层,从参考基准恢复
|
||||
layer.setMapRef(new Uint32Array(refArray));
|
||||
} else {
|
||||
// 以参考基准为底,叠加差分行
|
||||
isMapDirty = false;
|
||||
const size = layer.width * layer.height;
|
||||
const buf = new Uint32Array(size);
|
||||
if (refArray) buf.set(refArray.subarray(0, size));
|
||||
for (const [rowIdx, rowData] of layerSave.rows) {
|
||||
buf.set(
|
||||
rowData.subarray(0, layer.width),
|
||||
rowIdx * layer.width
|
||||
);
|
||||
}
|
||||
layer.setMapRef(buf);
|
||||
}
|
||||
}
|
||||
cur.setDirty(isMapDirty);
|
||||
}
|
||||
}
|
||||
|
||||
saveState(compression: SaveCompression): IMapStoreSave {
|
||||
if (compression === SaveCompression.HighCompression) {
|
||||
return this.saveHighCompression();
|
||||
} else if (compression === SaveCompression.LowCompression) {
|
||||
return this.saveLowCompression();
|
||||
} else {
|
||||
return this.saveNoCompression();
|
||||
}
|
||||
}
|
||||
|
||||
loadState(state: IMapStoreSave, compression: SaveCompression): void {
|
||||
if (compression === SaveCompression.HighCompression) {
|
||||
this.loadHighCompression(state);
|
||||
} else if (compression === SaveCompression.LowCompression) {
|
||||
this.loadLowCompression(state);
|
||||
} else {
|
||||
this.loadNoCompression(state);
|
||||
}
|
||||
}
|
||||
|
||||
//#region 内部方法
|
||||
|
||||
/**
|
||||
* 将楼层所有图层全量序列化(NoCompression / LowCompression 用)
|
||||
*/
|
||||
private saveLayerStateFull(state: LayerState): ILayerStateSave {
|
||||
const layersMap = new Map<number, IMapLayerSave>();
|
||||
for (const layer of state.layerList) {
|
||||
const arr = layer.getMapRef().array;
|
||||
layersMap.set(layer.zIndex, {
|
||||
width: layer.width,
|
||||
height: layer.height,
|
||||
fullMap: new Uint32Array(arr)
|
||||
});
|
||||
}
|
||||
return { background: state.getBackground(), layers: layersMap };
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅返回与参考基准不同的行(HighCompression 用)
|
||||
*/
|
||||
private diffRows(
|
||||
layer: IMapLayer,
|
||||
refArray?: Uint32Array
|
||||
): Map<number, Uint32Array> {
|
||||
const rows = new Map<number, Uint32Array>();
|
||||
const arr = layer.getMapRef().array;
|
||||
if (refArray) {
|
||||
for (let row = 0; row < layer.height; row++) {
|
||||
const start = row * layer.width;
|
||||
const end = start + layer.width;
|
||||
const slice = arr.subarray(start, end);
|
||||
const refSlice = refArray.subarray(start, end);
|
||||
const same = refSlice.every((v, i) => slice[i] === v);
|
||||
if (!same) {
|
||||
rows.set(row, new Uint32Array(slice));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let row = 0; row < layer.height; row++) {
|
||||
const start = row * layer.width;
|
||||
const end = start + layer.width;
|
||||
rows.set(row, new Uint32Array(arr.subarray(start, end)));
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断楼层所有图层是否与参考基准完全一致(LowCompression 去误判用)
|
||||
*/
|
||||
private isStateEqualToRef(id: string, state: LayerState): boolean {
|
||||
const refFloor = this.refData?.get(id);
|
||||
if (!refFloor) return false;
|
||||
for (const layer of state.layerList) {
|
||||
const refArray = refFloor.get(layer.zIndex);
|
||||
if (!refArray) return false;
|
||||
const cur = layer.getMapRef().array;
|
||||
if (cur.length !== refArray.length) return false;
|
||||
for (let i = 0; i < cur.length; i++) {
|
||||
if (cur[i] !== refArray[i]) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { IHookable, IHookBase, IHookController } from '@motajs/common';
|
||||
import { ISaveableContent } from '../common';
|
||||
|
||||
export interface IMapLayerData {
|
||||
/** 当前引用是否过期,当地图图层内部的地图数组引用更新时,此项会变为 `true` */
|
||||
@@ -48,8 +49,7 @@ export interface IMapLayerHooks extends IHookBase {
|
||||
onCloseDoor(num: number, x: number, y: number): Promise<void>;
|
||||
}
|
||||
|
||||
export interface IMapLayerHookController
|
||||
extends IHookController<IMapLayerHooks> {
|
||||
export interface IMapLayerHookController extends IHookController<IMapLayerHooks> {
|
||||
/** 拓展所属的图层对象 */
|
||||
readonly layer: IMapLayer;
|
||||
|
||||
@@ -59,8 +59,10 @@ export interface IMapLayerHookController
|
||||
getMapData(): Readonly<IMapLayerData>;
|
||||
}
|
||||
|
||||
export interface IMapLayer
|
||||
extends IHookable<IMapLayerHooks, IMapLayerHookController> {
|
||||
export interface IMapLayer extends IHookable<
|
||||
IMapLayerHooks,
|
||||
IMapLayerHookController
|
||||
> {
|
||||
/** 地图宽度 */
|
||||
readonly width: number;
|
||||
/** 地图高度 */
|
||||
@@ -155,6 +157,15 @@ export interface IMapLayer
|
||||
* @param y 门纵坐标
|
||||
*/
|
||||
closeDoor(num: number, x: number, y: number): Promise<void>;
|
||||
|
||||
/**
|
||||
* 直接替换内部图块数组引用,跳过拷贝,高性能但风险较高。
|
||||
* 一般仅供 `MapStore` 读档时内部使用,外部正常情况下不应调用。
|
||||
* 调用方需确保传入数组的长度与 `width * height` 匹配,
|
||||
* 且调用后不得再持有或修改传入的数组。
|
||||
* @param array 地图数组,会直接替换内部引用
|
||||
*/
|
||||
setMapRef(array: Uint32Array): void;
|
||||
}
|
||||
|
||||
export interface ILayerStateHooks extends IHookBase {
|
||||
@@ -212,6 +223,8 @@ export interface ILayerStateHooks extends IHookBase {
|
||||
export interface ILayerState extends IHookable<ILayerStateHooks> {
|
||||
/** 地图列表 */
|
||||
readonly layerList: Set<IMapLayer>;
|
||||
/** 此楼层是否处于激活状态 */
|
||||
readonly active: boolean;
|
||||
|
||||
/**
|
||||
* 添加图层
|
||||
@@ -275,4 +288,107 @@ export interface ILayerState extends IHookable<ILayerStateHooks> {
|
||||
* 获取背景图块数字,如果没有设置过,则返回 0
|
||||
*/
|
||||
getBackground(): number;
|
||||
|
||||
/**
|
||||
* 设置楼层激活状态
|
||||
* @param active 激活状态
|
||||
*/
|
||||
setActiveStatus(active: boolean): void;
|
||||
|
||||
/**
|
||||
* 楼层是否被修改过(相对于参考基准)
|
||||
*/
|
||||
isDirty(): boolean;
|
||||
|
||||
/**
|
||||
* 设置楼层脏标记
|
||||
*/
|
||||
setDirty(dirty: boolean): void;
|
||||
}
|
||||
|
||||
/** 单个 MapLayer 的存档数据 */
|
||||
export interface IMapLayerSave {
|
||||
readonly width: number;
|
||||
readonly height: number;
|
||||
|
||||
/**
|
||||
* key = 行索引,value = 该行完整的 Uint32Array 数据;
|
||||
* HighCompression 时使用此接口,仅包含与参考基准不同的行;
|
||||
* 读档时,不在此 Map 中的行从参考基准还原。
|
||||
*/
|
||||
readonly rows?: ReadonlyMap<number, Uint32Array>;
|
||||
|
||||
/** 完整地图,当使用 `NoCompression` 和 `LowCompression` 时使用此接口 */
|
||||
readonly fullMap?: Uint32Array;
|
||||
}
|
||||
|
||||
/** 单个楼层的存档数据 */
|
||||
export interface ILayerStateSave {
|
||||
readonly background: number;
|
||||
|
||||
/** key = zIndex,value = 对应图层存档数据 */
|
||||
readonly layers: ReadonlyMap<number, IMapLayerSave>;
|
||||
}
|
||||
|
||||
/** 整个 MapStore 的存档数据 */
|
||||
export interface IMapStoreSave {
|
||||
/** key = 楼层 id,只包含 active 的楼层,inactive 的楼层不写入,读档时无需处理 */
|
||||
readonly floors: ReadonlyMap<string, ILayerStateSave>;
|
||||
}
|
||||
|
||||
export interface IMapStore extends ISaveableContent<IMapStoreSave> {
|
||||
/** 所有楼层的 id 集合 */
|
||||
readonly maps: ReadonlySet<string>;
|
||||
|
||||
/**
|
||||
* 获取指定 id 的楼层状态,不存在则返回 null
|
||||
* @param id 楼层 id
|
||||
*/
|
||||
getLayerState(id: string): ILayerState | null;
|
||||
|
||||
/**
|
||||
* 获取指定 id 的楼层状态,要求楼层必须是 active 的,否则返回 null
|
||||
* @param id 楼层 id
|
||||
*/
|
||||
getActiveMap(id: string): ILayerState | null;
|
||||
|
||||
/**
|
||||
* 创建并注册一个空白楼层,若 id 已存在则警告并覆盖,返回楼层状态对象
|
||||
* @param id 楼层 id
|
||||
*/
|
||||
createLayerState(id: string): ILayerState;
|
||||
|
||||
/**
|
||||
* 获取指定 id 的楼层是否激活,不存在的 id 返回 false
|
||||
* @param id 楼层 id
|
||||
*/
|
||||
isMapActive(id: string): boolean;
|
||||
|
||||
/**
|
||||
* 设置指定 id 楼层的激活状态
|
||||
* @param id 楼层 id
|
||||
* @param active 激活状态
|
||||
*/
|
||||
setMapActiveStatus(id: string, active: boolean): void;
|
||||
|
||||
/**
|
||||
* 迭代所有 active 的楼层,yield [id, ILayerState]
|
||||
*/
|
||||
iterateActiveMaps(): Iterable<[string, ILayerState]>;
|
||||
|
||||
/**
|
||||
* 迭代所有 inactive 的楼层,yield [id, ILayerState]
|
||||
*/
|
||||
iterateInactiveMaps(): Iterable<[string, ILayerState]>;
|
||||
|
||||
/**
|
||||
* 迭代所有楼层,yield [id, ILayerState]
|
||||
*/
|
||||
iterateAllMaps(): Iterable<[string, ILayerState]>;
|
||||
|
||||
/**
|
||||
* 设置压缩参考基准,以首次调用为唯一基准,再次调用不更新。
|
||||
* @param ref 外层 key = 楼层 id,内层 key = zIndex,value = 图层完整图块数据
|
||||
*/
|
||||
compareWith(ref: Map<string, Map<number, Uint32Array>>): void;
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import { IHeroFollower, IHeroState } from './hero';
|
||||
import { IEnemyManager } from './enemy';
|
||||
import { IFlagSystem } from './flag';
|
||||
import { IRoleFaceBinder, ISaveableContent } from './common';
|
||||
import { ILayerState } from './map';
|
||||
import { IMapStore } from './map';
|
||||
|
||||
export interface IStateSaveData {
|
||||
/** 跟随者列表 */
|
||||
@@ -18,7 +18,7 @@ export interface IStateBase<TEnemy, THero> {
|
||||
readonly numberIdMap: Map<number, string>;
|
||||
|
||||
/** 地图状态 */
|
||||
readonly layer: ILayerState;
|
||||
readonly layer: IMapStore;
|
||||
/** 勇士状态 */
|
||||
readonly hero: IHeroState<THero>;
|
||||
|
||||
|
||||
Reference in new issue
Block a user