aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java2900
1 files changed, 1510 insertions, 1390 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
index 5fef4c62..df31834f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
@@ -1,14 +1,14 @@
package io.github.moulberry.notenoughupdates;
-import com.google.common.collect.Lists;
import com.google.gson.*;
import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
-import io.github.moulberry.notenoughupdates.overlays.CraftingOverlay;
-import io.github.moulberry.notenoughupdates.util.Constants;
-import io.github.moulberry.notenoughupdates.util.HypixelApi;
-import io.github.moulberry.notenoughupdates.util.SBInfo;
-import io.github.moulberry.notenoughupdates.util.Utils;
+import io.github.moulberry.notenoughupdates.miscgui.KatSitterOverlay;
+import io.github.moulberry.notenoughupdates.recipes.CraftingOverlay;
+import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe;
+import io.github.moulberry.notenoughupdates.recipes.Ingredient;
+import io.github.moulberry.notenoughupdates.recipes.NeuRecipe;
+import io.github.moulberry.notenoughupdates.util.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.init.Blocks;
@@ -17,113 +17,153 @@ import net.minecraft.inventory.ContainerChest;
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.ResourceLocation;
+import net.minecraftforge.fml.common.ProgressManager;
import org.apache.commons.io.FileUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
-import javax.swing.*;
+import javax.swing.JDialog;
+import javax.swing.JOptionPane;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.*;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class NEUManager {
-
- private final NotEnoughUpdates neu;
- public final Gson gson;
- public final APIManager auctionManager;
-
- private TreeMap<String, JsonObject> itemMap = new TreeMap<>();
-
- 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 keybindItemSelect = new KeyBinding("Select Item", -98 /*middle*/, "NotEnoughUpdates");
- public final KeyBinding[] keybinds = new KeyBinding[]{ keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe,
- keybindToggleDisplay, keybindClosePanes, keybindItemSelect};
-
- public String viewItemAttemptID = null;
- public long viewItemAttemptTime = 0;
-
- private String currentProfile = "";
- private String currentProfileBackup = "";
- public final HypixelApi hypixelApi = new HypixelApi();
-
- private Map<String, ItemStack> itemstackCache = new HashMap<>();
-
- private ExecutorService repoLoaderES = Executors.newSingleThreadExecutor();
-
- private static String GIT_COMMITS_URL;
-
- private HashMap<String, Set<String>> usagesMap = new HashMap<>();
-
- public String latestRepoCommit = null;
-
- public File configLocation;
- public File repoLocation;
- public File configFile;
-
- public NEUManager(NotEnoughUpdates neu, File configLocation) {
- this.neu = neu;
- this.configLocation = configLocation;
- this.auctionManager = new APIManager(this);
- GIT_COMMITS_URL = neu.config.hidden.repoCommitsURL;
-
- gson = new GsonBuilder().setPrettyPrinting().create();
-
- this.repoLocation = new File(configLocation, "repo");
- repoLocation.mkdir();
- }
-
- public void setCurrentProfile(String currentProfile) {
- this.currentProfile = currentProfile;
- }
-
- public String getCurrentProfile() {
- return SBInfo.getInstance().currentProfile;
- }
-
- public <T> T getJsonFromFile(File file, Class<T> clazz) {
- try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
- T obj = gson.fromJson(reader, clazz);
- return obj;
- } catch(Exception e) { return null; }
- }
-
- /**
- * Parses a file in to a JsonObject.
- */
- public JsonObject getJsonFromFile(File file) {
- try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
- JsonObject json = gson.fromJson(reader, JsonObject.class);
- return json;
- } catch(Exception e) { return null; }
- }
-
- public void resetRepo() {
- try { Utils.recursiveDelete(new File(configLocation, "repo")); } catch(Exception e) {}
- try { new File(configLocation, "currentCommit.json").delete(); } catch(Exception e) {}
- }
-
- /**
- * Called when the game is first loaded. Compares the local repository to the github repository and handles
- * the downloading of new/updated files. This then calls the "loadItem" method for every item in the local
- * repository.
- */
- public void loadItemInformation() {
+ private final NotEnoughUpdates neu;
+ public final Gson gson;
+ public final APIManager auctionManager;
+
+ private final TreeMap<String, JsonObject> itemMap = new TreeMap<>();
+
+ private final TreeMap<String, HashMap<String, List<Integer>>> titleWordMap = new TreeMap<>();
+ private final 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 keybindItemSelect = new KeyBinding("Select Item", -98 /*middle*/, "NotEnoughUpdates");
+ public final KeyBinding[] keybinds = new KeyBinding[]{
+ keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe,
+ keybindToggleDisplay, keybindClosePanes, keybindItemSelect
+ };
+
+ public String viewItemAttemptID = null;
+ public long viewItemAttemptTime = 0;
+
+ private final String currentProfile = "";
+ private final String currentProfileBackup = "";
+ public final HypixelApi hypixelApi = new HypixelApi();
+
+ private final Map<String, ItemStack> itemstackCache = new HashMap<>();
+
+ private final ExecutorService repoLoaderES = Executors.newSingleThreadExecutor();
+
+ private static String GIT_COMMITS_URL;
+
+ // TODO: private final Map<String, NeuItem>
+
+ private final Set<NeuRecipe> recipes = new HashSet<>();
+ private final HashMap<String, Set<NeuRecipe>> recipesMap = new HashMap<>();
+ private final HashMap<String, Set<NeuRecipe>> usagesMap = new HashMap<>();
+
+ public String latestRepoCommit = null;
+
+ public File configLocation;
+ public File repoLocation;
+ public File configFile;
+ public HotmInformation hotm;
+
+ public KatSitterOverlay katSitterOverlay;
+
+ public CraftingOverlay craftingOverlay;
+
+ public NEUManager(NotEnoughUpdates neu, File configLocation) {
+ this.neu = neu;
+ this.configLocation = configLocation;
+ this.auctionManager = new APIManager(this);
+ this.hotm = new HotmInformation(neu);
+ this.craftingOverlay = new CraftingOverlay(this);
+ this.katSitterOverlay = new KatSitterOverlay();
+
+ GIT_COMMITS_URL = neu.config.hidden.repoCommitsURL;
+
+ gson = new GsonBuilder().setPrettyPrinting().create();
+
+ this.repoLocation = new File(configLocation, "repo");
+ repoLocation.mkdir();
+ }
+
+ public void setCurrentProfile(String currentProfile) {
+ SBInfo.getInstance().currentProfile = currentProfile;
+ }
+
+ public String getCurrentProfile() {
+ return SBInfo.getInstance().currentProfile;
+ }
+
+ public <T> T getJsonFromFile(File file, Class<T> clazz) {
+ try (
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(file),
+ StandardCharsets.UTF_8
+ ))
+ ) {
+ T obj = gson.fromJson(reader, clazz);
+ return obj;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Parses a file in to a JsonObject.
+ */
+ public JsonObject getJsonFromFile(File file) {
+ try (
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(file),
+ StandardCharsets.UTF_8
+ ))
+ ) {
+ JsonObject json = gson.fromJson(reader, JsonObject.class);
+ return json;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public void resetRepo() {
+ try {
+ Utils.recursiveDelete(new File(configLocation, "repo"));
+ } catch (Exception ignored) {
+ }
+ try {
+ new File(configLocation, "currentCommit.json").delete();
+ } catch (Exception ignored) {
+ }
+ }
+
+ /**
+ * Called when the game is first loaded. Compares the local repository to the github repository and handles the
+ * downloading of new/updated files. This then calls the "loadItem" method for every item in the local repository.
+ */
+ public void loadItemInformation() {
/*File repoFile = new File(configLocation, "repo2");
repoFile.mkdirs();
@@ -155,1297 +195,1377 @@ public class NEUManager {
}*/
- repoLoaderES.submit(() -> {
- JDialog dialog = null;
- try {
- if(NotEnoughUpdates.INSTANCE.config.hidden.autoupdate) {
- JOptionPane pane = new JOptionPane("Getting items to download from remote repository.");
- dialog = pane.createDialog("NotEnoughUpdates Remote Sync");
- dialog.setModal(false);
- if(NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true);
-
- if (Display.isActive()) dialog.toFront();
-
- JsonObject currentCommitJSON = getJsonFromFile(new File(configLocation, "currentCommit.json"));
-
- latestRepoCommit = null;
- try(Reader inReader = new InputStreamReader(new URL(GIT_COMMITS_URL).openStream())) {
- JsonObject commits = gson.fromJson(inReader, JsonObject.class);
- latestRepoCommit = commits.get("sha").getAsString();
- } catch (Exception e) {
- e.printStackTrace();
- }
- if(latestRepoCommit == null || latestRepoCommit.isEmpty()) return;
-
- if(new File(configLocation, "repo").exists() && new File(configLocation, "repo/items").exists()) {
- if(currentCommitJSON != null && currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) {
- dialog.setVisible(false);
- return;
- }
- }
-
- if (Display.isActive()) dialog.toFront();
-
- Utils.recursiveDelete(repoLocation);
- repoLocation.mkdirs();
-
-
- String dlUrl = neu.config.hidden.repoURL;
-
- pane.setMessage("Downloading NEU Master Archive. (DL# >20)");
- dialog.pack();
- if(NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true);
- if (Display.isActive()) dialog.toFront();
-
- File itemsZip = new File(repoLocation, "neu-items-master.zip");
- try {
- itemsZip.createNewFile();
- } catch (IOException e) {
- return;
- }
-
-
- URL url = new URL(dlUrl);
- URLConnection urlConnection = url.openConnection();
- urlConnection.setConnectTimeout(15000);
- urlConnection.setReadTimeout(30000);
-
- try(InputStream is = urlConnection.getInputStream()) {
- FileUtils.copyInputStreamToFile(is, itemsZip);
- } catch (IOException e) {
- dialog.dispose();
- e.printStackTrace();
- System.err.println("Failed to download NEU Repo! Please report this issue to the mod creator");
- return;
- }
- /*try (BufferedInputStream inStream = new BufferedInputStream(urlConnection.getInputStream());
- FileOutputStream fileOutputStream = new FileOutputStream(itemsZip)) {
- byte dataBuffer[] = new byte[1024];
- int bytesRead;
- while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) {
- fileOutputStream.write(dataBuffer, 0, bytesRead);
- }
- } catch (IOException e) {
- dialog.dispose();
- return;
- }*/
-
- pane.setMessage("Unzipping NEU Master Archive.");
- dialog.pack();
- //dialog.setVisible(true);
- if (Display.isActive()) dialog.toFront();
-
- unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath());
-
- if(currentCommitJSON == null || !currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) {
- JsonObject newCurrentCommitJSON = new JsonObject();
- newCurrentCommitJSON.addProperty("sha", latestRepoCommit);
- try {
- writeJson(newCurrentCommitJSON, new File(configLocation, "currentCommit.json"));
- } catch (IOException e) {
- }
- }
- }
- } catch(Exception e) {
- e.printStackTrace();
- } finally {
- if(dialog != null) dialog.dispose();
- }
-
- File items = new File(repoLocation, "items");
- if(items.exists()) {
- File[] itemFiles = new File(repoLocation, "items").listFiles();
- if(itemFiles != null) {
- for(File f : itemFiles) {
- String internalname = f.getName().substring(0, f.getName().length()-5);
- synchronized(itemMap) {
- if(!itemMap.keySet().contains(internalname)) {
- loadItem(internalname);
- }
- }
- }
- }
- }
-
- try {
- Constants.reload();
- } catch(Exception e) {
- e.printStackTrace();
- }
- });
-
- File items = new File(repoLocation, "items");
- if(items.exists()) {
- File[] itemFiles = new File(repoLocation, "items").listFiles();
- if(itemFiles != null) {
- for(File f : itemFiles) {
- String internalname = f.getName().substring(0, f.getName().length()-5);
- synchronized(itemMap) {
- if(!itemMap.keySet().contains(internalname)) {
- loadItem(internalname);
- }
- }
- }
- }
- }
-
- try {
- Constants.reload();
- } catch(Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Loads the item in to the itemMap and also stores various words associated with this item
- * in to titleWordMap and loreWordMap. These maps are used in the searching algorithm.
- * @param internalName
- */
- public void loadItem(String internalName) {
- itemstackCache.remove(internalName);
- try {
- JsonObject json = getJsonFromFile(new File(new File(repoLocation, "items"), internalName + ".json"));
- if(json == null) {
- return;
- }
-
- if(json.get("itemid") == null) return;
-
- String itemid = json.get("itemid").getAsString();
- Item mcitem = Item.getByNameOrId(itemid);
- if(mcitem != null) {
- itemid = mcitem.getRegistryName();
- }
- json.addProperty("itemid", itemid);
-
- itemMap.put(internalName, json);
-
- if(json.has("recipe")) {
- synchronized(usagesMap) {
- JsonObject recipe = json.get("recipe").getAsJsonObject();
-
- 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();
- if(itemS != null && itemS.split(":").length == 2) {
- itemS = itemS.split(":")[0];
- }
-
- if(!usagesMap.containsKey(itemS)) {
- usagesMap.put(itemS, new HashSet<>());
- }
- usagesMap.get(itemS).add(internalName);
- }
- }
- }
-
- if(json.has("displayname")) {
- synchronized(titleWordMap) {
- int wordIndex=0;
- for(String str : json.get("displayname").getAsString().split(" ")) {
- str = clean(str);
- if(!titleWordMap.containsKey(str)) {
- titleWordMap.put(str, new HashMap<>());
- }
- if(!titleWordMap.get(str).containsKey(internalName)) {
- titleWordMap.get(str).put(internalName, new ArrayList<>());
- }
- titleWordMap.get(str).get(internalName).add(wordIndex);
- wordIndex++;
- }
- }
- }
-
- if(json.has("lore")) {
- synchronized(loreWordMap) {
- int wordIndex=0;
- for(JsonElement element : json.get("lore").getAsJsonArray()) {
- for(String str : element.getAsString().split(" ")) {
- str = clean(str);
- if(!loreWordMap.containsKey(str)) {
- loreWordMap.put(str, new HashMap<>());
- }
- if(!loreWordMap.get(str).containsKey(internalName)) {
- loreWordMap.get(str).put(internalName, new ArrayList<>());
- }
- loreWordMap.get(str).get(internalName).add(wordIndex);
- wordIndex++;
- }
- }
- }
- }
- } catch(Exception e) {
- synchronized(loreWordMap) {
- System.out.println("loreWordMap is : " + loreWordMap);
- }
- synchronized(titleWordMap) {
- System.out.println("titleWordMap is : " + titleWordMap);
- }
- System.out.println("internalName is : " + internalName);
- e.printStackTrace();
- }
- }
-
- /**
- * Searches a string for a query. This method is used to mimic the behaviour of the
- * more complex map-based search function. This method is used for the chest-item-search feature.
- */
- public boolean searchString(String toSearch, String query) {
- int lastMatch = -1;
-
- toSearch = clean(toSearch).toLowerCase();
- query = clean(query).toLowerCase();
- String[] splitToSeach = toSearch.split(" ");
- out:
- for(String s : query.split(" ")) {
- for(int i=0; i<splitToSeach.length; i++) {
- if(lastMatch == -1 || lastMatch == i-1) {
- if (splitToSeach[i].startsWith(s)) {
- lastMatch = i;
- continue out;
- }
- }
- }
- return false;
- }
-
- return true;
- }
-
- /**
- * Checks whether an itemstack matches a certain query, following the same rules implemented by the
- * more complex map-based search function.
- */
- public boolean doesStackMatchSearch(ItemStack stack, String query) {
- if(query.startsWith("title:")) {
- query = query.substring(6);
- return searchString(stack.getDisplayName(), query);
- } else if(query.startsWith("desc:")) {
- query = query.substring(5);
- String lore = "";
- NBTTagCompound tag = stack.getTagCompound();
- if(tag != null) {
- NBTTagCompound display = tag.getCompoundTag("display");
- if (display.hasKey("Lore", 9)) {
- NBTTagList list = display.getTagList("Lore", 8);
- for (int i = 0; i < list.tagCount(); i++) {
- lore += list.getStringTagAt(i) + " ";
- }
- }
- }
- return searchString(lore, query);
- } else if(query.startsWith("id:")) {
- query = query.substring(3);
- String internalName = getInternalNameForItem(stack);
- return query.equalsIgnoreCase(internalName);
- } else {
- boolean result = false;
- if(!query.trim().contains(" ")) {
- StringBuilder sb = new StringBuilder();
- for(char c : query.toCharArray()) {
- sb.append(c).append(" ");
- }
- result = result || searchString(stack.getDisplayName(), sb.toString());
- }
- result = result || searchString(stack.getDisplayName(), query);
-
- String lore = "";
- NBTTagCompound tag = stack.getTagCompound();
- if(tag != null) {
- NBTTagCompound display = tag.getCompoundTag("display");
- if (display.hasKey("Lore", 9)) {
- NBTTagList list = display.getTagList("Lore", 8);
- for (int i = 0; i < list.tagCount(); i++) {
- lore += list.getStringTagAt(i) + " ";
- }
- }
- }
-
- result = result || searchString(lore, query);
-
- return result;
- }
- }
-
- /**
- * 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<>();
-
- StringBuilder query2 = new StringBuilder();
- char lastOp = '|';
- for(char c : query.toCharArray()) {
- if(c == '|' || c == '&') {
- if(lastOp == '|') {
- result.addAll(search(query2.toString()));
- } else if(lastOp == '&') {
- result.retainAll(search(query2.toString()));
- }
-
- query2 = new StringBuilder();
- lastOp = c;
- } else {
- query2.append(c);
- }
- }
- if(lastOp == '|') {
- result.addAll(search(query2.toString()));
- } else if(lastOp == '&') {
- result.retainAll(search(query2.toString()));
- }
-
- return result;
- } else {
- return search(query);
- }
- }
-
- /*public TreeMap<ItemStack> searchForStacks(String query, Set<ItemStack> stacks, boolean multi) {
- if(multi) {
- Set<String> result = new HashSet<>();
-
- StringBuilder query2 = new StringBuilder();
- char lastOp = '|';
- for(char c : query.toCharArray()) {
- if(c == '|' || c == '&') {
- if(lastOp == '|') {
- result.addAll(doesStackMatchSearch(stack, query2.toString()));
- } else if(lastOp == '&') {
- result.retainAll(search(query2.toString()));
- }
-
- query2 = new StringBuilder();
- lastOp = c;
- } else {
- query2.append(c);
- }
- }
- if(lastOp == '|') {
- result.addAll(search(query2.toString()));
- } else if(lastOp == '&') {
- result.retainAll(search(query2.toString()));
- }
-
- return result;
- } else {
- return search(query);
- }
- }*/
-
- /**
- * Returns the name of items which match a certain search query.
- */
- public Set<String> search(String query) {
- query = query.trim();
- boolean negate = query.startsWith("!");
- if(negate) query = query.substring(1);
-
- LinkedHashSet<String> results = new LinkedHashSet<>();
- if(query.startsWith("title:")) {
- query = query.substring(6);
- results.addAll(new TreeSet<>(search(query, titleWordMap)));
- } else if(query.startsWith("desc:")) {
- query = query.substring(5);
- results.addAll(new TreeSet<>(search(query, loreWordMap)));
- } else if(query.startsWith("id:")) {
- query = query.substring(3);
- results.addAll(new TreeSet<>(subMapWithKeysThatAreSuffixes(query.toUpperCase(), itemMap).keySet()));
- } else {
- if(!query.trim().contains(" ")) {
- StringBuilder sb = new StringBuilder();
- for(char c : query.toCharArray()) {
- sb.append(c).append(" ");
- }
- results.addAll(new TreeSet<>(search(sb.toString(), titleWordMap)));
- }
- results.addAll(new TreeSet<>(search(query, titleWordMap)));
- results.addAll(new TreeSet<>(search(query, loreWordMap)));
- }
- if(!negate) {
- return results;
- } else {
- Set<String> negatedResults = new HashSet<>();
- for(String internalname : itemMap.keySet()) {
- negatedResults.add(internalname);
- }
- negatedResults.removeAll(results);
- return negatedResults;
- }
- }
-
- /**
- * Splits a search query into an array of strings delimited by a space character. Then, matches the query to
- * the start of words in the various maps (title & lore). The small query does not need to match the whole entry
- * of the map, only the beginning. eg. "ench" and "encha" will both match "enchanted". All sub queries must
- * follow a word matching the previous sub query. eg. "ench po" will match "enchanted pork" but will not match
- * "pork enchanted".
- */
- public Set<String> search(String query, TreeMap<String, HashMap<String, List<Integer>>> wordMap) {
- HashMap<String, List<Integer>> matches = null;
-
- query = clean(query).toLowerCase();
- for(String queryWord : query.split(" ")) {
- HashMap<String, List<Integer>> matchesToKeep = new HashMap<>();
- for(HashMap<String, List<Integer>> wordMatches : subMapWithKeysThatAreSuffixes(queryWord, wordMap).values()) {
- if(wordMatches != null && !wordMatches.isEmpty()) {
- if(matches == null) {
- //Copy all wordMatches to titleMatches
- for(String internalname : wordMatches.keySet()) {
- if(!matchesToKeep.containsKey(internalname)) {
- matchesToKeep.put(internalname, new ArrayList<>());
- }
- matchesToKeep.get(internalname).addAll(wordMatches.get(internalname));
- }
- } else {
- for(String internalname : matches.keySet()) {
- if(wordMatches.containsKey(internalname)) {
- for(Integer newIndex : wordMatches.get(internalname)) {
- if(matches.get(internalname).contains(newIndex-1)) {
- if(!matchesToKeep.containsKey(internalname)) {
- matchesToKeep.put(internalname, new ArrayList<>());
- }
- matchesToKeep.get(internalname).add(newIndex);
- }
- }
- }
- }
- }
- }
- }
- if(matchesToKeep.isEmpty()) return new HashSet<>();
- matches = matchesToKeep;
- }
-
- return matches.keySet();
- }
-
- /**
- * From https://stackoverflow.com/questions/10711494/get-values-in-treemap-whose-string-keys-start-with-a-pattern
- */
- public <T> Map<String, T> subMapWithKeysThatAreSuffixes(String prefix, NavigableMap<String, T> map) {
- if ("".equals(prefix)) return map;
- String lastKey = createLexicographicallyNextStringOfTheSameLength(prefix);
- return map.subMap(prefix, true, lastKey, false);
- }
-
- public String createLexicographicallyNextStringOfTheSameLength(String input) {
- final int lastCharPosition = input.length()-1;
- String inputWithoutLastChar = input.substring(0, lastCharPosition);
- char lastChar = input.charAt(lastCharPosition) ;
- char incrementedLastChar = (char) (lastChar + 1);
- return inputWithoutLastChar+incrementedLastChar;
- }
-
- public JsonObject getJsonFromItemBytes(String item_bytes) {
- try {
- NBTTagCompound tag = CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(item_bytes)));
- //System.out.println(tag.toString());
- return getJsonFromNBT(tag);
- } catch(IOException e) {
- return null;
- }
- }
-
- public String getUUIDFromNBT(NBTTagCompound tag) {
- String uuid = null;
- if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
- NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
-
- if (ea.hasKey("uuid", 8)) {
- uuid = ea.getString("uuid");
- }
- }
- return uuid;
- }
-
- public String getInternalnameFromNBT(NBTTagCompound tag) {
- String internalname = null;
- if(tag != null && tag.hasKey("ExtraAttributes", 10)) {
- NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
-
- if(ea.hasKey("id", 8)) {
- internalname = ea.getString("id").replaceAll(":", "-");
- } else {
- return null;
- }
-
- if("PET".equals(internalname)) {
- String petInfo = ea.getString("petInfo");
- if(petInfo.length() > 0) {
- JsonObject petInfoObject = gson.fromJson(petInfo, JsonObject.class);
- internalname = petInfoObject.get("type").getAsString();
- String tier = petInfoObject.get("tier").getAsString();
- switch(tier) {
- case "COMMON":
- internalname += ";0"; break;
- case "UNCOMMON":
- internalname += ";1"; break;
- case "RARE":
- internalname += ";2"; break;
- case "EPIC":
- internalname += ";3"; break;
- case "LEGENDARY":
- internalname += ";4"; break;
- case "MYTHIC":
- internalname += ";5"; break;
- }
- }
- }
- if("ENCHANTED_BOOK".equals(internalname)) {
- NBTTagCompound enchants = ea.getCompoundTag("enchantments");
-
- for(String enchname : enchants.getKeySet()) {
- internalname = enchname.toUpperCase() + ";" + enchants.getInteger(enchname);
- break;
- }
- }
- }
-
- return internalname;
- }
-
- public String[] getLoreFromNBT(NBTTagCompound tag) {
- String[] lore = new String[0];
- NBTTagCompound display = tag.getCompoundTag("display");
-
- if(display.hasKey("Lore", 9)) {
- NBTTagList list = display.getTagList("Lore", 8);
- lore = new String[list.tagCount()];
- for(int k=0; k<list.tagCount(); k++) {
- lore[k] = list.getStringTagAt(k);
- }
- }
- return lore;
- }
-
- public JsonObject getJsonFromNBT(NBTTagCompound tag) {
- return getJsonFromNBTEntry(tag.getTagList("i", 10).getCompoundTagAt(0));
- }
-
- public JsonObject getJsonFromNBTEntry(NBTTagCompound tag) {
- if(tag.getKeySet().size() == 0) return null;
-
- int id = tag.getShort("id");
- int damage = tag.getShort("Damage");
- int count = tag.getShort("Count");
- tag = tag.getCompoundTag("tag");
-
- if(id == 141) id = 391; //for some reason hypixel thinks carrots have id 141
-
- String internalname = getInternalnameFromNBT(tag);
- if(internalname == null) return null;
-
- NBTTagCompound display = tag.getCompoundTag("display");
- String[] lore = getLoreFromNBT(tag);
-
- Item itemMc = Item.getItemById(id);
- String itemid = "null";
- if(itemMc != null) {
- itemid = itemMc.getRegistryName();
- }
- String displayname = display.getString("Name");
- String[] info = new String[0];
- String clickcommand = "";
-
- JsonObject item = new JsonObject();
- item.addProperty("internalname", internalname);
- item.addProperty("itemid", itemid);
- item.addProperty("displayname", displayname);
-
- if(tag != null && tag.hasKey("ExtraAttributes", 10)) {
- NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
-
- byte[] bytes = null;
- for(String key : ea.getKeySet()) {
- if(key.endsWith("backpack_data") || key.equals("new_year_cake_bag_data")) {
- bytes = ea.getByteArray(key);
- break;
- }
- }
- if(bytes != null) {
- JsonArray bytesArr = new JsonArray();
- for(byte b : bytes) {
- bytesArr.add(new JsonPrimitive(b));
- }
- item.add("item_contents", bytesArr);
- }
- if(ea.hasKey("dungeon_item_level")) {
- item.addProperty("dungeon_item_level", ea.getInteger("dungeon_item_level"));
- }
- }
-
- if(lore != null && lore.length > 0) {
- JsonArray jsonLore = new JsonArray();
- for (String line : lore) {
- jsonLore.add(new JsonPrimitive(line));
- }
- item.add("lore", jsonLore);
- }
-
- item.addProperty("damage", damage);
- if(count > 1) item.addProperty("count", count);
- item.addProperty("nbttag", tag.toString());
-
- return item;
- }
-
- private String clean(String str) {
- return str.replaceAll("(\u00a7.)|[^0-9a-zA-Z ]", "").toLowerCase().trim();
- }
-
- public void showRecipe(JsonObject item) {
- ContainerChest container = null;
- if(Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest)
- container = (ContainerChest) Minecraft.getMinecraft().thePlayer.openContainer;
- if (item.has("recipe") && container != null && container.getLowerChestInventory().getDisplayName().getUnformattedText().equals("Craft Item")) {
- CraftingOverlay.updateItem(item);
- } else if(item.has("useneucraft") && item.get("us