diff options
author | nea <romangraef@gmail.com> | 2022-11-01 21:24:25 +0100 |
---|---|---|
committer | nea <romangraef@gmail.com> | 2022-11-01 21:24:25 +0100 |
commit | 05d2ae11997b85918890e853634efd7df2986aef (patch) | |
tree | 29afe632ddd32fe1887d4267914ac00c5f51464f /src/main | |
parent | 170ebea5a6e46c0f489e80460d5e169f6ebdd1dd (diff) | |
parent | e42dd2aa0a2e0a988e820e1ceb13cf2bc30ba987 (diff) | |
download | NotEnoughUpdates-05d2ae11997b85918890e853634efd7df2986aef.tar.gz NotEnoughUpdates-05d2ae11997b85918890e853634efd7df2986aef.tar.bz2 NotEnoughUpdates-05d2ae11997b85918890e853634efd7df2986aef.zip |
Merge remote-tracking branch 'origin/master' into feature/glowshrooms
Diffstat (limited to 'src/main')
113 files changed, 5006 insertions, 1495 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 34d87c5b..5fe902fb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -34,6 +34,7 @@ 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.recipes.RecipeHistory; import io.github.moulberry.notenoughupdates.util.ApiUtil; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.HotmInformation; @@ -113,12 +114,16 @@ public class NEUManager { 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 keybindPreviousRecipe = + new KeyBinding("Show previous recipe", Keyboard.KEY_LBRACKET, "NotEnoughUpdates"); + public final KeyBinding keybindNextRecipe = + new KeyBinding("Show next recipe", Keyboard.KEY_RBRACKET, "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 + keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe, keybindPreviousRecipe, + keybindNextRecipe, keybindToggleDisplay, keybindClosePanes, keybindItemSelect }; public String viewItemAttemptID = null; @@ -132,6 +137,8 @@ public class NEUManager { private final HashMap<String, Set<NeuRecipe>> recipesMap = new HashMap<>(); private final HashMap<String, Set<NeuRecipe>> usagesMap = new HashMap<>(); + private final Map<String, String> displayNameCache = new HashMap<>(); + public String latestRepoCommit = null; public File configLocation; @@ -157,10 +164,6 @@ public class NEUManager { repoLocation.mkdir(); } - public void setCurrentProfile(String currentProfile) { - SBInfo.getInstance().currentProfile = currentProfile; - } - public String getCurrentProfile() { return SBInfo.getInstance().currentProfile; } @@ -886,7 +889,6 @@ public class NEUManager { case "viewpotion": neu.sendChatMessage("/viewpotion " + internalName.split(";")[0].toLowerCase(Locale.ROOT)); } - displayGuiItemRecipe(internalName); } public void showRecipe(String internalName) { @@ -990,6 +992,7 @@ public class NEUManager { List<NeuRecipe> usages = getAvailableUsagesFor(internalName); if (usages.isEmpty()) return false; NotEnoughUpdates.INSTANCE.openGui = (new GuiItemRecipe(usages, this)); + RecipeHistory.add(NotEnoughUpdates.INSTANCE.openGui); return true; } @@ -998,6 +1001,7 @@ public class NEUManager { List<NeuRecipe> recipes = getAvailableRecipesFor(internalName); if (recipes.isEmpty()) return false; NotEnoughUpdates.INSTANCE.openGui = (new GuiItemRecipe(recipes, this)); + RecipeHistory.add(NotEnoughUpdates.INSTANCE.openGui); return true; } @@ -1593,6 +1597,7 @@ public class NEUManager { recipes.clear(); recipesMap.clear(); usagesMap.clear(); + itemMap.clear(); File[] itemFiles = new File(repoLocation, "items").listFiles(); if (itemFiles != null) { @@ -1606,6 +1611,7 @@ public class NEUManager { new RepositoryReloadEvent(repoLocation, !hasBeenLoadedBefore).post(); hasBeenLoadedBefore = true; comp.complete(null); + displayNameCache.clear(); } catch (Exception e) { comp.completeExceptionally(e); } @@ -1622,4 +1628,30 @@ public class NEUManager { public boolean isValidInternalName(String internalName) { return itemMap.containsKey(internalName); } + + public String getDisplayName(String internalName) { + if (displayNameCache.containsKey(internalName)) { + return displayNameCache.get(internalName); + } + + String displayName = null; + TreeMap<String, JsonObject> itemInformation = NotEnoughUpdates.INSTANCE.manager.getItemInformation(); + if (itemInformation.containsKey(internalName)) { + JsonObject jsonObject = itemInformation.get(internalName); + if (jsonObject.has("displayname")) { + displayName = jsonObject.get("displayname").getAsString(); + } + } + + if (displayName == null) { + displayName = internalName; + Utils.showOutdatedRepoNotification(); + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) { + Utils.addChatMessage("§c[NEU] Found no display name in repo for '" + internalName + "'!"); + } + } + + displayNameCache.put(internalName, displayName); + return displayName; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index 2f55c338..87ce915b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -1219,8 +1219,8 @@ public class NEUOverlay extends Gui { String internal1 = o1.get("internalname").getAsString(); String internal2 = o2.get("internalname").getAsString(); - double cost1 = manager.auctionManager.getBazaarOrBin(internal1); - double cost2 = manager.auctionManager.getBazaarOrBin(internal2); + double cost1 = manager.auctionManager.getBazaarOrBin(internal1, false); + double cost2 = manager.auctionManager.getBazaarOrBin(internal2, false); if (cost1 < cost2) return mult; if (cost1 > cost2) return -mult; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 308cbdc0..c1190b2b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -45,6 +45,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.CrystalOverlay; import io.github.moulberry.notenoughupdates.miscfeatures.CrystalWishingCompassSolver; import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects; import io.github.moulberry.notenoughupdates.miscfeatures.CustomSkulls; +import io.github.moulberry.notenoughupdates.miscfeatures.DungeonNpcProfitOverlay; import io.github.moulberry.notenoughupdates.miscfeatures.DwarvenMinesWaypoints; import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls; @@ -69,6 +70,7 @@ import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay; import io.github.moulberry.notenoughupdates.miscgui.InventoryStorageSelector; import io.github.moulberry.notenoughupdates.miscgui.SignCalculator; import io.github.moulberry.notenoughupdates.miscgui.TrophyRewardOverlay; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; import io.github.moulberry.notenoughupdates.mixins.AccessorMinecraft; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.overlays.EquipmentOverlay; @@ -78,6 +80,7 @@ import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.recipes.RecipeGenerator; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.TitleUtil; import io.github.moulberry.notenoughupdates.util.Utils; import io.github.moulberry.notenoughupdates.util.XPInformation; import net.minecraft.client.Minecraft; @@ -295,6 +298,7 @@ public class NotEnoughUpdates { MinecraftForge.EVENT_BUS.register(new DwarvenMinesWaypoints()); MinecraftForge.EVENT_BUS.register(new FuelBar()); MinecraftForge.EVENT_BUS.register(new AuctionProfit()); + MinecraftForge.EVENT_BUS.register(new DungeonNpcProfitOverlay()); MinecraftForge.EVENT_BUS.register(XPInformation.getInstance()); MinecraftForge.EVENT_BUS.register(OverlayManager.petInfoOverlay); MinecraftForge.EVENT_BUS.register(OverlayManager.timersOverlay); @@ -319,9 +323,11 @@ public class NotEnoughUpdates { MinecraftForge.EVENT_BUS.register(AbiphoneWarning.getInstance()); MinecraftForge.EVENT_BUS.register(new BetterContainers()); MinecraftForge.EVENT_BUS.register(AuctionBINWarning.getInstance()); + MinecraftForge.EVENT_BUS.register(MinionHelperManager.getInstance()); MinecraftForge.EVENT_BUS.register(navigation); MinecraftForge.EVENT_BUS.register(new GlowingMushroomHighlighter()); MinecraftForge.EVENT_BUS.register(new WorldListener(this)); + MinecraftForge.EVENT_BUS.register(TitleUtil.getInstance()); if (Minecraft.getMinecraft().getResourceManager() instanceof IReloadableResourceManager) { IReloadableResourceManager manager = (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java index 1b6896db..53e72dc1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java @@ -280,7 +280,7 @@ public class APIManager { if (lowestBins != null && lowestBins.has(internalName)) { JsonElement e = lowestBins.get(internalName); if (e.isJsonPrimitive() && e.getAsJsonPrimitive().isNumber()) { - return e.getAsBigDecimal().longValue(); + return e.getAsLong(); } } return -1; @@ -822,10 +822,11 @@ public class APIManager { return keys; } - public double getBazaarOrBin(String internalName) { + public double getBazaarOrBin(String internalName, boolean useSellingPrice) { + String curr = (useSellingPrice ? "curr_sell" : "curr_buy"); JsonObject bazaarInfo = manager.auctionManager.getBazaarInfo(internalName); - if (bazaarInfo != null && bazaarInfo.get("curr_buy") != null) { - return bazaarInfo.get("curr_buy").getAsFloat(); + if (bazaarInfo != null && bazaarInfo.get(curr) != null) { + return bazaarInfo.get(curr).getAsFloat(); } else { return manager.auctionManager.getLowestBin(internalName); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java index 7b4542d0..07ec4a59 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java @@ -190,8 +190,6 @@ public class CustomAH extends Gui { private static final int SORT_MODE_LOW = 1; private static final int SORT_MODE_SOON = 2; - // private static final String[] rarities = {"COMMON", "UNCOMMON", "RARE", "EPIC", -// "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL", "SUPREME", "DIVINE"}; private static final String[] rarityColours = { "" + EnumChatFormatting.WHITE, "" + EnumChatFormatting.GREEN, "" + EnumChatFormatting.BLUE, "" + EnumChatFormatting.DARK_PURPLE, @@ -264,10 +262,8 @@ public class CustomAH extends Gui { if (searchField == null || priceField == null) init(); if (System.currentTimeMillis() - lastOpen < 1000) Mouse.setGrabbed(false); - //sortMode = SORT_MODE_HIGH; rarityFilter = -1; filterMyAuctions = false; - //binFilter = BIN_FILTER_ALL; enchFilter = ENCH_FILTER_ALL; dungeonFilter = DUNGEON_FILTER_ALL; @@ -995,14 +991,6 @@ public class CustomAH extends Gui { searchField.drawTextBox(); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - /*if(auctionIds.size() == 0 && searchField.getText().length() == 0) { - drawRect(guiLeft+8, guiTop+17, guiLeft+170, guiTop+107+18*splits, - new Color(100, 100, 100, 100).getRGB()); - - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - int strWidth = fr.getStringWidth("Loading items..."); - fr.drawString("Loading items...", guiLeft+(8+170-strWidth)/2, guiTop+(17+107+18*splits)/2, Color.BLACK.getRGB()); - }*/ Minecraft.getMinecraft().getTextureManager().bindTexture(creativeInventoryTabs); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); @@ -1409,9 +1397,7 @@ public class CustomAH extends Gui { for (String internalname : itemMatches) { for (String aucid : manager.auctionManager.getAuctionsForInternalname(internalname)) { APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid); - if (doesAucMatch(auc)) { - //matches.add(aucid); - } else { + if (!doesAucMatch(auc)) { dontMatch.add(aucid); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java index 62981a30..91365cd1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java @@ -95,7 +95,6 @@ public class Commands { ClientCommandHandler.instance.registerCommand(new ScreenCommand("neubuttons", GuiInvButtonEditor::new)); ClientCommandHandler.instance.registerCommand(new ScreenCommand("neuec", GuiEnchantColour::new)); ClientCommandHandler.instance.registerCommand(new ScreenCommand("neuoverlay", NEUOverlayPlacements::new)); - //ClientCommandHandler.instance.registerCommand(new ScreenCommand("neututorial", NeuTutorial::new)); ClientCommandHandler.instance.registerCommand(new AhCommand()); ClientCommandHandler.instance.registerCommand(new CalculatorCommand()); ClientCommandHandler.instance.registerCommand(new CalendarCommand()); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java index 138486c3..5f1fe191 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java @@ -23,13 +23,17 @@ import io.github.moulberry.notenoughupdates.BuildFlags; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.core.config.GuiPositionEditor; +import io.github.moulberry.notenoughupdates.core.util.MiscUtils; import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.SpecialBlockZone; import io.github.moulberry.notenoughupdates.miscgui.GuiPriceGraph; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; import io.github.moulberry.notenoughupdates.util.PronounDB; import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.TabListUtils; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.command.CommandException; @@ -62,7 +66,8 @@ public class DevTestCommand extends ClientCommandBase { "a7d6b3f1-8425-48e5-8acc-9a38ab9b86f7", // whalker "0ce87d5a-fa5f-4619-ae78-872d9c5e07fe", // ascynx "a049a538-4dd8-43f8-87d5-03f09d48b4dc", // egirlefe - "7a9dc802-d401-4d7d-93c0-8dd1bc98c70d" // efefury + "7a9dc802-d401-4d7d-93c0-8dd1bc98c70d", // efefury + "bb855349-dfd8-4125-a750-5fc2cf543ad5" // hannibal2 ); private static final String[] DEV_FAIL_STRINGS = { @@ -114,8 +119,7 @@ public class DevTestCommand extends ClientCommandBase { Minecraft.getMinecraft().getNetHandler().getNetworkManager().closeChannel(component); return; } - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - DEV_FAIL_STRINGS[devFailIndex++])); + Utils.addChatMessage(EnumChatFormatting.RED + DEV_FAIL_STRINGS[devFailIndex++]); return; } if (args.length >= 1 && args[0].equalsIgnoreCase("profileinfo")) { @@ -167,7 +171,8 @@ public class DevTestCommand extends ClientCommandBase { return; } if (args.length == 1 && args[0].equalsIgnoreCase("dev")) { - NotEnoughUpdates.INSTANCE.config.hidden.dev = true; + NotEnoughUpdates.INSTANCE.config.hidden.dev = !NotEnoughUpdates.INSTANCE.config.hidden.dev; + Utils.addChatMessage("§e[NEU] Dev mode " + (NotEnoughUpdates.INSTANCE.config.hidden.dev ? "§aenabled": "§cdisabled")); return; } if (args.length == 1 && args[0].equalsIgnoreCase("saveconfig")) { @@ -176,8 +181,7 @@ public class DevTestCommand extends ClientCommandBase { } if (args.length == 1 && args[0].equalsIgnoreCase("searchmode")) { NotEnoughUpdates.INSTANCE.config.hidden.firstTimeSearchFocus = true; - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.AQUA + - "I would never search")); + Utils.addChatMessage(EnumChatFormatting.AQUA + "I would never search"); return; } if (args.length == 1 && args[0].equalsIgnoreCase("bluehair")) { @@ -187,11 +191,10 @@ public class DevTestCommand extends ClientCommandBase { if (args.length == 2 && args[0].equalsIgnoreCase("openGui")) { try { NotEnoughUpdates.INSTANCE.openGui = (GuiScreen) Class.forName(args[1]).newInstance(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "Opening gui: " + NotEnoughUpdates.INSTANCE.openGui)); + Utils.addChatMessage("Opening gui: " + NotEnoughUpdates.INSTANCE.openGui); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | ClassCastException e) { e.printStackTrace(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Failed to open this GUI.")); + Utils.addChatMessage("Failed to open this GUI."); } } if (args.length == 1 && args[0].equalsIgnoreCase("center")) { @@ -199,5 +202,16 @@ public class DevTestCommand extends ClientCommandBase { double z = Math.floor(Minecraft.getMinecraft().thePlayer.posZ) + 0.5f; Minecraft.getMinecraft().thePlayer.setPosition(x, Minecraft.getMinecraft().thePlayer.posY, z); } + if (args.length >= 1 && args[0].equalsIgnoreCase("minion")) { + MinionHelperManager.getInstance().handleCommand(args); + } + if (args.length == 1 && args[0].equalsIgnoreCase("copytablist")) { + StringBuilder builder = new StringBuilder(); + for (String name : TabListUtils.getTabList()) { + builder.append(name).append("\n"); + } + MiscUtils.copyToClipboard(builder.toString()); + Utils.addChatMessage("§e[NEU] Copied tablist to clipboard!"); + } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java index e1504472..1d30a15f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java @@ -22,6 +22,7 @@ package io.github.moulberry.notenoughupdates.commands.dev; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.core.util.MiscUtils; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.command.CommandException; @@ -290,11 +291,10 @@ public class PackDevCommand extends ClientCommandBase { } if ((single && closest == null) || (!single && result.length() == 0)) { - mc.thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "No " + typeFriendlyName + "s found within " + dist + " blocks.")); + Utils.addChatMessage(EnumChatFormatting.RED + "No " + typeFriendlyName + "s found within " + dist + " blocks."); } else { - mc.thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.GREEN + "Copied " + typeFriendlyName + " data to clipboard")); + Utils.addChatMessage( + EnumChatFormatting.GREEN + "Copied " + typeFriendlyName + " data to clipboard"); return single ? livingBaseDataBuilder(closest, clazz) : result; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java index e9d4eb44..ea417977 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java @@ -24,11 +24,11 @@ import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.util.DiscordMarkdownBuilder; import io.github.moulberry.notenoughupdates.util.HastebinUploader; import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.command.ICommandSender; import net.minecraft.util.BlockPos; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraftforge.common.ForgeVersion; import net.minecraftforge.fml.client.FMLClientHandler; @@ -119,10 +119,8 @@ public class StatsCommand extends ClientCommandBase { } private static void modPrefixedMessage(String message) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.GOLD + "[" + EnumChatFormatting.RED + "NotEnoughUpdates" + EnumChatFormatting.GOLD + "]: " + - message)); - + Utils.addChatMessage( + EnumChatFormatting.GOLD + "[" + EnumChatFormatting.RED + "NotEnoughUpdates" + EnumChatFormatting.GOLD + "]: " + message); } private static String createStats() { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java index a5a7bcca..3b697905 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java @@ -20,10 +20,10 @@ package io.github.moulberry.notenoughupdates.commands.dungeon; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; public class DnCommand extends ClientCommandBase { @@ -35,7 +35,6 @@ public class DnCommand extends ClientCommandBase { @Override public void processCommand(ICommandSender sender, String[] args) throws CommandException { Minecraft.getMinecraft().thePlayer.sendChatMessage("/warp dungeon_hub"); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.AQUA + "Warping to:" + EnumChatFormatting.YELLOW + " Deez Nuts lmao")); + Utils.addChatMessage(EnumChatFormatting.AQUA + "Warping to:" + EnumChatFormatting.YELLOW + " Deez Nuts lmao"); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java index c1f88942..58bfbef2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java @@ -21,10 +21,10 @@ package io.github.moulberry.notenoughupdates.commands.dungeon; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import org.apache.commons.lang3.StringUtils; @@ -40,19 +40,16 @@ public class JoinDungeonCommand extends ClientCommandBase { Minecraft.getMinecraft().thePlayer.sendChatMessage("/join " + StringUtils.join(args, " ")); } else { if (args.length != 1) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "Example Usage: /join f7, /join m6 or /join 7")); + Utils.addChatMessage(EnumChatFormatting.RED + "Example Usage: /join f7, /join m6 or /join 7"); } else { String cataPrefix = "catacombs"; if (args[0].toLowerCase().startsWith("m")) { cataPrefix = "master_catacombs"; } String cmd = "/joindungeon " + cataPrefix + " " + args[0].charAt(args[0].length() - 1); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "Running command: " + cmd)); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + - "The dungeon should start soon. If it doesn't, make sure you have a party of 5 people")); + Utils.addChatMessage(EnumChatFormatting.YELLOW + "Running command: " + cmd); + Utils.addChatMessage(EnumChatFormatting.YELLOW + + "The dungeon should start soon. If it doesn't, make sure you have a party of 5 people"); Minecraft.getMinecraft().thePlayer.sendChatMessage(cmd); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java index f5381adb..3967edb4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java @@ -24,6 +24,7 @@ import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.dungeons.GuiDungeonMapEditor; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.block.material.MapColor; import net.minecraft.client.Minecraft; import net.minecraft.command.CommandException; @@ -128,8 +129,7 @@ public class MapCommand extends ClientCommandBase { e.printStackTrace(); } - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + - "Saved to file.")); + Utils.addChatMessage(EnumChatFormatting.GREEN + "Saved to file."); } return; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java index 5f709c4f..bc389ad4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java @@ -41,18 +41,9 @@ public class FeaturesCommand extends ClientCommandBase { @Override public void processCommand(ICommandSender sender, String[] args) throws CommandException { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + Utils.addChatMessage(""); if (Constants.MISC == null || !Constants.MISC.has("featureslist")) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "" + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "WARNING: " + EnumChatFormatting.RESET + - EnumChatFormatting.RED + "Could not load URL from repo.")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "" + EnumChatFormatting.RED + "Please run " + EnumChatFormatting.BOLD + "/neuresetrepo" + - EnumChatFormatting.RESET + EnumChatFormatting.RED + " and " + EnumChatFormatting.BOLD + "restart your game" + - EnumChatFormatting.RESET + EnumChatFormatting.RED + " in order to fix. " + EnumChatFormatting.DARK_RED + - EnumChatFormatting.BOLD + "If that doesn't fix it" + EnumChatFormatting.RESET + EnumChatFormatting.RED + - ", please join discord.gg/moulberry and post in #neu-support")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + Utils.showOutdatedRepoNotification(); return; } String url = Constants.MISC.get("featureslist").getAsString(); @@ -60,9 +51,8 @@ public class FeaturesCommand extends ClientCommandBase { Desktop desk = Desktop.getDesktop(); try { desk.browse(new URI(url)); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.DARK_PURPLE + "" + EnumChatFormatting.BOLD + "NEU" + EnumChatFormatting.RESET + - EnumChatFormatting.GOLD + "> Opening Feature List in browser.")); + Utils.addChatMessage( EnumChatFormatting.DARK_PURPLE + "" + EnumChatFormatting.BOLD + "NEU" + EnumChatFormatting.RESET + + EnumChatFormatting.GOLD + "> Opening Feature List in browser."); } catch (URISyntaxException | IOException ignored) { ChatComponentText clickTextFeatures = new ChatComponentText( @@ -72,6 +62,6 @@ public class FeaturesCommand extends ClientCommandBase { Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextFeatures); } - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + Utils.addChatMessage(""); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java index 49123f45..3a47509d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java @@ -22,9 +22,8 @@ package io.github.moulberry.notenoughupdates.commands.help; import com.google.common.collect.Lists; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; -import net.minecraft.client.Minecraft; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.command.ICommandSender; -import net.minecraft.util.ChatComponentText; import java.util.ArrayList; @@ -66,7 +65,7 @@ public class HelpCommand extends ClientCommandBase { "\u00a76/neupackdev \u00a7r\u00a77- pack creator command - getnpc, getmob(s), getarmorstand(s), getall. Optional radius argument for all." ); for (String neuHelpMessage : neuHelpMessages) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(neuHelpMessage)); + Utils.addChatMessage(neuHelpMessage); } if (NotEnoughUpdates.INSTANCE.config.hidden.dev) { ArrayList<String> neuDevHelpMessages = Lists.newArrayList( @@ -76,7 +75,7 @@ public class HelpCommand extends ClientCommandBase { ); for (String neuDevHelpMessage : neuDevHelpMessages) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(neuDevHelpMessage)); + Utils.addChatMessage(neuDevHelpMessage); } } String[] helpInfo = { @@ -89,8 +88,7 @@ public class HelpCommand extends ClientCommandBase { }; for (String message : helpInfo) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(message)); + Utils.addChatMessage(message); } - } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java index 9938403c..793e652e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java @@ -22,10 +22,9 @@ package io.github.moulberry.notenoughupdates.commands.help; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; -import net.minecraft.client.Minecraft; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; -import net.minecraft.util.ChatComponentText; import java.io.File; @@ -43,9 +42,9 @@ public class LinksCommand extends ClientCommandBase { try { JsonObject update = NotEnoughUpdates.INSTANCE.manager.getJsonFromFile(updateJson); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + Utils.addChatMessage(""); NotEnoughUpdates.INSTANCE.displayLinks(update,0 ); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + Utils.addChatMessage(""); } catch (Exception ignored) { } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java index d51d4d2e..1ca398ef 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java @@ -22,10 +22,9 @@ package io.github.moulberry.notenoughupdates.commands.misc; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.auction.CustomAHGui; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; -import net.minecraft.client.Minecraft; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import org.apache.commons.lang3.StringUtils; @@ -38,12 +37,11 @@ public class AhCommand extends ClientCommandBase { @Override public void processCommand(ICommandSender sender, String[] args) throws CommandException { if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "You must be on SkyBlock to use this feature.")); + Utils.addChatMessage(EnumChatFormatting.RED + "You must be on SkyBlock to use this feature."); } else if (NotEnoughUpdates.INSTANCE.config.apiData.apiKey == null || NotEnoughUpdates.INSTANCE.config.apiData.apiKey.trim().isEmpty()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Can't open NEU AH: an api key is not set. Run /api new and put the result in settings.")); + Utils.addChatMessage( + EnumChatFormatting.RED + "Can't open NEU AH: an api key is not set. Run /api new and put the result in settings."); } else { NotEnoughUpdates.INSTANCE.openGui = new CustomAHGui(); NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.lastOpen = System.currentTimeMillis(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java index 2ba93585..b01f106b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java @@ -26,8 +26,8 @@ import net.minecraft.command.ICommandSender; import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; -import java.text.DecimalFormat; import java.math.BigDecimal; +import java.text.DecimalFormat; import java.util.Arrays; import java.util.List; import java.util.Objects; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java index 67430ffa..bbab316e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java @@ -22,11 +22,10 @@ package io.github.moulberry.notenoughupdates.commands.misc; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.cosmetics.GuiCosmetics; -import net.minecraft.client.Minecraft; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; public class CosmeticsCommand extends ClientCommandBase { @@ -38,8 +37,8 @@ public class CosmeticsCommand extends ClientCommandBase { @Override public void processCommand(ICommandSender sender, String[] args) throws CommandException { if (!OpenGlHelper.isFramebufferEnabled() && NotEnoughUpdates.INSTANCE.config.notifications.doFastRenderNotif) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "NEU Cosmetics do not work with OptiFine Fast Render. Go to ESC > Options > Video Settings > Performance > Fast Render to disable it.")); + Utils.addChatMessage(EnumChatFormatting.RED + + "NEU Cosmetics do not work with OptiFine Fast Render. Go to ESC > Options > Video Settings > Performance > Fast Render to disable it."); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java index 2b184fa0..28c2893d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java @@ -60,89 +60,4 @@ public class CustomizeCommand extends ClientCommandBase { NotEnoughUpdates.INSTANCE.openGui = new GuiItemCustomize(held, heldUUID); } - - /*SimpleCommand itemRenameCommand = new SimpleCommand("neurename", new SimpleCommand.ProcessCommandRunnable() { - public void processCommand(ICommandSender sender, String[] args) { - if (args.length == 0) { - args = new String[]{"help"}; - } - String heldUUID = NotEnoughUpdates.INSTANCE.manager.getUUIDForItem(Minecraft.getMinecraft().thePlayer.getHeldItem()); - switch (args[0].toLowerCase()) { - case "clearall": - NotEnoughUpdates.INSTANCE.manager.itemRenameJson = new JsonObject(); - NotEnoughUpdates.INSTANCE.manager.saveItemRenameConfig(); - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Cleared custom name for all items")); - break; - case "clear": - if (heldUUID == null) { - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't clear rename - no UUID")); - return; - } - NotEnoughUpdates.INSTANCE.manager.itemRenameJson.remove(heldUUID); - NotEnoughUpdates.INSTANCE.manager.saveItemRenameConfig(); - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Cleared custom name for held item")); - break; - case "copyuuid": - if (heldUUID == null) { - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't clear rename - no UUID")); - return; - } - StringSelection selection = new StringSelection(heldUUID); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] UUID copied to clipboard")); - break; - case "uuid": - if (heldUUID == null) { - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't get UUID - no UUID")); - return; - } - ChatStyle style = new ChatStyle(); - style.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, - new ChatComponentText(EnumChatFormatting.GRAY + "Click to copy to clipboard"))); - style.setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/neurename copyuuid")); - - ChatComponentText text = new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] The UUID of your currently held item is: " + - EnumChatFormatting.GREEN + heldUUID); - text.setChatStyle(style); - sender.addChatMessage(text); - break; - case "set": - if (heldUUID == null) { - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't rename item - no UUID")); - return; - } - if (args.length == 1) { - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Usage: /neurename set [name...]")); - return; - } - StringBuilder sb = new StringBuilder(); - for (int i = 1; i < args.length; i++) { - sb.append(args[i]); - if (i < args.length - 1) sb.append(" "); - } - String name = sb.toString() - .replace("\\&", "{amp}") - .replace("&", "\u00a7") - .replace("{amp}", "&"); - name = new UnicodeUnescaper().translate(name); - NotEnoughUpdates.INSTANCE.manager.itemRenameJson.addProperty(heldUUID, name); - NotEnoughUpdates.INSTANCE.manager.saveItemRenameConfig(); - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Set custom name for held item")); - break; - default: - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Unknown subcommand \"" + args[0] + "\"")); - case "help": - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] Available commands:")); - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "help: Print this message")); - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "clearall: Clears all custom names " - + EnumChatFormatting.BOLD + "(Cannot be undone)")); - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "clear: Clears held item name " - + EnumChatFormatting.BOLD + "(Cannot be undone)")); - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "uuid: Returns the UUID of the currently held item")); - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "set: Sets the custom name of the currently held item")); - sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "Usage: /neurename set [name...]")); - - } - } - });*/ } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java index 77377917..23852ab6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java @@ -78,8 +78,8 @@ public class PeekCommand extends ClientCommandBase { } if (peekScheduledFuture != null && !peekScheduledFuture.isDone()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "[PEEK] New peek command was run, cancelling old one.")); + Utils.addChatMessage( + EnumChatFormatting.RED + "[PEEK] New peek command was run, cancelling old one."); peekScheduledFuture.cancel(true); } @@ -136,8 +136,7 @@ public class PeekCommand extends ClientCommandBase { EnumChatFormatting.STRIKETHROUGH + "-=-"), id); if (skyblockInfo == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "Skills API disabled!")); + Utils.addChatMessage(EnumChatFormatting.YELLOW + "Skills API disabled!"); } else { float totalSkillLVL = 0; float totalSkillCount = 0; @@ -208,20 +207,17 @@ public class PeekCommand extends ClientCommandBase { overallScore += cata * cata / 2000f; - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - g + "Combat: " + combatPrefix + (int) Math.floor(combat) + + Utils.addChatMessage(g + "Combat: " + combatPrefix + (int) Math.floor(combat) + (cata > 0 ? g + " - Cata: " + cataPrefix + cata : "") + - g + " - AVG: " + avgPrefix + (int) Math.floor(avgSkillLVL))); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - g + "Slayer: " + zombiePrefix + (int) Math.floor(zombie) + g + "-" + + g + " - AVG: " + avgPrefix + (int) Math.floor(avgSkillLVL)); + Utils.addChatMessage(g + "Slayer: " + zombiePrefix + (int) Math.floor(zombie) + g + "-" + spiderPrefix + (int) Math.floor(spider) + g + "-" + wolfPrefix + (int) Math.floor(wolf) + g + "-" + endermanPrefix + (int) Math.floor(enderman) + g + "-" + - blazePrefix + (int) Math.floor(blaze))); + blazePrefix + (int) Math.floor(blaze)); } if (stats == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "Skills, collection and/or inventory apis disabled!")); + Utils.addChatMessage(EnumChatFormatting.YELLOW + "Skills, collection and/or inventory apis disabled!"); } else { int health = (int) stats.get("health"); int defence = (int) stats.get("defence"); @@ -249,11 +245,10 @@ public class PeekCommand extends ClientCommandBase { : EnumChatFormatting.YELLOW) : EnumChatFormatting.RED; - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - g + "Stats : " + healthPrefix + health + EnumChatFormatting.RED + "\u2764 " + - defencePrefix + defence + EnumChatFormatting.GREEN + "\u2748 " + - strengthPrefix + strength + EnumChatFormatting.RED + "\u2741 " + - intelligencePrefix + intelligence + EnumChatFormatting.AQUA + "\u270e ")); + Utils.addChatMessage( g + "Stats : " + healthPrefix + health + EnumChatFormatting.RED + "\u2764 " + + defencePrefix + defence + EnumChatFormatting.GREEN + "\u2748 " + + strengthPrefix + strength + EnumChatFormatting.RED + "\u2741 " + + intelligencePrefix + intelligence + EnumChatFormatting.AQUA + "\u270e "); } float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), -1); float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0); @@ -275,11 +270,10 @@ public class PeekCommand extends ClientCommandBase { (money > 200 * 1000 * 1000 ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) : EnumChatFormatting.RED; - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - g + "Purse: " + moneyPrefix + Utils.shortNumberFormat(purseBalance, 0) + g + " - Bank: " + - (bankBalance == -1 ? EnumChatFormatting.YELLOW + "N/A" : moneyPrefix + - (isMe ? "4.8b" : Utils.shortNumberFormat(bankBalance, 0))) + - (networth > 0 ? g + " - Net: " + moneyPrefix + Utils.shortNumberFormat(networth, 0) : ""))); + Utils.addChatMessage( g + "Purse: " + moneyPrefix + Utils.shortNumberFormat(purseBalance, 0) + g + " - Bank: " + + (bankBalance == -1 ? EnumChatFormatting.YELLOW + "N/A" : moneyPrefix + + (isMe ? "4.8b" : Utils.shortNumberFormat(bankBalance, 0))) + + (networth > 0 ? g + " - Net: " + moneyPrefix + Utils.shortNumberFormat(networth, 0) : "")); overallScore += Math.min(2, money / (100f * 1000 * 1000)); @@ -295,8 +289,7 @@ public class PeekCommand extends ClientCommandBase { String col = NotEnoughUpdates.petRarityToColourMap.get(activePetTier); if (col == null) col = EnumChatFormatting.LIGHT_PURPLE.toString(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(g + "Pet : " + - col + WordUtils.capitalizeFully(activePet.replace("_", " ")))); + Utils.addChatMessage(g + "Pet : " + col + WordUtils.capitalizeFully(activePet.replace("_", " "))); String overall = "Skywars Main"; if (isMe) { @@ -321,8 +314,7 @@ public class PeekCommand extends ClientCommandBase { overall = EnumChatFormatting.RED + "Played SkyBlock"; } - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(g + "Overall score: " + - overall + g + " (" + Math.round(overallScore * 10) / 10f + ")")); + Utils.addChatMessage(g + "Overall score: " + overall + g + " (" + Math.round(overallScore * 10) / 10f + ")"); peekCommandExecutorService.shutdownNow(); } else { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java index 887cd28f..26468e39 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java @@ -22,6 +22,7 @@ package io.github.moulberry.notenoughupdates.commands.profile; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.command.ICommandSender; @@ -38,32 +39,31 @@ public class ViewProfileCommand extends ClientCommandBase { public static final Consumer<String[]> RUNNABLE = (args) -> { if (!OpenGlHelper.isFramebufferEnabled()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Some parts of the profile viewer do not work with OptiFine Fast Render. Go to ESC > Options > Video Settings > Performance > Fast Render to disable it.")); + Utils.addChatMessage(EnumChatFormatting.RED + + "Some parts of the profile viewer do not work with OptiFine Fast Render. Go to ESC > Options > Video Settings > Performance > Fast Render to disable it."); } if (NotEnoughUpdates.INSTANCE.config.apiData.apiKey == null || NotEnoughUpdates.INSTANCE.config.apiData.apiKey.trim().isEmpty()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Can't view profile, an API key is not set. Run /api new and put the result in settings.")); + Utils.addChatMessage(EnumChatFormatting.RED + + "Can't view profile, an API key is not set. Run /api new and put the result in settings."); } else if (args.length == 0) { NotEnoughUpdates.profileViewer.getProfileByName(Minecraft.getMinecraft().thePlayer.getName(), profile -> { if (profile == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Invalid player name/API key. Maybe the API is down? Try /api new.")); + Utils.addChatMessage(EnumChatFormatting.RED + + "Invalid player name/API key. Maybe the API is down? Try /api new."); } else { profile.resetCache(); NotEnoughUpdates.INSTANCE.openGui = new GuiProfileViewer(profile); } }); } else if (args.length > 1) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Too many arguments. Usage: /neuprofile [name]")); + Utils.addChatMessage(EnumChatFormatting.RED + + "Too many arguments. Usage: /neuprofile [name]"); } else { NotEnoughUpdates.profileViewer.getProfileByName(args[0], profile -> { if (profile == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "Invalid player name/api key. Maybe the API is down? Try /api new.")); + Utils.addChatMessage(EnumChatFormatting.RED + "Invalid player name/api key. Maybe the API is down? Try /api new."); } else { profile.resetCache(); NotEnoughUpdates.INSTANCE.openGui = new GuiProfileViewer(profile); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/ArrowPagesUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/ArrowPagesUtils.java new file mode 100644 index 00000000..86430804 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/ArrowPagesUtils.java @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.core.util; + +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.function.Consumer; + +public class ArrowPagesUtils { + + public static final int BUTTON_POSITION_RIGHT_OFFSET_X = 37; + public static final int PAGE_STRING_OFFSET_X = 22; + public static final int PAGE_STRING_OFFSET_Y = 6; + + public static final int BUTTON_WIDTH = 7; + public static final int BUTTON_HEIGHT = 11; + + public static final ResourceLocation resourcePacksTexture = new ResourceLocation("textures/gui/resource_packs.png"); + + public static void onDraw(int guiLeft, int guiTop, int[] topLeftButton, int currentPage, int totalPages) { + if (totalPages < 2) return; + + final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + final int scaledWidth = scaledresolution.getScaledWidth(); + final int scaledHeight = scaledresolution.getScaledHeight(); + int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; + int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; + + int buttonPositionLeftX = topLeftButton[0]; + int buttonPositionRightX = buttonPositionLeftX + BUTTON_POSITION_RIGHT_OFFSET_X; + int pageStringX = buttonPositionLeftX + PAGE_STRING_OFFSET_X; + int buttonPositionY = topLeftButton[1]; + int pageStringY = buttonPositionY + PAGE_STRING_OFFSET_Y; + + boolean leftSelected = isWithinRect( + mouseX - guiLeft, + mouseY - guiTop, + buttonPositionLeftX, + buttonPositionY, + BUTTON_WIDTH, + BUTTON_HEIGHT + ); + boolean rightSelected = isWithinRect( + mouseX - guiLeft, + mouseY - guiTop, + buttonPositionRightX, + buttonPositionY, + BUTTON_WIDTH, + BUTTON_HEIGHT + ); + Minecraft.getMinecraft().getTextureManager().bindTexture(resourcePacksTexture); + + if (currentPage != 0) + Utils.drawTexturedRect( + guiLeft + buttonPositionLeftX, guiTop + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT, + 34 / 256f, 48 / 256f, + leftSelected ? 37 / 256f : 5 / 256f, leftSelected ? 59 / 256f : 27 / 256f + ); + if (currentPage != totalPages - 1) + Utils.drawTexturedRect( + guiLeft + buttonPositionRightX, guiTop + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT, + 10 / 256f, 24 / 256f, + rightSelected ? 37 / 256f : 5 / 256f, rightSelected ? 59 / 256f : 27 / 256f + ); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); + + String selectedPage = (currentPage + 1) + "/" + totalPages; + + FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj; + Utils.drawStringCenteredScaledMaxWidth(selectedPage, fontRendererObj, + guiLeft + pageStringX, guiTop + pageStringY, false, 28, Color.BLACK.getRGB() + ); + } + + public static boolean onPageSwitchKey( + int currentPage, + int totalPages, + Consumer<Integer> pageChange + ) { + + int keyPressed = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey(); + if (Keyboard.getEventKeyState() && keyPressed == Keyboard.KEY_LEFT) { + int newPage = currentPage - 1; + pageChange.accept(MathHelper.clamp_int(newPage, 0, totalPages - 1)); + return true; + } + if (Keyboard.getEventKeyState() && keyPressed == Keyboard.KEY_RIGHT) { + int newPage = currentPage + 1; + pageChange.accept(MathHelper.clamp_int(newPage, 0, totalPages - 1)); + return true; + } + + return false; + } + + public static boolean onPageSwitchMouse( + int guiLeft, + int guiTop, + int[] topLeft, + int currentPage, + int totalPages, + Consumer<Integer> pageChange + ) { + + int keyPressed = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey(); + if (Keyboard.getEventKeyState() && keyPressed == Keyboard.KEY_LEFT) { + int newPage = currentPage - 1; + pageChange.accept(MathHelper.clamp_int(newPage, 0, totalPages - 1)); + return true; + } + if (Keyboard.getEventKeyState() && keyPressed == Keyboard.KEY_RIGHT) { + int newPage = currentPage + 1; + pageChange.accept(MathHelper.clamp_int(newPage, 0, totalPages - 1)); + return true; + } + + final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + final int scaledWidth = scaledresolution.getScaledWidth(); + final int scaledHeight = scaledresolution.getScaledHeight(); + int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; + int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; + + int buttonPositionLeftX = topLeft[0]; + int buttonPositionRightX = buttonPositionLeftX + BUTTON_POSITION_RIGHT_OFFSET_X; + int buttonPositionY = topLeft[1]; + + if (isWithinRect( + mouseX - guiLeft, + mouseY - guiTop, + buttonPositionLeftX, + buttonPositionY, + BUTTON_WIDTH, + BUTTON_HEIGHT + ) && + currentPage > 0) { + int newPage = currentPage - 1; + pageChange.accept(MathHelper.clamp_int(newPage, 0, totalPages - 1)); + Utils.playPressSound(); + return true; + } + + if (isWithinRect( + mouseX - guiLeft, + mouseY - guiTop, + buttonPositionRightX, + buttonPositionY, + BUTTON_WIDTH, + BUTTON_HEIGHT + ) && + currentPage < totalPages) { + int newPage = currentPage + 1; + pageChange.accept(MathHelper.clamp_int(newPage, 0, totalPages - 1)); + Utils.playPressSound(); + return true; + } + + return false; + } + + private static boolean isWithinRect(int x, int y, int topLeftX, int topLeftY, int width, int height) { + return topLeftX <= x && x < topLeftX + width + && topLeftY <= y && y < topLeftY + height; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java index a4f814d1..7ea9cd00 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java @@ -102,4 +102,20 @@ public class StringUtils { int start = string.lastIndexOf(toReplace); return string.substring(0, start) + replacement + string.substring(start + toReplace.length()); } + + public static String removeLastWord(String string, String splitString) { + try { + String[] split = string.split(splitString); + String rawTier = split[split.length - 1]; + return string.substring(0, string.length() - rawTier.length() - 1); + } catch (StringIndexOutOfBoundsException e) { + throw new RuntimeException("removeLastWord: '" + string + "'", e); + } + } + + public static String firstUpperLetter(String text) { + if (text.isEmpty()) return text; + String firstLetter = ("" + text.charAt(0)).toUpperCase(); + return firstLetter + text.substring(1); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java index ed2afd69..50eff87a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java @@ -401,14 +401,18 @@ public class RenderUtils { } public static void renderWayPoint(List<String> str, Vec3i loc, float partialTicks) { - renderWayPoint(str, new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks); + renderWayPoint(str, new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks, false); } public static void renderWayPoint(String str, Vector3f loc, float partialTicks) { - renderWayPoint(Arrays.asList(str), loc, partialTicks); + renderWayPoint(Arrays.asList(str), loc, partialTicks, false); + } + + public static void renderWayPoint(Vec3i loc, float partialTicks) { + renderWayPoint(Arrays.asList(""), new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks, true); } - public static void renderWayPoint(List<String> lines, Vector3f loc, float partialTicks) { + public static void renderWayPoint(List<String> lines, Vector3f loc, float partialTicks, boolean onlyShowDistance) { GlStateManager.alphaFunc(516, 0.1F); GlStateManager.pushMatrix(); @@ -432,7 +436,7 @@ public class RenderUtils { GlStateManager.translate(x, y, z); GlStateManager.translate(0, viewer.getEyeHeight(), 0); - lines = new ArrayList<>(lines); + lines = onlyShowDistance ? new ArrayList<>() : new ArrayList<>(lines); lines.add(EnumChatFormatting.YELLOW.toString() + Math.round(dist) + "m"); renderNametag(lines); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java index a4c5a60a..88c89773 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java @@ -122,9 +122,6 @@ public class DungeonMap { private int startRoomY = -1; private int connectorSize = 5; private int roomSize = 0; - - //private final List<MapDecoration> decorations = new ArrayList<>(); - //private final List<MapDecoration> lastDecorations = new ArrayList<>(); private long lastDecorationsMillis = -1; private long lastLastDecorationsMillis = -1; @@ -1475,9 +1472,7 @@ public class DungeonMap { } } - //System.out.println("--- PERM START ---"); for (Map.Entry<String, Integer> entry : smallestPermutation.entrySet()) { - //System.out.println(entry.getKey() + ":" + entry.getValue() + " : Total dist: " + smallestTotalDistance); finalUsedIndexes.add(entry.getValue()); playerMarkerMapPositions.put(entry.getKey(), positions.get(entry.getValue())); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java index 8ce9d505..735fa3e6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java @@ -152,15 +152,6 @@ public class GuiDungeonMapEditor extends GuiScreen { public GuiDungeonMapEditor() { DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap; - //Map Border Size - //buttons.add(new Button(0, 6, 37, "Small", options.dmBorderSize)); - //buttons.add(new Button(1, 52, 37, "Medium", options.dmBorderSize)); - //buttons.add(new Button(2, 98, 37, "Large", options.dmBorderSize)); - - //Map Rooms Size - //buttons.add(new Button(3, 6, 67+19, "Small", options.dmRoomSize)); - //buttons.add(new Button(4, 52, 67+19, "Medium", options.dmRoomSize)); - //buttons.add(new Button(5, 98, 67+19, "Large", options.dmRoomSize)); //Map Border Styles buttons.add(new Button(6, 6, 97 + 30, "None")); @@ -241,9 +232,6 @@ public class GuiDungeonMapEditor extends GuiScreen { e.printStackTrace(); } - //buttons.add(new Button(29, 52, 86+19, "XLarge", options.dmRoomSize)); - //buttons.add(new Button(30, 52, 56, "XLarge", options.dmBorderSize)); - { double val = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur; String strVal; @@ -466,7 +454,6 @@ public class GuiDungeonMapEditor extends GuiScreen { button.render(); } - //List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font if (tooltipToDisplay != null) { Utils.drawHoveringText( tooltipToDisplay, diff --git a/src/main/java/io/github/moulberry/notenoughupdates/events/ProfileDataLoadedEvent.java b/src/main/java/io/github/moulberry/notenoughupdates/events/ProfileDataLoadedEvent.java new file mode 100644 index 00000000..956acfe0 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/events/ProfileDataLoadedEvent.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.events; + +import com.google.gson.JsonObject; + +import javax.annotation.Nullable; + +//TODO extend the usage of this event (accessory bag and storage data) +public class ProfileDataLoadedEvent extends NEUEvent { + + @Nullable + private final JsonObject data; + + public ProfileDataLoadedEvent(@Nullable JsonObject entireApiResponse) { + this.data = entireApiResponse; + } + + @Nullable + public JsonObject getData() { + return data; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java index 0b1963d6..421bc798 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java @@ -25,7 +25,6 @@ import io.github.moulberry.notenoughupdates.NEUOverlay; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.block.Block; -import net.minecraft.client.Minecraft; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.CraftingManager; @@ -33,7 +32,6 @@ import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.ShapedRecipes; import net.minecraft.item.crafting.ShapelessRecipes; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; import net.minecraftforge.oredict.ShapedOreRecipe; @@ -60,24 +58,6 @@ public class DevInfoPane extends TextInfoPane { private String getText() { String text = ""; - /*for(Map.Entry<String, JsonObject> item : manager.getItemInformation().entrySet()) { - if(!item.getValue().has("infoType") || item.getValue().get("infoType").getAsString().isEmpty()) { - text += item.getKey() + "\n"; - } - }*/ - /*for(String s : manager.neuio.getRemovedItems(manager.getItemInformation().keySet())) { - text += s + "\n"; - } - - if(true) return text;*/ - - /*for(Map.Entry<String, JsonObject> item : manager.getItemInformation().entrySet()) { - if(!item.getValue().has("infoType") || item.getValue().get("infoType").getAsString().isEmpty()) { - text += item.getKey() + "\n"; - } - }*/ - //if(true) return text; - for (String internalname : manager.auctionManager.getItemAuctionInfoKeySet()) { if (internalname.matches("^.*-[0-9]{1,3}$")) continue; if (!manager.getItemInformation().containsKey(internalname)) { @@ -86,23 +66,11 @@ public class DevInfoPane extends TextInfoPane { } } - /*for(Map.Entry<String, JsonElement> entry : manager.getAuctionPricesJson().get("prices").getAsJsonObject().entrySet()) { - if(!manager.getItemInformation().keySet().contains(entry.getKey())) { - if(entry.getKey().contains("-")) { - continue; - } - if(entry.getKey().startsWith("PERFECT")) continue; - if(Item.itemRegistry.getObject(new ResourceLocation(entry.getKey().toLowerCase())) != null) { - continue; - } - text += entry.getKey() + "\n"; - } - }*/ + return text; } //#region add vanilla items - AtomicBoolean running = new AtomicBoolean(false); ScheduledExecutorService ses = Executors.newScheduledThreadPool(1); @@ -555,7 +523,6 @@ public class DevInfoPane extends TextInfoPane { if (stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) { stacki += "-" + stack.getItemDamage(); } - //stacki += ":"+stack.stackSize; stacki += ":1"; } } @@ -595,7 +562,6 @@ public class DevInfoPane extends TextInfoPane { if (stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) { stacki += "-" + stack.getItemDamage(); } - //stacki += ":"+stack.stackSize; stacki += ":1"; } } @@ -645,7 +611,6 @@ public class DevInfoPane extends TextInfoPane { if (stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) { stacki += "-" + stack.getItemDamage(); } - //stacki += ":"+stack.stackSize; stacki += ":1"; } } @@ -689,7 +654,7 @@ public class DevInfoPane extends TextInfoPane { json.addProperty("modver", NotEnoughUpdates.VERSION); try { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + internalname)); + Utils.addChatMessage("Added: " + internalname); manager.writeJsonDefaultDir(json, internalname + ".json"); manager.loadItem(internalname); } catch (IOException ignored) { @@ -705,7 +670,6 @@ public class DevInfoPane extends TextInfoPane { for (String bukkit : bukkitList) { String internalname = bukkit.split("@")[0]; if (true || !manager.getItemInformation().containsKey(internalname)) { - //System.out.println("adding vanilla: " + internalname); String vanilla = internalname.toLowerCase().replace("_item", ""); if (bukkit.contains("@")) { vanilla = bukkit.split("@")[1]; @@ -750,7 +714,6 @@ public class DevInfoPane extends TextInfoPane { if (stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) { stacki += "-" + stack.getItemDamage(); } - //stacki += ":"+stack.stackSize; stacki += ":1"; } } @@ -801,7 +764,6 @@ public class DevInfoPane extends TextInfoPane { if (stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) { stacki += "-" + stack.getItemDamage(); } - //stacki += ":"+stack.stackSize; stacki += ":1"; } } @@ -839,7 +801,6 @@ public class DevInfoPane extends TextInfoPane { if (stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) { stacki += "-" + stack.getItemDamage(); } - //stacki += ":"+stack.stackSize; stacki += ":1"; } } @@ -887,7 +848,6 @@ public class DevInfoPane extends TextInfoPane { if (stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) { stacki += "-" + stack.getItemDamage(); } - //stacki += ":"+stack.stackSize; stacki += ":1"; } } @@ -919,7 +879,7 @@ public class DevInfoPane extends TextInfoPane { json.addProperty("clickcommand", ""); try { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + internalname)); + Utils.addChatMessage("Added: " + internalname); manager.writeJsonDefaultDir(json, internalname + ".json"); manager.loadItem(internalname); } catch (IOException ignored) { @@ -952,7 +912,7 @@ public class DevInfoPane extends TextInfoPane { json.addProperty("clickcommand", "viewrecipe"); json.add("recipe", entry.getValue()); try { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + internalname)); + Utils.addChatMessage("Added: " + internalname); if (entry.getKey() != 0 && entry.getKey() < 32000) { manager.writeJsonDefaultDir(json, internalname + "-" + entry.getKey() + ".json"); } else { @@ -967,126 +927,7 @@ public class DevInfoPane extends TextInfoPane { } } - //for(Map.Entry<String, JsonObject> item : manager.getItemInformation().entrySet()) { - /*if(!item.getValue().has("infoType") || item.getValue().get("infoType").getAsString().isEmpty()) { - if(item.getValue().has("info") && item.getValue().get("info").getAsJsonArray().size()>0) { - item.getValue().addProperty("infoType", "WIKI_URL"); - try { - manager.writeJsonDefaultDir(item.getValue(), item.getKey()+".json"); - } catch(IOException e){} - manager.loadItem(item.getKey()); - } - }*/ - /*if(item.getKey().startsWith("PET_ITEM_")) { - item.getValue().addProperty("infoType", "WIKI_URL"); - JsonArray array = new JsonArray(); - array.add(new JsonPrimitive("https://hypixel-skyblock.fandom.com/wiki/Pet_Items")); - item.getValue().add("info", array); - try { - manager.writeJsonDefaultDir(item.getValue(), item.getKey()+".json"); - } catch(IOException e){} - manager.loadItem(item.getKey()); - }*/ - /*if(!item.getValue().has("infoType") || item.getValue().get("infoType").getAsString().isEmpty()) { - //String prettyName = - - String itemS = item.getKey().split("-")[0].split(";")[0]; - StringBuilder prettyName = new StringBuilder(); - boolean capital = true; - for(int i=0; i<itemS.length(); i++) { - char c = itemS.charAt(i); - if(capital) { - prettyName.append(String.valueOf(c).toUpperCase()); - capital = false; - } else { - prettyName.append(String.valueOf(c).toLowerCase()); - } - if(String.valueOf(c).equals("_")) { - capital = true; - } - } - String prettyNameS = prettyName.toString(); - File f = manager.getWebFile("https://hypixel-skyblock.fandom.com/wiki/"+prettyNameS); - if(f == null) { - continue; - //#REDIRECT [[Armor of Magma]] - } - StringBuilder sb = new StringBuilder(); - try(BufferedReader br = new BufferedReader(new InputStreamReader( - new FileInputStream(f), StandardCharsets.UTF_8))) { - String l; - while((l = br.readLine()) != null){ - sb.append(l).append("\n"); - } - } catch(IOException e) { - continue; - } - if(sb.toString().isEmpty()) { - continue; - } - if(sb.toString().startsWith("#REDIRECT")) { - prettyNameS = sb.toString().split("\\[\\[")[1].split("]]")[0].replaceAll(" ", "_"); - } - item.getValue().addProperty("infoType", "WIKI_URL"); - JsonArray array = new JsonArray(); - array.add(new JsonPrimitive("https://hypixel-skyblock.fandom.com/wiki/"+prettyNameS)); - item.getValue().add("info", array); - try { - manager.writeJsonDefaultDir(item.getValue(), item.getKey()+".json"); - } catch(IOException e){} - manager.loadItem(item.getKey()); - }*/ } - - /*if(running.get()) { - List<String> add = new ArrayList<>(); - for(Map.Entry<String, JsonObject> item : manager.getItemInformation().entrySet()) { - if(item.getValue().has("recipe")) { - if(!item.getKey().contains("-") && !item.getKey().contains(";")) { - add.add(item.getKey()); - } - } - } - AtomicInteger index = new AtomicInteger(0); - - ses.schedule(new Runnable() { - public void run() { - if(!running.get()) return; - - int i = index.getAndIncrement(); - String item = add.get(i).split("-")[0].split(";")[0]; - Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewrecipe " + item); - ses.schedule(this, 1000L, TimeUnit.MILLISECONDS); - } - }, 1000L, TimeUnit.MILLISECONDS); - }*/ - //} - /*if(Keyboard.isKeyDown(Keyboard.KEY_J) && !running) { - running = true; - List<String> add = new ArrayList<>(); - for(Map.Entry<String, JsonElement> entry : manager.getAuctionPricesJson().get("prices").getAsJsonObject().entrySet()) { - if(!manager.getItemInformation().keySet().contains(entry.getKey())) { - if(entry.getKey().contains("-")) { - continue; - } - if(entry.getKey().startsWith("PERFECT")) continue; - if(Item.itemRegistry.getObject(new ResourceLocation(entry.getKey().toLowerCase())) != null) { - continue; - } - add.add(entry.getKey()); - } - } - AtomicInteger index = new AtomicInteger(0); - - ses.schedule(new Runnable() { - public void run() { - int i = index.getAndIncrement(); - String item = add.get(i).split("-")[0].split(";")[0]; - Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewrecipe " + item); - ses.schedule(this, 1000L, TimeUnit.MILLISECONDS); - } - }, 1000L, TimeUnit.MILLISECONDS); - }*/ return false; } //#endregion diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java index 71c4d498..7cc96d42 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java @@ -557,8 +557,6 @@ public class GuiElementTextField extends GuiElement { continue; } - //String c2 = bold ? EnumChatFormatting.BOLD.toString() : "" + c; - int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(String.valueOf(c)); if (bold) len++; if (i >= leftIndex && i < rightIndex) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java index f85c165a..6a94c0b3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java @@ -23,6 +23,7 @@ import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.dungeons.DungeonWin; import io.github.moulberry.notenoughupdates.miscfeatures.CookieWarning; import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver; +import io.github.moulberry.notenoughupdates.miscfeatures.EnderNodes; import io.github.moulberry.notenoughupdates.miscfeatures.StreamerMode; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; import io.github.moulberry.notenoughupdates.overlays.SlayerOverlay; @@ -201,11 +202,11 @@ public class ChatListener { String unformatted = Utils.cleanColour(e.message.getUnformattedText()); Matcher matcher = SLAYER_XP.matcher(unformatted); if (unformatted.startsWith("You are playing on profile: ")) { - neu.manager.setCurrentProfile(unformatted + SBInfo.getInstance().setCurrentProfile(unformatted .substring("You are playing on profile: ".length()) .split(" ")[0].trim()); } else if (unformatted.startsWith("Your profile was changed to: ")) {//Your profile was changed to: - neu.manager.setCurrentProfile(unformatted + SBInfo.getInstance().setCurrentProfile(unformatted .substring("Your profile was changed to: ".length()) .split(" ")[0].trim()); } else if (unformatted.startsWith("Your new API key is ")) { @@ -214,8 +215,7 @@ public class ChatListener { 0, 36 ); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "[NEU] API Key automatically configured")); + Utils.addChatMessage(EnumChatFormatting.YELLOW + "[NEU] API Key automatically configured"); NotEnoughUpdates.INSTANCE.saveConfig(); } else if (unformatted.startsWith("Player List Info is now disabled!")) { SBInfo.getInstance().hasNewTab = false; @@ -242,7 +242,6 @@ public class ChatListener { } else if (unformatted.startsWith(" RNG Meter")) { RNGMeter = unformatted.substring(" RNG Meter - ".length()); } else if (matcher.matches()) { - //matcher.group(1); SlayerOverlay.slayerLVL = matcher.group(2); if (!SlayerOverlay.slayerLVL.equals("9")) { SlayerOverlay.slayerXp = matcher.group(3); @@ -308,5 +307,9 @@ public class ChatListener { unformatted.equals("You have successfully picked the lock on this chest!") || (unformatted.startsWith("You received +") && unformatted.endsWith(" Powder"))) OverlayManager.powderGrindingOverlay.message(unformatted); + + if (unformatted.equals("ENDER NODE! You found Endermite Nest!")) { + EnderNodes.dispalyEndermiteNotif(); + } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java index d89e886f..27e7cfc6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java @@ -29,6 +29,7 @@ import io.github.moulberry.notenoughupdates.ItemPriceInformation; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.MiscUtils; import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager; import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; import io.github.moulberry.notenoughupdates.miscgui.GuiEnchantColour; import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; @@ -60,6 +61,7 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TreeSet; import java.util.regex.Matcher; @@ -79,6 +81,80 @@ public class ItemTooltipListener { private boolean pressedShiftLast = false; private int sbaloaded = -1; + //region Enchant optimisation + private String lastItemUuid; + + public static class EnchantString { + final String preEnchantText; + final String enchantName; + + final String mod; + final String colourCode; + final boolean isChroma; + + public EnchantString(String enchant, String preEnchantText, String modifier, String colourCode) { + this.preEnchantText = preEnchantText; + this.enchantName = enchant; + this.mod = modifier; + this.colourCode = colourCode; + this.isChroma = colourCode.equals("z"); + } + + private boolean matches(String line) { + return line.matches(".*" + preEnchantText + enchantName + ".*"); + } + + public String applyMods(String line, int lineIndex) { + if (!matches(line)) return null; + + if (!isChroma) { + return line.replace(preEnchantText + enchantName, + "\u00A7" + colourCode + mod + enchantName + ); + } else { + //if you couldn't tell, this is for chroma. + int newOffset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(preEnchantText + enchantName); + return line.replace( + preEnchantText + enchantName, + Utils.chromaString(enchantName, newOffset / 12f + lineIndex, preEnchantText.matches(".*\\u00A7d.*")) + ); + } + } +} + +public static class EnchantLine { + final String originalLine; + final ArrayList<EnchantString> enchants; + + public EnchantLine(String line, ArrayList<EnchantString> enchants) { + this.enchants = enchants; + this.originalLine = line; + } + + public boolean isSameAsBefore(String line) { + return line.equals(originalLine); + } + + public String replaceLine(String line, int index) { + if (line.equals(originalLine)) { + for (EnchantString enchant: enchants) { + String modifiedLine = enchant.applyMods(line, index); + if (modifiedLine != null) { + line = modifiedLine; + } + } + } + + return line; + } +} + + private final ArrayList<EnchantLine> enchantList = new ArrayList<>(); + private int firstEnchantIndex = -1; + private int lastEnchantIndex = -1; + + //endregion + public ItemTooltipListener(NotEnoughUpdates neu) { this.neu = neu; percentStats.add("bonus_attack_speed"); @@ -175,12 +251,26 @@ public class ItemTooltipListener { boolean gotToEnchants = false; boolean passedEnchants = false; + boolean foundEnchants = false; boolean dungeonProfit = false; - int index = 0; List<String> newTooltip = new ArrayList<>(); - for (String line : event.toolTip) { + String currentUuid = ItemCustomizeManager.getUuidForItem(event.itemStack); + + boolean resetEnchantCache = false; + //reset data if cache is off + if (!NotEnoughUpdates.INSTANCE.config.misc.cacheItemEnchant) { + lastItemUuid = null; + firstEnchantIndex = -1; + lastEnchantIndex = -1; + enchantList.clear(); + } + + for (int k = 0; k < event.toolTip.size(); k++) { + String line = event.toolTip.get(k); + boolean thisLineHasEnchants = false; + if (line.endsWith(EnumChatFormatting.DARK_GRAY + "Reforge Stone") && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showReforgeStats) { JsonObject reforgeStones = Constants.REFORGESTONES; @@ -327,7 +417,7 @@ public class ItemTooltipListener { } else if (line.contains("\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune")) { line = line.replace( "\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune", - Utils.chromaString("Rainbow Rune", index, false) + EnumChatFormatting.BLUE + Utils.chromaString("Rainbow Rune", k, false) + EnumChatFormatting.BLUE ); } else if (hasEnchantments) { if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && @@ -381,144 +471,182 @@ public class ItemTooltipListener { } } if (hasEnchantments || hasAttributes) { - ArrayList<String> addedEnchants = new ArrayList<>(); - for (String op : NotEnoughUpdates.INSTANCE.config.hidden.enchantColours) { - List<String> colourOps = GuiEnchantColour.splitter.splitToList(op); - String enchantName = GuiEnchantColour.getColourOpIndex(colourOps, 0); - String comparator = GuiEnchantColour.getColourOpIndex(colourOps, 1); - String comparison = GuiEnchantColour.getColourOpIndex(colourOps, 2); - String colourCode = GuiEnchantColour.getColourOpIndex(colourOps, 3); - String modifier = GuiEnchantColour.getColourOpIndex(colourOps, 4); - - int modifierI = GuiEnchantColour.getIntModifier(modifier); - - assert enchantName != null; - if (enchantName.length() == 0) continue; - assert comparator != null; - if (comparator.length() == 0) continue; - assert comparison != null; - if (comparison.length() == 0) continue; - assert colourCode != null; - if (colourCode.length() == 0) continue; - - int comparatorI = ">=<".indexOf(comparator.charAt(0)); - - int levelToFind; - try { - levelToFind = Integer.parseInt(comparison); - } catch (Exception e) { - continue; - } - - if (comparatorI < 0) continue; - String regexText = "0123456789abcdefz"; - if (isSkyblockAddonsLoaded()) { - regexText = regexText + "Z"; + Pattern findEnchantPattern = Pattern.compile(".*(?<enchant>[\\w ]+) (?<level>[0-9]+|[IVXLCDM]+)$"); + Matcher findEnchantMatcher = findEnchantPattern.matcher(line); + if (findEnchantMatcher.matches()) { + if (NotEnoughUpdates.INSTANCE.config.misc.cacheItemEnchant && !foundEnchants) { + foundEnchants = true; + if (( + lastItemUuid == null || currentUuid == null || + (currentUuid != null && + !Objects.equals(lastItemUuid, currentUuid)))) { + firstEnchantIndex = k;//k being the line index + lastEnchantIndex = k; + enchantList.clear(); + } } + thisLineHasEnchants = true; + } - if (regexText.indexOf(colourCode.charAt(0)) < 0) continue; + ArrayList<String> addedEnchants = new ArrayList<>(); + //if cacheItemEnchant option is disabled it will always be length of 0 + if (enchantList.size() == 0 || enchantList.size() <= k - firstEnchantIndex) { + ArrayList<EnchantString> enchants = new ArrayList<>(); + final String oLine = line; + + for (String op : NotEnoughUpdates.INSTANCE.config.hidden.enchantColours) { + List<String> colourOps = GuiEnchantColour.splitter.splitToList(op); + String enchantName = GuiEnchantColour.getColourOpIndex(colourOps, 0); + String comparator = GuiEnchantColour.getColourOpIndex(colourOps, 1); + String comparison = GuiEnchantColour.getColourOpIndex(colourOps, 2); + String colourCode = GuiEnchantColour.getColourOpIndex(colourOps, 3); + String modifier = GuiEnchantColour.getColourOpIndex(colourOps, 4); + + int modifierI = GuiEnchantColour.getIntModifier(modifier); + + assert enchantName != null; + if (enchantName.length() == 0) continue; + assert comparator != null; + if (comparator.length() == 0) continue; + assert comparison != null; + if (comparison.length() == 0) continue; + assert colourCode != null; + if (colourCode.length() == 0) continue; + + int comparatorI = ">=<".indexOf(comparator.charAt(0)); + + int levelToFind; + try { + levelToFind = Integer.parseInt(comparison); + } catch (Exception e) { + continue; + } - //item_lore = item_lore.replaceAll("\\u00A79("+lvl4Max+" IV)", EnumChatFormatting.DARK_PURPLE+"$1"); - //9([a-zA-Z ]+?) ([0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X))(,|$) - Pattern pattern; - try { - pattern = Pattern.compile( - "(\\u00A7b|\\u00A79|\\u00A7(b|9|l)\\u00A7d\\u00A7l)(?<enchantName>" + enchantName + ") " + - "(?<level>[0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV|XVI|XVII|XVIII|XIX|XX))((\\u00A79)?,|( \\u00A78(?:,?[0-9]+)*)?$)"); - } catch (Exception e) { - continue; - } - Matcher matcher = pattern.matcher(line); - int matchCount = 0; - while (matcher.find() && matchCount < 5) { - if (Utils.cleanColour(matcher.group("enchantName")).startsWith(" ")) continue; - - matchCount++; - int level = -1; - String levelStr = matcher.group("level"); - if (levelStr == null || levelStr.isEmpty()) continue; - level = Utils.parseIntOrRomanNumeral(levelStr); - boolean matches = false; - if (level > 0) { - switch (comparator) { - case ">": - matches = level > levelToFind; - break; - case "=": - matches = level == levelToFind; - break; - case "<": - matches = level < levelToFind; - break; - } + if (comparatorI < 0) continue; + String regexText = "0123456789abcdefz"; + if (isSkyblockAddonsLoaded()) { + regexText = regexText + "Z"; } - if (matches) { - String enchantText = matcher.group("enchantName"); - StringBuilder extraModifiersBuilder = new StringBuilder(); - if ((modifierI & GuiEnchantColour.BOLD_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.BOLD); - } - if ((modifierI & GuiEnchantColour.ITALIC_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.ITALIC); - } - if ((modifierI & GuiEnchantColour.UNDERLINE_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.UNDERLINE); - } - if ((modifierI & GuiEnchantColour.OBFUSCATED_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.OBFUSCATED); - } - if ((modifierI & GuiEnchantColour.STRIKETHROUGH_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.STRIKETHROUGH); + if (regexText.indexOf(colourCode.charAt(0)) < 0) continue; + + //item_lore = item_lore.replaceAll("\\u00A79("+lvl4Max+" IV)", EnumChatFormatting.DARK_PURPLE+"$1"); + //9([a-zA-Z ]+?) ([0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X))(,|$) + Pattern pattern; + try { + pattern = Pattern.compile( + "(\\u00A7b|\\u00A79|\\u00A7(b|9|l)\\u00A7d\\u00A7l)(?<enchantName>" + enchantName + ") " + + "(?<level>[0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV|XVI|XVII|XVIII|XIX|XX))((\\u00A79)?,|( \\u00A78(?:,?[0-9]+)*)?$)"); + } catch (Exception e) { + continue; + } + Matcher matcher = pattern.matcher(oLine); + int matchCount = 0; + while (matcher.find() && matchCount < 5) { + if (Utils.cleanColour(matcher.group("enchantName")).startsWith(" ")) continue; + + matchCount++; + int level = -1; + String levelStr = matcher.group("level"); + if (levelStr == null || levelStr.isEmpty()) continue; + level = Utils.parseIntOrRomanNumeral(levelStr); + boolean matches = false; + if (level > 0) { + switch (comparator) { + case ">": + matches = level > levelToFind; + break; + case "=": + matches = level == levelToFind; + break; + case "<": + matches = level < levelToFind; + break; + } } + if (matches) { + String enchantText = matcher.group("enchantName"); + StringBuilder extraModifiersBuilder = new StringBuilder(); - String extraMods = extraModifiersBuilder.toString(); + if ((modifierI & GuiEnchantColour.BOLD_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.BOLD); + } + if ((modifierI & GuiEnchantColour.ITALIC_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.ITALIC); + } + if ((modifierI & GuiEnchantColour.UNDERLINE_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.UNDERLINE); + } + if ((modifierI & GuiEnchantColour.OBFUSCATED_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.OBFUSCATED); + } + if ((modifierI & GuiEnchantColour.STRIKETHROUGH_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.STRIKETHROUGH); + } + + String extraMods = extraModifiersBuilder.toString(); + if (!colourCode.equals("z")) { + if (!addedEnchants.contains(enchantText)) { + int startMatch = matcher.start(); + int endMatch = matcher.end(); + String subString = oLine.substring(startMatch, endMatch); + String preEnchantText = subString.split(String.valueOf(enchantText.charAt(0)))[0]; + + line = line.replace(preEnchantText + enchantText, + "\u00A7" + colourCode + extraMods + enchantText + ); + + enchants.add(new EnchantString( + enchantText, + preEnchantText, + extraMods, + colourCode + )); + } + } else { + //Chroma + int startMatch = matcher.start(); + int endMatch = matcher.end(); + String subString = line.substring(startMatch, endMatch); + int newOffset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(subString); + + //split the substring with the first letter found in enchant text allowing to only get the color codes. + String preEnchantText = subString.split(String.valueOf(enchantText.charAt(0)))[0]; - if (!colourCode.equals("z")) { - if (!addedEnchants.contains(enchantText)) { - line = line.replace("\u00A79" + enchantText, "\u00A7" + colourCode + extraMods + enchantText); - line = line.replace("\u00A7b" + enchantText, "\u00A7" + colourCode + extraMods + enchantText); - line = line.replace( - "\u00A79\u00A7d\u00A7l" + enchantText, - "\u00A7" + colourCode + extraMods + enchantText - ); - line = line.replace( - "\u00A7b\u00A7d\u00A7l" + enchantText, - "\u00A7" + colourCode + extraMods + enchantText - ); line = line.replace( - "\u00A7l\u00A7d\u00A7l" + enchantText, - "\u00A7" + colourCode + extraMods + enchantText + preEnchantText + enchantText, + Utils.chromaString(enchantText, newOffset / 12f + k, preEnchantText.matches(".*\\u00A7d.*")) ); + enchants.add(new EnchantString( + enchantText, + preEnchantText, + extraMods, + colourCode + )); } - } else { - int offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( - "\\u00A79" + enchantText + ".*", - "" - )); - line = line.replace( - "\u00A79" + enchantText, - Utils.chromaString(enchantText, offset / 12f + index, false) - ); - - offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( - "\\u00A79\\u00A7d\\u00A7l" + enchantText + ".*", - "" - )); - line = line.replace( - "\u00A79\u00A7d\u00A7l" + enchantText, - Utils.chromaString(enchantText, offset / 12f + index, true) - ); - offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( - "\\u00A7l\\u00A7d\\u00A7l" + enchantText + ".*", - "" - )); - line = line.replace( - "\u00A7l\u00A7d\u00A7l" + enchantText, - Utils.chromaString(enchantText, offset / 12f + index, true) - ); + addedEnchants.add(enchantText); + } + } + } + if (NotEnoughUpdates.INSTANCE.config.misc.cacheItemEnchant) { + if (lastItemUuid == null || !Objects.equals(lastItemUuid, currentUuid)) { + EnchantLine enchantLine = new EnchantLine(oLine, enchants); + enchantList.add(enchantLine); + } + } + } + + if (NotEnoughUpdates.INSTANCE.config.misc.cacheItemEnchant && foundEnchants) { + //found enchants in the past + if (k <= lastEnchantIndex) { + if (Objects.equals(lastItemUuid, currentUuid) && (firstEnchantIndex != -1 && enchantList.size() > k - firstEnchantIndex) && (k - firstEnchantIndex) > 0) { + //if it has the line, replaces it with the cached line + EnchantLine enchantLine = enchantList.get(k - firstEnchantIndex); + if (!enchantLine.isSameAsBefore(line)) { + resetEnchantCache = true; } - addedEnchants.add(enchantText); + + line = enchantLine.replaceLine(line, k); } } } @@ -543,7 +671,7 @@ public class ItemTooltipListener { Minecraft.getMinecraft().currentScreen instanceof GuiChest) { if (line.contains(EnumChatFormatting.GREEN + "Open Reward Chest")) { dungeonProfit = true; - } else if (index == 7 && dungeonProfit) { + } else if (k == 7 && dungeonProfit) { GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; ContainerChest cc = (ContainerChest) eventGui.inventorySlots; IInventory lower = cc.getLowerChestInventory(); @@ -688,11 +816,9 @@ public class ItemTooltipListener { } } } - - index++; + if (thisLineHasEnchants) lastEnchantIndex+=1; } - pressedShiftLast = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); pressedArrowLast = Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_RIGHT); @@ -707,6 +833,18 @@ public class ItemTooltipListener { NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip) { event.toolTip.clear(); } + + + if (foundEnchants && currentUuid != null && lastItemUuid != currentUuid) { + lastItemUuid = currentUuid;//cache is set; + } + + if (resetEnchantCache) { + lastItemUuid = null; + enchantList.clear(); + firstEnchantIndex = -1; + lastEnchantIndex = -1; + } } private void petToolTipXPExtendPetMenu(ItemTooltipEvent event) { @@ -843,7 +981,6 @@ public class ItemTooltipListener { MiscUtils.copyToClipboard(NotEnoughUpdates.INSTANCE.manager.getSkullValueForItem(event.itemStack)); } - event.toolTip.add( EnumChatFormatting.AQUA + "Internal Name: " + EnumChatFormatting.GRAY + internal + EnumChatFormatting.GOLD + " [K]"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java index fdae53ea..2b7a9bef 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java @@ -139,7 +139,7 @@ public class ItemTooltipRngListener { private String getFormatCoinsPer(ItemStack stack, int needed, int multiplier, String label) { String internalName = neu.manager.createItemResolutionQuery().withItemStack(stack).resolveInternalName(); - double profit = neu.manager.auctionManager.getBazaarOrBin(internalName); + double profit = neu.manager.auctionManager.getBazaarOrBin(internalName, false); if (profit <= 0) return null; //ask hypixel nicely to release a 'chest price api' with 4 dimensions for us. the 4 dimensions needed are: item name, floor, normal/mm, s/s+ diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java index e202b828..5b388dea 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java @@ -34,11 +34,13 @@ import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager; import io.github.moulberry.notenoughupdates.miscfeatures.NPCRetexturing; import io.github.moulberry.notenoughupdates.miscgui.AccessoryBagOverlay; import io.github.moulberry.notenoughupdates.miscgui.GuiCustomEnchant; +import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe; import io.github.moulberry.notenoughupdates.miscgui.hex.GuiCustomHex; import io.github.moulberry.notenoughupdates.miscgui.StorageOverlay; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; import io.github.moulberry.notenoughupdates.overlays.TextOverlay; import io.github.moulberry.notenoughupdates.overlays.TextTabOverlay; +import io.github.moulberry.notenoughupdates.recipes.RecipeHistory; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.NotificationHandler; import io.github.moulberry.notenoughupdates.util.ProfileApiSyncer; @@ -162,6 +164,11 @@ public class NEUEventListener { if (longUpdate) { + + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiItemRecipe)) { + RecipeHistory.clear(); + } + CrystalOverlay.tick(); FairySouls.getInstance().tick(); XPInformation.getInstance().tick(); @@ -235,35 +242,24 @@ public class NEUEventListener { if (!NotEnoughUpdates.INSTANCE.config.hidden.loadedModBefore) { NotEnoughUpdates.INSTANCE.config.hidden.loadedModBefore = true; if (Constants.MISC == null || !Constants.MISC.has("featureslist")) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "" + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "WARNING: " + EnumChatFormatting.RESET + - EnumChatFormatting.RED + "Could not load Feature List URL from repo.")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "" + EnumChatFormatting.RED + "Please run " + EnumChatFormatting.BOLD + "/neuresetrepo" + - EnumChatFormatting.RESET + EnumChatFormatting.RED + " and " + EnumChatFormatting.BOLD + - "restart your game" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " in order to fix. " + - EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "If that doesn't fix it" + - EnumChatFormatting.RESET + EnumChatFormatting.RED + - ", please join discord.gg/moulberry and post in #neu-support")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "" + EnumChatFormatting.GOLD + "To view the feature list after restarting type /neufeatures")); + Utils.showOutdatedRepoNotification(); + Utils.addChatMessage( + "" + EnumChatFormatting.GOLD + "To view the feature list after restarting type /neufeatures"); } else { String url = Constants.MISC.get("featureslist").getAsString(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.BLUE + "It seems this is your first time using NotEnoughUpdates.")); + Utils.addChatMessage(""); + Utils.addChatMessage(EnumChatFormatting.BLUE + "It seems this is your first time using NotEnoughUpdates."); ChatComponentText clickTextFeatures = new ChatComponentText(EnumChatFormatting.YELLOW + "Click this message if you would like to view a list of NotEnoughUpdate's Features."); clickTextFeatures.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, url)); Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextFeatures); } - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + Utils.addChatMessage(""); ChatComponentText clickTextHelp = new ChatComponentText(EnumChatFormatting.YELLOW + "Click this message if you would like to view a list of NotEnoughUpdate's commands."); clickTextHelp.setChatStyle(Utils.createClickStyle(ClickEvent.Action.RUN_COMMAND, "/neuhelp")); Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextHelp); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + Utils.addChatMessage(""); } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java index 2abb2ee8..949358ad 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java @@ -40,6 +40,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.AuctionBINWarning; import io.github.moulberry.notenoughupdates.miscfeatures.AuctionProfit; import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers; import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver; +import io.github.moulberry.notenoughupdates.miscfeatures.DungeonNpcProfitOverlay; import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager; import io.github.moulberry.notenoughupdates.miscgui.AccessoryBagOverlay; @@ -50,6 +51,7 @@ import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe; import io.github.moulberry.notenoughupdates.miscgui.StorageOverlay; import io.github.moulberry.notenoughupdates.miscgui.TradeWindow; import io.github.moulberry.notenoughupdates.miscgui.TrophyRewardOverlay; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; import io.github.moulberry.notenoughupdates.miscgui.hex.GuiCustomHex; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; import io.github.moulberry.notenoughupdates.options.NEUConfig; @@ -83,7 +85,6 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StringUtils; @@ -136,6 +137,8 @@ public class RenderListener { public static long lastGuiClosed = 0; public static boolean inventoryLoaded = false; private final NotEnoughUpdates neu; + private final NumberFormat format = new DecimalFormat("#,##0.#", new DecimalFormatSymbols(Locale.US)); + private final Pattern ESSENCE_PATTERN = Pattern.compile("§d(.+) Essence §8x([\\d,]+)"); ScheduledExecutorService ses = Executors.newScheduledThreadPool(1); JsonObject essenceJson = new JsonObject(); private boolean hoverInv = false; @@ -150,9 +153,6 @@ public class RenderListener { private boolean typing; private HashMap<String, String> cachedDefinitions; private boolean inDungeonPage = false; - private final NumberFormat format = new DecimalFormat("#,##0.#", new DecimalFormatSymbols(Locale.US)); - - private final Pattern ESSENCE_PATTERN = Pattern.compile("§d(.+) Essence §8x([\\d,]+)"); public RenderListener(NotEnoughUpdates neu) { this.neu = neu; @@ -327,8 +327,7 @@ public class RenderListener { JsonObject json = neu.manager.getItemInformation().get(resInternalname); json.addProperty("crafttext", "Requires: " + col); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "Added: " + resInternalname)); + Utils.addChatMessage("Added: " + resInternalname); neu.manager.writeJsonDefaultDir(json, resInternalname + ".json"); neu.manager.loadItem(resInternalname); } @@ -459,7 +458,6 @@ public class RenderListener { return; } - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); boolean customAhActive = @@ -538,6 +536,12 @@ public class RenderListener { x += diffX; } } + if (MinionHelperManager.getInstance().inCraftedMinionsInventory()) { + int diffX = 172; + if (x > guiLeft + xSize && x < guiLeft + xSize + diffX + 5 && y > guiTop - 18 && y < guiTop + 128) { + x += diffX; + } + } if (AuctionProfit.inAuctionPage()) { if (x + 18 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && y < guiTop + 56) { @@ -554,7 +558,7 @@ public class RenderListener { x -= 25; } } - if (inDungeonPage) { + if (inDungeonPage || DungeonNpcProfitOverlay.isRendering()) { if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && y < guiTop + 100) { x += 185; @@ -666,6 +670,12 @@ public class RenderListener { x += diffX; } } + if (MinionHelperManager.getInstance().inCraftedMinionsInventory()) { + int diffX = 172; + if (x > guiLeft + xSize && x < guiLeft + xSize + diffX + 5 && y > guiTop - 18 && y < guiTop + 128) { + x += diffX; + } + } if (AuctionProfit.inAuctionPage()) { if (x + 18 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && y < guiTop + 56) { @@ -683,7 +693,7 @@ public class RenderListener { } } - if (inDungeonPage) { + if (inDungeonPage || DungeonNpcProfitOverlay.isRendering()) { if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && y < guiTop + 100) { x += 185; @@ -801,7 +811,7 @@ public class RenderListener { if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000; double worth = -1; - boolean isOnBz = false; + boolean isOnBz = false; if (bazaarPrice >= 0) { worth = bazaarPrice; isOnBz = true; @@ -1075,7 +1085,6 @@ public class RenderListener { return; } - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); boolean customAhActive = @@ -1143,6 +1152,12 @@ public class RenderListener { x += diffX; } } + if (MinionHelperManager.getInstance().inCraftedMinionsInventory()) { + int diffX = 172; + if (x > guiLeft + xSize && x < guiLeft + xSize + diffX + 5 && y > guiTop - 18 && y < guiTop + 128) { + x += diffX; + } + } if (AuctionProfit.inAuctionPage()) { if (x + 18 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && y < guiTop + 56) { @@ -1159,7 +1174,7 @@ public class RenderListener { x -= 25; } } - if (inDungeonPage) { + if (inDungeonPage || DungeonNpcProfitOverlay.isRendering()) { if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && y < guiTop + 100) { x += 185; @@ -1306,17 +1321,15 @@ public class RenderListener { )) ) { writer.write(gson.toJson(jsonObject)); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.AQUA + "Parsed and saved: " + EnumChatFormatting.WHITE + id)); + Utils.addChatMessage(EnumChatFormatting.AQUA + "Parsed and saved: " + EnumChatFormatting.WHITE + id); } } catch (IOException ignored) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "Error while writing file.")); + Utils.addChatMessage(EnumChatFormatting.RED + "Error while writing file."); } } catch (Exception e) { e.printStackTrace(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "Error while parsing inventory. Try again or check logs for details.")); + Utils.addChatMessage( + EnumChatFormatting.RED + "Error while parsing inventory. Try again or check logs for details."); } } } else if (Keyboard.isKeyDown(Keyboard.KEY_RETURN) && NotEnoughUpdates.INSTANCE.config.hidden.dev) { @@ -1411,8 +1424,7 @@ public class RenderListener { } else if (cachedDefinitions.containsKey(item)) { costArray.add(new JsonPrimitive(cachedDefinitions.get(item) + ":" + amountString)); } else { - mc.thePlayer.addChatMessage(new ChatComponentText( - "Change the item ID of " + item + " to the correct one and press Enter.")); + Utils.addChatMessage("Change the item ID of " + item + " to the correct one and press Enter."); NEUOverlay.getTextField().setText(item); event.setCanceled(true); typing = true; @@ -1441,17 +1453,16 @@ public class RenderListener { )) ) { writer.write(gson.toJson(newNPC)); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.AQUA + "Parsed and saved: " + EnumChatFormatting.WHITE + displayName)); + Utils.addChatMessage( + EnumChatFormatting.AQUA + "Parsed and saved: " + EnumChatFormatting.WHITE + displayName); } } catch (IOException ignored) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "Error while writing file.")); + Utils.addChatMessage(EnumChatFormatting.RED + "Error while writing file."); } } catch (Exception e) { e.printStackTrace(); - mc.thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "Error while parsing inventory. Try again or check logs for details")); + Utils.addChatMessage( + EnumChatFormatting.RED + "Error while parsing inventory. Try again or check logs for details"); } } } else if (NotEnoughUpdates.INSTANCE.config.hidden.dev && Keyboard.isKeyDown(Keyboard.KEY_B) && @@ -1471,9 +1482,9 @@ public class RenderListener { if (stack.getDisplayName().isEmpty() || stack.getDisplayName().equals(" ")) continue; String internalName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack); if (internalName == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + Utils.addChatMessage( EnumChatFormatting.RED + "ERROR: Could not get internal name for: " + EnumChatFormatting.AQUA + - stack.getDisplayName())); + stack.getDisplayName()); continue; } JsonObject itemObject = NotEnoughUpdates.INSTANCE.manager.getJsonForItem(stack); @@ -1493,13 +1504,11 @@ public class RenderListener { itemObject.add("lore", newLore); if (!NEUItemEditor.saveOnly(internalName, itemObject)) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "ERROR: Failed to save item: " + EnumChatFormatting.AQUA + - stack.getDisplayName())); + Utils.addChatMessage( + EnumChatFormatting.RED + "ERROR: Failed to save item: " + EnumChatFormatting.AQUA + stack.getDisplayName()); } } - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.AQUA + "Parsed page: " + lower.getDisplayName().getUnformattedText())); + Utils.addChatMessage(EnumChatFormatting.AQUA + "Parsed page: " + lower.getDisplayName().getUnformattedText()); event.setCanceled(true); return; } @@ -1553,7 +1562,6 @@ public class RenderListener { return; } - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); boolean customAhActive = @@ -1703,7 +1711,7 @@ public class RenderListener { json.addProperty("clickcommand", "viewrecipe"); json.addProperty("modver", NotEnoughUpdates.VERSION); try { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname)); + Utils.addChatMessage("Added: " + resInternalname); neu.manager.writeJsonDefaultDir(json, resInternalname + ".json"); neu.manager.loadItem(resInternalname); } catch (IOException ignored) { @@ -1717,4 +1725,24 @@ public class RenderListener { public void onRenderLast(RenderWorldLastEvent event) { CrystalMetalDetectorSolver.render(event.partialTicks); } + + /** + * Support for switching between different pages in the RecipeView gui via right and left arrow key + * @param event + */ + //Because GuiScreen.keyTyped does not fire the KEY_LEFT and KEY_RIGHT keys. Maybe some event cancelled it? + @SubscribeEvent + public void onMouseClick(GuiScreenEvent.KeyboardInputEvent.Post event) { + + if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return; + + Minecraft minecraft = Minecraft.getMinecraft(); + if (minecraft == null || minecraft.thePlayer == null) return; + + GuiScreen screen = minecraft.currentScreen; + if (screen instanceof GuiItemRecipe) { + GuiItemRecipe itemRecipe = (GuiItemRecipe) screen; + itemRecipe.arrowKeyboardInput(); + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ScoreboardLocationChangeListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ScoreboardLocationChangeListener.java index 622b2088..3727a441 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ScoreboardLocationChangeListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ScoreboardLocationChangeListener.java @@ -31,10 +31,10 @@ public class ScoreboardLocationChangeListener { try { Thread.sleep(3000); TimersOverlay.afterPearls = TimersOverlay.heavyPearlCount(); - //Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW+"You exited the beast with ["+EnumChatFormatting.AQUA+(TimersOverlay.afterPearls-TimersOverlay.beforePearls)+EnumChatFormatting.YELLOW+"/"+EnumChatFormatting.AQUA+TimersOverlay.availablePearls+EnumChatFormatting.YELLOW+"] Heavy Pearls!")); + //Utils.sendMessageToPlayer(EnumChatFormatting.YELLOW+"You exited the beast with ["+EnumChatFormatting.AQUA+(TimersOverlay.afterPearls-TimersOverlay.beforePearls)+EnumChatFormatting.YELLOW+"/"+EnumChatFormatting.AQUA+TimersOverlay.availablePearls+EnumChatFormatting.YELLOW+"] Heavy Pearls!"); if (TimersOverlay.afterPearls - TimersOverlay.beforePearls == TimersOverlay.availablePearls) { NotEnoughUpdates.INSTANCE.config.getProfileSpecific().dailyHeavyPearlCompleted = System.currentTimeMillis(); - //Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+"Daily "+EnumChatFormatting.DARK_AQUA+"Heavy Pearls"+EnumChatFormatting.GREEN+" Complete!")); + //Utils.sendMessageToPlayer(EnumChatFormatting.GREEN+"Daily "+EnumChatFormatting.DARK_AQUA+"Heavy Pearls"+EnumChatFormatting.GREEN+" Complete!"); } } catch (InterruptedException e) { e.printStackTrace(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CookieWarning.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CookieWarning.java index f21d0c50..fede9bdf 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CookieWarning.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CookieWarning.java @@ -23,8 +23,8 @@ import com.google.common.collect.Lists; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiPlayerTabOverlay; import io.github.moulberry.notenoughupdates.util.NotificationHandler; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; public class CookieWarning { @@ -94,9 +94,8 @@ public class CookieWarning { } } catch (NumberFormatException e) { e.printStackTrace(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + - "NEU ran into an issue when retrieving the Booster Cookie Timer. Check the logs for details.")); + Utils.addChatMessage(EnumChatFormatting.RED + + "NEU ran into an issue when retrieving the Booster Cookie Timer. Check the logs for details."); hasNotified = true; } if (minutes < NotEnoughUpdates.INSTANCE.config.notifications.boosterCookieWarningMins && !hasNotified) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java index ab9345cb..23115c36 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java @@ -25,10 +25,10 @@ import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag; import io.github.moulberry.notenoughupdates.util.NEUDebugLogger; import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.entity.item.EntityArmorStand; import net.minecraft.util.BlockPos; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; import net.minecraft.util.Vec3i; @@ -169,7 +169,7 @@ public class CrystalMetalDetectorSolver { NEUDebugLogger.log(NEUDebugFlag.METAL, "Known location identified."); // falls through case FOUND: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] Found solution.")); + Utils.addChatMessage(EnumChatFormatting.YELLOW + "[NEU] Found solution."); if (NEUDebugFlag.METAL.isSet() && (previousState == SolutionState.INVALID || previousState == SolutionState.FAILED)) { NEUDebugLogger.log( @@ -180,14 +180,12 @@ public class CrystalMetalDetectorSolver { } break; case INVALID: - mc.thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "[NEU] Previous solution is invalid.")); + Utils.addChatMessage(EnumChatFormatting.RED + "[NEU] Previous solution is invalid."); logDiagnosticData(false); resetSolution(false); break; case FAILED: - mc.thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "[NEU] Failed to find a solution.")); + Utils.addChatMessage(EnumChatFormatting.RED + "[NEU] Failed to find a solution."); logDiagnosticData(false); resetSolution(false); break; @@ -195,8 +193,9 @@ public class CrystalMetalDetectorSolver { NEUDebugLogger.log(NEUDebugFlag.METAL, "Multiple known locations identified:"); // falls through case MULTIPLE: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + - "[NEU] Need another position to find solution. Possible blocks: " + possibleBlocks.size())); + Utils.addChatMessage( + EnumChatFormatting.YELLOW + "[NEU] Need another position to find solution. Possible blocks: " + + possibleBlocks.size()); break; default: throw new IllegalStateException("Metal detector is in invalid state"); @@ -372,8 +371,8 @@ public class CrystalMetalDetectorSolver { if (keeperEntities.size() == 0) { if (!visitKeeperMessagePrinted) { - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + - "[NEU] Approach a Keeper while holding the metal detector to enable faster treasure hunting.")); + Utils.addChatMessage(EnumChatFormatting.YELLOW + + "[NEU] Approach a Keeper while holding the metal detector to enable faster treasure hunting."); visitKeeperMessagePrinted = true; } return false; @@ -387,8 +386,8 @@ public class CrystalMetalDetectorSolver { minesCenter = keeperEntity.getPosition().add(keeperOffsets.get(keeperType.toLowerCase())); NEUDebugLogger.log(NEUDebugFlag.METAL, "Mines center: " + EnumChatFormatting.WHITE + minesCenter.toString()); - mc.thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "[NEU] Faster treasure hunting is now enabled based on Keeper location.")); + Utils.addChatMessage( + EnumChatFormatting.YELLOW + "[NEU] Faster treasure hunting is now enabled based on Keeper location."); return true; } @@ -560,8 +559,7 @@ public class CrystalMetalDetectorSolver { } if (!NotEnoughUpdates.INSTANCE.config.mining.metalDetectorEnabled) { - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "[NEU] Metal Detector Solver is not enabled.")); + Utils.addChatMessage(EnumChatFormatting.RED + "[NEU] Metal Detector Solver is not enabled."); return; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java index 21d1d4a3..50975af9 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java @@ -234,35 +234,35 @@ public class CrystalWishingCompassSolver { case SUCCESS: return; case STILL_PROCESSING_PRIOR_USE: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + - "[NEU] Wait a little longer before using the wishing compass again.")); + Utils.addChatMessage( + EnumChatFormatting.YELLOW + "[NEU] Wait a little longer before using the wishing compass again."); event.setCanceled(true); break; case LOCATION_TOO_CLOSE: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + - "[NEU] Move a little further before using the wishing compass again.")); + Utils.addChatMessage( + EnumChatFormatting.YELLOW + "[NEU] Move a little further before using the wishing compass again."); event.setCanceled(true); break; case POSSIBLE_TARGETS_CHANGED: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + - "[NEU] Possible wishing compass targets have changed. Solver has been reset.")); + Utils.addChatMessage( + EnumChatFormatting.YELLOW + "[NEU] Possible wishing compass targets have changed. Solver has been reset."); event.setCanceled(true); break; case NO_PARTICLES_FOR_PREVIOUS_COMPASS: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + - "[NEU] No particles detected for prior compass use. Need another position to solve.")); + Utils.addChatMessage(EnumChatFormatting.YELLOW + + "[NEU] No particles detected for prior compass use. Need another position to solve."); break; case PLAYER_IN_NUCLEUS: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + - "[NEU] Wishing compass must be used outside the nucleus for accurate results.")); + Utils.addChatMessage( + EnumChatFormatting.YELLOW + "[NEU] Wishing compass must be used outside the nucleus for accurate results."); event.setCanceled(true); break; default: throw new IllegalStateException("Unexpected wishing compass solver state: \n" + getDiagnosticMessage()); } } catch (Exception e) { - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "[NEU] Error processing wishing compass action - see log for details")); + Utils.addChatMessage(EnumChatFormatting.RED + + "[NEU] Error processing wishing compass action - see log for details"); e.printStackTrace(); event.setCanceled(true); solverState = SolverState.FAILED_EXCEPTION; @@ -375,39 +375,36 @@ public class CrystalWishingCompassSolver { showSolution(); break; case FAILED_EXCEPTION: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "[NEU] Unable to determine wishing compass target.")); + Utils.addChatMessage(EnumChatFormatting.RED + "[NEU] Unable to determine wishing compass target."); logDiagnosticData(false); break; case FAILED_TIMEOUT_NO_REPEATING: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "[NEU] Timed out waiting for repeat set of compass particles.")); + Utils.addChatMessage( + EnumChatFormatting.RED + "[NEU] Timed out waiting for repeat set of compass particles."); logDiagnosticData(false); break; case FAILED_TIMEOUT_NO_PARTICLES: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "[NEU] Timed out waiting for compass particles.")); + Utils.addChatMessage(EnumChatFormatting.RED + "[NEU] Timed out waiting for compass particles."); logDiagnosticData(false); break; case FAILED_INTERSECTION_CALCULATION: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "[NEU] Unable to determine intersection of wishing compasses.")); + Utils.addChatMessage( + EnumChatFormatting.RED + "[NEU] Unable to determine intersection of wishing compasses."); logDiagnosticData(false); break; case FAILED_INVALID_SOLUTION: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "[NEU] Failed to find solution.")); + Utils.addChatMessage(EnumChatFormatting.RED + "[NEU] Failed to find solution."); logDiagnosticData(false); break; case NEED_SECOND_COMPASS: - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + - "[NEU] Need another position to determine wishing compass target.")); + Utils.addChatMessage( + EnumChatFormatting.YELLOW + "[NEU] Need another position to determine wishing compass target."); break; } } } catch (Exception e) { - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "[NEU] Exception while calculating wishing compass solution - see log for details")); + Utils.addChatMessage( + EnumChatFormatting.RED + "[NEU] Exception while calculating wishing compass solution - see log for details"); e.printStackTrace(); } } @@ -781,15 +778,14 @@ public class CrystalWishingCompassSolver { if (solution == null) return; if (NUCLEUS_BB.isVecInside(solution)) { - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] " + - EnumChatFormatting.AQUA + "Wishing compass target is the Crystal Nucleus")); + Utils.addChatMessage(EnumChatFormatting.YELLOW + "[NEU] " + EnumChatFormatting.AQUA + "Wishing compass target is the Crystal Nucleus"); return; } String destinationMessage = getWishingCompassDestinationsMessage(); if (!isSkytilsPresent) { - mc.thePlayer.addChatMessage(new ChatComponentText(destinationMessage)); + Utils.addChatMessage(destinationMessage); return; } @@ -799,13 +795,13 @@ public class CrystalWishingCompassSolver { String skytilsCommand = String.format("/sthw add %s %s", getSolutionCoordsText(), targetNameForSkytils); if (NotEnoughUpdates.INSTANCE.config.mining.wishingCompassAutocreateKnownWaypoints && solutionPossibleTargets.size() == 1) { - mc.thePlayer.addChatMessage(new ChatComponentText(destinationMessage)); + Utils.addChatMessage(destinationMessage); int commandResult = ClientCommandHandler.instance.executeCommand(mc.thePlayer, skytilsCommand); if (commandResult == 1) { return; } - mc.thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "[NEU] Failed to automatically run /sthw")); + Utils.addChatMessage( + EnumChatFormatting.RED + "[NEU] Failed to automatically run /sthw"); } destinationMessage += EnumChatFormatting.YELLOW + " [Add Skytils Waypoint]"; @@ -920,8 +916,8 @@ public class CrystalWishingCompassSolver { } if (!NotEnoughUpdates.INSTANCE.config.mining.wishingCompassSolver) { - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "[NEU] Wishing Compass Solver is not enabled.")); + Utils.addChatMessage(EnumChatFormatting.RED + + "[NEU] Wishing Compass Solver is not enabled."); return; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java new file mode 100644 index 00000000..7caa4d6b --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscfeatures; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; +import io.github.moulberry.notenoughupdates.util.ItemUtils; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Items; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.GL11; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DungeonNpcProfitOverlay { + + private static final ResourceLocation dungeonProfitResource = + new ResourceLocation("notenoughupdates:dungeon_chest_worth.png"); + + private static final Pattern chestNamePattern = Pattern.compile(".+ Catacombs - Floor .+"); + private static final Pattern essencePattern = Pattern.compile( + "^§.(?<essenceType>\\w+) Essence §.x(?<essenceAmount>\\d+)$"); + private static final Pattern enchantedBookPattern = Pattern.compile("^§.Enchanted Book \\((?<enchantName>.*)\\)"); + private static List<DungeonChest> chestProfits; + private static List<Slot> previousSlots; + + /** + * Check the current status for the overlay + * + * @return if the overlay is rendering right now + */ + public static boolean isRendering() { + return NotEnoughUpdates.INSTANCE.config.dungeons.croesusProfitOverlay && chestProfits != null; + } + + /** + * Highlight the slot that is being drawn if applicable. Called by MixinGuiContainer + * + * @param slot the slot to be checked + * @see io.github.moulberry.notenoughupdates.mixins.MixinGuiContainer#drawSlotRet(Slot, CallbackInfo) + */ + public static void onDrawSlot(Slot slot) { + if (isRendering() && NotEnoughUpdates.INSTANCE.config.dungeons.croesusHighlightHighestProfit) { + for (DungeonChest chestProfit : chestProfits) { + if (chestProfit.shouldHighlight) { + if (slot.slotNumber == chestProfit.slot) { + Gui.drawRect( + slot.xDisplayPosition, + slot.yDisplayPosition, + slot.xDisplayPosition + 16, + slot.yDisplayPosition + 16, + Color.GREEN.getRGB() + ); + } + } + } + } + } + + @SubscribeEvent + public void onDrawBackground(GuiScreenEvent.BackgroundDrawnEvent event) { + if (!NotEnoughUpdates.INSTANCE.config.dungeons.croesusProfitOverlay || !(event.gui instanceof GuiChest)) { + chestProfits = null; + previousSlots = null; + return; + } + + String lastOpenChestName = SBInfo.getInstance().lastOpenChestName; + Matcher matcher = chestNamePattern.matcher(lastOpenChestName); + if (!matcher.matches()) { + chestProfits = null; + previousSlots = null; + return; + } + GuiChest guiChest = (GuiChest) event.gui; + List<Slot> slots = guiChest.inventorySlots.inventorySlots; + + if (chestProfits == null || chestProfits.isEmpty() || !slots.equals(previousSlots)) { + updateDungeonChests(slots); + } + previousSlots = guiChest.inventorySlots.inventorySlots; + + render(guiChest); + } + + /** + * Update the profit applicable for the chests currently visible + * + * @param inventorySlots list of Slots from the GUI containing the dungeon chest previews + */ + private void updateDungeonChests(List<Slot> inventorySlots) { + chestProfits = new ArrayList<>(); + //loop through the upper chest + for (int i = 0; i < 27; i++) { + Slot inventorySlot = inventorySlots.get(i); + if (inventorySlot == null) { + continue; + } + + ItemStack stack = inventorySlot.getStack(); + if (stack != null && stack.getItem() != null && stack.getItem() == Items.skull) { + //each item is a DungeonChest + DungeonChest dungeonChest = new DungeonChest(); + dungeonChest.slot = i; + + List<String> lore = ItemUtils.getLore(stack); + if ("§7Contents".equals(lore.get(0))) { + dungeonChest.name = stack.getDisplayName(); + List<SkyblockItem> items = new ArrayList<>(); + for (String s : lore) { + //check if this line is showing the cost of opening the Chest + if (s.endsWith(" Coins")) { + String coinString = StringUtils.cleanColour(s); + int whitespace = coinString.indexOf(' '); + if (whitespace != -1) { + String amountString = coinString.substring(0, whitespace).replace(",", ""); + dungeonChest.costToOpen = Integer.parseInt(amountString); + continue; + } + } else if (s.equals("§aFREE")) { + dungeonChest.costToOpen = 0; + } + + //check if the line can be converted to a SkyblockItem + SkyblockItem skyblockItem = SkyblockItem.createFromLoreEntry(s); + if (skyblockItem != null) { + items.add(skyblockItem); + } + } + dungeonChest.items = items; + if (dungeonChest.costToOpen != -1) { + dungeonChest.calculateProfitAndBuildLore(); + chestProfits.add(dungeonChest); + } + } + } + } + + if (NotEnoughUpdates.INSTANCE.config.dungeons.croesusSortByProfit) { + chestProfits.sort(Comparator.comparing(DungeonChest::getProfit).reversed()); + } + + if (NotEnoughUpdates.INSTANCE.config.dungeons.croesusHighlightHighestProfit && chestProfits.size() >= 1) { + List<DungeonChest> copiedList = new ArrayList<>(chestProfits); + copiedList.sort(Comparator.comparing(DungeonChest::getProfit).reversed()); + + copiedList.get(0).shouldHighlight = true; + } + } + + public void render(GuiChest guiChest) { + int xSize = ((AccessorGuiContainer) guiChest).getXSize(); + int guiLeft = ((AccessorGuiContainer) guiChest).getGuiLeft(); + int guiTop = ((AccessorGuiContainer) guiChest).getGuiTop(); + Minecraft.getMinecraft().getTextureManager().bindTexture(dungeonProfitResource); + GL11.glColor4f(1, 1, 1, 1); + GlStateManager.disableLighting(); + Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 180, 101, 0, 180 / 256f, 0, 101 / 256f, GL11.GL_NEAREST); + + for (int i = 0; i < chestProfits.size(); i++) { + DungeonChest chestProfit = chestProfits.get(i); + int x = guiLeft + xSize + 14; + int y = guiTop + 6 + (i * 10); + Utils.renderAlignedString( + chestProfit.name, + (chestProfit.profit > 0 + ? EnumChatFormatting.GREEN.toString() + : EnumChatFormatting.RED) + Utils.shortNumberFormat(chestProfit.profit, 0), + x, + y, + 160 + ); + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + + int mouseX = Utils.getMouseX(); + int mouseY = Utils.getMouseY(); + + if (Utils.isWithinRect(mouseX, mouseY, x, y, 160, 10)) + Utils.drawHoveringText( + chestProfit.lore, + mouseX, + mouseY, + width, + height, + -1, + Minecraft.getMinecraft().fontRendererObj + ); + } + + } + + /** + * Dataclass holding info on a single Dungeon Chest Preview + * <p> + * This includes: + * <ul> + * <li>The items, represented as a SkyblockItem</li> + * <li>The cost to open the chest</li> + * </ul> + * + * @see SkyblockItem + */ + private static class DungeonChest { + private List<SkyblockItem> items = new ArrayList<>(); + private List<String> lore; + private int costToOpen = -1; + private String name; + private int slot; + private boolean shouldHighlight; + private double profit; + + public double getProfit() { + return profit; + } + + public void calculateProfitAndBuildLore() { + profit = 0d; + lore = new ArrayList<>(); + lore.add(name); + for (SkyblockItem item : items) { + double cost = item.calculateCost(); + profit += cost; + lore.add( + EnumChatFormatting.AQUA + " - " + item.getDisplayName() + EnumChatFormatting.RESET + " " + + EnumChatFormatting.GREEN + + Utils.shortNumberFormat(cost, 0)); + } + lore.add(""); + profit -= costToOpen; + lore.add( + EnumChatFormatting.AQUA + "Cost to open: " + EnumChatFormatting.RED + Utils.shortNumberFormat(costToOpen, 0)); + lore.add( + EnumChatFormatting.AQUA + "Total profit: " + (profit > 0 ? EnumChatFormatting.GREEN : EnumChatFormatting.RED) + + Utils.shortNumberFormat(profit, 0)); + } + } + + /** + * Dataclass holding info on a single skyblock item which is part of a DungeonChest + * <p> + * This includes: + * <ul> + * <li>The internal name of the item</li> + * <li>The amount</li> + * </ul> + * + * @see DungeonChest + */ + private static class SkyblockItem { + private final String internalName; + private final int amount; + + private SkyblockItem(String internalName, int amount) { + this.internalName = internalName; + this.amount = amount; + } + + /** + * Try to create a SkyblockItem from the given lore line. + * <p> + * This involves checking for: + * <ul> + * <li>Enchanted books</li> + * <li>Dungeon essence</li> + * <li>Normal items that can appear in dungeon chests</li> + * </ul> + * + * @param line the line to be parsed + * @return a new SkyblockItem if possible, otherwise null + */ + public static @Nullable SkyblockItem createFromLoreEntry(String line) { + Matcher essenceMatcher = essencePattern.matcher(line); + Matcher enchantedBookMatcher = enchantedBookPattern.matcher(line); + + if (enchantedBookMatcher.matches()) { + String enchant = StringUtils.cleanColour(enchantedBookMatcher.group("enchantName")); + + for (Map.Entry<String, JsonObject> entry : NotEnoughUpdates.INSTANCE.manager + .getItemInformation() + .entrySet()) { + String displayName = StringUtils.cleanColour(entry.getValue().get("displayname").getAsString()); + if (displayName.equals("Enchanted Book")) { + JsonArray lore = entry.getValue().get("lore").getAsJsonArray(); + String enchantName = StringUtils.cleanColour(lore.get(0).getAsString()); + if (enchant.equals(enchantName)) { + return new SkyblockItem(entry.getKey(), 1); + } + } + } + } else if (essenceMatcher.matches()) { + String essenceType = essenceMatcher.group("essenceType"); + String essenceAmount = essenceMatcher.group("essenceAmount"); + if (essenceType == null || essenceAmount == null) { + return null; + } + + String internalName = "ESSENCE_" + essenceType.toUpperCase(Locale.ROOT); + if (!NotEnoughUpdates.INSTANCE.manager.isValidInternalName(internalName)) { + return null; + } + + //this can only be an integer if the regex matches + int amount = Integer.parseInt(essenceAmount); + return new SkyblockItem(internalName, amount); + } else { + String s = StringUtils.cleanColour(line.trim()); + for (Map.Entry<String, JsonObject> entries : NotEnoughUpdates.INSTANCE.manager + .getItemInformation() + .entrySet()) { + String displayName = entries.getValue().get("displayname").getAsString(); + String cleanDisplayName = StringUtils.cleanColour(displayName); + if (s.equals(cleanDisplayName)) { + return new SkyblockItem(entries.getKey(), 1); + } + } + } + return null; + } + + /** + * Calculate the price of this item, factoring in the amount + * + * @return total price + */ + public double calculateCost() { + double price = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarOrBin(internalName, true); + if (price != -1) { + return price * amount; + } + return 0d; + } + + public String getDisplayName() { + JsonObject entry = NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery().withKnownInternalName( + internalName).resolveToItemListJson(); + if (entry != null) { + String displayName = entry.get("displayname").getAsString(); + String cleanedDisplayName = StringUtils.cleanColour(displayName); + if ("Enchanted Book".equals(cleanedDisplayName)) { + return entry.get("lore").getAsJsonArray().get(0).getAsString(); + } else { + return entry.get("displayname").getAsString(); + } + } + return "ERROR"; + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnderNodes.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnderNodes.java new file mode 100644 index 00000000..b0823a7d --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnderNodes.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscfeatures; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.SpecialColour; +import io.github.moulberry.notenoughupdates.util.TitleUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; + +public class EnderNodes { + // TODO Add ender node highliter + // TODO Add ender node counter ( maybe money estimation ) + + public static void dispalyEndermiteNotif() { + if (NotEnoughUpdates.INSTANCE.config.notifications.endermiteAlert && SBInfo.getInstance().getLocation() != null && + SBInfo.getInstance().getLocation().equals("combat_3")) { + TitleUtil.getInstance().createTitle("Nested Endermite", + NotEnoughUpdates.INSTANCE.config.notifications.endermiteAlertTicks, + SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.notifications.endermiteAlertColor)); + Minecraft.getMinecraft().thePlayer.playSound("random.orb", 1, 1); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java index 75f1b427..5fa68fc2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java @@ -29,11 +29,11 @@ import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.util.BlockPos; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraftforge.client.event.ClientChatReceivedEvent; import net.minecraftforge.client.event.RenderWorldLastEvent; @@ -177,6 +177,7 @@ public class FairySouls { double factor = normalize(currentDistSq, 0.0, farSoulDistSq); int rgb = interpolateColors(closeColor, farColor, Math.min(0.40, factor)); RenderUtils.renderBeaconBeamOrBoundingBox(currentSoul, rgb, 1.0f, event.partialTicks); + if (NotEnoughUpdates.INSTANCE.config.misc.fairySoulWaypointDistance) RenderUtils.renderWayPoint(currentSoul, event.partialTicks); } } @@ -370,7 +371,7 @@ public class FairySouls { } private static void print(String s) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(s)); + Utils.addChatMessage(s); } private static void printHelp() { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java index f68f3c58..4fc63734 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java @@ -150,9 +150,7 @@ public class ItemCooldowns { } else if (internalname.contains("_DRILL_")) { char lastChar = internalname.charAt(internalname.length() - 1); return lastChar >= '0' && lastChar <= '9'; - } else if (internalname.equals("DIVAN_DRILL")) { - return true; - } else return internalname.equals("GEMSTONE_GAUNTLET"); + } else return internalname.equals("GEMSTONE_GAUNTLET") || internalname.equals("PICKONIMBUS") || internalname.equals("DIVAN_DRILL"); } private static void updatePickaxeCooldown() { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java index e1b9d567..15fc8ef8 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java @@ -269,7 +269,7 @@ public class ItemCustomizeManager { return CUSTOM_GLINT_TEXTURE; } - private static String getUuidForItem(ItemStack stack) { + public static String getUuidForItem(ItemStack stack) { if (!stack.hasTagCompound()) return null; int nbtHash = stack.getTagCompound().hashCode(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java index 6244c32c..89e95e25 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java @@ -38,7 +38,6 @@ import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.inventory.ContainerChest; import net.minecraft.item.ItemStack; import net.minecraft.util.BlockPos; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.Vec3i; import net.minecraftforge.client.event.RenderWorldLastEvent; @@ -93,7 +92,7 @@ public class Navigation { } } - private NotEnoughUpdates neu; + private final NotEnoughUpdates neu; public Navigation(NotEnoughUpdates notEnoughUpdates) { neu = notEnoughUpdates; @@ -379,8 +378,7 @@ public class Navigation { private void showError(String message, boolean log) { EntityPlayerSP player = Minecraft.getMinecraft().thePlayer; if (player != null) - player.addChatMessage(new ChatComponentText(EnumChatFormatting.DARK_RED + - "[NEU-Waypoint] " + message)); + Utils.addChatMessage(EnumChatFormatting.DARK_RED + "[NEU-Waypoint] " + message); if (log) new RuntimeException("[NEU-Waypoint] " + message).printStackTrace(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java index 776e3647..20fa553f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java @@ -1087,7 +1087,7 @@ public class PetInfoOverlay extends TextOverlay { PetInfoOverlay.config.selectedPet = -1; Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( EnumChatFormatting.RED + "[NEU] Can't find pet \u00a7" + petStringMatch + - EnumChatFormatting.RED + " try revisiting all pages of /pets.")); + EnumChatFormatting.RED + " try revisiting all pages of /pets.")); } } } else if ((chatMessage.toLowerCase().startsWith("you despawned your")) || (chatMessage.toLowerCase().contains( diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java index e06c271f..cc9f36fa 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java @@ -21,7 +21,10 @@ package io.github.moulberry.notenoughupdates.miscgui; import com.google.common.collect.ImmutableList; import io.github.moulberry.notenoughupdates.NEUManager; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.ArrowPagesUtils; import io.github.moulberry.notenoughupdates.recipes.NeuRecipe; +import io.github.moulberry.notenoughupdates.recipes.RecipeHistory; import io.github.moulberry.notenoughupdates.recipes.RecipeSlot; import io.github.moulberry.notenoughupdates.recipes.RecipeType; import io.github.moulberry.notenoughupdates.util.Utils; @@ -38,24 +41,20 @@ import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; -import java.awt.*; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; public class GuiItemRecipe extends GuiScreen { - public static final ResourceLocation resourcePacksTexture = new ResourceLocation("textures/gui/resource_packs.png"); public static final ResourceLocation tabsTexture = new ResourceLocation("notenoughupdates", "textures/gui/tab.png"); public static final int SLOT_SIZE = 16; public static final int SLOT_SPACING = SLOT_SIZE + 2; - public static final int BUTTON_WIDTH = 7; - public static final int BUTTON_HEIGHT = 11; public static final int TITLE_X = 28; public static final int TITLE_Y = 6; public static final int HOTBAR_SLOT_X = 8; @@ -89,6 +88,7 @@ public class GuiItemRecipe extends GuiScreen { if (!tabs.contains(recipe.getType())) tabs.add(recipe.getType()); } + tabs.sort(Comparator.naturalOrder()); changeRecipe(0, 0); } @@ -145,7 +145,8 @@ public class GuiItemRecipe extends GuiScreen { Utils.drawItemStack(slot.getItemStack(), slot.getX(this), slot.getY(this), true); } - drawArrows(currentRecipe, mouseX, mouseY); + int[] topLeft = currentRecipe.getPageFlipPositionLeftTopCorner(); + ArrowPagesUtils.onDraw(guiLeft, guiTop, topLeft, currentIndex, getCurrentRecipeList().size()); Utils.drawStringScaledMaxWidth( currentRecipe.getTitle(), @@ -220,61 +221,6 @@ public class GuiItemRecipe extends GuiScreen { } } - public static final int BUTTON_POSITION_RIGHT_OFFSET_X = 37; - public static final int PAGE_STRING_OFFSET_X = 22; - public static final int PAGE_STRING_OFFSET_Y = 6; - - private void drawArrows( - NeuRecipe currentRecipe, - int mouseX, - int mouseY - ) { - int recipeCount = getCurrentRecipeList().size(); - if (recipeCount < 2) return; - int[] topLeft = currentRecipe.getPageFlipPositionLeftTopCorner(); - int buttonPositionLeftX = topLeft[0]; - int buttonPositionRightX = buttonPositionLeftX + BUTTON_POSITION_RIGHT_OFFSET_X; - int pageStringX = buttonPositionLeftX + PAGE_STRING_OFFSET_X; - int buttonPositionY = topLeft[1]; - int pageStringY = buttonPositionY + PAGE_STRING_OFFSET_Y; - - boolean leftSelected = isWithinRect( - mouseX - guiLeft, - mouseY - guiTop, - buttonPositionLeftX, - buttonPositionY, - BUTTON_WIDTH, - BUTTON_HEIGHT - ); - boolean rightSelected = isWithinRect( - mouseX - guiLeft, - mouseY - guiTop, - buttonPositionRightX, - buttonPositionY, - BUTTON_WIDTH, - BUTTON_HEIGHT - ); - Minecraft.getMinecraft().getTextureManager().bindTexture(resourcePacksTexture); - - if (currentIndex != 0) - Utils.drawTexturedRect(guiLeft + buttonPositionLeftX, guiTop + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT, - 34 / 256f, 48 / 256f, - leftSelected ? 37 / 256f : 5 / 256f, leftSelected ? 59 / 256f : 27 / 256f - ); - if (currentIndex != recipeCount - 1) - Utils.drawTexturedRect(guiLeft + buttonPositionRightX, guiTop + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT, - 10 / 256f, 24 / 256f, - rightSelected ? 37 / 256f : 5 / 256f, rightSelected ? 59 / 256f : 27 / 256f - ); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0); - - String selectedPage = (currentIndex + 1) + "/" + recipeCount; - - Utils.drawStringCenteredScaledMaxWidth(selectedPage, fontRendererObj, - guiLeft + pageStringX, guiTop + pageStringY, false, 24, Color.BLACK.getRGB() - ); - } - public List<RecipeSlot> getPlayerInventory() { List<RecipeSlot> slots = new ArrayList<>(); ItemStack[] inventory = Minecraft.getMinecraft().thePlayer.inventory.mainInventory; @@ -317,6 +263,12 @@ public class GuiItemRecipe extends GuiScreen { } } } + + if (keyPressed == manager.keybindPreviousRecipe.getKeyCode()) { + NotEnoughUpdates.INSTANCE.openGui = RecipeHistory.getPrevious(); + } else if (keyPressed == manager.keybindNextRecipe.getKeyCode()) { + NotEnoughUpdates.INSTANCE.openGui = RecipeHistory.getNext(); + } } public void changeRecipe(int tabIndex, int recipeIndex) { @@ -327,7 +279,7 @@ public class GuiItemRecipe extends GuiScreen { } @Override - protected void actionPerformed(GuiButton p_actionPerformed_1_) throws IOException { + protected void actionPerformed(GuiButton p_actionPerformed_1_) { getCurrentRecipe().actionPerformed(p_actionPerformed_1_); } @@ -336,38 +288,23 @@ public class GuiItemRecipe extends GuiScreen { super.mouseClicked(mouseX, mouseY, mouseButton); NeuRecipe currentRecipe = getCurrentRecipe(); int[] topLeft = currentRecipe.getPageFlipPositionLeftTopCorner(); - int buttonPositionLeftX = topLeft[0]; - int buttonPositionRightX = buttonPositionLeftX + BUTTON_POSITION_RIGHT_OFFSET_X; - int buttonPositionY = topLeft[1]; - - if (isWithinRect( - mouseX - guiLeft, - mouseY - guiTop, - buttonPositionLeftX, - buttonPositionY, - BUTTON_WIDTH, - BUTTON_HEIGHT - ) && - currentIndex > 0) { - changeRecipe(currentTab, currentIndex - 1); - Utils.playPressSound(); - return; - } - if (isWithinRect( - mouseX - guiLeft, - mouseY - guiTop, - buttonPositionRightX, - buttonPositionY, - BUTTON_WIDTH, - BUTTON_HEIGHT - ) && - currentIndex < getCurrentRecipeList().size()) { - changeRecipe(currentTab, currentIndex + 1); - Utils.playPressSound(); - return; + if (mouseButton == 3) { + NotEnoughUpdates.INSTANCE.openGui = RecipeHistory.getPrevious(); + } else if (mouseButton == 4) { + NotEnoughUpdates.INSTANCE.openGui = RecipeHistory.getNext(); } + if (ArrowPagesUtils.onPageSwitchMouse( + guiLeft, + guiTop, + topLeft, + currentIndex, + getCurrentRecipeList().size(), + pageChange -> + changeRecipe(currentTab, pageChange) + )) return; + for (int i = 0; i < tabs.size(); i++) { if (isWithinRect( mouseX - guiLeft, @@ -398,4 +335,9 @@ public class GuiItemRecipe extends GuiScreen { currentRecipe.mouseClicked(this, mouseX, mouseY, mouseButton); } + + public void arrowKeyboardInput() { + ArrowPagesUtils.onPageSwitchKey(currentIndex, getCurrentRecipeList().size(), pageChange -> + changeRecipe(currentTab, pageChange)); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java index e6c4dc74..828e50b1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java @@ -160,7 +160,7 @@ public class TrophyRewardOverlay { texts.add("Trophy Fish Exchange"); texts.add("Magma Fish: §e" + total); - for (Map.Entry<String, Integer> entry : sortByValue(totalExchange).entrySet()) { + for (Map.Entry<String, Integer> entry : sortByValueReverse(totalExchange).entrySet()) { String name = entry.getKey(); int amount = totalAmount.get(name); String[] split = name.split(" "); @@ -206,6 +206,19 @@ public class TrophyRewardOverlay { public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { List<Map.Entry<K, V>> list = new ArrayList<>(map.entrySet()); list.sort(Map.Entry.comparingByValue()); + + Map<K, V> result = new LinkedHashMap<>(); + for (Map.Entry<K, V> entry : list) { + result.put(entry.getKey(), entry.getValue()); + } + + return result; + } + + //TODO move into utils class maybe? + public static <K, V extends Comparable<? super V>> Map<K, V> sortByValueReverse(Map<K, V> map) { + List<Map.Entry<K, V>> list = new ArrayList<>(map.entrySet()); + list.sort(Map.Entry.comparingByValue()); Collections.reverse(list); Map<K, V> result = new LinkedHashMap<>(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/ApiData.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/ApiData.java new file mode 100644 index 00000000..215c3fe7 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/ApiData.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper; + +import java.util.List; +import java.util.Map; + +public class ApiData { + + private final Map<String, Integer> highestCollectionTier; + private final Map<String, Integer> slayerTiers; + private final int magesReputation; + private final int barbariansReputation; + private final boolean collectionApiDisabled; + private final List<String> craftedMinions; + private int peltCount; + + public ApiData( + Map<String, Integer> highestCollectionTier, + Map<String, Integer> slayerTiers, + int magesReputation, + int barbariansReputation, + boolean collectionApiDisabled, + List<String> craftedMinions, + int peltCount + ) { + this.highestCollectionTier = highestCollectionTier; + this.slayerTiers = slayerTiers; + this.magesReputation = magesReputation; + this.barbariansReputation = barbariansReputation; + this.collectionApiDisabled = collectionApiDisabled; + this.craftedMinions = craftedMinions; + this.peltCount = peltCount; + } + + public Map<String, Integer> getHighestCollectionTier() { + return highestCollectionTier; + } + + public Map<String, Integer> getSlayerTiers() { + return slayerTiers; + } + + public int getMagesReputation() { + return magesReputation; + } + + public int getBarbariansReputation() { + return barbariansReputation; + } + + public boolean isCollectionApiDisabled() { + return collectionApiDisabled; + } + + public List<String> getCraftedMinions() { + return craftedMinions; + } + + public int getPeltCount() { + return peltCount; + } + + public void setPeltCount(int peltCount) { + this.peltCount = peltCount; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/Minion.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/Minion.java new file mode 100644 index 00000000..ba38b01d --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/Minion.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables.OverviewLine; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.MinionRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.CustomSource; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.MinionSource; + +import java.util.ArrayList; +import java.util.List; + +public class Minion extends OverviewLine { + private final String internalName; + private final int tier; + private String displayName; + private MinionSource minionSource; + private CustomSource customSource; + private Minion parent; + private final List<MinionRequirement> requirements = new ArrayList<>(); + + private boolean crafted = false; + private boolean meetRequirements = false; + + public Minion(String internalName, int tier) { + this.internalName = internalName; + this.tier = tier; + } + + public MinionSource getMinionSource() { + return minionSource; + } + + public void setMinionSource(MinionSource minionSource) { + this.minionSource = minionSource; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public boolean isCrafted() { + return crafted; + } + + public void setCrafted(boolean crafted) { + this.crafted = crafted; + } + + public String getInternalName() { + return internalName; + } + + public void setParent(Minion parent) { + this.parent = parent; + } + + public Minion getParent() { + return parent; + } + + public int getTier() { + return tier; + } + + public List<MinionRequirement> getRequirements() { + return requirements; + } + + public boolean doesMeetRequirements() { + return meetRequirements; + } + + public void setMeetRequirements(boolean meetRequirements) { + this.meetRequirements = meetRequirements; + } + + @Override + public void onClick() { + NotEnoughUpdates.INSTANCE.manager.displayGuiItemRecipe(internalName); + } + + public void setCustomSource(CustomSource customSource) { + this.customSource = customSource; + } + + public CustomSource getCustomSource() { + return customSource; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/MinionHelperManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/MinionHelperManager.java new file mode 100644 index 00000000..f3c8a86a --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/MinionHelperManager.java @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders.MinionHelperApiLoader; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders.MinionHelperChatLoader; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders.MinionHelperInventoryLoader; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders.repo.MinionHelperRepoLoader; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.MinionHelperOverlay; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.MinionHelperTooltips; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.CustomSource; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.MinionSource; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.util.MinionHelperPriceCalculation; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.util.MinionHelperRequirementsManager; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.ContainerChest; +import net.minecraftforge.common.MinecraftForge; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MinionHelperManager { + private static MinionHelperManager instance = null; + private final Map<String, Minion> minions = new HashMap<>(); + private int needForNextSlot = -1; + private int localPelts = -1; + + private final MinionHelperPriceCalculation priceCalculation = new MinionHelperPriceCalculation(this); + private final MinionHelperRequirementsManager requirementsManager = new MinionHelperRequirementsManager(this); + private final MinionHelperApiLoader api = new MinionHelperApiLoader(this); + private final MinionHelperRepoLoader repo = new MinionHelperRepoLoader(this); + private final MinionHelperOverlay overlay = new MinionHelperOverlay(this); + private final MinionHelperInventoryLoader inventoryLoader = new MinionHelperInventoryLoader(this); + private String debugPlayerUuid; + private String debugProfileName; + private int debugNeedForNextSlot = -1; + + public static MinionHelperManager getInstance() { + if (instance == null) { + instance = new MinionHelperManager(); + } + return instance; + } + + private MinionHelperManager() { + MinecraftForge.EVENT_BUS.register(priceCalculation); + MinecraftForge.EVENT_BUS.register(api); + MinecraftForge.EVENT_BUS.register(repo); + MinecraftForge.EVENT_BUS.register(overlay); + MinecraftForge.EVENT_BUS.register(new MinionHelperTooltips(this)); + MinecraftForge.EVENT_BUS.register(new MinionHelperChatLoader(this)); + MinecraftForge.EVENT_BUS.register(inventoryLoader); + } + + public boolean inCraftedMinionsInventory() { + if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return false; + + Minecraft minecraft = Minecraft.getMinecraft(); + if (minecraft == null || minecraft.thePlayer == null) return false; + + Container inventoryContainer = minecraft.thePlayer.openContainer; + if (!(inventoryContainer instanceof ContainerChest)) return false; + ContainerChest containerChest = (ContainerChest) inventoryContainer; + String name = containerChest.getLowerChestInventory().getDisplayName().getUnformattedText(); + return name.equalsIgnoreCase("Crafted Minions"); + } + + public boolean notReady() { + return !repo.isReadyToUse() || !api.isReadyToUse(); + } + + public boolean isInvalidApiKey() { + return api.isInvalidApiKey(); + } + + public Minion getMinionById(String internalName) { + if (minions.containsKey(internalName)) { + return minions.get(internalName); + } else { + System.err.println("Cannot get minion for id '" + internalName + "'!"); + return null; + } + } + + public Minion getMinionByName(String displayName, int tier) { + for (Minion minion : minions.values()) { + if (displayName.equals(minion.getDisplayName())) { + if (minion.getTier() == tier) { + return minion; + } + } + } + System.err.println("Cannot get minion for display name '" + displayName + "'!"); + return null; + } + + public void createMinion(String internalName, int tier) { + minions.put(internalName, new Minion(internalName, tier)); + } + + public String formatInternalName(String minionName) { + return minionName.toUpperCase().replace(" ", "_"); + } + + private List<Minion> getChildren(Minion minion) { + List<Minion> list = new ArrayList<>(); + for (Minion other : minions.values()) { + if (minion == other.getParent()) { + list.add(other); + list.addAll(getChildren(other)); + break; + } + } + return list; + } + + public void onProfileSwitch() { + for (Minion minion : minions.values()) { + minion.setCrafted(false); + minion.setMeetRequirements(false); + } + + needForNextSlot = -1; + api.onProfileSwitch(); + overlay.onProfileSwitch(); + inventoryLoader.onProfileSwitch(); + } + + public void reloadData() { + requirementsManager.reloadRequirements(); + + ApiData apiData = api.getApiData(); + if (apiData != null) { + for (String minion : apiData.getCraftedMinions()) { + setCrafted(getMinionById(minion)); + } + } + } + + public void setCrafted(Minion minion) { + minion.setCrafted(true); + + if (minion.getCustomSource() != null) { + minion.setMeetRequirements(true); + + for (Minion child : getChildren(minion)) { + child.setMeetRequirements(true); + } + } + } + + public void handleCommand(String[] args) { + if (!NotEnoughUpdates.INSTANCE.config.minionHelper.gui) { + Utils.addChatMessage("§e[NEU] Minion Helper gui is disabled!"); + return; + } + + if (args.length > 1) { + String parameter = args[1]; + + if (parameter.equals("debugplayer")) { + if (args.length == 3) { + if (args[2].equals("reset")) { + Utils.addChatMessage("§e[NEU] Minion debug player reset."); + setDebugPlayer(null, null, -1); + return; + } + } + if (args.length < 4) { + Utils.addChatMessage("§c[NEU] Usage: /neudevtest minion " + + "setplayer <player-uuid> <player-profile-name> [need-for-next-slot]"); + return; + } + String playerUuid = args[2]; + String playerProfileName = args[3]; + int need = args.length == 5 ? Integer.parseInt(args[4]) : -1; + setDebugPlayer(playerUuid, playerProfileName, need); + Utils.addChatMessage("§e[NEU] Minion debug player set."); + return; + } + + if (args.length == 2) { + if (parameter.equals("clearminion")) { + minions.clear(); + Utils.addChatMessage("minion map cleared"); + return; + } + if (parameter.equals("reloadrepo")) { + repo.setDirty(); + Utils.addChatMessage("repo reload requested"); + return; + } + if (parameter.equals("reloadapi")) { + api.resetData(); + api.setDirty(); + Utils.addChatMessage("api reload requested"); + return; + } + if (parameter.equals("clearapi")) { + api.resetData(); + Utils.addChatMessage("api data cleared"); + return; + } + } + + if (args.length == 3) { + if (parameter.equals("maxperpage")) { + api.resetData(); + int maxPerPage = Integer.parseInt(args[2]); + Utils.addChatMessage("set max per page to " + maxPerPage); + overlay.setMaxPerPage(maxPerPage); + return; + } + } + + if (args.length == 4) { + if (parameter.equals("arrowpos")) { + int x = Integer.parseInt(args[2]); + int y = Integer.parseInt(args[3]); + Utils.addChatMessage("set page pos to " + x + ";" + y); + overlay.setTopLeft(new int[]{x, y}); + return; + } + } + } + + Utils.addChatMessage(""); + Utils.addChatMessage("§3NEU Minion Helper commands: §c(for testing only!)"); + Utils.addChatMessage("§6/neudevtest minion clearminion §7Clears the minion map"); + Utils.addChatMessage("§6/neudevtest minion reloadrepo §7Manually loading the data from repo"); + Utils.addChatMessage("§6/neudevtest minion reloadapi §7Manually loading the data from api"); + Utils.addChatMessage("§6/neudevtest minion clearapi §7Clears the api data"); + Utils.addChatMessage("§6/neudevtest minion maxperpage <number> §7Changes the max minions per page number"); + Utils.addChatMessage("§6/neudevtest minion arrowpos <x, y> §7Changes the position of the page numbers"); + Utils.addChatMessage("§6/neudevtest minion debugplayer <player-uuid> <player-profile-name> [need-for-next-slot] §7" + + "See the Minions missing of other player"); + Utils.addChatMessage(""); + } + + private void setDebugPlayer(String playerUuid, String playerProfileName, int fakeNeedForNextSlot) { + this.debugPlayerUuid = playerUuid; + this.debugProfileName = playerProfileName; + this.debugNeedForNextSlot = fakeNeedForNextSlot; + + onProfileSwitch(); + } + + public MinionHelperPriceCalculation getPriceCalculation() { + return priceCalculation; + } + + public MinionHelperRequirementsManager getRequirementsManager() { + return requirementsManager; + } + + public MinionHelperApiLoader getApi() { + return api; + } + + public MinionHelperOverlay getOverlay() { + return overlay; + } + + public Map<String, Minion> getAllMinions() { + return minions; + } + + public void setNeedForNextSlot(int needForNextSlot) { + this.needForNextSlot = needForNextSlot; + overlay.resetCache(); + } + + public int getNeedForNextSlot() { + return needForNextSlot; + } + + public void setCustomSource(Minion minion, CustomSource customSource) { + MinionSource minionSource = minion.getMinionSource(); + if (minionSource == null) { + minion.setMinionSource(customSource); + } + minion.setCustomSource(customSource); + } + + public int getLocalPelts() { + return localPelts; + } + + public void setLocalPelts(int pelts) { + localPelts = pelts; + if (localPelts != -1) { + ApiData apiData = api.getApiData(); + if (apiData != null) { + apiData.setPeltCount(localPelts); + } + } + } + + public String getDebugPlayerUuid() { + return debugPlayerUuid; + } + + public String getDebugProfileName() { + return debugProfileName; + } + + public int getDebugNeedForNextSlot() { + return debugNeedForNextSlot; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java new file mode 100644 index 00000000..aaa398f4 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperApiLoader.java @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.events.ProfileDataLoadedEvent; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.ApiData; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.item.ItemStack; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class MinionHelperApiLoader { + private final MinionHelperManager manager; + private boolean dirty = true; + private int ticks = 0; + private boolean collectionApiEnabled = true; + private boolean ignoreWorldSwitches = false; + private boolean readyToUse = false; + private ApiData apiData = null; + private boolean notifyNoCollectionApi = false; + private long lastLoaded = 0; + private boolean invalidApiKey = false; + + public MinionHelperApiLoader(MinionHelperManager manager) { + this.manager = manager; + } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Load event) { + if (ignoreWorldSwitches) return; + + setDirty(); + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (Minecraft.getMinecraft().thePlayer == null) return; + if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; + if (!NotEnoughUpdates.INSTANCE.config.minionHelper.gui) return; + ticks++; + + if (ticks % 20 != 0) return; + + if (dirty) { + load(); + } else { + if (System.currentTimeMillis() > lastLoaded + 60_000 * 3) { + dirty = true; + } + } + } + + private void load() { + lastLoaded = System.currentTimeMillis(); + + dirty = false; + String uuid = getUuid(); + if (uuid == null) return; + + NotEnoughUpdates.INSTANCE.manager.apiUtils.updateProfileData(uuid); + } + + private String getUuid() { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + if (thePlayer == null) return null; + + String debugPlayerUuid = manager.getDebugPlayerUuid(); + if (debugPlayerUuid != null) return debugPlayerUuid; + + return thePlayer.getUniqueID().toString().replace("-", ""); + } + + @SubscribeEvent + public void onApiDataLoaded(ProfileDataLoadedEvent event) { + JsonObject data = event.getData(); + if (data == null) { + invalidApiKey = true; + return; + } + invalidApiKey = false; + + if (!data.has("success") || !data.get("success").getAsBoolean()) return; + JsonArray profiles = data.getAsJsonArray("profiles"); + for (JsonElement element : profiles) { + JsonObject profile = element.getAsJsonObject(); + String profileName = profile.get("cute_name").getAsString(); + JsonObject members = profile.getAsJsonObject("members"); + JsonObject player = members.getAsJsonObject(getUuid()); + + String debugProfileName = manager.getDebugProfileName(); + String currentProfile = debugProfileName != null ? debugProfileName : SBInfo.getInstance().currentProfile; + + if (profileName.equals(currentProfile)) { + readData(player, members); + return; + } + } + } + + private void readData(JsonObject player, JsonObject members) { + int magesReputation = 0; + int barbariansReputation = 0; + if (player.has("nether_island_player_data")) { + JsonObject netherData = player.getAsJsonObject("nether_island_player_data"); + if (netherData.has("mages_reputation")) { + magesReputation = netherData.get("mages_reputation").getAsInt(); + } + if (netherData.has("barbarians_reputation")) { + barbariansReputation = netherData.get("barbarians_reputation").getAsInt(); + } + } + + apiData = new ApiData( + getCollections(player), + getSlayers(player), + magesReputation, + barbariansReputation, + !collectionApiEnabled, + loadCraftedMinions(members), + loadPeltCount(player) + ); + + manager.reloadData(); + readyToUse = true; + } + + private int loadPeltCount(JsonObject player) { + int localPelts = manager.getLocalPelts(); + if (localPelts != -1) return localPelts; + + int peltCount = 0; + if (player.has("trapper_quest")) { + JsonObject jsonObject = player.getAsJsonObject("trapper_quest"); + if (jsonObject.has("pelt_count")) { + peltCount = jsonObject.get("pelt_count").getAsInt(); + } + } + return peltCount; + } + + private Map<String, Integer> getSlayers(JsonObject player) { + JsonObject slayerLeveling = Constants.LEVELING.getAsJsonObject("slayer_xp"); + + Map<String, Integer> slayerTier = new HashMap<>(); + if (player.has("slayer_bosses")) { + JsonObject slayerBosses = player.getAsJsonObject("slayer_bosses"); + for (Map.Entry<String, JsonElement> entry : slayerBosses.entrySet()) { + String name = entry.getKey(); + JsonObject slayerEntry = entry.getValue().getAsJsonObject(); + if (slayerEntry.has("xp")) { + long xp = slayerEntry.get("xp").getAsLong(); + + int tier = 0; + for (JsonElement element : slayerLeveling.getAsJsonArray(name)) { + int needForLevel = element.getAsInt(); + if (xp >= needForLevel) { + tier++; + } else { + break; + } + } + slayerTier.put(name, tier); + } + } + } + return slayerTier; + } + + private Map<String, Integer> getCollections(JsonObject player) { + Map<String, Integer> highestCollectionTier = new HashMap<>(); + if (player.has("unlocked_coll_tiers")) { + for (JsonElement element : player.get("unlocked_coll_tiers").getAsJsonArray()) { + String text = element.getAsString(); + String[] split = text.split("_"); + int level = Integer.parseInt(split[split.length - 1]); + String name = StringUtils.removeLastWord(text, "_"); + + //Because skyblock is good in naming things + LinkedHashMap<String, ItemStack> collectionMap = ProfileViewer.getCollectionToCollectionDisplayMap(); + if (collectionMap.containsKey(name)) { + ItemStack itemStack = collectionMap.get(name); + String displayName = itemStack.getDisplayName(); + name = Utils.cleanColour(displayName); + name = manager.formatInternalName(name); + } else { + //Doing this since there is no space in the profile viewer gui for more entries in collectionToCollectionDisplayMap + if (name.equals("SAND:1")) name = "RED_SAND"; + if (name.equals("MYCEL")) name = "MYCELIUM"; + } + + level = Math.max(highestCollectionTier.getOrDefault(name, 0), level); + highestCollectionTier.put(name, level); + } + if (!collectionApiEnabled) { + Utils.addChatMessage("§e[NEU] Collection API detected!"); + } + collectionApiEnabled = true; + } else { + if (collectionApiEnabled) { + notifyNoCollectionApi = true; + } + collectionApiEnabled = false; + } + return highestCollectionTier; + } + + private List<String> loadCraftedMinions(JsonObject members) { + List<String> craftedMinions = new ArrayList<>(); + for (Map.Entry<String, JsonElement> entry : members.entrySet()) { + JsonObject value = entry.getValue().getAsJsonObject(); + if (value.has("crafted_generators")) { + for (JsonElement e : value.get("crafted_generators").getAsJsonArray()) { + String rawGenerator = e.getAsString(); + String[] split = rawGenerator.split("_"); + String tier = split[split.length - 1]; + String name = rawGenerator.substring(0, rawGenerator.length() - tier.length() - 1); + String internalName = name + "_GENERATOR_" + tier; + craftedMinions.add(internalName); + } + } + } + + return craftedMinions; + } + + public void setDirty() { + dirty = true; + readyToUse = false; + } + + public void prepareProfileSwitch() { + ignoreWorldSwitches = true; + readyToUse = false; + } + + public void onProfileSwitch() { + apiData = null; + setDirty(); + ignoreWorldSwitches = false; + collectionApiEnabled = true; + } + + public boolean isReadyToUse() { + return readyToUse; + } + + public ApiData getApiData() { + return apiData; + } + + public boolean isCollectionApiDisabled() { + return apiData != null && apiData.isCollectionApiDisabled(); + } + + public void resetData() { + apiData = null; + } + + public void setNotifyNoCollectionApi(boolean notifyNoCollectionApi) { + this.notifyNoCollectionApi = notifyNoCollectionApi; + } + + public boolean isNotifyNoCollectionApi() { + return notifyNoCollectionApi; + } + + public boolean isInvalidApiKey() { + return invalidApiKey; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperChatLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperChatLoader.java new file mode 100644 index 00000000..bef633d2 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperChatLoader.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MinionHelperChatLoader { + + private final MinionHelperManager manager; + + //§aYou crafted a §eTier I Redstone Minion§a! That's a new one! + // §aCraft §e7 §amore unique Minions to unlock your §e9th Minion slot§a! + private final Pattern PATTERN_OWN_MINION = Pattern.compile( + "§r§aYou crafted a §eTier (\\S+) (.+) Minion§a! That's a new one!(\\r\\n|\\r|\\n)(.*)"); + //§aYou crafted a §eTier VI Enderman Minion§a! That's a new one! + + //§b[MVP§3+§b] Eisengolem§f §acrafted a §eTier I Birch Minion§a! + private final Pattern PATTERN_COOP_MINION = Pattern.compile( + "(.+)§f §acrafted a §eTier (\\S+) (.+) Minion§a!(§r)?(\\r\\n|\\r|\\n)?(.*)?"); + + public MinionHelperChatLoader(MinionHelperManager manager) { + this.manager = manager; + } + + @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true) + public void onChat(ClientChatReceivedEvent event) { + if (event.type != 0) return; + String message = event.message.getFormattedText(); + if (!NotEnoughUpdates.INSTANCE.config.minionHelper.gui) return; + + try { + Matcher ownMatcher = PATTERN_OWN_MINION.matcher(message); + if (ownMatcher.matches()) { + String rawTier = ownMatcher.group(1); + int tier = Utils.parseRomanNumeral(rawTier); + String name = ownMatcher.group(2) + " Minion"; + + setCrafted(manager.getMinionByName(name, tier)); + } + + Matcher coopMatcher = PATTERN_COOP_MINION.matcher(message); + if (coopMatcher.matches()) { + String rawTier = coopMatcher.group(2); + int tier = Utils.parseRomanNumeral(rawTier); + String name = coopMatcher.group(3) + " Minion"; + + setCrafted(manager.getMinionByName(name, tier)); + manager.getOverlay().resetCache(); + } + + if (message.startsWith("§r§7Switching to profile ")) { + manager.getApi().prepareProfileSwitch(); + } + + } catch (Exception e) { + Utils.addChatMessage( + "[NEU] §cMinion Helper failed reading the minion upgrade message. See the logs for more info!"); + e.printStackTrace(); + } + } + + private void setCrafted(Minion minion) { + manager.setCrafted(minion); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperInventoryLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperInventoryLoader.java new file mode 100644 index 00000000..7fc703e6 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/MinionHelperInventoryLoader.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.util.ItemUtils; +import io.github.moulberry.notenoughupdates.util.TabListUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MinionHelperInventoryLoader { + private final MinionHelperManager manager; + private final List<String> pagesSeenAlready = new ArrayList<>(); + private boolean dirty = true; + + private int ticks = 0; + + //§7Craft §b5 §7more §aunique §7minions + private final Pattern PATTERN_MINIONS_NEEDED = Pattern.compile("§7Craft §b(\\d+) §7more §aunique( §7minions)?"); + + //§r §r§fPelts: §r§59§r + private final Pattern PATTERN_PELTS = Pattern.compile("§r §r§fPelts: §r§5(\\d+)§r"); + + public MinionHelperInventoryLoader(MinionHelperManager manager) { + this.manager = manager; + } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Load event) { + manager.setLocalPelts(-1); + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; + if (!NotEnoughUpdates.INSTANCE.config.minionHelper.gui) return; + if (manager.notReady()) return; + ticks++; + + if (ticks % 5 != 0) return; + + if (manager.inCraftedMinionsInventory()) { + checkInventory(); + } else { + pagesSeenAlready.clear(); + dirty = true; + } + } + + private void checkInventory() { + Container openContainer = Minecraft.getMinecraft().thePlayer.openContainer; + if (openContainer instanceof ContainerChest) { + if (dirty) { + dirty = false; + checkNextSlot(openContainer); + checkLocalPelts(); + } + if (manager.getDebugPlayerUuid() == null) { + loadMinionData(openContainer); + } + } + } + + private void checkLocalPelts() { + int pelts = -1; + for (String name : TabListUtils.getTabList()) { + Matcher matcher = PATTERN_PELTS.matcher(name); + if (matcher.matches()) { + pelts = Integer.parseInt(matcher.group(1)); + break; + } + } + + manager.setLocalPelts(pelts); + } + + private void checkNextSlot(Container openContainer) { + Slot informationSlot = openContainer.inventorySlots.get(50); + if (informationSlot.getHasStack()) { + ItemStack informationStack = informationSlot.getStack(); + for (String line : ItemUtils.getLore(informationStack)) { + Matcher matcher = PATTERN_MINIONS_NEEDED.matcher(line); + if (matcher.matches()) { + int debugNeedForNextSlot = manager.getDebugNeedForNextSlot(); + int needForNextSlot = debugNeedForNextSlot != -1 ? debugNeedForNextSlot : Integer.parseInt(matcher.group(1)); + + manager.setNeedForNextSlot(needForNextSlot); + return; + } + } + } + } + + private void loadMinionData(Container openContainer) { + Slot firstSlot = openContainer.inventorySlots.get(10); + boolean shouldLoad = false; + if (firstSlot != null) { + if (firstSlot.getHasStack()) { + ItemStack stack = firstSlot.getStack(); + String displayName = stack.getDisplayName(); + if (!pagesSeenAlready.contains(displayName)) { + pagesSeenAlready.add(displayName); + shouldLoad = true; + } + } + } + + if (!shouldLoad) return; + + int crafted = 0; + for (Slot slot : openContainer.inventorySlots) { + if (!slot.getHasStack()) continue; + ItemStack stack = slot.getStack(); + if (stack == null) continue; + if (slot.slotNumber != slot.getSlotIndex()) continue; + + String displayName = stack.getDisplayName(); + if (!displayName.contains(" Minion")) continue; + + displayName = StringUtils.cleanColour(displayName); + int index = 0; + for (String line : ItemUtils.getLore(stack)) { + index++; + if (!line.contains("Tier")) { + continue; + } + if (line.contains("§a")) { + Minion minion = manager.getMinionByName(displayName, index); + if (!minion.isCrafted()) { + minion.setCrafted(true); + crafted++; + } + } + } + } + if (crafted > 0) { + manager.getOverlay().resetCache(); + } + } + + public void onProfileSwitch() { + dirty = true; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/repo/MinionHelperRepoLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/repo/MinionHelperRepoLoader.java new file mode 100644 index 00000000..49dac537 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/repo/MinionHelperRepoLoader.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders.repo; + +import com.google.common.collect.ArrayListMultimap; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.CustomRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.CustomSource; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.NpcSource; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; + +public class MinionHelperRepoLoader { + private final MinionHelperManager manager; + private boolean dirty = true; + private int ticks = 0; + private boolean readyToUse = false; + private final MinionHelperRepoMinionLoader minionLoader; + boolean errorWhileLoading = false; + + public MinionHelperRepoLoader(MinionHelperManager manager) { + this.manager = manager; + minionLoader = new MinionHelperRepoMinionLoader(this, manager); + } + + /** + * This adds support for the /neureloadrepo command + */ + @SubscribeEvent(priority = EventPriority.LOWEST) + public void onRepoReload(RepositoryReloadEvent event) { + setDirty(); + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (Minecraft.getMinecraft().thePlayer == null) return; + if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; + if (!NotEnoughUpdates.INSTANCE.config.minionHelper.gui) return; + ticks++; + + if (ticks % 5 != 0) return; + + if (dirty) { + dirty = false; + load(); + } + } + + void load() { + errorWhileLoading = false; + + createMinions(); + + loadNpcData(); + minionLoader.loadMinionData(); + loadCustomSources(); + + testForMissingData(); + + manager.reloadData(); + readyToUse = true; + + if (errorWhileLoading) { + Utils.showOutdatedRepoNotification(); + } + } + + private void loadCustomSources() { + Map<String, String> customSource = new HashMap<>(); + + customSource.put("SNOW_GENERATOR_1", "Gifts"); + + customSource.put("FLOWER_GENERATOR_1", "Dark Auction"); + + customSource.put("REVENANT_GENERATOR_1", "Zombie Slayer"); + customSource.put("TARANTULA_GENERATOR_1", "Spider Slayer"); + + for (Map.Entry<String, String> entry : customSource.entrySet()) { + String internalName = entry.getKey(); + String sourceName = entry.getValue(); + Minion minion = manager.getMinionById(internalName); + if (minion == null) continue; + manager.setCustomSource(minion, new CustomSource(sourceName)); + } + + manager.getMinionById("FLOWER_GENERATOR_1").getRequirements().add(new CustomRequirement( + "Buy a §cFlower Minion 1 §7from Dark Auction")); + manager.getMinionById("SNOW_GENERATOR_1").getRequirements().add(new CustomRequirement( + "Get a §cSnow Minion 1 §7from opening gifts")); + + } + + private void loadNpcData() { + TreeMap<String, JsonObject> itemInformation = NotEnoughUpdates.INSTANCE.manager.getItemInformation(); + for (Map.Entry<String, JsonObject> entry : itemInformation.entrySet()) { + String internalName = entry.getKey(); + if (!internalName.endsWith("_NPC")) continue; + JsonObject jsonObject = entry.getValue(); + if (!jsonObject.has("recipes")) continue; + + if (!jsonObject.has("displayname")) continue; + String npcName = jsonObject.get("displayname").getAsString(); + npcName = StringUtils.cleanColour(npcName); + if (npcName.contains(" (")) { + npcName = npcName.split(" \\(")[0]; + } + + for (JsonElement element : jsonObject.get("recipes").getAsJsonArray()) { + JsonObject object = element.getAsJsonObject(); + if (!object.has("type")) continue; + if (!object.get("type").getAsString().equals("npc_shop")) continue; + if (!object.has("result")) continue; + + String result = object.get("result").getAsString(); + if (!result.contains("_GENERATOR_")) continue; + Minion minion = manager.getMinionById(result); + if (!object.has("cost")) continue; + + RecipeBuilder builder = new RecipeBuilder(manager); + + for (JsonElement costEntry : object.get("cost").getAsJsonArray()) { + String price = costEntry.getAsString(); + builder.addLine(minion, price); + } + + ArrayListMultimap<String, Integer> map = builder.getItems(); + int coins = 0; + if (map.containsKey("SKYBLOCK_COIN")) { + coins = map.get("SKYBLOCK_COIN").get(0); + map.removeAll("SKYBLOCK_COIN"); + } + + minion.setMinionSource(new NpcSource(npcName, coins, builder.getItems())); + minion.setParent(builder.getParent()); + } + } + } + + private void createMinions() { + for (Map.Entry<String, JsonElement> entry : Constants.MISC.get("minions").getAsJsonObject().entrySet()) { + String internalName = entry.getKey(); + int maxTier = entry.getValue().getAsInt(); + for (int i = 0; i < maxTier; i++) { + int tier = i + 1; + manager.createMinion(internalName + "_" + tier, tier); + } + } + } + + private void testForMissingData() { + for (Minion minion : manager.getAllMinions().values()) { + if (minion.getMinionSource() == null) { + errorWhileLoading = true; + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) { + Utils.addChatMessage("§c[NEU] The Minion '" + minion.getInternalName() + " has no source!"); + } + } + if (minion.getDisplayName() == null) { + errorWhileLoading = true; + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) { + Utils.addChatMessage("§c[NEU] The Minion '" + minion.getInternalName() + " has no display name!"); + } + } + if (manager.getRequirementsManager().getRequirements(minion).isEmpty()) { + errorWhileLoading = true; + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) { + Utils.addChatMessage("§c[NEU] The Minion '" + minion.getInternalName() + " has no requirements!"); + } + } + if (minion.getTier() > 1 && minion.getParent() == null) { + errorWhileLoading = true; + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) { + Utils.addChatMessage("§c[NEU] The Minion '" + minion.getInternalName() + " has parent!"); + } + } + } + } + + public void setDirty() { + dirty = true; + readyToUse = false; + } + + public boolean isReadyToUse() { + return readyToUse; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/repo/MinionHelperRepoMinionLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/repo/MinionHelperRepoMinionLoader.java new file mode 100644 index 00000000..6abc5c56 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/repo/MinionHelperRepoMinionLoader.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders.repo; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.CollectionRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.ReputationRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.SlayerRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.CraftingSource; +import io.github.moulberry.notenoughupdates.util.Utils; + +import java.util.Map; +import java.util.TreeMap; +import java.util.regex.Pattern; + +public class MinionHelperRepoMinionLoader { + + private final MinionHelperRepoLoader repoLoader; + private final MinionHelperManager manager; + + public MinionHelperRepoMinionLoader(MinionHelperRepoLoader repoLoader, MinionHelperManager manager) { + this.repoLoader = repoLoader; + this.manager = manager; + } + + void loadMinionData() { + TreeMap<String, JsonObject> itemInformation = NotEnoughUpdates.INSTANCE.manager.getItemInformation(); + + for (Map.Entry<String, Minion> entry : manager.getAllMinions().entrySet()) { + String internalName = entry.getKey(); + if (!itemInformation.containsKey(internalName)) continue; + Minion minion = entry.getValue(); + + JsonObject jsonObject = itemInformation.get(internalName); + if (jsonObject.has("displayname")) { + String displayName = jsonObject.get("displayname").getAsString(); + displayName = StringUtils.cleanColour(displayName); + displayName = StringUtils.removeLastWord(displayName, " "); + minion.setDisplayName(displayName); + } + + if (jsonObject.has("recipe")) { + loadRecipes(minion, jsonObject); + } + + loadRequirements(minion, jsonObject); + } + } + + private void loadRequirements(Minion minion, JsonObject jsonObject) { + for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { + String name = entry.getKey(); + if (name.endsWith("_req") || name.equals("crafttext")) { + String value = entry.getValue().getAsString(); + + try { + switch (name) { + case "reputation_req": { + String[] split = value.split(":"); + String reputationType = split[0]; + int reputation = Integer.parseInt(split[1]); + minion.getRequirements().add(new ReputationRequirement(reputationType, reputation)); + break; + } + case "crafttext": { + if (minion.getTier() != 1) break; + if (value.isEmpty()) break; + + String rawCollection = value.split(Pattern.quote(": "))[1]; + String cleanCollection = StringUtils.removeLastWord(rawCollection, " "); + String rawTier = rawCollection.substring(cleanCollection.length() + 1); + int tier = Utils.parseRomanNumeral(rawTier); + minion.getRequirements().add(new CollectionRequirement(cleanCollection, tier)); + break; + } + case "slayer_req": { + String[] split = value.split("_"); + String slayerType = split[0].toLowerCase(); + int tier = Integer.parseInt(split[1]); + minion.getRequirements().add(new SlayerRequirement(slayerType, tier)); + break; + } + } + } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { + repoLoader.errorWhileLoading = true; + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) { + Utils.addChatMessage( + "§c[NEU] Error in MinionHelperRepoLoader while loading repo entry " + minion.getDisplayName() + " " + + minion.getTier() + ": " + + e.getClass().getSimpleName() + ": " + e.getMessage()); + } + e.printStackTrace(); + } + } + } + } + + private void loadRecipes(Minion minion, JsonObject jsonObject) { + JsonObject recipes = jsonObject.get("recipe").getAsJsonObject(); + RecipeBuilder builder = new RecipeBuilder(manager); + for (Map.Entry<String, JsonElement> entry : recipes.entrySet()) { + String rawString = entry.getValue().getAsString(); + + builder.addLine(minion, rawString); + } + + minion.setMinionSource(new CraftingSource(builder.getItems())); + minion.setParent(builder.getParent()); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/repo/RecipeBuilder.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/repo/RecipeBuilder.java new file mode 100644 index 00000000..e7738954 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/loaders/repo/RecipeBuilder.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.loaders.repo; + +import com.google.common.collect.ArrayListMultimap; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.util.Utils; + +public class RecipeBuilder { + private final MinionHelperManager manager; + private Minion parent = null; + private final ArrayListMultimap<String, Integer> items = ArrayListMultimap.create(); + + public RecipeBuilder(MinionHelperManager manager) { + this.manager = manager; + } + + public Minion getParent() { + return parent; + } + + public ArrayListMultimap<String, Integer> getItems() { + return items; + } + + public void addLine(Minion minion, String rawString) { + String[] split = rawString.split(":"); + String itemName = split[0]; + + boolean isParent = false; + if (itemName.contains("_GENERATOR_")) { + String minionInternalName = minion.getInternalName(); + boolean same = StringUtils.removeLastWord(itemName, "_").equals(StringUtils.removeLastWord( + minionInternalName, + "_" + )); + if (same) { + Minion recipeMinion = manager.getMinionById(itemName); + if (recipeMinion.getTier() == minion.getTier() - 1) { + parent = recipeMinion; + if (parent == null) { + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) { + Utils.addChatMessage("Parent is null for minion " + minionInternalName); + } + } + isParent = true; + } + } + } + if (!isParent) { + int amount = Integer.parseInt(split[1]); + items.put(itemName, amount); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java new file mode 100644 index 00000000..6219cf2c --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlay.java @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.render; + +import com.google.common.collect.Lists; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.ArrowPagesUtils; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.miscgui.TrophyRewardOverlay; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables.OverviewLine; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables.OverviewText; +import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; +import io.github.moulberry.notenoughupdates.util.ItemUtils; +import io.github.moulberry.notenoughupdates.util.NotificationHandler; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +public class MinionHelperOverlay { + + private final ResourceLocation minionOverlayImage = new ResourceLocation("notenoughupdates:minion_overlay.png"); + private final ResourceLocation greenCheckImage = new ResourceLocation("notenoughupdates:dungeon_map/green_check.png"); + private final ResourceLocation whiteCheckImage = new ResourceLocation("notenoughupdates:dungeon_map/white_check.png"); + + private final MinionHelperManager manager; + private final MinionHelperOverlayHover hover; + private int[] topLeft = new int[]{237, 110}; + + private LinkedHashMap<String, OverviewLine> cacheRenderMap = null; + private int cacheTotalPages = -1; + + private boolean filterEnabled = true; + private boolean useInstantBuyPrice = true; + + private int maxPerPage = 8; + private int currentPage = 0; + + public MinionHelperOverlay(MinionHelperManager manager) { + this.manager = manager; + hover = new MinionHelperOverlayHover(this, manager); + } + + @SubscribeEvent + public void onGuiOpen(GuiOpenEvent event) { + resetCache(); + } + + public void resetCache() { + cacheRenderMap = null; + cacheTotalPages = -1; + } + + @SubscribeEvent + public void onDrawBackground(GuiScreenEvent.BackgroundDrawnEvent event) { + if (!manager.inCraftedMinionsInventory()) return; + if (!NotEnoughUpdates.INSTANCE.config.minionHelper.gui) return; + if (manager.isInvalidApiKey()) { + LinkedHashMap<String, OverviewLine> map = new LinkedHashMap<>(); + map.put("§cInvalid API Key!", new OverviewText(Collections.emptyList(), () -> {})); + render(map); + return; + } + if (manager.notReady()) { + LinkedHashMap<String, OverviewLine> map = new LinkedHashMap<>(); + map.put("§cLoading...", new OverviewText(Collections.emptyList(), () -> {})); + render(map); + return; + } + + if (manager.getApi().isNotifyNoCollectionApi()) { + NotificationHandler.displayNotification(Lists.newArrayList( + "", + "§cCollection API is disabled!", + "§cMinion Helper will not filter minions that", + "§cdo not meet the collection requirements!" + ), false, true); + manager.getApi().setNotifyNoCollectionApi(false); + } + + LinkedHashMap<String, OverviewLine> renderMap = getRenderMap(); + + hover.renderHover(renderMap); + render(renderMap); + + renderArrows(); + } + + private void renderArrows() { + GuiScreen gui = Minecraft.getMinecraft().currentScreen; + if (gui instanceof AccessorGuiContainer) { + AccessorGuiContainer container = (AccessorGuiContainer) gui; + int guiLeft = container.getGuiLeft(); + int guiTop = container.getGuiTop(); + int totalPages = getTotalPages(); + ArrowPagesUtils.onDraw(guiLeft, guiTop, topLeft, currentPage, totalPages); + } + } + + @SubscribeEvent + public void onMouseClick(GuiScreenEvent.MouseInputEvent.Pre event) { + if (!manager.inCraftedMinionsInventory()) return; + if (!NotEnoughUpdates.INSTANCE.config.minionHelper.gui) return; + if (manager.notReady()) return; + if (!Mouse.getEventButtonState()) return; + + OverviewLine overviewLine = getObjectOverMouse(getRenderMap()); + if (overviewLine != null) { + overviewLine.onClick(); + event.setCanceled(true); + } + + int totalPages = getTotalPages(); + if (event.gui instanceof AccessorGuiContainer) { + int guiLeft = ((AccessorGuiContainer) event.gui).getGuiLeft(); + int guiTop = ((AccessorGuiContainer) event.gui).getGuiTop(); + if (ArrowPagesUtils.onPageSwitchMouse(guiLeft, guiTop, topLeft, currentPage, totalPages, pageChange -> { + currentPage = pageChange; + resetCache(); + })) { + event.setCanceled(true); + } + } + checkButtonClick(); + } + + private void checkButtonClick() { + GuiScreen gui = Minecraft.getMinecraft().currentScreen; + if (!(gui instanceof GuiChest)) return; + + int xSize = ((AccessorGuiContainer) gui).getXSize(); + int guiLeft = ((AccessorGuiContainer) gui).getGuiLeft(); + int guiTop = ((AccessorGuiContainer) gui).getGuiTop(); + + final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + final int scaledWidth = scaledresolution.getScaledWidth(); + final int scaledHeight = scaledresolution.getScaledHeight(); + int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; + int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; + + int x = guiLeft + xSize + 4 + 149 - 3; + int y = guiTop + 109 - 3; + if (mouseX > x && mouseX < x + 16 && + mouseY > y && mouseY < y + 16) { + toggleShowAvailable(); + } + + x = guiLeft + xSize + 4 + 149 - 3 - 16 - 3; + y = guiTop + 109 - 3; + if (mouseX > x && mouseX < x + 16 && + mouseY > y && mouseY < y + 16) { + toggleUseInstantBuyPrice(); + } + } + + @SubscribeEvent + public void onMouseClick(GuiScreenEvent.KeyboardInputEvent.Pre event) { + if (!manager.inCraftedMinionsInventory()) return; + if (!NotEnoughUpdates.INSTANCE.config.minionHelper.gui) return; + if (manager.notReady()) return; + + int totalPages = getTotalPages(); + if (ArrowPagesUtils.onPageSwitchKey(currentPage, totalPages, pageChange -> { + currentPage = pageChange; + resetCache(); + })) { + event.setCanceled(true); + } + } + + private Map<Minion, Double> getMissing() { + Map<Minion, Double> prices = new HashMap<>(); + for (Minion minion : manager.getAllMinions().values()) { + + if (!minion.doesMeetRequirements() && filterEnabled) continue; + if (!minion.isCrafted()) { + double price = manager.getPriceCalculation().calculateUpgradeCosts(minion, true); + prices.put(minion, price); + } + } + return prices; + } + + private void render(Map<String, OverviewLine> renderMap) { + Minecraft minecraft = Minecraft.getMinecraft(); + Gui gui = Minecraft.getMinecraft().currentScreen; + if (!(gui instanceof GuiChest)) return; + int xSize = ((AccessorGuiContainer) gui).getXSize(); + int guiLeft = ((AccessorGuiContainer) gui).getGuiLeft(); + int guiTop = ((AccessorGuiContainer) gui).getGuiTop(); + minecraft.getTextureManager().bindTexture(minionOverlayImage); + GL11.glColor4f(1, 1, 1, 1); + GlStateManager.disableLighting(); + Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 168, 128, 0, 1f, 0, 1f, GL11.GL_NEAREST); + + if (filterEnabled) { + minecraft.getTextureManager().bindTexture(greenCheckImage); + } else { + minecraft.getTextureManager().bindTexture(whiteCheckImage); + } + Utils.drawTexturedRect(guiLeft + xSize + 4 + 149, guiTop + 109, 10, 10, 0, 1f, 0, 1f, GL11.GL_NEAREST); + GlStateManager.disableLighting(); + + RenderHelper.enableGUIStandardItemLighting(); + ItemStack itemStack; + if (useInstantBuyPrice) { + itemStack = ItemUtils.getCoinItemStack(10_000_000); + } else { + itemStack = ItemUtils.getCoinItemStack(100_000); + } + Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI( + itemStack, + guiLeft + xSize + 4 + 149 - 3 - 16 - 3, + guiTop + 109 - 3 + ); + + RenderHelper.disableStandardItemLighting(); + + int x = guiLeft + xSize + 10; + int i = 0; + int y = guiTop + 6; + FontRenderer fontRendererObj = minecraft.fontRendererObj; + for (Map.Entry<String, OverviewLine> entry : renderMap.entrySet()) { + String line = entry.getKey(); + + if (line.contains("§6")) { + String[] split = line.split("§6"); + line = split[0]; + String price = "§6§l" + split[1]; + int lineLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line); + fontRendererObj.drawString(price, x + lineLen, y, -1, true); + } + + fontRendererObj.drawString(line, x, y, -1, false); + i++; + if (i == 2) { + y += 15; + } else { + y += 10; + } + } + } + + private LinkedHashMap<String, OverviewLine> getRenderMap() { + if (cacheRenderMap != null) return cacheRenderMap; + + Map<Minion, Double> prices = getMissing(); + LinkedHashMap<String, OverviewLine> renderMap = new LinkedHashMap<>(); + + addTitle(prices, renderMap); + addNeedToNextSlot(prices, renderMap); + + if (!prices.isEmpty()) { + addMinions(prices, renderMap); + } + + cacheRenderMap = renderMap; + return renderMap; + } + + private void addNeedToNextSlot( + Map<Minion, Double> prices, + LinkedHashMap<String, OverviewLine> renderMap + ) { + int neededForNextSlot = manager.getNeedForNextSlot(); + String color = "§8"; + if (neededForNextSlot == -1) { + renderMap.put(color + "Next slot: ?", new OverviewText(Collections.emptyList(), () -> {})); + return; + } + + double priceNeeded = 0; + int index = 0; + for (Double price : TrophyRewardOverlay.sortByValue(prices).values()) { + priceNeeded += price; + index++; + if (index == neededForNextSlot) break; + } + String format = manager.getPriceCalculation().formatCoins(priceNeeded); + format = format.replace(" coins", ""); + String text = color + "Next slot: §3" + neededForNextSlot + " minions §8- " + format; + renderMap.put(text, new OverviewText(Collections.emptyList(), () -> {})); + } + + private void addTitle(Map<Minion, Double> prices, LinkedHashMap<String, OverviewLine> renderMap) { + String name = "§8" + prices.size() + " " + (filterEnabled ? "craftable" : "total") + " minions"; + renderMap.put(name, new OverviewText(Collections.emptyList(), () -> {})); + } + + private void addMinions(Map<Minion, Double> prices, LinkedHashMap<String, OverviewLine> renderMap) { + int skipPreviousPages = currentPage * maxPerPage; + int i = 0; + Map<Minion, Double> sort = TrophyRewardOverlay.sortByValue(prices); + for (Minion minion : sort.keySet()) { + if (i >= skipPreviousPages) { + String displayName = minion.getDisplayName(); + if (displayName == null) { + if (NotEnoughUpdates.INSTANCE.config.hidden.dev) { + Utils.addChatMessage("§cDisplayname is null for " + minion.getInternalName()); + } + continue; + } + + displayName = displayName.replace(" Minion", ""); + String format = manager.getPriceCalculation().calculateUpgradeCostsFormat(minion, true); + format = format.replace(" coins", ""); + String requirementFormat = minion.doesMeetRequirements() ? "§9" : "§c"; + renderMap.put( + requirementFormat + displayName + " " + minion.getTier() + " §8- " + format, + minion + ); + } + + i++; + if (i == ((currentPage + 1) * maxPerPage)) break; + } + } + + private int getTotalPages() { + if (cacheTotalPages != -1) return cacheTotalPages; + + Map<Minion, Double> prices = getMissing(); + int totalPages = (int) ((double) prices.size() / maxPerPage); + if (prices.size() % maxPerPage != 0) { + totalPages++; + } + + cacheTotalPages = totalPages; + return totalPages; + } + + private void toggleShowAvailable() { + filterEnabled = !filterEnabled; + currentPage = 0; + resetCache(); + } + + private void toggleUseInstantBuyPrice() { + useInstantBuyPrice = !useInstantBuyPrice; + currentPage = 0; + resetCache(); + manager.getPriceCalculation().resetCache(); + } + + OverviewLine getObjectOverMouse(LinkedHashMap<String, OverviewLine> renderMap) { + GuiScreen gui = Minecraft.getMinecraft().currentScreen; + if (!(gui instanceof GuiChest)) return null; + + int xSize = ((AccessorGuiContainer) gui).getXSize(); + int guiLeft = ((AccessorGuiContainer) gui).getGuiLeft(); + int guiTop = ((AccessorGuiContainer) gui).getGuiTop(); + + int x = guiLeft + xSize + 9; + int y = guiTop + 5; + + final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + final int scaledWidth = scaledresolution.getScaledWidth(); + final int scaledHeight = scaledresolution.getScaledHeight(); + int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; + int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; + + int i = 0; + FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj; + for (Map.Entry<String, OverviewLine> entry : renderMap.entrySet()) { + String text = entry.getKey(); + int width = fontRenderer.getStringWidth(StringUtils.cleanColour(text)); + if (mouseX > x && mouseX < x + width + 4 && + mouseY > y && mouseY < y + 11) { + return entry.getValue(); + } + i++; + if (i == 2) { + y += 15; + } else { + y += 10; + } + } + + return null; + } + + public void onProfileSwitch() { + currentPage = 0; + filterEnabled = true; + useInstantBuyPrice = true; + } + + public void setMaxPerPage(int maxPerPage) { + this.maxPerPage = maxPerPage; + } + + public void setTopLeft(int[] topLeft) { + this.topLeft = topLeft; + } + + public boolean isFilterEnabled() { + return filterEnabled; + } + + public boolean isUseInstantBuyPrice() { + return useInstantBuyPrice; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlayHover.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlayHover.java new file mode 100644 index 00000000..fcafa534 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperOverlayHover.java @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.render; + +import com.google.common.collect.ArrayListMultimap; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.ApiData; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables.OverviewLine; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables.OverviewText; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.CollectionRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.MinionRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.ReputationRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.CraftingSource; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.MinionSource; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.NpcSource; +import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.gui.inventory.GuiChest; +import org.lwjgl.input.Mouse; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class MinionHelperOverlayHover { + + private final MinionHelperOverlay overlay; + private final MinionHelperManager manager; + + public MinionHelperOverlayHover(MinionHelperOverlay overlay, MinionHelperManager manager) { + this.overlay = overlay; + this.manager = manager; + } + + void renderHover(LinkedHashMap<String, OverviewLine> renderMap) { + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) return; + + final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + final int scaledWidth = scaledresolution.getScaledWidth(); + final int scaledHeight = scaledresolution.getScaledHeight(); + int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; + int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; + + OverviewLine mouseObject = overlay.getObjectOverMouse(renderMap); + if (mouseObject != null) { + Utils.drawHoveringText(getTooltip(mouseObject), mouseX, mouseY, + scaledWidth, scaledHeight, -1, Minecraft.getMinecraft().fontRendererObj + ); + } + + renderButtons(); + } + + private void renderButtons() { + GuiScreen gui = Minecraft.getMinecraft().currentScreen; + if (!(gui instanceof GuiChest)) return; + + int xSize = ((AccessorGuiContainer) gui).getXSize(); + int guiLeft = ((AccessorGuiContainer) gui).getGuiLeft(); + int guiTop = ((AccessorGuiContainer) gui).getGuiTop(); + + final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + final int scaledWidth = scaledresolution.getScaledWidth(); + final int scaledHeight = scaledresolution.getScaledHeight(); + int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth; + int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1; + + + int x = guiLeft + xSize + 4 + 149 - 3; + int y = guiTop + 109 - 3; + if (mouseX > x && mouseX < x + 16 && + mouseY > y && mouseY < y + 16) { + renderFilterButton(scaledWidth, scaledHeight, mouseX, mouseY); + } + + x = guiLeft + xSize + 4 + 149 - 3 - 16 - 3; + y = guiTop + 109 - 3; + if (mouseX > x && mouseX < x + 16 && + mouseY > y && mouseY < y + 16) { + renderBuyPriceButton(scaledWidth, scaledHeight, mouseX, mouseY); + } + } + + private void renderFilterButton(int scaledWidth, int scaledHeight, int mouseX, int mouseY) { + List<String> list = new ArrayList<>(); + + if (overlay.isFilterEnabled()) { + list.add("§aFilter enabled"); + list.add("§7Only show minions that can be"); + list.add("§7crafted and meet requirements."); + } else { + list.add("§cFilter disabled"); + list.add("§7Show all minions. §cRed ones §7have"); + list.add("§7missing requirements."); + } + + list.add(""); + list.add("§eClick to toggle!"); + + Utils.drawHoveringText(list, mouseX, mouseY, scaledWidth, scaledHeight, -1, + Minecraft.getMinecraft().fontRendererObj + ); + } + + private void renderBuyPriceButton(int scaledWidth, int scaledHeight, int mouseX, int mouseY) { + List<String> list = new ArrayList<>(); + + if (overlay.isUseInstantBuyPrice()) { + list.add("§bUse Instant Buy price"); + list.add("§7Use the price to pay when"); + list.add("§7buying the item right now."); + list.add("§7This will be more expensive!"); + } else { + list.add("§6Use Buy Offer price"); + list.add("§7Use the price for creating an"); + list.add("§7offer to buy the item cheaper."); + list.add("§7This can take longer!"); + } + + list.add(""); + list.add("§eClick to toggle!"); + + Utils.drawHoveringText(list, mouseX, mouseY, scaledWidth, scaledHeight, -1, + Minecraft.getMinecraft().fontRendererObj + ); + } + + private List<String> getTooltip(OverviewLine overviewLine) { + List<String> lines = new ArrayList<>(); + + if (overviewLine instanceof OverviewText) { + OverviewText overviewText = (OverviewText) overviewLine; + lines.addAll(overviewText.getLines()); + } else if (overviewLine instanceof Minion) { + + Minion minion = (Minion) overviewLine; + MinionSource minionSource = minion.getMinionSource(); + if (minion.getCustomSource() != null) { + minionSource = minion.getCustomSource(); + } + String displayName = minion.getDisplayName(); + lines.add("§9" + displayName + " " + minion.getTier()); + List<MinionRequirement> requirements = manager.getRequirementsManager().getRequirements(minion); + if (!requirements.isEmpty()) { + for (MinionRequirement requirement : requirements) { + String result = getRequirementDescription(minion, requirement); + if (result == null) continue; + lines.add(result); + } + } else { + lines.add("§cNo requirements loaded!"); + } + + if (minionSource instanceof CraftingSource) { + CraftingSource craftingSource = (CraftingSource) minionSource; + lines.add(""); + String format = manager.getPriceCalculation().calculateUpgradeCostsFormat(minion, true); + if (minion.getTier() == 1) { + lines.add("§7Full crafting cost: " + format); + } else { + lines.add("§7Upgrade cost: " + format); + } + formatItems(lines, grabAllItems(craftingSource.getItems())); + + } else if (minionSource instanceof NpcSource) { + NpcSource npcSource = (NpcSource) minionSource; + String npcName = npcSource.getNpcName(); + lines.add(""); + lines.add("§7Buy from: §9" + npcName + " (NPC)"); + lines.add(""); + lines.add("§7Cost: " + manager.getPriceCalculation().calculateUpgradeCostsFormat(minion, true)); + int coins = npcSource.getCoins(); + if (coins != 0) { + lines.add(" §8- " + manager.getPriceCalculation().formatCoins(coins)); + } + formatItems(lines, grabAllItems(npcSource.getItems())); + } + + lines.add(""); + lines.add("§eClick to view recipe!"); + } + return lines; + } + + private String getRequirementDescription(Minion minion, MinionRequirement requirement) { + boolean meetRequirement = manager.getRequirementsManager().meetRequirement(minion, requirement); + String color = meetRequirement ? "§a" : "§c"; + + String description = requirement.printDescription(color); + if (requirement instanceof CollectionRequirement && manager.getApi().isCollectionApiDisabled()) { + description += " §cAPI DISABLED! §7"; + } + + if (!meetRequirement) { + if (requirement instanceof ReputationRequirement) { + ReputationRequirement reputationRequirement = (ReputationRequirement) requirement; + String reputationType = reputationRequirement.getReputationType(); + ApiData apiData = manager.getApi().getApiData(); + int having; + if (reputationType.equals("BARBARIAN")) { + having = apiData.getBarbariansReputation(); + } else if (reputationType.equals("MAGE")) { + having = apiData.getMagesReputation(); + } else { + Utils.addChatMessage("§c[NEU] Minion Helper: Unknown reputation type: '" + reputationType + "'"); + return null; + } + int need = reputationRequirement.getReputation(); + if (having < 0) having = 0; + + String reputationName = StringUtils.firstUpperLetter(reputationType.toLowerCase()); + String havingFormat = Utils.formatNumberWithDots(having); + String needFormat = Utils.formatNumberWithDots(need); + description = "Reputation: §c" + havingFormat + "§8/§c" + needFormat + " §7" + reputationName + " Reputation"; + } + } + + return " §8- §7" + description; + } + + private void formatItems(List<String> lines, Map<String, Integer> allItems) { + for (Map.Entry<String, Integer> entry : allItems.entrySet()) { + String internalName = entry.getKey(); + int amount = entry.getValue(); + if (internalName.equals("SKYBLOCK_PELT")) { + int peltCount = manager.getApi().getApiData().getPeltCount(); + + lines.add(" §8- §5" + peltCount + "§8/§5" + amount + " Pelts"); + continue; + } + + String name = NotEnoughUpdates.INSTANCE.manager.getDisplayName(internalName); + double price = manager.getPriceCalculation().getPrice(internalName); + String priceFormat = manager.getPriceCalculation().formatCoins(price * amount); + lines.add(" §8- §a" + amount + "§7x §f" + name + " " + priceFormat); + } + } + + private Map<String, Integer> grabAllItems(ArrayListMultimap<String, Integer> multimap) { + Map<String, Integer> allItems = new HashMap<>(); + for (Map.Entry<String, Integer> entry : multimap.entries()) { + String name = entry.getKey(); + int amount = entry.getValue(); + amount = allItems.getOrDefault(name, 0) + amount; + allItems.put(name, amount); + } + return allItems; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperTooltips.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperTooltips.java new file mode 100644 index 00000000..ef243a6f --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/MinionHelperTooltips.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.render; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.MinionSource; +import io.github.moulberry.notenoughupdates.util.ItemUtils; +import net.minecraft.item.ItemStack; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; + +import java.util.List; + +public class MinionHelperTooltips { + private final MinionHelperManager manager; + private boolean pressedShiftLast = false; + private boolean showFullCost = false; + + public MinionHelperTooltips(MinionHelperManager manager) { + this.manager = manager; + } + + @SubscribeEvent(priority = EventPriority.LOW) + public void onItemTooltip(ItemTooltipEvent event) { + if (!manager.inCraftedMinionsInventory()) return; + if (!NotEnoughUpdates.INSTANCE.config.minionHelper.tooltip) return; + if (manager.notReady()) return; + + boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + if (!pressedShiftLast && shift) { + showFullCost = !showFullCost; + } + pressedShiftLast = shift; + + ItemStack itemStack = event.itemStack; + if (itemStack == null) return; + String displayName = itemStack.getDisplayName(); + if (!displayName.endsWith(" Minion")) return; + displayName = StringUtils.cleanColour(displayName); + + List<String> lore = ItemUtils.getLore(itemStack); + if (lore.get(0).equals("§7You haven't crafted this minion.")) return; + + int index = 0; + for (String line : lore) { + index++; + if (!line.contains("Tier")) continue; + + Minion minion = manager.getMinionByName(displayName, index); + if (minion == null) { + System.err.println("minion is null for displayName '" + displayName + "' and tier " + index); + continue; + } + MinionSource minionSource = minion.getMinionSource(); + if (minionSource == null) { + System.err.println("minionSource is null for " + minion.getInternalName()); + continue; + } + String format = manager.getPriceCalculation().calculateUpgradeCostsFormat(minion, !showFullCost); + event.toolTip.set(index, line + " §8- " + format); + } + + if (showFullCost) { + event.toolTip.add("§8[Press SHIFT to show upgrade cost]"); + } else { + event.toolTip.add("§8[Press SHIFT to show full cost]"); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuConfigTutorial.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/renderables/OverviewLine.java index 6a2602f8..85d682b3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuConfigTutorial.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/renderables/OverviewLine.java @@ -17,10 +17,9 @@ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. */ -package io.github.moulberry.notenoughupdates.miscgui.tutorials; +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables; -public class NeuConfigTutorial extends TutorialBase { - static { - title = "NEU Config Tutorial"; - } +public abstract class OverviewLine { + + public abstract void onClick(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/renderables/OverviewText.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/renderables/OverviewText.java new file mode 100644 index 00000000..499ca758 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/renderables/OverviewText.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.render.renderables; + +import java.util.List; + +public class OverviewText extends OverviewLine { + + private final Runnable clickRunnable; + private final List<String> lines; + + public OverviewText(List<String> line, Runnable clickRunnable) { + this.lines = line; + this.clickRunnable = clickRunnable; + } + + public List<String> getLines() { + return lines; + } + + @Override + public void onClick() { + clickRunnable.run(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/CollectionRequirement.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/CollectionRequirement.java new file mode 100644 index 00000000..c01386e1 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/CollectionRequirement.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements; + +public class CollectionRequirement extends MinionRequirement { + + private final String collection; + private final int level; + + public CollectionRequirement(String collection, int level) { + this.collection = collection; + this.level = level; + } + + public int getLevel() { + return level; + } + + public String getCollection() { + return collection; + } + + @Override + public String printDescription(String color) { + return "Collection: " + color + collection + " level " + level; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/ButtonsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/CustomRequirement.java index 55113462..93174f03 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/ButtonsCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/CustomRequirement.java @@ -17,19 +17,17 @@ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. */ -package io.github.moulberry.notenoughupdates.commands.misc; +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements; -import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; +public class CustomRequirement extends MinionRequirement { -public class ButtonsCommand extends ClientCommandBase { - protected ButtonsCommand(String name) { - super(name); - } + private final String text; + public CustomRequirement(String text) { + this.text = text; + } @Override - public void processCommand(ICommandSender sender, String[] args) throws CommandException { - + public String printDescription(String color) { + return text; } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/MinionRequirement.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/MinionRequirement.java new file mode 100644 index 00000000..9dd3fe09 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/MinionRequirement.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements; + +public abstract class MinionRequirement { + public abstract String printDescription(String color); +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/ReputationRequirement.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/ReputationRequirement.java new file mode 100644 index 00000000..70d1e5fc --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/ReputationRequirement.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements; + +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.util.Utils; + +public class ReputationRequirement extends MinionRequirement { + + private final String reputationType; + private final int reputation; + private final String description; + + public ReputationRequirement(String reputationType, int reputation) { + this.reputationType = reputationType; + this.reputation = reputation; + + String reputationName = StringUtils.firstUpperLetter(reputationType.toLowerCase()); + description = Utils.formatNumberWithDots(reputation) + " §7" + reputationName + " Reputation"; + } + + public int getReputation() { + return reputation; + } + + public String getReputationType() { + return reputationType; + } + + @Override + public String printDescription(String color) { + return "Reputation: " + color + description; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/SlayerRequirement.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/SlayerRequirement.java new file mode 100644 index 00000000..78c588b1 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/SlayerRequirement.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements; + +import io.github.moulberry.notenoughupdates.core.util.StringUtils; + +public class SlayerRequirement extends MinionRequirement { + + private final String slayer; + private final int level; + + public SlayerRequirement(String slayer, int level) { + this.slayer = slayer; + this.level = level; + } + + public int getLevel() { + return level; + } + + public String getSlayer() { + return slayer; + } + + @Override + public String printDescription(String color) { + return "Slayer: " + color +StringUtils.firstUpperLetter(slayer)+ " level " + level; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/CraftingSource.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/CraftingSource.java new file mode 100644 index 00000000..eca689d1 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/CraftingSource.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources; + +import com.google.common.collect.ArrayListMultimap; + +public class CraftingSource extends MinionSource { + //name -> amount + private final ArrayListMultimap<String, Integer> items; + + public CraftingSource(ArrayListMultimap<String, Integer> items) { + this.items = items; + } + + public ArrayListMultimap<String, Integer> getItems() { + return items; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/CustomSource.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/CustomSource.java new file mode 100644 index 00000000..cf260a88 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/CustomSource.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources; + +public class CustomSource extends MinionSource { + + private final String sourceName; + + public CustomSource(String sourceName) { + this.sourceName = sourceName; + } + + public String getSourceName() { + return sourceName; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/MinionSource.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/MinionSource.java new file mode 100644 index 00000000..f54f0845 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/MinionSource.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources; + +public abstract class MinionSource { +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/NpcSource.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/NpcSource.java new file mode 100644 index 00000000..941890fa --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/sources/NpcSource.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources; + +import com.google.common.collect.ArrayListMultimap; + +public class NpcSource extends MinionSource { + private final String npcName; + // name -> amount + private final ArrayListMultimap<String, Integer> items; + private final int coins; + + public NpcSource(String npcName, int coins, ArrayListMultimap<String, Integer> items) { + this.npcName = npcName; + this.coins = coins; + this.items = items; + } + + public String getNpcName() { + return npcName; + } + + public ArrayListMultimap<String, Integer> getItems() { + return items; + } + + public int getCoins() { + return coins; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/util/MinionHelperPriceCalculation.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/util/MinionHelperPriceCalculation.java new file mode 100644 index 00000000..8f75b32c --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/util/MinionHelperPriceCalculation.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.util; + +import com.google.common.collect.ArrayListMultimap; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.CraftingSource; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.MinionSource; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.sources.NpcSource; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraftforge.client.event.GuiOpenEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.HashMap; +import java.util.Map; + +public class MinionHelperPriceCalculation { + + private final MinionHelperManager manager; + private final Map<String, String> upgradeCostFormatCache = new HashMap<>(); + private final Map<String, String> fullCostFormatCache = new HashMap<>(); + + public MinionHelperPriceCalculation(MinionHelperManager manager) { + this.manager = manager; + } + + @SubscribeEvent + public void onGuiOpen(GuiOpenEvent event) { + resetCache(); + } + + public void resetCache() { + upgradeCostFormatCache.clear(); + fullCostFormatCache.clear(); + } + + public String calculateUpgradeCostsFormat(Minion minion, boolean upgradeOnly) { + MinionSource source = minion.getMinionSource(); + + if (source == null) return "§c?"; + String internalName = minion.getInternalName(); + if (upgradeOnly) { + if (upgradeCostFormatCache.containsKey(internalName)) { + return upgradeCostFormatCache.get(internalName); + } + } else { + if (fullCostFormatCache.containsKey(internalName)) { + return fullCostFormatCache.get(internalName); + } + } + + if (upgradeOnly) { + if (minion.getCustomSource() != null) { + return (minion.getCustomSource()).getSourceName(); + } + } + + double costs = calculateUpgradeCosts(minion, upgradeOnly); + String result = formatCoins(costs, !upgradeOnly ? "§o" : ""); + + if (source instanceof NpcSource) { + ArrayListMultimap<String, Integer> items = ((NpcSource) source).getItems(); + if (items.containsKey("SKYBLOCK_PELT")) { + int amount = items.get("SKYBLOCK_PELT").get(0); + result += " §7+ §5" + amount + " Pelts"; + } + } + + if (upgradeOnly) { + upgradeCostFormatCache.put(internalName, result); + } else { + fullCostFormatCache.put(internalName, result); + } + + return result; + } + + public double calculateUpgradeCosts(Minion minion, boolean upgradeOnly) { + MinionSource source = minion.getMinionSource(); + + if (upgradeOnly) { + if (minion.getCustomSource() != null) { + return 0; + } + } + + if (source instanceof CraftingSource) { + CraftingSource craftingSource = (CraftingSource) source; + return getCosts(minion, upgradeOnly, craftingSource.getItems()); + + } else if (source instanceof NpcSource) { + NpcSource npcSource = (NpcSource) source; + double upgradeCost = getCosts(minion, upgradeOnly, npcSource.getItems()); + long coins = npcSource.getCoins(); + upgradeCost += coins; + + return upgradeCost; + } + + return 0; + } + + private double getCosts(Minion minion, boolean upgradeOnly, ArrayListMultimap<String, Integer> items) { + double upgradeCost = 0; + for (Map.Entry<String, Integer> entry : items.entries()) { + String internalName = entry.getKey(); + if (internalName.equals("SKYBLOCK_PELT")) continue; + double price = getPrice(internalName); + int amount = entry.getValue(); + upgradeCost += price * amount; + } + if (!upgradeOnly) { + Minion parent = minion.getParent(); + if (parent != null) { + upgradeCost += calculateUpgradeCosts(parent, false); + } + } + return upgradeCost; + } + + public double getPrice(String internalName) { + //Is minion + if (internalName.contains("_GENERATOR_")) { + return calculateUpgradeCosts(manager.getMinionById(internalName), false); + } + + //Is bazaar item + JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalName); + if (bazaarInfo != null) { + String bazaarMode; + if (manager.getOverlay().isUseInstantBuyPrice()) { + bazaarMode = "curr_buy"; + } else { + bazaarMode = "curr_sell"; + } + if (!bazaarInfo.has(bazaarMode)) { + + // Use buy order price when no sell offer exist. (e.g. inferno apex) + if (bazaarMode.equals("curr_buy")) { + bazaarMode = "curr_sell"; + if (!bazaarInfo.has(bazaarMode)) { + System.err.println(bazaarMode + " does not exist for '" + internalName + "'"); + return 0; + } + } else { + System.err.println(bazaarMode + " does not exist for '" + internalName + "'"); + return 0; + } + } + return bazaarInfo.get(bazaarMode).getAsDouble(); + } + + //is ah bin + double avgBinPrice = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAvgBin(internalName); + if (avgBinPrice >= 1) return avgBinPrice; + + //is ah without bin + JsonObject auctionInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalName); + if (auctionInfo == null) { + //only wood axe and similar useless items + return 1; + } + return (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + } + + public String formatCoins(double coins) { + return formatCoins(coins, ""); + } + + public String formatCoins(double coins, String extraFormat) { + int i = coins < 3 ? 1 : 0; + String format = Utils.shortNumberFormat(coins, i); + return "§6" + extraFormat + format + " coins"; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/util/MinionHelperRequirementsManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/util/MinionHelperRequirementsManager.java new file mode 100644 index 00000000..4a1b96b5 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/util/MinionHelperRequirementsManager.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscgui.minionhelper.util; + +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.ApiData; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.Minion; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.CollectionRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.CustomRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.MinionRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.ReputationRequirement; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.requirements.SlayerRequirement; +import io.github.moulberry.notenoughupdates.util.Utils; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class MinionHelperRequirementsManager { + + private final MinionHelperManager manager; + + public MinionHelperRequirementsManager(MinionHelperManager manager) { + this.manager = manager; + } + + public List<MinionRequirement> getRequirements(Minion minion) { + if (!minion.getRequirements().isEmpty()) { + return minion.getRequirements(); + } + + Minion parent = minion.getParent(); + if (parent != null) { + return getRequirements(parent); + } + + return Collections.emptyList(); + } + + public boolean meetAllRequirements(Minion minion) { + List<MinionRequirement> list = getRequirements(minion); + for (MinionRequirement requirement : list) { + if (!meetRequirement(minion, requirement)) { + return false; + } + } + + Minion parent = minion.getParent(); + if (parent != null) { + return meetAllRequirements(parent); + } + + return true; + } + + public boolean meetRequirement(Minion minion, MinionRequirement requirement) { + ApiData apiData = manager.getApi().getApiData(); + if (apiData == null) return false; + + if (requirement instanceof CollectionRequirement) { + if (apiData.isCollectionApiDisabled()) return true; + + CollectionRequirement collectionRequirement = (CollectionRequirement) requirement; + String collection = collectionRequirement.getCollection(); + String internalName = manager.formatInternalName(collection); + + int need = collectionRequirement.getLevel(); + Map<String, Integer> highestCollectionTier = apiData.getHighestCollectionTier(); + if (highestCollectionTier.containsKey(internalName)) { + int has = highestCollectionTier.get(internalName); + + return has >= need; + } + + } else if (requirement instanceof SlayerRequirement) { + SlayerRequirement slayerRequirement = (SlayerRequirement) requirement; + String slayer = slayerRequirement.getSlayer(); + //Because the neu-repo uses 'eman' and the hypixel api is using 'enderman' + if (slayer.equals("eman")) { + slayer = "enderman"; + } + int need = slayerRequirement.getLevel(); + Map<String, Integer> slayerTiers = apiData.getSlayerTiers(); + if (slayerTiers.containsKey(slayer)) { + return slayerTiers.get(slayer) >= need; + } + + } else if (requirement instanceof ReputationRequirement) { + ReputationRequirement reputationRequirement = (ReputationRequirement) requirement; + int need = reputationRequirement.getReputation(); + String reputationType = reputationRequirement.getReputationType(); + if (reputationType.equals("BARBARIAN")) { + return apiData.getBarbariansReputation() >= need; + } else if (reputationType.equals("MAGE")) { + return apiData.getMagesReputation() >= need; + } else { + Utils.addChatMessage("§c[NEU] Minion Helper: Unknown reputation type: '" + reputationType + "'"); + return false; + } + } else if (requirement instanceof CustomRequirement) { + return minion.doesMeetRequirements(); + } + + return false; + } + + public void reloadRequirements() { + for (Minion minion : manager.getAllMinions().values()) { + minion.setMeetRequirements(meetAllRequirements(minion)); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuTutorial.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuTutorial.java deleted file mode 100644 index c0a5d8c8..00000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuTutorial.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2022 NotEnoughUpdates contributors - * - * This file is part of NotEnoughUpdates. - * - * NotEnoughUpdates is free software: you can redistribute it - * and/or modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * NotEnoughUpdates is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. - */ - -package io.github.moulberry.notenoughupdates.miscgui.tutorials; - -import net.minecraft.client.Minecraft; -import net.minecraft.util.ResourceLocation; - -public class NeuTutorial extends TutorialBase { - static { - title = "NEU Tutorial"; - } - - @Override - public void setWorldAndResolution(Minecraft mc, int width, int height) { - super.setWorldAndResolution(mc, width, height); - screenshots = new ResourceLocation[18]; - for (int i = 0; i <= 17; i++) { - screenshots[i] = new ResourceLocation("notenoughupdates:ss_small/ss" + (i + 1) + "-0.jpg"); - } - } - - //static { - // texts[0].put(new Vector2f(0.73f, 0.60f), Utils.createList( - // EnumChatFormatting.GOLD + "Itemlist", - // EnumChatFormatting.GRAY + "Here you will find a list of (most) skyblock items", - // EnumChatFormatting.GRAY + "The itemlist can be accessed by opening your inventory or most menus while on skyblock" - // )); - // texts[1].put(new Vector2f(0.73f, 0.16f), Utils.createList( - // EnumChatFormatting.GOLD + "Itemlist", - // EnumChatFormatting.GRAY + "These are the page controls for the itemlist", - // EnumChatFormatting.GRAY + "Clicking these controls will bring you to other pages of the itemlist" - // )); - // texts[2].put(new Vector2f(0.73f, 1.05f), Utils.createList( - // EnumChatFormatting.GOLD + "Itemlist", - // EnumChatFormatting.GRAY + "These are the sorting controls for the itemlist", - // EnumChatFormatting.GRAY + "The buttons on the left control the ordering of the items", - // EnumChatFormatting.GRAY + "The buttons on the right can be used to filter a certain type of item" - // )); - // texts[3].put(new Vector2f(0.39f, 1.04f), Utils.createList( - // EnumChatFormatting.GOLD + "Itemlist", - // EnumChatFormatting.GRAY + "This is the search bar for the itemlist", - // EnumChatFormatting.GRAY + "Double-click the bar to enable inventory search mode", - // EnumChatFormatting.GRAY + "The button on the left opens up the mod settings", - // EnumChatFormatting.GRAY + "The button on the right displays this tutorial" - // )); - // texts[4].put(new Vector2f(0.39f, 0.99f), Utils.createList( - // EnumChatFormatting.GOLD + "QuickCommands", - // EnumChatFormatting.GRAY + "These are the QuickCommands", - // EnumChatFormatting.GRAY + "They let you warp around or access certain menus more easily" - // )); - // texts[5].put(new Vector2f(0.7f, 0.71f), Utils.createList( - // EnumChatFormatting.GOLD + "Itemlist", - // EnumChatFormatting.GRAY + "Hover over an item in the list to display it's lore", - // EnumChatFormatting.GRAY + "Left clicking some items will display the recipe for that item", - // EnumChatFormatting.GRAY + "Right clicking some items will display a wiki page for that item", - // EnumChatFormatting.GRAY + "'F' will favourite an item, putting it to the top of the itemlist" - // )); - // texts[6].put(new Vector2f(0.17f, 0.21f), Utils.createList( - // EnumChatFormatting.GOLD + "Collection Log", - // EnumChatFormatting.GRAY + - // "This is the collection log. It can be accessed using the /neucl command, or via the QuickCommand", - // EnumChatFormatting.GRAY + - // "The collection log keeps track of all items that enter your inventory while you are playing skyblock", - // EnumChatFormatting.GRAY + "If you are a completionist, this feature is for you" - // )); - // texts[7].put(new Vector2f(0.05f, 0.13f), Utils.createList( - // EnumChatFormatting.GOLD + "Collection Log", - // EnumChatFormatting.GRAY + "Clicking on 'Filter' will change the items that", - // EnumChatFormatting.GRAY + "appear in the list" - // )); - // texts[8].put(new Vector2f(0.35f, 0.74f), Utils.createList( - // EnumChatFormatting.GOLD + "NeuAH", - // EnumChatFormatting.GRAY + "This is the NEU Auction House (NeuAH)", - // EnumChatFormatting.GRAY + - // "This AH can be accessed from anywhere using the /neuah command, or via the QuickCommand", - // EnumChatFormatting.GRAY + - // "The items here refresh automatically, so there is no need to close the GUI to see the latest auctions", - // EnumChatFormatting.GRAY + "Sometimes, you might have to wait until the list is populated with items from the API" - // )); - // texts[9].put(new Vector2f(0.41f, 0.40f), Utils.createList( - // EnumChatFormatting.GOLD + "NeuAH", - // EnumChatFormatting.GRAY + "These tabs control the items that appear in NeuAH", - // EnumChatFormatting.GRAY + - // "You can find the main categories on the top of the GUI and subcategories appear on the side of the GUI once a main category is selected" - // )); - // texts[10].put(new Vector2f(0.57f, 0.38f), Utils.createList( - // EnumChatFormatting.GOLD + "NeuAH", - // EnumChatFormatting.GRAY + "Search for items using the search bar at the top", - // EnumChatFormatting.GRAY + "Boolean operators such as &, | or ! work here." - // )); - // texts[10].put(new Vector2f(0.40f, 0.72f), Utils.createList( - // EnumChatFormatting.GOLD + "NeuAH", - // EnumChatFormatting.GRAY + "This toolbar contains many useful features", - // EnumChatFormatting.GRAY + "which control the sorting and ordering of", - // EnumChatFormatting.GRAY + "the auction house, similar to the normal AH" - // )); - // texts[11].put(new Vector2f(0.55f, 0.72f), Utils.createList( - // EnumChatFormatting.GOLD + "NeuAH", - // EnumChatFormatting.GRAY + "Clicking on an item will bring up the auction view", - // EnumChatFormatting.GRAY + "Here you can viewer the buyer/seller and place bids or make purchases", - // EnumChatFormatting.GRAY + "Trying to purchase an item will result in a confirmation GUI similar to the normal AH" - // )); - // texts[12].put(new Vector2f(0.28f, 0.82f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + "Access the profile viewer using /neuprofile (ign) or /pv (ign)", - // EnumChatFormatting.GRAY + "This is the main page of the profile viewer", - // EnumChatFormatting.GRAY + "This page contains basic information like stats and skill levels" - // )); - // texts[12].put(new Vector2f(0.72f, 0.55f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + - // "Click the button on the left to switch profiles and use the bar on the right to switch players" - // )); - // texts[13].put(new Vector2f(0.28f, 0.82f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + "This is the extra info page of the profile viewer", - // EnumChatFormatting.GRAY + - // "This page contains all the small bits of information about a player that don't fit anywhere else" - // )); - // texts[14].put(new Vector2f(0.28f, 0.82f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + "This is the inventories page of the profile viewer", - // EnumChatFormatting.GRAY + - // "Click on the inventory icons in the top-left or use your keyboard to switch the inventory type", - // EnumChatFormatting.GRAY + "The bar on the bottom-left searches the current inventory for matching items" - // )); - // texts[15].put(new Vector2f(0.28f, 0.82f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + "This is the collections page of the profile viewer", - // EnumChatFormatting.GRAY + "Click on the icons on the left or use the keyboard shortcut to switch collection type" - // )); - // texts[16].put(new Vector2f(0.28f, 0.82f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + "This is the pets page of the profile viewer", - // EnumChatFormatting.GRAY + "Click to select the pet on the left", - // EnumChatFormatting.GRAY + "The selected pet's stats will display on the right" - // )); - // texts[17].put(new Vector2f(0.27f, 0.40f), Utils.createList( - // EnumChatFormatting.GOLD + "Overlay", - // EnumChatFormatting.GRAY + "Rearrange certain GUI elements of the main overlay using /neuoverlay", - // EnumChatFormatting.GRAY + - // "If you accidentally move them off screen, use the button in the top left to reset the GUI" - // )); - //} - // - //static { - // buttons = new ArrayList<JsonObject>() {{ - // add(createNewButton(0.27f, 0.40f, new int[]{1, 2}, "TESTSHIT", "neu")); - // }}; - //} -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/TutorialBase.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/TutorialBase.java deleted file mode 100644 index 27172ed8..00000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/TutorialBase.java +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (C) 2022 NotEnoughUpdates contributors - * - * This file is part of NotEnoughUpdates. - * - * NotEnoughUpdates is free software: you can redistribute it - * and/or modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * NotEnoughUpdates is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. - */ - -package io.github.moulberry.notenoughupdates.miscgui.tutorials; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import io.github.moulberry.notenoughupdates.NotEnoughUpdates; -import io.github.moulberry.notenoughupdates.util.Utils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.client.ClientCommandHandler; -import org.lwjgl.input.Keyboard; -import org.lwjgl.opengl.GL11; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import static io.github.moulberry.notenoughupdates.miscgui.GuiEnchantColour.custom_ench_colour; - -public class TutorialBase extends GuiScreen { - private int guiLeft = 0; - private int guiTop = 0; - private int sizeX = 0; - private int sizeY = 0; - - protected static String title; - - private int page = 0; - private final ResourceLocation screenshotBorder = new ResourceLocation("notenoughupdates:ss_border.jpg"); - - protected ResourceLocation[] screenshots = null; - - int scaleFactor = 0; - - @Override - public void setWorldAndResolution(Minecraft mc, int width, int height) { - super.setWorldAndResolution(mc, width, height); - } - - @Override - protected void keyTyped(char typedChar, int keyCode) throws IOException { - super.keyTyped(typedChar, keyCode); - if (keyCode == Keyboard.KEY_LEFT) { - page--; - } else if (keyCode == Keyboard.KEY_RIGHT) { - page++; - } - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - super.drawScreen(mouseX, mouseY, partialTicks); - - drawDefaultBackground(); - - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - scaleFactor = scaledResolution.getScaleFactor(); - - sizeX = width / 2 + 40 / scaleFactor; - sizeY = height / 2 + 40 / scaleFactor; - guiLeft = width / 4 - 20 / scaleFactor; - guiTop = height / 4 - 20 / scaleFactor; - - Minecraft.getMinecraft().getTextureManager().bindTexture(screenshotBorder); - Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY); - - page = Math.max(0, Math.min(17, page)); - - Minecraft.getMinecraft().getTextureManager().bindTexture(screenshots[page]); - Utils.drawTexturedRect( - guiLeft + 20f / scaleFactor, - guiTop + 20f / scaleFactor, - sizeX - 40f / scaleFactor, - sizeY - 40f / scaleFactor - ); - - Utils.drawStringCentered( - EnumChatFormatting.GOLD + title + " - Page " + (page + 1) + "/" + (texts.size()) + " - Use arrow keys", - Minecraft.getMinecraft().fontRendererObj, - width / 2, - guiTop + 8, - true, - 0 - ); - if (scaleFactor != 2) - Utils.drawStringCentered( - EnumChatFormatting.GOLD + "Use GUI Scale normal for better reading experience", - Minecraft.getMinecraft().fontRendererObj, - width / 2, - guiTop + 18, - true, - 0 - ); - JsonArray pageTexts = texts.get(page); - for (int i = 0; i < pageTexts.size(); i++) { - JsonObject textElement = pageTexts.get(i).getAsJsonObject(); - float oldX = textElement.get("x").getAsFloat(); - float oldY = textElement.get("y").getAsFloat(); - - // List<String> text = entry.getValue(); - JsonArray textArray = textElement.getAsJsonArray("lines"); - List<String> text = new ArrayList<>(); - for (int j = 0; j < textArray.size(); j++) { - text.add(textArray.get(j).getAsString()); - } - - float x = guiLeft + 20f / scaleFactor + (sizeX - 40f / scaleFactor) * oldX; - float y = guiTop + 20f / scaleFactor + (sizeY - 40f / scaleFactor) * oldY; - - Utils.drawHoveringText( - text, - (int) x, - (int) y + 12, - 100000, - 100000, - 200, - Minecraft.getMinecraft().fontRendererObj - ); - } - - drawButtons(); - } - - protected void drawButtons() { - - for (JsonObject button : buttons) { - JsonArray pages = button.get("pages").getAsJsonArray(); - boolean drawButton = false; - for (int i1 = 0; i1 < pages.size(); i1++) { - if (pages.get(i1).getAsInt() == page) { - drawButton = true; - break; - } - } - if (!drawButton) { - continue; - } - float x = button.get("x").getAsFloat(); - float y = button.get("y").getAsFloat(); - String text = button.get("text").getAsString(); - // String command = button.get("command").getAsString(); - Minecraft.getMinecraft().getTextureManager().bindTexture(custom_ench_colour); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect( - guiLeft + 20f / scaleFactor + (sizeX - 40f / scaleFactor) * x, - guiTop + 20f / scaleFactor + (sizeY - 40f / scaleFactor) * y, - 88, - 20, - 64 / 217f, - 152 / 217f, - 48 / 78f, - 68 / 78f, - GL11.GL_NEAREST - ); - Utils.drawStringCenteredScaledMaxWidth( - text, - fontRendererObj, - (guiLeft + 20f / scaleFactor + (sizeX - 40f / scaleFactor) * x) + 44, - (guiTop + 20f / scaleFactor + (sizeY - 40f / scaleFactor) * y) + 10, - false, - 86, - 4210752 - ); - - } - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - super.mouseClicked(mouseX, mouseY, mouseButton); - int width = 88; - int height = 20; - - for (JsonObject button : buttons) { - JsonArray pages = button.get("pages").getAsJsonArray(); - boolean drawButton = false; - for (int i1 = 0; i1 < pages.size(); i1++) { - if (pages.get(i1).getAsInt() == page) { - drawButton = true; - break; - } - } - if (!drawButton) { - continue; - } - float x = button.get("x").getAsFloat(); - float y = button.get("y").getAsFloat(); - // String text = button.get("text").getAsString(); - float realX = guiLeft + 20f / scaleFactor + (sizeX - 40f / scaleFactor) * x; - float realY = guiTop + 20f / scaleFactor + (sizeY - 40f / scaleFactor) * y; - if (mouseX > realX && mouseX < realX + width && mouseY > realY && mouseY < realY + height) { - String command = button.get("command").getAsString(); - NotEnoughUpdates.INSTANCE.openGui = null; - ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/" + command); - return; - } - } - } - - protected static List<JsonArray> texts = new ArrayList<>(); - - protected static List<JsonObject> buttons = new ArrayList<>(); - - protected static JsonObject createNewButton(float x, float y, int[] pages, String text, String command) { - JsonObject button = new JsonObject(); - JsonArray pagesArray = new JsonArray(); - for (int j : pages) { - pagesArray.add(new JsonPrimitive(j)); - } - button.add("pages", pagesArray); - button.add("x", new JsonPrimitive(x)); - button.add("y", new JsonPrimitive(y)); - button.add("text", new JsonPrimitive(text)); - button.add("command", new JsonPrimitive(command)); - return button; - } - - protected static JsonArray createNewTexts(JsonObject... texts) { - JsonArray textArray = new JsonArray(); - for (JsonObject text : texts) { - textArray.add(text); - } - return textArray; - } - - protected static JsonObject createNewText(float x, float y, String... texts) { - JsonObject tooltip = new JsonObject(); - tooltip.add("x", new JsonPrimitive(x)); - tooltip.add("y", new JsonPrimitive(y)); - JsonArray lines = new JsonArray(); - for (String text : texts) { - lines.add(new JsonPrimitive(text)); - } - tooltip.add("lines", lines); - return tooltip; - } - - protected static JsonObject createNewText(float x, float y, List<String> texts) { - JsonObject tooltip = new JsonObject(); - tooltip.add("x", new JsonPrimitive(x)); - tooltip.add("y", new JsonPrimitive(y)); - JsonArray lines = new JsonArray(); - for (String text : texts) { - lines.add(new JsonPrimitive(text)); - } - tooltip.add("lines", lines); - return tooltip; - } - - //static { - // for (int i = 0; i < 18; i++) { - // texts[i] = new HashMap<>(); - // } - // texts[0].put(new Vector2f(0.73f, 0.60f), Utils.createList( - // EnumChatFormatting.GOLD + "Itemlist", - // EnumChatFormatting.GRAY + "Here you will find a list of (most) skyblock items", - // EnumChatFormatting.GRAY + "The itemlist can be accessed by opening your inventory or most menus while on skyblock" - // )); - // texts[1].put(new Vector2f(0.73f, 0.16f), Utils.createList( - // EnumChatFormatting.GOLD + "Itemlist", - // EnumChatFormatting.GRAY + "These are the page controls for the itemlist", - // EnumChatFormatting.GRAY + "Clicking these controls will bring you to other pages of the itemlist" - // )); - // texts[2].put(new Vector2f(0.73f, 1.05f), Utils.createList( - // EnumChatFormatting.GOLD + "Itemlist", - // EnumChatFormatting.GRAY + "These are the sorting controls for the itemlist", - // EnumChatFormatting.GRAY + "The buttons on the left control the ordering of the items", - // EnumChatFormatting.GRAY + "The buttons on the right can be used to filter a certain type of item" - // )); - // texts[3].put(new Vector2f(0.39f, 1.04f), Utils.createList( - // EnumChatFormatting.GOLD + "Itemlist", - // EnumChatFormatting.GRAY + "This is the search bar for the itemlist", - // EnumChatFormatting.GRAY + "Double-click the bar to enable inventory search mode", - // EnumChatFormatting.GRAY + "The button on the left opens up the mod settings", - // EnumChatFormatting.GRAY + "The button on the right displays this tutorial" - // )); - // texts[4].put(new Vector2f(0.39f, 0.99f), Utils.createList( - // EnumChatFormatting.GOLD + "QuickCommands", - // EnumChatFormatting.GRAY + "These are the QuickCommands", - // EnumChatFormatting.GRAY + "They let you warp around or access certain menus more easily" - // )); - // texts[5].put(new Vector2f(0.7f, 0.71f), Utils.createList( - // EnumChatFormatting.GOLD + "Itemlist", - // EnumChatFormatting.GRAY + "Hover over an item in the list to display it's lore", - // EnumChatFormatting.GRAY + "Left clicking some items will display the recipe for that item", - // EnumChatFormatting.GRAY + "Right clicking some items will display a wiki page for that item", - // EnumChatFormatting.GRAY + "'F' will favourite an item, putting it to the top of the itemlist" - // )); - // texts[6].put(new Vector2f(0.17f, 0.21f), Utils.createList( - // EnumChatFormatting.GOLD + "Collection Log", - // EnumChatFormatting.GRAY + - // "This is the collection log. It can be accessed using the /neucl command, or via the QuickCommand", - // EnumChatFormatting.GRAY + - // "The collection log keeps track of all items that enter your inventory while you are playing skyblock", - // EnumChatFormatting.GRAY + "If you are a completionist, this feature is for you" - // )); - // texts[7].put(new Vector2f(0.05f, 0.13f), Utils.createList( - // EnumChatFormatting.GOLD + "Collection Log", - // EnumChatFormatting.GRAY + "Clicking on 'Filter' will change the items that", - // EnumChatFormatting.GRAY + "appear in the list" - // )); - // texts[8].put(new Vector2f(0.35f, 0.74f), Utils.createList( - // EnumChatFormatting.GOLD + "NeuAH", - // EnumChatFormatting.GRAY + "This is the NEU Auction House (NeuAH)", - // EnumChatFormatting.GRAY + - // "This AH can be accessed from anywhere using the /neuah command, or via the QuickCommand", - // EnumChatFormatting.GRAY + - // "The items here refresh automatically, so there is no need to close the GUI to see the latest auctions", - // EnumChatFormatting.GRAY + "Sometimes, you might have to wait until the list is populated with items from the API" - // )); - // texts[9].put(new Vector2f(0.41f, 0.40f), Utils.createList( - // EnumChatFormatting.GOLD + "NeuAH", - // EnumChatFormatting.GRAY + "These tabs control the items that appear in NeuAH", - // EnumChatFormatting.GRAY + - // "You can find the main categories on the top of the GUI and subcategories appear on the side of the GUI once a main category is selected" - // )); - // texts[10].put(new Vector2f(0.57f, 0.38f), Utils.createList( - // EnumChatFormatting.GOLD + "NeuAH", - // EnumChatFormatting.GRAY + "Search for items using the search bar at the top", - // EnumChatFormatting.GRAY + "Boolean operators such as &, | or ! work here." - // )); - // texts[10].put(new Vector2f(0.40f, 0.72f), Utils.createList( - // EnumChatFormatting.GOLD + "NeuAH", - // EnumChatFormatting.GRAY + "This toolbar contains many useful features", - // EnumChatFormatting.GRAY + "which control the sorting and ordering of", - // EnumChatFormatting.GRAY + "the auction house, similar to the normal AH" - // )); - // texts[11].put(new Vector2f(0.55f, 0.72f), Utils.createList( - // EnumChatFormatting.GOLD + "NeuAH", - // EnumChatFormatting.GRAY + "Clicking on an item will bring up the auction view", - // EnumChatFormatting.GRAY + "Here you can viewer the buyer/seller and place bids or make purchases", - // EnumChatFormatting.GRAY + "Trying to purchase an item will result in a confirmation GUI similar to the normal AH" - // )); - // texts[12].put(new Vector2f(0.28f, 0.82f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + "Access the profile viewer using /neuprofile (ign) or /pv (ign)", - // EnumChatFormatting.GRAY + "This is the main page of the profile viewer", - // EnumChatFormatting.GRAY + "This page contains basic information like stats and skill levels" - // )); - // texts[12].put(new Vector2f(0.72f, 0.55f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + - // "Click the button on the left to switch profiles and use the bar on the right to switch players" - // )); - // texts[13].put(new Vector2f(0.28f, 0.82f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + "This is the extra info page of the profile viewer", - // EnumChatFormatting.GRAY + - // "This page contains all the small bits of information about a player that don't fit anywhere else" - // )); - // texts[14].put(new Vector2f(0.28f, 0.82f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + "This is the inventories page of the profile viewer", - // EnumChatFormatting.GRAY + - // "Click on the inventory icons in the top-left or use your keyboard to switch the inventory type", - // EnumChatFormatting.GRAY + "The bar on the bottom-left searches the current inventory for matching items" - // )); - // texts[15].put(new Vector2f(0.28f, 0.82f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + "This is the collections page of the profile viewer", - // EnumChatFormatting.GRAY + "Click on the icons on the left or use the keyboard shortcut to switch collection type" - // )); - // texts[16].put(new Vector2f(0.28f, 0.82f), Utils.createList( - // EnumChatFormatting.GOLD + "Profile Viewer", - // EnumChatFormatting.GRAY + "This is the pets page of the profile viewer", - // EnumChatFormatting.GRAY + "Click to select the pet on the left", - // EnumChatFormatting.GRAY + "The selected pet's stats will display on the right" - // )); - // texts[17].put(new Vector2f(0.27f, 0.40f), Utils.createList( - // EnumChatFormatting.GOLD + "Overlay", - // EnumChatFormatting.GRAY + "Rearrange certain GUI elements of the main overlay using /neuoverlay", - // EnumChatFormatting.GRAY + - // "If you accidentally move them off screen, use the button in the top left to reset the GUI" - // )); - //} -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayerSP.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayerSP.java index 765ed372..581a2c17 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayerSP.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayerSP.java @@ -21,10 +21,10 @@ package io.github.moulberry.notenoughupdates.mixins; import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking; import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.entity.item.EntityItem; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -42,8 +42,7 @@ public class MixinEntityPlayerSP { int slot = Minecraft.getMinecraft().thePlayer.inventory.currentItem; if (SlotLocking.getInstance().isSlotIndexLocked(slot) || SlotLocking.getInstance().isSwapedSlotLocked()) { ci.cancel(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "NotEnoughUpdates has prevented you from dropping that locked item!")); + Utils.addChatMessage(EnumChatFormatting.RED + "NotEnoughUpdates has prevented you from dropping that locked item!"); } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java index 81918939..cb4cfa6c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java @@ -27,6 +27,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.AbiphoneWarning; import io.github.moulberry.notenoughupdates.miscfeatures.AuctionBINWarning; import io.github.moulberry.notenoughupdates.miscfeatures.AuctionSortModeWarning; import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers; +import io.github.moulberry.notenoughupdates.miscfeatures.DungeonNpcProfitOverlay; import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking; import io.github.moulberry.notenoughupdates.miscgui.GuiCustomEnchant; @@ -72,6 +73,7 @@ public abstract class MixinGuiContainer extends GuiScreen { @Inject(method = "drawSlot", at = @At("RETURN")) public void drawSlotRet(Slot slotIn, CallbackInfo ci) { SlotLocking.getInstance().drawSlot(slotIn); + DungeonNpcProfitOverlay.onDrawSlot(slotIn); } @Inject(method = "drawSlot", at = @At("HEAD"), cancellable = true) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiTextField.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiTextField.java index 55a5a098..039256e5 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiTextField.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiTextField.java @@ -80,7 +80,7 @@ public abstract class MixinGuiTextField { } } - @Inject(method = "deleteFromCursor", at = @At(value = "INVOKE", target = "Lcom/google/common/base/Predicate;apply(Ljava/lang/Object;)Z"), locals = LocalCapture.PRINT) + @Inject(method = "deleteFromCursor", at = @At(value = "INVOKE", target = "Lcom/google/common/base/Predicate;apply(Ljava/lang/Object;)Z", remap = false), locals = LocalCapture.CAPTURE_FAILSOFT) public void deleteFromCursor_stringStack(int i, CallbackInfo ci, boolean bl, int j, int k, String string) { if (NotEnoughUpdates.INSTANCE.config.misc.textFieldTweaksEnabled) { addToStack(string); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java index 8242c095..75ae33a1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java @@ -51,6 +51,7 @@ import io.github.moulberry.notenoughupdates.options.seperateSections.ItemOverlay import io.github.moulberry.notenoughupdates.options.seperateSections.Itemlist; import io.github.moulberry.notenoughupdates.options.seperateSections.LocationEdit; import io.github.moulberry.notenoughupdates.options.seperateSections.Mining; +import io.github.moulberry.notenoughupdates.options.seperateSections.MinionHelper; import io.github.moulberry.notenoughupdates.options.seperateSections.Misc; import io.github.moulberry.notenoughupdates.options.seperateSections.MiscOverlays; import io.github.moulberry.notenoughupdates.options.seperateSections.NeuAuctionHouse; @@ -414,6 +415,13 @@ public class NEUConfig extends Config { @Expose @Category( + name = "Minion Helper", + desc = "Minion Helper" + ) + public MinionHelper minionHelper = new MinionHelper(); + + @Expose + @Category( name = "Apis", desc = "Api Data" ) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java index cf5635ec..9179c6ea 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java @@ -130,7 +130,7 @@ public class Dungeons { ) @ConfigEditorBoolean @ConfigAccordionId(id = 1) - public boolean shouldWarningDerpy = true; + public boolean shouldWarningDerpy = true; @ConfigOption( name = "Dungeon Win Overlay", @@ -168,6 +168,7 @@ public class Dungeons { @ConfigEditorAccordion(id = 2) public boolean dungeonBlocksAccordion = false; + @ConfigOption( name = "\u00A7cWarning", desc = "You need Fast Render and Antialiasing off for these settings to work\n" + @@ -281,4 +282,38 @@ public class Dungeons { @ConfigAccordionId(id = 2) public String dungBatColour = "0:255:12:255:0"; + @ConfigOption( + name = "Croesus Overlay", + desc = "" + ) + @ConfigEditorAccordion(id = 4) + public boolean croesusAccordion = false; + + @Expose + @ConfigOption( + name = "Enable Croesus Overlay", + desc = "Shows a profit overlay next to your inventory when viewing chest previews at the Croesus NPC" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 4) + public boolean croesusProfitOverlay = true; + + @Expose + @ConfigOption( + name = "Sort by profit", + desc = "Lists the chest by profit (descending)" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 4) + public boolean croesusSortByProfit = true; + + @Expose + @ConfigOption( + name = "Highlight highest profit", + desc = "Highlight the chest which has the most profit" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 4) + public boolean croesusHighlightHighestProfit = true; + } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/MinionHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/MinionHelper.java new file mode 100644 index 00000000..089b2ae7 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/MinionHelper.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.options.seperateSections; + +import com.google.gson.annotations.Expose; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption; + +//TODO jani rename message format +public class MinionHelper { + @Expose + @ConfigOption( + name = "Enable gui", + desc = + "Shows a list in the crafted minions inventory of every available to craft or all missing minion, in multiple pages " + + "that you need to get the next minion slot, sorted by upgrade cost" + ) + + @ConfigEditorBoolean + public boolean gui = true; + @Expose + @ConfigOption( + name = "Enable tooltip", + desc = "Shows the price per minion at the crafted minions " + ) + @ConfigEditorBoolean + public boolean tooltip = true; +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java index ededb5da..78bb0f95 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java @@ -83,6 +83,15 @@ public class Misc { @Expose @ConfigOption( + name = "Show Waypoint Distance", + desc = "Show the distance to each fairy soul waypoint" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 0) + public boolean fairySoulWaypointDistance = false; + + @Expose + @ConfigOption( name = "Mark All As Found", desc = "Mark all fairy souls in current location as found" ) @@ -141,14 +150,23 @@ public class Misc { @ConfigEditorButton(runnableId = 13, buttonText = "Open") public boolean openPV = true; - @Expose @ConfigOption( + name = "Custom Enchant Colours", + desc = "" + ) + @ConfigEditorAccordion( + id = 1 + ) + public boolean neuEnchantsAccordion = true; + @Expose + @ConfigOption( name = "Edit Enchant Colours", desc = "Change the colours of certain SkyBlock enchants (/neuec)", searchTags = "color" ) @ConfigEditorButton(runnableId = 8, buttonText = "Open") + @ConfigAccordionId(id = 1) public boolean editEnchantColoursButton = true; @Expose @@ -162,10 +180,20 @@ public class Misc { maxValue = 500, minStep = 10 ) + @ConfigAccordionId(id = 1) public int chromaSpeed = 100; @Expose @ConfigOption( + name = "Cache Tooltip Enchants", + desc = "Caches item enchants in tooltip to only use the neuec config once per item lookup.\nNOTE: It doesn't work on items without a uuid" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean cacheItemEnchant = true; + + @Expose + @ConfigOption( name = "Disable Skull retexturing", desc = "Disables the skull retexturing." ) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java index 85ad2093..3541860d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java @@ -20,7 +20,10 @@ package io.github.moulberry.notenoughupdates.options.seperateSections; import com.google.gson.annotations.Expose; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorColour; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption; @@ -86,4 +89,43 @@ public class Notifications { minStep = 25 ) public int boosterCookieWarningMins = 1440; + + @Expose + @ConfigOption( + name = "Ender Nodes", + desc = "" + ) + @ConfigEditorAccordion(id = 1) + public boolean enderNodeAccordion = false; + + @Expose + @ConfigOption( + name = "Nested Endermite Alert", + desc = "It will alert the user if a nested endermite gets spawned" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean endermiteAlert = true; + + @Expose + @ConfigOption( + name = "Nested Endermite Alert Color", + desc = "The color the alert will be shown" + ) + @ConfigEditorColour + @ConfigAccordionId(id = 1) + public String endermiteAlertColor = "0:255:194:0:174"; + + @Expose + @ConfigOption( + name = "Nested Endermite Alert Display Time", + desc = "How long the display would stay for in ticks" + ) + @ConfigEditorSlider( + minValue = 1, + maxValue = 200, + minStep = 20 + ) + @ConfigAccordionId(id = 1) + public int endermiteAlertTicks = 20; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java index 60d9b607..7d0b9a0a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java @@ -19,8 +19,6 @@ package io.github.moulberry.notenoughupdates.overlays; -import com.google.common.collect.ComparisonChain; -import com.google.common.collect.Ordering; import com.google.gson.annotations.Expose; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.config.Position; @@ -29,16 +27,15 @@ import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils; import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.TabListUtils; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiChest; -import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.init.Items; import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; -import net.minecraft.scoreboard.ScorePlayerTeam; import net.minecraft.util.EnumChatFormatting; import net.minecraft.world.WorldSettings; import net.minecraftforge.fml.relauncher.Side; @@ -47,7 +44,6 @@ import org.lwjgl.input.Keyboard; import org.lwjgl.util.vector.Vector2f; import java.util.ArrayList; -import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -263,11 +259,8 @@ public class MiningOverlay extends TextTabOverlay { int forgeInt = 0; boolean commissions = false; boolean forges = false; - List<NetworkPlayerInfo> players = - playerOrdering.sortedCopy(Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()); - for (NetworkPlayerInfo info : players) { - String name = Minecraft.getMinecraft().ingameGUI.getTabList().getPlayerName(info); + for (String name : TabListUtils.getTabList()) { if (name.contains("Mithril Powder:")) { mithrilPowder = DARK_AQUA + Utils.trimWhitespaceAndFormatCodes(name).replaceAll("\u00a7[f|F|r]", ""); continue; @@ -584,27 +577,6 @@ public class MiningOverlay extends TextTabOverlay { } } - private static final Ordering<NetworkPlayerInfo> playerOrdering = Ordering.from(new PlayerComparator()); - - @SideOnly(Side.CLIENT) - static class PlayerComparator implements Comparator<NetworkPlayerInfo> { - private PlayerComparator() {} - - public int compare(NetworkPlayerInfo o1, NetworkPlayerInfo o2) { - ScorePlayerTeam team1 = o1.getPlayerTeam(); - ScorePlayerTeam team2 = o2.getPlayerTeam(); - return ComparisonChain.start().compareTrueFirst( - o1.getGameType() != WorldSettings.GameType.SPECTATOR, - o2.getGameType() != WorldSettings.GameType.SPECTATOR - ) - .compare( - team1 != null ? team1.getRegisteredName() : "", - team2 != null ? team2.getRegisteredName() : "" - ) - .compare(o1.getGameProfile().getName(), o2.getGameProfile().getName()).result(); - } - } - @Override protected Vector2f getSize(List<String> strings) { if (NotEnoughUpdates.INSTANCE.config.mining.dwarvenOverlayIcons) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java index 9ef9e474..e5c17a1a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java @@ -284,7 +284,8 @@ public class BasicPage extends GuiProfileViewerPage { .get("avg_buy") .getAsDouble() ); - String networthIRLMoney = GuiProfileViewer.numberFormat.format(Math.round(((networthInCookies * 325) / 675) * 4.99)); + String networthIRLMoney = GuiProfileViewer.numberFormat.format(Math.round( + ((networthInCookies * 325) / 675) * 4.99)); if ( mouseX > guiLeft + 8 && mouseX < guiLeft + 8 + fr.getStringWidth("Net Worth: " + GuiProfileViewer.numberFormat.format(networth)) @@ -302,6 +303,17 @@ public class BasicPage extends GuiProfileViewerPage { ); getInstance().tooltipToDisplay.add(""); + if (NotEnoughUpdates.INSTANCE.config.profileViewer.useSoopyNetworth + && profile.getSoopyNetworthLeaderboardPosition() >= 0 + && profile.isProfileMaxSoopyNetworth(profileId)) { + + String lbPosStr = + EnumChatFormatting.DARK_GREEN + "#" + EnumChatFormatting.GOLD + GuiProfileViewer.numberFormat.format( + profile.getSoopyNetworthLeaderboardPosition()); + getInstance().tooltipToDisplay.add(lbPosStr + EnumChatFormatting.GREEN + " on the networth leaderboard!"); + getInstance().tooltipToDisplay.add(""); + } + if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { getInstance().tooltipToDisplay.addAll(nwCategoryHover); getInstance().tooltipToDisplay.add(EnumChatFormatting.RED + "This is calculated using the current"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java index 6d59db27..cbebb6f4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java @@ -223,6 +223,7 @@ public class DungeonPage extends GuiProfileViewerPage { getInstance().tooltipToDisplay = Lists.newArrayList( + EnumChatFormatting.YELLOW + "Remaining XP: " + EnumChatFormatting.GRAY + String.format("%,d", floorLevelToXP), String.format("# F5 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpF5), runsF5), String.format("# F6 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpF6), runsF6), String.format("# F7 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpF7), runsF7), @@ -370,6 +371,7 @@ public class DungeonPage extends GuiProfileViewerPage { getInstance().tooltipToDisplay = Lists.newArrayList( + EnumChatFormatting.YELLOW + "Remaining XP: " + EnumChatFormatting.GRAY + String.format("%,d", floorLevelToXP), String.format("# M3 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM3), runsM3), String.format("# M4 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM4), runsM4), String.format("# M5 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM5), runsM5), @@ -668,6 +670,8 @@ public class DungeonPage extends GuiProfileViewerPage { activeClass = activeClassElement.getAsString(); } + ProfileViewer.Level classAverage = new ProfileViewer.Level(); + for (int i = 0; i < dungSkillsName.length; i++) { String skillName = dungSkillsName[i]; @@ -683,9 +687,19 @@ public class DungeonPage extends GuiProfileViewerPage { 50, false ); + + if (levelObj.level == 50) { + levelObj.level = 50 + (cataXp - 569809640) / 200000000; + } + levelObjClasses.put(skillName, levelObj); } + classAverage.level = (float) (levelObjClasses.values().stream().mapToDouble(l -> l.level).sum() / 5); + if (classAverage.level >= 50) { + classAverage.maxed = true; + } + String colour = EnumChatFormatting.WHITE.toString(); if (skillName.toLowerCase().equals(activeClass)) { colour = EnumChatFormatting.GREEN.toString(); @@ -694,8 +708,17 @@ public class DungeonPage extends GuiProfileViewerPage { ProfileViewer.Level levelObj = levelObjClasses.get(skillName); getInstance() - .renderXpBar(colour + skillName, dungSkillsStack[i], x, y + 20 + 29 * i, sectionWidth, levelObj, mouseX, mouseY); + .renderXpBar(colour + skillName, dungSkillsStack[i], x, y + 20 + 24 * i, sectionWidth, levelObj, mouseX, mouseY); } + + getInstance().renderXpBar( + EnumChatFormatting.WHITE + "Class Average", + new ItemStack(Items.nether_star), + x, + y + 20 + 24 * 5, + sectionWidth, + classAverage, + mouseX, mouseY); } drawSideButtons(); @@ -707,7 +730,7 @@ public class DungeonPage extends GuiProfileViewerPage { int guiLeft = GuiProfileViewer.getGuiLeft(); int guiTop = GuiProfileViewer.getGuiTop(); - if (mouseX >= guiLeft + 50 && mouseX <= guiLeft + 70 && mouseY >= guiTop + 54 && mouseY <= guiTop + 64) { + if (mouseX >= guiLeft + 45 && mouseX <= guiLeft + 65 && mouseY >= guiTop + 54 && mouseY <= guiTop + 64) { dungeonLevelTextField.mouseClicked(mouseX, mouseY, mouseButton); } else { dungeonLevelTextField.otherComponentClick(); @@ -829,7 +852,7 @@ public class DungeonPage extends GuiProfileViewerPage { if (level < Math.floor(levelObjCata.level)) { continue; } - remaining += levelingArray.get(level).getAsFloat(); + remaining += levelingArray.get(level).getAsFloat(); } if (remaining < 0) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java index a0af254c..1936e9c3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java @@ -58,7 +58,6 @@ public class ExtraPage extends GuiProfileViewerPage { private int killScroll = 0; private int mouseDWheel = 0; - public ExtraPage(GuiProfileViewer instance) { super(instance); getInstance().killDeathSearchTextField.setSize(80, 12); @@ -109,7 +108,8 @@ public class ExtraPage extends GuiProfileViewerPage { float xStart, float yStartTop, float xOffset, - float yOffset) { + float yOffset + ) { int guiLeft = GuiProfileViewer.getGuiLeft(); int guiTop = GuiProfileViewer.getGuiTop(); yStartTop = yStartTop + 78; @@ -131,17 +131,16 @@ public class ExtraPage extends GuiProfileViewerPage { return; } String displayName = itemInformation.get(essenceName).getAsJsonObject().get("displayname").getAsString(); - if (profileInfo.has(essenceName.toLowerCase())) { - int essenceNumber = profileInfo.get(essenceName.toLowerCase()).getAsInt(); + int essenceNumber = + (profileInfo.has(essenceName.toLowerCase()) ? profileInfo.get(essenceName.toLowerCase()).getAsInt() : 0); - Utils.renderAlignedString( - EnumChatFormatting.GOLD + displayName, - EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(essenceNumber, 0), - guiLeft + xStart + xOffset, - guiTop + yStartTop + yOffset * i, - 76 - ); - } + Utils.renderAlignedString( + EnumChatFormatting.GOLD + displayName, + EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(essenceNumber, 0), + guiLeft + xStart + xOffset, + guiTop + yStartTop + yOffset * i, + 76 + ); } } @@ -448,31 +447,28 @@ public class ExtraPage extends GuiProfileViewerPage { } } - getInstance().killDeathSearchTextField.render((int) (guiLeft + xStart + xOffset * 3), (int) (guiTop + yStartBottom + 77)); + getInstance().killDeathSearchTextField.render( + (int) (guiLeft + xStart + xOffset * 3), + (int) (guiTop + yStartBottom + 77) + ); float killDeathX = guiLeft + xStart + xOffset * 3; - if(mouseX >= killDeathX && mouseX <= killDeathX+76) { - if(mouseY >= guiTop + yStartTop && mouseY <= guiTop + yStartTop + 65) { - if(mouseDWheel != 0) {if(mouseDWheel > 0) {killScroll-=1;} else {killScroll+=1;}} mouseDWheel = Mouse.getDWheel(); - if(killScroll < 0) {killScroll = 0;} - } else if(mouseY >= guiTop + yStartBottom && mouseY <= guiTop + yStartBottom + 65) { - if(mouseDWheel != 0) {if(mouseDWheel > 0) {deathScroll-=1;} else {deathScroll+=1;}} mouseDWheel = Mouse.getDWheel(); - if(deathScroll < 0) {deathScroll = 0;} - } - - } int index = 0; int skipCount = 0; + int renderedKills = 0; for (int killCount : topKills.descendingKeySet()) { Set<String> kills = topKills.get(killCount); for (String killType : kills) { - boolean isSearch = getInstance().killDeathSearchTextField.getText().isEmpty() || killType.toLowerCase(Locale.ROOT).contains(getInstance().killDeathSearchTextField.getText().toLowerCase(Locale.ROOT)); - float killY = guiTop + yStartTop + yOffset * ((index-skipCount) - killScroll); - if(!isSearch) skipCount++; - if(isSearch && killY+6 < guiTop+yStartTop+65 && killY >= guiTop + yStartTop) { + boolean isSearch = + getInstance().killDeathSearchTextField.getText().isEmpty() || killType.toLowerCase(Locale.ROOT).contains( + getInstance().killDeathSearchTextField.getText().toLowerCase(Locale.ROOT)); + float killY = guiTop + yStartTop + yOffset * ((index - skipCount) - killScroll); + if (!isSearch) skipCount++; + if (isSearch && killY + 6 < guiTop + yStartTop + 65 && killY >= guiTop + yStartTop) { + renderedKills++; Utils.renderAlignedString( - EnumChatFormatting.YELLOW + killType + " Kills", + EnumChatFormatting.YELLOW + "K: " + killType, EnumChatFormatting.WHITE.toString() + killCount, killDeathX, killY, @@ -480,21 +476,25 @@ public class ExtraPage extends GuiProfileViewerPage { ); } - index++; } } + index = 0; skipCount = 0; + int renderedDeaths = 0; for (int deathCount : topDeaths.descendingKeySet()) { Set<String> deaths = topDeaths.get(deathCount); for (String deathType : deaths) { - boolean isSearch = getInstance().killDeathSearchTextField.getText().isEmpty() || deathType.toLowerCase(Locale.ROOT).contains(getInstance().killDeathSearchTextField.getText().toLowerCase(Locale.ROOT)); - float deathY = guiTop + yStartBottom + yOffset * ((index-skipCount) - deathScroll); - if(!isSearch) skipCount++; - if(isSearch && deathY+6 < guiTop+yStartBottom+65 && deathY >= guiTop + yStartBottom) { + boolean isSearch = + getInstance().killDeathSearchTextField.getText().isEmpty() || deathType.toLowerCase(Locale.ROOT).contains( + getInstance().killDeathSearchTextField.getText().toLowerCase(Locale.ROOT)); + float deathY = guiTop + yStartBottom + yOffset * ((index - skipCount) - deathScroll); + if (!isSearch) skipCount++; + if (isSearch && deathY + 6 < guiTop + yStartBottom + 65 && deathY >= guiTop + yStartBottom) { + renderedDeaths++; Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "Deaths: " + deathType, + EnumChatFormatting.YELLOW + "D: " + deathType, EnumChatFormatting.WHITE.toString() + deathCount, killDeathX, deathY, @@ -504,6 +504,38 @@ public class ExtraPage extends GuiProfileViewerPage { index++; } } + + mouseDWheel = Mouse.getDWheel(); + if (mouseX >= killDeathX && mouseX <= killDeathX + 76) { + if (mouseY >= guiTop + yStartTop && mouseY <= guiTop + yStartTop + 65) { + if (mouseDWheel > 0) { + killScroll -= 1; + } else if (mouseDWheel < 0) { + killScroll += 1; + } + + if (killScroll < 0) { + killScroll = 0; + } + } else if (mouseY >= guiTop + yStartBottom && mouseY <= guiTop + yStartBottom + 65) { + if (mouseDWheel > 0) { + deathScroll -= 1; + } else if (mouseDWheel < 0) { + deathScroll += 1; + } + if (deathScroll < 0) { + deathScroll = 0; + } + + } + } + + if (killScroll > renderedDeaths) { + killScroll = renderedDeaths; + } + if (deathScroll > renderedKills) { + deathScroll = renderedKills; + } } private String getTimeSinceString(JsonObject profileInfo, String path) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java index f327dae5..37605595 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java @@ -1039,15 +1039,27 @@ public class GuiProfileViewer extends GuiScreen { numberFormat.format(levelObj.totalXp) + EnumChatFormatting.DARK_GRAY + " (" + DECIMAL_FORMAT.format(getPercentage(skillName.toLowerCase(), levelObj)) + "% to 50)"; } + // Adds overflow level to each level object that is maxed, avoids hotm level as there is no overflow xp for it if (levelObj.maxed) { - levelStr = EnumChatFormatting.GOLD + "MAXED!"; + levelStr = levelObj.maxLevel != 7 ? + EnumChatFormatting.GOLD + "MAXED!" + EnumChatFormatting.GRAY + " (Overflow level: " + String.format("%.2f", levelObj.level) + ")" : + EnumChatFormatting.GOLD + "MAXED!"; } else { - int maxXp = (int) levelObj.maxXpForLevel; - levelStr = - EnumChatFormatting.DARK_PURPLE + - StringUtils.shortNumberFormat(Math.round((level % 1) * maxXp)) + - "/" + - StringUtils.shortNumberFormat(maxXp); + if (skillName.contains("Class Average")) { + levelStr = "Progress: " + EnumChatFormatting.DARK_PURPLE + String.format("%.1f", (level % 1 * 100)) + "%"; + totalXpStr = "Exact Class Average: " + EnumChatFormatting.WHITE + String.format("%.2f", levelObj.level); + } else { + int maxXp = (int) levelObj.maxXpForLevel; + levelStr = + EnumChatFormatting.DARK_PURPLE + + StringUtils.shortNumberFormat(Math.round((level % 1) * maxXp)) + + "/" + + StringUtils.shortNumberFormat(maxXp) + + // Since catacombs isn't considered 'maxed' at level 50 (since the cap is '99'), we can add + // a conditional here to add the overflow level rather than above + ((skillName.contains("Catacombs") && levelObj.level >= 50) ? + EnumChatFormatting.GRAY + " (Overflow level: " + String.format("%.2f", levelObj.level) + ")" : ""); + } } if (totalXpStr != null) { tooltipToDisplay = Utils.createList(levelStr, totalXpStr); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java index 41217201..af904e1d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java @@ -21,8 +21,6 @@ package io.github.moulberry.notenoughupdates.profileviewer; import io.github.moulberry.notenoughupdates.util.TexLoc; import io.github.moulberry.notenoughupdates.util.Utils; -import java.io.IOException; -import java.util.HashMap; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; @@ -36,6 +34,9 @@ import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; import org.lwjgl.util.glu.Project; +import java.io.IOException; +import java.util.HashMap; + public class Panorama { private static final TexLoc tl = new TexLoc(97, 19, Keyboard.KEY_P); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java index b32d3648..347ee660 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java @@ -654,6 +654,7 @@ public class ProfileViewer { private final AtomicBoolean updatingSoopyNetworth = new AtomicBoolean(false); private final AtomicBoolean updatingBingoInfo = new AtomicBoolean(false); private final Pattern COLL_TIER_PATTERN = Pattern.compile("_(-?\\d+)"); + private long soopyNetworthLeaderboardPosition = -1; //-1 = default, -2 = loading, -3 = error private String latestProfile = null; private JsonArray skyblockProfiles = null; private JsonObject guildInformation = null; @@ -748,7 +749,11 @@ public class ProfileViewer { } //Sort keys based on category value - keys = categoryWorth.keySet().stream().sorted(Comparator.comparingLong(k->getCategory((String) k)).reversed()).toArray(String[]::new); + keys = categoryWorth + .keySet() + .stream() + .sorted(Comparator.comparingLong(k -> getCategory((String) k)).reversed()) + .toArray(String[]::new); } private SoopyNetworthData setLoading() { @@ -771,6 +776,32 @@ public class ProfileViewer { } /** + * -1 = default, -2 = loading, -3 = error + * >= 0 = actual position + */ + public long getSoopyNetworthLeaderboardPosition() { + if ("d0e05de76067454dbeaec6d19d886191".equals(uuid)) return 1; + return soopyNetworthLeaderboardPosition; + } + + public boolean isProfileMaxSoopyNetworth(String profileName) { + String highestProfileName = ""; + long largestProfileNetworth = 0; + + for (String pName : soopyNetworth.keySet()) { + if (soopyNetworth.get(pName) == null) continue; + + long pNet = soopyNetworth.get(pName).totalWorth; + if (pNet < largestProfileNetworth) continue; + + highestProfileName = pName; + largestProfileNetworth = pNet; + } + + return highestProfileName.equals(profileName); + } + + /** * Returns SoopyNetworthData with total = -1 if error * Returns null if still loading */ @@ -782,10 +813,33 @@ public class ProfileViewer { } JsonArray playerInfo = getSkyblockProfiles(() -> {}); - if (playerInfo == null) return null; //Not sure how to support the callback in these cases - if (updatingSoopyNetworth.get()) return new SoopyNetworthData(null).setLoading(); //It shouldent really matter tho as these should never occur in /peek + if (playerInfo == null) + return null; //Not sure how to support the callback in these cases + if (updatingSoopyNetworth.get()) + return new SoopyNetworthData(null).setLoading(); //It shouldent really matter tho as these should never occur in /peek updatingSoopyNetworth.set(true); + soopyNetworthLeaderboardPosition = -2; //loading + manager.apiUtils + .request() + .url("https://soopy.dev/api/v2/leaderboard/networth/user/" + this.uuid) + .requestJson() + .handle((jsonObject, throwable) -> { + if (throwable != null) throwable.printStackTrace(); + if (throwable != null || !jsonObject.has("success") || !jsonObject.get("success").getAsBoolean() + || !jsonObject.has("data") + || !jsonObject.get("data").getAsJsonObject().has("data") + || !jsonObject.get("data").getAsJsonObject().get("data").getAsJsonObject().has("position")) { + //Something went wrong + //Set profile lb position to -3 to indicate that + soopyNetworthLeaderboardPosition = -3; //error + return null; + } + soopyNetworthLeaderboardPosition = jsonObject.get("data").getAsJsonObject().get("data").getAsJsonObject().get( + "position").getAsLong(); + return null; + }); + manager.apiUtils .request() .url("https://soopy.dev/api/v2/player_networth/" + this.uuid) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java index 7df88964..36fc07aa 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java @@ -20,14 +20,15 @@ package io.github.moulberry.notenoughupdates.profileviewer.bestiary; import io.github.moulberry.notenoughupdates.util.Utils; -import java.util.LinkedHashMap; -import java.util.List; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumChatFormatting; +import java.util.LinkedHashMap; +import java.util.List; + public class BestiaryData { private static final LinkedHashMap<ItemStack, List<String>> bestiaryLocations = new LinkedHashMap<ItemStack, List<String>>() { @@ -109,7 +110,7 @@ public class BestiaryData { "family_ghast", "family_mage_outlaw", "family_magma_cube", - "family_magma_cube_boss", + "family_magma_boss", "family_matcho", "family_charging_mushroom_cow", "family_pigman", @@ -505,9 +506,9 @@ public class BestiaryData { ) ); put( - "family_magma_cube_boss", + "family_magma_boss", Utils.createSkull( - EnumChatFormatting.AQUA + "§a§6§lMagma Cube Boss", + EnumChatFormatting.AQUA + "§a§4§lMagma Boss", "35f02923-7bec-3869-9ef5-b42a4794cac8", "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg5NTdkNTAyM2M5MzdjNGM0MWFhMjQxMmQ0MzQxMGJkYTIzY2Y3OWE5ZjZhYjM2Yjc2ZmVmMmQ3YzQyOSJ9fX0=" ) @@ -1010,7 +1011,7 @@ public class BestiaryData { put("family_ghast", "MOB"); put("family_mage_outlaw", "BOSS"); put("family_magma_cube", "MOB"); - put("family_magma_cube_boss", "BOSS"); + put("family_magma_boss", "BOSS"); put("family_matcho", "MOB"); put("family_charging_mushroom_cow", "MOB"); put("family_pigman", "MOB"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java index 3ceabaf5..819c16de 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java @@ -26,6 +26,7 @@ import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Dungeons import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; + import java.util.Map; public class LilyDungeonsWeight extends DungeonsWeight { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java index 8ed43f6e..f47032a4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java @@ -19,16 +19,17 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.lily; -import static io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight.SKILL_NAMES; - import com.google.gson.JsonArray; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SkillsWeight; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; + import java.util.Map; +import static io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight.SKILL_NAMES; + public class LilySkillsWeight extends SkillsWeight { public LilySkillsWeight(Map<String, ProfileViewer.Level> player) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java index d26597a1..12cb01e2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java @@ -24,6 +24,7 @@ import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SlayerWe import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; + import java.util.Map; public class LilySlayerWeight extends SlayerWeight { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java index 4ffc9fdd..03c5cfbf 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java @@ -22,6 +22,7 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.lily; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight; + import java.util.Map; public class LilyWeight extends Weight { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java index 3b5adae5..e41b0ff4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java @@ -24,6 +24,7 @@ import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Dungeons import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; + import java.util.Map; public class SenitherDungeonsWeight extends DungeonsWeight { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java index 2a4ee48c..7ac717f7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java @@ -25,6 +25,7 @@ import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SkillsWe import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; + import java.util.Map; public class SenitherSkillsWeight extends SkillsWeight { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java index 80853853..e9fd5b41 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java @@ -25,6 +25,7 @@ import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SlayerWe import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; + import java.util.Map; public class SenitherSlayerWeight extends SlayerWeight { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java index 2f813576..532db942 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java @@ -21,6 +21,7 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.senither; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight; + import java.util.Map; public class SenitherWeight extends Weight { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java index 9c233554..c915d3be 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.weight; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; + import java.util.Map; public abstract class DungeonsWeight { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java index 5c372591..84d3f551 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.weight; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; + import java.util.Map; public abstract class SkillsWeight { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java index 20b2762d..bab8a154 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java @@ -20,6 +20,7 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.weight; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; + import java.util.Map; public abstract class SlayerWeight { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java index d63ea42c..54daf42d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java @@ -33,7 +33,6 @@ import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; @@ -91,32 +90,30 @@ public class RecipeGenerator { if (uiTitle.equals("Confirm Process") && saveRecipe) { ForgeRecipe recipe = parseSingleForgeRecipe(menu); if (recipe == null) { - p.addChatMessage(new ChatComponentText( - "" + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "Could not parse recipe for this UI")); + Utils.addChatMessage( + "" + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "Could not parse recipe for this UI"); } else { - p.addChatMessage(new ChatComponentText( - "" + EnumChatFormatting.GREEN + EnumChatFormatting.BOLD + "Parsed recipe:")); - p.addChatMessage(new ChatComponentText("" + EnumChatFormatting.AQUA + " Inputs:")); + Utils.addChatMessage("" + EnumChatFormatting.GREEN + EnumChatFormatting.BOLD + "Parsed recipe:"); + Utils.addChatMessage("" + EnumChatFormatting.AQUA + " Inputs:"); for (Ingredient i : recipe.getInputs()) - p.addChatMessage(new ChatComponentText( - " - " + EnumChatFormatting.AQUA + i.getInternalItemId() + " x " + i.getCount())); - p.addChatMessage(new ChatComponentText("" + EnumChatFormatting.AQUA + " Output: " + EnumChatFormatting.GOLD + - recipe.getOutput().getInternalItemId() + " x " + recipe.getOutput().getCount())); - p.addChatMessage(new ChatComponentText( + Utils.addChatMessage(" - " + EnumChatFormatting.AQUA + i.getInternalItemId() + " x " + i.getCount()); + Utils.addChatMessage("" + EnumChatFormatting.AQUA + " Output: " + EnumChatFormatting.GOLD + + recipe.getOutput().getInternalItemId() + " x " + recipe.getOutput().getCount()); + Utils.addChatMessage( "" + EnumChatFormatting.AQUA + " Time: " + EnumChatFormatting.GRAY + recipe.getTimeInSeconds() + - " seconds (no QF) .")); + " seconds (no QF) ."); boolean saved = false; try { saved = saveRecipes(recipe.getOutput().getInternalItemId(), Collections.singletonList(recipe)); - } catch (IOException e) { + } catch (IOException ignored) { } if (!saved) - p.addChatMessage(new ChatComponentText("" + - EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + EnumChatFormatting.OBFUSCATED + "#" + - EnumChatFormatting.RESET + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + " ERROR " + - EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + EnumChatFormatting.OBFUSCATED + "#" + - EnumChatFormatting.RESET + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + - " Failed to save recipe. Does the item already exist?")); + Utils.addChatMessage( + "" + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + EnumChatFormatting.OBFUSCATED + "#" + + EnumChatFormatting.RESET + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + " ERROR " + + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + EnumChatFormatting.OBFUSCATED + "#" + + EnumChatFormatting.RESET + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + + " Failed to save recipe. Does the item already exist?"); } } if (saveRecipe) attemptToSaveBestiary(menu); @@ -171,8 +168,7 @@ public class RecipeGenerator { for (String loreLine : mobLore) { Matcher loreMatcher = LORE_PATTERN.matcher(loreLine); if (!loreMatcher.matches()) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "[WARNING] Unknown lore line: " + loreLine)); + Utils.addChatMessage("[WARNING] Unknown lore line: " + loreLine); continue; } if (loreMatcher.group("coins") != null) @@ -186,8 +182,7 @@ public class RecipeGenerator { List<JsonObject> possibleItems = neu.manager.getItemInformation().values().stream().filter(it -> it.get( "displayname").getAsString().equals(dropName)).collect(Collectors.toList()); if (possibleItems.size() != 1) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "[WARNING] Could not parse drop, ambiguous or missing item information: " + loreLine)); + Utils.addChatMessage("[WARNING] Could not parse drop, ambiguous or missing item information: " + loreLine); continue; } Ingredient item = new Ingredient(neu.manager, possibleItems.get(0).get("internalname").getAsString()); @@ -197,9 +192,7 @@ public class RecipeGenerator { drops.add(new MobLootRecipe.MobDrop(item, chance, new ArrayList<>())); } if (loreMatcher.group("missing") != null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "[WARNING] You are missing Bestiary levels for drop: " + loreLine)); - + Utils.addChatMessage("[WARNING] You are missing Bestiary levels for drop: " + loreLine); } } recipes.add(new MobLootRecipe( @@ -218,15 +211,15 @@ public class RecipeGenerator { boolean saved = false; try { saved = saveRecipes(internalMobName, recipes); - } catch (IOException e) { + } catch (IOException ignored) { } if (!saved) - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("" + - EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + EnumChatFormatting.OBFUSCATED + "#" + - EnumChatFormatting.RESET + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + " ERROR " + - EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + EnumChatFormatting.OBFUSCATED + "#" + - EnumChatFormatting.RESET + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + - " Failed to save recipe. Does the item already exist?")); // TODO: MERGE CODE OVER + Utils.addChatMessage( + "" + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + EnumChatFormatting.OBFUSCATED + "#" + + EnumChatFormatting.RESET + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + " ERROR " + + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + EnumChatFormatting.OBFUSCATED + "#" + + EnumChatFormatting.RESET + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + + " Failed to save recipe. Does the item already exist?"); // TODO: MERGE CODE OVER } private int parseIntIgnoringCommas(String text) { @@ -307,7 +300,7 @@ public class RecipeGenerator { ); } - private static Map<Character, Integer> durationSuffixLengthMap = new HashMap<Character, Integer>() {{ + private static final Map<Character, Integer> durationSuffixLengthMap = new HashMap<Character, Integer>() {{ put('d', 60 * 60 * 24); put('h', 60 * 60); put('m', 60); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeHistory.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeHistory.java new file mode 100644 index 00000000..c4a0f6e4 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeHistory.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.recipes; + +import net.minecraft.client.gui.GuiScreen; + +import java.util.ArrayList; + +public class RecipeHistory { + + private static final int MAX_HISTORY_SIZE = 50; + + private static ArrayList<GuiScreen> history = new ArrayList<>(); + private static int historyIndex = 0; + + public static void add(GuiScreen recipe) { + if (history.size() == MAX_HISTORY_SIZE) { + history.remove(0); + historyIndex--; + } else { + if (history.size() == 0) { + history.add(recipe); + } else { + if (historyIndex < history.size() - 1) { + history = new ArrayList<>(history.subList(0, historyIndex + 1)); + } + history.add(recipe); + historyIndex++; + } + } + } + + public static GuiScreen getPrevious() { + if (history.size() > 0) { + if (historyIndex - 1 < 0) { + return null; + } + historyIndex--; + return history.get(historyIndex); + } + return null; + } + + public static GuiScreen getNext() { + if (historyIndex < history.size() - 1) { + historyIndex++; + return history.get(historyIndex); + } + return null; + } + + public static void clear() { + history = new ArrayList<>(); + historyIndex = 0; + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java index 7818c3c0..e84c1c43 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java @@ -22,6 +22,8 @@ package io.github.moulberry.notenoughupdates.util; import com.google.gson.Gson; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.events.ProfileDataLoadedEvent; +import net.minecraft.client.Minecraft; import org.apache.commons.io.IOUtils; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URIBuilder; @@ -48,7 +50,9 @@ import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -59,6 +63,7 @@ public class ApiUtil { private static final ExecutorService executorService = Executors.newFixedThreadPool(3); private static final String USER_AGENT = "NotEnoughUpdates/" + NotEnoughUpdates.VERSION; private static SSLContext ctx; + private final Map<String, CompletableFuture<Void>> updateTasks = new HashMap<>(); static { try { @@ -77,6 +82,23 @@ public class ApiUtil { } } + public void updateProfileData() { + updateProfileData(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")); + } + + public void updateProfileData(String playerUuid) { + if (!updateTasks.getOrDefault(playerUuid, CompletableFuture.completedFuture(null)).isDone()) return; + + updateTasks.put(playerUuid, newHypixelApiRequest("skyblock/profiles") + .queryArgument("uuid", Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")) + .requestJson() + .handle((jsonObject, throwable) -> { + new ProfileDataLoadedEvent(jsonObject).post(); + return null; + })); + + } + public static class Request { private final List<NameValuePair> queryArguments = new ArrayList<>(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HotmInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HotmInformation.java index 1968b51e..57c4ae3b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/HotmInformation.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HotmInformation.java @@ -23,6 +23,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.events.ProfileDataLoadedEvent; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.inventory.ContainerChest; @@ -135,7 +136,7 @@ public class HotmInformation { public synchronized void onLobbyJoin(WorldEvent.Load event) { if (shouldReloadSoon) { shouldReloadSoon = false; - requestUpdate(false); + neu.manager.apiUtils.updateProfileData(); } } @@ -154,17 +155,7 @@ public class HotmInformation { @SubscribeEvent public synchronized void onChat(ClientChatReceivedEvent event) { if (event.message.getUnformattedText().equals("Welcome to Hypixel SkyBlock!")) - requestUpdate(false); - } - - public synchronized void requestUpdate(boolean force) { - if (updateTask.isDone() || force) { - updateTask = neu.manager.apiUtils - .newHypixelApiRequest("skyblock/profiles") - .queryArgument("uuid", Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")) - .requestJson() - .thenAccept(this::updateInformation); - } + neu.manager.apiUtils.updateProfileData(); } /* @@ -176,10 +167,13 @@ public class HotmInformation { if (level > 20) return -1; return QUICK_FORGE_MULTIPLIERS[level - 1]; } + @SubscribeEvent + public void onApiDataLoaded(ProfileDataLoadedEvent event) { + JsonObject data = event.getData(); + if (data == null) return; - public void updateInformation(JsonObject entireApiResponse) { - if (!entireApiResponse.has("success") || !entireApiResponse.get("success").getAsBoolean()) return; - JsonArray profiles = entireApiResponse.getAsJsonArray("profiles"); + if (!data.has("success") || !data.get("success").getAsBoolean()) return; + JsonArray profiles = data.getAsJsonArray("profiles"); for (JsonElement element : profiles) { JsonObject profile = element.getAsJsonObject(); String profileName = profile.get("cute_name").getAsString(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java index 3692602a..ea5e13ab 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java @@ -116,6 +116,9 @@ public class ItemResolutionQuery { case "PARTY_HAT_CRAB_ANIMATED": resolvedName = resolveCrabHatName(); break; + case "ABICASE": + resolvedName = resolvePhoneCase(); + break; } } @@ -235,6 +238,11 @@ public class ItemResolutionQuery { return "PARTY_HAT_CRAB_" + color.toUpperCase(Locale.ROOT) + (crabHatYear == 2022 ? "_ANIMATED" : ""); } + private String resolvePhoneCase() { + String model = getExtraAttributes().getString("model"); + return "ABICASE_" + model.toUpperCase(Locale.ROOT); + } + private String resolveEnchantedBookNameFromNBT() { NBTTagCompound enchantments = getExtraAttributes().getCompoundTag("enchantments"); String enchantName = IteratorUtils.getOnlyElement(enchantments.getKeySet(), null); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java index 230b8ae5..e5d00a66 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java @@ -34,7 +34,7 @@ public class NEUDebugLogger { public static boolean allFlagsEnabled = false; private static void chatLogger(String message) { - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU DEBUG] " + message)); + Utils.addChatMessage(EnumChatFormatting.YELLOW + "[NEU DEBUG] " + message); } public static boolean isFlagEnabled(NEUDebugFlag flag) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java index b5e6c391..b8e8312d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java @@ -24,6 +24,7 @@ import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.listener.ScoreboardLocationChangeListener; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent; +import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; import io.github.moulberry.notenoughupdates.overlays.SlayerOverlay; import net.minecraft.client.Minecraft; @@ -38,7 +39,6 @@ import net.minecraft.scoreboard.Score; import net.minecraft.scoreboard.ScoreObjective; import net.minecraft.scoreboard.ScorePlayerTeam; import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; import net.minecraftforge.client.event.ClientChatReceivedEvent; @@ -158,8 +158,7 @@ public class SBInfo { public boolean checkForSkyblockLocation() { if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() || getLocation() == null) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + - "[NEU] This command is not available outside SkyBlock")); + Utils.addChatMessage(EnumChatFormatting.RED + "[NEU] This command is not available outside SkyBlock"); return false; } @@ -316,6 +315,7 @@ public class SBInfo { String name = Minecraft.getMinecraft().ingameGUI.getTabList().getPlayerName(info); if (name.startsWith(profilePrefix)) { String newProfile = Utils.cleanColour(name.substring(profilePrefix.length())); + setCurrentProfile(newProfile); if (!Objects.equals(currentProfile, newProfile)) { currentProfile = newProfile; if (NotEnoughUpdates.INSTANCE.config != null) @@ -458,4 +458,11 @@ public class SBInfo { public JsonObject getMayorJson() { return mayorJson; } + + public void setCurrentProfile(String newProfile) { + if (!newProfile.equals(currentProfile)) { + currentProfile = newProfile; + MinionHelperManager.getInstance().onProfileSwitch(); + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/TabListUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/TabListUtils.java new file mode 100644 index 00000000..a0266122 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/TabListUtils.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util; + +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.Ordering; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.world.WorldSettings; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class TabListUtils { + + private static final Ordering<NetworkPlayerInfo> playerOrdering = Ordering.from(new PlayerComparator()); + + @SideOnly(Side.CLIENT) + static class PlayerComparator implements Comparator<NetworkPlayerInfo> { + private PlayerComparator() {} + + public int compare(NetworkPlayerInfo o1, NetworkPlayerInfo o2) { + ScorePlayerTeam team1 = o1.getPlayerTeam(); + ScorePlayerTeam team2 = o2.getPlayerTeam(); + return ComparisonChain.start().compareTrueFirst( + o1.getGameType() != WorldSettings.GameType.SPECTATOR, + o2.getGameType() != WorldSettings.GameType.SPECTATOR + ) + .compare( + team1 != null ? team1.getRegisteredName() : "", + team2 != null ? team2.getRegisteredName() : "" + ) + .compare(o1.getGameProfile().getName(), o2.getGameProfile().getName()).result(); + } + } + + public static List<String> getTabList() { + List<NetworkPlayerInfo> players = + playerOrdering.sortedCopy(Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()); + + List<String> result = new ArrayList<>(); + + for (NetworkPlayerInfo info : players) { + String name = Minecraft.getMinecraft().ingameGUI.getTabList().getPlayerName(info); + result.add(name); + } + return result; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/TitleUtil.java b/src/main/java/io/github/moulberry/notenoughupdates/util/TitleUtil.java new file mode 100644 index 00000000..59db7cac --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/TitleUtil.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class TitleUtil { + + private static final TitleUtil INSTANCE = new TitleUtil(); + + public static TitleUtil getInstance() { + return INSTANCE; + } + + private String title = null; + private long titleLifetime = 0; + private int color = 0xFF0000; + + public void createTitle(String title, int ticks, int color) { + this.title = title; + this.titleLifetime = System.nanoTime() + (ticks * 50000000L); + this.color = color; + } + /** + * Adapted from SkyblockAddons under MIT license + * @link https://github.com/BiscuitDevelopment/SkyblockAddons/blob/master/LICENSE + * @author BiscuitDevelopment + */ + private void renderTitles (ScaledResolution scaledResolution) { + Minecraft mc = Minecraft.getMinecraft(); + if (mc.theWorld == null || mc.thePlayer == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; + + int scaledWidth = scaledResolution.getScaledWidth(); + int scaledHeight = scaledResolution.getScaledHeight(); + + if (this.title != null) { + int stringWidth = mc.fontRendererObj.getStringWidth(this.title); + float scale = 4f; // Scale is normally 4, but if it's larger than the screen, scale it down... + if (stringWidth * scale > scaledWidth * 0.9f) { + scale = scaledWidth * 0.9f / (float) stringWidth; + } + GlStateManager.pushMatrix(); + GlStateManager.translate((float)(scaledWidth / 2),(float)(scaledHeight / 2), 0.0f); + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.pushMatrix(); + GlStateManager.scale(scale, scale, scale); + mc.fontRendererObj.drawString( + this.title, + ((float)-mc.fontRendererObj.getStringWidth(this.title) / 2), + -20.0f, + color, + true + ); + GlStateManager.popMatrix(); + GlStateManager.popMatrix(); + } + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onRenderHUD(RenderGameOverlayEvent event) { + if (event.type != RenderGameOverlayEvent.ElementType.HOTBAR) return; + if (System.nanoTime() >= titleLifetime) { + titleLifetime = 0; + title = null; + } + renderTitles(event.resolution); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java index 1ee24ec8..57f24370 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java @@ -78,6 +78,7 @@ import java.math.BigInteger; import java.nio.FloatBuffer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -117,7 +118,6 @@ public class Utils { "VERY SPECIAL", "SUPREME", "^^ THAT ONE IS DIVINE ^^" -//, "DIVINE" }; public static String[] rarityArrC = new String[]{ EnumChatFormatting.WHITE + EnumChatFormatting.BOLD.toString() + "COMMON", @@ -129,8 +129,6 @@ public class Utils { EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "SPECIAL", EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "VERY SPECIAL", EnumChatFormatting.AQUA + EnumChatFormatting.BOLD.toString() + "DIVINE", - EnumChatFormatting.AQUA + EnumChatFormatting.BOLD.toString() + "DIVINE", - //EnumChatFormatting.AQUA+EnumChatFormatting.BOLD.toString()+"DIVINE", }; public static final HashMap<String, String> rarityArrMap = new HashMap<String, String>() {{ put("COMMON", rarityArrC[0]); @@ -142,11 +140,11 @@ public class Utils { put("SPECIAL", rarityArrC[6]); put("VERY SPECIAL", rarityArrC[7]); put("DIVINE", rarityArrC[8]); - // put("DIVINE", rarityArrC[9]); }}; public static Splitter PATH_SPLITTER = Splitter.on(".").omitEmptyStrings().limit(2); private static ScaledResolution lastScale = new ScaledResolution(Minecraft.getMinecraft()); private static long startTime = 0; + private static DecimalFormat simpleDoubleFormat = new DecimalFormat("0.0"); public static <T> ArrayList<T> createList(T... values) { ArrayList<T> list = new ArrayList<>(); @@ -329,6 +327,11 @@ public class Utils { } public static String shortNumberFormat(double n, int iteration) { + if (n < 3 && n > 0) { + return simpleDoubleFormat.format(n); + } + + if (n < 1000 && iteration == 0) return "" + (int) n; double d = ((long) n / 100) / 10.0; boolean isRound = (d * 10) % 10 == 0; return (d < 1000 ? @@ -1228,7 +1231,6 @@ public class Utils { while ((lines++ < maxLines) || maxLines < 0) { if (trimmed.length() == str.length()) { drawStringScaled(trimmed, fr, x, y + yOff, shadow, colour, scale); - //fr.drawString(trimmed, x, y + yOff, colour, shadow); break; } else if (trimmed.isEmpty()) { yOff -= 12 * scale; @@ -1946,13 +1948,13 @@ public class Utils { if (NotEnoughUpdates.INSTANCE.config.notifications.outdatedRepo) { NotificationHandler.displayNotification(Lists.newArrayList( EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "Missing repo data", - EnumChatFormatting.RED + - "Data used for many NEU features is not up to date, this should normally not be the case.", - EnumChatFormatting.RED + "You can try " + EnumChatFormatting.BOLD + "/neuresetrepo" + EnumChatFormatting.RESET + - EnumChatFormatting.RED + " and restart your game" + - " to see if that fixes the issue.", - EnumChatFormatting.RED + "If the problem persists please join " + EnumChatFormatting.BOLD + - "discord.gg/moulberry" + + EnumChatFormatting.RED + + "Data used for many NEU features is not up to date, this should normally not be the case.", + EnumChatFormatting.RED + "You can try " + EnumChatFormatting.BOLD + "/neuresetrepo" + EnumChatFormatting.RESET + + EnumChatFormatting.RED + " and restart your game" + + " to see if that fixes the issue.", + EnumChatFormatting.RED + "If the problem persists please join " + EnumChatFormatting.BOLD + + "discord.gg/moulberry" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " and message in " + EnumChatFormatting.BOLD + "#neu-support" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " to get support" ), @@ -2016,4 +2018,13 @@ public class Utils { } return username; } + + public static void addChatMessage(String message) { + EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; + if (thePlayer != null) { + thePlayer.addChatMessage(new ChatComponentText(message)); + } else { + System.out.println(message); + } + } } diff --git a/src/main/resources/assets/notenoughupdates/minion_overlay.png b/src/main/resources/assets/notenoughupdates/minion_overlay.png Binary files differnew file mode 100644 index 00000000..a9bd91ab --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/minion_overlay.png |