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