feat: update plugins

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
MiaoWoo 2020-01-16 17:27:24 +08:00
parent 7263fbb437
commit fb83acfcc8
8 changed files with 426 additions and 90 deletions

View File

@ -17,6 +17,7 @@ declare global {
function engineLoad(str: string): any; function engineLoad(str: string): any;
interface Core { interface Core {
getClass(name: String): any; getClass(name: String): any;
getProxyClass(): any;
getInstance(): any; getInstance(): any;
read(path: string): string; read(path: string): string;
save(path: string, content: string): void; save(path: string, content: string): void;

View File

@ -12,8 +12,8 @@ const StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
/** /**
* *
*/ */
export function concat() { export function concat(...args: string[]) {
return Array.prototype.join.call(arguments, separatorChar); return args.join(separatorChar);
} }
/** /**
@ -23,12 +23,12 @@ export function concat() {
* @returns {*} * @returns {*}
*/ */
export function file(...opts: any[]): any { export function file(...opts: any[]): any {
if (!arguments[0]) { if (!opts[0]) {
console.warn("文件名称不得为 undefined 或者 null !"); console.warn("文件名称不得为 undefined 或者 null !");
} }
switch (arguments.length) { switch (opts.length) {
case 1: case 1:
var f = arguments[0]; var f = opts[0];
if (f instanceof File) { if (f instanceof File) {
return f; return f;
} }
@ -40,7 +40,7 @@ export function file(...opts: any[]): any {
} }
break; break;
default: 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 * @param path
*/ */
export function mkdirs(path) { export function mkdirs(path: any) {
// noinspection JSUnresolvedVariable // noinspection JSUnresolvedVariable
file(path).parentFile.mkdirs(); file(path).parentFile.mkdirs();
} }
@ -57,7 +57,7 @@ export function mkdirs(path) {
* *
* @param file * @param file
*/ */
export function create(path) { export function create(path: any) {
var f = file(path); var f = file(path);
if (!f.exists()) { if (!f.exists()) {
mkdirs(f); mkdirs(f);
@ -70,7 +70,7 @@ export function create(path) {
* @param file * @param file
* @returns {*} * @returns {*}
*/ */
export function path(f) { export function path(f: any) {
return file(f).canonicalPath; return file(f).canonicalPath;
} }
@ -80,7 +80,7 @@ export function path(f) {
* @param target * @param target
* @param override * @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']); Files.copy(inputStream, target.toPath(), StandardCopyOption[override ? 'REPLACE_EXISTING' : 'ATOMIC_MOVE']);
} }

View File

@ -6,7 +6,7 @@ var main = avalon.define({
server: window.localStorage.getItem(serverKey) || location.host, server: window.localStorage.getItem(serverKey) || location.host,
type: 'unknow', type: 'unknow',
logs: '', 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', code: 'default',
classes: { classes: {
total: 0, total: 0,

View File

@ -1,3 +1,7 @@
/// <reference types="@ms/types/dist/typings/bukkit" />
/// <reference types="@ms/types/dist/typings/sponge" />
/// <reference types="@ms/types/dist/typings/bungee" />
import { plugin, interfaces, cmd, listener, tab } from '@ms/plugin' import { plugin, interfaces, cmd, listener, tab } from '@ms/plugin'
@plugin({ name: 'HelloWorld', version: '1.0.0', author: 'MiaoWoo', source: __filename }) @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!') 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() @cmd()
hello(sender: any, command: string, args: string[]) { hello(sender: any, command: string, args: string[]) {
this.logger.log(sender, command, args); this.logger.log(sender, command, args);
@ -44,14 +58,22 @@ export class HelloWorld extends interfaces.Plugin {
} }
@listener({ servertype: 'bukkit' }) @listener({ servertype: 'bukkit' })
playerjoin(event: any) { playerjoin(event: org.bukkit.event.player.PlayerJoinEvent) {
this.logger.console(`§aBukkit PlayerJoinEvent: §b${event.player.name}`) let plyaer = event.getPlayer();
setTimeout(() => this.logger.sender(event.player, `§a欢迎来到 §bMiaoScript §a的世界!`), 10); this.logger.console(`§cBukkit §aPlayerJoinEvent: §b${plyaer.getName()}`)
setTimeout(() => this.logger.sender(plyaer, `§a欢迎来到 §bMiaoScript §a的世界!`), 10);
} }
@listener({ servertype: 'sponge' }) @listener({ servertype: 'sponge' })
clientconnectionevent$join(event: any) { clientconnectionevent$join(event: org.spongepowered.api.event.network.ClientConnectionEvent.Join) {
this.logger.console(`§aSponge ClientConnectionEvent.Join: §b${event.targetEntity.name}`) this.logger.console(`§cSponge §aClientConnectionEvent.Join: §b${event.getTargetEntity().getName()}`)
setTimeout(() => this.logger.sender(event.targetEntity, `§a欢迎来到 §bMiaoScript §a的世界!`), 10); 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);
} }
} }

View File

@ -0,0 +1,271 @@
/// <reference types="@ms/types/dist/typings/bukkit" />
/// <reference types="@ms/types/dist/typings/sponge" />
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)
}
}

View File

@ -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 { inject } from '@ms/container';
import { plugin, cmd, tab } from '@ms/plugin' import { interfaces, plugin, cmd, tab } from '@ms/plugin'
let help = [ let help = [
'§6========= §6[§aMiaoScriptPackageManager§6] 帮助 §aBy §b喵♂呜 §6=========', '§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 }) @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) @inject(pluginApi.PluginManager)
private pluginManager: pluginApi.PluginManager; private pluginManager: pluginApi.PluginManager;
@inject(task.TaskManager) @inject(task.TaskManager)
private taskManager: task.TaskManager; private taskManager: task.TaskManager;
@inject(server.ServerType)
private serverType: string;
@inject(server.Server)
private server: server.Server
private pluginCache = []; private packageCache: any[] = [];
private packageCache = []; private packageNameCache: any[] = [];
private packageNameCache = [];
load() { load() {
this.taskManager.create(() => { 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(); }).async().submit();
} }
@ -47,19 +46,19 @@ export class MiaoScriptPackageManager {
main(sender: any, command: string, args: string[]) { main(sender: any, command: string, args: string[]) {
if (!args[0] || args[1] === 'help') { if (!args[0] || args[1] === 'help') {
console.sender(sender, help); this.logger.sender(sender, help);
return; return;
} }
switch (args[0]) { switch (args[0]) {
case "list": case "list":
if (args[1]) { if (args[1]) {
console.sender(sender, '§6当前 §bMiaoScript §6已安装下列插件:'); this.logger.sender(sender, '§6当前 §bMiaoScript §6已安装下列插件:');
this.pluginCache.forEach(function listInfo(pluginName) { this.pluginManager.getPlugins().forEach((plugin) => {
// var desc = manager.plugins[pluginName].description; var desc = plugin.description;
// console.sender(sender, `§6插件名称: §b${desc.name} §6版本: §a${desc.version|| '1.0'} §6作者: §3${desc.author || '未知'}`) this.logger.sender(sender, `§6插件名称: §b${desc.name} §6版本: §a${desc.version || '1.0'} §6作者: §3${desc.author || '未知'}`)
}) })
} else { } else {
console.sender(sender, '§6当前 §bMiaoScriptPackageCenter §6中存在下列插件:'); this.logger.sender(sender, '§6当前 §bMiaoScriptPackageCenter §6中存在下列插件:');
for (var pkgName in this.packageCache) { for (var pkgName in this.packageCache) {
var pkg = this.packageCache[pkgName]; 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 || '未知')) // 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; break;
case "upgrade": case "upgrade":
if (args[3] === "engine") {
fs.del(fs.concat(root, '', ''))
}
break; break;
case "delete": case "delete":
// if (args.length > 1) { // if (args.length > 1) {
@ -91,57 +93,59 @@ export class MiaoScriptPackageManager {
// } // }
break; break;
case "reload": case "reload":
// if (args.length > 1) { if (args.length > 1) {
// var pname = args[1]; var pname = args[1];
// if (pluginCache.indexOf(pname) !== -1) { if (!this.pluginManager.getPlugins().has(pname)) {
// manager.reload(pname) this.logger.sender(sender, `§6插件 §b${pname} §c不存在!`)
// console.sender(sender, '§6插件 §b%s §a重载完成!'.format(pname)) return
// } else { }
// console.sender(sender, '§c插件 §b%s §c不存在!'.format(pname)) this.pluginManager.reload(pname);
// } this.logger.sender(sender, `§6插件 §b${pname} §a重载完成!`)
// } else { }
// self.reloadConfig();
// load();
// }
break; break;
case "restart": case "restart":
if (this.serverType === "sponge") {
setTimeout(() => this.server.dispatchConsoleCommand('sponge plugins reload'), 0)
return
}
try { try {
console.sender(sender, '§6Reloading §3MiaoScript Engine...'); this.logger.sender(sender, '§6Reloading §3MiaoScript Engine...');
ScriptEngineContextHolder.disableEngine(); ScriptEngineContextHolder.disableEngine();
ScriptEngineContextHolder.enableEngine(); ScriptEngineContextHolder.enableEngine();
console.sender(sender, '§3MiaoScript Engine §6Reload §aSuccessful...'); this.logger.sender(sender, '§3MiaoScript Engine §6Reload §aSuccessful...');
} catch (ex) { } catch (ex) {
console.sender(sender, "§3MiaoScript Engine §6Reload §cError! ERR: " + ex); this.logger.sender(sender, "§3MiaoScript Engine §6Reload §cError! ERR: " + ex);
console.sender(sender, console.stack(ex)); this.logger.sender(sender, this.logger.stack(ex));
} }
break; break;
case "run": case "run":
args.shift(); args.shift();
try { try {
var script = args.join(' ') var script = args.join(' ');
console.sender(sender, '§b运行脚本:§r', script) this.logger.sender(sender, '§b运行脚本:§r', script);
console.sender(sender, '§a返回结果:§r', eval(script) || '§4没有返回结果!'); this.logger.sender(sender, '§a返回结果:§r', eval(script) || '§4没有返回结果!');
} catch (ex) { } catch (ex) {
console.sender(sender, console.stack(ex)) this.logger.sender(sender, this.logger.stack(ex));
} }
break; break;
case "create": case "create":
this.logger.sender(sender, `§4当前暂不支持生成插件模板!`);
// var name = args[1]; // var name = args[1];
// if (!name) { // if (!name) {
// console.sender(sender, '§4参数错误 /mpm create <插件名称> [作者] [版本] [主命令]'); // this.logger.sender(sender, '§4参数错误 /mpm create <插件名称> [作者] [版本] [主命令]');
// return; // return;
// } // }
// var result = template.create(http.get(self.config.template)).render({ // // var result = template.create(http.get(self.config.template)).render({
// name: name, // // name: name,
// author: args[2] || 'MiaoWoo', // // author: args[2] || 'MiaoWoo',
// version: args[3] || '1.0', // // version: args[3] || '1.0',
// command: args[4] || name.toLowerCase(), // // command: args[4] || name.toLowerCase(),
// }); // // });
// fs.save(fs.file(__dirname, name + '.js'), result); // // fs.save(fs.file(__dirname, name + '.js'), result);
// console.sender(sender, '§6插件 §a' + name + ' §6已生成到插件目录...'); // this.logger.sender(sender, '§6插件 §a' + name + ' §6已生成到插件目录...');
break; break;
default: default:
console.sender(sender, help); this.logger.sender(sender, help);
break; break;
} }
} }
@ -156,7 +160,7 @@ export class MiaoScriptPackageManager {
case "update": case "update":
case "upgrade": case "upgrade":
case "reload": case "reload":
return this.pluginCache; return [...this.pluginManager.getPlugins().keys()];
} }
} }
} }

View File

@ -2,6 +2,9 @@ import { plugin as pluginApi } from '@ms/api'
import { plugin, interfaces, cmd, listener, tab } from '@ms/plugin' import { plugin, interfaces, cmd, listener, tab } from '@ms/plugin'
import { inject } from '@ms/container'; 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 }) @plugin({ name: 'Test', version: '1.0.0', author: 'MiaoWoo', source: __filename })
export class Test extends interfaces.Plugin { export class Test extends interfaces.Plugin {
@inject(pluginApi.PluginManager) @inject(pluginApi.PluginManager)
@ -51,7 +54,18 @@ export class Test extends interfaces.Plugin {
setTimeout(() => location.block.type = Java.type('org.bukkit.Material').STONE, 8); setTimeout(() => location.block.type = Java.type('org.bukkit.Material').STONE, 8);
break; break;
case "add": 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; break;
default: default:
this.logger.log(sender, command, args); this.logger.log(sender, command, args);

View File

@ -1,6 +1,8 @@
/// <reference types="@ms/types/dist/typings/bukkit" /> /// <reference types="@ms/types/dist/typings/bukkit" />
/// <reference types="@ms/types/dist/typings/sponge" /> /// <reference types="@ms/types/dist/typings/sponge" />
import { plugin as pluginApi, server } from '@ms/api' /// <reference types="@ms/types/dist/typings/bungee" />
import { plugin as pluginApi, server, task } from '@ms/api'
import { plugin, interfaces, cmd } from '@ms/plugin' import { plugin, interfaces, cmd } from '@ms/plugin'
import { DefaultContainer as container, inject, postConstruct } from '@ms/container' import { DefaultContainer as container, inject, postConstruct } from '@ms/container'
import * as reflect from '@ms/common/dist/reflect' import * as reflect from '@ms/common/dist/reflect'
@ -8,25 +10,31 @@ import * as reflect from '@ms/common/dist/reflect'
let clients: any[] = [] let clients: any[] = []
let SPLIT_LINE = '\\M\\W\\S|T|S|S/L/T/' let SPLIT_LINE = '\\M\\W\\S|T|S|S/L/T/'
const refList: Array<{ server: string, future: string }> = [ const refList: Array<{ server: string, future: string }> = [
{ server: 'an', future: 'g' }, { server: 'an', future: 'g' },//spigot 1.12.2
{ server: 'getServerConnection', future: 'f' }, { server: 'getServerConnection', future: 'f' },//spigot 1.14.4
{ server: 'func_147137_ag', future: 'field_151274_e' } { server: 'func_147137_ag', future: 'field_151274_e' }//catserver 1.12.2
] ]
const Callable = Java.type('java.util.concurrent.Callable') 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 }) @plugin({ name: 'MiaoConsole', version: '1.0.0', author: 'MiaoWoo', source: __filename })
export class WebSocket extends interfaces.Plugin { export class MiaoConsole extends interfaces.Plugin {
@inject(pluginApi.PluginManager) @inject(pluginApi.PluginManager)
private PluginManager: pluginApi.PluginManager private PluginManager: pluginApi.PluginManager
@inject(server.ServerType) @inject(server.ServerType)
private ServerType: string private ServerType: string
@inject(server.Server)
private Server: server.Server
@inject(task.TaskManager)
private Task: task.TaskManager
@inject(pluginApi.PluginInstance) @inject(pluginApi.PluginInstance)
private pluginInstance: any private pluginInstance: any
private pipeline: any private pipeline: any
@cmd() @cmd()
ws(sender: any, command: string, args: string[]) { mconsole(sender: any, command: string, args: string[]) {
switch (args[0]) { switch (args[0]) {
case "reload": case "reload":
this.PluginManager.reload(this) this.PluginManager.reload(this)
@ -37,7 +45,9 @@ export class WebSocket extends interfaces.Plugin {
disable() { disable() {
if (this.pipeline) { if (this.pipeline) {
if (this.pipeline.names().contains('miao_detect')) {
this.pipeline.remove('miao_detect') this.pipeline.remove('miao_detect')
}
clients.forEach(c => c.close()) clients.forEach(c => c.close())
container.unbind('onmessage') container.unbind('onmessage')
} }
@ -46,13 +56,28 @@ export class WebSocket extends interfaces.Plugin {
bukkitenable() { bukkitenable() {
let Bukkit = Java.type('org.bukkit.Bukkit') let Bukkit = Java.type('org.bukkit.Bukkit')
let consoleServer = reflect.on(Bukkit.getServer()).get('console').get() let consoleServer = reflect.on(Bukkit.getServer()).get('console').get()
this.injectMiaoDetect(this.reflectPromise(consoleServer)) this.reflectChannel(this.reflectPromise(consoleServer))
this.injectMiaoDetect()
} }
spongeenable() { spongeenable() {
let Sponge = Java.type('org.spongepowered.api.Sponge') let Sponge = Java.type('org.spongepowered.api.Sponge')
let consoleServer = reflect.on(Sponge.getServer()).get() 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) { 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 !`) } if (!promise) { throw Error(`Can't found ServerConnection or ChannelFuture !`) }
this.pipeline = reflect.on(promise).get('channel').get().pipeline() this.pipeline = reflect.on(promise).get('channel').get().pipeline()
}
injectMiaoDetect() {
this.pipeline.addFirst('miao_detect', new MiaoDetectHandler()) this.pipeline.addFirst('miao_detect', new MiaoDetectHandler())
container.bind('onmessage').toFunction(this.onmessage.bind(this)) container.bind('onmessage').toFunction(this.onmessage.bind(this))
this.logger.info('Netty Channel Pipeline Inject MiaoDetectHandler Successful!')
} }
onmessage(ctx: any, msg: any) { onmessage(ctx: any, msg: any) {
let text: string = msg.text() 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 { try {
var result = this[type](ctx, content) var result = this[type](ctx, content)
} catch (ex) { } catch (ex) {
@ -80,13 +109,7 @@ export class WebSocket extends interfaces.Plugin {
} }
execCommand(ctx: any, cmd: string) { execCommand(ctx: any, cmd: string) {
switch (this.ServerType) { setTimeout(() => this.Server.dispatchConsoleCommand(cmd), 0)
case "bukkit":
org.bukkit.Bukkit.dispatchCommand(org.bukkit.Bukkit.getConsoleSender(), cmd)
break
case "sponge":
break
}
return `§6命令: §b${cmd} §a执行成功!` return `§6命令: §b${cmd} §a执行成功!`
} }
@ -95,16 +118,17 @@ export class WebSocket extends interfaces.Plugin {
case "bukkit": case "bukkit":
return org.bukkit.Bukkit.getScheduler().callSyncMethod(this.pluginInstance, new Callable({ call: () => eval(code) })).get() || '无返回结果' return org.bukkit.Bukkit.getScheduler().callSyncMethod(this.pluginInstance, new Callable({ call: () => eval(code) })).get() || '无返回结果'
case "sponge": 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) { execDetect(ctx: any, cmd: string) {
switch (cmd) { switch (cmd) {
case "type": case "type":
let version = this.ServerType == 'bukkit' ? org.bukkit.Bukkit.getServer().getVersion() : org.spongepowered.api.Sponge.getPlatform().getMinecraftVersion()
this.sendResult(ctx, "type", this.ServerType) 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 channel = ctx.channel()
let pipeline = channel.pipeline() let pipeline = channel.pipeline()
if (message.indexOf('HTTP/1.1') > 0) { if (message.indexOf('HTTP/1.1') > 0) {
channel.pipeline().names().forEach(f => { pipeline.names().forEach(f => {
if (f == 'miaowebsocket' || f.indexOf('DefaultChannelPipeline') > -1) { return } if (f == 'miaowebsocket' || f.indexOf('DefaultChannelPipeline') > -1) { return }
pipeline.remove(f) pipeline.remove(f)
}) })