diff --git a/pom.xml b/pom.xml index 0407a4b..b231a40 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,10 @@ ashcon-repo https://repo.ashcon.app/content/repositories/snapshots + + pgm.fyi + https://repo.pgm.fyi/snapshots + @@ -23,13 +27,7 @@ tc.oc.pgm core - 0.14-SNAPSHOT - provided - - - tc.oc.pgm - util - 0.14-SNAPSHOT + 0.15-SNAPSHOT provided diff --git a/src/main/java/dev/pgm/events/EventsPlugin.java b/src/main/java/dev/pgm/events/EventsPlugin.java index 2e5ebf2..e4ae1bd 100644 --- a/src/main/java/dev/pgm/events/EventsPlugin.java +++ b/src/main/java/dev/pgm/events/EventsPlugin.java @@ -3,11 +3,7 @@ import dev.pgm.events.api.teams.ConfigTeams; import dev.pgm.events.api.teams.DefaultTeamRegistry; import dev.pgm.events.api.teams.TournamentTeamRegistry; -import dev.pgm.events.commands.TournamentAdminCommands; -import dev.pgm.events.commands.TournamentUserCommands; -import dev.pgm.events.commands.VetoCommands; -import dev.pgm.events.commands.providers.TournamentProvider; -import dev.pgm.events.format.TournamentFormat; +import dev.pgm.events.commands.EventsCommandGraph; import dev.pgm.events.listeners.MatchLoadListener; import dev.pgm.events.listeners.PlayerJoinListen; import dev.pgm.events.ready.ReadyCommands; @@ -18,17 +14,9 @@ import dev.pgm.events.ready.ReadySystem; import dev.pgm.events.team.DefaultTeamManager; import dev.pgm.events.team.TournamentTeamManager; +import java.util.Collections; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; -import tc.oc.pgm.api.PGM; -import tc.oc.pgm.api.match.Match; -import tc.oc.pgm.api.player.MatchPlayer; -import tc.oc.pgm.command.graph.CommandExecutor; -import tc.oc.pgm.command.graph.MatchPlayerProvider; -import tc.oc.pgm.command.graph.MatchProvider; -import tc.oc.pgm.lib.app.ashcon.intake.bukkit.graph.BasicBukkitCommandGraph; -import tc.oc.pgm.lib.app.ashcon.intake.fluent.DispatcherNode; -import tc.oc.pgm.lib.app.ashcon.intake.parametric.AbstractModule; public class EventsPlugin extends JavaPlugin { @@ -45,28 +33,24 @@ public void onEnable() { teamManager = DefaultTeamManager.manager(); tournamentManager = new TournamentManager(); - TournamentTeamRegistry teamRegistry = DefaultTeamRegistry.createRegistry(new ConfigTeams()); + teamRegistry = DefaultTeamRegistry.createRegistry(new ConfigTeams()); ReadyManager readyManager = new ReadyManagerImpl(new ReadySystem(), new ReadyParties()); ReadyListener readyListener = new ReadyListener(readyManager); ReadyCommands readyCommands = new ReadyCommands(readyManager); - BasicBukkitCommandGraph graph = - new BasicBukkitCommandGraph( - new CommandModule(tournamentManager, teamManager, teamRegistry)); - - DispatcherNode node = graph.getRootDispatcherNode(); - node.registerCommands(new VetoCommands()); - node.registerCommands(readyCommands); + EventsCommandGraph eventsCommandGraph; + try { + eventsCommandGraph = new EventsCommandGraph(this); + } catch (Exception e) { + throw new RuntimeException(e); + } - DispatcherNode subNode = node.registerNode("tourney", "tournament", "tm", "events"); - subNode.registerCommands(new TournamentUserCommands()); - subNode.registerCommands(new TournamentAdminCommands()); + eventsCommandGraph.registerCommands(Collections.singletonList(readyCommands)); Bukkit.getPluginManager().registerEvents(new MatchLoadListener(teamManager), this); Bukkit.getPluginManager().registerEvents(new PlayerJoinListen(teamManager), this); Bukkit.getPluginManager().registerEvents(readyListener, this); - new CommandExecutor(this, graph).register(); } @Override @@ -93,39 +77,4 @@ public void setTeamRegistry(TournamentTeamRegistry teamRegistry) { public static EventsPlugin get() { return plugin; } - - private static class CommandModule extends AbstractModule { - - private final TournamentManager tournamentManager; - private final TournamentTeamManager teamManager; - private final TournamentTeamRegistry teamRegistry; - - public CommandModule( - TournamentManager tournamentManager, - TournamentTeamManager teamManager, - TournamentTeamRegistry teamRegistry) { - this.tournamentManager = tournamentManager; - this.teamManager = teamManager; - this.teamRegistry = teamRegistry; - } - - @Override - protected void configure() { - configureInstances(); - configureProviders(); - } - - private void configureInstances() { - bind(PGM.class).toInstance(PGM.get()); - } - - private void configureProviders() { - bind(MatchPlayer.class).toProvider(new MatchPlayerProvider()); - bind(Match.class).toProvider(new MatchProvider()); - bind(TournamentManager.class).toInstance(tournamentManager); - bind(TournamentTeamRegistry.class).toInstance(teamRegistry); - bind(TournamentTeamManager.class).toInstance(teamManager); - bind(TournamentFormat.class).toProvider(new TournamentProvider(tournamentManager)); - } - } } diff --git a/src/main/java/dev/pgm/events/api/teams/DefaultTeamRegistry.java b/src/main/java/dev/pgm/events/api/teams/DefaultTeamRegistry.java index b08f7ec..057790c 100644 --- a/src/main/java/dev/pgm/events/api/teams/DefaultTeamRegistry.java +++ b/src/main/java/dev/pgm/events/api/teams/DefaultTeamRegistry.java @@ -37,7 +37,7 @@ public TournamentTeam findExact(String name) { @Override public TournamentTeam getTeam(String name) { TournamentTeam found = findExact(name); - return found != null ? found : StringUtils.bestFuzzyMatch(name, teamMap, 0.9); + return found != null ? found : StringUtils.bestFuzzyMatch(name, teamMap); } @Override diff --git a/src/main/java/dev/pgm/events/commands/CommandException.java b/src/main/java/dev/pgm/events/commands/CommandException.java new file mode 100644 index 0000000..2cf1485 --- /dev/null +++ b/src/main/java/dev/pgm/events/commands/CommandException.java @@ -0,0 +1,26 @@ +package dev.pgm.events.commands; + +import static net.kyori.adventure.text.Component.text; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.util.ComponentMessageThrowable; +import org.jetbrains.annotations.Nullable; + +public class CommandException extends RuntimeException implements ComponentMessageThrowable { + + private Component component; + + public CommandException(String message) { + super(message); + } + + public CommandException(Component component) { + this.component = component; + } + + @Override + public @Nullable Component componentMessage() { + if (component != null) return component; + return text(this.getMessage()); + } +} diff --git a/src/main/java/dev/pgm/events/commands/EventsCommandGraph.java b/src/main/java/dev/pgm/events/commands/EventsCommandGraph.java new file mode 100644 index 0000000..7f507ec --- /dev/null +++ b/src/main/java/dev/pgm/events/commands/EventsCommandGraph.java @@ -0,0 +1,69 @@ +package dev.pgm.events.commands; + +import dev.pgm.events.EventsPlugin; +import dev.pgm.events.TournamentManager; +import dev.pgm.events.api.teams.TournamentTeamRegistry; +import dev.pgm.events.commands.providers.TournamentProvider; +import dev.pgm.events.format.TournamentFormat; +import dev.pgm.events.team.TournamentTeamManager; +import java.util.List; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import tc.oc.pgm.api.PGM; +import tc.oc.pgm.api.match.Match; +import tc.oc.pgm.api.player.MatchPlayer; +import tc.oc.pgm.command.injectors.MatchPlayerProvider; +import tc.oc.pgm.command.injectors.MatchProvider; +import tc.oc.pgm.command.injectors.PlayerProvider; +import tc.oc.pgm.command.util.CommandGraph; +import tc.oc.pgm.lib.cloud.commandframework.extra.confirmation.CommandConfirmationManager; +import tc.oc.pgm.lib.cloud.commandframework.minecraft.extras.MinecraftHelp; +import tc.oc.pgm.util.Audience; + +public class EventsCommandGraph extends CommandGraph { + + public EventsCommandGraph(EventsPlugin plugin) throws Exception { + super(plugin); + } + + @Override + protected MinecraftHelp createHelp() { + return new MinecraftHelp<>("/events help", Audience::get, manager); + } + + @Override + protected CommandConfirmationManager createConfirmationManager() { + return null; + } + + @Override + protected void setupInjectors() { + // PGM Injectors + registerInjector(PGM.class, PGM::get); + registerInjector(Match.class, new MatchProvider()); + registerInjector(MatchPlayer.class, new MatchPlayerProvider()); + registerInjector(Player.class, new PlayerProvider()); + + // Events Injectors + registerInjector(TournamentManager.class, EventsPlugin::getTournamentManager); + registerInjector(TournamentTeamRegistry.class, EventsPlugin::getTeamRegistry); + registerInjector(TournamentTeamManager.class, EventsPlugin::getTeamManager); + registerInjector(TournamentFormat.class, new TournamentProvider(plugin.getTournamentManager())); + } + + @Override + protected void setupParsers() { + // No custom parses used + } + + @Override + public void registerCommands() { + register(new VetoCommands()); + register(new TournamentUserCommands()); + register(new TournamentAdminCommands()); + } + + public void registerCommands(List commands) { + commands.forEach(this::register); + } +} diff --git a/src/main/java/dev/pgm/events/commands/TournamentAdminCommands.java b/src/main/java/dev/pgm/events/commands/TournamentAdminCommands.java index e931932..3ce9751 100644 --- a/src/main/java/dev/pgm/events/commands/TournamentAdminCommands.java +++ b/src/main/java/dev/pgm/events/commands/TournamentAdminCommands.java @@ -10,51 +10,60 @@ import org.bukkit.ChatColor; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import tc.oc.pgm.api.PGM; +import tc.oc.pgm.api.integration.Integration; import tc.oc.pgm.api.match.Match; import tc.oc.pgm.api.match.MatchManager; -import tc.oc.pgm.api.player.VanishManager; -import tc.oc.pgm.lib.app.ashcon.intake.Command; -import tc.oc.pgm.lib.app.ashcon.intake.parametric.annotation.Text; +import tc.oc.pgm.api.player.MatchPlayer; +import tc.oc.pgm.lib.cloud.commandframework.annotations.Argument; +import tc.oc.pgm.lib.cloud.commandframework.annotations.CommandDescription; +import tc.oc.pgm.lib.cloud.commandframework.annotations.CommandMethod; +import tc.oc.pgm.lib.cloud.commandframework.annotations.CommandPermission; +import tc.oc.pgm.lib.cloud.commandframework.annotations.specifier.Greedy; +@CommandMethod("tourney|tournament|tm|events") public class TournamentAdminCommands { - @Command( - aliases = "create", - desc = "Creates a tournament", - usage = "", - perms = "events.staff") + @CommandMethod("create ") + @CommandDescription("Creates a tournament") + @CommandPermission("events.staff") public void tourney( - CommandSender sender, TournamentManager manager, Match match, @Text String pool) { + CommandSender sender, + TournamentManager manager, + Match match, + @Argument("format") @Greedy String pool) { manager.createTournament(match, MapFormatXMLParser.parse(pool)); sender.sendMessage(ChatColor.GOLD + "Starting tournament."); } - @Command(aliases = "register", desc = "Register a team", usage = "", perms = "events.staff") + @CommandMethod("register ") + @CommandDescription("Register a team") + @CommandPermission("events.staff") public void register( CommandSender sender, TournamentTeamRegistry teamRegistry, TournamentTeamManager teamManager, - @Text String name) { + @Argument("team") @Greedy String name) { TournamentTeam team = teamRegistry.getTeam(name); - if (team == null) { // TODO move to provider - sender.sendMessage(ChatColor.RED + "Team not found!"); - return; - } + // TODO move to provider + if (team == null) throw new CommandException("Team not found!"); - VanishManager vanishManager = PGM.get().getVanishManager(); MatchManager matchManager = PGM.get().getMatchManager(); - for (TournamentPlayer player : team.getPlayers()) - if (vanishManager.isVanished(player.getUUID())) - vanishManager.setVanished( - matchManager.getPlayer(Bukkit.getPlayer(player.getUUID())), false, false); + for (TournamentPlayer player : team.getPlayers()) { + Player bukkit = Bukkit.getPlayer(player.getUUID()); + MatchPlayer mp = matchManager.getPlayer(bukkit); + if (Integration.isVanished(bukkit)) Integration.setVanished(mp, false, false); + } teamManager.addTeam(team); sender.sendMessage(ChatColor.YELLOW + "Added team " + team.getName() + "!"); } - @Command(aliases = "list", desc = "List all loaded teams", perms = "events.staff") + @CommandMethod("list") + @CommandDescription("List all loaded teams") + @CommandPermission("events.staff") public void list(CommandSender sender, TournamentTeamRegistry registry) { sender.sendMessage( ChatColor.GOLD @@ -68,17 +77,15 @@ public void list(CommandSender sender, TournamentTeamRegistry registry) { sender.sendMessage(ChatColor.YELLOW + "Run /tourney info to see player roster!"); } - @Command( - aliases = "info", - desc = "View information about a team", - usage = "", - perms = "events.staff") - public void info(CommandSender sender, TournamentTeamRegistry registry, @Text String name) { + @CommandMethod("info ") + @CommandDescription("View information about a team") + @CommandPermission("events.staff") + public void info( + CommandSender sender, + TournamentTeamRegistry registry, + @Argument("team") @Greedy String name) { TournamentTeam team = registry.getTeam(name); - if (team == null) { - sender.sendMessage(ChatColor.RED + "Team not found!"); - return; - } + if (team == null) throw new CommandException("Team not found!"); sender.sendMessage( ChatColor.GOLD @@ -97,7 +104,9 @@ public void info(CommandSender sender, TournamentTeamRegistry registry, @Text St } } - @Command(aliases = "unregisterall", desc = "Clear all registered teams", perms = "events.staff") + @CommandMethod("unregisterall") + @CommandDescription("Clear all registered teams") + @CommandPermission("events.staff") public void clear(CommandSender sender, TournamentTeamManager teamManager) { teamManager.clear(); sender.sendMessage(ChatColor.YELLOW + "Unregistered all teams!"); diff --git a/src/main/java/dev/pgm/events/commands/TournamentUserCommands.java b/src/main/java/dev/pgm/events/commands/TournamentUserCommands.java index 2ea7ac8..be9df7d 100644 --- a/src/main/java/dev/pgm/events/commands/TournamentUserCommands.java +++ b/src/main/java/dev/pgm/events/commands/TournamentUserCommands.java @@ -8,11 +8,14 @@ import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; -import tc.oc.pgm.lib.app.ashcon.intake.Command; +import tc.oc.pgm.lib.cloud.commandframework.annotations.CommandDescription; +import tc.oc.pgm.lib.cloud.commandframework.annotations.CommandMethod; +@CommandMethod("tourney|tournament|tm|events") public class TournamentUserCommands { - @Command(aliases = "score", desc = "Shows the current score in the tournament") + @CommandMethod("score") + @CommandDescription("Shows the current score in the tournament") public void currentScore(CommandSender sender, TournamentFormat format) { if (format instanceof FormatTournamentImpl) { String formatName = ((FormatTournamentImpl) format).getFormatRound().settings().name(); @@ -30,7 +33,8 @@ public void currentScore(CommandSender sender, TournamentFormat format) { } } - @Command(aliases = "rounds", desc = "Shows the rounds from this event") + @CommandMethod("rounds") + @CommandDescription("Shows the rounds from this event") public void rounds(CommandSender sender, TournamentFormat format) { String header = "Event Rounds"; if (format instanceof FormatTournamentImpl) diff --git a/src/main/java/dev/pgm/events/commands/VetoCommands.java b/src/main/java/dev/pgm/events/commands/VetoCommands.java index c723a2a..3c42ec6 100644 --- a/src/main/java/dev/pgm/events/commands/VetoCommands.java +++ b/src/main/java/dev/pgm/events/commands/VetoCommands.java @@ -5,60 +5,49 @@ import dev.pgm.events.team.TournamentTeam; import dev.pgm.events.team.TournamentTeamManager; import java.util.Optional; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import tc.oc.pgm.api.match.Match; -import tc.oc.pgm.lib.app.ashcon.intake.Command; -import tc.oc.pgm.lib.app.ashcon.intake.parametric.annotation.Text; +import tc.oc.pgm.lib.cloud.commandframework.annotations.Argument; +import tc.oc.pgm.lib.cloud.commandframework.annotations.CommandDescription; +import tc.oc.pgm.lib.cloud.commandframework.annotations.CommandMethod; public class VetoCommands { - @Command(aliases = "veto", desc = "Veto a map") + @CommandMethod("veto ") + @CommandDescription("Veto a map") public void veto( CommandSender sender, Match match, TournamentTeamManager teamManager, TournamentFormat format, - @Text String option) { - if (format.currentRound() == null || !(format.currentRound() instanceof VetoRound)) { - sender.sendMessage(ChatColor.RED + "Veto round is not currently running!"); - return; - } + @Argument("map") Integer option) { + if (format.currentRound() == null || !(format.currentRound() instanceof VetoRound)) + throw new CommandException("Veto round is not currently running!"); - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "Only players can run this command!"); - return; - } + if (!(sender instanceof Player)) + throw new CommandException("Only players can run this command!"); Player player = (Player) sender; Optional team = teamManager.tournamentTeamPlayer((player).getUniqueId()); - if (!team.isPresent()) { - sender.sendMessage(ChatColor.RED + "Only players on teams can run this command!"); - return; - } + if (!team.isPresent()) + throw new CommandException("Only players on teams can run this command!"); - if (!team.get().canVeto(player)) { - sender.sendMessage(ChatColor.RED + "You are not registered as a vetoer for this team!"); - return; - } + if (!team.get().canVeto(player)) + throw new CommandException("You are not registered as a vetoer for this team!"); try { - int num = Integer.parseInt(option) - 1; + int num = option - 1; VetoRound vetoRound = (VetoRound) format.currentRound(); - if (!vetoRound.validVetoNumber(num)) { - sender.sendMessage(ChatColor.RED + "That is not a valid veto number: " + (num + 1)); - return; - } + if (!vetoRound.validVetoNumber(num)) + throw new CommandException("That is not a valid veto number: " + (num + 1)); - if (!vetoRound.picking().equals(team)) { - sender.sendMessage(ChatColor.RED + "It isn't your turn to veto!"); - return; - } + if (!vetoRound.picking().equals(team)) + throw new CommandException("It isn't your turn to veto!"); vetoRound.veto(match, team.get(), num); } catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + "Invalid argument! Only takes numbers!"); + throw new CommandException("Invalid argument! Only takes numbers!"); } } } diff --git a/src/main/java/dev/pgm/events/commands/providers/TournamentProvider.java b/src/main/java/dev/pgm/events/commands/providers/TournamentProvider.java index 10da26d..5c3f392 100644 --- a/src/main/java/dev/pgm/events/commands/providers/TournamentProvider.java +++ b/src/main/java/dev/pgm/events/commands/providers/TournamentProvider.java @@ -1,18 +1,19 @@ package dev.pgm.events.commands.providers; import dev.pgm.events.TournamentManager; +import dev.pgm.events.commands.CommandException; import dev.pgm.events.format.TournamentFormat; import dev.pgm.events.format.rounds.format.FormatRound; -import java.lang.annotation.Annotation; -import java.util.List; import java.util.Optional; import org.bukkit.command.CommandSender; -import tc.oc.pgm.lib.app.ashcon.intake.argument.ArgumentException; -import tc.oc.pgm.lib.app.ashcon.intake.argument.CommandArgs; -import tc.oc.pgm.lib.app.ashcon.intake.bukkit.parametric.provider.BukkitProvider; -import tc.oc.pgm.lib.app.ashcon.intake.parametric.ProvisionException; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import tc.oc.pgm.lib.cloud.commandframework.annotations.AnnotationAccessor; +import tc.oc.pgm.lib.cloud.commandframework.annotations.injection.ParameterInjector; +import tc.oc.pgm.lib.cloud.commandframework.context.CommandContext; +import tc.oc.pgm.lib.cloud.commandframework.exceptions.CommandExecutionException; -public class TournamentProvider implements BukkitProvider { +public class TournamentProvider implements ParameterInjector { private final TournamentManager tournamentManager; @@ -21,14 +22,9 @@ public TournamentProvider(TournamentManager tournamentManager) { } @Override - public boolean isProvided() { - return true; - } - - @Override - public TournamentFormat get( - CommandSender commandSender, CommandArgs commandArgs, List list) - throws ArgumentException, ProvisionException { + public @Nullable TournamentFormat create( + @NonNull CommandContext context, + @NonNull AnnotationAccessor annotationAccessor) { Optional tournamentFormat = tournamentManager.currentTournament(); if (tournamentFormat.isPresent()) { TournamentFormat format = tournamentFormat.get(); @@ -43,6 +39,7 @@ public TournamentFormat get( return format; } - throw new ArgumentException("No tournament is currently running!"); + throw new CommandExecutionException( + new CommandException("No tournament is currently running!")); } } diff --git a/src/main/java/dev/pgm/events/listeners/PlayerJoinListen.java b/src/main/java/dev/pgm/events/listeners/PlayerJoinListen.java index 522971d..dd6d299 100644 --- a/src/main/java/dev/pgm/events/listeners/PlayerJoinListen.java +++ b/src/main/java/dev/pgm/events/listeners/PlayerJoinListen.java @@ -12,6 +12,7 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerLoginEvent; import tc.oc.pgm.api.PGM; +import tc.oc.pgm.api.integration.Integration; import tc.oc.pgm.api.player.event.MatchPlayerAddEvent; import tc.oc.pgm.blitz.BlitzMatchModule; import tc.oc.pgm.events.PlayerParticipationStartEvent; @@ -77,9 +78,7 @@ public void vanish(PlayerJoinEvent event) { if (!event.getPlayer().isOp() && event.getPlayer().hasPermission("events.spectate.vanish") && !manager.playerTeam(event.getPlayer().getUniqueId()).isPresent()) - PGM.get() - .getVanishManager() - .setVanished(PGM.get().getMatchManager().getPlayer(event.getPlayer()), true, true); + Integration.setVanished(PGM.get().getMatchManager().getPlayer(event.getPlayer()), true, true); } @EventHandler diff --git a/src/main/java/dev/pgm/events/ready/ReadyCommands.java b/src/main/java/dev/pgm/events/ready/ReadyCommands.java index b52073f..5c1b857 100644 --- a/src/main/java/dev/pgm/events/ready/ReadyCommands.java +++ b/src/main/java/dev/pgm/events/ready/ReadyCommands.java @@ -1,10 +1,11 @@ package dev.pgm.events.ready; +import dev.pgm.events.commands.CommandException; import dev.pgm.events.utils.Response; import org.bukkit.command.CommandSender; import tc.oc.pgm.api.player.MatchPlayer; -import tc.oc.pgm.lib.app.ashcon.intake.Command; -import tc.oc.pgm.util.Audience; +import tc.oc.pgm.lib.cloud.commandframework.annotations.CommandDescription; +import tc.oc.pgm.lib.cloud.commandframework.annotations.CommandMethod; public class ReadyCommands { @@ -14,26 +15,20 @@ public ReadyCommands(ReadyManager readyManager) { this.manager = readyManager; } - @Command(aliases = "ready", desc = "Ready up") + @CommandMethod("ready") + @CommandDescription("Ready up") public void readyCommand(CommandSender sender, MatchPlayer player) { Response response = manager.canReady(player); - - if (response.isDenied()) { - Audience.get(sender).sendWarning(response.getMessage()); - return; - } + if (response.isDenied()) throw new CommandException(response.getMessage()); manager.ready(player.getParty(), player); } - @Command(aliases = "unready", desc = "Mark your team as no longer being ready") + @CommandMethod("unready") + @CommandDescription("Mark your team as no longer being ready") public void unreadyCommand(CommandSender sender, MatchPlayer player) { Response response = manager.canUnready(player); - - if (response.isDenied()) { - Audience.get(sender).sendWarning(response.getMessage()); - return; - } + if (response.isDenied()) throw new CommandException(response.getMessage()); manager.unready(player.getParty(), player); }