From ff602bc5e65bd16269c2697d99099e4d51bb2d63 Mon Sep 17 00:00:00 2001 From: Tux Date: Mon, 22 Jun 2015 04:35:45 -0400 Subject: [PATCH] Player/internal tweaks: - Switch to BungeeCord task scheduler, since it's fixed. - Moved player checks and such to LoginEvent. The login network event is still published from PostLoginEvent. - Fix a typo. Whee. --- .../minecraft/redisbungee/RedisBungee.java | 17 +---- .../redisbungee/RedisBungeeListener.java | 68 +++++++++++++------ .../redisbungee/util/RedisCallable.java | 6 +- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java index 8052d0a..0e66c0f 100644 --- a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java +++ b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java @@ -78,8 +78,6 @@ public final class RedisBungee extends Plugin { @Getter private DataManager dataManager; @Getter - private ExecutorService service; - @Getter private static OkHttpClient httpClient; private List serverIds; private AtomicInteger nagAboutServers = new AtomicInteger(); @@ -356,16 +354,6 @@ public final class RedisBungee extends Plugin { heartbeatTask.cancel(); getProxy().getPluginManager().unregisterListeners(this); - getLogger().info("Waiting for all tasks to finish."); - - service.shutdown(); - try { - if (!service.awaitTermination(60, TimeUnit.SECONDS)) { - service.shutdownNow(); - } - } catch (InterruptedException ignored) { - } - try (Jedis tmpRsc = pool.getResource()) { tmpRsc.hdel("heartbeats", configuration.getServerId()); if (tmpRsc.scard("proxy:" + configuration.getServerId() + ":usersOnline") > 0) { @@ -451,7 +439,7 @@ public final class RedisBungee extends Plugin { try { Long value = Long.valueOf(rsc.hget("heartbeats", serverId)); if (value != null && System.currentTimeMillis() < value + 20000) { - getLogger().severe("You have launched a possible imposter BungeeCord instance. Another instance is already running."); + 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 imposter instance!"); @@ -463,9 +451,8 @@ public final class RedisBungee extends Plugin { FutureTask task2 = new FutureTask<>(new Callable() { @Override public Void call() throws Exception { - service = Executors.newCachedThreadPool(); httpClient = new OkHttpClient(); - Dispatcher dispatcher = new Dispatcher(service); + Dispatcher dispatcher = new Dispatcher(getExecutorService()); httpClient.setDispatcher(dispatcher); NameFetcher.setHttpClient(httpClient); UUIDFetcher.setHttpClient(httpClient); diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java index 807e539..f817ea9 100644 --- a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java +++ b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java @@ -39,6 +39,8 @@ import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ServerPing; 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.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; @@ -61,33 +63,59 @@ public class RedisBungeeListener implements Listener { private final RedisBungee plugin; private final List exemptAddresses; - @EventHandler - public void onPlayerConnect(final PostLoginEvent event) { - try (Jedis rsc = plugin.getPool().getResource()) { - for (String server : plugin.getServerIds()) { - if (rsc.sismember("proxy:" + server + ":usersOnline", event.getPlayer().getUniqueId().toString())) { - event.getPlayer().disconnect(ALREADY_LOGGED_IN); - return; - } - } - } - - plugin.getService().submit(new RedisCallable(plugin) { + @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) { + if (event.isCancelled()) { + event.completeIntent(plugin); + return null; + } + + // If a player with this name isn't on this proxy, we make sure they aren't trying to use an existing + // player's name. This is BungeeCord behavior I disapprove of but I don't really care at this point. + ProxiedPlayer player = plugin.getProxy().getPlayer(event.getConnection().getName()); + + if (player == null) { + String online = jedis.hget("player:" + event.getConnection().getUniqueId().toString(), "online"); + + if (online != null && online.equals("0")) { + event.setCancelled(true); + // TODO: Make it accept a BaseComponent[] like everything else. + event.setCancelReason(TextComponent.toLegacyText(ALREADY_LOGGED_IN)); + event.completeIntent(plugin); + return null; + } + } + Map playerData = new HashMap<>(4); playerData.put("online", "0"); - playerData.put("ip", event.getPlayer().getAddress().getAddress().getHostAddress()); + playerData.put("ip", event.getConnection().getAddress().getAddress().getHostAddress()); playerData.put("proxy", RedisBungee.getConfiguration().getServerId()); Pipeline pipeline = jedis.pipelined(); - pipeline.sadd("proxy:" + RedisBungee.getApi().getServerId() + ":usersOnline", event.getPlayer().getUniqueId().toString()); - plugin.getUuidTranslator().persistInfo(event.getPlayer().getName(), event.getPlayer().getUniqueId(), pipeline); - pipeline.hmset("player:" + event.getPlayer().getUniqueId().toString(), playerData); - pipeline.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>( + pipeline.sadd("proxy:" + RedisBungee.getApi().getServerId() + ":usersOnline", event.getConnection().getUniqueId().toString()); + plugin.getUuidTranslator().persistInfo(event.getConnection().getName(), event.getConnection().getUniqueId(), pipeline); + pipeline.hmset("player:" + event.getConnection().getUniqueId().toString(), playerData); + // We're not publishing, the API says we only publish at PostLoginEvent time. + pipeline.sync(); + + event.completeIntent(plugin); + return null; + } + }); + } + + @EventHandler + public void onPostLogin(final PostLoginEvent event) { + plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) { + @Override + protected Void call(Jedis jedis) { + jedis.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>( event.getPlayer().getUniqueId(), DataManager.DataManagerMessage.Action.JOIN, new DataManager.LoginPayload(event.getPlayer().getAddress().getAddress())))); - pipeline.sync(); return null; } }); @@ -95,7 +123,7 @@ public class RedisBungeeListener implements Listener { @EventHandler public void onPlayerDisconnect(final PlayerDisconnectEvent event) { - plugin.getService().submit(new RedisCallable(plugin) { + plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) { @Override protected Void call(Jedis jedis) { Pipeline pipeline = jedis.pipelined(); @@ -113,7 +141,7 @@ public class RedisBungeeListener implements Listener { @EventHandler public void onServerChange(final ServerConnectedEvent event) { - plugin.getService().submit(new RedisCallable(plugin) { + plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable(plugin) { @Override protected Void call(Jedis jedis) { Pipeline pipeline = jedis.pipelined(); diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/RedisCallable.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/util/RedisCallable.java index f83db27..30b7337 100644 --- a/src/main/java/com/imaginarycode/minecraft/redisbungee/util/RedisCallable.java +++ b/src/main/java/com/imaginarycode/minecraft/redisbungee/util/RedisCallable.java @@ -35,7 +35,7 @@ import java.util.concurrent.Callable; import java.util.logging.Level; @AllArgsConstructor -public abstract class RedisCallable implements Callable { +public abstract class RedisCallable implements Callable, Runnable { private final RedisBungee plugin; @Override @@ -43,6 +43,10 @@ public abstract class RedisCallable implements Callable { return run(false); } + public void run() { + call(); + } + private T run(boolean retry) { try (Jedis jedis = plugin.getPool().getResource()) { return call(jedis);