-
Notifications
You must be signed in to change notification settings - Fork 0
messaging channels
If you have been working with Bukkit and BungeeCord/Velocity for a while, you will surely have encountered the term Plugin Messaging Channel.
If you want to know more about this technology and a little bit of history, I will link you to Spigot article
on how Bukkit and BungeeCord implement this, but in synthesis the Messaging Channels are a way with which a Proxy servers and a Bukkit servers communicate with each other.
What can be done with this communication is up to the user, but if you have experience with socket connections you will realize how powerful this system is.
However, especially for a newcomer, this might be intimidating, or they can find it difficult to work with certain Java objects (DataStreams).
This is where BearCommands comes in: the plugin offers a custom method to send and receive messages among plugins.
We will use Bukkit as our Sender and BungeeCord as our Receiver, however do keep in mind that not only Velocity supports everything we are going to talk about, but it is also interchangeable,
meaning that BungeeCord/Velocity can be the Sender while Bukkit the Receiver.
To start with sending or receiving data, you first have to register your custom channel. You can use the MessagingChannel class to create it:
public MessagingChannel(IBearPlugin<?> plugin, String channel);
This will create a channel with name <plugin-name>:<channel>
.
NOTE: you can also directly pass the channel name, without the plugin, but it is not recommended for identifying purposes.
Do keep in mind that channel must be equal among platforms, meaning that if my Bukkit channel is bukkitplugin:channel, I cannot use bungeeplugin:channel in BungeeCord.
Now that we have our custom channel ready, we can start talking!
Before doing that though, we have to tell the server that we are going to communicate using it.
Assuming you have followed the How to start a plugin guide
and that your plugin main class is an instance of IBearPlugin,
you can use addMessagingChannel()
:
public void addMessagingChannel(MessagingChannel channel);
This will make sure to register any channel passes as an outgoing plugin channel.
Communicating is really simple, thanks to cross-platform MessagingUtils class.
All you have to do, is invoke sendPluginMessage()
with the right parameters:
public static void sendPluginMessage(IBearPlugin<?> plugin, PlayerWrapper receiver, MessagingChannel channel, Object... data);
A couple of notes before we continue:
- PlayerWrapper is the same class we saw in Work with Custom Players;
-
MessagingChannel channel
should be the same channel created in Getting Started; -
Object... data
can be any data you decide.
BearCommands uses a custom object to handle any message received from a messaging channel: MessagingCommand.
This is an abstract class that you can use to create your own requests to the receiver and handle them accordingly.
To better understand this, let's check out how ExecuteCommand
works, an implementation of MessagingCommand used by the executeBungeeCommand() method:
public class ExecuteCommand extends MessagingCommand {
private final IBearPlugin<?> plugin;
public ExecuteCommand(IBearPlugin<?> plugin) {
super("executecommand");
this.plugin = plugin;
}
@Override
public void execute(PlayerWrapper player, DataInputStream inputStream) {
try {
String command = inputStream.readUTF();
if (command.startsWith("/")) command = command.substring(1);
if (ServerUtils.isVelocity()) {
((VelocityBearPlugin<?>) plugin).getProxyServer().getCommandManager().executeAsync(player.getPlayer(), command);
} else ServerUtils.getPluginManager().callMethod("dispatchCommand",
new Class<?>[]{ReflUtil.getClass("net.md_5.bungee.api.CommandSender"), String.class},
player.getPlayer(), command);
} catch (Exception e) {
e.printStackTrace();
}
}
}
There are only two things to keep in mind:
-
A constructor that specifies the command name by using the
super()
call; - The
execute(PlayerWrapper player, DataInputStream inputStream)
method, with:-
PlayerWrapper player
as the player sending the message (the sender); -
DataInputStream inputStream
as the data sent.
-
As you might immagine, using this kind of system allows to **easier interactions** among platforms while using the messaging channels.
Now that we have seen how to send messages and how to prepare commands, it is time to listen to them. We can do this thanks to a Listener provided for every platform (Bukkit: BukkitMessagingListener, BungeeCord: BungeeMessagingListener, Velocity: VelocityMessagingListener). However, BearCommands makes sure to simplify even more the listening, by providing a universal method from the IBearPlugin interface:
public void addMessagingListener(MessagingChannel channel, MessagingCommand... commands);
Just as we have seen when sending messages, you need to add the same messaging channel of the sender part.
Then, you can just add any MessagingCommand that you desire, and the plugin will automatically handle the rest for you.
Let's continue with our example and see how BearCommands prepares to listen to executeBungeeCommand() requests:
@Override
public void onEnable() {
addMessagingListener(BearMessagingChannel.MESSAGING_CHANNEL, new ExecuteCommand(this));
super.onEnable();
}
NOTE: it is crucial that you call the addMessagingListener()
method before enabling the plugin, as every channel and listener will be registered when calling the loadMessagingChannels()
and loadListeners()
methods.
- Home
- How to start a plugin
- Work with Configuration Files
- Work with Enums
- Work with Commands
- Work with Custom Players
- Work with Messaging Channels
- Creating custom SavableObjects
- Timers
- General Utils
- Placeholders
- Bukkit Utils
- Velocity Utils