package tc.oc.pgm.destroyable; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import javax.inject.Inject; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandException; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import tc.oc.commons.core.commands.Commands; import tc.oc.pgm.commands.CommandUtils; import tc.oc.pgm.match.Match; import tc.oc.pgm.match.inject.MatchScoped; import static tc.oc.commons.core.exception.LambdaExceptionUtils.rethrowSupplier; @MatchScoped public class DestroyableCommands implements Commands { private final Optional<DestroyableMatchModule> module; @Inject private DestroyableCommands(Optional<DestroyableMatchModule> module) { this.module = module; } private DestroyableMatchModule matchModule() throws CommandException { return module.orElseThrow(() -> new CommandException("No destroyables")); } private Destroyable lookup(Match match, String slug) throws CommandException { return match.features() .bySlug(Destroyable.class, slug) .orElseGet(rethrowSupplier(() -> { final List<Destroyable> destroyables = match.features() .all(Destroyable.class) .filter(d -> d.slug().startsWith(slug)) .collect(Collectors.toList()); switch(destroyables.size()) { case 0: throw new CommandException("No destroyable with ID '" + slug + "'"); case 1: return destroyables.get(0); default: throw new CommandException("Multiple destroyables have IDs that start with '" + slug + "'"); } })); } private void assertEditPerms(CommandSender sender) throws CommandException { if(!sender.hasPermission("pgm.destroyable.edit")) { throw new CommandException("You don't have permission to do that"); } } @Command( aliases = {"destroyable", "destroyables"}, desc = "Commands for working with destroyables (monuments)", usage = "[id [completion[=(<blocks>|<percent>%)]]]", min = 0, max = -1 ) public void destroyable(CommandContext args, CommandSender sender) throws CommandException { String id = args.getString(0, null); if(id == null) { list(args, sender); } else { Destroyable destroyable = lookup(CommandUtils.getMatch(sender), id); String action = args.getString(1, null); if(action == null) { details(args, sender, destroyable); } else if(action.startsWith("completion")) { if(action.startsWith("completion=")) { setCompletion(args, sender, destroyable, action.substring("completion=".length())); } completion(args, sender, destroyable); } else { throw new CommandException("Invalid action '" + action + "'"); } } } public void list(CommandContext args, CommandSender sender) throws CommandException { List<String> lines = new ArrayList<>(); lines.add(ChatColor.GRAY + "Destroyables"); for(Destroyable destroyable : matchModule().getDestroyables()) { lines.add(" " + ChatColor.AQUA + destroyable.slug() + ": " + ChatColor.WHITE + destroyable.getName() + ChatColor.GRAY + " owned by " + destroyable.getOwner().getColoredName()); } sender.sendMessage(lines.toArray(new String[lines.size()])); } private String formatProperty(String name, Object value) { return " " + ChatColor.GRAY + name + ChatColor.DARK_GRAY + ": " + ChatColor.WHITE + value; } public void details(CommandContext args, CommandSender sender, Destroyable destroyable) throws CommandException { List<String> lines = new ArrayList<>(); lines.add(ChatColor.GRAY + "Destroyable " + ChatColor.AQUA + destroyable.slug()); lines.add(formatProperty("name", destroyable.getName())); lines.add(formatProperty("owner", destroyable.getOwner().getColoredName())); lines.add(formatProperty("size", destroyable.getMaxHealth())); lines.add(formatProperty("completion", destroyable.getBreaksRequired() + " (" + destroyable.renderDestructionRequired() + ")")); sender.sendMessage(lines.toArray(new String[lines.size()])); } public void completion(CommandContext args, CommandSender sender, Destroyable destroyable) throws CommandException { sender.sendMessage(ChatColor.GRAY + "Destroyable " + ChatColor.AQUA + destroyable.slug() + ChatColor.GRAY + " has completion " + ChatColor.WHITE + Math.round(destroyable.getDestructionRequired() * 100) + "%" + ChatColor.GRAY + " or " + ChatColor.WHITE + destroyable.getBreaksRequired() + "/" + destroyable.getMaxHealth() + ChatColor.GRAY + " breaks"); } public void setCompletion(CommandContext args, CommandSender sender, Destroyable destroyable, String value) throws CommandException { assertEditPerms(sender); Double completion; Integer breaks; if(value.endsWith("%")) { completion = Double.parseDouble(value.substring(0, value.length() - 1)) / 100d; breaks = null; } else { completion = null; breaks = Integer.parseInt(value); } try { if(completion != null) { destroyable.setDestructionRequired(completion); } else if(breaks != null) { destroyable.setBreaksRequired(breaks); } } catch(IllegalArgumentException e) { throw new CommandException(e.getMessage()); } } }