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