Last active
April 22, 2019 11:24
-
-
Save DragonHunt3r/f754e8d063ec3af7fb8d047781f3c027 to your computer and use it in GitHub Desktop.
Minecraft ChatColor optimizer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ColorOptimizer { | |
/** | |
* Matches text until next color code. | |
* &a&lSome&b&oText -> &a&lSome, &b&oText | |
*/ | |
private static final Pattern SPLIT_PATTERN = Pattern.compile("(" + ChatColor.COLOR_CHAR + "[0-9A-Fa-fK-Ok-oRr])+(.*?)(?=(?:" + ChatColor.COLOR_CHAR + "[0-9A-Fa-fK-Ok-oRr])|$)"); | |
/** | |
* Matches any color. | |
*/ | |
private static final Pattern COLOR = Pattern.compile("(" + ChatColor.COLOR_CHAR + "[0-9A-Fa-f])"); | |
/** | |
* Matches any modifier. | |
*/ | |
private static final Pattern MODIFIER = Pattern.compile("(" + ChatColor.COLOR_CHAR + "[K-Ok-oRr])"); | |
/** | |
* Matches any color or modifier. | |
*/ | |
private static final Pattern ALL = Pattern.compile("(" + ChatColor.COLOR_CHAR + "[0-9A-Fa-fK-Ok-oRr])"); | |
/** | |
* &r (reset) color code. | |
*/ | |
private static final String RESET = color("&r"); | |
/** | |
* Private constructor to prevent initializing. | |
* @throws AssertionError when called. | |
*/ | |
private ColorOptimizer() { | |
throw new AssertionError(); | |
} | |
/** | |
* Optimize the chat colors in the input. | |
* @param string input. | |
* @return optimized text. | |
*/ | |
public static String optimize(String string) { | |
StringBuilder builder = new StringBuilder(); | |
String currentColor = null; | |
List<String> currentModifiers = null; | |
Matcher matcher = SPLIT_PATTERN.matcher(color("&f" + string)); | |
while (matcher.find()) { | |
// Fixes duplicate color codes. | |
// &a&l&b&oabc -> &b&oabc | |
String split = matcher.group().replaceAll("(.*(" + ChatColor.COLOR_CHAR + "[0-9A-Fa-f])+)", "$2"); | |
String color = getColor(split); | |
List<String> modifiers = getModifiers(split); | |
String text = getText(split); | |
// If reset (&r) was used. | |
if (modifiers != null && modifiers.contains(RESET)) { | |
String newText = ""; | |
for (String modifier : modifiers) { | |
newText += modifier; | |
} | |
// Color resets because of the reset code (&r). | |
currentColor = null; | |
// Modifiers reset because of the reset core (&r). | |
modifiers.remove(RESET); | |
currentModifiers = modifiers; | |
builder.append(newText).append(text); | |
continue; | |
} | |
// If a color was found. | |
if (color != null) { | |
// If the color is different. | |
if (!color.equalsIgnoreCase(currentColor)) { | |
currentColor = color; | |
currentModifiers = modifiers; | |
builder.append(split); | |
continue; | |
} | |
// If the color is the same, remove color from String. | |
split = split.replace(color, ""); | |
} | |
if (modifiers == null) { | |
builder.append(split); | |
continue; | |
} | |
String newText = ""; | |
// Remove all modifiers that already apply from the new modifiers. | |
if (currentModifiers != null) { | |
currentModifiers.forEach(modifier -> modifiers.remove(modifier)); | |
currentModifiers.addAll(modifiers); | |
} | |
else { | |
currentModifiers = modifiers; | |
} | |
for (String modifier : modifiers) { | |
newText += modifier; | |
} | |
builder.append(newText).append(text); | |
} | |
return builder.toString(); | |
} | |
/** | |
* Color input text. | |
* @see ChatColor#translateAlternateColorCodes(char, String) | |
* @param text input. | |
* @return colored text. | |
*/ | |
public static String color(String text) { | |
return ChatColor.translateAlternateColorCodes('&', text); | |
} | |
/** | |
* Uncolor input text. | |
* Does the opposite of {@link #color(String)} | |
* @param text input. | |
* @return uncolored text. | |
*/ | |
public static String uncolor(String text) { | |
char[] array = text.toCharArray(); | |
for (int i = 0; i < array.length - 1; i++) { | |
if (array[i] == ChatColor.COLOR_CHAR && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(array[i + 1]) != -1) { | |
array[i] = '&'; | |
array[i + 1] = Character.toLowerCase(array[i + 1]); | |
} | |
} | |
return new String(array); | |
} | |
/** | |
* Get the color of a String. | |
* &a&labc -> &a | |
* {@link #COLOR} | |
* @param string input. | |
* @return the color of the string or null if no color was found. | |
*/ | |
private static String getColor(String string) { | |
Matcher match = COLOR.matcher(string); | |
return match.find() ? match.group() : null; | |
} | |
/** | |
* Get the modifiers of a String. | |
* &5&labc -> &l | |
* &5&l&oabc -> &l, &o | |
* &5&l&r&o -> &o | |
* {@link #MODIFIER} | |
* @param string input. | |
* @return a list with all modifiers of the string or null if no modifiers were found. | |
*/ | |
private static List<String> getModifiers(String string) { | |
List<String> list = new ArrayList<String>(); | |
Matcher match = MODIFIER.matcher(string); | |
while (match.find()) { | |
String group = match.group().toLowerCase(); | |
// Reset modifiers at &r (reset) | |
if (group.equals(RESET)) { | |
list.clear(); | |
} | |
if (!list.contains(group)) { | |
list.add(group); | |
} | |
} | |
return list.isEmpty() ? null : list; | |
} | |
/** | |
* Get the text part of a String. | |
* &5&labc -> abc | |
* {@link #ALL} | |
* @param string input. | |
* @return the text part of the string. | |
*/ | |
private static String getText(String string) { | |
return ALL.matcher(string).replaceAll(""); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment