diff options
| author | Moulberry <jjenour@student.unimelb.edu.au> | 2022-03-03 11:03:58 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-03 11:03:58 +0800 |
| commit | 7c6d37b2eb758a13b342b906f0aef88b940bc52a (patch) | |
| tree | 9602a014425b859e3aba98f31f93d6de04521356 /src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java | |
| parent | b11742988dec635b5c5da7c2363803cbfafb37b1 (diff) | |
| parent | db59eba3fd9121c7c0a88363994876c5b582c08c (diff) | |
| download | notenoughupdates-7c6d37b2eb758a13b342b906f0aef88b940bc52a.tar.gz notenoughupdates-7c6d37b2eb758a13b342b906f0aef88b940bc52a.tar.bz2 notenoughupdates-7c6d37b2eb758a13b342b906f0aef88b940bc52a.zip | |
Merge pull request #248 from NotEnoughUpdates/master
NEU 2.1 🙂
Diffstat (limited to 'src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java')
| -rw-r--r-- | src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java | 723 |
1 files changed, 384 insertions, 339 deletions
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 df7069d4..baf88457 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java @@ -8,9 +8,9 @@ import info.bliki.wiki.model.WikiModel; import info.bliki.wiki.tags.HTMLBlockTag; import info.bliki.wiki.tags.HTMLTag; import info.bliki.wiki.tags.IgnoreTag; -import io.github.moulberry.notenoughupdates.util.AllowEmptyHTMLTag; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.NEUOverlay; +import io.github.moulberry.notenoughupdates.util.AllowEmptyHTMLTag; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; @@ -30,239 +30,269 @@ 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; public class HTMLInfoPane extends TextInfoPane { - - private static WikiModel wikiModel; - - private final int ZOOM_FACTOR = 2; - private final int IMAGE_WIDTH = 400; - private final int EXT_WIDTH = 100; - - private ResourceLocation imageTexture = null; - private BufferedImage imageTemp = null; - private int imageHeight = 0; - private int imageWidth = 0; - - private static boolean hasAttemptedDownload = false; - - /** - * Creates a wiki model and sets the configuration to work with hypixel-skyblock wikia. - */ - static { - Configuration conf = new Configuration(); - conf.addTokenTag("img", new HTMLTag("img")); - conf.addTokenTag("code", new HTMLTag("code")); - conf.addTokenTag("span", new AllowEmptyHTMLTag("span")); - conf.addTokenTag("table", new HTMLBlockTag("table", Configuration.SPECIAL_BLOCK_TAGS+"span|")); - conf.addTokenTag("infobox", new IgnoreTag("infobox")); - conf.addTokenTag("tabber", new IgnoreTag("tabber")); - conf.addTokenTag("kbd", new HTMLTag("kbd")); - wikiModel = new WikiModel(conf,"https://hypixel-skyblock.fandom.com/wiki/Special:Filepath/${image}", - "https://hypixel-skyblock.fandom.com/wiki/${title}") { - { - TagNode.addAllowedAttribute("style"); - TagNode.addAllowedAttribute("src"); - } - - protected String createImageName(ImageFormat imageFormat) { - String imageName = imageFormat.getFilename(); - if (imageName.endsWith(".svg")) { - imageName += ".png"; - } - imageName = Encoder.encodeUrl(imageName); - if (replaceColon()) { - imageName = imageName.replace(':', '/'); - } - return imageName; - } - - public void parseInternalImageLink(String imageNamespace, String rawImageLink) { - rawImageLink = rawImageLink.replaceFirst("\\|x([0-9]+)px", "\\|$1x$1px"); - if(!rawImageLink.split("\\|")[0].toLowerCase().endsWith(".jpg")) { - super.parseInternalImageLink(imageNamespace, rawImageLink); - } - } - }; - } - - /** - * 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); - }; - - 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); - } - return createFromWiki(overlay, manager, name, f.getName(), sb.toString()); - } - - /** - * Takes raw wikia code and uses Bliki to generate HTML. Lot's of shennanigans to get it to render appropriately. - * Honestly, I could have just downloaded the raw HTML of the wiki page and displayed that but I wanted - * 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) { - String[] split = wiki.split("</infobox>"); - wiki = split[split.length - 1]; //Remove everything before infobox - wiki = wiki.split("<span class=\"navbox-vde\">")[0]; //Remove navbox - wiki = wiki.split("<table class=\"navbox mw-collapsible\"")[0]; - wiki = "__NOTOC__\n" + wiki; //Remove TOC - try (PrintWriter out = new PrintWriter(new File(manager.configLocation, "debug/parsed.txt"))) { - out.println(wiki); - } catch (IOException e) { - } - String html; - try { - html = wikiModel.render(wiki); - } catch(IOException e) { - return new HTMLInfoPane(overlay, manager, "error", "error", "Could not render wiki."); - } - try (PrintWriter out = new PrintWriter(new File(manager.configLocation, "debug/html.txt"))) { - out.println(html); - } catch (IOException e) { - } - return new HTMLInfoPane(overlay, manager, name, filename, html); - } - - private String spaceEscape(String str) { - return str.replace(" ", "\\ "); - } - - private static final ExecutorService wkDownloadES = Executors.newSingleThreadExecutor(); - private static final ExecutorService rendererES = Executors.newCachedThreadPool(); - - /** - * Uses the wkhtmltoimage command-line tool to generate an image from the HTML code. This - * generation is done asynchronously as sometimes it can take up to 10 seconds for more - * complex webpages. - */ - public HTMLInfoPane(NEUOverlay overlay, NEUManager manager, String name, String filename, String html) { - super(overlay, manager, name, ""); - this.title = name; - - String osId; - if(SystemUtils.IS_OS_WINDOWS) { - osId = "win"; - } else if(SystemUtils.IS_OS_MAC) { - osId = "mac"; - } else if(SystemUtils.IS_OS_LINUX) { - osId = "linux"; - } else { - text = EnumChatFormatting.RED+"Unsupported operating system."; - return; - } - - File cssFile = new File(manager.configLocation, "wikia.css"); - File wkHtmlToImage = new File(manager.configLocation, "wkhtmltox-"+osId+"/bin/wkhtmltoimage"); - - //Use old binary folder - if(new File(manager.configLocation, "wkhtmltox/bin/wkhtmltoimage").exists() && SystemUtils.IS_OS_WINDOWS) { - wkHtmlToImage = new File(manager.configLocation, "wkhtmltox/bin/wkhtmltoimage"); - } - - Runtime runtime = Runtime.getRuntime(); - String[] chmodCommand = new String[]{ "chmod", "-R", "777", new File(manager.configLocation, "wkhtmltox-"+osId).getAbsolutePath() }; - try { - Process p = runtime.exec(chmodCommand); - p.waitFor(); - } catch(IOException | InterruptedException e) {} - - if(!wkHtmlToImage.exists()) { - if(hasAttemptedDownload) { - text = EnumChatFormatting.RED+"Downloading web renderer failed? Or still downloading? Not sure what to do"; - return; - } else { - hasAttemptedDownload = true; - Utils.recursiveDelete(new File(manager.configLocation, "wkhtmltox-"+osId)); - wkDownloadES.submit(() -> { - try { - File itemsZip = new File(manager.configLocation, "wkhtmltox-"+osId+".zip"); - if(!itemsZip.exists()) { - URL url = new URL("https://moulberry.codes/wkhtmltox/wkhtmltox-"+osId+".zip"); - URLConnection urlConnection = url.openConnection(); - urlConnection.setConnectTimeout(15000); - urlConnection.setReadTimeout(60000); - - FileUtils.copyInputStreamToFile(urlConnection.getInputStream(), itemsZip); - } - - try(InputStream is = new FileInputStream(itemsZip)) { - manager.unzip(is, manager.configLocation); - } - - itemsZip.delete(); - itemsZip.deleteOnExit(); - } catch (IOException e) { - e.printStackTrace(); - } - }); - - text = EnumChatFormatting.YELLOW+"Downloading web renderer... try again soon"; - return; - } - } - - File input = new File(manager.configLocation, "tmp/input.html"); - String outputFileName = filename.replaceAll("(?i)\\u00A7.", "") - .replaceAll("[^a-zA-Z0-9_\\-]", "_"); - File output = new File(manager.configLocation, "tmp/"+ - outputFileName+".png"); - File outputExt = new File(manager.configLocation, "tmp/"+ - outputFileName+"_ext.png"); - - input.deleteOnExit(); - output.deleteOnExit(); - - File tmp = new File(manager.configLocation, "tmp"); - if(!tmp.exists()) { - tmp.mkdir(); - } - - if(output.exists()) { - try { - imageTemp = ImageIO.read(output); - text = EnumChatFormatting.RED+"Creating dynamic texture."; - } catch(IOException e) { - e.printStackTrace(); - text = EnumChatFormatting.RED+"Failed to read image."; - return; - } - } else { - html = "<div id=\"mw-content-text\" lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr mw-content-text\">"+html+"</div>"; - html = "<div id=\"WikiaArticle\" class=\"WikiaArticle\">"+html+"</div>"; - html = "<link rel=\"stylesheet\" href=\"file:///"+cssFile.getAbsolutePath().replaceAll("^/", "")+"\">\n"+html; - - try(PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(input), StandardCharsets.UTF_8)), false)) { - - out.println(encodeNonAscii(html)); - } catch(IOException e) {} - - try { - text = EnumChatFormatting.GRAY+"Rendering webpage (" + name + EnumChatFormatting.RESET+ - EnumChatFormatting.GRAY+"), please wait..."; - - String[] wkCommand = new String[]{ wkHtmlToImage.getAbsolutePath(), "--width", ""+IMAGE_WIDTH*ZOOM_FACTOR, - "--transparent", "--allow", manager.configLocation.getAbsolutePath(), "--zoom", ""+ZOOM_FACTOR, input.getAbsolutePath(), output.getAbsolutePath()}; - Process p = runtime.exec(wkCommand); + private static final WikiModel wikiModel; + + private final int ZOOM_FACTOR = 2; + private final int IMAGE_WIDTH = 400; + private final int EXT_WIDTH = 100; + + private ResourceLocation imageTexture = null; + private BufferedImage imageTemp = null; + private int imageHeight = 0; + private int imageWidth = 0; + + private static boolean hasAttemptedDownload = false; + + /* + * Creates a wiki model and sets the configuration to work with hypixel-skyblock wikia. + */ + static { + Configuration conf = new Configuration(); + conf.addTokenTag("img", new HTMLTag("img")); + conf.addTokenTag("code", new HTMLTag("code")); + conf.addTokenTag("span", new AllowEmptyHTMLTag("span")); + conf.addTokenTag("table", new HTMLBlockTag("table", Configuration.SPECIAL_BLOCK_TAGS + "span|")); + conf.addTokenTag("infobox", new IgnoreTag("infobox")); + conf.addTokenTag("tabber", new IgnoreTag("tabber")); + conf.addTokenTag("kbd", new HTMLTag("kbd")); + wikiModel = new WikiModel(conf, "https://hypixel-skyblock.fandom.com/wiki/Special:Filepath/${image}", + "https://hypixel-skyblock.fandom.com/wiki/${title}" + ) { + { + TagNode.addAllowedAttribute("style"); + TagNode.addAllowedAttribute("src"); + } + + protected String createImageName(ImageFormat imageFormat) { + String imageName = imageFormat.getFilename(); + if (imageName.endsWith(".svg")) { + imageName += ".png"; + } + imageName = Encoder.encodeUrl(imageName); + if (replaceColon()) { + imageName = imageName.replace(':', '/'); + } + return imageName; + } + + public void parseInternalImageLink(String imageNamespace, String rawImageLink) { + rawImageLink = rawImageLink.replaceFirst("\\|x([0-9]+)px", "\\|$1x$1px"); + if (!rawImageLink.split("\\|")[0].toLowerCase().endsWith(".jpg")) { + super.parseInternalImageLink(imageNamespace, rawImageLink); + } + } + }; + } + + /** + * Takes a wiki url, uses NEUManager#getWebFile to download the web file and passed that in to #createFromWiki + */ + public static CompletableFuture<HTMLInfoPane> 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"); + } + } catch (IOException e) { + return new HTMLInfoPane(overlay, manager, "error", "error", "Failed to load wiki url: " + wikiUrl); + } + return createFromWikiText(overlay, manager, name, f.getName(), sb.toString()); + }); + } + + /** + * Takes raw wikia code and uses Bliki to generate HTML. Lot's of shennanigans to get it to render appropriately. + * Honestly, I could have just downloaded the raw HTML of the wiki page and displayed that but I wanted + * 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 createFromWikiText( + NEUOverlay overlay, NEUManager manager, String name, String filename, + String wiki + ) { + String[] split = wiki.split("</infobox>"); + wiki = split[split.length - 1]; //Remove everything before infobox + wiki = wiki.split("<span class=\"navbox-vde\">")[0]; //Remove navbox + wiki = wiki.split("<table class=\"navbox mw-collapsible\"")[0]; + wiki = "__NOTOC__\n" + wiki; //Remove TOC + try (PrintWriter out = new PrintWriter(new File(manager.configLocation, "debug/parsed.txt"))) { + out.println(wiki); + } catch (IOException ignored) { + } + String html; + try { + html = wikiModel.render(wiki); + } catch (IOException e) { + return new HTMLInfoPane(overlay, manager, "error", "error", "Could not render wiki."); + } + try (PrintWriter out = new PrintWriter(new File(manager.configLocation, "debug/html.txt"))) { + out.println(html); + } catch (IOException ignored) { + } + return new HTMLInfoPane(overlay, manager, name, filename, html); + } + + private String spaceEscape(String str) { + return str.replace(" ", "\\ "); + } + + private static final ExecutorService wkDownloadES = Executors.newSingleThreadExecutor(); + private static final ExecutorService rendererES = Executors.newCachedThreadPool(); + + /** + * Uses the wkhtmltoimage command-line tool to generate an image from the HTML code. This + * generation is done asynchronously as sometimes it can take up to 10 seconds for more + * complex webpages. + */ + public HTMLInfoPane(NEUOverlay overlay, NEUManager manager, String name, String filename, String html) { + super(overlay, manager, name, ""); + this.title = name; + + String osId; + if (SystemUtils.IS_OS_WINDOWS) { + osId = "win"; + } else if (SystemUtils.IS_OS_MAC) { + osId = "mac"; + } else if (SystemUtils.IS_OS_LINUX) { + osId = "linux"; + } else { + text = EnumChatFormatting.RED + "Unsupported operating system."; + return; + } + + File cssFile = new File(manager.configLocation, "wikia.css"); + File wkHtmlToImage = new File(manager.configLocation, "wkhtmltox-" + osId + "/bin/wkhtmltoimage"); + + //Use old binary folder + if (new File(manager.configLocation, "wkhtmltox/bin/wkhtmltoimage").exists() && SystemUtils.IS_OS_WINDOWS) { + wkHtmlToImage = new File(manager.configLocation, "wkhtmltox/bin/wkhtmltoimage"); + } + + Runtime runtime = Runtime.getRuntime(); + String[] chmodCommand = new String[]{ + "chmod", "-R", "777", new File( + manager.configLocation, + "wkhtmltox-" + osId + ).getAbsolutePath() + }; + try { + Process p = runtime.exec(chmodCommand); + p.waitFor(); + } catch (IOException | InterruptedException ignored) { + } + + if (!wkHtmlToImage.exists()) { + if (hasAttemptedDownload) { + text = EnumChatFormatting.RED + "Downloading web renderer failed? Or still downloading? Not sure what to do"; + } else { + hasAttemptedDownload = true; + Utils.recursiveDelete(new File(manager.configLocation, "wkhtmltox-" + osId)); + wkDownloadES.submit(() -> { + try { + File itemsZip = new File(manager.configLocation, "wkhtmltox-" + osId + ".zip"); + if (!itemsZip.exists()) { + URL url = new URL("https://moulberry.codes/wkhtmltox/wkhtmltox-" + osId + ".zip"); + URLConnection urlConnection = url.openConnection(); + urlConnection.setConnectTimeout(15000); + urlConnection.setReadTimeout(60000); + + FileUtils.copyInputStreamToFile(urlConnection.getInputStream(), itemsZip); + } + + try (InputStream is = new FileInputStream(itemsZip)) { + NEUManager.unzip(is, manager.configLocation); + } + + itemsZip.delete(); + itemsZip.deleteOnExit(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + text = EnumChatFormatting.YELLOW + "Downloading web renderer... try again soon"; + } + return; + } + + File input = new File(manager.configLocation, "tmp/input.html"); + String outputFileName = filename.replaceAll("(?i)\\u00A7.", "") + .replaceAll("[^a-zA-Z0-9_\\-]", "_"); + File output = new File(manager.configLocation, "tmp/" + + outputFileName + ".png"); + File outputExt = new File(manager.configLocation, "tmp/" + + outputFileName + "_ext.png"); + + input.deleteOnExit(); + output.deleteOnExit(); + + File tmp = new File(manager.configLocation, "tmp"); + if (!tmp.exists()) { + tmp.mkdir(); + } + + if (output.exists()) { + try { + imageTemp = ImageIO.read(output); + text = EnumChatFormatting.RED + "Creating dynamic texture."; + } catch (IOException e) { + e.printStackTrace(); + text = EnumChatFormatting.RED + "Failed to read image."; + return; + } + } else { + html = "<div id=\"mw-content-text\" lang=\"en\" dir=\"ltr\" class=\"mw-content-ltr mw-content-text\">" + html + + "</div>"; + html = "<div id=\"WikiaArticle\" class=\"WikiaArticle\">" + html + "</div>"; + html = "<link rel=\"stylesheet\" href=\"file:///" + cssFile.getAbsolutePath().replaceAll("^/", "") + "\">\n" + + html; + + try ( + PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(input), StandardCharsets.UTF_8)), false) + ) { + + out.println(encodeNonAscii(html)); + } catch (IOException ignored) { + } + + try { + text = EnumChatFormatting.GRAY + "Rendering webpage (" + name + EnumChatFormatting.RESET + + EnumChatFormatting.GRAY + "), please wait..."; + + String[] wkCommand = new String[]{ + wkHtmlToImage.getAbsolutePath(), + "--width", + "" + IMAGE_WIDTH * ZOOM_FACTOR, + "--transparent", + "--allow", + manager.configLocation.getAbsolutePath(), + "--zoom", + "" + ZOOM_FACTOR, + input.getAbsolutePath(), + output.getAbsolutePath() + }; + Process p = runtime.exec(wkCommand); /*Process p = runtime.exec(spaceEscape(wkHtmlToImage.getAbsolutePath()) + " --width "+ IMAGE_WIDTH*ZOOM_FACTOR+" --transparent --zoom "+ZOOM_FACTOR + " " + spaceEscape(input.getAbsolutePath()) + " " + spaceEscape(output.getAbsolutePath()));*/ @@ -272,14 +302,14 @@ public class HTMLInfoPane extends TextInfoPane { /*Process p2 = runtime.exec("\""+wkHtmlToImage.getAbsolutePath() + "\" --width "+ (IMAGE_WIDTH+EXT_WIDTH)*ZOOM_FACTOR+" --transparent --zoom "+ZOOM_FACTOR+" \"" + input.getAbsolutePath() + "\" \"" + outputExt.getAbsolutePath() + "\"");*/ - rendererES.submit(() -> { - try { - if(p.waitFor(15, TimeUnit.SECONDS)) { - //if(p2.waitFor(5, TimeUnit.SECONDS)) { - if(overlay.getActiveInfoPane() != this) return; - - try { - imageTemp = ImageIO.read(output); + rendererES.submit(() -> { + try { + if (p.waitFor(15, TimeUnit.SECONDS)) { + //if(p2.waitFor(5, TimeUnit.SECONDS)) { + if (overlay.getActiveInfoPane() != this) return; + + try { + imageTemp = ImageIO.read(output); /*BufferedImage imageReg = ImageIO.read(output); BufferedImage imageExt = ImageIO.read(outputExt); ArrayList<Integer[]> pixels = new ArrayList<>(); @@ -307,106 +337,121 @@ public class HTMLInfoPane extends TextInfoPane { imageTemp.setRGB(x, y, col); } }*/ - text = EnumChatFormatting.RED+"Creating dynamic texture."; - } catch(IOException e) { - e.printStackTrace(); - text = EnumChatFormatting.RED+"Failed to read image."; - return; - } - } else { - if(overlay.getActiveInfoPane() != this) return; - - text = EnumChatFormatting.RED+"Webpage render timed out (>15sec). Maybe it's too large?"; - } - } catch(Exception e) { - e.printStackTrace(); - } - }); - } catch(IOException e) { - e.printStackTrace(); - text = EnumChatFormatting.RED+"Failed to exec webpage renderer."; - } - } - } - - /** - * Renders a background, title and the image created in the ctor (if it has been generated). - */ - @Override - public void render(int width, int height, Color bg, Color fg, ScaledResolution scaledresolution, int mouseX, int mouseY) { - if(imageTemp != null && imageTexture == null) { - DynamicTexture tex = new DynamicTexture(imageTemp); - imageTexture = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation( - "notenoughupdates/informationPaneImage", tex); - imageHeight = imageTemp.getHeight(); - imageWidth = imageTemp.getWidth(); - } - if(imageTexture == null) { - super.render(width, height, bg, fg, scaledresolution, mouseX, mouseY); - return; - } - - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - - int paneWidth = (int)(width/3*overlay.getWidthMult()); - int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor()); - int leftSide = rightSide - paneWidth; - - int titleLen = fr.getStringWidth(title); - fr.drawString(title, (leftSide+rightSide-titleLen)/2, overlay.getBoxPadding() + 5, Color.WHITE.getRGB()); - - drawRect(leftSide+overlay.getBoxPadding()-5, overlay.getBoxPadding()-5, rightSide-overlay.getBoxPadding()+5, - height-overlay.getBoxPadding()+5, bg.getRGB()); - - int imageW = paneWidth - overlay.getBoxPadding()*2; - float scaleF = IMAGE_WIDTH*ZOOM_FACTOR/(float)imageW; - - Minecraft.getMinecraft().getTextureManager().bindTexture(imageTexture); - GlStateManager.color(1f, 1f, 1f, 1f); - if(height-overlay.getBoxPadding()*3 < imageHeight/scaleF) { - if(scrollHeight.getValue() > imageHeight/scaleF-height+overlay.getBoxPadding()*3) { - scrollHeight.setValue((int)(imageHeight/scaleF-height+overlay.getBoxPadding()*3)); - } - int yScroll = scrollHeight.getValue(); - - float vMin = yScroll/(imageHeight/scaleF); - float vMax = (yScroll+height-overlay.getBoxPadding()*3)/(imageHeight/scaleF); - Utils.drawTexturedRect(leftSide+overlay.getBoxPadding(), overlay.getBoxPadding()*2, imageW, - height-overlay.getBoxPadding()*3, - 0, 1, vMin, vMax); - } else { - scrollHeight.setValue(0); - - Utils.drawTexturedRect(leftSide+overlay.getBoxPadding(), overlay.getBoxPadding()*2, imageW, - (int)(imageHeight/scaleF)); - } - GlStateManager.bindTexture(0); - } - - @Override - public boolean keyboardInput() { - return false; - } - - @Override - public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) { - super.mouseInput(width, height, mouseX, mouseY, mouseDown); - } - - //From https://stackoverflow.com/questions/1760766/how-to-convert-non-supported-character-to-html-entity-in-java - public String encodeNonAscii(String c) { - StringBuilder buf = new StringBuilder(c.length()); - CharsetEncoder enc = StandardCharsets.US_ASCII.newEncoder(); - for (int idx = 0; idx < c.length(); ++idx) { - char ch = c.charAt(idx); - if (enc.canEncode(ch)) - buf.append(ch); - else { - buf.append("&#"); - buf.append((int) ch); - buf.append(';'); - } - } - return buf.toString(); - } + text = EnumChatFormatting.RED + "Creating dynamic texture."; + } catch (IOException e) { + e.printStackTrace(); + text = EnumChatFormatting.RED + "Failed to read image."; + return; + } + } else { + if (overlay.getActiveInfoPane() != this) return; + + text = EnumChatFormatting.RED + "Webpage render timed out (>15sec). Maybe it's too large?"; + } + } catch (Exception e) { + e.printStackTrace(); + } + }); + } catch (IOException e) { + e.printStackTrace(); + text = EnumChatFormatting.RED + "Failed to exec webpage renderer."; + } + } + } + + /** + * Renders a background, title and the image created in the ctor (if it has been generated). + */ + @Override + public void render( + int width, + int height, + Color bg, + Color fg, + ScaledResolution scaledresolution, + int mouseX, + int mouseY + ) { + if (imageTemp != null && imageTexture == null) { + DynamicTexture tex = new DynamicTexture(imageTemp); + imageTexture = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation( + "notenoughupdates/informationPaneImage", tex); + imageHeight = imageTemp.getHeight(); + imageWidth = imageTemp.getWidth(); + } + if (imageTexture == null) { + super.render(width, height, bg, fg, scaledresolution, mouseX, mouseY); + return; + } + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + int paneWidth = (int) (width / 3 * overlay.getWidthMult()); + int rightSide = (int) (width * overlay.getInfoPaneOffsetFactor()); + int leftSide = rightSide - paneWidth; + + int titleLen = fr.getStringWidth(title); + fr.drawString(title, (leftSide + rightSide - titleLen) / 2, overlay.getBoxPadding() + 5, Color.WHITE.getRGB()); + + drawRect( + leftSide + overlay.getBoxPadding() - 5, + overlay.getBoxPadding() - 5, + rightSide - overlay.getBoxPadding() + 5, + height - overlay.getBoxPadding() + 5, + bg.getRGB() + ); + + int imageW = paneWidth - overlay.getBoxPadding() * 2; + float scaleF = IMAGE_WIDTH * ZOOM_FACTOR / (float) imageW; + + Minecraft.getMinecraft().getTextureManager().bindTexture(imageTexture); + GlStateManager.color(1f, 1f, 1f, 1f); + if (height - overlay.getBoxPadding() * 3 < imageHeight / scaleF) { + if (scrollHeight.getValue() > imageHeight / scaleF - height + overlay.getBoxPadding() * 3) { + scrollHeight.setValue((int) (imageHeight / scaleF - height + overlay.getBoxPadding() * 3)); + } + int yScroll = scrollHeight.getValue(); + + float vMin = yScroll / (imageHeight / scaleF); + float vMax = (yScroll + height - overlay.getBoxPadding() * 3) / (imageHeight / scaleF); + Utils.drawTexturedRect(leftSide + overlay.getBoxPadding(), overlay.getBoxPadding() * 2, imageW, + height - overlay.getBoxPadding() * 3, + 0, 1, vMin, vMax + ); + } else { + scrollHeight.setValue(0); + + Utils.drawTexturedRect(leftSide + overlay.getBoxPadding(), overlay.getBoxPadding() * 2, imageW, + (int) (imageHeight / scaleF) + ); + } + GlStateManager.bindTexture(0); + } + + @Override + public boolean keyboardInput() { + return false; + } + + @Override + public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) { + super.mouseInput(width, height, mouseX, mouseY, mouseDown); + } + + //From https://stackoverflow.com/questions/1760766/how-to-convert-non-supported-character-to-html-entity-in-java + public String encodeNonAscii(String c) { + StringBuilder buf = new StringBuilder(c.length()); + CharsetEncoder enc = StandardCharsets.US_ASCII.newEncoder(); + for (int idx = 0; idx < c.length(); ++idx) { + char ch = c.charAt(idx); + if (enc.canEncode(ch)) + buf.append(ch); + else { + buf.append("&#"); + buf.append((int) ch); + buf.append(';'); + } + } + return buf.toString(); + } } |
