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 (name.length() < 3) { 021 issuer.sendError(MinecraftMessageKeys.USERNAME_TOO_SHORT); 022 return null; 023 } 024 if (!isValidName(name)) { 025 issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name); 026 return null; 027 } 028 029 List<Player> matches = matchPlayer(name); 030 List<Player> confirmList = new ArrayList<>(); 031 findMatches(search, requester, matches, confirmList); 032 033 034 if (matches.size() > 1 || confirmList.size() > 1) { 035 String allMatches = matches.stream().map(Player::getName).collect(Collectors.joining(", ")); 036 issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH, 037 "{search}", name, "{all}", allMatches); 038 return null; 039 } 040 041 if (matches.isEmpty()) { 042 Player player = ACFUtil.getFirstElement(confirmList); 043 if (player == null) { 044 issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name); 045 return null; 046 } else { 047 048 issuer.sendInfo(MinecraftMessageKeys.PLAYER_IS_VANISHED_CONFIRM, "{vanished}", player.getName()); 049 return null; 050 } 051 } 052 053 return matches.get(0); 054 } 055 056 private static void findMatches(String search, CommandSource requester, List<Player> matches, List<Player> confirmList) { 057 // Remove vanished players from smart matching. 058 Iterator<Player> iter = matches.iterator(); 059 //noinspection Duplicates 060 while (iter.hasNext()) { 061 Player player = iter.next(); 062 if (requester instanceof Player && !((Player) requester).canSee(player)) { 063 if (requester.hasPermission("acf.seevanish")) { 064 if (!search.endsWith(":confirm")) { 065 confirmList.add(player); 066 iter.remove(); 067 } 068 } else { 069 iter.remove(); 070 } 071 } 072 } 073 } 074 075 public static List<Player> matchPlayer(String partialName) { 076 List<Player> matchedPlayers = new ArrayList<>(); 077 078 for (Player iterPlayer : Sponge.getServer().getOnlinePlayers()) { 079 String iterPlayerName = iterPlayer.getName(); 080 081 if (partialName.equalsIgnoreCase(iterPlayerName)) { 082 // Exact match 083 matchedPlayers.clear(); 084 matchedPlayers.add(iterPlayer); 085 break; 086 } 087 if (iterPlayerName.toLowerCase(java.util.Locale.ENGLISH).contains(partialName.toLowerCase(java.util.Locale.ENGLISH))) { 088 // Partial match 089 matchedPlayers.add(iterPlayer); 090 } 091 } 092 093 return matchedPlayers; 094 } 095 096 public static boolean isValidName(String name) { 097 return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches(); 098 } 099 100}