Compare commits

...

7 Commits

Author SHA1 Message Date
edf8410cd1 v0.5.0 2020-04-26 10:24:49 +08:00
b0b4bbcc2b feat: merge stage exec & catch error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-04-26 10:19:44 +08:00
e68689c560 feat: update plugin & websocket
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-04-24 16:42:36 +08:00
58353cb5b8 feat: support stage decorators and remove space plugin floder
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-04-24 15:38:00 +08:00
8c6b75ff10 fix: netty inject error
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-04-24 13:05:46 +08:00
d53287fc51 feat: support base64 source map
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-04-24 13:04:45 +08:00
13a3611ebd feat: update MiaoConsole
Signed-off-by: MiaoWoo <admin@yumc.pw>
2020-04-07 13:39:35 +08:00
39 changed files with 357 additions and 237 deletions

View File

@@ -1,5 +1,5 @@
{ {
"version": "0.4.2", "version": "0.5.0",
"useWorkspaces": true, "useWorkspaces": true,
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/api", "name": "@ms/api",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript api package", "description": "MiaoScript api package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -22,11 +22,13 @@
"test": "echo \"Error: run tests from root\" && exit 1" "test": "echo \"Error: run tests from root\" && exit 1"
}, },
"dependencies": { "dependencies": {
"@ms/container": "^0.4.0", "@ms/container": "^0.5.0",
"@ms/ployfill": "^0.4.2", "@ms/ployfill": "^0.5.0",
"base64-js": "^1.3.1",
"source-map-builder": "^0.0.7" "source-map-builder": "^0.0.7"
}, },
"devDependencies": { "devDependencies": {
"@types/base64-js": "^1.2.5",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"typescript": "^3.8.3" "typescript": "^3.8.3"

View File

@@ -1,10 +1,9 @@
import i18m from '@ms/i18n' import i18m from '@ms/i18n'
import { SourceMapBuilder } from 'source-map-builder' import { SourceMapBuilder } from 'source-map-builder'
import * as base64 from 'base64-js'
const Arrays = Java.type('java.util.Arrays'); const Arrays = Java.type('java.util.Arrays');
const Level = Java.type('java.util.logging.Level'); const Level = Java.type('java.util.logging.Level');
const JavaString = Java.type('java.lang.String');
const Files = Java.type('java.nio.file.Files');
const Paths = Java.type('java.nio.file.Paths'); const Paths = Java.type('java.nio.file.Paths');
const ignoreLogPrefix = ['java.', 'net.minecraft.', 'org.bukkit.', 'jdk.nashorn.', 'io.netty.', 'org.spongepowered.']; const ignoreLogPrefix = ['java.', 'net.minecraft.', 'org.bukkit.', 'jdk.nashorn.', 'io.netty.', 'org.spongepowered.'];
@@ -23,6 +22,7 @@ export class MiaoScriptConsole implements Console {
Console: NodeJS.ConsoleConstructor; Console: NodeJS.ConsoleConstructor;
private sourceMaps: { [key: string]: SourceMapBuilder } = {}; private sourceMaps: { [key: string]: SourceMapBuilder } = {};
private sourceFileMaps: { [key: string]: string } = {};
private _name: string = ''; private _name: string = '';
private _level: LogLevel = LogLevel.INFO; private _level: LogLevel = LogLevel.INFO;
@@ -83,7 +83,7 @@ export class MiaoScriptConsole implements Console {
this.console(i18m.translate(name, param)) this.console(i18m.translate(name, param))
} }
object(obj) { object(obj) {
for (var i in obj) { for (const i in obj) {
this.info(i, '=>', obj[i]) this.info(i, '=>', obj[i])
} }
} }
@@ -93,23 +93,31 @@ export class MiaoScriptConsole implements Console {
readSourceMap(fileName: string, lineNumber: number) { readSourceMap(fileName: string, lineNumber: number) {
try { try {
if (fileName.endsWith('js')) { if (fileName.endsWith('js')) {
var file = Paths.get(fileName + '.map');
if (this.sourceMaps[fileName] === undefined) { if (this.sourceMaps[fileName] === undefined) {
if (file.toFile().exists()) { this.sourceMaps[fileName] = null
var sourceMapObj = JSON.parse(new JavaString(Files.readAllBytes(file), "UTF-8")) let sourceLine = base.read(fileName).split('\n');
this.sourceMaps[fileName] = new SourceMapBuilder(sourceMapObj) let lastLine = sourceLine[sourceLine.length - 1]
if (lastLine.startsWith('//# sourceMappingURL=')) {
let sourceContent = null;
let sourceMappingURL = lastLine.split('sourceMappingURL=', 2)[1];
if (sourceMappingURL.startsWith('data:application/json;base64,')) {
sourceContent = String.fromCharCode(...Array.from(base64.toByteArray(sourceMappingURL.split(',', 2)[1])))
} else if (sourceMappingURL.startsWith('http')) {
// TODO
} else { } else {
this.sourceMaps[fileName] = null; let file = Paths.get(Paths.get(fileName, '..', sourceMappingURL).toFile().getCanonicalPath()).toFile();
if (file.exists()) { sourceContent = base.read(file) }
}
if (sourceContent) {
this.sourceMaps[fileName] = new SourceMapBuilder(JSON.parse(sourceContent))
this.sourceFileMaps[fileName] = Paths.get(fileName, '..', this.sourceMaps[fileName].sources[0]).toFile().getCanonicalPath();
}
} }
} }
if (this.sourceMaps[fileName]) { if (this.sourceMaps[fileName]) {
var sourceMapping = this.sourceMaps[fileName].getSource(lineNumber, 25, true); let sourceMapping = this.sourceMaps[fileName].getSource(lineNumber, 25, true, true);
if (sourceMapping) { fileName = this.sourceFileMaps[fileName]
if (lineNumber != sourceMapping.mapping.sourceLine) { if (sourceMapping && lineNumber != sourceMapping.mapping.sourceLine) { lineNumber = sourceMapping.mapping.sourceLine; }
fileName = fileName.replace(".js", ".ts");
lineNumber = sourceMapping.mapping.sourceLine;
}
}
} }
} }
} catch (error) { } catch (error) {
@@ -121,26 +129,26 @@ export class MiaoScriptConsole implements Console {
} }
} }
stack(ex: Error): string[] { stack(ex: Error): string[] {
var stack = ex.getStackTrace(); let stack = ex.getStackTrace();
var cache = ['§c' + ex]; let cache = ['§c' + ex];
//@ts-ignore //@ts-ignore
if (stack.class) { if (stack.class) {
stack = Arrays.asList(stack) stack = Arrays.asList(stack)
} }
stack.forEach(trace => { stack.forEach(trace => {
if (trace.className.startsWith('<')) { if (trace.className.startsWith('<')) {
var { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber) let { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber)
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] } if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
cache.push(` §e->§c ${fileName} => §4${trace.methodName}:${lineNumber}`) cache.push(` §e->§c ${fileName} => §4${trace.methodName}:${lineNumber}`)
} else { } else {
var className = trace.className; let className = trace.className;
var fileName = trace.fileName as string; var fileName = trace.fileName as string;
if (className.startsWith('jdk.nashorn.internal.scripts')) { if (className.startsWith('jdk.nashorn.internal.scripts')) {
className = className.substr(className.lastIndexOf('$') + 1) className = className.substr(className.lastIndexOf('$') + 1)
var { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber) var { fileName, lineNumber } = this.readSourceMap(trace.fileName, trace.lineNumber)
if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] } if (fileName.startsWith(root)) { fileName = fileName.split(root)[1] }
} else { } else {
for (var prefix in ignoreLogPrefix) { for (let prefix in ignoreLogPrefix) {
if (className.startsWith(ignoreLogPrefix[prefix])) { if (className.startsWith(ignoreLogPrefix[prefix])) {
return; return;
} }

View File

@@ -0,0 +1,16 @@
export namespace constants {
export namespace Reflect {
export const Method = {
getServerConnection: [/*spigot 1.8.8*/'aq',/*spigot 1.12.2*/ 'an', /*spigot 1.14.4+*/'getServerConnection', /*catserver 1.12.2*/'func_147137_ag']
}
export const Field = {
listeningChannels: [/*spigot 1.8.8-1.12.2*/'g', /*spigot 1.14.4*/'f', /*spigot 1.15.2+*/'listeningChannels', /*catserver 1.12.2*/'field_151274_e']
}
}
export enum ServerType {
Bukkit = 'bukkit',
Sponge = 'sponge',
Nukkit = 'nukkit',
Bungee = 'bungee'
}
}

View File

@@ -62,8 +62,8 @@ export namespace event {
return count; return count;
} }
getJarFile(resource: string) { getJarFile(resource: string, loader?: any) {
let dirs = Thread.currentThread().getContextClassLoader().getResources(resource); let dirs = (loader || Thread.currentThread().getContextClassLoader()).getResources(resource);
if (dirs.hasMoreElements()) { if (dirs.hasMoreElements()) {
let url = dirs.nextElement(); let url = dirs.nextElement();
if (url.protocol === "jar") { return url.openConnection().jarFile; } if (url.protocol === "jar") { return url.openConnection().jarFile; }

View File

@@ -4,4 +4,5 @@ export * from './event'
export * from './console' export * from './console'
export * from './channel' export * from './channel'
export * from './command' export * from './command'
export * from './constants'
export * from './interfaces' export * from './interfaces'

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/bukkit", "name": "@ms/bukkit",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript bukkit package", "description": "MiaoScript bukkit package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -27,8 +27,8 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/api": "^0.4.2", "@ms/api": "^0.5.0",
"@ms/common": "^0.4.2", "@ms/common": "^0.5.0",
"@ms/container": "^0.4.0" "@ms/container": "^0.5.0"
} }
} }

View File

@@ -19,7 +19,7 @@ export class BukkitEvent extends event.Event {
} }
getJarFile(resource: string) { getJarFile(resource: string) {
return super.getJarFile('org/bukkit/Bukkit.class') return super.getJarFile('org/bukkit/Bukkit.class', Bukkit.class.classLoader)
} }
isValidEvent(clazz: any): boolean { isValidEvent(clazz: any): boolean {
// 继承于 org.bukkit.event.Event // 继承于 org.bukkit.event.Event

View File

@@ -1,16 +1,9 @@
import { server } from '@ms/api' import { server, constants } from '@ms/api'
import { provideSingleton } from '@ms/container'; import { provideSingleton } from '@ms/container';
import * as reflect from '@ms/common/dist/reflect' import * as reflect from '@ms/common/dist/reflect'
import chat from './enhance/chat' import chat from './enhance/chat'
const refList: Array<{ server: string, future: string }> = [
{ server: 'aq', future: 'g' },//spigot 1.8.8
{ server: 'an', future: 'g' },//spigot 1.12.2
{ server: 'getServerConnection', future: 'f' },//after spigot 1.14.4
{ server: 'func_147137_ag', future: 'field_151274_e' }//catserver 1.12.2
]
let Bukkit = org.bukkit.Bukkit; let Bukkit = org.bukkit.Bukkit;
@provideSingleton(server.Server) @provideSingleton(server.Server)
@@ -68,14 +61,24 @@ export class BukkitServer implements server.Server {
private reflectPipeline() { private reflectPipeline() {
let consoleServer = reflect.on(Bukkit.getServer()).get('console').get() let consoleServer = reflect.on(Bukkit.getServer()).get('console').get()
let connection: any;
let promise: any; let promise: any;
for (const ref of refList) { for (const method of constants.Reflect.Method.getServerConnection) {
try { try {
promise = reflect.on(consoleServer).call(ref.server).get(ref.future).get().get(0); break; connection = reflect.on(consoleServer).call(method).get()
} catch (error) { if (connection.class.name.indexOf('ServerConnection') !== -1) { break; }
connection = undefined;
} catch (error) { }
} }
if (!connection) { console.error("Can't found ServerConnection!"); return }
for (const field of constants.Reflect.Field.listeningChannels) {
try {
promise = reflect.on(connection).get(field).get().get(0);
if (promise.class.name.indexOf('Promise') !== -1) { break; }
promise = undefined;
} catch (error) { }
} }
if (!promise) { console.error("Can't found ServerConnection or ChannelFuture !"); return } if (!promise) { console.error("Can't found listeningChannels!"); return }
this.pipeline = reflect.on(promise).get('channel').get().pipeline() this.pipeline = reflect.on(promise).get('channel').get().pipeline()
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/bungee", "name": "@ms/bungee",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript bungee package", "description": "MiaoScript bungee package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -27,8 +27,8 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/api": "^0.4.2", "@ms/api": "^0.5.0",
"@ms/common": "^0.4.2", "@ms/common": "^0.5.0",
"@ms/container": "^0.4.0" "@ms/container": "^0.5.0"
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"private": true, "private": true,
"name": "@ms/client", "name": "@ms/client",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript client package", "description": "MiaoScript client package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/common", "name": "@ms/common",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript api package", "description": "MiaoScript api package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -27,7 +27,7 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/nashorn": "^0.4.0" "@ms/nashorn": "^0.5.0"
}, },
"gitHead": "562e2d00175c9d3a99c8b672aa07e6d92706a027" "gitHead": "562e2d00175c9d3a99c8b672aa07e6d92706a027"
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/compile", "name": "@ms/compile",
"version": "0.4.0", "version": "0.5.0",
"description": "MiaoScript compile package", "description": "MiaoScript compile package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/container", "name": "@ms/container",
"version": "0.4.0", "version": "0.5.0",
"description": "MiaoScript container package", "description": "MiaoScript container package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/core", "name": "@ms/core",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript api package", "description": "MiaoScript api package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -27,8 +27,8 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/api": "^0.4.2", "@ms/api": "^0.5.0",
"@ms/container": "^0.4.0" "@ms/container": "^0.5.0"
}, },
"gitHead": "781524f83e52cad26d7c480513e3c525df867121" "gitHead": "781524f83e52cad26d7c480513e3c525df867121"
} }

View File

@@ -1,6 +1,6 @@
let containerStartTime = Date.now(); let containerStartTime = Date.now();
console.i18n("ms.core.ioc.initialize"); console.i18n("ms.core.ioc.initialize");
import { plugin, server, task } from '@ms/api' import { plugin, server, task, constants } from '@ms/api'
import { DefaultContainer as container, inject, provideSingleton, ContainerInstance, buildProviderModule } from '@ms/container' import { DefaultContainer as container, inject, provideSingleton, ContainerInstance, buildProviderModule } from '@ms/container'
console.i18n("ms.core.ioc.completed", { time: (Date.now() - containerStartTime) / 1000 }) console.i18n("ms.core.ioc.completed", { time: (Date.now() - containerStartTime) / 1000 })
@@ -24,15 +24,13 @@ class MiaoScriptCore {
} }
loadServerConsole() { loadServerConsole() {
// @ts-ignore //@ts-ignore
console = new this.Console(); global.setGlobal('console', new this.Console())
} }
loadTaskFunction() { loadTaskFunction() {
//@ts-ignore global.setGlobal('setTimeout', (func: Function, tick: number, async: boolean = false) => this.taskManager.create(func).later(tick).async(async).submit())
global.setTimeout = (func: Function, tick: number, async: boolean = false) => this.taskManager.create(func).later(tick).async(async).submit() global.setGlobal('setInterval', (func: Function, tick: number, async: boolean = false) => this.taskManager.create(func).timer(tick).async(async).submit())
//@ts-ignore
global.setInterval = (func: Function, tick: number, async: boolean = false) => this.taskManager.create(func).timer(tick).async(async).submit()
} }
loadPlugins() { loadPlugins() {
@@ -49,34 +47,37 @@ class MiaoScriptCore {
console.i18n("ms.core.engine.disable") console.i18n("ms.core.engine.disable")
this.pluginManager.disable(); this.pluginManager.disable();
this.taskManager.disable(); this.taskManager.disable();
//@ts-ignore
require.disable()
} }
} }
function detectServer() { function detectServer(): constants.ServerType {
try { try {
Java.type("org.bukkit.Bukkit"); Java.type("org.bukkit.Bukkit");
return 'bukkit' return constants.ServerType.Bukkit
} catch (ex) { } catch (ex) {
} }
try { try {
Java.type("org.spongepowered.api.Sponge"); Java.type("org.spongepowered.api.Sponge");
return 'sponge' return constants.ServerType.Sponge
} catch (ex) { } catch (ex) {
} }
try { try {
Java.type("cn.nukkit.Nukkit"); Java.type("cn.nukkit.Nukkit");
return 'nukkit' return constants.ServerType.Nukkit
} catch (ex) { } catch (ex) {
} }
try { try {
Java.type("net.md_5.bungee.api.ProxyServer"); Java.type("net.md_5.bungee.api.ProxyServer");
return 'bungee' return constants.ServerType.Bungee
} catch (ex) { } catch (ex) {
} }
throw Error('Unknow Server Type...') throw Error('Unknow Server Type...')
} }
function initialize() { function initialize() {
try {
let corePackageStartTime = new Date().getTime() let corePackageStartTime = new Date().getTime()
container.bind(ContainerInstance).toConstantValue(container); container.bind(ContainerInstance).toConstantValue(container);
container.bind(plugin.PluginInstance).toConstantValue(base.getInstance()); container.bind(plugin.PluginInstance).toConstantValue(base.getInstance());
@@ -92,6 +93,11 @@ function initialize() {
let disable = container.get<MiaoScriptCore>(MiaoScriptCore).enable() let disable = container.get<MiaoScriptCore>(MiaoScriptCore).enable()
console.i18n("ms.core.engine.completed", { time: (Date.now() - global.NashornEngineStartTime) / 1000 }); console.i18n("ms.core.engine.completed", { time: (Date.now() - global.NashornEngineStartTime) / 1000 });
return disable; return disable;
} catch (error) {
console.i18n("ms.core.initialize.error", { error });
console.ex(error)
return () => console.i18n('ms.core.engine.disable.abnormal')
}
} }
export default initialize(); export default initialize();

View File

@@ -4,12 +4,14 @@ ms.ployfill.completed: "Java Nashorn ployfill loading completed... Cost ({time}s
ms.core.ioc.initialize: "Initialization MiaoScript IOC Container @ms/container. Please wait..." ms.core.ioc.initialize: "Initialization MiaoScript IOC Container @ms/container. Please wait..."
ms.core.ioc.completed: "MiaoScript IOC Container @ms/container loading completed({time}s)!" ms.core.ioc.completed: "MiaoScript IOC Container @ms/container loading completed({time}s)!"
ms.core.initialize.detect: "Detect Compatible Server set ServerType to {type} ..." ms.core.initialize.detect: "Detect Compatible Server set ServerType to {type} ..."
ms.core.initialize.error: "MiaoScript Engine Initialization Error: {error} ..."
ms.core.package.initialize: "Initialization MiaoScript Package @ms/core @ms/{type} @ms/plugin. Please wait..." ms.core.package.initialize: "Initialization MiaoScript Package @ms/core @ms/{type} @ms/plugin. Please wait..."
ms.core.package.completed: "MiaoScript Package @ms/core @ms/{type} @ms/plugin loading completed({time}s)!" ms.core.package.completed: "MiaoScript Package @ms/core @ms/{type} @ms/plugin loading completed({time}s)!"
ms.core.plugin.initialize: "Initialization MiaoScript Plugin System. Please wait..." ms.core.plugin.initialize: "Initialization MiaoScript Plugin System. Please wait..."
ms.core.plugin.completed: "MiaoScript Plugin System loading completed({time}s)!" ms.core.plugin.completed: "MiaoScript Plugin System loading completed({time}s)!"
ms.core.engine.completed: "MiaoScript ScriptEngine loading completed... Done({time}s)!" ms.core.engine.completed: "MiaoScript ScriptEngine loading completed... Done({time}s)!"
ms.core.engine.disable: "Disable MiaoScript Engine..." ms.core.engine.disable: "Disable MiaoScript Engine..."
ms.core.engine.disable.abnormal: "abnormal Initialization MiaoScript Engine. Skip disable step..."
ms.api.event.resource.not.found: "Can't Mapping Event Because not found Resources {resource}!" ms.api.event.resource.not.found: "Can't Mapping Event Because not found Resources {resource}!"
ms.api.event.empty.event.dir: "base event dir is empty, can't map event name !" ms.api.event.empty.event.dir: "base event dir is empty, can't map event name !"
@@ -26,11 +28,13 @@ ms.api.command.unregister: "[{plugin}] unregister command {name}..."
ms.api.command.execute.error: "§6Player {player} §6exec §b{plugin} §6Plugin Command §d{command} {args} §6error §4{ex}" ms.api.command.execute.error: "§6Player {player} §6exec §b{plugin} §6Plugin Command §d{command} {args} §6error §4{ex}"
ms.api.command.tab.completer.error: "§6Player {player} §6exec §b{plugin} §6Plugin TabComplete §d{command} {args} §6error §4{ex}" ms.api.command.tab.completer.error: "§6Player {player} §6exec §b{plugin} §6Plugin TabComplete §d{command} {args} §6error §4{ex}"
ms.plugin.initialize: "Initialization MiaoScript Plugin System: {plugin} ..." ms.plugin.initialize: "Initialization MiaoScript Plugin System: Plugin: {plugin} Loader: {loader}..."
ms.plugin.event.map: "Total {count} {type} Event Mapping Complate..." ms.plugin.event.map: "Total {count} {type} Event Mapping Complate..."
ms.plugin.manager.scan: "Scanning Plugins in {folder} ..." ms.plugin.manager.scan: "Scanning Plugins in {folder} ..."
ms.plugin.manager.initialize.error: "§6Plugin §b{name} §6initialize error §4{ex}" ms.plugin.manager.initialize.error: "§6Plugin §b{name} §6initialize error §4{ex}"
ms.plugin.manager.stage: "{stage} {plugin} version {version} by {author}" ms.plugin.manager.stage: "{stage} {plugin} version {version} by {author}"
ms.plugin.manager.stage.exec: "[{plugin}] Exec {name} Stage {stage} When servers is {servers}..."
ms.plugin.manager.stage.exec.error: "§6Plugin §b{plugin} §6exec §d{executor} §6function error §4{error}"
ms.plugin.manager.stage.load: "Loading" ms.plugin.manager.stage.load: "Loading"
ms.plugin.manager.stage.enable: "Enabling" ms.plugin.manager.stage.enable: "Enabling"
ms.plugin.manager.stage.disable: "Disabling" ms.plugin.manager.stage.disable: "Disabling"

View File

@@ -4,12 +4,14 @@ ms.ployfill.completed: "Java Nashorn 补丁 加载完成... 耗时 ({time}s)!"
ms.core.ioc.initialize: "初始化 MiaoScript IOC 容器 @ms/container. 请稍候..." ms.core.ioc.initialize: "初始化 MiaoScript IOC 容器 @ms/container. 请稍候..."
ms.core.ioc.completed: "MiaoScript IOC 容器 @ms/container 加载完成 耗时({time}s)" ms.core.ioc.completed: "MiaoScript IOC 容器 @ms/container 加载完成 耗时({time}s)"
ms.core.initialize.detect: "检测到兼容的服务器类型. 设置 ServerType 值 {type} ..." ms.core.initialize.detect: "检测到兼容的服务器类型. 设置 ServerType 值 {type} ..."
ms.core.initialize.error: "§4MiaoScript 系统初始化失败 §c{error} ..."
ms.core.package.initialize: "初始化 MiaoScript 扩展 @ms/core @ms/{type} @ms/plugin. 请稍候..." ms.core.package.initialize: "初始化 MiaoScript 扩展 @ms/core @ms/{type} @ms/plugin. 请稍候..."
ms.core.package.completed: "MiaoScript 扩展 @ms/core @ms/{type} @ms/plugin 加载完成 耗时({time}s)" ms.core.package.completed: "MiaoScript 扩展 @ms/core @ms/{type} @ms/plugin 加载完成 耗时({time}s)"
ms.core.plugin.initialize: "MiaoScript 开始引导插件系统. 请稍候..." ms.core.plugin.initialize: "MiaoScript 开始引导插件系统. 请稍候..."
ms.core.plugin.completed: "MiaoScript 插件加载完毕 耗时({time}s)!" ms.core.plugin.completed: "MiaoScript 插件加载完毕 耗时({time}s)!"
ms.core.engine.completed: "MiaoScript 脚本引擎 加载完毕... 耗时({time}s)!" ms.core.engine.completed: "MiaoScript 脚本引擎 加载完毕... 耗时({time}s)!"
ms.core.engine.disable: "关闭 MiaoScript 引擎..." ms.core.engine.disable: "关闭 MiaoScript 引擎..."
ms.core.engine.disable.abnormal: "引擎异常启动或初始化未完成 跳过关闭流程..."
ms.api.event.resource.not.found: "无法映射事件 未找到资源文件 {resource}!" ms.api.event.resource.not.found: "无法映射事件 未找到资源文件 {resource}!"
ms.api.event.empty.event.dir: "事件基础目录为空, 无法映射事件!" ms.api.event.empty.event.dir: "事件基础目录为空, 无法映射事件!"
@@ -26,11 +28,13 @@ ms.api.command.unregister: "[{plugin}] 注销命令 {name}..."
ms.api.command.execute.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6命令时发生异常 §4{ex}" ms.api.command.execute.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6命令时发生异常 §4{ex}"
ms.api.command.tab.completer.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6补全时发生异常 §4{ex}" ms.api.command.tab.completer.error: "§6玩家 §a{player} §6执行 §b{plugin} §6插件 §d{command} {args} §6补全时发生异常 §4{ex}"
ms.plugin.initialize: "初始化 MiaoScript 插件系统: {plugin} ..." ms.plugin.initialize: "初始化 MiaoScript 插件系统: 实例: {plugin} 加载器: {loader}..."
ms.plugin.event.map: "总计 {count} 个 {type} 事件 映射完成..." ms.plugin.event.map: "总计 {count} 个 {type} 事件 映射完成..."
ms.plugin.manager.scan: "扫描 {folder} 文件夹中插件..." ms.plugin.manager.scan: "扫描 {folder} 文件夹中插件..."
ms.plugin.manager.initialize.error: "§6插件 §b{name} §6初始化错误 §4{ex}" ms.plugin.manager.initialize.error: "§6插件 §b{name} §6初始化错误 §4{ex}"
ms.plugin.manager.stage: "{stage} {plugin} 版本 {version} 作者 {author}" ms.plugin.manager.stage: "{stage} {plugin} 版本 {version} 作者 {author}"
ms.plugin.manager.stage.exec: "[{plugin}] 执行 {stage} 阶段函数 {name} 匹配类型 {servers}..."
ms.plugin.manager.stage.exec.error: "§6插件 §b{plugin} §6执行 §d{executor} §6函数发生异常 错误: §4{error}"
ms.plugin.manager.stage.load: "加载" ms.plugin.manager.stage.load: "加载"
ms.plugin.manager.stage.enable: "启用" ms.plugin.manager.stage.enable: "启用"
ms.plugin.manager.stage.disable: "关闭" ms.plugin.manager.stage.disable: "关闭"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/i18n", "name": "@ms/i18n",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript i18n package", "description": "MiaoScript i18n package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -28,7 +28,7 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/nashorn": "^0.4.0", "@ms/nashorn": "^0.5.0",
"js-yaml": "^3.13.1" "js-yaml": "^3.13.1"
}, },
"gitHead": "781524f83e52cad26d7c480513e3c525df867121" "gitHead": "781524f83e52cad26d7c480513e3c525df867121"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/nashorn", "name": "@ms/nashorn",
"version": "0.4.0", "version": "0.5.0",
"description": "MiaoScript api package", "description": "MiaoScript api package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/nodejs", "name": "@ms/nodejs",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript nodejs package", "description": "MiaoScript nodejs package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -27,7 +27,7 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/nashorn": "^0.4.0" "@ms/nashorn": "^0.5.0"
}, },
"gitHead": "781524f83e52cad26d7c480513e3c525df867121" "gitHead": "781524f83e52cad26d7c480513e3c525df867121"
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/nukkit", "name": "@ms/nukkit",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript nukkit package", "description": "MiaoScript nukkit package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -27,8 +27,8 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/api": "^0.4.2", "@ms/api": "^0.5.0",
"@ms/common": "^0.4.2", "@ms/common": "^0.5.0",
"@ms/container": "^0.4.0" "@ms/container": "^0.5.0"
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/ployfill", "name": "@ms/ployfill",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript ployfill package", "description": "MiaoScript ployfill package",
"author": "MiaoWoo <admin@yumc.pw>", "author": "MiaoWoo <admin@yumc.pw>",
"homepage": "https://github.com/circlecloud/ms.git", "homepage": "https://github.com/circlecloud/ms.git",
@@ -17,8 +17,8 @@
"test": "echo \"Error: run tests from root\" && exit 1" "test": "echo \"Error: run tests from root\" && exit 1"
}, },
"dependencies": { "dependencies": {
"@ms/i18n": "^0.4.2", "@ms/i18n": "^0.5.0",
"@ms/nashorn": "^0.4.0", "@ms/nashorn": "^0.5.0",
"core-js": "^3.6.4" "core-js": "^3.6.4"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/plugin", "name": "@ms/plugin",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript api package", "description": "MiaoScript api package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -28,10 +28,10 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/api": "^0.4.2", "@ms/api": "^0.5.0",
"@ms/common": "^0.4.2", "@ms/common": "^0.5.0",
"@ms/container": "^0.4.0", "@ms/container": "^0.5.0",
"@ms/i18n": "^0.4.2", "@ms/i18n": "^0.5.0",
"js-yaml": "^3.13.1" "js-yaml": "^3.13.1"
} }
} }

View File

@@ -4,4 +4,9 @@ export const METADATA_KEY = {
tab: "@ms/plugin:tab", tab: "@ms/plugin:tab",
listener: "@ms/plugin:listener", listener: "@ms/plugin:listener",
config: "@ms/plugin:config", config: "@ms/plugin:config",
stage: {
load: "@ms/plugin:stage:load",
enable: "@ms/plugin:stage:enable",
disable: "@ms/plugin:stage:disable"
}
}; };

View File

@@ -1,14 +1,14 @@
import { injectable, decorate } from "@ms/container"; import { injectable, decorate } from "@ms/container";
import { interfaces } from './interfaces' import { interfaces } from './interfaces'
import { METADATA_KEY } from './constants' import { METADATA_KEY } from './constants'
import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPluginTabCompleterMetadata, getPluginConfigMetadata } from './utils' import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPluginTabCompleterMetadata, getPluginConfigMetadata, getPluginStageMetadata } from './utils'
/** /**
* MiaoScript plugin * MiaoScript plugin
* @param metadata PluginMetadata * @param metadata PluginMetadata
*/ */
export function plugin(metadata: interfaces.PluginMetadata) { export function plugin(metadata: interfaces.PluginMetadata) {
return function(target: any) { return function (target: any) {
metadata.target = target; metadata.target = target;
decorate(injectable(), target); decorate(injectable(), target);
Reflect.defineMetadata(METADATA_KEY.plugin, metadata, target); Reflect.defineMetadata(METADATA_KEY.plugin, metadata, target);
@@ -23,7 +23,7 @@ export function plugin(metadata: interfaces.PluginMetadata) {
* @param metadata CommandMetadata * @param metadata CommandMetadata
*/ */
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.executor = key; metadata.executor = key;
metadata.paramtypes = Reflect.getMetadata("design:paramtypes", target, key) metadata.paramtypes = Reflect.getMetadata("design:paramtypes", target, key)
@@ -38,7 +38,7 @@ export function cmd(metadata: interfaces.CommandMetadata = {}) {
* @param metadata TabCompleterMetadata * @param metadata TabCompleterMetadata
*/ */
export function tab(metadata: interfaces.CommandMetadata = {}) { 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.executor = key; metadata.executor = key;
@@ -54,7 +54,7 @@ export function tab(metadata: interfaces.CommandMetadata = {}) {
* @param metadata ListenerMetadata * @param metadata ListenerMetadata
*/ */
export function listener(metadata: interfaces.ListenerMetadata = {}) { export function listener(metadata: interfaces.ListenerMetadata = {}) {
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.ListenerMetadata[] = getPluginListenerMetadata(target) const previousMetadata: interfaces.ListenerMetadata[] = getPluginListenerMetadata(target)
@@ -63,7 +63,7 @@ export function listener(metadata: interfaces.ListenerMetadata = {}) {
} }
export function config(metadata: interfaces.ConfigMetadata = { version: 1, format: 'yml' }) { export function config(metadata: interfaces.ConfigMetadata = { version: 1, format: 'yml' }) {
return function(target: any, key: string) { return function (target: any, key: string) {
metadata.name = metadata.name || key; metadata.name = metadata.name || key;
metadata.variable = key; metadata.variable = key;
const previousMetadata: Map<string, interfaces.ConfigMetadata> = getPluginConfigMetadata(target) const previousMetadata: Map<string, interfaces.ConfigMetadata> = getPluginConfigMetadata(target)
@@ -71,3 +71,24 @@ export function config(metadata: interfaces.ConfigMetadata = { version: 1, forma
Reflect.defineMetadata(METADATA_KEY.config, previousMetadata, target.constructor); Reflect.defineMetadata(METADATA_KEY.config, previousMetadata, target.constructor);
} }
} }
function stage(metadata: interfaces.ExecMetadata = {}, stage: string) {
return function (target: any, key: string, value: any) {
metadata.name = metadata.name || key;
metadata.executor = key;
const previousMetadata: interfaces.ExecMetadata[] = getPluginStageMetadata(target, stage)
Reflect.defineMetadata(METADATA_KEY.stage[stage], [metadata, ...previousMetadata], target.constructor);
};
}
export function load(metadata: interfaces.ExecMetadata = {}) {
return stage(metadata, 'load')
}
export function enable(metadata: interfaces.ExecMetadata = {}) {
return stage(metadata, 'enable')
}
export function disable(metadata: interfaces.ExecMetadata = {}) {
return stage(metadata, 'disable')
}

View File

@@ -1,4 +1,4 @@
import { server, MiaoScriptConsole } from "@ms/api"; import { server, MiaoScriptConsole, event } from "@ms/api";
import { METADATA_KEY } from './constants' import { METADATA_KEY } from './constants'
import { injectable, inject, postConstruct } from "@ms/container"; import { injectable, inject, postConstruct } from "@ms/container";
import { getPluginMetadata } from "./utils"; import { getPluginMetadata } from "./utils";
@@ -55,7 +55,7 @@ export namespace interfaces {
*/ */
target?: any; target?: any;
} }
interface ExecMetadata extends BaseMetadata { export interface ExecMetadata extends BaseMetadata {
/** /**
* 执行器 * 执行器
*/ */
@@ -68,6 +68,15 @@ export namespace interfaces {
paramtypes?: string[]; paramtypes?: string[];
} }
export interface ListenerMetadata extends ExecMetadata { export interface ListenerMetadata extends ExecMetadata {
/**
* 监听优先级
*/
priority?: event.EventPriority;
/**
* 是否忽略已取消的事件
*/
ignoreCancel?: boolean;
} }
export interface ConfigMetadata extends BaseMetadata { export interface ConfigMetadata extends BaseMetadata {
/** /**

View File

@@ -1,12 +1,14 @@
import i18n from '@ms/i18n' import i18n from '@ms/i18n'
import { plugin, server, command, event } from '@ms/api' import { plugin, server, command, event } from '@ms/api'
import { inject, provideSingleton, postConstruct, Container, ContainerInstance } from '@ms/container' import { inject, provideSingleton, Container, ContainerInstance } from '@ms/container'
import * as fs from '@ms/common/dist/fs' import * as fs from '@ms/common/dist/fs'
import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPlugin, getPluginTabCompleterMetadata, getPluginConfigMetadata } from './utils' import { getPluginMetadatas, getPluginCommandMetadata, getPluginListenerMetadata, getPlugin, getPluginTabCompleterMetadata, getPluginConfigMetadata, getPluginStageMetadata } from './utils'
import { interfaces } from './interfaces' import { interfaces } from './interfaces'
import { getConfigLoader } from './config' import { getConfigLoader } from './config'
const Thread = Java.type('java.lang.Thread')
@provideSingleton(plugin.PluginManager) @provideSingleton(plugin.PluginManager)
export class PluginManagerImpl implements plugin.PluginManager { export class PluginManagerImpl implements plugin.PluginManager {
@inject(ContainerInstance) @inject(ContainerInstance)
@@ -22,25 +24,23 @@ export class PluginManagerImpl implements plugin.PluginManager {
@inject(event.Event) @inject(event.Event)
private EventManager: event.Event private EventManager: event.Event
private initialized: boolean = false
private pluginMap: Map<string, interfaces.Plugin> private pluginMap: Map<string, interfaces.Plugin>
@postConstruct()
initialize() { initialize() {
if (this.pluginInstance !== null) { if (this.pluginInstance !== null && this.initialized !== true) {
// 如果plugin不等于null 则代表是正式环境 // 如果plugin不等于null 则代表是正式环境
console.i18n('ms.plugin.initialize', { plugin: this.pluginInstance }) console.i18n('ms.plugin.initialize', { plugin: this.pluginInstance, loader: Thread.currentThread().contextClassLoader })
this.pluginMap = new Map() this.pluginMap = new Map()
console.i18n('ms.plugin.event.map', { count: this.EventManager.mapEventName().toFixed(0), type: this.serverType }); console.i18n('ms.plugin.event.map', { count: this.EventManager.mapEventName().toFixed(0), type: this.serverType });
this.initialized = true;
} }
} }
scan(folder: string): void { scan(folder: string): void {
this.initialize()
var plugin = fs.file(root, folder) var plugin = fs.file(root, folder)
var files = [] var files = this.scanFolder(plugin)
// load common plugin
.concat(this.scanFolder(plugin))
// load space plugin
.concat(this.scanFolder(fs.file(plugin, this.serverType)))
this.loadPlugins(files) this.loadPlugins(files)
} }
@@ -52,32 +52,36 @@ export class PluginManagerImpl implements plugin.PluginManager {
console.i18n("ms.plugin.manager.stage", { stage, plugin: plugin.description.name, version: plugin.description.version, author: plugin.description.author }) console.i18n("ms.plugin.manager.stage", { stage, plugin: plugin.description.name, version: plugin.description.version, author: plugin.description.author })
} }
private runPluginStage(plugin: interfaces.Plugin, stage: string, ext: Function) {
this.logStage(plugin, i18n.translate(`ms.plugin.manager.stage.${stage}`))
this.runCatch(plugin, stage)
this.runCatch(plugin, `${this.serverType}${stage}`)
this.execPluginStage(plugin, stage)
}
load(...args: any[]): void { load(...args: any[]): void {
this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => { this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => {
this.logStage(plugin, i18n.translate("ms.plugin.manager.stage.load")) this.runPluginStage(plugin, 'load', () => {
this.loadConfig(plugin) this.loadConfig(plugin)
this.runCatch(plugin, 'load') })
this.runCatch(plugin, `${this.serverType}load`)
}) })
} }
enable(...args: any[]): void { enable(...args: any[]): void {
this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => { this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => {
this.logStage(plugin, i18n.translate("ms.plugin.manager.stage.enable")) this.runPluginStage(plugin, 'enable', () => {
this.registryCommand(plugin) this.registryCommand(plugin)
this.registryListener(plugin) this.registryListener(plugin)
this.runCatch(plugin, 'enable') })
this.runCatch(plugin, `${this.serverType}enable`)
}) })
} }
disable(...args: any[]): void { disable(...args: any[]): void {
this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => { this.checkAndGet(args[0]).forEach((plugin: interfaces.Plugin) => {
this.logStage(plugin, i18n.translate("ms.plugin.manager.stage.disable")) this.runPluginStage(plugin, 'disable', () => {
this.unregistryCommand(plugin) this.unregistryCommand(plugin)
this.unregistryListener(plugin) this.unregistryListener(plugin)
this.runCatch(plugin, 'disable') })
this.runCatch(plugin, `${this.serverType}disable`)
}) })
} }
@@ -99,7 +103,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
try { try {
if (pl[func]) pl[func].call(pl) if (pl[func]) pl[func].call(pl)
} catch (ex) { } catch (ex) {
console.console(`§6Plugin §b${pl.description.name} §6exec §d${func} §6function error §4${ex}`) console.i18n("ms.plugin.manager.stage.exec.error", { plugin: pl.description.name, executor: func, error: ex })
console.ex(ex) console.ex(ex)
} }
} }
@@ -162,7 +166,7 @@ export class PluginManagerImpl implements plugin.PluginManager {
private allowProcess(servers: string[]) { private allowProcess(servers: string[]) {
// Not set servers allow // Not set servers allow
if (!servers) return true if (!servers || !servers.length) return true
// include !type deny // include !type deny
let denyServers = servers.filter(svr => svr.startsWith("!")) let denyServers = servers.filter(svr => svr.startsWith("!"))
if (denyServers.length !== 0) { if (denyServers.length !== 0) {
@@ -260,4 +264,18 @@ export class PluginManagerImpl implements plugin.PluginManager {
private unregistryListener(pluginInstance: interfaces.Plugin) { private unregistryListener(pluginInstance: interfaces.Plugin) {
this.EventManager.disable(pluginInstance) this.EventManager.disable(pluginInstance)
} }
private execPluginStage(pluginInstance: interfaces.Plugin, stageName: string) {
let stages = getPluginStageMetadata(pluginInstance, stageName);
for (const stage of stages) {
if (!this.allowProcess(stage.servers)) { continue }
console.i18n("ms.plugin.manager.stage.exec", { plugin: pluginInstance.description.name, name: stage.executor, stage: stageName, servers: stage.servers })
try {
pluginInstance[stage.executor].apply(pluginInstance)
} catch (error) {
console.i18n("ms.plugin.manager.stage.exec.error", { plugin: pluginInstance.description.name, executor: stage.executor, error })
console.ex(error)
}
}
}
} }

View File

@@ -57,6 +57,14 @@ function getPluginConfigMetadata(target: any) {
return configMetadata; return configMetadata;
} }
function getPluginStageMetadata(target: any, stage: string) {
let stageMetadata: interfaces.ExecMetadata[] = Reflect.getMetadata(
METADATA_KEY.stage[stage],
target.constructor
) || [];
return stageMetadata;
}
export { export {
getPlugin, getPlugin,
getPlugins, getPlugins,
@@ -65,5 +73,6 @@ export {
getPluginCommandMetadata, getPluginCommandMetadata,
getPluginTabCompleterMetadata, getPluginTabCompleterMetadata,
getPluginListenerMetadata, getPluginListenerMetadata,
getPluginConfigMetadata getPluginConfigMetadata,
getPluginStageMetadata
} }

View File

@@ -1,7 +1,7 @@
{ {
"private": true, "private": true,
"name": "@ms/plugins", "name": "@ms/plugins",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript plugins package", "description": "MiaoScript plugins package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -28,8 +28,8 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/api": "^0.4.2", "@ms/api": "^0.5.0",
"@ms/container": "^0.4.0", "@ms/container": "^0.5.0",
"@ms/plugin": "^0.4.2" "@ms/plugin": "^0.5.0"
} }
} }

View File

@@ -2,9 +2,9 @@
/// <reference types="@ms/types/dist/typings/sponge" /> /// <reference types="@ms/types/dist/typings/sponge" />
/// <reference types="@ms/types/dist/typings/bungee" /> /// <reference types="@ms/types/dist/typings/bungee" />
import { server, plugin as pluginApi, channel } from '@ms/api' import { server, plugin as pluginApi, channel, constants } from '@ms/api'
import { inject, optional } from '@ms/container'; import { inject, optional } from '@ms/container';
import { plugin, interfaces, cmd, listener, tab, config } from '@ms/plugin' import { plugin, interfaces, cmd, listener, tab, config, enable } from '@ms/plugin'
import Tellraw from '@ms/common/dist/tellraw' import Tellraw from '@ms/common/dist/tellraw'
const ByteArrayInputStream = Java.type("java.io.ByteArrayInputStream"); const ByteArrayInputStream = Java.type("java.io.ByteArrayInputStream");
@@ -12,10 +12,8 @@ const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream");
const StandardCharsets = Java.type("java.nio.charset.StandardCharsets"); const StandardCharsets = Java.type("java.nio.charset.StandardCharsets");
const GZIPInputStream = Java.type("java.util.zip.GZIPInputStream"); const GZIPInputStream = Java.type("java.util.zip.GZIPInputStream");
const GZIPOutputStream = Java.type("java.util.zip.GZIPOutputStream"); const GZIPOutputStream = Java.type("java.util.zip.GZIPOutputStream");
const Consumer = Java.type("java.util.function.Consumer");
const ByteArray = Java.type("byte[]")
const BiConsumer = Java.type('java.util.function.BiConsumer') const BiConsumer = Java.type('java.util.function.BiConsumer')
const ByteArray = Java.type("byte[]")
class MiaoMessage { class MiaoMessage {
// public static final String CHANNEL = "MiaoChat:Default".toLowerCase(); // public static final String CHANNEL = "MiaoChat:Default".toLowerCase();
@@ -146,7 +144,7 @@ export class MiaoChat extends interfaces.Plugin {
} }
private compare(prop: string) { private compare(prop: string) {
return function(obj1: { [x: string]: any; }, obj2: { [x: string]: any; }) { return function (obj1: { [x: string]: any; }, obj2: { [x: string]: any; }) {
var val1 = obj1[prop]; var val1 = obj1[prop];
var val2 = obj2[prop]; var val2 = obj2[prop];
if (!isNaN(Number(val1)) && !isNaN(Number(val2))) { if (!isNaN(Number(val1)) && !isNaN(Number(val2))) {
@@ -184,9 +182,6 @@ export class MiaoChat extends interfaces.Plugin {
} catch (ex) { } catch (ex) {
this.logger.console("§cCan't found me.clip.placeholderapi.PlaceholderAPI variable will not be replaced! Err: " + ex) this.logger.console("§cCan't found me.clip.placeholderapi.PlaceholderAPI variable will not be replaced! Err: " + ex)
} }
this.channelOff = this.Channel?.listen(this, MiaoMessage.CHANNEL, (data) => {
this.sendChatAll(MiaoMessage.decode(data).json)
})
} }
spongeenable() { spongeenable() {
@@ -205,6 +200,10 @@ export class MiaoChat extends interfaces.Plugin {
} catch (ex) { } catch (ex) {
this.logger.console("§cCan't found me.rojo8399.placeholderapi.PlaceholderService variable will not be replaced! Err: " + ex) this.logger.console("§cCan't found me.rojo8399.placeholderapi.PlaceholderService variable will not be replaced! Err: " + ex)
} }
}
@enable({ servers: [constants.ServerType.Bukkit, constants.ServerType.Sponge] })
serverEnbale() {
this.channelOff = this.Channel?.listen(this, MiaoMessage.CHANNEL, (data) => { this.channelOff = this.Channel?.listen(this, MiaoMessage.CHANNEL, (data) => {
this.sendChatAll(MiaoMessage.decode(data).json) this.sendChatAll(MiaoMessage.decode(data).json)
}) })
@@ -244,7 +243,7 @@ export class MiaoChat extends interfaces.Plugin {
@listener({ servers: ['bukkit'] }) @listener({ servers: ['bukkit'] })
AsyncPlayerChatEvent(event: org.bukkit.event.player.AsyncPlayerChatEvent) { AsyncPlayerChatEvent(event: org.bukkit.event.player.AsyncPlayerChatEvent) {
this.sendChat(event.getPlayer(), event.getMessage(), function() { this.sendChat(event.getPlayer(), event.getMessage(), function () {
event.setCancelled(true); event.setCancelled(true);
}); });
} }
@@ -260,7 +259,7 @@ export class MiaoChat extends interfaces.Plugin {
if (plain.startsWith(Tellraw.duplicateChar)) { if (plain.startsWith(Tellraw.duplicateChar)) {
return; return;
} }
this.sendChat(player, plain, function() { this.sendChat(player, plain, function () {
event.setMessageCancelled(true) event.setMessageCancelled(true)
}); });
} }

View File

@@ -4,101 +4,111 @@
import { plugin as pluginApi, server, task } from '@ms/api' import { plugin as pluginApi, server, task } from '@ms/api'
import { plugin, interfaces, cmd } from '@ms/plugin' import { plugin, interfaces, cmd } from '@ms/plugin'
import { inject, Container } from '@ms/container' import { inject, ContainerInstance, Container } from '@ms/container'
import * as reflect from '@ms/common/dist/reflect' import io, { Server as SocketIOServer, Socket as SocketIOSocket } from '@ms/websocket'
import { Server as SocketIOServer, Socket as SocketIOSocket } from '@ms/websocket'
const refList: Array<{ server: string, future: string }> = [ const suffixMap = {
{ server: 'an', future: 'g' },//spigot 1.12.2 ts: 'typescript',
{ server: 'getServerConnection', future: 'f' },//after spigot 1.14.4 js: 'javascript',
{ server: 'func_147137_ag', future: 'field_151274_e' }//catserver 1.12.2 yml: 'yaml'
] }
@plugin({ name: 'MiaoConsole', version: '1.0.0', author: 'MiaoWoo', servers: ['!nukkit'], source: __filename }) @plugin({ name: 'MiaoConsole', version: '1.0.0', author: 'MiaoWoo', servers: ['!nukkit'], source: __filename })
export class MiaoConsole extends interfaces.Plugin { export class MiaoConsole extends interfaces.Plugin {
@inject(ContainerInstance)
private container: Container
@inject(server.ServerType) @inject(server.ServerType)
private ServerType: string private serverType: string
@inject(server.Server) @inject(server.Server)
private Server: server.Server private server: server.Server
@inject(task.TaskManager) @inject(task.TaskManager)
private Task: task.TaskManager private task: task.TaskManager
@inject(pluginApi.PluginManager)
private pluginManager: pluginApi.PluginManager
private pipeline: any; private pipeline: any;
private socketIOServer: SocketIOServer; private socketIOServer: SocketIOServer;
@cmd() @cmd()
mconsole(sender: any, command: string, args: string[]) { mconsole(sender: any, command: string, args: string[]) {
if (args[0] == 'reload') {
// @ts-ignore
require.clear('websocket');
this.pluginManager.reload(this);
return
}
let tfunc = new Function('pipeline', args.join(' '))
tfunc.apply(this, [this.pipeline])
}
enable() {
let count = 0;
let wait = this.task.create(() => {
this.pipeline = this.server.getNettyPipeline()
if (this.pipeline) {
wait.cancel()
this.createSocketIOServer()
this.startSocketIOServer()
}
if (count > 30) { wait.cancel() }
count++
}).later(20).timer(40).submit()
} }
disable() { disable() {
this.socketIOServer?.close() this.socketIOServer?.close()
} if (this.container.isBound(io.Instance)) {
this.container.unbind(io.Instance)
bukkitenable() {
let Bukkit = Java.type('org.bukkit.Bukkit')
let consoleServer = reflect.on(Bukkit.getServer()).get('console').get()
this.reflectChannel(this.reflectPromise(consoleServer))
this.injectMiaoDetect()
}
spongeenable() {
let Sponge = Java.type('org.spongepowered.api.Sponge')
let consoleServer = reflect.on(Sponge.getServer()).get()
this.reflectChannel(this.reflectPromise(consoleServer))
this.injectMiaoDetect()
}
bungeeenable() {
let wait = this.Task.create(() => {
try {
// @ts-ignore
this.pipeline = reflect.on(base.getInstance().getProxy()).get('listeners').get().toArray()[0].pipeline()
this.injectMiaoDetect()
wait.cancel();
} catch (ex) {
this.logger.warn('Wait BungeeCord start ready to get netty channel pipeline. Err: ' + ex)
}
}).later(300).timer(500).submit()
}
reflectPromise(consoleServer: any) {
for (const ref of refList) {
try { return reflect.on(consoleServer).call(ref.server).get(ref.future).get().get(0) } catch (error) { }
} }
} }
reflectChannel(promise: any) { createSocketIOServer() {
if (!promise) { throw Error(`Can't found ServerConnection or ChannelFuture !`) } this.socketIOServer = io(this.pipeline, {
this.pipeline = reflect.on(promise).get('channel').get().pipeline() path: '/ws',
} root: '/home/project/TSWorkSpace/ms/packages/plugins/public'
injectMiaoDetect() {
this.socketIOServer = new SocketIOServer(this.pipeline, {
path: '/ws'
}); });
this.container.bind(io.Instance).toConstantValue(this.socketIOServer)
}
startSocketIOServer() {
let namespace = this.socketIOServer.of('/MiaoConsole') let namespace = this.socketIOServer.of('/MiaoConsole')
namespace.on('connect', (client: SocketIOSocket) => { namespace.on('connect', (client: SocketIOSocket) => {
global.setGlobal('client', client);
client.on('type', (fn) => {
this.logger.console(`§6客户端 §b${client.id} §a新建连接...`) this.logger.console(`§6客户端 §b${client.id} §a新建连接...`)
fn && fn(this.ServerType) client.on('type', (fn) => {
client.emit('log', `Currect Server Version is ${this.Server.getVersion()}`) fn && fn(this.serverType)
client.emit('log', `Currect Server Version is ${this.server.getVersion()}`)
}) })
client.on('command', (cmd) => { client.on('command', (cmd) => {
setTimeout(() => this.Server.dispatchConsoleCommand(cmd), 0) setTimeout(() => this.server.dispatchConsoleCommand(cmd), 0)
client.emit('log', `§6命令: §b${cmd} §a执行成功!`) client.emit('log', `§6命令: §b${cmd} §a执行成功!`)
}) })
client.on('exec', (code) => { client.on('exec', (code) => {
try { try {
client.emit('log', this.Task.callSyncMethod(() => eval(code)) + '') client.emit('log', this.runCode(code, namespace, client))
} catch (ex) { } catch (ex) {
client.emit('log', '§4代码执行异常\n' + console.stack(ex).join('\n')) client.emit('log', '§4代码执行异常\n' + console.stack(ex).join('\n'))
} }
}) })
client.on('edit', (file: string, fn) => {
fn && fn(base.read(file), suffixMap[file.split('.', 2)[1]])
})
client.on('disconnect', () => { client.on('disconnect', () => {
this.logger.console(`§6客户端 §b${client.id} §c断开连接...`) this.logger.console(`§6客户端 §b${client.id} §c断开连接...`)
}) })
}) })
this.logger.info('Netty Channel Pipeline Inject MiaoDetectHandler Successful!') this.logger.info('Netty Channel Pipeline Inject MiaoDetectHandler Successful!')
} }
private runCode(code: string, namespace: any, client: any) {
let tfunc = new Function('namespace', 'client', `
var reflect = require('@ms/common/dist/reflect');
var tempconcent = '';
function print(text) {
tempconcent += text + "\\n"
}
var result = eval(${JSON.stringify(code)});
return tempconcent + result
`)
return this.task.callSyncMethod(() => tfunc.apply(this, [namespace, client])) + ''
}
} }

View File

@@ -3,7 +3,9 @@
"compilerOptions": { "compilerOptions": {
"baseUrl": "src", "baseUrl": "src",
"outDir": "dist", "outDir": "dist",
"skipLibCheck": true "skipLibCheck": true,
"sourceMap": false,
"inlineSourceMap": true
}, },
"exclude": [ "exclude": [
"dist", "dist",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/sponge", "name": "@ms/sponge",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript api package", "description": "MiaoScript api package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -27,8 +27,8 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/api": "^0.4.2", "@ms/api": "^0.5.0",
"@ms/common": "^0.4.2", "@ms/common": "^0.5.0",
"@ms/container": "^0.4.0" "@ms/container": "^0.5.0"
} }
} }

View File

@@ -1,14 +1,8 @@
import { server } from '@ms/api' import { server, constants } from '@ms/api'
import { provideSingleton } from '@ms/container'; import { provideSingleton } from '@ms/container';
import * as reflect from '@ms/common/dist/reflect' import * as reflect from '@ms/common/dist/reflect'
const refList: Array<{ server: string, future: string }> = [
{ server: 'an', future: 'g' },//spigot 1.12.2
{ server: 'getServerConnection', future: 'f' },//after spigot 1.14.4
{ server: 'func_147137_ag', future: 'field_151274_e' }//catserver 1.12.2
]
const Sponge = org.spongepowered.api.Sponge; const Sponge = org.spongepowered.api.Sponge;
const TextSerializers = org.spongepowered.api.text.serializer.TextSerializers; const TextSerializers = org.spongepowered.api.text.serializer.TextSerializers;
const File = Java.type("java.io.File"); const File = Java.type("java.io.File");
@@ -64,14 +58,24 @@ export class SpongeServer implements server.Server {
} }
private reflectPipeline() { private reflectPipeline() {
let consoleServer = reflect.on(Sponge.getServer()).get() let consoleServer = reflect.on(Sponge.getServer()).get()
let connection: any;
let promise: any; let promise: any;
for (const ref of refList) { for (const method of constants.Reflect.Method.getServerConnection) {
try { try {
promise = reflect.on(consoleServer).call(ref.server).get(ref.future).get().get(0); break; connection = reflect.on(consoleServer).call(method).get()
} catch (error) { if (connection.class.name.indexOf('ServerConnection') !== -1) { break; }
connection = undefined;
} catch (error) { }
} }
if (!connection) { console.error("Can't found ServerConnection!"); return }
for (const field of constants.Reflect.Field.listeningChannels) {
try {
promise = reflect.on(connection).get(field).get().get(0);
if (promise.class.name.indexOf('Promise') !== -1) { break; }
promise = undefined;
} catch (error) { }
} }
if (!promise) { throw Error(`Can't found ServerConnection or ChannelFuture !`) } if (!promise) { console.error("Can't found listeningChannels!"); return }
this.pipeline = reflect.on(promise).get('channel').get().pipeline() this.pipeline = reflect.on(promise).get('channel').get().pipeline()
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/types", "name": "@ms/types",
"version": "0.4.0", "version": "0.5.0",
"description": "MiaoScript types package", "description": "MiaoScript types package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@ms/websocket", "name": "@ms/websocket",
"version": "0.4.2", "version": "0.5.0",
"description": "MiaoScript websocket package", "description": "MiaoScript websocket package",
"keywords": [ "keywords": [
"miaoscript", "miaoscript",
@@ -27,6 +27,6 @@
"typescript": "^3.8.3" "typescript": "^3.8.3"
}, },
"dependencies": { "dependencies": {
"@ms/nashorn": "^0.4.0" "@ms/nashorn": "^0.5.0"
} }
} }

View File

@@ -1,10 +1,10 @@
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
import { NettyClient } from './client'
import { ServerOptions } from '../socket-io'
import { ServerEvent, Keys } from './constants' import { ServerEvent, Keys } from './constants'
import { WebSocketDetect } from './websocket_detect' import { WebSocketDetect } from './websocket_detect'
import { WebSocketHandler } from './websocket_handler' import { WebSocketHandler } from './websocket_handler'
import { NettyClient } from './client'
import { ServerOptions } from '../socket-io'
class NettyWebSocketServer extends EventEmitter { class NettyWebSocketServer extends EventEmitter {
private pipeline: any; private pipeline: any;
@@ -22,10 +22,9 @@ class NettyWebSocketServer extends EventEmitter {
ctx.fireChannelRead(channel) ctx.fireChannelRead(channel)
}) })
connectEvent.on(ServerEvent.connect, (ctx) => { connectEvent.on(ServerEvent.connect, (ctx) => {
console.log('NettyWebSocketServer ServerEvent.connect', ctx, ctx.channel().id(), ctx.channel().class.name) let nettyClient = new NettyClient(this, ctx.channel())
let nettyClient = new NettyClient(this, ctx.channel()); this.allClients[nettyClient.id] = nettyClient
this.allClients[nettyClient.id] = nettyClient; this.emit(ServerEvent.connect, nettyClient)
this.emit(ServerEvent.connect, nettyClient);
}) })
connectEvent.on(ServerEvent.message, (ctx, msg) => { connectEvent.on(ServerEvent.message, (ctx, msg) => {
this.emit(ServerEvent.message, this.allClients[ctx.channel().id()], msg.text()) this.emit(ServerEvent.message, this.allClients[ctx.channel().id()], msg.text())
@@ -46,4 +45,4 @@ export {
NettyWebSocketServer, NettyWebSocketServer,
ServerEvent, ServerEvent,
NettyClient NettyClient
}; }

View File

@@ -1,7 +1,7 @@
import { TextWebSocketFrameHandlerAdapter } from '../netty'
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
import { ServerEvent } from './constants' import { ServerEvent } from './constants'
import { ServerOptions } from '../socket-io'; import { ServerOptions } from '../socket-io';
import { TextWebSocketFrameHandlerAdapter } from '../netty'
export class TextWebSocketFrameHandler extends TextWebSocketFrameHandlerAdapter { export class TextWebSocketFrameHandler extends TextWebSocketFrameHandlerAdapter {
private event: EventEmitter; private event: EventEmitter;