refactor: 插件系统结构

This commit is contained in:
AncTe committed 2026-10-20 20:44:33 +08:00
1 parent 3cc97e5ed3
commit e6f4346924
30 files changed
+260 -169

No files matched your search

+60 -43
View File
@@ -41,8 +41,6 @@ import {
} from '@motajs/animate';
import { IRendererUsing, RendererUsing } from '@motajs/render-vue';
import { IUIController, UIController } from '@motajs/system';
import { createApp } from './render';
import { LoadSceneUI } from '../../../src/client/ui/load';
import { createUIPropsBase } from './ui/func';
export class ClientCore extends CoreState implements IClientCore {
@@ -65,13 +63,9 @@ export class ClientCore extends CoreState implements IClientCore {
// Layer 5 渲染顶层 - 目前没东西
/** 已注册的渲染端插件 */
private readonly clientPlugins: Map<
string,
IClientPlugin<IClientPluginDefine>
> = new Map();
private readonly orderedClientPlugins: IPluginOrderResult<
IClientPlugin<IClientPluginDefine>
>;
private readonly clientPlugins: Map<string, IClientPlugin> = new Map();
/** 排序后的渲染端插件 */
private readonly orderedClientPlugins: IPluginOrderResult;
constructor(config: IClientCoreConfig) {
super(config);
@@ -119,15 +113,28 @@ export class ClientCore extends CoreState implements IClientCore {
plugin: define
});
}
this.orderedClientPlugins = orderPlugins(this.clientPlugins);
const deps = new Map<string, readonly string[]>();
for (const [id, plugin] of this.clientPlugins) {
deps.set(id, plugin.plugin.clientDeps);
}
this.orderedClientPlugins = orderPlugins(deps);
}
//#region 插件方法
getClientPlugin<T extends IClientPluginDefine>(
id: string
): Readonly<IClientPlugin<T>> | null {
return (this.clientPlugins.get(id) as IClientPlugin<T>) ?? null;
/**
* 获取指定插件的所有渲染端插件依赖对象
* @param plugin 目标插件定义对象
*/
protected getClientDependencies(
plugin: IClientPluginDefine
): IClientPlugin[] {
const dependencies: IClientPlugin[] = [];
for (const dependency of plugin.dataDeps) {
const plugin = this.clientPlugins.get(dependency);
if (plugin) dependencies.push(plugin);
}
return dependencies;
}
/**
@@ -144,14 +151,15 @@ export class ClientCore extends CoreState implements IClientCore {
logger.error(77, pluginId, dependency);
}
}
for (const holder of result.order) {
if (holder.status !== PluginStatus.NotAwakened) continue;
const dependencies: IClientPlugin<IClientPluginDefine>[] = [];
for (const dependency of holder.plugin.dependencies) {
const plugin = this.clientPlugins.get(dependency);
if (plugin) dependencies.push(plugin);
for (const id of result.order) {
const holder = this.clientPlugins.get(id)!;
const plugin = holder.plugin;
if (!this.checkPluginStatus(holder, PluginStatus.NotAwakened)) {
continue;
}
holder.plugin.awake(this, dependencies);
const dataDeps = this.getDataDependencies(plugin);
const clientDeps = this.getClientDependencies(plugin);
plugin.awake(this, dataDeps, clientDeps);
holder.status = PluginStatus.Awakened;
}
}
@@ -162,14 +170,15 @@ export class ClientCore extends CoreState implements IClientCore {
protected async initialize(): Promise<void> {
await super.initialize();
const result = this.orderedClientPlugins;
for (const holder of result.order) {
if (holder.status !== PluginStatus.Awakened) continue;
const dependencies: IClientPlugin<IClientPluginDefine>[] = [];
for (const dependency of holder.plugin.dependencies) {
const plugin = this.clientPlugins.get(dependency);
if (plugin) dependencies.push(plugin);
for (const id of result.order) {
const holder = this.clientPlugins.get(id)!;
const plugin = holder.plugin;
if (!this.checkPluginStatus(holder, PluginStatus.Awakened)) {
continue;
}
await holder.plugin.initialize(this, dependencies);
const dataDeps = this.getDataDependencies(plugin);
const clientDeps = this.getClientDependencies(plugin);
await plugin.initialize(this, dataDeps, clientDeps);
holder.status = PluginStatus.Initialized;
}
}
@@ -180,28 +189,36 @@ export class ClientCore extends CoreState implements IClientCore {
protected async afterLoad(): Promise<void> {
await super.afterLoad();
const result = this.orderedClientPlugins;
for (const holder of result.order) {
if (holder.status !== PluginStatus.Initialized) continue;
const dependencies: IClientPlugin<IClientPluginDefine>[] = [];
for (const dependency of holder.plugin.dependencies) {
const plugin = this.clientPlugins.get(dependency);
if (plugin) dependencies.push(plugin);
for (const id of result.order) {
const holder = this.clientPlugins.get(id)!;
const plugin = holder.plugin;
if (!this.checkPluginStatus(holder, PluginStatus.Initialized)) {
continue;
}
await holder.plugin.afterLoad(this, dependencies);
const dataDeps = this.getDataDependencies(plugin);
const clientDeps = this.getClientDependencies(plugin);
await plugin.initialize(this, dataDeps, clientDeps);
holder.status = PluginStatus.Loaded;
}
}
//#endregion
/**
* 初始化渲染端主对象
*/
private async init() {
createApp(this.sceneController.render()).mount(this.renderer);
this.sceneController.open(LoadSceneUI, {});
getClientPlugin<T extends IClientPluginDefine>(
id: string
): Readonly<IClientPlugin<T>> | null {
return (this.clientPlugins.get(id) as IClientPlugin<T>) ?? null;
}
async *load(): AsyncGenerator<number, void> {
yield* super.load();
for (const plugin of this.clientPlugins.values()) {
if (plugin.status !== PluginStatus.Loaded) {
logger.error(81, plugin.plugin.id);
}
}
}
//#endregion
/**
* 进行地图渲染拓展初始化
*/
+27 -18
View File
@@ -1,51 +1,60 @@
import { IClientSystem } from '@user/client-system';
import { ICoreStateConfig, PluginStatus } from '@user/data-state';
import {
ICoreStateConfig,
IDataPlugin,
IDataPluginDefine,
IPluginDefine,
IPluginBase
} from '@user/data-state';
//#region 插件系统
export interface IClientPlugin<T extends IClientPluginDefine> {
/** 插件的当前状态 */
status: PluginStatus;
/** 插件内容 */
plugin: T;
}
export interface IClientPlugin<
T extends IClientPluginDefine = IClientPluginDefine
> extends IPluginDefine<T> {}
export interface IClientPluginDefine {
/** 插件标识符 */
readonly id: string;
/** 插件所依赖的其他插件 id */
readonly dependencies: readonly string[];
export interface IClientPluginDefine extends IPluginBase {
/** 插件所依赖的其他数据端插件 id,对于渲染端来说,可以依赖任何数据端插件 */
readonly dataDeps: readonly string[];
/** 插件所依赖的其他渲染端插件 id。依赖插件不允许循环依赖,否则会抛出错误,且所有在环上的插件都不会初始化 */
readonly clientDeps: readonly string[];
/**
* 插件同步初始化,在渲染端主对象创建完毕,初始化之前时调用
* @param state 渲染端主对象
* @param dependencies 此插件的依赖插件对象
* @param dataDeps 此插件的数据端依赖插件对象
* @param clientDeps 此插件的渲染端依赖插件对象
*/
awake(
state: IClientCore,
dependencies: IClientPlugin<IClientPluginDefine>[]
dataDeps: IDataPlugin<IDataPluginDefine>[],
clientDeps: IClientPlugin<IClientPluginDefine>[]
): void;
/**
* 插件异步初始化,在主对象创建完毕,初始化时,加载开始前调用。
* 此方法具有阻塞效果,如果返回值迟迟不兑现,那么会导致依赖其的插件不会开始异步初始化
* @param state 渲染端主对象
* @param dependencies 此插件的依赖插件对象
* @param dataDeps 此插件的数据端依赖插件对象
* @param clientDeps 此插件的渲染端依赖插件对象
*/
initialize(
state: IClientCore,
dependencies: IClientPlugin<IClientPluginDefine>[]
dataDeps: IDataPlugin<IDataPluginDefine>[],
clientDeps: IClientPlugin<IClientPluginDefine>[]
): Promise<void>;
/**
* 当主对象加载完毕后调用,可以用于依赖加载内容的初始化。
* 此方法具有阻塞效果,如果返回值迟迟不兑现,那么会导致依赖其的插件不会开始加载初始化
* @param state 渲染端主对象
* @param dependencies 此插件的依赖插件对象
* @param dataDeps 此插件的数据端依赖插件对象
* @param clientDeps 此插件的渲染端依赖插件对象
*/
afterLoad(
state: IClientCore,
dependencies: IClientPlugin<IClientPluginDefine>[]
dataDeps: IDataPlugin<IDataPluginDefine>[],
clientDeps: IClientPlugin<IClientPluginDefine>[]
): Promise<void>;
}