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