diff --git a/packages/sponge/src/command.ts b/packages/sponge/src/command.ts new file mode 100644 index 00000000..9fd056e3 --- /dev/null +++ b/packages/sponge/src/command.ts @@ -0,0 +1,72 @@ +import { command, plugin } from "@ms/api"; +import { inject, injectable } from "@ms/container"; + +let Sponge = Java.type('org.spongepowered.api.Sponge'); + +var CommandCallable = Java.type('org.spongepowered.api.command.CommandCallable'); +var CommandResult = Java.type('org.spongepowered.api.command.CommandResult'); + +let Text = Java.type('org.spongepowered.api.text.Text'); + +var Optional = Java.type('java.util.Optional'); + +class SimpleCommandCallable { + public callable: any; + + private executor: Function; + private tabCompleter: Function; + + constructor(command: string, description: string = '暂无描述!') { + this.callable = new CommandCallable({ + //CommandResult process(CommandSource source, String arguments) throws CommandException; + process: (sender: any, args) => { + return this.executor(sender, command, args.length === 0 ? [] : args.split(" ").filter(e => e)) ? CommandResult.success() : CommandResult.empty(); + }, + //List getSuggestions(CommandSource source, String arguments, @Nullable Location targetPosition) throws CommandException; + getSuggestions: (sender: any, args, target) => { + return this.tabCompleter(sender, command, args.length === 0 ? [] : args.split(" ").filter(e => e)); + }, + //boolean testPermission(CommandSource source); + testPermission: () => { + return true; + }, + //Optional getShortDescription(CommandSource source); + getShortDescription: () => { + return Optional.of(Text.of(description)); + }, + //Optional getHelp(CommandSource source); + getHelp: () => { + return Optional.of(Text.of("")); + }, + //Text getUsage(CommandSource source); + getUsage: () => { + return Text.of(''); + } + }) + } + + setExecutor = (executor: Function) => this.executor = executor; + setTabCompleter = (tabCompleter: Function) => this.tabCompleter = tabCompleter; +} + +@injectable() +export class SpongeCommand extends command.Command { + @inject(plugin.PluginInstance) + private pluginInstance: any + private commandMap: any[] = []; + + create(plugin: any, command: string) { + var commandKey = plugin.description.name.toLowerCase() + ":" + command; + if (!this.commandMap[commandKey]) { + this.commandMap[commandKey] = new SimpleCommandCallable(command); + Sponge.getCommandManager().register(this.pluginInstance, this.commandMap[commandKey].callable, command, commandKey); + } + return this.commandMap[commandKey]; + } + onCommand(plugin: any, command: any, executor: Function) { + command.setExecutor(super.setExecutor(plugin, command, executor)); + } + onTabComplete(plugin: any, command: any, tabCompleter: Function) { + command.setTabCompleter(super.setTabCompleter(plugin, command, tabCompleter)); + } +} \ No newline at end of file diff --git a/packages/sponge/src/console.ts b/packages/sponge/src/console.ts index 2ce32ebb..ee0e846d 100644 --- a/packages/sponge/src/console.ts +++ b/packages/sponge/src/console.ts @@ -11,7 +11,7 @@ export class SpongeConsole extends MiaoScriptConsole { this.error('第一个参数未实现 org.spongepowered.api.command.CommandSource 无法发送消息!') return } - if (args[0].toString() === '[object Array]') { + if (Object.prototype.toString.call(args[0]) === '[object Array]') { args[0].forEach(line => sender.sendMessage(Text.of(this.prefix + line))) } else { sender.sendMessage(Text.of(this.prefix + args.join(' '))); diff --git a/packages/sponge/src/event.ts b/packages/sponge/src/event.ts new file mode 100644 index 00000000..0383290d --- /dev/null +++ b/packages/sponge/src/event.ts @@ -0,0 +1,52 @@ +import { event, plugin } from '@ms/api' +import { injectable, inject } from '@ms/container'; + +let Modifier = Java.type("java.lang.reflect.Modifier"); +let Order = Java.type("org.spongepowered.api.event.Order"); +let Event = Java.type("org.spongepowered.api.event.Event"); +let EventListener = Java.type("org.spongepowered.api.event.EventListener"); + +let Sponge = Java.type("org.spongepowered.api.Sponge"); + +let priorityMap = { + 'LOWEST': 'PRE', + 'LOW': 'FIRST', + 'NORMAL': 'DEFAULT', + 'HIGH': 'LATE', + 'HIGHEST': 'LAST', + 'MONITOR': 'POST' +}; +/** + * Sponge Event Impl + */ +@injectable() +export class SpongeEvent extends event.Event { + @inject(plugin.PluginInstance) + private pluginInstance: any; + + constructor() { + super('org/spongepowered/api/event'); + } + + isValidEvent(clazz: any): boolean { + //继承于 org.spongepowered.api.event.Event + return Event.class.isAssignableFrom(clazz) && + // 访问符为Public + Modifier.isPublic(clazz.getModifiers()) && + // Sponge的事件都是接口 + Modifier.isAbstract(clazz.getModifiers()); + } + class2Name(clazz: any) { + return clazz.canonicalName.substring(clazz.name.lastIndexOf(".") + 1); + } + register(eventCls: any, exec: Function, priority: any = 'NORMAL', ignoreCancel: boolean = true) { + var listener = new EventListener({ + handle: exec + }); + Sponge.getEventManager().registerListener(this.pluginInstance, eventCls, Order[priorityMap[priority]], listener); + return listener; + } + unregister(event: any, listener: any): void { + Sponge.getEventManager().unregisterListeners(listener); + } +} diff --git a/packages/sponge/src/index.ts b/packages/sponge/src/index.ts index c9bd8533..1cfce3e0 100644 --- a/packages/sponge/src/index.ts +++ b/packages/sponge/src/index.ts @@ -1,13 +1,22 @@ -import { server, plugin } from '@ms/api' +import './typings' + +import { server, plugin, command, event, task } from '@ms/api' import { DefaultContainer as container } from '@ms/container' -import { SpongeConsole } from './console' +import { SpongeConsole } from './console'; +import { SpongeEvent } from './event'; +import { SpongeCommand } from './command'; +import { SpongeTaskManager } from './task'; let SpongeServerType = 'sponge'; let Sponge = Java.type("org.spongepowered.api.Sponge"); -console.debug(`Detect Sponge Compatible set ServerType to ${SpongeServerType} ...`) - container.bind(server.Console).toConstantValue(SpongeConsole); container.bind(server.ServerType).toConstantValue(SpongeServerType); container.bind(plugin.PluginInstance).toConstantValue(Sponge.pluginManager.getPlugin('MiaoScript').orElse(null)); + +container.bind(event.Event).to(SpongeEvent).inSingletonScope(); +container.bind(command.Command).to(SpongeCommand).inSingletonScope(); +container.bind(task.TaskManager).to(SpongeTaskManager).inSingletonScope(); + +console.debug(`Detect Sponge Compatible set ServerType to ${SpongeServerType} ...`) diff --git a/packages/sponge/src/task.ts b/packages/sponge/src/task.ts new file mode 100644 index 00000000..421d96a1 --- /dev/null +++ b/packages/sponge/src/task.ts @@ -0,0 +1,28 @@ +import { task, plugin } from '@ms/api' +import { injectable, inject } from '@ms/container'; + +var Consumer = Java.type('java.util.function.Consumer'); +var Task = Java.type("org.spongepowered.api.scheduler.Task"); + +@injectable() +export class SpongeTaskManager 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 SpongeTask(this.pluginInstance, func); + } +} + +export class SpongeTask extends task.Task { + submit(): task.Cancelable { + let run = Task.builder().execute(new Consumer({ + accept: () => this.run() + })); + if (this.isAsync) { run.async() } + if (this.laterTime) { run.delayTicks(this.laterTime) } + if (this.interval) { run.intervalTicks(this.interval) } + return run.submit(this.plugin) + } +} diff --git a/packages/sponge/src/typings/index.ts b/packages/sponge/src/typings/index.ts new file mode 100644 index 00000000..e69de29b