001package co.aikar.commands; 002 003import org.jetbrains.annotations.Nullable; 004import org.spongepowered.api.Sponge; 005import org.spongepowered.api.command.CommandSource; 006import org.spongepowered.api.entity.living.player.Player; 007 008import java.util.ArrayList; 009import java.util.Iterator; 010import java.util.List; 011import java.util.stream.Collectors; 012 013@SuppressWarnings("WeakerAccess") 014public class ACFSpongeUtil { 015 public static Player findPlayerSmart(CommandIssuer issuer, String search) { 016 CommandSource requester = issuer.getIssuer(); 017 if (search == null) { 018 return null; 019 } 020 String name = ACFUtil.replace(search, ":confirm", ""); 021 022 List<Player> matches = matchPlayer(name); 023 List<Player> confirmList = new ArrayList<>(); 024 findMatches(search, requester, matches, confirmList); 025 026 027 if (matches.size() > 1 || confirmList.size() > 1) { 028 String allMatches = matches.stream().map(Player::getName).collect(Collectors.joining(", ")); 029 issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH, 030 "{search}", name, "{all}", allMatches); 031 return null; 032 } 033 034 if (matches.isEmpty()) { 035 if (!issuer.getManager().isValidName(name)) { 036 issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name); 037 return null; 038 } 039 Player player = ACFUtil.getFirstElement(confirmList); 040 if (player == null) { 041 issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name); 042 return null; 043 } else { 044 045 issuer.sendInfo(MinecraftMessageKeys.PLAYER_IS_VANISHED_CONFIRM, "{vanished}", player.getName()); 046 return null; 047 } 048 } 049 050 return matches.get(0); 051 } 052 053 private static void findMatches(String search, CommandSource requester, List<Player> matches, List<Player> confirmList) { 054 // Remove vanished players from smart matching. 055 Iterator<Player> iter = matches.iterator(); 056 //noinspection Duplicates 057 while (iter.hasNext()) { 058 Player player = iter.next(); 059 if (requester instanceof Player && !((Player) requester).canSee(player)) { 060 if (requester.hasPermission("acf.seevanish")) { 061 if (!search.endsWith(":confirm")) { 062 confirmList.add(player); 063 iter.remove(); 064 } 065 } else { 066 iter.remove(); 067 } 068 } 069 } 070 } 071 072 public static List<Player> matchPlayer(String partialName) { 073 List<Player> matchedPlayers = new ArrayList<>(); 074 075 for (Player iterPlayer : Sponge.getServer().getOnlinePlayers()) { 076 String iterPlayerName = iterPlayer.getName(); 077 078 if (partialName.equalsIgnoreCase(iterPlayerName)) { 079 // Exact match 080 matchedPlayers.clear(); 081 matchedPlayers.add(iterPlayer); 082 break; 083 } 084 if (iterPlayerName.toLowerCase(java.util.Locale.ENGLISH).contains(partialName.toLowerCase(java.util.Locale.ENGLISH))) { 085 // Partial match 086 matchedPlayers.add(iterPlayer); 087 } 088 } 089 090 return matchedPlayers; 091 } 092 093 public static boolean isValidName(@Nullable String name) { 094 return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches(); 095 } 096 097}