package org.mctourney.autoreferee.commands; import java.util.List; import java.util.Set; import com.google.common.collect.Sets; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.conversations.BooleanPrompt; import org.bukkit.conversations.Conversation; import org.bukkit.conversations.ConversationContext; import org.bukkit.conversations.Prompt; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; import org.mctourney.autoreferee.AutoRefMatch; import org.mctourney.autoreferee.AutoRefTeam; import org.mctourney.autoreferee.AutoReferee; import org.mctourney.autoreferee.event.player.PlayerTeamJoinEvent; import org.mctourney.autoreferee.listeners.TeamListener; import org.mctourney.autoreferee.util.commands.AutoRefCommand; import org.mctourney.autoreferee.util.commands.AutoRefPermission; import org.mctourney.autoreferee.util.commands.CommandHandler; import org.apache.commons.cli.CommandLine; import org.apache.commons.lang.StringUtils; import com.google.common.collect.Lists; public class PlayerCommands implements CommandHandler { AutoReferee plugin; public PlayerCommands(Plugin plugin) { this.plugin = (AutoReferee) plugin; } @AutoRefCommand(name={"autoref"}) @AutoRefPermission(console=true) public boolean alternateHelp(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { Bukkit.dispatchCommand(sender, "help AutoReferee"); return true; } @AutoRefCommand(name={"matchinfo"}, argmax=0, description="Get info regarding the current match.") @AutoRefPermission(console=true, nodes={"autoreferee.player"}) public boolean matchInfo(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { if (match != null) match.sendMatchInfo(sender); else sender.sendMessage(ChatColor.GRAY + plugin.getName() + " is not running for this world!"); return true; } @AutoRefCommand(name={"jointeam"}, description="Join a random team. If a team name is specified, that team will be joined.", usage="<command> [<team name>] [<player names...>]") @AutoRefPermission(console=false, nodes={"autoreferee.player"}) public boolean joinTeam(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { // if there is no match, or the plugin is running in auto-mode, quit if (match == null) return false; boolean isref = sender.hasPermission("autoreferee.referee"); // get the target team AutoRefTeam team = args.length > 0 ? match.getTeam(args[0]) : match.getArbitraryTeam(); if (team == null) { // team name is invalid. let the player know if (args.length > 0) { sender.sendMessage(ChatColor.DARK_GRAY + args[0] + ChatColor.RESET + " is not a valid team."); sender.sendMessage("Teams are " + match.getTeamList()); } return true; } // if there are players specified on the command line, add them if (args.length > 1 && isref) for (int i = 1; i < args.length; ++i) { Player target = plugin.getServer().getPlayer(args[i]); if (target != null) match.joinTeam(target, team, PlayerTeamJoinEvent.Reason.MANUAL, true); } // otherwise, add yourself else if (sender instanceof Player) match.joinTeam((Player) sender, team, PlayerTeamJoinEvent.Reason.MANUAL, isref || match.isPracticeMode()); return true; } @AutoRefCommand(name={"leaveteam"}, description="Leave a team.", usage="<command> [<player names...>]") @AutoRefPermission(console=false, nodes={"autoreferee.player"}) public boolean leaveTeam(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { // if there is no match, or the plugin is running in auto-mode, quit if (match == null) return false; boolean isref = sender.hasPermission("autoreferee.referee"); // if there are players specified on the command line, remove them if (args.length > 0 && isref) for (int i = 0; i < args.length; ++i) { Player target = plugin.getServer().getPlayer(args[i]); if (target != null) match.leaveTeam(target, true); } // otherwise, remove yourself else if (sender instanceof Player) match.leaveTeam((Player) sender, isref || match.isPracticeMode()); return true; } @AutoRefCommand(name={"listmatches"}, argmax=0, description="Lists all available matches.") @AutoRefPermission(console=true, nodes={"autoreferee.player"}) public boolean listMatches(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { boolean isref = sender.hasPermission("autoreferee.referee"); sender.sendMessage(ChatColor.DARK_GRAY + "Available matches:"); List<String> lines = Lists.newLinkedList(); for (AutoRefMatch m : plugin.getMatches()) { List<Player> players = m.getWorld().getPlayers(); if ((m.access == AutoRefMatch.AccessType.PUBLIC || isref) && players.size() > 0) lines.add("* " + ChatColor.GRAY + m.getMapName() + " v" + m.getMapVersion() + ChatColor.RESET + " with " + ChatColor.RED + players.get(0).getName()); } if (lines.size() == 0) sender.sendMessage(ChatColor.GRAY + "None available. Create one now!"); else for (String line : lines) sender.sendMessage(line); return true; } @AutoRefCommand(name={"joinmatch"}, argmin=0, argmax=1, description="Join the match of the named player. If no player is named, lists available matches.", usage="<command> <player name>") @AutoRefPermission(console=false, nodes={"autoreferee.player"}) public boolean joinMatch(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { // if no arguments are provided, execute the list match command if (args.length == 0) return listMatches(sender, match, args, options); // if the player is preoccupied, don't let this happen if (match != null && match.isPlayer((OfflinePlayer) sender) && match.getCurrentState().inProgress()) return false; // get the player this command is targeting Player player = plugin.getServer().getPlayer(args[0]); if (player == null) return true; // the match we are interested in is the match they are trying to join match = plugin.getMatch(player.getWorld()); if (match != null) { if (!sender.hasPermission("autoreferee.referee") && match.access != AutoRefMatch.AccessType.PUBLIC) sender.sendMessage(ChatColor.RED + "You do not have permission to join this match."); else match.joinMatch((Player) sender); } return true; } @AutoRefCommand(name={"leavematch"}, argmax=1, description="Leave the current match.", usage="<command> [<player name>]") @AutoRefPermission(console=true, nodes={"autoreferee.player"}) public boolean leaveMatch(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { // if the plugin is running in auto-mode, quit Player player = sender instanceof Player ? (Player) sender : null; if (sender.hasPermission("autoreferee.referee") && args.length > 0) match = plugin.getMatch((player = plugin.getServer().getPlayer(args[0])).getWorld()); if (match != null) match.ejectPlayer(player); return true; } @AutoRefCommand(name={"setaccess"}, argmin=1, argmax=1, options="q", description="Changes access type of the current match: PUBLIC or PRIVATE.", usage="<command> <access>", opthelp= { "q", "set quietly (don't announce to lobby)", }) @AutoRefPermission(console=true, nodes={"autoreferee.player"}) public boolean setAccess(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { // if the plugin is running in auto-mode, quit if (match == null) return false; AutoRefMatch.AccessType access = match.access; try { access = AutoRefMatch.AccessType.valueOf(args[0].toUpperCase()); } catch (Exception e) { return true; } if (access != null) match.access = access; sender.sendMessage(ChatColor.DARK_GRAY + "This match is now " + ChatColor.RED + match.access.name()); if (access == AutoRefMatch.AccessType.PUBLIC && sender instanceof Player && !options.hasOption('q') && plugin.getLobbyWorld() != null) for (Player p : plugin.getLobbyWorld().getPlayers()) { p.sendMessage(ChatColor.DARK_GRAY + sender.getName() + "'s " + match.getMapName() + " is now public"); p.sendMessage(ChatColor.DARK_GRAY + "Type " + ChatColor.RED + "/joinmatch " + sender.getName() + ChatColor.DARK_GRAY + " to join!"); } return true; } @AutoRefCommand(name={"ready"}, argmax=1, options="tfyns+", description="Mark your team as ready. Referees may use this command to begin a match.") @AutoRefPermission(console=true, nodes={"autoreferee.player"}) public boolean ready(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { // if there is no match in progress, or the match has started, quit if (match == null || !match.getCurrentState().isBeforeMatch()) return false; boolean rstate = !options.hasOption('f') && !options.hasOption('n'); Player player = sender instanceof Player ? (Player) sender : null; if (!rstate && match.isCountdownRunning()) { String name = sender instanceof ConsoleCommandSender ? "console" : match.getDisplayName(player); match.broadcast(ChatColor.GREEN + "Countdown cancelled by " + name); match.cancelCountdown(); } // Reset the ready delay. match.setReadyDelay(-1); // If a ready delay is specified (-s), and the delay is authorized (practise mode or ref), then set the delay. if (options.hasOption('s') && (match.willBePracticeMode() || sender instanceof ConsoleCommandSender || match.isReferee(player))) { try { match.setReadyDelay(Integer.parseInt(options.getOptionValue('s'))); } catch (NumberFormatException e) { } } // if console or referee sends this message if (sender instanceof ConsoleCommandSender || match.isReferee(player)) { match.setRefereeReady(rstate); } else { AutoRefTeam team = match.getPlayerTeam(player); if (team != null) team.setReady(rstate); } match.checkTeamsStart(); return true; } @AutoRefCommand(name={"autoref", "version"}, argmax=0, description="Returns the version information for the plugin.") @AutoRefPermission(console=true) public boolean getVersion(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { sender.sendMessage(ChatColor.DARK_GRAY + "This server is running " + ChatColor.BLUE + plugin.getDescription().getFullName() + ChatColor.GRAY + " (" + plugin.getCommit().substring(0, 8) + ") on " + Bukkit.getName()); return true; } @AutoRefCommand(name={"notify"}, description="Notifies spectators of your location. Follow this command with a message to provide further info.", usage="<command> <notification message>") @AutoRefPermission(console=false, nodes={"autoreferee.player"}) public boolean notify(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { if (match == null) return false; match.notify(((Player) sender).getLocation(), StringUtils.join(args, ' ')); return true; } @AutoRefCommand(name={"autoref", "me"}) @AutoRefPermission(console=false) public boolean me(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { Player speaker = (Player) sender; String message = StringUtils.join(args, ' '); Set<Player> recipients = Sets.newHashSet(speaker.getWorld().getPlayers()); if (match != null) TeamListener.modifyChatRecipients(match, speaker, recipients); String dispname = match == null ? speaker.getName() : match.getDisplayName(speaker); message = String.format("* %s %s", dispname, message); for (Player player : recipients) player.sendMessage(message); return true; } @AutoRefCommand(name={"autoref", "invite"}, argmin=1, description="Invite players to your current match.", usage="<command> <player names...>") @AutoRefPermission(console=true, nodes={"autoreferee.player"}) public boolean invitePlayers(CommandSender sender, AutoRefMatch match, String[] args, CommandLine options) { if (match == null || !match.getCurrentState().isBeforeMatch()) return false; // who is doing the inviting String from = (sender instanceof Player) ? match.getDisplayName((Player) sender) : "This server"; for (int i = 0; i < args.length; ++i) { // if this player cannot be found, skip Player invited = plugin.getServer().getPlayer(args[i]); if (invited == null) continue; // if this player is already busy competing in a match, skip AutoRefMatch m = plugin.getMatch(invited.getWorld()); if (m != null && m.isPlayer(invited) && m.getCurrentState().inProgress()) continue; // otherwise, invite them if (invited.getWorld() != match.getWorld()) new Conversation(plugin, invited, new InvitationPrompt(match, from)).begin(); } return true; } private class InvitationPrompt extends BooleanPrompt { public InvitationPrompt(AutoRefMatch match, String from) { this.match = match; this.from = from; } private AutoRefMatch match; private String from; @Override public String getPromptText(ConversationContext context) { return ChatColor.GREEN + String.format(">>> %s is inviting you to %s.", from, match.getMapName()) + " Do you accept? (type \"yes\" or \"no\")"; } @Override protected Prompt acceptValidatedInput(final ConversationContext context, boolean response) { if (response && context.getForWhom() instanceof Player) new BukkitRunnable() { @Override public void run() { match.joinMatch((Player) context.getForWhom()); } }.runTask(AutoReferee.getInstance()); return Prompt.END_OF_CONVERSATION; } } }