package us.ajg0702.queue; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; import us.ajg0702.utils.bungee.BungeeMessages; import us.ajg0702.utils.bungee.BungeeUtils; public class Manager { static Manager INSTANCE = null; public static Manager getInstance(Main pl) { if(INSTANCE == null) { INSTANCE = new Manager(pl); } return INSTANCE; } public static Manager getInstance() { return INSTANCE; } BungeeMessages msgs; Main pl; private Manager(Main pl) { this.pl = pl; msgs = BungeeMessages.getInstance(); reloadIntervals(); if(!pl.config.getBoolean("wait-to-load-servers")) { reloadServers(); } else { pl.getProxy().getScheduler().schedule(pl, new Runnable() { public void run() { reloadServers(); } }, pl.config.getInt("wait-to-load-servers-delay"), TimeUnit.MILLISECONDS); } } /* * Returns all servers */ public List getServers() { return servers; } /** * Returns the name of all servers * @return The names of all servers */ public List getServerNames() { List names = new ArrayList<>(); for(Server s : servers) { names.add(s.getName()); } return names; } int sendId = -1; int updateId = -1; int messagerId = -1; int actionbarId = -1; int srvRefId = -1; /** * Clears all intervals and re-makes them */ public void reloadIntervals() { if(sendId != -1) { pl.getProxy().getScheduler().cancel(sendId); } if(updateId != -1) { pl.getProxy().getScheduler().cancel(updateId); } if(messagerId != -1) { pl.getProxy().getScheduler().cancel(messagerId); } if(actionbarId != -1) { pl.getProxy().getScheduler().cancel(actionbarId); } if(srvRefId != -1) { pl.getProxy().getScheduler().cancel(srvRefId); } sendId = pl.getProxy().getScheduler().schedule(pl, new Runnable() { public void run() { sendPlayers(); } }, 2, Math.round(pl.timeBetweenPlayers*1000), TimeUnit.MILLISECONDS).getId(); updateId = pl.getProxy().getScheduler().schedule(pl, new Runnable() { public void run() { updateServers(); } }, 0, Math.max(Math.round(pl.timeBetweenPlayers), 2), TimeUnit.SECONDS).getId(); //pl.getLogger().info("Time: "+pl.timeBetweenPlayers); messagerId = pl.getProxy().getScheduler().schedule(pl, new Runnable() { public void run() { sendMessages(); } }, 0, pl.getConfig().getInt("message-time"), TimeUnit.SECONDS).getId(); actionbarId = pl.getProxy().getScheduler().schedule(pl, new Runnable() { public void run() { sendActionBars(); } }, 0, 2, TimeUnit.SECONDS).getId(); if(pl.config.getInt("reload-servers-interval") > 0) { srvRefId = pl.getProxy().getScheduler().schedule(pl, new Runnable() { public void run() { updateServers(); } }, pl.config.getInt("reload-servers-interval"), pl.config.getInt("reload-servers-interval"), TimeUnit.SECONDS).getId(); } } /** * Get the name of the server the player is queued for. * If multiple servers are queued for, it will use the multi-server-queue-pick option in the config * @param p The player * @return The name of the server, the placeholder none message if not queued */ public String getQueuedName(ProxiedPlayer p) { List queued = findPlayerInQueue(p); if(queued.size() <= 0) { return msgs.get("placeholders.queued.none"); } Server selected = queued.get(0); if(pl.config.getString("multi-server-queue-pick").equalsIgnoreCase("last")) { selected = queued.get(queued.size()-1); } return selected.getName(); } /** * Get a single server the player is queued for. Depends on the multi-server-queue-pick option in the config * @param p The player * @return The server that was chosen that the player is queued for. */ public Server getSingleServer(ProxiedPlayer p) { List queued = findPlayerInQueue(p); if(queued.size() <= 0) { return null; } Server selected = queued.get(0); if(pl.config.getString("multi-server-queue-pick").equalsIgnoreCase("last")) { selected = queued.get(queued.size()-1); } return selected; } List servers = new ArrayList<>(); /** * Checks servers that are in bungeecord and adds any it doesnt * know about. */ public void reloadServers() { Map svs = ProxyServer.getInstance().getServers(); for(String name : svs.keySet()) { if(findServer(name) != null) continue; ServerInfo info = svs.get(name); servers.add(new Server(name, info)); } } /** * Sends actionbar updates to all players in all queues with their * position in the queue and time remaining */ public void sendActionBars() { if(!pl.getConfig().getBoolean("send-actionbar")) return; for(ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) { Server s = this.getSingleServer(p); if(s == null) continue; List plys = s.getQueue(); int pos = plys.indexOf(p)+1; if(pos == 0) { plys.remove(p); continue; } int len = plys.size(); if(!s.isJoinable(p)) { String status = "unknown"; if(!s.isOnline()) { status = msgs.get("status.offline.restarting"); } if(s.getOfflineTime() > pl.config.getInt("offline-time")) { status = msgs.get("status.offline.offline"); } if(!s.canAccess(p)) { status = msgs.get("status.offline.restricted"); } if(s.isFull()) { status = msgs.get("status.offline.full"); } if(s.isPaused()) { status = msgs.get("status.offline.paused"); } BungeeUtils.sendCustomData(p, "actionbar", msgs.get("spigot.actionbar.offline") .replaceAll("\\{POS\\}", pos+"") .replaceAll("\\{LEN\\}", len+"") .replaceAll("\\{SERVER\\}", pl.aliases.getAlias(s.getName())) .replaceAll("\\{STATUS\\}", status)+";time="+pl.timeBetweenPlayers); } else { int time = (int) Math.round(pos*pl.timeBetweenPlayers); int min = (int) Math.floor((time) / (60)); int sec = (int) Math.floor((time % (60))); String timeStr; if(min <= 0) { timeStr = msgs.get("format.time.secs") .replaceAll("\\{m\\}", "0") .replaceAll("\\{s\\}", sec+""); } else { timeStr = msgs.get("format.time.mins") .replaceAll("\\{m\\}", min+"") .replaceAll("\\{s\\}", sec+""); } BungeeUtils.sendCustomData(p, "actionbar", msgs.get("spigot.actionbar.online") .replaceAll("\\{POS\\}", pos+"") .replaceAll("\\{LEN\\}", len+"") .replaceAll("\\{SERVER\\}", pl.aliases.getAlias(s.getName())) .replaceAll("\\{TIME\\}", timeStr)+";time="+pl.timeBetweenPlayers); } } /*for(Server s : servers) { int ot = s.getOfflineTime(); List plys = s.getQueue(); Iterator it = plys.iterator(); while(it.hasNext()) { ProxiedPlayer ply = it.next(); int pos = plys.indexOf(ply)+1; if(pos == 0) { plys.remove(ply); continue; } int len = plys.size(); if(!s.isOnline() || s.isFull() || !s.canAccess(ply)) { String status = msgs.get("status.offline.restarting"); if(ot > pl.config.getInt("offline-time")) { status = msgs.get("status.offline.offline"); } if(!s.canAccess(ply)) { status = msgs.get("status.offline.restricted"); } BungeeUtils.sendCustomData(ply, "actionbar", msgs.get("spigot.actionbar.offline") .replaceAll("\\{POS\\}", pos+"") .replaceAll("\\{LEN\\}", len+"") .replaceAll("\\{SERVER\\}", s.getName()) .replaceAll("\\{STATUS\\}", status)+";time="+pl.timeBetweenPlayers); } else { int time = pos*pl.timeBetweenPlayers; int min = (int) Math.floor((time) / (60)); int sec = (int) Math.floor((time % (60))); String timeStr; if(min <= 0) { timeStr = msgs.get("format.time.secs") .replaceAll("\\{m\\}", "0") .replaceAll("\\{s\\}", sec+""); } else { timeStr = msgs.get("format.time.mins") .replaceAll("\\{m\\}", min+"") .replaceAll("\\{s\\}", sec+""); } BungeeUtils.sendCustomData(ply, "actionbar", msgs.get("spigot.actionbar.online") .replaceAll("\\{POS\\}", pos+"") .replaceAll("\\{LEN\\}", len+"") .replaceAll("\\{SERVER\\}", s.getName()) .replaceAll("\\{TIME\\}", timeStr)+";time="+pl.timeBetweenPlayers); } } }*/ } /** * Sends the message to the player updating them on their position in the queue * along with their time remaining */ public void sendMessages() { for(Server s : servers) { int ot = s.getOfflineTime(); List plys = s.getQueue(); for(ProxiedPlayer ply : plys) { int pos = plys.indexOf(ply)+1; if(pos == 0) { plys.remove(ply); continue; } int len = plys.size(); if(!s.isJoinable(ply)) { String status = msgs.get("status.offline.restarting"); if(ot > pl.config.getInt("offline-time")) { status = msgs.get("status.offline.offline"); } if(s.isFull() && s.isOnline()) { status = msgs.get("status.offline.full"); } if(!s.canAccess(ply)) { status = msgs.get("status.offline.restricted"); } if(s.isPaused()) { status = msgs.get("status.offline.paused"); } ply.sendMessage(Main.formatMessage( msgs.get("status.offline.base") .replaceAll("\\{STATUS\\}", status) .replaceAll("\\{POS\\}", pos+"") .replaceAll("\\{LEN\\}", len+"") .replaceAll("\\{SERVER\\}", pl.aliases.getAlias(s.getName())) )); } else { int time = (int) Math.round(pos*pl.timeBetweenPlayers); int min = (int) Math.floor((time) / (60)); int sec = (int) Math.floor((time % (60))); String timeStr; if(min <= 0) { timeStr = msgs.get("format.time.secs") .replaceAll("\\{m\\}", "0") .replaceAll("\\{s\\}", sec+""); } else { timeStr = msgs.get("format.time.mins") .replaceAll("\\{m\\}", min+"") .replaceAll("\\{s\\}", sec+""); } ply.sendMessage(Main.formatMessage( msgs.get("status.online.base") .replaceAll("\\{POS\\}", pos+"") .replaceAll("\\{LEN\\}", len+"") .replaceAll("\\{TIME\\}", timeStr) .replaceAll("\\{SERVER\\}", pl.aliases.getAlias(s.getName())) )); } } } } /** * Find a server by name * @param name Name of the server * @return The server if it exists (otherwise null) */ public Server findServer(String name) { for(Server server : servers) { if(server.getName().equals(name)) { return server; } } return null; } /** * Updates info about servers. */ public void updateServers() { Iterator it = servers.iterator(); while(it.hasNext()) { it.next().update(); } } /** * Attempts to send the first player in all queues */ public void sendPlayers() { sendPlayers(null); } /** * Attempts to send the first player in this queue * @param server The server to send the first player in the queue. null for all servers. */ public void sendPlayers(String server) { for(Server s : servers) { String name = s.getName(); if(server != null && !server.equals(name)) continue; if(!s.isOnline()) continue; if(s.isPaused()) continue; if(s.getQueue().size() <= 0) continue; if(pl.config.getBoolean("send-all-when-back-online") && s.justWentOnline() && s.isOnline()) { for(ProxiedPlayer p : s.getQueue()) { if(s.isFull() && !p.hasPermission("ajqueue.joinfull")) break; p.sendMessage(msgs.getBC("status.sending-now", "SERVER:"+pl.aliases.getAlias(name))); p.connect(s.getInfo()); } return; } ProxiedPlayer nextplayer = s.getQueue().get(0); if(!s.canAccess(nextplayer)) continue; while(nextplayer.getServer().getInfo().getName().equals(s.getName())) { s.getQueue().remove(nextplayer); if(s.getQueue().size() <= 0) break; nextplayer = s.getQueue().get(0); } if(s.getQueue().size() <= 0) continue; while(!nextplayer.isConnected()) { s.getQueue().remove(nextplayer); if(s.getQueue().size() <= 0) break; nextplayer = s.getQueue().get(0); } if(s.getQueue().size() <= 0) continue; if(s.isFull() && !nextplayer.hasPermission("ajqueue.joinfull")) continue; nextplayer.sendMessage(Main.formatMessage(msgs.get("status.sending-now").replaceAll("\\{SERVER\\}", pl.aliases.getAlias(name)))); nextplayer.connect(s.getInfo()); } } /** * Add a player to the queue for a server * @param p The player * @param s The name of the server */ public void addToQueue(ProxiedPlayer p, String s) { Server server = findServer(s); if(server == null) { p.sendMessage(msgs.getBC("errors.server-not-exist")); return; } if(pl.config.getBoolean("joinfrom-server-permission") && !p.hasPermission("ajqueue.joinfrom."+p.getServer().getInfo().getName())) { p.sendMessage(msgs.getBC("errors.deny-joining-from-server")); return; } if(server.isPaused() && pl.config.getBoolean("prevent-joining-paused")) { p.sendMessage(msgs.getBC("errors.cant-join-paused", "SERVER:"+pl.aliases.getAlias(server.getName()))); return; } if(p.getServer().getInfo().getName().equals(s)) { p.sendMessage(msgs.getBC("errors.already-connected")); return; } List beforeQueues = findPlayerInQueue(p); if(beforeQueues.size() > 0) { if(beforeQueues.contains(server)) { p.sendMessage(msgs.getBC("errors.already-queued")); return; } if(!pl.config.getBoolean("allow-multiple-queues")) { p.sendMessage(msgs.getBC("status.left-last-queue")); for(Server ser : beforeQueues) { ser.getQueue().remove(p); } } } List list = server.getQueue(); if(list.indexOf(p) != -1) { int pos = list.indexOf(p)+1; int len = list.size(); p.sendMessage(Main.formatMessage( msgs.get("errors.already-queued") .replaceAll("\\{POS\\}", pos+"") .replaceAll("\\{LEN\\}", len+"") )); return; } if(pl.isp) { us.ajg0702.queue.Logic.priorityLogic(server.getQueue(), s, p); } else { if((p.hasPermission("ajqueue.priority") || p.hasPermission("ajqueue.serverpriority."+s)) && list.size() > 0) { int i = 0; for(ProxiedPlayer ply : list) { if(!(ply.hasPermission("ajqueue.priority") || ply.hasPermission("ajqueue.serverpriority."+s))) { list.add(i, p); break; } i++; } if(list.size() == 0) { list.add(p); } } else { list.add(p); } } int pos = list.indexOf(p)+1; int len = list.size(); if(list.size() <= 1 && server.isOnline() && server.canAccess(p) && !server.isFull() && !server.isWhitelisted()) { sendPlayers(s); p.sendMessage(Main.formatMessage( msgs.get("status.now-in-empty-queue") .replaceAll("\\{POS\\}", pos+"") .replaceAll("\\{LEN\\}", len+"") .replaceAll("\\{SERVER\\}", pl.aliases.getAlias(s)) )); } else { p.sendMessage(Main.formatMessage( msgs.get("status.now-in-queue") .replaceAll("\\{POS\\}", pos+"") .replaceAll("\\{LEN\\}", len+"") .replaceAll("\\{SERVER\\}", pl.aliases.getAlias(s)) )); } BungeeUtils.sendCustomData(p, "position", pos+""); BungeeUtils.sendCustomData(p, "positionof", len+""); BungeeUtils.sendCustomData(p, "queuename", pl.aliases.getAlias(s)); BungeeUtils.sendCustomData(p, "inqueue", "true"); } /** * Finds which servers the player is queued for * @param p The player to search for * @return The servers the player is queued for. */ public List findPlayerInQueue(ProxiedPlayer p) { List srs = new ArrayList<>(); for(Server s : servers) { if(s.getQueue().contains(p)) { srs.add(s); } } return srs; } public Server getServer(String name) { return findServer(name); } }