diff --git a/packages/nukkit/package.json b/packages/nukkit/package.json new file mode 100644 index 00000000..2ba23151 --- /dev/null +++ b/packages/nukkit/package.json @@ -0,0 +1,35 @@ +{ + "name": "@ms/nukkit", + "version": "0.2.0", + "description": "MiaoScript nukkit 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": "tsc --watch", + "build": "yarn clean && tsc", + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "devDependencies": { + "reflect-metadata": "^0.1.13", + "rimraf": "^3.0.2", + "typescript": "^3.7.5" + }, + "dependencies": { + "@ms/api": "^0.2.0", + "@ms/common": "^0.2.0", + "@ms/container": "^0.2.0", + "@ms/types": "^0.2.0" + } +} diff --git a/packages/nukkit/src/command.ts b/packages/nukkit/src/command.ts new file mode 100644 index 00000000..2d3b4372 --- /dev/null +++ b/packages/nukkit/src/command.ts @@ -0,0 +1,41 @@ +import '@ms/nashorn' + +import { command, plugin } from '@ms/api' +import { injectable, postConstruct, inject } from '@ms/container' + +let PluginCommand = Java.type('cn.nukkit.command.PluginCommand'); +let CommandExecutor = Java.type('cn.nukkit.command.CommandExecutor'); + +@injectable() +export class NukkitCommand extends command.Command { + @inject(plugin.PluginInstance) + private pluginInstance: any + private commandMap: any; + + @postConstruct() + init() { + this.commandMap = base.getInstance().getServer().getCommandMap(); + } + create(plugin: any, command: string) { + var cmd = this.commandMap.getCommand(command) + if (cmd && cmd instanceof PluginCommand) { return cmd }; + cmd = new PluginCommand(command, this.pluginInstance) + this.commandMap.register(plugin.description.name, cmd); + return cmd; + } + remove(plugin: any, command: string) { + var cmd = this.commandMap.getCommand(command) + if (cmd && cmd instanceof PluginCommand) { + cmd.unregister(this.commandMap); + } + } + onCommand(plugin: any, command: any, executor: Function) { + // 必须指定需要实现的接口类型 否则MOD服会报错 + command.setExecutor(new CommandExecutor({ + onCommand: super.setExecutor(plugin, command, executor) + })); + } + onTabComplete(plugin: any, command: any, tabCompleter: Function) { + // Not Support + } +} diff --git a/packages/nukkit/src/console.ts b/packages/nukkit/src/console.ts new file mode 100644 index 00000000..7c229b49 --- /dev/null +++ b/packages/nukkit/src/console.ts @@ -0,0 +1,21 @@ +import { MiaoScriptConsole } from '@ms/api' + +let Nukkit = base.getInstance().getServer(); +let CommandSender = Java.type('cn.nukkit.command.CommandSender') + +export class NukkitConsole extends MiaoScriptConsole { + sender(sender, ...args) { + if (!(sender instanceof CommandSender)) { + this.error(`First parameter ${sender} not instanceof cn.nukkit.command.CommandSender can't send message!`) + 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: string[]): void { + this.sender(Nukkit.getConsoleSender(), args.join(' ')); + } +} diff --git a/packages/nukkit/src/event.ts b/packages/nukkit/src/event.ts new file mode 100644 index 00000000..ebb54ae0 --- /dev/null +++ b/packages/nukkit/src/event.ts @@ -0,0 +1,47 @@ +import { event, server, plugin } from '@ms/api' +import { injectable, inject } from '@ms/container' + +const Nukkit: cn.nukkit.Server = base.getInstance().getServer(); +const Event = Java.type("cn.nukkit.event.Event"); +const Modifier = Java.type("java.lang.reflect.Modifier"); +const Listener = Java.type("cn.nukkit.event.Listener"); +const EventPriority = Java.type("cn.nukkit.event.EventPriority"); +const EventExecutor = Java.type("cn.nukkit.plugin.EventExecutor"); + +@injectable() +export class NukkitEvent extends event.Event { + @inject(plugin.PluginInstance) + private pluginInstance: any + + constructor() { + super('cn/nukkit/event'); + } + + getJarFile(resource: string) { + return super.getJarFile('cn/nukkit/Nukkit.class') + } + isValidEvent(clazz: any): boolean { + // 继承于 org.bukkit.event.Event + return Event.class.isAssignableFrom(clazz) && + // 访问符为Public + Modifier.isPublic(clazz.getModifiers()) && + // 不是抽象类 + !Modifier.isAbstract(clazz.getModifiers()); + } + register(eventCls: any, exec: Function, priority: event.EventPriority, ignoreCancel: boolean) { + let listener = new Listener({}); + Nukkit.getPluginManager().registerEvent( + eventCls, + listener, + EventPriority[priority], + new EventExecutor({ + execute: exec + }), + this.pluginInstance, + ignoreCancel); + return listener; + } + unregister(event: any, listener: any): void { + event.getHandlers().unregister(listener); + } +} diff --git a/packages/nukkit/src/index.ts b/packages/nukkit/src/index.ts new file mode 100644 index 00000000..6f855aa3 --- /dev/null +++ b/packages/nukkit/src/index.ts @@ -0,0 +1,18 @@ +/// + +import { server, command, event, task } from '@ms/api' +import { Container } from '@ms/container' + +import { NukkitConsole } from './console'; +import { NukkitEvent } from './event'; +import { NukkitServer } from './server'; +import { NukkitCommand } from './command'; +import { NukkitTaskManager } from './task'; + +export default function NukkitImpl(container: Container) { + container.bind(server.Console).toConstantValue(NukkitConsole); + container.bind(event.Event).to(NukkitEvent).inSingletonScope(); + container.bind(server.Server).to(NukkitServer).inSingletonScope(); + container.bind(command.Command).to(NukkitCommand).inSingletonScope(); + container.bind(task.TaskManager).to(NukkitTaskManager).inSingletonScope(); +} diff --git a/packages/nukkit/src/server.ts b/packages/nukkit/src/server.ts new file mode 100644 index 00000000..09759c2b --- /dev/null +++ b/packages/nukkit/src/server.ts @@ -0,0 +1,35 @@ +import { server } from '@ms/api' +import { injectable } from '@ms/container'; + +let Nukkit: cn.nukkit.Server = base.getInstance().getServer(); + +@injectable() +export class NukkitServer implements server.Server { + getPlayer(name: string) { + return Nukkit.getPlayer(name) + } + getVersion(): string { + return Nukkit.getVersion() + } + getOnlinePlayers() { + return Nukkit.getOnlinePlayers() as unknown as any[] + } + getConsoleSender() { + return Nukkit.getConsoleSender() + } + getService(service: string) { + return Nukkit.getServiceManager().getProvider(base.getClass(service)) + } + dispatchCommand(sender: string | any, command: string): boolean { + if (typeof sender === 'string') { + sender = this.getPlayer(sender) + } + return Nukkit.dispatchCommand(sender, command) + } + dispatchConsoleCommand(command: string): boolean { + return Nukkit.dispatchCommand(Nukkit.getConsoleSender(), command) + } + sendJson(sender: string | any, json: object | string): void { + throw new Error("Method not implemented."); + } +} diff --git a/packages/nukkit/src/task.ts b/packages/nukkit/src/task.ts new file mode 100644 index 00000000..26cae6af --- /dev/null +++ b/packages/nukkit/src/task.ts @@ -0,0 +1,35 @@ +import { task, plugin } from '@ms/api' +import { injectable, inject } from '@ms/container'; + +const Nukkit: cn.nukkit.Server = base.getInstance().getServer(); +const NukkitRunnable = Java.type('cn.nukkit.scheduler.NukkitRunnable'); +const Callable = Java.type('java.util.concurrent.Callable') + +@injectable() +export class NukkitTaskManager 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 NukkitTask(this.pluginInstance, func); + } + callSyncMethod(func: Function): any { + return func() + } +} + +export class NukkitTask extends task.Task { + submit(): task.Cancelable { + let run = new NukkitRunnable({ + run: () => this.run() + }) + let funcName = `runTask${this.interval ? 'Timer' : 'Later'}${this.isAsync ? 'Asynchronously' : ''}` + if (this.interval) { + run[funcName](this.plugin, this.laterTime, this.interval); + } else { + run[funcName](this.plugin, this.laterTime); + } + return run; + } +} diff --git a/packages/nukkit/tsconfig.json b/packages/nukkit/tsconfig.json new file mode 100644 index 00000000..7aae5d2b --- /dev/null +++ b/packages/nukkit/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": "src", + "outDir": "dist" + } +} \ No newline at end of file