This kinda "tutorial" is divided by two parts: BungeeCord (sending) and Spigot (receiving) part.
Make sure to check where the packets are coming from and disable the listeners if bungee is not enabled as a lot of plugins using packets don't seem to check and have vulnerabilities from custom clients sending packets.
BungeeCord part
Firstly, we need to register our custom channel into onEnable() in our main class. We do this with ProxyServer#registerChannel(String). The channel should be lowercase and should contain ":".
Example:
Code (Java):
public class ExampleMain extends Plugin
{
@Override
public void onEnable()
{
getProxy().registerChannel( "my:channel" );
getLogger().info( "Plugin enabled!" );
}
@Override
public void onDisable()
{
getLogger().info( "Plugin disabled!" );
}
}
{
@Override
public void onEnable()
{
getProxy().registerChannel( "my:channel" );
getLogger().info( "Plugin enabled!" );
}
@Override
public void onDisable()
{
getLogger().info( "Plugin disabled!" );
}
}
Sending a custom message is simple. You can create a method into the class where you want the plugin message to be send. Remember, for the plugin messaging channel to work you need atleast 1 player online at the server. Always check if the online players globally are null.
Example:
Code (Java):
public void sendCustomData(ProxiedPlayer player, String data1, int data2)
{
Collection<ProxiedPlayer> networkPlayers = ProxyServer.getInstance().getPlayers();
// perform a check to see if globally are no players
if ( networkPlayers == null || networkPlayers.isEmpty() )
{
return;
}
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF( "MySubChannel" ); // the channel could be whatever you want
out.writeUTF( data1 ); // this data could be whatever you want
out.writeInt( data2 ); // this data could be whatever you want
// we send the data to the server
// using ServerInfo the packet is being queued if there are no players in the server
// using only the server to send data the packet will be lost if no players are in it
player.getServer().getInfo().sendData( "my:channel", out.toByteArray() );
}
{
Collection<ProxiedPlayer> networkPlayers = ProxyServer.getInstance().getPlayers();
// perform a check to see if globally are no players
if ( networkPlayers == null || networkPlayers.isEmpty() )
{
return;
}
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF( "MySubChannel" ); // the channel could be whatever you want
out.writeUTF( data1 ); // this data could be whatever you want
out.writeInt( data2 ); // this data could be whatever you want
// we send the data to the server
// using ServerInfo the packet is being queued if there are no players in the server
// using only the server to send data the packet will be lost if no players are in it
player.getServer().getInfo().sendData( "my:channel", out.toByteArray() );
}
In Spigot, its a listener, in BungeeCord it's an event.
Code (Java):
public class PluginMessageReceiver implements Listener
{
@EventHandler
public void on(PluginMessageEvent event)
{
if ( !event.getTag().equalsIgnoreCase( "my:channel" ) )
{
return;
}
ByteArrayDataInput in = ByteStreams.newDataInput( event.getData() );
String subChannel = in.readUTF();
if ( subChannel.equalsIgnoreCase( "OtherSubchannel" ) )
{
// the receiver is a ProxiedPlayer when a server talks to the proxy
if ( event.getReceiver() instanceof ProxiedPlayer )
{
ProxiedPlayer receiver = (ProxiedPlayer) event.getReceiver();
// do things
}
// the receiver is a server when the proxy talks to a server
if ( event.getReceiver() instanceof Server )
{
Server receiver = (Server) event.getReceiver();
// do things
}
}
}
}
{
@EventHandler
public void on(PluginMessageEvent event)
{
if ( !event.getTag().equalsIgnoreCase( "my:channel" ) )
{
return;
}
ByteArrayDataInput in = ByteStreams.newDataInput( event.getData() );
String subChannel = in.readUTF();
if ( subChannel.equalsIgnoreCase( "OtherSubchannel" ) )
{
// the receiver is a ProxiedPlayer when a server talks to the proxy
if ( event.getReceiver() instanceof ProxiedPlayer )
{
ProxiedPlayer receiver = (ProxiedPlayer) event.getReceiver();
// do things
}
// the receiver is a server when the proxy talks to a server
if ( event.getReceiver() instanceof Server )
{
Server receiver = (Server) event.getReceiver();
// do things
}
}
}
}
Receiving the messages from the specified channel is easy. Also, when you create your receiver, make sure to check if the server is BungeeCord
Example main:
Code (Java):
public class ExampleMainDriver extends JavaPlugin implements PluginMessageListener
{
@Override
public void onEnable()
{
checkIfBungee();
if ( !getServer().getPluginManager().isPluginEnabled( this ) )
{
return;
}
getServer().getMessenger().registerIncomingPluginChannel( this, "my:channel", this ); // we register the incoming channel
// you can register outgoing channel if you want to send messages to the proxy
// getServer().getMessenger().registerOutgoingPluginChannel( this, "my:channel" );
getLogger().info( "<pluginName> driver enabled successfully." );
}
@Override
public void onDisable()
{
getLogger().info( "<pluginName> driver was disabled!" );
}
@Override
public void onPluginMessageReceived(String channel, Player player, byte[] bytes)
{
if ( !channel.equalsIgnoreCase( "my:channel" ) )
{
return;
}
ByteArrayDataInput in = ByteStreams.newDataInput( bytes );
String subChannel = in.readUTF();
if ( subChannel.equalsIgnoreCase( "MySubChannel" ) )
{
String data1 = in.readUTF();
int data2 = in.readInt();
// do things with the data
}
}
// we check like that if the specified server is BungeeCord.
private void checkIfBungee()
{
if ( !getServer().spigot().getConfig().getConfigurationSection("settings").getBoolean( "settings.bungeecord" ) )
{
getLogger().severe( "This server is not BungeeCord." );
getLogger().severe( "If the server is already hooked to BungeeCord, please enable it into your spigot.yml aswell." );
getLogger().severe( "Plugin disabled!" );
getServer().getPluginManager().disablePlugin( this );
}
}
}
{
@Override
public void onEnable()
{
checkIfBungee();
if ( !getServer().getPluginManager().isPluginEnabled( this ) )
{
return;
}
getServer().getMessenger().registerIncomingPluginChannel( this, "my:channel", this ); // we register the incoming channel
// you can register outgoing channel if you want to send messages to the proxy
// getServer().getMessenger().registerOutgoingPluginChannel( this, "my:channel" );
getLogger().info( "<pluginName> driver enabled successfully." );
}
@Override
public void onDisable()
{
getLogger().info( "<pluginName> driver was disabled!" );
}
@Override
public void onPluginMessageReceived(String channel, Player player, byte[] bytes)
{
if ( !channel.equalsIgnoreCase( "my:channel" ) )
{
return;
}
ByteArrayDataInput in = ByteStreams.newDataInput( bytes );
String subChannel = in.readUTF();
if ( subChannel.equalsIgnoreCase( "MySubChannel" ) )
{
String data1 = in.readUTF();
int data2 = in.readInt();
// do things with the data
}
}
// we check like that if the specified server is BungeeCord.
private void checkIfBungee()
{
if ( !getServer().spigot().getConfig().getConfigurationSection("settings").getBoolean( "settings.bungeecord" ) )
{
getLogger().severe( "This server is not BungeeCord." );
getLogger().severe( "If the server is already hooked to BungeeCord, please enable it into your spigot.yml aswell." );
getLogger().severe( "Plugin disabled!" );
getServer().getPluginManager().disablePlugin( this );
}
}
}