From 4e06a3b0ff9389ef75ee4e407ce4262e1b050ffc Mon Sep 17 00:00:00 2001 From: Roman / Nea Date: Sat, 18 Dec 2021 12:27:12 +0100 Subject: Load wiki pages asynchronously. (#30) Previous to this commit, wiki pages would be downloaded on the main rendering thread, preventing all rendering and user interaction while the download was occuring. This has now been shifted to the common forkpool provided by the JVM. --- .../moulberry/notenoughupdates/NEUManager.java | 49 ++++++++++++---------- .../moulberry/notenoughupdates/NEUOverlay.java | 34 +++++++-------- .../notenoughupdates/infopanes/HTMLInfoPane.java | 37 ++++++++-------- .../notenoughupdates/infopanes/InfoPane.java | 18 ++++++++ 4 files changed, 79 insertions(+), 59 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 01e97c75..b129f133 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -29,6 +29,7 @@ import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.zip.ZipEntry; @@ -1024,32 +1025,34 @@ public class NEUManager { /** * Downloads a web file, appending some HTML attributes that makes wikia give us the raw wiki syntax. */ - public File getWebFile(String url) { - File f = new File(configLocation, "tmp/" + Base64.getEncoder().encodeToString(url.getBytes()) + ".html"); - if (f.exists()) { - return f; - } + public CompletableFuture getWebFile(String url) { + return CompletableFuture.supplyAsync(() -> { + File f = new File(configLocation, "tmp/" + Base64.getEncoder().encodeToString(url.getBytes()) + ".html"); + if (f.exists()) { + return f; + } - try { - f.getParentFile().mkdirs(); - f.createNewFile(); - f.deleteOnExit(); - } catch (IOException e) { - return null; - } - try (BufferedInputStream inStream = new BufferedInputStream(new URL(url + "?action=raw&templates=expand").openStream()); - FileOutputStream fileOutputStream = new FileOutputStream(f)) { - byte[] dataBuffer = new byte[1024]; - int bytesRead; - while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) { - fileOutputStream.write(dataBuffer, 0, bytesRead); + try { + f.getParentFile().mkdirs(); + f.createNewFile(); + f.deleteOnExit(); + } catch (IOException e) { + return null; + } + try (BufferedInputStream inStream = new BufferedInputStream(new URL(url + "?action=raw&templates=expand").openStream()); + FileOutputStream fileOutputStream = new FileOutputStream(f)) { + byte[] dataBuffer = new byte[1024]; + int bytesRead; + while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) { + fileOutputStream.write(dataBuffer, 0, bytesRead); + } + } catch (IOException e) { + e.printStackTrace(); + return null; } - } catch (IOException e) { - e.printStackTrace(); - return null; - } - return f; + return f; + }); } /** diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index d943d135..2b518fec 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -9,7 +9,6 @@ import io.github.moulberry.notenoughupdates.core.BackgroundBlur; import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper; import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingInteger; import io.github.moulberry.notenoughupdates.infopanes.DevInfoPane; -import io.github.moulberry.notenoughupdates.infopanes.HTMLInfoPane; import io.github.moulberry.notenoughupdates.infopanes.InfoPane; import io.github.moulberry.notenoughupdates.infopanes.TextInfoPane; import io.github.moulberry.notenoughupdates.itemeditor.NEUItemEditor; @@ -50,7 +49,6 @@ import net.minecraft.util.Matrix4f; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.client.ClientCommandHandler; -import org.apache.commons.lang3.StringUtils; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; @@ -61,6 +59,7 @@ import java.awt.*; import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.*; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; @@ -159,6 +158,8 @@ public class NEUOverlay extends Gui { private int lastScreenHeight; private int lastScale; + private CompletableFuture infoPaneLoadingJob = CompletableFuture.completedFuture(null); + private List textToDisplay = null; public MBGuiGroupFloating guiGroup = null; @@ -628,6 +629,7 @@ public class NEUOverlay extends Gui { searchBarHasFocus = false; if (!(searchMode || (NotEnoughUpdates.INSTANCE.config.itemlist.keepopen && itemPaneOpen))) { itemPaneOpen = false; + displayInformationPane(null); itemPaneOffsetFactor.setValue(1); itemPaneTabOffset.setValue(20); } @@ -641,24 +643,19 @@ public class NEUOverlay extends Gui { public void showInfo(JsonObject item) { if (item.has("info") && item.has("infoType")) { JsonArray lore = item.get("info").getAsJsonArray(); - String[] loreA = new String[lore.size()]; - for (int i = 0; i < lore.size(); i++) loreA[i] = lore.get(i).getAsString(); - String loreS = StringUtils.join(loreA, "\n"); - + StringBuilder loreBuilder = new StringBuilder(); + for (int i = 0; i < lore.size(); i++) { + loreBuilder.append(lore.get(i).getAsString()); + if (i != lore.size() - 1) + loreBuilder.append("\n"); + } + String infoText = loreBuilder.toString(); String internalname = item.get("internalname").getAsString(); String name = item.get("displayname").getAsString(); - switch (item.get("infoType").getAsString()) { - case "WIKI_URL": - displayInformationPane(HTMLInfoPane.createFromWikiUrl(this, manager, name, loreS)); - return; - case "WIKI": - displayInformationPane(HTMLInfoPane.createFromWiki(this, manager, name, internalname, loreS)); - return; - case "HTML": - displayInformationPane(new HTMLInfoPane(this, manager, name, internalname, loreS)); - return; - } - displayInformationPane(new TextInfoPane(this, manager, name, loreS)); + String infoType = item.get("infoType").getAsString(); + displayInformationPane(new TextInfoPane(this, manager, "Loading", "Loading your requested information about " + name + ".")); + infoPaneLoadingJob = InfoPane.create(this, manager, infoType, name, internalname, infoText) + .thenAccept(this::displayInformationPane); } } @@ -882,6 +879,7 @@ public class NEUOverlay extends Gui { * Sets the activeInfoPane and sets the target of the infoPaneOffsetFactor to make the infoPane "slide" out. */ public void displayInformationPane(InfoPane pane) { + infoPaneLoadingJob.cancel(false); if (pane == null) { infoPaneOffsetFactor.setTarget(0); } else { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java index a8a98880..4ce581a6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java @@ -30,6 +30,7 @@ import java.net.URL; import java.net.URLConnection; import java.nio.charset.CharsetEncoder; import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -92,24 +93,24 @@ public class HTMLInfoPane extends TextInfoPane { /** * Takes a wiki url, uses NEUManager#getWebFile to download the web file and passed that in to #createFromWiki */ - public static HTMLInfoPane createFromWikiUrl(NEUOverlay overlay, NEUManager manager, String name, - String wikiUrl) { - File f = manager.getWebFile(wikiUrl); - if (f == null) { - return new HTMLInfoPane(overlay, manager, "error", "error", "Failed to load wiki url: " + wikiUrl); - } + public static CompletableFuture createFromWikiUrl(NEUOverlay overlay, NEUManager manager, String name, String wikiUrl) { + return manager.getWebFile(wikiUrl).thenApply(f -> { + if (f == null) { + return new HTMLInfoPane(overlay, manager, "error", "error", "Failed to load wiki url: " + wikiUrl); + } - StringBuilder sb = new StringBuilder(); - try (BufferedReader br = new BufferedReader(new InputStreamReader( - new FileInputStream(f), StandardCharsets.UTF_8))) { - String l; - while ((l = br.readLine()) != null) { - sb.append(l).append("\n"); + StringBuilder sb = new StringBuilder(); + try (BufferedReader br = new BufferedReader(new InputStreamReader( + new FileInputStream(f), StandardCharsets.UTF_8))) { + String l; + while ((l = br.readLine()) != null) { + sb.append(l).append("\n"); + } + } catch (IOException e) { + return new HTMLInfoPane(overlay, manager, "error", "error", "Failed to load wiki url: " + wikiUrl); } - } catch (IOException e) { - return new HTMLInfoPane(overlay, manager, "error", "error", "Failed to load wiki url: " + wikiUrl); - } - return createFromWiki(overlay, manager, name, f.getName(), sb.toString()); + return createFromWikiText(overlay, manager, name, f.getName(), sb.toString()); + }); } /** @@ -118,8 +119,8 @@ public class HTMLInfoPane extends TextInfoPane { * a more permanent solution that can be abstracted to work with arbitrary wiki codes (eg. moulberry.github.io/ * files/neu_help.html). */ - public static HTMLInfoPane createFromWiki(NEUOverlay overlay, NEUManager manager, String name, String filename, - String wiki) { + public static HTMLInfoPane createFromWikiText(NEUOverlay overlay, NEUManager manager, String name, String filename, + String wiki) { String[] split = wiki.split(""); wiki = split[split.length - 1]; //Remove everything before infobox wiki = wiki.split("")[0]; //Remove navbox diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java index 945b1bbf..3ceb0425 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java @@ -8,6 +8,7 @@ import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; import java.awt.*; +import java.util.concurrent.CompletableFuture; public abstract class InfoPane extends Gui { @@ -48,4 +49,21 @@ public abstract class InfoPane extends Gui { height - overlay.getBoxPadding() + 5, bg.getRGB()); } + public static CompletableFuture create(NEUOverlay overlay, NEUManager manager, String infoType, + String name, String internalName, String infoText) { + switch (infoType.intern()) { + case "WIKI_URL": + return HTMLInfoPane.createFromWikiUrl(overlay, manager, name, infoText); + case "WIKI": + return CompletableFuture.completedFuture( + HTMLInfoPane.createFromWikiText(overlay, manager, name, internalName, infoText)); + case "HTML": + return CompletableFuture.completedFuture( + new HTMLInfoPane(overlay, manager, name, internalName, infoText)); + default: + return CompletableFuture.completedFuture( + new TextInfoPane(overlay, manager, name, infoText)); + } + } + } -- cgit