diff --git a/pom.xml b/pom.xml
index 1f319cf..066aab9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.imaginarycode.minecraft
RedisBungee
- 0.4
+ 0.5
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java
index 4060754..a7156d1 100644
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java
+++ b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java
@@ -19,7 +19,6 @@
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
-import net.md_5.bungee.api.scheduler.ScheduledTask;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
@@ -368,7 +367,7 @@ public void run() {
}
}, 0, 1, TimeUnit.MINUTES);
}
- getProxy().registerChannel("RedisBungee");
+ getProxy().registerChannel("redisbungee:RedisBungee");
}
@Override
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java
index c99eab5..0e93abf 100644
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java
+++ b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java
@@ -1,290 +1,290 @@
-package com.imaginarycode.minecraft.redisbungee;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multiset;
-import com.google.common.io.ByteArrayDataInput;
-import com.google.common.io.ByteArrayDataOutput;
-import com.google.common.io.ByteStreams;
-import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
-import com.imaginarycode.minecraft.redisbungee.util.RedisCallable;
-import lombok.AllArgsConstructor;
-import net.md_5.bungee.api.AbstractReconnectHandler;
-import net.md_5.bungee.api.ChatColor;
-import net.md_5.bungee.api.chat.BaseComponent;
-import net.md_5.bungee.api.chat.ComponentBuilder;
-import net.md_5.bungee.api.chat.TextComponent;
-import net.md_5.bungee.api.config.ServerInfo;
-import net.md_5.bungee.api.connection.ProxiedPlayer;
-import net.md_5.bungee.api.connection.Server;
-import net.md_5.bungee.api.event.*;
-import net.md_5.bungee.api.plugin.Listener;
-import net.md_5.bungee.event.EventHandler;
-import net.md_5.bungee.event.EventPriority;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.Pipeline;
-
-import java.net.InetAddress;
-import java.util.*;
-
-@AllArgsConstructor
-public class RedisBungeeListener implements Listener {
- private static final BaseComponent[] ALREADY_LOGGED_IN =
- new ComponentBuilder("You are already logged on to this server.").color(ChatColor.RED)
- .append("\n\nIt may help to try logging in again in a few minutes.\nIf this does not resolve your issue, please contact staff.")
- .color(ChatColor.GRAY)
- .create();
- private static final BaseComponent[] ONLINE_MODE_RECONNECT =
- new ComponentBuilder("Whoops! You need to reconnect.").color(ChatColor.RED)
- .append("\n\nWe found someone online using your username. They were kicked and you may reconnect.\nIf this does not work, please contact staff.")
- .color(ChatColor.GRAY)
- .create();
- private final RedisBungee plugin;
- private final List exemptAddresses;
-
- @EventHandler(priority = EventPriority.LOWEST)
- public void onLogin(final LoginEvent event) {
- event.registerIntent(plugin);
- plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) {
- @Override
- protected Void call(Jedis jedis) {
- try {
- if (event.isCancelled()) {
- return null;
- }
-
- // We make sure they aren't trying to use an existing player's name.
- // This is problematic for online-mode servers as they always disconnect old clients.
- if (plugin.getProxy().getConfig().isOnlineMode()) {
- ProxiedPlayer player = plugin.getProxy().getPlayer(event.getConnection().getName());
-
- if (player != null) {
- event.setCancelled(true);
- // TODO: Make it accept a BaseComponent[] like everything else.
- event.setCancelReason(TextComponent.toLegacyText(ONLINE_MODE_RECONNECT));
- return null;
- }
- }
-
- for (String s : plugin.getServerIds()) {
- if (jedis.sismember("proxy:" + s + ":usersOnline", event.getConnection().getUniqueId().toString())) {
- event.setCancelled(true);
- // TODO: Make it accept a BaseComponent[] like everything else.
- event.setCancelReason(TextComponent.toLegacyText(ALREADY_LOGGED_IN));
- return null;
- }
- }
-
- Pipeline pipeline = jedis.pipelined();
- plugin.getUuidTranslator().persistInfo(event.getConnection().getName(), event.getConnection().getUniqueId(), pipeline);
- RedisUtil.createPlayer(event.getConnection(), pipeline, false);
- // We're not publishing, the API says we only publish at PostLoginEvent time.
- pipeline.sync();
-
- return null;
- } finally {
- event.completeIntent(plugin);
- }
- }
- });
- }
-
- @EventHandler
- public void onPostLogin(final PostLoginEvent event) {
- plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) {
- @Override
- protected Void call(Jedis jedis) {
- jedis.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
- event.getPlayer().getUniqueId(), DataManager.DataManagerMessage.Action.JOIN,
- new DataManager.LoginPayload(event.getPlayer().getAddress().getAddress()))));
- return null;
- }
- });
- }
-
- @EventHandler
- public void onPlayerDisconnect(final PlayerDisconnectEvent event) {
- plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) {
- @Override
- protected Void call(Jedis jedis) {
- Pipeline pipeline = jedis.pipelined();
- RedisUtil.cleanUpPlayer(event.getPlayer().getUniqueId().toString(), pipeline);
- pipeline.sync();
- return null;
- }
- });
- }
-
- @EventHandler
- public void onServerChange(final ServerConnectedEvent event) {
- final String currentServer = event.getPlayer().getServer() == null ? null : event.getPlayer().getServer().getInfo().getName();
- plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) {
- @Override
- protected Void call(Jedis jedis) {
- jedis.hset("player:" + event.getPlayer().getUniqueId().toString(), "server", event.getServer().getInfo().getName());
- jedis.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
- event.getPlayer().getUniqueId(), DataManager.DataManagerMessage.Action.SERVER_CHANGE,
- new DataManager.ServerChangePayload(event.getServer().getInfo().getName(), currentServer))));
- return null;
- }
- });
- }
-
- @EventHandler(priority = EventPriority.LOWEST)
- public void onPing(final ProxyPingEvent event) {
- if (exemptAddresses.contains(event.getConnection().getAddress().getAddress())) {
- return;
- }
-
- ServerInfo forced = AbstractReconnectHandler.getForcedHost(event.getConnection());
-
- if (forced != null && event.getConnection().getListener().isPingPassthrough()) {
- return;
- }
-
- event.getResponse().getPlayers().setOnline(plugin.getCount());
- }
-
- @EventHandler
- public void onPluginMessage(final PluginMessageEvent event) {
- if (event.getTag().equals("RedisBungee") && event.getSender() instanceof Server) {
- final byte[] data = Arrays.copyOf(event.getData(), event.getData().length);
- plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
- @Override
- public void run() {
- ByteArrayDataInput in = ByteStreams.newDataInput(data);
-
- String subchannel = in.readUTF();
- ByteArrayDataOutput out = ByteStreams.newDataOutput();
- String type;
-
- switch (subchannel) {
- case "PlayerList":
- out.writeUTF("PlayerList");
- Set original = Collections.emptySet();
- type = in.readUTF();
- if (type.equals("ALL")) {
- out.writeUTF("ALL");
- original = plugin.getPlayers();
- } else {
- try {
- original = RedisBungee.getApi().getPlayersOnServer(type);
- } catch (IllegalArgumentException ignored) {
- }
- }
- Set players = new HashSet<>();
- for (UUID uuid : original)
- players.add(plugin.getUuidTranslator().getNameFromUuid(uuid, false));
- out.writeUTF(Joiner.on(',').join(players));
- break;
- case "PlayerCount":
- out.writeUTF("PlayerCount");
- type = in.readUTF();
- if (type.equals("ALL")) {
- out.writeUTF("ALL");
- out.writeInt(plugin.getCount());
- } else {
- out.writeUTF(type);
- try {
- out.writeInt(RedisBungee.getApi().getPlayersOnServer(type).size());
- } catch (IllegalArgumentException e) {
- out.writeInt(0);
- }
- }
- break;
- case "LastOnline":
- String user = in.readUTF();
- out.writeUTF("LastOnline");
- out.writeUTF(user);
- out.writeLong(RedisBungee.getApi().getLastOnline(plugin.getUuidTranslator().getTranslatedUuid(user, true)));
- break;
- case "ServerPlayers":
- String type1 = in.readUTF();
- out.writeUTF("ServerPlayers");
- Multimap multimap = RedisBungee.getApi().getServerToPlayers();
-
- boolean includesUsers;
-
- switch (type1) {
- case "COUNT":
- includesUsers = false;
- break;
- case "PLAYERS":
- includesUsers = true;
- break;
- default:
- // TODO: Should I raise an error?
- return;
- }
-
- out.writeUTF(type1);
-
- if (includesUsers) {
- Multimap human = HashMultimap.create();
- for (Map.Entry entry : multimap.entries()) {
- human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false));
- }
- serializeMultimap(human, true, out);
- } else {
- serializeMultiset(multimap.keys(), out);
- }
- break;
- case "Proxy":
- out.writeUTF("Proxy");
- out.writeUTF(RedisBungee.getConfiguration().getServerId());
- break;
- case "PlayerProxy":
- String username = in.readUTF();
- out.writeUTF("PlayerProxy");
- out.writeUTF(username);
- out.writeUTF(RedisBungee.getApi().getProxy(plugin.getUuidTranslator().getTranslatedUuid(username, true)));
- break;
- default:
- return;
- }
-
- ((Server) event.getSender()).sendData("RedisBungee", out.toByteArray());
- }
- });
- }
- }
-
- private void serializeMultiset(Multiset collection, ByteArrayDataOutput output) {
- output.writeInt(collection.elementSet().size());
- for (Multiset.Entry entry : collection.entrySet()) {
- output.writeUTF(entry.getElement());
- output.writeInt(entry.getCount());
- }
- }
-
- private void serializeMultimap(Multimap collection, boolean includeNames, ByteArrayDataOutput output) {
- output.writeInt(collection.keySet().size());
- for (Map.Entry> entry : collection.asMap().entrySet()) {
- output.writeUTF(entry.getKey());
- if (includeNames) {
- serializeCollection(entry.getValue(), output);
- } else {
- output.writeInt(entry.getValue().size());
- }
- }
- }
-
- private void serializeCollection(Collection> collection, ByteArrayDataOutput output) {
- output.writeInt(collection.size());
- for (Object o : collection) {
- output.writeUTF(o.toString());
- }
- }
-
- @EventHandler
- public void onPubSubMessage(PubSubMessageEvent event) {
- if (event.getChannel().equals("redisbungee-allservers") || event.getChannel().equals("redisbungee-" + RedisBungee.getApi().getServerId())) {
- String message = event.getMessage();
- if (message.startsWith("/"))
- message = message.substring(1);
- plugin.getLogger().info("Invoking command via PubSub: /" + message);
- plugin.getProxy().getPluginManager().dispatchCommand(RedisBungeeCommandSender.instance, message);
- }
- }
-}
+package com.imaginarycode.minecraft.redisbungee;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multiset;
+import com.google.common.io.ByteArrayDataInput;
+import com.google.common.io.ByteArrayDataOutput;
+import com.google.common.io.ByteStreams;
+import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
+import com.imaginarycode.minecraft.redisbungee.util.RedisCallable;
+import lombok.AllArgsConstructor;
+import net.md_5.bungee.api.AbstractReconnectHandler;
+import net.md_5.bungee.api.ChatColor;
+import net.md_5.bungee.api.chat.BaseComponent;
+import net.md_5.bungee.api.chat.ComponentBuilder;
+import net.md_5.bungee.api.chat.TextComponent;
+import net.md_5.bungee.api.config.ServerInfo;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.connection.Server;
+import net.md_5.bungee.api.event.*;
+import net.md_5.bungee.api.plugin.Listener;
+import net.md_5.bungee.event.EventHandler;
+import net.md_5.bungee.event.EventPriority;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.Pipeline;
+
+import java.net.InetAddress;
+import java.util.*;
+
+@AllArgsConstructor
+public class RedisBungeeListener implements Listener {
+ private static final BaseComponent[] ALREADY_LOGGED_IN =
+ new ComponentBuilder("You are already logged on to this server.").color(ChatColor.RED)
+ .append("\n\nIt may help to try logging in again in a few minutes.\nIf this does not resolve your issue, please contact staff.")
+ .color(ChatColor.GRAY)
+ .create();
+ private static final BaseComponent[] ONLINE_MODE_RECONNECT =
+ new ComponentBuilder("Whoops! You need to reconnect.").color(ChatColor.RED)
+ .append("\n\nWe found someone online using your username. They were kicked and you may reconnect.\nIf this does not work, please contact staff.")
+ .color(ChatColor.GRAY)
+ .create();
+ private final RedisBungee plugin;
+ private final List exemptAddresses;
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onLogin(final LoginEvent event) {
+ event.registerIntent(plugin);
+ plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) {
+ @Override
+ protected Void call(Jedis jedis) {
+ try {
+ if (event.isCancelled()) {
+ return null;
+ }
+
+ // We make sure they aren't trying to use an existing player's name.
+ // This is problematic for online-mode servers as they always disconnect old clients.
+ if (plugin.getProxy().getConfig().isOnlineMode()) {
+ ProxiedPlayer player = plugin.getProxy().getPlayer(event.getConnection().getName());
+
+ if (player != null) {
+ event.setCancelled(true);
+ // TODO: Make it accept a BaseComponent[] like everything else.
+ event.setCancelReason(TextComponent.toLegacyText(ONLINE_MODE_RECONNECT));
+ return null;
+ }
+ }
+
+ for (String s : plugin.getServerIds()) {
+ if (jedis.sismember("proxy:" + s + ":usersOnline", event.getConnection().getUniqueId().toString())) {
+ event.setCancelled(true);
+ // TODO: Make it accept a BaseComponent[] like everything else.
+ event.setCancelReason(TextComponent.toLegacyText(ALREADY_LOGGED_IN));
+ return null;
+ }
+ }
+
+ Pipeline pipeline = jedis.pipelined();
+ plugin.getUuidTranslator().persistInfo(event.getConnection().getName(), event.getConnection().getUniqueId(), pipeline);
+ RedisUtil.createPlayer(event.getConnection(), pipeline, false);
+ // We're not publishing, the API says we only publish at PostLoginEvent time.
+ pipeline.sync();
+
+ return null;
+ } finally {
+ event.completeIntent(plugin);
+ }
+ }
+ });
+ }
+
+ @EventHandler
+ public void onPostLogin(final PostLoginEvent event) {
+ plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) {
+ @Override
+ protected Void call(Jedis jedis) {
+ jedis.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
+ event.getPlayer().getUniqueId(), DataManager.DataManagerMessage.Action.JOIN,
+ new DataManager.LoginPayload(event.getPlayer().getAddress().getAddress()))));
+ return null;
+ }
+ });
+ }
+
+ @EventHandler
+ public void onPlayerDisconnect(final PlayerDisconnectEvent event) {
+ plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) {
+ @Override
+ protected Void call(Jedis jedis) {
+ Pipeline pipeline = jedis.pipelined();
+ RedisUtil.cleanUpPlayer(event.getPlayer().getUniqueId().toString(), pipeline);
+ pipeline.sync();
+ return null;
+ }
+ });
+ }
+
+ @EventHandler
+ public void onServerChange(final ServerConnectedEvent event) {
+ final String currentServer = event.getPlayer().getServer() == null ? null : event.getPlayer().getServer().getInfo().getName();
+ plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) {
+ @Override
+ protected Void call(Jedis jedis) {
+ jedis.hset("player:" + event.getPlayer().getUniqueId().toString(), "server", event.getServer().getInfo().getName());
+ jedis.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
+ event.getPlayer().getUniqueId(), DataManager.DataManagerMessage.Action.SERVER_CHANGE,
+ new DataManager.ServerChangePayload(event.getServer().getInfo().getName(), currentServer))));
+ return null;
+ }
+ });
+ }
+
+ @EventHandler(priority = EventPriority.LOWEST)
+ public void onPing(final ProxyPingEvent event) {
+ if (exemptAddresses.contains(event.getConnection().getAddress().getAddress())) {
+ return;
+ }
+
+ ServerInfo forced = AbstractReconnectHandler.getForcedHost(event.getConnection());
+
+ if (forced != null && event.getConnection().getListener().isPingPassthrough()) {
+ return;
+ }
+
+ event.getResponse().getPlayers().setOnline(plugin.getCount());
+ }
+
+ @EventHandler
+ public void onPluginMessage(final PluginMessageEvent event) {
+ if (event.getTag().equals("redisbungee:RedisBungee") && event.getSender() instanceof Server) {
+ final byte[] data = Arrays.copyOf(event.getData(), event.getData().length);
+ plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
+ @Override
+ public void run() {
+ ByteArrayDataInput in = ByteStreams.newDataInput(data);
+
+ String subchannel = in.readUTF();
+ ByteArrayDataOutput out = ByteStreams.newDataOutput();
+ String type;
+
+ switch (subchannel) {
+ case "PlayerList":
+ out.writeUTF("PlayerList");
+ Set original = Collections.emptySet();
+ type = in.readUTF();
+ if (type.equals("ALL")) {
+ out.writeUTF("ALL");
+ original = plugin.getPlayers();
+ } else {
+ try {
+ original = RedisBungee.getApi().getPlayersOnServer(type);
+ } catch (IllegalArgumentException ignored) {
+ }
+ }
+ Set players = new HashSet<>();
+ for (UUID uuid : original)
+ players.add(plugin.getUuidTranslator().getNameFromUuid(uuid, false));
+ out.writeUTF(Joiner.on(',').join(players));
+ break;
+ case "PlayerCount":
+ out.writeUTF("PlayerCount");
+ type = in.readUTF();
+ if (type.equals("ALL")) {
+ out.writeUTF("ALL");
+ out.writeInt(plugin.getCount());
+ } else {
+ out.writeUTF(type);
+ try {
+ out.writeInt(RedisBungee.getApi().getPlayersOnServer(type).size());
+ } catch (IllegalArgumentException e) {
+ out.writeInt(0);
+ }
+ }
+ break;
+ case "LastOnline":
+ String user = in.readUTF();
+ out.writeUTF("LastOnline");
+ out.writeUTF(user);
+ out.writeLong(RedisBungee.getApi().getLastOnline(plugin.getUuidTranslator().getTranslatedUuid(user, true)));
+ break;
+ case "ServerPlayers":
+ String type1 = in.readUTF();
+ out.writeUTF("ServerPlayers");
+ Multimap multimap = RedisBungee.getApi().getServerToPlayers();
+
+ boolean includesUsers;
+
+ switch (type1) {
+ case "COUNT":
+ includesUsers = false;
+ break;
+ case "PLAYERS":
+ includesUsers = true;
+ break;
+ default:
+ // TODO: Should I raise an error?
+ return;
+ }
+
+ out.writeUTF(type1);
+
+ if (includesUsers) {
+ Multimap human = HashMultimap.create();
+ for (Map.Entry entry : multimap.entries()) {
+ human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false));
+ }
+ serializeMultimap(human, true, out);
+ } else {
+ serializeMultiset(multimap.keys(), out);
+ }
+ break;
+ case "Proxy":
+ out.writeUTF("Proxy");
+ out.writeUTF(RedisBungee.getConfiguration().getServerId());
+ break;
+ case "PlayerProxy":
+ String username = in.readUTF();
+ out.writeUTF("PlayerProxy");
+ out.writeUTF(username);
+ out.writeUTF(RedisBungee.getApi().getProxy(plugin.getUuidTranslator().getTranslatedUuid(username, true)));
+ break;
+ default:
+ return;
+ }
+
+ ((Server) event.getSender()).sendData("redisbungee:RedisBungee", out.toByteArray());
+ }
+ });
+ }
+ }
+
+ private void serializeMultiset(Multiset collection, ByteArrayDataOutput output) {
+ output.writeInt(collection.elementSet().size());
+ for (Multiset.Entry entry : collection.entrySet()) {
+ output.writeUTF(entry.getElement());
+ output.writeInt(entry.getCount());
+ }
+ }
+
+ private void serializeMultimap(Multimap collection, boolean includeNames, ByteArrayDataOutput output) {
+ output.writeInt(collection.keySet().size());
+ for (Map.Entry> entry : collection.asMap().entrySet()) {
+ output.writeUTF(entry.getKey());
+ if (includeNames) {
+ serializeCollection(entry.getValue(), output);
+ } else {
+ output.writeInt(entry.getValue().size());
+ }
+ }
+ }
+
+ private void serializeCollection(Collection> collection, ByteArrayDataOutput output) {
+ output.writeInt(collection.size());
+ for (Object o : collection) {
+ output.writeUTF(o.toString());
+ }
+ }
+
+ @EventHandler
+ public void onPubSubMessage(PubSubMessageEvent event) {
+ if (event.getChannel().equals("redisbungee-allservers") || event.getChannel().equals("redisbungee-" + RedisBungee.getApi().getServerId())) {
+ String message = event.getMessage();
+ if (message.startsWith("/"))
+ message = message.substring(1);
+ plugin.getLogger().info("Invoking command via PubSub: /" + message);
+ plugin.getProxy().getPluginManager().dispatchCommand(RedisBungeeCommandSender.instance, message);
+ }
+ }
+}
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index a5630e1..cf22257 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,6 +1,6 @@
name: RedisBungee
main: com.imaginarycode.minecraft.redisbungee.RedisBungee
-version: 0.3.10
+version: 0.5.0
author: tuxed
# This is used so that we can automagically override default BungeeCord behavior.
softDepends: ["cmd_find", "cmd_list"]
\ No newline at end of file