ms/packages/api/src/channel.ts

219 lines
8.8 KiB
TypeScript
Raw Normal View History

import { injectable, inject, provideSingleton } from "@ccms/container"
export namespace channel {
/**
* handle plugin message
* @param data byte[]
*/
export type ChannelListener = (data: any, exts?: any) => void
@injectable()
export abstract class Channel {
private listenerMap = [];
/**
*
* @param plugin
* @param channel
* @param exec
*/
listen(plugin: any, channel: string, exec: ChannelListener) {
2020-09-17 09:44:48 +00:00
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)
2020-09-17 09:44:48 +00:00
if (!this.listenerMap[name]) this.listenerMap[name] = []
let offExec = () => {
2020-09-17 09:44:48 +00:00
this.unregister(channel, listener)
console.debug(`[${name}] unregister channel ${channel}`)
}
var off = {
channel,
listener,
off: offExec
2020-09-17 09:44:48 +00:00
}
this.listenerMap[name].push(off)
console.debug(`[${name}] register channel ${channel} => ${exec.name || '[anonymous]'}`)
return off
}
/**
*
* @param plugin
*/
disable(plugin: any) {
2020-09-17 09:44:48 +00:00
var channelCache = this.listenerMap[plugin.description.name]
if (channelCache) {
2020-09-17 09:44:48 +00:00
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
}
export namespace proxy {
const CHANNEL_NAME = "BungeeCord"
const ByteArrayOutputStream = Java.type('java.io.ByteArrayOutputStream')
const DataOutputStream = Java.type('java.io.DataOutputStream')
const ByteStreams = Java.type('com.google.common.io.ByteStreams')
namespace bungeecord {
export class SubChannelBuilder {
private channel: Channel
private player: any
private params: string[]
constructor(channel: Channel, player: any) {
this.channel = channel
this.player = player
this.params = []
}
connect(server: string) {
this.params.push("Connect")
this.params.push(server)
}
connectOther(player: string, server: string) {
this.params.push("ConnectOther")
this.params.push(player)
this.params.push(server)
}
ip() {
this.params.push("IP")
}
ipOther(player: string) {
this.params.push("IPOther")
this.params.push(player)
}
playerCount(server: string | "ALL") {
this.params.push("PlayerCount")
this.params.push(server)
}
/**
* Get a list of players connected on a certain server, or on ALL the servers.
* @param server count server
* Response:
* String server = in.readUTF(); // The name of the server you got the player list of, as given in args.
* String[] playerList = in.readUTF().split(", ");
*/
playerList(server: string | "ALL") {
this.params.push("PlayerList")
this.params.push(server)
}
/**
* Get a list of server name strings, as defined in BungeeCord's config.yml
* Response:
* String[] serverList = in.readUTF().split(", ");
*/
getServers() {
this.params.push("GetServers")
return this.finalSend()
}
/**
* Get this server's name, as defined in BungeeCord's config.yml
*/
getServer() {
this.params.push("GetServer")
return this.finalSend()
}
broadcast(message: string) {
this.message("ALL", message)
return this.finalSend()
}
/**
* Send a message (as in, a chat message) to the specified player.
* @param player who reciver message
* @param message message content
*/
message(player: string | "ALL", message: string) {
this.params.push("Message")
this.params.push(player)
this.params.push(message)
return this.finalSend()
}
/**
* Send a raw message (as in, a chat message) to the specified player. The advantage of this method over Message is that you can include click events and hover events.
* @param player who reciver message
* @param message message content
*/
messageRaw(player: string | "ALL", json: string) {
this.params.push("MessageRaw")
this.params.push(player)
this.params.push(json)
return this.finalSend()
}
forwardAll(channel: string, data: any) {
this.forward("ALL", channel, data)
}
/**
* Send a custom plugin message to said server. This is one of the most useful channels ever.
* Remember, the sending and receiving server(s) need to have a player online.
* @param server reciver
* @param channel channelName
* @param data data
*/
forward(server: string | "ALL", channel: string, data: any) {
this.params.push("Forward")
this.params.push(server)
this.params.push(channel)
this.params.push(typeof data === "string" ? data : JSON.stringify(data))
return this.finalSend()
}
/**
* Send a custom plugin message to said server. This is one of the most useful channels ever.
* Remember, the sending and receiving server(s) need to have a player online.
* @param server reciver
* @param channel channelName
* @param data data
*/
forwardToPlayer(server: string | "ALL", channel: string, data: any) {
this.params.push("Forward")
this.params.push(server)
this.params.push(channel)
this.params.push(typeof data === "string" ? data : JSON.stringify(data))
return this.finalSend()
}
generic(...args: string[]) {
args && this.params.concat(...args)
return this.finalSend()
}
private send(...middlewares: ((out: java.io.DataOutputStream) => void)[]) {
let byteArray = new ByteArrayOutputStream()
let out = new DataOutputStream(byteArray)
this.params.forEach(utf => out.writeUTF(utf))
for (let middleware of middlewares) {
middleware(out)
}
this.channel.send(this.player, CHANNEL_NAME, byteArray.toByteArray())
}
private finalSend() {
return {
send: this.send.bind(this)
}
}
}
}
@provideSingleton(BungeeCord)
export class BungeeCord {
@inject(Channel)
private channel: Channel
/**
*
* @param player
*/
for(player: any): bungeecord.SubChannelBuilder {
return new bungeecord.SubChannelBuilder(this.channel, player)
}
}
}
}