diff --git a/packages/api/src/command.ts b/packages/api/src/command.ts index 6f75bd73..33f16f58 100644 --- a/packages/api/src/command.ts +++ b/packages/api/src/command.ts @@ -5,7 +5,7 @@ export namespace command { export abstract class Command { on(plugin: any, name: string, exec: { cmd: Function, tab?: Function }) { var cmd = this.create(plugin, name); - console.debug(`插件 ${plugin.description.name} 创建命令 ${name}(${cmd})...`) + console.debug(`[${plugin.description.name}] register command ${name}(${cmd})...`) if (exec.cmd && typeof exec.cmd === "function") { this.onCommand(plugin, cmd, exec.cmd); } else { @@ -16,7 +16,7 @@ export namespace command { } } off(plugin: any, name: string) { - console.debug(`插件 ${plugin.description.name} 注销命令 ${name}...`) + console.debug(`[${plugin.description.name}] unregister command ${name}...`) this.remove(plugin, name); } /** @@ -28,7 +28,7 @@ export namespace command { protected abstract onTabComplete(plugin: any, command: any, tabCompleter: Function); protected setExecutor(plugin: any, command: any, executor: Function) { - return (sender: any, _, command: string, args: string[]) => { + return (sender: any, _: any, command: string, args: string[]) => { try { return executor(sender, command, Java.from(args)); } catch (ex) { @@ -41,7 +41,7 @@ export namespace command { } protected setTabCompleter(plugin: any, command: any, tabCompleter: Function) { - return (sender: any, _, command: string, args: string[]) => { + return (sender: any, _: any, command: string, args: string[]) => { try { var token = args[args.length - 1]; var complete = tabCompleter(sender, command, Java.from(args)) || []; diff --git a/packages/api/src/console.ts b/packages/api/src/console.ts index 15143718..f2d6afcc 100644 --- a/packages/api/src/console.ts +++ b/packages/api/src/console.ts @@ -1,11 +1,23 @@ let Arrays = Java.type('java.util.Arrays'); let Level = Java.type('java.util.logging.Level'); -let ignoreLogPrefix = ['java.', 'net.minecraft.', 'org.bukkit.', 'jdk.nashorn.', 'io.netty.']; +let ignoreLogPrefix = ['java.', 'net.minecraft.', 'org.bukkit.', 'jdk.nashorn.', 'io.netty.', 'org.spongepowered.']; + +enum LogLevel { + ALL, + TRACE, + DEBUG, + INFO, + WARN, + ERROR, + FATAL, + OFF +} export class MiaoScriptConsole implements Console { Console: NodeJS.ConsoleConstructor; private _name: string = ''; + private _level: LogLevel = global.debug ? LogLevel.DEBUG : LogLevel.INFO; protected logger: any; protected prefix: string = '§6[§bMiaoScript§6]§r '; @@ -26,23 +38,28 @@ export class MiaoScriptConsole implements Console { this.prefix = `§6[§cMS§6][§b${name}§6]§r `; } } - log(...args): void { + log(...args: any[]): void { this.logger.info(this.name + args.join(' ')); } - info(...args) { + info(...args: any[]) { this.logger.info(this.name + args.join(' ')); - }; - warn(...args) { + } + warn(...args: any[]) { this.logger.warning(this.name + args.join(' ')); - }; - error(...args) { + } + error(...args: any[]) { this.logger.log(Level.SEVERE, this.name + args.join(' ')); - }; - debug(...args) { + } + debug(...args: any[]) { if (global.debug) { this.logger.info(this.name + '[DEBUG] ' + args.join(' ')); } - }; + } + trace(...args: any[]): void { + if (this._level <= LogLevel.TRACE) { + this.logger.info(this.name + '[TRACE] ' + args.join(' ')); + } + } sender(...args) { this.info(args) } @@ -53,10 +70,10 @@ export class MiaoScriptConsole implements Console { for (var i in obj) { this.logger(i, '=>', obj[i]) } - }; + } ex(ex: Error) { this.stack(ex).forEach(line => this.console(line)) - }; + } stack(ex: Error): string[] { var stack = ex.getStackTrace(); var cache = ['§4' + ex]; @@ -126,9 +143,6 @@ export class MiaoScriptConsole implements Console { timeLog(label?: string, ...data: any[]): void { throw new Error("Method not implemented."); } - trace(message?: any, ...optionalParams: any[]): void { - throw new Error("Method not implemented."); - } markTimeline(label?: string): void { throw new Error("Method not implemented."); } diff --git a/packages/api/src/event.ts b/packages/api/src/event.ts index fca55134..f0e744c1 100644 --- a/packages/api/src/event.ts +++ b/packages/api/src/event.ts @@ -9,6 +9,15 @@ import { injectable } from '@ms/container' const Thread = Java.type('java.lang.Thread'); export namespace event { + export enum EventPriority { + LOWEST = "LOWEST", + LOW = "LOW", + NORMAL = "NORMAL", + HIGH = "HIGH", + HIGHEST = "HIGHEST", + MONITOR = "MONITOR", + } + @injectable() export abstract class Event { private mapEvent = []; @@ -21,12 +30,13 @@ export namespace event { } /** - * 扫描包 org.bukkit.event 下的所有事件 - * 映射简写名称 org.bukkit.event.player.PlayerLoginEvent => playerloginevent + * abstract event map function + * ig: org.bukkit.event.player.PlayerLoginEvent => playerloginevent + * org.spongepowered.api.event.game.GameRegistryEvent.Register => gameregistryevent$register */ mapEventName() { if (this.baseEventDir === "") { - throw new Error("事件基础包名为空 无法进行事件映射!"); + throw new Error("base event dir is empty, can't map event name !"); } let count = 0; let jar = this.getJarFile(this.baseEventDir); @@ -34,15 +44,14 @@ export namespace event { while (entries.hasMoreElements()) { let entry = entries.nextElement(); let name = entry.name; - // 以 org/bukkit/event 开头 并且以 .class 结尾 if (name.startsWith(this.baseEventDir) && name.endsWith(".class")) { + // replace name to qualifiedName let qualifiedName = name.replaceAll('/', '.'); try { let clazz = base.getClass(qualifiedName.substring(0, qualifiedName.length - 6)); - // 继承于 org.bukkit.event.Event 访问符为Public if (this.isValidEvent(clazz)) { let simpleName = this.class2Name(clazz).toLowerCase(); - console.debug(`Mapping Event [${clazz.canonicalName}] => ${simpleName}`); + console.trace(`Mapping Event [${clazz.canonicalName}] => ${simpleName}`); this.mapEvent[simpleName] = clazz; count++; } @@ -63,11 +72,11 @@ export namespace event { throw new Error(`Can't Mapping Event Because not found Resources ${resource}!`) } - class2Name(clazz) { + class2Name(clazz: any) { return clazz.simpleName; } - name2Class(name, event) { + name2Class(name: any, event: string) { var eventCls = this.mapEvent[event.toLowerCase()] || this.mapEvent[event.toLowerCase() + 'event']; if (!eventCls) { try { @@ -75,7 +84,7 @@ export namespace event { this.mapEvent[event] = eventCls; } catch (ex) { console.console(`§6插件 §b${name} §6注册事件 §c${event} §6失败 §4事件未找到!`); - console.ex(new Error(`插件 ${name} 注册事件 ${event} 失败 事件未找到!`)); + console.ex(new Error(`Plugin ${name} register event error ${event} not found!`)); return; } } @@ -83,7 +92,7 @@ export namespace event { } execute(name, exec, eventCls) { - return (...args) => { + return (...args: any[]) => { try { var time = new Date().getTime() exec(args[args.length - 1]); @@ -100,31 +109,31 @@ export namespace event { /** * 添加事件监听 - * @param plugin - * @param event + * @param plugin {any} + * @param event {string} * @param exec {function} - * @param priority [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR] + * @param priority {string} [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR] * @param ignoreCancel */ - listen(plugin, event, exec, priority = 'NORMAL', ignoreCancel = false) { + listen(plugin: any, event: string, exec: () => void, priority: EventPriority = EventPriority.NORMAL, ignoreCancel = false) { if (!plugin || !plugin.description || !plugin.description.name) throw new TypeError('插件名称为空 请检查传入参数!'); var name = plugin.description.name; var eventCls = this.name2Class(name, event); if (!eventCls) { return; } if (typeof priority === 'boolean') { ignoreCancel = priority; - priority = 'NORMAL'; + priority = EventPriority.NORMAL; } - priority = priority || 'NORMAL'; + priority = priority || EventPriority.NORMAL; ignoreCancel = ignoreCancel || false; // noinspection JSUnusedGlobalSymbols var listener = this.register(eventCls, this.execute(name, exec, eventCls), priority, ignoreCancel); var listenerMap = this.listenerMap; - // 添加到缓存 用于关闭插件的时候关闭事件 + // add to cache Be used for close plugin to close event if (!listenerMap[name]) listenerMap[name] = []; var offExec = () => { this.unregister(eventCls, listener); - console.debug(`插件 ${name} 注销事件 ${this.class2Name(eventCls)}`); + console.debug(`[${name}] unregister event ${this.class2Name(eventCls)}`); }; var off = { event: eventCls, @@ -133,7 +142,7 @@ export namespace event { }; listenerMap[name].push(off); // noinspection JSUnresolvedVariable - console.debug(`插件 ${name} 注册事件 ${this.class2Name(eventCls)} => ${exec.name || '匿名方法'}`); + console.debug(`[${name}] register event ${this.class2Name(eventCls)} => ${exec.name || '[anonymous]'}`); return off; } diff --git a/packages/api/src/interfaces/server.ts b/packages/api/src/interfaces/server.ts index ae6d29bf..89fc7f38 100644 --- a/packages/api/src/interfaces/server.ts +++ b/packages/api/src/interfaces/server.ts @@ -1,7 +1,23 @@ export namespace server { + /** + * Runtime ServerType + */ export const ServerType = Symbol("ServerType"); + /** + * Runtime Console + */ export const Console = Symbol("Console"); + /** + * MiaoScript Server + */ export const Server = Symbol("Server"); + /** + * Runtime Server Instance + */ + export const ServerInstance = Symbol("ServerInstance"); + /** + * MiaoScript Server + */ export interface Server { getVersion(): string; getPlayer(name: string): any; diff --git a/packages/bukkit/src/console.ts b/packages/bukkit/src/console.ts index 8c88377d..52cf827f 100644 --- a/packages/bukkit/src/console.ts +++ b/packages/bukkit/src/console.ts @@ -5,7 +5,7 @@ let Bukkit = org.bukkit.Bukkit; export class BukkitConsole extends MiaoScriptConsole { sender(sender, ...args) { if (!(sender instanceof Java.type('org.bukkit.command.CommandSender'))) { - this.error("第一个参数未实现 org.bukkit.command.CommandSender 无法发送消息!") + this.error(`First parameter ${sender} not instanceof org.bukkit.command.CommandSender can't send message!`) return; } if (Object.prototype.toString.call(args[0]) === "[object Array]") { @@ -14,7 +14,7 @@ export class BukkitConsole extends MiaoScriptConsole { sender.sendMessage(this.prefix + args.join(' ')); } } - console(...args): void { + console(...args: string[]): void { this.sender(Bukkit.getConsoleSender(), args.join(' ')); } } diff --git a/packages/bukkit/src/event.ts b/packages/bukkit/src/event.ts index 4c85d0dc..98a911f9 100644 --- a/packages/bukkit/src/event.ts +++ b/packages/bukkit/src/event.ts @@ -29,7 +29,7 @@ export class BukkitEvent extends event.Event { // 不是抽象类 !Modifier.isAbstract(clazz.getModifiers()); } - register(eventCls: any, exec: Function, priority: any, ignoreCancel: boolean) { + register(eventCls: any, exec: Function, priority: event.EventPriority, ignoreCancel: boolean) { let listener = new Listener({}); Bukkit.pluginManager.registerEvent( eventCls, diff --git a/packages/bukkit/src/index.ts b/packages/bukkit/src/index.ts index 8bc77c48..fad3357a 100644 --- a/packages/bukkit/src/index.ts +++ b/packages/bukkit/src/index.ts @@ -14,7 +14,6 @@ let Bukkit = Java.type("org.bukkit.Bukkit"); container.bind(server.Console).toConstantValue(BukkitConsole); container.bind(server.ServerType).toConstantValue(BukkitServerType); -container.bind(plugin.PluginInstance).toConstantValue(Bukkit.pluginManager.getPlugin('MiaoScript')); container.bind(event.Event).to(BukkitEvent).inSingletonScope(); container.bind(server.Server).to(BukkitServer).inSingletonScope(); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 93b4daf3..1f85260f 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,6 +1,6 @@ import '@ms/nashorn' -import { plugin, server, task } from '@ms/api' +import { plugin, server, task, MiaoScriptConsole } from '@ms/api' import { PluginManagerImpl } from '@ms/plugin' import { XMLHttpRequest as xhr } from '@ms/ployfill' import { DefaultContainer as container, injectable, inject, postConstruct } from '@ms/container' @@ -17,18 +17,13 @@ class MiaoScriptCore { private pluginManager: plugin.PluginManager; enable() { - try { - this.loadServerConsole(); - this.loadTaskFunction(); - this.loadPlugins(); - } catch (error) { - console.console(`§cMiaoScript start error please contact plugin author!`); - console.ex(error); - } + this.loadServerConsole(); + this.loadTaskFunction(); + this.loadPlugins(); console.log('MiaoScript engine loading completed... Done (' + (new Date().getTime() - startTime) / 1000 + 's)!'); return () => this.disable(); } - + loadServerConsole() { // @ts-ignore console = new this.Console(); @@ -54,21 +49,38 @@ class MiaoScriptCore { } } -function init() { +function detectServer(){ + let type = 'unknow' try { Java.type("org.bukkit.Bukkit"); - require('@ms/bukkit'); + type = 'bukkit'; + console.info(`Detect Bukkit Compatible set ServerType to ${type} ...`) } catch (ex) { } - try { Java.type("org.spongepowered.api.Sponge"); - require('@ms/sponge'); + type = 'sponge'; + console.info(`Detect Sponge Compatible set ServerType to ${type} ...`) } catch (ex) { } + try { + Java.type("net.md_5.bungee.api.ProxyServer"); + type = 'bungee'; + console.info(`Detect Sponge Compatible set ServerType to ${type} ...`) + } catch (ex) { + } + if (type === 'unknow') { throw Error('Unknow Server Type...') } + return type; +} +function init() { + console.info('Initialization MiaoScript Core Package @ms/core. Please wait...') + container.bind(plugin.PluginInstance).toConstantValue(base.getInstance()); + let type = detectServer(); + require(`@ms/${type}`); container.bind(plugin.PluginManager).to(PluginManagerImpl).inSingletonScope(); container.bind(MiaoScriptCore).to(MiaoScriptCore).inSingletonScope(); + console.log(`Initialization MiaoScript Sub Package @ms/${type} loading completed... cost (${(new Date().getTime() - startTime) / 1000}s)!`); } init(); diff --git a/packages/plugin/src/manager.ts b/packages/plugin/src/manager.ts index 6f9fed36..62b34d13 100644 --- a/packages/plugin/src/manager.ts +++ b/packages/plugin/src/manager.ts @@ -111,7 +111,7 @@ export class PluginManagerImpl implements plugin.PluginManager { * 更新插件 * @param path */ - private checkUpdateFolder(path) { + private checkUpdateFolder(path: any) { var update = fs.file(path, "update") if (!update.exists()) { update.mkdirs() diff --git a/packages/sponge/src/command.ts b/packages/sponge/src/command.ts index 93017f0f..398ead04 100644 --- a/packages/sponge/src/command.ts +++ b/packages/sponge/src/command.ts @@ -12,11 +12,12 @@ var Optional = Java.type('java.util.Optional'); class SimpleCommandCallable { public callable: any; - + private name: string; private executor: Function; private tabCompleter: Function; constructor(command: string, description: string = '暂无描述!') { + this.name = command; this.callable = new CommandCallable({ //CommandResult process(CommandSource source, String arguments) throws CommandException; process: (sender: any, args) => { @@ -47,7 +48,7 @@ class SimpleCommandCallable { setExecutor = (executor: Function) => this.executor = executor; setTabCompleter = (tabCompleter: Function) => this.tabCompleter = tabCompleter; - toString = () => `Sponge SimpleCommandCallable` + toString = () => `Sponge SimpleCommandCallable(${this.name})` } @injectable() diff --git a/packages/sponge/src/event.ts b/packages/sponge/src/event.ts index 9af14daf..53797cdc 100644 --- a/packages/sponge/src/event.ts +++ b/packages/sponge/src/event.ts @@ -40,7 +40,7 @@ export class SpongeEvent extends event.Event { class2Name(clazz: any) { return clazz.name.substring(clazz.name.lastIndexOf(".") + 1); } - register(eventCls: any, exec: Function, priority: any = 'NORMAL', ignoreCancel: boolean = true) { + register(eventCls: any, exec: Function, priority: event.EventPriority = event.EventPriority.NORMAL, ignoreCancel: boolean = true) { var listener = new EventListener({ handle: exec }); diff --git a/packages/sponge/src/index.ts b/packages/sponge/src/index.ts index 6c19b9c9..3a85da42 100644 --- a/packages/sponge/src/index.ts +++ b/packages/sponge/src/index.ts @@ -14,7 +14,6 @@ let Sponge = Java.type("org.spongepowered.api.Sponge"); container.bind(server.Console).toConstantValue(SpongeConsole); container.bind(server.ServerType).toConstantValue(SpongeServerType); -container.bind(plugin.PluginInstance).toConstantValue(Sponge.getPluginManager().getPlugin('MiaoScript').orElse(null)); container.bind(event.Event).to(SpongeEvent).inSingletonScope(); container.bind(server.Server).to(SpongeServer).inSingletonScope();