refactor: optimize plugin system
This commit is contained in:
		@@ -15,51 +15,51 @@ export class PluginCommandManager {
 | 
			
		||||
        process.on('plugin.after.disable', this.unregistryCommand.bind(this))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private registryCommand(pluginInstance: plugin.Plugin) {
 | 
			
		||||
        let cmds = getPluginCommandMetadata(pluginInstance)
 | 
			
		||||
        let tabs = getPluginTabCompleterMetadata(pluginInstance)
 | 
			
		||||
    public registryCommand(pluginInstance: plugin.Plugin, executor: any = pluginInstance) {
 | 
			
		||||
        let cmds = getPluginCommandMetadata(executor)
 | 
			
		||||
        let tabs = getPluginTabCompleterMetadata(executor)
 | 
			
		||||
        for (const cmd of cmds) {
 | 
			
		||||
            if (!this.ServerChecker.check(cmd.servers)) {
 | 
			
		||||
                console.debug(`[${pluginInstance.description.name}] ${cmd.target.constructor.name} incompatible command ${cmd.name} server(${cmd.servers}) ignore.`)
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
            for (let command of [cmd.name, ...cmd.alias]) {
 | 
			
		||||
                let [cmdExecutor, cmdCompleter] = this.generateAutoMainCommand(pluginInstance, cmd, tabs.get(command))
 | 
			
		||||
                let [cmdExecutor, cmdCompleter] = this.generateAutoMainCommand(pluginInstance, executor, cmd, tabs.get(command))
 | 
			
		||||
                this.CommandManager.on(pluginInstance, command, {
 | 
			
		||||
                    cmd: cmdExecutor.bind(pluginInstance),
 | 
			
		||||
                    tab: cmdCompleter?.bind(pluginInstance)
 | 
			
		||||
                    cmd: cmdExecutor.bind(executor),
 | 
			
		||||
                    tab: cmdCompleter?.bind(executor)
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private unregistryCommand(pluginInstance: plugin.Plugin) {
 | 
			
		||||
        let cmds = getPluginCommandMetadata(pluginInstance)
 | 
			
		||||
    public unregistryCommand(pluginInstance: plugin.Plugin, executor: any = pluginInstance) {
 | 
			
		||||
        let cmds = getPluginCommandMetadata(executor)
 | 
			
		||||
        for (const cmd of cmds) {
 | 
			
		||||
            if (!this.ServerChecker.check(cmd.servers)) {
 | 
			
		||||
                console.debug(`[${pluginInstance.description.name}] ${cmd.target.constructor.name} incompatible command ${cmd.name} server(${cmd.servers}) ignore.`)
 | 
			
		||||
                continue
 | 
			
		||||
            }
 | 
			
		||||
            for (let command of [cmd.name, ...cmd.alias]) {
 | 
			
		||||
                this.CommandManager.off(pluginInstance, command)
 | 
			
		||||
                this.CommandManager.off(executor, command)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private generateAutoMainCommand(pluginInstance: plugin.Plugin, cmd: interfaces.CommandMetadata, tab: interfaces.CommandMetadata) {
 | 
			
		||||
        let cmdExecutor = pluginInstance[cmd.executor]
 | 
			
		||||
        let cmdCompleter = tab ? pluginInstance[tab.executor] : undefined
 | 
			
		||||
        let cmdSubCache = Object.keys(pluginInstance.constructor.prototype).filter(s => s.startsWith('cmd')).map(s => s.substring(3))
 | 
			
		||||
    private generateAutoMainCommand(pluginInstance: plugin.Plugin, executor: any, cmd: interfaces.CommandMetadata, tab: interfaces.CommandMetadata) {
 | 
			
		||||
        let cmdExecutor = executor[cmd.executor]
 | 
			
		||||
        let cmdCompleter = tab ? executor[tab.executor] : undefined
 | 
			
		||||
        let cmdSubCache = Object.keys(executor.constructor.prototype).filter(s => s.startsWith('cmd')).map(s => s.substring(3))
 | 
			
		||||
        if (cmd.autoMain) {
 | 
			
		||||
            cmdExecutor = (sender: any, command: string, args: string[]) => {
 | 
			
		||||
                let subcommand = args[0]
 | 
			
		||||
                let cmdKey = 'cmd' + subcommand
 | 
			
		||||
                if (!cmdSubCache.includes(subcommand)) {
 | 
			
		||||
                    if (!pluginInstance[cmd.executor].apply(pluginInstance, [sender, command, args])) {
 | 
			
		||||
                    if (!executor[cmd.executor].apply(executor, [sender, command, args])) {
 | 
			
		||||
                        subcommand && pluginInstance.logger.sender(sender, `§4未知的命令: §b/${command} §c${subcommand}`)
 | 
			
		||||
                        pluginInstance.logger.sender(
 | 
			
		||||
                            sender,
 | 
			
		||||
                            pluginInstance['cmdhelp'] ?
 | 
			
		||||
                            executor['cmdhelp'] ?
 | 
			
		||||
                                `§6请执行 §b/${command} §ahelp §6查看帮助!` :
 | 
			
		||||
                                [
 | 
			
		||||
                                    `§6插件: §b${pluginInstance.description.name}`,
 | 
			
		||||
@@ -69,7 +69,7 @@ export class PluginCommandManager {
 | 
			
		||||
                    }
 | 
			
		||||
                    return
 | 
			
		||||
                }
 | 
			
		||||
                let subcommandexec = pluginInstance[cmdKey]
 | 
			
		||||
                let subcommandexec = executor[cmdKey]
 | 
			
		||||
                let permission: string
 | 
			
		||||
                if (cmd.permission && sender.hasPermission) {
 | 
			
		||||
                    if (typeof cmd.permission == "string") {
 | 
			
		||||
@@ -82,7 +82,7 @@ export class PluginCommandManager {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                args.shift()
 | 
			
		||||
                return subcommandexec.apply(pluginInstance, [sender, ...args])
 | 
			
		||||
                return subcommandexec.apply(executor, [sender, ...args])
 | 
			
		||||
            }
 | 
			
		||||
            let originCompleter = cmdCompleter
 | 
			
		||||
            cmdCompleter = (sender: any, command: string, args: string[]) => {
 | 
			
		||||
@@ -95,7 +95,7 @@ export class PluginCommandManager {
 | 
			
		||||
                    }
 | 
			
		||||
                    if (!sender.hasPermission(permission)) { return [] }
 | 
			
		||||
                }
 | 
			
		||||
                return (args.length == 1 ? cmdSubCache : []).concat(originCompleter?.apply(pluginInstance, [sender, command, args]) || [])
 | 
			
		||||
                return (args.length == 1 ? cmdSubCache : []).concat(originCompleter?.apply(executor, [sender, command, args]) || [])
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (!cmdCompleter) { console.debug(`[${pluginInstance.description.name}] command ${cmd.name} is not registry tabCompleter`) }
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,8 @@ export class PluginEventManager {
 | 
			
		||||
    @Autowired()
 | 
			
		||||
    private nativePluginChecker: server.NativePluginChecker
 | 
			
		||||
 | 
			
		||||
    private listenerMap = [];
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
        process.on('plugin.before.enable', this.registryListener.bind(this))
 | 
			
		||||
        process.on('plugin.after.disable', this.unregistryListener.bind(this))
 | 
			
		||||
@@ -20,8 +22,9 @@ export class PluginEventManager {
 | 
			
		||||
        return this.eventManager.mapEventName().toFixed(0)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private registryListener(pluginInstance: plugin.Plugin) {
 | 
			
		||||
        let events = getPluginListenerMetadata(pluginInstance)
 | 
			
		||||
    public registryListener(pluginInstance: plugin.Plugin, listener: any = pluginInstance) {
 | 
			
		||||
        let events = getPluginListenerMetadata(listener)
 | 
			
		||||
        let execes = []
 | 
			
		||||
        for (const event of events) {
 | 
			
		||||
            // ignore space listener
 | 
			
		||||
            if (!this.serverChecker.check(event.servers)) {
 | 
			
		||||
@@ -35,13 +38,25 @@ export class PluginEventManager {
 | 
			
		||||
            }
 | 
			
		||||
            // here must bind this to pluginInstance
 | 
			
		||||
            let exec = event.target[event.executor]
 | 
			
		||||
            let execBinded = exec.bind(pluginInstance)
 | 
			
		||||
            let execBinded = exec.bind(listener)
 | 
			
		||||
            execBinded.executor = event.executor
 | 
			
		||||
            exec.off = this.eventManager.listen(pluginInstance, event.name, execBinded, event.priority, event.ignoreCancel)
 | 
			
		||||
            execes.push(exec)
 | 
			
		||||
        }
 | 
			
		||||
        let off = () => {
 | 
			
		||||
            if (off['offed']) return
 | 
			
		||||
            off['offed'] = true
 | 
			
		||||
            execes.forEach((exec: { off: () => void }) => exec.off())
 | 
			
		||||
        }
 | 
			
		||||
        listener.off = off
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private unregistryListener(pluginInstance: plugin.Plugin) {
 | 
			
		||||
        this.eventManager.disable(pluginInstance)
 | 
			
		||||
    private unregistryListener(pluginInstance: plugin.Plugin, listener: any = pluginInstance) {
 | 
			
		||||
        if (listener && listener.off) {
 | 
			
		||||
            listener.off()
 | 
			
		||||
        }
 | 
			
		||||
        if (pluginInstance) {
 | 
			
		||||
            this.eventManager.disable(pluginInstance)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,9 @@ export * from './manager'
 | 
			
		||||
export * from './decorators'
 | 
			
		||||
export * from './interfaces'
 | 
			
		||||
 | 
			
		||||
export * from './event'
 | 
			
		||||
export * from './command'
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
    plugin as JSPlugin,
 | 
			
		||||
    cmd as Cmd,
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ export namespace interfaces {
 | 
			
		||||
    @injectable()
 | 
			
		||||
    export abstract class Plugin implements plugin.Plugin {
 | 
			
		||||
        public description: plugin.PluginMetadata
 | 
			
		||||
        public logger: Console
 | 
			
		||||
        public logger: MiaoScriptConsole
 | 
			
		||||
        @inject(server.Console)
 | 
			
		||||
        private Console: MiaoScriptConsole
 | 
			
		||||
 | 
			
		||||
@@ -28,6 +28,11 @@ export namespace interfaces {
 | 
			
		||||
            return dataFolder.getAbsolutePath()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public registryCommand(executor: any) { }
 | 
			
		||||
        public unregistryCommand(executor: any) { }
 | 
			
		||||
        public registryListener(listener: any) { }
 | 
			
		||||
        public unregistryListener(listener: any) { }
 | 
			
		||||
 | 
			
		||||
        public load() { }
 | 
			
		||||
        public enable() { }
 | 
			
		||||
        public disable() { }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user