All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.nukkit.utils.TextFormat Maven / Gradle / Ivy

There is a newer version: 1.20.40-r1
Show newest version
package cn.nukkit.utils;

import cn.nukkit.api.DeprecationDetails;
import cn.nukkit.api.PowerNukkitXOnly;
import cn.nukkit.api.Since;
import com.google.common.collect.Maps;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * All supported formatting values for chat and console.
 */
public enum TextFormat {
    /**
     * Represents black.
     */
    BLACK('0', 0x00),
    /**
     * Represents dark blue.
     */
    DARK_BLUE('1', 0x1),
    /**
     * Represents dark green.
     */
    DARK_GREEN('2', 0x2),
    /**
     * Represents dark blue (aqua).
     */
    DARK_AQUA('3', 0x3),
    /**
     * Represents dark red.
     */
    DARK_RED('4', 0x4),
    /**
     * Represents dark purple.
     */
    DARK_PURPLE('5', 0x5),
    /**
     * Represents gold.
     */
    GOLD('6', 0x6),
    /**
     * Represents gray.
     */
    GRAY('7', 0x7),
    /**
     * Represents dark gray.
     */
    DARK_GRAY('8', 0x8),
    /**
     * Represents blue.
     */
    BLUE('9', 0x9),
    /**
     * Represents green.
     */
    GREEN('a', 0xA),
    /**
     * Represents aqua.
     */
    AQUA('b', 0xB),
    /**
     * Represents red.
     */
    RED('c', 0xC),
    /**
     * Represents light purple.
     */
    LIGHT_PURPLE('d', 0xD),
    /**
     * Represents yellow.
     */
    YELLOW('e', 0xE),
    /**
     * Represents white.
     */
    WHITE('f', 0xF),
    /**
     * Represents minecoins gold.
     */
    MINECOIN_GOLD('g', 0x16),
    /**
     * Represents material quartz.
     */
    @PowerNukkitXOnly
    @Since("1.19.80-r3")
    MATERIAL_QUARTZ('h', 0x17),
    /**
     * Represents material iron.
     */
    @PowerNukkitXOnly
    @Since("1.19.80-r3")
    MATERIAL_IRON('i', 0x18),
    /**
     * Represents material netherite.
     */
    @PowerNukkitXOnly
    @Since("1.19.80-r3")
    MATERIAL_NETHERITE('j', 0x19),
    /**
     * Represents material redstone.
     */
    @PowerNukkitXOnly
    @Since("1.19.80-r3")
    MATERIAL_REDSTONE('m', 0x20),
    /**
     * Represents material copper.
     */
    @PowerNukkitXOnly
    @Since("1.19.80-r3")
    MATERIAL_COPPER('n', 0x21),
    /**
     * Represents material gold.
     */
    @PowerNukkitXOnly
    @Since("1.19.80-r3")
    MATERIAL_GOLD('p', 0x22),
    /**
     * Represents material emerald.
     */
    @PowerNukkitXOnly
    @Since("1.19.80-r3")
    MATERIAL_EMERALD('q', 0x23),
    /**
     * Represents material diamond.
     */
    @PowerNukkitXOnly
    @Since("1.19.80-r3")
    MATERIAL_DIAMOND('s', 0x24),
    /**
     * Represents material lapis.
     */
    @PowerNukkitXOnly
    @Since("1.19.80-r3")
    MATERIAL_LAPIS('t', 0x25),
    /**
     * Represents material amethyst.
     */
    @PowerNukkitXOnly
    @Since("1.19.80-r3")
    MATERIAL_AMETHYST('u', 0x26),
    /**
     * Makes the text obfuscated.
     */
    OBFUSCATED('k', 0x10, true),
    /**
     * Makes the text bold.
     */
    BOLD('l', 0x11, true),
    /**
     * Makes a line appear through the text.
     */
    @Deprecated
    @DeprecationDetails(since = "1.19.80-r3",
            reason = "Code STRIKETHROUGH has been replaced by MATERIAL_REDSTONE in Minecraft version 1.19.81",
            replaceWith = "TextFormat.MATERIAL_REDSTONE")
    STRIKETHROUGH('m', 0x12, true),
    /**
     * Makes the text appear underlined.
     */
    @Deprecated
    @DeprecationDetails(since = "1.19.80-r3",
            reason = "Code UNDERLINE has been replaced by MATERIAL_COPPER in Minecraft version 1.19.81",
            replaceWith = "TextFormat.MATERIAL_COPPER")
    UNDERLINE('n', 0x13, true),
    /**
     * Makes the text italic.
     */
    ITALIC('o', 0x14, true),
    /**
     * Resets all previous chat colors or formats.
     */
    RESET('r', 0x15);

    /**
     * The special character which prefixes all format codes. Use this if
     * you need to dynamically convert format codes from your custom format.
     */
    public static final char ESCAPE = '\u00A7';

    private static final Pattern CLEAN_PATTERN = Pattern.compile("(?i)" + ESCAPE + "[0-9A-GK-OR]");
    private final static Map BY_ID = Maps.newTreeMap();
    private final static Map BY_CHAR = new HashMap<>();

    static {
        for (TextFormat color : values()) {
            BY_ID.put(color.intCode, color);
            BY_CHAR.put(color.code, color);
        }
    }

    private final int intCode;
    private final char code;
    private final boolean isFormat;
    private final String toString;

    TextFormat(char code, int intCode) {
        this(code, intCode, false);
    }

    TextFormat(char code, int intCode, boolean isFormat) {
        this.code = code;
        this.intCode = intCode;
        this.isFormat = isFormat;
        this.toString = new String(new char[]{ESCAPE, code});
    }

    /**
     * Gets the TextFormat represented by the specified format code.
     *
     * @param code Code to check
     * @return Associative {@link TextFormat} with the given code,
     * or null if it doesn't exist
     */
    public static TextFormat getByChar(char code) {
        return BY_CHAR.get(code);
    }

    /**
     * Gets the TextFormat represented by the specified format code.
     *
     * @param code Code to check
     * @return Associative {@link TextFormat} with the given code,
     * or null if it doesn't exist
     */
    public static TextFormat getByChar(String code) {
        if (code == null || code.length() <= 1) {
            return null;
        }

        return BY_CHAR.get(code.charAt(0));
    }

    /**
     * Cleans the given message of all format codes.
     *
     * @param input String to clean.
     * @return A copy of the input string, without any formatting.
     */
    public static String clean(final String input) {
        return clean(input, false);
    }

    public static String clean(final String input, final boolean recursive) {
        if (input == null) {
            return null;
        }

        String result = CLEAN_PATTERN.matcher(input).replaceAll("");

        if (recursive && CLEAN_PATTERN.matcher(result).find()) {
            return clean(result, true);
        }
        return result;
    }

    /**
     * Translates a string using an alternate format code character into a
     * string that uses the internal TextFormat.ESCAPE format code
     * character. The alternate format code character will only be replaced if
     * it is immediately followed by 0-9, A-G, a-g, K-O, k-o, R or r.
     *
     * @param altFormatChar   The alternate format code character to replace. Ex: &
     * @param textToTranslate Text containing the alternate format code character.
     * @return Text containing the TextFormat.ESCAPE format code character.
     */
    public static String colorize(char altFormatChar, String textToTranslate) {
        char[] b = textToTranslate.toCharArray();
        for (int i = 0; i < b.length - 1; i++) {
            if (b[i] == altFormatChar && "0123456789AaBbCcDdEeFfGgHhIiJjMmNnPpQqSsTtUuKkLlOoRr".indexOf(b[i + 1]) > -1) {
                b[i] = TextFormat.ESCAPE;
                b[i + 1] = Character.toLowerCase(b[i + 1]);
            }
        }
        return new String(b);
    }

    /**
     * Translates a string, using an ampersand (&) as an alternate format code
     * character, into a string that uses the internal TextFormat.ESCAPE format
     * code character. The alternate format code character will only be replaced if
     * it is immediately followed by 0-9, A-G, a-g, K-O, k-o, R or r.
     *
     * @param textToTranslate Text containing the alternate format code character.
     * @return Text containing the TextFormat.ESCAPE format code character.
     */
    public static String colorize(String textToTranslate) {
        return colorize('&', textToTranslate);
    }

    /**
     * Gets the chat color used at the end of the given input string.
     *
     * @param input Input string to retrieve the colors from.
     * @return Any remaining chat color to pass onto the next line.
     */
    public static String getLastColors(String input) {
        StringBuilder result = new StringBuilder();
        int length = input.length();

        // Search backwards from the end as it is faster
        for (int index = length - 1; index > -1; index--) {
            char section = input.charAt(index);
            if (section == ESCAPE && index < length - 1) {
                char c = input.charAt(index + 1);
                TextFormat color = getByChar(c);

                if (color != null) {
                    result.insert(0, color.toString());

                    // Once we find a color or reset we can stop searching
                    if (color.isColor() || color.equals(RESET)) {
                        break;
                    }
                }
            }
        }

        return result.toString();
    }

    /**
     * Gets the char value associated with this color
     *
     * @return A char value of this color code
     */
    public char getChar() {
        return code;
    }

    @Override
    public String toString() {
        return toString;
    }

    /**
     * Checks if this code is a format code as opposed to a color code.
     */
    public boolean isFormat() {
        return isFormat;
    }

    /**
     * Checks if this code is a color code as opposed to a format code.
     */
    public boolean isColor() {
        return !isFormat && this != RESET;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy