diff --git a/README.MD b/README.MD new file mode 100644 index 00000000..2f63ac5f --- /dev/null +++ b/README.MD @@ -0,0 +1,22 @@ +# MiaoScript implement + +## MiaoScript JS 实现 + +项目 由 TypeScript 进行编写 然后编译至 `es5` 用于兼容 Java8 的 `Nashorn` + +### Project Path + +```txt +└─packages + ├─api 全平台兼容的接口 + ├─core 核心代码 用于引导加载 + ├─common 公共类库代码 例如 http reflect 模块 + ├─container IOC容器 用于注入具体实现 + ├─nashorn Nashorn 的类型定义 + ├─bukkit BukkitAPI内部实现 + ├─sponge SpongeAPI内部实现 + ├─plugin 插件管理器 + └─plugins 这里当然是插件啦 + ├─bukkit 只兼容Bukkit的插件 + └─sponge 只兼容Sponge的插件 +``` diff --git a/packages/common/src/reflect.ts b/packages/common/src/reflect.ts index 2a377443..6c375461 100644 --- a/packages/common/src/reflect.ts +++ b/packages/common/src/reflect.ts @@ -18,7 +18,9 @@ class Reflect { this.class = obj; } else { this.obj = obj; - this.class = obj.class; + if (obj !== null && obj !== undefined && obj.class) { + this.class = obj.class; + } } } @@ -30,7 +32,7 @@ class Reflect { return Java.from(declaredMethods(this.class)); } - field(name) { + field(name): Reflect { try { // Try getting a public field var field = this.class.field(name); @@ -41,36 +43,34 @@ class Reflect { } }; - fields(declared) { + fields(declared = false) { return Java.from(declared ? this.class.declaredFields : this.class.fields); } - values(declared) { + values(declared = false) { var cache = {}; - var feds = declared ? this.class.declaredFields : this.class.fields; - Java.from(feds).forEach(function(fed) { - cache[fed.name] = this.field(fed.name).get(); - }.bind(this)) + this.fields(declared).forEach(fed => cache[fed.name] = this.field(fed.name).get()) return cache; } - call(...args) { + call(...args): Reflect { var params = args.slice(1); - var method = declaredMethod(this.class, args[0], types(params)); - return on(method.invoke(this.get(), params)); + var method = accessible(declaredMethod(this.class, args[0], types(params))); + let result = method.invoke(this.get(), params); + return result && on(result); }; - get(...args) { + get(...args): Reflect | any { return args.length === 1 ? this.field(args[0]) : this.obj; }; // noinspection JSUnusedGlobalSymbols - set(name, value) { + set(name, value): Reflect { accessible(declaredField(this.class, name)).set(this.obj, value); return this; }; - create(...args) { + create(...args): Reflect { return on(declaredConstructor(this.class, args).newInstance(args)); }; } @@ -112,16 +112,17 @@ function declaredConstructor(clazz, param) { } function declaredField(clazz, name) { + var clazzt = clazz; var field = null; // noinspection JSUnresolvedVariable - while (clazz !== JavaObject.class) { + while (clazzt !== JavaObject.class) { try { - field = clazz.getDeclaredField(name); + field = clazzt.getDeclaredField(name); if (field !== null) { break; } } catch (e) { - clazz = clazz.getSuperclass(); + clazzt = clazzt.getSuperclass(); } } if (field === null) { @@ -136,7 +137,16 @@ function declaredMethod(clazz, name, clazzs) { try { methodCache[key] = clazz.getMethod(name, clazzs); } catch (ex) { - methodCache[key] = clazz.getDeclaredMethod(name, clazzs); + try { + methodCache[key] = clazz.getDeclaredMethod(name, clazzs); + } catch (ex) { + for (const m of Java.from(declaredMethods(clazz))) { + if (m.name == name) { + methodCache[key] = m; + break; + } + } + } } } return methodCache[key]; @@ -179,7 +189,7 @@ function mapMethod(target, source, name) { } function on(obj) { - if (!obj || !obj.class) { throw new TypeError(`参数 ${obj} 不是一个Java对象!`) } + // if (!obj || !obj.class) { throw new TypeError(`参数 ${obj} 不是一个Java对象!`) } return new Reflect(obj); } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 3aedbdd8..d039372a 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,28 +1,71 @@ import '@ms/nashorn' -import { plugin, server } from '@ms/api' -import { DefaultContainer as container } from '@ms/container' +import { plugin, server, task } from '@ms/api' +import { DefaultContainer as container, injectable, inject, postConstruct } from '@ms/container' import { PluginManagerImpl } from '@ms/plugin' -try { - Java.type("org.bukkit.Bukkit"); - require('@ms/bukkit'); -} catch (ex) { +@injectable() +class MiaoScriptCore { + @inject(server.Console) + private Console: Console; + @inject(task.TaskManager) + private taskManager: task.TaskManager; + @inject(plugin.PluginManager) + 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); + } + return () => this.disable(); + } + + loadServerConsole() { + //@ts-ignore + global.console = new this.Console(); + } + + loadTaskFunction() { + //@ts-ignore + global.setTimeout = (func: Function, tick: number) => this.taskManager.create(func).later(tick).run() + //@ts-ignore + global.setInterval = (func: Function, tick: number) => this.taskManager.create(func).timer(tick).run() + } + + loadPlugins() { + this.pluginManager.scan('plugins'); + this.pluginManager.build(container); + this.pluginManager.load(); + this.pluginManager.enable(); + } + + disable() { + this.pluginManager.disable(); + } } -try { - Java.type("org.spongepowered.api.Sponge"); - require('@ms/sponge'); -} catch (ex) { +function init() { + try { + Java.type("org.bukkit.Bukkit"); + require('@ms/bukkit'); + } catch (ex) { + } + + try { + Java.type("org.spongepowered.api.Sponge"); + require('@ms/sponge'); + } catch (ex) { + } + + container.bind(plugin.PluginManager).to(PluginManagerImpl).inSingletonScope(); + container.bind(MiaoScriptCore).to(MiaoScriptCore).inSingletonScope(); } -let Console = container.get(server.Console); -//@ts-ignore -global.console = new Console(); +init(); -container.bind(plugin.PluginManager).to(PluginManagerImpl).inSingletonScope(); - -let manager = container.get(plugin.PluginManager); -manager.scan('plugins'); -manager.load(container); -manager.enable(); +export default container.get(MiaoScriptCore).enable(); diff --git a/tsconfig.json b/tsconfig.json index dd9fbeaa..8ecbb4f7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,7 @@ "sourceMap": false, "declaration": true, "noImplicitAny": false, + "downlevelIteration": true, "allowUnreachableCode": true, "experimentalDecorators": true, "emitDecoratorMetadata": true,