summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorunknown <james.jenour@protonmail.com>2020-04-22 04:02:59 +1000
committerunknown <james.jenour@protonmail.com>2020-04-22 04:02:59 +1000
commit6360be89887b2c7b31a1739228deccbb0648d7cf (patch)
tree559e2367dbea689e7964a5db395e640105ed34a6 /src
parentae5bace43a14f2d8be9f1c1d9c644cc5dabd5d2f (diff)
downloadNotEnoughUpdates-BETA-1.5.tar.gz
NotEnoughUpdates-BETA-1.5.tar.bz2
NotEnoughUpdates-BETA-1.5.zip
Diffstat (limited to 'src')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/AllowEmptyHTMLTag.java74
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java78
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java516
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java1524
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java347
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/RequestFocusListener.java63
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/Utils.java185
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/WikiaParser.java212
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/WikiaParserOLD.java270
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java51
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/Options.java173
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/HTMLParagraphView.java30
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/HtmlImageGenerator.java125
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/LargeHTMLEditorKit.java132
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/SynchronousHTMLEditorKit.java36
-rw-r--r--src/main/resources/assets/notenoughupdates/ascending_overlay.pngbin0 -> 1497 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/close.pngbin0 -> 2350 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/descending_overlay.pngbin0 -> 1513 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/help.pngbin0 -> 3500 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/next.pngbin5005 -> 3912 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/next.xcfbin0 -> 8805 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/next_pow2.pngbin17733 -> 0 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/off.pngbin0 -> 1386 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/on.pngbin0 -> 1490 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/order_alphabetical.pngbin0 -> 1862 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/order_alphabetical_active.pngbin0 -> 1819 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/order_rarity.pngbin0 -> 1808 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/order_rarity_active.pngbin0 -> 1953 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/prev.pngbin5207 -> 4508 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/prev.xcfbin0 -> 8371 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/prev_pow2.pngbin18696 -> 0 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/settings.pngbin0 -> 3962 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_accessory.pngbin0 -> 1885 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_accessory_active.pngbin0 -> 1871 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_all.pngbin0 -> 1817 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_all_active.pngbin0 -> 1850 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_armor.pngbin0 -> 1792 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_armor_active.pngbin0 -> 1921 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_mob.pngbin0 -> 1800 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_mob_active.pngbin0 -> 1815 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_pet.pngbin0 -> 1902 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_pet_active.pngbin0 -> 1932 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_weapon.pngbin0 -> 749 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/sort_weapon_active.pngbin0 -> 1869 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/wkhtmltox.zipbin0 -> 47859019 bytes
47 files changed, 3406 insertions, 435 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/AllowEmptyHTMLTag.java b/src/main/java/io/github/moulberry/notenoughupdates/AllowEmptyHTMLTag.java
new file mode 100644
index 00000000..3cf5ef31
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/AllowEmptyHTMLTag.java
@@ -0,0 +1,74 @@
+package io.github.moulberry.notenoughupdates;
+
+import info.bliki.htmlcleaner.TagNode;
+import info.bliki.wiki.filter.ITextConverter;
+import info.bliki.wiki.model.IWikiModel;
+import info.bliki.wiki.tags.HTMLTag;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public class AllowEmptyHTMLTag extends HTMLTag {
+ public AllowEmptyHTMLTag(String name) {
+ super(name);
+ }
+
+ public void renderHTML(ITextConverter converter, Appendable buf, IWikiModel model) throws IOException {
+ boolean newLinesAfterTag = false;
+ boolean newLinesAfterChildren = false;
+ TagNode node = this;
+ String name = node.getName();
+ List<Object> children = node.getChildren();
+
+ if (NEW_LINES) {
+ switch (name) {
+ case "div":
+ case "p":
+ case "li":
+ case "td":
+ buf.append('\n');
+ break;
+ case "table":
+ case "ul":
+ case "ol":
+ case "th":
+ case "tr":
+ buf.append('\n');
+ newLinesAfterTag = true;
+ newLinesAfterChildren = true;
+ break;
+ case "pre":
+ buf.append('\n');
+ newLinesAfterTag = false;
+ newLinesAfterChildren = true;
+ break;
+ case "blockquote":
+ newLinesAfterChildren = true;
+ break;
+ }
+ }
+ buf.append('<');
+ buf.append(name);
+
+ Map<String, String> tagAtttributes = node.getAttributes();
+
+ appendAttributes(buf, tagAtttributes);
+
+ if (children.size() == 0) {
+ buf.append(" />");
+ } else {
+ buf.append('>');
+ if (newLinesAfterTag) {
+ buf.append('\n');
+ }
+ converter.nodesToText(children, buf, model);
+ if (newLinesAfterChildren) {
+ buf.append('\n');
+ }
+ buf.append("</");
+ buf.append(node.getName());
+ buf.append('>');
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java
new file mode 100644
index 00000000..1e31a0f2
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java
@@ -0,0 +1,78 @@
+package io.github.moulberry.notenoughupdates;
+
+import com.google.gson.JsonObject;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.inventory.GuiCrafting;
+import net.minecraft.client.resources.I18n;
+import net.minecraft.inventory.ContainerWorkbench;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+
+public class GuiItemRecipe extends GuiCrafting {
+
+ private ItemStack[] craftMatrix;
+ private String text;
+ private String craftText = "";
+ private NEUManager manager;
+
+ public GuiItemRecipe(ItemStack[] craftMatrix, JsonObject result, String text, NEUManager manager) {
+ super(Minecraft.getMinecraft().thePlayer.inventory, Minecraft.getMinecraft().theWorld);
+ this.craftMatrix = craftMatrix;
+ this.text = text;
+ this.manager = manager;
+
+ ContainerWorkbench cw = (ContainerWorkbench) this.inventorySlots;
+ for(int i=0; i<Math.min(craftMatrix.length, 9); i++) {
+ if(craftMatrix[i] == null) continue;
+ cw.craftMatrix.setInventorySlotContents(i, craftMatrix[i]);
+ }
+ if(result.has("crafttext")) {
+ craftText = result.get("crafttext").getAsString();
+ }
+ cw.craftResult.setInventorySlotContents(0, manager.jsonToStack(result));
+ }
+
+ protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
+ String t = text.equals("") ? I18n.format("container.crafting", new Object[0]) : text;
+ int xPos = 28;
+ if(this.fontRendererObj.getStringWidth(t) > this.xSize - 40) {
+ xPos = 4;
+ }
+ if(t.contains("\u00a7")) {
+ this.fontRendererObj.drawStringWithShadow(t, xPos, 6, 4210752);
+ } else {
+ this.fontRendererObj.drawString(t, xPos, 6, 4210752);
+ }
+ this.fontRendererObj.drawString(I18n.format("container.inventory", new Object[0]), 8, this.ySize - 96 + 2, 4210752);
+
+ this.fontRendererObj.drawString(craftText, 88, 19, 4210752);
+ }
+
+ protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
+ }
+
+ protected void handleMouseClick(Slot slotIn, int slotId, int clickedButton, int clickType) {
+ if(slotId >= 1 && slotId <= 9) {
+ ItemStack click = craftMatrix[slotId-1];
+ if(click != null) {
+ manager.displayGuiItemRecipe(manager.getInternalNameForItem(click), "");
+ }
+ }
+ }
+
+ /*public void handleMouseInput() throws IOException {
+ ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ int height = scaledresolution.getScaledHeight();
+
+ int mouseX = Mouse.getX() / scaledresolution.getScaleFactor();
+ int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor();
+ if(mouseY > this.guiTop + this.ySize - 94 || mouseY < this.guiTop ||
+ mouseX < this.guiLeft || mouseX > this.guiLeft+this.xSize) {
+ //Potentially allow mouse input in the future. For now this is still broken.
+ //super.handleMouseInput();
+ }
+ }*/
+
+ public void onCraftMatrixChanged(IInventory inventoryIn){}
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
index 7e7091cf..a89bd1dc 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
@@ -74,7 +74,9 @@ public class NEUIO {
changedFiles.put(content.getName(), content.getSha());
}
}
- } catch(IOException e) { }
+ } catch(IOException e) {
+ return null;
+ }
return changedFiles;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
index c6fab0f1..bcf4635e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
@@ -1,14 +1,18 @@
package io.github.moulberry.notenoughupdates;
+import com.google.common.io.CharSource;
import com.google.gson.*;
+import io.github.moulberry.notenoughupdates.options.Options;
import javafx.scene.control.Alert;
import net.minecraft.client.Minecraft;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.JsonToNBT;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.nbt.NBTTagList;
-import net.minecraft.nbt.NBTUtil;
+import net.minecraft.nbt.*;
import net.minecraft.util.ResourceLocation;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.ReaderInputStream;
+import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.opengl.Display;
import javax.swing.*;
@@ -22,8 +26,9 @@ import java.util.zip.ZipInputStream;
public class NEUManager {
+ private final NotEnoughUpdates neu;
public final NEUIO neuio;
- public static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ public final Gson gson;
private TreeMap<String, JsonObject> itemMap = new TreeMap<>();
@@ -31,23 +36,41 @@ public class NEUManager {
private TreeMap<String, HashMap<String, List<Integer>>> titleWordMap = new TreeMap<>();
private TreeMap<String, HashMap<String, List<Integer>>> loreWordMap = new TreeMap<>();
- private File configLocation;
+ public String viewItemAttemptID = null;
+ public long viewItemAttemptTime = 0;
+
+ private ResourceLocation wkZip = new ResourceLocation("notenoughupdates:wkhtmltox.zip");
+ private Map<String, ItemStack> itemstackCache = new HashMap<>();
+
+ private static final String AUCTIONS_PRICE_URL = "https://sll5cr6l5a.execute-api.us-east-1.amazonaws.com/Prod/get_prices";
+ private TreeMap<String, Float> auctionPrices = new TreeMap<>();
+ private TreeMap<String, Pair<Float, Float>> bazaarBuySellPrices = new TreeMap<>();
+ private long auctionLastUpdate = 0;
+
+ public File configLocation;
private File itemsLocation;
private File itemShaLocation;
private JsonObject itemShaConfig;
- private File config;
- private JsonObject configJson;
+ private File configFile;
+ public Options config;
- public NEUManager(NEUIO neuio, File configLocation) {
+ public NEUManager(NotEnoughUpdates neu, NEUIO neuio, File configLocation) {
+ this.neu = neu;
this.configLocation = configLocation;
this.neuio = neuio;
- this.config = new File(configLocation, "config.json");
+ GsonBuilder gsonBuilder = new GsonBuilder().setPrettyPrinting();
+ gsonBuilder.registerTypeAdapter(Options.Option.class, Options.createSerializer());
+ gsonBuilder.registerTypeAdapter(Options.Option.class, Options.createDeserializer());
+ gson = gsonBuilder.create();
+
+ this.configFile = new File(configLocation, "config.json");
try {
- config.createNewFile();
- configJson = getJsonFromFile(config);
- if(configJson == null) configJson = new JsonObject();
- } catch(IOException e) { }
+ configFile.createNewFile();
+ config = Options.loadFromFile(gson, configFile);
+ } catch(IOException e) {
+ config = new Options();
+ }
this.itemsLocation = new File(configLocation, "items");
itemsLocation.mkdir();
@@ -58,6 +81,115 @@ public class NEUManager {
itemShaConfig = getJsonFromFile(itemShaLocation);
if(itemShaConfig == null) itemShaConfig = new JsonObject();
} catch(IOException e) { }
+
+ File wkShell = new File(configLocation, "wkhtmltox/bin/wkhtmltoimage");
+ if(!wkShell.exists()) {
+ try {
+ InputStream is = Minecraft.getMinecraft().getResourceManager().getResource(wkZip).getInputStream();
+ unzip(is, configLocation);
+ } catch (IOException e) {
+ }
+ }
+
+ //Unused code, used to automatically grab items from auctions. Leaving here in case I need it.
+ /*try {
+ for(int j=0; j<=89; j++) {
+ JsonObject auctions0 = getJsonFromFile(new File(configLocation, "auctions/auctions"+j+".json"));
+
+ JsonArray arr = auctions0.getAsJsonArray("auctions");
+ for(int i=0; i<arr.size(); i++) {
+ JsonObject item0 = arr.get(i).getAsJsonObject();
+ try {
+ String item_bytes = item0.get("item_bytes").getAsString();
+
+ NBTTagCompound tag = CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(item_bytes)));
+ tag = tag.getTagList("i", 10).getCompoundTagAt(0);
+ int id = tag.getShort("id");
+ int damage = tag.getShort("Damage");
+ tag = tag.getCompoundTag("tag");
+
+ String internalname = "";
+ if(tag != null && tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+
+ if(ea.hasKey("id", 8)) {
+ internalname = ea.getString("id");
+ }
+ }
+
+ String[] lore = new String[0];
+ NBTTagCompound display = tag.getCompoundTag("display");
+
+ if(display.hasKey("Lore", 9)) {
+ NBTTagList list = display.getTagList("Lore", 8);
+ lore = new String[list.tagCount()];
+ for(int k=0; k<list.tagCount(); k++) {
+ lore[k] = list.getStringTagAt(k);
+ }
+ }
+
+ if(Item.itemRegistry.getObject(new ResourceLocation(internalname.toLowerCase())) != null) {
+ continue;
+ }
+
+ String itemid = Item.getItemById(id).getRegistryName();
+ String displayname = display.getString("Name");
+ String[] info = new String[0];
+ String clickcommand = "";
+
+ File file = new File(itemsLocation, internalname+".json");
+ if(!file.exists()) {
+ writeItemJson(internalname, itemid, displayname, lore, info, clickcommand, damage, tag);
+ } else {
+ JsonObject existing = getJsonFromFile(file);
+ String nbttag = existing.get("nbttag").toString();
+ if(nbttag.length() > tag.toString().length()) {
+ writeItemJson(internalname, itemid, displayname, lore, info, clickcommand, damage, tag);
+ }
+ }
+
+ } catch(Exception e) {
+ }
+ }
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ throw new RuntimeException();*/
+ }
+
+ public void saveConfig() throws IOException {
+ config.saveToFile(gson, configFile);
+ }
+
+ public void updatePrices() {
+ if(System.currentTimeMillis() - auctionLastUpdate > 1000*60*30) { //30 minutes
+ System.out.println("UPDATING PRICE INFORMATION");
+ auctionLastUpdate = System.currentTimeMillis();
+ try (Reader inReader = new BufferedReader(new InputStreamReader(new URL(AUCTIONS_PRICE_URL).openStream()))) {
+ JsonObject json = gson.fromJson(inReader, JsonObject.class);
+ for(Map.Entry<String, JsonElement> entry : json.getAsJsonObject("AuctionPricesItem").entrySet()) {
+ if(entry.getKey().equals("id")) continue;
+ auctionPrices.put(entry.getKey(), entry.getValue().getAsFloat());
+ }
+ for(Map.Entry<String, JsonElement> entry : json.getAsJsonObject("BazaarPricesItem").entrySet()) {
+ if(entry.getKey().equals("id")) continue;
+ JsonObject val = entry.getValue().getAsJsonObject();
+ bazaarBuySellPrices.put(entry.getKey(), Pair.of(val.get("buyPrice").getAsFloat(), val.get("sellPrice").getAsFloat()));
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public NavigableMap<String, Float> getAuctionPrices() {
+ return Collections.unmodifiableNavigableMap(auctionPrices);
+ }
+
+ public NavigableMap<String, Pair<Float, Float>> getBazaarBuySellPrices() {
+ return Collections.unmodifiableNavigableMap(bazaarBuySellPrices);
}
/**
@@ -71,69 +203,84 @@ public class NEUManager {
}
/**
- * Some convenience methods for working with the config. Should probably switch to using a more sophisticated
- * config system, but until we only use it for more than one value, this should be fine.
- */
- public void setAllowEditing(boolean allowEditing) {
- try {
- configJson.addProperty("allowEditing", allowEditing);
- writeJson(configJson, config);
- } catch(IOException e) {}
- }
-
- public boolean getAllowEditing() {
- try {
- return configJson.get("allowEditing").getAsBoolean();
- } catch(Exception e) {}
- return false;
- }
-
- /**
* Called when the game is first loaded. Compares the local repository to the github repository and handles
* the downloading of new/updated files. This then calls the "loadItem" method for every item in the local
* repository.
*/
public void loadItemInformation() {
- JOptionPane pane = new JOptionPane("Getting items to download from remote repository.");
- JDialog dialog = pane.createDialog("NotEnoughUpdates Remote Sync");
- dialog.setModal(false);
- dialog.setVisible(true);
+ if(config.autoupdate.value) {
+ JOptionPane pane = new JOptionPane("Getting items to download from remote repository.");
+ JDialog dialog = pane.createDialog("NotEnoughUpdates Remote Sync");
+ dialog.setModal(false);
+ dialog.setVisible(true);
- if(Display.isActive()) dialog.toFront();
+ if (Display.isActive()) dialog.toFront();
- HashMap<String, String> oldShas = new HashMap<>();
- for(Map.Entry<String, JsonElement> entry : itemShaConfig.entrySet()) {
- if(new File(itemsLocation, entry.getKey()+".json").exists()) {
- oldShas.put(entry.getKey()+".json", entry.getValue().getAsString());
+ HashMap<String, String> oldShas = new HashMap<>();
+ for (Map.Entry<String, JsonElement> entry : itemShaConfig.entrySet()) {
+ if (new File(itemsLocation, entry.getKey() + ".json").exists()) {
+ oldShas.put(entry.getKey() + ".json", entry.getValue().getAsString());
+ }
}
- }
- Map<String, String> changedFiles = neuio.getChangedItems(oldShas);
- for(Map.Entry<String, String> changedFile : changedFiles.entrySet()) {
- itemShaConfig.addProperty(changedFile.getKey().substring(0, changedFile.getKey().length()-5),
- changedFile.getValue());
- }
- try {
- writeJson(itemShaConfig, itemShaLocation);
- } catch(IOException e) {}
+ Map<String, String> changedFiles = neuio.getChangedItems(oldShas);
- if(Display.isActive()) dialog.toFront();
+ if (changedFiles != null) {
+ for (Map.Entry<String, String> changedFile : changedFiles.entrySet()) {
+ itemShaConfig.addProperty(changedFile.getKey().substring(0, changedFile.getKey().length() - 5),
+ changedFile.getValue());
+ }
+ try {
+ writeJson(itemShaConfig, itemShaLocation);
+ } catch (IOException e) {
+ }
+ }
+
+ if (Display.isActive()) dialog.toFront();
- if(changedFiles.size() <= 20) {
- Map<String, String> downloads = neuio.getItemsDownload(changedFiles.keySet());
+ if (changedFiles != null && changedFiles.size() <= 20) {
+ Map<String, String> downloads = neuio.getItemsDownload(changedFiles.keySet());
- String startMessage = "NotEnoughUpdates: Syncing with remote repository (";
- int downloaded = 0;
+ String startMessage = "NotEnoughUpdates: Syncing with remote repository (";
+ int downloaded = 0;
- for(Map.Entry<String, String> entry : downloads.entrySet()) {
- pane.setMessage(startMessage + (++downloaded) + "/" + downloads.size() + ")\nCurrent: " + entry.getKey());
+ for (Map.Entry<String, String> entry : downloads.entrySet()) {
+ pane.setMessage(startMessage + (++downloaded) + "/" + downloads.size() + ")\nCurrent: " + entry.getKey());
+ dialog.pack();
+ dialog.setVisible(true);
+ if (Display.isActive()) dialog.toFront();
+
+ File item = new File(itemsLocation, entry.getKey());
+ try {
+ item.createNewFile();
+ } catch (IOException e) {
+ }
+ try (BufferedInputStream inStream = new BufferedInputStream(new URL(entry.getValue()).openStream());
+ FileOutputStream fileOutputStream = new FileOutputStream(item)) {
+ 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();
+ }
+ }
+ } else {
+ //TODO: Store hard-coded value somewhere else
+ String dlUrl = "https://github.com/Moulberry/NotEnoughUpdates-REPO/archive/master.zip";
+
+ pane.setMessage("Downloading NEU Master Archive. (DL# >20)");
dialog.pack();
dialog.setVisible(true);
- if(Display.isActive()) dialog.toFront();
+ if (Display.isActive()) dialog.toFront();
- File item = new File(itemsLocation, entry.getKey());
- try { item.createNewFile(); } catch(IOException e) { }
- try(BufferedInputStream inStream = new BufferedInputStream(new URL(entry.getValue()).openStream());
- FileOutputStream fileOutputStream = new FileOutputStream(item)) {
+ File itemsZip = new File(configLocation, "neu-items-master.zip");
+ try {
+ itemsZip.createNewFile();
+ } catch (IOException e) {
+ }
+ try (BufferedInputStream inStream = new BufferedInputStream(new URL(dlUrl).openStream());
+ FileOutputStream fileOutputStream = new FileOutputStream(itemsZip)) {
byte dataBuffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) {
@@ -142,40 +289,18 @@ public class NEUManager {
} catch (IOException e) {
e.printStackTrace();
}
- }
- } else {
- //TODO: Store hard-coded value somewhere else
- String dlUrl = "https://github.com/Moulberry/NotEnoughUpdates-REPO/archive/master.zip";
- pane.setMessage("Downloading NEU Master Archive. (DL# >20)");
- dialog.pack();
- dialog.setVisible(true);
- if(Display.isActive()) dialog.toFront();
-
- File itemsZip = new File(configLocation, "neu-items-master.zip");
- try { itemsZip.createNewFile(); } catch(IOException e) { }
- try(BufferedInputStream inStream = new BufferedInputStream(new URL(dlUrl).openStream());
- FileOutputStream fileOutputStream = new FileOutputStream(itemsZip)) {
- 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();
- }
+ pane.setMessage("Unzipping NEU Master Archive.");
+ dialog.pack();
+ dialog.setVisible(true);
+ if (Display.isActive()) dialog.toFront();
- pane.setMessage("Unzipping NEU Master Archive.");
- dialog.pack();
- dialog.setVisible(true);
- if(Display.isActive()) dialog.toFront();
+ unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), configLocation.getAbsolutePath());
+ }
- unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), configLocation.getAbsolutePath());
+ dialog.dispose();
}
-
- dialog.dispose();
-
for(File f : itemsLocation.listFiles()) {
loadItem(f.getName().substring(0, f.getName().length()-5));
}
@@ -186,7 +311,8 @@ public class NEUManager {
* in to titleWordMap and loreWordMap. These maps are used in the searching algorithm.
* @param internalName
*/
- private void loadItem(String internalName) {
+ public void loadItem(String internalName) {
+ itemstackCache.remove(internalName);
try {
JsonObject json = getJsonFromFile(new File(itemsLocation, internalName + ".json"));
if(json == null) {
@@ -406,6 +532,28 @@ public class NEUManager {
return str.replaceAll("(\u00a7.)|[^0-9a-zA-Z ]", "").toLowerCase().trim();
}
+ public void showRecipe(JsonObject item) {
+ if(item.has("useneucraft") && item.get("useneucraft").getAsBoolean()) {
+ displayGuiItemRecipe(item.get("internalname").getAsString(), "");
+ } else if(item.has("clickcommand")) {
+ String clickcommand = item.get("clickcommand").getAsString();
+
+ if(clickcommand.equals("viewrecipe")) {
+ neu.sendChatMessage(
+ "/" + clickcommand + " " +
+ item.get("internalname").getAsString().split(";")[0]);
+ viewItemAttemptID = item.get("internalname").getAsString();
+ viewItemAttemptTime = System.currentTimeMillis();
+ } else if(clickcommand.equals("viewpotion")) {
+ neu.sendChatMessage(
+ "/" + clickcommand + " " +
+ item.get("internalname").getAsString().split(";")[0].toLowerCase());
+ viewItemAttemptID = item.get("internalname").getAsString();
+ viewItemAttemptTime = System.currentTimeMillis();
+ }
+ }
+ }
+
/**
* Takes an item stack and produces a JsonObject. This is used in the item editor.
*/
@@ -430,8 +578,8 @@ public class NEUManager {
stack.setStackDisplayName(stack.getDisplayName().substring(0, stack.getDisplayName().length()-8));
}
- if(lore.length > 0 && (lore[lore.length-1].endsWith("Click to view recipes!") ||
- lore[lore.length-1].endsWith("Click to view recipe!"))) {
+ if(lore.length > 0 && (lore[lore.length-1].contains("Click to view recipes!") ||
+ lore[lore.length-1].contains("Click to view recipe!"))) {
String[] lore2 = new String[lore.length-2];
System.arraycopy(lore, 0, lore2, 0, lore.length-2);
lore = lore2;
@@ -459,7 +607,7 @@ public class NEUManager {
NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
if(ea.hasKey("id", 8)) {
- return ea.getString("id");
+ return ea.getString("id").replaceAll(":", "-");
}
}
return null;
@@ -475,13 +623,9 @@ public class NEUManager {
JsonObject json = getJsonForItem(stack);
json.addProperty("internalname", internalname);
- json.addProperty("clickcommand", "viewrecipe");
+ json.addProperty("clickcommand", "");
json.addProperty("modver", NotEnoughUpdates.VERSION);
- if(!json.has("internalname")) {
- return;
- }
-
try {
writeJson(json, new File(itemsLocation, internalname+".json"));
} catch (IOException e) {}
@@ -489,13 +633,18 @@ public class NEUManager {
loadItem(internalname);
}
- public JsonObject createItemJson(String internalname, String itemid, String displayname, String[] lore, String[] info,
+ public JsonObject createItemJson(String internalname, String itemid, String displayname, String[] lore, String infoType, String[] info,
+ String clickcommand, int damage, NBTTagCompound nbttag) {
+ return createItemJson(new JsonObject(), internalname, itemid, displayname, lore, infoType, info, clickcommand, damage, nbttag);
+ }
+
+ public JsonObject createItemJson(JsonObject base, String internalname, String itemid, String displayname, String[] lore, String infoType, String[] info,
String clickcommand, int damage, NBTTagCompound nbttag) {
if(internalname == null || internalname.isEmpty()) {
return null;
}
- JsonObject json = new JsonObject();
+ JsonObject json = gson.fromJson(gson.toJson(base, JsonObject.class), JsonObject.class);
json.addProperty("internalname", internalname);
json.addProperty("itemid", itemid);
json.addProperty("displayname", displayname);
@@ -503,6 +652,7 @@ public class NEUManager {
json.addProperty("damage", damage);
json.addProperty("nbttag", nbttag.toString());
json.addProperty("modver", NotEnoughUpdates.VERSION);
+ json.addProperty("infoType", infoType.toString());
if(info != null && info.length > 0) {
JsonArray jsoninfo = new JsonArray();
@@ -514,7 +664,6 @@ public class NEUManager {
JsonArray jsonlore = new JsonArray();
for(String line : lore) {
- System.out.println("Lore:"+line);
jsonlore.add(new JsonPrimitive(line));
}
json.add("lore", jsonlore);
@@ -522,9 +671,14 @@ public class NEUManager {
return json;
}
- public boolean writeItemJson(String internalname, String itemid, String displayname, String[] lore, String[] info,
+ public boolean writeItemJson(String internalname, String itemid, String displayname, String[] lore, String infoType, String[] info,
+ String clickcommand, int damage, NBTTagCompound nbttag) {
+ return writeItemJson(new JsonObject(), internalname, itemid, displayname, lore, infoType, info, clickcommand, damage, nbttag);
+ }
+
+ public boolean writeItemJson(JsonObject base, String internalname, String itemid, String displayname, String[] lore, String infoType, String[] info,
String clickcommand, int damage, NBTTagCompound nbttag) {
- JsonObject json = createItemJson(internalname, itemid, displayname, lore, info, clickcommand, damage, nbttag);
+ JsonObject json = createItemJson(base, internalname, itemid, displayname, lore, infoType, info, clickcommand, damage, nbttag);
if(json == null) {
return false;
}
@@ -539,9 +693,9 @@ public class NEUManager {
return true;
}
- public boolean uploadItemJson(String internalname, String itemid, String displayname, String[] lore, String[] info,
+ public boolean uploadItemJson(String internalname, String itemid, String displayname, String[] lore, String infoType, String[] info,
String clickcommand, int damage, NBTTagCompound nbttag) {
- JsonObject json = createItemJson(internalname, itemid, displayname, lore, info, clickcommand, damage, nbttag);
+ JsonObject json = createItemJson(internalname, itemid, displayname, lore, infoType, info, clickcommand, damage, nbttag);
if(json == null) {
return false;
}
@@ -565,7 +719,7 @@ public class NEUManager {
return true;
}
- private void writeJson(JsonObject json, File file) throws IOException {
+ public void writeJson(JsonObject json, File file) throws IOException {
file.createNewFile();
try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {
@@ -573,7 +727,7 @@ public class NEUManager {
}
}
- private void writeJsonDefaultDir(JsonObject json, String filename) throws IOException {
+ public void writeJsonDefaultDir(JsonObject json, String filename) throws IOException {
File file = new File(itemsLocation, filename);
writeJson(json, file);
}
@@ -621,7 +775,151 @@ public class NEUManager {
} catch (IOException e) {
e.printStackTrace();
}
+ }
+
+ /**
+ * Stolen from https://www.journaldev.com/960/java-unzip-file-example
+ */
+ private static void unzip(InputStream src, File dest) {
+ //buffer for read and write data to file
+ byte[] buffer = new byte[1024];
+ try {
+ ZipInputStream zis = new ZipInputStream(src);
+ ZipEntry ze = zis.getNextEntry();
+ while(ze != null){
+ if(!ze.isDirectory()) {
+ String fileName = ze.getName();
+ File newFile = new File(dest, fileName);
+ //create directories for sub directories in zip
+ new File(newFile.getParent()).mkdirs();
+ FileOutputStream fos = new FileOutputStream(newFile);
+ int len;
+ while ((len = zis.read(buffer)) > 0) {
+ fos.write(buffer, 0, len);
+ }
+ fos.close();
+ }
+ //close this ZipEntry
+ zis.closeEntry();
+ ze = zis.getNextEntry();
+ }
+ //close last ZipEntry
+ zis.closeEntry();
+ zis.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public ItemStack jsonToStack(JsonObject json) {
+ if(itemstackCache.containsKey(json.get("internalname").getAsString())) {
+ return itemstackCache.get(json.get("internalname").getAsString());
+ }
+ ItemStack stack = new ItemStack(Item.itemRegistry.getObject(
+ new ResourceLocation(json.get("itemid").getAsString())));
+
+ if(stack.getItem() == null) {
+ stack = new ItemStack(Items.diamond, 1, 10); //Purple broken texture item
+ } else {
+ if(json.has("damage")) {
+ stack.setItemDamage(json.get("damage").getAsInt());
+ }
+
+ if(json.has("nbttag")) {
+ try {
+ NBTTagCompound tag = JsonToNBT.getTagFromJson(json.get("nbttag").getAsString());
+ stack.setTagCompound(tag);
+ } catch(NBTException e) {
+ }
+ }
+
+ if(json.has("lore")) {
+ NBTTagCompound display = stack.getTagCompound().getCompoundTag("display");
+ NBTTagList lore = new NBTTagList();
+ for(JsonElement line : json.get("lore").getAsJsonArray()) {
+ String lineStr = line.getAsString();
+ if(!lineStr.contains("Click to view recipes!") &&
+ !lineStr.contains("Click to view recipe!")) {
+ lore.appendTag(new NBTTagString(lineStr));
+ }
+ }
+ display.setTag("Lore", lore);
+ NBTTagCompound tag = stack.getTagCompound();
+ tag.setTag("display", display);
+ stack.setTagCompound(tag);
+ }
+ }
+
+ itemstackCache.put(json.get("internalname").getAsString(), stack);
+ return stack;
+ }
+
+ public boolean displayGuiItemRecipe(String internalName, String text) {
+ JsonObject item = getItemInformation().get(internalName);
+ if(item != null && item.has("recipe")) {
+ JsonObject recipe = item.get("recipe").getAsJsonObject();
+
+ ItemStack[] craftMatrix = new ItemStack[9];
+
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+ for(int i=0; i<9; i++) {
+ String name = y[i/3]+x[i%3];
+ String itemS = recipe.get(name).getAsString();
+ int count = 1;
+ if(itemS != null && itemS.split(":").length == 2) {
+ count = Integer.valueOf(itemS.split(":")[1]);
+ itemS = itemS.split(":")[0];
+ }
+ JsonObject craft = getItemInformation().get(itemS);
+ if(craft != null) {
+ ItemStack stack = jsonToStack(craft);
+ stack.stackSize = count;
+ craftMatrix[i] = stack;
+ }
+ }
+
+ Minecraft.getMinecraft().displayGuiScreen(new GuiItemRecipe(craftMatrix, item, text, this));
+ return true;
+ }
+ return false;
+ }
+
+ public boolean failViewItem(String text) {
+ if(viewItemAttemptID != null && !viewItemAttemptID.isEmpty()) {
+ if(System.currentTimeMillis() - viewItemAttemptTime < 500) {
+ return displayGuiItemRecipe(viewItemAttemptID, text);
+ }
+ }
+ return false;
+ }
+
+ public File getWebFile(String url) {
+ 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);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ 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 b86ad932..3eadcf25 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
@@ -3,31 +3,65 @@ package io.github.moulberry.notenoughupdates;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.mojang.realmsclient.gui.ChatFormatting;
+import info.bliki.htmlcleaner.TagNode;
+import info.bliki.wiki.filter.Encoder;
+import info.bliki.wiki.model.Configuration;
+import info.bliki.wiki.model.ImageFormat;
+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 info.bliki.wiki.tags.MathTag;
+import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField;
import io.github.moulberry.notenoughupdates.itemeditor.NEUItemEditor;
+import io.github.moulberry.notenoughupdates.options.Options;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*;
import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.client.renderer.*;
+import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
+import net.minecraft.client.renderer.entity.RenderEnderman;
import net.minecraft.client.renderer.entity.RenderItem;
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
-import net.minecraft.init.Blocks;
-import net.minecraft.init.Items;
+import net.minecraft.client.renderer.entity.RenderManager;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import net.minecraft.client.renderer.texture.TextureMap;
+import net.minecraft.client.resources.model.IBakedModel;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityList;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.boss.EntityDragon;
+import net.minecraft.entity.monster.EntityCaveSpider;
+import net.minecraft.entity.monster.EntityEnderman;
+import net.minecraft.entity.monster.EntitySpider;
+import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.inventory.Slot;
-import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.*;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
-import net.minecraftforge.fml.client.config.GuiUtils;
+import net.minecraft.world.World;
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+import javax.imageio.ImageIO;
import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.*;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.List;
+import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.regex.Matcher;
@@ -38,25 +72,85 @@ public class NEUOverlay extends Gui {
private NEUManager manager;
private ResourceLocation itemPaneTabArrow = new ResourceLocation("notenoughupdates:item_pane_tab_arrow.png");
- private ResourceLocation prev = new ResourceLocation("notenoughupdates:prev_pow2.png");
- private ResourceLocation next = new ResourceLocation("notenoughupdates:next_pow2.png");
+ private ResourceLocation prev = new ResourceLocation("notenoughupdates:prev.png");
+ private ResourceLocation next = new ResourceLocation("notenoughupdates:next.png");
private ResourceLocation item_edit = new ResourceLocation("notenoughupdates:item_edit.png");
+ private ResourceLocation close = new ResourceLocation("notenoughupdates:close.png");
+ private ResourceLocation settings = new ResourceLocation("notenoughupdates:settings.png");
+ private ResourceLocation off = new ResourceLocation("notenoughupdates:off.png");
+ private ResourceLocation on = new ResourceLocation("notenoughupdates:on.png");
+ private ResourceLocation help = new ResourceLocation("notenoughupdates:help.png");
+
+ private ResourceLocation sort_all = new ResourceLocation("notenoughupdates:sort_all.png");
+ private ResourceLocation sort_mob = new ResourceLocation("notenoughupdates:sort_mob.png");
+ private ResourceLocation sort_pet = new ResourceLocation("notenoughupdates:sort_pet.png");
+ private ResourceLocation sort_tool = new ResourceLocation("notenoughupdates:sort_weapon.png");
+ private ResourceLocation sort_armor = new ResourceLocation("notenoughupdates:sort_armor.png");
+ private ResourceLocation sort_accessory = new ResourceLocation("notenoughupdates:sort_accessory.png");
+ private ResourceLocation sort_all_active = new ResourceLocation("notenoughupdates:sort_all_active.png");
+ private ResourceLocation sort_mob_active = new ResourceLocation("notenoughupdates:sort_mob_active.png");
+ private ResourceLocation sort_pet_active = new ResourceLocation("notenoughupdates:sort_pet_active.png");
+ private ResourceLocation sort_tool_active = new ResourceLocation("notenoughupdates:sort_weapon_active.png");
+ private ResourceLocation sort_armor_active = new ResourceLocation("notenoughupdates:sort_armor_active.png");
+ private ResourceLocation sort_accessory_active = new ResourceLocation("notenoughupdates:sort_accessory_active.png");
+
+
+ private ResourceLocation order_alphabetical = new ResourceLocation("notenoughupdates:order_alphabetical.png");
+ private ResourceLocation order_rarity = new ResourceLocation("notenoughupdates:order_rarity.png");
+ private ResourceLocation order_alphabetical_active = new ResourceLocation("notenoughupdates:order_alphabetical_active.png");
+ private ResourceLocation order_rarity_active = new ResourceLocation("notenoughupdates:order_rarity_active.png");
+ private ResourceLocation ascending_overlay = new ResourceLocation("notenoughupdates:ascending_overlay.png");
+ private ResourceLocation descending_overlay = new ResourceLocation("notenoughupdates:descending_overlay.png");
+
+
+
+ private String mobRegex = ".*?((_MONSTER)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$";
+ private String petRegex = ".*?;[0-4]$";
+
+ private ResourceLocation[] sortIcons = new ResourceLocation[] {
+ sort_all, sort_mob, sort_pet, sort_tool, sort_armor, sort_accessory
+ };
+ private ResourceLocation[] sortIconsActive = new ResourceLocation[] {
+ sort_all_active, sort_mob_active, sort_pet_active, sort_tool_active, sort_armor_active, sort_accessory_active
+ };
+
+ private ResourceLocation[] orderIcons = new ResourceLocation[] {
+ order_alphabetical, order_rarity
+ };
+ private ResourceLocation[] orderIconsActive = new ResourceLocation[] {
+ order_alphabetical_active, order_rarity_active
+ };
+
+ private final WikiModel wikiModel;
private final int searchBarXSize = 200;
private final int searchBarYOffset = 10;
private final int searchBarYSize = 40;
private final int searchBarPadding = 2;
+ private final int ZOOM_FACTOR = 2;
+ private final int IMAGE_WIDTH = 400;
+
private final int boxPadding = 15;
private final int itemPadding = 4;
private final int itemSize = 16;
+ private Color bg = new Color(90, 90, 140, 50);
+ private Color fg = new Color(100,100,100, 255);
+
private String informationPaneTitle;
+ private ResourceLocation informationPaneImage = null;
+ private BufferedImage webpageLoadTemp = null;
+ private int informationPaneImageHeight = 0;
private String[] informationPane;
+ private AtomicInteger webpageAwaitID = new AtomicInteger(-1);
+ private boolean configOpen = false;
- private boolean allowItemEditing;
+ private static final int SCROLL_AMOUNT = 50;
+ private LerpingInteger scrollHeight = new LerpingInteger(0);
- private LinkedHashMap<String, JsonObject> searchedItems = null;
+ private TreeSet<JsonObject> searchedItems = null;
+ private JsonObject[] searchedItemsArr = null;
private boolean itemPaneOpen = false;
@@ -69,40 +163,110 @@ public class NEUOverlay extends Gui {
private boolean searchMode = false;
private long millisLastLeftClick = 0;
+ boolean mouseDown = false;
+
private boolean searchBarHasFocus = false;
GuiTextField textField = new GuiTextField(0, null, 0, 0, 0, 0);
+ Map<Options.Option<?>, GuiElementTextField> textConfigMap = new HashMap<>();
+
+ private static final int COMPARE_MODE_ALPHABETICAL = 0;
+ private static final int COMPARE_MODE_RARITY = 1;
+
+ private static final int SORT_MODE_ALL = 0;
+ private static final int SORT_MODE_MOB = 1;
+ private static final int SORT_MODE_PET = 2;
+ private static final int SORT_MODE_TOOL = 3;
+ private static final int SORT_MODE_ARMOR = 4;
+ private static final int SORT_MODE_ACCESSORY = 5;
+
+ private ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+
public NEUOverlay(NEUManager manager) {
this.manager = manager;
textField.setFocused(true);
textField.setCanLoseFocus(false);
- allowItemEditing = manager.getAllowEditing();
+ 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();
+ /*String sizeStr = imageFormat.getWidthStr();
+ if (sizeStr != null) {
+ imageName = sizeStr + '-' + imageName;
+ }*/
+ 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);
+ }
+ }
+ };
+
}
public void reset() {
searchBarHasFocus = false;
- itemPaneOpen = searchMode;
- itemPaneOffsetFactor.setValue(1);
- itemPaneTabOffset.setValue(20);
+ if(!(searchMode || (manager.config.keepopen.value && itemPaneOpen))) {
+ itemPaneOpen = false;
+ itemPaneOffsetFactor.setValue(1);
+ itemPaneTabOffset.setValue(20);
+ }
+ }
+
+ 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();
+ displayInformationPane(item.get("displayname").getAsString(), item.get("infoType").getAsString(), loreA);
+ }
}
/**
* Handles the mouse input, cancelling the forge event if a NEU gui element is clicked.
*/
public boolean mouseInput() {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledresolution.getScaledWidth();
int height = scaledresolution.getScaledHeight();
int mouseX = Mouse.getX() / scaledresolution.getScaleFactor();
int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor();
+ if(Mouse.getEventButtonState()) {
+ mouseDown = true;
+ } else if(Mouse.getEventButton() != -1) {
+ mouseDown = false;
+ }
+
//Unfocuses the search bar by default. Search bar is focused if the click is on the bar itself.
if(Mouse.getEventButtonState()) setSearchBarFocus(false);
//Item selection (right) gui
- if(mouseX > width*itemPaneOffsetFactor.getValue()) {
+ if(mouseX > width*getItemPaneOffsetFactor()) {
if(!Mouse.getEventButtonState()) return true; //End early if the mouse isn't pressed, but still cancel event.
AtomicBoolean clickedItem = new AtomicBoolean(false);
@@ -114,49 +278,112 @@ public class NEUOverlay extends Gui {
int id = getSlotId(x, y);
JsonObject item = getSearchedItemPage(id);
if (item != null) {
- if(item.has("clickcommand") && Mouse.getEventButton() == 0) {
- String clickcommand = item.get("clickcommand").getAsString();
-
- if(clickcommand.equals("viewrecipe")) {
- Minecraft.getMinecraft().thePlayer.sendChatMessage(
- "/" + clickcommand + " " + item.get("internalname").getAsString().toUpperCase());
- } else if(clickcommand.equals("viewpotion")) {
-
- Minecraft.getMinecraft().thePlayer.sendChatMessage(
- "/" + clickcommand + " " + item.get("internalname").getAsString().toLowerCase());
- }
- } else if(item.has("info") && Mouse.getEventButton() == 1) {
- 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();
- displayInformationPane(item.get("displayname").getAsString(), loreA);
- } else if(Mouse.getEventButton() == 3) {
- textField.setText("itemid:"+item.get("internalname").getAsString());
+ if(Mouse.getEventButton() == 0) {
+ manager.showRecipe(item);
+ } else if(Mouse.getEventButton() == 1) {
+ showInfo(item);
+ } else if(Mouse.getEventButton() == 2) {
+ textField.setText("id:"+item.get("internalname").getAsString());
+ updateSearch();
+ searchMode = true;
}
}
}
}
});
if(!clickedItem.get()) {
- int leftSide = (int)(width*itemPaneOffsetFactor.getValue());
+ int paneWidth = (int)(width/3*getWidthMult());
+ int leftSide = (int)(width*getItemPaneOffsetFactor());
+ int rightSide = leftSide+paneWidth-boxPadding-getItemBoxXPadding();
+
+ int scaledYSize = searchBarYSize/scaledresolution.getScaleFactor();
- if(mouseY > boxPadding && mouseY < boxPadding+searchBarYSize/scaledresolution.getScaleFactor()) {
+ if(mouseY >= boxPadding && mouseY <= boxPadding+getSearchBarYSize()) {
int leftPrev = leftSide+boxPadding+getItemBoxXPadding();
- if(mouseX > leftPrev && mouseX < leftPrev+120/scaledresolution.getScaleFactor()) { //"Previous" button
+ if(mouseX > leftPrev && mouseX < leftPrev+scaledYSize*400/160) { //"Previous" button
page--;
}
- int rightNext = leftSide+width/3-boxPadding-getItemBoxXPadding();
- if(mouseX > rightNext-120/scaledresolution.getScaleFactor() && mouseX < rightNext) {
+ int rightNext = leftSide+paneWidth-boxPadding-getItemBoxXPadding();
+ if(mouseX > rightNext-scaledYSize*400/160 && mouseX < rightNext) { //"Next" button
page++;
}
}
+
+ float sortIconsMinX = (sortIcons.length+orderIcons.length)*(itemSize+itemPadding)+itemSize;
+ float availableX = rightSide-(leftSide+boxPadding+getItemBoxXPadding());
+ float sortOrderScaleFactor = Math.min(1, availableX / sortIconsMinX);
+
+ int scaledItemSize = (int)(itemSize*sortOrderScaleFactor);
+ int scaledItemPaddedSize = (int)((itemSize+itemPadding)*sortOrderScaleFactor);
+ int iconTop = height-boxPadding-(itemSize+scaledItemSize)/2-1;
+
+ if(mouseY >= iconTop && mouseY <= iconTop+scaledItemSize) {
+ for(int i=0; i<orderIcons.length; i++) {
+ int orderIconX = leftSide+boxPadding+getItemBoxXPadding()+i*scaledItemPaddedSize;
+ if(mouseX >= orderIconX && mouseX <= orderIconX+scaledItemSize) {
+ if(Mouse.getEventButton() == 0) {
+ manager.config.compareMode.value = new Double(i);
+ updateSearch();
+ } else if(Mouse.getEventButton() == 1) {
+ manager.config.compareAscending.value.set(i, !manager.config.compareAscending.value.get(i));
+ updateSearch();
+ }
+ }
+ }
+
+ for(int i=0; i<sortIcons.length; i++) {
+ int sortIconX = rightSide-scaledItemSize-i*scaledItemPaddedSize;
+ if(mouseX >= sortIconX && mouseX <= sortIconX+scaledItemSize) {
+ manager.config.sortMode.value = new Double(i);
+ updateSearch();
+ }
+ }
+ }
}
return true;
}
+ if(Mouse.getEventButton() == 2) {
+ Slot slot = ((GuiContainer)Minecraft.getMinecraft().currentScreen).getSlotUnderMouse();
+ if(slot != null) {
+ ItemStack hover = slot.getStack();
+ if(hover != null) {
+ textField.setText("id:"+manager.getInternalNameForItem(hover));
+ updateSearch();
+ searchMode = true;
+ }
+ }
+ }
+
+ //Left gui
+ if(mouseX < width*infoPaneOffsetFactor.getValue()) {
+ int dWheel = Mouse.getEventDWheel();
+
+ if(dWheel < 0) {
+ scrollHeight.setTarget(scrollHeight.getTarget()+SCROLL_AMOUNT);
+ scrollHeight.resetTimer();
+ return true;
+ } else if(dWheel > 0) {
+ scrollHeight.setTarget(scrollHeight.getTarget()-SCROLL_AMOUNT);
+ scrollHeight.resetTimer();
+ return true;
+ }
+ }
+
+ if(mouseX > width*getInfoPaneOffsetFactor()-22 && mouseX < width*getInfoPaneOffsetFactor()-6) {
+ if(mouseY > 7 && mouseY < 23) {
+ if(Mouse.getEventButtonState() && Mouse.getEventButton() < 2) { //Left or right click up
+ informationPaneTitle = null;
+ informationPaneImage = null;
+ informationPane = new String[0];
+ configOpen = false;
+ }
+ }
+ }
+
//Search bar
if(mouseX >= width/2 - searchBarXSize/2 && mouseX <= width/2 + searchBarXSize/2) {
- if(mouseY >= height - searchBarYOffset - searchBarYSize/scaledresolution.getScaleFactor() &&
+ if(mouseY >= height - searchBarYOffset - getSearchBarYSize() &&
mouseY <= height - searchBarYOffset) {
if(Mouse.getEventButtonState()) {
setSearchBarFocus(true);
@@ -176,36 +403,225 @@ public class NEUOverlay extends Gui {
}
int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor();
- int topTextBox = height - searchBarYOffset - searchBarYSize/scaledresolution.getScaleFactor();
- int iconSize = searchBarYSize/scaledresolution.getScaleFactor()+paddingUnscaled*2;
+ int topTextBox = height - searchBarYOffset - getSearchBarYSize();
+ int iconSize = getSearchBarYSize()+paddingUnscaled*2;
if(paddingUnscaled < 1) paddingUnscaled = 1;
- if(mouseX > width/2 + searchBarXSize/2 + paddingUnscaled*6 &&
- mouseX < width/2 + searchBarXSize/2 + paddingUnscaled*6 + iconSize) {
- if(mouseY > topTextBox - paddingUnscaled && mouseY < topTextBox - paddingUnscaled + iconSize) {
+
+ if(mouseY > topTextBox - paddingUnscaled && mouseY < topTextBox - paddingUnscaled + iconSize) {
+ if(mouseX > width/2 + searchBarXSize/2 + paddingUnscaled*6 &&
+ mouseX < width/2 + searchBarXSize/2 + paddingUnscaled*6 + iconSize) {
+ if(Mouse.getEventButtonState()) {
+ manager.config.enableItemEditing.value = !manager.config.enableItemEditing.value;
+ }
+ } else if(mouseX > width/2 - searchBarXSize/2 - paddingUnscaled*6 - iconSize &&
+ mouseX < width/2 - searchBarXSize/2 - paddingUnscaled*6) {
if(Mouse.getEventButtonState()) {
- allowItemEditing = !allowItemEditing;
- manager.setAllowEditing(allowItemEditing);
+ configOpen = !configOpen;
+ infoPaneOffsetFactor.setTarget(1/3f);
+ infoPaneOffsetFactor.resetTimer();
+
}
}
}
+ iterateSettingTile(new SettingsTileConsumer() {
+ @Override
+ public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option) {
+ float mult = tileWidth/90f;
+ if(option.value instanceof Boolean) {
+ if(Mouse.getEventButtonState()) {
+ if(mouseX > x+tileWidth/2-(int)(32*mult) && mouseX < x+tileWidth/2-(int)(32*mult)+(int)(48*mult)) {
+ if(mouseY > y+tileHeight-(int)(20*mult) && mouseY < y+tileHeight-(int)(20*mult)+(int)(16*mult)) {
+ ((Options.Option<Boolean>)option).value = !((Boolean)option.value);
+ }
+ }
+ }
+ } else {
+ if(!textConfigMap.containsKey(option)) {
+ textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0));
+ }
+ GuiElementTextField tf = textConfigMap.get(option);
+ if(mouseX > x+(int)(10*mult) && mouseX < x+(int)(10*mult)+tileWidth-(int)(20*mult)) {
+ if(mouseY > y+tileHeight-(int)(20*mult) && mouseY < y+tileHeight-(int)(20*mult)+(int)(16*mult)) {
+ if(Mouse.getEventButtonState()) {
+ tf.mouseClicked(mouseX, mouseY, Mouse.getEventButton());
+ } else if(Mouse.getEventButton() == -1 && mouseDown) {
+ tf.mouseClickMove(mouseX, mouseY, 0, 0); //last 2 values are unused
+ }
+ return;
+ }
+ }
+ if(Mouse.getEventButtonState()) tf.otherComponentClick();
+ }
+ }
+ });
+
return false;
}
- public void displayInformationPane(String title, String[] info) {
+ //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();
+ }
+
+ ExecutorService ste = Executors.newSingleThreadExecutor();
+
+ private void processAndSetWebpageImage(String html, String name) {
+ File cssFile = new File(manager.configLocation, "wikia.css");
+ File wkHtmlToImage = new File(manager.configLocation, "wkhtmltox/bin/wkhtmltoimage");
+ File input = new File(manager.configLocation, "tmp/input.html");
+ File output = new File(manager.configLocation, "tmp/"+
+ name.replaceAll("(?i)\\u00A7.", "")
+ .replaceAll("[^a-zA-Z0-9_\\-]", "_")+".png");
+ input.deleteOnExit();
+ output.deleteOnExit();
+
+ if(output.exists()) {
+ try {
+ webpageLoadTemp = ImageIO.read(output);
+ informationPane = new String[] { EnumChatFormatting.RED+"Failed to set informationPaneImage." };
+ } catch(IOException e) {
+ e.printStackTrace();
+ informationPaneImage = null;
+ informationPane = new String[] { EnumChatFormatting.RED+"ERROR" };
+ 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()+"\">\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 {
+ final int awaitID = webpageAwaitID.get();
+
+ informationPane = new String[] { EnumChatFormatting.GRAY+"Rendering webpage, please wait... (AwaitID: "+awaitID+")" };
+
+ Runtime runtime = Runtime.getRuntime();
+ Process p = runtime.exec("\""+wkHtmlToImage.getAbsolutePath() + "\" --width "+ IMAGE_WIDTH*ZOOM_FACTOR+" --transparent --zoom "+ZOOM_FACTOR+" \"" + input.getAbsolutePath() + "\" \"" + output.getAbsolutePath() + "\"");
+ ste.submit(() -> {
+ try {
+ if(p.waitFor(15, TimeUnit.SECONDS)) {
+ if(awaitID != webpageAwaitID.get()) return;
+
+ try {
+ webpageLoadTemp = ImageIO.read(output);
+ informationPane = new String[] { EnumChatFormatting.RED+"Failed to set informationPaneImage." };
+ } catch(IOException e) {
+ e.printStackTrace();
+ informationPaneImage = null;
+ informationPane = new String[] { EnumChatFormatting.RED+"ERROR" };
+ return;
+ }
+ } else {
+ if(awaitID != webpageAwaitID.get()) return;
+
+ informationPane = new String[] { EnumChatFormatting.RED+"Webpage render timed out (>15sec). Maybe it's too large?" };
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ });
+ } catch(Exception e) {
+ e.printStackTrace();
+ informationPaneImage = null;
+ informationPane = new String[] { EnumChatFormatting.RED+"ERROR" };
+ return;
+ }
+ }
+ }
+
+ public void displayInformationPane(String title, String infoType, String[] info) {
+ scrollHeight.setValue(0);
informationPaneTitle = title;
+ informationPaneImage = null;
+ informationPane = null;
+
+ configOpen = false;
+
+ infoPaneOffsetFactor.setTarget(1/3f);
+ infoPaneOffsetFactor.resetTimer();
+
+ webpageAwaitID.incrementAndGet();
if(info == null || info.length == 0) {
informationPane = new String[]{"\u00A77No additional information."};
} else {
- informationPane = info;
+ String joined = StringUtils.join(info, "\n");
+ String wiki = null;
+ String html = null;
+ if(infoType.equals("TEXT")) {
+ informationPane = info;
+ return;
+ } else if(infoType.equals("WIKI_URL")) {
+ File f = manager.getWebFile(joined);
+ if(f == null) {
+ informationPane = new String[] { EnumChatFormatting.RED+"Failed to load wiki url: "+joined };
+ return;
+ };
+
+ 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) {
+ informationPane = new String[] { EnumChatFormatting.RED+"Failed to load wiki url: "+joined };
+ return;
+ }
+ wiki = sb.toString();
+ }
+
+ if(infoType.equals("WIKI") || wiki != null) {
+ if(wiki == null) wiki = joined;
+ try {
+ 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) {
+ }
+ html = wikiModel.render(wiki);
+ try (PrintWriter out = new PrintWriter(new File(manager.configLocation, "debug/html.txt"))) {
+ out.println(html);
+ } catch (IOException e) {
+ }
+ } catch (Exception e) {
+ informationPane = new String[]{EnumChatFormatting.RED + "Failed to parse wiki: " + joined};
+ return;
+ }
+ }
+
+ if(infoType.equals("HTML") || html != null) {
+ if(html == null) html = joined;
+ processAndSetWebpageImage(html, title);
+ }
}
- infoPaneOffsetFactor.setTarget(1/3f);
- infoPaneOffsetFactor.resetTimer();
}
public int getClickedIndex(int mouseX, int mouseY) {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledresolution.getScaledWidth();
int height = scaledresolution.getScaledHeight();
@@ -235,82 +651,244 @@ public class NEUOverlay extends Gui {
* Handles the keyboard input, cancelling the forge event if the search bar has focus.
*/
public boolean keyboardInput() {
- if(searchBarHasFocus && Keyboard.getEventKey() == 1 && Keyboard.getEventKeyState()) {
- searchBarHasFocus = false;
- if(!textField.getText().isEmpty()) {
- return true;
- }
- }
+ if(Minecraft.getMinecraft().currentScreen == null) return false;
- if(searchBarHasFocus && Keyboard.getEventKeyState()) {
- if(textField.textboxKeyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey())) {
- if(textField.getText().isEmpty()) {
- searchedItems = null;
+ if(Keyboard.getEventKeyState()) {
+ if(searchBarHasFocus) {
+ if(Keyboard.getEventKey() == 1) {
+ searchBarHasFocus = false;
} else {
- updateSearch();
+ if(textField.textboxKeyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey())) {
+ updateSearch();
+ }
}
+ } else {
+ if(Keyboard.getEventKey() == Keyboard.KEY_LEFT) yaw--;
+ if(Keyboard.getEventKey() == Keyboard.KEY_RIGHT) yaw++;
+ if(Keyboard.getEventKey() == Keyboard.KEY_UP) pitch--;
+ if(Keyboard.getEventKey() == Keyboard.KEY_DOWN) pitch++;
+
+ iterateSettingTile(new SettingsTileConsumer() {
+ @Override
+ public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option) {
+ if(!textConfigMap.containsKey(option)) {
+ textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0));
+ }
+ GuiElementTextField tf = textConfigMap.get(option);
+
+ if(!(option.value instanceof Boolean)) {
+ tf.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
+ }
+ }
+ });
}
}
- if(allowItemEditing) {
- if(Keyboard.getEventCharacter() == 'k' && Keyboard.getEventKeyState()) {
- Slot slot = ((GuiContainer)Minecraft.getMinecraft().currentScreen).getSlotUnderMouse();
- if(slot != null) {
- ItemStack hover = slot.getStack();
- if(hover != null) {
+ if(Keyboard.getEventKeyState()) {
+ AtomicReference<String> internalname = new AtomicReference<>(null);
+ Slot slot = ((GuiContainer)Minecraft.getMinecraft().currentScreen).getSlotUnderMouse();
+ if(slot != null) {
+ ItemStack hover = slot.getStack();
+ if(hover != null) {
+ internalname.set(manager.getInternalNameForItem(hover));
+ }
+ } else {
+ int height = scaledresolution.getScaledHeight();
+
+ int mouseX = Mouse.getX() / scaledresolution.getScaleFactor();
+ int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor();
+
+ iterateItemSlots((x, y) -> {
+ if (mouseX >= x - 1 && mouseX <= x + itemSize + 1) {
+ if (mouseY >= y - 1 && mouseY <= y + itemSize + 1) {
+ int id = getSlotId(x, y);
+ JsonObject json = getSearchedItemPage(id);
+ if(json != null) internalname.set(json.get("internalname").getAsString());
+ return;
+ }
+ }
+ });
+ }
+ if(internalname.get() != null) {
+ JsonObject item = manager.getItemInformation().get(internalname.get());
+ if(item != null) {
+ if(manager.config.enableItemEditing.value && Keyboard.getEventCharacter() == 'k') {
Minecraft.getMinecraft().displayGuiScreen(new NEUItemEditor(manager,
- manager.getInternalNameForItem(hover), manager.getJsonForItem(hover)));
- //manager.writeItemToFile(hover);
+ item.get("internalname").getAsString(), item));
+ return true;
+ } else if(Keyboard.getEventCharacter() == 'f') {
+ toggleRarity(item.get("internalname").getAsString());
+ return true;
+ } else if(Keyboard.getEventCharacter() == 'r') {
+ manager.showRecipe(item);
+ return true;
}
- } else {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
- int height = scaledresolution.getScaledHeight();
+ }
+ }
+ }
- int mouseX = Mouse.getX() / scaledresolution.getScaleFactor();
- int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor();
+ return searchBarHasFocus; //Cancels keyboard events if the search bar has focus
+ }
- iterateItemSlots((x, y) -> {
- if (mouseX >= x - 1 && mouseX <= x + itemSize + 1) {
- if (mouseY >= y - 1 && mouseY <= y + itemSize + 1) {
- int id = getSlotId(x, y);
- JsonObject item = getSearchedItemPage(id);
+ public void toggleRarity(String internalname) {
+ if(getFavourites().contains(internalname)) {
+ getFavourites().remove(internalname);
+ } else {
+ getFavourites().add(internalname);
+ }
+ updateSearch();
+ }
- if(item != null) {
- Minecraft.getMinecraft().displayGuiScreen(new NEUItemEditor(manager,
- item.get("internalname").getAsString(), item));
- }
- }
- }
- });
+ String[] rarityArr = new String[] {
+ EnumChatFormatting.WHITE+EnumChatFormatting.BOLD.toString()+"COMMON",
+ EnumChatFormatting.GREEN+EnumChatFormatting.BOLD.toString()+"UNCOMMON",
+ EnumChatFormatting.BLUE+EnumChatFormatting.BOLD.toString()+"RARE",
+ EnumChatFormatting.DARK_PURPLE+EnumChatFormatting.BOLD.toString()+"EPIC",
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD.toString()+"LEGENDARY",
+ EnumChatFormatting.LIGHT_PURPLE+EnumChatFormatting.BOLD.toString()+"SPECIAL",
+ };
+ public int getRarity(JsonArray lore) {
+ for(int i=lore.size()-1; i>=0; i--) {
+ String line = lore.get(i).getAsString();
+
+ for(int j=0; j<rarityArr.length; j++) {
+ if(line.startsWith(rarityArr[j])) {
+ return j;
}
}
}
+ return -1;
+ }
- return searchBarHasFocus; //Cancels keyboard events if the search bar has focus
+ private int getCompareMode() {
+ return manager.config.compareMode.value.intValue();
+ }
+ private int getSortMode() {
+ return manager.config.sortMode.value.intValue();
+ }
+ private List<Boolean> getCompareAscending() {
+ return manager.config.compareAscending.value;
+ }
+ private List<String> getFavourites() {
+ return manager.config.favourites.value;
+ }
+
+ private Comparator<JsonObject> getItemComparator() {
+ return (o1, o2) -> {
+ //1 (mult) if o1 should appear after o2
+ //-1 (-mult) if o2 should appear after o1
+ if(getFavourites().contains(o1.get("internalname").getAsString()) && !getFavourites().contains(o2.get("internalname").getAsString())) {
+ return -1;
+ }
+ if(!getFavourites().contains(o1.get("internalname").getAsString()) && getFavourites().contains(o2.get("internalname").getAsString())) {
+ return 1;
+ }
+
+ int mult = getCompareAscending().get(getCompareMode()) ? 1 : -1;
+ if(getCompareMode() == COMPARE_MODE_RARITY) {
+ int rarity1 = getRarity(o1.get("lore").getAsJsonArray());
+ int rarity2 = getRarity(o2.get("lore").getAsJsonArray());
+
+ if(rarity1 < rarity2) return mult;
+ if(rarity1 > rarity2) return -mult;
+ }
+
+ String i1 = o1.get("internalname").getAsString();
+ String[] split1 = i1.split("_");
+ String last1 = split1[split1.length-1];
+ String start1 = i1.substring(0, i1.length()-last1.length());
+
+ String i2 = o2.get("internalname").getAsString();
+ String[] split2 = i2.split("_");
+ String last2 = split2[split2.length-1];
+ String start2 = i2.substring(0, i2.length()-last2.length());
+
+ mult = getCompareAscending().get(COMPARE_MODE_ALPHABETICAL) ? 1 : -1;
+ if(start1.equals(start2)) {
+ String[] order = new String[]{"HELMET","CHESTPLATE","LEGGINGS","BOOTS"};
+ int type1 = checkItemType(o1.get("lore").getAsJsonArray(), order);
+ int type2 = checkItemType(o2.get("lore").getAsJsonArray(), order);
+
+
+ if(type1 < type2) return -mult;
+ if(type1 > type2) return mult;
+ }
+
+ int nameComp = mult*o1.get("displayname").getAsString().replaceAll("(?i)\\u00A7.", "")
+ .compareTo(o2.get("displayname").getAsString().replaceAll("(?i)\\u00A7.", ""));
+ if(nameComp != 0) {
+ return nameComp;
+ }
+ return mult*o1.get("internalname").getAsString().compareTo(o2.get("internalname").getAsString());
+ };
+ }
+
+ public int checkItemType(JsonArray lore, String... typeMatches) {
+ for(int i=lore.size()-1; i>=0; i--) {
+ String line = lore.get(i).getAsString();
+
+ for(String rarity : rarityArr) {
+ for(int j=0; j<typeMatches.length; j++) {
+ if(line.trim().equals(rarity + " " + typeMatches[j])) {
+ return j;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ public boolean checkMatchesSort(String internalname, JsonObject item) {
+ if(getSortMode() == SORT_MODE_ALL) {
+ return !internalname.matches(mobRegex);
+ } else if(getSortMode() == SORT_MODE_MOB) {
+ return internalname.matches(mobRegex);
+ } else if(getSortMode() == SORT_MODE_PET) {
+ return internalname.matches(petRegex);
+ } else if(getSortMode() == SORT_MODE_TOOL) {
+ return checkItemType(item.get("lore").getAsJsonArray(),
+ "SWORD", "BOW", "AXE", "PICKAXE", "FISHING ROD", "WAND", "SHOVEL", "HOE") >= 0;
+ } else if(getSortMode() == SORT_MODE_ARMOR) {
+ return checkItemType(item.get("lore").getAsJsonArray(), "HELMET", "CHESTPLATE", "LEGGINGS", "BOOTS") >= 0;
+ } else if(getSortMode() == SORT_MODE_ACCESSORY) {
+ return checkItemType(item.get("lore").getAsJsonArray(), "ACCESSORY") >= 0;
+ }
+ return true;
}
public void updateSearch() {
- if(searchedItems==null) searchedItems = new LinkedHashMap<>();
+ if(searchedItems==null) searchedItems = new TreeSet<>(getItemComparator());
searchedItems.clear();
+ searchedItemsArr = null;
Set<String> itemsMatch = manager.search(textField.getText());
- for(String item : itemsMatch) {
- searchedItems.put(item, manager.getItemInformation().get(item));
+ for(String itemname : itemsMatch) {
+ JsonObject item = manager.getItemInformation().get(itemname);
+ if(checkMatchesSort(itemname, item)) {
+ searchedItems.add(item);
+ }
}
}
- public Collection<JsonObject> getSearchedItems() {
+ public JsonObject[] getSearchedItems() {
if(searchedItems==null) {
- return manager.getItemInformation().values();
- } else {
- return searchedItems.values();
+ updateSearch();
+ }
+ if(searchedItemsArr==null) {
+ searchedItemsArr = new JsonObject[searchedItems.size()];
+ int i=0;
+ for(JsonObject item : searchedItems) {
+ searchedItemsArr[i] = item;
+ i++;
+ }
}
+ return searchedItemsArr;
}
public JsonObject getSearchedItemPage(int index) {
if(index < getSlotsXSize()*getSlotsYSize()) {
int actualIndex = index + getSlotsXSize()*getSlotsYSize()*page;
- if(actualIndex < getSearchedItems().size()) {
- return (JsonObject) (getSearchedItems().toArray()[actualIndex]);
+ if(actualIndex < getSearchedItems().length) {
+ return getSearchedItems()[actualIndex];
} else {
return null;
}
@@ -320,9 +898,8 @@ public class NEUOverlay extends Gui {
}
public int getItemBoxXPadding() {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledresolution.getScaledWidth();
- return (((int)(width-width*itemPaneOffsetFactor.getValue())-2*boxPadding)%(itemSize+itemPadding)+itemPadding)/2;
+ return (((int)(width-width*getItemPaneOffsetFactor())-2*boxPadding)%(itemSize+itemPadding)+itemPadding)/2;
}
/**
@@ -331,17 +908,17 @@ public class NEUOverlay extends Gui {
* code duplication issues.
*/
public void iterateItemSlots(BiConsumer<Integer, Integer> itemSlotConsumer) {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledresolution.getScaledWidth();
int height = scaledresolution.getScaledHeight();
+ int paneWidth = (int)(width/3*getWidthMult());
int itemBoxXPadding = getItemBoxXPadding();
- int itemBoxYPadding = ((height-2*boxPadding)%(itemSize+itemPadding)+itemPadding)/2;
+ int itemBoxYPadding = ((height-getSearchBarYSize()-2*boxPadding-itemSize-2)%(itemSize+itemPadding)+itemPadding)/2;
- int xStart = (int)(width*itemPaneOffsetFactor.getValue())+boxPadding+itemBoxXPadding;
- int yStart = boxPadding+searchBarYSize/scaledresolution.getScaleFactor()+itemBoxYPadding;
- int xEnd = (int)(width*itemPaneOffsetFactor.getValue())+width/3-boxPadding-itemSize;
- int yEnd = height-boxPadding-itemSize;
+ int xStart = (int)(width*getItemPaneOffsetFactor())+boxPadding+itemBoxXPadding;
+ int yStart = boxPadding+getSearchBarYSize()+itemBoxYPadding;
+ int xEnd = (int)(width*getItemPaneOffsetFactor())+paneWidth-boxPadding-itemSize;
+ int yEnd = height-boxPadding-itemSize-2-itemBoxYPadding;
//Render the items, displaying the tooltip if the cursor is over the item
for(int y = yStart; y < yEnd; y+=itemSize+itemPadding) {
@@ -351,16 +928,22 @@ public class NEUOverlay extends Gui {
}
}
+ public float getWidthMult() {
+ float scaleFMult = 1;
+ if(scaledresolution.getScaleFactor()==4) scaleFMult = 0.9f;
+ return (float)Math.min(1.5, Math.max(0.5, manager.config.paneWidthMult.value.floatValue()))*scaleFMult;
+ }
+
/**
* Calculates the number of horizontal item slots.
*/
public int getSlotsXSize() {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledresolution.getScaledWidth();
- int itemBoxXPadding = (((int)(width-width*itemPaneOffsetFactor.getValue())-2*boxPadding)%(itemSize+itemPadding)+itemPadding)/2;
- int xStart = (int)(width*itemPaneOffsetFactor.getValue())+boxPadding+itemBoxXPadding;
- int xEnd = (int)(width*itemPaneOffsetFactor.getValue())+width/3-boxPadding-itemSize;
+ int paneWidth = (int)(width/3*getWidthMult());
+ int itemBoxXPadding = (((int)(width-width*getItemPaneOffsetFactor())-2*boxPadding)%(itemSize+itemPadding)+itemPadding)/2;
+ int xStart = (int)(width*getItemPaneOffsetFactor())+boxPadding+itemBoxXPadding;
+ int xEnd = (int)(width*getItemPaneOffsetFactor())+paneWidth-boxPadding-itemSize;
return (int)Math.ceil((xEnd - xStart)/((float)(itemSize+itemPadding)));
}
@@ -369,62 +952,155 @@ public class NEUOverlay extends Gui {
* Calculates the number of vertical item slots.
*/
public int getSlotsYSize() {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
int height = scaledresolution.getScaledHeight();
- int itemBoxYPadding = ((height-2*boxPadding)%(itemSize+itemPadding)+itemPadding)/2;
- int yStart = boxPadding+searchBarYSize/scaledresolution.getScaleFactor()+itemBoxYPadding;
- int yEnd = height-boxPadding-itemSize;
+ int itemBoxYPadding = ((height-getSearchBarYSize()-2*boxPadding-itemSize-2)%(itemSize+itemPadding)+itemPadding)/2;
+ int yStart = boxPadding+getSearchBarYSize()+itemBoxYPadding;
+ int yEnd = height-boxPadding-itemSize-2-itemBoxYPadding;
return (int)Math.ceil((yEnd - yStart)/((float)(itemSize+itemPadding)));
}
public int getMaxPages() {
- if(getSearchedItems().size() == 0) return 1;
- return (int)Math.ceil(getSearchedItems().size()/(float)getSlotsYSize()/getSlotsXSize());
+ if(getSearchedItems().length == 0) return 1;
+ return (int)Math.ceil(getSearchedItems().length/(float)getSlotsYSize()/getSlotsXSize());
}
/**
* Takes in the x and y coordinates of a slot and returns the id of that slot.
*/
public int getSlotId(int x, int y) {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledresolution.getScaledWidth();
int height = scaledresolution.getScaledHeight();
- int itemBoxXPadding = (((int)(width-width*itemPaneOffsetFactor.getValue())-2*boxPadding)%(itemSize+itemPadding)+itemPadding)/2;
- int itemBoxYPadding = ((height-2*boxPadding)%(itemSize+itemPadding)+itemPadding)/2;
+ int itemBoxXPadding = (((int)(width-width*getItemPaneOffsetFactor())-2*boxPadding)%(itemSize+itemPadding)+itemPadding)/2;
+ int itemBoxYPadding = ((height-getSearchBarYSize()-2*boxPadding-itemSize-2)%(itemSize+itemPadding)+itemPadding)/2;
- int xStart = (int)(width*itemPaneOffsetFactor.getValue())+boxPadding+itemBoxXPadding;
- int yStart = boxPadding+searchBarYSize/scaledresolution.getScaleFactor()+itemBoxYPadding;
+ int xStart = (int)(width*getItemPaneOffsetFactor())+boxPadding+itemBoxXPadding;
+ int yStart = boxPadding+getSearchBarYSize()+itemBoxYPadding;
int xIndex = (x-xStart)/(itemSize+itemPadding);
int yIndex = (y-yStart)/(itemSize+itemPadding);
return xIndex + yIndex*getSlotsXSize();
}
- /**
- * Renders the search bar, item selection (right) and item info (left) gui elements.
- */
- public void render(float partialTicks, int mouseX, int mouseY) {
+ private int getSearchBarYSize() {
+ return Math.max(searchBarYSize/scaledresolution.getScaleFactor(), itemSize);
+ }
+
+ public void renderNavElement(int leftSide, int rightSide, int maxPages, String name) {
FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
- int width = scaledresolution.getScaledWidth();
- int height = scaledresolution.getScaledHeight();
+ drawRect(leftSide-1, boxPadding,
+ rightSide+1,
+ boxPadding+getSearchBarYSize(), fg.getRGB());
+
+ float scaledYSize = searchBarYSize/scaledresolution.getScaleFactor();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(prev);
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ drawTexturedRect(leftSide, boxPadding+(getSearchBarYSize()-scaledYSize)/2f,
+ scaledYSize*400/160, scaledYSize);
+ GlStateManager.bindTexture(0);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(next);
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ drawTexturedRect(rightSide-scaledYSize*400/160, boxPadding+(getSearchBarYSize()-scaledYSize)/2f,
+ scaledYSize*400/160, scaledYSize);
+ GlStateManager.bindTexture(0);
+
+ String pageText = EnumChatFormatting.BOLD+name + (page+1) + "/" + maxPages;
+ fr.drawString(pageText, (leftSide+rightSide)/2-fr.getStringWidth(pageText)/2,
+ boxPadding+(getSearchBarYSize()-8)/2+1, Color.BLACK.getRGB());
+ }
+
+ private int limCol(int col) {
+ return Math.min(255, Math.max(0, col));
+ }
+
+ public float yaw = 0;
+ public float pitch = 20;
+
+ private void renderEntity(float posX, float posY, float scale, String name, Class<? extends EntityLivingBase>... classes) {
+ EntityLivingBase[] entities = new EntityLivingBase[classes.length];
+ try {
+ EntityLivingBase last = null;
+ for(int i=0; i<classes.length; i++) {
+ Class<? extends EntityLivingBase> clazz = classes[i];
+ if(clazz == null) continue;
+
+ EntityLivingBase newEnt = clazz.getConstructor(new Class[] {World.class}).newInstance(Minecraft.getMinecraft().theWorld);
+
+ //newEnt.renderYawOffset = yaw;
+ //newEnt.rotationYaw = yaw;
+ newEnt.rotationPitch = pitch;
+ //newEnt.rotationYawHead = yaw;
+ //newEnt.prevRotationYawHead = yaw-1;
+
+ newEnt.setCustomNameTag(name);
+
+ if(last != null) {
+ last.riddenByEntity = newEnt;
+ newEnt.ridingEntity = last;
+ last.updateRiderPosition();
+ }
+ last = newEnt;
+
+ entities[i] = newEnt;
+ }
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+ e.printStackTrace();
+ return;
+ }
+
+
+ GlStateManager.enableColorMaterial();
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(posX, posY, 50.0F);
+ GlStateManager.scale(-scale, scale, scale);
+ GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F);
+
+ GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F);
+ RenderHelper.enableStandardItemLighting();
+ GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F);
+
+ GlStateManager.rotate(pitch, 1.0F, 0.0F, 0.0F);
+ GlStateManager.rotate(yaw, 0.0F, 1.0F, 0.0F);
+
+ RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager();
+ rendermanager.setPlayerViewY(180.0F);
+ rendermanager.setRenderShadow(false);
+ for(EntityLivingBase ent : entities) {
+ GL11.glColor4f(1,1,1,1);
+ if(ent != null) rendermanager.renderEntityWithPosYaw(ent, ent.posX, ent.posY, ent.posZ, 0.0F, 1.0F);
+ }
+ rendermanager.setRenderShadow(true);
+
+ GlStateManager.popMatrix();
+ RenderHelper.disableStandardItemLighting();
+ GlStateManager.disableRescaleNormal();
+ GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit);
+ GlStateManager.disableTexture2D();
+ GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit);
+
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ }
+
+ public void renderOverlay(int mouseX, int mouseY) {
if(searchMode && textField.getText().length() > 0) {
+ int width = scaledresolution.getScaledWidth();
+ int height = scaledresolution.getScaledHeight();
try {
GuiContainer inv = (GuiContainer) Minecraft.getMinecraft().currentScreen;
- Field guiLeft = GuiContainer.class.getDeclaredField("field_147003_i");
- Field guiTop = GuiContainer.class.getDeclaredField("field_147009_r");
+ Field guiLeft = GuiContainer.class.getDeclaredField("field_147003_i");//guiLeft
+ Field guiTop = GuiContainer.class.getDeclaredField("field_147009_r");//guiTop
guiLeft.setAccessible(true);
guiTop.setAccessible(true);
int guiLeftI = (int) guiLeft.get(inv);
int guiTopI = (int) guiTop.get(inv);
- GL11.glPushMatrix();
GL11.glTranslatef(0, 0, 300);
- int overlay = new Color(50, 50, 50, 150).getRGB();
+ int overlay = new Color(0, 0, 0, 100).getRGB();
for(Slot slot : inv.inventorySlots.inventorySlots) {
if(slot.getStack() == null || !manager.doesStackMatchSearch(slot.getStack(), textField.getText())) {
drawRect(guiLeftI+slot.xDisplayPosition, guiTopI+slot.yDisplayPosition,
@@ -440,20 +1116,53 @@ public class NEUOverlay extends Gui {
for (int i = 0; i < list.size(); ++i){
if (i == 0){
- list.set(i, stack.getRarity().rarityColor + (String)list.get(i));
+ list.set(i, stack.getRarity().rarityColor + list.get(i));
} else {
- list.set(i, EnumChatFormatting.GRAY + (String)list.get(i));
+ list.set(i, EnumChatFormatting.GRAY + list.get(i));
}
}
- GuiUtils.drawHoveringText(list, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj);
+ Utils.drawHoveringText(list, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj);
}
}
- GL11.glPopMatrix();
+ GL11.glTranslatef(0, 0, -300);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
+ }
+
+ /**
+ * Renders the search bar, item selection (right) and item info (left) gui elements.
+ */
+ public void render(int mouseX, int mouseY) {
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledresolution.getScaledWidth();
+ int height = scaledresolution.getScaledHeight();
+
+ yaw++;
+ yaw %= 360;
+
+ scrollHeight.tick();
+ manager.updatePrices();
+
+ int opacity = Math.min(255, Math.max(0, manager.config.bgOpacity.value.intValue()));
+ bg = new Color((bg.getRGB() & 0x00ffffff) | opacity << 24, true);
+
+ opacity = Math.min(255, Math.max(0, manager.config.fgOpacity.value.intValue()));
+ Color fgCustomOpacity = new Color((fg.getRGB() & 0x00ffffff) | opacity << 24, true);
+ Color fgFavourite = new Color(limCol(fg.getRed()+20), limCol(fg.getGreen()+10), limCol(fg.getBlue()-10), opacity);
+ Color fgFavourite2 = new Color(limCol(fg.getRed()+100), limCol(fg.getGreen()+50), limCol(fg.getBlue()-50), opacity);
+
+ if(webpageLoadTemp != null && informationPaneImage == null) {
+ DynamicTexture tex = new DynamicTexture(webpageLoadTemp);
+ informationPaneImage = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation(
+ "notenoughupdates/informationPaneImage", tex);
+ informationPaneImageHeight = webpageLoadTemp.getHeight();
+
+ webpageLoadTemp = null;
+ }
if(itemPaneOpen) {
if(itemPaneTabOffset.getValue() == 0) {
@@ -496,7 +1205,7 @@ public class NEUOverlay extends Gui {
int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor();
if(paddingUnscaled < 1) paddingUnscaled = 1;
- int topTextBox = height - searchBarYOffset - searchBarYSize/scaledresolution.getScaleFactor();
+ int topTextBox = height - searchBarYOffset - getSearchBarYSize();
//Search bar background
drawRect(width/2 - searchBarXSize/2 - paddingUnscaled,
@@ -508,102 +1217,61 @@ public class NEUOverlay extends Gui {
width/2 + searchBarXSize/2,
height - searchBarYOffset, Color.BLACK.getRGB());
- //Item editor enable button
- int iconSize = searchBarYSize/scaledresolution.getScaleFactor()+paddingUnscaled*2;
- Minecraft.getMinecraft().getTextureManager().bindTexture(item_edit);
- drawRect(width/2 + searchBarXSize/2 + paddingUnscaled*6,
+ //Settings
+ int iconSize = getSearchBarYSize()+paddingUnscaled*2;
+ Minecraft.getMinecraft().getTextureManager().bindTexture(settings);
+ drawRect(width/2 - searchBarXSize/2 - paddingUnscaled*6 - iconSize,
topTextBox - paddingUnscaled,
- width/2 + searchBarXSize/2 + paddingUnscaled*6 + iconSize,
+ width/2 - searchBarXSize/2 - paddingUnscaled*6,
topTextBox - paddingUnscaled + iconSize, Color.WHITE.getRGB());
- drawRect(width/2 + searchBarXSize/2 + paddingUnscaled*7,
+ drawRect(width/2 - searchBarXSize/2 - paddingUnscaled*5 - iconSize,
topTextBox,
- width/2 + searchBarXSize/2 + paddingUnscaled*5 + iconSize,
- topTextBox - paddingUnscaled*2 + iconSize, allowItemEditing ? Color.GREEN.getRGB() : Color.RED.getRGB());
+ width/2 - searchBarXSize/2 - paddingUnscaled*7,
+ topTextBox - paddingUnscaled*2 + iconSize, Color.GRAY.getRGB());
GlStateManager.color(1f, 1f, 1f, 1f);
- drawTexturedRect(width/2 + searchBarXSize/2 + paddingUnscaled*6, topTextBox - paddingUnscaled, iconSize, iconSize);
+ drawTexturedRect(width/2 - searchBarXSize/2 - paddingUnscaled*6 - iconSize, topTextBox - paddingUnscaled, iconSize, iconSize);
GlStateManager.bindTexture(0);
- if(mouseX > width/2 + searchBarXSize/2 + paddingUnscaled*6 &&
- mouseX < width/2 + searchBarXSize/2 + paddingUnscaled*6 + iconSize) {
- if(mouseY > topTextBox - paddingUnscaled && mouseY < topTextBox - paddingUnscaled + iconSize) {
- GuiUtils.drawHoveringText(Arrays.asList(
- EnumChatFormatting.GOLD.toString()+EnumChatFormatting.BOLD+"Enable item editing",
- EnumChatFormatting.RED+"Warning: "+EnumChatFormatting.YELLOW+"Uploading fake, " +
- "misinformative or misleading information using the item editor may result in your " +
- "account being banned from using this mod.",
- EnumChatFormatting.GREEN.toString()+EnumChatFormatting.BOLD+"Press k on an any item to use the item editor."),
- mouseX, mouseY, width, height, 250, Minecraft.getMinecraft().fontRendererObj);
- GlStateManager.disableLighting();
- }
- }
-
//Search bar text
fr.drawString(textField.getText(), width/2 - searchBarXSize/2 + 5,
- topTextBox+(searchBarYSize/scaledresolution.getScaleFactor()-8)/2, Color.WHITE.getRGB());
+ topTextBox+(getSearchBarYSize()-8)/2, Color.WHITE.getRGB());
//Determines position of cursor. Cursor blinks on and off every 500ms.
if(searchBarHasFocus && System.currentTimeMillis()%1000>500) {
String textBeforeCursor = textField.getText().substring(0, textField.getCursorPosition());
int textBeforeCursorWidth = fr.getStringWidth(textBeforeCursor);
drawRect(width/2 - searchBarXSize/2 + 5 + textBeforeCursorWidth,
- topTextBox+(searchBarYSize/scaledresolution.getScaleFactor()-8)/2-1,
+ topTextBox+(getSearchBarYSize()-8)/2-1,
width/2 - searchBarXSize/2 + 5 + textBeforeCursorWidth+1,
- topTextBox+(searchBarYSize/scaledresolution.getScaleFactor()-8)/2+9, Color.WHITE.getRGB());
+ topTextBox+(getSearchBarYSize()-8)/2+9, Color.WHITE.getRGB());
}
String selectedText = textField.getSelectedText();
if(!selectedText.isEmpty()) {
int selectionWidth = fr.getStringWidth(selectedText);
- int leftIndex = textField.getCursorPosition() < textField.getSelectionEnd() ?
- textField.getCursorPosition() : textField.getSelectionEnd();
+ int leftIndex = Math.min(textField.getCursorPosition(), textField.getSelectionEnd());
String textBeforeSelection = textField.getText().substring(0, leftIndex);
int textBeforeSelectionWidth = fr.getStringWidth(textBeforeSelection);
drawRect(width/2 - searchBarXSize/2 + 5 + textBeforeSelectionWidth,
- topTextBox+(searchBarYSize/scaledresolution.getScaleFactor()-8)/2-1,
+ topTextBox+(getSearchBarYSize()-8)/2-1,
width/2 - searchBarXSize/2 + 5 + textBeforeSelectionWidth + selectionWidth,
- topTextBox+(searchBarYSize/scaledresolution.getScaleFactor()-8)/2+9, Color.LIGHT_GRAY.getRGB());
+ topTextBox+(getSearchBarYSize()-8)/2+9, Color.LIGHT_GRAY.getRGB());
fr.drawString(selectedText,
width/2 - searchBarXSize/2 + 5 + textBeforeSelectionWidth,
- topTextBox+(searchBarYSize/scaledresolution.getScaleFactor()-8)/2, Color.BLACK.getRGB());
+ topTextBox+(getSearchBarYSize()-8)/2, Color.BLACK.getRGB());
}
/**
* Item selection (right) gui element rendering
*/
- Color bg = new Color(128, 128, 128, 50);
- int leftSide = (int)(width*itemPaneOffsetFactor.getValue());
- int rightSide = leftSide+width/3-boxPadding-getItemBoxXPadding();
- drawRect(leftSide+boxPadding-5, boxPadding-5,
- leftSide+width/3-boxPadding+5, height-boxPadding+5, bg.getRGB());
-
- drawRect(leftSide+boxPadding+getItemBoxXPadding()-1, boxPadding,
- rightSide+1,
- boxPadding+searchBarYSize/scaledresolution.getScaleFactor(), Color.GRAY.getRGB());
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(prev);
- GlStateManager.color(1f, 1f, 1f, 1f);
- drawTexturedRect(leftSide+boxPadding+getItemBoxXPadding(), boxPadding,
- 120/scaledresolution.getScaleFactor(), searchBarYSize/scaledresolution.getScaleFactor());
- GlStateManager.bindTexture(0);
-
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(next);
- GlStateManager.color(1f, 1f, 1f, 1f);
- drawTexturedRect(rightSide-120/scaledresolution.getScaleFactor(), boxPadding,
- 120/scaledresolution.getScaleFactor(), searchBarYSize/scaledresolution.getScaleFactor());
- GlStateManager.bindTexture(0);
-
- int offset = 1;
- if(scaledresolution.getScaleFactor()==4) offset = 0;
-
- String pageText = EnumChatFormatting.BOLD+"Page: " + (page+1) + "/" + getMaxPages();
- fr.drawString(pageText, leftSide+width/6-fr.getStringWidth(pageText)/2-1,
- boxPadding+(searchBarYSize/scaledresolution.getScaleFactor())/2-4+offset, Color.BLACK.getRGB());
+ int paneWidth = (int)(width/3*getWidthMult());
+ int leftSide = (int)(width*getItemPaneOffsetFactor());
+ int rightSide = leftSide+paneWidth-boxPadding-getItemBoxXPadding();
//Tab
Minecraft.getMinecraft().getTextureManager().bindTexture(itemPaneTabArrow);
@@ -612,50 +1280,242 @@ public class NEUOverlay extends Gui {
GlStateManager.bindTexture(0);
if(mouseX > width-itemPaneTabOffset.getValue() && mouseY > height/2 - 50
- && mouseY < height/2 + 50) {
+ && mouseY < height/2 + 50) {
itemPaneOpen = true;
}
- //Atomic integer used so that below lambda doesn't complain about non-effectively-final variable
+ //Atomic reference used so that below lambda doesn't complain about non-effectively-final variable
AtomicReference<JsonObject> tooltipToDisplay = new AtomicReference<>(null);
- //Iterate through all item slots and display the appropriate item
- iterateItemSlots((x, y) -> {
- int id = getSlotId(x, y);
- JsonObject json = getSearchedItemPage(id);
- if(json == null) {
- return;
+ if(itemPaneOffsetFactor.getValue() < 1) {
+ drawRect(leftSide+boxPadding-5, boxPadding-5,
+ leftSide+paneWidth-boxPadding+5, height-boxPadding+5, bg.getRGB());
+
+ renderNavElement(leftSide+boxPadding+getItemBoxXPadding(), rightSide, getMaxPages(),
+ scaledresolution.getScaleFactor()<4?"Page: ":"");
+
+ //Sort bar
+ drawRect(leftSide+boxPadding+getItemBoxXPadding()-1,
+ height-boxPadding-itemSize-2,
+ rightSide+1,
+ height-boxPadding, fgCustomOpacity.getRGB());
+
+ float sortIconsMinX = (sortIcons.length+orderIcons.length)*(itemSize+itemPadding)+itemSize;
+ float availableX = rightSide-(leftSide+boxPadding+getItemBoxXPadding());
+ float sortOrderScaleFactor = Math.min(1, availableX / sortIconsMinX);
+
+ int scaledItemSize = (int)(itemSize*sortOrderScaleFactor);
+ int scaledItemPaddedSize = (int)((itemSize+itemPadding)*sortOrderScaleFactor);
+ int iconTop = height-boxPadding-(itemSize+scaledItemSize)/2-1;
+
+ for(int i=0; i<orderIcons.length; i++) {
+ int orderIconX = leftSide+boxPadding+getItemBoxXPadding()+i*scaledItemPaddedSize;
+ drawRect(orderIconX, iconTop,scaledItemSize+orderIconX,iconTop+scaledItemSize, fg.getRGB());
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(getCompareMode() == i ? orderIconsActive[i] : orderIcons[i]);
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ drawTexturedRect(orderIconX, iconTop, scaledItemSize, scaledItemSize,0, 1, 0, 1, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(getCompareAscending().get(i) ? ascending_overlay : descending_overlay);
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ drawTexturedRect(orderIconX, iconTop, scaledItemSize, scaledItemSize,0, 1, 0, 1, GL11.GL_NEAREST);
+ GlStateManager.bindTexture(0);
+ }
+
+ for(int i=0; i<sortIcons.length; i++) {
+ int sortIconX = rightSide-scaledItemSize-i*scaledItemPaddedSize;
+ drawRect(sortIconX, iconTop,scaledItemSize+sortIconX,iconTop+scaledItemSize, fg.getRGB());
+ Minecraft.getMinecraft().getTextureManager().bindTexture(getSortMode() == i ? sortIconsActive[i] : sortIcons[i]);
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ drawTexturedRect(sortIconX, iconTop, scaledItemSize, scaledItemSize, 0, 1, 0, 1, GL11.GL_NEAREST);
+ GlStateManager.bindTexture(0);
}
- drawRect(x-1, y-1, x+itemSize+1, y+itemSize+1, Color.GRAY.getRGB());
- ItemStack stack = new ItemStack(Item.itemRegistry.getObject(
- new ResourceLocation(json.get("itemid").getAsString())));
+ //Iterate through all item slots and display the appropriate item
+ iterateItemSlots((x, y) -> {
+ int id = getSlotId(x, y);
+ JsonObject json = getSearchedItemPage(id);
+ if(json == null) {
+ return;
+ }
- if(stack.getItem() == null) {
- stack = new ItemStack(Items.diamond, 1, 10); //Purple broken texture item
- } else {
- if(json.has("damage")) {
- stack.setItemDamage(json.get("damage").getAsInt());
+ if(getFavourites().contains(json.get("internalname").getAsString())) {
+ drawRect(x-1, y-1, x+itemSize+1, y+itemSize+1, fgFavourite2.getRGB());
+ drawRect(x, y, x+itemSize, y+itemSize, fgFavourite.getRGB());
+ } else {
+ drawRect(x-1, y-1, x+itemSize+1, y+itemSize+1, fgCustomOpacity.getRGB());
}
- if(json.has("nbttag")) {
- try {
- NBTTagCompound tag = JsonToNBT.getTagFromJson(json.get("nbttag").getAsString());
- stack.setTagCompound(tag);
- } catch(NBTException e) {
+ if(json.has("entityrender")) {
+ String name = json.get("displayname").getAsString();
+ String[] split = name.split(" \\(");
+ name = name.substring(0, name.length()-split[split.length-1].length()-2);
+
+ Class<? extends EntityLivingBase>[] entities = new Class[1];
+ if(json.get("entityrender").isJsonArray()) {
+ JsonArray entityrender = json.get("entityrender").getAsJsonArray();
+ entities = new Class[entityrender.size()];
+ for(int i=0; i<entityrender.size(); i++) {
+ Class<? extends Entity> clazz = EntityList.stringToClassMapping.get(entityrender.get(i).getAsString());
+ if(clazz != null && EntityLivingBase.class.isAssignableFrom(clazz)) {
+ entities[i] = (Class<? extends EntityLivingBase>)clazz;
+ }
+ }
+ } else if(json.get("entityrender").isJsonPrimitive()) {
+ Class<? extends Entity> clazz = EntityList.stringToClassMapping.get(json.get("entityrender").getAsString());
+ if(clazz != null && EntityLivingBase.class.isAssignableFrom(clazz)) {
+ entities[0] = (Class<? extends EntityLivingBase>)clazz;
+ }
+ }
+
+ float scale = 8;
+ if(json.has("entityscale")) {
+ scale *= json.get("entityscale").getAsFloat();
}
+
+ renderEntity(x+itemSize/2, y+itemSize, scale, name, entities);
+ } else {
+ drawItemStack(manager.jsonToStack(json), x, y, null);
}
- }
- //Integer.toString(getSlotId(x, y))
- drawItemStack(stack, x, y, null);
- if(mouseX > x-1 && mouseX < x+itemSize+1) {
- if(mouseY > y-1 && mouseY < y+itemSize+1) {
- tooltipToDisplay.set(json);
+ if(mouseX > x-1 && mouseX < x+itemSize+1) {
+ if(mouseY > y-1 && mouseY < y+itemSize+1) {
+ tooltipToDisplay.set(json);
+ }
+ }
+ });
+ }
+
+ /**
+ * Item info (left) gui element rendering
+ */
+
+ rightSide = (int)(width*getInfoPaneOffsetFactor());
+ leftSide = rightSide - paneWidth;
+
+ if(scrollHeight.getValue() < 0) scrollHeight.setValue(0);
+
+ if(informationPaneTitle != null || configOpen) {
+ if(configOpen) {
+ int boxLeft = leftSide+boxPadding-5;
+ int boxRight = rightSide-boxPadding+5;
+ drawRect(boxLeft, boxPadding-5, boxRight,
+ height-boxPadding+5, bg.getRGB());
+
+ renderNavElement(leftSide+boxPadding, rightSide-boxPadding, 1,"Settings: ");
+
+ AtomicReference<List<String>> textToDisplay = new AtomicReference<>(null);
+ iterateSettingTile(new SettingsTileConsumer() {
+ public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option) {
+ float mult = tileWidth/90f;
+
+ drawRect(x, y, x+tileWidth, y+tileHeight, fg.getRGB());
+ if(scaledresolution.getScaleFactor()==4) {
+ GL11.glScalef(0.5f,0.5f,1);
+ renderStringTrimWidth(option.displayName, fr, true, (x+(int)(8*mult))*2, (y+(int)(8*mult))*2,
+ (tileWidth-(int)(16*mult))*2, new Color(100,255,150).getRGB(), 3);
+ GL11.glScalef(2,2,1);
+ } else {
+ renderStringTrimWidth(option.displayName, fr, true, x+(int)(8*mult), y+(int)(8*mult),
+ tileWidth-(int)(16*mult), new Color(100,255,150).getRGB(), 3);
+ }
+
+ if(option.value instanceof Boolean) {
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(((Boolean)option.value) ? on : off);
+ drawTexturedRect(x+tileWidth/2-(int)(32*mult), y+tileHeight-(int)(20*mult), (int)(48*mult), (int)(16*mult));
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ drawTexturedRect(x+tileWidth/2+(int)(19*mult), y+tileHeight-(int)(19*mult), (int)(14*mult), (int)(14*mult));
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
+
+ if(mouseX > x+tileWidth/2+(int)(19*mult) && mouseX < x+tileWidth/2+(int)(19*mult)+(int)(14*mult)) {
+ if(mouseY > y+tileHeight-(int)(19*mult) && mouseY < y+tileHeight-(int)(19*mult)+(int)(14*mult)) {
+ List<String> textLines = new ArrayList<>();
+ textLines.add(option.displayName);
+ textLines.add(EnumChatFormatting.GRAY+option.desc);
+ textToDisplay.set(textLines);
+ }
+ }
+ } else {
+ if(!textConfigMap.containsKey(option)) {
+ textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0));
+ }
+ GuiElementTextField tf = textConfigMap.get(option);
+ tf.setSize(tileWidth-(int)(20*mult), (int)(16*mult));
+ tf.render(x+(int)(10*mult), y+tileHeight-(int)(20*mult));
+
+ try {
+ tf.setCustomBorderColour(-1);
+ option.setValue(tf.getText());
+ } catch(Exception e) {
+ tf.setCustomBorderColour(Color.RED.getRGB());
+ }
+ }
+ }
+ });
+ if(textToDisplay.get() != null) {
+ Utils.drawHoveringText(textToDisplay.get(), mouseX, mouseY, width, height, 200, fr);
}
+ } else if(informationPaneImage != null) {
+ int titleLen = fr.getStringWidth(informationPaneTitle);
+ fr.drawString(informationPaneTitle, (leftSide+rightSide-titleLen)/2, +boxPadding + 5, Color.WHITE.getRGB());
+
+ drawRect(leftSide+boxPadding-5, boxPadding-5, rightSide-boxPadding+5,
+ height-boxPadding+5, bg.getRGB());
+
+ int imageW = paneWidth - boxPadding*2;
+ float scaleF = IMAGE_WIDTH*ZOOM_FACTOR/(float)imageW;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(informationPaneImage);
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ if(height-boxPadding*3 < informationPaneImageHeight/scaleF) {
+ if(scrollHeight.getValue() > informationPaneImageHeight/scaleF-height+boxPadding*3) {
+ scrollHeight.setValue((int)(informationPaneImageHeight/scaleF-height+boxPadding*3));
+ }
+ int yScroll = scrollHeight.getValue();
+
+ float vMin = yScroll/(informationPaneImageHeight/scaleF);
+ float vMax = (yScroll+height-boxPadding*3)/(informationPaneImageHeight/scaleF);
+ drawTexturedRect(leftSide+boxPadding, boxPadding*2, imageW, height-boxPadding*3,
+ 0, 1, vMin, vMax);
+ } else {
+ scrollHeight.setValue(0);
+
+ drawTexturedRect(leftSide+boxPadding, boxPadding*2, imageW, (int)(informationPaneImageHeight/scaleF));
+ }
+ GlStateManager.bindTexture(0);
+ } else if(informationPane != null) {
+ int titleLen = fr.getStringWidth(informationPaneTitle);
+ int yScroll = -scrollHeight.getValue();
+ fr.drawString(informationPaneTitle, (leftSide+rightSide-titleLen)/2, yScroll+boxPadding + 5, Color.WHITE.getRGB());
+
+ int yOff = 20;
+ for(int i=0; i<informationPane.length; i++) {
+ String line = informationPane[i];
+
+ yOff += renderStringTrimWidth(line, fr, false,leftSide+boxPadding + 5, yScroll+boxPadding + 10 + yOff,
+ width*1/3-boxPadding*2-10, Color.WHITE.getRGB(), -1);
+ yOff += 16;
+ }
+
+ int top = boxPadding - 5;
+ int totalBoxHeight = yOff+14;
+ int bottom = Math.max(top+totalBoxHeight, height-boxPadding+5);
+
+ if(scrollHeight.getValue() > top+totalBoxHeight-(height-boxPadding+5)) {
+ scrollHeight.setValue(top+totalBoxHeight-(height-boxPadding+5));
+ }
+ drawRect(leftSide+boxPadding-5, yScroll+boxPadding-5, rightSide-boxPadding+5, yScroll+bottom, bg.getRGB());
}
- });
+ if(rightSide > 0) {
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(close);
+ drawTexturedRect(rightSide-22, 7, 16, 16);
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
+ }
+ }
//Render tooltip
JsonObject json = tooltipToDisplay.get();
@@ -667,6 +1527,20 @@ public class NEUOverlay extends Gui {
text.add(lore.get(i).getAsString());
}
+ Float auctionPrice = manager.getAuctionPrices().get(json.get("internalname").getAsString());
+ Pair<Float, Float> bazaarBuySellPrice = manager.getBazaarBuySellPrices().get(json.get("internalname").getAsString());
+
+ boolean hasAuctionPrice = auctionPrice != null;
+ boolean hasBazaarPrice = bazaarBuySellPrice != null;
+
+ if(hasAuctionPrice || hasBazaarPrice) text.add("");
+ if(hasBazaarPrice) text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Buy: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+bazaarBuySellPrice.getLeft()+" coins");
+ if(hasBazaarPrice) text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Sell: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+bazaarBuySellPrice.getRight()+" coins");
+ if(hasAuctionPrice) text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Auction House Buy/Sell: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+auctionPrice+" coins");
+
boolean hasClick = false;
boolean hasInfo = false;
if(json.has("clickcommand") && !json.get("clickcommand").getAsString().isEmpty()) {
@@ -677,77 +1551,66 @@ public class NEUOverlay extends Gui {
}
if(hasClick || hasInfo) text.add("");
- if(hasClick) text.add("\u00A7e\u00A7lLeft click to view recipe!");
- if(hasInfo) text.add("\u00A7e\u00A7lRight click to view additional information!");
+ if(hasClick) text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"LMB/R : View recipe!");
+ if(hasInfo) text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"RMB : View additional information!");
- GuiUtils.drawHoveringText(text, mouseX, mouseY, width, height, -1, fr);
- GlStateManager.disableLighting();
+ Utils.drawHoveringText(text, mouseX, mouseY, width, height, -1, fr);
}
+ }
- /**
- * Item info (left) gui element rendering
- */
+ public float getItemPaneOffsetFactor() {
+ return itemPaneOffsetFactor.getValue() * getWidthMult() + (1-getWidthMult());
+ }
- rightSide = (int)(width*getInfoPaneOffsetFactor());
- leftSide = rightSide - width/3;
-
- drawRect(leftSide+boxPadding-5, boxPadding-5, rightSide-boxPadding+5, height-boxPadding+5, bg.getRGB());
- if(informationPane != null && informationPaneTitle != null) {
- int titleLen = fr.getStringWidth(informationPaneTitle);
- fr.drawString(informationPaneTitle, (leftSide+rightSide-titleLen)/2, boxPadding + 5, Color.WHITE.getRGB());
-
- int yOff = 20;
- for(int i=0; i<informationPane.length; i++) {
- String line = informationPane[i];
-
- String excess;
- String trimmed = trimToWidth(line, width*1/3-boxPadding*2-10);
-
- String colourCodes = "";
- Pattern pattern = Pattern.compile("\\u00A7.");
- Matcher matcher = pattern.matcher(trimmed);
- while(matcher.find()) {
- colourCodes += matcher.group();
- }
-
- boolean firstLine = true;
- int trimmedCharacters = trimmed.length();
- while(true) {
- if(trimmed.length() == line.length()) {
- fr.drawString(trimmed, leftSide+boxPadding + 5, boxPadding + 10 + yOff, Color.WHITE.getRGB());
- break;
- } else if(trimmed.isEmpty()) {
- yOff -= 12;
- break;
- } else {
- if(firstLine) {
- fr.drawString(trimmed, leftSide+boxPadding + 5, boxPadding + 10 + yOff, Color.WHITE.getRGB());
- firstLine = false;
- } else {
- if(trimmed.startsWith(" ")) {
- trimmed = trimmed.substring(1);
- }
- fr.drawString(colourCodes + trimmed, leftSide+boxPadding + 5, boxPadding + 10 + yOff, Color.WHITE.getRGB());
- }
+ public float getInfoPaneOffsetFactor() {
+ if(configOpen) return infoPaneOffsetFactor.getValue() * getWidthMult();
+ if(itemPaneOffsetFactor.getValue() < 1 && itemPaneOffsetFactor.getValue() == itemPaneOffsetFactor.getTarget()) {
+ return infoPaneOffsetFactor.getValue() * getWidthMult();
+ } else {
+ return Math.min(infoPaneOffsetFactor.getValue(), 1-getItemPaneOffsetFactor());
+ }
+ }
+
+ public int renderStringTrimWidth(String str, FontRenderer fr, boolean shadow, int x, int y, int len, int colour, int maxLines) {
+ int yOff = 0;
+ String excess;
+ String trimmed = trimToWidth(str, len);
- excess = line.substring(trimmedCharacters);
- trimmed = trimToWidth(excess, width * 1 / 3 - boxPadding * 2 - 10);
- trimmedCharacters += trimmed.length();
- yOff += 12;
+ String colourCodes = "";
+ Pattern pattern = Pattern.compile("\\u00A7.");
+ Matcher matcher = pattern.matcher(trimmed);
+ while(matcher.find()) {
+ colourCodes += matcher.group();
+ }
+
+ boolean firstLine = true;
+ int trimmedCharacters = trimmed.length();
+ int lines = 0;
+ while((lines++<maxLines) || maxLines<0) {
+ if(trimmed.length() == str.length()) {
+ fr.drawString(trimmed, x, y + yOff, colour, shadow);
+ break;
+ } else if(trimmed.isEmpty()) {
+ yOff -= 12;
+ break;
+ } else {
+ if(firstLine) {
+ fr.drawString(trimmed, x, y + yOff, colour, shadow);
+ firstLine = false;
+ } else {
+ if(trimmed.startsWith(" ")) {
+ trimmed = trimmed.substring(1);
}
+ fr.drawString(colourCodes + trimmed, x, y + yOff, colour, shadow);
}
- yOff += 16;
+ excess = str.substring(trimmedCharacters);
+ trimmed = trimToWidth(excess, len);
+ trimmedCharacters += trimmed.length();
+ yOff += 12;
}
}
- }
-
- public float getInfoPaneOffsetFactor() {
- if(itemPaneOffsetFactor.getValue() == 2/3f) {
- return infoPaneOffsetFactor.getValue();
- } else {
- return Math.min(infoPaneOffsetFactor.getValue(), 1-itemPaneOffsetFactor.getValue());
- }
+ return yOff;
}
public String trimToWidth(String str, int len) {
@@ -768,37 +1631,94 @@ public class NEUOverlay extends Gui {
return trim;
}
+ private abstract class SettingsTileConsumer {
+ public abstract void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option);
+ }
+
+ public int getTotalOptions() {
+ return manager.config.getOptions().size();
+ }
+
+ public void iterateSettingTile(SettingsTileConsumer settingsTileConsumer) {
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ int width = scaledresolution.getScaledWidth();
+ int height = scaledresolution.getScaledHeight();
+
+ int numHorz = scaledresolution.getScaleFactor() >= 3 ? 2 : 3;
+
+ int paneWidth = (int)(width/3*getWidthMult());
+ int rightSide = (int)(width*getInfoPaneOffsetFactor());
+ int leftSide = rightSide - paneWidth;
+
+ int boxLeft = leftSide+boxPadding-5;
+ int boxRight = rightSide-boxPadding+5;
+
+ int boxWidth = boxRight-boxLeft;
+ int tilePadding = 7;
+ int tileWidth = (boxWidth-tilePadding*4)/numHorz;
+ int tileHeight = tileWidth*3/4;
+
+ int x=0;
+ int y=tilePadding+boxPadding+getSearchBarYSize();
+ for(int i=0; i<getTotalOptions(); i++) {
+ if(i!=0 && i%numHorz==0) {
+ x = 0;
+ y += tileHeight+tilePadding;
+ }
+ x+=tilePadding;
+
+ settingsTileConsumer.consume(boxLeft+x, y, tileWidth, tileHeight, manager.config.getOptions().get(i));
+
+ x+=tileWidth;
+ }
+ }
+
private void drawItemStack(ItemStack stack, int x, int y, String altText) {
RenderItem itemRender = Minecraft.getMinecraft().getRenderItem();
- FontRenderer font = Minecraft.getMinecraft().fontRendererObj;
RenderHelper.enableGUIStandardItemLighting();
itemRender.renderItemAndEffectIntoGUI(stack, x, y);
RenderHelper.disableStandardItemLighting();
-
- itemRender.renderItemOverlayIntoGUI(font, stack, x, y, altText);
}
- private void drawTexturedRect(int x, int y, int width, int height) {
+ private void drawTexturedRect(float x, float y, float width, float height) {
drawTexturedRect(x, y, width, height, 0, 1, 0 , 1);
}
- private void drawTexturedRect(int x, int y, int width, int height, float uMin, float uMax, float vMin, float vMax) {
- Tessellator tessellator = Tessellator.getInstance();
- WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ private void drawTexturedRect(float x, float y, float width, float height, float uMin, float uMax, float vMin, float vMax) {
+ drawTexturedRect(x, y, width, height, uMin, uMax, vMin , vMax, GL11.GL_LINEAR);
+ }
- GlStateManager.enableAlpha();
+ private void drawTexturedRect(float x, float y, float width, float height, float uMin, float uMax, float vMin, float vMax, int filter) {
+ GlStateManager.enableTexture2D();
GlStateManager.enableBlend();
- GlStateManager.blendFunc(770, 771);
- GlStateManager.alphaFunc(516, 0.003921569F);
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter);
+
+ GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
+ GL11.glTexCoord2f(uMin, vMin);
+ GL11.glVertex3f(x, y, 0.0F);
+ GL11.glTexCoord2f(uMin, vMax);
+ GL11.glVertex3f(x, y+height, 0.0F);
+ GL11.glTexCoord2f(uMax, vMin);
+ GL11.glVertex3f(x+width, y, 0.0F);
+ GL11.glTexCoord2f(uMax, vMax);
+ GL11.glVertex3f(x+width, y+height, 0.0F);
+ GL11.glEnd();
- worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
- worldrenderer.pos(x + 0, y + height, this.zLevel).tex(uMin, vMax).endVertex();
- worldrenderer.pos(x + width, y + height, this.zLevel).tex(uMax, vMax).endVertex();
- worldrenderer.pos(x + width, y + 0, this.zLevel).tex(uMax, vMin).endVertex();
- worldrenderer.pos(x + 0, y + 0, this.zLevel).tex(uMin, vMin).endVertex();
- tessellator.draw();
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GlStateManager.disableBlend();
+
+ /*worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
+ worldrenderer.pos(x, y + height + offset, this.zLevel).tex(uMin, vMax).endVertex();
+ worldrenderer.pos(x + width + offset, y + height + offset, this.zLevel).tex(uMax, vMax).endVertex();
+ worldrenderer.pos(x + width + offset, y, this.zLevel).tex(uMax, vMin).endVertex();
+ worldrenderer.pos(x, y, this.zLevel).tex(uMin, vMin).endVertex();
+ tessellator.draw();*/
+
}
} \ No newline at end of file
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
index 17295aa8..0e310cf5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
@@ -1,14 +1,30 @@
package io.github.moulberry.notenoughupdates;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
import com.mojang.authlib.Agent;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.scoreboard.ScoreObjective;
+import net.minecraft.scoreboard.Scoreboard;
+import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.Session;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
@@ -18,15 +34,25 @@ import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
import javax.swing.*;
-import java.io.File;
+import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.Proxy;
+import java.nio.charset.StandardCharsets;
+import java.util.ConcurrentModificationException;
import java.util.Scanner;
+import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
@Mod(modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION)
public class NotEnoughUpdates {
@@ -36,26 +62,57 @@ public class NotEnoughUpdates {
private NEUManager manager;
private NEUOverlay overlay;
private NEUIO neuio;
-
+
+ private static final long CHAT_MSG_COOLDOWN = 200;
+ private long lastChatMessage = 0;
+ private String currChatMessage = null;
+
+ //Stolen from Biscut and used for detecting whether in skyblock
+ private static final Set<String> SKYBLOCK_IN_ALL_LANGUAGES = Sets.newHashSet("SKYBLOCK","\u7A7A\u5C9B\u751F\u5B58");
+
+ //Github Access Token, may change. Value hard-coded.
+ //Token is obfuscated so that github doesn't delete it whenever I upload the jar.
+ String[] token = new String[]{"b292496d2c","9146a","9f55d0868a545305a8","96344bf"};
+ private String getAccessToken() {
+ String s = "";
+ for(String str : token) {
+ s += str;
+ }
+ return s;
+ }
+
@EventHandler
public void preinit(FMLPreInitializationEvent event) {
MinecraftForge.EVENT_BUS.register(this);
File f = new File(event.getModConfigurationDirectory(), "notenoughupdates");
f.mkdirs();
- //Github Access Token, may change. Value hard-coded.
- neuio = new NEUIO("c49fcad378ae46e5c08bf6b0c5502f7e4830bfef");
- manager = new NEUManager(neuio, f);
+ neuio = new NEUIO(getAccessToken());
+ manager = new NEUManager(this, neuio, f);
manager.loadItemInformation();
overlay = new NEUOverlay(manager);
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
+ try {
+ File tmp = new File(f, "tmp");
+ if(tmp.exists()) {
+ for(File tmpFile : tmp.listFiles()) {
+ tmpFile.delete();
+ }
+ tmp.delete();
+ }
+
+ manager.saveConfig();
+ } catch(IOException e) {}
+ }));
+
//TODO: login code. Ignore this, used for testing.
/*try {
Field field = Minecraft.class.getDeclaredField("session");
YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication)
new YggdrasilAuthenticationService(Proxy.NO_PROXY, UUID.randomUUID().toString())
.createUserAuthentication(Agent.MINECRAFT);
- auth.setUsername("...");
+ auth.setUsername("james.jenour@protonmail.com");
JPasswordField pf = new JPasswordField();
JOptionPane.showConfirmDialog(null,
pf,
@@ -81,36 +138,282 @@ public class NotEnoughUpdates {
} catch (NoSuchFieldException | AuthenticationException | IllegalAccessException e) {
e.printStackTrace();
}*/
+ }
+
+ public void sendChatMessage(String message) {
+ if(System.currentTimeMillis() - lastChatMessage > CHAT_MSG_COOLDOWN) {
+ lastChatMessage = System.currentTimeMillis();
+ Minecraft.getMinecraft().thePlayer.sendChatMessage(message);
+ currChatMessage = null;
+ } else {
+ currChatMessage = message;
+ }
+ }
+ @EventHandler
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if(currChatMessage != null && System.currentTimeMillis() - lastChatMessage > CHAT_MSG_COOLDOWN) {
+ lastChatMessage = System.currentTimeMillis();
+ Minecraft.getMinecraft().thePlayer.sendChatMessage(currChatMessage);
+ currChatMessage = null;
+ }
}
+ AtomicBoolean missingRecipe = new AtomicBoolean(false);
@SubscribeEvent
public void onGuiOpen(GuiOpenEvent event) {
+ /*if(event.gui != null) {
+ if(event.gui instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) event.gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+ ses.schedule(() -> {
+ if(Minecraft.getMinecraft().currentScreen != event.gui) {
+ return;
+ }
+ if(lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) {
+ try {
+ ItemStack res = lower.getStackInSlot(25);
+ String resInternalname = manager.getInternalNameForItem(res);
+
+ /*JsonArray arr = null;
+ File f = new File(manager.configLocation, "missing.json");
+ try(InputStream instream = new FileInputStream(f)) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(instream, StandardCharsets.UTF_8));
+ JsonObject json = manager.gson.fromJson(reader, JsonObject.class);
+ arr = json.getAsJsonArray("missing");
+ } catch(IOException e) {}
+ try {
+ JsonObject json = new JsonObject();
+ JsonArray newArr = new JsonArray();
+ for(JsonElement e : arr) {
+ if(!e.getAsString().equals(resInternalname)) {
+ newArr.add(e);
+ }
+ }
+ json.add("missing", newArr);
+ manager.writeJson(json, f);
+ } catch(IOException e) {}
+
+ JsonObject recipe = new JsonObject();
+
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+
+ for(int i=0; i<=18; i+=9) {
+ for(int j=0; j<3; j++) {
+ ItemStack stack = lower.getStackInSlot(10+i+j);
+ String internalname = "";
+ if(stack != null) {
+ internalname = manager.getInternalNameForItem(stack);
+ if(!manager.getItemInformation().containsKey(internalname)) {
+ manager.writeItemToFile(stack);
+ }
+ internalname += ":"+stack.stackSize;
+ }
+ recipe.addProperty(y[i/9]+x[j], internalname);
+ }
+ }
+
+ JsonObject json = manager.getJsonForItem(res);
+ json.add("recipe", recipe);
+ json.addProperty("internalname", resInternalname);
+ json.addProperty("clickcommand", "viewrecipe");
+ json.addProperty("modver", NotEnoughUpdates.VERSION);
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
+ manager.writeJsonDefaultDir(json, resInternalname+".json");
+ manager.loadItem(resInternalname);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }, 200, TimeUnit.MILLISECONDS);
+ return;
+ }
+ }*/
+ //OPEN
if(Minecraft.getMinecraft().currentScreen == null
&& event.gui instanceof GuiContainer) {
overlay.reset();
}
+ //CLOSE
+ if(Minecraft.getMinecraft().currentScreen != null && event.gui == null) {
+ try {
+ manager.saveConfig();
+ } catch(IOException e) {}
+ }
+ }
+
+ @SubscribeEvent
+ public void onGuiChat(ClientChatReceivedEvent e) {
+ String r = null;
+ if(e.message.getFormattedText().equals(EnumChatFormatting.RESET.toString()+
+ EnumChatFormatting.RED+"You haven't unlocked this recipe!"+EnumChatFormatting.RESET)) {
+ r = EnumChatFormatting.RED+"You haven't unlocked this recipe!";
+ } else if(e.message.getFormattedText().startsWith(EnumChatFormatting.RESET.toString()+
+ EnumChatFormatting.RED+"Invalid recipe ")) {
+ r = "";
+ }
+ if(r != null) {
+ if(manager.failViewItem(r)) {
+ e.setCanceled(true);
+ }
+ missingRecipe.set(true);
+ }
+ }
+
+ @SubscribeEvent
+ public void onGuiBackgroundDraw(GuiScreenEvent.BackgroundDrawnEvent event) {
+ if(event.gui instanceof GuiContainer && isOnSkyblock()) {
+ ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledresolution.getScaledWidth();
+ if(event.getMouseX() <= width*2/3 && event.getMouseX() >= width*1/3) {
+ try {
+ overlay.render(event.getMouseX(), event.getMouseY());
+ } catch(ConcurrentModificationException e) {e.printStackTrace(); }
+ }
+ }
}
@SubscribeEvent
public void onGuiScreenDraw(GuiScreenEvent.DrawScreenEvent.Post event) {
- if(event.gui instanceof GuiContainer) {
- overlay.render(event.renderPartialTicks, event.mouseX, event.mouseY);
+ if(event.gui instanceof GuiContainer && isOnSkyblock()) {
+ ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledresolution.getScaledWidth();
+ if(event.mouseX > width*2/3 || event.mouseX < width*1/3) {
+ try {
+ overlay.render(event.mouseX, event.mouseY);
+ } catch(ConcurrentModificationException e) {e.printStackTrace(); }
+ }
+ overlay.renderOverlay(event.mouseX, event.mouseY);
}
}
@SubscribeEvent
public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) {
- if(event.gui instanceof GuiContainer) {
+ if(event.gui instanceof GuiContainer && isOnSkyblock()) {
if(overlay.mouseInput()) {
event.setCanceled(true);
}
}
}
+ ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
+
+ boolean started = false;
@SubscribeEvent
public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) {
- if(event.gui instanceof GuiContainer) {
+ if(manager.config.enableItemEditing.value && Minecraft.getMinecraft().theWorld != null &&
+ Keyboard.getEventKey() == Keyboard.KEY_O && Keyboard.getEventKeyState()) {
+ GuiScreen gui = Minecraft.getMinecraft().currentScreen;
+ if(gui != null && gui instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) event.gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ if(lower.getStackInSlot(23) != null &&
+ lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) {
+ ItemStack res = lower.getStackInSlot(25);
+ String resInternalname = manager.getInternalNameForItem(res);
+ JTextField tf = new JTextField();
+ tf.setText(resInternalname);
+ tf.addAncestorListener(new RequestFocusListener());
+ JOptionPane.showOptionDialog(null,
+ tf,
+ "Enter Name:",
+ JOptionPane.NO_OPTION,
+ JOptionPane.PLAIN_MESSAGE,
+ null, new String[]{"Enter"}, "Enter");
+ resInternalname = tf.getText();
+
+ JsonObject recipe = new JsonObject();
+
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+
+ for(int i=0; i<=18; i+=9) {
+ for(int j=0; j<3; j++) {
+ ItemStack stack = lower.getStackInSlot(10+i+j);
+ String internalname = "";
+ if(stack != null) {
+ internalname = manager.getInternalNameForItem(stack);
+ if(!manager.getItemInformation().containsKey(internalname)) {
+ manager.writeItemToFile(stack);
+ }
+ internalname += ":"+stack.stackSize;
+ }
+ recipe.addProperty(y[i/9]+x[j], internalname);
+ }
+ }
+
+ JsonObject json = manager.getJsonForItem(res);
+ json.add("recipe", recipe);
+ json.addProperty("internalname", resInternalname);
+ json.addProperty("clickcommand", "viewrecipe");
+ json.addProperty("modver", NotEnoughUpdates.VERSION);
+ try {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
+ manager.writeJsonDefaultDir(json, resInternalname+".json");
+ manager.loadItem(resInternalname);
+ } catch(IOException e) {}
+ }
+ }
+ }
+ /*if(Minecraft.getMinecraft().theWorld != null && Keyboard.getEventKey() == Keyboard.KEY_RBRACKET && Keyboard.getEventKeyState()) {
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ started = true;
+ final Object[] items = manager.getItemInformation().values().toArray();
+ AtomicInteger i = new AtomicInteger(0);
+
+ Runnable checker = new Runnable() {
+ @Override
+ public void run() {
+ int in = i.getAndIncrement();
+ /*if(missingRecipe.get()) {
+ String internalname = ((JsonObject)items[in]).get("internalname").getAsString();
+
+ JsonArray arr = null;
+ File f = new File(manager.configLocation, "missing.json");
+ try(InputStream instream = new FileInputStream(f)) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(instream, StandardCharsets.UTF_8));
+ JsonObject json = manager.gson.fromJson(reader, JsonObject.class);
+ arr = json.getAsJsonArray("missing");
+ } catch(IOException e) {}
+
+ try {
+ JsonObject json = new JsonObject();
+ if(arr == null) arr = new JsonArray();
+ arr.add(new JsonPrimitive(internalname));
+ json.add("missing", arr);
+ manager.writeJson(json, f);
+ } catch(IOException e) {}
+ }
+ missingRecipe.set(false);
+
+ ses.schedule(() -> {
+ int index = i.get();
+ JsonObject o = (JsonObject)items[index];
+ if(Minecraft.getMinecraft().currentScreen != null) {
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ }
+ Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewrecipe " + o.get("internalname").getAsString());
+
+ ses.schedule(this, 1000, TimeUnit.MILLISECONDS);
+ }, 100, TimeUnit.MILLISECONDS);
+ }
+ };
+
+ int index = i.get();
+ JsonObject o = (JsonObject)items[index];
+ if(Minecraft.getMinecraft().currentScreen != null) {
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ }
+ Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewrecipe " + o.get("internalname").getAsString());
+
+ ses.schedule(checker, 1000, TimeUnit.MILLISECONDS);
+ }*/
+ if(event.gui instanceof GuiContainer && isOnSkyblock()) {
if(overlay.keyboardInput()) {
event.setCanceled(true);
}
@@ -125,7 +428,7 @@ public class NotEnoughUpdates {
*/
@SubscribeEvent
public void onItemTooltip(ItemTooltipEvent event) {
- if(!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) return;
+ if(!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || !manager.config.dev.value) return;
if(event.toolTip.get(event.toolTip.size()-1).startsWith(EnumChatFormatting.DARK_GRAY + "NBT: ")) {
event.toolTip.remove(event.toolTip.size()-1);
@@ -156,4 +459,26 @@ public class NotEnoughUpdates {
event.toolTip.add(sb.toString());
}
}
+
+ //Stolen from Biscut's SkyblockAddons
+ public boolean isOnSkyblock() {
+ if(!manager.config.onlyShowOnSkyblock.value) return true;
+
+ Minecraft mc = Minecraft.getMinecraft();
+
+ if (mc != null && mc.theWorld != null) {
+ Scoreboard scoreboard = mc.theWorld.getScoreboard();
+ ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1);
+ if (sidebarObjective != null) {
+ String objectiveName = sidebarObjective.getDisplayName().replaceAll("(?i)\\u00A7.", "");
+ for (String skyblock : SKYBLOCK_IN_ALL_LANGUAGES) {
+ if (objectiveName.startsWith(skyblock)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/RequestFocusListener.java b/src/main/java/io/github/moulberry/notenoughupdates/RequestFocusListener.java
new file mode 100644
index 00000000..ecc27c9a
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/RequestFocusListener.java
@@ -0,0 +1,63 @@
+package io.github.moulberry.notenoughupdates;
+
+import javax.swing.*;
+import javax.swing.event.*;
+
+/**
+ * Convenience class to request focus on a component.
+ *
+ * When the component is added to a realized Window then component will
+ * request focus immediately, since the ancestorAdded event is fired
+ * immediately.
+ *
+ * When the component is added to a non realized Window, then the focus
+ * request will be made once the window is realized, since the
+ * ancestorAdded event will not be fired until then.
+ *
+ * Using the default constructor will cause the listener to be removed
+ * from the component once the AncestorEvent is generated. A second constructor
+ * allows you to specify a boolean value of false to prevent the
+ * AncestorListener from being removed when the event is generated. This will
+ * allow you to reuse the listener each time the event is generated.
+ */
+public class RequestFocusListener implements AncestorListener
+{
+ private boolean removeListener;
+
+ /*
+ * Convenience constructor. The listener is only used once and then it is
+ * removed from the component.
+ */
+ public RequestFocusListener()
+ {
+ this(true);
+ }
+
+ /*
+ * Constructor that controls whether this listen can be used once or
+ * multiple times.
+ *
+ * @param removeListener when true this listener is only invoked once
+ * otherwise it can be invoked multiple times.
+ */
+ public RequestFocusListener(boolean removeListener)
+ {
+ this.removeListener = removeListener;
+ }
+
+ @Override
+ public void ancestorAdded(AncestorEvent e)
+ {
+ JComponent component = e.getComponent();
+ component.requestFocusInWindow();
+
+ if (removeListener)
+ component.removeAncestorListener( this );
+ }
+
+ @Override
+ public void ancestorMoved(AncestorEvent e) {}
+
+ @Override
+ public void ancestorRemoved(AncestorEvent e) {}
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/Utils.java
new file mode 100644
index 00000000..bcab59c4
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/Utils.java
@@ -0,0 +1,185 @@
+package io.github.moulberry.notenoughupdates;
+
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Utils {
+
+ public static <T> ArrayList<T> createList(T... values) {
+ ArrayList<T> list = new ArrayList<>();
+ for(T value : values)list.add(value);
+ return list;
+ }
+
+ public static void drawHoveringText(List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font) {
+ if (!textLines.isEmpty())
+ {
+ GlStateManager.disableRescaleNormal();
+ RenderHelper.disableStandardItemLighting();
+ GlStateManager.disableLighting();
+ GlStateManager.disableDepth();
+ int tooltipTextWidth = 0;
+
+ for (String textLine : textLines)
+ {
+ int textLineWidth = font.getStringWidth(textLine);
+
+ if (textLineWidth > tooltipTextWidth)
+ {
+ tooltipTextWidth = textLineWidth;
+ }
+ }
+
+ boolean needsWrap = false;
+
+ int titleLinesCount = 1;
+ int tooltipX = mouseX + 12;
+ if (tooltipX + tooltipTextWidth + 4 > screenWidth)
+ {
+ tooltipX = mouseX - 16 - tooltipTextWidth;
+ if (tooltipX < 4) // if the tooltip doesn't fit on the screen
+ {
+ if (mouseX > screenWidth / 2)
+ {
+ tooltipTextWidth = mouseX - 12 - 8;
+ }
+ else
+ {
+ tooltipTextWidth = screenWidth - 16 - mouseX;
+ }
+ needsWrap = true;
+ }
+ }
+
+ if (maxTextWidth > 0 && tooltipTextWidth > maxTextWidth)
+ {
+ tooltipTextWidth = maxTextWidth;
+ needsWrap = true;
+ }
+
+ if (needsWrap)
+ {
+ int wrappedTooltipWidth = 0;
+ List<String> wrappedTextLines = new ArrayList<String>();
+ for (int i = 0; i < textLines.size(); i++)
+ {
+ String textLine = textLines.get(i);
+ List<String> wrappedLine = font.listFormattedStringToWidth(textLine, tooltipTextWidth);
+ if (i == 0)
+ {
+ titleLinesCount = wrappedLine.size();
+ }
+
+ for (String line : wrappedLine)
+ {
+ int lineWidth = font.getStringWidth(line);
+ if (lineWidth > wrappedTooltipWidth)
+ {
+ wrappedTooltipWidth = lineWidth;
+ }
+ wrappedTextLines.add(line);
+ }
+ }
+ tooltipTextWidth = wrappedTooltipWidth;
+ textLines = wrappedTextLines;
+
+ if (mouseX > screenWidth / 2)
+ {
+ tooltipX = mouseX - 16 - tooltipTextWidth;
+ }
+ else
+ {
+ tooltipX = mouseX + 12;
+ }
+ }
+
+ int tooltipY = mouseY - 12;
+ int tooltipHeight = 8;
+
+ if (textLines.size() > 1)
+ {
+ tooltipHeight += (textLines.size() - 1) * 10;
+ if (textLines.size() > titleLinesCount) {
+ tooltipHeight += 2; // gap between title lines and next lines
+ }
+ }
+
+ if (tooltipY + tooltipHeight + 6 > screenHeight)
+ {
+ tooltipY = screenHeight - tooltipHeight - 6;
+ }
+
+ final int zLevel = 300;
+ final int backgroundColor = 0xF0100010;
+ drawGradientRect(zLevel, tooltipX - 3, tooltipY - 4, tooltipX + tooltipTextWidth + 3, tooltipY - 3, backgroundColor, backgroundColor);
+ drawGradientRect(zLevel, tooltipX - 3, tooltipY + tooltipHeight + 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 4, backgroundColor, backgroundColor);
+ drawGradientRect(zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor);
+ drawGradientRect(zLevel, tooltipX - 4, tooltipY - 3, tooltipX - 3, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor);
+ drawGradientRect(zLevel, tooltipX + tooltipTextWidth + 3, tooltipY - 3, tooltipX + tooltipTextWidth + 4, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor);
+ final int borderColorStart = 0x505000FF;
+ final int borderColorEnd = (borderColorStart & 0xFEFEFE) >> 1 | borderColorStart & 0xFF000000;
+ drawGradientRect(zLevel, tooltipX - 3, tooltipY - 3 + 1, tooltipX - 3 + 1, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd);
+ drawGradientRect(zLevel, tooltipX + tooltipTextWidth + 2, tooltipY - 3 + 1, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd);
+ drawGradientRect(zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY - 3 + 1, borderColorStart, borderColorStart);
+ drawGradientRect(zLevel, tooltipX - 3, tooltipY + tooltipHeight + 2, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, borderColorEnd, borderColorEnd);
+
+ for (int lineNumber = 0; lineNumber < textLines.size(); ++lineNumber)
+ {
+ String line = textLines.get(lineNumber);
+ font.drawStringWithShadow(line, (float)tooltipX, (float)tooltipY, -1);
+
+ if (lineNumber + 1 == titleLinesCount)
+ {
+ tooltipY += 2;
+ }
+
+ tooltipY += 10;
+ }
+
+ GlStateManager.enableLighting();
+ GlStateManager.enableDepth();
+ RenderHelper.enableStandardItemLighting();
+ GlStateManager.enableRescaleNormal();
+ }
+ GlStateManager.disableLighting();
+ }
+
+ public static void drawGradientRect(int zLevel, int left, int top, int right, int bottom, int startColor, int endColor) {
+ float startAlpha = (float)(startColor >> 24 & 255) / 255.0F;
+ float startRed = (float)(startColor >> 16 & 255) / 255.0F;
+ float startGreen = (float)(startColor >> 8 & 255) / 255.0F;
+ float startBlue = (float)(startColor & 255) / 255.0F;
+ float endAlpha = (float)(endColor >> 24 & 255) / 255.0F;
+ float endRed = (float)(endColor >> 16 & 255) / 255.0F;
+ float endGreen = (float)(endColor >> 8 & 255) / 255.0F;
+ float endBlue = (float)(endColor & 255) / 255.0F;
+
+ GlStateManager.disableTexture2D();
+ GlStateManager.enableBlend();
+ GlStateManager.disableAlpha();
+ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+ GlStateManager.shadeModel(7425);
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR);
+ worldrenderer.pos(right, top, zLevel).color(startRed, startGreen, startBlue, startAlpha).endVertex();
+ worldrenderer.pos(left, top, zLevel).color(startRed, startGreen, startBlue, startAlpha).endVertex();
+ worldrenderer.pos(left, bottom, zLevel).color(endRed, endGreen, endBlue, endAlpha).endVertex();
+ worldrenderer.pos(right, bottom, zLevel).color(endRed, endGreen, endBlue, endAlpha).endVertex();
+ tessellator.draw();
+
+ GlStateManager.shadeModel(7424);
+ GlStateManager.disableBlend();
+ GlStateManager.enableAlpha();
+ GlStateManager.enableTexture2D();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/WikiaParser.java b/src/main/java/io/github/moulberry/notenoughupdates/WikiaParser.java
new file mode 100644
index 00000000..fc94f60c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/WikiaParser.java
@@ -0,0 +1,212 @@
+package io.github.moulberry.notenoughupdates;
+
+import info.bliki.wiki.filter.PlainTextConverter;
+import info.bliki.wiki.model.WikiModel;
+import net.minecraft.util.EnumChatFormatting;
+
+import java.io.*;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Stack;
+
+public class WikiaParser {
+
+ private static Stack<Formatting> formattingStack = new Stack<>();
+ private static Stack<String> textStack = new Stack<>();
+
+ public static String parse(String raw) {
+ if(textStack.isEmpty()) textStack.push(get());
+
+ raw = raw.replaceAll("\u00A0", " ");
+
+ out:
+ for(int i=0; i<raw.length(); i++) {
+ if(i >= raw.length()) break;
+ String lineS = raw.substring(i);
+ for(Formatting f : Formatting.values()) {
+ if(lineS.startsWith(f.start)) {
+ if(tryPush(f, true)) {
+ writeToStack(get());
+ i += f.start.length()-1;
+ continue out;
+ }
+ } else if(lineS.startsWith(f.end)) {
+ if(tryPush(f, false)) {
+ writeToStack(get());
+ i += f.end.length()-1;
+ continue out;
+ }
+ }
+ }
+ writeToStack(String.valueOf(lineS.charAt(0)));
+ if(lineS.charAt(0) == '\n') {
+ writeToStack(get());
+ }
+ }
+
+ String f = trimIgnoreColour(clear());
+ return f.replaceAll("(\\n(\\u00A7.)*){2,}", "$1")
+ .replaceAll("\r","\n");
+ }
+ private enum Formatting {
+ LINK("[[", "]]", "") {
+ public String apply(String ctx) {
+ String[] split = ctx.split("\\|");
+ String base = split[split.length-1];
+ return "[["+ctx+"]]";
+ }
+ },
+ INFOBOX("<infobox", "</infobox>", "") {
+ public String apply(String ctx) {
+ return "";
+ }
+ },
+ MATH("<math>", "</math>", "") {
+ public String apply(String ctx) {
+ //ctx = trimIgnoreColour(ctx).replaceAll("\\times", "")
+ return ctx;
+ }
+ },
+ TEMPLATE("{{", "}}", "") {
+ @Override
+ public String apply(String ctx) {
+ //String[] colours = new String[]{"red","green","yellow"};
+
+ String[] split = ctx.split("\\|");
+ String after = split[split.length-1].trim();
+ /*if(ctx.trim().startsWith("ItemAbility")) {
+ return "<br><br><span style=\"color:orange\">Item Ability: " + after + "</span> ";
+ } else {
+ for(String col : colours) {
+ if(ctx.trim().toLowerCase().startsWith(col)) {
+ return "<p style=\"color:"+col+"\">"+after+"</p>";
+ }
+ }
+ }*/
+ return "{{"+ctx+"}}";
+ }
+ };
+
+ private boolean ambiguous;
+ private String start;
+ private String end;
+ private String colourCode;
+ private boolean autoend;
+
+ Formatting(String start, String end, String colourCode) {
+ this.start = start;
+ this.end = end;
+ this.ambiguous = start.equals(end);
+ this.colourCode = colourCode;
+ }
+
+ Formatting(String start, String end, String colourCode, boolean autoend) {
+ this.start = start;
+ this.end = end;
+ this.ambiguous = start.equals(end);
+ this.colourCode = colourCode;
+ this.autoend = autoend;
+ }
+
+ public String apply(String ctx) {
+ return ctx;
+ }
+ public boolean consume(boolean start) {
+ return true;
+ }
+ }
+
+ private static String trimIgnoreColour(String str) {
+ StringBuilder sb = new StringBuilder();
+
+ while(!str.isEmpty()) {
+ str = str.trim();
+ if(str.startsWith("\u00a7")) {
+ sb.append(str, 0, 2);
+ str = str.substring(2);
+ } else {
+ sb.append(str);
+ break;
+ }
+ }
+
+ return sb.toString();
+ }
+
+ private static int strLenNoColor(String str) {
+ return noColour(str).length();
+ }
+
+ private static String noColour(String str) {
+ return str.replaceAll("(?i)\\u00A7.", "");
+ }
+
+ private static boolean tryPush(Formatting formatting, boolean start) {
+ if(formatting.ambiguous) {
+ if(!formattingStack.isEmpty() && formattingStack.peek() == formatting) {
+ pop();
+ } else {
+ push(formatting);
+ }
+ } else {
+ if(start) {
+ push(formatting);
+ } else {
+ if(!formattingStack.isEmpty()) {
+ for(int i=1; i<=formattingStack.size(); i++) {
+ Formatting f = formattingStack.get(formattingStack.size()-i);
+ if(f == formatting) {
+ pop();
+ return formatting.consume(start);
+ } else if(f.autoend) {
+ pop();
+ } else {
+ return false;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ return formatting.consume(start);
+ }
+
+ private static String clear() {
+ while(!formattingStack.empty()) {
+ pop();
+ }
+ String ret = textStack.peek();
+
+ formattingStack.clear();
+ textStack.clear();
+ textStack.push(get());
+
+ return ret;
+ }
+
+ private static void pop() {
+ Formatting f = formattingStack.pop();
+ String applied = f.apply(textStack.pop());
+ writeToStack(applied);
+ }
+
+ private static void push(Formatting formatting) {
+ formattingStack.push(formatting);
+ textStack.push("");
+ }
+
+ private static void writeToStack(String s) {
+ textStack.push(textStack.pop() + s);
+ }
+
+ private static String get() {
+ StringBuilder colour = new StringBuilder("");
+ for(Formatting f : formattingStack) {
+ colour.append(f.colourCode);
+ }
+ return colour.toString();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/WikiaParserOLD.java b/src/main/java/io/github/moulberry/notenoughupdates/WikiaParserOLD.java
new file mode 100644
index 00000000..82f7505e
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/WikiaParserOLD.java
@@ -0,0 +1,270 @@
+package io.github.moulberry.notenoughupdates;
+
+import info.bliki.wiki.filter.PlainTextConverter;
+import info.bliki.wiki.model.WikiModel;
+import net.minecraft.util.EnumChatFormatting;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Stack;
+
+public class WikiaParserOLD {
+
+ private static WikiModel wikiModel = new WikiModel("https://hypixel-skyblock.fandom.com/wiki/${image}",
+ "https://hypixel-skyblock.fandom.com/wiki/${title}");
+ private static PlainTextConverter ptc = new PlainTextConverter();
+ private static Stack<Formatting> formattingStack = new Stack<>();
+ private static Stack<String> textStack = new Stack<>();
+
+ public static String parse(String raw) {
+ if(textStack.isEmpty()) textStack.push(get());
+
+ raw = raw.replaceAll("\u00A0", " ");
+ String[] split = raw.split("</infobox>");
+ String afterInfobox = split[split.length-1];
+
+ out:
+ for(int i=0; i<afterInfobox.length(); i++) {
+ if(i >= afterInfobox.length()) break;
+ String lineS = afterInfobox.substring(i);
+ for(Formatting f : Formatting.values()) {
+ if(lineS.startsWith(f.start)) {
+ if(tryPush(f, true)) {
+ writeToStack(get());
+ i += f.start.length()-1;
+ continue out;
+ }
+ } else if(lineS.startsWith(f.end)) {
+ if(tryPush(f, false)) {
+ writeToStack(get());
+ i += f.end.length()-1;
+ continue out;
+ }
+ }
+ }
+ writeToStack(String.valueOf(lineS.charAt(0)));
+ if(lineS.charAt(0) == '\n') {
+ writeToStack(get());
+ }
+ }
+
+ String f = trimIgnoreColour(clear());
+ return f.replaceAll("(\\n(\\u00A7.)*){2,}", "$1")
+ .replaceAll("\r","\n");
+ }
+
+ private enum Formatting {
+ BOLD("'''", "'''", EnumChatFormatting.WHITE+EnumChatFormatting.BOLD.toString()),
+ //GREEN("{{Green|","}}",EnumChatFormatting.GREEN.toString()),
+ LIST("\n*", "\n", "", true) {
+ public String apply(String ctx) {
+ return "\n \u2022 " + trimIgnoreColour(ctx) + "\n";
+ }
+ public boolean consume(boolean start) {
+ return start;
+ }
+ },
+ LIST2("\n#", "\n", "", true) {
+ public String apply(String ctx) {
+ return "\n \u2022 " + trimIgnoreColour(ctx) + "\n";
+ }
+ public boolean consume(boolean start) {
+ return start;
+ }
+ },
+ SMALL_HEADER("\n;", "\n", EnumChatFormatting.WHITE.toString(), true) {
+ public String apply(String ctx) {
+ return "\n" + trimIgnoreColour(ctx) + "\n";
+ }
+ public boolean consume(boolean start) {
+ return start;
+ }
+ },
+ TAB("\n:", "\n", "", true) {
+ public String apply(String ctx) {
+ return "\n " + trimIgnoreColour(ctx) + "\n";
+ }
+ public boolean consume(boolean start) {
+ return start;
+ }
+ },
+ TINY("====", "====", EnumChatFormatting.WHITE+EnumChatFormatting.BOLD.toString()) {
+ public String apply(String ctx) {
+ return trimIgnoreColour(ctx);
+ }
+ },
+ SMALL("===", "===", EnumChatFormatting.GOLD.toString()) {
+ public String apply(String ctx) {
+ return " " + trimIgnoreColour(ctx);
+ }
+ },
+ MEDIUM("==", "==", EnumChatFormatting.GOLD+EnumChatFormatting.BOLD.toString()) {
+ public String apply(String ctx) {
+ return "\r " + trimIgnoreColour(ctx);
+ }
+ },
+ CUSTOM("{{","}}","") {
+ //❤,❁,☠,✦
+ public String apply(String ctx) {
+ if(noColour(ctx).trim().startsWith("Green|")) {
+ return EnumChatFormatting.GREEN+ctx.split("Green\\|")[1];
+ } else if(noColour(ctx).trim().startsWith("Grey|")) {
+ return EnumChatFormatting.DARK_GRAY+ctx.split("Grey\\|")[1];
+ } else if(noColour(ctx).trim().equalsIgnoreCase("Statname|Crit Damage")) {
+ return EnumChatFormatting.BLUE+"☠ Crit Damage";
+ } else {
+ try {
+ return wikiModel.render(ptc, "{{"+ctx+"}}");
+ } catch(Exception e) {return "";}
+ }
+ }
+ },
+ LINK("[[", "]]", "") {
+ public String apply(String ctx) {
+ if(noColour(ctx).toLowerCase().startsWith("file:")) return "";
+
+ String[] split = ctx.split("#");
+ ctx = split[split.length-1];
+
+ split = ctx.split("\\|");
+ ctx = split[split.length-1];
+ return ctx;
+ }
+ },
+ MATH("<math>", "</math>", EnumChatFormatting.BOLD.toString()+EnumChatFormatting.WHITE) {
+ public String apply(String ctx) {
+ //ctx = trimIgnoreColour(ctx).replaceAll("\\times", "")
+ return ctx;
+ }
+ },CLASS("{|", "|}", "") {
+ public String apply(String ctx) {
+ try {
+ return wikiModel.render(ptc, "{|"+ctx+"|}");
+ } catch(Exception e) {return "";}
+ }
+ };
+
+ private boolean ambiguous;
+ private String start;
+ private String end;
+ private String colourCode;
+ private boolean autoend;
+
+ Formatting(String start, String end, String colourCode) {
+ this.start = start;
+ this.end = end;
+ this.ambiguous = start.equals(end);
+ this.colourCode = colourCode;
+ }
+
+ Formatting(String start, String end, String colourCode, boolean autoend) {
+ this.start = start;
+ this.end = end;
+ this.ambiguous = start.equals(end);
+ this.colourCode = colourCode;
+ this.autoend = autoend;
+ }
+
+ public String apply(String ctx) {
+ return ctx;
+ }
+ public boolean consume(boolean start) {
+ return true;
+ }
+ }
+
+ private static String trimIgnoreColour(String str) {
+ StringBuilder sb = new StringBuilder();
+
+ while(!str.isEmpty()) {
+ str = str.trim();
+ if(str.startsWith("\u00a7")) {
+ sb.append(str, 0, 2);
+ str = str.substring(2);
+ } else {
+ sb.append(str);
+ break;
+ }
+ }
+
+ return sb.toString();
+ }
+
+ private static int strLenNoColor(String str) {
+ return noColour(str).length();
+ }
+
+ private static String noColour(String str) {
+ return str.replaceAll("(?i)\\u00A7.", "");
+ }
+
+ private static boolean tryPush(Formatting formatting, boolean start) {
+ if(formatting.ambiguous) {
+ if(!formattingStack.isEmpty() && formattingStack.peek() == formatting) {
+ pop();
+ } else {
+ push(formatting);
+ }
+ } else {
+ if(start) {
+ push(formatting);
+ } else {
+ if(!formattingStack.isEmpty()) {
+ for(int i=1; i<=formattingStack.size(); i++) {
+ Formatting f = formattingStack.get(formattingStack.size()-i);
+ if(f == formatting) {
+ pop();
+ return formatting.consume(start);
+ } else if(f.autoend) {
+ pop();
+ } else {
+ return false;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ return formatting.consume(start);
+ }
+
+ private static String clear() {
+ while(!formattingStack.empty()) {
+ pop();
+ }
+ String ret = textStack.peek();
+
+ formattingStack.clear();
+ textStack.clear();
+ textStack.push(get());
+
+ return ret;
+ }
+
+ private static void pop() {
+ Formatting f = formattingStack.pop();
+ String applied = f.apply(textStack.pop());
+ writeToStack(applied);
+ }
+
+ private static void push(Formatting formatting) {
+ formattingStack.push(formatting);
+ textStack.push("");
+ }
+
+ private static void writeToStack(String s) {
+ textStack.push(textStack.pop() + s);
+ }
+
+ private static String get() {
+ StringBuilder colour = new StringBuilder(EnumChatFormatting.RESET.toString() + EnumChatFormatting.GRAY);
+ for(Formatting f : formattingStack) {
+ colour.append(f.colourCode);
+ }
+ return colour.toString();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java
index 5ad5c66c..99fbfd78 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java
@@ -6,6 +6,7 @@ import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.EnumChatFormatting;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Nullable;
@@ -21,8 +22,8 @@ public class GuiElementTextField extends GuiElement {
public static final int COLOUR = 0b00010;
public static final int MULTILINE = 0b00001;
- private static final int searchBarYSize = 20;
- private static final int searchBarXSize = 350;
+ private int searchBarYSize = 20;
+ private int searchBarXSize = 350;
private static final int searchBarPadding = 2;
private int options = 0;
@@ -35,6 +36,8 @@ public class GuiElementTextField extends GuiElement {
private GuiTextField textField = new GuiTextField(0, Minecraft.getMinecraft().fontRendererObj,
0 , 0, 0, 0);
+ private int customBorderColour = -1;
+
public GuiElementTextField(String initialText, int options) {
textField.setFocused(true);
textField.setCanLoseFocus(false);
@@ -43,6 +46,19 @@ public class GuiElementTextField extends GuiElement {
this.options = options;
}
+ public void setCustomBorderColour(int colour) {
+ this.customBorderColour = colour;
+ }
+
+ public String getText() {
+ return textField.getText();
+ }
+
+ public void setSize(int searchBarXSize, int searchBarYSize) {
+ this.searchBarXSize = searchBarXSize;
+ this.searchBarYSize = searchBarYSize;
+ }
+
@Override
public String toString() {
return textField.getText();
@@ -307,17 +323,21 @@ public class GuiElementTextField extends GuiElement {
int extraSize = (searchBarYSize-8)/2+8;
int bottomTextBox = y + searchBarYSize + extraSize*(numLines-1);
- //Search bar background
+ int borderColour = focus ? Color.GREEN.getRGB() : Color.WHITE.getRGB();
+ if(customBorderColour != -1) {
+ borderColour = customBorderColour;
+ }
+ //bar background
drawRect(x - paddingUnscaled,
y - paddingUnscaled,
x + searchBarXSize + paddingUnscaled,
- bottomTextBox + paddingUnscaled, focus ? Color.GREEN.getRGB() : Color.WHITE.getRGB());
+ bottomTextBox + paddingUnscaled, borderColour);
drawRect(x,
y,
x + searchBarXSize,
bottomTextBox, Color.BLACK.getRGB());
- //Search bar text
+ //bar text
Pattern patternControlCode = Pattern.compile("(?i)\\u00A7([^\\u00B6\n])(?!\\u00B6)");
String text = textField.getText();
@@ -373,8 +393,21 @@ public class GuiElementTextField extends GuiElement {
int texX = 0;
int texY = 0;
+ boolean sectionSignPrev = false;
+ boolean bold = false;
for(int i=0; i<textNoColor.length(); i++) {
char c = textNoColor.charAt(i);
+ if(sectionSignPrev) {
+ if(c != 'k' && c != 'K'
+ && c != 'm' && c != 'M'
+ && c != 'n' && c != 'N'
+ && c != 'o' && c != 'O') {
+ bold = c == 'l' || c == 'L';
+ }
+ }
+ sectionSignPrev = false;
+ if(c == '\u00B6') sectionSignPrev = true;
+
if(c == '\n') {
if(i >= leftIndex && i < rightIndex) {
drawRect(x + 5 + texX,
@@ -388,7 +421,10 @@ public class GuiElementTextField extends GuiElement {
continue;
}
+ //String c2 = bold ? EnumChatFormatting.BOLD.toString() : "" + c;
+
int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(String.valueOf(c));
+ if(bold) len++;
if(i >= leftIndex && i < rightIndex) {
drawRect(x + 5 + texX,
y+(searchBarYSize-8)/2-1 + texY,
@@ -398,6 +434,11 @@ public class GuiElementTextField extends GuiElement {
Minecraft.getMinecraft().fontRendererObj.drawString(String.valueOf(c),
x + 5 + texX,
y+(searchBarYSize-8)/2 + texY, Color.BLACK.getRGB());
+ if(bold) {
+ Minecraft.getMinecraft().fontRendererObj.drawString(String.valueOf(c),
+ x + 5 + texX +1,
+ y+(searchBarYSize-8)/2 + texY, Color.BLACK.getRGB());
+ }
}
texX += len;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java
index 6cc8aacd..23849ceb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java
@@ -4,6 +4,7 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.LerpingInteger;
import io.github.moulberry.notenoughupdates.NEUManager;
+import io.github.moulberry.notenoughupdates.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*;
import net.minecraft.client.renderer.GlStateManager;
@@ -13,8 +14,6 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.*;
import net.minecraft.util.ResourceLocation;
-import net.minecraftforge.fml.client.config.GuiUtils;
-import org.apache.commons.lang3.StringUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
@@ -44,6 +43,7 @@ public class NEUItemEditor extends GuiScreen {
private Supplier<String> itemid;
private Supplier<String> displayname;
private Supplier<String> lore;
+ private Supplier<String> infoType;
private Supplier<String> info;
private Supplier<String> clickcommand;
private Supplier<String> damage;
@@ -77,8 +77,15 @@ public class NEUItemEditor extends GuiScreen {
for(int i=0; i<lore.size(); i++) loreA[i] = lore.get(i).getAsString();
this.lore = addTextFieldWithSupplier(String.join("\n", loreA), COLOUR | MULTILINE);
+ options.add(new GuiElementText("Info type: ", Color.WHITE.getRGB()));
+ String infoType = item.has("infoType") ? item.get("infoType").getAsString() : "";
+ this.infoType = addTextFieldWithSupplier(infoType, NO_SPACE | FORCE_CAPS);
+
options.add(new GuiElementText("Additional information: ", Color.WHITE.getRGB()));
- this.info = addTextFieldWithSupplier("", COLOUR | MULTILINE);
+ JsonArray info = item.has("info") ? item.get("info").getAsJsonArray() : new JsonArray();
+ String[] infoA = new String[info.size()];
+ for(int i=0; i<info.size(); i++) infoA[i] = info.get(i).getAsString();
+ this.info = addTextFieldWithSupplier(String.join("\n", infoA), COLOUR | MULTILINE);
options.add(new GuiElementText("Click-command (viewrecipe or viewpotion): ", Color.WHITE.getRGB()));
String clickcommand = item.has("clickcommand") ? item.get("clickcommand").getAsString() : "";
@@ -144,8 +151,8 @@ public class NEUItemEditor extends GuiScreen {
if(infoA.length == 0 || infoA[0].isEmpty()) {
infoA = new String[0];
}
- return manager.writeItemJson(internalname.get(), itemid.get(), displayname.get(), lore.get().split("\n"),
- infoA, clickcommand.get(), damageI, nbttag);
+ return manager.writeItemJson(item, internalname.get(), itemid.get(), displayname.get(), lore.get().split("\n"),
+ infoType.get(), infoA, clickcommand.get(), damageI, nbttag);
}
public boolean upload() {
@@ -159,7 +166,7 @@ public class NEUItemEditor extends GuiScreen {
infoA = new String[0];
}
return manager.uploadItemJson(internalname.get(), itemid.get(), displayname.get(), lore.get().split("\n"),
- infoA, clickcommand.get(), damageI, nbttag);
+ infoType.get(), infoA, clickcommand.get(), damageI, nbttag);
}
public void onGuiClosed() {
@@ -292,7 +299,7 @@ public class NEUItemEditor extends GuiScreen {
text.add(displayname.get());
text.addAll(Arrays.asList(lore.get().split("\n")));
- GuiUtils.drawHoveringText(text, itemX-20, itemY+itemSize+28, width, height, -1,
+ Utils.drawHoveringText(text, itemX-20, itemY+itemSize+28, width, height, -1,
Minecraft.getMinecraft().fontRendererObj);
GlStateManager.disableLighting();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java
new file mode 100644
index 00000000..61807553
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java
@@ -0,0 +1,173 @@
+package io.github.moulberry.notenoughupdates.options;
+
+import com.google.common.collect.Lists;
+import com.google.gson.*;
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.Utils;
+
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Options {
+
+ public Option<Boolean> enableItemEditing = new Option(
+ false,
+ "Enable Item Editing",
+ true,
+ "Dev Feature. Please don't use.");
+ public Option<Boolean> onlyShowOnSkyblock = new Option(
+ true,
+ "Only Show On Skyblock",
+ false,
+ "GUI Overlay only appears when you are playing Skyblock.");
+ public Option<Boolean> autoupdate = new Option(
+ true,
+ "Automatically Update Items",
+ false,
+ "If true, updated items will automatically download from the remote repository when you start the game. \nHIGHLY RECOMMENDED.");
+ public Option<Boolean> keepopen = new Option(
+ false,
+ "Keep Itempane Open",
+ false,
+ "If true, the itempane will stay open after the gui is closed.");
+ public Option<Double> paneWidthMult = new Option(
+ 1.0,
+ "Pane Width Multiplier",
+ false,
+ "Changes how wide the item and info panes are. Value between 0.5-1.5.");
+ public Option<Double> bgOpacity = new Option(
+ 50.0,
+ "Pane Background Opacity",
+ false,
+ "Changes the background colour opacity of item and info panes. Value between 0-255.");
+ public Option<Double> fgOpacity = new Option(
+ 255.0,
+ "Item Background Opacity",
+ false,
+ "Changes the opacity of item background. Value between 0-255.");
+
+ /**
+ * OPTIONS THAT DON'T SHOW IN GUI
+ */
+ public Option<Boolean> dev = new Option(
+ false,
+ "Show Dev Options",
+ true,
+ "Dev Feature. Please don't use.");
+ public Option<Double> compareMode = new Option(
+ 0.0,
+ "Compare Mode",
+ false,
+ "Compare Mode");
+ public Option<Double> sortMode = new Option(
+ 0.0,
+ "Sort Mode",
+ false,
+ "Sort Mode");
+ public Option<ArrayList<Boolean>> compareAscending = new Option(
+ Utils.createList(true, true),
+ "Compare Ascending",
+ false,
+ "Compare Ascending");
+ public Option<ArrayList<String>> favourites = new Option(
+ new ArrayList<String>(),
+ "Favourites",
+ false,
+ "Favourites");
+
+ public List<Option> getOptions() {
+ List<Option> options = new ArrayList<>();
+
+ tryAddOption(enableItemEditing, options);
+ tryAddOption(onlyShowOnSkyblock, options);
+ tryAddOption(autoupdate, options);
+ tryAddOption(keepopen, options);
+ tryAddOption(paneWidthMult, options);
+ tryAddOption(bgOpacity, options);
+ tryAddOption(fgOpacity, options);
+
+ return options;
+ }
+
+ private void tryAddOption(Option<?> option, List<Option> list) {
+ if(!option.secret || dev.value) {
+ list.add(option);
+ }
+ }
+
+ public static class Option<T> implements Serializable {
+ public T value;
+ public final transient T defaultValue;
+ public final transient String displayName;
+ public final transient boolean secret;
+ public final transient String desc;
+
+ public Option(T defaultValue, String displayName, boolean secret, String desc) {
+ this.value = defaultValue;
+ this.defaultValue = defaultValue;
+ this.displayName = displayName;
+ this.secret = secret;
+ this.desc = desc;
+ }
+
+ public void setValue(String value) {
+ if(this.value instanceof Boolean) {
+ ((Option<Boolean>) this).value = Boolean.valueOf(value);
+ } else if(this.value instanceof Double) {
+ ((Option<Double>)this).value = Double.valueOf(value);
+ } else if(this.value instanceof String) {
+ ((Option<String>)this).value = value;
+ }
+ }
+ }
+
+ public static JsonSerializer<Option<?>> createSerializer() {
+ return (src, typeOfSrc, context) -> {
+ if(src.secret && src.defaultValue.equals(src.value)) {
+ return null;
+ }
+ return context.serialize(src.value);
+ };
+ }
+
+ public static JsonDeserializer<Option<?>> createDeserializer() {
+ return (json, typeOfT, context) -> {
+ try {
+ return new Option(context.deserialize(json, Object.class), "unknown", false, "unknown");
+ } catch(Exception e) {
+ return null;
+ }
+ };
+ }
+
+ public static Options loadFromFile(Gson gson, File file) throws IOException {
+ InputStream in = new FileInputStream(file);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
+
+ Options oLoad = gson.fromJson(reader, Options.class);
+ Options oDefault = new Options();
+ if(oLoad == null) return oDefault;
+
+ for(Field f : Options.class.getDeclaredFields()) {
+ try {
+ ((Option)f.get(oDefault)).value = ((Option)f.get(oLoad)).value;
+ } catch (Exception e) { }
+ }
+ return oDefault;
+ }
+
+ public void saveToFile(Gson gson, File file) throws IOException {
+ file.createNewFile();
+
+ try(BufferedWriter writer = new BufferedWriter(
+ new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {
+ writer.write(gson.toJson(this));
+ }
+ }
+
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HTMLParagraphView.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HTMLParagraphView.java
new file mode 100644
index 00000000..ab4be4a7
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HTMLParagraphView.java
@@ -0,0 +1,30 @@
+package io.github.moulberry.notenoughupdates.util;
+
+import javax.swing.text.Element;
+import javax.swing.text.FlowView;
+import javax.swing.text.View;
+import javax.swing.text.html.ParagraphView;
+
+class HTMLParagraphView extends ParagraphView {
+
+ public static int MAX_VIEW_SIZE=100;
+
+ public HTMLParagraphView(Element elem) {
+ super(elem);
+ strategy = new HTMLParagraphView.HTMLFlowStrategy();
+ }
+
+ public static class HTMLFlowStrategy extends FlowStrategy {
+ protected View createView(FlowView fv, int startOffset, int spanLeft, int rowIndex) {
+ View res=super.createView(fv, startOffset, spanLeft, rowIndex);
+ if (res.getEndOffset()-res.getStartOffset()> MAX_VIEW_SIZE) {
+ res = res.createFragment(startOffset, startOffset+ MAX_VIEW_SIZE);
+ }
+ return res;
+ }
+
+ }
+ public int getResizeWeight(int axis) {
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HtmlImageGenerator.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HtmlImageGenerator.java
new file mode 100644
index 00000000..40866a00
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HtmlImageGenerator.java
@@ -0,0 +1,125 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by Fernflower decompiler)
+//
+package io.github.moulberry.notenoughupdates.util;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import javax.imageio.ImageIO;
+import javax.swing.JEditorPane;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.ImageView;
+import javax.swing.text.html.StyleSheet;
+
+public class HtmlImageGenerator {
+ public JEditorPane editorPane = this.createJEditorPane();
+ static final Dimension DEFAULT_SIZE = new Dimension(800, 800);
+
+ public HtmlImageGenerator() {
+ }
+
+ public ComponentOrientation getOrientation() {
+ return this.editorPane.getComponentOrientation();
+ }
+
+ public void setOrientation(ComponentOrientation orientation) {
+ this.editorPane.setComponentOrientation(orientation);
+ }
+
+ public Dimension getSize() {
+ return this.editorPane.getSize();
+ }
+
+ public void setSize(Dimension dimension) {
+ this.editorPane.setSize(dimension);
+ }
+
+ public void loadUrl(URL url) {
+ try {
+ this.editorPane.setPage(url);
+ } catch (IOException var3) {
+ throw new RuntimeException(String.format("Exception while loading %s", url), var3);
+ }
+ }
+
+ public void loadUrl(String url) {
+ try {
+ this.editorPane.setPage(url);
+ } catch (IOException var3) {
+ throw new RuntimeException(String.format("Exception while loading %s", url), var3);
+ }
+ }
+
+ public void loadHtml(String html) {
+ this.editorPane.setText(html);
+ this.onDocumentLoad();
+ }
+
+ public void saveAsImage(String file) {
+ this.saveAsImage(new File(file));
+ }
+
+ public void saveAsImage(File file) {
+ BufferedImage img = this.getBufferedImage();
+
+ try {
+ ImageIO.write(img, "png", file);
+ } catch (IOException var4) {
+ throw new RuntimeException(String.format("Exception while saving '%s' image", file), var4);
+ }
+ }
+
+ protected void onDocumentLoad() {
+ }
+
+ public Dimension getDefaultSize() {
+ return DEFAULT_SIZE;
+ }
+
+ public BufferedImage getBufferedImage() {
+ Dimension prefSize = this.editorPane.getPreferredSize();
+ BufferedImage img = new BufferedImage(prefSize.width, this.editorPane.getPreferredSize().height, 2);
+ Graphics graphics = img.getGraphics();
+ this.editorPane.setSize(prefSize);
+ this.editorPane.paint(graphics);
+ return img;
+ }
+
+ public void addCss(String css) {
+ HTMLEditorKit kit = (HTMLEditorKit) editorPane.getEditorKitForContentType("text/html");
+ kit.getStyleSheet().addRule(css);
+ }
+
+ public void setScale(float factor) {
+ editorPane.getDocument().putProperty("ZOOM_FACTOR", new Double(factor));
+ }
+
+ protected JEditorPane createJEditorPane() {
+ JEditorPane editorPane = new JEditorPane();
+ editorPane.setSize(this.getDefaultSize());
+ editorPane.setEditable(false);
+ HTMLEditorKit kit = new LargeHTMLEditorKit();
+ editorPane.setEditorKitForContentType("text/html", kit);
+ editorPane.setBackground(new Color(0, true));
+ editorPane.setContentType("text/html");
+ editorPane.addPropertyChangeListener(new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (evt.getPropertyName().equals("page")) {
+ HtmlImageGenerator.this.onDocumentLoad();
+ }
+
+ }
+ });
+ return editorPane;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/LargeHTMLEditorKit.java b/src/main/java/io/github/moulberry/notenoughupdates/util/LargeHTMLEditorKit.java
new file mode 100644
index 00000000..7b69a541
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/LargeHTMLEditorKit.java
@@ -0,0 +1,132 @@
+package io.github.moulberry.notenoughupdates.util;
+
+import javax.swing.text.*;
+import javax.swing.text.html.*;
+import java.awt.*;
+import java.awt.geom.AffineTransform;
+
+public class LargeHTMLEditorKit extends HTMLEditorKit {
+
+ ViewFactory factory = new MyViewFactory();
+
+ @Override
+ public ViewFactory getViewFactory() {
+ return factory;
+ }
+
+ public Document createDefaultDocument() {
+ HTMLDocument doc = (HTMLDocument)super.createDefaultDocument();
+ doc.setAsynchronousLoadPriority(-1);
+ return doc;
+ }
+
+ class MyViewFactory extends HTMLFactory {
+ @Override
+ public View create(Element elem) {
+ AttributeSet attrs = elem.getAttributes();
+ Object elementName = attrs.getAttribute(AbstractDocument.ElementNameAttribute);
+ Object o = (elementName != null) ? null : attrs.getAttribute(StyleConstants.NameAttribute);
+ if (o instanceof HTML.Tag) {
+ HTML.Tag kind = (HTML.Tag) o;
+ if (kind == HTML.Tag.HTML) {
+ return new HTMLBlockView(elem);
+ }
+ }
+ View view = super.create(elem);
+ if(view instanceof ImageView) {
+ //((ImageView)view).setLoadsSynchronously(true);
+ }
+ return view;
+ }
+
+ }
+
+
+ private class HTMLBlockView extends BlockView {
+
+ public HTMLBlockView(Element elem) {
+ super(elem, View.Y_AXIS);
+ }
+
+ @Override
+ protected void layout(int width, int height) {
+ if (width<Integer.MAX_VALUE) {
+ super.layout(new Double(width / getZoomFactor()).intValue(),
+ new Double(height *
+ getZoomFactor()).intValue());
+ }
+ }
+
+ public double getZoomFactor() {
+ Double scale = (Double) getDocument().getProperty("ZOOM_FACTOR");
+ if (scale != null) {
+ return scale.doubleValue();
+ }
+
+ return 1;
+ }
+
+ @Override
+ public void paint(Graphics g, Shape allocation) {
+ Graphics2D g2d = (Graphics2D) g;
+ double zoomFactor = getZoomFactor();
+ AffineTransform old = g2d.getTransform();
+ g2d.scale(zoomFactor, zoomFactor);
+ super.paint(g2d, allocation);
+ g2d.setTransform(old);
+ }
+
+ @Override
+ public float getMinimumSpan(int axis) {
+ float f = super.getMinimumSpan(axis);
+ f *= getZoomFactor();
+ return f;
+ }
+
+ @Override
+ public float getMaximumSpan(int axis) {
+ float f = super.getMaximumSpan(axis);
+ f *= getZoomFactor();
+ return f;
+ }
+
+ @Override
+ public float getPreferredSpan(int axis) {
+ float f = super.getPreferredSpan(axis);
+ f *= getZoomFactor();
+ return f;
+ }
+
+ @Override
+ public Shape modelToView(int pos, Shape a, Position.Bias b) throws BadLocationException {
+ double zoomFactor = getZoomFactor();
+ Rectangle alloc;
+ alloc = a.getBounds();
+ Shape s = super.modelToView(pos, alloc, b);
+ alloc = s.getBounds();
+ alloc.x *= zoomFactor;
+ alloc.y *= zoomFactor;
+ alloc.width *= zoomFactor;
+ alloc.height *= zoomFactor;
+
+ return alloc;
+ }
+
+ @Override
+ public int viewToModel(float x, float y, Shape a,
+ Position.Bias[] bias) {
+ double zoomFactor = getZoomFactor();
+ Rectangle alloc = a.getBounds();
+ x /= zoomFactor;
+ y /= zoomFactor;
+ alloc.x /= zoomFactor;
+ alloc.y /= zoomFactor;
+ alloc.width /= zoomFactor;
+ alloc.height /= zoomFactor;
+
+ return super.viewToModel(x, y, alloc, bias);
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/SynchronousHTMLEditorKit.java b/src/main/java/io/github/moulberry/notenoughupdates/util/SynchronousHTMLEditorKit.java
new file mode 100644
index 00000000..7f02baa7
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/SynchronousHTMLEditorKit.java
@@ -0,0 +1,36 @@
+package io.github.moulberry.notenoughupdates.util;
+
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.View;
+import javax.swing.text.ViewFactory;
+import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.ImageView;
+import javax.swing.text.html.HTMLEditorKit.HTMLFactory;
+
+public class SynchronousHTMLEditorKit extends HTMLEditorKit {
+ public SynchronousHTMLEditorKit() {
+ }
+
+ public Document createDefaultDocument() {
+ HTMLDocument doc = (HTMLDocument)super.createDefaultDocument();
+ doc.setAsynchronousLoadPriority(-1);
+ return doc;
+ }
+
+ public ViewFactory getViewFactory() {
+ return new HTMLFactory() {
+ public View create(Element elem) {
+ View view = super.create(elem);
+ if (view instanceof ImageView) {
+ //((ImageView)view).setLoadsSynchronously(true);
+ }
+
+ return view;
+ }
+ };
+ }
+
+
+}
diff --git a/src/main/resources/assets/notenoughupdates/ascending_overlay.png b/src/main/resources/assets/notenoughupdates/ascending_overlay.png
new file mode 100644
index 00000000..5b703a93
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ascending_overlay.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/close.png b/src/main/resources/assets/notenoughupdates/close.png
new file mode 100644
index 00000000..8ba630fb
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/close.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/descending_overlay.png b/src/main/resources/assets/notenoughupdates/descending_overlay.png
new file mode 100644
index 00000000..ad9d0bd6
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/descending_overlay.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/help.png b/src/main/resources/assets/notenoughupdates/help.png
new file mode 100644
index 00000000..1a7ebb60
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/help.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/next.png b/src/main/resources/assets/notenoughupdates/next.png
index 8e4a96cc..d215a7e8 100644
--- a/src/main/resources/assets/notenoughupdates/next.png
+++ b/src/main/resources/assets/notenoughupdates/next.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/next.xcf b/src/main/resources/assets/notenoughupdates/next.xcf
new file mode 100644
index 00000000..f93cc5b9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/next.xcf
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/next_pow2.png b/src/main/resources/assets/notenoughupdates/next_pow2.png
deleted file mode 100644
index 03365e1c..00000000
--- a/src/main/resources/assets/notenoughupdates/next_pow2.png
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/off.png b/src/main/resources/assets/notenoughupdates/off.png
new file mode 100644
index 00000000..5d0b6ad2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/off.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/on.png b/src/main/resources/assets/notenoughupdates/on.png
new file mode 100644
index 00000000..4117c519
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/on.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/order_alphabetical.png b/src/main/resources/assets/notenoughupdates/order_alphabetical.png
new file mode 100644
index 00000000..4e204691
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/order_alphabetical.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/order_alphabetical_active.png b/src/main/resources/assets/notenoughupdates/order_alphabetical_active.png
new file mode 100644
index 00000000..ab596112
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/order_alphabetical_active.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/order_rarity.png b/src/main/resources/assets/notenoughupdates/order_rarity.png
new file mode 100644
index 00000000..df23e5da
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/order_rarity.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/order_rarity_active.png b/src/main/resources/assets/notenoughupdates/order_rarity_active.png
new file mode 100644
index 00000000..84bd3318
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/order_rarity_active.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/prev.png b/src/main/resources/assets/notenoughupdates/prev.png
index a4cef66d..a4ec7743 100644
--- a/src/main/resources/assets/notenoughupdates/prev.png
+++ b/src/main/resources/assets/notenoughupdates/prev.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/prev.xcf b/src/main/resources/assets/notenoughupdates/prev.xcf
new file mode 100644
index 00000000..e9fecc61
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/prev.xcf
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/prev_pow2.png b/src/main/resources/assets/notenoughupdates/prev_pow2.png
deleted file mode 100644
index 3b756716..00000000
--- a/src/main/resources/assets/notenoughupdates/prev_pow2.png
+++ /dev/null
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/settings.png b/src/main/resources/assets/notenoughupdates/settings.png
new file mode 100644
index 00000000..481a0588
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/settings.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_accessory.png b/src/main/resources/assets/notenoughupdates/sort_accessory.png
new file mode 100644
index 00000000..e901e5ba
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_accessory.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_accessory_active.png b/src/main/resources/assets/notenoughupdates/sort_accessory_active.png
new file mode 100644
index 00000000..dcc4d985
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_accessory_active.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_all.png b/src/main/resources/assets/notenoughupdates/sort_all.png
new file mode 100644
index 00000000..d7f2a1e3
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_all.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_all_active.png b/src/main/resources/assets/notenoughupdates/sort_all_active.png
new file mode 100644
index 00000000..fe2cc803
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_all_active.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_armor.png b/src/main/resources/assets/notenoughupdates/sort_armor.png
new file mode 100644
index 00000000..fab73503
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_armor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_armor_active.png b/src/main/resources/assets/notenoughupdates/sort_armor_active.png
new file mode 100644
index 00000000..37135164
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_armor_active.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_mob.png b/src/main/resources/assets/notenoughupdates/sort_mob.png
new file mode 100644
index 00000000..1049e056
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_mob.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_mob_active.png b/src/main/resources/assets/notenoughupdates/sort_mob_active.png
new file mode 100644
index 00000000..90ef509e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_mob_active.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_pet.png b/src/main/resources/assets/notenoughupdates/sort_pet.png
new file mode 100644
index 00000000..72bcb674
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_pet.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_pet_active.png b/src/main/resources/assets/notenoughupdates/sort_pet_active.png
new file mode 100644
index 00000000..ea0c9852
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_pet_active.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_weapon.png b/src/main/resources/assets/notenoughupdates/sort_weapon.png
new file mode 100644
index 00000000..f3292f66
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_weapon.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/sort_weapon_active.png b/src/main/resources/assets/notenoughupdates/sort_weapon_active.png
new file mode 100644
index 00000000..f6854ce5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/sort_weapon_active.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/wkhtmltox.zip b/src/main/resources/assets/notenoughupdates/wkhtmltox.zip
new file mode 100644
index 00000000..427617a9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/wkhtmltox.zip
Binary files differ