ProjectAres/PGM/src/main/java/tc/oc/pgm/mutation/command/MutationCommands.java

219 lines
9.7 KiB
Java

package tc.oc.pgm.mutation.command;
import java.util.Collection;
import java.util.HashSet;
import java.util.logging.Level;
import javax.inject.Inject;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.sk89q.minecraft.util.commands.*;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.command.CommandSender;
import tc.oc.commons.bukkit.chat.PlayerComponent;
import tc.oc.commons.bukkit.chat.WarningComponent;
import tc.oc.commons.bukkit.nick.IdentityProvider;
import tc.oc.commons.core.chat.Audience;
import tc.oc.minecraft.scheduler.SyncExecutor;
import tc.oc.commons.bukkit.chat.Audiences;
import tc.oc.commons.bukkit.chat.ListComponent;
import tc.oc.commons.bukkit.chat.Paginator;
import tc.oc.commons.core.chat.Component;
import tc.oc.commons.core.commands.Commands;
import tc.oc.commons.core.commands.NestedCommands;
import tc.oc.commons.core.formatting.StringUtils;
import tc.oc.commons.core.random.RandomUtils;
import tc.oc.pgm.commands.CommandUtils;
import tc.oc.pgm.match.Match;
import tc.oc.pgm.mutation.Mutation;
import tc.oc.pgm.mutation.MutationMatchModule;
import tc.oc.pgm.mutation.MutationQueue;
import static tc.oc.commons.bukkit.commands.CommandUtils.newCommandException;
/**
* Commands for {@link MutationMatchModule}.
*/
public class MutationCommands implements NestedCommands {
public static final String PERMISSION_SET = "mutation.set";
public static final String PERMISSION_LIST = "mutation.list";
public static class Parent implements Commands {
@Command(
aliases = {"mutation", "mutations", "mutate", "mt"},
desc = "Commands to manage match mutations.",
usage = "<list|enable|disable>",
min = 1,
max = -1
)
@NestedCommand(value = MutationCommands.class, executeBody = true)
public void mutate(CommandContext args, CommandSender sender) throws CommandException {}
}
private final SyncExecutor syncExecutor;
private final Audiences audiences;
private final MutationQueue mutationQueue;
private final IdentityProvider identityProvider;
@Inject MutationCommands(SyncExecutor syncExecutor, Audiences audiences, MutationQueue mutationQueue, IdentityProvider identityProvider) {
this.syncExecutor = syncExecutor;
this.audiences = audiences;
this.mutationQueue = mutationQueue;
this.identityProvider = identityProvider;
}
@Command(
aliases = {"enable", "e"},
desc = "Adds a mutation to the upcoming match." +
"You can use '?' as a wildcard or " +
"'*' to use all.",
usage = "<mutation|?|*>",
flags = "q",
min = 1,
max = 1
)
@CommandPermissions(PERMISSION_SET)
public void enable(CommandContext args, CommandSender sender) throws CommandException, SuggestException {
set(args, sender, true);
}
@Command(
aliases = {"disable", "d"},
desc = "Remove a mutation to the upcoming match." +
"You can use '?' as a wildcard or " +
"'*' to use all.",
usage = "<mutation|?|*>",
flags = "q",
min = 1,
max = 1
)
@CommandPermissions(PERMISSION_SET)
public void disable(CommandContext args, CommandSender sender) throws CommandException, SuggestException {
set(args, sender, false);
}
@Command(
aliases = {"list"},
desc = "List all the mutations options." +
"Use '-q' to see queued mutations.",
usage = "[page]",
flags = "q",
min = 0,
max = 1
)
@CommandPermissions(PERMISSION_LIST)
public void list(final CommandContext args, CommandSender sender) throws CommandException {
MutationMatchModule module = verify(sender);
final boolean queued = args.hasFlag('q');
final Collection<Mutation> active = queued ? mutationQueue.mutations() : module.mutationsActive();
new Paginator<Mutation>(Mutation.values().length / 2) {
@Override
protected BaseComponent title() {
return new TranslatableComponent(queued ? "command.mutation.list.queued" : "command.mutation.list.current");
}
@Override
protected BaseComponent entry(Mutation entry, int index) {
return new Component(new BaseComponent[] {entry.getComponent(active.contains(entry) ? ChatColor.AQUA : ChatColor.GRAY)})
.extra(new Component(" (", ChatColor.WHITE).extra(new TranslatableComponent(entry.getDescription())).extra(")"));
}
}.display(sender, Sets.newHashSet(Mutation.values()), args.getInteger(0, 1));
}
public MutationMatchModule verify(CommandSender sender) throws CommandException {
return CommandUtils.getMatchModule(MutationMatchModule.class, sender);
}
public void set(CommandContext args, final CommandSender sender, final boolean value) throws CommandException, SuggestException {
final MutationMatchModule module = verify(sender);
final Match match = module.getMatch();
String action = args.getString(0);
boolean queued = args.hasFlag('q') || match.isFinished();
// Mutations that *will* be added or removed
final Collection<Mutation> mutations = new HashSet<>();
// Mutations that *are allowed* to be added or removed
final Collection<Mutation> availableMutations = Sets.newHashSet(Mutation.values());
final Collection<Mutation> queue = queued ? mutationQueue.mutations() : module.mutationsActive();
if(value) availableMutations.removeAll(queue); else availableMutations.retainAll(queue);
// Check if all mutations have been enabled/disabled
if((queue.size() == Mutation.values().length && value) || (queue.isEmpty() && !value)) {
throw newCommandException(sender, new TranslatableComponent(value ? "command.mutation.error.enabled.all" : "command.mutation.error.disabled.all"));
}
// Suggest mutations for the user to choose
final SuggestionContext context = args.getSuggestionContext();
if(context != null) {
context.suggestArgument(0, StringUtils.complete(context.getPrefix(), availableMutations.stream().map(mutation -> mutation.name().toLowerCase())));
}
// Get which action the user wants to preform
switch (action) {
case "*": mutations.addAll(availableMutations); break;
case "?": mutations.add(Iterables.get(availableMutations, RandomUtils.safeNextInt(match.getRandom(), availableMutations.size()))); break;
default:
Mutation query = StringUtils.bestFuzzyMatch(action, Sets.newHashSet(Mutation.values()), 0.9);
if(query == null) {
throw newCommandException(sender, new TranslatableComponent("command.mutation.error.find", action));
} else if(value == queue.contains(query)) {
throw newCommandException(sender, new TranslatableComponent(value ? "command.mutation.error.enabled" : "command.mutation.error.disabled", query.getComponent(ChatColor.RED)));
} else {
mutations.add(query);
}
}
Audience origin = audiences.get(sender);
Audience all = audiences.localServer();
String message = message(!queued, value, mutations.size() == 1);
ListComponent changed = new ListComponent(Collections2.transform(mutations, Mutation.toComponent(ChatColor.AQUA)));
if(queued) {
// Send the queued changes off to the api
syncExecutor.callback(
value ? mutationQueue.mergeAll(mutations)
: mutationQueue.removeAll(mutations),
result -> {
origin.sendMessage(new Component(new TranslatableComponent(message, changed), ChatColor.WHITE));
}
);
} else {
// Make the changes immediately
for(Mutation mutation : mutations) {
try {
module.register(mutation, value);
module.mutate(mutation);
} catch(Throwable t) {
module.register(mutation, !value);
origin.sendMessage(
new WarningComponent(
"command.mutation.error.mutate",
mutation.getComponent(ChatColor.RED)
)
);
module.getLogger().log(Level.SEVERE, "Unable to enable/disable mutation", t);
return;
}
}
PlayerComponent player = new PlayerComponent(identityProvider.currentIdentity(sender));
all.sendMessage(new Component(new TranslatableComponent(message, player, changed)));
}
}
public String message(boolean now, boolean enable, boolean singular) {
if(now) {
if(enable) {
return singular ? "command.mutation.enable.now.singular" : "command.mutation.enable.now.plural";
} else {
return singular ? "command.mutation.disable.now.singular" : "command.mutation.disable.now.plural";
}
} else {
if(enable) {
return singular ? "command.mutation.enable.later.singular" : "command.mutation.enable.later.plural";
} else {
return singular ? "command.mutation.disable.later.singular" : "command.mutation.disable.later.plural";
}
}
}
}