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) })