fix: command registry error

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
MiaoWoo 2020-09-24 10:33:16 +08:00
parent 9c137574f5
commit afd04ed972
8 changed files with 46 additions and 41 deletions

View File

@ -62,9 +62,9 @@ export namespace command {
var complete = tabCompleter(sender, command, Java.from(args)) || [] var complete = tabCompleter(sender, command, Java.from(args)) || []
return this.copyPartialMatches(complete, token) return this.copyPartialMatches(complete, token)
} catch (ex) { } catch (ex) {
console.i18n("ms.api.command.tab.completer.error", { sender: sender.name, plugin: plugin.description.name, command, args: Java.from(args).join(' '), ex }) console.i18n("ms.api.command.tab.completer.error", { player: sender.name, plugin: plugin.description.name, command, args: Java.from(args).join(' '), ex })
console.ex(ex) console.ex(ex)
console.sender(sender, [i18n.translate("ms.api.command.tab.completer.error", { sender: sender.name, plugin: plugin.description.name, command, args: Java.from(args).join(' '), ex }), ...console.stack(ex)]) console.sender(sender, [i18n.translate("ms.api.command.tab.completer.error", { player: sender.name, plugin: plugin.description.name, command, args: Java.from(args).join(' '), ex }), ...console.stack(ex)])
return [] return []
} }
} }

View File

@ -2,7 +2,7 @@
import "reflect-metadata" import "reflect-metadata"
import { initContainer, getContainer } from './decorators' import { initContainer, getContainer } from './decorators'
import { interfaces, Container } from 'inversify' import { interfaces, Container, inject, named } from 'inversify'
import { fluentProvide } from 'inversify-binding-decorators' import { fluentProvide } from 'inversify-binding-decorators'
import { ioc } from "./constants" import { ioc } from "./constants"
@ -59,22 +59,20 @@ export const JSClass = (className: string) => {
* *
* @param className * @param className
*/ */
export const Autowired = (className?: string | any) => { export const Autowired = (className?: any) => {
return function (target: any, propertyKey: string, index?: number) { return function (target: any, propertyKey: string, index?: number) {
let container = getContainer() let container = getContainer()
if (className instanceof Symbol || className instanceof Function) {
return inject(className)(target, propertyKey, index)
}
let type = Reflect.getMetadata('design:type', target, propertyKey) let type = Reflect.getMetadata('design:type', target, propertyKey)
if (type && type !== Object) { if (type && type !== Object) {
try { inject(type)(target, propertyKey, index)
return target[propertyKey] = container.getNamed(type, className || propertyKey) named(className || propertyKey)(target, propertyKey, index)
} catch (error) { } else if (container.isBound(ioc.Autowired)) {
try {
return target[propertyKey] = container.get(type)
} catch (error) {
}
}
}
if (container.isBound(ioc.Autowired)) {
target[propertyKey] = container.getNamed(ioc.Autowired, className || propertyKey) target[propertyKey] = container.getNamed(ioc.Autowired, className || propertyKey)
} else {
throw new Error(`No matching bindings found for target: ${target.constructor.name} type: ${type} named: ${className || propertyKey}`)
} }
} }
} }

View File

@ -1,5 +1,5 @@
import { command, plugin, server } from '@ccms/api' import { command, plugin, server } from '@ccms/api'
import { provideSingleton, postConstruct, inject } from '@ccms/container' import { provideSingleton, inject } from '@ccms/container'
import { getPluginCommandMetadata, getPluginTabCompleterMetadata } from './utils' import { getPluginCommandMetadata, getPluginTabCompleterMetadata } from './utils'
@provideSingleton(PluginCommandManager) @provideSingleton(PluginCommandManager)
@ -17,13 +17,19 @@ export class PluginCommandManager {
private registryCommand(pluginInstance: plugin.Plugin) { private registryCommand(pluginInstance: plugin.Plugin) {
let cmds = getPluginCommandMetadata(pluginInstance) let cmds = getPluginCommandMetadata(pluginInstance)
let tabs = getPluginTabCompleterMetadata(pluginInstance) let tabs = getPluginTabCompleterMetadata(pluginInstance)
for (const [_, cmd] of cmds) { for (const cmd of cmds) {
let tab = tabs.get(cmd.name) let tab = tabs.get(cmd.name)
if (!this.ServerChecker.check(cmd.servers)) { continue } if (!this.ServerChecker.check(cmd.servers)) {
this.CommandManager.on(pluginInstance, cmd.name, { console.debug(`[${pluginInstance.description.name}] ${cmd.target.constructor.name} incompatible command ${cmd.name} server(${cmd.servers}) ignore.`)
continue
}
let exec = {
cmd: pluginInstance[cmd.executor].bind(pluginInstance), cmd: pluginInstance[cmd.executor].bind(pluginInstance),
tab: tab ? pluginInstance[tab.executor].bind(pluginInstance) : undefined tab: tab ? pluginInstance[tab.executor].bind(pluginInstance) : undefined
}) }
for (let command of [cmd.name, ...cmd.alias]) {
this.CommandManager.on(pluginInstance, command, exec)
}
} }
} }

View File

@ -30,13 +30,11 @@ export function plugin(metadata: pluginApi.PluginMetadata | any) {
export function cmd(metadata: interfaces.CommandMetadata = {}) { export function cmd(metadata: interfaces.CommandMetadata = {}) {
return function (target: any, key: string, value: any) { return function (target: any, key: string, value: any) {
metadata.name = metadata.name || key metadata.name = metadata.name || key
metadata.alias = metadata.alias || []
metadata.target = target metadata.target = target
metadata.executor = key metadata.executor = key
metadata.paramtypes = Reflect.getMetadata("design:paramtypes", target, key) metadata.paramtypes = Reflect.getMetadata("design:paramtypes", target, key)
const previousMetadata: Map<string, interfaces.CommandMetadata> = getPluginCommandMetadata(target) Reflect.defineMetadata(METADATA_KEY.cmd, [metadata, ...getPluginCommandMetadata(target)], target.constructor)
previousMetadata.set(metadata.name, metadata)
metadata.alias?.forEach((name) => previousMetadata.set(name, metadata))
Reflect.defineMetadata(METADATA_KEY.cmd, previousMetadata, target.constructor)
} }
} }
@ -48,10 +46,11 @@ export function tab(metadata: interfaces.CommandMetadata = {}) {
return function (target: any, key: string, value: any) { return function (target: any, key: string, value: any) {
metadata.name = metadata.name || (key.startsWith('tab') ? key.split('tab', 2)[1] : key) metadata.name = metadata.name || (key.startsWith('tab') ? key.split('tab', 2)[1] : key)
if (!metadata.name) { return } if (!metadata.name) { return }
metadata.alias = metadata.alias || []
metadata.target = target metadata.target = target
metadata.executor = key metadata.executor = key
metadata.paramtypes = Reflect.getMetadata("design:paramtypes", target, key) metadata.paramtypes = Reflect.getMetadata("design:paramtypes", target, key)
const previousMetadata: Map<string, interfaces.CommandMetadata> = getPluginTabCompleterMetadata(target) let previousMetadata = getPluginTabCompleterMetadata(target)
previousMetadata.set(metadata.name, metadata) previousMetadata.set(metadata.name, metadata)
metadata.alias?.forEach((name) => previousMetadata.set(name, metadata)) metadata.alias?.forEach((name) => previousMetadata.set(name, metadata))
Reflect.defineMetadata(METADATA_KEY.tab, previousMetadata, target.constructor) Reflect.defineMetadata(METADATA_KEY.tab, previousMetadata, target.constructor)
@ -67,8 +66,7 @@ export function listener(metadata: interfaces.ListenerMetadata = {}) {
metadata.name = metadata.name || key metadata.name = metadata.name || key
metadata.target = target metadata.target = target
metadata.executor = key metadata.executor = key
const previousMetadata: interfaces.ListenerMetadata[] = getPluginListenerMetadata(target) Reflect.defineMetadata(METADATA_KEY.listener, [metadata, ...getPluginListenerMetadata(target)], target.constructor)
Reflect.defineMetadata(METADATA_KEY.listener, [metadata, ...previousMetadata], target.constructor)
Reflect.defineMetadata(METADATA_KEY.listener, metadata, target[key]) Reflect.defineMetadata(METADATA_KEY.listener, metadata, target[key])
} }
} }
@ -79,7 +77,7 @@ export function config(metadata: interfaces.ConfigMetadata = {}) {
metadata.variable = key metadata.variable = key
metadata.version = metadata.version ?? 1 metadata.version = metadata.version ?? 1
metadata.format = metadata.format ?? 'yml' metadata.format = metadata.format ?? 'yml'
const previousMetadata: Map<string, interfaces.ConfigMetadata> = getPluginConfigMetadata(target) let previousMetadata = getPluginConfigMetadata(target)
previousMetadata.set(metadata.name, metadata) previousMetadata.set(metadata.name, metadata)
Reflect.defineMetadata(METADATA_KEY.config, previousMetadata, target.constructor) Reflect.defineMetadata(METADATA_KEY.config, previousMetadata, target.constructor)
} }
@ -90,8 +88,7 @@ function stage(stage: string) {
return function (target: any, key: string, value: any) { return function (target: any, key: string, value: any) {
metadata.name = metadata.name || key metadata.name = metadata.name || key
metadata.executor = key metadata.executor = key
const previousMetadata: interfaces.ExecMetadata[] = getPluginStageMetadata(target, stage) Reflect.defineMetadata(METADATA_KEY.stage[stage], [metadata, ...getPluginStageMetadata(target, stage)], target.constructor)
Reflect.defineMetadata(METADATA_KEY.stage[stage], [metadata, ...previousMetadata], target.constructor)
} }
} }
} }

View File

@ -18,7 +18,10 @@ export class PluginEventManager {
let events = getPluginListenerMetadata(pluginInstance) let events = getPluginListenerMetadata(pluginInstance)
for (const event of events) { for (const event of events) {
// ignore space listener // ignore space listener
if (!this.ServerChecker.check(event.servers)) { continue } if (!this.ServerChecker.check(event.servers)) {
console.debug(`[${pluginInstance.description.name}] ${event.target.constructor.name} incompatible event ${event.name} server(${event.servers}) ignore.`)
continue
}
// here must bind this to pluginInstance // here must bind this to pluginInstance
let exec = event.target[event.executor] let exec = event.target[event.executor]
let execBinded = exec.bind(pluginInstance) let execBinded = exec.bind(pluginInstance)

View File

@ -37,10 +37,10 @@ function getPluginMetadata(target: any) {
} }
function getPluginCommandMetadata(target: any) { function getPluginCommandMetadata(target: any) {
let commandMetadata: Map<string, interfaces.CommandMetadata> = Reflect.getMetadata( let commandMetadata: interfaces.CommandMetadata[] = Reflect.getMetadata(
METADATA_KEY.cmd, METADATA_KEY.cmd,
target.constructor target.constructor
) || new Map<string, interfaces.CommandMetadata>() ) || []
return commandMetadata return commandMetadata
} }

View File

@ -49,11 +49,11 @@ class SimpleCommandCallable {
this.callable = new CommandCallable({ this.callable = new CommandCallable({
//CommandResult process(CommandSource source, String arguments) throws CommandException //CommandResult process(CommandSource source, String arguments) throws CommandException
process: (sender: any, args) => { process: (sender: any, args) => {
return this.executor(sender, '', command, Java.to(args.split(" ").filter(e => e))) ? CommandResult.success() : CommandResult.empty() return this.executor(sender, '', command, Java.to(args.split(" "))) ? CommandResult.success() : CommandResult.empty()
}, },
//List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) throws CommandException //List<String> getSuggestions(CommandSource source, String arguments, @Nullable Location<World> targetPosition) throws CommandException
getSuggestions: (sender: any, args, target) => { getSuggestions: (sender: any, args, target) => {
return this.tabCompleter(sender, '', command, Java.to(args.split(" ").filter(e => e))) return this.tabCompleter(sender, '', command, Java.to(args.split(" ")))
}, },
//boolean testPermission(CommandSource source) //boolean testPermission(CommandSource source)
testPermission: () => { testPermission: () => {

View File

@ -3,13 +3,14 @@
import { server } from '@ccms/api' import { server } from '@ccms/api'
import { Container } from '@ccms/container' import { Container } from '@ccms/container'
import { SpongeConsole } from './console'; import { SpongeConsole } from './console'
import './event'; import './chat'
import './server'; import './task'
import './command'; import './event'
import './channel'; import './server'
import './task'; import './command'
import './channel'
export default function SpongeImpl(container: Container) { export default function SpongeImpl(container: Container) {
container.bind(server.Console).toConstantValue(SpongeConsole); container.bind(server.Console).toConstantValue(SpongeConsole)
} }