diff --git a/packages/bungee/package.json b/packages/bungee/package.json new file mode 100644 index 00000000..c702a37c --- /dev/null +++ b/packages/bungee/package.json @@ -0,0 +1,35 @@ +{ + "name": "@ms/bungee", + "version": "0.1.1", + "description": "MiaoScript bungee package", + "keywords": [ + "miaoscript", + "minecraft", + "bukkit", + "sponge" + ], + "author": "MiaoWoo ", + "homepage": "https://github.com/circlecloud/ms.git", + "license": "ISC", + "main": "dist/index.js", + "publishConfig": { + "registry": "https://repo.yumc.pw/repository/npm-hosted/" + }, + "scripts": { + "clean": "rimraf dist", + "watch": "npx tsc --watch", + "build": "yarn clean && npx tsc", + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "devDependencies": { + "reflect-metadata": "^0.1.13", + "rimraf": "^3.0.0", + "typescript": "^3.7.4" + }, + "dependencies": { + "@ms/api": "^0.1.1", + "@ms/common": "^0.1.0", + "@ms/container": "^0.1.0", + "@ms/types": "^0.1.1" + } +} \ No newline at end of file diff --git a/packages/bungee/src/command.ts b/packages/bungee/src/command.ts new file mode 100644 index 00000000..63b91814 --- /dev/null +++ b/packages/bungee/src/command.ts @@ -0,0 +1,57 @@ +import { command, plugin } from "@ms/api"; +import { inject, injectable } from "@ms/container"; +import * as ref from '@ms/common/dist/reflect' + +const Command = Java.type('net.md_5.bungee.api.plugin.Command'); +const createCommand = eval(` + function(cls, name, exec){ + return new cls(name) {execute:exec} + } + `) + +class SimpleCommand { + public callable: any; + private name: string; + private executor: Function; + + constructor(command: string) { + this.name = command; + this.callable = createCommand(Command, command, (sender, args) => this.executor(sender, '', command, args)); + } + + setExecutor = (executor: Function) => this.executor = executor; + toString = () => `Bungee SimpleCommand(${this.name})` +} + +@injectable() +export class BungeeCommand extends command.Command { + @inject(plugin.PluginInstance) + private pluginInstance: any; + private pluginManager: net.md_5.bungee.api.plugin.PluginManager = base.getInstance().getProxy().getPluginManager(); + private commandMapping: any[] = []; + + create(plugin: any, command: string) { + let commandKey = this.getCommandKey(plugin, command); + let commandCallable = new SimpleCommand(command); + this.pluginManager.registerCommand(this.pluginInstance, commandCallable.callable) + this.commandMapping[commandKey] = commandCallable.callable; + return commandCallable; + } + remove(plugin: any, command: string) { + var commandKey = this.getCommandKey(plugin, command); + if (this.commandMapping[commandKey]) { + this.pluginManager.unregisterCommand(this.commandMapping[commandKey]) + delete this.commandMapping[commandKey]; + } + } + onCommand(plugin: any, command: any, executor: Function) { + command.setExecutor(super.setExecutor(plugin, command, executor)); + } + onTabComplete(plugin: any, command: any, tabCompleter: Function) { + console.warn(`[${plugin.description.name}] command ${command.name} register tab failed. BungeeCord not support !`) + } + + private getCommandKey(plugin: any, command: string) { + return plugin.description.name.toLowerCase() + ":" + command; + } +} diff --git a/packages/bungee/src/console.ts b/packages/bungee/src/console.ts new file mode 100644 index 00000000..36fd3cee --- /dev/null +++ b/packages/bungee/src/console.ts @@ -0,0 +1,27 @@ +import '@ms/nashorn' +import { plugin, MiaoScriptConsole } from '@ms/api' +import { inject, injectable } from "@ms/container"; + +let CommandSender = Java.type("net.md_5.bungee.api.CommandSender") + +@injectable() +export class BungeeConsole extends MiaoScriptConsole { + @inject(plugin.PluginInstance) + private pluginInstance: any + private proxyServer: net.md_5.bungee.api.ProxyServer = base.getInstance().getProxy(); + + sender(sender, ...args) { + if (!(sender instanceof CommandSender)) { + this.error('第一个参数未实现 net.md_5.bungee.api.CommandSender 无法发送消息!') + return + } + if (Object.prototype.toString.call(args[0]) === '[object Array]') { + args[0].forEach(line => sender.sendMessage(this.prefix + line)) + } else { + sender.sendMessage(this.prefix + args.join(' ')); + } + } + console(...args): void { + this.sender(this.proxyServer.getConsole(), args.join(' ')); + } +} diff --git a/packages/bungee/src/event.ts b/packages/bungee/src/event.ts new file mode 100644 index 00000000..886abb49 --- /dev/null +++ b/packages/bungee/src/event.ts @@ -0,0 +1,35 @@ +import { event, plugin } from '@ms/api' +import { injectable, inject } from '@ms/container'; + +const Bungee: net.md_5.bungee.api.ProxyServer = base.getInstance().getProxy(); +const Event = Java.type("net.md_5.bungee.api.plugin.Event"); +const Modifier = Java.type("java.lang.reflect.Modifier"); + +/** + * Bungee Event Impl + */ +@injectable() +export class BungeeEvent extends event.Event { + @inject(plugin.PluginInstance) + private pluginInstance: any; + private pluginManager = Bungee.getPluginManager() + + constructor() { + super('net/md_5/bungee/api/event'); + } + + isValidEvent(clazz: any): boolean { + //继承于 net.md_5.bungee.api.plugin.Event + return Event.class.isAssignableFrom(clazz) && + // 访问符为Public + Modifier.isPublic(clazz.getModifiers()) && + // 不是抽象类 + !Modifier.isAbstract(clazz.getModifiers()); + } + register(eventCls: any, exec: Function, priority: event.EventPriority = event.EventPriority.NORMAL, ignoreCancel: boolean = true) { + this.pluginManager.registerListener(this.pluginInstance, null); + } + unregister(event: any, listener: any): void { + this.pluginManager.unregisterListener(listener) + } +} diff --git a/packages/bungee/src/index.ts b/packages/bungee/src/index.ts new file mode 100644 index 00000000..c81c4ea5 --- /dev/null +++ b/packages/bungee/src/index.ts @@ -0,0 +1,20 @@ +/// + +import { server, plugin, command, event, task } from '@ms/api' +import { DefaultContainer as container } from '@ms/container' + +import { BungeeConsole } from './console'; +import { BungeeEvent } from './event'; +import { BungeeServer } from './server'; +import { BungeeCommand } from './command'; +import { BungeeTaskManager } from './task'; + +let BungeeServerType = 'bungee'; + +container.bind(server.Console).toConstantValue(BungeeConsole); +container.bind(server.ServerType).toConstantValue(BungeeServerType); + +container.bind(event.Event).to(BungeeEvent).inSingletonScope(); +container.bind(server.Server).to(BungeeServer).inSingletonScope(); +container.bind(command.Command).to(BungeeCommand).inSingletonScope(); +container.bind(task.TaskManager).to(BungeeTaskManager).inSingletonScope(); diff --git a/packages/bungee/src/server.ts b/packages/bungee/src/server.ts new file mode 100644 index 00000000..8b77703d --- /dev/null +++ b/packages/bungee/src/server.ts @@ -0,0 +1,32 @@ +import { server } from '@ms/api' +import { injectable } from '@ms/container'; + +let Bungee: net.md_5.bungee.api.ProxyServer = base.getInstance().getProxy(); + +@injectable() +export class BungeeServer implements server.Server { + getPlayer(name: string) { + return Bungee.getPlayer(name); + } + getVersion(): string { + return Bungee.getVersion() + } + getOnlinePlayers() { + return Bungee.getPlayers() + } + getConsoleSender() { + return Bungee.getConsole() + } + getService(service: string) { + throw new Error("Method not implemented."); + } + dispatchCommand(sender: string | any, command: string): boolean { + return false + } + dispatchConsoleCommand(command: string): boolean { + return false + } + sendJson(sender: string | any, json: string): void { + throw new Error("Method not implemented."); + } +} diff --git a/packages/bungee/src/task.ts b/packages/bungee/src/task.ts new file mode 100644 index 00000000..b65a3828 --- /dev/null +++ b/packages/bungee/src/task.ts @@ -0,0 +1,30 @@ +import { task, plugin } from '@ms/api' +import { injectable, inject } from '@ms/container'; + +var Runnable = Java.type('java.lang.Runnable') +let TimeUnit = Java.type('java.util.concurrent.TimeUnit') + +@injectable() +export class BungeeTaskManager implements task.TaskManager { + @inject(plugin.PluginInstance) + private pluginInstance: any; + + create(func: Function): task.Task { + if (Object.prototype.toString.call(func) !== "[object Function]") { throw TypeError('第一个参数 Task 必须为 function !'); }; + return new BungeeTask(this.pluginInstance, func); + } +} + +export class BungeeTask extends task.Task { + submit(): task.Cancelable { + let run = new Runnable({ run: () => this.run() }) + if (this.isAsync) { + return this.plugin.getProxy().getScheduler().runAsync(this.plugin, run) + } + if (this.interval) { + return this.plugin.getProxy().getScheduler().schedule(this.plugin, run, this.laterTime, this.interval, TimeUnit.MILLISECONDS) + } else { + return this.plugin.getProxy().getScheduler().schedule(this.plugin, run, this.laterTime, TimeUnit.MILLISECONDS) + } + } +} diff --git a/packages/bungee/tsconfig.json b/packages/bungee/tsconfig.json new file mode 100644 index 00000000..a4a9b30b --- /dev/null +++ b/packages/bungee/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": "src", + "outDir": "dist", + "allowJs": true + } +} \ No newline at end of file