Skip to content

Commit 383cae5

Browse files
committed
Improve with custom color codes
Allow you set your own color codes for the map colors.
1 parent a9b2195 commit 383cae5

File tree

6 files changed

+139
-24
lines changed

6 files changed

+139
-24
lines changed

Item Creator/src/main/java/org/broken/arrow/library/itemcreator/meta/map/MapRendererData.java

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package org.broken.arrow.library.itemcreator.meta.map;
22

33
import org.broken.arrow.library.itemcreator.ItemCreator;
4+
import org.broken.arrow.library.itemcreator.meta.map.color.parser.AmpersandHexColorParser;
5+
import org.broken.arrow.library.itemcreator.meta.map.color.parser.ColorParser;
46
import org.broken.arrow.library.itemcreator.meta.map.cursor.MapCursorAdapter;
57
import org.broken.arrow.library.itemcreator.meta.map.cursor.MapCursorWrapper;
6-
import org.broken.arrow.library.itemcreator.meta.map.font.CharacterSprite;
7-
import org.broken.arrow.library.itemcreator.meta.map.font.MapFontWrapper;
88
import org.broken.arrow.library.itemcreator.meta.map.font.customdraw.MapTextRenderer;
9+
import org.broken.arrow.library.itemcreator.meta.map.font.customdraw.RenderState;
910
import org.broken.arrow.library.itemcreator.meta.map.pixel.ImageOverlay;
1011
import org.broken.arrow.library.itemcreator.meta.map.pixel.MapPixel;
1112
import org.broken.arrow.library.itemcreator.meta.map.pixel.MapColoredPixel;
@@ -44,6 +45,7 @@ public class MapRendererData {
4445
private final List<MapPixel> pixels = new ArrayList<>();
4546
private MapRenderHandler dynamicRenderer;
4647
private char[] fontChars = Characters.getFontCharsArray();
48+
private ColorParser colorParser = new AmpersandHexColorParser();
4749

4850
/**
4951
* Constructs a new MapRendererData instance with no associated {@link MapRenderer}.
@@ -146,6 +148,33 @@ public void addText(@Nonnull final TextOverlay textOverlay) {
146148
pixels.add(textOverlay);
147149
}
148150

151+
/**
152+
* Applies the global {@link ColorParser} to the text at the specified index.
153+
* <p>
154+
* This works like the per-text parser, but uses the global parser set for all text
155+
* instances that do not have a per-instance override.
156+
*
157+
* @see org.broken.arrow.library.itemcreator.meta.map.font.MapFontWrapper#applyColorParser(String, int, RenderState)
158+
* @param text the text to parse
159+
* @param index the starting position in the text
160+
* @param renderState the current render state to update with color/style
161+
* @return the number of characters consumed by the formatting code, or 0 if none
162+
*/
163+
public int applyGlobalColorParser(@Nonnull final String text, final int index, @Nonnull final RenderState renderState) {
164+
return colorParser.tryParse(text, index, renderState);
165+
}
166+
167+
/**
168+
* Sets the global {@link ColorParser} used for all text instances that do not
169+
* have a per-text parser set.
170+
*
171+
* @see org.broken.arrow.library.itemcreator.meta.map.font.MapFontWrapper#applyColorParser(String, int, RenderState)
172+
* @param colorParser the global color parser to use
173+
*/
174+
public void setGlobalColorParser(@Nonnull final ColorParser colorParser) {
175+
this.colorParser = colorParser;
176+
}
177+
149178
/**
150179
* Adds an image overlay to the map at the specified coordinates.
151180
*
@@ -343,9 +372,8 @@ private void setPixels(@Nonnull final MapCanvas canvas) {
343372
if (mapFont instanceof MinecraftFont)
344373
canvas.drawText(mapPixel.getX(), mapPixel.getY(), mapFont, textOverlay.getText());
345374
else {
346-
MapTextRenderer mapTextRenderer = new MapTextRenderer(canvas, textOverlay.getMapFontWrapper(), textOverlay.getText());
375+
final MapTextRenderer mapTextRenderer = new MapTextRenderer(canvas, this, textOverlay);
347376
mapTextRenderer.drawCustomFontText(mapPixel.getX(), mapPixel.getY());
348-
// drawCustomFontText(canvas, mapPixel.getX(), mapPixel.getY(), textOverlay.getText(), textOverlay.getMapFontWrapper());
349377
}
350378
}
351379
if (mapPixel instanceof ImageOverlay) {

Item Creator/src/main/java/org/broken/arrow/library/itemcreator/meta/map/color/parser/AmpersandHexColorParser.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.broken.arrow.library.itemcreator.meta.map.color.parser;
22

3-
import org.broken.arrow.library.itemcreator.meta.map.font.customdraw.MapTextRenderer;
43
import org.broken.arrow.library.itemcreator.meta.map.font.customdraw.RenderState;
54

65
import javax.annotation.Nonnull;
@@ -18,7 +17,7 @@ public final class AmpersandHexColorParser implements ColorParser {
1817
* @return how many characters were consumed (0 = not a formatting code)
1918
*/
2019
@Override
21-
public int tryParse(String text, int i, RenderState state) {
20+
public int tryParse(@Nonnull String text, int i, @Nonnull RenderState state) {
2221
if (i + 1 >= text.length())
2322
return 0;
2423

Item Creator/src/main/java/org/broken/arrow/library/itemcreator/meta/map/color/parser/ColorParser.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@
22

33
import org.broken.arrow.library.itemcreator.meta.map.font.customdraw.RenderState;
44

5+
import javax.annotation.Nonnull;
6+
7+
/**
8+
* Handle the colors from a text and provide the length of your color code
9+
* to ignore when create the text.
10+
*/
11+
@FunctionalInterface
512
public interface ColorParser {
613
/**
714
* @param text Full user input
815
* @param i Current index
916
* @param renderState Modify if parsed successfully
1017
* @return number of characters consumed (0 = not parsed)
1118
*/
12-
int tryParse(String text, int i, RenderState renderState);
19+
int tryParse(@Nonnull final String text, final int i,@Nonnull final RenderState renderState);
1320
}
1421

1522

Item Creator/src/main/java/org/broken/arrow/library/itemcreator/meta/map/font/MapFontWrapper.java

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package org.broken.arrow.library.itemcreator.meta.map.font;
22

33
import net.md_5.bungee.api.ChatColor;
4+
import org.broken.arrow.library.itemcreator.meta.map.color.parser.AmpersandHexColorParser;
5+
import org.broken.arrow.library.itemcreator.meta.map.color.parser.ColorParser;
6+
import org.broken.arrow.library.itemcreator.meta.map.font.customdraw.RenderState;
47
import org.bukkit.map.MapFont;
58
import org.bukkit.map.MinecraftFont;
69

@@ -25,11 +28,10 @@
2528
* character sprites can be added.
2629
*/
2730
public class MapFontWrapper {
28-
29-
3031
private final Map<Character, CharacterSprite> chars = new HashMap<>();
3132
private int height = 0;
3233
private IntUnaryOperator defaultFontSpacing = (charter) -> 8;
34+
private ColorParser colorParser;
3335

3436
/**
3537
* just a check if the front is malleable
@@ -109,6 +111,61 @@ public int applyDefaultFontSpacing(char ch) {
109111
return defaultFontSpacing.applyAsInt(ch);
110112
}
111113

114+
/**
115+
* Applies the current {@link ColorParser} to the text at the specified index.
116+
* <p>
117+
* The parser will attempt to detect a formatting sequence (such as Minecraft-style
118+
* codes or custom hex codes—the default implementation) starting at {@code index}
119+
* and update the {@link RenderState} with the corresponding color and/or style.
120+
* <p>
121+
* By default, the following codes are supported:
122+
* <ul>
123+
* <li>{@code &0 - &f}: standard color codes</li>
124+
* <li>{@code &#fff}: 3-digit hex color</li>
125+
* <li>{@code &#ffffff}: 6-digit hex color</li>
126+
* <li>{@code &l}: bold text</li>
127+
* <li>{@code &o}: shadow effect</li>
128+
* <li>{@code &r}: reset color and styles</li>
129+
* </ul>
130+
* <p>
131+
* See {@link RenderState#applyFormattingCode(char)} and
132+
* {@link RenderState#translateChatColor(char)} for details on the default parser's behavior.
133+
* <p>
134+
* You can also provide a custom {@link ColorParser} to define alternative parsing logic
135+
* or support additional formatting sequences.
136+
* <p>
137+
* This method returns the number of characters consumed by the formatting sequence,
138+
* allowing the caller to advance the cursor appropriately. If no sequence is found,
139+
* it returns 0. If no parser is set, it returns -1.
140+
* <p>
141+
* <strong>Note:</strong> This method is intended for internal use by the API and
142+
* usually does not need to be invoked directly.
143+
*
144+
* @param text the text to parse
145+
* @param index the starting position in the text
146+
* @param renderState the current render state to update with color/style
147+
* @return the number of characters consumed by the formatting code, 0 if none found, or -1 if no parser is set
148+
*/
149+
public int applyColorParser(@Nonnull final String text, final int index,@Nonnull final RenderState renderState) {
150+
if(colorParser == null)
151+
return -1;
152+
return colorParser.tryParse( text, index, renderState);
153+
}
154+
155+
/**
156+
* Sets the {@link ColorParser} used to interpret color and style codes
157+
* in this text instance.
158+
* <p>
159+
* By default, the API uses the global parser from {@link MapFontWrapper} (typically
160+
* {@link AmpersandHexColorParser}). This method allows overriding it for this
161+
* specific text, including using lambda-based or custom parser implementations.
162+
*
163+
* @param colorParser the color parser to use for this text
164+
*/
165+
public void setColorParser(@Nonnull final ColorParser colorParser) {
166+
this.colorParser = colorParser;
167+
}
168+
112169
/**
113170
* Sets the default spacing function for characters.
114171
* <p>

Item Creator/src/main/java/org/broken/arrow/library/itemcreator/meta/map/font/customdraw/MapTextRenderer.java

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
package org.broken.arrow.library.itemcreator.meta.map.font.customdraw;
22

33
import org.broken.arrow.library.itemcreator.ItemCreator;
4-
import org.broken.arrow.library.itemcreator.meta.map.color.parser.AmpersandHexColorParser;
5-
import org.broken.arrow.library.itemcreator.meta.map.color.parser.ColorParser;
4+
import org.broken.arrow.library.itemcreator.meta.map.MapRendererData;
65
import org.broken.arrow.library.itemcreator.meta.map.font.CharacterSprite;
76
import org.broken.arrow.library.itemcreator.meta.map.font.MapFontWrapper;
7+
import org.broken.arrow.library.itemcreator.meta.map.pixel.TextOverlay;
88
import org.bukkit.map.MapCanvas;
99
import org.bukkit.map.MapPalette;
1010

11+
import javax.annotation.Nonnull;
1112
import java.awt.*;
1213

13-
1414
/**
1515
* Responsible for rendering text using a custom pixel-based {@link MapFontWrapper} onto a {@link MapCanvas}.
1616
* <p>
@@ -27,23 +27,27 @@
2727
* Each visible pixel is drawn directly into the map canvas at the computed coordinate.
2828
*/
2929
public class MapTextRenderer {
30+
private final MapRendererData mapRendererData;
3031
private final MapCanvas canvas;
3132
private final MapFontWrapper font;
3233
private final String text;
3334

35+
3436
/**
3537
* Creates a new custom font renderer.
3638
*
37-
* @param canvas the target map canvas to draw on
38-
* @param font the custom font wrapper providing character sprites and spacing rules
39-
* @param text the raw input text containing characters and formatting codes
39+
* @param canvas the target map canvas to draw on
40+
* @param mapRendererData the rendered data instance with your global settings.
41+
* @param textOverlay the custom text overlay wrapper providing character sprites and spacing rules
4042
*/
41-
public MapTextRenderer(final MapCanvas canvas, final MapFontWrapper font, final String text) {
43+
public MapTextRenderer(@Nonnull final MapCanvas canvas, @Nonnull final MapRendererData mapRendererData, @Nonnull final TextOverlay textOverlay) {
4244
this.canvas = canvas;
43-
this.font = font;
44-
this.text = text;
45+
this.mapRendererData = mapRendererData;
46+
this.font = textOverlay.getMapFontWrapper();
47+
this.text = textOverlay.getText();
4548
}
4649

50+
4751
/**
4852
* Draws the configured text to the map canvas starting at the given coordinate.
4953
* <p>
@@ -67,8 +71,11 @@ public void drawCustomFontText(int x, int y) {
6771
for (int i = 0; i < text.length(); i++) {
6872
char ch = text.charAt(i);
6973

70-
ColorParser parser = new AmpersandHexColorParser();
71-
int consumed = parser.tryParse(text, i, renderState);
74+
int consumed;
75+
consumed = this.font.applyColorParser(text, i, renderState);
76+
if (consumed <= 0)
77+
consumed = this.mapRendererData.applyGlobalColorParser(text, i, renderState);
78+
7279
if (consumed > 0) {
7380
i += consumed - 1;
7481
continue;
@@ -98,7 +105,6 @@ public void drawCustomFontText(int x, int y) {
98105
}
99106

100107

101-
102108
/**
103109
* Draws all visible pixels of a sprite at an offset.
104110
* Any pixel in the sprite marked as {@code true} is drawn to the final canvas.
@@ -129,9 +135,9 @@ private void drawPixelsOffset(CharacterSprite sprite, int startX, int startY, Co
129135
* older versions use {@link MapPalette#matchColor(Color)}.
130136
*
131137
* @param canvas the target map canvas to draw on
132-
* @param x location where draw in digonal direction.
133-
* @param y location where draw in vertical direction.
134-
* @param color the color to set for the pixel
138+
* @param x location where draw in digonal direction.
139+
* @param y location where draw in vertical direction.
140+
* @param color the color to set for the pixel
135141
*/
136142
private void setMapPixel(MapCanvas canvas, int x, int y, Color color) {
137143
if (ItemCreator.getServerVersion() < 20.0F) {

Item Creator/src/main/java/org/broken/arrow/library/itemcreator/meta/map/pixel/TextOverlay.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package org.broken.arrow.library.itemcreator.meta.map.pixel;
22

3+
import org.broken.arrow.library.itemcreator.meta.map.color.parser.AmpersandHexColorParser;
4+
import org.broken.arrow.library.itemcreator.meta.map.color.parser.ColorParser;
35
import org.broken.arrow.library.itemcreator.meta.map.font.CharacterSprite;
46
import org.broken.arrow.library.itemcreator.meta.map.font.MapFontWrapper;
7+
import org.broken.arrow.library.itemcreator.meta.map.font.customdraw.RenderState;
58

69
import javax.annotation.Nonnull;
710
import java.awt.*;
@@ -65,6 +68,21 @@ public void setMapFont(final char[] chars, @Nonnull final Font font) {
6568
}
6669
}
6770

71+
/**
72+
* Sets the {@link ColorParser} used for interpreting color and style codes
73+
* in the text.
74+
* <p>
75+
* The parser is responsible for detecting formatting sequences and updating
76+
* the {@link RenderState} accordingly. By default, the API uses
77+
* {@link AmpersandHexColorParser}, but this method allows you to replace it
78+
* with a custom implementation, including lambda-based parsers.
79+
*
80+
* @param colorParser the color parser to use
81+
*/
82+
public void setColorParser(@Nonnull final ColorParser colorParser) {
83+
mapFontWrapper.setColorParser(colorParser);
84+
}
85+
6886

6987
/**
7088
* Gets the {@link org.bukkit.map.MapFont} used to render this text overlay.

0 commit comments

Comments
 (0)