From f6526e79fc1ae2a20acf0015505d0930241e6710 Mon Sep 17 00:00:00 2001 From: MiaoWoo Date: Mon, 24 Feb 2020 18:36:08 +0800 Subject: [PATCH] feat: add channel support for bungee bukkit sponge Signed-off-by: MiaoWoo --- packages/api/src/channel.ts | 58 ++++++++++++++++++++++++++++++++++ packages/api/src/event.ts | 2 +- packages/api/src/index.ts | 1 + packages/bukkit/src/channel.ts | 28 ++++++++++++++++ packages/bukkit/src/index.ts | 4 ++- packages/bungee/src/channel.ts | 18 +++++++++++ packages/bungee/src/index.ts | 4 ++- packages/sponge/src/channel.ts | 38 ++++++++++++++++++++++ packages/sponge/src/index.ts | 4 ++- 9 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 packages/api/src/channel.ts create mode 100644 packages/bukkit/src/channel.ts create mode 100644 packages/bungee/src/channel.ts create mode 100644 packages/sponge/src/channel.ts diff --git a/packages/api/src/channel.ts b/packages/api/src/channel.ts new file mode 100644 index 00000000..87100a9d --- /dev/null +++ b/packages/api/src/channel.ts @@ -0,0 +1,58 @@ +import { injectable } from "@ms/container"; + +export namespace channel { + /** + * handle plugin message + * @param data byte[] + */ + export type ChannelListener = (data: any) => void + + @injectable() + export abstract class Channel { + private listenerMap = []; + + listen(plugin: any, channel: string, exec: ChannelListener) { + if (!plugin || !plugin.description || !plugin.description.name) throw new TypeError('Plugin can\'t be undefiend!'); + let name = plugin.description.name; + let listener = this.register(channel, exec) + if (!this.listenerMap[name]) this.listenerMap[name] = []; + let offExec = () => { + this.unregister(channel, listener); + console.debug(`[${name}] unregister channel ${channel}`); + }; + var off = { + channel, + listener, + off: offExec + }; + this.listenerMap[name].push(off); + console.debug(`[${name}] register channel ${channel} => ${exec.name || '[anonymous]'}`); + return off; + } + disable(plugin: any) { + var channelCache = this.listenerMap[plugin.description.name]; + if (channelCache) { + channelCache.forEach(t => t.off()); + delete this.listenerMap[plugin.description.name]; + } + } + + /** + * Send Channel Message + * @param player recover target + * @param channel ChannelName + * @param data byte[] + */ + abstract send(player: any, channel: string, data: any) + /** + * register channel + * @param channel ChannelName + */ + abstract register(channel: string, listener: ChannelListener): any + /** + * unregister channel + * @param channel ChannelName + */ + abstract unregister(channel: string, listener?: any): void + } +} diff --git a/packages/api/src/event.ts b/packages/api/src/event.ts index f0e744c1..567c7e47 100644 --- a/packages/api/src/event.ts +++ b/packages/api/src/event.ts @@ -115,7 +115,7 @@ export namespace event { * @param priority {string} [LOWEST,LOW,NORMAL,HIGH,HIGHEST,MONITOR] * @param ignoreCancel */ - listen(plugin: any, event: string, exec: () => void, priority: EventPriority = EventPriority.NORMAL, ignoreCancel = false) { + listen(plugin: any, event: string, exec: (event: any) => void, priority: EventPriority = EventPriority.NORMAL, ignoreCancel = false) { if (!plugin || !plugin.description || !plugin.description.name) throw new TypeError('插件名称为空 请检查传入参数!'); var name = plugin.description.name; var eventCls = this.name2Class(name, event); diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index e7ede333..d3826377 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -2,5 +2,6 @@ export * from './task' export * from './event' export * from './console' +export * from './channel' export * from './command' export * from './interfaces' diff --git a/packages/bukkit/src/channel.ts b/packages/bukkit/src/channel.ts new file mode 100644 index 00000000..58c516a0 --- /dev/null +++ b/packages/bukkit/src/channel.ts @@ -0,0 +1,28 @@ +import { channel, plugin } from '@ms/api' +import { inject, injectable } from '@ms/container' + +const Bukkit = org.bukkit.Bukkit +const PluginMessageListener = Java.type("org.bukkit.plugin.messaging.PluginMessageListener") +const Messenger = Bukkit.getMessenger() + +@injectable() +export class BukkitChannel extends channel.Channel { + @inject(plugin.PluginInstance) + private pluginInstance: any; + + send(player: any, channel: string, data: any) { + player.sendPluginMessage(this.pluginInstance, channel, data); + } + register(channel: string, listener: channel.ChannelListener) { + Messenger.registerIncomingPluginChannel(this.pluginInstance, channel, new PluginMessageListener({ + onPluginMessageReceived: (/**String */ var1, /**Player */ var2, /**byte[] */var3) => { + listener(var3) + } + })); + Messenger.registerOutgoingPluginChannel(this.pluginInstance, channel); + } + unregister(channel: string, listener: any) { + Messenger.unregisterIncomingPluginChannel(this.pluginInstance, channel) + Messenger.unregisterOutgoingPluginChannel(this.pluginInstance, channel) + } +} diff --git a/packages/bukkit/src/index.ts b/packages/bukkit/src/index.ts index a49a76c9..b7d99770 100644 --- a/packages/bukkit/src/index.ts +++ b/packages/bukkit/src/index.ts @@ -1,12 +1,13 @@ /// -import { server, command, event, task } from '@ms/api' +import { server, command, event, channel, task } from '@ms/api' import { Container } from '@ms/container' import { BukkitConsole } from './console'; import { BukkitEvent } from './event'; import { BukkitServer } from './server'; import { BukkitCommand } from './command'; +import { BukkitChannel } from './channel'; import { BukkitTaskManager } from './task'; export default function BukkitImpl(container: Container) { @@ -14,5 +15,6 @@ export default function BukkitImpl(container: Container) { container.bind(event.Event).to(BukkitEvent).inSingletonScope(); container.bind(server.Server).to(BukkitServer).inSingletonScope(); container.bind(command.Command).to(BukkitCommand).inSingletonScope(); + container.bind(channel.Channel).to(BukkitChannel).inSingletonScope(); container.bind(task.TaskManager).to(BukkitTaskManager).inSingletonScope(); } diff --git a/packages/bungee/src/channel.ts b/packages/bungee/src/channel.ts new file mode 100644 index 00000000..3038e1d1 --- /dev/null +++ b/packages/bungee/src/channel.ts @@ -0,0 +1,18 @@ +import { channel, plugin, event } from '@ms/api' +import { inject, injectable } from '@ms/container' + +const Bungee: net.md_5.bungee.api.ProxyServer = base.getInstance().getProxy() + +@injectable() +export class BungeeChannel extends channel.Channel { + send(player: any, channel: string, data: any) { + throw new Error("Method not implemented."); + } + register(channel: string, listener: channel.ChannelListener) { + Bungee.registerChannel(channel); + console.console('§6[§eWARN§6] §eBungeeCord Channel only registerChannel you need self hanler PluginMessageEvent!') + } + unregister(channel: string, listener: any) { + Bungee.unregisterChannel(channel); + } +} diff --git a/packages/bungee/src/index.ts b/packages/bungee/src/index.ts index 79123d5a..a3a59a16 100644 --- a/packages/bungee/src/index.ts +++ b/packages/bungee/src/index.ts @@ -1,12 +1,13 @@ /// -import { server, command, event, task } from '@ms/api' +import { server, command, event, channel, task } from '@ms/api' import { Container } from '@ms/container' import { BungeeConsole } from './console'; import { BungeeEvent } from './event'; import { BungeeServer } from './server'; import { BungeeCommand } from './command'; +import { BungeeChannel } from './channel'; import { BungeeTaskManager } from './task'; export default function BungeeImpl(container: Container) { @@ -14,5 +15,6 @@ export default function BungeeImpl(container: Container) { container.bind(event.Event).to(BungeeEvent).inSingletonScope(); container.bind(server.Server).to(BungeeServer).inSingletonScope(); container.bind(command.Command).to(BungeeCommand).inSingletonScope(); + container.bind(channel.Channel).to(BungeeChannel).inSingletonScope(); container.bind(task.TaskManager).to(BungeeTaskManager).inSingletonScope(); } diff --git a/packages/sponge/src/channel.ts b/packages/sponge/src/channel.ts new file mode 100644 index 00000000..33688079 --- /dev/null +++ b/packages/sponge/src/channel.ts @@ -0,0 +1,38 @@ +import { channel, plugin } from '@ms/api' +import { inject, injectable } from '@ms/container' + +const Sponge = org.spongepowered.api.Sponge +const RawDataListener = Java.type("org.spongepowered.api.network.RawDataListener") +const ChannelRegistrar = Sponge.getChannelRegistrar() +const Consumer = Java.type("java.util.function.Consumer"); + +@injectable() +export class SpongeChannel extends channel.Channel { + @inject(plugin.PluginInstance) + private pluginInstance: any; + + private channelMap = new Map(); + + send(player: any, channel: string, data: any) { + if (!this.channelMap.has(channel)) { return } + this.channelMap.get(channel).sendTo(player, new Consumer({ + accept: (channelBuf: any) => channelBuf.writeBytes(data) + })) + } + register(channel: string, listener: channel.ChannelListener) { + if (!this.channelMap.has(channel)) { + this.channelMap.set(channel, ChannelRegistrar.getOrCreateRaw(this.pluginInstance, channel)) + } + let innerListener = new RawDataListener({ + handlePayload: (/* ChannelBuf */ data: any, /**RemoteConnection */ connection: any, /**Platform.Type */ side: any) => { + listener(data.readBytes(data.available())) + } + }) + this.channelMap.get(channel).addListener(innerListener); + return innerListener; + } + unregister(channel: string, listener: any) { + if (!this.channelMap.has(channel)) { return } + this.channelMap.get(channel).removeListener(listener); + } +} diff --git a/packages/sponge/src/index.ts b/packages/sponge/src/index.ts index 62ecc7a8..bd26aa0b 100644 --- a/packages/sponge/src/index.ts +++ b/packages/sponge/src/index.ts @@ -1,12 +1,13 @@ /// -import { server, command, event, task } from '@ms/api' +import { server, command, event, channel, task } from '@ms/api' import { Container } from '@ms/container' import { SpongeConsole } from './console'; import { SpongeEvent } from './event'; import { SpongeServer } from './server'; import { SpongeCommand } from './command'; +import { SpongeChannel } from './channel'; import { SpongeTaskManager } from './task'; export default function SpongeImpl(container: Container) { @@ -14,5 +15,6 @@ export default function SpongeImpl(container: Container) { container.bind(event.Event).to(SpongeEvent).inSingletonScope(); container.bind(server.Server).to(SpongeServer).inSingletonScope(); container.bind(command.Command).to(SpongeCommand).inSingletonScope(); + container.bind(channel.Channel).to(SpongeChannel).inSingletonScope(); container.bind(task.TaskManager).to(SpongeTaskManager).inSingletonScope(); }