diff --git a/build.gradle.kts b/build.gradle.kts index 78fcf29..a003f1e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ plugins { } group = "dev.meyi.bazaarnotifier" -version = "1.5.0" +version = "1.6.0" java { toolchain.languageVersion.set(JavaLanguageVersion.of(8)) diff --git a/src/main/java/dev/meyi/bn/BazaarNotifier.java b/src/main/java/dev/meyi/bn/BazaarNotifier.java index f496e6b..cf43e45 100644 --- a/src/main/java/dev/meyi/bn/BazaarNotifier.java +++ b/src/main/java/dev/meyi/bn/BazaarNotifier.java @@ -5,6 +5,8 @@ import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.MalformedJsonException; import dev.meyi.bn.commands.BazaarNotifierCommand; import dev.meyi.bn.config.Configuration; import dev.meyi.bn.handlers.ChestTickHandler; @@ -20,7 +22,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.io.Reader; +import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; @@ -39,7 +41,7 @@ public class BazaarNotifier { public static final String MODID = "BazaarNotifier"; - public static final String VERSION = "1.5.0"; + public static final String VERSION = "1.6.0"; public static final String prefix = EnumChatFormatting.GOLD + "[" + EnumChatFormatting.YELLOW + "BN" + EnumChatFormatting.GOLD + "] " + EnumChatFormatting.RESET; @@ -55,7 +57,6 @@ public class BazaarNotifier { public static boolean activeBazaar = true; public static boolean inBazaar = false; - public static boolean inBank = false; public static boolean forceRender = false; public static boolean validApiKey = false; public static boolean apiKeyDisabled = true; @@ -93,15 +94,16 @@ public void preInit(FMLPreInitializationEvent event) { bnDir.mkdirs(); configFile = new File(bnDir, "config.json"); resourcesFile = new File(bnDir, "resources.json"); - String configString = null; + JsonReader configString = null; Gson gson = new Gson(); try { if (configFile.isFile()) { try { - configString = new String(Files.readAllBytes(Paths.get(configFile.getPath()))); + configString = new JsonReader(new StringReader(new String(Files.readAllBytes(Paths.get(configFile.getPath()))))); + configString.setLenient(true); config = gson.fromJson(configString, Configuration.class); config.version = BazaarNotifier.VERSION; - } catch (JsonSyntaxException e) { + } catch (JsonSyntaxException | MalformedJsonException e) { e.printStackTrace(); config = Configuration.createDefaultConfig(); } @@ -112,18 +114,21 @@ public void preInit(FMLPreInitializationEvent event) { try { if (resourcesFile.isFile()) { try { - String resourcesString = new String( - Files.readAllBytes(Paths.get(resourcesFile.getPath()))); - resources = gson.fromJson(resourcesString, JsonObject.class); + JsonReader resourcesReader = new JsonReader(new StringReader(new String( + Files.readAllBytes(Paths.get(resourcesFile.getPath()))))); + resourcesReader.setLenient(true); + resources = gson.fromJson(resourcesReader, JsonObject.class); } catch (JsonSyntaxException | ClassCastException e) { e.printStackTrace(); - Reader reader = new InputStreamReader(Objects.requireNonNull( - BazaarNotifier.class.getResourceAsStream("/resources.json")), StandardCharsets.UTF_8); + JsonReader reader = new JsonReader(new InputStreamReader(Objects.requireNonNull( + BazaarNotifier.class.getResourceAsStream("/resources.json")), StandardCharsets.UTF_8)); + reader.setLenient(true); resources = gson.fromJson(reader, JsonObject.class); } } else { - Reader reader = new InputStreamReader(Objects.requireNonNull( - BazaarNotifier.class.getResourceAsStream("/resources.json")), StandardCharsets.UTF_8); + JsonReader reader = new JsonReader(new InputStreamReader(Objects.requireNonNull( + BazaarNotifier.class.getResourceAsStream("/resources.json")), StandardCharsets.UTF_8)); + reader.setLenient(true); resources = gson.fromJson(reader, JsonObject.class); } } catch (IOException e) { diff --git a/src/main/java/dev/meyi/bn/handlers/ChestTickHandler.java b/src/main/java/dev/meyi/bn/handlers/ChestTickHandler.java index d6d81a4..d32421c 100644 --- a/src/main/java/dev/meyi/bn/handlers/ChestTickHandler.java +++ b/src/main/java/dev/meyi/bn/handlers/ChestTickHandler.java @@ -162,23 +162,6 @@ public void onChestTick(TickEvent e) { chest.getDisplayName().getUnformattedText()); } } - } else if (BazaarNotifier.inBank - && Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - IInventory chest = ReflectionHelper.getLowerChestInventory( - (GuiChest) Minecraft.getMinecraft().currentScreen); - if (chest == null) { - return; - } - String chestName = chest.getDisplayName().getUnformattedText().toLowerCase(); - if (chestName.contains("personal bank account") && !chestName.contains("upgrade")) { - BankCalculator.extractBankFromItemDescription(chest, false); - } else if (chestName.contains("co-op bank account") && !chestName.contains("upgrade")) { - BankCalculator.extractBankFromItemDescription(chest, true); - } else if (chestName.equals("bank deposit") || chestName.equals("bank withdrawal")) { - BankCalculator.isOnDangerousPage = true; - BankCalculator.purseInBank = BankCalculator.getPurse(); - } - } else if (!BazaarNotifier.inBazaar) { // if you aren't in the bazaar, this should be clear ChestTickHandler.lastScreenDisplayName = ""; } diff --git a/src/main/java/dev/meyi/bn/handlers/EventHandler.java b/src/main/java/dev/meyi/bn/handlers/EventHandler.java index 4f12250..f8cca09 100644 --- a/src/main/java/dev/meyi/bn/handlers/EventHandler.java +++ b/src/main/java/dev/meyi/bn/handlers/EventHandler.java @@ -38,6 +38,10 @@ public void bazaarChatHandler(ClientChatReceivedEvent e) { } String message = StringUtils.stripControlCodes(e.message.getUnformattedText()); + if (message.startsWith("[Bazaar] Claimed") || message.startsWith("[Bazaar] Bought") || message.startsWith("[Bazaar] Sold")) { + BankCalculator.evaluate(message); + } + if (message.startsWith("Buy Order Setup!") || message.startsWith("Sell Offer Setup!") || message.startsWith("[Bazaar] Buy Order Setup!") || message.startsWith( "[Bazaar] Sell Offer Setup!")) { @@ -45,7 +49,6 @@ public void bazaarChatHandler(ClientChatReceivedEvent e) { BazaarNotifier.bazaarConv.inverse().get(message.split("x ", 2)[1].split(" for ")[0])) && productVerify[1].equals(message.split("! ")[1].split(" for ")[0])) { BazaarNotifier.orders.add(verify); - BankCalculator.getBazaarProfit(); verify = null; productVerify = new String[2]; } @@ -120,11 +123,7 @@ public void bazaarChatHandler(ClientChatReceivedEvent e) { } } } else if (message.startsWith("Bazaar! Claimed ") || message.startsWith("[Bazaar] Claimed")) { - ChestTickHandler.lastScreenDisplayName = ""; // Force update on next tick - // ChestTickHandler.updateBazaarOrders( - // ((GuiChest) Minecraft.getMinecraft().currentScreen).lowerChestInventory); - } else if (message.startsWith("Welcome to Hypixel SkyBlock!")) { - BankCalculator.getPurse(); + ChestTickHandler.lastScreenDisplayName = ""; } else if (message.startsWith("Your new API key is")) { String apiKey = message.split("key is ")[1]; try { @@ -157,10 +156,8 @@ public void menuOpenedEvent(GuiOpenEvent e) { if (e.gui instanceof GuiChest && (BazaarNotifier.validApiKey || BazaarNotifier.apiKeyDisabled)) { IInventory chest = ReflectionHelper.getLowerChestInventory((GuiChest) e.gui); - if (chest == null) { - return; - } - if ((chest.hasCustomName() && ( + + if (chest != null && ((chest.hasCustomName() && ( StringUtils.stripControlCodes(chest.getDisplayName().getUnformattedText()) .startsWith("Bazaar") || StringUtils.stripControlCodes( chest.getDisplayName().getUnformattedText()) @@ -168,66 +165,17 @@ public void menuOpenedEvent(GuiOpenEvent e) { chest.getDisplayName().getUnformattedText()) .matches("Confirm (Buy|Sell) (Order|Offer)")) || StringUtils.stripControlCodes( chest.getDisplayName().getUnformattedText()).contains("Bazaar")) - || BazaarNotifier.forceRender) { - if (!BazaarNotifier.inBazaar) { - BazaarNotifier.inBazaar = true; - if (!BankCalculator.orderWait) { - BankCalculator.purseLast = BankCalculator.getPurse(); - } - } + || BazaarNotifier.forceRender)) { + BazaarNotifier.inBazaar = true; } - } else if (e.gui instanceof GuiEditSign) { + } else if (e.gui == null || e.gui instanceof GuiEditSign) { BazaarNotifier.inBazaar = false; } - - if (e.gui == null && BazaarNotifier.inBazaar) { - BazaarNotifier.inBazaar = false; - Thread t = new Thread(() -> { - BankCalculator.orderWait = true; - try { - Thread.sleep(1000); - BankCalculator.getBazaarProfit(); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } - BankCalculator.orderWait = false; - }); - t.start(); - } - - if (e.gui == null && BazaarNotifier.inBank) { - BazaarNotifier.inBank = false; - } - - if (e.gui == null && BankCalculator.isOnDangerousPage) { - BankCalculator.isOnDangerousPage = false; - Thread t = new Thread(() -> { - try { - Thread.sleep(1000); - BankCalculator.bank += (BankCalculator.purseInBank - BankCalculator.getPurse()); - } catch (InterruptedException ex) { - ex.printStackTrace(); - } - }); - t.start(); - - } - - if (e.gui instanceof GuiChest) { - IInventory chest = ReflectionHelper.getLowerChestInventory((GuiChest) e.gui); - BazaarNotifier.inBank = - chest != null && chest.hasCustomName() && StringUtils.stripControlCodes( - chest.getDisplayName().getUnformattedText()).contains("Bank") - && !StringUtils.stripControlCodes(chest.getDisplayName().getUnformattedText()) - .contains("Bank Account Upgrades"); - } } @SubscribeEvent public void disconnectEvent(ClientDisconnectionFromServerEvent e) { BazaarNotifier.inBazaar = false; - BazaarNotifier.inBank = false; - BankCalculator.isOnDangerousPage = false; } @SubscribeEvent diff --git a/src/main/java/dev/meyi/bn/json/Exchange.java b/src/main/java/dev/meyi/bn/json/Exchange.java new file mode 100644 index 0000000..c531aa4 --- /dev/null +++ b/src/main/java/dev/meyi/bn/json/Exchange.java @@ -0,0 +1,72 @@ +package dev.meyi.bn.json; + +import dev.meyi.bn.BazaarNotifier; +import dev.meyi.bn.json.Order.OrderType; +import dev.meyi.bn.modules.calc.CraftingCalculator; +import java.util.Map; + +public class Exchange { + + private final String productId; + private final double pricePerUnit; + private int amount; + private final OrderType type; + + private final Map craftingResources; + + public Exchange(OrderType type, String productId, double pricePerUnit, int amount) { + this.type = type; + this.productId = productId; + this.pricePerUnit = pricePerUnit; + this.amount = amount; + + if (canCraft()) { + craftingResources = CraftingCalculator.getMaterialsMap(productId); + } else { + craftingResources = null; + } + } + + public String getProductId() { + return productId; + } + + public Map getCraftingResources() { + return craftingResources; + } + + public double getPricePerUnit() { + return pricePerUnit; + } + + public int getAmount() { + return amount; + } + + public void removeAmount(int remove) { + this.amount -= remove; + } + + public void addAmount(int add) { + this.amount += add; + } + + public OrderType getType() { + return type; + } + + public boolean matchesOrder(Exchange exchange) { + return this.type != exchange.type && this.productId.equals(exchange.productId); + } + + public boolean canCraft() { + return BazaarNotifier.enchantCraftingList.getAsJsonObject("other").has(productId) + && type == OrderType.SELL; + } + + @Override + public boolean equals(Object obj) { + return (obj instanceof Exchange) && this.pricePerUnit == ((Exchange) obj).pricePerUnit + && this.productId.equals(((Exchange) obj).productId); + } +} diff --git a/src/main/java/dev/meyi/bn/modules/calc/BankCalculator.java b/src/main/java/dev/meyi/bn/modules/calc/BankCalculator.java index 2f00ca5..c9c1c97 100644 --- a/src/main/java/dev/meyi/bn/modules/calc/BankCalculator.java +++ b/src/main/java/dev/meyi/bn/modules/calc/BankCalculator.java @@ -1,166 +1,180 @@ package dev.meyi.bn.modules.calc; - -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; import dev.meyi.bn.BazaarNotifier; -import dev.meyi.bn.json.Order; -import java.util.Collection; +import dev.meyi.bn.json.Exchange; +import dev.meyi.bn.json.Order.OrderType; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -import java.util.stream.Collectors; -import net.minecraft.client.Minecraft; -import net.minecraft.inventory.IInventory; -import net.minecraft.scoreboard.Score; -import net.minecraft.scoreboard.ScoreObjective; -import net.minecraft.scoreboard.ScorePlayerTeam; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.util.StringUtils; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class BankCalculator { - public static double purseLast = 0; - public static boolean orderWait = false; - public static double purseInBank = 0; //fix for personal bank - public static boolean isOnDangerousPage = false; //a page that can instantly close the bank gui without opening it again - public static double bank = 0; - private static double bazaarProfit2 = 0; - private static double purseBackup = 0; - private static boolean personalBankInitialised = false; - private static boolean coopBankInitialised = false; - private static boolean purseInitialised = false; - private static double moneyOnStartup = 0; - - public static double getBazaarProfit() { - bazaarProfit2 += getPurse() - purseLast; - purseLast = getPurse(); - return bazaarProfit2; - } + private static boolean changed = false; + private static final List orderHistory = new ArrayList<>(); + private static double calculatedProfit = 0; + + public static synchronized double getBazaarProfit() { + if (changed) { + for (int i = orderHistory.size() - 1; i >= 0; i--) { + if (orderHistory.get(i).getAmount() != 0) { + for (int j = orderHistory.size() - 1; j >= 0; j--) { + if (orderHistory.get(j).getAmount() != 0 && orderHistory.get(i) + .matchesOrder(orderHistory.get(j))) { + Exchange buy, sell; + int buyIndex, sellIndex; + + if (orderHistory.get(i).getType() == OrderType.BUY) { + buy = orderHistory.get((buyIndex = i)); + sell = orderHistory.get((sellIndex = j)); + } else { + buy = orderHistory.get((buyIndex = j)); + sell = orderHistory.get((sellIndex = i)); + } + + if (buy.getAmount() >= sell.getAmount()) { + calculatedProfit += + buy.getAmount() * (sell.getPricePerUnit() * .99 - buy.getPricePerUnit()); + buy.removeAmount(buy.getAmount()); + sell.removeAmount(buy.getAmount()); + } else { + calculatedProfit += + sell.getAmount() * (sell.getPricePerUnit() * .99 - buy.getPricePerUnit()); + sell.removeAmount(sell.getAmount()); + buy.removeAmount(sell.getAmount()); + } + + if ((buyIndex == i && buy.getAmount() == 0) || + (sellIndex == i && sell.getAmount() == 0)) { + break; + } + } + } + } + } - public static double calculateProfit() { - return getPurse() + moneyStoredInBuyOrders() + moneyStoredInSellOffers() + bank - - moneyOnStartup; - } + orderHistory.removeIf(v -> v.getAmount() == 0); + + craftingLoop: + for (int i = orderHistory.size() - 1; i >= 0; i--) { + if (orderHistory.get(i).getAmount() != 0 && orderHistory.get(i).canCraft()) { + Map craftingResources = orderHistory.get(i).getCraftingResources(); + Map> availableResources = new HashMap<>(); + craftingResources.keySet().forEach(key -> availableResources.put(key, new ArrayList<>())); + for (Exchange exchange : orderHistory) { + if (craftingResources.containsKey(exchange.getProductId())) { + availableResources.get(exchange.getProductId()).add(exchange); + } + } + int maxCrafting = orderHistory.get(i).getAmount(); - public static double moneyStoredInSellOffers() { - if (BazaarNotifier.orders.size() != 0) { - double orderWorth = 0; - for (int i = 0; i < BazaarNotifier.orders.size(); i++) { - if (BazaarNotifier.orders.get(i).type.equals(Order.OrderType.SELL)) { - orderWorth += BazaarNotifier.orders.get(i).orderValue; - } - } - return orderWorth; - } - return 0; - } + for (Entry> entry : availableResources.entrySet()) { + int amountAvailable = 0; + for (Exchange e : entry.getValue()) { + amountAvailable += e.getAmount(); + } + + int craftCost = craftingResources.get(entry.getKey()); + + if (amountAvailable < craftCost) { + break craftingLoop; + } else { + maxCrafting = Math.min(maxCrafting, amountAvailable / craftCost); + } + } - public static double moneyStoredInBuyOrders() { - if (BazaarNotifier.orders.size() != 0) { - double orderWorth = 0; - for (int i = 0; i < BazaarNotifier.orders.size(); i++) { - if (BazaarNotifier.orders.get(i).type.equals(Order.OrderType.BUY)) { - orderWorth += BazaarNotifier.orders.get(i).orderValue; + double buyValue = 0; + + if (maxCrafting > 0) { + for (String key : availableResources.keySet()) { + int valueToRemove = maxCrafting * craftingResources.get(key); + for (Exchange e : availableResources.get(key)) { + if (e.getAmount() >= valueToRemove) { + buyValue += valueToRemove * e.getPricePerUnit(); + e.removeAmount(valueToRemove); + valueToRemove = 0; + } else { + buyValue += e.getAmount() * e.getPricePerUnit(); + valueToRemove -= e.getAmount(); + e.removeAmount(e.getAmount()); + } + } + } + } + orderHistory.get(i).removeAmount(maxCrafting); + calculatedProfit += + ((double) maxCrafting * orderHistory.get(i).getPricePerUnit()) * .99 - buyValue; } } - return orderWorth; - } - return 0; - } - public static double getPurse() { - double ps = getPurseFromSidebar(); - if (ps == -1) { - return purseBackup; - } else { - if (!purseInitialised) { - moneyOnStartup += ps; - purseInitialised = true; - } - return ps; + orderHistory.removeIf(v -> v.getAmount() == 0); } + + return calculatedProfit; } - private static double getPurseFromSidebar() { - if (Minecraft.getMinecraft().theWorld == null) { - return -1; - } - Scoreboard scoreboard = Minecraft.getMinecraft().theWorld.getScoreboard(); - if (scoreboard == null) { - return -1; + public static synchronized void evaluate(String message) { + String productId; + double pricePerUnit; + int amount; + OrderType type; + + Matcher m; + + if ((m = sellOffer.matcher(message)).find()) { + type = OrderType.SELL; + amount = Integer.parseInt(m.group(1).replaceAll("[,.]", "")); + pricePerUnit = Double.parseDouble(m.group(3).replaceAll(",", "")); + } else if ((m = instantSell.matcher(message)).find()) { + type = OrderType.SELL; + amount = Integer.parseInt(m.group(1).replaceAll("[,.]", "")); + double coins = Double.parseDouble(m.group(3).replaceAll(",", "")); + pricePerUnit = coins / (double) amount; + } else if ((m = buyOrder.matcher(message)).find()) { + type = OrderType.BUY; + amount = Integer.parseInt(m.group(1).replaceAll("[,.]", "")); + pricePerUnit = Double.parseDouble(m.group(3).replaceAll(",", "")); + } else if ((m = instantBuy.matcher(message)).find()) { + type = OrderType.BUY; + amount = Integer.parseInt(m.group(1).replaceAll("[,.]", "")); + double coins = Double.parseDouble(m.group(3).replaceAll(",", "")); + pricePerUnit = coins / (double) amount; + } else { + return; } - ScoreObjective objective = scoreboard.getObjectiveInDisplaySlot(1); - if (objective == null) { - return -1; - } + productId = BazaarNotifier.bazaarConv.inverse().get(m.group(2)); - Collection scores = scoreboard.getSortedScores(objective); - List list = scores.stream() - .filter(input -> input != null && input.getPlayerName() != null && !input.getPlayerName() - .startsWith("#")).collect(Collectors.toList()); + Exchange e = new Exchange(type, productId, pricePerUnit, amount); - if (list.size() > 15) { - scores = Lists.newArrayList(Iterables.skip(list, scores.size() - 15)); + int index; + if ((index = orderHistory.indexOf(e)) != -1) { + orderHistory.get(index).addAmount(amount); } else { - scores = list; + orderHistory.add(e); } - for (Score score : scores) { - ScorePlayerTeam team = scoreboard.getPlayersTeam(score.getPlayerName()); - if (ScorePlayerTeam.formatPlayerName(team, score.getPlayerName()).contains("Purse")) { - if (ScorePlayerTeam.formatPlayerName(team, score.getPlayerName()) - .contains(")")) {// coins get added to your purse - String purse = StringUtils - .stripControlCodes(ScorePlayerTeam.formatPlayerName(team, score.getPlayerName())); - int i = purse.indexOf("("); - String s = purse.substring(i + 1, purse.length() - 1); - purse = purse.replace(s, "").replaceAll("[^0-9 .]", ""); - purseBackup = Float.parseFloat(purse); - return purseBackup; - } else { - String purse = StringUtils - .stripControlCodes(ScorePlayerTeam.formatPlayerName(team, score.getPlayerName())) - .replaceAll("[^0-9 +.]", ""); - purseBackup = Float.parseFloat(purse); - return purseBackup; - } - } - } - - return -1; - } - - public static void extractBankFromItemDescription(IInventory chest, boolean isCoop) { - // TODO: Test co-op check - if (chest != null) { - if (chest.getStackInSlot(11) != null) { - if (chest.getStackInSlot(11).getDisplayName().toLowerCase().contains("deposit coins")) { - if ((!isCoop && !personalBankInitialised) || (isCoop && !coopBankInitialised)) { - double p = Double.parseDouble(StringUtils.stripControlCodes( - chest.getStackInSlot(11).getTagCompound().getCompoundTag("display") - .getTagList("Lore", 8) - .getStringTagAt(0)).split("balance: ")[1].replaceAll(",", "")); - bank += p; - moneyOnStartup += p; - if (!isCoop) { - personalBankInitialised = true; - } else { - coopBankInitialised = true; - } - } - - } - } - } + changed = type == OrderType.SELL; // Profit is only changed if something is sold } - public static void reset() { - moneyOnStartup = getPurse() + moneyStoredInBuyOrders() + moneyStoredInSellOffers() + bank; - bazaarProfit2 = 0; + public static synchronized void reset() { + orderHistory.clear(); + calculatedProfit = 0; } + private static final Pattern sellOffer = Pattern.compile( + "\\[Bazaar] Claimed .* coins from selling (.*)x (.*) at (.*) each!"); + private static final Pattern buyOrder = Pattern.compile( + "\\[Bazaar] Claimed (.*)x (.*) worth .* coins bought for (.*) each!"); + private static final Pattern instantSell = Pattern.compile( + "\\[Bazaar] Sold (.*)x (.*) for (.*) coins!"); + private static final Pattern instantBuy = Pattern.compile( + "\\[Bazaar] Bought (.*)x (.*) for (.*) coins!"); } \ No newline at end of file diff --git a/src/main/java/dev/meyi/bn/modules/calc/CraftingCalculator.java b/src/main/java/dev/meyi/bn/modules/calc/CraftingCalculator.java index 3bc9b5f..64bd1b9 100644 --- a/src/main/java/dev/meyi/bn/modules/calc/CraftingCalculator.java +++ b/src/main/java/dev/meyi/bn/modules/calc/CraftingCalculator.java @@ -1,5 +1,6 @@ package dev.meyi.bn.modules.calc; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import dev.meyi.bn.BazaarNotifier; import dev.meyi.bn.modules.module.CraftingModule; @@ -8,6 +9,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -150,6 +152,16 @@ public static String[] getEnchantCraft(String itemName) { } + public static Map getMaterialsMap(String productId) { + JsonArray materialsArray = BazaarNotifier.enchantCraftingList.getAsJsonObject("other") + .getAsJsonObject(productId).getAsJsonArray("material"); + Map materials = new HashMap<>(); + for (int i = 0; i < materialsArray.size(); i += 2) { + materials.put(materialsArray.get(i).getAsString(), materialsArray.get(i+1).getAsInt()); + } + return materials; + } + public static void getUnlockedRecipes() { try { List s = Utils.unlockedRecipes(); diff --git a/src/main/java/dev/meyi/bn/modules/module/BankModule.java b/src/main/java/dev/meyi/bn/modules/module/BankModule.java index e019bdc..54f0116 100644 --- a/src/main/java/dev/meyi/bn/modules/module/BankModule.java +++ b/src/main/java/dev/meyi/bn/modules/module/BankModule.java @@ -33,19 +33,17 @@ protected void draw() { LinkedHashMap header = new LinkedHashMap<>(); header.put("Bank Module (Experimental)", Color.GRAY); items.add(header); - LinkedHashMap message = new LinkedHashMap<>(); - message.put("Total profit: ", Color.CYAN); - message.put(BazaarNotifier.df.format((int) BankCalculator.calculateProfit()), Color.MAGENTA); - items.add(message); + LinkedHashMap message2 = new LinkedHashMap<>(); - message2.put("Bazaar profit: ", Color.CYAN); + message2.put("Bazaar Profit: ", Color.CYAN); message2.put(BazaarNotifier.df.format(BankCalculator.getBazaarProfit()), Color.MAGENTA); items.add(message2); + int lines = 2; int longestXString = RenderUtils.drawColorfulParagraph(items, x, y, scale); boundsX = x + longestXString; boundsY = (int) ( - y + (Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT * 3) * scale + 3 * scale - 2); + y + (Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT * lines) * scale + lines * scale - 2); } @Override diff --git a/src/main/java/dev/meyi/bn/modules/module/NotificationModule.java b/src/main/java/dev/meyi/bn/modules/module/NotificationModule.java index 5dce35c..e850e0c 100644 --- a/src/main/java/dev/meyi/bn/modules/module/NotificationModule.java +++ b/src/main/java/dev/meyi/bn/modules/module/NotificationModule.java @@ -5,16 +5,13 @@ import dev.meyi.bn.json.Order; import dev.meyi.bn.modules.Module; import dev.meyi.bn.modules.ModuleName; +import dev.meyi.bn.utilities.Defaults; import dev.meyi.bn.utilities.ReflectionHelper; import dev.meyi.bn.utilities.RenderUtils; -import dev.meyi.bn.utilities.Defaults; import java.awt.Color; -import java.text.NumberFormat; -import java.text.ParseException; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; -import java.util.regex.Pattern; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; @@ -158,8 +155,11 @@ public void highlightOrder(int hoveredText) { if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && BazaarNotifier.inBazaar && BazaarNotifier.activeBazaar) { - IInventory chest = ReflectionHelper.getLowerChestInventory((GuiChest) Minecraft.getMinecraft().currentScreen); - if (chest == null) return; + IInventory chest = ReflectionHelper.getLowerChestInventory( + (GuiChest) Minecraft.getMinecraft().currentScreen); + if (chest == null) { + return; + } String chestName = chest.getDisplayName().getUnformattedText().toLowerCase(); if (chestName.contains("bazaar orders")) { @@ -189,18 +189,23 @@ public void highlightOrder(int hoveredText) { lore.add(StringUtils.stripControlCodes(lorePreFilter.getStringTagAt(k))); } - int amount = Integer.parseInt(lore.get(2).toLowerCase().split("amount: ")[1].replaceAll("[x,.]", "")); + int amount = Integer.parseInt( + lore.get(2).toLowerCase().split("amount: ")[1].replaceAll("[x,.]", "")); String ppu = lore.get(3).equals("") ? lore.get(4) : lore.get(5); ppu = ppu.toLowerCase().replace("price per unit: ", "").replace(" coins", "") .replaceAll(",", ""); - double pricePerUnit = Double.parseDouble(ppu); - Order o = new Order(product, type, pricePerUnit, amount); + if (!ppu.contains("expired!")) { + + double pricePerUnit = Double.parseDouble(ppu); + + Order o = new Order(product, type, pricePerUnit, amount); - for (int i = 0; i < BazaarNotifier.orders.size(); i++) { - if (o.matches(BazaarNotifier.orders.get(hoveredText))) { - drawOnSlot(chest.getSizeInventory(), j, 0xff00ff00); + for (int i = 0; i < BazaarNotifier.orders.size(); i++) { + if (o.matches(BazaarNotifier.orders.get(hoveredText))) { + drawOnSlot(chest.getSizeInventory(), j, 0xff00ff00); + } } } } diff --git a/src/main/java/dev/meyi/bn/utilities/RenderUtils.java b/src/main/java/dev/meyi/bn/utilities/RenderUtils.java index 841445b..c0f75d5 100644 --- a/src/main/java/dev/meyi/bn/utilities/RenderUtils.java +++ b/src/main/java/dev/meyi/bn/utilities/RenderUtils.java @@ -66,18 +66,20 @@ public static void chatNotification(Order order, String notification) { (notification.equalsIgnoreCase("REVIVED") ? EnumChatFormatting.GREEN : order.type.equals(Order.OrderType.BUY) ? EnumChatFormatting.DARK_PURPLE : EnumChatFormatting.BLUE); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - messageColor + order.type.longName - + EnumChatFormatting.GRAY + " for " - + messageColor + BazaarNotifier.dfNoDecimal - .format(order.startAmount) - + EnumChatFormatting.GRAY + "x " + messageColor - + order.product - + EnumChatFormatting.YELLOW - + " " + notification + " " + EnumChatFormatting.GRAY + "(" - + messageColor + BazaarNotifier.df.format(order.pricePerUnit) - + EnumChatFormatting.GRAY + ")" - )); + if (Minecraft.getMinecraft().thePlayer != null) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + messageColor + order.type.longName + + EnumChatFormatting.GRAY + " for " + + messageColor + BazaarNotifier.dfNoDecimal + .format(order.startAmount) + + EnumChatFormatting.GRAY + "x " + messageColor + + order.product + + EnumChatFormatting.YELLOW + + " " + notification + " " + EnumChatFormatting.GRAY + "(" + + messageColor + BazaarNotifier.df.format(order.pricePerUnit) + + EnumChatFormatting.GRAY + ")" + )); + } } public static void drawCenteredString(String text, int x, int y, int color, float moduleScale) { diff --git a/src/main/java/dev/meyi/bn/utilities/Utils.java b/src/main/java/dev/meyi/bn/utilities/Utils.java index 1947c50..9e72e85 100644 --- a/src/main/java/dev/meyi/bn/utilities/Utils.java +++ b/src/main/java/dev/meyi/bn/utilities/Utils.java @@ -6,8 +6,8 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSyntaxException; +import com.google.gson.stream.JsonReader; import dev.meyi.bn.BazaarNotifier; -import dev.meyi.bn.json.Order; import dev.meyi.bn.json.resp.BazaarResponse; import java.io.BufferedReader; import java.io.File; @@ -22,15 +22,12 @@ import java.util.Set; import java.util.regex.Pattern; import net.minecraft.client.Minecraft; -import net.minecraft.util.ChatComponentText; -import net.minecraft.util.EnumChatFormatting; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; -import org.lwjgl.opengl.GL11; public class Utils { @@ -41,7 +38,7 @@ public class Utils { public static BazaarResponse getBazaarData() throws IOException { Gson gson = new Gson(); - HttpClient client = HttpClientBuilder.create().build(); + CloseableHttpClient client = HttpClientBuilder.create().build(); String apiBit = ""; if (!BazaarNotifier.apiKeyDisabled) { apiBit = "?key=" + BazaarNotifier.config.api; @@ -50,10 +47,13 @@ public static BazaarResponse getBazaarData() throws IOException { "https://api.hypixel.net/skyblock/bazaar" + apiBit); HttpResponse response = client.execute(request); + String result = IOUtils.toString(new BufferedReader (new InputStreamReader( response.getEntity().getContent()))); + client.close(); + if (isJSONValid(result)) { return gson.fromJson(result, BazaarResponse.class); } else { @@ -67,7 +67,7 @@ public static List unlockedRecipes() throws IOException { if (!BazaarNotifier.config.api.isEmpty() && (BazaarNotifier.validApiKey || (BazaarNotifier.validApiKey = validateApiKey()))) { - HttpClient client = HttpClientBuilder.create().build(); + CloseableHttpClient client = HttpClientBuilder.create().build(); if (playerUUID.equals("")) { HttpGet request = new HttpGet( "https://api.mojang.com/users/profiles/minecraft/" + Minecraft.getMinecraft() @@ -89,9 +89,11 @@ public static List unlockedRecipes() throws IOException { + playerUUID); HttpResponse response = client.execute(request); - String _results = IOUtils - .toString(new BufferedReader(new InputStreamReader(response.getEntity().getContent()))); - JsonObject results = gson.fromJson(_results, JsonObject.class); + JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(response.getEntity().getContent()))); + jsonReader.setLenient(true); + JsonObject results = gson.fromJson(jsonReader, JsonObject.class); + + client.close(); int profileIndex = 0; if (!results.get("success").getAsBoolean() || !results.has("profiles")) { return null; @@ -151,9 +153,9 @@ public static boolean validateApiKey(String key) throws IOException { if (uuidMatcher.matcher(key).find()) { try { if (gson.fromJson(IOUtils.toString(new BufferedReader - (new InputStreamReader(HttpClientBuilder.create().build().execute(new HttpGet( - "https://api.hypixel.net/key?key=" + key)).getEntity() - .getContent()))), JsonObject.class).getAsJsonObject().get("success") + (new InputStreamReader(HttpClientBuilder.create().build().execute(new HttpGet( + "https://api.hypixel.net/key?key=" + key)).getEntity() + .getContent()))), JsonObject.class).getAsJsonObject().get("success") .getAsBoolean()) { return true; } else { @@ -179,22 +181,25 @@ public static boolean validateApiKey() throws IOException { public static void updateResources() throws IOException { Gson gson = new Gson(); - String result; HttpGet request; HttpResponse response; - HttpClient client = HttpClientBuilder.create().build(); + CloseableHttpClient client = HttpClientBuilder.create().build(); request = new HttpGet(BazaarNotifier.RESOURCE_LOCATION); response = client.execute(request); - result = IOUtils - .toString(new BufferedReader(new InputStreamReader(response.getEntity().getContent()))); + + JsonReader jsonReader = new JsonReader( + new BufferedReader(new InputStreamReader(response.getEntity().getContent()))); + jsonReader.setLenient(true); try { - BazaarNotifier.resources = gson.fromJson(result, JsonObject.class).getAsJsonObject(); + BazaarNotifier.resources = gson.fromJson(jsonReader, JsonObject.class); BazaarNotifier.bazaarConv = jsonToBimap( BazaarNotifier.resources.getAsJsonObject("bazaarConversions")); BazaarNotifier.enchantCraftingList = BazaarNotifier.resources .getAsJsonObject("enchantCraftingList"); } catch (JsonSyntaxException e) { e.printStackTrace(); + } finally { + client.close(); } }