From d0f5a24f38ff5251dacb981a96de54ab68d0af38 Mon Sep 17 00:00:00 2001 From: Tux Date: Sun, 29 Sep 2013 16:16:47 -0400 Subject: [PATCH] first commit --- .gitignore | 36 +++ LICENSE | 14 + license-maven-friendly.txt | 4 + pom.xml | 131 +++++++++ .../minecraft/redisbungee/RedisBungee.java | 273 ++++++++++++++++++ src/main/resources/example_config.yml | 6 + src/main/resources/plugin.yml | 4 + 7 files changed, 468 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 license-maven-friendly.txt create mode 100644 pom.xml create mode 100644 src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java create mode 100644 src/main/resources/example_config.yml create mode 100644 src/main/resources/plugin.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b73ee2d --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# Eclipse stuff +/.classpath +/.project +/.settings + +# netbeans +/nbproject +/nbactions.xml +/nb-configuration.xml + +# we use maven! +/build.xml + +# maven +/target +/dependency-reduced-pom.xml +*/target +*/dependency-reduced-pom.xml + +# vim +.*.sw[a-p] + +# various other potential build files +/build +/bin +/dist +/manifest.mf + +# Mac filesystem dust +/.DS_Store + +# intellij +*.iml +*.ipr +*.iws +.idea/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5a8e332 --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + Version 2, December 2004 + + Copyright (C) 2004 Sam Hocevar + + Everyone is permitted to copy and distribute verbatim or modified + copies of this license document, and changing it is allowed as long + as the name is changed. + + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. You just DO WHAT THE FUCK YOU WANT TO. + diff --git a/license-maven-friendly.txt b/license-maven-friendly.txt new file mode 100644 index 0000000..cc5707d --- /dev/null +++ b/license-maven-friendly.txt @@ -0,0 +1,4 @@ +Copyright © ${project.inceptionYear} ${owner} <${email}> +This work is free. You can redistribute it and/or modify it under the +terms of the Do What The Fuck You Want To Public License, Version 2, +as published by Sam Hocevar. See http://www.wtfpl.net/ for more details. \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8e6ab1c --- /dev/null +++ b/pom.xml @@ -0,0 +1,131 @@ + + + + 4.0.0 + + groupId + RedisBungee + 1.0-SNAPSHOT + + + + bungeecord-repo + https://oss.sonatype.org/content/repositories/snapshots + + + bungeeyaml-repo + http://repo.craftminecraft.net/content/repositories/releases + + + + 2013 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-shade-plugin + 2.1 + + + package + + shade + + + + + redis.clients:jedis + commons-pool:commons-pool + + + + + redis.clients + com.imaginarycode.minecraft.redisbungee.internal.jedis + + + org.apache.commons.pool + com.imaginarycode.minecraft.redisbungee.internal.commonspool + + + + + + + + com.mycila + license-maven-plugin + 2.3 + +
license-maven-friendly.txt
+ + tuxed + 2013 + write@imaginarycode.com + + + README.md + LICENSE + .gitignore + src/test/resources/** + src/main/resources/** + +
+ + + + check + + + +
+
+
+ + + + redis.clients + jedis + 2.0.0 + + + net.md-5 + bungeecord-api + 1.6.2-SNAPSHOT + jar + provided + + + net.craftminecraft.bungee + bungeeyaml + 1.2.3 + jar + provided + + + org.projectlombok + lombok + 0.12.0 + provided + + +
\ No newline at end of file diff --git a/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java new file mode 100644 index 0000000..cad3c3e --- /dev/null +++ b/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java @@ -0,0 +1,273 @@ +/** + * Copyright © 2013 tuxed + * This work is free. You can redistribute it and/or modify it under the + * terms of the Do What The Fuck You Want To Public License, Version 2, + * as published by Sam Hocevar. See http://www.wtfpl.net/ for more details. + */ +package com.imaginarycode.minecraft.redisbungee; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.ServerPing; +import net.md_5.bungee.api.config.ServerInfo; +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.event.ProxyPingEvent; +import net.md_5.bungee.api.event.ServerConnectedEvent; +import net.md_5.bungee.api.plugin.Command; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.api.plugin.Plugin; +import net.md_5.bungee.event.EventHandler; +import org.yaml.snakeyaml.Yaml; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +import java.io.*; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +public class RedisBungee extends Plugin implements Listener { + private static JedisPool pool; + private static String serverId; + private static List servers = Lists.newArrayList(); + private static RedisBungee plugin; + + public static int getCount() { + int count = 0; + count += plugin.getProxy().getOnlineCount(); + if (pool != null) { + Jedis rsc = pool.getResource(); + try { + for (String i : servers) { + if (i.equals(serverId)) continue; + if (rsc.exists("server:" + i + ":playerCount")) + count += Integer.valueOf(rsc.get("server:" + i + ":playerCount")); + } + } finally { + pool.returnResource(rsc); + } + } + return count; + } + + public static Set getPlayers() { + Set players = Sets.newHashSet(); + for (ProxiedPlayer pp : plugin.getProxy().getPlayers()) { + players.add(pp.getName()); + } + if (pool != null) { + Jedis rsc = pool.getResource(); + try { + for (String i : servers) { + if (i.equals(serverId)) continue; + for (String p : rsc.smembers("server:" + i + ":usersOnline")) { + if (!players.contains(p)) { + players.add(p); + } + } + } + } finally { + pool.returnResource(rsc); + } + } + return ImmutableSet.copyOf(players); + } + + public static ServerInfo getServerFor(ProxiedPlayer pp) { + return getServerFor(pp.getName()); + } + + public static ServerInfo getServerFor(String name) { + ServerInfo server = null; + if (plugin.getProxy().getPlayer(name) != null) return plugin.getProxy().getPlayer(name).getServer().getInfo(); + if (pool != null) { + Jedis tmpRsc = pool.getResource(); + try { + if (tmpRsc.hexists("player:" + name, "server")) + server = plugin.getProxy().getServerInfo(tmpRsc.hget("player:" + name, "server")); + } finally { + pool.returnResource(tmpRsc); + } + } + return server; + } + + public static long getLastOnline(ProxiedPlayer pp) { + return getLastOnline(pp.getName()); + } + + private static long getUnixTimestamp() { + return TimeUnit.SECONDS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS); + } + + public static long getLastOnline(String name) { + long time = 0L; + if (plugin.getProxy().getPlayer(name) != null) return time; + if (pool != null) { + Jedis tmpRsc = pool.getResource(); + try { + if (tmpRsc.hexists("player:" + name, "online")) + time = Long.valueOf(tmpRsc.hget("player:" + name, "online")); + } finally { + pool.returnResource(tmpRsc); + } + } + return time; + } + + @Override + public void onEnable() { + plugin = this; + try { + loadConfig(); + } catch (IOException e) { + e.printStackTrace(); + } + if (pool != null) { + Jedis tmpRsc = pool.getResource(); + try { + tmpRsc.set("server:" + serverId + ":playerCount", "0"); // reset + for (String i : tmpRsc.smembers("server:" + serverId + ":usersOnline")) { + tmpRsc.srem("server:" + serverId + ":usersOnline", i); + } + } finally { + pool.returnResource(tmpRsc); + } + getProxy().getScheduler().schedule(this, new Runnable() { + @Override + public void run() { + Jedis rsc = pool.getResource(); + try { + rsc.set("server:" + serverId + ":playerCount", String.valueOf(getProxy().getOnlineCount())); + } finally { + pool.returnResource(rsc); + } + } + }, 3, 3, TimeUnit.SECONDS); + getProxy().getPluginManager().registerCommand(this, new Command("glist") { + @Override + public void execute(CommandSender sender, String[] args) { + sender.sendMessage(ChatColor.YELLOW + String.valueOf(getCount()) + " player(s) are currently online."); + if (args.length > 0 && args[0].equals("showall")) { + sender.sendMessage(ChatColor.YELLOW + "Players: " + Joiner.on(", ").join(getPlayers())); + } else { + sender.sendMessage(ChatColor.YELLOW + "To see all players online, use /glist showall."); + } + } + }); + getProxy().getPluginManager().registerListener(this, this); + } + } + + @Override + public void onDisable() { + pool.destroy(); + } + + private void loadConfig() throws IOException { + if (!getDataFolder().exists()) { + getDataFolder().mkdir(); + } + + File exampleConfig = new File(getDataFolder(), "config.yml"); + if (!exampleConfig.exists()) { + exampleConfig.createNewFile(); + InputStream in = getResourceAsStream("example_config.yml"); + OutputStream out = new FileOutputStream(exampleConfig); + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + out.close(); + in.close(); + } + + File file = new File(getDataFolder() + File.separator + "config.yml"); + Yaml yaml = new Yaml(); + Map rawYaml = (Map) yaml.load(new FileInputStream(file)); + + String redisServer = ((String) rawYaml.get("redis-server")); + serverId = ((String) rawYaml.get("server-id")); + List tmp = (List) rawYaml.get("linked-servers"); + if (tmp != null) + for (Object i : tmp) { + if (i instanceof String) { + servers.add((String) i); + } + } + + if (redisServer != null) { + if (!redisServer.equals("")) { + pool = new JedisPool(new JedisPoolConfig(), redisServer); + } + } + } + + @EventHandler + public void onPlayerConnect(final PostLoginEvent event) { + if (pool != null) { + Jedis rsc = pool.getResource(); + try { + rsc.sadd("server:" + serverId + ":usersOnline", event.getPlayer().getName()); + rsc.hset("player:" + event.getPlayer().getName(), "online", "0"); + rsc.hset("player:" + event.getPlayer().getName(), "online", (String)getProxy().getServers().keySet().toArray()[0]); + } finally { + pool.returnResource(rsc); + } + getProxy().getScheduler().schedule(this, new Runnable() { + @Override + public void run() { + Jedis rsc = pool.getResource(); + try { + rsc.hset("player:" + event.getPlayer().getName(), "server", event.getPlayer().getServer().getInfo().getName()); + } finally { + pool.returnResource(rsc); + } + } + }, 3, TimeUnit.SECONDS); + } + } + + @EventHandler + public void onPlayerDisconnect(PlayerDisconnectEvent event) { + if (pool != null) { + Jedis rsc = pool.getResource(); + try { + rsc.srem("server:" + serverId + ":usersOnline", event.getPlayer().getName()); + rsc.hset("player:" + event.getPlayer().getName(), "online", String.valueOf(getUnixTimestamp())); + rsc.hdel("player:" + event.getPlayer().getName(), "server"); + } finally { + pool.returnResource(rsc); + } + } + } + + @EventHandler + public void onServerChange(ServerConnectedEvent event) { + if (pool != null) { + Jedis rsc = pool.getResource(); + try { + rsc.hset("player:" + event.getPlayer().getName(), "server", event.getServer().getInfo().getName()); + } finally { + pool.returnResource(rsc); + } + } + } + + @EventHandler + public void onPing(ProxyPingEvent event) { + ServerPing old = event.getResponse(); + int players = getCount(); + ServerPing newResponse = new ServerPing(old.getProtocolVersion(), old.getGameVersion(), old.getMotd(), players, old.getMaxPlayers()); + event.setResponse(newResponse); + } +} diff --git a/src/main/resources/example_config.yml b/src/main/resources/example_config.yml new file mode 100644 index 0000000..adf3504 --- /dev/null +++ b/src/main/resources/example_config.yml @@ -0,0 +1,6 @@ +redis-server: 127.0.0.1 +server-id: iluvbungee +linked-servers: +- dastank +- americancoffee +- guavaissweet \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..a41ce69 --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,4 @@ +name: RedisBungee +main: com.imaginarycode.minecraft.redisbungee.RedisBungee +version: 0.1 +author: tuxed \ No newline at end of file