diff --git a/core/src/main/java/tc/oc/pgm/command/MapCommand.java b/core/src/main/java/tc/oc/pgm/command/MapCommand.java index 55abfbe557..7e19cd64c5 100644 --- a/core/src/main/java/tc/oc/pgm/command/MapCommand.java +++ b/core/src/main/java/tc/oc/pgm/command/MapCommand.java @@ -47,7 +47,6 @@ import tc.oc.pgm.util.Audience; import tc.oc.pgm.util.LiquidMetal; import tc.oc.pgm.util.PrettyPaginatedComponentResults; -import tc.oc.pgm.util.StringUtils; import tc.oc.pgm.util.named.MapNameStyle; import tc.oc.pgm.util.named.NameStyle; import tc.oc.pgm.util.text.TextFormatter; @@ -83,15 +82,21 @@ public void maps( search = search.filter(map -> matchesTags(map, tagSet.get(false), tagSet.get(true))); } - if (author != null) { - String query = StringUtils.normalize(author); - search = search.filter(map -> matchesAuthor(map, query)); - } - // FIXME: change when cloud gets support for default flag values final Phase finalPhase = phase == null ? Phase.PRODUCTION : phase; search = search.filter(map -> map.getPhase() == finalPhase); + if (author != null) { + String query = author; + + List collect = search.collect(Collectors.toList()); + boolean exactMatch = + collect.stream().anyMatch((suggestion) -> matchesAuthor(suggestion, query, true)); + search = + collect.stream() + .filter((mapSuggestion -> matchesAuthor(mapSuggestion, query, exactMatch))); + } + Set maps = search.collect(Collectors.toCollection(TreeSet::new)); int resultsPerPage = 8; int pages = (maps.size() + resultsPerPage - 1) / resultsPerPage; @@ -154,9 +159,12 @@ private static boolean matchesTags( return posTags == null || matches == posTags.size(); } - private static boolean matchesAuthor(MapInfo map, String query) { + private static boolean matchesAuthor(MapInfo map, String query, boolean exact) { + String lowerCaseQuery = query.toLowerCase(Locale.ROOT); for (Contributor contributor : map.getAuthors()) { - if (StringUtils.normalize(contributor.getNameLegacy()).contains(query)) { + String name = contributor.getNameLegacy(); + if ((exact && lowerCaseQuery.equalsIgnoreCase(name)) + || (!exact && name != null && name.toLowerCase(Locale.ROOT).contains(lowerCaseQuery))) { return true; } } diff --git a/core/src/main/java/tc/oc/pgm/util/Players.java b/core/src/main/java/tc/oc/pgm/util/Players.java index 2c0b5e133d..010fb1f69f 100644 --- a/core/src/main/java/tc/oc/pgm/util/Players.java +++ b/core/src/main/java/tc/oc/pgm/util/Players.java @@ -2,6 +2,7 @@ import cloud.commandframework.context.CommandContext; import java.util.List; +import java.util.Locale; import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; @@ -34,11 +35,22 @@ public static String getVisibleName(CommandSender viewer, Player other) { } public static List getPlayerNames(CommandSender sender, String query) { - return Bukkit.getOnlinePlayers().stream() - .filter(p -> Players.isVisible(sender, p)) - .map(p -> Players.getVisibleName(sender, p)) - .filter(n -> LiquidMetal.match(n, query)) - .collect(Collectors.toList()); + String lowerCaseQuery = query.toLowerCase(Locale.ROOT); + List playerSuggestions = + Bukkit.getOnlinePlayers().stream() + .filter(p -> Players.isVisible(sender, p)) + .map(p -> Players.getVisibleName(sender, p)) + .filter(n -> LiquidMetal.match(n, query)) + .collect(Collectors.toList()); + List prefixMatched = + playerSuggestions.stream() + .filter((suggestion) -> suggestion.toLowerCase(Locale.ROOT).startsWith(lowerCaseQuery)) + .collect(Collectors.toList()); + if (!prefixMatched.isEmpty()) { + return prefixMatched; + } else { + return playerSuggestions; + } } public static Player getPlayer(CommandSender sender, String query) {