When you want to use Color in a Text on a map, you must add the corresponding bytecode (a number from -127 to 128) (see MapPalette) into the string, between a section sign (§) and a semicolon (.
When displaying the text on a map, the section sign, the byte and the semicolon do not get displayed, but instead change the color of the text following it. You can see the implementation of this in CraftMapCanvas#drawText
For example "$-49;This is black. §34;And this is white", will result in "This is black. And this is white".
However when using MapFont#getWidth, only the § is properly ignored, but the byte and semicolon after it aren't.
You can clearly see this in the code:
for (int i = 0; i < text.length(); ++i) { char ch = text.charAt(i); if (ch == ChatColor.COLOR_CHAR) continue; //Here result += chars.get(ch).getWidth(); }
As you can see, when the char equals $, the width calculation of that char gets skipped. But only that, and not the numbers and semicolon following it. In the example above, the width of "-49;" and "34;" would still get added to the result, althought these chars are not getting displayed on the map.
Therefore you end up with a wrong width, when using colors in your text.
Should be fairly easy to fix, for example using:
public int getWidth(String text) { if (!isValid(text)) { throw new IllegalArgumentException("text contains invalid characters"); } if (text.length() == 0) { return 0; } int result = 0; int ignored = 0; for (int i = 0; i < text.length(); ++i) { char ch = text.charAt(i); if (ch == ChatColor.COLOR_CHAR) { int j = text.indexOf(';', i); if (j < 0) throw new IllegalArgumentException("Text contains unterminated color string"); ignored += j-i+1; i = j; continue; } result += chars.get(ch).getWidth(); } result += text.length() - ignored - 1; // Account for 1px spacing between characters, but ignore color-setting characters return result; }