Allow maps to be filtered by author or gamemode

This commit is contained in:
Potato 2017-12-03 16:25:29 +08:00 committed by Ashcon Partovi
parent 3a2cfa7c98
commit 3744813dd2
2 changed files with 109 additions and 9 deletions

View File

@ -21,6 +21,18 @@ command.admin.skipto.success = Successfully skipped to {0}
command.admin.pgm = Configuration successfully reloaded.
command.map.mapList.title = Maps
# {0} = Name of author
command.map.mapList.displayByAuthor = Maps by {0}
# {0} = Name of gamemode
command.map.mapList.displayByGamemode = Maps with {0}
# {0} = Name of author
# {1} = Name of gamemode
command.map.mapList.displayByBoth = {0}'s {1} maps
# {0} = map title and version
command.map.next.success = Next map: {0}

View File

@ -3,7 +3,9 @@ package tc.oc.pgm.commands;
import java.net.URL;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import javax.inject.Inject;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableSortedSet;
@ -12,23 +14,32 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import java.util.stream.Collectors;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TranslatableComponent;
import org.bukkit.command.CommandSender;
import tc.oc.api.docs.User;
import tc.oc.api.docs.virtual.MapDoc;
import tc.oc.api.util.Permissions;
import tc.oc.commons.bukkit.chat.BukkitAudiences;
import tc.oc.commons.bukkit.chat.ComponentRenderContext;
import tc.oc.commons.bukkit.chat.NameStyle;
import tc.oc.commons.bukkit.chat.PlayerComponent;
import tc.oc.commons.bukkit.chat.UserTextComponent;
import tc.oc.commons.bukkit.commands.PrettyPaginatedResult;
import tc.oc.commons.bukkit.commands.UserFinder;
import tc.oc.commons.bukkit.localization.Translations;
import tc.oc.commons.bukkit.nick.Identity;
import tc.oc.commons.bukkit.nick.IdentityProvider;
import tc.oc.commons.bukkit.nick.UsernameRenderer;
import tc.oc.commons.core.chat.Audience;
import tc.oc.commons.core.chat.Component;
import tc.oc.commons.core.chat.Components;
import tc.oc.commons.core.commands.CommandFutureCallback;
import tc.oc.commons.core.commands.Commands;
import tc.oc.minecraft.scheduler.SyncExecutor;
import tc.oc.pgm.PGM;
import tc.oc.pgm.PGMTranslations;
import tc.oc.pgm.ffa.FreeForAllModule;
@ -41,24 +52,101 @@ import tc.oc.pgm.rotation.RotationProviderInfo;
import tc.oc.pgm.rotation.RotationState;
import tc.oc.pgm.teams.TeamFactory;
public class MapCommands {
public class MapCommands implements Commands {
private final UserFinder userFinder;
private final SyncExecutor syncExecutor;
private final IdentityProvider identityProvider;
private final ComponentRenderContext renderer;
@Inject MapCommands(UserFinder userFinder, IdentityProvider identityProvider, SyncExecutor syncExecutor, ComponentRenderContext renderer) {
this.userFinder = userFinder;
this.identityProvider = identityProvider;
this.syncExecutor = syncExecutor;
this.renderer = renderer;
}
@Command(
aliases = {"maplist", "maps", "ml"},
desc = "Shows the maps that are currently loaded",
usage = "[page]",
usage = "[-a author] [-g gamemode] [page]",
min = 0,
max = 1,
max = 2,
flags = "a:g:",
help = "Shows all the maps that are currently loaded including ones that are not in the rotation."
)
@CommandPermissions("pgm.maplist")
public static void maplist(CommandContext args, final CommandSender sender) throws CommandException {
final Set<PGMMap> maps = ImmutableSortedSet.copyOf(new PGMMap.DisplayOrder(), PGM.getMatchManager().getMaps());
public void maplist(final CommandContext args, final CommandSender sender) throws CommandException {
final Identity senderIdentity = identityProvider.createIdentity(sender);
final MapDoc.Gamemode gamemode = parseGamemode(args.getFlag('g'));
final String author = args.getFlag('a');
if(args.getFlag('a') != null) {
syncExecutor.callback(
userFinder.findUser(sender, author, UserFinder.Scope.ALL, UserFinder.Default.NULL),
CommandFutureCallback.onSuccess(sender, result -> {
BaseComponent displayMsg = gamemode != null ?
new TranslatableComponent("command.map.mapList.displayByBoth",
new PlayerComponent(identityProvider.currentIdentity(result.user)),
new UserTextComponent(senderIdentity, gamemode.name())) :
new TranslatableComponent("command.map.mapList.displayByAuthor",
new PlayerComponent(identityProvider.createIdentity(result.user)));
displayMaps(sender,
displayMsg,
getFilteredMaps(gamemode, result.user),
args);
}));
} else if(gamemode != null) {
displayMaps(sender,
new TranslatableComponent("command.map.mapList.displayByGamemode",
new UserTextComponent(senderIdentity, gamemode.name())),
getFilteredMaps(gamemode, null),
args);
} else {
displayMaps(sender,
new TranslatableComponent("command.map.mapList.title"),
getFilteredMaps(null, null), args);
}
}
new PrettyPaginatedResult<PGMMap>(PGMTranslations.get().t("command.map.mapList.title", sender)) {
@Override public String format(PGMMap map, int index) {
return (index + 1) + ". " + map.getInfo().getShortDescription(sender);
private MapDoc.Gamemode parseGamemode(@Nullable String gamemode) throws CommandException {
if(gamemode == null) return null;
try {
return MapDoc.Gamemode.valueOf(gamemode);
} catch (IllegalArgumentException e) {
throw new CommandException("Invalid input " + gamemode);
}
}
/**
* Returns a list of filtered map with the given parameters.
* If both parameters are null, this method returns the full set of maps from the repository.
*
* @param gamemode Gamemode used to filter the map with - can be null.
* @param author An author given from the result of a UserFinder - can be null.
*/
private Set<PGMMap> getFilteredMaps(@Nullable MapDoc.Gamemode gamemode, @Nullable User author) {
final Set<PGMMap> maps = ImmutableSortedSet.copyOf(new PGMMap.DisplayOrder(), PGM.get().getMapLibrary().getMaps());
if(gamemode == null && author == null) return maps;
return maps.stream().filter(m -> (gamemode == null || m.getDocument().gamemode().contains(gamemode)) &&
(author == null || m.getDocument().author_uuids().contains(author.uuid())))
.collect(Collectors.toSet());
}
/**
* Returns a PrettyPaginatedResult of the list of maps given.
*
* @param sender CommandSender to display to.
* @param title BaseComponent of the title to be provided for display.
* @param maps The list of maps to be formatted and displayed.
* @param args The arguments of a command.
*/
private void displayMaps(CommandSender sender, BaseComponent title, Set<PGMMap> maps, CommandContext args) throws CommandException {
new PrettyPaginatedResult<PGMMap>(renderer.renderLegacy(title, sender)) {
@Override
public String format(PGMMap pgmMap, int i) {
return (i + 1) + ". " + pgmMap.getInfo().getShortDescription(sender);
}
}.display(new BukkitWrappedCommandSender(sender), maps, args.getInteger(0, 1) /* page */);
}.display(new BukkitWrappedCommandSender(sender), maps, args.getInteger(0, 1) /*page*/);
}
private static BaseComponent mapInfoLabel(String key) {