From 4fd393c4fe367ae6de217dcd74bd9a0ded11e495 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 16 Apr 2023 10:04:23 -0700 Subject: [PATCH 01/51] Slash server commands will now not be shown if the user doesnt have permissions --- .../queue/commands/commands/SlashServer/SlashServerCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java b/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java index 0f1c93f..803b2f1 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java @@ -37,7 +37,7 @@ public class SlashServerCommand extends BaseCommand { @Override public String getPermission() { - return null; + return main.getConfig().getBoolean("require-permission") ? "ajqueue.queue."+server : null; } @Override From 1c9a41316ca5707f8574b5888899e281a1bba491 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 16 Apr 2023 12:25:08 -0700 Subject: [PATCH 02/51] Fixed fulljoin and bypasspaused priority options not working --- .../java/us/ajg0702/queue/api/premium/Logic.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java b/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java index 774f645..8e1667d 100644 --- a/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java +++ b/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java @@ -42,19 +42,19 @@ public interface Logic { Config config = AjQueueAPI.getInstance().getConfig(); int highest = 0; - int whitelitedPriority = config.getInt("give-whitelisted-players-priority"); - int bypassPausedPriotity = config.getInt("give-whitelisted-players-priority"); - int fulljoinPriority = config.getInt("give-whitelisted-players-priority"); + int whitelistedPriority = config.getInt("give-whitelisted-players-priority"); + int bypassPausedPriority = config.getInt("give-pausedbypass-players-priority"); + int fulljoinPriority = config.getInt("give-fulljoin-players-priority"); - if(whitelitedPriority > 0) { + if(whitelistedPriority > 0) { if(server.isWhitelisted() && server.getWhitelistedPlayers().contains(player.getUniqueId())) { - highest = whitelitedPriority; + highest = whitelistedPriority; } } - if(bypassPausedPriotity > 0) { + if(bypassPausedPriority > 0) { if(queueServer.isPaused() && (player.hasPermission("ajqueue.bypasspaused"))) { - highest = Math.max(highest, bypassPausedPriotity); + highest = Math.max(highest, bypassPausedPriority); } } From 786a302a2a5822178932ec4fe80ffd0fd59f2544 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Thu, 20 Apr 2023 14:19:09 -0700 Subject: [PATCH 03/51] (spigot) echo queue name when sending a player to a queue --- spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java b/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java index 982ec0a..7e2b6f9 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java @@ -47,7 +47,7 @@ public class Commands implements CommandExecutor { String srvname = args[0]; if(args.length > 1) { - pl.getLogger().info("Sending "+args[0]+" to queue"); + pl.getLogger().info("Sending "+args[0]+" to queue '" + args[1] + "'"); if(!sender.hasPermission("ajqueue.send")) { sender.sendMessage(color("&cYou do not have permission to do this!")); return true; From e9bfeb22b9ce084c8d45db78c7f005760cc693b4 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 23 Apr 2023 19:10:53 -0700 Subject: [PATCH 04/51] Update adventure --- api/build.gradle.kts | 4 ++-- common/build.gradle.kts | 4 ++-- free/build.gradle.kts | 2 +- platforms/bungeecord/build.gradle.kts | 4 ++-- platforms/velocity/build.gradle.kts | 2 +- premium/build.gradle.kts | 2 +- spigot/build.gradle.kts | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 432dcef..89724a8 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -14,8 +14,8 @@ repositories { } dependencies { - implementation("net.kyori:adventure-api:4.9.3") - implementation("net.kyori:adventure-text-serializer-plain:4.9.3") + implementation("net.kyori:adventure-api:4.13.1") + implementation("net.kyori:adventure-text-serializer-plain:4.13.1") compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("us.ajg0702:ajUtils:1.2.10") diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 6b85863..da816f9 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -14,8 +14,8 @@ repositories { dependencies { testImplementation("junit:junit:4.12") - compileOnly("net.kyori:adventure-api:4.9.3") - compileOnly("net.kyori:adventure-text-serializer-plain:4.9.3") + compileOnly("net.kyori:adventure-api:4.13.1") + compileOnly("net.kyori:adventure-text-serializer-plain:4.13.1") compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("us.ajg0702:ajUtils:1.2.10") diff --git a/free/build.gradle.kts b/free/build.gradle.kts index cea97ae..d483eb8 100644 --- a/free/build.gradle.kts +++ b/free/build.gradle.kts @@ -14,7 +14,7 @@ repositories { } dependencies { - compileOnly("net.kyori:adventure-api:4.9.3") + compileOnly("net.kyori:adventure-api:4.13.1") compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("org.spongepowered:configurate-yaml:4.0.0") diff --git a/platforms/bungeecord/build.gradle.kts b/platforms/bungeecord/build.gradle.kts index 6af3501..0641a93 100644 --- a/platforms/bungeecord/build.gradle.kts +++ b/platforms/bungeecord/build.gradle.kts @@ -14,7 +14,7 @@ repositories { } dependencies { - compileOnly("net.kyori:adventure-api:4.9.3") + compileOnly("net.kyori:adventure-api:4.13.1") compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("us.ajg0702:ajUtils:1.2.10") @@ -23,7 +23,7 @@ dependencies { implementation("net.kyori:adventure-text-minimessage:4.10.0") implementation("net.kyori:adventure-platform-bungeecord:4.0.0") - compileOnly("net.kyori:adventure-text-serializer-plain:4.9.3") + compileOnly("net.kyori:adventure-text-serializer-plain:4.13.1") compileOnly("com.viaversion:viaversion-api:4.3.1") diff --git a/platforms/velocity/build.gradle.kts b/platforms/velocity/build.gradle.kts index 9ee5692..bb00849 100644 --- a/platforms/velocity/build.gradle.kts +++ b/platforms/velocity/build.gradle.kts @@ -14,7 +14,7 @@ repositories { } dependencies { - compileOnly("net.kyori:adventure-api:4.9.3") + compileOnly("net.kyori:adventure-api:4.13.1") compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("us.ajg0702:ajUtils:1.2.10") diff --git a/premium/build.gradle.kts b/premium/build.gradle.kts index e12c799..c4d27e0 100644 --- a/premium/build.gradle.kts +++ b/premium/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { compileOnly("us.ajg0702:ajUtils:1.2.10") - compileOnly("net.kyori:adventure-api:4.9.3") + compileOnly("net.kyori:adventure-api:4.13.1") compileOnly(fileTree(mapOf("dir" to "../libs/private", "include" to listOf("*.jar")))) compileOnly(fileTree(mapOf("dir" to "../libs/public", "include" to listOf("*.jar")))) diff --git a/spigot/build.gradle.kts b/spigot/build.gradle.kts index c9d3508..d34eeff 100644 --- a/spigot/build.gradle.kts +++ b/spigot/build.gradle.kts @@ -19,7 +19,7 @@ repositories { } dependencies { - implementation("net.kyori:adventure-api:4.9.3") + implementation("net.kyori:adventure-api:4.13.1") compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("org.spongepowered:configurate-yaml:4.1.2") From f1c9749c590574906519dc0253255ea9c43fb386 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 30 Apr 2023 09:59:16 -0700 Subject: [PATCH 05/51] Throw warning instead of error when trying to send a plugin message to a player thats not connected to a server --- .../us/ajg0702/queue/platforms/velocity/VelocityMethods.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 1be9456..b552710 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 @@ -50,7 +50,8 @@ public class VelocityMethods implements PlatformMethods { } Optional server = velocityPlayer.getCurrentServer(); if(!server.isPresent()) { - throw new IllegalStateException("No server to send data to"); + logger.warn("Unable to send message to " + player.getName() + ", as they are not connected to any server!"); + return; } server.get().sendPluginMessage(MinecraftChannelIdentifier.from("ajqueue:tospigot"), out.toByteArray()); } From a91d271932fc87408e5010bb7d07d4cda8df4018 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 30 Apr 2023 10:12:41 -0700 Subject: [PATCH 06/51] Allow disabling of queue command cooldown system --- .../commands/commands/queue/QueueCommand.java | 16 ++++++++++------ common/src/main/resources/config.yml | 2 ++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/queue/QueueCommand.java b/common/src/main/java/us/ajg0702/queue/commands/commands/queue/QueueCommand.java index 7882641..0409689 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/queue/QueueCommand.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/queue/QueueCommand.java @@ -62,13 +62,17 @@ public class QueueCommand extends BaseCommand { } AdaptedPlayer player = main.getPlatformMethods().senderToPlayer(sender); - long lastUse = cooldowns.getOrDefault(player, 0L); - if(System.currentTimeMillis() - lastUse < main.getConfig().getDouble("queue-command-cooldown") * 1000L) { - sender.sendMessage(main.getMessages().getComponent("errors.too-fast-queue")); - return; - } + double cooldownTime = main.getConfig().getDouble("queue-command-cooldown"); - cooldowns.put(player, System.currentTimeMillis()); + if(cooldownTime > 0) { + long lastUse = cooldowns.getOrDefault(player, 0L); + if(System.currentTimeMillis() - lastUse < cooldownTime * 1000L) { + sender.sendMessage(main.getMessages().getComponent("errors.too-fast-queue")); + return; + } + + cooldowns.put(player, System.currentTimeMillis()); + } if(args.length > 0) { if(main.getConfig().getBoolean("require-permission") && !player.hasPermission("ajqueue.queue."+args[0])) { diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index e74f6e3..74055e5 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -314,6 +314,8 @@ give-fulljoin-players-priority: 0 force-queue-server-target: true # How long should the cooldown for queue commands be? (in seconds) +# Set to -1 to disable +# Default: 3 queue-command-cooldown: 3 # Should any server switch (including the initial join) count against the queue command cooldown? From 9f0881756dcb2c7c451e7d2f88304620792fc95e Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Wed, 24 May 2023 17:08:24 -0700 Subject: [PATCH 07/51] Legacy format velocity kick reason instead of just stripping all formatting --- .../queue/platforms/velocity/players/VelocityPlayer.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 5200956..dda062e 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 @@ -9,6 +9,7 @@ import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.sound.Sound; import net.kyori.adventure.sound.SoundStop; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.title.Title; import org.jetbrains.annotations.NotNull; @@ -153,8 +154,10 @@ public class VelocityPlayer implements AdaptedPlayer, Audience { handle.sendMessage( main.getMessages().getComponent( "velocity-kick-message", - "SERVER:"+server.getName(), - "REASON:"+PlainTextComponentSerializer.plainText().serialize(reason) + "SERVER:" + server.getName(), + "REASON:" + + LegacyComponentSerializer.legacyAmpersand() + .serialize(reason) ) ); } From c26e5835b7aef1c5e765589d837d94f71e04d7eb Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 27 May 2023 18:14:28 -0700 Subject: [PATCH 08/51] Added Spigot-side API --- api/build.gradle.kts | 1 + .../java/us/ajg0702/queue/api/AjQueueAPI.java | 7 +- .../queue/api/communication/ComResponse.java | 86 ++++++++++ .../queue/api/spigot/AjQueueSpigotAPI.java | 84 ++++++++++ .../queue/api/spigot/MessagedResponse.java | 36 ++++ .../queue/common/EventHandlerImpl.java | 123 +------------- .../communication/CommunicationManager.java | 69 ++++++++ .../common/communication/MessageHandler.java | 15 ++ .../communication/handlers/AckHandler.java | 19 +++ .../handlers/EstimatedTimeHandler.java | 39 +++++ .../handlers/InQueueHandler.java | 23 +++ .../handlers/LeaveQueueHandler.java | 25 +++ .../handlers/MassQueueHandler.java | 33 ++++ .../handlers/PlayerStatusHandler.java | 33 ++++ .../handlers/PositionHandler.java | 31 ++++ .../handlers/PositionOfHandler.java | 32 ++++ .../communication/handlers/QueueHandler.java | 25 +++ .../handlers/QueueNameHandler.java | 31 ++++ .../handlers/QueuedForHandler.java | 29 ++++ .../communication/handlers/StatusHandler.java | 32 ++++ .../queue/common/utils/MapBuilder.java | 12 ++ .../platforms/bungeecord/BungeeMethods.java | 1 - .../platforms/velocity/VelocityMethods.java | 1 - spigot/build.gradle.kts | 1 + .../us/ajg0702/queue/spigot/SpigotMain.java | 111 +++---------- .../ajg0702/queue/spigot/api/SpigotAPI.java | 157 ++++++++++++++++++ .../spigot/communication/ResponseKey.java | 34 ++++ .../spigot/communication/ResponseManager.java | 31 ++++ .../placeholders/CachedPlaceholder.java | 21 +++ .../spigot/placeholders/Placeholder.java | 32 ++++ .../placeholders/PlaceholderExpansion.java | 88 ++++++++++ .../placeholders/EstimatedTime.java | 55 ++++++ .../placeholders/placeholders/InQueue.java | 54 ++++++ .../placeholders/placeholders/Position.java | 55 ++++++ .../placeholders/placeholders/PositionOf.java | 55 ++++++ .../placeholders/placeholders/Queued.java | 55 ++++++ .../placeholders/placeholders/QueuedFor.java | 62 +++++++ .../placeholders/placeholders/Status.java | 62 +++++++ 38 files changed, 1454 insertions(+), 206 deletions(-) create mode 100644 api/src/main/java/us/ajg0702/queue/api/communication/ComResponse.java create mode 100644 api/src/main/java/us/ajg0702/queue/api/spigot/AjQueueSpigotAPI.java create mode 100644 api/src/main/java/us/ajg0702/queue/api/spigot/MessagedResponse.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/MessageHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/AckHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/EstimatedTimeHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/InQueueHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/LeaveQueueHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/MassQueueHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/PlayerStatusHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/PositionHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/PositionOfHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueNameHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueuedForHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/StatusHandler.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/utils/MapBuilder.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseKey.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseManager.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/CachedPlaceholder.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/Placeholder.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 89724a8..71cfb61 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -16,6 +16,7 @@ repositories { dependencies { implementation("net.kyori:adventure-api:4.13.1") implementation("net.kyori:adventure-text-serializer-plain:4.13.1") + implementation("com.google.code.gson:gson:2.10.1") compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("us.ajg0702:ajUtils:1.2.10") 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 2f54b52..dd3aea5 100644 --- a/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java +++ b/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java @@ -2,6 +2,7 @@ package us.ajg0702.queue.api; import us.ajg0702.queue.api.premium.Logic; import us.ajg0702.queue.api.premium.LogicGetter; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; import us.ajg0702.queue.api.util.QueueLogger; import us.ajg0702.utils.common.Config; import us.ajg0702.utils.common.Messages; @@ -11,6 +12,7 @@ import java.util.concurrent.ExecutorService; public abstract class AjQueueAPI { public static AjQueueAPI INSTANCE; + public static AjQueueSpigotAPI SPIGOT_INSTANCE; /** * Gets the instance of the ajQueue API @@ -21,6 +23,10 @@ public abstract class AjQueueAPI { return INSTANCE; } + public static AjQueueSpigotAPI getSpigotInstance() { + return SPIGOT_INSTANCE; + } + /** * Gets the time that ajQueue will wait between sending players. In seconds @@ -79,7 +85,6 @@ public abstract class AjQueueAPI { /** * Gets the event handler. - * * This class will probably be replaced in the future with an actual event system * @return the EventHandler */ diff --git a/api/src/main/java/us/ajg0702/queue/api/communication/ComResponse.java b/api/src/main/java/us/ajg0702/queue/api/communication/ComResponse.java new file mode 100644 index 0000000..bcdd5bb --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/communication/ComResponse.java @@ -0,0 +1,86 @@ +package us.ajg0702.queue.api.communication; + +import com.google.common.io.ByteArrayDataInput; + +import java.util.UUID; + +public class ComResponse { + private String from; + private String response; + private String identifier; + private String noneMessage; + + private ComResponse(String from, String response) { + this.from = from; + this.response = response; + } + + public static ComResponse from(String from) { + return new ComResponse(from, null); + } + public static ComResponse from(String from, ByteArrayDataInput in) { + String id = in.readUTF(); + String response = in.readUTF(); + String noneMessage = in.readUTF(); + + if(id.equalsIgnoreCase("null")) id = null; + if(response.equalsIgnoreCase("null")) response = null; + if(noneMessage.equalsIgnoreCase("null")) noneMessage = null; + + return from(from) + .id(id) + .with(response) + .noneMessage(noneMessage); + } + public ComResponse id(String id) { + this.identifier = id; + return this; + } + public ComResponse id(UUID id) { + this.identifier = String.valueOf(id); + return this; + } + public ComResponse with(String response) { + this.response = response; + return this; + } + public ComResponse with(boolean response) { + this.response = String.valueOf(response); + return this; + } + public ComResponse with(Integer response) { + this.response = String.valueOf(response); + return this; + } + + public ComResponse noneMessage(String message) { + this.noneMessage = message; + return this; + } + + public String getIdentifier() { + return identifier; + } + + public String getFrom() { + return from; + } + + public String getNoneMessage() { + return noneMessage; + } + + public String getResponse() { + return response; + } + + @Override + public String toString() { + return "ComResponse{" + + "from='" + from + '\'' + + ", response='" + response + '\'' + + ", identifier='" + identifier + '\'' + + ", noneMessage='" + noneMessage + '\'' + + '}'; + } +} diff --git a/api/src/main/java/us/ajg0702/queue/api/spigot/AjQueueSpigotAPI.java b/api/src/main/java/us/ajg0702/queue/api/spigot/AjQueueSpigotAPI.java new file mode 100644 index 0000000..2c191fa --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/spigot/AjQueueSpigotAPI.java @@ -0,0 +1,84 @@ +package us.ajg0702.queue.api.spigot; + +import java.util.UUID; +import java.util.concurrent.Future; + +/** + * An API that is usable from the spigot-side + */ +public abstract class AjQueueSpigotAPI { + + public static AjQueueSpigotAPI INSTANCE; + + /** + * Gets the instance of the ajQueue spigot API + * @return the ajQueue API + */ + @SuppressWarnings("unused") + public static AjQueueSpigotAPI getInstance() { + return INSTANCE; + } + + public abstract Future isInQueue(UUID player); + + /** + * Adds a player to a queue + * @param player The player to be added + * @param queueName The server or group to add the player to + * @return True if adding was successful, false if not. + */ + public abstract Future addToQueue(UUID player, String queueName); + + /** + * Gets the name of the queue that the player is in + * @param player the player + * @return the name of the queue that the player is in + */ + public abstract Future> getQueueName(UUID player); + + /** + * Gets the position of the player in their queue + * @param player The player + * @return The position of the player in their queue + */ + public abstract Future> getPosition(UUID player); + + /** + * Gets the total number of players who are in queue with the player + * @param player The player + * @return The number of player in the queue that the player is in. + */ + public abstract Future> getTotalPositions(UUID player); + + /** + * Gets the number of players in a specific queue + * @param queueName The name of the queue + * @return The number of players in that queue. + */ + public abstract Future getPlayersInQueue(String queueName); + + /** + * Gets the status string for the queue specified (e.g. full, restarting, etc) + * This is the display status, which is meant to be shown to players (and is pulled from the messages file) + * @param queueName the name of the queue + * @return The status string for the queue you specified. + */ + public abstract Future getServerStatusString(String queueName); + + /** + * Gets the status string for the queue specified (e.g. full, restarting, etc) + * This is the display status, which is meant to be shown to players (and is pulled from the messages file) + * @param queueName the name of the queue + * @param player the player to check with + * @return The status string for the queue you specified. + */ + public abstract Future getServerStatusString(String queueName, UUID player); + + /** + * Gets the estimated time until the player is sent to the server + * @param player The player to get + * @return The estimated time until the player is sent to the server + */ + public abstract Future> getEstimatedTime(UUID player); + +} diff --git a/api/src/main/java/us/ajg0702/queue/api/spigot/MessagedResponse.java b/api/src/main/java/us/ajg0702/queue/api/spigot/MessagedResponse.java new file mode 100644 index 0000000..ff4489f --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/spigot/MessagedResponse.java @@ -0,0 +1,36 @@ +package us.ajg0702.queue.api.spigot; + +public class MessagedResponse { + private final T response; + private final String none; + + public MessagedResponse(T response, String none) { + this.response = response; + this.none = none; + } + + /** + * Gets the response from the method. + * @return The response. Null if there is a "none" message + */ + public T getResponse() { + return response; + } + + /** + * Gets the "none" message + * @return The none message. null if there is a response. + */ + public String getNone() { + return none; + } + + /** + * Gets either the response (as a string) or the none message, whichever is available + * @return A string + */ + public String getEither() { + if(response == null) return none; + return String.valueOf(response); + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java index b6860d4..cde11a5 100644 --- a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java @@ -5,20 +5,16 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.jetbrains.annotations.NotNull; import us.ajg0702.queue.api.EventHandler; -import us.ajg0702.queue.api.commands.IBaseCommand; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.players.QueuePlayer; import us.ajg0702.queue.api.queues.QueueServer; import us.ajg0702.queue.api.server.AdaptedServer; -import us.ajg0702.queue.commands.commands.PlayerSender; import us.ajg0702.queue.commands.commands.manage.PauseQueueServer; import us.ajg0702.queue.commands.commands.queue.QueueCommand; +import us.ajg0702.queue.common.communication.CommunicationManager; import us.ajg0702.queue.common.players.QueuePlayerImpl; import us.ajg0702.queue.common.utils.Debug; -import us.ajg0702.utils.common.TimeUtils; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; @@ -26,121 +22,20 @@ import java.util.concurrent.TimeUnit; public class EventHandlerImpl implements EventHandler { final QueueMain main; + CommunicationManager communicationManager; public EventHandlerImpl(QueueMain main) { this.main = main; } @Override - public void handleMessage(AdaptedPlayer recievingPlayer, byte[] data) { - IBaseCommand moveCommand = main.getPlatformMethods().getCommands().get(0); - IBaseCommand leaveCommand = main.getPlatformMethods().getCommands().get(1); - DataInputStream in = new DataInputStream(new ByteArrayInputStream(data)); + public void handleMessage(AdaptedPlayer receivingPlayer, byte[] data) { + if(communicationManager == null) { + communicationManager = new CommunicationManager(main); + } try { - String subchannel = in.readUTF(); - - if(subchannel.equals("ack")) { - main.getPlatformMethods().sendPluginMessage(recievingPlayer, "ack", "yes, im here"); - } - - if(subchannel.equals("queue")) { - String rawData = in.readUTF(); - String[] args = new String[1]; - args[0] = rawData; - moveCommand.execute(new PlayerSender(recievingPlayer), args); - } - if(subchannel.equals("massqueue")) { - String inData = in.readUTF(); - String[] parts = inData.split(","); - for(String part : parts) { - String[] pparts = part.split(":"); - if(pparts.length < 2) continue; - String pname = pparts[0]; - String pserver = pparts[1]; - AdaptedPlayer p = main.getPlatformMethods().getPlayer(pname); - String[] args = new String[1]; - args[0] = pserver; - moveCommand.execute(new PlayerSender(p), args); - } - } - if(subchannel.equals("queuename")) { - QueueServer server = main.getQueueManager().getSingleServer(recievingPlayer); - String name = main.getMessages().getString("placeholders.position.none"); - if(server != null) { - name = server.getAlias(); - } - main.getPlatformMethods().sendPluginMessage(recievingPlayer, "queuename", name); - } - if(subchannel.equals("position")) { - QueueServer server = main.getQueueManager().getSingleServer(recievingPlayer); - String pos = main.getMessages().getString("placeholders.position.none"); - if(server != null) { - pos = server.getQueue().indexOf(server.findPlayer(recievingPlayer))+1+""; - } - main.getPlatformMethods().sendPluginMessage(recievingPlayer, "position", pos); - } - if(subchannel.equals("positionof")) { - QueueServer server = main.getQueueManager().getSingleServer(recievingPlayer); - String pos = main.getMessages().getString("placeholders.position.none"); - if(server != null) { - pos = server.getQueue().size()+""; - } - main.getPlatformMethods().sendPluginMessage(recievingPlayer, "positionof", pos); - } - if(subchannel.equals("estimated_time")) { - QueueServer server = main.getQueueManager().getSingleServer(recievingPlayer); - - int time; - String timeString; - if(server != null) { - QueuePlayer queuePlayer = server.findPlayer(recievingPlayer); - time = (int) Math.round(queuePlayer.getPosition() * main.getTimeBetweenPlayers()); - timeString = TimeUtils.timeString( - time, - main.getMessages().getString("format.time.mins"), - main.getMessages().getString("format.time.secs") - ); - } else { - timeString = main.getMessages().getString("placeholders.estimated_time.none"); - } - main.getPlatformMethods().sendPluginMessage( - recievingPlayer, - "estimated_time", - timeString - ); - } - if(subchannel.equals("inqueue")) { - QueueServer server = main.getQueueManager().getSingleServer(recievingPlayer); - main.getPlatformMethods().sendPluginMessage(recievingPlayer, "inqueue", (server != null)+""); - } - if(subchannel.equals("queuedfor")) { - String srv = in.readUTF(); - QueueServer server = main.getQueueManager().findServer(srv); - if(server == null) return; - main.getPlatformMethods().sendPluginMessage(recievingPlayer, "queuedfor", srv, server.getQueue().size()+""); - } - if(subchannel.equals("status")) { - String srv = in.readUTF(); - QueueServer server = main.getQueueManager().findServer(srv); - if(server == null) return; - if(!recievingPlayer.isConnected() || recievingPlayer.getServerName() == null) return; - main.getPlatformMethods().sendPluginMessage( - recievingPlayer, - "status", - srv, - main.getMessages().getRawString("placeholders.status."+server.getStatus(recievingPlayer)) - ); - } - if(subchannel.equals("leavequeue")) { - String[] args = new String[1]; - try { - args[0] = in.readUTF(); - } catch(Exception ignored) {} - leaveCommand.execute(new PlayerSender(recievingPlayer), args); - } - - } catch (IOException e1) { - main.getLogger().warning("An error occured while reading data from spigot side:"); - e1.printStackTrace(); + communicationManager.handle(receivingPlayer, data); + } catch (IOException e) { + main.getLogger().warning("An error occurred while reading data from spigot side:", e); } } diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java b/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java new file mode 100644 index 0000000..bd2eb3a --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java @@ -0,0 +1,69 @@ +package us.ajg0702.queue.common.communication; + +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.common.communication.handlers.*; +import us.ajg0702.queue.common.utils.Debug; +import us.ajg0702.queue.common.utils.MapBuilder; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.util.Map; + +public class CommunicationManager { + private final QueueMain main; + Map handlers; + + public CommunicationManager(QueueMain main) { + this.main = main; + + handlers = new MapBuilder<>( + "ack", new AckHandler(main), + + "queue", new QueueHandler(main), + "massqueue", new MassQueueHandler(main), + "leavequeue", new LeaveQueueHandler(main), + + "queuename", new QueueNameHandler(main), + "position", new PositionHandler(main), + "positionof", new PositionOfHandler(main), + "estimated_time", new EstimatedTimeHandler(main), + "inqueue", new InQueueHandler(main), + "queuedfor", new QueuedForHandler(main), + "status", new StatusHandler(main), + "playerstatus", new PlayerStatusHandler(main) + ); + } + + public void handle(AdaptedPlayer receivingPlayer, byte[] data) throws IOException { + DataInputStream in = new DataInputStream(new ByteArrayInputStream(data)); + String subChannel = in.readUTF(); + + MessageHandler handler = handlers.get(subChannel); + + if(handler == null) { + main.getLogger().warn("Invalid sub-channel " + subChannel); + return; + } + + ComResponse response = handler.handleMessage(receivingPlayer, in.readUTF()); + + if(response == null) return; + + Debug.info("Responding with " + response); + + main.getPlatformMethods().sendPluginMessage( + receivingPlayer, + s(response.getFrom()), + s(response.getIdentifier()), + s(response.getResponse()), + s(response.getNoneMessage()) + ); + } + + private String s(String s) { + return s + ""; + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/MessageHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/MessageHandler.java new file mode 100644 index 0000000..6d46c2d --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/MessageHandler.java @@ -0,0 +1,15 @@ +package us.ajg0702.queue.common.communication; + +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.common.QueueMain; + +public abstract class MessageHandler { + protected final QueueMain main; + + public MessageHandler(QueueMain main) { + this.main = main; + } + + public abstract ComResponse handleMessage(AdaptedPlayer player, String data); +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/AckHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/AckHandler.java new file mode 100644 index 0000000..5b20172 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/AckHandler.java @@ -0,0 +1,19 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class AckHandler extends MessageHandler { + public AckHandler(QueueMain main) { + super(main); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + return ComResponse + .from("ack") + .with("yes, im here"); + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/EstimatedTimeHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/EstimatedTimeHandler.java new file mode 100644 index 0000000..e9cf49e --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/EstimatedTimeHandler.java @@ -0,0 +1,39 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.players.QueuePlayer; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; +import us.ajg0702.utils.common.TimeUtils; + +public class EstimatedTimeHandler extends MessageHandler { + + public EstimatedTimeHandler(QueueMain main) { + super(main); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + QueueServer server = main.getQueueManager().getSingleServer(player); + + int time; + String timeString; + if(server != null) { + QueuePlayer queuePlayer = server.findPlayer(player); + time = (int) Math.round(queuePlayer.getPosition() * main.getTimeBetweenPlayers()); + timeString = TimeUtils.timeString( + time, + main.getMessages().getString("format.time.mins"), + main.getMessages().getString("format.time.secs") + ); + } else { + timeString = main.getMessages().getString("placeholders.estimated_time.none"); + } + return ComResponse + .from("estimated_time") + .id(player.getUniqueId()) + .with(timeString); + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/InQueueHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/InQueueHandler.java new file mode 100644 index 0000000..f21d300 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/InQueueHandler.java @@ -0,0 +1,23 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class InQueueHandler extends MessageHandler { + + public InQueueHandler(QueueMain main) { + super(main); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + QueueServer server = main.getQueueManager().getSingleServer(player); + return ComResponse + .from("inqueue") + .id(player.getUniqueId()) + .with(server != null); + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/LeaveQueueHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/LeaveQueueHandler.java new file mode 100644 index 0000000..3a33ac7 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/LeaveQueueHandler.java @@ -0,0 +1,25 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.commands.IBaseCommand; +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.commands.commands.PlayerSender; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class LeaveQueueHandler extends MessageHandler { + IBaseCommand leaveCommand; + + public LeaveQueueHandler(QueueMain main) { + super(main); + leaveCommand = main.getPlatformMethods().getCommands().get(1); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + String[] args = new String[1]; + args[0] = data; + leaveCommand.execute(new PlayerSender(player), args); + return null; + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/MassQueueHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/MassQueueHandler.java new file mode 100644 index 0000000..fd28a95 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/MassQueueHandler.java @@ -0,0 +1,33 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.commands.IBaseCommand; +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.commands.commands.PlayerSender; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class MassQueueHandler extends MessageHandler { + private final IBaseCommand moveCommand; + + public MassQueueHandler(QueueMain main) { + super(main); + moveCommand = main.getPlatformMethods().getCommands().get(0); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + String[] parts = data.split(","); + for(String part : parts) { + String[] playerParts = part.split(":"); + if(playerParts.length < 2) continue; + String playerName = playerParts[0]; + String targetServer = playerParts[1]; + AdaptedPlayer p = main.getPlatformMethods().getPlayer(playerName); + String[] args = new String[1]; + args[0] = targetServer; + moveCommand.execute(new PlayerSender(p), args); + } + return null; + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PlayerStatusHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PlayerStatusHandler.java new file mode 100644 index 0000000..62e3d6e --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PlayerStatusHandler.java @@ -0,0 +1,33 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class PlayerStatusHandler extends MessageHandler { + public PlayerStatusHandler(QueueMain main) { + super(main); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + QueueServer server = main.getQueueManager().findServer(data); + if(server == null) { + return ComResponse + .from("playerstatus") + .id(data) + .with("invalid_server"); + } + if(!player.isConnected() || player.getServerName() == null) return null; + return ComResponse + .from("playerstatus") + .id(player.getUniqueId() + data) + .with( + main.getMessages().getRawString( + "placeholders.status." + server.getStatus(player) + ) + ); + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PositionHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PositionHandler.java new file mode 100644 index 0000000..ad71e87 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PositionHandler.java @@ -0,0 +1,31 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class PositionHandler extends MessageHandler { + + public PositionHandler(QueueMain main) { + super(main); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + QueueServer server = main.getQueueManager().getSingleServer(player); + Integer pos = null; + String noneMessage = null; + if(server != null) { + pos = server.getQueue().indexOf(server.findPlayer(player)) + 1; + } else { + noneMessage = main.getMessages().getString("placeholders.position.none"); + } + return ComResponse + .from("position") + .id(player.getUniqueId()) + .with(pos) + .noneMessage(noneMessage); + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PositionOfHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PositionOfHandler.java new file mode 100644 index 0000000..0872d76 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PositionOfHandler.java @@ -0,0 +1,32 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class PositionOfHandler extends MessageHandler { + + + public PositionOfHandler(QueueMain main) { + super(main); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + QueueServer server = main.getQueueManager().getSingleServer(player); + Integer size = null; + String noneMessage = null; + if(server != null) { + size = server.getQueue().size(); + } else { + noneMessage = main.getMessages().getString("placeholders.position.none"); + } + return ComResponse + .from("positionof") + .id(player.getUniqueId()) + .with(size) + .noneMessage(noneMessage); + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueHandler.java new file mode 100644 index 0000000..30cf62a --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueHandler.java @@ -0,0 +1,25 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.commands.IBaseCommand; +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.commands.commands.PlayerSender; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class QueueHandler extends MessageHandler { + private final IBaseCommand moveCommand; + + public QueueHandler(QueueMain main) { + super(main); + moveCommand = main.getPlatformMethods().getCommands().get(0); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + String[] args = new String[1]; + args[0] = data; + moveCommand.execute(new PlayerSender(player), args); + return null; + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueNameHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueNameHandler.java new file mode 100644 index 0000000..f9793c4 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueNameHandler.java @@ -0,0 +1,31 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class QueueNameHandler extends MessageHandler { + + public QueueNameHandler(QueueMain main) { + super(main); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + QueueServer server = main.getQueueManager().getSingleServer(player); + String name = null; + String none = null; + if(server != null) { + name = server.getAlias(); + } else { + none = main.getMessages().getString("placeholders.position.none"); + } + return ComResponse + .from("queuename") + .id(player.getUniqueId()) + .with(name) + .noneMessage(none); + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueuedForHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueuedForHandler.java new file mode 100644 index 0000000..4f3e94d --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueuedForHandler.java @@ -0,0 +1,29 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class QueuedForHandler extends MessageHandler { + + public QueuedForHandler(QueueMain main) { + super(main); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + QueueServer server = main.getQueueManager().findServer(data); + if(server == null) { + return ComResponse + .from("queuedfor") + .id(data) + .with("invalid_server"); + } + return ComResponse + .from("queuedfor") + .id(data) + .with(server.getQueue().size()); + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/StatusHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/StatusHandler.java new file mode 100644 index 0000000..11f65d9 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/StatusHandler.java @@ -0,0 +1,32 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class StatusHandler extends MessageHandler { + public StatusHandler(QueueMain main) { + super(main); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + QueueServer server = main.getQueueManager().findServer(data); + if(server == null) { + return ComResponse + .from("status") + .id(data) + .with("invalid_server"); + } + return ComResponse + .from("status") + .id(data) + .with( + main.getMessages().getRawString( + "placeholders.status." + server.getStatus() + ) + ); + } +} diff --git a/common/src/main/java/us/ajg0702/queue/common/utils/MapBuilder.java b/common/src/main/java/us/ajg0702/queue/common/utils/MapBuilder.java new file mode 100644 index 0000000..e1f366a --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/utils/MapBuilder.java @@ -0,0 +1,12 @@ +package us.ajg0702.queue.common.utils; + +import java.util.LinkedHashMap; + +public class MapBuilder extends LinkedHashMap { + @SuppressWarnings("unchecked") + public MapBuilder(Object... entries) { + for (int i = 0; i < entries.length; i += 2) { + put((K) entries[i], (V) entries[i+1]); + } + } +} 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 31da45b..453ea4a 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 @@ -39,7 +39,6 @@ public class BungeeMethods implements PlatformMethods { if(playerName == null) return; ByteArrayDataOutput out = ByteStreams.newDataOutput(); out.writeUTF(channel); - out.writeUTF(playerName); for (String s : data) { out.writeUTF(s); 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 b552710..c8106c8 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 @@ -44,7 +44,6 @@ public class VelocityMethods implements PlatformMethods { String playerName = player.getName(); if(playerName == null) return; out.writeUTF( channel ); - out.writeUTF(playerName); for(String s : data) { out.writeUTF( s ); } diff --git a/spigot/build.gradle.kts b/spigot/build.gradle.kts index d34eeff..39bbdf6 100644 --- a/spigot/build.gradle.kts +++ b/spigot/build.gradle.kts @@ -20,6 +20,7 @@ repositories { dependencies { implementation("net.kyori:adventure-api:4.13.1") + compileOnly(project(":api")) compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("org.spongepowered:configurate-yaml:4.1.2") diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java b/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java index bb85f41..0fc8747 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java @@ -15,16 +15,25 @@ import org.bukkit.event.server.ServerListPingEvent; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.messaging.PluginMessageListener; import org.jetbrains.annotations.NotNull; +import us.ajg0702.queue.api.AjQueueAPI; +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; +import us.ajg0702.queue.spigot.api.SpigotAPI; +import us.ajg0702.queue.spigot.communication.ResponseManager; +import us.ajg0702.queue.spigot.placeholders.PlaceholderExpansion; import us.ajg0702.utils.common.ConfigFile; import java.io.File; import java.util.HashMap; +import java.util.logging.Level; @SuppressWarnings("UnstableApiUsage") public class SpigotMain extends JavaPlugin implements PluginMessageListener,Listener { private boolean papi = false; - private Placeholders placeholders; + private PlaceholderExpansion placeholders; + + private ResponseManager responseManager = new ResponseManager(); private ConfigFile config; @@ -34,6 +43,9 @@ public class SpigotMain extends JavaPlugin implements PluginMessageListener,List public void onEnable() { getServer().getMessenger().registerIncomingPluginChannel(this, "ajqueue:tospigot", this); getServer().getMessenger().registerOutgoingPluginChannel(this, "ajqueue:toproxy"); + + AjQueueAPI.SPIGOT_INSTANCE = new SpigotAPI(responseManager, this); + AjQueueSpigotAPI.INSTANCE = AjQueueAPI.SPIGOT_INSTANCE; this.getCommand("move").setExecutor(new Commands(this)); this.getCommand("leavequeue").setExecutor(new Commands(this)); @@ -43,7 +55,7 @@ public class SpigotMain extends JavaPlugin implements PluginMessageListener,List papi = Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null; if(papi) { - placeholders = new Placeholders(this); + placeholders = new PlaceholderExpansion(this); placeholders.register(); getLogger().info("Registered PlaceholderAPI placeholders"); } @@ -94,6 +106,7 @@ public class SpigotMain extends JavaPlugin implements PluginMessageListener,List if(subchannel.equals("ack")) { hasProxy = true; + return; } if(subchannel.equals("inqueueevent")) { @@ -102,95 +115,15 @@ public class SpigotMain extends JavaPlugin implements PluginMessageListener,List if(p == null) return; QueueScoreboardActivator e = new QueueScoreboardActivator(p); Bukkit.getPluginManager().callEvent(e); + return; } - if(subchannel.equals("queuename") && papi) { - 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") && papi) { - 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") && papi) { - 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); - } - if(subchannel.equals("inqueue") && papi) { - 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("inqueue", data); - placeholders.responseCache.put(p, phs); - } - if(subchannel.equals("queuedfor")) { - String playername = in.readUTF(); - String queuename = in.readUTF(); - - Player p = Bukkit.getPlayer(playername); - if(p == null) return; - if(!p.isOnline()) return; - - int number = Integer.parseInt(in.readUTF()); - HashMap phs = placeholders.responseCache.get(p); - if(phs == null) phs = new HashMap<>(); - phs.put("queuedfor_"+queuename, number+""); - placeholders.responseCache.put(p, phs); - } - if(subchannel.equals("estimated_time")) { - String playername = in.readUTF(); - Player p = Bukkit.getPlayer(playername); - if(p == null) return; - if(!p.isOnline()) return; + try { + ComResponse response = ComResponse.from(subchannel, in); - String time = in.readUTF(); - HashMap phs = placeholders.responseCache.get(p); - if(phs == null) phs = new HashMap<>(); - phs.put("estimated_time", time); - placeholders.responseCache.put(p, phs); - } - if(subchannel.equals("status")) { - String playername = in.readUTF(); - String server = in.readUTF(); - - Player p = Bukkit.getPlayer(playername); - if(p == null) return; - if(!p.isOnline()) return; - - String status = in.readUTF(); - HashMap phs = placeholders.responseCache.get(p); - if(phs == null) phs = new HashMap<>(); - phs.put("status_"+server, status+""); - placeholders.responseCache.put(p, phs); + responseManager.executeResponse(response); + } catch (Exception e) { + getLogger().log(Level.SEVERE, "Error while processing proxy response " + subchannel + ": ", e); } } @@ -215,7 +148,7 @@ public class SpigotMain extends JavaPlugin implements PluginMessageListener,List @EventHandler public void onLeave(PlayerQuitEvent e) { if(!papi) return; - placeholders.cleanCache(); + placeholders.cleanCache(e.getPlayer()); } @EventHandler diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java b/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java new file mode 100644 index 0000000..1a6607f --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java @@ -0,0 +1,157 @@ +package us.ajg0702.queue.spigot.api; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; +import us.ajg0702.queue.api.spigot.MessagedResponse; +import us.ajg0702.queue.spigot.SpigotMain; +import us.ajg0702.queue.spigot.communication.ResponseManager; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; + +public class SpigotAPI extends AjQueueSpigotAPI { + private final ResponseManager responseManager; + private final SpigotMain main; + + public SpigotAPI(ResponseManager responseManager, SpigotMain main) { + this.responseManager = responseManager; + this.main = main; + } + + @Override + public Future isInQueue(UUID player) { + Player p = Bukkit.getPlayer(player); + if(p == null) throw new IllegalArgumentException("Player must be online!"); + + CompletableFuture future = new CompletableFuture<>(); + + responseManager.awaitResponse(player.toString(), "inqueue", response -> { + future.complete(Boolean.valueOf(response.getResponse())); + }); + + main.sendMessage(p, "inqueue", ""); + + return future; + } + + @Override + public Future addToQueue(UUID player, String queueName) { + throw new UnsupportedOperationException("Not yet implemented!"); + } + + @Override + public Future> getQueueName(UUID player) { + Player p = Bukkit.getPlayer(player); + if(p == null) throw new IllegalArgumentException("Player must be online!"); + + CompletableFuture> future = new CompletableFuture<>(); + + responseManager.awaitResponse(player.toString(), "queuename", response -> { + future.complete(new MessagedResponse<>(response.getResponse(), response.getNoneMessage())); + }); + + main.sendMessage(p, "queuename", ""); + + return future; + } + + @Override + public Future> getPosition(UUID player) { + Player p = Bukkit.getPlayer(player); + if(p == null) throw new IllegalArgumentException("Player must be online!"); + + CompletableFuture> future = new CompletableFuture<>(); + + responseManager.awaitResponse(player.toString(), "position", response -> { + String r = response.getResponse(); + Integer i = r == null ? null : Integer.valueOf(r); + future.complete(new MessagedResponse<>(i, response.getNoneMessage())); + }); + + main.sendMessage(p, "position", ""); + + return future; + } + + @Override + public Future> getTotalPositions(UUID player) { + Player p = Bukkit.getPlayer(player); + if(p == null) throw new IllegalArgumentException("Player must be online!"); + + CompletableFuture> future = new CompletableFuture<>(); + + responseManager.awaitResponse(player.toString(), "positionof", response -> { + String r = response.getResponse(); + Integer i = r == null ? null : Integer.valueOf(r); + future.complete(new MessagedResponse<>(i, response.getNoneMessage())); + }); + + main.sendMessage(p, "positionof", ""); + + return future; + } + + @Override + public Future getPlayersInQueue(String queueName) { + Player p = Bukkit.getOnlinePlayers().iterator().next(); + + CompletableFuture future = new CompletableFuture<>(); + + responseManager.awaitResponse(queueName, "queuedfor", response -> { + String responseString = response.getResponse(); + if(responseString.equals("invalid_server")) { + future.completeExceptionally(new IllegalArgumentException(queueName + " does not exist!")); + } + future.complete(Integer.valueOf(responseString)); + }); + + main.sendMessage(p, "queuedfor", queueName); + + return future; + } + + @Override + public Future getServerStatusString(String queueName) { + return getServerStatusString(queueName, null); + } + + @Override + public Future getServerStatusString(String queueName, UUID player) { + Player p = player == null ? Bukkit.getOnlinePlayers().iterator().next() : Bukkit.getPlayer(player); + if(p == null) throw new IllegalArgumentException("Player must be online!"); + + String channel = player == null ? "status" : "playerstatus"; + + CompletableFuture future = new CompletableFuture<>(); + + responseManager.awaitResponse(queueName, channel, response -> { + String responseString = response.getResponse(); + if(responseString.equals("invalid_server")) { + future.completeExceptionally(new IllegalArgumentException(queueName + " does not exist!")); + } + future.complete(responseString); + }); + + main.sendMessage(p, channel, queueName); + + return future; + } + + @Override + public Future> getEstimatedTime(UUID player) { + Player p = Bukkit.getPlayer(player); + if(p == null) throw new IllegalArgumentException("Player must be online!"); + + CompletableFuture> future = new CompletableFuture<>(); + + responseManager.awaitResponse(player.toString(), "estimated_time", response -> { + future.complete(new MessagedResponse<>(response.getResponse(), response.getNoneMessage())); + }); + + main.sendMessage(p, "estimated_time", ""); + + return future; + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseKey.java b/spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseKey.java new file mode 100644 index 0000000..7ac0cba --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseKey.java @@ -0,0 +1,34 @@ +package us.ajg0702.queue.spigot.communication; + +import java.util.Objects; + +public class ResponseKey { + private final String id; + private final String from; + + public ResponseKey(String id, String from) { + this.id = id; + this.from = from; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ResponseKey that = (ResponseKey) o; + return id.equals(that.id) && from.equals(that.from); + } + + @Override + public int hashCode() { + return Objects.hash(id, from); + } + + @Override + public String toString() { + return "ResponseKey{" + + "id='" + id + '\'' + + ", from='" + from + '\'' + + '}'; + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseManager.java b/spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseManager.java new file mode 100644 index 0000000..b8ed6a8 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseManager.java @@ -0,0 +1,31 @@ +package us.ajg0702.queue.spigot.communication; + +import us.ajg0702.queue.api.communication.ComResponse; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; + + +public class ResponseManager { + private final Map> responseMap = new ConcurrentHashMap<>(); + + public synchronized void awaitResponse(String id, String from, Consumer callback) { + ResponseKey key = new ResponseKey(id, from); + responseMap.merge(key, callback, (a, b) -> r -> { + b.accept(r); + a.accept(r); + }); + } + + public void executeResponse(ComResponse response) { + ResponseKey key = new ResponseKey(response.getIdentifier(), response.getFrom()); + Consumer callback = responseMap.get(key); + if(callback == null) { + System.out.println("[ajQueue] No callback for " + key + " with " + response); + return; + } + responseMap.remove(key); + callback.accept(response); + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/CachedPlaceholder.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/CachedPlaceholder.java new file mode 100644 index 0000000..73c223d --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/CachedPlaceholder.java @@ -0,0 +1,21 @@ +package us.ajg0702.queue.spigot.placeholders; + +import java.util.regex.Matcher; + +public class CachedPlaceholder { + private final Matcher matcher; + private final Placeholder placeholder; + + public CachedPlaceholder(Matcher matcher, Placeholder placeholder) { + this.matcher = matcher; + this.placeholder = placeholder; + } + + public Matcher getMatcher() { + return matcher; + } + + public Placeholder getPlaceholder() { + return placeholder; + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/Placeholder.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/Placeholder.java new file mode 100644 index 0000000..03e943f --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/Placeholder.java @@ -0,0 +1,32 @@ +package us.ajg0702.queue.spigot.placeholders; + +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import us.ajg0702.queue.spigot.SpigotMain; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public abstract class Placeholder { + + protected final SpigotMain plugin; + + private Pattern pattern; + + public Placeholder(SpigotMain plugin) { + this.plugin = plugin; + } + + public abstract String getRegex(); + + public Pattern getPattern() { + if(pattern == null) { + pattern = Pattern.compile(getRegex()); + } + return pattern; + } + + public abstract String parse(Matcher matcher, OfflinePlayer p); + + public abstract void cleanCache(Player player); +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java new file mode 100644 index 0000000..374024c --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java @@ -0,0 +1,88 @@ +package us.ajg0702.queue.spigot.placeholders; + +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import us.ajg0702.queue.spigot.SpigotMain; +import us.ajg0702.queue.spigot.placeholders.placeholders.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; + +public class PlaceholderExpansion extends me.clip.placeholderapi.expansion.PlaceholderExpansion { + + private final List placeholders = new ArrayList<>(); + + private final SpigotMain plugin; + + @SuppressWarnings("deprecated") + public PlaceholderExpansion(SpigotMain plugin) { + + this.plugin = plugin; + + placeholders.add(new EstimatedTime(plugin)); + placeholders.add(new InQueue(plugin)); + placeholders.add(new Position(plugin)); + placeholders.add(new PositionOf(plugin)); + placeholders.add(new Queued(plugin)); + placeholders.add(new QueuedFor(plugin)); + placeholders.add(new Status(plugin)); + + } + + Map placeholderCache = new HashMap<>(); + + @Override + public String onRequest(OfflinePlayer p, @NotNull String params) { + + if(p == null || !p.isOnline()) { + return "No player"; + } + + CachedPlaceholder cachedPlaceholder = placeholderCache.computeIfAbsent(params, s -> { + for(Placeholder placeholder : placeholders) { + Matcher matcher = placeholder.getPattern().matcher(params); + if(!matcher.matches()) continue; + return new CachedPlaceholder(matcher, placeholder); + } + return null; + }); + if(cachedPlaceholder == null) return null; + + return cachedPlaceholder.getPlaceholder().parse(cachedPlaceholder.getMatcher(), p); + } + + + + @Override + public @NotNull String getIdentifier() { + return "ajqueue"; + } + + @Override + public @NotNull String getAuthor() { + return "ajgeiss0702"; + } + + @Override + public @NotNull String getVersion() { + return plugin.getDescription().getVersion(); + } + + @Override + public boolean persist(){ + return true; + } + + @Override + public boolean canRegister() { + return true; + } + + public void cleanCache(Player player) { + placeholders.forEach(p -> p.cleanCache(player)); + } +} \ No newline at end of file diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java new file mode 100644 index 0000000..a07b022 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java @@ -0,0 +1,55 @@ +package us.ajg0702.queue.spigot.placeholders.placeholders; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; +import us.ajg0702.queue.api.spigot.MessagedResponse; +import us.ajg0702.queue.spigot.SpigotMain; +import us.ajg0702.queue.spigot.placeholders.Placeholder; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.regex.Matcher; + +public class EstimatedTime extends Placeholder { + public EstimatedTime(SpigotMain plugin) { + super(plugin); + } + + private final Map cache = new ConcurrentHashMap<>(); + + @Override + public String getRegex() { + return "estimated_time"; + } + + @Override + public String parse(Matcher matcher, OfflinePlayer p) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + try { + MessagedResponse response = AjQueueSpigotAPI.getInstance() + .getEstimatedTime(p.getUniqueId()) + .get(30, TimeUnit.SECONDS); + + cache.put(p.getUniqueId(), response.getEither()); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } catch (TimeoutException e) { + plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); + } + }); + + return cache.getOrDefault(p.getUniqueId(), "..."); + } + + @Override + public void cleanCache(Player player) { + cache.remove(player.getUniqueId()); + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java new file mode 100644 index 0000000..9b83582 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java @@ -0,0 +1,54 @@ +package us.ajg0702.queue.spigot.placeholders.placeholders; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; +import us.ajg0702.queue.spigot.SpigotMain; +import us.ajg0702.queue.spigot.placeholders.Placeholder; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.regex.Matcher; + +public class InQueue extends Placeholder { + public InQueue(SpigotMain plugin) { + super(plugin); + } + + private final Map cache = new ConcurrentHashMap<>(); + + @Override + public String getRegex() { + return "inqueue"; + } + + @Override + public String parse(Matcher matcher, OfflinePlayer p) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + try { + Boolean response = AjQueueSpigotAPI.getInstance() + .isInQueue(p.getUniqueId()) + .get(30, TimeUnit.SECONDS); + + cache.put(p.getUniqueId(), response + ""); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } catch (TimeoutException e) { + plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); + } + }); + + return cache.getOrDefault(p.getUniqueId(), "..."); + } + + @Override + public void cleanCache(Player player) { + cache.remove(player.getUniqueId()); + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java new file mode 100644 index 0000000..037420f --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java @@ -0,0 +1,55 @@ +package us.ajg0702.queue.spigot.placeholders.placeholders; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; +import us.ajg0702.queue.api.spigot.MessagedResponse; +import us.ajg0702.queue.spigot.SpigotMain; +import us.ajg0702.queue.spigot.placeholders.Placeholder; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.regex.Matcher; + +public class Position extends Placeholder { + public Position(SpigotMain plugin) { + super(plugin); + } + + private final Map cache = new ConcurrentHashMap<>(); + + @Override + public String getRegex() { + return "position"; + } + + @Override + public String parse(Matcher matcher, OfflinePlayer p) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + try { + MessagedResponse response = AjQueueSpigotAPI.getInstance() + .getPosition(p.getUniqueId()) + .get(30, TimeUnit.SECONDS); + + cache.put(p.getUniqueId(), response.getEither()); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } catch (TimeoutException e) { + plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); + } + }); + + return cache.getOrDefault(p.getUniqueId(), "..."); + } + + @Override + public void cleanCache(Player player) { + cache.remove(player.getUniqueId()); + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java new file mode 100644 index 0000000..a3c4cba --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java @@ -0,0 +1,55 @@ +package us.ajg0702.queue.spigot.placeholders.placeholders; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; +import us.ajg0702.queue.api.spigot.MessagedResponse; +import us.ajg0702.queue.spigot.SpigotMain; +import us.ajg0702.queue.spigot.placeholders.Placeholder; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.regex.Matcher; + +public class PositionOf extends Placeholder { + public PositionOf(SpigotMain plugin) { + super(plugin); + } + + private final Map cache = new ConcurrentHashMap<>(); + + @Override + public String getRegex() { + return "of"; + } + + @Override + public String parse(Matcher matcher, OfflinePlayer p) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + try { + MessagedResponse response = AjQueueSpigotAPI.getInstance() + .getTotalPositions(p.getUniqueId()) + .get(30, TimeUnit.SECONDS); + + cache.put(p.getUniqueId(), response.getEither()); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } catch (TimeoutException e) { + plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); + } + }); + + return cache.getOrDefault(p.getUniqueId(), "..."); + } + + @Override + public void cleanCache(Player player) { + cache.remove(player.getUniqueId()); + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java new file mode 100644 index 0000000..cf4d26a --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java @@ -0,0 +1,55 @@ +package us.ajg0702.queue.spigot.placeholders.placeholders; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; +import us.ajg0702.queue.api.spigot.MessagedResponse; +import us.ajg0702.queue.spigot.SpigotMain; +import us.ajg0702.queue.spigot.placeholders.Placeholder; + +import java.util.Map; +import java.util.UUID; +import java.util.logging.Level; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.regex.Matcher; + +public class Queued extends Placeholder { + public Queued(SpigotMain plugin) { + super(plugin); + } + + private final Map cache = new ConcurrentHashMap<>(); + + @Override + public String getRegex() { + return "queued"; + } + + @Override + public String parse(Matcher matcher, OfflinePlayer p) { + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + try { + MessagedResponse response = AjQueueSpigotAPI.getInstance() + .getQueueName(p.getUniqueId()) + .get(30, TimeUnit.SECONDS); + + cache.put(p.getUniqueId(), response.getEither()); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } catch (TimeoutException e) { + plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); + } + }); + + return cache.getOrDefault(p.getUniqueId(), "..."); + } + + @Override + public void cleanCache(Player player) { + cache.remove(player.getUniqueId()); + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java new file mode 100644 index 0000000..13259e5 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java @@ -0,0 +1,62 @@ +package us.ajg0702.queue.spigot.placeholders.placeholders; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; +import us.ajg0702.queue.spigot.SpigotMain; +import us.ajg0702.queue.spigot.placeholders.Placeholder; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.regex.Matcher; + +public class QueuedFor extends Placeholder { + public QueuedFor(SpigotMain plugin) { + super(plugin); + } + + private final String invalidMessage = "Invalid queue name"; + + private final Map cache = new ConcurrentHashMap<>(); + + @Override + public String getRegex() { + return "queuedfor_(.*)"; + } + + @Override + public String parse(Matcher matcher, OfflinePlayer p) { + String queue = matcher.group(1); + String cached = cache.getOrDefault(queue, "..."); + + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + try { + Integer response = AjQueueSpigotAPI.getInstance() + .getPlayersInQueue(queue) + .get(30, TimeUnit.SECONDS); + + cache.put(queue, response + ""); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (TimeoutException e) { + plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); + } catch (ExecutionException e) { + if(e.getCause() instanceof IllegalArgumentException) { + cache.put(queue, invalidMessage); + } else { + throw new RuntimeException(e); + } + } + }); + + return cached; + } + + @Override + public void cleanCache(Player player) {} +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java new file mode 100644 index 0000000..af1848d --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java @@ -0,0 +1,62 @@ +package us.ajg0702.queue.spigot.placeholders.placeholders; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; +import us.ajg0702.queue.spigot.SpigotMain; +import us.ajg0702.queue.spigot.placeholders.Placeholder; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.regex.Matcher; + +public class Status extends Placeholder { + public Status(SpigotMain plugin) { + super(plugin); + } + + private final String invalidMessage = "Invalid queue name"; + + private final Map cache = new ConcurrentHashMap<>(); + + @Override + public String getRegex() { + return "status_(.*)"; + } + + @Override + public String parse(Matcher matcher, OfflinePlayer p) { + String queue = matcher.group(1); + String cached = cache.getOrDefault(queue, "..."); + + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + try { + String response = AjQueueSpigotAPI.getInstance() + .getServerStatusString(queue) + .get(30, TimeUnit.SECONDS); + + cache.put(queue, response); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (TimeoutException e) { + plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); + } catch (ExecutionException e) { + if(e.getCause() instanceof IllegalArgumentException) { + cache.put(queue, invalidMessage); + } else { + throw new RuntimeException(e); + } + } + }); + + return cached; + } + + @Override + public void cleanCache(Player player) {} +} From 17c69638896d2e0dcc90f1bcaf8148ef98453cc4 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 27 May 2023 18:15:44 -0700 Subject: [PATCH 09/51] [nolist] whoops, don't need gson --- api/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 71cfb61..89724a8 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -16,7 +16,6 @@ repositories { dependencies { implementation("net.kyori:adventure-api:4.13.1") implementation("net.kyori:adventure-text-serializer-plain:4.13.1") - implementation("com.google.code.gson:gson:2.10.1") compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("us.ajg0702:ajUtils:1.2.10") From 67aece11f02fd7fe114663db8b2cdb11d62796b7 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 28 May 2023 16:48:29 -0700 Subject: [PATCH 10/51] Parse colors after placeholders so that colors work in placeholders --- api/build.gradle.kts | 2 +- common/build.gradle.kts | 2 +- free/build.gradle.kts | 2 +- platforms/bungeecord/build.gradle.kts | 2 +- platforms/velocity/build.gradle.kts | 2 +- premium/build.gradle.kts | 2 +- spigot/build.gradle.kts | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/build.gradle.kts b/api/build.gradle.kts index 89724a8..a960f06 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { implementation("net.kyori:adventure-text-serializer-plain:4.13.1") compileOnly("com.google.guava:guava:30.1.1-jre") - compileOnly("us.ajg0702:ajUtils:1.2.10") + compileOnly("us.ajg0702:ajUtils:1.2.14") } publishing { diff --git a/common/build.gradle.kts b/common/build.gradle.kts index da816f9..d39f318 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { compileOnly("net.kyori:adventure-text-serializer-plain:4.13.1") compileOnly("com.google.guava:guava:30.1.1-jre") - compileOnly("us.ajg0702:ajUtils:1.2.10") + compileOnly("us.ajg0702:ajUtils:1.2.14") compileOnly("org.slf4j:slf4j-log4j12:1.7.29") diff --git a/free/build.gradle.kts b/free/build.gradle.kts index d483eb8..bf8eb31 100644 --- a/free/build.gradle.kts +++ b/free/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("org.spongepowered:configurate-yaml:4.0.0") - implementation("us.ajg0702:ajUtils:1.2.10") + implementation("us.ajg0702:ajUtils:1.2.14") implementation(project(":platforms:velocity")) implementation(project(":platforms:bungeecord")) diff --git a/platforms/bungeecord/build.gradle.kts b/platforms/bungeecord/build.gradle.kts index 0641a93..bd055ba 100644 --- a/platforms/bungeecord/build.gradle.kts +++ b/platforms/bungeecord/build.gradle.kts @@ -16,7 +16,7 @@ repositories { dependencies { compileOnly("net.kyori:adventure-api:4.13.1") compileOnly("com.google.guava:guava:30.1.1-jre") - compileOnly("us.ajg0702:ajUtils:1.2.10") + compileOnly("us.ajg0702:ajUtils:1.2.14") compileOnly("net.md-5:bungeecord-api:1.16-R0.4") diff --git a/platforms/velocity/build.gradle.kts b/platforms/velocity/build.gradle.kts index bb00849..162e3b2 100644 --- a/platforms/velocity/build.gradle.kts +++ b/platforms/velocity/build.gradle.kts @@ -16,7 +16,7 @@ repositories { dependencies { compileOnly("net.kyori:adventure-api:4.13.1") compileOnly("com.google.guava:guava:30.1.1-jre") - compileOnly("us.ajg0702:ajUtils:1.2.10") + compileOnly("us.ajg0702:ajUtils:1.2.14") compileOnly("com.velocitypowered:velocity-api:3.1.1") annotationProcessor("com.velocitypowered:velocity-api:3.1.1") diff --git a/premium/build.gradle.kts b/premium/build.gradle.kts index c4d27e0..b4ef8b9 100644 --- a/premium/build.gradle.kts +++ b/premium/build.gradle.kts @@ -23,7 +23,7 @@ dependencies { compileOnly("me.TechsCode:FakeUltraPerms:1.0.2") - compileOnly("us.ajg0702:ajUtils:1.2.10") + compileOnly("us.ajg0702:ajUtils:1.2.14") compileOnly("net.kyori:adventure-api:4.13.1") diff --git a/spigot/build.gradle.kts b/spigot/build.gradle.kts index 39bbdf6..2535b31 100644 --- a/spigot/build.gradle.kts +++ b/spigot/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { compileOnly("org.spongepowered:configurate-yaml:4.1.2") - compileOnly("us.ajg0702:ajUtils:1.2.10") + compileOnly("us.ajg0702:ajUtils:1.2.14") compileOnly(group = "org.spigotmc", name = "spigot", version = "1.16.5-R0.1-SNAPSHOT") compileOnly("me.clip:placeholderapi:2.10.4") From 429eb354b02f14aa64511ed6f871411d32695fc4 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 28 May 2023 16:57:04 -0700 Subject: [PATCH 11/51] Fixed API not having javadocs & sources --- api/build.gradle.kts | 5 +++++ .../java/us/ajg0702/queue/api/server/AdaptedServerPing.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/api/build.gradle.kts b/api/build.gradle.kts index a960f06..2392b5c 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -13,6 +13,11 @@ repositories { mavenCentral() } +java { + withJavadocJar() + withSourcesJar() +} + dependencies { implementation("net.kyori:adventure-api:4.13.1") implementation("net.kyori:adventure-text-serializer-plain:4.13.1") diff --git a/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServerPing.java b/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServerPing.java index 733c35f..945899d 100644 --- a/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServerPing.java +++ b/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServerPing.java @@ -35,7 +35,7 @@ public interface AdaptedServerPing extends Handle { void addPlayer(); /** - * Returns an epoch timestamp of when this ping was sent. + * Returns an epoch timestamp of when this ping was sent. * @return A long of an epoch timestamp */ long getFetchedTime(); From a99bd73614c34e1197d991a3335d9e55489254f4 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Mon, 29 May 2023 11:31:41 -0700 Subject: [PATCH 12/51] Added %ajqueue_status__player% --- .../us/ajg0702/queue/api/QueueHolder.java | 6 ++ .../placeholders/PlaceholderExpansion.java | 1 + .../placeholders/StatusPlayer.java | 59 +++++++++++++++++++ .../queue/spigot/utils/UUIDStringKey.java | 36 +++++++++++ 4 files changed, 102 insertions(+) create mode 100644 api/src/main/java/us/ajg0702/queue/api/QueueHolder.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/utils/UUIDStringKey.java diff --git a/api/src/main/java/us/ajg0702/queue/api/QueueHolder.java b/api/src/main/java/us/ajg0702/queue/api/QueueHolder.java new file mode 100644 index 0000000..a3ceb66 --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/QueueHolder.java @@ -0,0 +1,6 @@ +package us.ajg0702.queue.api; + +public interface QueueHolder { + boolean isAvailable(); + +} \ No newline at end of file diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java index 374024c..f4d1eae 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java @@ -30,6 +30,7 @@ public class PlaceholderExpansion extends me.clip.placeholderapi.expansion.Place placeholders.add(new Queued(plugin)); placeholders.add(new QueuedFor(plugin)); placeholders.add(new Status(plugin)); + placeholders.add(new StatusPlayer(plugin)); } diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java new file mode 100644 index 0000000..8fe71e0 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java @@ -0,0 +1,59 @@ +package us.ajg0702.queue.spigot.placeholders.placeholders; + +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; +import us.ajg0702.queue.api.spigot.MessagedResponse; +import us.ajg0702.queue.spigot.SpigotMain; +import us.ajg0702.queue.spigot.placeholders.Placeholder; +import us.ajg0702.queue.spigot.utils.UUIDStringKey; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.regex.Matcher; + +public class StatusPlayer extends Placeholder { + public StatusPlayer(SpigotMain plugin) { + super(plugin); + } + + private final Map cache = new ConcurrentHashMap<>(); + + @Override + public String getRegex() { + return "status_(.*)_player"; + } + + @Override + public String parse(Matcher matcher, OfflinePlayer p) { + String queue = matcher.group(1); + UUIDStringKey key = new UUIDStringKey(p.getUniqueId(), queue); + + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + try { + String response = AjQueueSpigotAPI.getInstance() + .getServerStatusString(queue, p.getUniqueId()) + .get(30, TimeUnit.SECONDS); + + cache.put(key, response); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } catch (TimeoutException e) { + plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); + } + }); + + return cache.getOrDefault(key, "..."); + } + + @Override + public void cleanCache(Player player) { + cache.entrySet().removeIf(entry -> entry.getKey().getUuid().equals(player.getUniqueId())); + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/utils/UUIDStringKey.java b/spigot/src/main/java/us/ajg0702/queue/spigot/utils/UUIDStringKey.java new file mode 100644 index 0000000..4d22743 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/utils/UUIDStringKey.java @@ -0,0 +1,36 @@ +package us.ajg0702.queue.spigot.utils; + +import java.util.Objects; +import java.util.UUID; + +public class UUIDStringKey { + + private final UUID uuid; + private final String string; + + public UUIDStringKey(UUID uuid, String string) { + this.uuid = uuid; + this.string = string; + } + + public UUID getUuid() { + return uuid; + } + + public String getString() { + return string; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof UUIDStringKey)) return false; + UUIDStringKey that = (UUIDStringKey) o; + return uuid.equals(that.uuid) && string.equals(that.string); + } + + @Override + public int hashCode() { + return Objects.hash(uuid, string); + } +} From 80289de37157f360df01cc9ede0bbfb87c074bd3 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Tue, 6 Jun 2023 09:09:54 -0700 Subject: [PATCH 13/51] Fixed whitelist/restricted not working well in groups --- .../queue/common/communication/CommunicationManager.java | 2 -- .../queue/common/queues/balancers/DefaultBalancer.java | 5 +++++ spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java b/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java index bd2eb3a..750da5b 100644 --- a/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java +++ b/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java @@ -52,8 +52,6 @@ public class CommunicationManager { if(response == null) return; - Debug.info("Responding with " + response); - main.getPlatformMethods().sendPluginMessage( receivingPlayer, s(response.getFrom()), diff --git a/common/src/main/java/us/ajg0702/queue/common/queues/balancers/DefaultBalancer.java b/common/src/main/java/us/ajg0702/queue/common/queues/balancers/DefaultBalancer.java index 119e6ad..6370f5b 100644 --- a/common/src/main/java/us/ajg0702/queue/common/queues/balancers/DefaultBalancer.java +++ b/common/src/main/java/us/ajg0702/queue/common/queues/balancers/DefaultBalancer.java @@ -37,6 +37,11 @@ public class DefaultBalancer implements Balancer { selectednum = online; continue; } + if(!selected.isJoinable(player) && sv.isJoinable(player)) { + selected = sv; + selectednum = online; + continue; + } if(selectednum > online && sv.isJoinable(player)) { selected = sv; selectednum = online; diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java b/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java index 0fc8747..abde51e 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java @@ -122,6 +122,8 @@ public class SpigotMain extends JavaPlugin implements PluginMessageListener,List ComResponse response = ComResponse.from(subchannel, in); responseManager.executeResponse(response); + } catch (IllegalStateException ignored) { + // This seems to happen often when a player leaves. So, we'll ignore it. } catch (Exception e) { getLogger().log(Level.SEVERE, "Error while processing proxy response " + subchannel + ": ", e); } From 2414c698edf9fa20ef87b346649135d58dec62d3 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Thu, 8 Jun 2023 10:05:53 -0700 Subject: [PATCH 14/51] Seperate sudo-queueing and normal queueing on spigot side. `/queue ` on the spigot side now acts the same as `/ajqueue send` --- .../queue/api/spigot/AjQueueSpigotAPI.java | 9 ++++- .../communication/CommunicationManager.java | 4 +-- .../communication/handlers/QueueHandler.java | 3 ++ .../handlers/ServerQueueHandler.java | 28 +++++++++++++++ .../us/ajg0702/queue/spigot/Commands.java | 36 +++++++++++++------ .../ajg0702/queue/spigot/api/SpigotAPI.java | 20 ++++++++++- 6 files changed, 85 insertions(+), 15 deletions(-) create mode 100644 common/src/main/java/us/ajg0702/queue/common/communication/handlers/ServerQueueHandler.java diff --git a/api/src/main/java/us/ajg0702/queue/api/spigot/AjQueueSpigotAPI.java b/api/src/main/java/us/ajg0702/queue/api/spigot/AjQueueSpigotAPI.java index 2c191fa..90d456c 100644 --- a/api/src/main/java/us/ajg0702/queue/api/spigot/AjQueueSpigotAPI.java +++ b/api/src/main/java/us/ajg0702/queue/api/spigot/AjQueueSpigotAPI.java @@ -22,13 +22,20 @@ public abstract class AjQueueSpigotAPI { public abstract Future isInQueue(UUID player); /** - * Adds a player to a queue + * Adds a player to a queue (bypassing any permission checks that would prevent it) * @param player The player to be added * @param queueName The server or group to add the player to * @return True if adding was successful, false if not. */ public abstract Future addToQueue(UUID player, String queueName); + /** + * Emulate the player running the queue command for a certain server, including any permission checks + * @param player The player to sudo the command for + * @param queueName The queue to send the player to + */ + public abstract void sudoQueue(UUID player, String queueName); + /** * Gets the name of the queue that the player is in * @param player the player diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java b/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java index 750da5b..7533639 100644 --- a/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java +++ b/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java @@ -4,7 +4,6 @@ import us.ajg0702.queue.api.communication.ComResponse; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.common.QueueMain; import us.ajg0702.queue.common.communication.handlers.*; -import us.ajg0702.queue.common.utils.Debug; import us.ajg0702.queue.common.utils.MapBuilder; import java.io.ByteArrayInputStream; @@ -33,7 +32,8 @@ public class CommunicationManager { "inqueue", new InQueueHandler(main), "queuedfor", new QueuedForHandler(main), "status", new StatusHandler(main), - "playerstatus", new PlayerStatusHandler(main) + "playerstatus", new PlayerStatusHandler(main), + "serverqueue", new ServerQueueHandler(main) ); } diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueHandler.java index 30cf62a..7a4e943 100644 --- a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueHandler.java +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/QueueHandler.java @@ -7,6 +7,9 @@ import us.ajg0702.queue.common.QueueMain; import us.ajg0702.queue.api.communication.ComResponse; import us.ajg0702.queue.common.communication.MessageHandler; +/** + * Actually SudoQueue. Confusing naming is due to legacy support and will be removed next major revision. + */ public class QueueHandler extends MessageHandler { private final IBaseCommand moveCommand; diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/ServerQueueHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/ServerQueueHandler.java new file mode 100644 index 0000000..312acff --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/ServerQueueHandler.java @@ -0,0 +1,28 @@ +package us.ajg0702.queue.common.communication.handlers; + +import us.ajg0702.queue.api.communication.ComResponse; +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.common.communication.MessageHandler; + +public class ServerQueueHandler extends MessageHandler { + public ServerQueueHandler(QueueMain main) { + super(main); + } + + @Override + public ComResponse handleMessage(AdaptedPlayer player, String data) { + QueueServer server = main.getQueueManager().findServer(data); + if(server == null) { + return ComResponse + .from("serverqueue") + .id(player.getUniqueId()) + .with("invalid_server"); + } + return ComResponse + .from("serverqueue") + .id(player.getUniqueId()) + .with(main.getQueueManager().addToQueue(player, server)); + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java b/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java index 7e2b6f9..d86936e 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java @@ -7,6 +7,7 @@ import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; public class Commands implements CommandExecutor { @@ -42,23 +43,32 @@ public class Commands implements CommandExecutor { pl.sendMessage(player, "leavequeue", arg.toString()); return true; } + + + // Queue command + + if(args.length < 1) return false; - - String srvname = args[0]; - + + String serverName = args[0]; + + boolean sudo = true; + + // /queue if(args.length > 1) { - pl.getLogger().info("Sending "+args[0]+" to queue '" + args[1] + "'"); + sudo = false; if(!sender.hasPermission("ajqueue.send")) { sender.sendMessage(color("&cYou do not have permission to do this!")); return true; } - Player tply = Bukkit.getPlayer(args[0]); - if(tply == null) { + pl.getLogger().info("Sending "+args[0]+" to queue '" + args[1] + "'"); + Player playerToSend = Bukkit.getPlayer(args[0]); + if(playerToSend == null) { sender.sendMessage(color("&cCannot find that player!")); return true; } - player = tply; - srvname = args[1]; + player = playerToSend; + serverName = args[1]; } if(player == null) { @@ -66,10 +76,14 @@ public class Commands implements CommandExecutor { return true; } - if(pl.getAConfig().getBoolean("send-queue-commands-in-batches")) { - pl.queuebatch.put(player, srvname); + if(sudo) { + if(pl.getAConfig().getBoolean("send-queue-commands-in-batches")) { + pl.queuebatch.put(player, serverName); + } else { + AjQueueSpigotAPI.getInstance().sudoQueue(player.getUniqueId(), serverName); + } } else { - pl.sendMessage(player, "queue", srvname); + AjQueueSpigotAPI.getInstance().addToQueue(player.getUniqueId(), serverName); } return true; diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java b/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java index 1a6607f..7dcb80d 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java @@ -38,7 +38,25 @@ public class SpigotAPI extends AjQueueSpigotAPI { @Override public Future addToQueue(UUID player, String queueName) { - throw new UnsupportedOperationException("Not yet implemented!"); + Player p = Bukkit.getPlayer(player); + if(p == null) throw new IllegalArgumentException("Player must be online!"); + + CompletableFuture future = new CompletableFuture<>(); + + responseManager.awaitResponse(player.toString(), "serverqueue", response -> { + future.complete(Boolean.valueOf(response.getResponse())); + }); + + main.sendMessage(p, "serverqueue", queueName); + + return future; + } + + @Override + public void sudoQueue(UUID player, String queueName) { + Player p = Bukkit.getPlayer(player); + if(p == null) throw new IllegalArgumentException("Player must be online!"); + main.sendMessage(p, "queue", queueName); } @Override From 0899bf88edbb32725583f801fc5bb0bf767f20a2 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Thu, 8 Jun 2023 17:00:49 -0700 Subject: [PATCH 15/51] Add API events system --- .github/workflows/javadocs.yml | 46 +++++++++++++++++ .../java/us/ajg0702/queue/api/AjQueueAPI.java | 3 ++ .../ajg0702/queue/api/events/Cancellable.java | 15 ++++++ .../us/ajg0702/queue/api/events/Event.java | 4 ++ .../queue/api/events/PositionChangeEvent.java | 51 +++++++++++++++++++ .../queue/api/events/PreQueueEvent.java | 45 ++++++++++++++++ .../queue/api/events/SuccessfulSendEvent.java | 34 +++++++++++++ .../queue/api/events/utils/EventReceiver.java | 6 +++ .../queue/api/players/AdaptedPlayer.java | 6 +++ .../queue/common/EventHandlerImpl.java | 4 ++ .../us/ajg0702/queue/common/QueueMain.java | 30 ++++++++++- .../queue/common/QueueManagerImpl.java | 9 ++++ .../us/ajg0702/queue/common/TaskManager.java | 13 +++-- .../queue/common/queues/QueueServerImpl.java | 9 ++++ .../common/utils/QueueThreadFactory.java | 21 ++++++++ .../bungeecord/players/BungeePlayer.java | 6 +++ .../velocity/players/VelocityPlayer.java | 10 +++- 17 files changed, 306 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/javadocs.yml create mode 100644 api/src/main/java/us/ajg0702/queue/api/events/Cancellable.java create mode 100644 api/src/main/java/us/ajg0702/queue/api/events/Event.java create mode 100644 api/src/main/java/us/ajg0702/queue/api/events/PositionChangeEvent.java create mode 100644 api/src/main/java/us/ajg0702/queue/api/events/PreQueueEvent.java create mode 100644 api/src/main/java/us/ajg0702/queue/api/events/SuccessfulSendEvent.java create mode 100644 api/src/main/java/us/ajg0702/queue/api/events/utils/EventReceiver.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/utils/QueueThreadFactory.java diff --git a/.github/workflows/javadocs.yml b/.github/workflows/javadocs.yml new file mode 100644 index 0000000..1318501 --- /dev/null +++ b/.github/workflows/javadocs.yml @@ -0,0 +1,46 @@ +name: JavaDocs Generation + +on: + push: + branches: ["master"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Pages + uses: actions/configure-pages@v3 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'temurin' + - name: Build with Gradle + uses: gradle/gradle-build-action@937999e9cc2425eddc7fd62d1053baf041147db7 + with: + arguments: :api:javadoc + - name: Upload artifact + uses: actions/upload-pages-artifact@v1 + with: + path: 'api/build/docs/javadoc' + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 \ No newline at end of file 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 dd3aea5..5a2fa72 100644 --- a/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java +++ b/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java @@ -1,5 +1,6 @@ package us.ajg0702.queue.api; +import us.ajg0702.queue.api.events.utils.EventReceiver; import us.ajg0702.queue.api.premium.Logic; import us.ajg0702.queue.api.premium.LogicGetter; import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; @@ -114,5 +115,7 @@ public abstract class AjQueueAPI { */ public abstract void shutdown(); + public abstract void listen(Class event, EventReceiver handler); + public abstract ExecutorService getServersUpdateExecutor(); } diff --git a/api/src/main/java/us/ajg0702/queue/api/events/Cancellable.java b/api/src/main/java/us/ajg0702/queue/api/events/Cancellable.java new file mode 100644 index 0000000..a7b61f0 --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/events/Cancellable.java @@ -0,0 +1,15 @@ +package us.ajg0702.queue.api.events; + +public interface Cancellable { + /** + * Whether this event is canceled. + * @return True if canceled. False if not. + */ + boolean isCancelled(); + + /** + * Allows you to cancel or un-cancel this event + * @param cancelled True to cancel the event, false to un-cancel + */ + void setCancelled(boolean cancelled); +} diff --git a/api/src/main/java/us/ajg0702/queue/api/events/Event.java b/api/src/main/java/us/ajg0702/queue/api/events/Event.java new file mode 100644 index 0000000..776b7d2 --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/events/Event.java @@ -0,0 +1,4 @@ +package us.ajg0702.queue.api.events; + +public interface Event { +} diff --git a/api/src/main/java/us/ajg0702/queue/api/events/PositionChangeEvent.java b/api/src/main/java/us/ajg0702/queue/api/events/PositionChangeEvent.java new file mode 100644 index 0000000..61bfe0b --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/events/PositionChangeEvent.java @@ -0,0 +1,51 @@ +package us.ajg0702.queue.api.events; + +import org.jetbrains.annotations.Nullable; +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.players.QueuePlayer; +import us.ajg0702.queue.api.queues.QueueServer; + +/** + * Called when someone is added or removed from a queue that the player is in, causing the player's position to change + */ +public class PositionChangeEvent implements Event { + private final QueuePlayer player; + private final int position; + + public PositionChangeEvent(QueuePlayer player) { + this.player = player; + position = player.getPosition(); + } + + /** + * Gets the QueuePlayer object that represents this player + * @return the QueuePlayer object + */ + public QueuePlayer getQueuePlayer() { + return player; + } + + /** + * Gets the AdaptedPlayer that this event is about. May return null! + * @return The AdaptedPlayer that this event is about. Returns null if the player is offline. + */ + public @Nullable AdaptedPlayer getPlayer() { + return player.getPlayer(); + } + + /** + * Gets the player's new position in the queue + * @return The player's new position. 1 being 1st, 2 being 2nd, etc + */ + public int getPosition() { + return position; + } + + /** + * Gets the queue that this event is from + * @return The QueueServer that the player is in that their position changed + */ + public QueueServer getQueue() { + return player.getQueueServer(); + } +} diff --git a/api/src/main/java/us/ajg0702/queue/api/events/PreQueueEvent.java b/api/src/main/java/us/ajg0702/queue/api/events/PreQueueEvent.java new file mode 100644 index 0000000..3195044 --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/events/PreQueueEvent.java @@ -0,0 +1,45 @@ +package us.ajg0702.queue.api.events; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.queues.QueueServer; + +/** + * Called after all checks are made, right before a player is actually added to the queue. + * If canceled, the player will not be added to the queue. + * If you cancel this event, it is up to you to send a message telling the player why they were not added to the queue. + */ +public class PreQueueEvent implements Event, Cancellable { + private final AdaptedPlayer player; + private final QueueServer target; + + private boolean cancelled = false; + + public PreQueueEvent(AdaptedPlayer player, QueueServer target) { + this.player = player; + this.target = target; + } + + /** + * Gets the player that is joining the queue + * @return + */ + public AdaptedPlayer getPlayer() { + return player; + } + + /** + * Gets the target QueueServer that the player is trying to queue for + * @return The QueueServer that the player is trying to queue for + */ + public QueueServer getTarget() { + return target; + } + + public boolean isCancelled() { + return cancelled; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} diff --git a/api/src/main/java/us/ajg0702/queue/api/events/SuccessfulSendEvent.java b/api/src/main/java/us/ajg0702/queue/api/events/SuccessfulSendEvent.java new file mode 100644 index 0000000..2336d7c --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/events/SuccessfulSendEvent.java @@ -0,0 +1,34 @@ +package us.ajg0702.queue.api.events; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.players.QueuePlayer; +import us.ajg0702.queue.api.server.AdaptedServer; + +/** + * Called after a player is successfully sent to a server. + */ +public class SuccessfulSendEvent implements Event { + private final QueuePlayer player; + private final AdaptedServer server; + + public SuccessfulSendEvent(QueuePlayer player, AdaptedServer server) { + this.player = player; + this.server = server; + } + + /** + * Gets the player that was sent + * @return the player that was sent + */ + public AdaptedPlayer getPlayer() { + return player.getPlayer(); + } + + /** + * Gets the server that the player was sent to + * @return The server that the player was sent to + */ + public AdaptedServer getServer() { + return server; + } +} diff --git a/api/src/main/java/us/ajg0702/queue/api/events/utils/EventReceiver.java b/api/src/main/java/us/ajg0702/queue/api/events/utils/EventReceiver.java new file mode 100644 index 0000000..04c1424 --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/events/utils/EventReceiver.java @@ -0,0 +1,6 @@ +package us.ajg0702.queue.api.events.utils; + +@FunctionalInterface +public interface EventReceiver { + void execute(E event); +} 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 2ed2baa..456f09c 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 @@ -55,6 +55,12 @@ public interface AdaptedPlayer extends Handle, Audience { */ String getServerName(); + /** + * Gets the server that the player is currently connected to + * @return The server that the player is currently connected to. + */ + AdaptedServer getCurrentServer(); + /** * Gets the player's unique id (UUID) * @return The player's uuid diff --git a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java index cde11a5..0565f17 100644 --- a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java @@ -5,6 +5,7 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.jetbrains.annotations.NotNull; import us.ajg0702.queue.api.EventHandler; +import us.ajg0702.queue.api.events.SuccessfulSendEvent; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.players.QueuePlayer; import us.ajg0702.queue.api.queues.QueueServer; @@ -87,6 +88,9 @@ public class EventHandlerImpl implements EventHandler { server.removePlayer(player); server.setLastSentTime(System.currentTimeMillis()); main.getQueueManager().getSendingAttempts().remove(queuePlayer); + main.getTaskManager().runNow(() -> { + main.call(new SuccessfulSendEvent(queuePlayer, player.getCurrentServer())); + }); } } 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 b46f843..3b69bab 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueMain.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueMain.java @@ -2,6 +2,8 @@ package us.ajg0702.queue.common; import org.spongepowered.configurate.ConfigurateException; import us.ajg0702.queue.api.*; +import us.ajg0702.queue.api.events.Event; +import us.ajg0702.queue.api.events.utils.EventReceiver; import us.ajg0702.queue.api.premium.Logic; import us.ajg0702.queue.api.premium.LogicGetter; import us.ajg0702.queue.api.util.QueueLogger; @@ -12,7 +14,8 @@ import us.ajg0702.utils.common.Messages; import us.ajg0702.utils.common.Updater; import java.io.File; -import java.util.LinkedHashMap; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.regex.Pattern; @@ -124,6 +127,31 @@ public class QueueMain extends AjQueueAPI { updater.shutdown(); } + + private final Map, ArrayList>> listeners = new ConcurrentHashMap<>(); + + @SuppressWarnings("unchecked") + @Override + public void listen(Class event, EventReceiver handler) { + if(!Arrays.asList(event.getInterfaces()).contains(Event.class)) { + throw new IllegalArgumentException("You can only listen to ajQueue events!"); + } + List> existingList = listeners.computeIfAbsent(event, (k) -> new ArrayList<>()); + existingList.add((e) -> handler.execute((E) e)); + } + + public void call(Event event) { + List> list = listeners.computeIfAbsent(event.getClass(), (k) -> new ArrayList<>()); + list.forEach(eventReceiver -> { + try { + eventReceiver.execute(event); + } catch(Exception e) { + logger.severe("An external plugin threw an error while handling an event (this is probably not the fault of ajQueue!)", e); + } + }); + + } + @Override public ExecutorService getServersUpdateExecutor() { return taskManager.getServersUpdateExecutor(); 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 ba6ad62..f144e6c 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList; import net.kyori.adventure.text.Component; import net.kyori.adventure.title.Title; import us.ajg0702.queue.api.QueueManager; +import us.ajg0702.queue.api.events.PreQueueEvent; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.players.QueuePlayer; import us.ajg0702.queue.api.premium.Logic; @@ -208,6 +209,14 @@ public class QueueManagerImpl implements QueueManager { } } + + PreQueueEvent preQueueEvent = new PreQueueEvent(player, server); + main.call(preQueueEvent); + if(preQueueEvent.isCancelled()) return false; + + + // Player should be added! + ImmutableList list = server.getQueue(); QueuePlayer queuePlayer; AdaptedServer ideal = server.getIdealServer(player); diff --git a/common/src/main/java/us/ajg0702/queue/common/TaskManager.java b/common/src/main/java/us/ajg0702/queue/common/TaskManager.java index 52f3b0b..6abe8be 100644 --- a/common/src/main/java/us/ajg0702/queue/common/TaskManager.java +++ b/common/src/main/java/us/ajg0702/queue/common/TaskManager.java @@ -1,5 +1,7 @@ package us.ajg0702.queue.common; +import us.ajg0702.queue.common.utils.QueueThreadFactory; + import java.util.Arrays; import java.util.List; import java.util.concurrent.*; @@ -7,10 +9,9 @@ import java.util.concurrent.*; public class TaskManager { - final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); - final ScheduledExecutorService updateExecutor = Executors.newScheduledThreadPool(1); - - final ExecutorService serversUpdateExecutor = Executors.newCachedThreadPool(); + final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1, new QueueThreadFactory("GENERIC")); + final ScheduledExecutorService updateExecutor = Executors.newScheduledThreadPool(1, new QueueThreadFactory("UPDATE-EXECUTOR")); + final ExecutorService serversUpdateExecutor = Executors.newCachedThreadPool(new QueueThreadFactory("SERVER-UPDATE")); final QueueMain main; public TaskManager(QueueMain main) { @@ -128,6 +129,10 @@ public class TaskManager { return executor.schedule(runnable, delay, unit); } + public Future runNow(Runnable runnable) { + return executor.submit(runnable); + } + private ScheduledFuture scheduleAtFixedRate(ScheduledExecutorService executor, Runnable command, long initialDelay, long period, TimeUnit unit) { return executor.scheduleAtFixedRate(() -> { 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 cbdfd53..50a0e89 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 @@ -1,6 +1,7 @@ package us.ajg0702.queue.common.queues; import com.google.common.collect.ImmutableList; +import us.ajg0702.queue.api.events.PositionChangeEvent; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.players.QueuePlayer; import us.ajg0702.queue.api.queues.Balancer; @@ -203,6 +204,7 @@ public class QueueServerImpl implements QueueServer { public synchronized void removePlayer(QueuePlayer player) { main.getQueueManager().getSendingAttempts().remove(player); queue.remove(player); + positionChange(); } @Override @@ -226,6 +228,7 @@ public class QueueServerImpl implements QueueServer { } else { queue.add(player); } + positionChange(); } @Override @@ -316,4 +319,10 @@ public class QueueServerImpl implements QueueServer { return balancer; } + private void positionChange() { + main.getTaskManager().runNow( + () -> queue.forEach(queuePlayer -> main.call(new PositionChangeEvent(queuePlayer))) + ); + } + } diff --git a/common/src/main/java/us/ajg0702/queue/common/utils/QueueThreadFactory.java b/common/src/main/java/us/ajg0702/queue/common/utils/QueueThreadFactory.java new file mode 100644 index 0000000..514b9f1 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/utils/QueueThreadFactory.java @@ -0,0 +1,21 @@ +package us.ajg0702.queue.common.utils; + +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +public class QueueThreadFactory implements ThreadFactory { + private final String name; + private final AtomicInteger i = new AtomicInteger(0); + + public QueueThreadFactory(String name) { + this.name = name; + } + + @Override + public Thread newThread(@NotNull Runnable runnable) { + return new Thread(runnable, "AJQUEUE-" + name + "-" + i.incrementAndGet()); + + } +} 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 1627d2a..e9f3794 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 @@ -122,6 +122,12 @@ public class BungeePlayer implements AdaptedPlayer, Audience { return handle.getServer().getInfo().getName(); } + @Override + public AdaptedServer getCurrentServer() { + if(handle.getServer() == null) return null; + return new BungeeServer(handle.getServer().getInfo()); + } + @Override public UUID getUniqueId() { return handle.getUniqueId(); 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 dda062e..c73a1dc 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 @@ -17,6 +17,7 @@ import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.server.AdaptedServer; import us.ajg0702.queue.common.QueueMain; import us.ajg0702.queue.common.utils.Debug; +import us.ajg0702.queue.platforms.velocity.server.VelocityServer; import java.util.List; import java.util.Objects; @@ -111,10 +112,17 @@ public class VelocityPlayer implements AdaptedPlayer, Audience { @Override public String getServerName() { + AdaptedServer currentServer = getCurrentServer(); + if(currentServer == null) return null; + return currentServer.getName(); + } + + @Override + public AdaptedServer getCurrentServer() { Optional serverConnection = handle.getCurrentServer(); if(!serverConnection.isPresent()) return null; ServerConnection connection = serverConnection.get(); - return connection.getServerInfo().getName(); + return new VelocityServer(connection.getServer()); } @Override From e5d9df9aa80b3c97bc19dc4347a6f6384909268a Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 10 Jun 2023 09:34:02 -0700 Subject: [PATCH 16/51] Ignore plugin messages from disconnected players --- .../src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java | 1 + .../ajg0702/queue/common/communication/CommunicationManager.java | 1 + 2 files changed, 2 insertions(+) diff --git a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java index 0565f17..b477971 100644 --- a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java @@ -30,6 +30,7 @@ public class EventHandlerImpl implements EventHandler { @Override public void handleMessage(AdaptedPlayer receivingPlayer, byte[] data) { + if(!receivingPlayer.isConnected()) return; if(communicationManager == null) { communicationManager = new CommunicationManager(main); } diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java b/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java index 7533639..298fa40 100644 --- a/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java +++ b/common/src/main/java/us/ajg0702/queue/common/communication/CommunicationManager.java @@ -51,6 +51,7 @@ public class CommunicationManager { ComResponse response = handler.handleMessage(receivingPlayer, in.readUTF()); if(response == null) return; + if(!receivingPlayer.isConnected()) return; main.getPlatformMethods().sendPluginMessage( receivingPlayer, From 49a3812867003e165e879de02c05535d65874c6f Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 10 Jun 2023 09:38:26 -0700 Subject: [PATCH 17/51] [nolist] remove debug spigot-side warning --- .../ajg0702/queue/spigot/communication/ResponseManager.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseManager.java b/spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseManager.java index b8ed6a8..5ed1b87 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseManager.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/communication/ResponseManager.java @@ -21,10 +21,7 @@ public class ResponseManager { public void executeResponse(ComResponse response) { ResponseKey key = new ResponseKey(response.getIdentifier(), response.getFrom()); Consumer callback = responseMap.get(key); - if(callback == null) { - System.out.println("[ajQueue] No callback for " + key + " with " + response); - return; - } + if(callback == null) return; responseMap.remove(key); callback.accept(response); } From fa9f594830965bdebbbf15d953fdca94bcf31d3a Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 10 Jun 2023 09:41:42 -0700 Subject: [PATCH 18/51] Fixed PositionChangeEvent being called when a player's position didn't change --- .../us/ajg0702/queue/common/players/QueuePlayerImpl.java | 4 ++++ .../us/ajg0702/queue/common/queues/QueueServerImpl.java | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/us/ajg0702/queue/common/players/QueuePlayerImpl.java b/common/src/main/java/us/ajg0702/queue/common/players/QueuePlayerImpl.java index 5c1b619..379e7f6 100644 --- a/common/src/main/java/us/ajg0702/queue/common/players/QueuePlayerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/players/QueuePlayerImpl.java @@ -21,6 +21,8 @@ public class QueuePlayerImpl implements QueuePlayer { private final int maxOfflineTime; + public int lastPosition; + public QueuePlayerImpl(UUID uuid, String name, QueueServer server, int highestPriority, int maxOfflineTime) { this(null, name, uuid, server, highestPriority, maxOfflineTime); } @@ -39,6 +41,8 @@ public class QueuePlayerImpl implements QueuePlayer { this.name = name; this.maxOfflineTime = maxOfflineTime; + + lastPosition = getPosition(); } @Override 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 50a0e89..988d8be 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 @@ -321,7 +321,11 @@ public class QueueServerImpl implements QueueServer { private void positionChange() { main.getTaskManager().runNow( - () -> queue.forEach(queuePlayer -> main.call(new PositionChangeEvent(queuePlayer))) + () -> queue.forEach(queuePlayer -> { + if(((QueuePlayerImpl) queuePlayer).lastPosition != queuePlayer.getPosition()) { + main.call(new PositionChangeEvent(queuePlayer)); + } + }) ); } From 609f1e4b817538ef2312f14103636b82d6958d8e Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 11 Jun 2023 10:41:42 -0700 Subject: [PATCH 19/51] [nolist] use real UltraPermissionsAPI --- premium/build.gradle.kts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/premium/build.gradle.kts b/premium/build.gradle.kts index b4ef8b9..2a9861d 100644 --- a/premium/build.gradle.kts +++ b/premium/build.gradle.kts @@ -10,6 +10,7 @@ repositories { //mavenLocal() maven { url = uri("https://repo.ajg0702.us/releases/") } maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots") } + maven { url = uri("https://repo.techscode.com/repository/maven-releases/") } mavenCentral() } @@ -21,7 +22,7 @@ dependencies { compileOnly("com.google.guava:guava:30.1.1-jre") - compileOnly("me.TechsCode:FakeUltraPerms:1.0.2") + compileOnly("me.TechsCode:UltraPermissionsAPI:1.0.0") compileOnly("us.ajg0702:ajUtils:1.2.14") From bc3aa1ffe1096f45ac04cf3bb324f1d048cffd99 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 11 Jun 2023 10:42:06 -0700 Subject: [PATCH 20/51] [nolist] 2.5.0 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index cbbd27b..d4d7364 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ repositories { } allprojects { - version = "2.4.0" + version = "2.5.0" group = "us.ajg0702" plugins.apply("java") From e0c8c29204ffd983125c7027f193cd9babc27cd9 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 11 Jun 2023 10:44:13 -0700 Subject: [PATCH 21/51] [nolist] found why I needed fakeultraperms --- premium/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/premium/build.gradle.kts b/premium/build.gradle.kts index 2a9861d..92c3e01 100644 --- a/premium/build.gradle.kts +++ b/premium/build.gradle.kts @@ -22,7 +22,7 @@ dependencies { compileOnly("com.google.guava:guava:30.1.1-jre") - compileOnly("me.TechsCode:UltraPermissionsAPI:1.0.0") + compileOnly("me.TechsCode:FakeUltraPerms:1.0.2") compileOnly("us.ajg0702:ajUtils:1.2.14") From 06a4c47072f50544e5d10c736668d0fc0facf834 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Tue, 13 Jun 2023 14:53:33 -0700 Subject: [PATCH 22/51] Fixed invalid servers in placeholders throwing an error instead of just saying the server is invalid --- spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java b/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java index 7dcb80d..adeb7ea 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java @@ -121,6 +121,7 @@ public class SpigotAPI extends AjQueueSpigotAPI { String responseString = response.getResponse(); if(responseString.equals("invalid_server")) { future.completeExceptionally(new IllegalArgumentException(queueName + " does not exist!")); + return; } future.complete(Integer.valueOf(responseString)); }); @@ -148,6 +149,7 @@ public class SpigotAPI extends AjQueueSpigotAPI { String responseString = response.getResponse(); if(responseString.equals("invalid_server")) { future.completeExceptionally(new IllegalArgumentException(queueName + " does not exist!")); + return; } future.complete(responseString); }); From ca36bdfc1f7e0aa65d612a4326ecd96a1c815472 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 17 Jun 2023 11:55:42 -0700 Subject: [PATCH 23/51] Config re-format --- .../us/ajg0702/queue/common/TaskManager.java | 13 +- common/src/main/resources/config.yml | 427 ++++++++++-------- 2 files changed, 237 insertions(+), 203 deletions(-) diff --git a/common/src/main/java/us/ajg0702/queue/common/TaskManager.java b/common/src/main/java/us/ajg0702/queue/common/TaskManager.java index 6abe8be..87d665f 100644 --- a/common/src/main/java/us/ajg0702/queue/common/TaskManager.java +++ b/common/src/main/java/us/ajg0702/queue/common/TaskManager.java @@ -61,11 +61,14 @@ public class TaskManager { TimeUnit.MILLISECONDS ); - messageTask = scheduleAtFixedRate( - main.getQueueManager()::sendMessages, - main.getConfig().getInt("message-time"), - TimeUnit.SECONDS - ); + int messageTime = main.getConfig().getInt("message-time"); + if(messageTime > 0) { + messageTask = scheduleAtFixedRate( + main.getQueueManager()::sendMessages, + messageTime, + TimeUnit.SECONDS + ); + } actionBarTask = scheduleAtFixedRate( main.getQueueManager()::sendActionBars, diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index 74055e5..a4e6633 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -1,179 +1,66 @@ -# Dont touch this number please -config-version: 35 +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # +# _ ___ # +# (_) / _ \ # +# __ _ _ | | | | _ _ ___ _ _ ___ # +# / _` || || | | || | | | / _ \| | | | / _ \ # +# | (_| || |\ \/' /| |_| || __/| |_| || __/ # +# \__,_|| | \_/\_\ \__,_| \___| \__,_| \___| # +# _/ | # +# |__/ # +# # +# Welcome to the config for ajQueue! # +# # +# Make sure to read the comments above each option to know what that option does. # +# # +# If you have any questions, first make sure you've read the comment above the option, then # +# feel free to join my discord and ask there (invite link is on the plugin page) # +# # +# Happy configuring! # +# # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -# 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 +# The time the server will wait between sending people in the queue (in seconds, supports decimals) # Default: 5 wait-time: 5.0 -# The time that a server has to be offline to be marked as offline instead of restarting -# Default: 120 -offline-time: 120 - -# The time the server will wait between sending players update messages on what position they are in the queue. +# The time ajQueue will wait between sending players update messages on +# what position they are in the queue, their ETA, and status of the queue (in seconds) +# You can set to any negative number to disable the messages # Default: 10 message-time: 10 -# If a player is in a server, you can have the plugin make them automatically join a queue for another server -# Example with the default values: Player joins the limbo server, they will auto-join the queue for the lobbys group -# Note that you dont have to use groups. Just put the name of a server to use a single server instead. -queue-servers: - - 'limbo:lobbys' - -# Should the plugin send an actionbar to the player? -# The actionbar contains some info such as which server they are queued for, what position they are in, estimated time remaining, etc. -send-actionbar: true - -# What kick reasons should cause the player to be removed from the queue? -# For example, if one of the below kick reasons is 'banned' and the player gets kicked when trying to connect to -# a server in a queue with a message saying "You are banned from this server!" then it will kick them from the queue too. -kick-reasons: - - 'banned' - - 'blacklisted' - -# Should we completly kick the user from the server if they are in a queue-server -# and are kicked from the server with one of the above reasons? -# Note this will do nothing on servers that arent queue-servers -# (as in the config option queue-servers) -# Default: true -kick-kicked-players: true - -# Should we remove a player from the queue if they move servers? -# This will remove the player from if they switch to any other server -# Default: false -remove-player-on-server-switch: false - - -# Should we wait until the server is done loading to load the servers? -# Enable this if you have a plugin that adds servers to the server list during startup. -# Default: false -wait-to-load-servers: false - -# How long should we wait after the server finishes loading to load the server list? -# Only works if the above is enabled. -# This is in miliseconds so 1000 = 1 second -# Default: 500 -wait-to-load-servers-delay: 500 - - -# How often (in seconds) we should check for new servers to add queues for. -# If you dynamicly add servers, set this to something other than 0. -# To disable, set to 0 -# Default: 0 -reload-servers-interval: 0 - # Should we require permissions for players to be able to join queues? # If enabled, players will be required to have the permission ajqueue.queue. to be able to join queues +# Replace with the name of the server or group to let the player queue for # Default: false require-permission: false - -# Should we let players join more than one queue? -# If enabled, players will be able to be in multiple queues at once. -# If disabled, players will be removed from the previous queue when joining a new queue -# Default: true -allow-multiple-queues: true - -# If the player is queued for multiple servers, which server should we pick to use in things like placeholders and actionbars -# Options are first and last -# Default: last -multi-server-queue-pick: last - - -# THIS FEATURE IS ONLY AVAILABLE ON ajQueuePlus (https://www.spigotmc.org/resources/ajqueueplus.79123/) -# This will show players a different name than the actual proxy server name -# for example, instead of showing players "event-a", this option can make it appear as "Event A" -# With this example, you would use this: - "event-a:Event A" -# Note that currently players still have to use the normal names in queue commands and leave commands -# Format: "realname:Alias" -server-aliases: - - "event-a:Event A" - - -# How long should we wait after a server is online before sending players? -# The server will still show up as offline or restarting until this amount of time after its up -# Meant to let your server 'cool down' after lag from starting up -# In seconds -# Default: 1 -wait-after-online: 1 - - -# This is for helping with finding issues with the server pinged -# This will spam the console when enabled -# When this enabled, if servers are offline then it will spam errors. You can ignore them. -# Default: false -pinger-debug: false - - -# When a queue is paused, should we prevent players from joining it? -# Default: false -prevent-joining-paused: false - -# When a server goes back online, should we send all players in the queue instantly? -# Default: false -send-all-when-back-online: false - -# Require a permission for players to be able to join a queue from a server +# Require a permission for players to be able to join a queue from a server. # If enabled, players will need the permission ajqueue.joinfrom. to join queues. # Replace with the name of the server # Default: false joinfrom-server-permission: false -# Server groups are a group of servers that you can queue for. It will send you to the server that is the least full. -# If all servers in the group are full, it will act the same as it would when a single server is full. -# Same if all servers are offline. It will only send players to servers that are online. -# Format: "groupname:server1,server2,etc" -server-groups: - - "lobbys:lobby-1,lobby-2,lobby-3" - - -# Should we allow tab-completing in the /queue command? -# Default: true -tab-complete-queues: true - -# Should we have no wait time for these servers? -# If the server is joinable, the plugin will attempt to send players who join these queues as soon as they join. -# If the server is not immidiatly joinable, they will have to wait for the normal wait-time -# This also works with group -# NOTE: Server names are caps sensitive -send-instantly: - - "lobbys" - -# Should we log to the proxy console when a player fails to get sent to a server from the queue? -# Enable this if you are having an issue with one player stopping the queue -# Default: false -send-fail-debug: false - -# After how many (unsuccessfull) attempts of sending the player should we remove them from the queue? -# Set to -1 to disable -# Default: 10 -max-tries: 10 - # Should we enable the ajqueue.bypasspaused permission? # If enabled, anyone with the permission ajqueue.bypasspaused will be able to join paused servers # Default: false enable-bypasspaused-permission: false -# Should we check to make sure that people dont get sent quicker than wait-time? -# Default: true -check-last-player-sent-time: true -# Should we send debug info to the console when priority queue is used? -# This will print several lines to the console when a player joins a queue, -# so you should probably only use this for debugging purposes -# Default: false -priority-queue-debug: false +# What kick reasons should cause the player to be removed from the queue? +# This works on contains, so you only need to include a word or two from the kick message. +# For example, if one of the below kick reasons is 'banned' and the player gets kicked when trying to connect to +# a server in a queue with a message saying "You are banned from this server!" then it will kick them from the queue too. +kick-reasons: + - 'banned' + - 'blacklisted' + # When a player is kicked from a server, should we automatically add that player to the queue? -# You will still need to use another plugin to make sure the player doesnt get kicked from the proxy completly. +# On BungeeCord, you will still need to use another plugin to make sure the player doesn't get kicked from the proxy completely. # Default: false auto-add-to-queue-on-kick: false # The delay for the above option. @@ -182,19 +69,87 @@ auto-add-to-queue-on-kick: false auto-add-to-queue-on-kick-delay: 1 # With what kick reasons should we auto-add the player to the queue -# This wont work if auto-add-to-queue-on-kick is disabled. +# This won't work if auto-add-to-queue-on-kick is disabled. # If you set it to [], then all kick messages will cause the player to be added to the queue -# This works on contains, so you dont have to include the whole kick message, just a few words. +# This works on contains, so you don't have to include the whole kick message, just a few words. auto-add-kick-reasons: - "restarting" - "closed" + +# If a player is in a server, you can have the plugin make them automatically join a queue for another server +# Example with the default values: Player joins the limbo server, they will auto-join the queue for the lobbys group +# Note that you don't have to use groups. Just put the name of a server to use a single server instead. +# You do NOT have to set a queue server to use queues. +queue-servers: + - 'limbo:lobbys' + +# Should we completely kick the user from the server if they are in a queue-server +# and are kicked from the server with one of the above reasons? +# Note this will do nothing on servers that aren't queue-servers +# (as in the config option queue-servers) +# Default: true +kick-kicked-players: true + + +# Server groups are a group of servers that you can queue for. It will send you to the server that is the least full. +# If all servers in the group are full, it will act the same as it would when a single server is full. +# Same if all servers are offline. It will only send players to servers that are online. +# Format: "groupname:server1,server2,etc" +server-groups: + - "lobbys:lobby-1,lobby-2,lobby-3" + +# What balancer should we use for groups? +# If a group is not specified here, then the default one is used +# Example entry: - "bedwars:minigame" +# Balancers: +# default - Will send the player to the server in the group with the least number of players +# minigame - Will send the player to the server with the most players, until that server is full, which it will then send to the next server +balancer-types: + - "bedwars:minigame" + + +# What priority should we give whitelisted players priority when the server is whitelisted? +# This will have no effect if the server isn't whitelisted +# If you set to 0, this will be disabled +# If you have the free version, set it to 1 to enable +give-whitelisted-players-priority: 0 + +# What priority should we give players that are able to bypass paused priority when the server is paused? +# This will have no effect if the server isn't paused +# If you set to 0, this will be disabled +# If you have the free version, set it to 1 to enable +give-pausedbypass-players-priority: 0 + +# What priority should we give players that are able to bypass full servers priority when the server is full? +# This will have no effect if the server isn't full +# If you set to 0, this will be disabled +# If you have the free version, set it to 1 to enable +give-fulljoin-players-priority: 0 + + +# Should we remove a player from the queue if they move servers? +# This will remove the player from if they switch to any other server +# Default: false +remove-player-on-server-switch: false + # Should we enable the server command being a queue command? # This may require extra setup on bungeecord. See the wiki: # https://wiki.ajg0702.us/ajqueue/setup/replacing-server-command # Default: false enable-server-command: false +# What servers should we make slash server commands for? +# For example, if survival is in this list, then if a player executes /survival +# then they will be put in the queue for survival +# This works for both servers and groups +# If you have ajQueuePlus, you can also make aliases. +# For example, if you have a server called lobby, and you want people to be able to use /hub, you can use this: +# - "hub:lobby" +# If you have the free version, you can only put the server name, no aliases. +slash-servers: [] + + # Should we enable priority messages? # Configure the priority messages in the option below. # Default: false @@ -209,11 +164,118 @@ priority-messages: - "*:Joining the queue with a priority of {PRIORITY}!" - "100:Wow! You have a priority of 100!" + # 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 +# Should we log to the proxy console when a player fails to get sent to a server from the queue? +# Enable this if you are having an issue with one player stopping the queue +# Default: false +send-fail-debug: false + +# Should the plugin send an actionbar to the player? +# The actionbar contains some info such as which server they are queued for, what position they are in, estimated time remaining, etc. +send-actionbar: true + +# THIS FEATURE IS ONLY AVAILABLE ON ajQueuePlus (https://www.spigotmc.org/resources/ajqueueplus.79123/) +# This will show players a different name than the actual proxy server name +# for example, instead of showing players "event-a", this option can make it appear as "Event A" +# With this example, you would use this: - "event-a:Event A" +# Note that currently players still have to use the normal names in queue commands and leave commands +# Format: "realname:Alias" +server-aliases: + - "event-a:Event A" + +# The time that a server has to be offline to be marked as offline instead of restarting (in seconds) +# Default: 120 +offline-time: 120 + +# On velocity, should we end a player a message when they are kicked while trying to connect to a server with the queue? +# This has no effect on bungee, because the message is sent from bungee and there's no way to change that in ajQueue +# Default: false +velocity-kick-message: false + +# Should we wait until the server is done loading to load the servers? +# Enable this if you have a plugin that adds servers to the server list during startup. +# Default: false +wait-to-load-servers: false + +# How long should we wait after the server finishes loading to load the server list? +# Only works if the above is enabled. +# This is in miliseconds so 1000 = 1 second +# Default: 500 +wait-to-load-servers-delay: 500 + +# How often (in seconds) we should check for new servers to add queues for. +# If you dynamicly add servers, set this to something other than 0. +# To disable, set to 0 +# Default: 0 +reload-servers-interval: 0 + +# Should we let players join more than one queue? +# If enabled, players will be able to be in multiple queues at once. +# If disabled, players will be removed from the previous queue when joining a new queue +# Default: true +allow-multiple-queues: true + +# If the player is queued for multiple servers, which server should we pick to use in things like placeholders and actionbars +# Options are first and last +# Default: last +multi-server-queue-pick: last + +# How long should we wait after a server is online before sending players? +# The server will still show up as offline or restarting until this amount of time after its up +# Meant to let your server 'cool down' after lag from starting up +# In seconds +# Default: 1 +wait-after-online: 1 + +# This is for helping with finding issues with the server pinged +# This will spam the console when enabled +# When this enabled, if servers are offline then it will spam errors. You can ignore them. +# Default: false +pinger-debug: false + +# When a queue is paused, should we prevent players from joining it? +# (instead of having players wait in the queue until it's unpaused) +# Default: false +prevent-joining-paused: false + +# When a server goes back online, should we send all players in the queue instantly? +# Default: false +send-all-when-back-online: false + +# Should we allow tab-completing in the /queue command? +# Any server the player doesn't have permission for (require-permission) +# will not tab-complete +# Default: true +tab-complete-queues: true + +# Should we have no wait time for these servers? +# If the server is joinable, the plugin will attempt to send players who join these queues as soon as they join. +# If the server is not immidiatly joinable, they will have to wait for the normal wait-time +# This also works with group +# NOTE: Server names are caps sensitive +send-instantly: + - "lobbys" + +# After how many (unsuccessfull) attempts of sending the player should we remove them from the queue? +# Set to -1 to disable +# Default: 10 +max-tries: 10 + +# Should we check to make sure that people dont get sent quicker than wait-time? +# Default: true +check-last-player-sent-time: true + +# Should we send debug info to the console when priority queue is used? +# This will print several lines to the console when a player joins a queue, +# so you should probably only use this for debugging purposes +# Default: false +priority-queue-debug: 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) @@ -224,7 +286,6 @@ send-title: false 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. @@ -262,52 +323,9 @@ protocol-names: - "47:1.8.9" - "5:1.7.10" -# On velocity, should we end a player a message when they are kicked while trying to connect to a server with the queue? -# This has no effect on bungee, because the message is sent from bungee and theres no way to change that in ajQueue -# Default: false -velocity-kick-message: false - # Should the updater be enabled? enable-updater: true -# What servers should we make slash server commands for? -# For example, if survival is in this list, then if a player executes /survival -# then they will be put in the queue for survival -# This works for both servers and groups -# If you have ajQueuePlus, you can also make aliases. -# For example, if you have a server called lobby, and you want people to be able to use /hub, you can use this: -# - "hub:lobby" -# If you have the free version, you can only put the server name, no aliases. -slash-servers: [] - -# What balancer should we use? -# If a group is not specified here, then the default one is used -# Example entry: - "bedwars:minigame" -# Balancers: -# default - Will send the player to the server in the group with the least number of players -# minigame - Will send the player to the server with the most players, until that server is full, which it will then send to the next server -balancer-types: - - "bedwars:minigame" - -# What priority should we give whitelisted players priority when the server is whitelisted? -# This will have no effect if the server isnt whitelisted -# If you set to 0, this will be disabled -# If you have the free version, set it to 1 to enable -give-whitelisted-players-priority: 0 - -# What priority should we give players that are able to bypass paused priority when the server is paused? -# This will have no effect if the server isnt paused -# If you set to 0, this will be disabled -# If you have the free version, set it to 1 to enable -give-pausedbypass-players-priority: 0 - -# What priority should we give players that are able to bypass full servers priority when the server is full? -# This will have no effect if the server isnt full -# If you set to 0, this will be disabled -# If you have the free version, set it to 1 to enable -give-fulljoin-players-priority: 0 - - # Should we force players to be queued every few seconds for queue-servers? # This will check every few seconds, and if a player in a queue-server is # not in the queue for the target server, it will add them. @@ -321,10 +339,23 @@ queue-command-cooldown: 3 # Should any server switch (including the initial join) count against the queue command cooldown? include-server-switch-in-cooldown: false - -# The minimum time between pinging the server. +# The minimum time between pinging the server. (in seconds) # If ajQueue is pinging your backend servers too often, raise this number minimum-ping-time: 1.0 # Should we print some extra stuff to the console that might help aj diagnose some issues? -debug: false \ No newline at end of file +debug: false + + + +# # # # # # # # # # # # # # # # # # # # # +# # +# End of config. Happy queue-ing :) # +# # +# # # # # # # # # # # # # # # # # # # # # + + + + +# Dont touch this number please +config-version: 36 From 3e25fd7e2d2ae3bff935d7d75e44330c9d34a9cb Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 17 Jun 2023 11:55:59 -0700 Subject: [PATCH 24/51] [nolist] add more aliases for permissionlist debug command --- .../queue/commands/commands/manage/debug/PermissionList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/debug/PermissionList.java b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/debug/PermissionList.java index 06b73eb..473f15f 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/debug/PermissionList.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/debug/PermissionList.java @@ -26,7 +26,7 @@ public class PermissionList extends SubCommand { @Override public ImmutableList getAliases() { - return ImmutableList.of(); + return ImmutableList.of("permissionslist", "listpermissions", "listpermission"); } @Override From 12031cf8dd9596557fe53cbd7a267ccb3a656e1e Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 18 Jun 2023 17:23:47 -0700 Subject: [PATCH 25/51] Added require-queueserver-permission option to the config --- .../us/ajg0702/queue/common/EventHandlerImpl.java | 8 +++++++- .../us/ajg0702/queue/common/QueueManagerImpl.java | 8 +++++++- common/src/main/resources/config.yml | 13 ++++++++++--- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java index b477971..8497be3 100644 --- a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java @@ -108,7 +108,13 @@ public class EventHandlerImpl implements EventHandler { String[] parts = s.split(":"); String from = parts[0]; QueueServer to = main.getQueueManager().findServer(parts[1]); - if(from.equalsIgnoreCase(serverName) && to != null) { + if( + from.equalsIgnoreCase(serverName) && to != null && + ( + !main.getConfig().getBoolean("require-queueserver-permission") || + player.hasPermission("ajqueue.queueserver." + to.getName()) + ) + ) { main.getQueueManager().addToQueue(player, to); } } 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 f144e6c..4426d6c 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -467,7 +467,13 @@ public class QueueManagerImpl implements QueueManager { } return; } - if(!getPlayerQueues(player).contains(to)) { + if( + !getPlayerQueues(player).contains(to) && + ( + !main.getConfig().getBoolean("require-queueserver-permission") || + player.hasPermission("ajqueue.queueserver." + to.getName()) + ) + ) { addToQueue(player, to); } }); diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index a4e6633..1025256 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -255,18 +255,25 @@ tab-complete-queues: true # Should we have no wait time for these servers? # If the server is joinable, the plugin will attempt to send players who join these queues as soon as they join. -# If the server is not immidiatly joinable, they will have to wait for the normal wait-time +# If the server is not immediately joinable, they will have to wait for the normal wait-time # This also works with group # NOTE: Server names are caps sensitive send-instantly: - "lobbys" -# After how many (unsuccessfull) attempts of sending the player should we remove them from the queue? +# Should we require permissions for queue-servers to work? +# If enabled, players will need to have the ajqueue.queueserver. permission +# being the target server +# Note that this will only affect queue-servers +# Default: false +require-queueserver-permission: false + +# After how many (unsuccessful) attempts of sending the player should we remove them from the queue? # Set to -1 to disable # Default: 10 max-tries: 10 -# Should we check to make sure that people dont get sent quicker than wait-time? +# Should we check to make sure that people don't get sent quicker than wait-time? # Default: true check-last-player-sent-time: true From 06ed22e65f152e934155bd86489984d23b86081d Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Mon, 19 Jun 2023 07:54:33 -0700 Subject: [PATCH 26/51] Fixed player status placeholder not working --- .../common/communication/handlers/PlayerStatusHandler.java | 2 +- .../src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java | 3 ++- .../queue/spigot/placeholders/PlaceholderExpansion.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PlayerStatusHandler.java b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PlayerStatusHandler.java index 62e3d6e..d4f7df0 100644 --- a/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PlayerStatusHandler.java +++ b/common/src/main/java/us/ajg0702/queue/common/communication/handlers/PlayerStatusHandler.java @@ -17,7 +17,7 @@ public class PlayerStatusHandler extends MessageHandler { if(server == null) { return ComResponse .from("playerstatus") - .id(data) + .id(player.getUniqueId() + data) .with("invalid_server"); } if(!player.isConnected() || player.getServerName() == null) return null; diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java b/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java index adeb7ea..f37e366 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java @@ -142,10 +142,11 @@ public class SpigotAPI extends AjQueueSpigotAPI { if(p == null) throw new IllegalArgumentException("Player must be online!"); String channel = player == null ? "status" : "playerstatus"; + String id = player == null ? queueName : player + queueName; CompletableFuture future = new CompletableFuture<>(); - responseManager.awaitResponse(queueName, channel, response -> { + responseManager.awaitResponse(id, channel, response -> { String responseString = response.getResponse(); if(responseString.equals("invalid_server")) { future.completeExceptionally(new IllegalArgumentException(queueName + " does not exist!")); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java index f4d1eae..393f099 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/PlaceholderExpansion.java @@ -29,8 +29,8 @@ public class PlaceholderExpansion extends me.clip.placeholderapi.expansion.Place placeholders.add(new PositionOf(plugin)); placeholders.add(new Queued(plugin)); placeholders.add(new QueuedFor(plugin)); - placeholders.add(new Status(plugin)); placeholders.add(new StatusPlayer(plugin)); + placeholders.add(new Status(plugin)); } From fab9cd8d34139f8e536e5b1519fec2560238e677 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Mon, 19 Jun 2023 11:50:45 -0700 Subject: [PATCH 27/51] Fixed whitelisted status not showing for the non-player status placeholder --- .../java/us/ajg0702/queue/common/queues/QueueServerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 988d8be..58cb9a7 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 @@ -118,7 +118,7 @@ public class QueueServerImpl implements QueueServer { return msgs.getString("status.offline.paused"); } - if(p != null && server.isWhitelisted() && !server.getWhitelistedPlayers().contains(p.getUniqueId())) { + if(server.isWhitelisted() && (p == null || !server.getWhitelistedPlayers().contains(p.getUniqueId()))) { return msgs.getString("status.offline.whitelisted"); } @@ -154,7 +154,7 @@ public class QueueServerImpl implements QueueServer { return "paused"; } - if(p != null && server.isWhitelisted() && !server.getWhitelistedPlayers().contains(p.getUniqueId())) { + if(server.isWhitelisted() && (p == null || !server.getWhitelistedPlayers().contains(p.getUniqueId()))) { return "whitelisted"; } From 412d173d82163fd7aabdd793a04ee7753449bc4f Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Thu, 29 Jun 2023 11:35:34 -0500 Subject: [PATCH 28/51] Better fetching of players for spigot api --- .../java/us/ajg0702/queue/spigot/api/SpigotAPI.java | 11 +++++++++-- .../placeholders/placeholders/StatusPlayer.java | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java b/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java index f37e366..a126d18 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/api/SpigotAPI.java @@ -7,6 +7,7 @@ import us.ajg0702.queue.api.spigot.MessagedResponse; import us.ajg0702.queue.spigot.SpigotMain; import us.ajg0702.queue.spigot.communication.ResponseManager; +import java.util.Collection; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; @@ -113,7 +114,7 @@ public class SpigotAPI extends AjQueueSpigotAPI { @Override public Future getPlayersInQueue(String queueName) { - Player p = Bukkit.getOnlinePlayers().iterator().next(); + Player p = getSomePlayer(); CompletableFuture future = new CompletableFuture<>(); @@ -138,7 +139,7 @@ public class SpigotAPI extends AjQueueSpigotAPI { @Override public Future getServerStatusString(String queueName, UUID player) { - Player p = player == null ? Bukkit.getOnlinePlayers().iterator().next() : Bukkit.getPlayer(player); + Player p = player == null ? getSomePlayer() : Bukkit.getPlayer(player); if(p == null) throw new IllegalArgumentException("Player must be online!"); String channel = player == null ? "status" : "playerstatus"; @@ -175,4 +176,10 @@ public class SpigotAPI extends AjQueueSpigotAPI { return future; } + + private Player getSomePlayer() { + Collection players = Bukkit.getOnlinePlayers(); + if(players.size() == 0) return null; + return players.iterator().next(); + } } diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java index 8fe71e0..f7b8307 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java @@ -35,6 +35,8 @@ public class StatusPlayer extends Placeholder { String queue = matcher.group(1); UUIDStringKey key = new UUIDStringKey(p.getUniqueId(), queue); + if(!p.isOnline()) return "You aren't online!"; + Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { try { String response = AjQueueSpigotAPI.getInstance() From 46fedd2276acc5991f67b69c6151b721103c16b4 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Thu, 29 Jun 2023 12:36:53 -0500 Subject: [PATCH 29/51] Added plus-level-fallback to allow some leveled permissions on ajQueuePlus to work without a supported permission plugin --- common/src/main/resources/config.yml | 10 ++++- .../logic/permissions/hooks/BuiltInHook.java | 38 ++++++++++++++++++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index 1025256..a9c6f07 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -350,6 +350,12 @@ include-server-switch-in-cooldown: false # If ajQueue is pinging your backend servers too often, raise this number minimum-ping-time: 1.0 +# In ajQueuePlus, if your permission plugin isn't yet supported, you can use this workaround to +# be able to use levels 1-10 for priority, or 15, 30, 60, and 120 for stayqueued +# If you want more levels than that, contact aj to add support for your permission plugin if possible. +# Does nothing if you are not on ajQueuePlus, or if you have a supported permission plugin +plus-level-fallback: false + # Should we print some extra stuff to the console that might help aj diagnose some issues? debug: false @@ -364,5 +370,5 @@ debug: false -# Dont touch this number please -config-version: 36 +# Don't touch this number please +config-version: 37 diff --git a/premium/src/main/java/us/ajg0702/queue/logic/permissions/hooks/BuiltInHook.java b/premium/src/main/java/us/ajg0702/queue/logic/permissions/hooks/BuiltInHook.java index 1ea1391..e134a03 100644 --- a/premium/src/main/java/us/ajg0702/queue/logic/permissions/hooks/BuiltInHook.java +++ b/premium/src/main/java/us/ajg0702/queue/logic/permissions/hooks/BuiltInHook.java @@ -5,6 +5,8 @@ import us.ajg0702.queue.common.QueueMain; import us.ajg0702.queue.api.premium.PermissionHook; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; public class BuiltInHook implements PermissionHook { @@ -26,9 +28,41 @@ public class BuiltInHook implements PermissionHook { @Override public List getPermissions(AdaptedPlayer player) { - if(main.getPlatformMethods().getImplementationName().equals("velocity")) { - return new ArrayList<>(); + if(main.getConfig().getBoolean("plus-level-fallback")) { + List hasPermissions = new ArrayList<>(); + for (String fallbackPermission : fallbackPermissions) { + if(player.hasPermission(fallbackPermission)) { + hasPermissions.add(fallbackPermission); + } + } + if(!main.getPlatformMethods().getImplementationName().equals("velocity")) { + hasPermissions.addAll(player.getPermissions()); + } + return hasPermissions; } + + + if(main.getPlatformMethods().getImplementationName().equals("velocity")) { + return Collections.emptyList(); + } + return player.getPermissions(); } + + private final List fallbackPermissions = Arrays.asList( + "ajqueue.priority.1", + "ajqueue.priority.2", + "ajqueue.priority.3", + "ajqueue.priority.4", + "ajqueue.priority.5", + "ajqueue.priority.6", + "ajqueue.priority.7", + "ajqueue.priority.8", + "ajqueue.priority.9", + "ajqueue.priority.10", + "ajqueue.stayqueued.15", + "ajqueue.stayqueued.30", + "ajqueue.stayqueued.60", + "ajqueue.stayqueued.120" + ); } From 89a11c176bdf581f2ce0cf7883993180a8415471 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Thu, 29 Jun 2023 20:10:30 -0500 Subject: [PATCH 30/51] Fixed QueueScoreboardActivator not activating on the correct player --- .../main/java/us/ajg0702/queue/common/QueueManagerImpl.java | 2 +- spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) 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 4426d6c..ba04942 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -481,7 +481,7 @@ public class QueueManagerImpl implements QueueManager { } for (QueueServer s : servers) { for (QueuePlayer queuePlayer : s.getQueue()) { - AdaptedPlayer player = queuePlayer.getPlayer(); + AdaptedPlayer player = queuePlayer.getPlayer(); if (player == null || !player.isConnected()) continue; if(player.getServerName() == null) continue; main.getPlatformMethods().sendPluginMessage(player, "inqueueevent", "true"); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java b/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java index abde51e..63257aa 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java @@ -110,10 +110,7 @@ public class SpigotMain extends JavaPlugin implements PluginMessageListener,List } if(subchannel.equals("inqueueevent")) { - String playername = in.readUTF(); - Player p = Bukkit.getPlayer(playername); - if(p == null) return; - QueueScoreboardActivator e = new QueueScoreboardActivator(p); + QueueScoreboardActivator e = new QueueScoreboardActivator(player); Bukkit.getPluginManager().callEvent(e); return; } From 567f97f4406984f0dd1aa3ed83d4195ad1c2d6a0 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Fri, 7 Jul 2023 22:21:25 -0500 Subject: [PATCH 31/51] Ignore timeouts in placeholders --- .../queue/spigot/placeholders/placeholders/EstimatedTime.java | 4 +--- .../queue/spigot/placeholders/placeholders/InQueue.java | 4 +--- .../queue/spigot/placeholders/placeholders/Position.java | 4 +--- .../queue/spigot/placeholders/placeholders/PositionOf.java | 4 +--- .../queue/spigot/placeholders/placeholders/Queued.java | 4 +--- .../queue/spigot/placeholders/placeholders/QueuedFor.java | 4 +--- .../queue/spigot/placeholders/placeholders/Status.java | 4 +--- .../queue/spigot/placeholders/placeholders/StatusPlayer.java | 4 +--- 8 files changed, 8 insertions(+), 24 deletions(-) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java index a07b022..77d301b 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java @@ -40,9 +40,7 @@ public class EstimatedTime extends Placeholder { cache.put(p.getUniqueId(), response.getEither()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException e) { - plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); - } + } catch (TimeoutException ignored) {} }); return cache.getOrDefault(p.getUniqueId(), "..."); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java index 9b83582..5913750 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java @@ -39,9 +39,7 @@ public class InQueue extends Placeholder { cache.put(p.getUniqueId(), response + ""); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException e) { - plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); - } + } catch (TimeoutException ignored) {} }); return cache.getOrDefault(p.getUniqueId(), "..."); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java index 037420f..447a6a7 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java @@ -40,9 +40,7 @@ public class Position extends Placeholder { cache.put(p.getUniqueId(), response.getEither()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException e) { - plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); - } + } catch (TimeoutException ignored) {} }); return cache.getOrDefault(p.getUniqueId(), "..."); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java index a3c4cba..b3a2c0e 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java @@ -40,9 +40,7 @@ public class PositionOf extends Placeholder { cache.put(p.getUniqueId(), response.getEither()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException e) { - plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); - } + } catch (TimeoutException ignored) {} }); return cache.getOrDefault(p.getUniqueId(), "..."); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java index cf4d26a..bc7bd40 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java @@ -40,9 +40,7 @@ public class Queued extends Placeholder { cache.put(p.getUniqueId(), response.getEither()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException e) { - plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); - } + } catch (TimeoutException ignored) {} }); return cache.getOrDefault(p.getUniqueId(), "..."); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java index 13259e5..5dd7201 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java @@ -43,15 +43,13 @@ public class QueuedFor extends Placeholder { cache.put(queue, response + ""); } catch (InterruptedException e) { throw new RuntimeException(e); - } catch (TimeoutException e) { - plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); } catch (ExecutionException e) { if(e.getCause() instanceof IllegalArgumentException) { cache.put(queue, invalidMessage); } else { throw new RuntimeException(e); } - } + } catch (TimeoutException ignored) {} }); return cached; diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java index af1848d..db7780c 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java @@ -43,15 +43,13 @@ public class Status extends Placeholder { cache.put(queue, response); } catch (InterruptedException e) { throw new RuntimeException(e); - } catch (TimeoutException e) { - plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); } catch (ExecutionException e) { if(e.getCause() instanceof IllegalArgumentException) { cache.put(queue, invalidMessage); } else { throw new RuntimeException(e); } - } + } catch (TimeoutException ignored) {} }); return cached; diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java index f7b8307..88eb676 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java @@ -46,9 +46,7 @@ public class StatusPlayer extends Placeholder { cache.put(key, response); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException e) { - plugin.getLogger().log(Level.WARNING, "Timed out while trying to get placeholder data from proxy: ", e); - } + } catch (TimeoutException ignored) {} }); return cache.getOrDefault(key, "..."); From a0e8411cc6cb5606f358a70ef81f8f7593c68c73 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 8 Jul 2023 18:37:34 -0500 Subject: [PATCH 32/51] Should fix nullpointers while modifying queue --- .../java/us/ajg0702/queue/common/queues/QueueServerImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 58cb9a7..2ac2ec6 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 @@ -17,6 +17,7 @@ import us.ajg0702.utils.common.Messages; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; public class QueueServerImpl implements QueueServer { @@ -27,7 +28,7 @@ public class QueueServerImpl implements QueueServer { private final List servers; - private final List queue = new ArrayList<>(); + private final List queue = new CopyOnWriteArrayList<>(); private List supportedProtocols = new ArrayList<>(); From 8fe8713aaf319a7af65e520f8c159365f2018f2c Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Mon, 10 Jul 2023 10:56:24 -0500 Subject: [PATCH 33/51] [nolist] remove unnecessary synchronized --- .../us/ajg0702/queue/common/queues/QueueServerImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 2ac2ec6..9eea8f4 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 @@ -202,7 +202,7 @@ public class QueueServerImpl implements QueueServer { } @Override - public synchronized void removePlayer(QueuePlayer player) { + public void removePlayer(QueuePlayer player) { main.getQueueManager().getSendingAttempts().remove(player); queue.remove(player); positionChange(); @@ -221,7 +221,7 @@ public class QueueServerImpl implements QueueServer { } @Override - public synchronized void addPlayer(QueuePlayer player, int position) { + public void addPlayer(QueuePlayer player, int position) { if(!player.getQueueServer().equals(this) || queue.contains(player)) return; if(position >= 0) { @@ -291,7 +291,7 @@ public class QueueServerImpl implements QueueServer { return findPlayer(player.getUniqueId()); } @Override - public synchronized QueuePlayer findPlayer(UUID uuid) { + public QueuePlayer findPlayer(UUID uuid) { for(QueuePlayer queuePlayer : queue) { if(queuePlayer.getUniqueId().toString().equals(uuid.toString())) { return queuePlayer; From 391080483b76a27434f0cd37704a0d1bd17f3532 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Thu, 20 Jul 2023 22:41:41 -0500 Subject: [PATCH 34/51] Add option to allow re-queueing for groups --- .../us/ajg0702/queue/api/queues/Balancer.java | 3 ++- .../ajg0702/queue/common/QueueManagerImpl.java | 16 +++++++++------- .../common/queues/balancers/DefaultBalancer.java | 13 +++++++++---- .../queues/balancers/MinigameBalancer.java | 15 ++++++++++++--- common/src/main/resources/config.yml | 8 +++++++- 5 files changed, 39 insertions(+), 16 deletions(-) diff --git a/api/src/main/java/us/ajg0702/queue/api/queues/Balancer.java b/api/src/main/java/us/ajg0702/queue/api/queues/Balancer.java index 331aec4..806aabc 100644 --- a/api/src/main/java/us/ajg0702/queue/api/queues/Balancer.java +++ b/api/src/main/java/us/ajg0702/queue/api/queues/Balancer.java @@ -1,8 +1,9 @@ package us.ajg0702.queue.api.queues; +import org.jetbrains.annotations.Nullable; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.server.AdaptedServer; public interface Balancer { - AdaptedServer getIdealServer(AdaptedPlayer player); + AdaptedServer getIdealServer(@Nullable AdaptedPlayer player); } 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 ba04942..6b31a11 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -188,11 +188,13 @@ public class QueueManagerImpl implements QueueManager { } } - List notInServers = new ArrayList<>(server.getServers()); - notInServers.removeIf(adaptedServer -> !adaptedServer.getName().equals(player.getServerName())); - if(notInServers.size() > 0) { - player.sendMessage(msgs.getComponent("errors.already-connected", "SERVER:"+server.getAlias())); - return false; + if(!server.isGroup() || !main.getConfig().getBoolean("allow-group-requeue")) { + List notInServers = new ArrayList<>(server.getServers()); + notInServers.removeIf(adaptedServer -> !adaptedServer.getName().equals(player.getServerName())); + if(notInServers.size() > 0) { + player.sendMessage(msgs.getComponent("errors.already-connected", "SERVER:"+server.getAlias())); + return false; + } } ImmutableList beforeQueues = getPlayerQueues(player); @@ -438,7 +440,7 @@ public class QueueManagerImpl implements QueueManager { "TIME:"+ TimeUtils.timeString(time, msgs.getString("format.time.mins"), msgs.getString("format.time.secs")) ); - Title title = Title.title(titleMessage, subTitleMessage, Title.Times.of(Duration.ZERO, Duration.ofSeconds(2L), Duration.ZERO)); + Title title = Title.title(titleMessage, subTitleMessage, Title.Times.times(Duration.ZERO, Duration.ofSeconds(2L), Duration.ZERO)); player.showTitle(title); } } @@ -688,7 +690,7 @@ public class QueueManagerImpl implements QueueManager { "title.sending-now.subtitle", "SERVER:"+server.getAlias() ), - Title.Times.of(Duration.ZERO, Duration.ofSeconds(2L), Duration.ZERO) + Title.Times.times(Duration.ZERO, Duration.ofSeconds(2L), Duration.ZERO) )); } sendingNowAntiSpam.put(nextPlayer, System.currentTimeMillis()); diff --git a/common/src/main/java/us/ajg0702/queue/common/queues/balancers/DefaultBalancer.java b/common/src/main/java/us/ajg0702/queue/common/queues/balancers/DefaultBalancer.java index 6370f5b..8c90fe8 100644 --- a/common/src/main/java/us/ajg0702/queue/common/queues/balancers/DefaultBalancer.java +++ b/common/src/main/java/us/ajg0702/queue/common/queues/balancers/DefaultBalancer.java @@ -1,15 +1,13 @@ package us.ajg0702.queue.common.queues.balancers; +import org.jetbrains.annotations.Nullable; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.queues.Balancer; import us.ajg0702.queue.api.queues.QueueServer; import us.ajg0702.queue.api.server.AdaptedServer; -import us.ajg0702.queue.api.server.AdaptedServerPing; import us.ajg0702.queue.common.QueueMain; -import us.ajg0702.queue.common.utils.Debug; import us.ajg0702.utils.common.GenUtils; -import java.util.HashMap; import java.util.List; public class DefaultBalancer implements Balancer { @@ -22,7 +20,13 @@ public class DefaultBalancer implements Balancer { } @Override - public AdaptedServer getIdealServer(AdaptedPlayer player) { + public AdaptedServer getIdealServer(@Nullable AdaptedPlayer player) { + AdaptedServer alreadyConnected; + if(player == null) { + alreadyConnected = null; + } else { + alreadyConnected = player.getCurrentServer(); + } List servers = server.getServers(); AdaptedServer selected = null; int selectednum = 0; @@ -31,6 +35,7 @@ public class DefaultBalancer implements Balancer { } else { for(AdaptedServer sv : servers) { if(!sv.isOnline()) continue; + if(sv.equals(alreadyConnected)) continue; int online = sv.getPlayerCount(); if(selected == null) { selected = sv; diff --git a/common/src/main/java/us/ajg0702/queue/common/queues/balancers/MinigameBalancer.java b/common/src/main/java/us/ajg0702/queue/common/queues/balancers/MinigameBalancer.java index 941b82e..3eb67c3 100644 --- a/common/src/main/java/us/ajg0702/queue/common/queues/balancers/MinigameBalancer.java +++ b/common/src/main/java/us/ajg0702/queue/common/queues/balancers/MinigameBalancer.java @@ -1,13 +1,15 @@ package us.ajg0702.queue.common.queues.balancers; +import org.jetbrains.annotations.Nullable; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.queues.Balancer; import us.ajg0702.queue.api.queues.QueueServer; import us.ajg0702.queue.api.server.AdaptedServer; -import us.ajg0702.queue.api.server.AdaptedServerPing; import us.ajg0702.queue.common.QueueMain; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; public class MinigameBalancer implements Balancer { @@ -19,7 +21,13 @@ public class MinigameBalancer implements Balancer { } @Override - public AdaptedServer getIdealServer(AdaptedPlayer player) { + public AdaptedServer getIdealServer(@Nullable AdaptedPlayer player) { + AdaptedServer alreadyConnected; + if(player == null) { + alreadyConnected = null; + } else { + alreadyConnected = player.getCurrentServer(); + } List servers = server.getServers(); if(servers.size() == 1) { return servers.get(0); @@ -30,6 +38,7 @@ public class MinigameBalancer implements Balancer { for(AdaptedServer si : svs) { if(!si.isOnline()) continue; + if(si.equals(alreadyConnected)) continue; int online = si.getPlayerCount(); int max = si.getMaxPlayers(); if(online < max && si.isJoinable(player)) { diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index a9c6f07..05a0438 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -108,6 +108,12 @@ server-groups: balancer-types: - "bedwars:minigame" +# If a player is in a server that is in a group and they re-queue for that group, should we allow it? +# false - prevent player from re-queueing; say "already connected" message +# true - let player re-queue; will send them to a server other than the one they're connected to +# Default: false +allow-group-requeue: false + # What priority should we give whitelisted players priority when the server is whitelisted? # This will have no effect if the server isn't whitelisted @@ -371,4 +377,4 @@ debug: false # Don't touch this number please -config-version: 37 +config-version: 38 From 3a33b7b5120965ac34521c13d6547891de0806bc Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Thu, 20 Jul 2023 23:17:27 -0500 Subject: [PATCH 35/51] Fix player being removed before allow-group-requeue could work --- .../java/us/ajg0702/queue/api/players/QueuePlayer.java | 7 +++++++ .../java/us/ajg0702/queue/common/QueueManagerImpl.java | 4 +++- .../ajg0702/queue/common/players/QueuePlayerImpl.java | 10 ++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/us/ajg0702/queue/api/players/QueuePlayer.java b/api/src/main/java/us/ajg0702/queue/api/players/QueuePlayer.java index 7008553..9e5a3ff 100644 --- a/api/src/main/java/us/ajg0702/queue/api/players/QueuePlayer.java +++ b/api/src/main/java/us/ajg0702/queue/api/players/QueuePlayer.java @@ -1,6 +1,7 @@ package us.ajg0702.queue.api.players; import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.api.server.AdaptedServer; import javax.annotation.Nullable; import java.util.UUID; @@ -68,4 +69,10 @@ public interface QueuePlayer { * @return the max number of seconds this player can be offline before being removed from the queue */ int getMaxOfflineTime(); + + /** + * Gets the server that the player was in when they joined the queue + * @return the server that the player was in when they joined the queue + */ + AdaptedServer getInitialServer(); } 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 6b31a11..6138455 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -626,7 +626,9 @@ public class QueueManagerImpl implements QueueManager { // If the first person int the queue is offline or already in the server, find the next online player in the queue int i = 0; - while((nextPlayer == null || server.getServerNames().contains(nextPlayer.getServerName())) && i < server.getQueue().size()) { + List excludableServers = new ArrayList<>(server.getServerNames()); + if(nextQueuePlayer.getInitialServer() != null) excludableServers.remove(nextQueuePlayer.getInitialServer().getName()); + while((nextPlayer == null || excludableServers.contains(nextPlayer.getServerName())) && i < server.getQueue().size()) { if(nextPlayer != null) { // Remove them if they are already in the server server.removePlayer(nextQueuePlayer); if(server.getQueue().size() > i) { diff --git a/common/src/main/java/us/ajg0702/queue/common/players/QueuePlayerImpl.java b/common/src/main/java/us/ajg0702/queue/common/players/QueuePlayerImpl.java index 379e7f6..47a7b7d 100644 --- a/common/src/main/java/us/ajg0702/queue/common/players/QueuePlayerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/players/QueuePlayerImpl.java @@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.players.QueuePlayer; import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.api.server.AdaptedServer; import java.util.UUID; @@ -21,6 +22,8 @@ public class QueuePlayerImpl implements QueuePlayer { private final int maxOfflineTime; + private final AdaptedServer initialServer; + public int lastPosition; public QueuePlayerImpl(UUID uuid, String name, QueueServer server, int highestPriority, int maxOfflineTime) { @@ -42,6 +45,8 @@ public class QueuePlayerImpl implements QueuePlayer { this.maxOfflineTime = maxOfflineTime; + initialServer = player != null ? player.getCurrentServer() : null; + lastPosition = getPosition(); } @@ -106,6 +111,11 @@ public class QueuePlayerImpl implements QueuePlayer { return maxOfflineTime; } + @Override + public AdaptedServer getInitialServer() { + return initialServer; + } + private long leaveTime = 0; public void setLeaveTime(long leaveTime) { From d935ae337008cb17cf3ad929aa7d7954c6c8a249 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 22 Jul 2023 16:41:30 -0500 Subject: [PATCH 36/51] Filter auto-complete arguments --- .../commands/SlashServer/SlashServerCommand.java | 4 ++-- .../queue/commands/commands/leavequeue/LeaveCommand.java | 4 +++- .../queue/commands/commands/listqueues/ListCommand.java | 4 ++-- .../us/ajg0702/queue/commands/commands/manage/Kick.java | 4 ++-- .../ajg0702/queue/commands/commands/manage/KickAll.java | 5 +++-- .../queue/commands/commands/manage/ManageCommand.java | 2 +- .../us/ajg0702/queue/commands/commands/manage/Pause.java | 6 +++--- .../queue/commands/commands/manage/QueueList.java | 4 ++-- .../ajg0702/queue/commands/commands/manage/Reload.java | 4 ++-- .../us/ajg0702/queue/commands/commands/manage/Send.java | 7 ++++--- .../queue/commands/commands/queue/QueueCommand.java | 9 +++------ 11 files changed, 27 insertions(+), 26 deletions(-) diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java b/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java index 803b2f1..eaf7952 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java @@ -6,7 +6,7 @@ import us.ajg0702.queue.commands.BaseCommand; import us.ajg0702.queue.common.QueueMain; import us.ajg0702.utils.common.Messages; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class SlashServerCommand extends BaseCommand { @@ -60,6 +60,6 @@ public class SlashServerCommand extends BaseCommand { @Override public List autoComplete(ICommandSender sender, String[] args) { - return new ArrayList<>(); + return Collections.emptyList(); } } diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/leavequeue/LeaveCommand.java b/common/src/main/java/us/ajg0702/queue/commands/commands/leavequeue/LeaveCommand.java index 336a621..00909e6 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/leavequeue/LeaveCommand.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/leavequeue/LeaveCommand.java @@ -11,6 +11,7 @@ import us.ajg0702.queue.common.QueueMain; import us.ajg0702.utils.common.Messages; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class LeaveCommand extends BaseCommand { @@ -105,11 +106,12 @@ public class LeaveCommand extends BaseCommand { @Override public List autoComplete(ICommandSender sender, String[] args) { + if(args.length > 1) return Collections.emptyList(); List servers = main.getQueueManager().findPlayerInQueues(main.getPlatformMethods().senderToPlayer(sender)); List serverNames = new ArrayList<>(); for(QueuePlayer queuePlayer : servers) { serverNames.add(queuePlayer.getQueueServer().getName()); } - return serverNames; + return filterCompletion(serverNames, args[0]); } } diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/listqueues/ListCommand.java b/common/src/main/java/us/ajg0702/queue/commands/commands/listqueues/ListCommand.java index 2e9ff6c..814006c 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/listqueues/ListCommand.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/listqueues/ListCommand.java @@ -10,7 +10,7 @@ import us.ajg0702.queue.commands.BaseCommand; import us.ajg0702.queue.common.QueueMain; import us.ajg0702.utils.common.Messages; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class ListCommand extends BaseCommand { @@ -79,6 +79,6 @@ public class ListCommand extends BaseCommand { @Override public List autoComplete(ICommandSender sender, String[] args) { - return new ArrayList<>(); + return Collections.emptyList(); } } diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Kick.java b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Kick.java index e0d5197..450a9fe 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Kick.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Kick.java @@ -81,10 +81,10 @@ public class Kick extends SubCommand { @Override public List autoComplete(ICommandSender sender, String[] args) { if(args.length == 1) { - return main.getPlatformMethods().getPlayerNames(false); + return filterCompletion(main.getPlatformMethods().getPlayerNames(false), args[0]); } if(args.length == 2) { - return main.getQueueManager().getServerNames(); + return filterCompletion(main.getQueueManager().getServerNames(), args[1]); } return new ArrayList<>(); } diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/KickAll.java b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/KickAll.java index 57ff453..2dbeaa9 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/KickAll.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/KickAll.java @@ -9,6 +9,7 @@ import us.ajg0702.queue.common.QueueMain; import us.ajg0702.utils.common.Messages; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class KickAll extends SubCommand { @@ -65,9 +66,9 @@ public class KickAll extends SubCommand { @Override public List autoComplete(ICommandSender sender, String[] args) { if(args.length == 1) { - return main.getQueueManager().getServerNames(); + return filterCompletion(main.getQueueManager().getServerNames(), args[0]); } - return new ArrayList<>(); + return Collections.emptyList(); } } diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/ManageCommand.java b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/ManageCommand.java index b32e67a..d26fee2 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/ManageCommand.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/ManageCommand.java @@ -104,6 +104,6 @@ public class ManageCommand extends BaseCommand { commands.add(subCommand.getName()); commands.addAll(subCommand.getAliases()); } - return commands; + return filterCompletion(commands, args[0]); } } diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Pause.java b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Pause.java index 92205b7..bbe4121 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Pause.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Pause.java @@ -77,11 +77,11 @@ public class Pause extends SubCommand { if(args.length == 1) { List servers = new ArrayList<>(main.getQueueManager().getServerNames()); servers.add("all"); - return servers; + return filterCompletion(servers, args[0]); } if(args.length == 2) { - return Arrays.asList("on", "off", "true", "false"); + return filterCompletion(Arrays.asList("on", "off", "true", "false"), args[1]); } - return new ArrayList<>(); + return Collections.emptyList(); } } diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/QueueList.java b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/QueueList.java index 1aa49e3..fdc4961 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/QueueList.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/QueueList.java @@ -11,7 +11,7 @@ import us.ajg0702.queue.commands.SubCommand; import us.ajg0702.queue.common.QueueMain; import us.ajg0702.utils.common.Messages; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.regex.Pattern; @@ -88,6 +88,6 @@ public class QueueList extends SubCommand { @Override public java.util.List autoComplete(ICommandSender sender, String[] args) { - return new ArrayList<>(); + return Collections.emptyList(); } } diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Reload.java b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Reload.java index c45b0aa..9e8ac6c 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Reload.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Reload.java @@ -9,7 +9,7 @@ import us.ajg0702.queue.commands.SubCommand; import us.ajg0702.queue.common.QueueMain; import us.ajg0702.utils.common.Messages; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class Reload extends SubCommand { @@ -63,6 +63,6 @@ public class Reload extends SubCommand { @Override public List autoComplete(ICommandSender sender, String[] args) { - return new ArrayList<>(); + return Collections.emptyList(); } } diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Send.java b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Send.java index 576d3c2..ff14169 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Send.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/manage/Send.java @@ -10,6 +10,7 @@ import us.ajg0702.queue.common.QueueMain; import us.ajg0702.utils.common.Messages; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class Send extends SubCommand { @@ -93,12 +94,12 @@ public class Send extends SubCommand { if(args.length == 1) { List options = new ArrayList<>(main.getPlatformMethods().getServerNames()); options.addAll(main.getPlatformMethods().getPlayerNames(false)); - return options; + return filterCompletion(options, args[0]); } if(args.length == 2) { - return main.getQueueManager().getServerNames(); + return filterCompletion(main.getQueueManager().getServerNames(), args[1]); } - return new ArrayList<>(); + return Collections.emptyList(); } diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/queue/QueueCommand.java b/common/src/main/java/us/ajg0702/queue/commands/commands/queue/QueueCommand.java index 0409689..8952bf3 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/queue/QueueCommand.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/queue/QueueCommand.java @@ -8,10 +8,7 @@ import us.ajg0702.queue.commands.BaseCommand; import us.ajg0702.queue.common.QueueMain; import us.ajg0702.utils.common.Messages; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class QueueCommand extends BaseCommand { @@ -92,7 +89,7 @@ public class QueueCommand extends BaseCommand { @Override public List autoComplete(ICommandSender sender, String[] args) { if(!main.getConfig().getBoolean("tab-complete-queues")) { - return new ArrayList<>(); + return Collections.emptyList(); } if(args.length == 1) { List servers = filterCompletion(main.getQueueManager().getServerNames(), args[0]); @@ -101,6 +98,6 @@ public class QueueCommand extends BaseCommand { } return servers; } - return new ArrayList<>(); + return Collections.emptyList(); } } From d92d8796fd1b74954dd6def274f6ddce280e12bd Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Tue, 25 Jul 2023 14:37:14 -0500 Subject: [PATCH 37/51] Added ajqueue.make-room permission (disabled by default) --- .../java/us/ajg0702/queue/api/AjQueueAPI.java | 6 ++ .../ajg0702/queue/api/ServerTimeManager.java | 12 +++ .../us/ajg0702/queue/api/premium/Logic.java | 7 +- .../queue/common/EventHandlerImpl.java | 5 ++ .../us/ajg0702/queue/common/QueueMain.java | 13 +++ .../queue/common/QueueManagerImpl.java | 88 ++++++++++++++++++- .../queue/common/ServerTimeManagerImpl.java | 27 ++++++ common/src/main/resources/config.yml | 24 ++++- 8 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 api/src/main/java/us/ajg0702/queue/api/ServerTimeManager.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/ServerTimeManagerImpl.java 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 5a2fa72..c17d341 100644 --- a/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java +++ b/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java @@ -40,6 +40,12 @@ public abstract class AjQueueAPI { */ public abstract void setTimeBetweenPlayers(); + /** + * Gets the server time manager instance, which tracks when players last changed servers + * @return The server time manager instance + */ + public abstract ServerTimeManager getServerTimeManager(); + /** * Gets the ajQueue config * @return the ajQueue config diff --git a/api/src/main/java/us/ajg0702/queue/api/ServerTimeManager.java b/api/src/main/java/us/ajg0702/queue/api/ServerTimeManager.java new file mode 100644 index 0000000..7e75b95 --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/ServerTimeManager.java @@ -0,0 +1,12 @@ +package us.ajg0702.queue.api; + +import us.ajg0702.queue.api.players.AdaptedPlayer; + +public interface ServerTimeManager { + /** + * Gets the time that the player specified was last seen switching servers + * @param player The player to check + * @return The time that they last switched servers, in miliseconds since midnight, January 1, 1970, UTC + */ + long getLastServerChange(AdaptedPlayer player); +} diff --git a/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java b/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java index 8e1667d..a08fe98 100644 --- a/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java +++ b/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java @@ -59,7 +59,12 @@ public interface Logic { } if(fulljoinPriority > 0) { - if(server.isFull() && server.canJoinFull(player)) { + if(server.isFull() && (server.canJoinFull(player) || + ( + player.hasPermission("ajqueue.make-room") && + AjQueueAPI.getInstance().getConfig().getBoolean("enable-make-room-permission") + ) + )) { highest = Math.max(highest, fulljoinPriority); } } diff --git a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java index 8497be3..28b5198 100644 --- a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java @@ -58,6 +58,8 @@ public class EventHandlerImpl implements EventHandler { if(queues.size() > 0) { main.getQueueManager().sendMessage(main.getQueueManager().getSingleServer(player).findPlayer(player)); } + + main.serverTimeManager.playerChanged(player); } @Override @@ -77,6 +79,7 @@ public class EventHandlerImpl implements EventHandler { } main.getQueueManager().clear(player); QueueCommand.cooldowns.remove(player); + main.serverTimeManager.removePlayer(player); } @Override @@ -120,6 +123,8 @@ public class EventHandlerImpl implements EventHandler { } } + main.serverTimeManager.playerChanged(player); + } @Override 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 3b69bab..4688b6a 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueMain.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueMain.java @@ -27,6 +27,14 @@ public class QueueMain extends AjQueueAPI { } private double timeBetweenPlayers; + + protected ServerTimeManagerImpl serverTimeManager = new ServerTimeManagerImpl(); + + @Override + public ServerTimeManager getServerTimeManager() { + return serverTimeManager; + } + @Override public double getTimeBetweenPlayers() { return timeBetweenPlayers; @@ -230,6 +238,7 @@ public class QueueMain extends AjQueueAPI { d.put("status.now-in-queue", "&aYou are now queued for {SERVER}! &7You are in position &f{POS}&7 of &f{LEN}&7.\n&7Type &f/leavequeue&7 or &fclick here&7 to leave the queue!"); d.put("status.now-in-empty-queue", ""); d.put("status.sending-now", "&aSending you to &f{SERVER} &anow.."); + d.put("status.making-room", "Making room for you.."); d.put("errors.server-not-exist", "&cThe server {SERVER} does not exist!"); d.put("errors.already-queued", "&cYou are already queued for that server!"); @@ -241,6 +250,10 @@ public class QueueMain extends AjQueueAPI { d.put("errors.wrong-version.or", " or "); d.put("errors.wrong-version.comma", ", "); d.put("errors.too-fast-queue", "You're queueing too fast!"); + d.put("errors.kicked-to-make-room", "You were moved to the lobby to make room for another player."); + d.put("errors.make-room-failed.player", "Failed to make room for you in that server."); + d.put("errors.make-room-failed.admin", "Failed to make room for you in that server. Check the console for more information."); + 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 6138455..3105f06 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -660,7 +660,93 @@ public class QueueManagerImpl implements QueueManager { if(!server.canAccess(nextPlayer)) continue; - if(selected.isFull() && !selected.canJoinFull(nextPlayer)) continue; + if( + selected.isFull() && + !selected.canJoinFull(nextPlayer) && + !( + nextPlayer.hasPermission("ajqueue.make-room") && + main.getConfig().getBoolean("enable-make-room-permission") + ) + ) continue; + + + // ajqueue.make-room logic + if( + selected.isFull() && + !selected.canJoinFull(nextPlayer) && + main.getConfig().getBoolean("enable-make-room-permission") && + nextPlayer.hasPermission("ajqueue.make-room") && + !server.isGroup() + ) { + List players = selected.getPlayers(); + + // first, we need to find what the lowest priority on the server is + int lowestPriority = Integer.MAX_VALUE; + for (AdaptedPlayer player : players) { + int priority = main.getLogic().getPermissionGetter().getPriority(player); + if(priority < lowestPriority) lowestPriority = priority; + } + + boolean kickLongest = main.getConfig().getBoolean("make-room-kick-longest-playtime"); + + long selectedTime = kickLongest ? Long.MAX_VALUE : 0; + AdaptedPlayer selectedPlayer = null; + for (AdaptedPlayer player : players) { + long switchTime = main.getServerTimeManager().getLastServerChange(player); + if(selectedPlayer == null) { + selectedPlayer = player; + selectedTime = switchTime; + continue; + } + if(kickLongest) { + if(switchTime < selectedTime) { + selectedTime = switchTime; + selectedPlayer = player; + } + } else { + if(switchTime > selectedTime) { + selectedTime = switchTime; + selectedPlayer = player; + } + } + } + + + if(selectedPlayer == null) { + main.getLogger().warn( + "Unable to find player to kick from " + selected.getName() + " " + + "to let " + nextPlayer.getName() + "join!" + ); + } else { + Debug.info( + "Selected " + selectedPlayer.getName() + " " + + "to make room for " + nextPlayer.getName() + " in " + selected.getName() + ); + String kickToName = main.getConfig().getString("make-room-kick-to"); + AdaptedServer kickTo = main.getPlatformMethods().getServer(kickToName); + if(kickTo == null) { + main.getLogger().warn( + "Unable to make room due to '" + kickToName + "' not existing! " + + "Please configure make-room-kick-to in the config" + ); + boolean isAdmin = nextPlayer.hasPermission("ajqueue.manage"); + nextPlayer.sendMessage( + main.getMessages().getComponent( + isAdmin ? "errors.make-room-failed.admin" : "errors.make-room-failed.player" + ) + ); + } else { + selectedPlayer.connect(kickTo); + selectedPlayer.sendMessage(main.getMessages().getComponent("errors.kicked-to-make-room")); + + if(main.getTimeBetweenPlayers() >= 1d) { + nextPlayer.sendMessage(main.getMessages().getComponent("status.making-room")); + } + + continue; + } + } + } if(main.getConfig().getBoolean("enable-bypasspaused-permission")) { if(server.isPaused() && !nextPlayer.hasPermission("ajqueue.bypasspaused")) continue; diff --git a/common/src/main/java/us/ajg0702/queue/common/ServerTimeManagerImpl.java b/common/src/main/java/us/ajg0702/queue/common/ServerTimeManagerImpl.java new file mode 100644 index 0000000..5f37296 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/ServerTimeManagerImpl.java @@ -0,0 +1,27 @@ +package us.ajg0702.queue.common; + +import us.ajg0702.queue.api.ServerTimeManager; +import us.ajg0702.queue.api.players.AdaptedPlayer; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class ServerTimeManagerImpl implements ServerTimeManager { + + Map serverSwitches = new ConcurrentHashMap<>(); + + + @Override + public long getLastServerChange(AdaptedPlayer player) { + return serverSwitches.get(player.getUniqueId()); + } + + public void playerChanged(AdaptedPlayer player) { + serverSwitches.put(player.getUniqueId(), System.currentTimeMillis()); + } + + public void removePlayer(AdaptedPlayer player) { + serverSwitches.remove(player.getUniqueId()); + } +} diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index 05a0438..9b73ccd 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -129,6 +129,7 @@ give-pausedbypass-players-priority: 0 # What priority should we give players that are able to bypass full servers priority when the server is full? # This will have no effect if the server isn't full +# If you are using make-room, this also applies to that # If you set to 0, this will be disabled # If you have the free version, set it to 1 to enable give-fulljoin-players-priority: 0 @@ -279,6 +280,27 @@ require-queueserver-permission: false # Default: 10 max-tries: 10 + +# Should we enable the ajqueue.make-room permission? +# The make-room permission will force there to be room in a server. +# So, if a player with this permission queues for a server and has this permission, +# someone from the server will be moved to the lobby to make room +# This can be further configured using the next few options +# Default: false +enable-make-room-permission: false + +# What server should the make-room permission move players to? +# Default: lobby +make-room-kick-to: lobby + +# For the make-room permission, players with the lowest priority are kicked first. +# Of those players, this option decides which to kick. +# true - kick players who have been on the server the longest +# false - kick players who have been on nthe server the shortest +# Default: true +make-room-kick-longest-playtime: true + + # Should we check to make sure that people don't get sent quicker than wait-time? # Default: true check-last-player-sent-time: true @@ -377,4 +399,4 @@ debug: false # Don't touch this number please -config-version: 38 +config-version: 39 From 4fc7ca38ca3d5eb2ffd18a27fc08c03daf837315 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Tue, 25 Jul 2023 20:37:36 -0500 Subject: [PATCH 38/51] Fixed priorities not being taken into account with make-room --- .../src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java | 2 ++ 1 file changed, 2 insertions(+) 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 3105f06..f24165f 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -692,6 +692,8 @@ public class QueueManagerImpl implements QueueManager { long selectedTime = kickLongest ? Long.MAX_VALUE : 0; AdaptedPlayer selectedPlayer = null; for (AdaptedPlayer player : players) { + int priority = main.getLogic().getPermissionGetter().getPriority(player); + if(priority > lowestPriority) continue; // dont select players with higher priorities long switchTime = main.getServerTimeManager().getLastServerChange(player); if(selectedPlayer == null) { selectedPlayer = player; From 71c471c407aa82855a33a67a9581c0be2b9fb23c Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Wed, 26 Jul 2023 20:53:48 -0500 Subject: [PATCH 39/51] Add re-check-priority option to re-queue players when their priority increases --- .../us/ajg0702/queue/api/premium/Logic.java | 2 ++ .../us/ajg0702/queue/common/QueueMain.java | 1 + .../queue/common/QueueManagerImpl.java | 28 +++++++++++++++++-- .../us/ajg0702/queue/logic/FreeLogic.java | 5 ++++ common/src/main/resources/config.yml | 7 ++++- .../us/ajg0702/queue/logic/PremiumLogic.java | 9 ++++++ 6 files changed, 48 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java b/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java index a08fe98..d60468e 100644 --- a/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java +++ b/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java @@ -38,6 +38,8 @@ public interface Logic { */ PermissionGetter getPermissionGetter(); + int getHighestPriority(QueueServer queueServer, AdaptedServer server, AdaptedPlayer player); + static int getUnJoinablePriorities(QueueServer queueServer, AdaptedServer server, AdaptedPlayer player) { Config config = AjQueueAPI.getInstance().getConfig(); int highest = 0; 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 4688b6a..728e146 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueMain.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueMain.java @@ -239,6 +239,7 @@ public class QueueMain extends AjQueueAPI { d.put("status.now-in-empty-queue", ""); d.put("status.sending-now", "&aSending you to &f{SERVER} &anow.."); d.put("status.making-room", "Making room for you.."); + d.put("status.priority-increased", "You now have higher priority! Moving you up in the queue.."); d.put("errors.server-not-exist", "&cThe server {SERVER} does not exist!"); d.put("errors.already-queued", "&cYou are already queued for that server!"); 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 f24165f..08f1edf 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -447,6 +447,7 @@ public class QueueManagerImpl implements QueueManager { } protected final Map pausedAntiSpam = new ConcurrentHashMap<>(); + private boolean skipPriorityCheck = true; @Override public void sendQueueEvents() { @@ -489,6 +490,27 @@ public class QueueManagerImpl implements QueueManager { main.getPlatformMethods().sendPluginMessage(player, "inqueueevent", "true"); } } + if(main.getConfig().getBoolean("re-check-priority")) { + if(skipPriorityCheck) { + skipPriorityCheck = false; + } else { + for (QueueServer server : servers) { + for (QueuePlayer queuePlayer : server.getQueue()) { + if(queuePlayer.getPlayer() == null) continue; + AdaptedPlayer player = queuePlayer.getPlayer(); + AdaptedServer ideal = server.getIdealServer(player); + + int currentHighestPriority = main.getLogic().getHighestPriority(server, ideal, player); + if(queuePlayer.getPriority() >= currentHighestPriority) continue; + + player.sendMessage(main.getMessages().getComponent("status.priority-increased")); + + server.removePlayer(queuePlayer); + addToQueue(player, server); + } + } + } + } } @Override @@ -683,7 +705,7 @@ public class QueueManagerImpl implements QueueManager { // first, we need to find what the lowest priority on the server is int lowestPriority = Integer.MAX_VALUE; for (AdaptedPlayer player : players) { - int priority = main.getLogic().getPermissionGetter().getPriority(player); + int priority = main.getLogic().getHighestPriority(server, selected, player); if(priority < lowestPriority) lowestPriority = priority; } @@ -692,8 +714,8 @@ public class QueueManagerImpl implements QueueManager { long selectedTime = kickLongest ? Long.MAX_VALUE : 0; AdaptedPlayer selectedPlayer = null; for (AdaptedPlayer player : players) { - int priority = main.getLogic().getPermissionGetter().getPriority(player); - if(priority > lowestPriority) continue; // dont select players with higher priorities + int priority = main.getLogic().getHighestPriority(server, selected, player); + if(priority > lowestPriority) continue; // don't select players with higher priorities long switchTime = main.getServerTimeManager().getLastServerChange(player); if(selectedPlayer == null) { selectedPlayer = player; diff --git a/common/src/main/java/us/ajg0702/queue/logic/FreeLogic.java b/common/src/main/java/us/ajg0702/queue/logic/FreeLogic.java index 3feb389..fa16f35 100644 --- a/common/src/main/java/us/ajg0702/queue/logic/FreeLogic.java +++ b/common/src/main/java/us/ajg0702/queue/logic/FreeLogic.java @@ -28,6 +28,11 @@ public class FreeLogic implements Logic { return null; } + @Override + public int getHighestPriority(QueueServer queueServer, AdaptedServer server, AdaptedPlayer player) { + return player.hasPermission("ajqueue.priority") ? 1 : 0; + } + @Override public boolean hasAnyBypass(AdaptedPlayer player, String server) { return false; diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index 9b73ccd..b11fb4b 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -301,6 +301,11 @@ make-room-kick-to: lobby make-room-kick-longest-playtime: true +# Should we check every 4 seconds if a player has a higher priority permission than before +# If they do, they are removed and re-added to the queue (only if they would be put in a higher position) +# Default: false +re-check-priority: false + # Should we check to make sure that people don't get sent quicker than wait-time? # Default: true check-last-player-sent-time: true @@ -399,4 +404,4 @@ debug: false # Don't touch this number please -config-version: 39 +config-version: 40 diff --git a/premium/src/main/java/us/ajg0702/queue/logic/PremiumLogic.java b/premium/src/main/java/us/ajg0702/queue/logic/PremiumLogic.java index bd86144..1bf4e14 100644 --- a/premium/src/main/java/us/ajg0702/queue/logic/PremiumLogic.java +++ b/premium/src/main/java/us/ajg0702/queue/logic/PremiumLogic.java @@ -18,6 +18,15 @@ public class PremiumLogic implements Logic { return permissionGetter; } + @Override + public int getHighestPriority(QueueServer queueServer, AdaptedServer server, AdaptedPlayer player) { + int normalPriority = permissionGetter.getPriority(player); + int serverPriority = permissionGetter.getServerPriotity(queueServer.getName(), player); + int unJoinablePriority = Logic.getUnJoinablePriorities(queueServer, server, player); + + return Math.max(normalPriority, Math.max(serverPriority, unJoinablePriority)); + } + private final PermissionGetter permissionGetter; public PremiumLogic(QueueMain main) { permissionGetter = new PermissionGetterImpl(main); From 8d7d56a8c6d976271a92be0d3b879982e0552268 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Thu, 27 Jul 2023 09:40:01 -0500 Subject: [PATCH 40/51] move protocol-names to messages.yml and add newer version names --- .../us/ajg0702/queue/common/QueueMain.java | 52 ++++++++++++++++++- common/src/main/resources/config.yml | 44 +++------------- 2 files changed, 56 insertions(+), 40 deletions(-) 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 728e146..229fe71 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueMain.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueMain.java @@ -190,8 +190,6 @@ public class QueueMain extends AjQueueAPI { this.platformMethods = platformMethods; this.dataFolder = dataFolder; - constructMessages(); - try { config = new Config(dataFolder, new LogConverter(logger)); } catch (ConfigurateException e) { @@ -200,6 +198,8 @@ public class QueueMain extends AjQueueAPI { return; } + constructMessages(); + logic = logicGetter.constructLogic(); aliasManager = logicGetter.constructAliasManager(config); @@ -336,6 +336,54 @@ public class QueueMain extends AjQueueAPI { d.put("updater.fail", "An error occurred while downloading the update. Check the console for more info."); d.put("updater.already-downloaded", "The update has already been downloaded."); + List oldProtocolNames = config.getStringList("protocol-names"); + for (String oldProtocolName : oldProtocolNames) { + String[] parts = oldProtocolName.split(":"); + String protocol = parts[0]; + String name = parts[1]; + + d.put("protocol-names." + protocol, name); + } + + + d.putIfAbsent("protocol-names.763", "1.20.1"); + d.putIfAbsent("protocol-names.762", "1.19.4"); + d.putIfAbsent("protocol-names.761", "1.19.3"); + d.putIfAbsent("protocol-names.760", "1.19.2"); + d.putIfAbsent("protocol-names.759", "1.19"); + d.putIfAbsent("protocol-names.758", "1.18.2"); + d.putIfAbsent("protocol-names.757", "1.18.1"); + d.putIfAbsent("protocol-names.756", "1.17.1"); + d.putIfAbsent("protocol-names.755", "1.17"); + d.putIfAbsent("protocol-names.754", "1.16.5"); + d.putIfAbsent("protocol-names.753", "1.16.3"); + d.putIfAbsent("protocol-names.751", "1.16.2"); + d.putIfAbsent("protocol-names.736", "1.16.1"); + d.putIfAbsent("protocol-names.735", "1.16"); + d.putIfAbsent("protocol-names.578", "1.15.2"); + d.putIfAbsent("protocol-names.575", "1.15.1"); + d.putIfAbsent("protocol-names.573", "1.15"); + d.putIfAbsent("protocol-names.498", "1.14.4"); + d.putIfAbsent("protocol-names.490", "1.14.3"); + d.putIfAbsent("protocol-names.485", "1.14.2"); + d.putIfAbsent("protocol-names.480", "1.14.1"); + d.putIfAbsent("protocol-names.477", "1.14"); + d.putIfAbsent("protocol-names.404", "1.13.2"); + d.putIfAbsent("protocol-names.401", "1.13.1"); + d.putIfAbsent("protocol-names.393", "1.13"); + d.putIfAbsent("protocol-names.340", "1.12.2"); + d.putIfAbsent("protocol-names.338", "1.12.1"); + d.putIfAbsent("protocol-names.335", "1.12"); + d.putIfAbsent("protocol-names.316", "1.11.2"); + d.putIfAbsent("protocol-names.315", "1.11"); + d.putIfAbsent("protocol-names.210", "1.10.2"); + d.putIfAbsent("protocol-names.110", "1.9.4"); + d.putIfAbsent("protocol-names.109", "1.9.2"); + d.putIfAbsent("protocol-names.108", "1.9.1"); + d.putIfAbsent("protocol-names.107", "1.9"); + d.putIfAbsent("protocol-names.47", "1.8.9"); + d.putIfAbsent("protocol-names.5", "1.7.10"); + messages = new Messages(dataFolder, new LogConverter(logger), d); } } diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index b11fb4b..1ffcf1d 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -326,43 +326,6 @@ priority-queue-debug: false 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: - - "757:1.18.1" - - "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" - # Should the updater be enabled? enable-updater: true @@ -404,4 +367,9 @@ debug: false # Don't touch this number please -config-version: 40 +config-version: 41 + + +# This is ONLY here so that they can be moved to messages.yml. Please edit these in messages.yml! +protocol-names: [] +# ^ only edit these in messages.yml From 6592925c6d0aeba61204b39e7f4d068afbde9d87 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Mon, 31 Jul 2023 17:53:28 -0700 Subject: [PATCH 41/51] Added manual-max-players to the config, which allows you to set a max player count for servers/groups --- .../us/ajg0702/queue/api/premium/Logic.java | 10 ++-- .../ajg0702/queue/api/queues/QueueServer.java | 14 ++++- .../queue/api/server/AdaptedServer.java | 16 ++++- .../queue/common/QueueManagerImpl.java | 30 +++++++--- .../queue/common/queues/QueueServerImpl.java | 59 +++++++++++++++++-- .../queues/balancers/FirstBalancer.java | 37 ++++++++++++ common/src/main/resources/config.yml | 20 +++++-- .../bungeecord/server/BungeeServer.java | 11 ---- .../velocity/server/VelocityServer.java | 14 ----- 9 files changed, 159 insertions(+), 52 deletions(-) create mode 100644 common/src/main/java/us/ajg0702/queue/common/queues/balancers/FirstBalancer.java diff --git a/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java b/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java index d60468e..9dc7bf7 100644 --- a/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java +++ b/api/src/main/java/us/ajg0702/queue/api/premium/Logic.java @@ -61,12 +61,10 @@ public interface Logic { } if(fulljoinPriority > 0) { - if(server.isFull() && (server.canJoinFull(player) || - ( - player.hasPermission("ajqueue.make-room") && - AjQueueAPI.getInstance().getConfig().getBoolean("enable-make-room-permission") - ) - )) { + boolean hasMakeRoom = player.hasPermission("ajqueue.make-room") && AjQueueAPI.getInstance().getConfig().getBoolean("enable-make-room-permission"); + if( + (server.isFull() && (server.canJoinFull(player) || hasMakeRoom)) || + (queueServer.isManuallyFull() && (AdaptedServer.canJoinFull(player, queueServer.getName()) || hasMakeRoom))) { highest = Math.max(highest, fulljoinPriority); } } 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 652ca67..d8d135f 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 @@ -4,9 +4,7 @@ import com.google.common.collect.ImmutableList; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.players.QueuePlayer; import us.ajg0702.queue.api.server.AdaptedServer; -import us.ajg0702.queue.api.server.AdaptedServerPing; -import java.util.HashMap; import java.util.List; import java.util.UUID; @@ -69,6 +67,18 @@ public interface QueueServer { */ boolean isJoinable(AdaptedPlayer p); + /** + * Gets the manually-set max player count for this server/group + * @return The manually-set max player count + */ + int getManualMaxPlayers(); + + /** + * Checks if the total number of players in this server/group is above the manually-set max player count + * @return If the server is at or above the manually-set player limit + */ + boolean isManuallyFull(); + /** * Pauses or unpauses a server * @param paused true = paused, false = unpaused diff --git a/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServer.java b/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServer.java index 94c5f4f..80ee926 100644 --- a/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServer.java +++ b/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServer.java @@ -1,5 +1,6 @@ package us.ajg0702.queue.api.server; +import us.ajg0702.queue.api.AjQueueAPI; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.util.Handle; import us.ajg0702.queue.api.util.QueueLogger; @@ -52,7 +53,20 @@ public interface AdaptedServer extends Handle { */ int getOfflineTime(); - boolean canJoinFull(AdaptedPlayer player); + default boolean canJoinFull(AdaptedPlayer player) { + return canJoinFull(player, getName()); + } + + static boolean canJoinFull(AdaptedPlayer player, String serverName) { + if(player == null) return true; + return + player.hasPermission("ajqueue.joinfull") || + player.hasPermission("ajqueue.joinfullserver." + serverName) || + player.hasPermission("ajqueue.joinfullandbypassserver." + serverName) || + player.hasPermission("ajqueue.joinfullandbypass") || + (AjQueueAPI.getInstance().isPremium() && AjQueueAPI.getInstance().getLogic().getPermissionGetter().hasUniqueFullBypass(player, serverName)) + ; + } boolean justWentOnline(); 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 08f1edf..c44666d 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -598,9 +598,10 @@ public class QueueManagerImpl implements QueueManager { final ConcurrentHashMap sendingNowAntiSpam = new ConcurrentHashMap<>(); final Map sendingAttempts = new WeakHashMap<>(); + final Map makeRoomAntispam = new WeakHashMap<>(); @Override - public void sendPlayers(QueueServer queueServer) { + public synchronized void sendPlayers(QueueServer queueServer) { List sendingServers; if(queueServer == null) { sendingServers = new ArrayList<>(servers); @@ -633,7 +634,10 @@ public class QueueManagerImpl implements QueueManager { continue; } - if(selected.isFull() && !selected.canJoinFull(p.getPlayer())) continue; + if( + (selected.isFull() && !selected.canJoinFull(player)) || + (server.isManuallyFull() && !AdaptedServer.canJoinFull(player, server.getName())) + ) continue; player.sendMessage(msgs.getComponent("status.sending-now", "SERVER:"+server.getAlias())); Debug.info("Calling player.connect for " + player.getName() + "(send when back online)"); @@ -683,23 +687,33 @@ public class QueueManagerImpl implements QueueManager { if(!server.canAccess(nextPlayer)) continue; if( - selected.isFull() && - !selected.canJoinFull(nextPlayer) && + ( + (selected.isFull() && !selected.canJoinFull(nextPlayer)) || + (server.isManuallyFull() && !AdaptedServer.canJoinFull(nextPlayer, server.getName())) + ) && !( nextPlayer.hasPermission("ajqueue.make-room") && - main.getConfig().getBoolean("enable-make-room-permission") + main.getConfig().getBoolean("enable-make-room-permission") && + (!server.isGroup() || server.isManuallyFull()) // only use make-room on groups if the server is manually full ) ) continue; // ajqueue.make-room logic if( - selected.isFull() && - !selected.canJoinFull(nextPlayer) && + ( + (selected.isFull() && !selected.canJoinFull(nextPlayer)) || + (server.isManuallyFull() && !AdaptedServer.canJoinFull(nextPlayer, server.getName())) + ) && main.getConfig().getBoolean("enable-make-room-permission") && nextPlayer.hasPermission("ajqueue.make-room") && - !server.isGroup() + (!server.isGroup() || server.isManuallyFull()) && // only use make-room on groups if the server is manually full + ( // don't make room more than the minimum ping time + System.currentTimeMillis() - makeRoomAntispam.getOrDefault(nextQueuePlayer, 0L) + >= (main.getConfig().getDouble("minimum-ping-time") * 1e3) + ) ) { + makeRoomAntispam.put(nextQueuePlayer, System.currentTimeMillis()); List players = selected.getPlayers(); // first, we need to find what the lowest priority on the server is 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 9eea8f4..cbb3828 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 @@ -11,14 +11,13 @@ import us.ajg0702.queue.api.server.AdaptedServerPing; import us.ajg0702.queue.common.QueueMain; import us.ajg0702.queue.common.players.QueuePlayerImpl; import us.ajg0702.queue.common.queues.balancers.DefaultBalancer; +import us.ajg0702.queue.common.queues.balancers.FirstBalancer; import us.ajg0702.queue.common.queues.balancers.MinigameBalancer; import us.ajg0702.queue.common.utils.Debug; import us.ajg0702.utils.common.Messages; import java.util.*; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.TimeUnit; public class QueueServerImpl implements QueueServer { @@ -38,6 +37,9 @@ public class QueueServerImpl implements QueueServer { private long lastSentTime = 0; + private int manualMaxPlayers = Integer.MAX_VALUE; + + public QueueServerImpl(String name, QueueMain main, AdaptedServer server, List previousPlayers) { this(name, main, Collections.singletonList(server), previousPlayers); } @@ -55,11 +57,13 @@ public class QueueServerImpl implements QueueServer { String balancerType = type.substring(colon+1); if(groupName.equals(name)) { - //noinspection SwitchStatementWithTooFewBranches switch(balancerType.toLowerCase(Locale.ROOT)) { case "minigame": balancer = new MinigameBalancer(this, main); break; + case "first": + balancer = new FirstBalancer(this, main); + break; default: balancerType = "default"; balancer = new DefaultBalancer(this, main); @@ -73,6 +77,26 @@ public class QueueServerImpl implements QueueServer { Debug.info("Using default balancer for "+name); } + List manualLimits = main.getConfig().getStringList("manual-max-players"); + for (String manualLimit : manualLimits) { + String[] parts = manualLimit.split(":"); + if(parts.length != 2) { + main.getLogger().warn("Invalid manual limit: " + manualLimit); + continue; + } + String limitFor = parts[0]; + + if(!limitFor.equals(name)) continue; + + String limitStr = parts[1]; + try { + manualMaxPlayers = Integer.parseInt(limitStr); + } catch(NumberFormatException e) { + main.getLogger().warn("Invalid limit number for " + limitFor); + } + break; + } + for(QueuePlayer queuePlayer : previousPlayers) { if(queuePlayer.getPlayer() == null) { addPlayer( @@ -123,7 +147,7 @@ public class QueueServerImpl implements QueueServer { return msgs.getString("status.offline.whitelisted"); } - if(server.isFull() && !server.canJoinFull(p)) { + if((server.isFull() && !server.canJoinFull(p)) || (isManuallyFull() && !AdaptedServer.canJoinFull(p, getName()))) { return msgs.getString("status.offline.full"); } @@ -159,7 +183,7 @@ public class QueueServerImpl implements QueueServer { return "whitelisted"; } - if(server.isFull() && !server.canJoinFull(p)) { + if(((server.isFull() && !server.canJoinFull(p)) || (isManuallyFull() && !AdaptedServer.canJoinFull(p, getName())))) { return "full"; } @@ -186,11 +210,31 @@ public class QueueServerImpl implements QueueServer { @Override public boolean isJoinable(AdaptedPlayer p) { + if(isManuallyFull() && !AdaptedServer.canJoinFull(p, getName())) return false; AdaptedServer server = getIdealServer(p); if(server == null) return false; return server.isJoinable(p) && !isPaused(); } + @Override + public int getManualMaxPlayers() { + return manualMaxPlayers; + } + + @Override + public boolean isManuallyFull() { + int total = 0; + for (AdaptedServer server : servers) { + Optional lastPing = server.getLastPing(); + if(!lastPing.isPresent()) continue; + total += lastPing.get().getPlayerCount(); + } + +// Debug.info(total + " >= " + getManualMaxPlayers() + " = " + (total >= getManualMaxPlayers())); + + return total >= getManualMaxPlayers(); + } + @Override public synchronized void setPaused(boolean paused) { this.paused = paused; @@ -272,6 +316,11 @@ public class QueueServerImpl implements QueueServer { return ImmutableList.copyOf(names); } + @Override + public boolean isOnline() { + return QueueServer.super.isOnline(); + } + @Override public boolean isGroup() { return servers.size() > 1; diff --git a/common/src/main/java/us/ajg0702/queue/common/queues/balancers/FirstBalancer.java b/common/src/main/java/us/ajg0702/queue/common/queues/balancers/FirstBalancer.java new file mode 100644 index 0000000..0604768 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/queues/balancers/FirstBalancer.java @@ -0,0 +1,37 @@ +package us.ajg0702.queue.common.queues.balancers; + +import org.jetbrains.annotations.Nullable; +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.queues.Balancer; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.api.server.AdaptedServer; +import us.ajg0702.queue.common.QueueMain; + +public class FirstBalancer implements Balancer { + + private final QueueServer server; + private final QueueMain main; + public FirstBalancer(QueueServer server, QueueMain main) { + this.server = server; + this.main = main; + } + + @Override + public AdaptedServer getIdealServer(@Nullable AdaptedPlayer player) { + AdaptedServer alreadyConnected; + if(player == null) { + alreadyConnected = null; + } else { + alreadyConnected = player.getCurrentServer(); + } + for (AdaptedServer sv : server.getServers()) { + if(!sv.isOnline()) continue; + if(sv.equals(alreadyConnected)) continue; + if(!sv.isJoinable(player)) continue; + return sv; + } + + // If all servers are unavailable, just select the first one + return server.getServers().get(0); + } +} diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index 1ffcf1d..e53d287 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -91,6 +91,14 @@ queue-servers: # Default: true kick-kicked-players: true +# This option allows you to manually set player caps for servers +# Note that this does NOT override the player cap returned by the server. +# Format: - ':' +# Example: - 'lobbys:50' +# The example above will limit the lobbys group to have a total of 50 players. +# This works on both groups and individual servers +manual-max-players: [] + # Server groups are a group of servers that you can queue for. It will send you to the server that is the least full. # If all servers in the group are full, it will act the same as it would when a single server is full. @@ -101,10 +109,12 @@ server-groups: # What balancer should we use for groups? # If a group is not specified here, then the default one is used -# Example entry: - "bedwars:minigame" +# Example: - "bedwars:minigame" +# The example above will set the bedwars group to use the minigame balancer # Balancers: # default - Will send the player to the server in the group with the least number of players # minigame - Will send the player to the server with the most players, until that server is full, which it will then send to the next server +# first - Will send the player to the first available server in the group (as long as it is joinable) balancer-types: - "bedwars:minigame" @@ -211,12 +221,12 @@ wait-to-load-servers: false # How long should we wait after the server finishes loading to load the server list? # Only works if the above is enabled. -# This is in miliseconds so 1000 = 1 second +# This is in milliseconds so 1000 = 1 second # Default: 500 wait-to-load-servers-delay: 500 # How often (in seconds) we should check for new servers to add queues for. -# If you dynamicly add servers, set this to something other than 0. +# If you dynamically add servers, set this to something other than 0. # To disable, set to 0 # Default: 0 reload-servers-interval: 0 @@ -296,7 +306,7 @@ make-room-kick-to: lobby # For the make-room permission, players with the lowest priority are kicked first. # Of those players, this option decides which to kick. # true - kick players who have been on the server the longest -# false - kick players who have been on nthe server the shortest +# false - kick players who have been on the server the shortest # Default: true make-room-kick-longest-playtime: true @@ -367,7 +377,7 @@ debug: false # Don't touch this number please -config-version: 41 +config-version: 42 # This is ONLY here so that they can be moved to messages.yml. Please edit these in messages.yml! diff --git a/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServer.java b/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServer.java index 8361efd..55bb3f2 100644 --- a/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServer.java +++ b/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServer.java @@ -106,17 +106,6 @@ public class BungeeServer implements AdaptedServer { return offlineTime; } - @Override - public boolean canJoinFull(AdaptedPlayer player) { - if(player == null) return true; - return - player.hasPermission("ajqueue.joinfull") || - player.hasPermission("ajqueue.joinfullserver."+getName()) || - player.hasPermission("ajqueue.joinfullandbypassserver."+getName()) || - player.hasPermission("ajqueue.joinfullandbypass") || - (AjQueueAPI.getInstance().isPremium() && AjQueueAPI.getInstance().getLogic().getPermissionGetter().hasUniqueFullBypass(player, getName())) - ; - } @Override public boolean justWentOnline() { diff --git a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/server/VelocityServer.java b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/server/VelocityServer.java index e42268b..4630a7c 100644 --- a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/server/VelocityServer.java +++ b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/server/VelocityServer.java @@ -9,7 +9,6 @@ import us.ajg0702.queue.api.server.AdaptedServer; import us.ajg0702.queue.api.server.AdaptedServerInfo; import us.ajg0702.queue.api.server.AdaptedServerPing; import us.ajg0702.queue.api.util.QueueLogger; -import us.ajg0702.queue.common.utils.Debug; import us.ajg0702.queue.platforms.velocity.players.VelocityPlayer; import java.util.ArrayList; @@ -113,19 +112,6 @@ public class VelocityServer implements AdaptedServer { return offlineTime; } - @Override - public boolean canJoinFull(AdaptedPlayer player) { - if(player == null) return true; - Debug.info("on "+getName()); - return - player.hasPermission("ajqueue.joinfull") || - player.hasPermission("ajqueue.joinfullserver."+getName()) || - player.hasPermission("ajqueue.joinfullandbypassserver."+getName()) || - player.hasPermission("ajqueue.joinfullandbypass") || - (AjQueueAPI.getInstance().isPremium() && AjQueueAPI.getInstance().getLogic().getPermissionGetter().hasUniqueFullBypass(player, getName())) - ; - } - @Override public boolean justWentOnline() { return System.currentTimeMillis()-lastOffline <= (AjQueueAPI.getInstance().getConfig().getDouble("wait-time") * 2 * 1000) && isOnline(); From 1f875fa622784eeea7058e96dabe6a2f40e43cae Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sun, 6 Aug 2023 08:33:41 -0700 Subject: [PATCH 42/51] Fixed wait-after-online not doing anything --- .../java/us/ajg0702/queue/api/server/AdaptedServer.java | 6 ++++-- .../queue/platforms/bungeecord/server/BungeeServer.java | 5 +++++ .../queue/platforms/velocity/server/VelocityServer.java | 5 +++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServer.java b/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServer.java index 80ee926..50e5c26 100644 --- a/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServer.java +++ b/api/src/main/java/us/ajg0702/queue/api/server/AdaptedServer.java @@ -89,14 +89,16 @@ public interface AdaptedServer extends Handle { } /** - * Gets if the last ping was successfull + * Gets if the last ping was successful * (which almost always means the server is online) * @return If the server is determined to be online or not */ default boolean isOnline() { - return getLastPing().isPresent(); + return getLastPing().isPresent() && !shouldWaitAfterOnline(); } + boolean shouldWaitAfterOnline(); + /** * Gets the number of players currently online * @return The number of players online diff --git a/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServer.java b/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServer.java index 55bb3f2..84b6d0b 100644 --- a/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServer.java +++ b/platforms/bungeecord/src/main/java/us/ajg0702/queue/platforms/bungeecord/server/BungeeServer.java @@ -112,6 +112,11 @@ public class BungeeServer implements AdaptedServer { return System.currentTimeMillis()-lastOffline <= (AjQueueAPI.getInstance().getConfig().getDouble("wait-time") * 2 * 1000) && isOnline(); } + @Override + public boolean shouldWaitAfterOnline() { + return System.currentTimeMillis()-lastOffline <= (AjQueueAPI.getInstance().getConfig().getDouble("wait-after-online") * 2 * 1000) && getLastPing().isPresent(); + } + @Override public ServerInfo getHandle() { return handle; diff --git a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/server/VelocityServer.java b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/server/VelocityServer.java index 4630a7c..2ae6563 100644 --- a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/server/VelocityServer.java +++ b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/server/VelocityServer.java @@ -117,6 +117,11 @@ public class VelocityServer implements AdaptedServer { return System.currentTimeMillis()-lastOffline <= (AjQueueAPI.getInstance().getConfig().getDouble("wait-time") * 2 * 1000) && isOnline(); } + @Override + public boolean shouldWaitAfterOnline() { + return System.currentTimeMillis()-lastOffline <= (AjQueueAPI.getInstance().getConfig().getDouble("wait-after-online") * 2 * 1000) && getLastPing().isPresent(); + } + @Override public RegisteredServer getHandle() { return handle; From d95f892cfe6222b3a5e8876bd809867f3344fe76 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Mon, 14 Aug 2023 11:25:29 -0700 Subject: [PATCH 43/51] Don't parse placeholder if the player is no longer online --- .../queue/spigot/placeholders/placeholders/EstimatedTime.java | 1 + .../ajg0702/queue/spigot/placeholders/placeholders/InQueue.java | 1 + .../ajg0702/queue/spigot/placeholders/placeholders/Position.java | 1 + .../queue/spigot/placeholders/placeholders/PositionOf.java | 1 + .../ajg0702/queue/spigot/placeholders/placeholders/Queued.java | 1 + .../queue/spigot/placeholders/placeholders/QueuedFor.java | 1 + .../ajg0702/queue/spigot/placeholders/placeholders/Status.java | 1 + .../queue/spigot/placeholders/placeholders/StatusPlayer.java | 1 + 8 files changed, 8 insertions(+) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java index 77d301b..0db41f1 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java @@ -32,6 +32,7 @@ public class EstimatedTime extends Placeholder { @Override public String parse(Matcher matcher, OfflinePlayer p) { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + if(!p.isOnline()) return; try { MessagedResponse response = AjQueueSpigotAPI.getInstance() .getEstimatedTime(p.getUniqueId()) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java index 5913750..ed90dc2 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java @@ -31,6 +31,7 @@ public class InQueue extends Placeholder { @Override public String parse(Matcher matcher, OfflinePlayer p) { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + if(!p.isOnline()) return; try { Boolean response = AjQueueSpigotAPI.getInstance() .isInQueue(p.getUniqueId()) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java index 447a6a7..22c326a 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java @@ -32,6 +32,7 @@ public class Position extends Placeholder { @Override public String parse(Matcher matcher, OfflinePlayer p) { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + if(!p.isOnline()) return; try { MessagedResponse response = AjQueueSpigotAPI.getInstance() .getPosition(p.getUniqueId()) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java index b3a2c0e..4431246 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java @@ -32,6 +32,7 @@ public class PositionOf extends Placeholder { @Override public String parse(Matcher matcher, OfflinePlayer p) { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + if(!p.isOnline()) return; try { MessagedResponse response = AjQueueSpigotAPI.getInstance() .getTotalPositions(p.getUniqueId()) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java index bc7bd40..575b8f2 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java @@ -32,6 +32,7 @@ public class Queued extends Placeholder { @Override public String parse(Matcher matcher, OfflinePlayer p) { Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + if(!p.isOnline()) return; try { MessagedResponse response = AjQueueSpigotAPI.getInstance() .getQueueName(p.getUniqueId()) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java index 5dd7201..7dfb3ad 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/QueuedFor.java @@ -35,6 +35,7 @@ public class QueuedFor extends Placeholder { String cached = cache.getOrDefault(queue, "..."); Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + if(!p.isOnline()) return; try { Integer response = AjQueueSpigotAPI.getInstance() .getPlayersInQueue(queue) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java index db7780c..0e065f4 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java @@ -35,6 +35,7 @@ public class Status extends Placeholder { String cached = cache.getOrDefault(queue, "..."); Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + if(!p.isOnline()) return; try { String response = AjQueueSpigotAPI.getInstance() .getServerStatusString(queue) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java index 88eb676..c9766c1 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java @@ -38,6 +38,7 @@ public class StatusPlayer extends Placeholder { if(!p.isOnline()) return "You aren't online!"; Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> { + if(!p.isOnline()) return; try { String response = AjQueueSpigotAPI.getInstance() .getServerStatusString(queue, p.getUniqueId()) From de4ff2ba262bdd1b86ab0ca6a7b20e354a63ff01 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 19 Aug 2023 16:54:56 -0700 Subject: [PATCH 44/51] Ignore error from player no longer being online --- .../queue/spigot/placeholders/placeholders/EstimatedTime.java | 2 +- .../ajg0702/queue/spigot/placeholders/placeholders/InQueue.java | 2 +- .../queue/spigot/placeholders/placeholders/Position.java | 2 +- .../queue/spigot/placeholders/placeholders/PositionOf.java | 2 +- .../ajg0702/queue/spigot/placeholders/placeholders/Queued.java | 2 +- .../ajg0702/queue/spigot/placeholders/placeholders/Status.java | 2 +- .../queue/spigot/placeholders/placeholders/StatusPlayer.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java index 0db41f1..a9e1ebb 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/EstimatedTime.java @@ -41,7 +41,7 @@ public class EstimatedTime extends Placeholder { cache.put(p.getUniqueId(), response.getEither()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException ignored) {} + } catch (TimeoutException | IllegalArgumentException ignored) {} }); return cache.getOrDefault(p.getUniqueId(), "..."); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java index ed90dc2..7ebd222 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/InQueue.java @@ -40,7 +40,7 @@ public class InQueue extends Placeholder { cache.put(p.getUniqueId(), response + ""); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException ignored) {} + } catch (TimeoutException | IllegalArgumentException ignored) {} }); return cache.getOrDefault(p.getUniqueId(), "..."); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java index 22c326a..1dbf949 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Position.java @@ -41,7 +41,7 @@ public class Position extends Placeholder { cache.put(p.getUniqueId(), response.getEither()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException ignored) {} + } catch (TimeoutException | IllegalArgumentException ignored) {} }); return cache.getOrDefault(p.getUniqueId(), "..."); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java index 4431246..64a34ce 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/PositionOf.java @@ -41,7 +41,7 @@ public class PositionOf extends Placeholder { cache.put(p.getUniqueId(), response.getEither()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException ignored) {} + } catch (TimeoutException | IllegalArgumentException ignored) {} }); return cache.getOrDefault(p.getUniqueId(), "..."); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java index 575b8f2..91d895b 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Queued.java @@ -41,7 +41,7 @@ public class Queued extends Placeholder { cache.put(p.getUniqueId(), response.getEither()); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException ignored) {} + } catch (TimeoutException | IllegalArgumentException ignored) {} }); return cache.getOrDefault(p.getUniqueId(), "..."); diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java index 0e065f4..41575e0 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/Status.java @@ -50,7 +50,7 @@ public class Status extends Placeholder { } else { throw new RuntimeException(e); } - } catch (TimeoutException ignored) {} + } catch (TimeoutException | IllegalArgumentException ignored) {} }); return cached; diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java index c9766c1..a1a0bef 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/placeholders/placeholders/StatusPlayer.java @@ -47,7 +47,7 @@ public class StatusPlayer extends Placeholder { cache.put(key, response); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); - } catch (TimeoutException ignored) {} + } catch (TimeoutException | IllegalArgumentException ignored) {} }); return cache.getOrDefault(key, "..."); From c0b736b78176d5462948f663d8c3c9e33be5c447 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Mon, 28 Aug 2023 18:24:59 -0700 Subject: [PATCH 45/51] Add QueueHolder API --- .../java/us/ajg0702/queue/api/AjQueueAPI.java | 7 ++ .../us/ajg0702/queue/api/QueueHolder.java | 6 -- .../queue/api/queueholders/QueueHolder.java | 84 +++++++++++++++++++ .../api/queueholders/QueueHolderRegistry.java | 44 ++++++++++ .../ajg0702/queue/api/queues/QueueServer.java | 9 ++ .../queue/common/DefaultQueueHolder.java | 69 +++++++++++++++ .../us/ajg0702/queue/common/QueueMain.java | 2 + .../queue/common/queues/QueueServerImpl.java | 36 ++++---- common/src/main/resources/config.yml | 7 +- 9 files changed, 237 insertions(+), 27 deletions(-) delete mode 100644 api/src/main/java/us/ajg0702/queue/api/QueueHolder.java create mode 100644 api/src/main/java/us/ajg0702/queue/api/queueholders/QueueHolder.java create mode 100644 api/src/main/java/us/ajg0702/queue/api/queueholders/QueueHolderRegistry.java create mode 100644 common/src/main/java/us/ajg0702/queue/common/DefaultQueueHolder.java 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 c17d341..4e1d906 100644 --- a/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java +++ b/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java @@ -3,6 +3,7 @@ package us.ajg0702.queue.api; import us.ajg0702.queue.api.events.utils.EventReceiver; import us.ajg0702.queue.api.premium.Logic; import us.ajg0702.queue.api.premium.LogicGetter; +import us.ajg0702.queue.api.queueholders.QueueHolderRegistry; import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; import us.ajg0702.queue.api.util.QueueLogger; import us.ajg0702.utils.common.Config; @@ -12,6 +13,8 @@ import java.util.concurrent.ExecutorService; public abstract class AjQueueAPI { + public static QueueHolderRegistry queueHolderRegistry = new QueueHolderRegistry(); + public static AjQueueAPI INSTANCE; public static AjQueueSpigotAPI SPIGOT_INSTANCE; @@ -121,6 +124,10 @@ public abstract class AjQueueAPI { */ public abstract void shutdown(); + public static QueueHolderRegistry getQueueHolderRegistry() { + return queueHolderRegistry; + } + public abstract void listen(Class event, EventReceiver handler); public abstract ExecutorService getServersUpdateExecutor(); diff --git a/api/src/main/java/us/ajg0702/queue/api/QueueHolder.java b/api/src/main/java/us/ajg0702/queue/api/QueueHolder.java deleted file mode 100644 index a3ceb66..0000000 --- a/api/src/main/java/us/ajg0702/queue/api/QueueHolder.java +++ /dev/null @@ -1,6 +0,0 @@ -package us.ajg0702.queue.api; - -public interface QueueHolder { - boolean isAvailable(); - -} \ No newline at end of file diff --git a/api/src/main/java/us/ajg0702/queue/api/queueholders/QueueHolder.java b/api/src/main/java/us/ajg0702/queue/api/queueholders/QueueHolder.java new file mode 100644 index 0000000..d9cf7c6 --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/queueholders/QueueHolder.java @@ -0,0 +1,84 @@ +package us.ajg0702.queue.api.queueholders; + +import us.ajg0702.queue.api.players.AdaptedPlayer; +import us.ajg0702.queue.api.players.QueuePlayer; +import us.ajg0702.queue.api.queues.QueueServer; + +import java.util.List; +import java.util.UUID; + +public abstract class QueueHolder { + + private final QueueServer queueServer; + + public QueueHolder(QueueServer queueServer) { + this.queueServer = queueServer; + } + + /** + * Returns the identifier of this QueueHolder + * Used by the server owner in order to tell ajQueue to use this QueueHolder + * @return a string that is very unlikely to be re-used by another QueueHolder + */ + public abstract String getIdentifier(); + + + /** + * Adds a player to the end of the queue + * NOTE: Do not manually call this! Use the QueueManager to add players to queues + * @param player The QueuePlayer to add + */ + public abstract void addPlayer(QueuePlayer player); + + /** + * Adds a player to the specified position in the queue + * NOTE: Do not manually call this! Use the QueueManager to add players to queues + * @param player The QueuePlayer to add + * @param position The position to add them to + */ + public abstract void addPlayer(QueuePlayer player, int position); + + public void removePlayer(AdaptedPlayer player) { + removePlayer(player.getUniqueId()); + } + + public void removePlayer(UUID uuid) { + QueuePlayer player = findPlayer(uuid); + if(player == null) return; + removePlayer(player); + } + + /** + * Removes a player from the queue + * @param player The player to remove + */ + public abstract void removePlayer(QueuePlayer player); + + /** + * Finds the player with this uuid in this queue and returns the representative QueuePlayer + * @return The QueuePlayer representing the player, null if not found + */ + public abstract QueuePlayer findPlayer(UUID uuid); + + /** + * Finds the player with this username in this queue and returns the representative QueuePlayer + * @return The QueuePlayer representing the player, null if not found + */ + public abstract QueuePlayer findPlayer(String name); + + public QueuePlayer findPlayer(AdaptedPlayer player) { + return findPlayer(player.getUniqueId()); + } + + /** + * Returns the size of the queue + * @return The number of players in the queue + */ + public abstract int getQueueSize(); + + /** + * Get all players that are in the queue + * @return a list of players in the queue + */ + public abstract List getAllPlayers(); +} diff --git a/api/src/main/java/us/ajg0702/queue/api/queueholders/QueueHolderRegistry.java b/api/src/main/java/us/ajg0702/queue/api/queueholders/QueueHolderRegistry.java new file mode 100644 index 0000000..5ac96d7 --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/queueholders/QueueHolderRegistry.java @@ -0,0 +1,44 @@ +package us.ajg0702.queue.api.queueholders; + +import us.ajg0702.queue.api.AjQueueAPI; +import us.ajg0702.queue.api.queues.QueueServer; + +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class QueueHolderRegistry { + + private Map> holders = new ConcurrentHashMap<>(); + + /** + * Register a QueueHolder that can be used + * @param holder The QueueHolder to register + */ + public void register(String identifier, Class holder) { + holders.put(identifier, holder); + } + + public QueueHolder getQueueHolder(QueueServer queueServer) { + String queueHolderName = AjQueueAPI.getInstance().getConfig().getString("queue-holder"); + QueueHolder queueHolder = getQueueHolder(queueHolderName, queueServer); + if(queueHolder == null) { + AjQueueAPI.getInstance().getLogger().warn("Invalid queue-holder '" + queueHolderName + "'! Using the default one"); + return getQueueHolder("default", queueServer); + } + return queueHolder; + } + + public QueueHolder getQueueHolder(String identifier, QueueServer queueServer) { + Class holder = holders.get(identifier); + if(holder == null) return null; + try { + return holder.getConstructor(QueueServer.class).newInstance(queueServer); + } catch(NoSuchMethodException e) { + throw new IllegalArgumentException("QueueHolder " + identifier + " is missing the required constructor!"); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } +} 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 d8d135f..68c404d 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 @@ -3,6 +3,7 @@ package us.ajg0702.queue.api.queues; import com.google.common.collect.ImmutableList; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.players.QueuePlayer; +import us.ajg0702.queue.api.queueholders.QueueHolder; import us.ajg0702.queue.api.server.AdaptedServer; import java.util.List; @@ -17,7 +18,9 @@ public interface QueueServer { /** * Get the players who are queued. * @return The players who are queued + * @deprecated It is recommended to not use this method unless you absolutely have to. If you have to, use getQueueHolder().getAllPlayers() */ + @Deprecated ImmutableList getQueue(); /** @@ -219,6 +222,12 @@ public interface QueueServer { */ Balancer getBalancer(); + /** + * Gets the QueueHolder for this queue + * @return the QueueHolder that holds the queue + */ + QueueHolder getQueueHolder(); + /** * elliot is bad diff --git a/common/src/main/java/us/ajg0702/queue/common/DefaultQueueHolder.java b/common/src/main/java/us/ajg0702/queue/common/DefaultQueueHolder.java new file mode 100644 index 0000000..4fef9f5 --- /dev/null +++ b/common/src/main/java/us/ajg0702/queue/common/DefaultQueueHolder.java @@ -0,0 +1,69 @@ +package us.ajg0702.queue.common; + +import com.google.common.collect.ImmutableList; +import us.ajg0702.queue.api.players.QueuePlayer; +import us.ajg0702.queue.api.queueholders.QueueHolder; +import us.ajg0702.queue.api.queues.QueueServer; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CopyOnWriteArrayList; + +public class DefaultQueueHolder extends QueueHolder { + + List queue = new CopyOnWriteArrayList<>(); + + public DefaultQueueHolder(QueueServer queueServer) { + super(queueServer); + } + + @Override + public String getIdentifier() { + return "default"; + } + + @Override + public void addPlayer(QueuePlayer player) { + queue.add(player); + } + + @Override + public void addPlayer(QueuePlayer player, int position) { + queue.add(position, player); + } + + @Override + public void removePlayer(QueuePlayer player) { + queue.remove(player); + } + + @Override + public QueuePlayer findPlayer(UUID uuid) { + for(QueuePlayer queuePlayer : queue) { + if(queuePlayer.getUniqueId().toString().equals(uuid.toString())) { + return queuePlayer; + } + } + return null; + } + + @Override + public QueuePlayer findPlayer(String name) { + for(QueuePlayer queuePlayer : queue) { + if(queuePlayer.getName().equalsIgnoreCase(name)) { + return queuePlayer; + } + } + return null; + } + + @Override + public int getQueueSize() { + return queue.size(); + } + + @Override + public List getAllPlayers() { + return ImmutableList.copyOf(queue); + } +} 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 229fe71..3b0b5a0 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueMain.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueMain.java @@ -200,6 +200,8 @@ public class QueueMain extends AjQueueAPI { constructMessages(); + getQueueHolderRegistry().register("default", DefaultQueueHolder.class); + logic = logicGetter.constructLogic(); aliasManager = logicGetter.constructAliasManager(config); 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 cbb3828..72561d1 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 @@ -1,9 +1,11 @@ package us.ajg0702.queue.common.queues; import com.google.common.collect.ImmutableList; +import us.ajg0702.queue.api.AjQueueAPI; import us.ajg0702.queue.api.events.PositionChangeEvent; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.players.QueuePlayer; +import us.ajg0702.queue.api.queueholders.QueueHolder; import us.ajg0702.queue.api.queues.Balancer; import us.ajg0702.queue.api.queues.QueueServer; import us.ajg0702.queue.api.server.AdaptedServer; @@ -17,7 +19,6 @@ import us.ajg0702.queue.common.utils.Debug; import us.ajg0702.utils.common.Messages; import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; public class QueueServerImpl implements QueueServer { @@ -27,7 +28,7 @@ public class QueueServerImpl implements QueueServer { private final List servers; - private final List queue = new CopyOnWriteArrayList<>(); + private final QueueHolder queueHolder = AjQueueAPI.getQueueHolderRegistry().getQueueHolder(this); private List supportedProtocols = new ArrayList<>(); @@ -123,7 +124,7 @@ public class QueueServerImpl implements QueueServer { @Override public ImmutableList getQueue() { - return ImmutableList.copyOf(queue); + return ImmutableList.copyOf(queueHolder.getAllPlayers()); } @Override @@ -248,7 +249,7 @@ public class QueueServerImpl implements QueueServer { @Override public void removePlayer(QueuePlayer player) { main.getQueueManager().getSendingAttempts().remove(player); - queue.remove(player); + queueHolder.removePlayer(player); positionChange(); } @@ -266,12 +267,12 @@ public class QueueServerImpl implements QueueServer { @Override public void addPlayer(QueuePlayer player, int position) { - if(!player.getQueueServer().equals(this) || queue.contains(player)) return; + if(!player.getQueueServer().equals(this) || queueHolder.findPlayer(player.getUniqueId()) != null) return; if(position >= 0) { - queue.add(position, player); + queueHolder.addPlayer(player, position); } else { - queue.add(player); + queueHolder.addPlayer(player); } positionChange(); } @@ -328,12 +329,7 @@ public class QueueServerImpl implements QueueServer { @Override public QueuePlayer findPlayer(String player) { - for(QueuePlayer queuePlayer : queue) { - if(queuePlayer.getName().equalsIgnoreCase(player)) { - return queuePlayer; - } - } - return null; + return queueHolder.findPlayer(player); } @Override public QueuePlayer findPlayer(AdaptedPlayer player) { @@ -341,12 +337,7 @@ public class QueueServerImpl implements QueueServer { } @Override public QueuePlayer findPlayer(UUID uuid) { - for(QueuePlayer queuePlayer : queue) { - if(queuePlayer.getUniqueId().toString().equals(uuid.toString())) { - return queuePlayer; - } - } - return null; + return queueHolder.findPlayer(uuid); } @Override @@ -369,9 +360,14 @@ public class QueueServerImpl implements QueueServer { return balancer; } + @Override + public QueueHolder getQueueHolder() { + return queueHolder; + } + private void positionChange() { main.getTaskManager().runNow( - () -> queue.forEach(queuePlayer -> { + () -> queueHolder.getAllPlayers().forEach(queuePlayer -> { if(((QueuePlayerImpl) queuePlayer).lastPosition != queuePlayer.getPosition()) { main.call(new PositionChangeEvent(queuePlayer)); } diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index e53d287..846b3d1 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -290,6 +290,11 @@ require-queueserver-permission: false # Default: 10 max-tries: 10 +# What QueueHolder should we use? +# By default, the only QueueHolder available is 'default' +# But more may be available via addons (registered via the API) +queue-holder: default + # Should we enable the ajqueue.make-room permission? # The make-room permission will force there to be room in a server. @@ -377,7 +382,7 @@ debug: false # Don't touch this number please -config-version: 42 +config-version: 43 # This is ONLY here so that they can be moved to messages.yml. Please edit these in messages.yml! From 52938eeb4d0d6892ec4b9cc13be7108555599d9a Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Fri, 22 Sep 2023 09:40:11 -0700 Subject: [PATCH 46/51] Added api to register custom PermissionHooks --- .../java/us/ajg0702/queue/api/AjQueueAPI.java | 7 ++++++ .../api/premium/PermissionHookRegistry.java | 24 +++++++++++++++++++ .../permissions/PermissionGetterImpl.java | 20 ++++++++-------- 3 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 api/src/main/java/us/ajg0702/queue/api/premium/PermissionHookRegistry.java 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 4e1d906..fc868e3 100644 --- a/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java +++ b/api/src/main/java/us/ajg0702/queue/api/AjQueueAPI.java @@ -3,6 +3,7 @@ package us.ajg0702.queue.api; import us.ajg0702.queue.api.events.utils.EventReceiver; import us.ajg0702.queue.api.premium.Logic; import us.ajg0702.queue.api.premium.LogicGetter; +import us.ajg0702.queue.api.premium.PermissionHookRegistry; import us.ajg0702.queue.api.queueholders.QueueHolderRegistry; import us.ajg0702.queue.api.spigot.AjQueueSpigotAPI; import us.ajg0702.queue.api.util.QueueLogger; @@ -15,6 +16,8 @@ public abstract class AjQueueAPI { public static QueueHolderRegistry queueHolderRegistry = new QueueHolderRegistry(); + public static PermissionHookRegistry permissionHookRegistry = new PermissionHookRegistry(); + public static AjQueueAPI INSTANCE; public static AjQueueSpigotAPI SPIGOT_INSTANCE; @@ -128,6 +131,10 @@ public abstract class AjQueueAPI { return queueHolderRegistry; } + public static PermissionHookRegistry getPermissionHookRegistry() { + return permissionHookRegistry; + } + public abstract void listen(Class event, EventReceiver handler); public abstract ExecutorService getServersUpdateExecutor(); diff --git a/api/src/main/java/us/ajg0702/queue/api/premium/PermissionHookRegistry.java b/api/src/main/java/us/ajg0702/queue/api/premium/PermissionHookRegistry.java new file mode 100644 index 0000000..8762cf9 --- /dev/null +++ b/api/src/main/java/us/ajg0702/queue/api/premium/PermissionHookRegistry.java @@ -0,0 +1,24 @@ +package us.ajg0702.queue.api.premium; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class PermissionHookRegistry { + private final Map hooks = new HashMap<>(); + + public void register(PermissionHook... permissionHooks) { + for (PermissionHook hook : permissionHooks) { + if(hooks.containsKey(hook.getName())) { + throw new IllegalArgumentException("Hook " + hook.getName() + " is already registered!"); + } + } + for (PermissionHook hook : permissionHooks) { + hooks.put(hook.getName(), hook); + } + } + + public Collection getRegisteredHooks() { + return hooks.values(); + } +} diff --git a/premium/src/main/java/us/ajg0702/queue/logic/permissions/PermissionGetterImpl.java b/premium/src/main/java/us/ajg0702/queue/logic/permissions/PermissionGetterImpl.java index 9cff1a4..e624b0e 100644 --- a/premium/src/main/java/us/ajg0702/queue/logic/permissions/PermissionGetterImpl.java +++ b/premium/src/main/java/us/ajg0702/queue/logic/permissions/PermissionGetterImpl.java @@ -1,9 +1,11 @@ package us.ajg0702.queue.logic.permissions; +import us.ajg0702.queue.api.AjQueueAPI; import us.ajg0702.queue.api.players.AdaptedPlayer; import us.ajg0702.queue.api.premium.PermissionGetter; import us.ajg0702.queue.api.premium.PermissionHook; import us.ajg0702.queue.common.QueueMain; +import us.ajg0702.queue.common.utils.Debug; import us.ajg0702.queue.logic.permissions.hooks.AquaCoreHook; import us.ajg0702.queue.logic.permissions.hooks.BuiltInHook; import us.ajg0702.queue.logic.permissions.hooks.LuckPermsHook; @@ -13,16 +15,15 @@ import java.util.*; public class PermissionGetterImpl implements PermissionGetter { - private final List hooks; - private final QueueMain main; + private PermissionHook builtInHook; public PermissionGetterImpl(QueueMain main) { - hooks = Arrays.asList( - new BuiltInHook(main), + AjQueueAPI.getPermissionHookRegistry().register( new LuckPermsHook(main), new UltraPermissionsHook(main), new AquaCoreHook(main) ); + builtInHook = new BuiltInHook(main); this.main = main; } @@ -30,16 +31,15 @@ public class PermissionGetterImpl implements PermissionGetter { @Override public PermissionHook getSelected() { if(selected != null) return selected; - if(hooks == null) { - throw new IllegalStateException("Hooks are not initialized yet!"); - } - for(PermissionHook hook : hooks) { - if(hook.canUse()) { + for(PermissionHook hook : AjQueueAPI.getPermissionHookRegistry().getRegisteredHooks()) { + boolean canUse = hook.canUse(); + Debug.info(hook.getName() + " "+ canUse); + if(canUse) { selected = hook; } } if(selected == null) { - throw new IllegalStateException("All hooks are unusable!"); + selected = builtInHook; } main.getLogger().info("Using "+selected.getName()+" for permissions."); return selected; From c5fd5fb32f53bdf80f75c8d52156d070152ef8be Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Mon, 9 Oct 2023 09:07:57 -0700 Subject: [PATCH 47/51] Add option to delay queue-servers by up to 3 seconds --- .../us/ajg0702/queue/api/ServerTimeManager.java | 2 +- .../us/ajg0702/queue/common/EventHandlerImpl.java | 14 +++++++++++++- .../us/ajg0702/queue/common/QueueManagerImpl.java | 5 +++++ common/src/main/resources/config.yml | 9 ++++++++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/us/ajg0702/queue/api/ServerTimeManager.java b/api/src/main/java/us/ajg0702/queue/api/ServerTimeManager.java index 7e75b95..ff2a62c 100644 --- a/api/src/main/java/us/ajg0702/queue/api/ServerTimeManager.java +++ b/api/src/main/java/us/ajg0702/queue/api/ServerTimeManager.java @@ -6,7 +6,7 @@ public interface ServerTimeManager { /** * Gets the time that the player specified was last seen switching servers * @param player The player to check - * @return The time that they last switched servers, in miliseconds since midnight, January 1, 1970, UTC + * @return The time that they last switched servers, in milliseconds since midnight, January 1, 1970, UTC */ long getLastServerChange(AdaptedPlayer player); } diff --git a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java index 28b5198..5efe06f 100644 --- a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java @@ -118,7 +118,19 @@ public class EventHandlerImpl implements EventHandler { player.hasPermission("ajqueue.queueserver." + to.getName()) ) ) { - main.getQueueManager().addToQueue(player, to); + int delay = Math.min(main.getConfig().getInt("queue-server-delay"), 3000); + Runnable task = () -> { + if(to.getServers().contains(player.getCurrentServer())) return; + main.getQueueManager().addToQueue(player, to); + }; + + Debug.info("Delaying queue-server by " + delay); + + if(delay > 0) { + main.getTaskManager().executor.schedule(task, delay, TimeUnit.MILLISECONDS); + } else { + task.run(); + } } } } 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 c44666d..c133677 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -470,6 +470,11 @@ public class QueueManagerImpl implements QueueManager { } return; } + long lastSwitch = main.getServerTimeManager().getLastServerChange(player); + int delay = Math.min(Math.max(main.getConfig().getInt("queue-server-delay"), 0), 3000); + if(System.currentTimeMillis() - lastSwitch > delay + 1000 || !player.getCurrentServer().equals(from)) { + return; + } if( !getPlayerQueues(player).contains(to) && ( diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml index 846b3d1..2012927 100644 --- a/common/src/main/resources/config.yml +++ b/common/src/main/resources/config.yml @@ -84,6 +84,13 @@ auto-add-kick-reasons: queue-servers: - 'limbo:lobbys' +# How much should we delay queueing players in queue servers? +# You should only use this if you have issues with the instant sending. +# Set to 0 or any negative number to disable +# In milliseconds. Maximum value is 3000 (3 seconds) +# Default: 0 +queue-server-delay: 0 + # Should we completely kick the user from the server if they are in a queue-server # and are kicked from the server with one of the above reasons? # Note this will do nothing on servers that aren't queue-servers @@ -382,7 +389,7 @@ debug: false # Don't touch this number please -config-version: 43 +config-version: 44 # This is ONLY here so that they can be moved to messages.yml. Please edit these in messages.yml! From cda97662d3947fb2b9c966e78bfa409f8e4c3024 Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Fri, 13 Oct 2023 10:47:19 -0700 Subject: [PATCH 48/51] Fixed queue-server-delay being ignored by force-queue-server-target --- .../src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c133677..70325d7 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -472,7 +472,7 @@ public class QueueManagerImpl implements QueueManager { } long lastSwitch = main.getServerTimeManager().getLastServerChange(player); int delay = Math.min(Math.max(main.getConfig().getInt("queue-server-delay"), 0), 3000); - if(System.currentTimeMillis() - lastSwitch > delay + 1000 || !player.getCurrentServer().equals(from)) { + if(System.currentTimeMillis() - lastSwitch < delay + 1000 || !player.getCurrentServer().equals(from)) { return; } if( From e51ff8dca5d0f8a7f3cd12cde7b036ec36887d7f Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 14 Oct 2023 16:14:18 -0700 Subject: [PATCH 49/51] Fixed slash-server commands ignoring pre-queue checks (e.g. joinfrom permission) --- .../commands/SlashServer/SlashServerCommand.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java b/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java index eaf7952..551ce4e 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/SlashServer/SlashServerCommand.java @@ -1,6 +1,7 @@ package us.ajg0702.queue.commands.commands.SlashServer; import com.google.common.collect.ImmutableList; +import us.ajg0702.queue.api.commands.IBaseCommand; import us.ajg0702.queue.api.commands.ICommandSender; import us.ajg0702.queue.commands.BaseCommand; import us.ajg0702.queue.common.QueueMain; @@ -14,6 +15,10 @@ public class SlashServerCommand extends BaseCommand { final QueueMain main; final String server; final String command; + + private IBaseCommand moveCommand; + + public SlashServerCommand(QueueMain main, String server) { this.main = main; this.server = server; @@ -51,11 +56,10 @@ public class SlashServerCommand extends BaseCommand { sender.sendMessage(getMessages().getComponent("errors.player-only")); return; } - if(main.getConfig().getBoolean("require-permission") && !sender.hasPermission("ajqueue.queue."+server)) { - sender.sendMessage(getMessages().getComponent("noperm")); - return; + if(moveCommand == null) { + moveCommand = main.getPlatformMethods().getCommands().get(0); } - main.getQueueManager().addToQueue(main.getPlatformMethods().senderToPlayer(sender), server); + moveCommand.execute(sender, new String[]{server}); } @Override From b3480b6ac202b98b164a35036650e6b823c6260c Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 21 Oct 2023 11:25:04 -0700 Subject: [PATCH 50/51] Skip invalid protocol names when moving them --- common/src/main/java/us/ajg0702/queue/common/QueueMain.java | 4 ++++ 1 file changed, 4 insertions(+) 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 3b0b5a0..3f281c6 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueMain.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueMain.java @@ -341,6 +341,10 @@ public class QueueMain extends AjQueueAPI { List oldProtocolNames = config.getStringList("protocol-names"); for (String oldProtocolName : oldProtocolNames) { String[] parts = oldProtocolName.split(":"); + if(parts.length != 2) { + logger.warn("Invalid old (in the config) protocol name '" + oldProtocolName + "'. Skipping."); + continue; + } String protocol = parts[0]; String name = parts[1]; From 8355c7619c46b9c7b421e698bff8f86c71a8935e Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Sat, 21 Oct 2023 11:30:41 -0700 Subject: [PATCH 51/51] [nolist] 2.6.0 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index d4d7364..1321d05 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ repositories { } allprojects { - version = "2.5.0" + version = "2.6.0" group = "us.ajg0702" plugins.apply("java")