diff --git a/src/main/java/net/md_5/bungee/BungeeCord.java b/src/main/java/net/md_5/bungee/BungeeCord.java index 41194f165..c9d32d626 100644 --- a/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/src/main/java/net/md_5/bungee/BungeeCord.java @@ -8,7 +8,9 @@ import java.net.Socket; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; @@ -23,6 +25,7 @@ import net.md_5.bungee.command.CommandSender; import net.md_5.bungee.command.CommandServer; import net.md_5.bungee.command.ConsoleCommandSender; import net.md_5.bungee.packet.DefinedPacket; +import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.plugin.JavaPluginManager; import net.md_5.bungee.tablist.GlobalPingTabList; import net.md_5.bungee.tablist.GlobalTabList; @@ -82,6 +85,10 @@ public class BungeeCord * Tab list handler */ public TabListHandler tabListHandler; + /** + * Registered Global Plugin Channels + */ + public Queue globalPluginChannels = new ConcurrentLinkedQueue<>(); /** * Plugin manager. */ @@ -184,6 +191,9 @@ public class BungeeCord break; } + // Add RubberBand to the global plugin channel list + globalPluginChannels.add("RubberBand"); + InetSocketAddress addr = Util.getAddr(config.bindHost); listener = new ListenThread(addr); listener.start(); @@ -262,4 +272,15 @@ public class BungeeCord con.packetQueue.add(packet); } } + + /** + * Register a plugin channel for all users + * + * @param channel name + */ + public void registerPluginChannel(String channel) + { + globalPluginChannels.add(channel); + broadcast(new PacketFAPluginMessage("REGISTER", channel.getBytes())); + } } diff --git a/src/main/java/net/md_5/bungee/ServerConnection.java b/src/main/java/net/md_5/bungee/ServerConnection.java index 2ed02b38f..70f7edb97 100644 --- a/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/src/main/java/net/md_5/bungee/ServerConnection.java @@ -4,7 +4,10 @@ import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.Socket; import java.security.PublicKey; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; import javax.crypto.SecretKey; +import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.Packet2Handshake; import net.md_5.bungee.packet.PacketCDClientStatus; @@ -24,6 +27,7 @@ public class ServerConnection extends GenericConnection public final String name; public final Packet1Login loginPacket; + public Queue packetQueue = new ConcurrentLinkedQueue<>(); public ServerConnection(String name, Socket socket, PacketInputStream in, OutputStream out, Packet1Login loginPacket) { @@ -73,7 +77,13 @@ public class ServerConnection extends GenericConnection throw new KickException("[Kicked] " + new PacketFFKick(loginResponse).message); } Packet1Login login = new Packet1Login(loginResponse); - out.write(new PacketFAPluginMessage("REGISTER", "RubberBand".getBytes()).getPacket()); + + // Register all global plugin message channels + // TODO: Allow player-specific plugin message channels for full mod support + for (String channel : BungeeCord.instance.globalPluginChannels) + { + out.write(new PacketFAPluginMessage("REGISTER", channel.getBytes()).getPacket()); + } return new ServerConnection(name, socket, in, out, login); } catch (KickException ex) diff --git a/src/main/java/net/md_5/bungee/UserConnection.java b/src/main/java/net/md_5/bungee/UserConnection.java index e9d3a2d5e..11a466c2e 100644 --- a/src/main/java/net/md_5/bungee/UserConnection.java +++ b/src/main/java/net/md_5/bungee/UserConnection.java @@ -20,6 +20,8 @@ import net.md_5.bungee.packet.PacketC9PlayerListItem; import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.packet.PacketInputStream; import net.md_5.bungee.plugin.ServerConnectEvent; +import net.md_5.bungee.plugin.PluginMessageEvent; +import net.md_5.bungee.plugin.PluginMessageEvent.Destination; public class UserConnection extends GenericConnection implements CommandSender { @@ -38,6 +40,7 @@ public class UserConnection extends GenericConnection implements CommandSender private int trackingPingId; private long pingTime; private int ping; + public UserConnection instance = this; public UserConnection(Socket socket, PacketInputStream in, OutputStream out, Packet2Handshake handshake, List loginPackets) { @@ -165,6 +168,11 @@ public class UserConnection extends GenericConnection implements CommandSender packetQueue.add(new Packet3Chat(message)); } + public void sendPluginMessage(String tag, byte[] data) + { + server.packetQueue.add(new PacketFAPluginMessage(tag, data)); + } + @Override public String getName() { @@ -190,7 +198,20 @@ public class UserConnection extends GenericConnection implements CommandSender boolean sendPacket = true; int id = Util.getId(packet); - if (id == 0x03) + if (id == 0xFA) + { + // Call the onPluginMessage event + PacketFAPluginMessage message = new PacketFAPluginMessage(packet); + PluginMessageEvent event = new PluginMessageEvent(Destination.SERVER, instance); + event.setTag(message.tag); + event.setData(new String(message.data)); + BungeeCord.instance.pluginManager.onPluginMessage(event); + + if (event.isCancelled()) + { + continue; + } + } else if (id == 0x03) { Packet3Chat chat = new Packet3Chat(packet); String message = chat.message; @@ -206,6 +227,15 @@ public class UserConnection extends GenericConnection implements CommandSender } } + while (!server.packetQueue.isEmpty()) + { + DefinedPacket p = server.packetQueue.poll(); + if (p != null) + { + server.out.write(p.getPacket()); + } + } + EntityMap.rewrite(packet, clientEntityId, serverEntityId); if (sendPacket && !server.socket.isClosed()) { @@ -242,7 +272,27 @@ public class UserConnection extends GenericConnection implements CommandSender int id = Util.getId(packet); if (id == 0xFA) { + // Call the onPluginMessage event PacketFAPluginMessage message = new PacketFAPluginMessage(packet); + PluginMessageEvent event = new PluginMessageEvent(Destination.CLIENT, instance); + event.setTag(message.tag); + event.setData(new String(message.data)); + BungeeCord.instance.pluginManager.onPluginMessage(event); + + if (event.isCancelled()) + { + continue; + } + + message.tag = event.getTag(); + message.data = event.getData().getBytes(); + + // Allow a message for killing the connection outright + if (message.tag.equals("KillCon")) + { + break; + } + if (message.tag.equals("RubberBand")) { String server = new String(message.data); diff --git a/src/main/java/net/md_5/bungee/plugin/JavaPlugin.java b/src/main/java/net/md_5/bungee/plugin/JavaPlugin.java index a14656c3e..f24b6f1c6 100644 --- a/src/main/java/net/md_5/bungee/plugin/JavaPlugin.java +++ b/src/main/java/net/md_5/bungee/plugin/JavaPlugin.java @@ -51,6 +51,13 @@ public abstract class JavaPlugin { } + /** + * Called when a plugin message is sent to the client or server + */ + public void onPluginMessage(PluginMessageEvent event) + { + } + /** * Register a command for use with the proxy. */ diff --git a/src/main/java/net/md_5/bungee/plugin/JavaPluginManager.java b/src/main/java/net/md_5/bungee/plugin/JavaPluginManager.java index 5cd6afb3e..b21dd041c 100644 --- a/src/main/java/net/md_5/bungee/plugin/JavaPluginManager.java +++ b/src/main/java/net/md_5/bungee/plugin/JavaPluginManager.java @@ -106,4 +106,13 @@ public class JavaPluginManager extends JavaPlugin p.onServerConnect(event); } } + + @Override + public void onPluginMessage(PluginMessageEvent event) + { + for (JavaPlugin p : plugins) + { + p.onPluginMessage(event); + } + } }