reservedChannels;
private static RedisBungeeAPI redisBungeeApi;
- RedisBungeeAPI(RedisBungee plugin) {
+ RedisBungeeAPI(RedisBungeePlugin> plugin) {
this.plugin = plugin;
redisBungeeApi = this;
this.reservedChannels = ImmutableList.of(
"redisbungee-allservers",
- "redisbungee-" + RedisBungee.getConfiguration().getServerId(),
+ "redisbungee-" + plugin.getConfiguration().getServerId(),
"redisbungee-data"
);
}
@@ -58,11 +61,10 @@ public class RedisBungeeAPI {
* as well, and will return local information on them.
*
* @param player a player name
- * @return a {@link net.md_5.bungee.api.config.ServerInfo} for the server the player is on.
+ * @return a String name for the server the player is on.
*/
- public final ServerInfo getServerFor(@NonNull UUID player) {
- String server = plugin.getDataManager().getServer(player);
- return plugin.getProxy().getServerInfo(server);
+ public final String getServerFor(@NonNull UUID player) {
+ return plugin.getDataManager().getServer(player);
}
/**
@@ -178,7 +180,7 @@ public class RedisBungeeAPI {
}
/**
- * Sends a message to a PubSub channel. The channel has to be subscribed to on this, or another redisbungee instance for {@link com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent} to fire.
+ * Sends a message to a PubSub channel. The channel has to be subscribed to on this, or another redisbungee instance for {@link PubSubMessageEvent} to fire.
*
* @param channel The PubSub channel
* @param message the message body to send
@@ -196,7 +198,7 @@ public class RedisBungeeAPI {
* @since 0.2.5
*/
public final String getServerId() {
- return RedisBungee.getConfiguration().getServerId();
+ return plugin.getConfiguration().getServerId();
}
/**
@@ -211,13 +213,13 @@ public class RedisBungeeAPI {
}
/**
- * Register (a) PubSub channel(s), so that you may handle {@link com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent} for it.
+ * Register (a) PubSub channel(s), so that you may handle {@link PubSubMessageEvent} for it.
*
* @param channels the channels to register
* @since 0.3
*/
public final void registerPubSubChannels(String... channels) {
- RedisBungee.getPubSubListener().addChannel(channels);
+ plugin.getPubSubListener().addChannel(channels);
}
/**
@@ -231,7 +233,7 @@ public class RedisBungeeAPI {
Preconditions.checkArgument(!reservedChannels.contains(channel), "attempting to unregister internal channel");
}
- RedisBungee.getPubSubListener().removeChannel(channels);
+ plugin.getPubSubListener().removeChannel(channels);
}
/**
@@ -302,18 +304,16 @@ public class RedisBungeeAPI {
}
/**
- * This gets Redis Bungee Jedis pool
+ * This gives you instance of Jedis!
*
* @return {@link JedisPool}
- * @since 0.6.5
+ * @since 0.7.0
*/
- public JedisPool getJedisPool() {
- return this.plugin.getPool();
+ public Jedis getJedisPool() {
+ return this.plugin.requestJedis();
}
/**
- * This alternative to {@link RedisBungee#getApi()}
- * which now deprecated. but to maintain old plugins compatibility it won't be removed.
*
* @return the API instance.
* @since 0.6.5
diff --git a/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java
new file mode 100644
index 0000000..e336d64
--- /dev/null
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java
@@ -0,0 +1,27 @@
+package com.imaginarycode.minecraft.redisbungee.events;
+
+/**
+ * This event is posted when a PubSub message is received.
+ *
+ * Warning : This event is fired in a separate thread!
+ *
+ * @since 0.2.6
+ */
+
+public class PubSubMessageEvent {
+ private final String channel;
+ private final String message;
+
+ public PubSubMessageEvent(String channel, String message) {
+ this.channel = channel;
+ this.message = message;
+ }
+
+ public String getChannel() {
+ return channel;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/AbstractRedisBungeeListener.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/AbstractRedisBungeeListener.java
new file mode 100644
index 0000000..3370f4e
--- /dev/null
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/AbstractRedisBungeeListener.java
@@ -0,0 +1,70 @@
+package com.imaginarycode.minecraft.redisbungee.internal;
+
+
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multiset;
+import com.google.common.io.ByteArrayDataOutput;
+import com.google.gson.Gson;
+
+import java.net.InetAddress;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+public abstract class AbstractRedisBungeeListener {
+
+ protected static final String ALREADY_LOGGED_IN = "§cYou are already logged on to this server. \n\nIt may help to try logging in again in a few minutes.\nIf this does not resolve your issue, please contact staff.";
+
+ protected static final String ONLINE_MODE_RECONNECT = "§cWhoops! You need to reconnect\n\nWe found someone online using your username. They were kicked and you may reconnect.\nIf this does not work, please contact staff.";
+
+ protected final RedisBungeePlugin> plugin;
+ protected final List exemptAddresses;
+ protected final Gson gson = new Gson();
+
+ public AbstractRedisBungeeListener(RedisBungeePlugin> plugin, List exemptAddresses) {
+ this.plugin = plugin;
+ this.exemptAddresses = exemptAddresses;
+ }
+
+ public abstract void onLogin(LE event);
+
+ public abstract void onPostLogin(PLE event);
+
+ public abstract void onPlayerDisconnect(PD event);
+
+ public abstract void onServerChange(SC event);
+
+ public abstract void onPing(PP event);
+
+ public abstract void onPluginMessage(PM event);
+
+ 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());
+ }
+ }
+
+ @SuppressWarnings("SameParameterValue")
+ 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());
+ }
+ }
+
+ public abstract void onPubSubMessage(PS event);
+}
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/DataManager.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/DataManager.java
similarity index 57%
rename from src/main/java/com/imaginarycode/minecraft/redisbungee/DataManager.java
rename to RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/DataManager.java
index b063a3a..298aa67 100644
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/DataManager.java
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/DataManager.java
@@ -1,23 +1,14 @@
-package com.imaginarycode.minecraft.redisbungee;
+package com.imaginarycode.minecraft.redisbungee.internal;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.net.InetAddresses;
+import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.UncheckedExecutionException;
+import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
-import com.google.gson.reflect.TypeToken;
-import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetworkEvent;
-import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent;
-import com.imaginarycode.minecraft.redisbungee.events.PlayerLeftNetworkEvent;
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import net.md_5.bungee.api.connection.ProxiedPlayer;
-import net.md_5.bungee.api.event.PlayerDisconnectEvent;
-import net.md_5.bungee.api.event.PostLoginEvent;
-import net.md_5.bungee.api.plugin.Listener;
-import net.md_5.bungee.event.EventHandler;
import redis.clients.jedis.Jedis;
import java.net.InetAddress;
@@ -26,21 +17,21 @@ import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
/**
* This class manages all the data that RedisBungee fetches from Redis, along with updates to that data.
*
* @since 0.3.3
*/
-public class DataManager implements Listener {
- private final RedisBungee plugin;
+public abstract class DataManager {
+ private final RedisBungeePlugin
plugin;
private final Cache serverCache = createCache();
private final Cache proxyCache = createCache();
private final Cache ipCache = createCache();
private final Cache lastOnlineCache = createCache();
+ private final Gson gson = new Gson();
- public DataManager(RedisBungee plugin) {
+ public DataManager(RedisBungeePlugin plugin) {
this.plugin = plugin;
}
@@ -55,16 +46,16 @@ public class DataManager implements Listener {
private final JsonParser parser = new JsonParser();
public String getServer(final UUID uuid) {
- ProxiedPlayer player = plugin.getProxy().getPlayer(uuid);
+ P player = plugin.getPlayer(uuid);
if (player != null)
- return player.getServer() != null ? player.getServer().getInfo().getName() : null;
+ return plugin.isPlayerOnAServer(player) ? plugin.getPlayerServerName(player) : null;
try {
return serverCache.get(uuid, new Callable() {
@Override
public String call() throws Exception {
- try (Jedis tmpRsc = plugin.getPool().getResource()) {
+ try (Jedis tmpRsc = plugin.requestJedis()) {
return Objects.requireNonNull(tmpRsc.hget("player:" + uuid, "server"), "user not found");
}
}
@@ -72,22 +63,23 @@ public class DataManager implements Listener {
} catch (ExecutionException | UncheckedExecutionException e) {
if (e.getCause() instanceof NullPointerException && e.getCause().getMessage().equals("user not found"))
return null; // HACK
- plugin.getLogger().log(Level.SEVERE, "Unable to get server", e);
+ plugin.logFatal("Unable to get server");
throw new RuntimeException("Unable to get server for " + uuid, e);
}
}
+
public String getProxy(final UUID uuid) {
- ProxiedPlayer player = plugin.getProxy().getPlayer(uuid);
+ P player = plugin.getPlayer(uuid);
if (player != null)
- return RedisBungee.getConfiguration().getServerId();
+ return plugin.getConfiguration().getServerId();
try {
return proxyCache.get(uuid, new Callable() {
@Override
public String call() throws Exception {
- try (Jedis tmpRsc = plugin.getPool().getResource()) {
+ try (Jedis tmpRsc = plugin.requestJedis()) {
return Objects.requireNonNull(tmpRsc.hget("player:" + uuid, "proxy"), "user not found");
}
}
@@ -95,22 +87,22 @@ public class DataManager implements Listener {
} catch (ExecutionException | UncheckedExecutionException e) {
if (e.getCause() instanceof NullPointerException && e.getCause().getMessage().equals("user not found"))
return null; // HACK
- plugin.getLogger().log(Level.SEVERE, "Unable to get proxy", e);
+ plugin.logFatal("Unable to get proxy");
throw new RuntimeException("Unable to get proxy for " + uuid, e);
}
}
public InetAddress getIp(final UUID uuid) {
- ProxiedPlayer player = plugin.getProxy().getPlayer(uuid);
+ P player = plugin.getPlayer(uuid);
if (player != null)
- return player.getAddress().getAddress();
+ return plugin.getPlayerIp(player);
try {
return ipCache.get(uuid, new Callable() {
@Override
public InetAddress call() throws Exception {
- try (Jedis tmpRsc = plugin.getPool().getResource()) {
+ try (Jedis tmpRsc = plugin.requestJedis()) {
String result = tmpRsc.hget("player:" + uuid, "ip");
if (result == null)
throw new NullPointerException("user not found");
@@ -121,13 +113,13 @@ public class DataManager implements Listener {
} catch (ExecutionException | UncheckedExecutionException e) {
if (e.getCause() instanceof NullPointerException && e.getCause().getMessage().equals("user not found"))
return null; // HACK
- plugin.getLogger().log(Level.SEVERE, "Unable to get IP", e);
+ plugin.logFatal( "Unable to get IP");
throw new RuntimeException("Unable to get IP for " + uuid, e);
}
}
public long getLastOnline(final UUID uuid) {
- ProxiedPlayer player = plugin.getProxy().getPlayer(uuid);
+ P player = plugin.getPlayer(uuid);
if (player != null)
return 0;
@@ -136,14 +128,14 @@ public class DataManager implements Listener {
return lastOnlineCache.get(uuid, new Callable() {
@Override
public Long call() throws Exception {
- try (Jedis tmpRsc = plugin.getPool().getResource()) {
+ try (Jedis tmpRsc = plugin.requestJedis()) {
String result = tmpRsc.hget("player:" + uuid, "online");
return result == null ? -1 : Long.valueOf(result);
}
}
});
} catch (ExecutionException e) {
- plugin.getLogger().log(Level.SEVERE, "Unable to get last time online", e);
+ plugin.logFatal("Unable to get last time online");
throw new RuntimeException("Unable to get last time online for " + uuid, e);
}
}
@@ -155,104 +147,153 @@ public class DataManager implements Listener {
proxyCache.invalidate(uuid);
}
- @EventHandler
- public void onPostLogin(PostLoginEvent event) {
- // Invalidate all entries related to this player, since they now lie.
- invalidate(event.getPlayer().getUniqueId());
+
+ public void onPostLogin(PL event) {
+
}
- @EventHandler
- public void onPlayerDisconnect(PlayerDisconnectEvent event) {
- // Invalidate all entries related to this player, since they now lie.
- invalidate(event.getPlayer().getUniqueId());
+ public void onPlayerDisconnect(PD event) {
+
}
- @EventHandler
- public void onPubSubMessage(PubSubMessageEvent event) {
- if (!event.getChannel().equals("redisbungee-data"))
+ public abstract void onPubSubMessage(PS event);
+
+ protected void handlePubSubMessage(String channel, String message) {
+ if (!channel.equals("redisbungee-data"))
return;
// Partially deserialize the message so we can look at the action
- JsonObject jsonObject = parser.parse(event.getMessage()).getAsJsonObject();
+ JsonObject jsonObject = parser.parse(message).getAsJsonObject();
String source = jsonObject.get("source").getAsString();
- if (source.equals(RedisBungee.getConfiguration().getServerId()))
+ if (source.equals(plugin.getConfiguration().getServerId()))
return;
DataManagerMessage.Action action = DataManagerMessage.Action.valueOf(jsonObject.get("action").getAsString());
switch (action) {
case JOIN:
- final DataManagerMessage message1 = RedisBungee.getGson().fromJson(jsonObject, new TypeToken>() {
+ final DataManagerMessage message1 = gson.fromJson(jsonObject, new TypeToken() {
}.getType());
proxyCache.put(message1.getTarget(), message1.getSource());
lastOnlineCache.put(message1.getTarget(), (long) 0);
- ipCache.put(message1.getTarget(), message1.getPayload().getAddress());
- plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
+ ipCache.put(message1.getTarget(), ((LoginPayload)message1.getPayload()).getAddress());
+ plugin.executeAsync(new Runnable() {
@Override
public void run() {
- plugin.getProxy().getPluginManager().callEvent(new PlayerJoinedNetworkEvent(message1.getTarget()));
+ //plugin.getProxy().getPluginManager().callEvent(new PlayerJoinedNetworkEvent(message1.getTarget()));
}
});
break;
case LEAVE:
- final DataManagerMessage message2 = RedisBungee.getGson().fromJson(jsonObject, new TypeToken>() {
+ final DataManagerMessage message2 = gson.fromJson(jsonObject, new TypeToken() {
}.getType());
invalidate(message2.getTarget());
- lastOnlineCache.put(message2.getTarget(), message2.getPayload().getTimestamp());
- plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
+ lastOnlineCache.put(message2.getTarget(), ((LogoutPayload)message2.getPayload()).getTimestamp());
+ plugin.executeAsync(new Runnable() {
@Override
public void run() {
- plugin.getProxy().getPluginManager().callEvent(new PlayerLeftNetworkEvent(message2.getTarget()));
+ // plugin.getProxy().getPluginManager().callEvent(new PlayerLeftNetworkEvent(message2.getTarget()));
}
});
break;
case SERVER_CHANGE:
- final DataManagerMessage message3 = RedisBungee.getGson().fromJson(jsonObject, new TypeToken>() {
+ final DataManagerMessage message3 = gson.fromJson(jsonObject, new TypeToken() {
}.getType());
- serverCache.put(message3.getTarget(), message3.getPayload().getServer());
- plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
+ serverCache.put(message3.getTarget(), ((ServerChangePayload)message3.getPayload()).getServer());
+ plugin.executeAsync(new Runnable() {
@Override
public void run() {
- plugin.getProxy().getPluginManager().callEvent(new PlayerChangedServerNetworkEvent(message3.getTarget(), message3.getPayload().getOldServer(), message3.getPayload().getServer()));
+ //plugin.getProxy().getPluginManager().callEvent(new PlayerChangedServerNetworkEvent(message3.getTarget(), message3.getPayload().getOldServer(), message3.getPayload().getServer()));
}
});
break;
}
}
- @Getter
- @RequiredArgsConstructor
- static class DataManagerMessage {
- private final UUID target;
- private final String source = RedisBungee.getApi().getServerId();
- private final Action action; // for future use!
- private final T payload;
- enum Action {
+
+ public static class DataManagerMessage {
+ private final UUID target;
+ private final String source;
+ private final Action action; // for future use!
+ private final Payload payload;
+
+ public DataManagerMessage(UUID target, String source, Action action, Payload payload) {
+ this.target = target;
+ this.source = source;
+ this.action = action;
+ this.payload = payload;
+ }
+
+ public UUID getTarget() {
+ return target;
+ }
+
+ public String getSource() {
+ return source;
+ }
+
+ public Action getAction() {
+ return action;
+ }
+
+ public Payload getPayload() {
+ return payload;
+ }
+
+ public enum Action {
JOIN,
LEAVE,
SERVER_CHANGE
}
}
- @Getter
- @RequiredArgsConstructor
- static class LoginPayload {
- private final InetAddress address;
+ public static abstract class Payload {
}
- @Getter
- @RequiredArgsConstructor
- static class ServerChangePayload {
+
+ public static class LoginPayload extends Payload{
+ private final InetAddress address;
+
+ public LoginPayload(InetAddress address) {
+ this.address = address;
+ }
+
+ public InetAddress getAddress() {
+ return address;
+ }
+ }
+
+ public static class ServerChangePayload extends Payload{
private final String server;
private final String oldServer;
+
+ ServerChangePayload(String server, String oldServer) {
+ this.server = server;
+ this.oldServer = oldServer;
+ }
+
+ public String getServer() {
+ return server;
+ }
+
+ public String getOldServer() {
+ return oldServer;
+ }
}
- @Getter
- @RequiredArgsConstructor
- static class LogoutPayload {
+
+ public static class LogoutPayload extends Payload {
private final long timestamp;
+
+ public LogoutPayload(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/JedisPubSubHandler.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/JedisPubSubHandler.java
new file mode 100644
index 0000000..453ab53
--- /dev/null
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/JedisPubSubHandler.java
@@ -0,0 +1,47 @@
+package com.imaginarycode.minecraft.redisbungee.internal;
+
+import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
+import redis.clients.jedis.JedisPubSub;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class JedisPubSubHandler extends JedisPubSub {
+
+ private final RedisBungeePlugin> plugin;
+
+ public JedisPubSubHandler(RedisBungeePlugin> plugin) {
+ this.plugin = plugin;
+ }
+
+ private Class> bungeeEvent;
+
+ @Override
+ public void onMessage(final String s, final String s2) {
+ if (s2.trim().length() == 0) return;
+ plugin.executeAsync(new Runnable() {
+ @Override
+ public void run() {
+ if (isBungeeEvent()) {
+ try {
+ Object object = bungeeEvent.getConstructor(String.class, String.class).newInstance(s, s2);
+ plugin.callEvent(object);
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+ e.printStackTrace();
+ throw new RuntimeException("unable to fire pubsub event.");
+ }
+ return;
+ }
+ PubSubMessageEvent event = new PubSubMessageEvent(s, s2);
+ plugin.callEvent(event);
+ }
+ });
+ }
+
+ public boolean isBungeeEvent() {
+ return bungeeEvent != null;
+ }
+
+ public void setBungeeEvent(Class> clazz) {
+ bungeeEvent = clazz;
+ }
+}
\ No newline at end of file
diff --git a/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/PubSubListener.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/PubSubListener.java
new file mode 100644
index 0000000..c14a271
--- /dev/null
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/PubSubListener.java
@@ -0,0 +1,71 @@
+package com.imaginarycode.minecraft.redisbungee.internal;
+
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.exceptions.JedisConnectionException;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+
+public class PubSubListener implements Runnable {
+ private JedisPubSubHandler jpsh;
+ private Set addedChannels = new HashSet();
+
+ private final RedisBungeePlugin> plugin;
+
+ public PubSubListener(RedisBungeePlugin> plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public void run() {
+ boolean broken = false;
+ try (Jedis rsc = plugin.requestJedis()) {
+ try {
+ jpsh = new JedisPubSubHandler(plugin);
+ addedChannels.add("redisbungee-" + plugin.getConfiguration().getServerId());
+ addedChannels.add("redisbungee-allservers");
+ addedChannels.add("redisbungee-data");
+ rsc.subscribe(jpsh, addedChannels.toArray(new String[0]));
+ } catch (Exception e) {
+ // FIXME: Extremely ugly hack
+ // Attempt to unsubscribe this instance and try again.
+ plugin.logWarn("PubSub error, attempting to recover.");
+ try {
+ jpsh.unsubscribe();
+ } catch (Exception e1) {
+ /* This may fail with
+ - java.net.SocketException: Broken pipe
+ - redis.clients.jedis.exceptions.JedisConnectionException: JedisPubSub was not subscribed to a Jedis instance
+ */
+ }
+ broken = true;
+ }
+ } catch (JedisConnectionException e) {
+ plugin.logWarn("PubSub error, attempting to recover in 5 secs.");
+ plugin.executeAsyncAfter(this, TimeUnit.SECONDS, 5);
+ }
+
+ if (broken) {
+ run();
+ }
+ }
+
+ public void addChannel(String... channel) {
+ addedChannels.addAll(Arrays.asList(channel));
+ jpsh.subscribe(channel);
+ }
+
+ public void removeChannel(String... channel) {
+ Arrays.asList(channel).forEach(addedChannels::remove);
+ jpsh.unsubscribe(channel);
+ }
+
+ public void poison() {
+ addedChannels.clear();
+ jpsh.unsubscribe();
+ }
+}
+
diff --git a/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/RedisBungeeConfiguration.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/RedisBungeeConfiguration.java
new file mode 100644
index 0000000..55ec281
--- /dev/null
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/RedisBungeeConfiguration.java
@@ -0,0 +1,36 @@
+package com.imaginarycode.minecraft.redisbungee.internal;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.net.InetAddresses;
+
+import java.net.InetAddress;
+import java.util.List;
+
+public class RedisBungeeConfiguration {
+ private final String serverId;
+ private final List exemptAddresses;
+ private static RedisBungeeConfiguration config;
+
+ public RedisBungeeConfiguration(String serverId, List exemptAddresses) {
+ this.serverId = serverId;
+
+ ImmutableList.Builder addressBuilder = ImmutableList.builder();
+ for (String s : exemptAddresses) {
+ addressBuilder.add(InetAddresses.forString(s));
+ }
+ this.exemptAddresses = addressBuilder.build();
+ config = this;
+ }
+
+ public String getServerId() {
+ return serverId;
+ }
+
+ public List getExemptAddresses() {
+ return exemptAddresses;
+ }
+
+ public static RedisBungeeConfiguration getConfig() {
+ return config;
+ }
+}
diff --git a/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/RedisBungeePlugin.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/RedisBungeePlugin.java
new file mode 100644
index 0000000..3111728
--- /dev/null
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/RedisBungeePlugin.java
@@ -0,0 +1,79 @@
+package com.imaginarycode.minecraft.redisbungee.internal;
+
+import com.google.common.collect.Multimap;
+import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
+import com.imaginarycode.minecraft.redisbungee.internal.util.uuid.UUIDTranslator;
+import redis.clients.jedis.Jedis;
+
+import java.net.InetAddress;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+public interface RedisBungeePlugin {
+
+ void enable();
+
+ void disable();
+
+ RedisBungeeConfiguration getConfiguration();
+
+ int getCount();
+
+ DataManager
getDataManager();
+
+ Set getPlayers();
+
+ Jedis requestJedis();
+
+ RedisBungeeAPI getApi();
+
+ UUIDTranslator getUuidTranslator();
+
+ Multimap serversToPlayers();
+
+ Set getPlayersOnProxy(String proxyId);
+
+ void sendProxyCommand(String serverId, String command);
+
+ List getServerIds();
+
+ PubSubListener getPubSubListener();
+
+ void sendChannelMessage(String channel, String message);
+
+ void executeAsync(Runnable runnable);
+
+ void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int seconds);
+
+ void callEvent(Object object);
+
+ boolean isOnlineMode();
+
+ void logInfo(String msg);
+
+ void logWarn(String msg);
+
+ void logFatal(String msg);
+
+ boolean isPlayerServerNull(P player);
+
+ P getPlayer(UUID uuid);
+
+ P getPlayer(String name);
+
+ UUID getPlayerUUID(String player);
+
+ String getPlayerName(UUID player);
+
+ String getPlayerServerName(P player);
+
+ boolean isPlayerOnAServer(P player);
+
+ InetAddress getPlayerIp(P player);
+
+ void executeProxyCommand(String cmd);
+
+
+}
diff --git a/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/RedisUtil.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/RedisUtil.java
new file mode 100644
index 0000000..697a1e6
--- /dev/null
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/RedisUtil.java
@@ -0,0 +1,51 @@
+package com.imaginarycode.minecraft.redisbungee.internal;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.gson.Gson;
+import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.Pipeline;
+
+import java.util.UUID;
+
+@VisibleForTesting
+public class RedisUtil {
+ private static final Gson gson = new Gson();
+
+ public static void cleanUpPlayer(String player, Jedis rsc) {
+ rsc.srem("proxy:" + RedisBungeeAPI.getRedisBungeeApi().getServerId() + ":usersOnline", player);
+ rsc.hdel("player:" + player, "server", "ip", "proxy");
+ long timestamp = System.currentTimeMillis();
+ rsc.hset("player:" + player, "online", String.valueOf(timestamp));
+ rsc.publish("redisbungee-data", gson.toJson(new DataManager.DataManagerMessage(
+ UUID.fromString(player), RedisBungeeAPI.getRedisBungeeApi().getServerId(), DataManager.DataManagerMessage.Action.LEAVE,
+ new DataManager.LogoutPayload(timestamp))));
+ }
+
+ public static void cleanUpPlayer(String player, Pipeline rsc) {
+ rsc.srem("proxy:" + RedisBungeeAPI.getRedisBungeeApi().getServerId() + ":usersOnline", player);
+ rsc.hdel("player:" + player, "server", "ip", "proxy");
+ long timestamp = System.currentTimeMillis();
+ rsc.hset("player:" + player, "online", String.valueOf(timestamp));
+ rsc.publish("redisbungee-data", gson.toJson(new DataManager.DataManagerMessage(
+ UUID.fromString(player), RedisBungeeAPI.getRedisBungeeApi().getServerId(), DataManager.DataManagerMessage.Action.LEAVE,
+ new DataManager.LogoutPayload(timestamp))));
+ }
+
+ public static boolean isRedisVersionRight(String redisVersion) {
+ // Need to use >=6.2 to use Lua optimizations.
+ String[] args = redisVersion.split("\\.");
+ if (args.length < 2) {
+ return false;
+ }
+ int major = Integer.parseInt(args[0]);
+ int minor = Integer.parseInt(args[1]);
+ return major >= 6 && minor >= 0;
+ }
+
+ // Ham1255: i am keeping this if some plugin uses this *IF*
+ @Deprecated
+ public static boolean canUseLua(String redisVersion) {
+ return isRedisVersionRight(redisVersion);
+ }
+}
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/IOUtil.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/IOUtil.java
similarity index 74%
rename from src/main/java/com/imaginarycode/minecraft/redisbungee/util/IOUtil.java
rename to RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/IOUtil.java
index be44849..f2b943d 100644
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/IOUtil.java
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/IOUtil.java
@@ -1,14 +1,12 @@
-package com.imaginarycode.minecraft.redisbungee.util;
+package com.imaginarycode.minecraft.redisbungee.internal.util;
import com.google.common.io.ByteStreams;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
+
public class IOUtil {
public static String readInputStreamAsString(InputStream is) {
String string;
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/LuaManager.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/LuaManager.java
similarity index 58%
rename from src/main/java/com/imaginarycode/minecraft/redisbungee/util/LuaManager.java
rename to RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/LuaManager.java
index 42bcb91..008b2c2 100644
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/LuaManager.java
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/LuaManager.java
@@ -1,32 +1,46 @@
-package com.imaginarycode.minecraft.redisbungee.util;
+package com.imaginarycode.minecraft.redisbungee.internal.util;
-import com.imaginarycode.minecraft.redisbungee.RedisBungee;
-import lombok.RequiredArgsConstructor;
+import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisDataException;
import java.util.List;
-@RequiredArgsConstructor
public class LuaManager {
- private final RedisBungee plugin;
+ private final RedisBungeePlugin> plugin;
+
+ public LuaManager(RedisBungeePlugin> plugin) {
+ this.plugin = plugin;
+ }
public Script createScript(String script) {
- try (Jedis jedis = plugin.getPool().getResource()) {
+ try (Jedis jedis = plugin.requestJedis()) {
String hash = jedis.scriptLoad(script);
return new Script(script, hash);
}
}
- @RequiredArgsConstructor
public class Script {
private final String script;
private final String hashed;
+ public Script(String script, String hashed) {
+ this.script = script;
+ this.hashed = hashed;
+ }
+
+ public String getScript() {
+ return script;
+ }
+
+ public String getHashed() {
+ return hashed;
+ }
+
public Object eval(List keys, List args) {
Object data;
- try (Jedis jedis = plugin.getPool().getResource()) {
+ try (Jedis jedis = plugin.requestJedis()) {
try {
data = jedis.evalsha(hashed, keys, args);
} catch (JedisDataException e) {
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/RedisCallable.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/RedisCallable.java
similarity index 69%
rename from src/main/java/com/imaginarycode/minecraft/redisbungee/util/RedisCallable.java
rename to RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/RedisCallable.java
index 11b3e49..3aa3e28 100644
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/RedisCallable.java
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/RedisCallable.java
@@ -1,16 +1,19 @@
-package com.imaginarycode.minecraft.redisbungee.util;
+package com.imaginarycode.minecraft.redisbungee.internal.util;
-import com.imaginarycode.minecraft.redisbungee.RedisBungee;
-import lombok.AllArgsConstructor;
+import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisConnectionException;
import java.util.concurrent.Callable;
-import java.util.logging.Level;
-@AllArgsConstructor
+
+
public abstract class RedisCallable implements Callable, Runnable {
- private final RedisBungee plugin;
+ private final RedisBungeePlugin> plugin;
+
+ public RedisCallable(RedisBungeePlugin> plugin) {
+ this.plugin = plugin;
+ }
@Override
public T call() {
@@ -22,10 +25,10 @@ public abstract class RedisCallable implements Callable, Runnable {
}
private T run(boolean retry) {
- try (Jedis jedis = plugin.getPool().getResource()) {
+ try (Jedis jedis = plugin.requestJedis()) {
return call(jedis);
} catch (JedisConnectionException e) {
- plugin.getLogger().log(Level.SEVERE, "Unable to get connection", e);
+ plugin.logFatal("Unable to get connection");
if (!retry) {
// Wait one second before retrying the task
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/uuid/NameFetcher.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/uuid/NameFetcher.java
similarity index 76%
rename from src/main/java/com/imaginarycode/minecraft/redisbungee/util/uuid/NameFetcher.java
rename to RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/uuid/NameFetcher.java
index b7c035f..58c369a 100644
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/uuid/NameFetcher.java
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/uuid/NameFetcher.java
@@ -1,24 +1,23 @@
-package com.imaginarycode.minecraft.redisbungee.util.uuid;
+package com.imaginarycode.minecraft.redisbungee.internal.util.uuid;
+import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
-import com.imaginarycode.minecraft.redisbungee.RedisBungee;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.ResponseBody;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class NameFetcher {
- @Setter
private static OkHttpClient httpClient;
+ private static final Gson gson = new Gson();
+
+ public static void setHttpClient(OkHttpClient httpClient) {
+ NameFetcher.httpClient = httpClient;
+ }
public static List nameHistoryFromUuid(UUID uuid) throws IOException {
String url = "https://api.mojang.com/user/profiles/" + uuid.toString().replace("-", "") + "/names";
@@ -29,7 +28,7 @@ public class NameFetcher {
Type listType = new TypeToken>() {
}.getType();
- List names = RedisBungee.getGson().fromJson(response, listType);
+ List names = gson.fromJson(response, listType);
List humanNames = new ArrayList<>();
for (Name name : names) {
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/uuid/UUIDFetcher.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/uuid/UUIDFetcher.java
similarity index 82%
rename from src/main/java/com/imaginarycode/minecraft/redisbungee/util/uuid/UUIDFetcher.java
rename to RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/uuid/UUIDFetcher.java
index 61dca92..c8696fa 100644
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/uuid/UUIDFetcher.java
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/uuid/UUIDFetcher.java
@@ -1,9 +1,8 @@
-package com.imaginarycode.minecraft.redisbungee.util.uuid;
+package com.imaginarycode.minecraft.redisbungee.internal.util.uuid;
import com.google.common.collect.ImmutableList;
-import com.imaginarycode.minecraft.redisbungee.RedisBungee;
+import com.google.gson.Gson;
import com.squareup.okhttp.*;
-import lombok.Setter;
import java.util.HashMap;
import java.util.List;
@@ -18,8 +17,13 @@ public class UUIDFetcher implements Callable> {
private static final MediaType JSON = MediaType.parse("application/json");
private final List names;
private final boolean rateLimiting;
+ private static final Gson gson = new Gson();
+
+
+ public static void setHttpClient(OkHttpClient httpClient) {
+ UUIDFetcher.httpClient = httpClient;
+ }
- @Setter
private static OkHttpClient httpClient;
private UUIDFetcher(List names, boolean rateLimiting) {
@@ -39,12 +43,12 @@ public class UUIDFetcher implements Callable> {
Map uuidMap = new HashMap<>();
int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST);
for (int i = 0; i < requests; i++) {
- String body = RedisBungee.getGson().toJson(names.subList(i * 100, Math.min((i + 1) * 100, names.size())));
+ String body = gson.toJson(names.subList(i * 100, Math.min((i + 1) * 100, names.size())));
Request request = new Request.Builder().url(PROFILE_URL).post(RequestBody.create(JSON, body)).build();
ResponseBody responseBody = httpClient.newCall(request).execute().body();
String response = responseBody.string();
responseBody.close();
- Profile[] array = RedisBungee.getGson().fromJson(response, Profile[].class);
+ Profile[] array = gson.fromJson(response, Profile[].class);
for (Profile profile : array) {
UUID uuid = UUIDFetcher.getUUID(profile.id);
uuidMap.put(profile.name, uuid);
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/uuid/UUIDTranslator.java b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/uuid/UUIDTranslator.java
similarity index 77%
rename from src/main/java/com/imaginarycode/minecraft/redisbungee/util/uuid/UUIDTranslator.java
rename to RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/uuid/UUIDTranslator.java
index 0554dbf..f2c8ff0 100644
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/uuid/UUIDTranslator.java
+++ b/RedisBungee-API/src/main/java/com/imaginarycode/minecraft/redisbungee/internal/util/uuid/UUIDTranslator.java
@@ -1,13 +1,12 @@
-package com.imaginarycode.minecraft.redisbungee.util.uuid;
+package com.imaginarycode.minecraft.redisbungee.internal.util.uuid;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
-import com.imaginarycode.minecraft.redisbungee.RedisBungee;
-import lombok.Getter;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import net.md_5.bungee.api.ProxyServer;
+import com.google.gson.Gson;
+import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.exceptions.JedisException;
@@ -17,13 +16,17 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.regex.Pattern;
-@RequiredArgsConstructor
public final class UUIDTranslator {
private static final Pattern UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}");
private static final Pattern MOJANGIAN_UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{32}");
- private final RedisBungee plugin;
+ private final RedisBungeePlugin> plugin;
private final Map nameToUuidMap = new ConcurrentHashMap<>(128, 0.5f, 4);
private final Map uuidToNameMap = new ConcurrentHashMap<>(128, 0.5f, 4);
+ private static final Gson gson = new Gson();
+
+ public UUIDTranslator(RedisBungeePlugin> plugin) {
+ this.plugin = plugin;
+ }
private void addToMaps(String name, UUID uuid) {
// This is why I like LocalDate...
@@ -41,8 +44,8 @@ public final class UUIDTranslator {
public final UUID getTranslatedUuid(@NonNull String player, boolean expensiveLookups) {
// If the player is online, give them their UUID.
// Remember, local data > remote data.
- if (ProxyServer.getInstance().getPlayer(player) != null)
- return ProxyServer.getInstance().getPlayer(player).getUniqueId();
+ if (plugin.getPlayer(player) != null)
+ return plugin.getPlayerUUID(player);
// Check if it exists in the map
CachedUUIDEntry cachedUUIDEntry = nameToUuidMap.get(player.toLowerCase());
@@ -65,16 +68,16 @@ public final class UUIDTranslator {
// If we are in offline mode, UUID generation is simple.
// We don't even have to cache the UUID, since this is easy to recalculate.
- if (!plugin.getProxy().getConfig().isOnlineMode()) {
+ if (!plugin.isOnlineMode()) {
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player).getBytes(Charsets.UTF_8));
}
// Let's try Redis.
- try (Jedis jedis = plugin.getPool().getResource()) {
+ try (Jedis jedis = plugin.requestJedis()) {
String stored = jedis.hget("uuid-cache", player.toLowerCase());
if (stored != null) {
// Found an entry value. Deserialize it.
- CachedUUIDEntry entry = RedisBungee.getGson().fromJson(stored, CachedUUIDEntry.class);
+ CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class);
// Check for expiry:
if (entry.expired()) {
@@ -89,14 +92,14 @@ public final class UUIDTranslator {
}
// That didn't work. Let's ask Mojang.
- if (!expensiveLookups || !ProxyServer.getInstance().getConfig().isOnlineMode())
+ if (!expensiveLookups || !plugin.isOnlineMode())
return null;
Map uuidMap1;
try {
uuidMap1 = new UUIDFetcher(Collections.singletonList(player)).call();
} catch (Exception e) {
- plugin.getLogger().log(Level.SEVERE, "Unable to fetch UUID from Mojang for " + player, e);
+ plugin.logFatal("Unable to fetch UUID from Mojang for " + player);
return null;
}
for (Map.Entry entry : uuidMap1.entrySet()) {
@@ -106,7 +109,7 @@ public final class UUIDTranslator {
}
}
} catch (JedisException e) {
- plugin.getLogger().log(Level.SEVERE, "Unable to fetch UUID for " + player, e);
+ plugin.logFatal("Unable to fetch UUID for " + player);
}
return null; // Nope, game over!
@@ -115,8 +118,8 @@ public final class UUIDTranslator {
public final String getNameFromUuid(@NonNull UUID player, boolean expensiveLookups) {
// If the player is online, give them their UUID.
// Remember, local data > remote data.
- if (ProxyServer.getInstance().getPlayer(player) != null)
- return ProxyServer.getInstance().getPlayer(player).getName();
+ if (plugin.getPlayer(player) != null)
+ return plugin.getPlayerName(player);
// Check if it exists in the map
CachedUUIDEntry cachedUUIDEntry = uuidToNameMap.get(player);
@@ -128,11 +131,11 @@ public final class UUIDTranslator {
}
// Okay, it wasn't locally cached. Let's try Redis.
- try (Jedis jedis = plugin.getPool().getResource()) {
+ try (Jedis jedis = plugin.requestJedis()) {
String stored = jedis.hget("uuid-cache", player.toString());
if (stored != null) {
// Found an entry value. Deserialize it.
- CachedUUIDEntry entry = RedisBungee.getGson().fromJson(stored, CachedUUIDEntry.class);
+ CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class);
// Check for expiry:
if (entry.expired()) {
@@ -147,7 +150,7 @@ public final class UUIDTranslator {
}
}
- if (!expensiveLookups || !ProxyServer.getInstance().getConfig().isOnlineMode())
+ if (!expensiveLookups || !plugin.isOnlineMode())
return null;
// That didn't work. Let's ask Mojang. This call may fail, because Mojang is insane.
@@ -156,7 +159,7 @@ public final class UUIDTranslator {
List nameHist = NameFetcher.nameHistoryFromUuid(player);
name = Iterables.getLast(nameHist, null);
} catch (Exception e) {
- plugin.getLogger().log(Level.SEVERE, "Unable to fetch name from Mojang for " + player, e);
+ plugin.logFatal("Unable to fetch name from Mojang for " + player);
return null;
}
@@ -167,30 +170,46 @@ public final class UUIDTranslator {
return null;
} catch (JedisException e) {
- plugin.getLogger().log(Level.SEVERE, "Unable to fetch name for " + player, e);
+ plugin.logFatal("Unable to fetch name for " + player);
return null;
}
}
public final void persistInfo(String name, UUID uuid, Jedis jedis) {
addToMaps(name, uuid);
- String json = RedisBungee.getGson().toJson(uuidToNameMap.get(uuid));
+ String json = gson.toJson(uuidToNameMap.get(uuid));
jedis.hmset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json));
}
public final void persistInfo(String name, UUID uuid, Pipeline jedis) {
addToMaps(name, uuid);
- String json = RedisBungee.getGson().toJson(uuidToNameMap.get(uuid));
+ String json = gson.toJson(uuidToNameMap.get(uuid));
jedis.hmset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json));
}
- @RequiredArgsConstructor
- @Getter
- private class CachedUUIDEntry {
+ private static class CachedUUIDEntry {
private final String name;
private final UUID uuid;
private final Calendar expiry;
+ public CachedUUIDEntry(String name, UUID uuid, Calendar expiry) {
+ this.name = name;
+ this.uuid = uuid;
+ this.expiry = expiry;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public UUID getUuid() {
+ return uuid;
+ }
+
+ public Calendar getExpiry() {
+ return expiry;
+ }
+
public boolean expired() {
return Calendar.getInstance().after(expiry);
}
diff --git a/RedisBungee-Bungee/pom.xml b/RedisBungee-Bungee/pom.xml
new file mode 100644
index 0000000..24d951f
--- /dev/null
+++ b/RedisBungee-Bungee/pom.xml
@@ -0,0 +1,110 @@
+
+
+
+ RedisBungee
+ com.imaginarycode.minecraft
+ 0.7.0-SNAPSHOT
+
+ 4.0.0
+
+ RedisBungee-Bungee
+
+
+ 8
+ 8
+
+
+
+ bungeecord-repo
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+
+
+
+
+ src/main/resources
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.4
+
+
+ package
+
+ shade
+
+
+
+
+ redis.clients.jedis
+ com.imaginarycode.minecraft.redisbungee.internal.jedis
+
+
+
+ redis.clients.util
+ com.imaginarycode.minecraft.redisbungee.internal.jedisutil
+
+
+
+ org.apache.commons.pool
+ com.imaginarycode.minecraft.redisbungee.internal.commonspool
+
+
+
+ com.squareup.okhttp
+ com.imaginarycode.minecraft.redisbungee.internal.okhttp
+
+
+
+ okio
+ com.imaginarycode.minecraft.redisbungee.internal.okio
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.3.0
+
+ 8
+
+
+
+
+
+
+
+ com.imaginarycode.minecraft
+ RedisBungee-API
+ 0.7.0-SNAPSHOT
+
+
+ net.md-5
+ bungeecord-api
+ 1.17-R0.1-SNAPSHOT
+ jar
+ provided
+
+
+
+
\ No newline at end of file
diff --git a/RedisBungee-Bungee/src/main/java/com/imaginarycode/minecraft/redisbungee/RBUtils.java b/RedisBungee-Bungee/src/main/java/com/imaginarycode/minecraft/redisbungee/RBUtils.java
new file mode 100644
index 0000000..66c0022
--- /dev/null
+++ b/RedisBungee-Bungee/src/main/java/com/imaginarycode/minecraft/redisbungee/RBUtils.java
@@ -0,0 +1,39 @@
+package com.imaginarycode.minecraft.redisbungee;
+
+import com.google.gson.Gson;
+import com.imaginarycode.minecraft.redisbungee.internal.DataManager;
+import net.md_5.bungee.api.connection.PendingConnection;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import redis.clients.jedis.Pipeline;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class RBUtils {
+
+ private static final Gson gson = new Gson();
+
+ protected static void createPlayer(ProxiedPlayer player, Pipeline pipeline, boolean fireEvent) {
+ createPlayer(player.getPendingConnection(), pipeline, fireEvent);
+ if (player.getServer() != null)
+ pipeline.hset("player:" + player.getUniqueId().toString(), "server", player.getServer().getInfo().getName());
+ }
+
+ protected static void createPlayer(PendingConnection connection, Pipeline pipeline, boolean fireEvent) {
+ Map playerData = new HashMap<>(4);
+ playerData.put("online", "0");
+ playerData.put("ip", connection.getAddress().getAddress().getHostAddress());
+ playerData.put("proxy", RedisBungeeAPI.getRedisBungeeApi().getServerId());
+
+ pipeline.sadd("proxy:" + RedisBungeeAPI.getRedisBungeeApi().getServerId() + ":usersOnline", connection.getUniqueId().toString());
+ pipeline.hmset("player:" + connection.getUniqueId().toString(), playerData);
+
+ if (fireEvent) {
+ pipeline.publish("redisbungee-data", gson.toJson(new DataManager.DataManagerMessage(
+ connection.getUniqueId(), RedisBungeeAPI.getRedisBungeeApi().getServerId(), DataManager.DataManagerMessage.Action.JOIN,
+ new DataManager.LoginPayload(connection.getAddress().getAddress()))));
+ }
+ }
+
+
+}
diff --git a/RedisBungee-Bungee/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java b/RedisBungee-Bungee/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java
new file mode 100644
index 0000000..ac17a19
--- /dev/null
+++ b/RedisBungee-Bungee/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java
@@ -0,0 +1,135 @@
+package com.imaginarycode.minecraft.redisbungee;
+
+import com.imaginarycode.minecraft.redisbungee.internal.AbstractRedisBungeeListener;
+import com.imaginarycode.minecraft.redisbungee.internal.DataManager;
+import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
+import com.imaginarycode.minecraft.redisbungee.events.bungee.PubSubMessageEvent;
+import com.imaginarycode.minecraft.redisbungee.internal.RedisUtil;
+import com.imaginarycode.minecraft.redisbungee.internal.util.RedisCallable;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.event.*;
+import net.md_5.bungee.api.plugin.Listener;
+import net.md_5.bungee.api.plugin.Plugin;
+import net.md_5.bungee.event.EventHandler;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.Pipeline;
+
+import java.net.InetAddress;
+import java.util.List;
+
+public class RedisBungeeListener extends AbstractRedisBungeeListener implements Listener {
+
+
+ public RedisBungeeListener(RedisBungeePlugin> plugin, List exemptAddresses) {
+ super(plugin, exemptAddresses);
+ }
+
+ @Override
+ @EventHandler
+ public void onLogin(LoginEvent event) {
+ event.registerIntent((Plugin) plugin);
+ plugin.executeAsync(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.isOnlineMode()) {
+ ProxiedPlayer player = (ProxiedPlayer) plugin.getPlayer(event.getConnection().getName());
+
+ if (player != null) {
+ event.setCancelled(true);
+ // TODO: Make it accept a BaseComponent[] like everything else.
+ event.setCancelReason(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(ALREADY_LOGGED_IN);
+ return null;
+ }
+ }
+ return null;
+ } finally {
+ event.completeIntent((Plugin) plugin);
+ }
+ }
+ });
+ }
+
+ @Override
+ @EventHandler
+ public void onPostLogin(PostLoginEvent event) {
+ plugin.executeAsync(new RedisCallable(plugin) {
+ @Override
+ protected Void call(Jedis jedis) {
+ // this code was moved out from login event due being async..
+ // and it can be cancelled but it will show as false in redis-bungee
+ // which will register the player into the redis database.
+ Pipeline pipeline = jedis.pipelined();
+ plugin.getUuidTranslator().persistInfo(event.getPlayer().getName(), event.getPlayer().getUniqueId(), pipeline);
+ RBUtils.createPlayer(event.getPlayer(), pipeline, false);
+ pipeline.sync();
+ // the end of moved code.
+
+ jedis.publish("redisbungee-data", gson.toJson(new DataManager.DataManagerMessage(
+ event.getPlayer().getUniqueId(), plugin.getApi().getServerId(), DataManager.DataManagerMessage.Action.JOIN,
+ new DataManager.LoginPayload(event.getPlayer().getAddress().getAddress()))));
+ return null;
+ }
+ });
+ }
+
+ @Override
+ @EventHandler
+ public void onPlayerDisconnect(PlayerDisconnectEvent event) {
+ plugin.executeAsync(new RedisCallable(plugin) {
+ @Override
+ protected Void call(Jedis jedis) {
+ Pipeline pipeline = jedis.pipelined();
+ RedisUtil.cleanUpPlayer(event.getPlayer().getUniqueId().toString(), pipeline);
+ pipeline.sync();
+ return null;
+ }
+ });
+
+ }
+
+ @Override
+ @EventHandler
+ public void onServerChange(ServerConnectedEvent event) {
+
+ }
+
+ @Override
+ @EventHandler
+ public void onPing(ProxyPingEvent event) {
+
+ }
+
+ @Override
+ @EventHandler
+ public void onPluginMessage(PluginMessageEvent event) {
+
+ }
+
+ @Override
+ @EventHandler
+ public void onPubSubMessage(PubSubMessageEvent event) {
+ if (event.getChannel().equals("redisbungee-allservers") || event.getChannel().equals("redisbungee-" + plugin.getApi().getServerId())) {
+ String message = event.getMessage();
+ if (message.startsWith("/"))
+ message = message.substring(1);
+ plugin.logInfo("Invoking command via PubSub: /" + message);
+ plugin.executeProxyCommand(message);
+ }
+ }
+}
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java b/RedisBungee-Bungee/src/main/java/com/imaginarycode/minecraft/redisbungee/events/bungee/PubSubMessageEvent.java
similarity index 69%
rename from src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java
rename to RedisBungee-Bungee/src/main/java/com/imaginarycode/minecraft/redisbungee/events/bungee/PubSubMessageEvent.java
index 967f31e..5eabc57 100644
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java
+++ b/RedisBungee-Bungee/src/main/java/com/imaginarycode/minecraft/redisbungee/events/bungee/PubSubMessageEvent.java
@@ -1,7 +1,5 @@
-package com.imaginarycode.minecraft.redisbungee.events;
+package com.imaginarycode.minecraft.redisbungee.events.bungee;
-import lombok.RequiredArgsConstructor;
-import lombok.ToString;
import net.md_5.bungee.api.plugin.Event;
/**
@@ -11,12 +9,16 @@ import net.md_5.bungee.api.plugin.Event;
*
* @since 0.2.6
*/
-@RequiredArgsConstructor
-@ToString
+
public class PubSubMessageEvent extends Event {
private final String channel;
private final String message;
+ public PubSubMessageEvent(String channel, String message) {
+ this.channel = channel;
+ this.message = message;
+ }
+
public String getChannel() {
return channel;
}
diff --git a/pom.xml b/pom.xml
index 91b3965..939f3e1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,87 +6,34 @@
com.imaginarycode.minecraft
RedisBungee
+ pom
0.7.0-SNAPSHOT
-
-
-
-
- bungeecord-repo
- https://oss.sonatype.org/content/repositories/snapshots
-
-
-
-
-
- src/main/resources
- true
-
-
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.1
-
- 1.8
- 1.8
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 3.2.4
-
-
- package
-
- shade
-
-
-
-
- redis.clients.jedis
- com.imaginarycode.minecraft.redisbungee.internal.jedis
-
-
-
- redis.clients.util
- com.imaginarycode.minecraft.redisbungee.internal.jedisutil
-
-
-
- org.apache.commons.pool
- com.imaginarycode.minecraft.redisbungee.internal.commonspool
-
-
-
- com.squareup.okhttp
- com.imaginarycode.minecraft.redisbungee.internal.okhttp
-
-
-
- okio
- com.imaginarycode.minecraft.redisbungee.internal.okio
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 3.3.0
8
+ 8
+
+ RedisBungee-API
+ RedisBungee-Bungee
+
+
+
+
+ com.google.guava
+ guava
+ 31.1-jre
+ compile
+
redis.clients
jedis
@@ -99,19 +46,6 @@
2.11.1
compile
-
- net.md-5
- bungeecord-api
- 1.17-R0.1-SNAPSHOT
- jar
- provided
-
-
- org.projectlombok
- lombok
- 1.18.22
- provided
-
com.squareup.okhttp
okhttp
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java
deleted file mode 100644
index 3594848..0000000
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java
+++ /dev/null
@@ -1,595 +0,0 @@
-package com.imaginarycode.minecraft.redisbungee;
-
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.collect.*;
-import com.google.common.io.ByteStreams;
-import com.google.gson.Gson;
-import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
-import com.imaginarycode.minecraft.redisbungee.util.*;
-import com.imaginarycode.minecraft.redisbungee.util.uuid.NameFetcher;
-import com.imaginarycode.minecraft.redisbungee.util.uuid.UUIDFetcher;
-import com.imaginarycode.minecraft.redisbungee.util.uuid.UUIDTranslator;
-import com.squareup.okhttp.Dispatcher;
-import com.squareup.okhttp.OkHttpClient;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.NonNull;
-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.config.Configuration;
-import net.md_5.bungee.config.ConfigurationProvider;
-import net.md_5.bungee.config.YamlConfiguration;
-import redis.clients.jedis.*;
-import redis.clients.jedis.exceptions.JedisConnectionException;
-
-import java.io.*;
-import java.lang.reflect.Field;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.logging.Level;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
-/**
- * The RedisBungee plugin.
- *
- * The only function of interest is {@link #getApi()}, which deprecated now,
- * Please check {@link RedisBungeeAPI#getRedisBungeeApi()},
- *
- * which exposes some functions in this class.
- * but if you want old version support,
- * then you can use old method {@link #getApi()}
- *
- */
-public final class RedisBungee extends Plugin {
- @Getter
- private static Gson gson = new Gson();
- private static RedisBungeeAPI api;
- @Getter(AccessLevel.PACKAGE)
- private static PubSubListener psl = null;
- @Getter
- private JedisPool pool;
- @Getter
- private UUIDTranslator uuidTranslator;
- @Getter(AccessLevel.PACKAGE)
- private static RedisBungeeConfiguration configuration;
- @Getter
- private DataManager dataManager;
- @Getter
- private static OkHttpClient httpClient;
- private volatile List serverIds;
- private final AtomicInteger nagAboutServers = new AtomicInteger();
- private final AtomicInteger globalPlayerCount = new AtomicInteger();
- private Future> integrityCheck;
- private Future> heartbeatTask;
- private LuaManager.Script serverToPlayersScript;
- private LuaManager.Script getPlayerCountScript;
-
- private static final Object SERVER_TO_PLAYERS_KEY = new Object();
- private final Cache> serverToPlayersCache = CacheBuilder.newBuilder()
- .expireAfterWrite(5, TimeUnit.SECONDS)
- .build();
-
- /**
- * Fetch the {@link RedisBungeeAPI} object created on plugin start.
- *
- * @deprecated Please use {@link RedisBungeeAPI#getRedisBungeeApi()}
- *
- * @return the {@link RedisBungeeAPI} object instance.
- */
- @Deprecated
- public static RedisBungeeAPI getApi() {
- return api;
- }
-
- static PubSubListener getPubSubListener() {
- return psl;
- }
-
- final List getServerIds() {
- return serverIds;
- }
-
- private List getCurrentServerIds(boolean nag, boolean lagged) {
- try (Jedis jedis = pool.getResource()) {
- long time = getRedisTime(jedis.time());
- int nagTime = 0;
- if (nag) {
- nagTime = nagAboutServers.decrementAndGet();
- if (nagTime <= 0) {
- nagAboutServers.set(10);
- }
- }
- ImmutableList.Builder servers = ImmutableList.builder();
- Map heartbeats = jedis.hgetAll("heartbeats");
- for (Map.Entry entry : heartbeats.entrySet()) {
- try {
- long stamp = Long.parseLong(entry.getValue());
- if (lagged ? time >= stamp + 30 : time <= stamp + 30)
- servers.add(entry.getKey());
- else if (nag && nagTime <= 0) {
- getLogger().warning(entry.getKey() + " is " + (time - stamp) + " seconds behind! (Time not synchronized or server down?) and was removed from heartbeat.");
- jedis.hdel("heartbeats", entry.getKey());
- }
- } catch (NumberFormatException ignored) {
- }
- }
- return servers.build();
- } catch (JedisConnectionException e) {
- getLogger().log(Level.SEVERE, "Unable to fetch server IDs", e);
- return Collections.singletonList(configuration.getServerId());
- }
- }
-
- public Set getPlayersOnProxy(String server) {
- checkArgument(getServerIds().contains(server), server + " is not a valid proxy ID");
- try (Jedis jedis = pool.getResource()) {
- Set users = jedis.smembers("proxy:" + server + ":usersOnline");
- ImmutableSet.Builder builder = ImmutableSet.builder();
- for (String user : users) {
- builder.add(UUID.fromString(user));
- }
- return builder.build();
- }
- }
-
- final Multimap serversToPlayers() {
- try {
- return serverToPlayersCache.get(SERVER_TO_PLAYERS_KEY, new Callable>() {
- @Override
- public Multimap call() throws Exception {
- Collection data = (Collection) serverToPlayersScript.eval(ImmutableList.of(), getServerIds());
-
- ImmutableMultimap.Builder builder = ImmutableMultimap.builder();
- String key = null;
- for (String s : data) {
- if (key == null) {
- key = s;
- continue;
- }
-
- builder.put(key, UUID.fromString(s));
- key = null;
- }
-
- return builder.build();
- }
- });
- } catch (ExecutionException e) {
- throw new RuntimeException(e);
- }
- }
-
- final int getCount() {
- return globalPlayerCount.get();
- }
-
- final int getCurrentCount() {
- Long count = (Long) getPlayerCountScript.eval(ImmutableList.of(), ImmutableList.of());
- return count.intValue();
- }
-
- private Set getLocalPlayersAsUuidStrings() {
- ImmutableSet.Builder builder = ImmutableSet.builder();
- for (ProxiedPlayer player : getProxy().getPlayers()) {
- builder.add(player.getUniqueId().toString());
- }
- return builder.build();
- }
-
- final Set getPlayers() {
- ImmutableSet.Builder setBuilder = ImmutableSet.builder();
- if (pool != null) {
- try (Jedis rsc = pool.getResource()) {
- List keys = new ArrayList<>();
- for (String i : getServerIds()) {
- keys.add("proxy:" + i + ":usersOnline");
- }
- if (!keys.isEmpty()) {
- Set users = rsc.sunion(keys.toArray(new String[keys.size()]));
- if (users != null && !users.isEmpty()) {
- for (String user : users) {
- try {
- setBuilder = setBuilder.add(UUID.fromString(user));
- } catch (IllegalArgumentException ignored) {
- }
- }
- }
- }
- } catch (JedisConnectionException e) {
- // Redis server has disappeared!
- getLogger().log(Level.SEVERE, "Unable to get connection from pool - did your Redis server go away?", e);
- throw new RuntimeException("Unable to get all players online", e);
- }
- }
- return setBuilder.build();
- }
-
- final void sendProxyCommand(@NonNull String proxyId, @NonNull String command) {
- checkArgument(getServerIds().contains(proxyId) || proxyId.equals("allservers"), "proxyId is invalid");
- sendChannelMessage("redisbungee-" + proxyId, command);
- }
-
- final void sendChannelMessage(String channel, String message) {
- try (Jedis jedis = pool.getResource()) {
- jedis.publish(channel, message);
- } catch (JedisConnectionException e) {
- // Redis server has disappeared!
- getLogger().log(Level.SEVERE, "Unable to get connection from pool - did your Redis server go away?", e);
- throw new RuntimeException("Unable to publish channel message", e);
- }
- }
-
- private long getRedisTime(List timeRes) {
- return Long.parseLong(timeRes.get(0));
- }
-
- @Override
- public void onEnable() {
- ThreadFactory factory = ((ThreadPoolExecutor) getExecutorService()).getThreadFactory();
- ScheduledExecutorService service = Executors.newScheduledThreadPool(24, factory);
- try {
- Field field = Plugin.class.getDeclaredField("service");
- field.setAccessible(true);
- ExecutorService builtinService = (ExecutorService) field.get(this);
- field.set(this, service);
- builtinService.shutdownNow();
- } catch (IllegalAccessException | NoSuchFieldException e) {
- getLogger().log(Level.WARNING, "Can't replace BungeeCord thread pool with our own");
- getLogger().log(Level.INFO, "skipping replacement.....");
- }
- try {
- loadConfig();
- } catch (IOException e) {
- throw new RuntimeException("Unable to load/save config", e);
- } catch (JedisConnectionException e) {
- throw new RuntimeException("Unable to connect to your Redis server!", e);
- }
- if (pool != null) {
- try (Jedis tmpRsc = pool.getResource()) {
- // This is more portable than INFO
- String info = tmpRsc.info();
- for (String s : info.split("\r\n")) {
- if (s.startsWith("redis_version:")) {
- String version = s.split(":")[1];
- getLogger().info(version + " <- redis version");
- if (!RedisUtil.isRedisVersionRight(version)) {
- getLogger().warning("Your version of Redis (" + version + ") is not at least version 6.0 RedisBungee requires a newer version of Redis.");
- throw new RuntimeException("Unsupported Redis version detected");
- } else {
- LuaManager manager = new LuaManager(this);
- serverToPlayersScript = manager.createScript(IOUtil.readInputStreamAsString(getResourceAsStream("lua/server_to_players.lua")));
- getPlayerCountScript = manager.createScript(IOUtil.readInputStreamAsString(getResourceAsStream("lua/get_player_count.lua")));
- }
- break;
- }
- }
-
- tmpRsc.hset("heartbeats", configuration.getServerId(), tmpRsc.time().get(0));
-
- long uuidCacheSize = tmpRsc.hlen("uuid-cache");
- if (uuidCacheSize > 750000) {
- getLogger().info("Looks like you have a really big UUID cache! Run https://www.spigotmc.org/resources/redisbungeecleaner.8505/ as soon as possible.");
- }
- }
- serverIds = getCurrentServerIds(true, false);
- uuidTranslator = new UUIDTranslator(this);
- heartbeatTask = service.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try (Jedis rsc = pool.getResource()) {
- long redisTime = getRedisTime(rsc.time());
- rsc.hset("heartbeats", configuration.getServerId(), String.valueOf(redisTime));
- } catch (JedisConnectionException e) {
- // Redis server has disappeared!
- getLogger().log(Level.SEVERE, "Unable to update heartbeat - did your Redis server go away?", e);
- return;
- }
- try {
- serverIds = getCurrentServerIds(true, false);
- globalPlayerCount.set(getCurrentCount());
- } catch (Throwable e) {
- getLogger().log(Level.SEVERE, "Unable to update data - did your Redis server go away?", e);
- }
- }
- }, 0, 3, TimeUnit.SECONDS);
- dataManager = new DataManager(this);
- if (configuration.isRegisterBungeeCommands()) {
- getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.GlistCommand(this));
- getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.FindCommand(this));
- getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.LastSeenCommand(this));
- getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.IpCommand(this));
- }
- getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.SendToAll(this));
- getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.ServerId(this));
- getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.ServerIds());
- getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.PlayerProxyCommand(this));
- getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.PlistCommand(this));
- getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.DebugCommand(this));
- api = new RedisBungeeAPI(this);
- getProxy().getPluginManager().registerListener(this, new RedisBungeeListener(this, configuration.getExemptAddresses()));
- getProxy().getPluginManager().registerListener(this, dataManager);
- psl = new PubSubListener();
- getProxy().getScheduler().runAsync(this, psl);
- integrityCheck = service.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- try (Jedis tmpRsc = pool.getResource()) {
- Set players = getLocalPlayersAsUuidStrings();
- Set playersInRedis = tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
- List lagged = getCurrentServerIds(false, true);
-
- // Clean up lagged players.
- for (String s : lagged) {
- Set laggedPlayers = tmpRsc.smembers("proxy:" + s + ":usersOnline");
- tmpRsc.del("proxy:" + s + ":usersOnline");
- if (!laggedPlayers.isEmpty()) {
- getLogger().info("Cleaning up lagged proxy " + s + " (" + laggedPlayers.size() + " players)...");
- for (String laggedPlayer : laggedPlayers) {
- RedisUtil.cleanUpPlayer(laggedPlayer, tmpRsc);
- }
- }
- }
-
- Set absentLocally = new HashSet<>(playersInRedis);
- absentLocally.removeAll(players);
- Set absentInRedis = new HashSet<>(players);
- absentInRedis.removeAll(playersInRedis);
-
- for (String member : absentLocally) {
- boolean found = false;
- for (String proxyId : getServerIds()) {
- if (proxyId.equals(configuration.getServerId())) continue;
- if (tmpRsc.sismember("proxy:" + proxyId + ":usersOnline", member)) {
- // Just clean up the set.
- found = true;
- break;
- }
- }
- if (!found) {
- RedisUtil.cleanUpPlayer(member, tmpRsc);
- getLogger().warning("Player found in set that was not found locally and globally: " + member);
- } else {
- tmpRsc.srem("proxy:" + configuration.getServerId() + ":usersOnline", member);
- getLogger().warning("Player found in set that was not found locally, but is on another proxy: " + member);
- }
- }
-
- Pipeline pipeline = tmpRsc.pipelined();
-
- for (String player : absentInRedis) {
- // Player not online according to Redis but not BungeeCord.
- getLogger().warning("Player " + player + " is on the proxy but not in Redis.");
-
- ProxiedPlayer proxiedPlayer = ProxyServer.getInstance().getPlayer(UUID.fromString(player));
- if (proxiedPlayer == null)
- continue; // We'll deal with it later.
-
- RedisUtil.createPlayer(proxiedPlayer, pipeline, true);
- }
-
- pipeline.sync();
- } catch (Throwable e) {
- getLogger().log(Level.SEVERE, "Unable to fix up stored player data", e);
- }
- }
- }, 0, 1, TimeUnit.MINUTES);
- }
- getProxy().registerChannel("legacy:redisbungee");
- getProxy().registerChannel("RedisBungee");
- }
-
- @Override
- public void onDisable() {
- if (pool != null) {
- // Poison the PubSub listener
- psl.poison();
- integrityCheck.cancel(true);
- heartbeatTask.cancel(true);
- getProxy().getPluginManager().unregisterListeners(this);
-
- try (Jedis tmpRsc = pool.getResource()) {
- tmpRsc.hdel("heartbeats", configuration.getServerId());
- if (tmpRsc.scard("proxy:" + configuration.getServerId() + ":usersOnline") > 0) {
- Set players = tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
- for (String member : players)
- RedisUtil.cleanUpPlayer(member, tmpRsc);
- }
- }
-
- pool.destroy();
- }
- }
-
- private void loadConfig() throws IOException, JedisConnectionException {
- if (!getDataFolder().exists()) {
- getDataFolder().mkdir();
- }
-
- File file = new File(getDataFolder(), "config.yml");
-
- if (!file.exists()) {
- file.createNewFile();
- try (InputStream in = getResourceAsStream("example_config.yml");
- OutputStream out = new FileOutputStream(file)) {
- ByteStreams.copy(in, out);
- }
- }
-
- final Configuration configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(file);
-
- final String redisServer = configuration.getString("redis-server", "localhost");
- final int redisPort = configuration.getInt("redis-port", 6379);
- final boolean useSSL = configuration.getBoolean("useSSL");
- String redisPassword = configuration.getString("redis-password");
- String serverId = configuration.getString("server-id");
- final String randomUUID = UUID.randomUUID().toString();
-
- if (redisPassword != null && (redisPassword.isEmpty() || redisPassword.equals("none"))) {
- redisPassword = null;
- }
-
- // Configuration sanity checks.
- if (serverId == null || serverId.isEmpty()) {
- /*
- * this check causes the config comments to disappear somehow
- * I think due snake yaml limitations so as todo: write our own yaml parser?
- */
- String genId = UUID.randomUUID().toString();
- getLogger().info("Generated server id " + genId + " and saving it to config.");
- configuration.set("server-id", genId);
- ConfigurationProvider.getProvider(YamlConfiguration.class).save(configuration, new File(getDataFolder(), "config.yml"));
- } else {
- getLogger().info("Loaded server id " + serverId + '.');
- }
-
- if (configuration.getBoolean("use-random-id-string", false)) {
- serverId = configuration.getString("server-id") + "-" + randomUUID;
- }
-
- if (redisServer != null && !redisServer.isEmpty()) {
- final String finalRedisPassword = redisPassword;
- FutureTask task = new FutureTask<>(new Callable() {
- @Override
- public JedisPool call() throws Exception {
- // Create the pool...
- JedisPoolConfig config = new JedisPoolConfig();
- config.setMaxTotal(configuration.getInt("max-redis-connections", 8));
- return new JedisPool(config, redisServer, redisPort, 0, finalRedisPassword, useSSL);
- }
- });
-
- getProxy().getScheduler().runAsync(this, task);
-
- try {
- pool = task.get();
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException("Unable to create Redis pool", e);
- }
-
- // Test the connection
- try (Jedis rsc = pool.getResource()) {
- rsc.ping();
- // If that worked, now we can check for an existing, alive Bungee:
- File crashFile = new File(getDataFolder(), "restarted_from_crash.txt");
- if (crashFile.exists()) {
- crashFile.delete();
- } else if (rsc.hexists("heartbeats", serverId)) {
- try {
- long value = Long.parseLong(rsc.hget("heartbeats", serverId));
- long redisTime = getRedisTime(rsc.time());
- if (redisTime < value + 20) {
- getLogger().severe("You have launched a possible impostor BungeeCord instance. Another instance is already running.");
- getLogger().severe("For data consistency reasons, RedisBungee will now disable itself.");
- getLogger().severe("If this instance is coming up from a crash, create a file in your RedisBungee plugins directory with the name 'restarted_from_crash.txt' and RedisBungee will not perform this check.");
- throw new RuntimeException("Possible impostor instance!");
- }
- } catch (NumberFormatException ignored) {
- }
- }
-
- FutureTask task2 = new FutureTask<>(new Callable() {
- @Override
- public Void call() throws Exception {
- httpClient = new OkHttpClient();
- Dispatcher dispatcher = new Dispatcher(getExecutorService());
- httpClient.setDispatcher(dispatcher);
- NameFetcher.setHttpClient(httpClient);
- UUIDFetcher.setHttpClient(httpClient);
- RedisBungee.configuration = new RedisBungeeConfiguration(RedisBungee.this.getPool(), configuration, randomUUID);
- return null;
- }
- });
-
- getProxy().getScheduler().runAsync(this, task2);
-
- try {
- task2.get();
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException("Unable to create HTTP client", e);
- }
-
- getLogger().log(Level.INFO, "Successfully connected to Redis.");
- } catch (JedisConnectionException e) {
- pool.destroy();
- pool = null;
- throw e;
- }
- } else {
- throw new RuntimeException("No redis server specified!");
- }
- }
-
- @NoArgsConstructor(access = AccessLevel.PRIVATE)
- class PubSubListener implements Runnable {
- private JedisPubSubHandler jpsh;
-
- private Set addedChannels = new HashSet();
-
- @Override
- public void run() {
- boolean broken = false;
- try (Jedis rsc = pool.getResource()) {
- try {
- jpsh = new JedisPubSubHandler();
- addedChannels.add("redisbungee-" + configuration.getServerId());
- addedChannels.add("redisbungee-allservers");
- addedChannels.add("redisbungee-data");
- rsc.subscribe(jpsh, addedChannels.toArray(new String[0]));
- } catch (Exception e) {
- // FIXME: Extremely ugly hack
- // Attempt to unsubscribe this instance and try again.
- getLogger().log(Level.INFO, "PubSub error, attempting to recover.", e);
- try {
- jpsh.unsubscribe();
- } catch (Exception e1) {
- /* This may fail with
- - java.net.SocketException: Broken pipe
- - redis.clients.jedis.exceptions.JedisConnectionException: JedisPubSub was not subscribed to a Jedis instance
- */
- }
- broken = true;
- }
- } catch (JedisConnectionException e) {
- getLogger().log(Level.INFO, "PubSub error, attempting to recover in 5 secs.");
- getProxy().getScheduler().schedule(RedisBungee.this, PubSubListener.this, 5, TimeUnit.SECONDS);
- }
-
- if (broken) {
- run();
- }
- }
-
- public void addChannel(String... channel) {
- addedChannels.addAll(Arrays.asList(channel));
- jpsh.subscribe(channel);
- }
-
- public void removeChannel(String... channel) {
- addedChannels.removeAll(Arrays.asList(channel));
- jpsh.unsubscribe(channel);
- }
-
- public void poison() {
- addedChannels.clear();
- jpsh.unsubscribe();
- }
- }
-
- private class JedisPubSubHandler extends JedisPubSub {
- @Override
- public void onMessage(final String s, final String s2) {
- if (s2.trim().length() == 0) return;
- getProxy().getScheduler().runAsync(RedisBungee.this, new Runnable() {
- @Override
- public void run() {
- getProxy().getPluginManager().callEvent(new PubSubMessageEvent(s, s2));
- }
- });
- }
- }
-}
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSender.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSender.java
deleted file mode 100644
index c3e778e..0000000
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSender.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.imaginarycode.minecraft.redisbungee;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import net.md_5.bungee.api.CommandSender;
-import net.md_5.bungee.api.chat.BaseComponent;
-
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * This class is the CommandSender that RedisBungee uses to dispatch commands to BungeeCord.
- *
- * It inherits all permissions of the console command sender. Sending messages and modifying permissions are no-ops.
- *
- * @author tuxed
- * @since 0.2.3
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class RedisBungeeCommandSender implements CommandSender {
- static final RedisBungeeCommandSender instance = new RedisBungeeCommandSender();
-
- @Override
- public String getName() {
- return "RedisBungee";
- }
-
- @Override
- public void sendMessage(String s) {
- // no-op
- }
-
- @Override
- public void sendMessages(String... strings) {
- // no-op
- }
-
- @Override
- public void sendMessage(BaseComponent... baseComponents) {
- // no-op
- }
-
- @Override
- public void sendMessage(BaseComponent baseComponent) {
- // no-op
- }
-
- @Override
- public Collection getGroups() {
- return Collections.emptySet();
- }
-
- @Override
- public void addGroups(String... strings) {
- // no-op
- }
-
- @Override
- public void removeGroups(String... strings) {
- // no-op
- }
-
- @Override
- public boolean hasPermission(String s) {
- return true;
- }
-
- @Override
- public void setPermission(String s, boolean b) {
- // no-op
- }
-
- @Override
- public Collection getPermissions() {
- return Collections.emptySet();
- }
-}
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommands.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommands.java
deleted file mode 100644
index 3ccc507..0000000
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommands.java
+++ /dev/null
@@ -1,356 +0,0 @@
-package com.imaginarycode.minecraft.redisbungee;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import net.md_5.bungee.api.ChatColor;
-import net.md_5.bungee.api.CommandSender;
-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.plugin.Command;
-
-import java.net.InetAddress;
-import java.text.SimpleDateFormat;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.UUID;
-
-/**
- * This class contains subclasses that are used for the commands RedisBungee overrides or includes: /glist, /find and /lastseen.
- *
- * All classes use the {@link RedisBungeeAPI}.
- *
- * @author tuxed
- * @since 0.2.3
- */
-class RedisBungeeCommands {
- private static final BaseComponent[] NO_PLAYER_SPECIFIED =
- new ComponentBuilder("You must specify a player name.").color(ChatColor.RED).create();
- private static final BaseComponent[] PLAYER_NOT_FOUND =
- new ComponentBuilder("No such player found.").color(ChatColor.RED).create();
- private static final BaseComponent[] NO_COMMAND_SPECIFIED =
- new ComponentBuilder("You must specify a command to be run.").color(ChatColor.RED).create();
-
- private static String playerPlural(int num) {
- return num == 1 ? num + " player is" : num + " players are";
- }
-
- public static class GlistCommand extends Command {
- private final RedisBungee plugin;
-
- GlistCommand(RedisBungee plugin) {
- super("glist", "bungeecord.command.list", "redisbungee", "rglist");
- this.plugin = plugin;
- }
-
- @Override
- public void execute(final CommandSender sender, final String[] args) {
- plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
- @Override
- public void run() {
- int count = RedisBungee.getApi().getPlayerCount();
- BaseComponent[] playersOnline = new ComponentBuilder("").color(ChatColor.YELLOW)
- .append(playerPlural(count) + " currently online.").create();
- if (args.length > 0 && args[0].equals("showall")) {
- Multimap serverToPlayers = RedisBungee.getApi().getServerToPlayers();
- Multimap human = HashMultimap.create();
- for (Map.Entry entry : serverToPlayers.entries()) {
- human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false));
- }
- for (String server : new TreeSet<>(serverToPlayers.keySet())) {
- TextComponent serverName = new TextComponent();
- serverName.setColor(ChatColor.GREEN);
- serverName.setText("[" + server + "] ");
- TextComponent serverCount = new TextComponent();
- serverCount.setColor(ChatColor.YELLOW);
- serverCount.setText("(" + serverToPlayers.get(server).size() + "): ");
- TextComponent serverPlayers = new TextComponent();
- serverPlayers.setColor(ChatColor.WHITE);
- serverPlayers.setText(Joiner.on(", ").join(human.get(server)));
- sender.sendMessage(serverName, serverCount, serverPlayers);
- }
- sender.sendMessage(playersOnline);
- } else {
- sender.sendMessage(playersOnline);
- sender.sendMessage(new ComponentBuilder("To see all players online, use /glist showall.").color(ChatColor.YELLOW).create());
- }
- }
- });
- }
- }
-
- public static class FindCommand extends Command {
- private final RedisBungee plugin;
-
- FindCommand(RedisBungee plugin) {
- super("find", "bungeecord.command.find", "rfind");
- this.plugin = plugin;
- }
-
- @Override
- public void execute(final CommandSender sender, final String[] args) {
- plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
- @Override
- public void run() {
- if (args.length > 0) {
- UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
- if (uuid == null) {
- sender.sendMessage(PLAYER_NOT_FOUND);
- return;
- }
- ServerInfo si = RedisBungee.getApi().getServerFor(uuid);
- if (si != null) {
- TextComponent message = new TextComponent();
- message.setColor(ChatColor.BLUE);
- message.setText(args[0] + " is on " + si.getName() + ".");
- sender.sendMessage(message);
- } else {
- sender.sendMessage(PLAYER_NOT_FOUND);
- }
- } else {
- sender.sendMessage(NO_PLAYER_SPECIFIED);
- }
- }
- });
- }
- }
-
- public static class LastSeenCommand extends Command {
- private final RedisBungee plugin;
-
- LastSeenCommand(RedisBungee plugin) {
- super("lastseen", "redisbungee.command.lastseen", "rlastseen");
- this.plugin = plugin;
- }
-
- @Override
- public void execute(final CommandSender sender, final String[] args) {
- plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
- @Override
- public void run() {
- if (args.length > 0) {
- UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
- if (uuid == null) {
- sender.sendMessage(PLAYER_NOT_FOUND);
- return;
- }
- long secs = RedisBungee.getApi().getLastOnline(uuid);
- TextComponent message = new TextComponent();
- if (secs == 0) {
- message.setColor(ChatColor.GREEN);
- message.setText(args[0] + " is currently online.");
- } else if (secs != -1) {
- message.setColor(ChatColor.BLUE);
- message.setText(args[0] + " was last online on " + new SimpleDateFormat().format(secs) + ".");
- } else {
- message.setColor(ChatColor.RED);
- message.setText(args[0] + " has never been online.");
- }
- sender.sendMessage(message);
- } else {
- sender.sendMessage(NO_PLAYER_SPECIFIED);
- }
- }
- });
- }
- }
-
- public static class IpCommand extends Command {
- private final RedisBungee plugin;
-
- IpCommand(RedisBungee plugin) {
- super("ip", "redisbungee.command.ip", "playerip", "rip", "rplayerip");
- this.plugin = plugin;
- }
-
- @Override
- public void execute(final CommandSender sender, final String[] args) {
- plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
- @Override
- public void run() {
- if (args.length > 0) {
- UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
- if (uuid == null) {
- sender.sendMessage(PLAYER_NOT_FOUND);
- return;
- }
- InetAddress ia = RedisBungee.getApi().getPlayerIp(uuid);
- if (ia != null) {
- TextComponent message = new TextComponent();
- message.setColor(ChatColor.GREEN);
- message.setText(args[0] + " is connected from " + ia.toString() + ".");
- sender.sendMessage(message);
- } else {
- sender.sendMessage(PLAYER_NOT_FOUND);
- }
- } else {
- sender.sendMessage(NO_PLAYER_SPECIFIED);
- }
- }
- });
- }
- }
-
- public static class PlayerProxyCommand extends Command {
- private final RedisBungee plugin;
-
- PlayerProxyCommand(RedisBungee plugin) {
- super("pproxy", "redisbungee.command.pproxy");
- this.plugin = plugin;
- }
-
- @Override
- public void execute(final CommandSender sender, final String[] args) {
- plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
- @Override
- public void run() {
- if (args.length > 0) {
- UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
- if (uuid == null) {
- sender.sendMessage(PLAYER_NOT_FOUND);
- return;
- }
- String proxy = RedisBungee.getApi().getProxy(uuid);
- if (proxy != null) {
- TextComponent message = new TextComponent();
- message.setColor(ChatColor.GREEN);
- message.setText(args[0] + " is connected to " + proxy + ".");
- sender.sendMessage(message);
- } else {
- sender.sendMessage(PLAYER_NOT_FOUND);
- }
- } else {
- sender.sendMessage(NO_PLAYER_SPECIFIED);
- }
- }
- });
- }
- }
-
- public static class SendToAll extends Command {
- private final RedisBungee plugin;
-
- SendToAll(RedisBungee plugin) {
- super("sendtoall", "redisbungee.command.sendtoall", "rsendtoall");
- this.plugin = plugin;
- }
-
- @Override
- public void execute(CommandSender sender, String[] args) {
- if (args.length > 0) {
- String command = Joiner.on(" ").skipNulls().join(args);
- RedisBungee.getApi().sendProxyCommand(command);
- TextComponent message = new TextComponent();
- message.setColor(ChatColor.GREEN);
- message.setText("Sent the command /" + command + " to all proxies.");
- sender.sendMessage(message);
- } else {
- sender.sendMessage(NO_COMMAND_SPECIFIED);
- }
- }
- }
-
- public static class ServerId extends Command {
- private final RedisBungee plugin;
-
- ServerId(RedisBungee plugin) {
- super("serverid", "redisbungee.command.serverid", "rserverid");
- this.plugin = plugin;
- }
-
- @Override
- public void execute(CommandSender sender, String[] args) {
- TextComponent textComponent = new TextComponent();
- textComponent.setText("You are on " + RedisBungee.getApi().getServerId() + ".");
- textComponent.setColor(ChatColor.YELLOW);
- sender.sendMessage(textComponent);
- }
- }
-
- public static class ServerIds extends Command {
- public ServerIds() {
- super("serverids", "redisbungee.command.serverids");
- }
-
- @Override
- public void execute(CommandSender sender, String[] strings) {
- TextComponent textComponent = new TextComponent();
- textComponent.setText("All server IDs: " + Joiner.on(", ").join(RedisBungee.getApi().getAllServers()));
- textComponent.setColor(ChatColor.YELLOW);
- sender.sendMessage(textComponent);
- }
- }
-
- public static class PlistCommand extends Command {
- private final RedisBungee plugin;
-
- PlistCommand(RedisBungee plugin) {
- super("plist", "redisbungee.command.plist", "rplist");
- this.plugin = plugin;
- }
-
- @Override
- public void execute(final CommandSender sender, final String[] args) {
- plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
- @Override
- public void run() {
- String proxy = args.length >= 1 ? args[0] : RedisBungee.getConfiguration().getServerId();
- if (!plugin.getServerIds().contains(proxy)) {
- sender.sendMessage(new ComponentBuilder(proxy + " is not a valid proxy. See /serverids for valid proxies.").color(ChatColor.RED).create());
- return;
- }
- Set players = RedisBungee.getApi().getPlayersOnProxy(proxy);
- BaseComponent[] playersOnline = new ComponentBuilder("").color(ChatColor.YELLOW)
- .append(playerPlural(players.size()) + " currently on proxy " + proxy + ".").create();
- if (args.length >= 2 && args[1].equals("showall")) {
- Multimap serverToPlayers = RedisBungee.getApi().getServerToPlayers();
- Multimap human = HashMultimap.create();
- for (Map.Entry entry : serverToPlayers.entries()) {
- if (players.contains(entry.getValue())) {
- human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false));
- }
- }
- for (String server : new TreeSet<>(human.keySet())) {
- TextComponent serverName = new TextComponent();
- serverName.setColor(ChatColor.RED);
- serverName.setText("[" + server + "] ");
- TextComponent serverCount = new TextComponent();
- serverCount.setColor(ChatColor.YELLOW);
- serverCount.setText("(" + human.get(server).size() + "): ");
- TextComponent serverPlayers = new TextComponent();
- serverPlayers.setColor(ChatColor.WHITE);
- serverPlayers.setText(Joiner.on(", ").join(human.get(server)));
- sender.sendMessage(serverName, serverCount, serverPlayers);
- }
- sender.sendMessage(playersOnline);
- } else {
- sender.sendMessage(playersOnline);
- sender.sendMessage(new ComponentBuilder("To see all players online, use /plist " + proxy + " showall.").color(ChatColor.YELLOW).create());
- }
- }
- });
- }
- }
-
- public static class DebugCommand extends Command {
- private final RedisBungee plugin;
-
- DebugCommand(RedisBungee plugin) {
- super("rdebug", "redisbungee.command.debug");
- this.plugin = plugin;
- }
-
- @Override
- public void execute(final CommandSender sender, final String[] args) {
- TextComponent poolActiveStat = new TextComponent("Currently active pool objects: " + plugin.getPool().getNumActive());
- TextComponent poolIdleStat = new TextComponent("Currently idle pool objects: " + plugin.getPool().getNumIdle());
- TextComponent poolWaitingStat = new TextComponent("Waiting on free objects: " + plugin.getPool().getNumWaiters());
- sender.sendMessage(poolActiveStat);
- sender.sendMessage(poolIdleStat);
- sender.sendMessage(poolWaitingStat);
- }
- }
-}
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeConfiguration.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeConfiguration.java
deleted file mode 100644
index d5b68b1..0000000
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeConfiguration.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.imaginarycode.minecraft.redisbungee;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.net.InetAddresses;
-import lombok.Getter;
-import net.md_5.bungee.config.Configuration;
-import redis.clients.jedis.JedisPool;
-
-import java.net.InetAddress;
-import java.util.List;
-import java.util.UUID;
-
-public class RedisBungeeConfiguration {
- @Getter
- private final JedisPool pool;
- @Getter
- private final String serverId;
- @Getter
- private final boolean registerBungeeCommands;
- @Getter
- private final List exemptAddresses;
-
-
- public RedisBungeeConfiguration(JedisPool pool, Configuration configuration, String randomUUID) {
- this.pool = pool;
- if (configuration.getBoolean("use-random-id-string", false)) {
- this.serverId = configuration.getString("server-id") + "-" + randomUUID;
- } else {
- this.serverId = configuration.getString("server-id");
- }
-
- this.registerBungeeCommands = configuration.getBoolean("register-bungee-commands", true);
-
- List stringified = configuration.getStringList("exempt-ip-addresses");
- ImmutableList.Builder addressBuilder = ImmutableList.builder();
-
- for (String s : stringified) {
- addressBuilder.add(InetAddresses.forString(s));
- }
-
- this.exemptAddresses = addressBuilder.build();
- }
-
-}
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java
deleted file mode 100644
index 04f5ffc..0000000
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java
+++ /dev/null
@@ -1,291 +0,0 @@
-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.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(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(ALREADY_LOGGED_IN);
- return null;
- }
- }
- 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) {
- // this code was moved out from login event due being async..
- // and it can be cancelled but it will show as false in redis-bungee
- // which will register the player into the redis database.
- Pipeline pipeline = jedis.pipelined();
- plugin.getUuidTranslator().persistInfo(event.getPlayer().getName(), event.getPlayer().getUniqueId(), pipeline);
- RedisUtil.createPlayer(event.getPlayer(), pipeline, false);
- pipeline.sync();
- // the end of moved code.
-
- 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());
- }
-
- @SuppressWarnings("UnstableApiUsage")
- @EventHandler
- public void onPluginMessage(final PluginMessageEvent event) {
- if ((event.getTag().equals("legacy:redisbungee") || event.getTag().equals("RedisBungee")) && event.getSender() instanceof Server) {
- final String currentChannel = event.getTag();
- final byte[] data = Arrays.copyOf(event.getData(), event.getData().length);
- plugin.getProxy().getScheduler().runAsync(plugin, () -> {
- 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(currentChannel, 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());
- }
- }
-
- @SuppressWarnings("SameParameterValue")
- 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/java/com/imaginarycode/minecraft/redisbungee/RedisUtil.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisUtil.java
deleted file mode 100644
index c4fc059..0000000
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisUtil.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.imaginarycode.minecraft.redisbungee;
-
-import com.google.common.annotations.VisibleForTesting;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import net.md_5.bungee.api.connection.PendingConnection;
-import net.md_5.bungee.api.connection.ProxiedPlayer;
-import redis.clients.jedis.Jedis;
-import redis.clients.jedis.Pipeline;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-
-@VisibleForTesting
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class RedisUtil {
- protected static void createPlayer(ProxiedPlayer player, Pipeline pipeline, boolean fireEvent) {
- createPlayer(player.getPendingConnection(), pipeline, fireEvent);
- if (player.getServer() != null)
- pipeline.hset("player:" + player.getUniqueId().toString(), "server", player.getServer().getInfo().getName());
- }
-
- protected static void createPlayer(PendingConnection connection, Pipeline pipeline, boolean fireEvent) {
- Map playerData = new HashMap<>(4);
- playerData.put("online", "0");
- playerData.put("ip", connection.getAddress().getAddress().getHostAddress());
- playerData.put("proxy", RedisBungee.getConfiguration().getServerId());
-
- pipeline.sadd("proxy:" + RedisBungee.getApi().getServerId() + ":usersOnline", connection.getUniqueId().toString());
- pipeline.hmset("player:" + connection.getUniqueId().toString(), playerData);
-
- if (fireEvent) {
- pipeline.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
- connection.getUniqueId(), DataManager.DataManagerMessage.Action.JOIN,
- new DataManager.LoginPayload(connection.getAddress().getAddress()))));
- }
- }
-
- public static void cleanUpPlayer(String player, Jedis rsc) {
- rsc.srem("proxy:" + RedisBungee.getApi().getServerId() + ":usersOnline", player);
- rsc.hdel("player:" + player, "server", "ip", "proxy");
- long timestamp = System.currentTimeMillis();
- rsc.hset("player:" + player, "online", String.valueOf(timestamp));
- rsc.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
- UUID.fromString(player), DataManager.DataManagerMessage.Action.LEAVE,
- new DataManager.LogoutPayload(timestamp))));
- }
-
- public static void cleanUpPlayer(String player, Pipeline rsc) {
- rsc.srem("proxy:" + RedisBungee.getApi().getServerId() + ":usersOnline", player);
- rsc.hdel("player:" + player, "server", "ip", "proxy");
- long timestamp = System.currentTimeMillis();
- rsc.hset("player:" + player, "online", String.valueOf(timestamp));
- rsc.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
- UUID.fromString(player), DataManager.DataManagerMessage.Action.LEAVE,
- new DataManager.LogoutPayload(timestamp))));
- }
-
- public static boolean isRedisVersionRight(String redisVersion) {
- // Need to use >=6.2 to use Lua optimizations.
- String[] args = redisVersion.split("\\.");
- if (args.length < 2) {
- return false;
- }
- int major = Integer.parseInt(args[0]);
- int minor = Integer.parseInt(args[1]);
- return major >= 6 && minor >= 0;
- }
-
- // Ham1255: i am keeping this if some plugin uses this *IF*
- @Deprecated
- public static boolean canUseLua(String redisVersion) {
- return isRedisVersionRight(redisVersion);
- }
-}
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java
deleted file mode 100644
index 145b6d5..0000000
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.imaginarycode.minecraft.redisbungee.events;
-
-import lombok.ToString;
-import net.md_5.bungee.api.plugin.Event;
-
-import java.util.UUID;
-
-/**
- * This event is sent when a player connects to a new server. RedisBungee sends the event only when
- * the proxy the player has been connected to is different than the local proxy.
- *
- * This event corresponds to {@link net.md_5.bungee.api.event.ServerConnectedEvent}, and is fired
- * asynchronously.
- *
- * @since 0.3.4
- */
-@ToString
-public class PlayerChangedServerNetworkEvent extends Event {
- private final UUID uuid;
- private final String previousServer;
- private final String server;
-
- public PlayerChangedServerNetworkEvent(UUID uuid, String previousServer, String server) {
- this.uuid = uuid;
- this.previousServer = previousServer;
- this.server = server;
- }
-
- public UUID getUuid() {
- return uuid;
- }
-
- public String getServer() {
- return server;
- }
-
- public String getPreviousServer() {
- return previousServer;
- }
-}
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java
deleted file mode 100644
index aeb700b..0000000
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.imaginarycode.minecraft.redisbungee.events;
-
-import lombok.ToString;
-import net.md_5.bungee.api.plugin.Event;
-
-import java.util.UUID;
-
-/**
- * This event is sent when a player joins the network. RedisBungee sends the event only when
- * the proxy the player has been connected to is different than the local proxy.
- *
- * This event corresponds to {@link net.md_5.bungee.api.event.PostLoginEvent}, and is fired
- * asynchronously.
- *
- * @since 0.3.4
- */
-@ToString
-public class PlayerJoinedNetworkEvent extends Event {
- private final UUID uuid;
-
- public PlayerJoinedNetworkEvent(UUID uuid) {
- this.uuid = uuid;
- }
-
- public UUID getUuid() {
- return uuid;
- }
-}
diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java
deleted file mode 100644
index 23ded72..0000000
--- a/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.imaginarycode.minecraft.redisbungee.events;
-
-import lombok.ToString;
-import net.md_5.bungee.api.plugin.Event;
-
-import java.util.UUID;
-
-/**
- * This event is sent when a player disconnects. RedisBungee sends the event only when
- * the proxy the player has been connected to is different than the local proxy.
- *
- * This event corresponds to {@link net.md_5.bungee.api.event.PlayerDisconnectEvent}, and is fired
- * asynchronously.
- *
- * @since 0.3.4
- */
-@ToString
-public class PlayerLeftNetworkEvent extends Event {
- private final UUID uuid;
-
- public PlayerLeftNetworkEvent(UUID uuid) {
- this.uuid = uuid;
- }
-
- public UUID getUuid() {
- return uuid;
- }
-}
diff --git a/src/main/resources/example_config.yml b/src/main/resources/example_config.yml
deleted file mode 100644
index be0c1cd..0000000
--- a/src/main/resources/example_config.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-# RedisBungee configuration file.
-# PLEASE READ THE WIKI: https://github.com/Limework/RedisBungee/wiki
-
-# The Redis server you use.
-# Get Redis from http://redis.io/
-redis-server: 127.0.0.1
-redis-port: 6379
-# OPTIONAL: If your Redis server uses AUTH, set the password required.
-redis-password: ""
-# Maximum connections that will be maintained to the Redis server.
-# The default is 8. This setting should be left as-is unless you have some wildly
-# inefficient plugins or a lot of players.
-max-redis-connections: 8
-
-# since redis can support ssl by version 6 you can use ssl in redis bungee too!
-# you must disable this if redis version is under 6 you must disable this or connection wont work!!!
-useSSL: false
-
-# An identifier for this BungeeCord instance. Will randomly generate if leaving it blank.
-server-id: "test1"
-# Should use random string? if this is enabled the proxy id will be like this if server-id is test1: "test1-66cd2aeb-91f3-43a7-a106-e0307b098652"
-# or if id is limework-bungee it will be "limework-bungee-66cd2aeb-91f3-43a7-a106-e0307b098652"
-# this great for servers who run replicas in Kubernetes or any auto deploying replica service
-# and used for if proxy died in a kubernetes network and deleted then new proxy setup itself.
-use-random-id-string: false
-
-# Whether or not RedisBungee should install its version of regular BungeeCord commands.
-# Often, the RedisBungee commands are desired, but in some cases someone may wish to
-# override the commands using another plugin.
-#
-# If you are just denying access to the commands, RedisBungee uses the default BungeeCord
-# permissions - just deny them and access will be denied.
-#
-# Please note that with build 787+, most commands overridden by RedisBungee were moved to
-# modules, and these must be disabled or overridden yourself.
-register-bungee-commands: true
-
-# A list of IP addresses for which RedisBungee will not modify the response for, useful for automatic
-# restart scripts.
-exempt-ip-addresses: []
\ No newline at end of file
diff --git a/src/main/resources/lua/get_player_count.lua b/src/main/resources/lua/get_player_count.lua
deleted file mode 100644
index 0882aec..0000000
--- a/src/main/resources/lua/get_player_count.lua
+++ /dev/null
@@ -1,24 +0,0 @@
-local c = redis.call
-
-local curTime = c("TIME")
-local time = tonumber(curTime[1])
-
-local heartbeats = c("HGETALL", "heartbeats")
-local total = 0
-local key
-
-for _, v in ipairs(heartbeats) do
- if not key then
- key = v
- else
- local n = tonumber(v)
- if n then
- if n + 30 >= time then
- total = total + c("SCARD", "proxy:" .. key .. ":usersOnline")
- end
- end
- key = nil
- end
-end
-
-return total
diff --git a/src/main/resources/lua/server_to_players.lua b/src/main/resources/lua/server_to_players.lua
deleted file mode 100644
index ee66398..0000000
--- a/src/main/resources/lua/server_to_players.lua
+++ /dev/null
@@ -1,18 +0,0 @@
-local call = redis.call
-local ipairs = ipairs
-
-local serverToData = {}
-
-for _, proxy in ipairs(ARGV) do
- local players = call("SMEMBERS", "proxy:" .. proxy .. ":usersOnline")
- for _, player in ipairs(players) do
- local server = call("HGET", "player:" .. player, "server")
- if server then
- local sz = #serverToData
- serverToData[sz + 1] = server
- serverToData[sz + 2] = player
- end
- end
-end
-
-return serverToData
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
deleted file mode 100644
index 27b3ff5..0000000
--- a/src/main/resources/plugin.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-name: ${project.name}
-main: com.imaginarycode.minecraft.redisbungee.RedisBungee
-version: ${project.version}
-author: Chunkr and Govindas limework
-authors:
- - chunkr
- - Govindas Limework
-# This is used so that we can automatically override default BungeeCord behavior.
-softDepends: ["cmd_find", "cmd_list"]
\ No newline at end of file
diff --git a/src/test/java/com/imaginarycode/minecraft/redisbungee/test/RedisUtilTest.java b/src/test/java/com/imaginarycode/minecraft/redisbungee/test/RedisUtilTest.java
deleted file mode 100644
index 5f03f88..0000000
--- a/src/test/java/com/imaginarycode/minecraft/redisbungee/test/RedisUtilTest.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.imaginarycode.minecraft.redisbungee.test;
-
-import com.imaginarycode.minecraft.redisbungee.RedisUtil;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class RedisUtilTest {
- @Test
- public void testRedisLuaCheck() {
- Assert.assertTrue(RedisUtil.canUseLua("6.2.0"));
- Assert.assertTrue(RedisUtil.canUseLua("6.1.0"));
- Assert.assertTrue(RedisUtil.canUseLua("6.0.0"));
- Assert.assertFalse(RedisUtil.canUseLua("2.6.0"));
- Assert.assertFalse(RedisUtil.canUseLua("2.2.12"));
- Assert.assertFalse(RedisUtil.canUseLua("1.2.4"));
- Assert.assertFalse(RedisUtil.canUseLua("2.8.4"));
- Assert.assertFalse(RedisUtil.canUseLua("3.0.0"));
- Assert.assertFalse(RedisUtil.canUseLua("3.2.1"));
- }
-}
diff --git a/src/test/java/com/imaginarycode/minecraft/redisbungee/test/UUIDNameTest.java b/src/test/java/com/imaginarycode/minecraft/redisbungee/test/UUIDNameTest.java
deleted file mode 100644
index 613f97b..0000000
--- a/src/test/java/com/imaginarycode/minecraft/redisbungee/test/UUIDNameTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.imaginarycode.minecraft.redisbungee.test;
-
-import com.imaginarycode.minecraft.redisbungee.util.uuid.NameFetcher;
-import com.imaginarycode.minecraft.redisbungee.util.uuid.UUIDFetcher;
-import com.squareup.okhttp.OkHttpClient;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-public class UUIDNameTest {
- private String[] uuidsToTest = {"68ec43f7234b41b48764dfb38b9ffe8c", "652a2bc4e8cd405db7b698156ee2dc09"};
- private String[] namesToTest = {"vemacs"};
-
- @Test
- public void testUuidToName() throws IOException {
- OkHttpClient httpClient = new OkHttpClient();
- NameFetcher.setHttpClient(httpClient);
- for (String uuid : uuidsToTest) {
- List names = NameFetcher.nameHistoryFromUuid(UUIDFetcher.getUUID(uuid));
- String currentName = names.get(names.size() - 1);
- System.out.println("Current name for UUID " + uuid + " is " + currentName);
- }
- }
-
- @Test
- public void testNameToUuid() throws IOException {
- OkHttpClient httpClient = new OkHttpClient();
- UUIDFetcher.setHttpClient(httpClient);
- for (String name : namesToTest) {
- Map uuidMap1;
- try {
- uuidMap1 = new UUIDFetcher(Collections.singletonList(name)).call();
- for (Map.Entry entry : uuidMap1.entrySet()) {
- if (entry.getKey().equalsIgnoreCase(name)) {
- System.out.println("Current UUID for name " + name + " is " + entry.getValue());
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-}