33import com .google .common .collect .Maps ;
44import lombok .Getter ;
55import org .apache .commons .lang3 .Validate ;
6+ import org .jetbrains .annotations .Contract ;
7+ import org .jetbrains .annotations .NotNull ;
8+ import org .jetbrains .annotations .Nullable ;
69
710import java .util .Map ;
811import java .util .regex .Pattern ;
@@ -106,9 +109,8 @@ public enum ColorCode {
106109 private final char code ;
107110 @ Getter
108111 private final boolean isFormat ;
109- @ Getter
110- private final String colorCodeString ;
111- private final static Map <Character , ColorCode > BY_CHAR = Maps .newHashMap ();
112+ private final String toString ;
113+ private static final Map <Character , ColorCode > BY_CHAR = Maps .newHashMap ();
112114
113115 ColorCode (char code , int intCode ) {
114116 this (code , intCode , false );
@@ -118,7 +120,7 @@ public enum ColorCode {
118120 this .code = code ;
119121 this .intCode = intCode ;
120122 this .isFormat = isFormat ;
121- this .colorCodeString = new String (new char []{COLOR_CHAR , code });
123+ this .toString = new String (new char []{COLOR_CHAR , code });
122124 }
123125
124126 public boolean isColor () {
@@ -142,28 +144,44 @@ public static ColorCode getByChar(String code) {
142144 * @param input String to strip of color
143145 * @return A copy of the input string, without any coloring
144146 */
145- public static String stripColor (final String input ) {
147+ @ Contract ("!null -> !null; null -> null" )
148+ @ Nullable
149+ public static String stripColor (@ Nullable final String input ) {
146150 if (input == null ) {
147151 return null ;
148152 }
149153
150154 return STRIP_COLOR_PATTERN .matcher (input ).replaceAll ("" );
151155 }
152156
157+ private static final Pattern HEX_COLOR_PATTERN = Pattern .compile (COLOR_CHAR + "x(?>" + COLOR_CHAR + "[0-9a-f]){6}" , Pattern .CASE_INSENSITIVE ); // Paper - Support hex colors in getLastColors
158+
153159 /**
154- * Gets the ColorCodes used at the end of the given input string.
160+ * Gets the ChatColors used at the end of the given input string.
155161 *
156162 * @param input Input string to retrieve the colors from.
157- * @return Any remaining ColorCodes to pass onto the next line.
163+ * @return Any remaining ChatColors to pass onto the next line.
158164 */
159- public static String getLastColors (String input ) {
165+ @ NotNull
166+ public static String getLastColors (@ NotNull String input ) {
167+ Validate .notNull (input , "Cannot get last colors from null text" );
168+
160169 StringBuilder result = new StringBuilder ();
161170 int length = input .length ();
162171
163172 // Search backwards from the end as it is faster
164173 for (int index = length - 1 ; index > -1 ; index --) {
165174 char section = input .charAt (index );
166175 if (section == COLOR_CHAR && index < length - 1 ) {
176+ // Paper start - Support hex colors
177+ if (index > 11 && input .charAt (index - 12 ) == COLOR_CHAR && (input .charAt (index - 11 ) == 'x' || input .charAt (index - 11 ) == 'X' )) {
178+ String color = input .substring (index - 12 , index + 2 );
179+ if (HEX_COLOR_PATTERN .matcher (color ).matches ()) {
180+ result .insert (0 , color );
181+ break ;
182+ }
183+ }
184+ // Paper end
167185 char c = input .charAt (index + 1 );
168186 ColorCode color = getByChar (c );
169187
@@ -181,6 +199,35 @@ public static String getLastColors(String input) {
181199 return result .toString ();
182200 }
183201
202+ /**
203+ * Translates a string using an alternate color code character into a
204+ * string that uses the internal ChatColor.COLOR_CODE color code
205+ * character. The alternate color code character will only be replaced if
206+ * it is immediately followed by 0-9, A-F, a-f, K-O, k-o, R or r.
207+ *
208+ * @param altColorChar The alternate color code character to replace. Ex: {@literal &}
209+ * @param textToTranslate Text containing the alternate color code character.
210+ * @return Text containing the ChatColor.COLOR_CODE color code character.
211+ */
212+ @ NotNull
213+ public static String translateAlternateColorCodes (char altColorChar , @ NotNull String textToTranslate ) {
214+ Validate .notNull (textToTranslate , "Cannot translate null text" );
215+
216+ char [] b = textToTranslate .toCharArray ();
217+ for (int i = 0 ; i < b .length - 1 ; i ++) {
218+ if (b [i ] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRrXx" .indexOf (b [i + 1 ]) > -1 ) {
219+ b [i ] = ColorCode .COLOR_CHAR ;
220+ b [i + 1 ] = Character .toLowerCase (b [i + 1 ]);
221+ }
222+ }
223+ return new String (b );
224+ }
225+
226+ @ Override
227+ public String toString () {
228+ return toString ;
229+ }
230+
184231 static {
185232 for (ColorCode color : values ()) {
186233 BY_CHAR .put (color .code , color );
0 commit comments