package com.imaginarycode.minecraft.redisbungee.api.tasks; import com.imaginarycode.minecraft.redisbungee.api.GenericPlayerUtils; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisCluster; import redis.clients.jedis.Pipeline; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.logging.Level; public abstract class IntegrityCheckTask extends RedisTask { public static int INTERVAL = 30; public static TimeUnit TIMEUNIT = TimeUnit.SECONDS; public IntegrityCheckTask(RedisBungeePlugin plugin) { super(plugin); } @Override public Void jedisTask(Jedis jedis) { try { Set players = plugin.getLocalPlayersAsUuidStrings(); Set playersInRedis = jedis.smembers("proxy:" + plugin.getConfiguration().getProxyId() + ":usersOnline"); List lagged = plugin.getCurrentProxiesIds(true); // Clean up lagged players. for (String s : lagged) { Set laggedPlayers = jedis.smembers("proxy:" + s + ":usersOnline"); jedis.del("proxy:" + s + ":usersOnline"); if (!laggedPlayers.isEmpty()) { plugin.logInfo("Cleaning up lagged proxy " + s + " (" + laggedPlayers.size() + " players)..."); for (String laggedPlayer : laggedPlayers) { GenericPlayerUtils.cleanUpPlayer(laggedPlayer, jedis, true); } } } 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 : plugin.getProxiesIds()) { if (proxyId.equals(plugin.getConfiguration().getProxyId())) continue; if (jedis.sismember("proxy:" + proxyId + ":usersOnline", member)) { // Just clean up the set. found = true; break; } } if (!found) { GenericPlayerUtils.cleanUpPlayer(member, jedis, false); plugin.logWarn("Player found in set that was not found locally and globally: " + member); } else { jedis.srem("proxy:" + plugin.getConfiguration().getProxyId() + ":usersOnline", member); plugin.logWarn("Player found in set that was not found locally, but is on another proxy: " + member); } } Pipeline pipeline = jedis.pipelined(); for (String player : absentInRedis) { // Player not online according to Redis but not BungeeCord. plugin.logWarn("Player " + player + " is on the proxy but not in Redis."); handlePlatformPlayer(player, pipeline); } pipeline.sync(); } catch (Throwable e) { plugin.logFatal("Unable to fix up stored player data"); e.printStackTrace(); } return null; } @Override public Void clusterJedisTask(JedisCluster jedisCluster) { try { Set players = plugin.getLocalPlayersAsUuidStrings(); Set playersInRedis = jedisCluster.smembers("proxy:" + plugin.getConfiguration().getProxyId() + ":usersOnline"); List lagged = plugin.getCurrentProxiesIds(true); // Clean up lagged players. for (String s : lagged) { Set laggedPlayers = jedisCluster.smembers("proxy:" + s + ":usersOnline"); jedisCluster.del("proxy:" + s + ":usersOnline"); if (!laggedPlayers.isEmpty()) { plugin.logInfo("Cleaning up lagged proxy " + s + " (" + laggedPlayers.size() + " players)..."); for (String laggedPlayer : laggedPlayers) { GenericPlayerUtils.cleanUpPlayer(laggedPlayer, jedisCluster, true); } } } 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 : plugin.getProxiesIds()) { if (proxyId.equals(plugin.getConfiguration().getProxyId())) continue; if (jedisCluster.sismember("proxy:" + proxyId + ":usersOnline", member)) { // Just clean up the set. found = true; break; } } if (!found) { GenericPlayerUtils.cleanUpPlayer(member, jedisCluster, false); plugin.logWarn("Player found in set that was not found locally and globally: " + member); } else { jedisCluster.srem("proxy:" + plugin.getConfiguration().getProxyId() + ":usersOnline", member); plugin.logWarn("Player found in set that was not found locally, but is on another proxy: " + member); } } // due JedisCluster does not support pipelined. //Pipeline pipeline = jedis.pipelined(); for (String player : absentInRedis) { // Player not online according to Redis but not BungeeCord. handlePlatformPlayer(player, jedisCluster); } } catch (Throwable e) { plugin.logFatal("Unable to fix up stored player data"); e.printStackTrace(); } return null; } public abstract void handlePlatformPlayer(String player, JedisCluster jedisCluster); public abstract void handlePlatformPlayer(String player, Pipeline pipeline); }