diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8b2c76d..bcd3c01 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,6 +14,7 @@ build: script: - gradle clean :free:shadowJar artifacts: + untracked: true paths: - free/build/libs diff --git a/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java b/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java index 9ae7d58..ce7fc5f 100644 --- a/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java +++ b/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java @@ -95,6 +95,13 @@ public abstract class AjQueueAPI { */ public abstract LogicGetter getLogicGetter(); + /** + * Gets the protocol name manager + * Used to get version names from protocol versions + * @return The ProtocolNameManager + */ + public abstract ProtocolNameManager getProtocolNameManager(); + /** * Tells ajQueue to shut down. */ diff --git a/api/src/main/java/us/ajg0702/queue/api/PlatformMethods.java b/api/src/main/java/us/ajg0702/queue/api/PlatformMethods.java index 14bfcc4..367c8a1 100644 --- a/api/src/main/java/us/ajg0702/queue/api/PlatformMethods.java +++ b/api/src/main/java/us/ajg0702/queue/api/PlatformMethods.java @@ -6,6 +6,7 @@ import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.server.AdaptedServer; import java.util.List; +import java.util.UUID; public interface PlatformMethods { @@ -15,7 +16,6 @@ public interface PlatformMethods { * @param channel The (sub)channel * @param data The data */ - @SuppressWarnings("EmptyMethod") void sendPluginMessage(AdaptedPlayer player, String channel, String... data); /** @@ -27,12 +27,34 @@ public interface PlatformMethods { String getPluginVersion(); + @SuppressWarnings("unused") List getOnlinePlayers(); List getPlayerNames(boolean lowercase); + + /** + * Gets an online player by their name + * @param name The players name + * @return The AdaptedPlayer for this player + */ AdaptedPlayer getPlayer(String name); + /** + * Gets an online player by their UUID + * @param uuid their UUID + * @return the AdaptedPlayer for this player + */ + AdaptedPlayer getPlayer(UUID uuid); + + /** + * Gets a list of the server names + * @return A list of the server names + */ List getServerNames(); + /** + * Gets the name of the implementation. E.g. bungeecord, velocity + * @return the name of the implementation + */ String getImplementationName(); List getCommands(); @@ -44,7 +66,14 @@ public interface PlatformMethods { */ boolean hasPlugin(String pluginName); + /** + * Gets an AdaptedServer from the server name + * @param name The name of the server + * @return The AdaptedServer + */ AdaptedServer getServer(String name); List getServers(); + + String getProtocolName(int protocol); } diff --git a/api/src/main/java/us/ajg0702/queue/api/ProtocolNameManager.java b/api/src/main/java/us/ajg0702/queue/api/ProtocolNameManager.java new file mode 100644 index 0000000..5806460 --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/ProtocolNameManager.java @@ -0,0 +1,8 @@ +package us.ajg0702.queue.api; + +import java.util.HashMap; + +public interface ProtocolNameManager { + String getProtocolName(int protocol); + HashMap getProtocolNames(); +} diff --git a/api/src/main/java/us/ajg0702/queue/api/players/AdaptedPlayer.java b/api/src/main/java/us/ajg0702/queue/api/players/AdaptedPlayer.java index 7e725e4..2f63a0d 100644 --- a/api/src/main/java/us/ajg0702/queue/api/players/AdaptedPlayer.java +++ b/api/src/main/java/us/ajg0702/queue/api/players/AdaptedPlayer.java @@ -66,6 +66,12 @@ public interface AdaptedPlayer extends Handle, Audience { */ void connect(AdaptedServer server); + /** + * Returns the version this player is running. + * @return the version + */ + int getProtocolVersion(); + /** * Gets the player's username * @return the player's username diff --git a/api/src/main/java/us/ajg0702/queue/api/queues/QueueServer.java b/api/src/main/java/us/ajg0702/queue/api/queues/QueueServer.java index be6fc20..d860358 100644 --- a/api/src/main/java/us/ajg0702/queue/api/queues/QueueServer.java +++ b/api/src/main/java/us/ajg0702/queue/api/queues/QueueServer.java @@ -218,6 +218,20 @@ public interface QueueServer { */ HashMap getLastPings(); + /** + * Gets the protocol versions this queue supports. + * A blank list means all protocols are supported. + * @return The protocol versions this queue supports + */ + List getSupportedProtocols(); + + /** + * Sets the protocols that are supported + * A blank list means all protocols are supported. + * @param list the list of protocols that are supported + */ + void setSupportedProtocols(List list); + /** * elliot is bad diff --git a/build.gradle.kts b/build.gradle.kts index 99e913c..06cabdd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ repositories { } allprojects { - version = "2.0.4" + version = "2.0.5" group = "us.ajg0702" plugins.apply("java") diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 511b94d..9a812b2 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -12,6 +12,8 @@ repositories { } dependencies { + testImplementation("junit:junit:4.12") + compileOnly("net.kyori:adventure-api:4.8.1") compileOnly("net.kyori:adventure-text-serializer-plain:4.0.0-SNAPSHOT") diff --git a/common/src/main/java/us/ajg0702/queue/common/ProtocolNameManagerImpl.java b/common/src/main/java/us/ajg0702/queue/common/ProtocolNameManagerImpl.java new file mode 100644 index 0000000..9f03e3c --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/ProtocolNameManagerImpl.java @@ -0,0 +1,44 @@ +package us.ajg0702.queue.common; + +import us.ajg0702.queue.api.PlatformMethods; +import us.ajg0702.queue.api.ProtocolNameManager; +import us.ajg0702.utils.common.Config; + +import java.util.HashMap; +import java.util.List; + +public class ProtocolNameManagerImpl implements ProtocolNameManager { + + private final Config config; + private final PlatformMethods platformMethods; + public ProtocolNameManagerImpl(Config config, PlatformMethods platformMethods) { + this.config = config; + this.platformMethods = platformMethods; + } + + @Override + public String getProtocolName(int protocol) { + return getProtocolNames().getOrDefault(protocol, platformMethods.getProtocolName(protocol)); + } + + @Override + public HashMap getProtocolNames() { + List raw = config.getStringList("protocol-names"); + HashMap result = new HashMap<>(); + for(String protocolRaw : raw) { + String[] parts = protocolRaw.split(":"); + if(parts.length < 2) continue; + String versionRaw = parts[0]; + String versionString = parts[1]; + int version; + try { + version = Integer.parseInt(versionRaw); + } catch(NumberFormatException e) { + continue; + } + + result.put(version, versionString); + } + return result; + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/QueueMain.java b/common/src/main/java/us/ajg0702/queue/common/QueueMain.java index 07d2bc0..092ba4e 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueMain.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueMain.java @@ -94,6 +94,12 @@ public class QueueMain extends AjQueueAPI { return logicGetter; } + private ProtocolNameManager protocolNameManager; + @Override + public ProtocolNameManager getProtocolNameManager() { + return protocolNameManager; + } + @Override public void shutdown() { taskManager.shutdown(); @@ -140,6 +146,8 @@ public class QueueMain extends AjQueueAPI { logic = logicGetter.constructLogic(); aliasManager = logicGetter.constructAliasManager(config); + protocolNameManager = new ProtocolNameManagerImpl(config, platformMethods); + taskManager.rescheduleTasks(); } @@ -168,6 +176,9 @@ public class QueueMain extends AjQueueAPI { d.put("errors.already-connected", "&cYou are already connected to this server!"); d.put("errors.cant-join-paused", "&cYou cannot join the queue for {SERVER} because it is paused."); d.put("errors.deny-joining-from-server", "&cYou are not allowed to join queues from this server!"); + d.put("errors.wrong-version.base", "You must be on {VERSIONS} to join this server!"); + d.put("errors.wrong-version.or", " or "); + d.put("errors.wrong-version.comma", ", "); d.put("commands.leave-queue", "&aYou left the queue for {SERVER}!"); d.put("commands.reload", "&aConfig and messages reloaded successfully!"); diff --git a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java index 6dc192f..b2dee1f 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -55,6 +55,35 @@ public class QueueManagerImpl implements QueueManager { result.add(queueServer); } + List supportedProtocolsRaw = main.getConfig().getStringList("supported-protocols"); + for(String supportedProtocolsString : supportedProtocolsRaw) { + String[] parts = supportedProtocolsString.split(":"); + if(parts.length < 2) { + main.getLogger().warn("Invalid supported protocols entry! Must have a colon to seperate the server(s) and the protocols"); + continue; + } + String serversRaw = parts[0]; + String protocolsRaw = parts[1]; + + List protocols = new ArrayList<>(); + for(String protocolString : protocolsRaw.split(",")) { + try { + protocols.add(Integer.valueOf(protocolString)); + } catch(NumberFormatException e) { + main.getLogger().info("The protocol "+protocolString+" is not a valid number!"); + } + } + + for(String serverName : serversRaw.split(",")) { + for(QueueServer server : result) { + if(serverName.equalsIgnoreCase(server.getName())) { + server.setSupportedProtocols(protocols); + break; + } + } + } + } + return result; } @@ -70,6 +99,22 @@ public class QueueManagerImpl implements QueueManager { return false; } + int playerVersion = player.getProtocolVersion(); + List supportedProtocols = server.getSupportedProtocols(); + if(!supportedProtocols.contains(playerVersion) && supportedProtocols.size() > 0) { + StringBuilder versions = new StringBuilder(); + for(int protocol : supportedProtocols) { + versions.append(main.getProtocolNameManager().getProtocolName(protocol)); + if(supportedProtocols.indexOf(protocol) == supportedProtocols.size()-2) { + versions.append(msgs.getString("errors.wrong-version.or")); + } else if(supportedProtocols.indexOf(protocol) != supportedProtocols.size()-1) { + versions.append(msgs.getString("errors.wrong-version.comma")); + } + } + player.sendMessage(msgs.getComponent("errors.wrong-version.base", "VERSIONS:" + versions)); + return false; + } + if(server.isPaused() && main.getConfig().getBoolean("prevent-joining-paused")) { player.sendMessage(msgs.getComponent("errors.cant-join-paused", "SERVER:"+server.getAlias())); return false; diff --git a/common/src/main/java/us/ajg0702/queue/common/queues/QueueServerImpl.java b/common/src/main/java/us/ajg0702/queue/common/queues/QueueServerImpl.java index fd77111..c876233 100644 --- a/common/src/main/java/us/ajg0702/queue/common/queues/QueueServerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/queues/QueueServerImpl.java @@ -62,6 +62,8 @@ public class QueueServerImpl implements QueueServer { private final List queue = new ArrayList<>(); + private List supportedProtocols = new ArrayList<>(); + private int playerCount; private int maxPlayers; @@ -160,7 +162,10 @@ public class QueueServerImpl implements QueueServer { maxPlayers = 0; for(AdaptedServer pingedServer : pings.keySet()) { AdaptedServerPing serverPing = pings.get(pingedServer); - if(serverPing == null) { + if(serverPing == null || serverPing.getPlainDescription() == null) { + if(serverPing != null) { + pings.put(pingedServer, null); + } continue; } if(serverPing.getPlainDescription().contains("ajQueue;whitelisted=")) { @@ -170,7 +175,14 @@ public class QueueServerImpl implements QueueServer { List uuids = new ArrayList<>(); for(String uuid : serverPing.getPlainDescription().substring(20).split(",")) { if(uuid.isEmpty()) continue; - uuids.add(UUID.fromString(uuid)); + UUID parsedUUID; + try { + parsedUUID = UUID.fromString(uuid); + } catch(IllegalArgumentException e) { + main.getLogger().warn("UUID '"+uuid+"' in whitelist of "+getName()+" is invalid! "+e.getMessage()); + continue; + } + uuids.add(parsedUUID); } setWhitelistedPlayers(uuids); } else { @@ -399,4 +411,14 @@ public class QueueServerImpl implements QueueServer { public HashMap getLastPings() { return new HashMap<>(pings); } + + @Override + public List getSupportedProtocols() { + return new ArrayList<>(supportedProtocols); + } + + @Override + public void setSupportedProtocols(List list) { + supportedProtocols = new ArrayList<>(list); + } } diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index 38b014d..ec92773 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -1,5 +1,13 @@ # Dont touch this number please -config-version: 25 +config-version: 26 + + +# This is the main config for ajQueue. +# If you have any questions, make sure to read the comment above the options first, +# then feel free to join my discord and ask for support. +# Discord invite link is on the plugin page. + + # The time the server will wait between sending people in the queue # Default: 5 @@ -197,4 +205,51 @@ priority-messages: # Should the plugin send a title to the player? # The title shows what position the player is in the queue # Default: false -send-title: false \ No newline at end of file +send-title: false + +# What protocols do servers support? +# The protocol version number list can be found here: https://wiki.vg/Protocol_version_numbers +# Format: server(s):protocol(s) +# Example: 1.17:755,756 +# This example will only allow 1.17 and 1.17.1 on the server called 1.17 +# Example: lobby-1,lobby-2,lobby-3:754,755,756 +# This example will only allow 1.16.5, 1.17, and 1.17.1 on the 3 lobby servers +supported-protocols: + - "1.17:755,756" + + +# These are the protocol names the plugin should use. +# If you are on velocity, if the protocol is not listed here then the velocity +# api will be used to find the name of the protocol. +# If you are on bungee, only this list can be used. +protocol-names: + - "756:1.17.1" + - "755:1.17" + - "754:1.16.5" + - "753:1.16.3" + - "751:1.16.2" + - "736:1.16.1" + - "735:1.16" + - "578:1.15.2" + - "575:1.15.1" + - "573:1.15" + - "498:1.14.4" + - "490:1.14.3" + - "485:1.14.2" + - "480:1.14.1" + - "477:1.14" + - "404:1.13.2" + - "401:1.13.1" + - "393:1.13" + - "340:1.12.2" + - "338:1.12.1" + - "335:1.12" + - "316:1.11.2" + - "315:1.11" + - "210:1.10.2" + - "110:1.9.4" + - "109:1.9.2" + - "108:1.9.1" + - "107:1.9" + - "47:1.8.9" + - "5:1.7.10" \ No newline at end of file diff --git a/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/BungeeMethods.java b/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/BungeeMethods.java index c09244e..347b20d 100644 --- a/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/BungeeMethods.java +++ b/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/BungeeMethods.java @@ -16,10 +16,7 @@ import us.ajg0702.queue.commands.commands.PlayerSender; import us.ajg0702.queue.platforms.bungeecord.players.BungeePlayer; import us.ajg0702.queue.platforms.bungeecord.server.BungeeServer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Locale; +import java.util.*; public class BungeeMethods implements PlatformMethods { @@ -87,6 +84,13 @@ public class BungeeMethods implements PlatformMethods { return new BungeePlayer(player); } + @Override + public AdaptedPlayer getPlayer(UUID uuid) { + ProxiedPlayer player = proxyServer.getPlayer(uuid); + if(player == null) return null; + return new BungeePlayer(player); + } + @Override public List getServerNames() { return new ArrayList<>(proxyServer.getServers().keySet()); @@ -122,4 +126,9 @@ public class BungeeMethods implements PlatformMethods { return result; } + + @Override + public String getProtocolName(int protocol) { + return protocol+""; + } } diff --git a/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/players/BungeePlayer.java b/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/players/BungeePlayer.java index 50c1b62..8e69d93 100644 --- a/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/players/BungeePlayer.java +++ b/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/players/BungeePlayer.java @@ -124,6 +124,11 @@ public class BungeePlayer implements AdaptedPlayer, Audience { handle.connect(((BungeeServer) server).getHandle()); } + @Override + public int getProtocolVersion() { + return handle.getPendingConnection().getVersion(); + } + @Override public String getName() { return handle.getName(); diff --git a/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServerPing.java b/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServerPing.java index 5df1d43..9175344 100644 --- a/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServerPing.java +++ b/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServerPing.java @@ -24,7 +24,7 @@ public class BungeeServerPing implements AdaptedServerPing { @Override public String getPlainDescription() { BaseComponent desc = handle.getDescriptionComponent(); - if(desc == null) return ""; + if(desc == null) return null; return desc.toPlainText(); } diff --git a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/VelocityMethods.java b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/VelocityMethods.java index e899725..f0b99ad 100644 --- a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/VelocityMethods.java +++ b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/VelocityMethods.java @@ -2,6 +2,7 @@ package us.ajg0702.queue.platforms.velocity; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; +import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; @@ -19,10 +20,7 @@ import us.ajg0702.queue.commands.commands.PlayerSender; import us.ajg0702.queue.platforms.velocity.players.VelocityPlayer; import us.ajg0702.queue.platforms.velocity.server.VelocityServer; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Optional; +import java.util.*; @SuppressWarnings("OptionalIsPresent") public class VelocityMethods implements PlatformMethods { @@ -96,7 +94,15 @@ public class VelocityMethods implements PlatformMethods { public AdaptedPlayer getPlayer(String name) { Optional player = proxyServer.getPlayer(name); if(!player.isPresent()) { - System.out.println("Player "+name+" not found"); + return null; + } + return new VelocityPlayer(player.get()); + } + + @Override + public AdaptedPlayer getPlayer(UUID uuid) { + Optional player = proxyServer.getPlayer(uuid); + if(!player.isPresent()) { return null; } return new VelocityPlayer(player.get()); @@ -142,4 +148,13 @@ public class VelocityMethods implements PlatformMethods { return result; } + + @Override + public String getProtocolName(int protocol) { + String version = ProtocolVersion.getProtocolVersion(protocol).getMostRecentSupportedVersion(); + if(version.equalsIgnoreCase("Unknown")) { + return protocol+""; + } + return version; + } } diff --git a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/players/VelocityPlayer.java b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/players/VelocityPlayer.java index cf77ebb..b430cb9 100644 --- a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/players/VelocityPlayer.java +++ b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/players/VelocityPlayer.java @@ -131,6 +131,11 @@ public class VelocityPlayer implements AdaptedPlayer, Audience { ); } + @Override + public int getProtocolVersion() { + return handle.getProtocolVersion().getProtocol(); + } + @Override public String getName() { return handle.getUsername();