001package co.aikar.commands; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.Collections; 006import java.util.List; 007import java.util.Optional; 008import java.util.stream.Collectors; 009 010import com.velocitypowered.api.command.CommandSource; 011import com.velocitypowered.api.proxy.Player; 012import com.velocitypowered.api.proxy.ProxyServer; 013 014import net.kyori.text.TextComponent; 015import net.kyori.text.serializer.ComponentSerializers; 016 017public class ACFVelocityUtil { 018 019 @SuppressWarnings("deprecation") 020 public static TextComponent color(String message) { 021 return ComponentSerializers.LEGACY.deserialize(message); 022 } 023 024 public static Player findPlayerSmart(ProxyServer server, CommandIssuer issuer, String search) { 025 CommandSource requester = issuer.getIssuer(); 026 String name = ACFUtil.replace(search, ":confirm", ""); 027 if (name.length() < 3) { 028 issuer.sendError(MinecraftMessageKeys.USERNAME_TOO_SHORT); 029 return null; 030 } 031 if (!isValidName(name)) { 032 issuer.sendError(MinecraftMessageKeys.IS_NOT_A_VALID_NAME, "{name}", name); 033 return null; 034 } 035 036 List<Player> matches = new ArrayList<>(matchPlayer(server, name)); 037 038 if (matches.size() > 1) { 039 String allMatches = matches.stream().map(Player::getUsername).collect(Collectors.joining(", ")); 040 issuer.sendError(MinecraftMessageKeys.MULTIPLE_PLAYERS_MATCH, "{search}", name, "{all}", allMatches); 041 return null; 042 } 043 044 if (matches.isEmpty()) { 045 issuer.sendError(MinecraftMessageKeys.NO_PLAYER_FOUND_SERVER, "{search}", name); 046 return null; 047 } 048 049 return matches.get(0); 050 } 051 052 /* 053 * Original code written by md_5 054 * 055 * Modified to work with Velocity by Crypnotic 056 */ 057 private static Collection<Player> matchPlayer(ProxyServer server, final String partialName) { 058 // A better error message might be nice. This just mimics the previous output 059 if (partialName == null) { 060 throw new NullPointerException("partialName"); 061 } 062 063 Optional<Player> exactMatch = server.getPlayer(partialName); 064 //noinspection OptionalIsPresent 065 if (exactMatch.isPresent()) { 066 return Collections.singleton(exactMatch.get()); 067 } 068 069 return server.getAllPlayers().stream() 070 .filter(player -> player.getUsername().regionMatches(true, 0, partialName, 0, partialName.length())) 071 .collect(Collectors.toList()); 072 } 073 074 public static boolean isValidName(String name) { 075 return name != null && !name.isEmpty() && ACFPatterns.VALID_NAME_PATTERN.matcher(name).matches(); 076 } 077 078 public static <T> T validate(T object, String message, Object... values) { 079 if (object == null) { 080 throw new NullPointerException(String.format(message, values)); 081 } 082 return object; 083 } 084}