mirror of
				https://github.com/proxiodev/RedisBungee.git
				synced 2025-11-04 01:28:02 +00:00 
			
		
		
		
	make velocity init on constructor than init method, change runables to lambdas and some generic removeals with supressing unchecked for eval lua
This commit is contained in:
		
							parent
							
								
									2c11cb179a
								
							
						
					
					
						commit
						76787455d8
					
				@ -38,6 +38,7 @@ import redis.clients.jedis.exceptions.JedisConnectionException;
 | 
				
			|||||||
import java.io.*;
 | 
					import java.io.*;
 | 
				
			||||||
import java.lang.reflect.Field;
 | 
					import java.lang.reflect.Field;
 | 
				
			||||||
import java.net.InetAddress;
 | 
					import java.net.InetAddress;
 | 
				
			||||||
 | 
					import java.nio.file.Files;
 | 
				
			||||||
import java.util.*;
 | 
					import java.util.*;
 | 
				
			||||||
import java.util.concurrent.*;
 | 
					import java.util.concurrent.*;
 | 
				
			||||||
import java.util.concurrent.atomic.AtomicInteger;
 | 
					import java.util.concurrent.atomic.AtomicInteger;
 | 
				
			||||||
@ -46,8 +47,6 @@ import java.util.logging.Level;
 | 
				
			|||||||
import static com.google.common.base.Preconditions.checkArgument;
 | 
					import static com.google.common.base.Preconditions.checkArgument;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin<ProxiedPlayer> {
 | 
					public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin<ProxiedPlayer> {
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static final Gson gson = new Gson();
 | 
					 | 
				
			||||||
    private RedisBungeeAPI api;
 | 
					    private RedisBungeeAPI api;
 | 
				
			||||||
    private PubSubListener psl = null;
 | 
					    private PubSubListener psl = null;
 | 
				
			||||||
    private JedisSummoner jedisSummoner;
 | 
					    private JedisSummoner jedisSummoner;
 | 
				
			||||||
@ -81,7 +80,7 @@ public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public int getCurrentCount() {
 | 
					    public int getCurrentCount() {
 | 
				
			||||||
        Long count = (Long) getPlayerCountScript.eval(ImmutableList.<String>of(), ImmutableList.<String>of());
 | 
					        Long count = (Long) getPlayerCountScript.eval(ImmutableList.of(), ImmutableList.of());
 | 
				
			||||||
        return count.intValue();
 | 
					        return count.intValue();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -109,7 +108,7 @@ public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin
 | 
				
			|||||||
                    keys.add("proxy:" + i + ":usersOnline");
 | 
					                    keys.add("proxy:" + i + ":usersOnline");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (!keys.isEmpty()) {
 | 
					                if (!keys.isEmpty()) {
 | 
				
			||||||
                    Set<String> users = rsc.sunion(keys.toArray(new String[keys.size()]));
 | 
					                    Set<String> users = rsc.sunion(keys.toArray(new String[0]));
 | 
				
			||||||
                    if (users != null && !users.isEmpty()) {
 | 
					                    if (users != null && !users.isEmpty()) {
 | 
				
			||||||
                        for (String user : users) {
 | 
					                        for (String user : users) {
 | 
				
			||||||
                            try {
 | 
					                            try {
 | 
				
			||||||
@ -149,26 +148,24 @@ public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
					    @SuppressWarnings("unchecked")
 | 
				
			||||||
    public Multimap<String, UUID> serversToPlayers() {
 | 
					    public Multimap<String, UUID> serversToPlayers() {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            return serverToPlayersCache.get(SERVER_TO_PLAYERS_KEY, new Callable<Multimap<String, UUID>>() {
 | 
					            return serverToPlayersCache.get(SERVER_TO_PLAYERS_KEY, () -> {
 | 
				
			||||||
                @Override
 | 
					                Collection<String> data = (Collection<String>) serverToPlayersScript.eval(ImmutableList.of(), getServerIds());
 | 
				
			||||||
                public Multimap<String, UUID> call() throws Exception {
 | 
					                ImmutableMultimap.Builder<String, UUID> builder = ImmutableMultimap.builder();
 | 
				
			||||||
                    Collection<String> data = (Collection<String>) serverToPlayersScript.eval(ImmutableList.<String>of(), getServerIds());
 | 
					                String key = null;
 | 
				
			||||||
                    ImmutableMultimap.Builder<String, UUID> builder = ImmutableMultimap.builder();
 | 
					                for (String s : data) {
 | 
				
			||||||
                    String key = null;
 | 
					                    if (key == null) {
 | 
				
			||||||
                    for (String s : data) {
 | 
					                        key = s;
 | 
				
			||||||
                        if (key == null) {
 | 
					                        continue;
 | 
				
			||||||
                            key = s;
 | 
					 | 
				
			||||||
                            continue;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        builder.put(key, UUID.fromString(s));
 | 
					 | 
				
			||||||
                        key = null;
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return builder.build();
 | 
					                    builder.put(key, UUID.fromString(s));
 | 
				
			||||||
 | 
					                    key = null;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return builder.build();
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        } catch (ExecutionException e) {
 | 
					        } catch (ExecutionException e) {
 | 
				
			||||||
            throw new RuntimeException(e);
 | 
					            throw new RuntimeException(e);
 | 
				
			||||||
@ -362,12 +359,13 @@ public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin
 | 
				
			|||||||
                        String version = s.split(":")[1];
 | 
					                        String version = s.split(":")[1];
 | 
				
			||||||
                        getLogger().info(version + " <- redis version");
 | 
					                        getLogger().info(version + " <- redis version");
 | 
				
			||||||
                        if (!RedisUtil.isRedisVersionRight(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.");
 | 
					                            getLogger().severe("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");
 | 
					                            throw new RuntimeException("Unsupported Redis version detected");
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            LuaManager manager = new LuaManager(this);
 | 
					                            LuaManager manager = new LuaManager(this);
 | 
				
			||||||
                            serverToPlayersScript = manager.createScript(IOUtil.readInputStreamAsString(getResourceAsStream("lua/server_to_players.lua")));
 | 
					                            serverToPlayersScript = manager.createScript(IOUtil.readInputStreamAsString(getResourceAsStream("lua/server_to_players.lua")));
 | 
				
			||||||
                            getPlayerCountScript = manager.createScript(IOUtil.readInputStreamAsString(getResourceAsStream("lua/get_player_count.lua")));
 | 
					                            getPlayerCountScript = manager.createScript(IOUtil.readInputStreamAsString(getResourceAsStream("lua/get_player_count.lua")));
 | 
				
			||||||
 | 
					                            getLogger().info("lua manager was loaded");
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -382,23 +380,20 @@ public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            serverIds = getCurrentServerIds(true, false);
 | 
					            serverIds = getCurrentServerIds(true, false);
 | 
				
			||||||
            uuidTranslator = new UUIDTranslator(this);
 | 
					            uuidTranslator = new UUIDTranslator(this);
 | 
				
			||||||
            heartbeatTask = service.scheduleAtFixedRate(new Runnable() {
 | 
					            heartbeatTask = service.scheduleAtFixedRate(() -> {
 | 
				
			||||||
                @Override
 | 
					                try (Jedis rsc = requestJedis()) {
 | 
				
			||||||
                public void run() {
 | 
					                    long redisTime = getRedisTime(rsc.time());
 | 
				
			||||||
                    try (Jedis rsc = requestJedis()) {
 | 
					                    rsc.hset("heartbeats", configuration.getServerId(), String.valueOf(redisTime));
 | 
				
			||||||
                        long redisTime = getRedisTime(rsc.time());
 | 
					                } catch (JedisConnectionException e) {
 | 
				
			||||||
                        rsc.hset("heartbeats", configuration.getServerId(), String.valueOf(redisTime));
 | 
					                    // Redis server has disappeared!
 | 
				
			||||||
                    } catch (JedisConnectionException e) {
 | 
					                    getLogger().log(Level.SEVERE, "Unable to update heartbeat - did your Redis server go away?", e);
 | 
				
			||||||
                        // Redis server has disappeared!
 | 
					                    return;
 | 
				
			||||||
                        getLogger().log(Level.SEVERE, "Unable to update heartbeat - did your Redis server go away?", e);
 | 
					                }
 | 
				
			||||||
                        return;
 | 
					                try {
 | 
				
			||||||
                    }
 | 
					                    serverIds = getCurrentServerIds(true, false);
 | 
				
			||||||
                    try {
 | 
					                    globalPlayerCount.set(getCurrentCount());
 | 
				
			||||||
                        serverIds = getCurrentServerIds(true, false);
 | 
					                } catch (Throwable e) {
 | 
				
			||||||
                        globalPlayerCount.set(getCurrentCount());
 | 
					                    getLogger().log(Level.SEVERE, "Unable to update data - did your Redis server go away?", e);
 | 
				
			||||||
                    } catch (Throwable e) {
 | 
					 | 
				
			||||||
                        getLogger().log(Level.SEVERE, "Unable to update data - did your Redis server go away?", e);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }, 0, 3, TimeUnit.SECONDS);
 | 
					            }, 0, 3, TimeUnit.SECONDS);
 | 
				
			||||||
            dataManager = new BungeeDataManager(this);
 | 
					            dataManager = new BungeeDataManager(this);
 | 
				
			||||||
@ -406,67 +401,64 @@ public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin
 | 
				
			|||||||
            getProxy().getPluginManager().registerListener(this, dataManager);
 | 
					            getProxy().getPluginManager().registerListener(this, dataManager);
 | 
				
			||||||
            psl = new PubSubListener(this);
 | 
					            psl = new PubSubListener(this);
 | 
				
			||||||
            getProxy().getScheduler().runAsync(this, psl);
 | 
					            getProxy().getScheduler().runAsync(this, psl);
 | 
				
			||||||
            integrityCheck = service.scheduleAtFixedRate(new Runnable() {
 | 
					            integrityCheck = service.scheduleAtFixedRate(() -> {
 | 
				
			||||||
                @Override
 | 
					                try (Jedis tmpRsc = requestJedis()) {
 | 
				
			||||||
                public void run() {
 | 
					                    Set<String> players = getLocalPlayersAsUuidStrings();
 | 
				
			||||||
                    try (Jedis tmpRsc = requestJedis()) {
 | 
					                    Set<String> playersInRedis = tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
 | 
				
			||||||
                        Set<String> players = getLocalPlayersAsUuidStrings();
 | 
					                    List<String> lagged = getCurrentServerIds(false, true);
 | 
				
			||||||
                        Set<String> playersInRedis = tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
 | 
					 | 
				
			||||||
                        List<String> lagged = getCurrentServerIds(false, true);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // Clean up lagged players.
 | 
					                    // Clean up lagged players.
 | 
				
			||||||
                        for (String s : lagged) {
 | 
					                    for (String s : lagged) {
 | 
				
			||||||
                            Set<String> laggedPlayers = tmpRsc.smembers("proxy:" + s + ":usersOnline");
 | 
					                        Set<String> laggedPlayers = tmpRsc.smembers("proxy:" + s + ":usersOnline");
 | 
				
			||||||
                            tmpRsc.del("proxy:" + s + ":usersOnline");
 | 
					                        tmpRsc.del("proxy:" + s + ":usersOnline");
 | 
				
			||||||
                            if (!laggedPlayers.isEmpty()) {
 | 
					                        if (!laggedPlayers.isEmpty()) {
 | 
				
			||||||
                                getLogger().info("Cleaning up lagged proxy " + s + " (" + laggedPlayers.size() + " players)...");
 | 
					                            getLogger().info("Cleaning up lagged proxy " + s + " (" + laggedPlayers.size() + " players)...");
 | 
				
			||||||
                                for (String laggedPlayer : laggedPlayers) {
 | 
					                            for (String laggedPlayer : laggedPlayers) {
 | 
				
			||||||
                                    RedisUtil.cleanUpPlayer(laggedPlayer, tmpRsc);
 | 
					                                RedisUtil.cleanUpPlayer(laggedPlayer, tmpRsc);
 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        Set<String> absentLocally = new HashSet<>(playersInRedis);
 | 
					 | 
				
			||||||
                        absentLocally.removeAll(players);
 | 
					 | 
				
			||||||
                        Set<String> 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            RBUtils.createPlayer(proxiedPlayer, pipeline, true);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        pipeline.sync();
 | 
					 | 
				
			||||||
                    } catch (Throwable e) {
 | 
					 | 
				
			||||||
                        getLogger().log(Level.SEVERE, "Unable to fix up stored player data", e);
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Set<String> absentLocally = new HashSet<>(playersInRedis);
 | 
				
			||||||
 | 
					                    absentLocally.removeAll(players);
 | 
				
			||||||
 | 
					                    Set<String> 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        RBUtils.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);
 | 
					            }, 0, 1, TimeUnit.MINUTES);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -513,16 +505,15 @@ public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void loadConfig() throws IOException {
 | 
					    public void loadConfig() throws IOException {
 | 
				
			||||||
        if (!getDataFolder().exists()) {
 | 
					        if (!getDataFolder().exists() && getDataFolder().mkdir()) {
 | 
				
			||||||
            getDataFolder().mkdir();
 | 
					            getLogger().info("data folder was created");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        File file = new File(getDataFolder(), "config.yml");
 | 
					        File file = new File(getDataFolder(), "config.yml");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!file.exists()) {
 | 
					        if (!file.exists() && file.createNewFile()) {
 | 
				
			||||||
            file.createNewFile();
 | 
					 | 
				
			||||||
            try (InputStream in = getResourceAsStream("example_config.yml");
 | 
					            try (InputStream in = getResourceAsStream("example_config.yml");
 | 
				
			||||||
                 OutputStream out = new FileOutputStream(file)) {
 | 
					                 OutputStream out = Files.newOutputStream(file.toPath())) {
 | 
				
			||||||
                ByteStreams.copy(in, out);
 | 
					                ByteStreams.copy(in, out);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -574,8 +565,8 @@ public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin
 | 
				
			|||||||
                rsc.ping();
 | 
					                rsc.ping();
 | 
				
			||||||
                // If that worked, now we can check for an existing, alive Bungee:
 | 
					                // If that worked, now we can check for an existing, alive Bungee:
 | 
				
			||||||
                File crashFile = new File(getDataFolder(), "restarted_from_crash.txt");
 | 
					                File crashFile = new File(getDataFolder(), "restarted_from_crash.txt");
 | 
				
			||||||
                if (crashFile.exists()) {
 | 
					                if (crashFile.exists() && crashFile.delete()) {
 | 
				
			||||||
                    crashFile.delete();
 | 
					                    getLogger().info("crash file was deleted");
 | 
				
			||||||
                } else if (rsc.hexists("heartbeats", serverId)) {
 | 
					                } else if (rsc.hexists("heartbeats", serverId)) {
 | 
				
			||||||
                    try {
 | 
					                    try {
 | 
				
			||||||
                        long value = Long.parseLong(rsc.hget("heartbeats", serverId));
 | 
					                        long value = Long.parseLong(rsc.hget("heartbeats", serverId));
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,6 @@ import com.google.common.collect.ImmutableSet;
 | 
				
			|||||||
import com.google.common.collect.Multimap;
 | 
					import com.google.common.collect.Multimap;
 | 
				
			||||||
import com.google.common.io.ByteStreams;
 | 
					import com.google.common.io.ByteStreams;
 | 
				
			||||||
import com.google.common.reflect.TypeToken;
 | 
					import com.google.common.reflect.TypeToken;
 | 
				
			||||||
import com.google.gson.Gson;
 | 
					 | 
				
			||||||
import com.google.inject.Inject;
 | 
					import com.google.inject.Inject;
 | 
				
			||||||
import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetworkEvent;
 | 
					import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetworkEvent;
 | 
				
			||||||
import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent;
 | 
					import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent;
 | 
				
			||||||
@ -40,6 +39,7 @@ import redis.clients.jedis.JedisPool;
 | 
				
			|||||||
import redis.clients.jedis.JedisPoolConfig;
 | 
					import redis.clients.jedis.JedisPoolConfig;
 | 
				
			||||||
import redis.clients.jedis.Pipeline;
 | 
					import redis.clients.jedis.Pipeline;
 | 
				
			||||||
import redis.clients.jedis.exceptions.JedisConnectionException;
 | 
					import redis.clients.jedis.exceptions.JedisConnectionException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static com.google.common.base.Preconditions.checkArgument;
 | 
					import static com.google.common.base.Preconditions.checkArgument;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.*;
 | 
					import java.io.*;
 | 
				
			||||||
@ -52,18 +52,16 @@ import java.util.concurrent.atomic.AtomicInteger;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@Plugin(id = "redisbungee", name = "RedisBungee", version = RBUtils.VERSION, url = "https://github.com/ProxioDev/RedisBungee", authors = "ProxioDev")
 | 
					@Plugin(id = "redisbungee", name = "RedisBungee", version = RBUtils.VERSION, url = "https://github.com/ProxioDev/RedisBungee", authors = "ProxioDev")
 | 
				
			||||||
public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
 | 
					public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static final Gson gson = new Gson();
 | 
					 | 
				
			||||||
    private final ProxyServer server;
 | 
					    private final ProxyServer server;
 | 
				
			||||||
    private final Logger logger;
 | 
					    private final Logger logger;
 | 
				
			||||||
    private final File dataFolder;
 | 
					    private final File dataFolder;
 | 
				
			||||||
    private RedisBungeeAPI api;
 | 
					    private final RedisBungeeAPI api;
 | 
				
			||||||
    private PubSubListener psl = null;
 | 
					    private final PubSubListener psl;
 | 
				
			||||||
    private JedisSummoner jedisSummoner;
 | 
					    private JedisSummoner jedisSummoner;
 | 
				
			||||||
    private UUIDTranslator uuidTranslator;
 | 
					    private final UUIDTranslator uuidTranslator;
 | 
				
			||||||
    private RedisBungeeConfiguration configuration;
 | 
					    private RedisBungeeConfiguration configuration;
 | 
				
			||||||
    private VelocityDataManager dataManager;
 | 
					    private final VelocityDataManager dataManager;
 | 
				
			||||||
    private OkHttpClient httpClient;
 | 
					    private final OkHttpClient httpClient;
 | 
				
			||||||
    private volatile List<String> serverIds;
 | 
					    private volatile List<String> serverIds;
 | 
				
			||||||
    private final AtomicInteger nagAboutServers = new AtomicInteger();
 | 
					    private final AtomicInteger nagAboutServers = new AtomicInteger();
 | 
				
			||||||
    private final AtomicInteger globalPlayerCount = new AtomicInteger();
 | 
					    private final AtomicInteger globalPlayerCount = new AtomicInteger();
 | 
				
			||||||
@ -83,6 +81,44 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
 | 
				
			|||||||
        this.server = server;
 | 
					        this.server = server;
 | 
				
			||||||
        this.logger = logger;
 | 
					        this.logger = logger;
 | 
				
			||||||
        this.dataFolder = dataDirectory.toFile();
 | 
					        this.dataFolder = dataDirectory.toFile();
 | 
				
			||||||
 | 
					        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);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.api = new RedisBungeeAPI(this);
 | 
				
			||||||
 | 
					        uuidTranslator = new UUIDTranslator(this);
 | 
				
			||||||
 | 
					        dataManager = new VelocityDataManager(this);
 | 
				
			||||||
 | 
					        psl = new PubSubListener(this);
 | 
				
			||||||
 | 
					        this.httpClient = new OkHttpClient();
 | 
				
			||||||
 | 
					        Dispatcher dispatcher = new Dispatcher(Executors.newFixedThreadPool(6));
 | 
				
			||||||
 | 
					        this.httpClient.setDispatcher(dispatcher);
 | 
				
			||||||
 | 
					        NameFetcher.setHttpClient(httpClient);
 | 
				
			||||||
 | 
					        UUIDFetcher.setHttpClient(httpClient);
 | 
				
			||||||
 | 
					        // keeping this lol
 | 
				
			||||||
 | 
					        new RedisBungee(api);
 | 
				
			||||||
 | 
					        // check if redis version compatible
 | 
				
			||||||
 | 
					        try (Jedis jedis = requestJedis()) {
 | 
				
			||||||
 | 
					            String info = jedis.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().error("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")));
 | 
				
			||||||
 | 
					                        getLogger().info("lua manager was loaded");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -99,7 +135,7 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public int getCurrentCount() {
 | 
					    public int getCurrentCount() {
 | 
				
			||||||
        Long count = (Long) getPlayerCountScript.eval(ImmutableList.<String>of(), ImmutableList.<String>of());
 | 
					        Long count = (Long) getPlayerCountScript.eval(ImmutableList.of(), ImmutableList.of());
 | 
				
			||||||
        return count.intValue();
 | 
					        return count.intValue();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -127,7 +163,7 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
 | 
				
			|||||||
                    keys.add("proxy:" + i + ":usersOnline");
 | 
					                    keys.add("proxy:" + i + ":usersOnline");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (!keys.isEmpty()) {
 | 
					                if (!keys.isEmpty()) {
 | 
				
			||||||
                    Set<String> users = rsc.sunion(keys.toArray(new String[keys.size()]));
 | 
					                    Set<String> users = rsc.sunion(keys.toArray(new String[0]));
 | 
				
			||||||
                    if (users != null && !users.isEmpty()) {
 | 
					                    if (users != null && !users.isEmpty()) {
 | 
				
			||||||
                        for (String user : users) {
 | 
					                        for (String user : users) {
 | 
				
			||||||
                            try {
 | 
					                            try {
 | 
				
			||||||
@ -167,26 +203,24 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
					    @SuppressWarnings("unchecked")
 | 
				
			||||||
    public Multimap<String, UUID> serversToPlayers() {
 | 
					    public Multimap<String, UUID> serversToPlayers() {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            return serverToPlayersCache.get(SERVER_TO_PLAYERS_KEY, new Callable<Multimap<String, UUID>>() {
 | 
					            return serverToPlayersCache.get(SERVER_TO_PLAYERS_KEY, () -> {
 | 
				
			||||||
                @Override
 | 
					                Collection<String> data = (Collection<String>) serverToPlayersScript.eval(ImmutableList.of(), getServerIds());
 | 
				
			||||||
                public Multimap<String, UUID> call() throws Exception {
 | 
					                ImmutableMultimap.Builder<String, UUID> builder = ImmutableMultimap.builder();
 | 
				
			||||||
                    Collection<String> data = (Collection<String>) serverToPlayersScript.eval(ImmutableList.<String>of(), getServerIds());
 | 
					                String key = null;
 | 
				
			||||||
                    ImmutableMultimap.Builder<String, UUID> builder = ImmutableMultimap.builder();
 | 
					                for (String s : data) {
 | 
				
			||||||
                    String key = null;
 | 
					                    if (key == null) {
 | 
				
			||||||
                    for (String s : data) {
 | 
					                        key = s;
 | 
				
			||||||
                        if (key == null) {
 | 
					                        continue;
 | 
				
			||||||
                            key = s;
 | 
					 | 
				
			||||||
                            continue;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        builder.put(key, UUID.fromString(s));
 | 
					 | 
				
			||||||
                        key = null;
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return builder.build();
 | 
					                    builder.put(key, UUID.fromString(s));
 | 
				
			||||||
 | 
					                    key = null;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return builder.build();
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        } catch (ExecutionException e) {
 | 
					        } catch (ExecutionException e) {
 | 
				
			||||||
            throw new RuntimeException(e);
 | 
					            throw new RuntimeException(e);
 | 
				
			||||||
@ -349,133 +383,96 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void initialize() {
 | 
					    public void initialize() {
 | 
				
			||||||
        try {
 | 
					        // set the first heartbeat
 | 
				
			||||||
            loadConfig();
 | 
					        try (Jedis tmpRsc = requestJedis()) {
 | 
				
			||||||
        } catch (IOException e) {
 | 
					            tmpRsc.hset("heartbeats", configuration.getServerId(), tmpRsc.time().get(0));
 | 
				
			||||||
            throw new RuntimeException("Unable to load/save config", e);
 | 
					            long uuidCacheSize = tmpRsc.hlen("uuid-cache");
 | 
				
			||||||
        } catch (JedisConnectionException e) {
 | 
					            if (uuidCacheSize > 750000) {
 | 
				
			||||||
            throw new RuntimeException("Unable to connect to your Redis server!", e);
 | 
					                getLogger().info("Looks like you have a really big UUID cache! Run https://www.spigotmc.org/resources/redisbungeecleaner.8505/ as soon as possible.");
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.api = new RedisBungeeAPI(this);
 | 
					 | 
				
			||||||
        // call old plugin class to support old plugins
 | 
					 | 
				
			||||||
        new RedisBungee(api);
 | 
					 | 
				
			||||||
        if (isJedisAvailable()) {
 | 
					 | 
				
			||||||
            try (Jedis tmpRsc = requestJedis()) {
 | 
					 | 
				
			||||||
                // This is more portable than INFO <section>
 | 
					 | 
				
			||||||
                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().warn("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 = getProxy().getScheduler().buildTask(this, new Runnable() {
 | 
					 | 
				
			||||||
                @Override
 | 
					 | 
				
			||||||
                public void run() {
 | 
					 | 
				
			||||||
                    try (Jedis rsc = requestJedis()) {
 | 
					 | 
				
			||||||
                        long redisTime = getRedisTime(rsc.time());
 | 
					 | 
				
			||||||
                        rsc.hset("heartbeats", configuration.getServerId(), String.valueOf(redisTime));
 | 
					 | 
				
			||||||
                    } catch (JedisConnectionException e) {
 | 
					 | 
				
			||||||
                        // Redis server has disappeared!
 | 
					 | 
				
			||||||
                        getLogger().error("Unable to update heartbeat - did your Redis server go away?", e);
 | 
					 | 
				
			||||||
                        return;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    try {
 | 
					 | 
				
			||||||
                        serverIds = getCurrentServerIds(true, false);
 | 
					 | 
				
			||||||
                        globalPlayerCount.set(getCurrentCount());
 | 
					 | 
				
			||||||
                    } catch (Throwable e) {
 | 
					 | 
				
			||||||
                        getLogger().error("Unable to update data - did your Redis server go away?", e);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }).repeat(3, TimeUnit.SECONDS).schedule();
 | 
					 | 
				
			||||||
            dataManager = new VelocityDataManager(this);
 | 
					 | 
				
			||||||
            getProxy().getEventManager().register(this, new RedisBungeeListener(this, configuration.getExemptAddresses()));
 | 
					 | 
				
			||||||
            getProxy().getEventManager().register(this, dataManager);
 | 
					 | 
				
			||||||
            psl = new PubSubListener(this);
 | 
					 | 
				
			||||||
            getProxy().getScheduler().buildTask(this, psl).schedule();
 | 
					 | 
				
			||||||
            integrityCheck = getProxy().getScheduler().buildTask(this,new Runnable() {
 | 
					 | 
				
			||||||
                @Override
 | 
					 | 
				
			||||||
                public void run() {
 | 
					 | 
				
			||||||
                    try (Jedis tmpRsc = requestJedis()) {
 | 
					 | 
				
			||||||
                        Set<String> players = getLocalPlayersAsUuidStrings();
 | 
					 | 
				
			||||||
                        Set<String> playersInRedis = tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
 | 
					 | 
				
			||||||
                        List<String> lagged = getCurrentServerIds(false, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        // Clean up lagged players.
 | 
					 | 
				
			||||||
                        for (String s : lagged) {
 | 
					 | 
				
			||||||
                            Set<String> 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<String> absentLocally = new HashSet<>(playersInRedis);
 | 
					 | 
				
			||||||
                        absentLocally.removeAll(players);
 | 
					 | 
				
			||||||
                        Set<String> 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().warn("Player found in set that was not found locally and globally: " + member);
 | 
					 | 
				
			||||||
                            } else {
 | 
					 | 
				
			||||||
                                tmpRsc.srem("proxy:" + configuration.getServerId() + ":usersOnline", member);
 | 
					 | 
				
			||||||
                                getLogger().warn("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().warn("Player " + player + " is on the proxy but not in Redis.");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            Player playerProxied = getProxy().getPlayer(UUID.fromString(player)).orElse(null);
 | 
					 | 
				
			||||||
                            if (playerProxied == null)
 | 
					 | 
				
			||||||
                                continue; // We'll deal with it later.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            RBUtils.createPlayer(playerProxied, pipeline, true);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        pipeline.sync();
 | 
					 | 
				
			||||||
                    } catch (Throwable e) {
 | 
					 | 
				
			||||||
                        getLogger().error("Unable to fix up stored player data", e);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }).repeat(1, TimeUnit.MINUTES).schedule();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        serverIds = getCurrentServerIds(true, false);
 | 
				
			||||||
 | 
					        heartbeatTask = getProxy().getScheduler().buildTask(this, () -> {
 | 
				
			||||||
 | 
					            try (Jedis rsc = requestJedis()) {
 | 
				
			||||||
 | 
					                long redisTime = getRedisTime(rsc.time());
 | 
				
			||||||
 | 
					                rsc.hset("heartbeats", configuration.getServerId(), String.valueOf(redisTime));
 | 
				
			||||||
 | 
					            } catch (JedisConnectionException e) {
 | 
				
			||||||
 | 
					                // Redis server has disappeared!
 | 
				
			||||||
 | 
					                getLogger().error("Unable to update heartbeat - did your Redis server go away?", e);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                serverIds = getCurrentServerIds(true, false);
 | 
				
			||||||
 | 
					                globalPlayerCount.set(getCurrentCount());
 | 
				
			||||||
 | 
					            } catch (Throwable e) {
 | 
				
			||||||
 | 
					                getLogger().error("Unable to update data - did your Redis server go away?", e);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }).repeat(3, TimeUnit.SECONDS).schedule();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        getProxy().getEventManager().register(this, new RedisBungeeListener(this, configuration.getExemptAddresses()));
 | 
				
			||||||
 | 
					        getProxy().getEventManager().register(this, dataManager);
 | 
				
			||||||
 | 
					        getProxy().getScheduler().buildTask(this, psl).schedule();
 | 
				
			||||||
 | 
					        integrityCheck = getProxy().getScheduler().buildTask(this, () -> {
 | 
				
			||||||
 | 
					            try (Jedis tmpRsc = requestJedis()) {
 | 
				
			||||||
 | 
					                Set<String> players = getLocalPlayersAsUuidStrings();
 | 
				
			||||||
 | 
					                Set<String> playersInRedis = tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
 | 
				
			||||||
 | 
					                List<String> lagged = getCurrentServerIds(false, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Clean up lagged players.
 | 
				
			||||||
 | 
					                for (String s : lagged) {
 | 
				
			||||||
 | 
					                    Set<String> 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<String> absentLocally = new HashSet<>(playersInRedis);
 | 
				
			||||||
 | 
					                absentLocally.removeAll(players);
 | 
				
			||||||
 | 
					                Set<String> 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().warn("Player found in set that was not found locally and globally: " + member);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        tmpRsc.srem("proxy:" + configuration.getServerId() + ":usersOnline", member);
 | 
				
			||||||
 | 
					                        getLogger().warn("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().warn("Player " + player + " is on the proxy but not in Redis.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Player playerProxied = getProxy().getPlayer(UUID.fromString(player)).orElse(null);
 | 
				
			||||||
 | 
					                    if (playerProxied == null)
 | 
				
			||||||
 | 
					                        continue; // We'll deal with it later.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    RBUtils.createPlayer(playerProxied, pipeline, true);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                pipeline.sync();
 | 
				
			||||||
 | 
					            } catch (Throwable e) {
 | 
				
			||||||
 | 
					                getLogger().error("Unable to fix up stored player data", e);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }).repeat(1, TimeUnit.MINUTES).schedule();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // plugin messages are disabled for now
 | 
					        // plugin messages are disabled for now
 | 
				
			||||||
        //getProxy().registerChannel("legacy:redisbungee");
 | 
					        //getProxy().registerChannel("legacy:redisbungee");
 | 
				
			||||||
        //getProxy().registerChannel("RedisBungee");
 | 
					        //getProxy().registerChannel("RedisBungee");
 | 
				
			||||||
@ -527,26 +524,24 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void loadConfig() throws IOException {
 | 
					    public void loadConfig() throws IOException {
 | 
				
			||||||
        if (!getDataFolder().exists()) {
 | 
					        if (!getDataFolder().exists() && getDataFolder().mkdir()) {
 | 
				
			||||||
            getDataFolder().mkdir();
 | 
					            getLogger().info("data folder was created");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        File file = new File(getDataFolder(), "config.yml");
 | 
					        File file = new File(getDataFolder(), "config.yml");
 | 
				
			||||||
        if (!file.exists()) {
 | 
					        if (!file.exists() && file.createNewFile()) {
 | 
				
			||||||
            file.createNewFile();
 | 
					            getLogger().info("config file was created");
 | 
				
			||||||
            try (InputStream in = getResourceAsStream("example_config.yml");
 | 
					            try (InputStream in = getResourceAsStream("example_config.yml");
 | 
				
			||||||
                 OutputStream out = Files.newOutputStream(file.toPath())) {
 | 
					                 OutputStream out = Files.newOutputStream(file.toPath())) {
 | 
				
			||||||
                ByteStreams.copy(in, out);
 | 
					                ByteStreams.copy(in, out);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        final YAMLConfigurationLoader yamlConfiguration = YAMLConfigurationLoader.builder().setFile(file).build();
 | 
					        final YAMLConfigurationLoader yamlConfiguration = YAMLConfigurationLoader.builder().setFile(file).build();
 | 
				
			||||||
 | 
					 | 
				
			||||||
        ConfigurationNode node = yamlConfiguration.load();
 | 
					        ConfigurationNode node = yamlConfiguration.load();
 | 
				
			||||||
        final String redisServer = node.getNode("redis-server").getString();
 | 
					        final String redisServer = node.getNode("redis-server").getString();
 | 
				
			||||||
        final int redisPort = node.getNode("redis-port").getInt();
 | 
					        final int redisPort = node.getNode("redis-port").getInt();
 | 
				
			||||||
        final boolean useSSL = node.getNode("useSSL").getBoolean();
 | 
					        final boolean useSSL = node.getNode("useSSL").getBoolean();
 | 
				
			||||||
        String redisPassword = node.getNode("redis-password").getString();
 | 
					        String redisPassword = node.getNode("redis-password").getString();
 | 
				
			||||||
        String serverId =  node.getNode("server-id").getString();
 | 
					        String serverId = node.getNode("server-id").getString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // check redis password
 | 
					        // check redis password
 | 
				
			||||||
        if (redisPassword != null && (redisPassword.isEmpty() || redisPassword.equals("none"))) {
 | 
					        if (redisPassword != null && (redisPassword.isEmpty() || redisPassword.equals("none"))) {
 | 
				
			||||||
@ -591,8 +586,8 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
 | 
				
			|||||||
                rsc.ping();
 | 
					                rsc.ping();
 | 
				
			||||||
                // If that worked, now we can check for an existing, alive Bungee:
 | 
					                // If that worked, now we can check for an existing, alive Bungee:
 | 
				
			||||||
                File crashFile = new File(getDataFolder(), "restarted_from_crash.txt");
 | 
					                File crashFile = new File(getDataFolder(), "restarted_from_crash.txt");
 | 
				
			||||||
                if (crashFile.exists()) {
 | 
					                if (crashFile.exists() && crashFile.delete()) {
 | 
				
			||||||
                    crashFile.delete();
 | 
					                    getLogger().info("crash file was deleted");
 | 
				
			||||||
                } else if (rsc.hexists("heartbeats", serverId)) {
 | 
					                } else if (rsc.hexists("heartbeats", serverId)) {
 | 
				
			||||||
                    try {
 | 
					                    try {
 | 
				
			||||||
                        long value = Long.parseLong(rsc.hget("heartbeats", serverId));
 | 
					                        long value = Long.parseLong(rsc.hget("heartbeats", serverId));
 | 
				
			||||||
@ -606,14 +601,6 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
 | 
				
			|||||||
                    } catch (NumberFormatException ignored) {
 | 
					                    } catch (NumberFormatException ignored) {
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                httpClient = new OkHttpClient();
 | 
					 | 
				
			||||||
                Dispatcher dispatcher = new Dispatcher(Executors.newFixedThreadPool(6));
 | 
					 | 
				
			||||||
                httpClient.setDispatcher(dispatcher);
 | 
					 | 
				
			||||||
                NameFetcher.setHttpClient(httpClient);
 | 
					 | 
				
			||||||
                UUIDFetcher.setHttpClient(httpClient);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                getLogger().info("Successfully connected to Redis.");
 | 
					                getLogger().info("Successfully connected to Redis.");
 | 
				
			||||||
            } catch (JedisConnectionException e) {
 | 
					            } catch (JedisConnectionException e) {
 | 
				
			||||||
                this.jedisSummoner.close();
 | 
					                this.jedisSummoner.close();
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user