diff options
| author | Moulberry <jjenour@student.unimelb.edu.au> | 2022-03-03 11:03:58 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-03 11:03:58 +0800 |
| commit | 7c6d37b2eb758a13b342b906f0aef88b940bc52a (patch) | |
| tree | 9602a014425b859e3aba98f31f93d6de04521356 /src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java | |
| parent | b11742988dec635b5c5da7c2363803cbfafb37b1 (diff) | |
| parent | db59eba3fd9121c7c0a88363994876c5b582c08c (diff) | |
| download | notenoughupdates-7c6d37b2eb758a13b342b906f0aef88b940bc52a.tar.gz notenoughupdates-7c6d37b2eb758a13b342b906f0aef88b940bc52a.tar.bz2 notenoughupdates-7c6d37b2eb758a13b342b906f0aef88b940bc52a.zip | |
Merge pull request #248 from NotEnoughUpdates/master
NEU 2.1 🙂
Diffstat (limited to 'src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java')
| -rw-r--r-- | src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java | 2900 |
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; - |
