Bukkit & Bungee Plugin Messaging Channel - Historical

Applied By Dead-i: Aug 25, 2014 at 10:46 AM

Bukkit & Bungee Plugin Messaging Channel

BungeeCord Plugin Messaging Channel



This page explains the Bukkit and BungeeCord plugin messaging channel. The channel allows plugins to communicate with the BungeeCord server and the servers connected to it.


What is a plugin message?(top)

Originally, plugin messaging was implemented so server-side plugins could send any kind of data to client-side mods. Before, they would have needed to implement custom packets, but the problem with this is that it meant the Minecraft client would get disconnected from the servers using those custom packets with an incomprehensible error message, because it would be unable to read that packet. To fix this issue, Mojang introduced the "Custom Plugin Message Packet".

The anatomy of a Plugin Message Packet is as such:
  1. The name of the "channel" (also named "tag" in BungeeCord) the plugin message transits through (in a string)
  2. The size of the plugin message (in a short)
  3. The actual data (in a byte array)
The protocol-level details can be found here.

The BungeeCord plugin channel(top)

BungeeCord exposes a plugin channel to the backend/Bukkit servers called "BungeeCord". The byte array you will send (and receive) will use output generated by the DataInputStream and DataOutputStream classes. For convenience, we will use the ByteArrayDataInput and ByteArrayDataOutput classes from Google Guava, which silences IOException for us.

Before using the BungeeCord plugin channel, you'll need to register it with the Bukkit messenger. That is, you need to tell Bukkit "Hey, I want to use this channel". We'll also need to tell Bukkit what method to call whenever they receive a new message on channel "BungeeCord". Here is a example of a simple plugin message-enabled plugin:

Code (Java):

public class MyPlugin extends JavaPlugin implements PluginMessageListener {
  @Override
  public void onEnable() {
    this.getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
    this.getServer().getMessenger().registerIncomingPluginChannel(this, "BungeeCord", this);
  }

  @Override
  public void onPluginMessageReceived(String channel, Player player, byte[] message) {
    if (!channel.equals("BungeeCord")) {
      return;
    }
    ByteArrayDataInput in = ByteStreams.newDataInput(message);
    String subchannel = in.readUTF();
    if (subchannel.equals("SomeSubChannel")) {
      // Use the code sample in the 'Response' sections below to read
      // the data.
    }
  }
}
 
Sending a plugin message is trivial:
Code (Java):
  ByteArrayDataOutput out = ByteStreams.newDataOutput();
  out.writeUTF("Subchannel");
  out.writeUTF("Argument");

  // If you don't care about the player
  // Player player = Iterables.getFirst(Bukkit.getOnlinePlayers(), null);
  // Else, specify them
  Player player = Bukkit.getPlayerExact("Example");

  player.sendPluginMessage(this, "BungeeCord", out.toByteArray());
Keep in mind that you can't send plugin messages directly after a player joins(Eg. in PlayerJoinEvent). You have to include a slight delay.

BungeeCord subchannel specification(top)

Connect(top)

Connects a player to said subserver.

Arguments
String name of server to connect to, as defined in BungeeCord config.yml

Receiver
the player you want to teleport

Sending Example
Code (Java):
out.writeUTF("Connect");
out.writeUTF("pvp");
Response
None


ConnectOther(top)

Connect a named player to said subserver.

Arguments

String name of the player to teleport
String name of server to connect to, as defined in BungeeCord config.yml

Receiver
Any player

Sending Example
Code (Java):
out.writeUTF("ConnectOther");
out.writeUTF("roblabla");
out.writeUTF("pvp");
Response
None


IP(top)

Get the (real) IP of a player.

Arguments
None

Receiver
The player you wish to get the IP of.

Example
Code (Java):
out.writeUTF("IP");
Response
Code (Java):
String ip = in.readUTF();
int port = in.readInt();

PlayerCount(top)

Get the amount of players on a certain server, or on ALL the servers.

Arguments
String the name of the server to get the player count of, or ALL to get the global player count

Receiver
Any player

Example
Code (Java):
out.writeUTF("PlayerCount");
out.writeUTF("pvp");
Response
Code (Java):
String server = in.readUTF(); // Name of server, as given in the arguments
int playercount = in.readInt();

PlayerList(top)

Get a list of players connected on a certain server, or on ALL the servers.

Arguments
String the name of the server to get the list of connected players, or ALL for global online player list

Receiver
Any player

Example
Code (Java):
out.writeUTF("PlayerList");
out.writeUTF("pvp");
Response
Code (Java):
String server = in.readUTF(); // The name of the server you got the player list of, as given in args.
String[] playerList = in.readUTF().split(", ");

GetServers(top)

Get a list of server name strings, as defined in BungeeCord's config.yml

Arguments
None

Receiver
Any player

Example
Code (Java):
out.writeUTF("GetServers");
Response
Code (Java):
String[] serverList = in.readUTF().split(", ");

Message(top)

Send a message (as in, a chat message) to the specified player.

Arguments
String the name of the player to send the chat message
String the message to send to the player

Receiver
Any player

Example
Code (Java):
out.writeUTF("Message");
out.writeUTF("roblabla");
out.writeUTF(ChatColor.RED + "Congrats, you just won 1$!");
Response
None


GetServer(top)

Get this server's name, as defined in BungeeCord's config.yml

Arguments
None

Receiver
Any player

Example
Code (Java):
out.writeUTF("GetServer");
Response
Code (Java):
String servername = in.readUTF();

Forward(top)

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.

Arguments
String server to send to, ALL to send to every server (except the one sending the plugin message), or ONLINE to send to every server that's online (except the one sending the plugin message)
String Subchannel for plugin usage.
Short The size of the plugin message array.
Byte[] message to send.

Receiver
Any player

Example
Code (Java):
out.writeUTF("Forward"); // So BungeeCord knows to forward it
out.writeUTF("ALL");
out.writeUTF("MyChannel"); // The channel name to check if this your data

ByteArrayOutputStream msgbytes = new ByteArrayOutputStream();
DataOutputStream msgout = new DataOutputStream(msgbytes);
msgout.writeUTF("Some kind of data here"); // You can do anything you want with msgout
msgout.writeShort(123);

out.writeShort(msgbytes.toByteArray().length);
out.write(msgbytes.toByteArray());
Response
Code (Java):
String subChannel = in.readUTF();
short len = in.readShort();
byte[] msgbytes = new byte[len];
in.readFully(msgbytes);

DataInputStream msgin = new DataInputStream(new ByteArrayInputStream(msgbytes));
String somedata = msgin.readUTF(); // Read the data in the same way you wrote it
short somenumber = msgin.readShort();

ForwardToPlayer(top)

Send a custom plugin message to specific player.

Arguments
Playername to send to.
String Subchannel for plugin usage.
Short The size of the plugin message array.
Byte[] message to send.

Receiver
Any player

Example
Code (Java):
out.writeUTF("ForwardToPlayer");
out.writeUTF("md_5");
out.writeUTF("MyChannel");

ByteArrayOutputStream msgbytes = new ByteArrayOutputStream();
DataOutputStream msgout = new DataOutputStream(msgbytes);
msgout.writeUTF("Some kind of data here");
msgout.writeShort(123);

out.writeShort(msgbytes.toByteArray().length);
out.write(msgbytes.toByteArray());
Response
Code (Java):
String subChannel = in.readUTF();
short len = in.readShort();
byte[] msgbytes = new byte[len];
in.readFully(msgbytes);

DataInputStream msgin = new DataInputStream(new ByteArrayInputStream(msgbytes));
String somedata = msgin.readUTF(); // Read the data in the same way you wrote it
short somenumber = msgin.readShort();

UUID(top)

Request the UUID of this player

Arguments
None

Receiver
The player whose UUID you requested

Example
Code (Java):
out.writeUTF("UUID");
Response
Code (Java):
String uuid = in.readUTF();

UUIDOther(top)

Request the UUID of any player connected to the BungeeCord proxy

Arguments
String the name of the player whose UUID you would like

Receiver
The sender

Example
Code (Java):
out.writeUTF("UUIDOther");
out.writeUTF("Notch");
Response
Code (Java):
String playerName = in.readUTF();
String uuid = in.readUTF();

ServerIP(top)

Request the IP of any server on this proxy

Arguments
String - the name of the server

Receiver
Any player

Example
Code (Java):
out.writeUTF("ServerIP");
out.writeUTF("lobby");
Response
Code (Java):
String serverName = in.readUTF();
String ip = in.readUTF();
short port = in.readShort();

KickPlayer(top)

Kick any player on this proxy

Arguments
String - the name of the player
String - the reason the player is kicked with

Receiver
Any player

Example
Code (Java):
out.writeUTF("KickPlayer");
out.writeUTF("Notch");
out.writeUTF("You were kicked from the server");
Response
None