diff --git a/packages/api/src/typings/global.ts b/packages/api/src/typings/global.ts
index 1124866e..5ca641be 100644
--- a/packages/api/src/typings/global.ts
+++ b/packages/api/src/typings/global.ts
@@ -17,6 +17,7 @@ declare global {
function engineLoad(str: string): any;
interface Core {
getClass(name: String): any;
+ getProxyClass(): any;
getInstance(): any;
read(path: string): string;
save(path: string, content: string): void;
diff --git a/packages/common/src/fs.ts b/packages/common/src/fs.ts
index 5a9069dc..899dbb93 100644
--- a/packages/common/src/fs.ts
+++ b/packages/common/src/fs.ts
@@ -12,8 +12,8 @@ const StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
/**
* 用文件分割符合并路径
*/
-export function concat() {
- return Array.prototype.join.call(arguments, separatorChar);
+export function concat(...args: string[]) {
+ return args.join(separatorChar);
}
/**
@@ -23,12 +23,12 @@ export function concat() {
* @returns {*}
*/
export function file(...opts: any[]): any {
- if (!arguments[0]) {
+ if (!opts[0]) {
console.warn("文件名称不得为 undefined 或者 null !");
}
- switch (arguments.length) {
+ switch (opts.length) {
case 1:
- var f = arguments[0];
+ var f = opts[0];
if (f instanceof File) {
return f;
}
@@ -40,7 +40,7 @@ export function file(...opts: any[]): any {
}
break;
default:
- return new File(file(arguments[0]), arguments[1]);
+ return new File(file(opts[0]), opts[1]);
}
}
@@ -48,7 +48,7 @@ export function file(...opts: any[]): any {
* 创建目录
* @param path
*/
-export function mkdirs(path) {
+export function mkdirs(path: any) {
// noinspection JSUnresolvedVariable
file(path).parentFile.mkdirs();
}
@@ -57,7 +57,7 @@ export function mkdirs(path) {
* 创建文件
* @param file
*/
-export function create(path) {
+export function create(path: any) {
var f = file(path);
if (!f.exists()) {
mkdirs(f);
@@ -70,7 +70,7 @@ export function create(path) {
* @param file
* @returns {*}
*/
-export function path(f) {
+export function path(f: any) {
return file(f).canonicalPath;
}
@@ -80,7 +80,7 @@ export function path(f) {
* @param target 目标文件
* @param override 是否覆盖
*/
-export function copy(inputStream, target, override) {
+export function copy(inputStream: any, target: any, override: any) {
Files.copy(inputStream, target.toPath(), StandardCopyOption[override ? 'REPLACE_EXISTING' : 'ATOMIC_MOVE']);
}
diff --git a/packages/plugins/public/js/main.js b/packages/plugins/public/js/main.js
index 88029812..3fce69e6 100644
--- a/packages/plugins/public/js/main.js
+++ b/packages/plugins/public/js/main.js
@@ -6,7 +6,7 @@ var main = avalon.define({
server: window.localStorage.getItem(serverKey) || location.host,
type: 'unknow',
logs: '',
- codes: ["default", "bukkit", "sponge", "common", "test", "dev", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
+ codes: ["default", "bukkit", "sponge", "bungee", "common", "test", "dev", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
code: 'default',
classes: {
total: 0,
diff --git a/packages/plugins/src/HelloWorld.ts b/packages/plugins/src/HelloWorld.ts
index 008993c9..0cd7daaf 100644
--- a/packages/plugins/src/HelloWorld.ts
+++ b/packages/plugins/src/HelloWorld.ts
@@ -1,3 +1,7 @@
+///
+///
+///
+
import { plugin, interfaces, cmd, listener, tab } from '@ms/plugin'
@plugin({ name: 'HelloWorld', version: '1.0.0', author: 'MiaoWoo', source: __filename })
@@ -32,6 +36,16 @@ export class HelloWorld extends interfaces.Plugin {
this.logger.log('Disable When ServerType is Sponge!')
}
+ bungeeload() {
+ this.logger.log('Load When ServerType is BungeeCord!')
+ }
+ bungeeenable() {
+ this.logger.log('Enable When ServerType is BungeeCord!')
+ }
+ bungeedisable() {
+ this.logger.log('Disable When ServerType is BungeeCord!')
+ }
+
@cmd()
hello(sender: any, command: string, args: string[]) {
this.logger.log(sender, command, args);
@@ -44,14 +58,22 @@ export class HelloWorld extends interfaces.Plugin {
}
@listener({ servertype: 'bukkit' })
- playerjoin(event: any) {
- this.logger.console(`§aBukkit PlayerJoinEvent: §b${event.player.name}`)
- setTimeout(() => this.logger.sender(event.player, `§a欢迎来到 §bMiaoScript §a的世界!`), 10);
+ playerjoin(event: org.bukkit.event.player.PlayerJoinEvent) {
+ let plyaer = event.getPlayer();
+ this.logger.console(`§cBukkit §aPlayerJoinEvent: §b${plyaer.getName()}`)
+ setTimeout(() => this.logger.sender(plyaer, `§a欢迎来到 §bMiaoScript §a的世界!`), 10);
}
@listener({ servertype: 'sponge' })
- clientconnectionevent$join(event: any) {
- this.logger.console(`§aSponge ClientConnectionEvent.Join: §b${event.targetEntity.name}`)
- setTimeout(() => this.logger.sender(event.targetEntity, `§a欢迎来到 §bMiaoScript §a的世界!`), 10);
+ clientconnectionevent$join(event: org.spongepowered.api.event.network.ClientConnectionEvent.Join) {
+ this.logger.console(`§cSponge §aClientConnectionEvent.Join: §b${event.getTargetEntity().getName()}`)
+ setTimeout(() => this.logger.sender(event.getTargetEntity(), `§a欢迎来到 §bMiaoScript §a的世界!`), 10);
+ }
+
+ @listener({ servertype: 'bungee' })
+ serverconnected(e: any) {
+ let event = e as net.md_5.bungee.api.event.ServerConnectedEvent
+ this.logger.console(`§cBungeeCord §aServerConnectedEvent: §b${event.getPlayer().getDisplayName()}`)
+ setTimeout(() => this.logger.sender(event.getPlayer(), `§a欢迎来到 §bMiaoScript §a的世界 §6来自 §cBungeeCord §6的问候!`), 10);
}
}
diff --git a/packages/plugins/src/MiaoChat.ts b/packages/plugins/src/MiaoChat.ts
new file mode 100644
index 00000000..693d00be
--- /dev/null
+++ b/packages/plugins/src/MiaoChat.ts
@@ -0,0 +1,271 @@
+///
+///
+
+import { server } from '@ms/api'
+import { inject } from '@ms/container';
+import { plugin, interfaces, cmd, listener, tab } from '@ms/plugin'
+import Tellraw from '@ms/common/dist/tellraw'
+
+@plugin({ name: 'MiaoChat', version: '1.0.0', author: 'MiaoWoo', source: __filename })
+export class MiaoChat extends interfaces.Plugin {
+ @inject(server.Server)
+ private Server: server.Server
+
+ private config = {
+ Version: "1.8.5",
+ BungeeCord: true,
+ Server: "生存服",
+ ChatFormats: {
+ default: {
+ index: 50,
+ permission: "MiaoChat.default",
+ range: 0,
+ format: "[world][player]: ",
+ item: true,
+ itemformat: "&6[&b%s&6]&r"
+ },
+ admin: {
+ index: 49,
+ permission: "MiaoChat.admin",
+ format: "[admin][world][player][help]: ",
+ range: 0,
+ item: true,
+ itemformat: "&6[&b%s&6]&r"
+ }
+ },
+ StyleFormats: {
+ world: {
+ text: "&6[&a%player_world%&6]",
+ hover: [
+ "&6当前所在位置:",
+ "&6世界: &d%player_world%",
+ "&6坐标: &aX:%player_x% Y: %player_y% Z: %player_z%",
+ "",
+ "&c点击即可TP我!"
+ ],
+ click: {
+ type: "COMMAND",
+ command: "/tpa %player_name%"
+ }
+ },
+ player: {
+ text: "&b%player_name%",
+ hover: [
+ "&6玩家名称: &b%player_name%",
+ "&6玩家等级: &a%player_level%",
+ "&6玩家血量: &c%player_health%",
+ "&6玩家饥饿: &d%player_food_level%",
+ "&6游戏模式: &4%player_gamemode%",
+ "",
+ "&c点击与我聊天"
+ ],
+ click: {
+ type: "SUGGEST",
+ command: "/tell %player_name%"
+ }
+ },
+ admin: {
+ text: "&6[&c管理员&6]"
+ },
+ help: {
+ text: "&4[求助]",
+ hover: [
+ "点击求助OP"
+ ],
+ click: {
+ type: "COMMAND",
+ command: "管理员@%player_name% 我需要你的帮助!"
+ }
+ }
+ }
+ }
+
+ private chatFormats: any[];
+ private styleFormats: any;
+ // 用于匹配 '[xx]' 聊天格式
+ private FORMAT_PATTERN = /[\[]([^\[\]]+)[\]]/ig;
+
+ private PlaceholderAPI: { setPlaceholders: (player: any, str: string) => string };
+
+ load() {
+ if (!Object.values) {
+ Object.defineProperty(Object, "values", {
+ enumerable: false,
+ configurable: true,
+ writable: true,
+ value: function(target) {
+ "use strict";
+ var values = [];
+ for (var key in target) {
+ var desc = Object.getOwnPropertyDescriptor(target, key);
+ if (desc !== undefined && desc.enumerable) values.push(target[key]);
+ }
+ return values;
+ }
+ });
+ }
+ this.chatFormats = Object.values(this.config.ChatFormats);
+ this.chatFormats.sort(this.compare('index'));
+ this.initFormat(this.chatFormats);
+ this.styleFormats = this.config.StyleFormats;
+ }
+
+ private compare(prop: string) {
+ return function(obj1: { [x: string]: any; }, obj2: { [x: string]: any; }) {
+ var val1 = obj1[prop];
+ var val2 = obj2[prop];
+ if (!isNaN(Number(val1)) && !isNaN(Number(val2))) {
+ val1 = Number(val1);
+ val2 = Number(val2);
+ }
+ if (val1 < val2) {
+ return -1;
+ } else if (val1 > val2) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ }
+
+ enable() {
+ }
+ disable() {
+ }
+
+ bukkitenable() {
+ // 尝试加载 Bukkit 的 PlaceholderAPI
+ try {
+ //@ts-ignore
+ this.PlaceholderAPI = base.getClass("me.clip.placeholderapi.PlaceholderAPI").static;
+ console.log('[PAPI] Found Bukkit PlaceholderAPI Hooking...')
+ } catch (ex) {
+ }
+ }
+
+ spongeenable() {
+ // 尝试加载 Sponge 的 PlaceholderAPI
+ try {
+ var spongePapi = this.Server.getService('me.rojo8399.placeholderapi.PlaceholderService');
+ var s = org.spongepowered.api.text.serializer.TextSerializers.formattingCode('§');
+ if (spongePapi) {
+ this.PlaceholderAPI = {
+ setPlaceholders: (player: any, string: string) => {
+ return s.serialize(spongePapi.replacePlaceholders(string, player, player));
+ }
+ };
+ console.log('[PAPI] Found Sponge PlaceholderAPI Hooking...')
+ }
+ } catch (ex) {
+ }
+ }
+
+ @cmd()
+ mchat(sender: any, command: string, args: string[]) {
+ this.logger.log(sender, command, args);
+ sender.sendMessage(JSON.stringify({ command, ...args }))
+ }
+
+ @tab()
+ tabmchat(_sender: any, _command: string, _args: string[]) {
+ }
+
+ @listener({ servertype: 'bukkit' })
+ AsyncPlayerChatEvent(event: org.bukkit.event.player.AsyncPlayerChatEvent) {
+ this.sendChat(event.getPlayer(), event.getMessage(), function() {
+ event.setCancelled(true);
+ });
+ }
+
+ @listener({ servertype: 'sponge' })
+ MessageChannelEvent$Chat(event: org.spongepowered.api.event.message.MessageChannelEvent.Chat) {
+ //@ts-ignore
+ var player = event.getCause().first(org.spongepowered.api.entity.living.player.Player.class).orElse(null);
+ if (player == null) {
+ return;
+ }
+ var plain = event.getRawMessage().toPlain();
+ if (plain.startsWith(Tellraw.duplicateChar)) {
+ return;
+ }
+ this.sendChat(player, plain, function() {
+ event.setMessageCancelled(true)
+ });
+ }
+
+ initFormat(chatFormats: any[]) {
+ chatFormats.forEach(chatFormat => {
+ var chat_format_str = chatFormat.format;
+ var temp = [];
+ var r: any[];
+ while (r = this.FORMAT_PATTERN.exec(chat_format_str)) {
+ temp.push(r[1]);
+ }
+ var format_list = [];
+ temp.forEach(function splitStyle(t) {
+ var arr = chat_format_str.split('[' + t + ']', 2);
+ if (arr[0]) {
+ format_list.push(arr[0]);
+ }
+ format_list.push(t);
+ chat_format_str = arr[1];
+ });
+ if (chat_format_str) {
+ format_list.push(chat_format_str);
+ }
+ chatFormat.format_list = format_list;
+ })
+ }
+
+ sendChat(player: any, plain: string, callback: { (): void; }) {
+ var chat_format = this.getChatFormat(player);
+ if (!chat_format) {
+ console.debug('未获得用户', player.getName(), '的 ChatRule 跳过执行...');
+ return;
+ }
+ callback();
+ var tr = Tellraw.create();
+ chat_format.format_list.forEach((format) => {
+ var style = this.styleFormats[format];
+ if (style) {
+ tr.then(this.replace(player, style.text));
+ if (style.hover) {
+ tr.tip(this.replace(player, style.hover.join('\n')));
+ }
+ if (style.click && style.click.type && style.click.command) {
+ var command = this.replace(player, style.click.command);
+ switch (style.click.type.toUpperCase()) {
+ case "COMMAND":
+ tr.command(command);
+ break;
+ case "OPENURL":
+ tr.link(command);
+ break;
+ case "SUGGEST":
+ tr.suggest(command);
+ break;
+ default:
+ }
+ }
+ } else {
+ tr.then(this.replace(player, format));
+ }
+ });
+ let json = tr.then(this.replace(player, plain)).json()
+ this.Server.getOnlinePlayers().forEach(player => this.Server.sendJson(player, json))
+ }
+
+ getChatFormat(player: any) {
+ for (var i in this.chatFormats) {
+ var format = this.chatFormats[i];
+ if (player.hasPermission(format.permission)) {
+ return format;
+ }
+ }
+ return null;
+ }
+
+ replace(player: any, target: string) {
+ return this.PlaceholderAPI.setPlaceholders(player, target)
+ }
+}
diff --git a/packages/plugins/src/MiaoScriptPackageManager.ts b/packages/plugins/src/MiaoScriptPackageManager.ts
index 0c957030..9344b442 100644
--- a/packages/plugins/src/MiaoScriptPackageManager.ts
+++ b/packages/plugins/src/MiaoScriptPackageManager.ts
@@ -1,7 +1,8 @@
-import { plugin as pluginApi, task } from '@ms/api'
+import { plugin as pluginApi, task, server } from '@ms/api'
+import * as fs from '@ms/common/dist/fs'
import { inject } from '@ms/container';
-import { plugin, cmd, tab } from '@ms/plugin'
+import { interfaces, plugin, cmd, tab } from '@ms/plugin'
let help = [
'§6========= §6[§aMiaoScriptPackageManager§6] 帮助 §aBy §b喵♂呜 §6=========',
@@ -16,23 +17,21 @@ let help = [
];
@plugin({ name: 'MiaoScriptPackageManager', prefix: 'PM', version: '1.0.0', author: 'MiaoWoo', source: __filename })
-export class MiaoScriptPackageManager {
+export class MiaoScriptPackageManager extends interfaces.Plugin {
@inject(pluginApi.PluginManager)
private pluginManager: pluginApi.PluginManager;
@inject(task.TaskManager)
private taskManager: task.TaskManager;
+ @inject(server.ServerType)
+ private serverType: string;
+ @inject(server.Server)
+ private server: server.Server
- private pluginCache = [];
- private packageCache = [];
- private packageNameCache = [];
+ private packageCache: any[] = [];
+ private packageNameCache: any[] = [];
load() {
this.taskManager.create(() => {
- this.pluginCache = [...this.pluginManager.getPlugins().keys()];
- // JSON.parse(http.get(self.config.center)).data.forEach(function cachePackageName(pkg) {
- // packageCache[pkg.name] = pkg;
- // })
- // packageNameCache = Object.keys(packageCache);
}).async().submit();
}
@@ -47,19 +46,19 @@ export class MiaoScriptPackageManager {
main(sender: any, command: string, args: string[]) {
if (!args[0] || args[1] === 'help') {
- console.sender(sender, help);
+ this.logger.sender(sender, help);
return;
}
switch (args[0]) {
case "list":
if (args[1]) {
- console.sender(sender, '§6当前 §bMiaoScript §6已安装下列插件:');
- this.pluginCache.forEach(function listInfo(pluginName) {
- // var desc = manager.plugins[pluginName].description;
- // console.sender(sender, `§6插件名称: §b${desc.name} §6版本: §a${desc.version|| '1.0'} §6作者: §3${desc.author || '未知'}`)
+ this.logger.sender(sender, '§6当前 §bMiaoScript §6已安装下列插件:');
+ this.pluginManager.getPlugins().forEach((plugin) => {
+ var desc = plugin.description;
+ this.logger.sender(sender, `§6插件名称: §b${desc.name} §6版本: §a${desc.version || '1.0'} §6作者: §3${desc.author || '未知'}`)
})
} else {
- console.sender(sender, '§6当前 §bMiaoScriptPackageCenter §6中存在下列插件:');
+ this.logger.sender(sender, '§6当前 §bMiaoScriptPackageCenter §6中存在下列插件:');
for (var pkgName in this.packageCache) {
var pkg = this.packageCache[pkgName];
// console.sender(sender, '§6插件名称: §b%s §6版本: §a%s §6作者: §3%s'.format(pkg.name, pkg.version || '1.0', pkg.author || '未知'))
@@ -82,6 +81,9 @@ export class MiaoScriptPackageManager {
// }
break;
case "upgrade":
+ if (args[3] === "engine") {
+ fs.del(fs.concat(root, '', ''))
+ }
break;
case "delete":
// if (args.length > 1) {
@@ -91,57 +93,59 @@ export class MiaoScriptPackageManager {
// }
break;
case "reload":
- // if (args.length > 1) {
- // var pname = args[1];
- // if (pluginCache.indexOf(pname) !== -1) {
- // manager.reload(pname)
- // console.sender(sender, '§6插件 §b%s §a重载完成!'.format(pname))
- // } else {
- // console.sender(sender, '§c插件 §b%s §c不存在!'.format(pname))
- // }
- // } else {
- // self.reloadConfig();
- // load();
- // }
+ if (args.length > 1) {
+ var pname = args[1];
+ if (!this.pluginManager.getPlugins().has(pname)) {
+ this.logger.sender(sender, `§6插件 §b${pname} §c不存在!`)
+ return
+ }
+ this.pluginManager.reload(pname);
+ this.logger.sender(sender, `§6插件 §b${pname} §a重载完成!`)
+ }
break;
case "restart":
+ if (this.serverType === "sponge") {
+ setTimeout(() => this.server.dispatchConsoleCommand('sponge plugins reload'), 0)
+ return
+ }
try {
- console.sender(sender, '§6Reloading §3MiaoScript Engine...');
+ this.logger.sender(sender, '§6Reloading §3MiaoScript Engine...');
ScriptEngineContextHolder.disableEngine();
ScriptEngineContextHolder.enableEngine();
- console.sender(sender, '§3MiaoScript Engine §6Reload §aSuccessful...');
+ this.logger.sender(sender, '§3MiaoScript Engine §6Reload §aSuccessful...');
} catch (ex) {
- console.sender(sender, "§3MiaoScript Engine §6Reload §cError! ERR: " + ex);
- console.sender(sender, console.stack(ex));
+ this.logger.sender(sender, "§3MiaoScript Engine §6Reload §cError! ERR: " + ex);
+ this.logger.sender(sender, this.logger.stack(ex));
}
break;
case "run":
args.shift();
try {
- var script = args.join(' ')
- console.sender(sender, '§b运行脚本:§r', script)
- console.sender(sender, '§a返回结果:§r', eval(script) || '§4没有返回结果!');
+ var script = args.join(' ');
+ this.logger.sender(sender, '§b运行脚本:§r', script);
+ this.logger.sender(sender, '§a返回结果:§r', eval(script) || '§4没有返回结果!');
} catch (ex) {
- console.sender(sender, console.stack(ex))
+ this.logger.sender(sender, this.logger.stack(ex));
}
break;
case "create":
+ this.logger.sender(sender, `§4当前暂不支持生成插件模板!`);
// var name = args[1];
// if (!name) {
- // console.sender(sender, '§4参数错误 /mpm create <插件名称> [作者] [版本] [主命令]');
+ // this.logger.sender(sender, '§4参数错误 /mpm create <插件名称> [作者] [版本] [主命令]');
// return;
// }
- // var result = template.create(http.get(self.config.template)).render({
- // name: name,
- // author: args[2] || 'MiaoWoo',
- // version: args[3] || '1.0',
- // command: args[4] || name.toLowerCase(),
- // });
- // fs.save(fs.file(__dirname, name + '.js'), result);
- // console.sender(sender, '§6插件 §a' + name + ' §6已生成到插件目录...');
+ // // var result = template.create(http.get(self.config.template)).render({
+ // // name: name,
+ // // author: args[2] || 'MiaoWoo',
+ // // version: args[3] || '1.0',
+ // // command: args[4] || name.toLowerCase(),
+ // // });
+ // // fs.save(fs.file(__dirname, name + '.js'), result);
+ // this.logger.sender(sender, '§6插件 §a' + name + ' §6已生成到插件目录...');
break;
default:
- console.sender(sender, help);
+ this.logger.sender(sender, help);
break;
}
}
@@ -156,8 +160,8 @@ export class MiaoScriptPackageManager {
case "update":
case "upgrade":
case "reload":
- return this.pluginCache;
+ return [...this.pluginManager.getPlugins().keys()];
}
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/plugins/src/Test.ts b/packages/plugins/src/Test.ts
index a5711050..e9467ba5 100644
--- a/packages/plugins/src/Test.ts
+++ b/packages/plugins/src/Test.ts
@@ -2,6 +2,9 @@ import { plugin as pluginApi } from '@ms/api'
import { plugin, interfaces, cmd, listener, tab } from '@ms/plugin'
import { inject } from '@ms/container';
+import * as reflect from '@ms/common/dist/reflect';
+import http from '@ms/common/dist/http';
+
@plugin({ name: 'Test', version: '1.0.0', author: 'MiaoWoo', source: __filename })
export class Test extends interfaces.Plugin {
@inject(pluginApi.PluginManager)
@@ -51,7 +54,18 @@ export class Test extends interfaces.Plugin {
setTimeout(() => location.block.type = Java.type('org.bukkit.Material').STONE, 8);
break;
case "add":
- require('js-yaml1');
+ break;
+ case "get":
+ let result = http.get('https://www.baidu.com');
+ this.logger.sender(sender, JSON.stringify(result));
+ // 好了 扯结束 继续咸鱼
+ break;
+ case "ws":
+ let Sponge = Java.type('org.spongepowered.api.Sponge');
+ // let promise = reflect.on(Bukkit.server).get('console').get('field_147144_o').get('field_151274_e').get().get(0);
+ console.log(reflect.on(Sponge.server).get('field_147144_o').get())
+ // let channel = reflect.on(promise).get('channel').get().pipeline().first();
+ // console.log(channel);
break;
default:
this.logger.log(sender, command, args);
diff --git a/packages/plugins/src/WebSocket.ts b/packages/plugins/src/WebSocket.ts
index 49fcd934..2523e8a9 100644
--- a/packages/plugins/src/WebSocket.ts
+++ b/packages/plugins/src/WebSocket.ts
@@ -1,6 +1,8 @@
///
///
-import { plugin as pluginApi, server } from '@ms/api'
+///
+
+import { plugin as pluginApi, server, task } from '@ms/api'
import { plugin, interfaces, cmd } from '@ms/plugin'
import { DefaultContainer as container, inject, postConstruct } from '@ms/container'
import * as reflect from '@ms/common/dist/reflect'
@@ -8,25 +10,31 @@ import * as reflect from '@ms/common/dist/reflect'
let clients: any[] = []
let SPLIT_LINE = '\\M\\W\\S|T|S|S/L/T/'
const refList: Array<{ server: string, future: string }> = [
- { server: 'an', future: 'g' },
- { server: 'getServerConnection', future: 'f' },
- { server: 'func_147137_ag', future: 'field_151274_e' }
+ { server: 'an', future: 'g' },//spigot 1.12.2
+ { server: 'getServerConnection', future: 'f' },//spigot 1.14.4
+ { server: 'func_147137_ag', future: 'field_151274_e' }//catserver 1.12.2
]
const Callable = Java.type('java.util.concurrent.Callable')
+const Runnable = Java.type('java.lang.Runnable')
-@plugin({ name: 'WebSocket', version: '1.0.0', author: 'MiaoWoo', source: __filename })
-export class WebSocket extends interfaces.Plugin {
+@plugin({ name: 'MiaoConsole', version: '1.0.0', author: 'MiaoWoo', source: __filename })
+export class MiaoConsole extends interfaces.Plugin {
@inject(pluginApi.PluginManager)
private PluginManager: pluginApi.PluginManager
@inject(server.ServerType)
private ServerType: string
+ @inject(server.Server)
+ private Server: server.Server
+ @inject(task.TaskManager)
+ private Task: task.TaskManager
@inject(pluginApi.PluginInstance)
private pluginInstance: any
+
private pipeline: any
@cmd()
- ws(sender: any, command: string, args: string[]) {
+ mconsole(sender: any, command: string, args: string[]) {
switch (args[0]) {
case "reload":
this.PluginManager.reload(this)
@@ -37,7 +45,9 @@ export class WebSocket extends interfaces.Plugin {
disable() {
if (this.pipeline) {
- this.pipeline.remove('miao_detect')
+ if (this.pipeline.names().contains('miao_detect')) {
+ this.pipeline.remove('miao_detect')
+ }
clients.forEach(c => c.close())
container.unbind('onmessage')
}
@@ -46,13 +56,28 @@ export class WebSocket extends interfaces.Plugin {
bukkitenable() {
let Bukkit = Java.type('org.bukkit.Bukkit')
let consoleServer = reflect.on(Bukkit.getServer()).get('console').get()
- this.injectMiaoDetect(this.reflectPromise(consoleServer))
+ this.reflectChannel(this.reflectPromise(consoleServer))
+ this.injectMiaoDetect()
}
spongeenable() {
let Sponge = Java.type('org.spongepowered.api.Sponge')
let consoleServer = reflect.on(Sponge.getServer()).get()
- this.injectMiaoDetect(this.reflectPromise(consoleServer))
+ 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) {
@@ -61,16 +86,20 @@ export class WebSocket extends interfaces.Plugin {
}
}
- injectMiaoDetect(promise) {
+ reflectChannel(promise) {
if (!promise) { throw Error(`Can't found ServerConnection or ChannelFuture !`) }
this.pipeline = reflect.on(promise).get('channel').get().pipeline()
+ }
+
+ injectMiaoDetect() {
this.pipeline.addFirst('miao_detect', new MiaoDetectHandler())
container.bind('onmessage').toFunction(this.onmessage.bind(this))
+ this.logger.info('Netty Channel Pipeline Inject MiaoDetectHandler Successful!')
}
onmessage(ctx: any, msg: any) {
let text: string = msg.text()
- const [type, content] = text.split('\\M\\W\\S|T|S|S/L/T/')
+ const [type, content] = text.split(SPLIT_LINE)
try {
var result = this[type](ctx, content)
} catch (ex) {
@@ -80,13 +109,7 @@ export class WebSocket extends interfaces.Plugin {
}
execCommand(ctx: any, cmd: string) {
- switch (this.ServerType) {
- case "bukkit":
- org.bukkit.Bukkit.dispatchCommand(org.bukkit.Bukkit.getConsoleSender(), cmd)
- break
- case "sponge":
- break
- }
+ setTimeout(() => this.Server.dispatchConsoleCommand(cmd), 0)
return `§6命令: §b${cmd} §a执行成功!`
}
@@ -95,16 +118,17 @@ export class WebSocket extends interfaces.Plugin {
case "bukkit":
return org.bukkit.Bukkit.getScheduler().callSyncMethod(this.pluginInstance, new Callable({ call: () => eval(code) })).get() || '无返回结果'
case "sponge":
- return ''
+ return org.spongepowered.api.Sponge.getScheduler().createSyncExecutor(this.pluginInstance).schedule(new Runnable({ run: () => eval(code) }), 0, {})
+ case "bungee":
+ return eval(code)
}
}
execDetect(ctx: any, cmd: string) {
switch (cmd) {
case "type":
- let version = this.ServerType == 'bukkit' ? org.bukkit.Bukkit.getServer().getVersion() : org.spongepowered.api.Sponge.getPlatform().getMinecraftVersion()
this.sendResult(ctx, "type", this.ServerType)
- return `Currect Server Version is ${version}`
+ return `Currect Server Version is ${this.Server.getVersion()}`
}
}
@@ -196,7 +220,7 @@ const WebSocketHandler = Java.extend(ChannelInboundHandlerAdapter, {
let channel = ctx.channel()
let pipeline = channel.pipeline()
if (message.indexOf('HTTP/1.1') > 0) {
- channel.pipeline().names().forEach(f => {
+ pipeline.names().forEach(f => {
if (f == 'miaowebsocket' || f.indexOf('DefaultChannelPipeline') > -1) { return }
pipeline.remove(f)
})