aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java64
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/GuiItemUsages.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java49
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java525
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java799
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java106
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java105
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/FlipperInfoPane.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java45
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java14
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/QOLInfoPane.java33
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java25
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/TextInfoPane.java24
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java24
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/Options.java33
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java5
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java3
17 files changed, 1249 insertions, 627 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java
index c4d3b57b..148f1bc5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java
@@ -1,4 +1,68 @@
package io.github.moulberry.notenoughupdates;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import net.minecraft.util.EnumChatFormatting;
+
public class CustomItems {
+
+ /**
+ * So it has come to this, huh? Snooping through the source to find all my carefully crafted easter eggs. Well
+ * guess what, you cheated not only the game, but yourself. You didn't grow. You didn't improve. You took a
+ * shortcut and gained nothing. You experienced a hollow victory. Nothing was risked and nothing was gained.
+ * It's sad that you don't know the difference.
+ */
+
+ public static JsonObject NULLZEE = create(
+ "NULLZEE",
+ "dirt",
+ "Nullzee242 Youtube Channel",
+ "Dirt, AOTD. Dirt, AOTD.",
+ "Dirt, AOTD. Dirt, AOTD.",
+ "Ooh, Dirt to Midas! Let's shake it up a little.",
+ "",
+ "Also, Did you know that only 10% of the people watching are subscribed?",
+ "It's OK, everyone makes mistakes",
+ "Also follow -> twitch.tv/nullzeelive",
+ "Also -> discord.gg/nullzee");
+ public static JsonObject DUCTTAPE = create(
+ "DUCTTAPE",
+ "iron_shovel",
+ "You ever accidentally bury your duct tape?",
+ "No problem! Our team of experts specialise in",
+ "subterranean duct tape excavation. That's right:",
+ "your buried duct tape problems are a thing of the past,",
+ "all for the low price of $7.99 or a subscription",
+ "to the Ducttapedigger youtube channel!");
+ public static JsonObject RUNE = create("RUNE", "paper", "No.", "I hate runes.");
+ public static JsonObject TWOBEETWOTEE = create("2B2T", "bedrock", "Minecraft's oldest anarchy Minecraft server in Minecraft.",
+ "This Minecraft anarchy server is the oldest server,",
+ "being a server since 2010 when Minecraft was a game with a server.",
+ "It is complete anarchy in Minecraft which means that there is total anarchy.",
+ "Hacking is allowed in Minecraft on this anarchy server which",
+ "is the oldest anarchy server in Minecraft, 2b2t. Hack. Steal. Cheat. Lie.",
+ "On the oldest anarchy server in Minecraft. 2b2t. The worst server in Minecraft,",
+ "where there are no rules. On the oldest anarchy server in Minecraft.",
+ "In this Minecraft anarchy server, there have been numerous Minecraft",
+ "incursions on the server, some of which I, a player on this Minecraft",
+ "anarchy server in Minecraft, have participated in. One of this server's",
+ "most infamous Minecraft players on the oldest Minecraft");
+
+ /**
+ * SHAAAAAAAAAAAAAAAAAAME
+ */
+
+ private static JsonObject create(String internalname, String itemid, String displayname, String... lore) {
+ JsonObject json = new JsonObject();
+ json.addProperty("itemid", itemid);
+ json.addProperty("internalname", internalname);
+ json.addProperty("displayname", EnumChatFormatting.RED+displayname);
+ JsonArray jsonlore = new JsonArray();
+ for(String line : lore) {
+ jsonlore.add(new JsonPrimitive(EnumChatFormatting.GRAY + line));
+ }
+ json.add("lore", jsonlore);
+ return json;
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/GuiItemUsages.java b/src/main/java/io/github/moulberry/notenoughupdates/GuiItemUsages.java
index ceb4e5d4..49a1be51 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/GuiItemUsages.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/GuiItemUsages.java
@@ -55,6 +55,8 @@ public class GuiItemUsages extends GuiCrafting {
}
if(results.get(currentIndex).has("crafttext")) {
craftText = results.get(currentIndex).get("crafttext").getAsString();
+ } else {
+ craftText = "";
}
cw.craftResult.setInventorySlotContents(0, manager.jsonToStack(results.get(currentIndex)));
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
index a89bd1dc..a7c7a1e4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
@@ -3,15 +3,20 @@ package io.github.moulberry.notenoughupdates;
import org.kohsuke.github.*;
import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
public class NEUIO {
private final String accessToken;
+ /**
+ * THIS CLASS PROVIDES METHODS FOR INTERFACING WITH THE GIT REPOSITORY NotEnoughUpdates-REPO. THIS REPOSITORY
+ * CONTAINS ALL THE JSON ITEMS. THIS SHOULD NOT BE A PERMANENT SOLUTION AND I SHOULD LOOK AT USING SOME FORM OF
+ * HOSTING SERVICE OTHER THAN A GIT REPOSITORY IF THE USERBASE OF THE MOD GROWS SIGNIFICANTLY. UNFORTUNATELY I
+ * CANT AFFORD HOSTING RIGHT NOW SO THIS IS WHAT YOU GET AND GITHUB WILL PROBABLY THROW A FIT IF A LARGE NUMBER
+ * OF USERS START DOWNLOADING FROM THE REPO ALL AT ONCE.
+ */
+
public NEUIO(String accessToken) {
this.accessToken = accessToken;
}
@@ -68,18 +73,50 @@ public class NEUIO {
GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build();
GHRepository repo = github.getRepositoryById("247692460");
- for(GHContent content : repo.getDirectoryContent("items")) {
+ for(GHTreeEntry treeEntry : repo.getTreeRecursive("master", 1).getTree()) {
+ if(treeEntry.getPath().startsWith("items/")) {
+ String[] split = treeEntry.getPath().split("/");
+ String name = split[split.length-1];
+
+ String oldSha = oldShas.get(name);
+ if(!treeEntry.getSha().equals(oldSha)) {
+ changedFiles.put(name, treeEntry.getSha());
+ }
+ }
+ }
+
+ /*for(GHContent content : repo.getDirectoryContent("items")) {
String oldSha = oldShas.get(content.getName());
if(!content.getSha().equals(oldSha)) {
changedFiles.put(content.getName(), content.getSha());
}
- }
+ }*/
} catch(IOException e) {
return null;
}
return changedFiles;
}
+ public Set<String> getRemovedItems(Set<String> currentlyInstalled) {
+ Set<String> removedItems = new HashSet<>();
+ Set<String> repoItems = new HashSet<>();
+ try {
+ GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build();
+ GHRepository repo = github.getRepositoryById("247692460");
+
+ for(GHTreeEntry treeEntry : repo.getTreeRecursive("master", 1).getTree()) {
+ String[] split = treeEntry.getPath().split("/");
+ repoItems.add(split[split.length-1].split("\\.")[0]);
+ }
+ } catch(IOException e) {
+ e.printStackTrace();
+ return removedItems;
+ }
+ removedItems.addAll(currentlyInstalled);
+ removedItems.removeAll(repoItems);
+ return removedItems;
+ }
+
/**
* Takes set of filename (eg. BOW.json) and returns map from that filename to the individual download link.
*/
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
index 08939cca..bebd090c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
@@ -6,15 +6,18 @@ import io.github.moulberry.notenoughupdates.options.Options;
import io.github.moulberry.notenoughupdates.util.HypixelApi;
import javafx.scene.control.Alert;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.settings.KeyBinding;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.*;
+import net.minecraft.network.play.client.C0DPacketCloseWindow;
import net.minecraft.util.EnumChatFormatting;
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.input.Keyboard;
import org.lwjgl.opengl.Display;
import javax.swing.*;
@@ -40,6 +43,14 @@ public class NEUManager {
private TreeMap<String, HashMap<String, List<Integer>>> titleWordMap = new TreeMap<>();
private TreeMap<String, HashMap<String, List<Integer>>> loreWordMap = new TreeMap<>();
+ public final KeyBinding keybindGive = new KeyBinding("Add item to inventory (Creative-only)", Keyboard.KEY_L, "NotEnoughUpdates");
+ public final KeyBinding keybindFavourite = new KeyBinding("Set item as favourite", Keyboard.KEY_F, "NotEnoughUpdates");
+ public final KeyBinding keybindViewUsages = new KeyBinding("Show usages for item", Keyboard.KEY_U, "NotEnoughUpdates");
+ public final KeyBinding keybindViewRecipe = new KeyBinding("Show recipe for item", Keyboard.KEY_R, "NotEnoughUpdates");
+ public final KeyBinding keybindToggleDisplay = new KeyBinding("Toggle NEU overlay", 0, "NotEnoughUpdates");
+ public final KeyBinding keybindClosePanes = new KeyBinding("Close NEU panes", 0, "NotEnoughUpdates");
+ public final KeyBinding[] keybinds = new KeyBinding[]{keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe, keybindToggleDisplay, keybindClosePanes};
+
public String viewItemAttemptID = null;
public long viewItemAttemptTime = 0;
@@ -74,13 +85,7 @@ public class NEUManager {
gsonBuilder.registerTypeAdapter(Options.Option.class, Options.createDeserializer());
gson = gsonBuilder.create();
- this.configFile = new File(configLocation, "config.json");
- try {
- configFile.createNewFile();
- config = Options.loadFromFile(gson, configFile);
- } catch(Exception e) {
- config = new Options();
- }
+ this.loadConfig();
this.itemsLocation = new File(configLocation, "items");
itemsLocation.mkdir();
@@ -171,15 +176,38 @@ public class NEUManager {
public class CraftInfo {
public boolean fromRecipe = false;
+ public boolean vanillaItem = false;
public float craftCost = -1;
}
+ /**
+ * Recursively calculates the cost of crafting an item from raw materials.
+ */
public CraftInfo getCraftCost(String internalname) {
if(craftCost.containsKey(internalname)) {
return craftCost.get(internalname);
} else {
CraftInfo ci = new CraftInfo();
+ //Removes trailing numbers and underscores, eg. LEAVES_2-3 -> LEAVES
+ String vanillaName = internalname.split("-")[0];
+ int sub = 0;
+ for(int i=vanillaName.length()-1; i>1; i--) {
+ char c = vanillaName.charAt(i);
+ if((int)c >= 48 && (int)c <= 57) { //0-9
+ sub++;
+ } else if(c == '_') {
+ sub++;
+ break;
+ } else {
+ break;
+ }
+ }
+ vanillaName = vanillaName.substring(0, vanillaName.length()-sub);
+ if(Item.itemRegistry.getObject(new ResourceLocation(vanillaName)) != null) {
+ ci.vanillaItem = true;
+ }
+
JsonObject auctionInfo = getItemAuctionInfo(internalname);
JsonObject bazaarInfo = getBazaarInfo(internalname);
@@ -187,7 +215,7 @@ public class NEUManager {
float bazaarInstantBuyPrice = bazaarInfo.get("curr_buy").getAsFloat();
ci.craftCost = bazaarInstantBuyPrice;
}
- if(auctionInfo != null) {
+ if(auctionInfo != null && !ci.vanillaItem) { //Don't use auction prices for vanilla items cuz people like to transfer money, messing up the cost of vanilla items.
float auctionPrice = auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat();
if(ci.craftCost < 0 || auctionPrice < ci.craftCost) {
ci.craftCost = auctionPrice;
@@ -212,8 +240,10 @@ public class NEUManager {
}
float compCost = getCraftCost(itemS).craftCost * count;
if(compCost < 0) {
- craftCost.put(internalname, ci);
- return ci;
+ if(!getCraftCost(itemS).vanillaItem) { //If it's a vanilla item without a cost attached to it, let compCost = 0.
+ craftCost.put(internalname, ci);
+ return ci;
+ }
} else {
craftPrice += compCost;
}
@@ -233,8 +263,21 @@ public class NEUManager {
config.saveToFile(gson, configFile);
}
+ public void loadConfig() {
+ this.configFile = new File(configLocation, "config.json");
+ try {
+ configFile.createNewFile();
+ config = Options.loadFromFile(gson, configFile);
+ } catch(Exception e) {
+ config = new Options();
+ }
+ }
+
+ /**
+ * Downloads and sets auctionPricesJson from the URL specified by AUCTIONS_PRICE_URL.
+ */
public void updatePrices() {
- if(System.currentTimeMillis() - auctionLastUpdate > 1000*60*30) { //30 minutes
+ if(System.currentTimeMillis() - auctionLastUpdate > 1000*60*120) { //2 hours
craftCost.clear();
System.out.println("UPDATING PRICE INFORMATION");
auctionLastUpdate = System.currentTimeMillis();
@@ -266,23 +309,40 @@ public class NEUManager {
return e.getAsJsonObject();
}
+ /**
+ * Calculates the cost of enchants + other price modifiers such as pet xp, midas price, etc.
+ */
public float getCostOfEnchants(String internalname, NBTTagCompound tag) {
float costOfEnchants = 0;
+ if(true) return 0;
+
JsonObject info = getItemAuctionInfo(internalname);
if(info == null || !info.has("price")) {
return 0;
}
+ if(!auctionPricesJson.has("ench_prices") || !auctionPricesJson.has("ench_maximums")) {
+ return 0;
+ }
+ JsonObject ench_prices = auctionPricesJson.getAsJsonObject("ench_prices");
+ JsonObject ench_maximums = auctionPricesJson.getAsJsonObject("ench_maximums");
+ if(!ench_prices.has(internalname) || !ench_maximums.has(internalname)) {
+ return 0;
+ }
+ JsonObject iid_variables = ench_prices.getAsJsonObject(internalname);
+ float ench_maximum = ench_maximums.get(internalname).getAsFloat();
+
+ int enchants = 0;
float price = getItemAuctionInfo(internalname).get("price").getAsFloat();
if(tag.hasKey("ExtraAttributes")) {
NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
if(ea.hasKey("enchantments")) {
- JsonObject ench_prices = auctionPricesJson.get("ench_prices").getAsJsonObject();
NBTTagCompound enchs = ea.getCompoundTag("enchantments");
for(String ench : enchs.getKeySet()) {
+ enchants++;
int level = enchs.getInteger(ench);
- for(Map.Entry<String, JsonElement> entry : ench_prices.entrySet()) {
+ for(Map.Entry<String, JsonElement> entry : iid_variables.entrySet()) {
if(matchEnch(ench, level, entry.getKey())) {
costOfEnchants += entry.getValue().getAsJsonObject().get("A").getAsFloat()*price +
entry.getValue().getAsJsonObject().get("B").getAsFloat();
@@ -295,15 +355,23 @@ public class NEUManager {
return costOfEnchants;
}
+ /**
+ * Checks whether a certain enchant (ench name + lvl) matches an enchant id
+ * eg. PROTECTION_GE6 will match -> ench_name = PROTECTION, lvl >= 6
+ */
private boolean matchEnch(String ench, int level, String id) {
+ if(!id.contains(":")) {
+ return false;
+ }
+
String idEnch = id.split(":")[0];
String idLevel = id.split(":")[1];
- if(!ench.equals(idEnch)) {
+ if(!ench.equalsIgnoreCase(idEnch)) {
return false;
}
- if(String.valueOf(level).equals(idLevel)) {
+ if(String.valueOf(level).equalsIgnoreCase(idLevel)) {
return true;
}
@@ -583,6 +651,22 @@ public class NEUManager {
}
/**
+ * Calls search for each query, separated by |
+ * eg. search(A|B) = search(A) + search(B)
+ */
+ public Set<String> search(String query, boolean multi) {
+ if(multi) {
+ Set<String> result = new HashSet<>();
+ for(String query2 : query.split("\\|")) {
+ result.addAll(search(query2));
+ }
+ return result;
+ } else {
+ return search(query);
+ }
+ }
+
+ /**
* Returns the name of items which match a certain search query.
*/
public Set<String> search(String query) {
@@ -700,7 +784,7 @@ public class NEUManager {
}
/**
- * Takes an item stack and produces a JsonObject. This is used in the item editor.
+ * Takes an item stack and produces a JsonObject.
*/
public JsonObject getJsonForItem(ItemStack stack) {
NBTTagCompound tag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound();
@@ -775,9 +859,220 @@ public class NEUManager {
writeJson(json, new File(itemsLocation, internalname+".json"));
} catch (IOException e) {}
- loadItem(internalname); //Collection: Cocoa Beans VII
+ loadItem(internalname);
+ }
+
+ /**
+ * Constructs a GuiItemUsages from the recipe usage data (see #usagesMap) of a given item
+ */
+ public boolean displayGuiItemUsages(String internalName, String text) {
+ List<ItemStack[]> craftMatrices = new ArrayList<>();
+ List<JsonObject> results = new ArrayList<>();
+
+ if(!usagesMap.containsKey(internalName)) {
+ return false;
+ }
+
+ for(String internalNameResult : usagesMap.get(internalName)) {
+ JsonObject item = getItemInformation().get(internalNameResult);
+ results.add(item);
+
+ 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;
+ }
+ }
+
+ craftMatrices.add(craftMatrix);
+ }
+ }
+
+ if(craftMatrices.size() > 0) {
+ Minecraft.getMinecraft().thePlayer.sendQueue.addToSendQueue(new C0DPacketCloseWindow(
+ Minecraft.getMinecraft().thePlayer.openContainer.windowId));
+ Minecraft.getMinecraft().displayGuiScreen(new GuiItemUsages(craftMatrices, results, text, this));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Constructs a GuiItemRecipe from the recipe data of a given item.
+ */
+ 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().thePlayer.sendQueue.addToSendQueue(new C0DPacketCloseWindow(
+ Minecraft.getMinecraft().thePlayer.openContainer.windowId));
+ Minecraft.getMinecraft().displayGuiScreen(new GuiItemRecipe(craftMatrix, item, text, this));
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Will display guiItemRecipe if a player attempted to view the recipe to an item but they didn't have the recipe
+ * unlocked. See NotEnoughUpdates#onGuiChat for where this method is called.
+ */
+ public boolean failViewItem(String text) {
+ if(viewItemAttemptID != null && !viewItemAttemptID.isEmpty()) {
+ if(System.currentTimeMillis() - viewItemAttemptTime < 500) {
+ return displayGuiItemRecipe(viewItemAttemptID, text);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Downloads a web file, appending some HTML attributes that makes wikia give us the raw wiki syntax.
+ */
+ public File getWebFile(String url) {
+ File f = new File(configLocation, "tmp/"+Base64.getEncoder().encodeToString(url.getBytes())+".html");
+ if(f.exists()) {
+ return f;
+ }
+
+ 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;
+ }
+
+
+ /**
+ * Modified from https://www.journaldev.com/960/java-unzip-file-example
+ */
+ private static void unzipIgnoreFirstFolder(String zipFilePath, String destDir) {
+ File dir = new File(destDir);
+ // create output directory if it doesn't exist
+ if(!dir.exists()) dir.mkdirs();
+ FileInputStream fis;
+ //buffer for read and write data to file
+ byte[] buffer = new byte[1024];
+ try {
+ fis = new FileInputStream(zipFilePath);
+ ZipInputStream zis = new ZipInputStream(fis);
+ ZipEntry ze = zis.getNextEntry();
+ while(ze != null){
+ if(!ze.isDirectory()) {
+ String fileName = ze.getName();
+ fileName = fileName.substring(fileName.split("/")[0].length()+1);
+ File newFile = new File(destDir + File.separator + 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();
+ fis.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Modified 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();
+ }
}
+ /**
+ * From here to the end of the file are various helper functions for creating and writing json files,
+ * in particular json files representing skyblock item data.
+ */
public JsonObject createItemJson(String internalname, String itemid, String displayname, String[] lore,
String crafttext, String infoType, String[] info,
String clickcommand, int damage, NBTTagCompound nbttag) {
@@ -884,81 +1179,6 @@ public class NEUManager {
return itemMap;
}
- /**
- * Stolen from https://www.journaldev.com/960/java-unzip-file-example
- */
- private static void unzipIgnoreFirstFolder(String zipFilePath, String destDir) {
- File dir = new File(destDir);
- // create output directory if it doesn't exist
- if(!dir.exists()) dir.mkdirs();
- FileInputStream fis;
- //buffer for read and write data to file
- byte[] buffer = new byte[1024];
- try {
- fis = new FileInputStream(zipFilePath);
- ZipInputStream zis = new ZipInputStream(fis);
- ZipEntry ze = zis.getNextEntry();
- while(ze != null){
- if(!ze.isDirectory()) {
- String fileName = ze.getName();
- fileName = fileName.substring(fileName.split("/")[0].length()+1);
- File newFile = new File(destDir + File.separator + 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();
- fis.close();
- } 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()).copy();
@@ -982,7 +1202,10 @@ public class NEUManager {
}
if(json.has("lore")) {
- NBTTagCompound display = stack.getTagCompound().getCompoundTag("display");
+ NBTTagCompound display = new NBTTagCompound();
+ if(stack.getTagCompound() != null && stack.getTagCompound().hasKey("display")) {
+ display = stack.getTagCompound().getCompoundTag("display");
+ }
NBTTagList lore = new NBTTagList();
for(JsonElement line : json.get("lore").getAsJsonArray()) {
String lineStr = line.getAsString();
@@ -992,7 +1215,7 @@ public class NEUManager {
}
}
display.setTag("Lore", lore);
- NBTTagCompound tag = stack.getTagCompound();
+ NBTTagCompound tag = stack.getTagCompound() != null ? stack.getTagCompound() : new NBTTagCompound();
tag.setTag("display", display);
stack.setTagCompound(tag);
}
@@ -1002,118 +1225,4 @@ public class NEUManager {
return stack;
}
- public boolean displayGuiItemUsages(String internalName, String text) {
- List<ItemStack[]> craftMatrices = new ArrayList<>();
- List<JsonObject> results = new ArrayList<>();
-
- if(!usagesMap.containsKey(internalName)) {
- return false;
- }
-
- for(String internalNameResult : usagesMap.get(internalName)) {
- JsonObject item = getItemInformation().get(internalNameResult);
- results.add(item);
-
- 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;
- }
- }
-
- craftMatrices.add(craftMatrix);
- }
- }
-
- if(craftMatrices.size() > 0) {
- Minecraft.getMinecraft().displayGuiScreen(new GuiItemUsages(craftMatrices, results, text, this));
- return true;
- }
- return false;
- }
-
- 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 e60ca14f..59233882 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
@@ -6,7 +6,6 @@ import io.github.moulberry.notenoughupdates.infopanes.*;
import io.github.moulberry.notenoughupdates.itemeditor.NEUItemEditor;
import io.github.moulberry.notenoughupdates.util.LerpingFloat;
import io.github.moulberry.notenoughupdates.util.LerpingInteger;
-import io.github.moulberry.notenoughupdates.util.TexLoc;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*;
import net.minecraft.client.gui.inventory.GuiContainer;
@@ -17,14 +16,15 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.shader.Framebuffer;
import net.minecraft.client.shader.Shader;
-import net.minecraft.client.shader.ShaderGroup;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLivingBase;
-import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.inventory.Slot;
+import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.Matrix4f;
@@ -34,9 +34,9 @@ import org.apache.commons.lang3.StringUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
import java.awt.*;
-import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.NumberFormat;
@@ -68,23 +68,19 @@ public class NEUOverlay extends Gui {
order_alphabetical_active, order_rarity_active
};
+ //Various constants used for GUI structure
private int searchBarXSize = 200;
private final int searchBarYOffset = 10;
private final int searchBarYSize = 40;
private final int searchBarPadding = 2;
- public static final int BOX_PADDING = 15;
+ private static final int BOX_PADDING = 15;
public static final int ITEM_PADDING = 4;
public static final int ITEM_SIZE = 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 String[] informationPane;
- //private AtomicInteger webpageAwaitID = new AtomicInteger(-1);
- //private boolean configOpen = false;
private InfoPane activeInfoPane = null;
private TreeSet<JsonObject> searchedItems = null;
@@ -121,12 +117,17 @@ public class NEUOverlay extends Gui {
private ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ private boolean disabled = false;
+
public NEUOverlay(NEUManager manager) {
this.manager = manager;
textField.setFocused(true);
textField.setCanLoseFocus(false);
}
+ /**
+ * Disables searchBarFocus and resets the item pane position. Called whenever NEUOverlay is opened.
+ */
public void reset() {
searchBarHasFocus = false;
if(!(searchMode || (manager.config.keepopen.value && itemPaneOpen))) {
@@ -136,6 +137,9 @@ public class NEUOverlay extends Gui {
}
}
+ /**
+ * Calls #displayInformationPane with a HTMLInfoPane created from item.info and item.infoType.
+ */
public void showInfo(JsonObject item) {
if(item.has("info") && item.has("infoType")) {
JsonArray lore = item.get("info").getAsJsonArray();
@@ -163,6 +167,10 @@ public class NEUOverlay extends Gui {
* Handles the mouse input, cancelling the forge event if a NEU gui element is clicked.
*/
public boolean mouseInput() {
+ if(disabled) {
+ return false;
+ }
+
int width = scaledresolution.getScaledWidth();
int height = scaledresolution.getScaledHeight();
@@ -208,8 +216,8 @@ public class NEUOverlay extends Gui {
if(!clickedItem.get()) {
int paneWidth = (int)(width/3*getWidthMult());
int leftSide = (int)(width*getItemPaneOffsetFactor());
- int rightSide = leftSide+paneWidth-BOX_PADDING-getItemBoxXPadding();
- leftSide = leftSide+BOX_PADDING+getItemBoxXPadding();
+ int rightSide = leftSide+paneWidth-getBoxPadding()-getItemBoxXPadding();
+ leftSide = leftSide+getBoxPadding()+getItemBoxXPadding();
FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
int maxPages = getMaxPages();
@@ -219,7 +227,7 @@ public class NEUOverlay extends Gui {
int buttonXSize = (int)Math.min(maxButtonXSize, getSearchBarYSize()*480/160f);
int ySize = (int)(buttonXSize/480f*160);
int yOffset = (int)((getSearchBarYSize()-ySize)/2f);
- int top = BOX_PADDING+yOffset;
+ int top = getBoxPadding()+yOffset;
if(mouseY >= top && mouseY <= top+ySize) {
int leftPrev = leftSide-1;
@@ -233,16 +241,16 @@ public class NEUOverlay extends Gui {
}
float sortIconsMinX = (sortIcons.length+orderIcons.length)*(ITEM_SIZE+ITEM_PADDING)+ITEM_SIZE;
- float availableX = rightSide-(leftSide+BOX_PADDING+getItemBoxXPadding());
+ float availableX = rightSide-leftSide;
float sortOrderScaleFactor = Math.min(1, availableX / sortIconsMinX);
int scaledITEM_SIZE = (int)(ITEM_SIZE*sortOrderScaleFactor);
int scaledItemPaddedSize = (int)((ITEM_SIZE+ITEM_PADDING)*sortOrderScaleFactor);
- int iconTop = height-BOX_PADDING-(ITEM_SIZE+scaledITEM_SIZE)/2-1;
+ int iconTop = height-getBoxPadding()-(ITEM_SIZE+scaledITEM_SIZE)/2-1;
if(mouseY >= iconTop && mouseY <= iconTop+scaledITEM_SIZE) {
for(int i=0; i<orderIcons.length; i++) {
- int orderIconX = leftSide+BOX_PADDING+getItemBoxXPadding()+i*scaledItemPaddedSize;
+ int orderIconX = leftSide+i*scaledItemPaddedSize;
if(mouseX >= orderIconX && mouseX <= orderIconX+scaledITEM_SIZE) {
if(Mouse.getEventButton() == 0) {
manager.config.compareMode.value = new Double(i);
@@ -289,6 +297,39 @@ public class NEUOverlay extends Gui {
}
}
+
+ //Quickcommands
+ int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor();
+ if(paddingUnscaled < 1) paddingUnscaled = 1;
+ int topTextBox = height - searchBarYOffset - getSearchBarYSize();
+
+ if(Mouse.getEventButtonState() && manager.config.showQuickCommands.value) {
+ ArrayList<String> quickCommands = manager.config.quickCommands.value;
+ int bigItemSize = getSearchBarYSize();
+ int bigItemPadding = paddingUnscaled*4;
+ int xStart = width/2 + bigItemPadding/2 - (bigItemSize+bigItemPadding)*quickCommands.size()/2;
+ int xEnd = width/2 - bigItemPadding/2 + (bigItemSize+bigItemPadding)*quickCommands.size()/2;
+ int y = topTextBox - bigItemSize - bigItemPadding - paddingUnscaled*2;
+
+ if(mouseY >= y && mouseY <= topTextBox-paddingUnscaled*2) {
+ if(mouseX > xStart && mouseX < xEnd) {
+ if((mouseX - xStart)%(bigItemSize+bigItemPadding) < bigItemSize) {
+ int index = (mouseX - xStart)/(bigItemSize+bigItemPadding);
+ if(index >= 0 && index < quickCommands.size()) {
+ String quickCommand = quickCommands.get(index);
+ if(quickCommand.contains(":")) {
+ String command = quickCommand.split(":")[0].trim();
+ if(command.startsWith("/")) {
+ NotEnoughUpdates.INSTANCE.sendChatMessage(command);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
//Search bar
if(mouseX >= width/2 - getSearchBarXSize()/2 && mouseX <= width/2 + getSearchBarXSize()/2) {
if(mouseY >= height - searchBarYOffset - getSearchBarYSize() &&
@@ -310,10 +351,7 @@ public class NEUOverlay extends Gui {
}
}
- int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor();
- int topTextBox = height - searchBarYOffset - getSearchBarYSize();
int iconSize = getSearchBarYSize()+paddingUnscaled*2;
- if(paddingUnscaled < 1) paddingUnscaled = 1;
if(mouseY > topTextBox - paddingUnscaled && mouseY < topTextBox - paddingUnscaled + iconSize) {
if(mouseX > width/2 + getSearchBarXSize()/2 + paddingUnscaled*6 &&
@@ -344,11 +382,17 @@ public class NEUOverlay extends Gui {
return false;
}
+ /**
+ * Returns searchBarXSize, scaled by 0.8 if gui scale == AUTO.
+ */
public int getSearchBarXSize() {
if(scaledresolution.getScaleFactor()==4) return (int)(searchBarXSize*0.8);
return searchBarXSize;
}
+ /**
+ * Sets the activeInfoPane and sets the target of the infoPaneOffsetFactor to make the infoPane "slide" out.
+ */
public void displayInformationPane(InfoPane pane) {
if(pane == null) {
infoPaneOffsetFactor.setTarget(0);
@@ -363,79 +407,9 @@ public class NEUOverlay extends Gui {
return activeInfoPane;
}
- /*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 {
- 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);
- }
- }
- }*/
-
+ /**
+ * Finds the index of the character inside the search bar that was clicked, used to set the caret.
+ */
public int getClickedIndex(int mouseX, int mouseY) {
int width = scaledresolution.getScaledWidth();
int height = scaledresolution.getScaledHeight();
@@ -469,23 +443,46 @@ public class NEUOverlay extends Gui {
if(Minecraft.getMinecraft().currentScreen == null) return false;
Keyboard.enableRepeatEvents(true);
- if(Keyboard.isKeyDown(Keyboard.KEY_Y)) {
+ int keyPressed = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() : Keyboard.getEventKey();
+
+ if(disabled) {
+ if(Keyboard.getEventKeyState() && keyPressed == manager.keybindToggleDisplay.getKeyCode()) {
+ disabled = !disabled;
+ }
+ return false;
+ }
+
+ if(Keyboard.isKeyDown(Keyboard.KEY_Y) && manager.config.dev.value) {
displayInformationPane(new DevInfoPane(this, manager));
//displayInformationPane(new QOLInfoPane(this, manager));
}
if(Keyboard.getEventKeyState()) {
if(searchBarHasFocus) {
- if(Keyboard.getEventKey() == 1) {
+ if(keyPressed == 1) {
searchBarHasFocus = false;
} else {
- if(textField.textboxKeyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey())) {
+ if(textField.textboxKeyTyped(Keyboard.getEventCharacter(), keyPressed)) {
updateSearch();
}
}
} else {
if(activeInfoPane != null) {
- activeInfoPane.keyboardInput();
+ if(activeInfoPane.keyboardInput()) {
+ return true;
+ }
+ }
+
+ if(keyPressed == manager.keybindClosePanes.getKeyCode()) {
+ itemPaneOffsetFactor.setValue(1);
+ itemPaneTabOffset.setValue(20);
+ itemPaneOpen = false;
+ displayInformationPane(null);
+ }
+
+ if(keyPressed == manager.keybindToggleDisplay.getKeyCode()) {
+ disabled = !disabled;
+ return true;
}
AtomicReference<String> internalname = new AtomicReference<>(null);
@@ -524,16 +521,16 @@ public class NEUOverlay extends Gui {
}
JsonObject item = manager.getItemInformation().get(internalname.get());
if(item != null) {
- if(Keyboard.getEventCharacter() == 'u') {
+ if(keyPressed == manager.keybindViewUsages.getKeyCode()) {
manager.displayGuiItemUsages(internalname.get(), "");
return true;
- } else if(Keyboard.getEventCharacter() == 'f') {
- toggleRarity(item.get("internalname").getAsString());
+ } else if(keyPressed == manager.keybindFavourite.getKeyCode()) {
+ toggleFavourite(item.get("internalname").getAsString());
return true;
- } else if(Keyboard.getEventCharacter() == 'r') {
+ } else if(keyPressed == manager.keybindViewRecipe.getKeyCode()) {
manager.showRecipe(item);
return true;
- } else if(Keyboard.getEventCharacter() == 'l') {
+ } else if(keyPressed == manager.keybindGive.getKeyCode()) {
if(Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) {
Minecraft.getMinecraft().thePlayer.inventory.addItemStackToInventory(
manager.jsonToStack(item));
@@ -551,7 +548,7 @@ public class NEUOverlay extends Gui {
return searchBarHasFocus; //Cancels keyboard events if the search bar has focus
}
- public void toggleRarity(String internalname) {
+ public void toggleFavourite(String internalname) {
if(getFavourites().contains(internalname)) {
getFavourites().remove(internalname);
} else {
@@ -568,6 +565,17 @@ public class NEUOverlay extends Gui {
EnumChatFormatting.GOLD+EnumChatFormatting.BOLD.toString()+"LEGENDARY",
EnumChatFormatting.LIGHT_PURPLE+EnumChatFormatting.BOLD.toString()+"SPECIAL",
};
+
+ /**
+ * Finds the rarity from the lore of an item.
+ * -1 = UNKNOWN
+ * 0 = COMMON
+ * 1 = UNCOMMON
+ * 2 = RARE
+ * 3 = EPIC
+ * 4 = LEGENDARY
+ * 5 = SPECIAL
+ */
public int getRarity(JsonArray lore) {
for(int i=lore.size()-1; i>=0; i--) {
String line = lore.get(i).getAsString();
@@ -581,6 +589,9 @@ public class NEUOverlay extends Gui {
return -1;
}
+ /**
+ * Convenience functions that get various compare/sort modes from the config.
+ */
private int getCompareMode() {
return manager.config.compareMode.value.intValue();
}
@@ -594,6 +605,10 @@ public class NEUOverlay extends Gui {
return manager.config.favourites.value;
}
+ /**
+ * Creates an item comparator used to sort the list of items according to the favourite set then compare mode.
+ * Defaults to alphabetical sorting if the above factors cannot distinguish between two items.
+ */
private Comparator<JsonObject> getItemComparator() {
return (o1, o2) -> {
//1 (mult) if o1 should appear after o2
@@ -644,6 +659,11 @@ public class NEUOverlay extends Gui {
};
}
+ /**
+ * Checks whether an item matches a certain type, i.e. whether the item lore ends in "{rarity} {item type}"
+ * eg. "SHOVEL" will return >0 for "COMMON SHOVEL", "EPIC SHOVEL", etc.
+ * @return the index of the type that matched, or -1 otherwise.
+ */
public int checkItemType(JsonArray lore, String... typeMatches) {
for(int i=lore.size()-1; i>=0; i--) {
String line = lore.get(i).getAsString();
@@ -659,6 +679,9 @@ public class NEUOverlay extends Gui {
return -1;
}
+ /**
+ * Checks whether an item matches the current sort mode.
+ */
public boolean checkMatchesSort(String internalname, JsonObject item) {
if(getSortMode() == SORT_MODE_ALL) {
return !internalname.matches(mobRegex);
@@ -677,20 +700,44 @@ public class NEUOverlay extends Gui {
return true;
}
+ /**
+ * Clears the current item list, creating a new TreeSet if necessary.
+ * Adds all items that match the search AND match the sort mode to the current item list.
+ * Also adds some easter egg items. (Also I'm very upset if you came here to find them :'( )
+ */
public void updateSearch() {
if(searchedItems==null) searchedItems = new TreeSet<>(getItemComparator());
searchedItems.clear();
searchedItemsArr = null;
redrawItems = true;
- Set<String> itemsMatch = manager.search(textField.getText());
+ Set<String> itemsMatch = manager.search(textField.getText(), true);
for(String itemname : itemsMatch) {
JsonObject item = manager.getItemInformation().get(itemname);
if(checkMatchesSort(itemname, item)) {
searchedItems.add(item);
}
}
+ switch(textField.getText().toLowerCase().trim()) {
+ case "nullzee":
+ searchedItems.add(CustomItems.NULLZEE);
+ break;
+ case "rune":
+ searchedItems.add(CustomItems.RUNE);
+ break;
+ case "2b2t":
+ searchedItems.add(CustomItems.TWOBEETWOTEE);
+ break;
+ case "ducttape":
+ case "ducttapedigger":
+ searchedItems.add(CustomItems.DUCTTAPE);
+ break;
+ }
}
+ /**
+ * Returns an index-able array containing the elements in searchedItems.
+ * Whenever searchedItems is updated via the above method, the array is recreated here.
+ */
public JsonObject[] getSearchedItems() {
if(searchedItems==null) {
updateSearch();
@@ -706,6 +753,10 @@ public class NEUOverlay extends Gui {
return searchedItemsArr;
}
+ /**
+ * Gets the item in searchedItemArr corresponding to the certain index on the current page.
+ * @return item, if the item exists. null, otherwise.
+ */
public JsonObject getSearchedItemPage(int index) {
if(index < getSlotsXSize()*getSlotsYSize()) {
int actualIndex = index + getSlotsXSize()*getSlotsYSize()*page;
@@ -721,7 +772,11 @@ public class NEUOverlay extends Gui {
public int getItemBoxXPadding() {
int width = scaledresolution.getScaledWidth();
- return (((int)(width/3*getWidthMult())-2*BOX_PADDING)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
+ return (((int)(width/3*getWidthMult())-2*getBoxPadding())%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
+ }
+
+ public int getBoxPadding() {
+ return (BOX_PADDING-5)*2/scaledresolution.getScaleFactor()+5;
}
private abstract class ItemSlotConsumer {
@@ -731,7 +786,7 @@ public class NEUOverlay extends Gui {
public void iterateItemSlots(ItemSlotConsumer itemSlotConsumer) {
int width = scaledresolution.getScaledWidth();
int itemBoxXPadding = getItemBoxXPadding();
- iterateItemSlots(itemSlotConsumer, (int)(width*getItemPaneOffsetFactor())+BOX_PADDING+itemBoxXPadding);
+ iterateItemSlots(itemSlotConsumer, (int)(width*getItemPaneOffsetFactor())+getBoxPadding()+itemBoxXPadding);
}
/**
@@ -744,12 +799,12 @@ public class NEUOverlay extends Gui {
int height = scaledresolution.getScaledHeight();
int paneWidth = (int)(width/3*getWidthMult());
- int itemBoxYPadding = ((height-getSearchBarYSize()-2*BOX_PADDING-ITEM_SIZE-2)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
+ int itemBoxYPadding = ((height-getSearchBarYSize()-2*getBoxPadding()-ITEM_SIZE-2)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
- int yStart = BOX_PADDING+getSearchBarYSize()+itemBoxYPadding;
+ int yStart = getBoxPadding()+getSearchBarYSize()+itemBoxYPadding;
int itemBoxXPadding = getItemBoxXPadding();
- int xEnd = xStart+paneWidth-BOX_PADDING*2-ITEM_SIZE-itemBoxXPadding;
- int yEnd = height-BOX_PADDING-ITEM_SIZE-2-itemBoxYPadding;
+ int xEnd = xStart+paneWidth-getBoxPadding()*2-ITEM_SIZE-itemBoxXPadding;
+ int yEnd = height-getBoxPadding()-ITEM_SIZE-2-itemBoxYPadding;
//Render the items, displaying the tooltip if the cursor is over the item
int id = 0;
@@ -773,9 +828,9 @@ public class NEUOverlay extends Gui {
int width = scaledresolution.getScaledWidth();
int paneWidth = (int)(width/3*getWidthMult());
- int itemBoxXPadding = (((int)(width-width*getItemPaneOffsetFactor())-2*BOX_PADDING)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
- int xStart = (int)(width*getItemPaneOffsetFactor())+BOX_PADDING+itemBoxXPadding;
- int xEnd = (int)(width*getItemPaneOffsetFactor())+paneWidth-BOX_PADDING-ITEM_SIZE;
+ int itemBoxXPadding = (((int)(width-width*getItemPaneOffsetFactor())-2*getBoxPadding())%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
+ int xStart = (int)(width*getItemPaneOffsetFactor())+getBoxPadding()+itemBoxXPadding;
+ int xEnd = (int)(width*getItemPaneOffsetFactor())+paneWidth-getBoxPadding()-ITEM_SIZE;
return (int)Math.ceil((xEnd - xStart)/((float)(ITEM_SIZE+ITEM_PADDING)));
}
@@ -786,9 +841,9 @@ public class NEUOverlay extends Gui {
public int getSlotsYSize() {
int height = scaledresolution.getScaledHeight();
- int itemBoxYPadding = ((height-getSearchBarYSize()-2*BOX_PADDING-ITEM_SIZE-2)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
- int yStart = BOX_PADDING+getSearchBarYSize()+itemBoxYPadding;
- int yEnd = height-BOX_PADDING-ITEM_SIZE-2-itemBoxYPadding;
+ int itemBoxYPadding = ((height-getSearchBarYSize()-2*getBoxPadding()-ITEM_SIZE-2)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
+ int yStart = getBoxPadding()+getSearchBarYSize()+itemBoxYPadding;
+ int yEnd = height-getBoxPadding()-ITEM_SIZE-2-itemBoxYPadding;
return (int)Math.ceil((yEnd - yStart)/((float)(ITEM_SIZE+ITEM_PADDING)));
}
@@ -798,28 +853,14 @@ public class NEUOverlay extends Gui {
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) {
- int width = scaledresolution.getScaledWidth();
- int height = scaledresolution.getScaledHeight();
-
- int itemBoxXPadding = (((int)(width-width*getItemPaneOffsetFactor())-2*BOX_PADDING)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
- int itemBoxYPadding = ((height-getSearchBarYSize()-2*BOX_PADDING-ITEM_SIZE-2)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
-
- int xStart = (int)(width*getItemPaneOffsetFactor())+BOX_PADDING+itemBoxXPadding;
- int yStart = BOX_PADDING+getSearchBarYSize()+itemBoxYPadding;
-
- int xIndex = (x-xStart)/(ITEM_SIZE+ITEM_PADDING);
- int yIndex = (y-yStart)/(ITEM_SIZE+ITEM_PADDING);
- return xIndex + yIndex*getSlotsXSize();
- }*/
-
public int getSearchBarYSize() {
return Math.max(searchBarYSize/scaledresolution.getScaleFactor(), ITEM_SIZE);
}
+ /**
+ * Renders the top navigation bar, can be used by InfoPane implementations (such as SettingsInfoPane).
+ * Renders "prev" button, index/maxIndex string, "next" button.
+ */
public void renderNavElement(int leftSide, int rightSide, int maxPages, int page, String name) {
FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
@@ -830,11 +871,7 @@ public class NEUOverlay extends Gui {
int buttonXSize = (int)Math.min(maxButtonXSize, getSearchBarYSize()*480/160f);
int ySize = (int)(buttonXSize/480f*160);
int yOffset = (int)((getSearchBarYSize()-ySize)/2f);
- int top = BOX_PADDING+yOffset;
-
- /*drawRect(leftSide-1, top,
- rightSide+1,
- top+ySize, fg.getRGB());*/
+ int top = getBoxPadding()+yOffset;
int leftPressed = 0;
int rightPressed = 0;
@@ -907,6 +944,9 @@ public class NEUOverlay extends Gui {
public float yaw = 0;
public float pitch = 20;
+ /**
+ * Renders an entity onto the GUI at a certain x and y position.
+ */
private void renderEntity(float posX, float posY, float scale, String name, Class<? extends EntityLivingBase>... classes) {
EntityLivingBase[] entities = new EntityLivingBase[classes.length];
try {
@@ -972,6 +1012,10 @@ public class NEUOverlay extends Gui {
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
}
+ /**
+ * Renders black squares over the inventory to indicate items that do not match a specific search. (When searchMode
+ * is enabled)
+ */
public void renderOverlay(int mouseX, int mouseY) {
if(searchMode && textField.getText().length() > 0) {
GuiContainer inv = (GuiContainer) Minecraft.getMinecraft().currentScreen;
@@ -1008,6 +1052,13 @@ public class NEUOverlay extends Gui {
Shader blurShaderVert = null;
Framebuffer blurOutputVert = null;
+ /**
+ * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate
+ * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis).
+ *
+ * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to
+ * apply scales and translations manually.
+ */
private Matrix4f createProjectionMatrix(int width, int height) {
Matrix4f projMatrix = new Matrix4f();
projMatrix.setIdentity();
@@ -1021,12 +1072,18 @@ public class NEUOverlay extends Gui {
return projMatrix;
}
+ /**
+ * Renders whatever is currently in the Minecraft framebuffer to our two framebuffers, applying a horizontal
+ * and vertical blur separately in order to significantly save computation time.
+ * This is only possible if framebuffers are supported by the system, so this method will exit prematurely
+ * if framebuffers are not available. (Apple machines, for example, have poor framebuffer support).
+ */
private double lastBgBlurFactor = 5;
private void blurBackground() {
int width = Minecraft.getMinecraft().displayWidth;
int height = Minecraft.getMinecraft().displayHeight;
- if(manager.config.bgBlurFactor.value <= 0) return;
+ if(manager.config.bgBlurFactor.value <= 0 || !OpenGlHelper.isFramebufferEnabled()) return;
if(blurOutputHorz == null) {
blurOutputHorz = new Framebuffer(width, height, false);
@@ -1079,8 +1136,12 @@ public class NEUOverlay extends Gui {
}
}
+ /**
+ * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen.
+ * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight]
+ */
public void renderBlurredBackground(int width, int height, int x, int y, int blurWidth, int blurHeight) {
- if(manager.config.bgBlurFactor.value <= 0) return;
+ if(manager.config.bgBlurFactor.value <= 0 || !OpenGlHelper.isFramebufferEnabled()) return;
int f = scaledresolution.getScaleFactor();
float uMin = x/(float)width;
@@ -1099,9 +1160,12 @@ public class NEUOverlay extends Gui {
int guiScaleLast = 0;
/**
- * Renders the search bar, item selection (right) and item info (left) gui elements.
+ * Renders the search bar, quick commands, item selection (right) and item info (left) gui elements.
*/
public void render(int mouseX, int mouseY, boolean hoverInv) {
+ if(disabled) {
+ return;
+ }
FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledresolution.getScaledWidth();
@@ -1163,108 +1227,11 @@ public class NEUOverlay extends Gui {
GlStateManager.disableLighting();
/**
- * Search bar
- */
- int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor();
- if(paddingUnscaled < 1) paddingUnscaled = 1;
-
- int topTextBox = height - searchBarYOffset - getSearchBarYSize();
-
- /*Minecraft.getMinecraft().getTextureManager().bindTexture(logo_bg);
- GlStateManager.color(1f, 1f, 1f, 1f);
- Utils.drawTexturedRect((width)/2-37,
- height - searchBarYOffset - getSearchBarYSize()-30,
- 74, 54);
- GlStateManager.bindTexture(0);*/
-
- //Search bar background
- drawRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled,
- topTextBox - paddingUnscaled,
- width/2 + getSearchBarXSize()/2 + paddingUnscaled,
- height - searchBarYOffset + paddingUnscaled, searchMode ? Color.YELLOW.getRGB() : Color.WHITE.getRGB());
- drawRect(width/2 - getSearchBarXSize()/2,
- topTextBox,
- width/2 + getSearchBarXSize()/2,
- height - searchBarYOffset, Color.BLACK.getRGB());
-
- /*Minecraft.getMinecraft().getTextureManager().bindTexture(logo_fg);
- GlStateManager.color(1f, 1f, 1f, 1f);
- Utils.drawTexturedRect((width)/2-37,
- height - searchBarYOffset - getSearchBarYSize()-27,
- 74, 54);
- GlStateManager.bindTexture(0);*/
-
- //Settings
- int iconSize = getSearchBarYSize()+paddingUnscaled*2;
- Minecraft.getMinecraft().getTextureManager().bindTexture(settings);
- drawRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled*6 - iconSize,
- topTextBox - paddingUnscaled,
- width/2 - getSearchBarXSize()/2 - paddingUnscaled*6,
- topTextBox - paddingUnscaled + iconSize, Color.WHITE.getRGB());
-
- drawRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled*5 - iconSize,
- topTextBox,
- width/2 - getSearchBarXSize()/2 - paddingUnscaled*7,
- topTextBox - paddingUnscaled*2 + iconSize, Color.GRAY.getRGB());
- GlStateManager.color(1f, 1f, 1f, 1f);
- Utils.drawTexturedRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled*6 - iconSize, topTextBox - paddingUnscaled, iconSize, iconSize);
- GlStateManager.bindTexture(0);
-
- //Help
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- drawRect(width/2 + getSearchBarXSize()/2 + paddingUnscaled*6,
- topTextBox - paddingUnscaled,
- width/2 + getSearchBarXSize()/2 + paddingUnscaled*6 + iconSize,
- topTextBox - paddingUnscaled + iconSize, Color.WHITE.getRGB());
-
- drawRect(width/2 + getSearchBarXSize()/2 + paddingUnscaled*7,
- topTextBox,
- width/2 + getSearchBarXSize()/2 + paddingUnscaled*5 + iconSize,
- topTextBox - paddingUnscaled*2 + iconSize, Color.GRAY.getRGB());
- GlStateManager.color(1f, 1f, 1f, 1f);
- Utils.drawTexturedRect(width/2 + getSearchBarXSize()/2 + paddingUnscaled*7, topTextBox,
- iconSize-paddingUnscaled*2, iconSize-paddingUnscaled*2);
- GlStateManager.bindTexture(0);
-
- //Search bar text
- fr.drawString(textField.getText(), width/2 - getSearchBarXSize()/2 + 5,
- 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 - getSearchBarXSize()/2 + 5 + textBeforeCursorWidth,
- topTextBox+(getSearchBarYSize()-8)/2-1,
- width/2 - getSearchBarXSize()/2 + 5 + textBeforeCursorWidth+1,
- topTextBox+(getSearchBarYSize()-8)/2+9, Color.WHITE.getRGB());
- }
-
- String selectedText = textField.getSelectedText();
- if(!selectedText.isEmpty()) {
- int selectionWidth = fr.getStringWidth(selectedText);
-
- int leftIndex = Math.min(textField.getCursorPosition(), textField.getSelectionEnd());
- String textBeforeSelection = textField.getText().substring(0, leftIndex);
- int textBeforeSelectionWidth = fr.getStringWidth(textBeforeSelection);
-
- drawRect(width/2 - getSearchBarXSize()/2 + 5 + textBeforeSelectionWidth,
- topTextBox+(getSearchBarYSize()-8)/2-1,
- width/2 - getSearchBarXSize()/2 + 5 + textBeforeSelectionWidth + selectionWidth,
- topTextBox+(getSearchBarYSize()-8)/2+9, Color.LIGHT_GRAY.getRGB());
-
- fr.drawString(selectedText,
- width/2 - getSearchBarXSize()/2 + 5 + textBeforeSelectionWidth,
- topTextBox+(getSearchBarYSize()-8)/2, Color.BLACK.getRGB());
- }
-
-
- /**
* Item selection (right) gui element rendering
*/
int paneWidth = (int)(width/3*getWidthMult());
int leftSide = (int)(width*getItemPaneOffsetFactor());
- int rightSide = leftSide+paneWidth-BOX_PADDING-getItemBoxXPadding();
+ int rightSide = leftSide+paneWidth-getBoxPadding()-getItemBoxXPadding();
//Tab
@@ -1288,31 +1255,31 @@ public class NEUOverlay extends Gui {
if(itemPaneOffsetFactor.getValue() < 1) {
renderBlurredBackground(width, height,
- leftSide+BOX_PADDING-5, BOX_PADDING-5,
- paneWidth-BOX_PADDING*2+10, height-BOX_PADDING*2+10);
+ leftSide+getBoxPadding()-5, getBoxPadding()-5,
+ paneWidth-getBoxPadding()*2+10, height-getBoxPadding()*2+10);
- drawRect(leftSide+BOX_PADDING-5, BOX_PADDING-5,
- leftSide+paneWidth-BOX_PADDING+5, height-BOX_PADDING+5, bg.getRGB());
+ drawRect(leftSide+getBoxPadding()-5, getBoxPadding()-5,
+ leftSide+paneWidth-getBoxPadding()+5, height-getBoxPadding()+5, bg.getRGB());
- renderNavElement(leftSide+BOX_PADDING+getItemBoxXPadding(), rightSide, getMaxPages(), page+1,
+ renderNavElement(leftSide+getBoxPadding()+getItemBoxXPadding(), rightSide, getMaxPages(), page+1,
scaledresolution.getScaleFactor()<4?"Page: ":"");
//Sort bar
- drawRect(leftSide+BOX_PADDING+getItemBoxXPadding()-1,
- height-BOX_PADDING-ITEM_SIZE-2,
+ drawRect(leftSide+getBoxPadding()+getItemBoxXPadding()-1,
+ height-getBoxPadding()-ITEM_SIZE-2,
rightSide+1,
- height-BOX_PADDING, fgCustomOpacity.getRGB());
+ height-getBoxPadding(), fgCustomOpacity.getRGB());
float sortIconsMinX = (sortIcons.length+orderIcons.length)*(ITEM_SIZE+ITEM_PADDING)+ITEM_SIZE;
- float availableX = rightSide-(leftSide+BOX_PADDING+getItemBoxXPadding());
+ float availableX = rightSide-(leftSide+getBoxPadding()+getItemBoxXPadding());
float sortOrderScaleFactor = Math.min(1, availableX / sortIconsMinX);
int scaledITEM_SIZE = (int)(ITEM_SIZE*sortOrderScaleFactor);
int scaledItemPaddedSize = (int)((ITEM_SIZE+ITEM_PADDING)*sortOrderScaleFactor);
- int iconTop = height-BOX_PADDING-(ITEM_SIZE+scaledITEM_SIZE)/2-1;
+ int iconTop = height-getBoxPadding()-(ITEM_SIZE+scaledITEM_SIZE)/2-1;
for(int i=0; i<orderIcons.length; i++) {
- int orderIconX = leftSide+BOX_PADDING+getItemBoxXPadding()+i*scaledItemPaddedSize;
+ int orderIconX = leftSide+getBoxPadding()+getItemBoxXPadding()+i*scaledItemPaddedSize;
drawRect(orderIconX, iconTop,scaledITEM_SIZE+orderIconX,iconTop+scaledITEM_SIZE, fg.getRGB());
Minecraft.getMinecraft().getTextureManager().bindTexture(getCompareMode() == i ? orderIconsActive[i] : orderIcons[i]);
@@ -1352,17 +1319,27 @@ public class NEUOverlay extends Gui {
//Iterate through all item slots and display the appropriate item
int itemBoxXPadding = getItemBoxXPadding();
- int xStart = (int)(width*getItemPaneOffsetFactor())+BOX_PADDING+itemBoxXPadding;
+ int xStart = (int)(width*getItemPaneOffsetFactor())+getBoxPadding()+itemBoxXPadding;
- renderItemsFromImage(xStart, width, height);
- renderEnchOverlay();
+ if(OpenGlHelper.isFramebufferEnabled()) {
+ renderItemsFromImage(xStart, width, height);
+ renderEnchOverlay();
- checkFramebufferSizes(width, height);
+ checkFramebufferSizes(width, height);
- if(redrawItems || !manager.config.cacheRenderedItempane.value) {
- renderItemsToImage(width, height, fgFavourite2, fgFavourite, fgCustomOpacity, true, true);
- redrawItems = false;
+ if(redrawItems || !manager.config.cacheRenderedItempane.value) {
+ renderItemsToImage(width, height, fgFavourite2, fgFavourite, fgCustomOpacity, true, true);
+ redrawItems = false;
+ }
+ } else {
+ renderItems(xStart, true, true, true);
}
+
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.enableAlpha();
+ GlStateManager.alphaFunc(516, 0.1F);
+ GlStateManager.disableLighting();
}
/**
@@ -1382,6 +1359,154 @@ public class NEUOverlay extends Gui {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
}
+ /**
+ * Search bar
+ */
+ int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor();
+ if(paddingUnscaled < 1) paddingUnscaled = 1;
+
+ int topTextBox = height - searchBarYOffset - getSearchBarYSize();
+
+ //Search bar background
+ drawRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled,
+ topTextBox - paddingUnscaled,
+ width/2 + getSearchBarXSize()/2 + paddingUnscaled,
+ height - searchBarYOffset + paddingUnscaled, searchMode ? Color.YELLOW.getRGB() : Color.WHITE.getRGB());
+ drawRect(width/2 - getSearchBarXSize()/2,
+ topTextBox,
+ width/2 + getSearchBarXSize()/2,
+ height - searchBarYOffset, Color.BLACK.getRGB());
+
+ //Quickcommands
+ if(manager.config.showQuickCommands.value) {
+ ArrayList<String> quickCommands = manager.config.quickCommands.value;
+ int bigItemSize = getSearchBarYSize();
+ int bigItemPadding = paddingUnscaled*4;
+ int x = width/2 + bigItemPadding/2 - (bigItemSize+bigItemPadding)*quickCommands.size()/2;
+ int y = topTextBox - bigItemSize - bigItemPadding - paddingUnscaled*2;
+
+ for(String quickCommand : quickCommands) {
+ if(!quickCommand.contains(":")) {
+ continue;
+ }
+ String display = quickCommand.split(":")[1];
+ ItemStack render = null;
+ float extraScale = 1;
+ if(display.length() > 20) { //Custom head
+ render = new ItemStack(Items.skull, 1, 3);
+ NBTTagCompound nbt = new NBTTagCompound();
+ NBTTagCompound skullOwner = new NBTTagCompound();
+ NBTTagCompound properties = new NBTTagCompound();
+ NBTTagList textures = new NBTTagList();
+ NBTTagCompound textures_0 = new NBTTagCompound();
+
+
+ String uuid = UUID.nameUUIDFromBytes(display.getBytes()).toString();
+ skullOwner.setString("Id", uuid);
+ skullOwner.setString("Name", uuid);
+
+ textures_0.setString("Value", display);
+ textures.appendTag(textures_0);
+
+ properties.setTag("textures", textures);
+ skullOwner.setTag("Properties", properties);
+ nbt.setTag("SkullOwner", skullOwner);
+ render.setTagCompound(nbt);
+
+ extraScale = 1.3f;
+ } else if(manager.getItemInformation().containsKey(display)) {
+ render = manager.jsonToStack(manager.getItemInformation().get(display));
+ } else {
+ Item item = Item.itemRegistry.getObject(new ResourceLocation(display.toLowerCase()));
+ if(item != null) {
+ render = new ItemStack(item);
+ }
+ }
+ if(render != null) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(x - paddingUnscaled, y - paddingUnscaled,
+ bigItemSize + paddingUnscaled*2, bigItemSize + paddingUnscaled*2, GL11.GL_NEAREST);
+ GlStateManager.color(fg.getRed() / 255f,fg.getGreen() / 255f,
+ fg.getBlue() / 255f, fg.getAlpha() / 255f);
+ Utils.drawTexturedRect(x, y, bigItemSize, bigItemSize, GL11.GL_NEAREST);
+
+ float itemScale = bigItemSize/(float)ITEM_SIZE*extraScale;
+ GlStateManager.pushMatrix();
+ GlStateManager.scale(itemScale, itemScale, 1);
+ GlStateManager.translate((x-(extraScale-1)*bigItemSize/2) /itemScale,
+ (y-(extraScale-1)*bigItemSize/2)/itemScale, 0f);
+ Utils.drawItemStack(render, 0, 0);
+ GlStateManager.popMatrix();
+ }
+ x += bigItemSize + bigItemPadding;
+ }
+ }
+
+ //Settings
+ int iconSize = getSearchBarYSize()+paddingUnscaled*2;
+ Minecraft.getMinecraft().getTextureManager().bindTexture(settings);
+ drawRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled*6 - iconSize,
+ topTextBox - paddingUnscaled,
+ width/2 - getSearchBarXSize()/2 - paddingUnscaled*6,
+ topTextBox - paddingUnscaled + iconSize, Color.WHITE.getRGB());
+
+ drawRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled*5 - iconSize,
+ topTextBox,
+ width/2 - getSearchBarXSize()/2 - paddingUnscaled*7,
+ topTextBox - paddingUnscaled*2 + iconSize, Color.GRAY.getRGB());
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ Utils.drawTexturedRect(width/2 - getSearchBarXSize()/2 - paddingUnscaled*6 - iconSize, topTextBox - paddingUnscaled, iconSize, iconSize);
+ GlStateManager.bindTexture(0);
+
+ //Help
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ drawRect(width/2 + getSearchBarXSize()/2 + paddingUnscaled*6,
+ topTextBox - paddingUnscaled,
+ width/2 + getSearchBarXSize()/2 + paddingUnscaled*6 + iconSize,
+ topTextBox - paddingUnscaled + iconSize, Color.WHITE.getRGB());
+
+ drawRect(width/2 + getSearchBarXSize()/2 + paddingUnscaled*7,
+ topTextBox,
+ width/2 + getSearchBarXSize()/2 + paddingUnscaled*5 + iconSize,
+ topTextBox - paddingUnscaled*2 + iconSize, Color.GRAY.getRGB());
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ Utils.drawTexturedRect(width/2 + getSearchBarXSize()/2 + paddingUnscaled*7, topTextBox,
+ iconSize-paddingUnscaled*2, iconSize-paddingUnscaled*2);
+ GlStateManager.bindTexture(0);
+
+ //Search bar text
+ fr.drawString(textField.getText(), width/2 - getSearchBarXSize()/2 + 5,
+ 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 - getSearchBarXSize()/2 + 5 + textBeforeCursorWidth,
+ topTextBox+(getSearchBarYSize()-8)/2-1,
+ width/2 - getSearchBarXSize()/2 + 5 + textBeforeCursorWidth+1,
+ topTextBox+(getSearchBarYSize()-8)/2+9, Color.WHITE.getRGB());
+ }
+
+ String selectedText = textField.getSelectedText();
+ if(!selectedText.isEmpty()) {
+ int selectionWidth = fr.getStringWidth(selectedText);
+
+ int leftIndex = Math.min(textField.getCursorPosition(), textField.getSelectionEnd());
+ String textBeforeSelection = textField.getText().substring(0, leftIndex);
+ int textBeforeSelectionWidth = fr.getStringWidth(textBeforeSelection);
+
+ drawRect(width/2 - getSearchBarXSize()/2 + 5 + textBeforeSelectionWidth,
+ topTextBox+(getSearchBarYSize()-8)/2-1,
+ width/2 - getSearchBarXSize()/2 + 5 + textBeforeSelectionWidth + selectionWidth,
+ topTextBox+(getSearchBarYSize()-8)/2+9, Color.LIGHT_GRAY.getRGB());
+
+ fr.drawString(selectedText,
+ width/2 - getSearchBarXSize()/2 + 5 + textBeforeSelectionWidth,
+ topTextBox+(getSearchBarYSize()-8)/2, Color.BLACK.getRGB());
+ }
+
//Render tooltip
JsonObject json = tooltipToDisplay.get();
if(json != null) {
@@ -1446,10 +1571,17 @@ public class NEUOverlay extends Gui {
}
}
+ /**
+ * Used in SettingsInfoPane to redraw the items when a setting changes.
+ */
public void redrawItems() {
redrawItems = true;
}
+ /**
+ * Sets the current page and marks that the itemsPane should be redrawn
+ * @param page
+ */
public void setPage(int page) {
this.page = page;
redrawItems = true;
@@ -1457,6 +1589,10 @@ public class NEUOverlay extends Gui {
private Framebuffer[] itemFramebuffers = new Framebuffer[2];
+ /**
+ * Checks whether the screen size has changed, if so it reconstructs the itemPane framebuffer and marks that the
+ * itemPane should be redrawn.
+ */
private void checkFramebufferSizes(int width, int height) {
int sw = width*scaledresolution.getScaleFactor();
int sh = height*scaledresolution.getScaleFactor();
@@ -1483,7 +1619,11 @@ public class NEUOverlay extends Gui {
Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
}
-
+ /**
+ * Renders all items to a framebuffer so that it can be reused later, drastically improving performance.
+ * Unfortunately using this feature will mean that animated textures will not work, but oh well.
+ * Mojang please optimize item rendering thanks.
+ */
private void renderItemsToImage(int width, int height, Color fgFavourite2,
Color fgFavourite, Color fgCustomOpacity, boolean items, boolean entities) {
int sw = width*scaledresolution.getScaleFactor();
@@ -1491,7 +1631,7 @@ public class NEUOverlay extends Gui {
GL11.glPushMatrix();
prepareFramebuffer(itemFramebuffers[0], sw, sh);
- renderItems(10, items, entities);
+ renderItems(10, items, entities, false);
cleanupFramebuffer(itemFramebuffers[0], sw, sh);
GL11.glPopMatrix();
@@ -1504,6 +1644,11 @@ public class NEUOverlay extends Gui {
private static final ResourceLocation RES_ITEM_GLINT = new ResourceLocation("textures/misc/enchanted_item_glint.png");
+ /**
+ * Renders the framebuffer created by #renderItemsToImage to the screen.
+ * itemRenderOffset is a magic number that makes the z-level of the rendered items equal to the z-level of
+ * the item glint overlay model, meaning that a depthFunc of GL_EQUAL can correctly render on to the item.
+ */
float itemRenderOffset = 7.5001f;
private void renderItemsFromImage(int xOffset, int width, int height) {
if(itemFramebuffers[0] != null && itemFramebuffers[1] != null) {
@@ -1521,6 +1666,14 @@ public class NEUOverlay extends Gui {
}
}
+ /**
+ * Renders the enchant overlay, since only the items have the specific z-offset of 7.5001, this will only apply
+ * the enchant overlay to the actual items and not anything else.
+ *
+ * (I tried very hard to replicate the enchant rendering overlay code from vanilla, but I couldn't get it to
+ * work without rendering with the "ITEM" vertex model like in vanilla, so I choose to render an arbitrary 2D
+ * item. If a texture pack sets a custom 3D model for an apple, this will probably break.)
+ */
private void renderEnchOverlay() {
ItemStack stack = new ItemStack(Items.apple);
IBakedModel model = Minecraft.getMinecraft().getRenderItem().getItemModelMesher()
@@ -1533,49 +1686,48 @@ public class NEUOverlay extends Gui {
GL11.glTranslatef(0, 0, -7.5001f+itemRenderOffset);
iterateItemSlots(new ItemSlotConsumer() {
public void consume(int x, int y, int id) {
- JsonObject json = getSearchedItemPage(id);
- if (json == null || !manager.jsonToStack(json).hasEffect()) {
- return;
- }
-
- GlStateManager.pushMatrix();
- GlStateManager.enableRescaleNormal();
- GlStateManager.enableAlpha();
- GlStateManager.alphaFunc(516, 0.1F);
- GlStateManager.enableBlend();
+ JsonObject json = getSearchedItemPage(id);
+ if (json == null || !manager.jsonToStack(json).hasEffect()) {
+ return;
+ }
- GlStateManager.disableLighting();
+ GlStateManager.pushMatrix();
+ GlStateManager.enableRescaleNormal();
+ GlStateManager.enableAlpha();
+ GlStateManager.alphaFunc(516, 0.1F);
+ GlStateManager.enableBlend();
- GlStateManager.translate(x, y, 0);
- GlStateManager.scale(16f, 16f, 16f);
+ GlStateManager.disableLighting();
- GlStateManager.depthMask(false);
- GlStateManager.depthFunc(GL11.GL_EQUAL);
- GlStateManager.blendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE);
- GlStateManager.matrixMode(5890);
- GlStateManager.pushMatrix();
- GlStateManager.scale(8.0F, 8.0F, 8.0F);
- GlStateManager.translate(f, 0.0F, 0.0F);
- GlStateManager.rotate(-50.0F, 0.0F, 0.0F, 1.0F);
+ GlStateManager.translate(x, y, 0);
+ GlStateManager.scale(16f, 16f, 16f);
- renderModel(model, -8372020, null);
+ GlStateManager.depthMask(false);
+ GlStateManager.depthFunc(GL11.GL_EQUAL);
+ GlStateManager.blendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE);
+ GlStateManager.matrixMode(5890);
+ GlStateManager.pushMatrix();
+ GlStateManager.scale(8.0F, 8.0F, 8.0F);
+ GlStateManager.translate(f, 0.0F, 0.0F);
+ GlStateManager.rotate(-50.0F, 0.0F, 0.0F, 1.0F);
- GlStateManager.popMatrix();
- GlStateManager.pushMatrix();
- GlStateManager.scale(8.0F, 8.0F, 8.0F);
- GlStateManager.translate(-f1, 0.0F, 0.0F);
- GlStateManager.rotate(10.0F, 0.0F, 0.0F, 1.0F);
+ renderModel(model, -8372020, null);
- renderModel(model, -8372020, null);
+ GlStateManager.popMatrix();
+ GlStateManager.pushMatrix();
+ GlStateManager.scale(8.0F, 8.0F, 8.0F);
+ GlStateManager.translate(-f1, 0.0F, 0.0F);
+ GlStateManager.rotate(10.0F, 0.0F, 0.0F, 1.0F);
- GlStateManager.popMatrix();
- GlStateManager.matrixMode(5888);
- GlStateManager.blendFunc(770, 771);
- GlStateManager.depthFunc(515);
- GlStateManager.depthMask(true);
+ renderModel(model, -8372020, null);
- GlStateManager.popMatrix();
+ GlStateManager.popMatrix();
+ GlStateManager.matrixMode(5888);
+ GlStateManager.blendFunc(770, 771);
+ GlStateManager.depthFunc(515);
+ GlStateManager.depthMask(true);
+ GlStateManager.popMatrix();
}
});
GlStateManager.disableBlend();
@@ -1610,44 +1762,47 @@ public class NEUOverlay extends Gui {
}
}
+ /**
+ * Renders all the item backgrounds, either squares or squircles.
+ */
private void renderItemBackgrounds(Color fgFavourite2, Color fgFavourite, Color fgCustomOpacity) {
if(fgCustomOpacity.getAlpha() == 0) return;
iterateItemSlots(new ItemSlotConsumer() {
public void consume(int x, int y, int id) {
- JsonObject json = getSearchedItemPage(id);
- if (json == null) {
- return;
- }
+ JsonObject json = getSearchedItemPage(id);
+ if (json == null) {
+ return;
+ }
- Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask);
- if (getFavourites().contains(json.get("internalname").getAsString())) {
- if(manager.config.itemStyle.value) {
- GlStateManager.color(fgFavourite2.getRed() / 255f, fgFavourite2.getGreen() / 255f,
- fgFavourite2.getBlue() / 255f, fgFavourite2.getAlpha() / 255f);
- Utils.drawTexturedRect(x - 1, y - 1, ITEM_SIZE + 2, ITEM_SIZE + 2, GL11.GL_NEAREST);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask);
+ if (getFavourites().contains(json.get("internalname").getAsString())) {
+ if(manager.config.itemStyle.value) {
+ GlStateManager.color(fgFavourite2.getRed() / 255f, fgFavourite2.getGreen() / 255f,
+ fgFavourite2.getBlue() / 255f, fgFavourite2.getAlpha() / 255f);
+ Utils.drawTexturedRect(x - 1, y - 1, ITEM_SIZE + 2, ITEM_SIZE + 2, GL11.GL_NEAREST);
- GlStateManager.color(fgFavourite.getRed() / 255f, fgFavourite.getGreen() / 255f,
- fgFavourite.getBlue() / 255f, fgFavourite.getAlpha() / 255f);
- Utils.drawTexturedRect(x, y, ITEM_SIZE, ITEM_SIZE, GL11.GL_NEAREST);
- } else {
- drawRect(x-1, y-1, x+ITEM_SIZE+1, y+ITEM_SIZE+1, fgFavourite2.getRGB());
- drawRect(x, y, x+ITEM_SIZE, y+ITEM_SIZE, fgFavourite.getRGB());
- }
+ GlStateManager.color(fgFavourite.getRed() / 255f, fgFavourite.getGreen() / 255f,
+ fgFavourite.getBlue() / 255f, fgFavourite.getAlpha() / 255f);
+ Utils.drawTexturedRect(x, y, ITEM_SIZE, ITEM_SIZE, GL11.GL_NEAREST);
} else {
- if(manager.config.itemStyle.value) {
- GlStateManager.color(fgCustomOpacity.getRed() / 255f, fgCustomOpacity.getGreen() / 255f,
- fgCustomOpacity.getBlue() / 255f, fgCustomOpacity.getAlpha() / 255f);
- Utils.drawTexturedRect(x - 1, y - 1, ITEM_SIZE + 2, ITEM_SIZE + 2, GL11.GL_NEAREST);
- } else {
- drawRect(x-1, y-1, x+ITEM_SIZE+1, y+ITEM_SIZE+1, fgCustomOpacity.getRGB());
- }
+ drawRect(x-1, y-1, x+ITEM_SIZE+1, y+ITEM_SIZE+1, fgFavourite2.getRGB());
+ drawRect(x, y, x+ITEM_SIZE, y+ITEM_SIZE, fgFavourite.getRGB());
}
- GlStateManager.bindTexture(0);
+ } else {
+ if(manager.config.itemStyle.value) {
+ GlStateManager.color(fgCustomOpacity.getRed() / 255f, fgCustomOpacity.getGreen() / 255f,
+ fgCustomOpacity.getBlue() / 255f, fgCustomOpacity.getAlpha() / 255f);
+ Utils.drawTexturedRect(x - 1, y - 1, ITEM_SIZE + 2, ITEM_SIZE + 2, GL11.GL_NEAREST);
+ } else {
+ drawRect(x-1, y-1, x+ITEM_SIZE+1, y+ITEM_SIZE+1, fgCustomOpacity.getRGB());
+ }
+ }
+ GlStateManager.bindTexture(0);
}
}, 10);
}
- private void renderItems(int xStart, boolean items, boolean entities) {
+ private void renderItems(int xStart, boolean items, boolean entities, boolean glint) {
iterateItemSlots(new ItemSlotConsumer() {
public void consume(int x, int y, int id) {
JsonObject json = getSearchedItemPage(id);
@@ -1687,7 +1842,11 @@ public class NEUOverlay extends Gui {
} else {
if(!items) return;
ItemStack stack = manager.jsonToStack(json);
- Utils.drawItemStackWithoutGlint(stack, x, y);
+ if(glint) {
+ Utils.drawItemStack(stack, x, y);
+ } else {
+ Utils.drawItemStackWithoutGlint(stack, x, y);
+ }
}
}
}, xStart);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
index 28b35a0b..b4b48db5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
@@ -11,6 +11,7 @@ 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.client.settings.KeyBinding;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
@@ -27,6 +28,7 @@ import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
+import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
@@ -36,6 +38,8 @@ import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import javax.swing.*;
+import java.awt.*;
+import java.awt.datatransfer.StringSelection;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -52,7 +56,9 @@ public class NotEnoughUpdates {
public static final String MODID = "notenoughupdates";
public static final String VERSION = "1.0.0";
- private NEUManager manager;
+ public static NotEnoughUpdates INSTANCE = null;
+
+ public NEUManager manager;
private NEUOverlay overlay;
private NEUIO neuio;
@@ -77,8 +83,13 @@ public class NotEnoughUpdates {
return s;
}
+ /**
+ * Instantiates NEUIo, NEUManager and NEUOverlay instances. Registers keybinds and adds a shutdown hook to clear tmp folder.
+ * @param event
+ */
@EventHandler
public void preinit(FMLPreInitializationEvent event) {
+ INSTANCE = this;
MinecraftForge.EVENT_BUS.register(this);
File f = new File(event.getModConfigurationDirectory(), "notenoughupdates");
@@ -88,6 +99,10 @@ public class NotEnoughUpdates {
manager.loadItemInformation();
overlay = new NEUOverlay(manager);
+ for(KeyBinding kb : manager.keybinds) {
+ ClientRegistry.registerKeyBinding(kb);
+ }
+
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
File tmp = new File(f, "tmp");
@@ -135,6 +150,10 @@ public class NotEnoughUpdates {
}
}
+ /**
+ * If the last chat messages was sent >200ms ago, sends the message.
+ * If the last chat message was sent <200 ago, will cache the message for #onTick to handle.
+ */
public void sendChatMessage(String message) {
if (System.currentTimeMillis() - lastChatMessage > CHAT_MSG_COOLDOWN) {
lastChatMessage = System.currentTimeMillis();
@@ -145,6 +164,10 @@ public class NotEnoughUpdates {
}
}
+ /**
+ * Will send the cached message from #sendChatMessage when at least 200ms has passed since the last message.
+ * This is used in order to prevent the mod spamming messages.
+ */
@EventHandler
public void onTick(TickEvent.ClientTickEvent event) {
if(currChatMessage != null && System.currentTimeMillis() - lastChatMessage > CHAT_MSG_COOLDOWN) {
@@ -154,16 +177,32 @@ public class NotEnoughUpdates {
}
}
+ /**
+ * When opening a GuiContainer, will reset the overlay and load the config.
+ * When closing a GuiContainer, will save the config.
+ * Also includes a dev feature used for automatically acquiring crafting information from the "Crafting Table" GUI.
+ */
AtomicBoolean missingRecipe = new AtomicBoolean(false);
@SubscribeEvent
public void onGuiOpen(GuiOpenEvent event) {
- if(event.gui != null) {
- System.out.println("2");
+ //OPEN
+ if(Minecraft.getMinecraft().currentScreen == null
+ && event.gui instanceof GuiContainer) {
+ overlay.reset();
+ manager.loadConfig();
+ }
+ //CLOSE
+ if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer
+ && event.gui == null) {
+ try {
+ manager.saveConfig();
+ } catch(IOException e) {}
+ }
+ if(event.gui != null && manager.config.dev.value) {
if(event.gui instanceof GuiChest) {
GuiChest eventGui = (GuiChest) event.gui;
ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
IInventory lower = cc.getLowerChestInventory();
- System.out.println("3");
ses.schedule(() -> {
if(Minecraft.getMinecraft().currentScreen != event.gui) {
return;
@@ -258,19 +297,12 @@ public class NotEnoughUpdates {
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) {}
- }
}
+ /**
+ * 1) When receiving "You are playing on profile" messages, will set the current profile.
+ * 2) When a /viewrecipe command fails (i.e. player does not have recipe unlocked, will open the custom recipe GUI)
+ */
@SubscribeEvent
public void onGuiChat(ClientChatReceivedEvent e) {
String r = null;
@@ -295,6 +327,17 @@ public class NotEnoughUpdates {
}
}
+ /**
+ * Sets hoverInv and focusInv variables, representing whether the NEUOverlay should render behind the inventory when
+ * (hoverInv == true) and whether mouse/kbd inputs shouldn't be sent to NEUOverlay (focusInv == true).
+ *
+ * If hoverInv is true, will render the overlay immediately (resulting in the inventory being drawn over the GUI)
+ * If hoverInv is false, the overlay will render in #onGuiScreenDraw (resulting in the GUI being drawn over the inv)
+ *
+ * All of this only matters if players are using gui scale auto which may result in the inventory being drawn
+ * over the various panes.
+ * @param event
+ */
@SubscribeEvent
public void onGuiBackgroundDraw(GuiScreenEvent.BackgroundDrawnEvent event) {
if(event.gui instanceof GuiContainer && isOnSkyblock()) {
@@ -331,6 +374,11 @@ public class NotEnoughUpdates {
}
}
+ /**
+ * Will draw the NEUOverlay over the inventory if focusInv == false. (z-translation of 300 is so that NEUOverlay
+ * will draw over Items in the inventory (which render at a z value of about 250))
+ * @param event
+ */
@SubscribeEvent
public void onGuiScreenDraw(GuiScreenEvent.DrawScreenEvent.Post event) {
if(event.gui instanceof GuiContainer && isOnSkyblock()) {
@@ -343,6 +391,11 @@ public class NotEnoughUpdates {
}
}
+ /**
+ * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused.
+ * Will also cancel the event if if NEUOverlay#mouseInput returns true.
+ * @param event
+ */
@SubscribeEvent
public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) {
if(event.gui instanceof GuiContainer && !(hoverInv && focusInv) && isOnSkyblock()) {
@@ -354,13 +407,22 @@ public class NotEnoughUpdates {
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
+ /**
+ * Sends a kbd event to NEUOverlay, cancelling if NEUOverlay#keyboardInput returns true.
+ * Also includes a dev function used for creating custom named json files with recipes.
+ */
boolean started = false;
@SubscribeEvent
public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) {
- if(manager.config.enableItemEditing.value && Minecraft.getMinecraft().theWorld != null &&
+ if(event.gui instanceof GuiContainer && isOnSkyblock()) {
+ if(overlay.keyboardInput(focusInv)) {
+ event.setCanceled(true);
+ }
+ }
+ if(manager.config.dev.value && 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) {
+ if(gui instanceof GuiChest) {
GuiChest eventGui = (GuiChest) event.gui;
ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
IInventory lower = cc.getLowerChestInventory();
@@ -466,15 +528,9 @@ public class NotEnoughUpdates {
ses.schedule(checker, 1000, TimeUnit.MILLISECONDS);
}*/
- if(event.gui instanceof GuiContainer && isOnSkyblock()) {
- if(overlay.keyboardInput(focusInv)) {
- event.setCanceled(true);
- }
- }
}
/**
- * This was code leftover from testing but it ended up in the final mod so I guess its staying here.
* This makes it so that holding LCONTROL while hovering over an item with NBT will show the NBT of the item.
* @param event
*/
@@ -557,6 +613,10 @@ public class NotEnoughUpdates {
}
}
event.toolTip.add(sb.toString());
+ if(Keyboard.isKeyDown(Keyboard.KEY_H)) {
+ StringSelection selection = new StringSelection(sb.toString());
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
+ }
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java
index 0abca240..61344237 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java
@@ -1,7 +1,9 @@
package io.github.moulberry.notenoughupdates.infopanes;
+import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.NEUOverlay;
import io.github.moulberry.notenoughupdates.Utils;
@@ -13,6 +15,8 @@ import net.minecraft.util.ResourceLocation;
import org.lwjgl.input.Keyboard;
import java.awt.*;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.List;
import java.util.concurrent.Executors;
@@ -23,6 +27,10 @@ import java.util.concurrent.atomic.AtomicInteger;
public class DevInfoPane extends TextInfoPane {
+ /**
+ * Provides some dev functions used to help with adding new items/detecting missing items.
+ */
+
public DevInfoPane(NEUOverlay overlay, NEUManager manager) {
super(overlay, manager, "Dev", "");
text = getText();
@@ -30,6 +38,25 @@ public class DevInfoPane extends TextInfoPane {
private String getText() {
String text = "";
+
+ /*for(Map.Entry<String, JsonObject> item : manager.getItemInformation().entrySet()) {
+ if(!item.getValue().has("infoType") || item.getValue().get("infoType").getAsString().isEmpty()) {
+ text += item.getKey() + "\n";
+ }
+ }*/
+ for(String s : manager.neuio.getRemovedItems(manager.getItemInformation().keySet())) {
+ text += s + "\n";
+ }
+
+ if(true) return text;
+
+ /*for(Map.Entry<String, JsonObject> item : manager.getItemInformation().entrySet()) {
+ if(!item.getValue().has("infoType") || item.getValue().get("infoType").getAsString().isEmpty()) {
+ text += item.getKey() + "\n";
+ }
+ }*/
+ //if(true) return text;
+
for(Map.Entry<String, JsonElement> entry : manager.getAuctionPricesJson().get("prices").getAsJsonObject().entrySet()) {
if(!manager.getItemInformation().keySet().contains(entry.getKey())) {
if(entry.getKey().contains("-")) {
@@ -49,11 +76,82 @@ public class DevInfoPane extends TextInfoPane {
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
@Override
- public void keyboardInput() {
+ public boolean keyboardInput() {
if(Keyboard.isKeyDown(Keyboard.KEY_J)) {
running.set(!running.get());
- if(running.get()) {
+ for(Map.Entry<String, JsonObject> item : manager.getItemInformation().entrySet()) {
+ /*if(!item.getValue().has("infoType") || item.getValue().get("infoType").getAsString().isEmpty()) {
+ if(item.getValue().has("info") && item.getValue().get("info").getAsJsonArray().size()>0) {
+ item.getValue().addProperty("infoType", "WIKI_URL");
+ try {
+ manager.writeJsonDefaultDir(item.getValue(), item.getKey()+".json");
+ } catch(IOException e){}
+ manager.loadItem(item.getKey());
+ }
+ }*/
+ /*if(item.getKey().startsWith("PET_ITEM_")) {
+ item.getValue().addProperty("infoType", "WIKI_URL");
+ JsonArray array = new JsonArray();
+ array.add(new JsonPrimitive("https://hypixel-skyblock.fandom.com/wiki/Pet_Items"));
+ item.getValue().add("info", array);
+ try {
+ manager.writeJsonDefaultDir(item.getValue(), item.getKey()+".json");
+ } catch(IOException e){}
+ manager.loadItem(item.getKey());
+ }*/
+ /*if(!item.getValue().has("infoType") || item.getValue().get("infoType").getAsString().isEmpty()) {
+ //String prettyName =
+
+ String itemS = item.getKey().split("-")[0].split(";")[0];
+ StringBuilder prettyName = new StringBuilder();
+ boolean capital = true;
+ for(int i=0; i<itemS.length(); i++) {
+ char c = itemS.charAt(i);
+ if(capital) {
+ prettyName.append(String.valueOf(c).toUpperCase());
+ capital = false;
+ } else {
+ prettyName.append(String.valueOf(c).toLowerCase());
+ }
+ if(String.valueOf(c).equals("_")) {
+ capital = true;
+ }
+ }
+ String prettyNameS = prettyName.toString();
+ File f = manager.getWebFile("https://hypixel-skyblock.fandom.com/wiki/"+prettyNameS);
+ if(f == null) {
+ continue;
+ //#REDIRECT [[Armor of Magma]]
+ }
+ 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) {
+ continue;
+ }
+ if(sb.toString().isEmpty()) {
+ continue;
+ }
+ if(sb.toString().startsWith("#REDIRECT")) {
+ prettyNameS = sb.toString().split("\\[\\[")[1].split("]]")[0].replaceAll(" ", "_");
+ }
+ item.getValue().addProperty("infoType", "WIKI_URL");
+ JsonArray array = new JsonArray();
+ array.add(new JsonPrimitive("https://hypixel-skyblock.fandom.com/wiki/"+prettyNameS));
+ item.getValue().add("info", array);
+ try {
+ manager.writeJsonDefaultDir(item.getValue(), item.getKey()+".json");
+ } catch(IOException e){}
+ manager.loadItem(item.getKey());
+ }*/
+ }
+
+ /*if(running.get()) {
List<String> add = new ArrayList<>();
for(Map.Entry<String, JsonObject> item : manager.getItemInformation().entrySet()) {
if(item.getValue().has("recipe")) {
@@ -74,7 +172,7 @@ public class DevInfoPane extends TextInfoPane {
ses.schedule(this, 1000L, TimeUnit.MILLISECONDS);
}
}, 1000L, TimeUnit.MILLISECONDS);
- }
+ }*/
}
/*if(Keyboard.isKeyDown(Keyboard.KEY_J) && !running) {
running = true;
@@ -102,5 +200,6 @@ public class DevInfoPane extends TextInfoPane {
}
}, 1000L, TimeUnit.MILLISECONDS);
}*/
+ return false;
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/FlipperInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/FlipperInfoPane.java
index 49cc5389..152d0628 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/FlipperInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/FlipperInfoPane.java
@@ -21,6 +21,10 @@ import java.util.List;
public class FlipperInfoPane extends InfoPane {
+ /**
+ * Not currently used in BETA-1.6
+ */
+
protected String title;
protected String text;
@@ -46,7 +50,7 @@ public class FlipperInfoPane extends InfoPane {
int leftSide = rightSide - paneWidth;
int titleLen = fr.getStringWidth(title);
- fr.drawString(title, (leftSide+rightSide-titleLen)/2, overlay.BOX_PADDING + 5,
+ fr.drawString(title, (leftSide+rightSide-titleLen)/2, overlay.getBoxPadding() + 5,
Color.WHITE.getRGB());
int y = 0;
@@ -73,8 +77,8 @@ public class FlipperInfoPane extends InfoPane {
fr.drawString("Incl. Stackables: ", x, y, Color.WHITE.getRGB());
drawButton(x, y, false);
- drawRect(leftSide+overlay.BOX_PADDING-5, overlay.BOX_PADDING-5,
- rightSide-overlay.BOX_PADDING+5, height-overlay.BOX_PADDING+5, bg.getRGB());
+ drawRect(leftSide+overlay.getBoxPadding()-5, overlay.getBoxPadding()-5,
+ rightSide-overlay.getBoxPadding()+5, height-overlay.getBoxPadding()+5, bg.getRGB());
}
private void drawButton(int x, int y, boolean enabled) {
@@ -87,8 +91,8 @@ public class FlipperInfoPane extends InfoPane {
}
- public void keyboardInput() {
-
+ public boolean keyboardInput() {
+ return false;
}
private int renderParagraph(int width, int height, int startY, String text, Color bg) {
@@ -100,9 +104,9 @@ public class FlipperInfoPane extends InfoPane {
int yOff = 0;
for(String line : text.split("\n")) {
- yOff += Utils.renderStringTrimWidth(line, fr, false,leftSide+overlay.BOX_PADDING + 5,
- startY+overlay.BOX_PADDING + 10 + yOff,
- width*1/3-overlay.BOX_PADDING*2-10, Color.WHITE.getRGB(), -1);
+ yOff += Utils.renderStringTrimWidth(line, fr, false,leftSide+overlay.getBoxPadding() + 5,
+ startY+overlay.getBoxPadding() + 10 + yOff,
+ width*1/3-overlay.getBoxPadding()*2-10, Color.WHITE.getRGB(), -1);
yOff += 16;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
index 6469ff1c..ddf8d962 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
@@ -44,6 +44,9 @@ public class HTMLInfoPane extends TextInfoPane {
private int imageHeight = 0;
private int imageWidth = 0;
+ /**
+ * Creates a wiki model and sets the configuration to work with hypixel-skyblock wikia.
+ */
static {
Configuration conf = new Configuration();
conf.addTokenTag("img", new HTMLTag("img"));
@@ -81,6 +84,9 @@ public class HTMLInfoPane extends TextInfoPane {
};
}
+ /**
+ * Takes a wiki url, uses NEUManager#getWebFile to download the web file and passed that in to #createFromWiki
+ */
public static HTMLInfoPane createFromWikiUrl(NEUOverlay overlay, NEUManager manager, String name, String wikiUrl) {
File f = manager.getWebFile(wikiUrl);
if(f == null) {
@@ -100,6 +106,12 @@ public class HTMLInfoPane extends TextInfoPane {
return createFromWiki(overlay, manager, name, sb.toString());
}
+ /**
+ * Takes raw wikia code and uses Bliki to generate HTML. Lot's of shennanigans to get it to render appropriately.
+ * Honestly, I could have just downloaded the raw HTML of the wiki page and displayed that but I wanted
+ * a more permanent solution that can be abstracted to work with arbitrary wiki codes (eg. moulberry.github.io/
+ * files/neu_help.html).
+ */
public static HTMLInfoPane createFromWiki(NEUOverlay overlay, NEUManager manager, String name, String wiki) {
String[] split = wiki.split("</infobox>");
wiki = split[split.length - 1]; //Remove everything before infobox
@@ -123,6 +135,11 @@ public class HTMLInfoPane extends TextInfoPane {
return new HTMLInfoPane(overlay, manager, name, html);
}
+ /**
+ * Uses the wkhtmltoimage command-line tool to generate an image from the HTML code. This
+ * generation is done asynchronously as sometimes it can take up to 10 seconds for more
+ * complex webpages.
+ */
public HTMLInfoPane(NEUOverlay overlay, NEUManager manager, String name, String html) {
super(overlay, manager, name, "");
this.title = name;
@@ -237,6 +254,9 @@ public class HTMLInfoPane extends TextInfoPane {
}
}
+ /**
+ * Renders a background, title and the image created in the ctor (if it has been generated).
+ */
@Override
public void render(int width, int height, Color bg, Color fg, ScaledResolution scaledresolution, int mouseX, int mouseY) {
if(imageTemp != null && imageTexture == null) {
@@ -258,38 +278,39 @@ public class HTMLInfoPane extends TextInfoPane {
int leftSide = rightSide - paneWidth;
int titleLen = fr.getStringWidth(title);
- fr.drawString(title, (leftSide+rightSide-titleLen)/2, overlay.BOX_PADDING + 5, Color.WHITE.getRGB());
+ fr.drawString(title, (leftSide+rightSide-titleLen)/2, overlay.getBoxPadding() + 5, Color.WHITE.getRGB());
- drawRect(leftSide+overlay.BOX_PADDING-5, overlay.BOX_PADDING-5, rightSide-overlay.BOX_PADDING+5,
- height-overlay.BOX_PADDING+5, bg.getRGB());
+ drawRect(leftSide+overlay.getBoxPadding()-5, overlay.getBoxPadding()-5, rightSide-overlay.getBoxPadding()+5,
+ height-overlay.getBoxPadding()+5, bg.getRGB());
- int imageW = paneWidth - overlay.BOX_PADDING*2;
+ int imageW = paneWidth - overlay.getBoxPadding()*2;
float scaleF = IMAGE_WIDTH*ZOOM_FACTOR/(float)imageW;
Minecraft.getMinecraft().getTextureManager().bindTexture(imageTexture);
GlStateManager.color(1f, 1f, 1f, 1f);
- if(height-overlay.BOX_PADDING*3 < imageHeight/scaleF) {
- if(scrollHeight.getValue() > imageHeight/scaleF-height+overlay.BOX_PADDING*3) {
- scrollHeight.setValue((int)(imageHeight/scaleF-height+overlay.BOX_PADDING*3));
+ if(height-overlay.getBoxPadding()*3 < imageHeight/scaleF) {
+ if(scrollHeight.getValue() > imageHeight/scaleF-height+overlay.getBoxPadding()*3) {
+ scrollHeight.setValue((int)(imageHeight/scaleF-height+overlay.getBoxPadding()*3));
}
int yScroll = scrollHeight.getValue();
float vMin = yScroll/(imageHeight/scaleF);
- float vMax = (yScroll+height-overlay.BOX_PADDING*3)/(imageHeight/scaleF);
- Utils.drawTexturedRect(leftSide+overlay.BOX_PADDING, overlay.BOX_PADDING*2, imageW,
- height-overlay.BOX_PADDING*3,
+ float vMax = (yScroll+height-overlay.getBoxPadding()*3)/(imageHeight/scaleF);
+ Utils.drawTexturedRect(leftSide+overlay.getBoxPadding(), overlay.getBoxPadding()*2, imageW,
+ height-overlay.getBoxPadding()*3,
0, 1, vMin, vMax);
} else {
scrollHeight.setValue(0);
- Utils.drawTexturedRect(leftSide+overlay.BOX_PADDING, overlay.BOX_PADDING*2, imageW,
+ Utils.drawTexturedRect(leftSide+overlay.getBoxPadding(), overlay.getBoxPadding()*2, imageW,
(int)(imageHeight/scaleF));
}
GlStateManager.bindTexture(0);
}
@Override
- public void keyboardInput() {
+ public boolean keyboardInput() {
+ return false;
}
@Override
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java
index 74321081..2b87fdbc 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java
@@ -24,21 +24,21 @@ public abstract class InfoPane extends Gui {
public abstract void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown);
- public abstract void keyboardInput();
+ public abstract boolean keyboardInput();
public void renderDefaultBackground(int width, int height, Color bg) {
int paneWidth = (int)(width/3*overlay.getWidthMult());
int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor());
int leftSide = rightSide - paneWidth;
- int boxLeft = leftSide + overlay.BOX_PADDING - 5;
- int boxRight = rightSide - overlay.BOX_PADDING + 5;
+ int boxLeft = leftSide + overlay.getBoxPadding() - 5;
+ int boxRight = rightSide - overlay.getBoxPadding() + 5;
overlay.renderBlurredBackground(width, height,
- boxLeft, overlay.BOX_PADDING-5,
- boxRight-boxLeft, height-overlay.BOX_PADDING*2+10);
- drawRect(boxLeft, overlay.BOX_PADDING - 5, boxRight,
- height - overlay.BOX_PADDING + 5, bg.getRGB());
+ boxLeft, overlay.getBoxPadding()-5,
+ boxRight-boxLeft, height-overlay.getBoxPadding()*2+10);
+ drawRect(boxLeft, overlay.getBoxPadding() - 5, boxRight,
+ height - overlay.getBoxPadding() + 5, bg.getRGB());
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/QOLInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/QOLInfoPane.java
index bf1a987e..e847a01c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/QOLInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/QOLInfoPane.java
@@ -29,6 +29,11 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class QOLInfoPane extends ScrollableInfoPane {
+
+ /**
+ * Not currently used in BETA-1.6
+ */
+
private LinkedHashMap<String, ItemStack> accessoryMap = new LinkedHashMap<>();
private LinkedHashMap<String, JsonObject> allTalismans = new LinkedHashMap<>();
private List<JsonObject> recommended = new ArrayList<>();
@@ -231,11 +236,11 @@ public class QOLInfoPane extends ScrollableInfoPane {
int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor());
int leftSide = rightSide - paneWidth;
- int y=overlay.BOX_PADDING+10;
+ int y=overlay.getBoxPadding()+10;
y += renderParagraph(width, height, y, "Current Accessories");
ItemStack display = null;
- int x=leftSide+overlay.BOX_PADDING+5;
+ int x=leftSide+overlay.getBoxPadding()+5;
for(Map.Entry<String, ItemStack> entry : accessoryMap.entrySet()) {
if(mouseX > x && mouseX < x+16) {
if(mouseY > y && mouseY < y+16) {
@@ -246,8 +251,8 @@ public class QOLInfoPane extends ScrollableInfoPane {
drawRect(x, y, x+16, y+16, fg.getRGB());
Utils.drawItemStack(entry.getValue(), x, y);
x += 20;
- if(x + 20 + (leftSide+overlay.BOX_PADDING+5) > paneWidth) {
- x=leftSide+overlay.BOX_PADDING+5;
+ if(x + 20 + (leftSide+overlay.getBoxPadding()+5) > paneWidth) {
+ x=leftSide+overlay.getBoxPadding()+5;
y+=20;
}
}
@@ -258,7 +263,7 @@ public class QOLInfoPane extends ScrollableInfoPane {
y+=10;
- x=leftSide+overlay.BOX_PADDING+5;
+ x=leftSide+overlay.getBoxPadding()+5;
for(Map.Entry<String, JsonObject> entry : allTalismans.entrySet()) {
if(accessoryMap.containsKey(entry.getKey())) {
continue;
@@ -272,8 +277,8 @@ public class QOLInfoPane extends ScrollableInfoPane {
drawRect(x, y, x+16, y+16, fg.getRGB());
Utils.drawItemStack(manager.jsonToStack(entry.getValue()), x, y);
x += 20;
- if(x + 20 + (leftSide+overlay.BOX_PADDING+5) > paneWidth) {
- x=leftSide+overlay.BOX_PADDING+5;
+ if(x + 20 + (leftSide+overlay.getBoxPadding()+5) > paneWidth) {
+ x=leftSide+overlay.getBoxPadding()+5;
y+=20;
}
}
@@ -281,7 +286,7 @@ public class QOLInfoPane extends ScrollableInfoPane {
y+=20;
y += renderParagraph(width, height, y, "Recommended Accessory Upgrades");
- x=leftSide+overlay.BOX_PADDING+5;
+ x=leftSide+overlay.getBoxPadding()+5;
for(JsonObject json : recommended) {
if(mouseX > x && mouseX < x+16) {
if(mouseY > y && mouseY < y+16) {
@@ -292,8 +297,8 @@ public class QOLInfoPane extends ScrollableInfoPane {
drawRect(x, y, x+16, y+16, fg.getRGB());
Utils.drawItemStack(manager.jsonToStack(json), x, y);
x += 20;
- if(x + 20 + (leftSide+overlay.BOX_PADDING+5) > paneWidth) {
- x=leftSide+overlay.BOX_PADDING+5;
+ if(x + 20 + (leftSide+overlay.getBoxPadding()+5) > paneWidth) {
+ x=leftSide+overlay.getBoxPadding()+5;
y+=20;
}
}
@@ -317,8 +322,8 @@ public class QOLInfoPane extends ScrollableInfoPane {
}
}
- public void keyboardInput() {
-
+ public boolean keyboardInput() {
+ return false;
}
@@ -331,9 +336,9 @@ public class QOLInfoPane extends ScrollableInfoPane {
int yOff = 0;
for(String line : text.split("\n")) {
- yOff += Utils.renderStringTrimWidth(line, fr, false,leftSide+overlay.BOX_PADDING + 5,
+ yOff += Utils.renderStringTrimWidth(line, fr, false,leftSide+overlay.getBoxPadding() + 5,
startY + yOff,
- width*1/3-overlay.BOX_PADDING*2-10, Color.WHITE.getRGB(), -1);
+ width*1/3-overlay.getBoxPadding()*2-10, Color.WHITE.getRGB(), -1);
yOff += 16;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java
index 31f6dca9..2fccbf9e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java
@@ -47,7 +47,7 @@ public class SettingsInfoPane extends InfoPane {
if(page > maxPages-1) page = maxPages-1;
if(page < 0) page = 0;
- overlay.renderNavElement(leftSide+overlay.BOX_PADDING, rightSide-overlay.BOX_PADDING,
+ overlay.renderNavElement(leftSide+overlay.getBoxPadding(), rightSide-overlay.getBoxPadding(),
maxPages,page+1,"Settings: ");
AtomicReference<List<String>> textToDisplay = new AtomicReference<>(null);
@@ -69,8 +69,6 @@ public class SettingsInfoPane extends InfoPane {
tileWidth-(int)(16*mult), new Color(100,255,150).getRGB(), 3);
}
- if(Keyboard.isKeyDown(Keyboard.KEY_H)) return;
-
if(option.value instanceof Boolean) {
GlStateManager.color(1f, 1f, 1f, 1f);
Minecraft.getMinecraft().getTextureManager().bindTexture(((Boolean)option.value) ? on : off);
@@ -164,8 +162,8 @@ public class SettingsInfoPane extends InfoPane {
int paneWidth = (int)(width/3*overlay.getWidthMult());
int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor());
int leftSide = rightSide - paneWidth;
- rightSide -= overlay.BOX_PADDING;
- leftSide += overlay.BOX_PADDING;
+ rightSide -= overlay.getBoxPadding();
+ leftSide += overlay.getBoxPadding();
FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
float maxStrLen = fr.getStringWidth(EnumChatFormatting.BOLD+"Settings: " + maxPages + "/" + maxPages);
@@ -173,7 +171,7 @@ public class SettingsInfoPane extends InfoPane {
int buttonXSize = (int)Math.min(maxButtonXSize, overlay.getSearchBarYSize()*480/160f);
int ySize = (int)(buttonXSize/480f*160);
int yOffset = (int)((overlay.getSearchBarYSize()-ySize)/2f);
- int top = overlay.BOX_PADDING+yOffset;
+ int top = overlay.getBoxPadding()+yOffset;
if(mouseY >= top && mouseY <= top+ySize) {
int leftPrev = leftSide-1;
@@ -188,7 +186,8 @@ public class SettingsInfoPane extends InfoPane {
}
}
- public void keyboardInput() {
+ public boolean keyboardInput() {
+ AtomicBoolean ret = new AtomicBoolean(false);
iterateSettingTile(new SettingsTileConsumer() {
@Override
public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option) {
@@ -201,10 +200,12 @@ public class SettingsInfoPane extends InfoPane {
if(tf.getFocus()) {
tf.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
onTextfieldChange(tf, option);
+ ret.set(true);
}
}
}
});
+ return ret.get();
}
private abstract static class SettingsTileConsumer {
@@ -222,10 +223,10 @@ public class SettingsInfoPane extends InfoPane {
int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor());
int leftSide = rightSide - paneWidth;
- int boxLeft = leftSide+overlay.BOX_PADDING-5;
- int boxRight = rightSide-overlay.BOX_PADDING+5;
+ int boxLeft = leftSide+overlay.getBoxPadding()-5;
+ int boxRight = rightSide-overlay.getBoxPadding()+5;
- int boxBottom = height - overlay.BOX_PADDING + 5;
+ int boxBottom = height - overlay.getBoxPadding() + 5;
int boxWidth = boxRight-boxLeft;
int tilePadding = 7;
@@ -235,7 +236,7 @@ public class SettingsInfoPane extends InfoPane {
maxPages=1;
int currPage=0;
int x=0;
- int y=tilePadding+overlay.BOX_PADDING+overlay.getSearchBarYSize();
+ int y=tilePadding+overlay.getBoxPadding()+overlay.getSearchBarYSize();
for(int i=0; i<manager.config.getOptions().size(); i++) {
if(i!=0 && i%numHorz==0) {
x = 0;
@@ -243,7 +244,7 @@ public class SettingsInfoPane extends InfoPane {
}
if(y + tileHeight > boxBottom) {
x=0;
- y=tilePadding+overlay.BOX_PADDING+overlay.getSearchBarYSize();
+ y=tilePadding+overlay.getBoxPadding()+overlay.getSearchBarYSize();
currPage++;
maxPages = currPage+1;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/TextInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/TextInfoPane.java
index 388719d0..1072ca4f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/TextInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/TextInfoPane.java
@@ -29,30 +29,30 @@ public class TextInfoPane extends ScrollableInfoPane {
int titleLen = fr.getStringWidth(title);
int yScroll = -scrollHeight.getValue();
- fr.drawString(title, (leftSide+rightSide-titleLen)/2, yScroll+overlay.BOX_PADDING + 5,
+ fr.drawString(title, (leftSide+rightSide-titleLen)/2, yScroll+overlay.getBoxPadding() + 5,
Color.WHITE.getRGB());
int yOff = 20;
for(String line : text.split("\n")) {
- yOff += Utils.renderStringTrimWidth(line, fr, false,leftSide+overlay.BOX_PADDING + 5,
- yScroll+overlay.BOX_PADDING + 10 + yOff,
- width*1/3-overlay.BOX_PADDING*2-10, Color.WHITE.getRGB(), -1);
+ yOff += Utils.renderStringTrimWidth(line, fr, false,leftSide+overlay.getBoxPadding() + 5,
+ yScroll+overlay.getBoxPadding() + 10 + yOff,
+ width*1/3-overlay.getBoxPadding()*2-10, Color.WHITE.getRGB(), -1);
yOff += 16;
}
- int top = overlay.BOX_PADDING - 5;
+ int top = overlay.getBoxPadding() - 5;
int totalBoxHeight = yOff+14;
- int bottom = Math.max(top+totalBoxHeight, height-overlay.BOX_PADDING+5);
+ int bottom = Math.max(top+totalBoxHeight, height-overlay.getBoxPadding()+5);
- if(scrollHeight.getValue() > top+totalBoxHeight-(height-overlay.BOX_PADDING+5)) {
- scrollHeight.setValue(top+totalBoxHeight-(height-overlay.BOX_PADDING+5));
+ if(scrollHeight.getValue() > top+totalBoxHeight-(height-overlay.getBoxPadding()+5)) {
+ scrollHeight.setValue(top+totalBoxHeight-(height-overlay.getBoxPadding()+5));
}
- drawRect(leftSide+overlay.BOX_PADDING-5, yScroll+overlay.BOX_PADDING-5,
- rightSide-overlay.BOX_PADDING+5, yScroll+bottom, bg.getRGB());
+ drawRect(leftSide+overlay.getBoxPadding()-5, yScroll+overlay.getBoxPadding()-5,
+ rightSide-overlay.getBoxPadding()+5, yScroll+bottom, bg.getRGB());
}
- public void keyboardInput() {
-
+ public boolean keyboardInput() {
+ return false;
}
public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java
index 88ffe16e..524c9ffb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java
@@ -1,4 +1,28 @@
package io.github.moulberry.notenoughupdates.mixins;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.Utils;
+import net.minecraft.client.renderer.InventoryEffectRenderer;
+import net.minecraft.item.ItemStack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.ModifyVariable;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+
+@Mixin({InventoryEffectRenderer.class})
public class MixinInventoryEffectRenderer {
+
+ @ModifyVariable(method="updateActivePotionEffects", at=@At(value="STORE"))
+ public boolean hasVisibleEffect_updateActivePotionEffects(boolean hasVisibleEffect) {
+ if(NotEnoughUpdates.INSTANCE.manager.config.hidePotionEffect.value &&
+ NotEnoughUpdates.INSTANCE.isOnSkyblock()) {
+ return false;
+ } else {
+ return hasVisibleEffect;
+ }
+ }
+
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java
index 6c7a70a0..5eae3886 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java
@@ -14,6 +14,11 @@ import java.util.List;
public class Options {
+ /**
+ * Ok, I'll be honest. I wrote this class without looking too much in to how to make proper serializable
+ * variables with defaults values/etc. It works. I'm happy.
+ */
+
public Option<Boolean> enableItemEditing = new Option(
false,
"Enable Item Editing",
@@ -24,6 +29,16 @@ public class Options {
"Only Show On Skyblock",
false,
"GUI Overlay only appears when you are playing Skyblock.");
+ public Option<Boolean> hidePotionEffect = new Option(
+ true,
+ "Hide Potion Effect",
+ false,
+ "If true, the potion effects will not show in the inventory GUI.");
+ public Option<Boolean> showQuickCommands = new Option(
+ true,
+ "Quick Commands",
+ false,
+ "If true, shows quick commands above search bar.");
public Option<Boolean> advancedPriceInfo = new Option(
false,
"Advanced Price Information",
@@ -35,7 +50,7 @@ public class Options {
false,
"Caches the drawn itempane, drastically improving performance. However, animated textures will not work.");
public Option<Double> bgBlurFactor = new Option(
- 5.0,
+ 10.0,
"Background Blur Factor",
false,
"Changes the strength of pane background blur. 0-50.");
@@ -103,12 +118,28 @@ public class Options {
"Favourites",
false,
"Favourites");
+ public Option<ArrayList<String>> quickCommands = new Option(
+ createDefaultQuickCommands(),
+ "Quick Commands",
+ false,
+ "Quick Commands");
+
+ private ArrayList<String> createDefaultQuickCommands() {
+ ArrayList<String> arr = new ArrayList<>();
+ arr.add("/warp home:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzljODg4MWU0MjkxNWE5ZDI5YmI2MWExNmZiMjZkMDU5OTEzMjA0ZDI2NWRmNWI0MzliM2Q3OTJhY2Q1NiJ9fX0=");
+ arr.add("/warp hub:eyJ0aW1lc3RhbXAiOjE1NTkyMTU0MTY5MDksInByb2ZpbGVJZCI6IjQxZDNhYmMyZDc0OTQwMGM5MDkwZDU0MzRkMDM4MzFiIiwicHJvZmlsZU5hbWUiOiJNZWdha2xvb24iLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2Q3Y2M2Njg3NDIzZDA1NzBkNTU2YWM1M2UwNjc2Y2I1NjNiYmRkOTcxN2NkODI2OWJkZWJlZDZmNmQ0ZTdiZjgifX19");
+ arr.add("/craft:CRAFTING_TABLE");
+ arr.add("/enderchest:ENDER_CHEST");
+ arr.add("/wardrobe:LEATHER_CHESTPLATE");
+ return arr;
+ }
public List<Option> getOptions() {
List<Option> options = new ArrayList<>();
tryAddOption(enableItemEditing, options);
tryAddOption(onlyShowOnSkyblock, options);
+ tryAddOption(hidePotionEffect, options);
tryAddOption(advancedPriceInfo, options);
tryAddOption(cacheRenderedItempane, options);
tryAddOption(autoupdate, options);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java
index a39da281..7e8e8a14 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java
@@ -18,10 +18,13 @@ import java.util.function.Consumer;
public class HypixelApi {
+ /**
+ * Not currently used as of BETA-1.6.
+ */
+
private Gson gson = new Gson();
private ExecutorService es = Executors.newSingleThreadExecutor();
- //https://api.hypixel.net/skyblock/profiles?key=06b20aa2-ff04-4851-9687-669c8111526f&uuid=d0e05de7-6067-454d-beae-c6d19d886191
public void getHypixelApiAsync(String apiKey, String method, HashMap<String, String> args, Consumer<JsonObject> consumer) {
getHypixelApiAsync(generateApiUrl(apiKey, method, args), consumer);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java b/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java
index 47a9c86b..65e7305a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java
@@ -2,6 +2,9 @@ package io.github.moulberry.notenoughupdates.util;
import org.lwjgl.input.Keyboard;
+/**
+ * Utility used for positioning GUI elements during development.
+ */
public class TexLoc {
public int x;