Skip to content

Instantly share code, notes, and snippets.

@justisr
Last active April 14, 2021 20:37
Show Gist options
  • Save justisr/e9034b7952e0801e687e to your computer and use it in GitHub Desktop.
Save justisr/e9034b7952e0801e687e to your computer and use it in GitHub Desktop.
Bungee communications wrapper util
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.messaging.PluginMessageListener;
import com.google.common.collect.Sets;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
/**
*
* @author Justis
* Bungee wrapper for handling incoming and outgoing bungee messages, because plugin messages are a pain in the arse I refuse to work with them without a wrapper thank you. xD
*
*/
public class BungeeCom implements PluginMessageListener {
// The instance for this class, because there should only ever be one.
private static BungeeCom com;
private Plugin plugin;
/**
* All of the below maps, sets, and strings will remain without data until you send a plugin message to update them.
* This is to reduce overhead, and running plugin messages that don't need to be run.
*/
// This server's server name as defined in the bungee config.
private String serverName;
// Set of servers.
private Set<String> servers = new HashSet<>();
// Map of player uuid's for the Key, and their IP for the value.
private Map<UUID, String> playerIps = new HashMap<>();
// Map of server names for the Key, and player count for the value.
private Map<String, Integer> playerCount = new HashMap<>();
// Map of server names for the Key, and player names for the value.
private Map<String, String[]> playerList = new HashMap<>();
// Map of server names for the Key, and the server IP for the value.
private Map<String, String> serverIp = new HashMap<>();
// Map of player names for the Key, and player UUIDs for the value.
private Map<String, UUID> playerIds = new HashMap<>();
/**
* Initiate the bungee com, and register channels.
*/
public BungeeCom(Plugin plugin) {
com = this;
this.plugin = plugin;
plugin.getServer().getMessenger().registerIncomingPluginChannel(plugin, "BungeeCord", this);
plugin.getServer().getMessenger().registerOutgoingPluginChannel(plugin, "BungeeCord");
}
/**
* Receive method, determines the incoming message and runs the appropriate updating method as a result.
*/
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
if (!channel.equals("BungeeCord")) return;
ByteArrayDataInput in = ByteStreams.newDataInput(message);
String subchannel = in.readUTF();
switch (Channel.fromString(subchannel)) {
case GET_SERVER:
receiveServerName(in.readUTF());
break;
case GET_SERVERS:
receiveServers(in.readUTF().split(", "));
break;
case IP:
receiveIP(player, in.readUTF(), in.readInt());
break;
case PLAYER_COUNT:
receivePlayerCount(in.readUTF(), in.readInt());
break;
case PLAYER_LIST:
receivePlayerList(in.readUTF(), in.readUTF().split(", "));
break;
case SERVER_IP:
receiveServerIP(in.readUTF(), in.readUTF(), in.readShort());
break;
case UUID:
receivePlayerUUID(player.getName(), in.readUTF());
break;
case UUID_OTHER:
receivePlayerUUID(in.readUTF(), in.readUTF());
break;
default:
byte[] data = new byte[in.readShort()];
in.readFully(data);
receiveForward(player, subchannel, new String(data).substring(2));
}
}
/**
* Update server name
* @param name to update it to.
*/
private void receiveServerName(String name) {
com.serverName = name;
}
/**
* @return server name
*/
public static String getServerName() {
return com.serverName;
}
/**
* Update server set
* @param servers to update it to.
*/
private void receiveServers(String[] servers) {
com.servers = Sets.newHashSet(servers);
}
/**
* @return the server set.
*/
public static Set<String> getServers() {
return Collections.unmodifiableSet(com.servers);
}
/**
* Add/update a player to the ip list.
* @param player
* @param ip
* @param port
*/
private void receiveIP(Player player, String ip, int port) {
com.playerIps.put(player.getUniqueId(), ip + ":" + port);
}
/**
* Get the ip of a player
* @param name of the player
* @return player's ip.
* Null if player's ip has not been gathered.
*/
public static String getPlayerIp(String name) {
return (String) com.playerIps.get(name);
}
/**
* Update a server's player count.
* @param server
* @param count
*/
private void receivePlayerCount(String server, int count) {
com.playerCount.put(server, Integer.valueOf(count));
}
/**
* @param server
* @return player count for given server.
*/
public static int getPlayerCount(String server) {
return ((Integer) com.playerCount.get(server)).intValue();
}
/**
* Receive list of player names for a given server
* @param server
* @param playerList
*/
private void receivePlayerList(String server, String[] playerList) {
com.playerList.put(server, playerList);
}
/**
* @param server to get player names from
* @return list of player names for the given server.
*/
public static String[] getPlayerList(String server) {
return (String[]) com.playerList.get(server);
}
/**
* Update ip for the given server
* @param server
* @param ip
* @param port
*/
private void receiveServerIP(String server, String ip, short port) {
com.serverIp.put(server, ip + ":" + port);
}
/**
* Update the UUID for a given player
* @param player
* @param id
*/
private void receivePlayerUUID(String player, String id) {
com.playerIds.put(player, UUID.fromString(id));
}
/**
* Do whatever you want here.
*
* @param player May be relevant if the forward was to that specific player
* @param subChannel Sub channel name.
* @param message The message received.
*
* TODO: Fill this in with stuff I wanna do. :P
*/
private void receiveForward(Player player, String subChannel, String message) {
}
/**
* Send a player to another server
* @param player to send
* @param server to send the player to
*/
public static void sendConnect(Player player, String server) {
out(Channel.CONNECT, player, server);
}
/**
* Send another player to a server
* @param player to connect
* @param server to connect the player to
*/
public static void sendConnectOther(String player, String server) {
out(Channel.CONNECT_OTHER, null, player, server);
}
/**
* Send for the player's ip
* @param player who's ip to get
*/
public static void sendIP(Player player) {
out(Channel.IP, player);
}
/**
* Send for the player count to this server
* @param server to get the player count from
*/
public static void sendPlayerCount(String server) {
out(Channel.PLAYER_COUNT, null, server);
}
/**
* Send for the total player count to all the servers
*/
public static void sendPlayerCountAll() {
out(Channel.PLAYER_COUNT, null, "ALL");
}
/**
* Send for the player list to a specific server
* @param server to get the player list from
*/
public static void sendPlayerList(String server) {
out(Channel.PLAYER_LIST, null, server);
}
/**
* Send for player list from all the servers
*/
public static void sendPlayerListAll() {
out(Channel.PLAYER_LIST, null, "ALL");
}
/**
* Send for server list
*/
public static void sendGetServers() {
out(Channel.GET_SERVERS, null);
}
/**
* Send a player a message
* @param player
* @param message
*/
public static void sendMessage(String player, String message) {
out(Channel.MESSAGE, null, player, message);
}
/**
* Send for the server name
*/
public static void sendGetServer() {
out(Channel.GET_SERVER, null);
}
/**
* Send a specific server a message on a specific subchannel
* Remember, the sending and receiving server(s) need to have a player online
* @param server
* @param subChannel
* @param message
*/
public static void sendForward(String server, String subChannel, String message) {
out(Channel.FORWARD, null, server, subChannel, message);
}
/**
* Send a message on a specific subchannel to all online servers exept for the one sending the message
* Remember, the sending and receiving server(s) need to have a player online
* @param subChannel
* @param message
*/
public static void sendForwardOnline(String subChannel, String message) {
out(Channel.FORWARD, null, "ONLINE", subChannel, message);
}
/**
* Send a message on a specific subchannel to all servers exept for the one sending the message
* Remember, the sending and receiving server(s) need to have a player online
* @param subChannel
* @param message
*/
public static void sendForwardAll(String subChannel, String message) {
out(Channel.FORWARD, null, "ALL", subChannel, message);
}
/**
* Send a message on a specific subchannel to the server with a specific player
* Remember, the sending and receiving server(s) need to have a player online
* @param player
* @param subChannel
* @param message
*/
public static void sendForwardToPlayer(String player, String subChannel, String message) {
out(Channel.FORWARD_TO_PLAYER, null, player, subChannel, message);
}
/**
* Send for the uuid of a specific player
* @param player
*/
public static void sendUUID(Player player) {
out(Channel.UUID, player);
}
/**
* Send for the UUID of a specific player
* @param player
*/
public static void sendUUIDOther(String player) {
out(Channel.UUID_OTHER, null, player);
}
/**
* Send for the server ip of a specific server
* @param server
*/
public static void sendServerIP(String server) {
out(Channel.SERVER_IP, null, server);
}
/**
* Kick a player for a specific reason.
* @param player
* @param reason
*/
public static void sendKickPlayer(String player, String reason) {
out(Channel.KICK_PLAYER, null, player, reason);
}
/**
* Handles the outgoing messages.
* @param subChannel Subchannel of the message, if there is one.
* @param p player to send the message to.
* @param args
*/
private static void out(Channel subChannel, Player p, String... args) {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF(subChannel.toString());
if ((subChannel.equals(Channel.FORWARD)) || (subChannel.equals(Channel.FORWARD_TO_PLAYER))) {
out.writeUTF(args[0]);
out.writeUTF(args[1]);
try {
ByteArrayOutputStream msgbytes = new ByteArrayOutputStream();
new DataOutputStream(msgbytes).writeUTF(args[2]);
out.writeShort(msgbytes.toByteArray().length);
out.write(msgbytes.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}
} else {
for (String arg : args)
out.writeUTF(arg);
}
if (p == null)
p = (Player) Bukkit.getOnlinePlayers().iterator().next();
p.sendPluginMessage(com.plugin, "BungeeCord", out.toByteArray());
}
/**
*
* @author Justis
* Enum for all of the bungee channels.
*/
static enum Channel {
CONNECT("Connect"),
CONNECT_OTHER("ConnectOther"),
IP("IP"),
PLAYER_COUNT("PlayerCount"),
PLAYER_LIST("PlayerList"),
GET_SERVERS("GetServers"),
MESSAGE("Message"),
GET_SERVER("GetServer"),
FORWARD("Forward"),
FORWARD_TO_PLAYER("ForwardToPlayer"),
UUID("UUID"),
UUID_OTHER("UUIDOther"),
SERVER_IP("ServerIP"),
KICK_PLAYER("KickPlayer"),
OTHER("");
private String string;
/**
* You better know how an enum works.... -.-
* @param string
*/
private Channel(String string) {
this.string = string;
}
/**
* Convert the channel to it's string value.
*/
public String toString() {
return this.string;
}
/**
* Get the enum value from a string
* @param string to get the enum value from.
* @return enum value of the string
* OTHER if it is empty or does not match any of bungee's channels.
*/
public static Channel fromString(String string) {
for (Channel ch : values()) {
if (ch.toString().equalsIgnoreCase(string))
return ch;
}
return OTHER;
}
}
}
@kingarchie
Copy link

how get PlayerCount of other server?
Example: Lobby

You can do that with the BungeeCord API, something like,

main.getProxy().getServerInfo(String server)#getPlayers()#size().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment