diff --git a/src/main/java/de/oliver/fancynpcs/FancyNpcs.java b/src/main/java/de/oliver/fancynpcs/FancyNpcs.java index c4891992..c4d85144 100644 --- a/src/main/java/de/oliver/fancynpcs/FancyNpcs.java +++ b/src/main/java/de/oliver/fancynpcs/FancyNpcs.java @@ -107,7 +107,7 @@ public FancyNpcs() { } } JsonAppender jsonAppender = new JsonAppender(false, false, true, logsFile.getPath()); - this.fancyLogger = new ExtendedFancyLogger("FancyNpcs", LogLevel.INFO, List.of(consoleAppender, jsonAppender), new ArrayList<>()); + this.fancyLogger = new ExtendedFancyLogger("FancyNpcs", LogLevel.DEBUG, List.of(consoleAppender, jsonAppender), new ArrayList<>()); this.npcThread = Executors.newSingleThreadScheduledExecutor( new ThreadFactoryBuilder() diff --git a/src/main/java/de/oliver/fancynpcs/skins/MineSkinQueue.java b/src/main/java/de/oliver/fancynpcs/skins/MineSkinQueue.java new file mode 100644 index 00000000..ac531a79 --- /dev/null +++ b/src/main/java/de/oliver/fancynpcs/skins/MineSkinQueue.java @@ -0,0 +1,57 @@ +package de.oliver.fancynpcs.skins; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +import java.util.LinkedList; +import java.util.Queue; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class MineSkinQueue { + + private final static ScheduledExecutorService EXECUTOR = Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder() + .setNameFormat("MineSkinQueue") + .build()); + private static MineSkinQueue INSTANCE; + private final Queue queue; + + private MineSkinQueue() { + this.queue = new LinkedList<>(); + + run(); + } + + public static MineSkinQueue get() { + if (INSTANCE == null) { + INSTANCE = new MineSkinQueue(); + } + + return INSTANCE; + } + + public void add(Runnable runnable) { + this.queue.add(runnable); + } + + private void run() { + EXECUTOR.scheduleAtFixedRate(this::poll, 5, 60, TimeUnit.SECONDS); + } + + private void poll() { + System.out.println("Polling queue"); + if (this.queue.isEmpty()) { + return; + } + + System.out.println("Running runnables"); + int counter = 0; + while (!this.queue.isEmpty() && counter < 9) { + Runnable runnable = this.queue.poll(); + if (runnable != null) { + runnable.run(); + } + counter++; + } + } +} diff --git a/src/main/java/de/oliver/fancynpcs/skins/SkinManagerImpl.java b/src/main/java/de/oliver/fancynpcs/skins/SkinManagerImpl.java index fcb44fab..b8be93c7 100644 --- a/src/main/java/de/oliver/fancynpcs/skins/SkinManagerImpl.java +++ b/src/main/java/de/oliver/fancynpcs/skins/SkinManagerImpl.java @@ -38,7 +38,7 @@ public class SkinManagerImpl implements SkinManager { private final SkinCache memCache; public SkinManagerImpl(SkinCache fileCache, SkinCache memCache) { - this.executor = Executors.newScheduledThreadPool(2, new ThreadFactoryBuilder() + this.executor = Executors.newScheduledThreadPool(5, new ThreadFactoryBuilder() .setNameFormat("FancyNpcs-Skins") .build()); @@ -244,11 +244,21 @@ private SkinInfo executeRequest(GenerateRequest req) { // submit job to the queue CompletableFuture queueResp = client.queue().submit(req); + queueResp.exceptionally(throwable -> { + FancyNpcs.getInstance().getFancyLogger().error("Could not submit job to MineSkin queue: " + throwable.getMessage()); + return null; + }); + // wait for job completion CompletableFuture jobResp = queueResp.thenCompose( queueResponse -> queueResponse.getJob().waitForCompletion(client) ); + jobResp.exceptionally(throwable -> { + FancyNpcs.getInstance().getFancyLogger().error("Could not wait for job completion: " + throwable.getMessage()); + return null; + }); + // get skin from job or load it from the API CompletableFuture skinResp = jobResp.thenCompose( jobResponse -> jobResponse.getOrLoadSkin(client) @@ -275,11 +285,17 @@ private SkinInfo executeRequest(GenerateRequest req) { return null; }); - return skinResp.join(); + try { + SkinInfo skinInfo = skinResp.join(); + return skinInfo; + } catch (Exception e) { + System.out.println("Error in mineskin req: " + e.getMessage()); + return null; + } } private SkinData tryToGetFromCache(String identifier, SkinData.SkinVariant variant) { - FancyNpcs.getInstance().getFancyLogger().debug("Trying to get skin from mem cache: " + identifier); +// FancyNpcs.getInstance().getFancyLogger().debug("Trying to get skin from mem cache: " + identifier); SkinCacheData data = memCache.getSkin(identifier); if (data != null) { @@ -290,7 +306,7 @@ private SkinData tryToGetFromCache(String identifier, SkinData.SkinVariant varia return data.skinData(); } - FancyNpcs.getInstance().getFancyLogger().debug("Trying to get skin from file cache: " + identifier); +// FancyNpcs.getInstance().getFancyLogger().debug("Trying to get skin from file cache: " + identifier); data = fileCache.getSkin(identifier); if (data != null) { diff --git a/src/main/java/de/oliver/fancynpcs/skins/SkinUtils.java b/src/main/java/de/oliver/fancynpcs/skins/SkinUtils.java index 75d38259..489e1161 100644 --- a/src/main/java/de/oliver/fancynpcs/skins/SkinUtils.java +++ b/src/main/java/de/oliver/fancynpcs/skins/SkinUtils.java @@ -23,7 +23,7 @@ public static boolean isFile(String identifier) { } public static void applySkinLater(String npcID, String skinID, SkinData.SkinVariant variant, Runnable successCallback, Runnable errorCallback) { - FancyNpcs.getInstance().getSkinManagerImpl().getExecutor().submit(() -> { + MineSkinQueue.get().add(() -> { FancyNpcs.getInstance().getFancyLogger().debug("Loading skin for npc '" + npcID + "'. Skin: " + skinID + ", Variant: " + variant); SkinData skin = FancyNpcs.getInstance().getSkinManagerImpl().getByIdentifier(skinID, variant); @@ -49,6 +49,7 @@ public static void applySkinLater(String npcID, String skinID, SkinData.SkinVari FancyNpcs.getInstance().getFancyLogger().debug("Successfully applied skin for npc '" + npcID + "'"); successCallback.run(); }); + System.out.println("Added skin to queue"); } public static void applySkinLater(String npcID, String skinID, SkinData.SkinVariant variant) { diff --git a/src/main/resources/languages/default.yml b/src/main/resources/languages/default.yml index 8b98a40c..b2a9631e 100644 --- a/src/main/resources/languages/default.yml +++ b/src/main/resources/languages/default.yml @@ -115,7 +115,7 @@ messages: npc_nearby: "Syntax: {primaryColor}/npc nearby {secondaryColor}[filters...]" npc_remove: "Syntax: {primaryColor}/npc remove {secondaryColor}(npc)" npc_show_in_tab: "Syntax: {primaryColor}/npc show_in_tab {secondaryColor}(npc) (state)" - npc_skin: "Syntax: {primaryColor}/npc skin {secondaryColor}(npc) (@none | @mirror | name | url) [--slim]" + npc_skin: "Syntax: {primaryColor}/npc skin {secondaryColor}(npc) (@none | @mirror | name | uuid | placeholder | url | file name) [--slim]" npc_teleport: "Syntax: {primaryColor}/npc teleport {secondaryColor}(npc)" npc_turn_to_player: "Syntax: {primaryColor}/npc turn_to_player {secondaryColor}(npc) (state)" npc_type: "Syntax: {primaryColor}/npc type {secondaryColor}(npc) (type)" @@ -292,7 +292,6 @@ messages: npc_skin_set: "NPC {warningColor}{npc} is now using the {warningColor}{name} skin." npc_skin_set_mirror: "NPC {warningColor}{npc} is now mirroring player skin." npc_skin_set_none: "NPC {warningColor}{npc} is no longer using any skin." - npc_skin_failure_invalid: "› {errorColor}Argument {warningColor}{input}{errorColor} is invalid. Common issues: invalid URL, player not found, player has no skin." # Commands (npc teleport) npc_teleport_success: "You have been teleported to NPC {warningColor}{npc}."