001 package org.bukkit; 002 003 import java.util.Map; 004 import java.util.regex.Pattern; 005 006 import org.apache.commons.lang.Validate; 007 008 import com.google.common.collect.Maps; 009 010 /** 011 * All supported color values for chat 012 */ 013 public enum ChatColor { 014 /** 015 * Represents black 016 */ 017 BLACK('0', 0x00), 018 /** 019 * Represents dark blue 020 */ 021 DARK_BLUE('1', 0x1), 022 /** 023 * Represents dark green 024 */ 025 DARK_GREEN('2', 0x2), 026 /** 027 * Represents dark blue (aqua) 028 */ 029 DARK_AQUA('3', 0x3), 030 /** 031 * Represents dark red 032 */ 033 DARK_RED('4', 0x4), 034 /** 035 * Represents dark purple 036 */ 037 DARK_PURPLE('5', 0x5), 038 /** 039 * Represents gold 040 */ 041 GOLD('6', 0x6), 042 /** 043 * Represents gray 044 */ 045 GRAY('7', 0x7), 046 /** 047 * Represents dark gray 048 */ 049 DARK_GRAY('8', 0x8), 050 /** 051 * Represents blue 052 */ 053 BLUE('9', 0x9), 054 /** 055 * Represents green 056 */ 057 GREEN('a', 0xA), 058 /** 059 * Represents aqua 060 */ 061 AQUA('b', 0xB), 062 /** 063 * Represents red 064 */ 065 RED('c', 0xC), 066 /** 067 * Represents light purple 068 */ 069 LIGHT_PURPLE('d', 0xD), 070 /** 071 * Represents yellow 072 */ 073 YELLOW('e', 0xE), 074 /** 075 * Represents white 076 */ 077 WHITE('f', 0xF), 078 /** 079 * Represents magical characters that change around randomly 080 */ 081 MAGIC('k', 0x10, true), 082 /** 083 * Makes the text bold. 084 */ 085 BOLD('l', 0x11, true), 086 /** 087 * Makes a line appear through the text. 088 */ 089 STRIKETHROUGH('m', 0x12, true), 090 /** 091 * Makes the text appear underlined. 092 */ 093 UNDERLINE('n', 0x13, true), 094 /** 095 * Makes the text italic. 096 */ 097 ITALIC('o', 0x14, true), 098 /** 099 * Resets all previous chat colors or formats. 100 */ 101 RESET('r', 0x15); 102 103 /** 104 * The special character which prefixes all chat colour codes. Use this if 105 * you need to dynamically convert colour codes from your custom format. 106 */ 107 public static final char COLOR_CHAR = '\u00A7'; 108 private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf(COLOR_CHAR) + "[0-9A-FK-OR]"); 109 110 private final int intCode; 111 private final char code; 112 private final boolean isFormat; 113 private final String toString; 114 private final static Map<Integer, ChatColor> BY_ID = Maps.newHashMap(); 115 private final static Map<Character, ChatColor> BY_CHAR = Maps.newHashMap(); 116 117 private ChatColor(char code, int intCode) { 118 this(code, intCode, false); 119 } 120 121 private ChatColor(char code, int intCode, boolean isFormat) { 122 this.code = code; 123 this.intCode = intCode; 124 this.isFormat = isFormat; 125 this.toString = new String(new char[] {COLOR_CHAR, code}); 126 } 127 128 /** 129 * Gets the char value associated with this color 130 * 131 * @return A char value of this color code 132 */ 133 public char getChar() { 134 return code; 135 } 136 137 @Override 138 public String toString() { 139 return toString; 140 } 141 142 /** 143 * Checks if this code is a format code as opposed to a color code. 144 */ 145 public boolean isFormat() { 146 return isFormat; 147 } 148 149 /** 150 * Checks if this code is a color code as opposed to a format code. 151 */ 152 public boolean isColor() { 153 return !isFormat && this != RESET; 154 } 155 156 /** 157 * Gets the color represented by the specified color code 158 * 159 * @param code Code to check 160 * @return Associative {@link org.bukkit.ChatColor} with the given code, 161 * or null if it doesn't exist 162 */ 163 public static ChatColor getByChar(char code) { 164 return BY_CHAR.get(code); 165 } 166 167 /** 168 * Gets the color represented by the specified color code 169 * 170 * @param code Code to check 171 * @return Associative {@link org.bukkit.ChatColor} with the given code, 172 * or null if it doesn't exist 173 */ 174 public static ChatColor getByChar(String code) { 175 Validate.notNull(code, "Code cannot be null"); 176 Validate.isTrue(code.length() > 0, "Code must have at least one char"); 177 178 return BY_CHAR.get(code.charAt(0)); 179 } 180 181 /** 182 * Strips the given message of all color codes 183 * 184 * @param input String to strip of color 185 * @return A copy of the input string, without any coloring 186 */ 187 public static String stripColor(final String input) { 188 if (input == null) { 189 return null; 190 } 191 192 return STRIP_COLOR_PATTERN.matcher(input).replaceAll(""); 193 } 194 195 /** 196 * Translates a string using an alternate color code character into a 197 * string that uses the internal ChatColor.COLOR_CODE color code 198 * character. The alternate color code character will only be replaced if 199 * it is immediately followed by 0-9, A-F, a-f, K-O, k-o, R or r. 200 * 201 * @param altColorChar The alternate color code character to replace. Ex: & 202 * @param textToTranslate Text containing the alternate color code character. 203 * @return Text containing the ChatColor.COLOR_CODE color code character. 204 */ 205 public static String translateAlternateColorCodes(char altColorChar, String textToTranslate) { 206 char[] b = textToTranslate.toCharArray(); 207 for (int i = 0; i < b.length - 1; i++) { 208 if (b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i+1]) > -1) { 209 b[i] = ChatColor.COLOR_CHAR; 210 b[i+1] = Character.toLowerCase(b[i+1]); 211 } 212 } 213 return new String(b); 214 } 215 216 /** 217 * Gets the ChatColors used at the end of the given input string. 218 * 219 * @param input Input string to retrieve the colors from. 220 * @return Any remaining ChatColors to pass onto the next line. 221 */ 222 public static String getLastColors(String input) { 223 String result = ""; 224 int length = input.length(); 225 226 // Search backwards from the end as it is faster 227 for (int index = length - 1; index > -1; index--) { 228 char section = input.charAt(index); 229 if (section == COLOR_CHAR && index < length - 1) { 230 char c = input.charAt(index + 1); 231 ChatColor color = getByChar(c); 232 233 if (color != null) { 234 result = color.toString() + result; 235 236 // Once we find a color or reset we can stop searching 237 if (color.isColor() || color.equals(RESET)) { 238 break; 239 } 240 } 241 } 242 } 243 244 return result; 245 } 246 247 static { 248 for (ChatColor color : values()) { 249 BY_ID.put(color.intCode, color); 250 BY_CHAR.put(color.code, color); 251 } 252 } 253 }