refactor: 地图渲染器改为与 LayerState 绑定

This commit is contained in:
AncTe committed 2025-11-18 21:12:43 +08:00
1 parent 6ae0d6ca5f
commit ebaa35ea5b
17 files changed
+564 -387

No files matched your search

+82
View File
@@ -0,0 +1,82 @@
import { logger } from './logger';
import { IHookable, IHookBase, IHookController, IHookObject } from './types';
export abstract class Hookable<
H extends IHookBase = IHookBase,
C extends IHookController<H> = IHookController<H>
> implements IHookable<H, C>
{
/** 加载完成的钩子列表 */
protected readonly loadedList: Set<IHookObject<H, C>> = new Set();
/** 钩子列表 */
private readonly hookList: Set<IHookObject<H, C>> = new Set();
/** 钩子对象到钩子存储对象的映射 */
private readonly hookMap: Map<Partial<H>, IHookObject<H, C>> = new Map();
/** 钩子控制器到钩子存储对象的映射 */
private readonly controllerMap: Map<C, IHookObject<H, C>> = new Map();
/**
* 创建钩子对象的控制器
* @param hook 钩子对象
*/
protected abstract createController(hook: Partial<H>): C;
addHook(hook: Partial<H>): C {
const controller = this.createController(hook);
const obj: IHookObject<H, C> = { hook, controller };
this.hookMap.set(hook, obj);
this.controllerMap.set(controller, obj);
this.hookList.add(obj);
return controller;
}
loadHook(hook: Partial<H>): void {
const obj = this.hookMap.get(hook);
if (!obj) {
logger.warn(85);
return;
}
hook.awake?.(obj.controller);
this.loadedList.add(obj);
}
removeHook(hook: Partial<H>): void {
const obj = this.hookMap.get(hook);
if (!obj) return;
obj.hook.destroy?.(obj.controller);
this.hookList.delete(obj);
this.loadedList.delete(obj);
this.hookMap.delete(hook);
this.controllerMap.delete(obj.controller);
}
removeHookByController(hook: C): void {
const obj = this.controllerMap.get(hook);
if (!obj) return;
obj.hook.destroy?.(obj.controller);
this.hookList.delete(obj);
this.loadedList.delete(obj);
this.controllerMap.delete(hook);
this.hookMap.delete(obj.hook);
}
forEachHook(fn: (hook: Partial<H>, controller: C) => void): void {
this.loadedList.forEach(v => fn(v.hook, v.controller));
}
}
export class HookController<H extends IHookBase> implements IHookController<H> {
constructor(
readonly hookable: IHookable<H, IHookController<H>>,
readonly hook: Partial<H>
) {}
load(): void {
this.hookable.loadHook(this.hook);
}
unload(): void {
this.hookable.removeHookByController(this);
}
}
+1
View File
@@ -1,4 +1,5 @@
export * from './dirtyTracker';
export * from './hook';
export * from './logger';
export * from './utils';
export * from './types';
+2 -1
View File
@@ -41,7 +41,7 @@
"39": "Offset pool size exceeds WebGL2 limitation, ensure size type of your big image is less than $1.",
"40": "Material used by map block $1 is not found in built asset. Please ensure you have pack it into asset.",
"41": "You are trying to use a texture on moving block whose offset is not in the offset pool, please build it into asset after loading.",
"42": "The layerList property of map-render element is required.",
"42": "The layerState property of map-render element is required.",
"1101": "Shadow extension needs 'floor-hero' extension as dependency.",
"1201": "Floor-damage extension needs 'floor-binder' extension as dependency.",
"1301": "Portal extension need 'floor-binder' extension as dependency.",
@@ -132,6 +132,7 @@
"82": "Big image offset size is larger than 64. Considier reduce big image offset bucket.",
"83": "It seems that you call '$1' too frequently. This will extremely affect game's performance, so considering integrate them into one 'updateArea' or 'updateBlockList' call.",
"84": "Cannot set alias '$1' for layer, since '$1' is already an alias for another layer.",
"85": "Hook to load does not belong to current hookable object.",
"1001": "Item-detail extension needs 'floor-binder' and 'floor-damage' extension as dependency.",
"1101": "Cannot add new effect to point effect instance, for there's no more reserve space for it. Please increase the max count of the instance."
}
+82
View File
@@ -1,3 +1,5 @@
//#region 脏标记
export interface IDirtyMarker<T> {
/**
* 标记为脏,即进行了一次更新
@@ -32,3 +34,83 @@ export interface IDirtyTracker<T> {
*/
hasMark(symbol: IDirtyMark): boolean;
}
//#endregion
//#region 钩子
export interface IHookObject<
H extends IHookBase,
C extends IHookController<H>
> {
/** 钩子对象 */
readonly hook: Partial<H>;
/** 钩子控制器 */
readonly controller: C;
}
export interface IHookController<H extends IHookBase = IHookBase> {
/** 控制器的钩子对象 */
readonly hook: Partial<H>;
/**
* 加载此控制器对应的钩子对象
*/
load(): void;
/**
* 卸载此控制器对应的钩子对象,之后此钩子将不会再被触发
*/
unload(): void;
}
export interface IHookBase {
/**
* 加载此钩子对象
* @param controller 钩子控制器对象
*/
awake(controller: IHookController<this>): void;
/**
* 摧毁此钩子对象
* @param controller 钩子控制器对象
*/
destroy(controller: IHookController<this>): void;
}
export interface IHookable<
H extends IHookBase = IHookBase,
C extends IHookController<H> = IHookController<H>
> {
/**
* 添加钩子对象,返回控制该钩子对象的控制器
* @param hook 钩子对象
*/
addHook(hook: Partial<H>): C;
/**
* 加载指定的钩子对象
* @param hook 钩子对象
*/
loadHook(hook: Partial<H>): void;
/**
* 移除钩子对象,会调用钩子对象的 `destroy` 方法
* @param hook 钩子对象
*/
removeHook(hook: Partial<H>): void;
/**
* 传入钩子控制器,移除对应的钩子对象
* @param hook 钩子控制器
*/
removeHookByController(hook: C): void;
/**
* 遍历每个钩子
* @param fn 对每个钩子执行的函数
*/
forEachHook(fn: (hook: Partial<H>, controller: C) => void): void;
}
//#endregion