diff --git a/src/main/java/us/ajg0702/queue/Main.java b/src/main/java/us/ajg0702/queue/Main.java index bde347a..3ab8696 100644 --- a/src/main/java/us/ajg0702/queue/Main.java +++ b/src/main/java/us/ajg0702/queue/Main.java @@ -19,6 +19,7 @@ import us.ajg0702.queue.commands.MoveCommand; import us.ajg0702.queue.utils.BungeeConfig; import us.ajg0702.queue.utils.BungeeMessages; import us.ajg0702.queue.utils.BungeeStats; +import us.ajg0702.queue.utils.BungeeUtils; public class Main extends Plugin implements Listener { @@ -134,13 +135,32 @@ public class Main extends Plugin implements Listener { DataInputStream in = new DataInputStream(new ByteArrayInputStream(e.getData())); try { String subchannel = in.readUTF(); + ProxiedPlayer player = (ProxiedPlayer) e.getReceiver(); if(subchannel.equals("queue")) { String data = in.readUTF(); - ProxiedPlayer player = (ProxiedPlayer) e.getReceiver(); man.addToQueue(player, data); } + if(subchannel.equals("queuename")) { + BungeeUtils.sendCustomData(player, "queuename", man.getQueuedName(player)); + } + if(subchannel.equals("position")) { + Server server = man.findPlayerInQueue(player); + String pos = msgs.get("placeholders.position.none"); + if(server != null) { + pos = server.getQueue().indexOf(player)+1+""; + } + BungeeUtils.sendCustomData(player, "position", pos); + } + if(subchannel.equals("positionof")) { + Server server = man.findPlayerInQueue(player); + String pos = msgs.get("placeholders.position.none"); + if(server != null) { + pos = server.getQueue().size()+""; + } + BungeeUtils.sendCustomData(player, "positionof", pos); + } } catch (IOException e1) { getLogger().warning("An error occured while reading data from spigot side:"); diff --git a/src/main/java/us/ajg0702/queue/Manager.java b/src/main/java/us/ajg0702/queue/Manager.java index edcbea3..771cb3c 100644 --- a/src/main/java/us/ajg0702/queue/Manager.java +++ b/src/main/java/us/ajg0702/queue/Manager.java @@ -89,6 +89,19 @@ public class Manager { }, 0, 2, TimeUnit.SECONDS).getId(); } + /** + * Get the name of the server the player is queued for + * @param p The player + * @return The name of the server, the placeholder none message if not queued + */ + public String getQueuedName(ProxiedPlayer p) { + Server queued = findPlayerInQueue(p); + if(queued == null) { + return msgs.get("placeholders.queued.none"); + } + return queued.getName(); + } + @@ -326,8 +339,13 @@ public class Manager { msgs.get("status.now-in-queue") .replaceAll("\\{POS\\}", pos+"") .replaceAll("\\{LEN\\}", len+"") + .replaceAll("\\{SERVER\\}", s) )); + BungeeUtils.sendCustomData(p, "position", pos+""); + BungeeUtils.sendCustomData(p, "positionof", len+""); + BungeeUtils.sendCustomData(p, "queuename", s); + if(list.size() <= 1) { sendPlayers(s); } diff --git a/src/main/java/us/ajg0702/queue/spigot/Main.java b/src/main/java/us/ajg0702/queue/spigot/Main.java index bd7ab87..112c1d3 100644 --- a/src/main/java/us/ajg0702/queue/spigot/Main.java +++ b/src/main/java/us/ajg0702/queue/spigot/Main.java @@ -1,7 +1,12 @@ package us.ajg0702.queue.spigot; +import java.util.HashMap; + import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.messaging.PluginMessageListener; @@ -11,13 +16,26 @@ import com.google.common.io.ByteStreams; import us.ajg0702.queue.spigot.utils.VersionSupport; -public class Main extends JavaPlugin implements PluginMessageListener { +public class Main extends JavaPlugin implements PluginMessageListener,Listener { + + boolean papi = false; + Placeholders placeholders; public void onEnable() { getServer().getMessenger().registerIncomingPluginChannel(this, "ajqueue:tospigot", this); getServer().getMessenger().registerOutgoingPluginChannel(this, "ajqueue:tobungee"); this.getCommand("move").setExecutor(new Commands(this)); + Bukkit.getPluginManager().registerEvents(this, this); + + papi = Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null; + + if(papi) { + placeholders = new Placeholders(this); + placeholders.register(); + getLogger().info("Registered PlaceholderAPI placeholders"); + } + getLogger().info("Spigot side enabled! v"+getDescription().getVersion()); } @@ -40,6 +58,42 @@ public class Main extends JavaPlugin implements PluginMessageListener { VersionSupport.sendActionBar(p, text); return; } + if(subchannel.equals("queuename")) { + String playername = in.readUTF(); + Player p = Bukkit.getPlayer(playername); + if(p == null) return; + if(!p.isOnline()) return; + + String data = in.readUTF(); + HashMap phs = placeholders.responseCache.get(p); + if(phs == null) phs = new HashMap<>(); + phs.put("queued", data); + placeholders.responseCache.put(p, phs); + } + if(subchannel.equals("position")) { + String playername = in.readUTF(); + Player p = Bukkit.getPlayer(playername); + if(p == null) return; + if(!p.isOnline()) return; + + String data = in.readUTF(); + HashMap phs = placeholders.responseCache.get(p); + if(phs == null) phs = new HashMap<>(); + phs.put("position", data); + placeholders.responseCache.put(p, phs); + } + if(subchannel.equals("positionof")) { + String playername = in.readUTF(); + Player p = Bukkit.getPlayer(playername); + if(p == null) return; + if(!p.isOnline()) return; + + String data = in.readUTF(); + HashMap phs = placeholders.responseCache.get(p); + if(phs == null) phs = new HashMap<>(); + phs.put("of", data); + placeholders.responseCache.put(p, phs); + } } @@ -51,4 +105,10 @@ public class Main extends JavaPlugin implements PluginMessageListener { player.sendPluginMessage(this, "ajqueue:tobungee", out.toByteArray()); } + + @EventHandler + public void onLeave(PlayerQuitEvent e) { + if(!papi) return; + placeholders.cleanCache(); + } } diff --git a/src/main/java/us/ajg0702/queue/spigot/Placeholders.java b/src/main/java/us/ajg0702/queue/spigot/Placeholders.java new file mode 100644 index 0000000..49f2c25 --- /dev/null +++ b/src/main/java/us/ajg0702/queue/spigot/Placeholders.java @@ -0,0 +1,197 @@ +package us.ajg0702.queue.spigot; + +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Iterator; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import me.clip.placeholderapi.expansion.PlaceholderExpansion; + +/** + * This class will be registered through the register-method in the + * plugins onEnable-method. + */ +public class Placeholders extends PlaceholderExpansion { + + private Main plugin; + + /** + * Since we register the expansion inside our own plugin, we + * can simply use this method here to get an instance of our + * plugin. + * + * @param plugin + * The instance of our plugin. + */ + public Placeholders(Main plugin){ + this.plugin = plugin; + } + + /** + * Because this is an internal class, + * you must override this method to let PlaceholderAPI know to not unregister your expansion class when + * PlaceholderAPI is reloaded + * + * @return true to persist through reloads + */ + @Override + public boolean persist(){ + return true; + } + + /** + * Because this is a internal class, this check is not needed + * and we can simply return {@code true} + * + * @return Always true since it's an internal class. + */ + @Override + public boolean canRegister(){ + return true; + } + + /** + * The name of the person who created this expansion should go here. + *
For convienience do we return the author from the plugin.yml + * + * @return The name of the author as a String. + */ + @Override + public String getAuthor(){ + return plugin.getDescription().getAuthors().toString(); + } + + /** + * The placeholder identifier should go here. + *
This is what tells PlaceholderAPI to call our onRequest + * method to obtain a value if a placeholder starts with our + * identifier. + *
This must be unique and can not contain % or _ + * + * @return The identifier in {@code %_%} as String. + */ + @Override + public String getIdentifier(){ + return "ajqueue"; + } + + /** + * This is the version of the expansion. + *
You don't have to use numbers, since it is set as a String. + * + * For convienience do we return the version from the plugin.yml + * + * @return The version as a String. + */ + @Override + public String getVersion(){ + return plugin.getDescription().getVersion(); + } + + HashMap> responseCache = new HashMap<>(); + + public void cleanCache() { + Iterator it = responseCache.keySet().iterator(); + while(it.hasNext()) { + Player p = it.next(); + if(p == null) { + it.remove(); + continue; + } + if(!p.isOnline()) { + it.remove(); + } + } + } + + /** + * This is the method called when a placeholder with our identifier + * is found and needs a value. + *
We specify the value identifier in this method. + *
Since version 2.9.1 can you use OfflinePlayers in your requests. + * + * @param player + * A {@link org.bukkit.PkPlayer Player}. + * @param identifier + * A String containing the identifier/value. + * + * @return possibly-null String of the requested identifier. + */ + @Override + public String onPlaceholderRequest(Player player, final String identifier){ + //Bukkit.getLogger().info("itentifier: "+identifier); + + + String noc = "_nocache"; + if(identifier.length() > noc.length()) { + int olen = identifier.length()-noc.length(); + if(identifier.indexOf(noc) == olen) { + String idfr = identifier.substring(0, olen); + return this.parsePlaceholder(player, idfr); + } + } + + Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { + public void run() { + HashMap playerCache; + if(responseCache.containsKey(player)) { + playerCache = responseCache.get(player); + } else { + playerCache = new HashMap(); + } + if(playerCache.size() > 75) { + try { + playerCache.remove(playerCache.keySet().toArray()[0]); + } catch(ConcurrentModificationException e) { + Bukkit.getScheduler().runTask(plugin, new Runnable() { + public void run() { + playerCache.remove(playerCache.keySet().toArray()[0]); + } + }); + } + } + String resp = parsePlaceholder(player, identifier); + if(resp == null) return; + playerCache.put(identifier, resp); + responseCache.put(player, playerCache); + } + }); + + + if(responseCache.containsKey(player)) { + HashMap playerCache = responseCache.get(player); + if(playerCache.containsKey(identifier)) { + return playerCache.get(identifier); + } + } else { + if(identifier.equalsIgnoreCase("queued")) { + return "None"; + } + if(identifier.equalsIgnoreCase("position") || identifier.equalsIgnoreCase("of")) { + return "None"; + } + } + + + return null; + } + + private String parsePlaceholder(Player player, String identifier) { + if(identifier.equalsIgnoreCase("queued")) { + plugin.sendMessage(player, "queuename", ""); + return null; + } + if(identifier.equalsIgnoreCase("position")) { + plugin.sendMessage(player, "position", ""); + return null; + } + if(identifier.equalsIgnoreCase("of")) { + plugin.sendMessage(player, "positionof", ""); + return null; + } + + + return null; + } +} diff --git a/src/main/java/us/ajg0702/queue/utils/BungeeMessages.java b/src/main/java/us/ajg0702/queue/utils/BungeeMessages.java index 19f9eb5..39c47d4 100644 --- a/src/main/java/us/ajg0702/queue/utils/BungeeMessages.java +++ b/src/main/java/us/ajg0702/queue/utils/BungeeMessages.java @@ -84,6 +84,9 @@ public class BungeeMessages { d.put("send", "&aAdded &f{PLAYER}&a to the queue for &f{SERVER}"); + d.put("placeholders.queued.none", "None"); + d.put("placeholders.position.none", "None"); + for(String k : d.keySet()) { if(!msgs.contains(k)) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index f031858..d4a001e 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -2,6 +2,7 @@ main: us.ajg0702.queue.spigot.Main version: ${project.version} author: ajgeiss0702 name: ajQueue +softdepend: [PlaceholderAPI] commands: move: aliases: [server, queue]