From 0ca8d5731c44e5855afa77fb2db276303b7c688d Mon Sep 17 00:00:00 2001 From: Ryan Barlow <7389646+ryanbarlow97@users.noreply.github.com> Date: Thu, 15 Oct 2026 17:58:43 +0000 Subject: [PATCH] fix: complete valid poker targets and deal modifiers --- .../games/command/CommandManager.java | 26 ++++++- .../games/command/CommandManagerTest.java | 77 +++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/tfminecraft/games/command/CommandManager.java b/src/main/java/net/tfminecraft/games/command/CommandManager.java index 44479d0..5553ea1 100644 --- a/src/main/java/net/tfminecraft/games/command/CommandManager.java +++ b/src/main/java/net/tfminecraft/games/command/CommandManager.java @@ -542,7 +542,8 @@ public List onTabComplete(CommandSender sender, Command cmd, String alia first.add("poker"); } if (admin) { - first.addAll(List.of("reload", "deck", "display", "place", "payout", "session", "deal")); + if (sender.hasPermission("games.admin.reload")) first.add("reload"); + first.addAll(List.of("deck", "display", "place", "payout", "session", "deal")); } return prefix(first, args[0]); } @@ -556,6 +557,17 @@ public List onTabComplete(CommandSender sender, Command cmd, String alia if (args.length == 2 && args[0].equalsIgnoreCase("poker") && bet) { return prefix(List.of("configure", "buyin", "rebuy", "bet", "start", "kick", "finish", "status"), args[1]); } + if (args.length == 3 && args[0].equalsIgnoreCase("poker") && args[1].equalsIgnoreCase("kick") + && bet && sender instanceof Player player) { + TableManager manager = TableManager.get(); + Table table = manager.tableNearby(player); + if (table == null || !"poker".equalsIgnoreCase(table.getGameId()) + || table.live() || table.isPaying() || !table.poker().enabled() + || !manager.canEditHouse(player, table)) return Collections.emptyList(); + return prefix(Bukkit.getOnlinePlayers().stream() + .filter(target -> table.poker().registered(target.getUniqueId())) + .map(Player::getName).toList(), args[2]); + } if (!admin) { return Collections.emptyList(); } @@ -565,6 +577,18 @@ public List onTabComplete(CommandSender sender, Command cmd, String alia if (args.length == 3 && args[0].equalsIgnoreCase("deal") && args[1].equalsIgnoreCase("table")) { return prefix(List.of("board", "dealer"), args[2]); } + if (sender instanceof Player && (args.length == 4 || args.length == 5) + && args[0].equalsIgnoreCase("deal") && args[1].equalsIgnoreCase("table") + && (args[2].equalsIgnoreCase("board") || args[2].equalsIgnoreCase("dealer"))) { + if (args.length == 5) { + try { + if (Integer.parseInt(args[3]) < 1) return Collections.emptyList(); + } catch (NumberFormatException ex) { + return Collections.emptyList(); + } + } + return prefix(List.of("back"), args[args.length - 1]); + } if (args.length == 2 && args[0].equalsIgnoreCase("session")) { return prefix(List.of("start", "stop"), args[1]); } diff --git a/src/test/java/net/tfminecraft/games/command/CommandManagerTest.java b/src/test/java/net/tfminecraft/games/command/CommandManagerTest.java index 533d119..91fbedf 100644 --- a/src/test/java/net/tfminecraft/games/command/CommandManagerTest.java +++ b/src/test/java/net/tfminecraft/games/command/CommandManagerTest.java @@ -438,10 +438,87 @@ private void dealer() { when(player.hasPermission("games.help")).thenReturn(true); assertEquals(List.of("help"), commands.onTabComplete(player, command, "games", new String[] {""})); admin(); + when(player.hasPermission("games.admin.reload")).thenReturn(true); assertEquals(List.of("help", "reload", "deck", "display", "place", "payout", "session", "deal"), commands.onTabComplete(player, command, "games", new String[] {""})); } + @Test void reloadCompletionHonorsAnExplicitChildPermissionDenial() { + admin(); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"REL"}).isEmpty()); + when(player.hasPermission("games.admin.reload")).thenReturn(true); + assertEquals(List.of("reload"), commands.onTabComplete(player, command, "games", new String[] {"REL"})); + when(player.hasPermission("games.admin")).thenReturn(false); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {""}).isEmpty()); + } + + @Test void dealBackCompletionFollowsBothAcceptedModifierPositions() { + admin(); + for (String pile : List.of("board", "DEALER")) { + for (String prefix : List.of("", "B", "back")) { + assertEquals(List.of("back"), commands.onTabComplete(player, command, "games", + new String[] {"DEAL", "TABLE", pile, prefix})); + assertEquals(List.of("back"), commands.onTabComplete(player, command, "games", + new String[] {"deal", "table", pile, "2", prefix})); + } + } + for (String invalid : List.of("0", "-1", "x", "99999999999999", "back")) { + assertTrue(commands.onTabComplete(player, command, "games", + new String[] {"deal", "table", "board", invalid, ""}).isEmpty()); + } + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"deal", "table", "board", "x"}).isEmpty()); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"deal", "table", "invalid", ""}).isEmpty()); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"deal", "table", "board", "2", "back", ""}).isEmpty()); + CommandSender console = mock(CommandSender.class); + when(console.hasPermission("games.admin")).thenReturn(true); + assertTrue(commands.onTabComplete(console, command, "games", new String[] {"deal", "table", "board", ""}).isEmpty()); + when(player.hasPermission("games.admin")).thenReturn(false); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"deal", "table", "board", ""}).isEmpty()); + } + + @Test void pokerKickCompletesOnlyOnlineRegistrantsAtAnEditableIdleTournament() { + when(player.hasPermission("games.bet")).thenReturn(true); + Table poker = new Table(UUID.randomUUID(), "poker", null, 0, null); + when(manager.tableNearby(player)).thenReturn(poker); + when(manager.canEditHouse(player, poker)).thenReturn(true); + Player alice = mock(Player.class), bob = mock(Player.class); + when(alice.getUniqueId()).thenReturn(UUID.randomUUID()); + when(alice.getName()).thenReturn("Alice"); + when(bob.getUniqueId()).thenReturn(UUID.randomUUID()); + when(bob.getName()).thenReturn("Bob"); + try (var bukkit = mockStatic(org.bukkit.Bukkit.class)) { + bukkit.when(org.bukkit.Bukkit::getOnlinePlayers).thenReturn(List.of(alice, bob)); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"poker", "kick", ""}).isEmpty()); + poker.poker().configure(10, 1000, 0, 0, 0); + poker.poker().buy(alice.getUniqueId()); + poker.poker().buy(UUID.randomUUID()); // An offline registrant has no executable name target. + for (String prefix : List.of("", "aL", "Alice")) { + assertEquals(List.of("Alice"), commands.onTabComplete(player, command, "games", + new String[] {"POKER", "KICK", prefix})); + } + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"poker", "kick", "Bob"}).isEmpty()); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"poker", "kick", "Alice", ""}).isEmpty()); + when(manager.canEditHouse(player, poker)).thenReturn(false); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"poker", "kick", ""}).isEmpty()); + when(manager.canEditHouse(player, poker)).thenReturn(true); + poker.startSession(); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"poker", "kick", ""}).isEmpty()); + poker.clearSession(); + poker.beginPayout(List.of(), null); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"poker", "kick", ""}).isEmpty()); + when(manager.tableNearby(player)).thenReturn(table); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"poker", "kick", ""}).isEmpty()); + when(manager.tableNearby(player)).thenReturn(null); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"poker", "kick", ""}).isEmpty()); + when(manager.tableNearby(player)).thenReturn(poker); + when(player.hasPermission("games.bet")).thenReturn(false); + assertTrue(commands.onTabComplete(player, command, "games", new String[] {"poker", "kick", ""}).isEmpty()); + CommandSender console = mock(CommandSender.class); + when(console.hasPermission("games.bet")).thenReturn(true); + assertTrue(commands.onTabComplete(console, command, "games", new String[] {"poker", "kick", ""}).isEmpty()); + } + } + @Test void adminsWithoutHelpOrBetPermissionGetNoSuggestionsForThem() { admin(); assertTrue(commands.onTabComplete(player, command, "games", new String[] {"help", ""}).isEmpty());