diff options
83 files changed, 3810 insertions, 428 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..af190244 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -132,6 +132,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 +159,6 @@ public class NEUManager { repoLocation.mkdir(); } - public void setCurrentProfile(String currentProfile) { - SBInfo.getInstance().currentProfile = currentProfile; - } - public String getCurrentProfile() { return SBInfo.getInstance().currentProfile; } @@ -1606,6 +1604,7 @@ public class NEUManager { new RepositoryReloadEvent(repoLocation, !hasBeenLoadedBefore).post(); hasBeenLoadedBefore = true; comp.complete(null); + displayNameCache.clear(); } catch (Exception e) { comp.completeExceptionally(e); } @@ -1622,4 +1621,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/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 054cbca4..143033b7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -68,6 +68,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; @@ -318,6 +319,7 @@ 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 WorldListener(this)); 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/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/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 253cc245..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; @@ -656,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) { @@ -881,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) { @@ -914,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 { 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 0ad9fd99..a5acd5b4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java @@ -201,11 +201,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 +214,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; 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..43a1daf9 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java @@ -235,35 +235,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..2eb4c23a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java @@ -50,6 +50,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 +84,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; @@ -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); } @@ -538,6 +537,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) { @@ -666,6 +671,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) { @@ -1143,6 +1154,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) { @@ -1306,17 +1323,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 +1426,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 +1455,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 +1484,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 +1506,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; } @@ -1703,7 +1714,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 +1728,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 0ee29b4f..f378fdca 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java @@ -233,35 +233,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; @@ -374,39 +374,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(); } } @@ -780,15 +777,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; } @@ -798,13 +794,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]"; @@ -919,8 +915,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/FairySouls.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java index 75f1b427..4cdb1557 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; @@ -370,7 +370,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/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..0a1e5b81 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java @@ -21,6 +21,7 @@ package io.github.moulberry.notenoughupdates.miscgui; import com.google.common.collect.ImmutableList; import io.github.moulberry.notenoughupdates.NEUManager; +import io.github.moulberry.notenoughupdates.core.util.ArrowPagesUtils; import io.github.moulberry.notenoughupdates.recipes.NeuRecipe; import io.github.moulberry.notenoughupdates.recipes.RecipeSlot; import io.github.moulberry.notenoughupdates.recipes.RecipeType; @@ -38,9 +39,7 @@ 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; @@ -49,13 +48,10 @@ 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; @@ -145,7 +141,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 +217,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; @@ -327,7 +269,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,52 +278,15 @@ 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; - } - - for (int i = 0; i < tabs.size(); i++) { - if (isWithinRect( - mouseX - guiLeft, - mouseY - guiTop, - TAB_POS_X, - TAB_POS_Y + TAB_OFFSET_Y * i, - TAB_SIZE_X, - TAB_SIZE_Y - )) { - changeRecipe(i, currentIndex); - Utils.playPressSound(); - return; - } - } + ArrowPagesUtils.onPageSwitchMouse( + guiLeft, + guiTop, + topLeft, + currentIndex, + getCurrentRecipeList().size(), + pageChange -> + changeRecipe(currentTab, pageChange) + ); for (RecipeSlot slot : getAllRenderedSlots()) { if (isWithinRect(mouseX, mouseY, slot.getX(this), slot.getY(this), SLOT_SIZE, SLOT_SIZE)) { @@ -398,4 +303,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/minionhelper/render/renderables/OverviewLine.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/renderables/OverviewLine.java new file mode 100644 index 00000000..85d682b3 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/render/renderables/OverviewLine.java @@ -0,0 +1,25 @@ +/* + * 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; + +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/miscgui/minionhelper/requirements/CustomRequirement.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/CustomRequirement.java new file mode 100644 index 00000000..93174f03 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/minionhelper/requirements/CustomRequirement.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.requirements; + +public class CustomRequirement extends MinionRequirement { + + private final String text; + + public CustomRequirement(String text) { + this.text = text; + } + @Override + 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/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/options/NEUConfig.java b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java index e18d1d84..e1e18940 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java @@ -50,6 +50,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; @@ -406,6 +407,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/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/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/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/bestiary/BestiaryData.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java index 7df88964..6f541833 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>>() { 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/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/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 095dde87..e28e52d6 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; } @@ -312,6 +311,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) @@ -454,4 +454,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/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java index b02565cd..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; @@ -143,6 +144,7 @@ public class Utils { 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<>(); @@ -325,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 ? @@ -1941,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" ), @@ -2011,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 |