diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 0000000..331aa5f --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1,11 @@ + diff --git a/api/src/main/java/us/ajg0702/queue/api/QueueManager.java b/api/src/main/java/us/ajg0702/queue/api/QueueManager.java index ccc3062..fcc2c41 100644 --- a/api/src/main/java/us/ajg0702/queue/api/QueueManager.java +++ b/api/src/main/java/us/ajg0702/queue/api/QueueManager.java @@ -54,8 +54,8 @@ public interface QueueManager { String getQueuedName(AdaptedPlayer player); /** - * Checks servers that are in bungeecord and adds any it doesnt - * know about. + * Checks servers that are in the proxy and adds any it doesn't + * know about. (and removes any that no longer exist) * * Also creates/edits server groups */ 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 e66789e..2ed2baa 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 @@ -3,6 +3,7 @@ package us.ajg0702.queue.api.players; import net.kyori.adventure.audience.Audience; import net.kyori.adventure.text.Component; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import us.ajg0702.queue.api.server.AdaptedServer; import us.ajg0702.queue.api.util.Handle; @@ -76,7 +77,7 @@ public interface AdaptedPlayer extends Handle, Audience { * Gets the player's username * @return the player's username */ - String getName(); + @Nullable String getName(); /** * Kick a player from the proxy 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 cdebdf4..774f645 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 @@ -67,4 +67,6 @@ public interface Logic { return highest; } + + boolean hasAnyBypass(AdaptedPlayer player, String server); } diff --git a/build.gradle.kts b/build.gradle.kts index cd5e4b7..cbbd27b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ repositories { } allprojects { - version = "2.3.1" + version = "2.4.0" group = "us.ajg0702" plugins.apply("java") diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/PlayerSender.java b/common/src/main/java/us/ajg0702/queue/commands/commands/PlayerSender.java index d640008..8f8ab69 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/PlayerSender.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/PlayerSender.java @@ -1,5 +1,17 @@ package us.ajg0702.queue.commands.commands; +import net.kyori.adventure.audience.MessageType; +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.identity.Identified; +import net.kyori.adventure.identity.Identity; +import net.kyori.adventure.inventory.Book; +import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.sound.SoundStop; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.title.Title; +import net.kyori.adventure.title.TitlePart; +import org.jetbrains.annotations.NotNull; import us.ajg0702.queue.api.commands.ICommandSender; import us.ajg0702.queue.api.players.AdaptedPlayer; @@ -32,4 +44,169 @@ public class PlayerSender implements ICommandSender { public AdaptedPlayer getHandle() { return handle; } + + @Override + public void sendMessage(@NotNull ComponentLike message) { + handle.sendMessage(message); + } + + @Override + public void sendMessage(@NotNull Identified source, @NotNull ComponentLike message) { + handle.sendMessage(source, message); + } + + @Override + public void sendMessage(@NotNull Identity source, @NotNull ComponentLike message) { + handle.sendMessage(source, message); + } + + @Override + public void sendMessage(@NotNull Component message) { + handle.sendMessage(message); + } + + @Override + public void sendMessage(@NotNull Identified source, @NotNull Component message) { + handle.sendMessage(source, message); + } + + @Override + public void sendMessage(@NotNull Identity source, @NotNull Component message) { + handle.sendMessage(source, message); + } + + @Override + public void sendMessage(@NotNull ComponentLike message, @NotNull MessageType type) { + handle.sendMessage(message, type); + } + + @Override + public void sendMessage(@NotNull Identified source, @NotNull ComponentLike message, @NotNull MessageType type) { + handle.sendMessage(source, message, type); + } + + @Override + public void sendMessage(@NotNull Identity source, @NotNull ComponentLike message, @NotNull MessageType type) { + handle.sendMessage(source, message, type); + } + + @Override + public void sendMessage(@NotNull Component message, @NotNull MessageType type) { + handle.sendMessage(message, type); + } + + @Override + public void sendMessage(@NotNull Identified source, @NotNull Component message, @NotNull MessageType type) { + handle.sendMessage(source, message, type); + } + + @Override + public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) { + handle.sendMessage(source, message, type); + } + + @Override + public void sendActionBar(@NotNull ComponentLike message) { + handle.sendActionBar(message); + } + + @Override + public void sendActionBar(@NotNull Component message) { + handle.sendActionBar(message); + } + + @Override + public void sendPlayerListHeader(@NotNull ComponentLike header) { + handle.sendPlayerListHeader(header); + } + + @Override + public void sendPlayerListHeader(@NotNull Component header) { + handle.sendPlayerListHeader(header); + } + + @Override + public void sendPlayerListFooter(@NotNull ComponentLike footer) { + handle.sendPlayerListFooter(footer); + } + + @Override + public void sendPlayerListFooter(@NotNull Component footer) { + handle.sendPlayerListFooter(footer); + } + + @Override + public void sendPlayerListHeaderAndFooter(@NotNull ComponentLike header, @NotNull ComponentLike footer) { + handle.sendPlayerListHeaderAndFooter(header, footer); + } + + @Override + public void sendPlayerListHeaderAndFooter(@NotNull Component header, @NotNull Component footer) { + handle.sendPlayerListHeaderAndFooter(header, footer); + } + + @Override + public void showTitle(@NotNull Title title) { + handle.showTitle(title); + } + + @Override + public void sendTitlePart(@NotNull TitlePart part, @NotNull T value) { + handle.sendTitlePart(part, value); + } + + @Override + public void clearTitle() { + handle.clearTitle(); + } + + @Override + public void resetTitle() { + handle.resetTitle(); + } + + @Override + public void showBossBar(@NotNull BossBar bar) { + handle.showBossBar(bar); + } + + @Override + public void hideBossBar(@NotNull BossBar bar) { + handle.hideBossBar(bar); + } + + @Override + public void playSound(@NotNull Sound sound) { + handle.playSound(sound); + } + + @Override + public void playSound(@NotNull Sound sound, double x, double y, double z) { + handle.playSound(sound, x, y, z); + } + + @Override + public void stopSound(@NotNull Sound sound) { + handle.stopSound(sound); + } + + @Override + public void playSound(@NotNull Sound sound, Sound.@NotNull Emitter emitter) { + handle.playSound(sound, emitter); + } + + @Override + public void stopSound(@NotNull SoundStop stop) { + handle.stopSound(stop); + } + + @Override + public void openBook(Book.@NotNull Builder book) { + handle.openBook(book); + } + + @Override + public void openBook(@NotNull Book book) { + handle.openBook(book); + } } 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 fddb210..b32e67a 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 @@ -60,7 +60,7 @@ public class ManageCommand extends BaseCommand { @Override public String getPermission() { - return null; + return "ajqueue.manage"; } @Override 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 d15af1a..b6860d4 100644 --- a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java @@ -179,6 +179,7 @@ public class EventHandlerImpl implements EventHandler { } } main.getQueueManager().clear(player); + QueueCommand.cooldowns.remove(player); } @Override 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 af92142..ba6ad62 100644 --- a/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/QueueManagerImpl.java @@ -246,9 +246,16 @@ public class QueueManagerImpl implements QueueManager { boolean sendInstant = server.isJoinable(player); boolean sendInstantp = list.size() <= 1 && server.isJoinable(player); boolean timeGood = !main.getConfig().getBoolean("check-last-player-sent-time") || server.getLastSentTime() > Math.floor(main.getTimeBetweenPlayers() * 1000); + boolean alwaysSendInstantly = main.getConfig().getStringList("send-instantly").contains(server.getName()); + boolean hasBypass = main.getLogic().hasAnyBypass(player, server.getName()); - if(main.getConfig().getStringList("send-instantly").contains(server.getName()) || (sendInstant && (sendInstantp && timeGood))) { - sendPlayers(server); + boolean sentInstantly = alwaysSendInstantly || (sendInstant && (sendInstantp && timeGood)) || hasBypass; + + Debug.info("should send instantly (" + sentInstantly + "): " + alwaysSendInstantly + " || (" + sendInstant + " && (" + sendInstantp + " && " + timeGood + ") && " + (!hasBypass) + ")"); + if(sentInstantly) { + if(!hasBypass) { + sendPlayers(server); + } if(!msgs.isEmpty("status.now-in-empty-queue")) { player.sendMessage(msgs.getComponent("status.now-in-empty-queue", "POS:"+pos, @@ -573,7 +580,7 @@ public class QueueManagerImpl implements QueueManager { if(!server.isOnline()) continue; if(server.getQueue().size() == 0) continue; - Debug.info("should send instantly: " + !server.isGroup() + " && " + main.getConfig().getBoolean("send-all-when-back-online") + " && " + server.getServers().get(0).justWentOnline()); + Debug.info("should send when back online: " + !server.isGroup() + " && " + main.getConfig().getBoolean("send-all-when-back-online") + " && " + server.getServers().get(0).justWentOnline()); if(!server.isGroup() && main.getConfig().getBoolean("send-all-when-back-online") && server.getServers().get(0).justWentOnline()) { for(QueuePlayer p : server.getQueue()) { @@ -590,6 +597,7 @@ public class QueueManagerImpl implements QueueManager { if(selected.isFull() && !selected.canJoinFull(p.getPlayer())) continue; player.sendMessage(msgs.getComponent("status.sending-now", "SERVER:"+server.getAlias())); + Debug.info("Calling player.connect for " + player.getName() + "(send when back online)"); player.connect(selected); } continue; @@ -673,6 +681,7 @@ public class QueueManagerImpl implements QueueManager { server.setLastSentTime(System.currentTimeMillis()); + Debug.info("calling nextPlayer.connect on " + nextPlayer.getName()); nextPlayer.connect(selected); selected.addPlayer(); Debug.info(selected.getName()+" player count is now set to "+ selected.getPlayerCount()); 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 4a94030..3feb389 100644 --- a/common/src/main/java/us/ajg0702/queue/logic/FreeLogic.java +++ b/common/src/main/java/us/ajg0702/queue/logic/FreeLogic.java @@ -27,4 +27,9 @@ public class FreeLogic implements Logic { public PermissionGetter getPermissionGetter() { return null; } + + @Override + public boolean hasAnyBypass(AdaptedPlayer player, String server) { + return false; + } } 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 f8551ff..31da45b 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 @@ -35,9 +35,11 @@ public class BungeeMethods implements PlatformMethods { public void sendPluginMessage(AdaptedPlayer player, String channel, String... data) { Collection networkPlayers = ProxyServer.getInstance().getPlayers(); if (networkPlayers != null && !networkPlayers.isEmpty()) { + String playerName = player.getName(); + if(playerName == null) return; ByteArrayDataOutput out = ByteStreams.newDataOutput(); out.writeUTF(channel); - out.writeUTF(player.getName()); + out.writeUTF(playerName); for (String s : data) { out.writeUTF(s); @@ -127,7 +129,7 @@ public class BungeeMethods implements PlatformMethods { for (ServerInfo serverInfo : proxyServer.getServers().values()) { boolean found = false; for(BungeeServer sv : new ArrayList<>(serverList)) { - if(sv.getHandle().equals(serverInfo)) { + if(sv.getHandle().equals(serverInfo) && sv.getName().equals(serverInfo.getName())) { found = true; break; } @@ -140,7 +142,7 @@ public class BungeeMethods implements PlatformMethods { for(BungeeServer sv : new ArrayList<>(serverList)) { boolean found = false; for (ServerInfo serverInfo : proxyServer.getServers().values()) { - if(sv.getHandle().equals(serverInfo)) { + if(sv.getHandle().equals(serverInfo) && sv.getName().equals(serverInfo.getName())) { found = true; break; } 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 dff7d5a..1627d2a 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 @@ -118,6 +118,7 @@ public class BungeePlayer implements AdaptedPlayer, Audience { @Override public String getServerName() { + if(handle.getServer() == null) return null; return handle.getServer().getInfo().getName(); } 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 c414a32..8361efd 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 @@ -75,7 +75,7 @@ public class BungeeServer implements AdaptedServer { private void markOffline(boolean debug, QueueLogger logger, CompletableFuture future, long sent, @Nullable Throwable e) { long lastOnline = lastSuccessfullPing == null ? 0 : lastSuccessfullPing.getFetchedTime(); - offlineTime = (int) Math.min(sent - lastOnline, Integer.MAX_VALUE); + offlineTime = (int) Math.min(sent - lastOnline, Integer.MAX_VALUE) / 1000; lastOffline = sent; 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 a7e5f05..1be9456 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 @@ -41,8 +41,10 @@ public class VelocityMethods implements PlatformMethods { if(player == null) return; Player velocityPlayer = ((VelocityPlayer) player).getHandle(); @SuppressWarnings("UnstableApiUsage") ByteArrayDataOutput out = ByteStreams.newDataOutput(); + String playerName = player.getName(); + if(playerName == null) return; out.writeUTF( channel ); - out.writeUTF(player.getName()); + out.writeUTF(playerName); for(String s : data) { out.writeUTF( s ); } 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 7fd35df..e42268b 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 @@ -80,7 +80,7 @@ public class VelocityServer implements AdaptedServer { private void markOffline(boolean debug, QueueLogger logger, CompletableFuture future, long sent, Throwable e) { long lastOnline = lastSuccessfullPing == null ? 0 : lastSuccessfullPing.getFetchedTime(); - offlineTime = (int) Math.min(sent - lastOnline, Integer.MAX_VALUE); + offlineTime = (int) Math.min(sent - lastOnline, Integer.MAX_VALUE) / 1000; lastOffline = sent; 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 f7c5e83..bd86144 100644 --- a/premium/src/main/java/us/ajg0702/queue/logic/PremiumLogic.java +++ b/premium/src/main/java/us/ajg0702/queue/logic/PremiumLogic.java @@ -37,14 +37,7 @@ public class PremiumLogic implements Logic { QueueLogger logger = main.getLogger(); boolean debug = main.getConfig().getBoolean("priority-queue-debug"); - if( - player.hasPermission("ajqueue.bypass") || - player.hasPermission("ajqueue.serverbypass."+ queueServer.getName()) || - player.hasPermission("ajqueue.joinfullandbypassserver."+ queueServer.getName()) || - player.hasPermission("ajqueue.joinfullandbypass") || - permissionGetter.hasContextBypass(player, queueServer.getName()) || - (main.isPremium() && main.getLogic().getPermissionGetter().hasUniqueFullBypass(player, queueServer.getName())) - ) { + if(hasAnyBypass(player, queueServer.getName())) { if(debug) { logger.info("[priority] "+player.getName()+" bypass"); } @@ -105,4 +98,14 @@ public class PremiumLogic implements Logic { public boolean playerDisconnectedTooLong(QueuePlayer player) { return player.getTimeSinceOnline() > player.getMaxOfflineTime()*1000L; } + @Override + public boolean hasAnyBypass(AdaptedPlayer player, String server) { + return player.hasPermission("ajqueue.bypass") || + player.hasPermission("ajqueue.serverbypass."+ server) || + player.hasPermission("ajqueue.joinfullandbypassserver."+ server) || + player.hasPermission("ajqueue.joinfullandbypass") || + permissionGetter.hasContextBypass(player, server) || + (QueueMain.getInstance().isPremium() && permissionGetter.hasUniqueFullBypass(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 7acad6d..982ec0a 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java @@ -18,7 +18,14 @@ public class Commands implements CommandExecutor { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { if(!pl.hasProxy() && pl.getAConfig().getBoolean("check-proxy-response")) { - sender.sendMessage(color("&cajQueue must also be installed on the proxy!&7 If it has been installed on the proxy, make sure it loaded correctly and try relogging.")); + if(sender instanceof Player) pl.sendMessage((Player) sender, "ack", ""); + sender.sendMessage( + color( + "&c" + + (sender.hasPermission("ajqueue.manage") ? "ajQueue" : "The queue plugin") + + " must also be installed on the proxy!&7 If it has been installed on the proxy, make sure it loaded correctly and try again." + ) + ); return true; } Player player = null; 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 443bf70..bb85f41 100644 --- a/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/SpigotMain.java @@ -221,7 +221,7 @@ public class SpigotMain extends JavaPlugin implements PluginMessageListener,List @EventHandler public void onJoin(PlayerJoinEvent e) { if(hasProxy) return; - Bukkit.getScheduler().runTask(this, () -> sendMessage(e.getPlayer(), "ack", "")); + Bukkit.getScheduler().runTaskLater(this, () -> sendMessage(e.getPlayer(), "ack", ""), 5); } @EventHandler(priority = EventPriority.HIGH)