Velocity queueing solution
at master 227 lines 8.5 kB view raw
1/* 2 * ProxyQueues, a Velocity queueing solution 3 * Copyright (c) 2021 James Lyne 4 * 5 * Some portions of this file were taken from https://github.com/darbyjack/DeluxeQueues 6 * These portions are Copyright (c) 2019 Glare 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a copy 9 * of this software and associated documentation files (the "Software"), to deal 10 * in the Software without restriction, including without limitation the rights 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 * copies of the Software, and to permit persons to whom the Software is 13 * furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included in all 16 * copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26package uk.co.notnull.proxyqueues.queues; 27 28import ch.jalu.configme.SettingsManager; 29import com.velocitypowered.api.proxy.Player; 30import com.velocitypowered.api.proxy.ServerConnection; 31import com.velocitypowered.api.proxy.server.RegisteredServer; 32import uk.co.notnull.proxyqueues.api.MessageType; 33import uk.co.notnull.proxyqueues.ProxyQueuesImpl; 34import uk.co.notnull.proxyqueues.api.queues.ProxyQueue; 35import uk.co.notnull.proxyqueues.api.queues.QueueHandler; 36import uk.co.notnull.proxyqueues.configuration.sections.ConfigOptions; 37import uk.co.notnull.proxyqueues.Messages; 38import org.jetbrains.annotations.NotNull; 39 40import java.util.*; 41import java.util.concurrent.ConcurrentHashMap; 42 43public final class QueueHandlerImpl implements QueueHandler { 44 45 private final ConcurrentHashMap<RegisteredServer, ProxyQueue> queues; 46 private final SettingsManager settingsManager; 47 private final ProxyQueuesImpl proxyQueues; 48 49 public QueueHandlerImpl(SettingsManager settingsManager, ProxyQueuesImpl proxyQueues) { 50 this.settingsManager = settingsManager; 51 this.proxyQueues = proxyQueues; 52 this.queues = new ConcurrentHashMap<>(); 53 54 updateQueues(); 55 } 56 57 /** 58 * Create a new queue for a server 59 * @param server The server the new queue is for 60 * @return ProxyQueue - The queue 61 */ 62 public ProxyQueue createQueue(@NotNull RegisteredServer server, int requiredPlayers, int maxNormal, int maxPriority, int maxStaff) { 63 return queues.compute(server, (s, queue) -> { 64 if(queue == null) { 65 proxyQueues.getLogger().info("Creating queue for " + server.getServerInfo().getName()); 66 return new ProxyQueueImpl(proxyQueues, s, requiredPlayers, maxNormal, maxPriority, maxStaff); 67 } else { 68 proxyQueues.getLogger().info("Updating queue for " + server.getServerInfo().getName()); 69 queue.setPlayersRequired(requiredPlayers); 70 queue.setMaxSlots(maxNormal); 71 queue.setPriorityMaxSlots(maxPriority); 72 queue.setStaffMaxSlots(maxStaff); 73 74 return queue; 75 } 76 }); 77 } 78 79 /** 80 * Delete a queue if it exists 81 * @param server The server to remove the queue for 82 */ 83 public void deleteQueue(@NotNull RegisteredServer server) { 84 queues.computeIfPresent(server, (s, queue) -> { 85 queue.destroy(); 86 return null; 87 }); 88 } 89 90 /** 91 * Get a queue from it's server 92 * @param server the server to get the queue for 93 * @return the queue 94 */ 95 public ProxyQueue getQueue(@NotNull RegisteredServer server) { 96 return queues.get(server); 97 } 98 99 /** 100 * Get a queue from it's server 101 * @param player the server to get the queue from 102 * @return the queue 103 */ 104 public Optional<ProxyQueue> getCurrentQueue(@NotNull Player player) { 105 return queues.values().stream() 106 .filter(q -> q.isPlayerQueued(player)).findFirst(); 107 } 108 109 public Optional<ProxyQueue> getCurrentQueue(@NotNull UUID uuid) { 110 return queues.values().stream() 111 .filter(q -> q.isPlayerQueued(uuid)).findFirst(); 112 } 113 114 /** 115 * Remove a player from all queues 116 * @param player the player to remove 117 */ 118 public void clearPlayer(Player player) { 119 clearPlayer(player, true); 120 } 121 122 /** 123 * Remove a player from all queues 124 * @param uuid the UUID of the player to remove 125 */ 126 public void clearPlayer(UUID uuid) { 127 clearPlayer(uuid, true); 128 } 129 130 /** 131 * Remove a player from all queues 132 * @param player The player to remove 133 */ 134 public void clearPlayer(Player player, boolean silent) { 135 queues.forEach((server, queue) -> queue.removePlayer(player, false)); 136 137 if(silent) { 138 return; 139 } 140 141 notifyQueueRemoval(player, "commands.leave-success", MessageType.INFO); 142 } 143 144 /** 145 * Remove a player from all queues 146 * @param uuid The UUID of the player to remove 147 */ 148 public void clearPlayer(UUID uuid, boolean silent) { 149 queues.forEach((server, queue) -> queue.removePlayer(uuid, false)); 150 151 if(silent) { 152 return; 153 } 154 155 ProxyQueuesImpl.getInstance().getProxyServer().getPlayer(uuid).ifPresent( 156 onlinePlayer -> notifyQueueRemoval(onlinePlayer, "commands.leave-success", MessageType.INFO)); 157 } 158 159 public void kickPlayer(Player player) { 160 clearPlayer(player, true); 161 notifyQueueRemoval(player, "errors.queue-removed", MessageType.ERROR); 162 } 163 164 public void kickPlayer(UUID uuid) { 165 clearPlayer(uuid, true); 166 167 ProxyQueuesImpl.getInstance().getProxyServer().getPlayer(uuid).ifPresent( 168 onlinePlayer -> notifyQueueRemoval(onlinePlayer, "errors.queue-removed", MessageType.ERROR)); 169 } 170 171 private void notifyQueueRemoval(Player player, String message, MessageType messageType) { 172 if(!player.isActive()) { 173 return; 174 } 175 176 RegisteredServer waitingServer = proxyQueues.getWaitingServer().orElse(null); 177 Optional<ServerConnection> currentServer = player.getCurrentServer(); 178 179 if(currentServer.isPresent() && currentServer.get().getServer().equals(waitingServer)) { 180 player.disconnect(Messages.getComponent(message)); 181 } else { 182 proxyQueues.sendMessage(player, messageType, message); 183 } 184 } 185 186 /** 187 * Updates all queues from the config, creating/updating/deleting as required 188 */ 189 public void updateQueues() { 190 ArrayList<RegisteredServer> queuedServers = new ArrayList<>(); 191 192 settingsManager.getProperty(ConfigOptions.QUEUE_SERVERS).forEach(s -> { 193 try { 194 String[] split = s.split(";"); 195 String serverName = split[0]; 196 197 int requiredPlayers = Integer.parseInt(split[1]), 198 maxNormal = Integer.parseInt(split[2]), 199 maxPriority = Integer.parseInt(split[3]), 200 maxStaff = Integer.parseInt(split[4]); 201 202 RegisteredServer server = proxyQueues.getProxyServer().getServer(serverName).orElseThrow(); 203 204 ProxyQueue queue = createQueue(server, requiredPlayers, maxNormal, maxPriority, maxStaff); 205 queue.setDelayLength(settingsManager.getProperty(ConfigOptions.DELAY_LENGTH)); 206 207 queuedServers.add(server); 208 } catch (Exception ex) { 209 proxyQueues.getLogger().warn("It seems like one of your servers was configured invalidly in the config."); 210 ex.printStackTrace(); 211 } 212 }); 213 214 Iterator<Map.Entry<RegisteredServer, ProxyQueue>> it = queues.entrySet().iterator(); 215 216 //Delete queues removed from config 217 while(it.hasNext()) { 218 Map.Entry<RegisteredServer, ProxyQueue> pair = it.next(); 219 220 if(!queuedServers.contains(pair.getKey())) { 221 proxyQueues.getLogger().info("Deleting queue for " + pair.getKey().getServerInfo().getName()); 222 pair.getValue().destroy(); 223 it.remove(); 224 } 225 } 226 } 227}