Skip to content

Commit 3d1953f

Browse files
committed
Implemented cache for the map item custom render
This will make images or text fast to load when is pre-loaded and also when the itemstack is created and also adding tread-safe option to update the image or text.
1 parent 8d3df80 commit 3d1953f

File tree

5 files changed

+324
-25
lines changed

5 files changed

+324
-25
lines changed

Item Creator/src/main/java/org/broken/arrow/library/itemcreator/ItemCreator.java

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.broken.arrow.library.itemcreator.utility.ConvertToItemStack;
66
import org.broken.arrow.library.itemcreator.utility.ServerVersion;
77
import org.broken.arrow.library.itemcreator.utility.builders.ItemBuilder;
8+
import org.broken.arrow.library.logging.Logging;
89
import org.broken.arrow.library.logging.Validate;
910
import org.broken.arrow.library.logging.Validate.ValidateExceptions;
1011
import org.broken.arrow.library.nbt.RegisterNbtAPI;
@@ -28,11 +29,11 @@
2829
* Supports setting display names, lore, NBT data, and color translation.
2930
*/
3031
public class ItemCreator {
31-
32+
private static final Logging log = new Logging(ItemCreator.class);
3233
private static ServerVersion serverVersion;
34+
private static Plugin plugin;
3335
private final NBTManger nbtManger;
3436
private final ConvertToItemStack convertItems;
35-
private final Plugin plugin;
3637
private boolean haveTextTranslator = true;
3738
private boolean enableColorTranslation = true;
3839

@@ -56,13 +57,13 @@ public ItemCreator(final Plugin plugin) {
5657
/**
5758
* Constructs an ItemCreator instance associated with the given plugin.
5859
*
59-
* @param plugin the plugin instance
60-
* @param turnOffLogger whether to disable logging for NBT manager
60+
* @param pluginInstance the plugin instance
61+
* @param turnOffLogger whether to disable logging for NBT manager
6162
*/
62-
public ItemCreator(final Plugin plugin, boolean turnOffLogger) {
63-
this.plugin = plugin;
64-
this.nbtManger = new NBTManger(plugin, turnOffLogger);
65-
setServerVersion(plugin);
63+
public ItemCreator(final Plugin pluginInstance, boolean turnOffLogger) {
64+
this.setPlugin(pluginInstance);
65+
this.nbtManger = new NBTManger(pluginInstance, turnOffLogger);
66+
setServerVersion(pluginInstance);
6667

6768
this.convertItems = new ConvertToItemStack(serverVersion.getServerVersion());
6869

@@ -440,4 +441,32 @@ private static Enchantment getEnchantment(@Nullable final NamespacedKey key, @Nu
440441
return enchantment == null ? Enchantment.VANISHING_CURSE : enchantment;
441442
}
442443

444+
/**
445+
* Executes the given runnable safely, falling back to direct execution if
446+
* Bukkit or the plugin instance is not available.
447+
*
448+
* @param runnable the task to run
449+
*/
450+
public static void runSync(@Nonnull final Runnable runnable) {
451+
try {
452+
Plugin plugin = ItemCreator.plugin;
453+
if (plugin == null || !plugin.isEnabled()) {
454+
runnable.run();
455+
return;
456+
}
457+
Bukkit.getScheduler().runTask(plugin, runnable);
458+
} catch (NoClassDefFoundError | ExceptionInInitializerError ex) {
459+
runnable.run();
460+
} catch (Throwable t) {
461+
if (t instanceof NullPointerException || t instanceof IllegalStateException) {
462+
throw t;
463+
}
464+
log.logError(t, () -> "Failed to execute scheduled task safely. The runnable crashed.");
465+
}
466+
}
467+
468+
private void setPlugin(final Plugin pluginInstance) {
469+
plugin = pluginInstance;
470+
}
471+
443472
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,14 @@ public MapRendererData addRenderer(@Nonnull final Consumer<MapRendererData> data
193193
return mapRenderer;
194194
}
195195

196+
/**
197+
* Add your cached image data.
198+
*
199+
* @param cache the cache to get the image.
200+
*/
201+
public void addAllCachedRenderers(@Nonnull MapRendererDataCache cache) {
202+
this.renderers.addAll(cache.getAllRendererData());
203+
}
196204
/**
197205
* Adds a map list of renderer instance's.
198206
*

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

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import org.broken.arrow.library.itemcreator.meta.map.color.parser.ColorParser;
66
import org.broken.arrow.library.itemcreator.meta.map.cursor.MapCursorAdapter;
77
import org.broken.arrow.library.itemcreator.meta.map.cursor.MapCursorWrapper;
8-
import org.broken.arrow.library.itemcreator.meta.map.font.customdraw.MapTextRenderer;
98
import org.broken.arrow.library.itemcreator.meta.map.font.customdraw.RenderState;
109
import org.broken.arrow.library.itemcreator.meta.map.pixel.ImageOverlay;
1110
import org.broken.arrow.library.itemcreator.meta.map.pixel.MapPixel;
@@ -22,6 +21,7 @@
2221
import java.util.List;
2322
import java.util.Map;
2423
import java.util.Objects;
24+
import java.util.function.Supplier;
2525
import java.util.stream.Collectors;
2626

2727
/**
@@ -41,11 +41,14 @@ public class MapRendererData {
4141
private static int id;
4242
private final int mapRenderId;
4343
private final MapRenderer mapRenderer;
44-
private MapCursorAdapter mapCursors = new MapCursorAdapter();
4544
private final List<MapPixel> pixels = new ArrayList<>();
45+
private MapCursorAdapter mapCursors = new MapCursorAdapter();
46+
4647
private MapRenderHandler dynamicRenderer;
48+
4749
private char[] fontChars = Characters.getFontCharsArray();
4850
private ColorParser colorParser = new AmpersandHexColorParser();
51+
private boolean contextual;
4952

5053
/**
5154
* Constructs a new MapRendererData instance with no associated {@link MapRenderer}.
@@ -75,6 +78,7 @@ public void setDynamicRenderer(MapRenderHandler handler) {
7578
this.dynamicRenderer = handler;
7679
}
7780

81+
7882
/**
7983
* Adds a colored pixel overlay to the map at the specified coordinates.
8084
*
@@ -103,7 +107,7 @@ public void addPixel(@Nonnull final MapColoredPixel mapColoredPixel) {
103107
* @param text The text to display.
104108
* @return returns the newly created text overlay, so you could set some of the options after.
105109
*/
106-
public TextOverlay addText(final int x, int y, final String text) {
110+
public TextOverlay addText(final int x, int y,@Nonnull final String text) {
107111
return this.addText(x, y, text, null, null);
108112
}
109113

@@ -117,7 +121,7 @@ public TextOverlay addText(final int x, int y, final String text) {
117121
* @param font The font for the character.
118122
* @return returns the newly created text overlay, so you could set some of the options after.
119123
*/
120-
public TextOverlay addText(final int x, int y, final String text, @Nullable final Font font) {
124+
public TextOverlay addText(final int x, int y,@Nonnull final String text, @Nullable final Font font) {
121125
return this.addText(x, y, text, null, font);
122126
}
123127

@@ -240,6 +244,52 @@ public MapCursorWrapper addCursor(@Nonnull final MapCursorWrapper cursorWrapper)
240244
return cursorWrapper;
241245
}
242246

247+
/**
248+
* Adds a collection of map overlays (pixels, text, or images) to this renderer.
249+
* <p>
250+
* This method appends the provided overlays to the existing pixel list
251+
* without clearing previous entries. It can be used to add multiple
252+
* overlay types at once or to batch-apply preprocessed render data.
253+
* </p>
254+
*
255+
* <p><strong>Note:</strong> For most use cases, prefer the more specific
256+
* methods such as {@link #addPixel(int, int, Color)},{@link #addText(int, int, String)}
257+
* or {@link #addImage(int, int, Image)} for clarity.</p>
258+
*
259+
* @param mapPixels the list of {@link MapPixel} instances to add
260+
*/
261+
public void addAll(List<MapPixel> mapPixels) {
262+
this.pixels.addAll(mapPixels);
263+
}
264+
265+
/**
266+
* Clear the list of set pixels.
267+
*/
268+
public void clear() {
269+
this.pixels.clear();
270+
}
271+
272+
/**
273+
* Set whether the renderer is contextual, i.e. has different canvases for
274+
* different players.
275+
*
276+
* @param contextual Whether the renderer is contextual. See {@link
277+
* #isContextual()}.
278+
*/
279+
public void setContextual(boolean contextual) {
280+
this.contextual = contextual;
281+
}
282+
283+
/**
284+
* Get whether the renderer is contextual, i.e. has different canvases for
285+
* different players.
286+
*
287+
* @return True if contextual, false otherwise.
288+
*/
289+
public final boolean isContextual() {
290+
return contextual;
291+
}
292+
243293
/**
244294
* Returns the unique ID assigned to this map renderer data instance.
245295
*
@@ -277,20 +327,20 @@ public MapRenderer getMapRenderer() {
277327
if (this.mapRenderer != null) {
278328
return mapRenderer;
279329
}
280-
return new MapRenderer() {
330+
return new MapRenderer(this.contextual) {
281331
@Override
282332
public void render(@Nonnull MapView map, @Nonnull MapCanvas canvas, @Nonnull Player player) {
283333
if (dynamicRenderer != null && dynamicRenderer.render(map, canvas, player))
284334
return;
285335
canvas.setCursors(mapCursors.getMapCursorCollection());
336+
286337
if (!getPixels().isEmpty()) {
287338
setPixels(canvas);
288339
}
289340
}
290341
};
291342
}
292343

293-
294344
@Override
295345
public boolean equals(Object o) {
296346
if (o == null || getClass() != o.getClass()) return false;
@@ -365,4 +415,5 @@ private void setPixels(@Nonnull final MapCanvas canvas) {
365415
getPixels().forEach(mapPixel -> mapPixel.render(this, canvas));
366416
}
367417

418+
368419
}

0 commit comments

Comments
 (0)