From d44f33636eb301ff029bf41d7f1decb3340efb54 Mon Sep 17 00:00:00 2001 From: Lulonaut <67191924+Lulonaut@users.noreply.github.com> Date: Thu, 3 Mar 2022 04:05:45 +0100 Subject: [PATCH 001/222] NeuEventListener changes and dead code removal (#88) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * hide Hypixel reforge stats * unused import? * better comments * 2.1.md 🙂 * 2.1.md 🙂 * minor cleanup * api * remove collectionLog and morus and cape.png * remove FancyPortals and panorama dev cmd Co-authored-by: IRONM00N <64110067+IRONM00N@users.noreply.github.com> --- build.gradle.kts | 1 - cape.png | Bin 14652 -> 0 bytes deps/Morus-1.0.jar | Bin 74917 -> 0 bytes .../moulberry/notenoughupdates/NEUApi.java | 2 +- .../notenoughupdates/NEUEventListener.java | 2842 ----------------- .../notenoughupdates/NEUOverlay.java | 339 +- .../notenoughupdates/NotEnoughUpdates.java | 70 +- .../collectionlog/CollectionConstant.java | 15 - .../collectionlog/GuiCollectionLog.java | 111 - .../commands/dev/DevTestCommand.java | 76 +- .../help/StorageViewerWhyCommand.java | 4 +- .../commands/misc/CollectionLogCommand.java | 20 - .../commands/misc/GamemodesCommand.java | 20 - .../gamemodes/GuiGamemodes.java | 323 -- .../gamemodes/SBGamemodes.java | 374 --- .../infopanes/CollectionLogInfoPane.java | 534 ---- .../listener/ChatListener.java | 219 ++ .../listener/ItemTooltipListener.java | 980 ++++++ .../listener/NEUEventListener.java | 328 ++ .../listener/RenderListener.java | 1183 +++++++ .../miscfeatures/BetterContainers.java | 4 +- .../miscfeatures/CollectionLogManager.java | 44 - .../miscfeatures/FancyPortals.java | 293 -- .../miscfeatures/PetInfoOverlay.java | 4 +- .../miscgui/AccessoryBagOverlay.java | 105 +- .../miscgui/StorageOverlay.java | 4 +- .../mixins/MixinEntityRenderer.java | 43 +- .../mixins/MixinGuiContainer.java | 4 +- .../mixins/MixinGuiInventory.java | 4 +- .../mixins/MixinLoadingScreenRenderer.java | 18 - .../mixins/MixinMouseHelper.java | 4 +- .../mixins/MixinNetHandlerPlayClient.java | 13 - .../mixins/MixinRenderItem.java | 8 +- .../notenoughupdates/util/Constants.java | 3 - .../util/NotificationHandler.java | 112 + 35 files changed, 3135 insertions(+), 4969 deletions(-) delete mode 100644 cape.png delete mode 100644 deps/Morus-1.0.jar delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CollectionLogManager.java delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLoadingScreenRenderer.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/util/NotificationHandler.java diff --git a/build.gradle.kts b/build.gradle.kts index e824a9a0e1..e47b0f679d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -59,7 +59,6 @@ mixin { repositories { mavenCentral() - flatDir { dirs("deps/") } maven("https://repo.spongepowered.org/maven/") } diff --git a/cape.png b/cape.png deleted file mode 100644 index a2a2d5f759b21eb7a929c054732b2e004c0936d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14652 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

SpOjOeB4$?@18jMS%6o(n`Yg+mh6 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

_^S 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 G1NwixAt71- diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java index d83035d0db..feb18c669b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java @@ -3,7 +3,7 @@ import net.minecraftforge.fml.relauncher.ReflectionHelper; public class NEUApi { - static boolean disableInventoryButtons = false; + public static boolean disableInventoryButtons = false; public static void setInventoryButtonsToDisabled() { disableInventoryButtons = true; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java deleted file mode 100644 index 84289e3456..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java +++ /dev/null @@ -1,2842 +0,0 @@ -package io.github.moulberry.notenoughupdates; - -import com.google.common.collect.Lists; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.MinecraftProfileTexture; -import io.github.moulberry.notenoughupdates.auction.CustomAHGui; -import io.github.moulberry.notenoughupdates.commands.profile.ViewProfileCommand; -import io.github.moulberry.notenoughupdates.core.BackgroundBlur; -import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper; -import io.github.moulberry.notenoughupdates.core.util.MiscUtils; -import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; -import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; -import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks; -import io.github.moulberry.notenoughupdates.dungeons.DungeonWin; -import io.github.moulberry.notenoughupdates.miscfeatures.*; -import io.github.moulberry.notenoughupdates.miscgui.*; -import io.github.moulberry.notenoughupdates.options.NEUConfig; -import io.github.moulberry.notenoughupdates.overlays.*; -import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; -import io.github.moulberry.notenoughupdates.util.*; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.*; -import net.minecraft.client.gui.inventory.GuiChest; -import net.minecraft.client.gui.inventory.GuiContainer; -import net.minecraft.client.gui.inventory.GuiEditSign; -import net.minecraft.client.gui.inventory.GuiInventory; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.event.ClickEvent; -import net.minecraft.init.Items; -import net.minecraft.inventory.ContainerChest; -import net.minecraft.inventory.IInventory; -import net.minecraft.inventory.Slot; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.nbt.NBTUtil; -import net.minecraft.util.*; -import net.minecraftforge.client.ClientCommandHandler; -import net.minecraftforge.client.event.*; -import net.minecraftforge.event.entity.player.ItemTooltipEvent; -import net.minecraftforge.event.world.WorldEvent; -import net.minecraftforge.fml.common.Loader; -import net.minecraftforge.fml.common.eventhandler.EventPriority; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import org.apache.commons.lang3.text.WordUtils; -import org.lwjgl.input.Keyboard; -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; - -import javax.swing.*; -import java.awt.*; -import java.awt.datatransfer.StringSelection; -import java.io.File; -import java.io.IOException; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.List; -import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static io.github.moulberry.notenoughupdates.overlays.SlayerOverlay.*; -import static io.github.moulberry.notenoughupdates.util.GuiTextures.dungeon_chest_worth; - -public class NEUEventListener { - - private final NotEnoughUpdates neu; - - private boolean hoverInv = false; - private boolean focusInv = false; - - private boolean joinedSB = false; - - public NEUEventListener(NotEnoughUpdates neu) { - this.neu = neu; - } - - private void displayUpdateMessageIfOutOfDate() { - File repo = neu.manager.repoLocation; - if (repo.exists()) { - File updateJson = new File(repo, "update.json"); - try { - JsonObject o = neu.manager.getJsonFromFile(updateJson); - - String version = o.get("version").getAsString(); - String preVersion = o.get("pre_version").getAsString(); - - boolean shouldUpdate = !NotEnoughUpdates.VERSION.equalsIgnoreCase(version); - boolean shouldPreUpdate = !NotEnoughUpdates.PRE_VERSION.equalsIgnoreCase(preVersion); - - if (o.has("version_id") && o.get("version_id").isJsonPrimitive()) { - int version_id = o.get("version_id").getAsInt(); - shouldUpdate = version_id > NotEnoughUpdates.VERSION_ID; - } - if (o.has("pre_version_id") && o.get("pre_version_id").isJsonPrimitive()) { - int pre_version_id = o.get("pre_version_id").getAsInt(); - shouldPreUpdate = pre_version_id > NotEnoughUpdates.PRE_VERSION_ID; - } - - if (shouldUpdate) { - String update_msg = o.get("update_msg").getAsString(); - - int first_len = -1; - for (String line : update_msg.split("\n")) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - int len = fr.getStringWidth(line); - if (first_len == -1) { - first_len = len; - } - int missing_len = first_len - len; - if (missing_len > 0) { - StringBuilder sb = new StringBuilder(line); - for (int i = 0; i < missing_len / 8; i++) { - sb.insert(0, " "); - } - line = sb.toString(); - } - line = line.replaceAll("\\{version}", version); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line)); - } - - neu.displayLinks(o); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - } else if (shouldPreUpdate && NotEnoughUpdates.VERSION_ID == o.get("version").getAsInt()) { - String pre_update_msg = o.get("pre_update_msg").getAsString(); - - int first_len = -1; - for (String line : pre_update_msg.split("\n")) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - int len = fr.getStringWidth(line); - if (first_len == -1) { - first_len = len; - } - int missing_len = first_len - len; - if (missing_len > 0) { - StringBuilder sb = new StringBuilder(line); - for (int i = 0; i < missing_len / 8; i++) { - sb.insert(0, " "); - } - line = sb.toString(); - } - line = line.replaceAll("\\{pre_version}", preVersion); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line)); - } - - neu.displayLinks(o); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - } - } catch (Exception ignored) { - } - } - } - - @SubscribeEvent - public void onWorldLoad(WorldEvent.Unload event) { - NotEnoughUpdates.INSTANCE.saveConfig(); - CrystalMetalDetectorSolver.reset(false); - } - - private static long notificationDisplayMillis = 0; - private static List notificationLines = null; - private static boolean showNotificationOverInv = false; - - private static final Pattern BAD_ITEM_REGEX = Pattern.compile("x[0-9]{1,2}$"); - private static final Pattern SLAYER_XP = - Pattern.compile(" (Spider|Zombie|Wolf|Enderman) Slayer LVL (\\d) - (?:Next LVL in ([\\d,]+) XP!|LVL MAXED OUT!)"); - - /** - * 1)Will send the cached message from #sendChatMessage when at least 200ms has passed since the last message. - * This is used in order to prevent the mod spamming messages. - * 2)Adds unique items to the collection log - */ - private boolean preloadedItems = false; - private long lastLongUpdate = 0; - private long lastSkyblockScoreboard = 0; - - private final ExecutorService itemPreloader = Executors.newFixedThreadPool(10); - private final List toPreload = new ArrayList<>(); - - private int inventoryLoadedTicks = 0; - private String loadedInvName = ""; - public static boolean inventoryLoaded = false; - - public static void displayNotification(List lines, boolean showForever) { - displayNotification(lines, showForever, false); - } - - public static void displayNotification(List lines, boolean showForever, boolean overInventory) { - if (showForever) { - notificationDisplayMillis = -420; - } else { - notificationDisplayMillis = System.currentTimeMillis(); - } - notificationLines = lines; - showNotificationOverInv = overInventory; - } - - @SubscribeEvent - public void onTick(TickEvent.ClientTickEvent event) { - Keyboard.enableRepeatEvents( - Minecraft.getMinecraft().currentScreen != null && (Minecraft.getMinecraft().currentScreen instanceof GuiChat - || Minecraft.getMinecraft().currentScreen instanceof GuiEditSign || - Minecraft.getMinecraft().currentScreen instanceof GuiScreenBook)); - if (event.phase != TickEvent.Phase.START) return; - if (Minecraft.getMinecraft().theWorld == null) return; - if (Minecraft.getMinecraft().thePlayer == null) return; - - if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest cc = (ContainerChest) chest.inventorySlots; - - if (!loadedInvName.equals(cc.getLowerChestInventory().getDisplayName().getUnformattedText())) { - loadedInvName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - inventoryLoaded = false; - inventoryLoadedTicks = 3; - } - - if (!inventoryLoaded) { - if (cc.getLowerChestInventory().getStackInSlot(cc.getLowerChestInventory().getSizeInventory() - 1) != null) { - inventoryLoaded = true; - } else { - for (ItemStack stack : chest.inventorySlots.getInventory()) { - if (stack != null) { - if (--inventoryLoadedTicks <= 0) { - inventoryLoaded = true; - } - break; - } - } - } - } - } else { - inventoryLoaded = false; - inventoryLoadedTicks = 3; - } - - if ((Keyboard.isKeyDown(Keyboard.KEY_NUMPAD1) && Keyboard.isKeyDown(Keyboard.KEY_NUMPAD4) && - Keyboard.isKeyDown(Keyboard.KEY_NUMPAD9))) { - ChatComponentText component = new ChatComponentText("\u00a7cYou are permanently banned from this server!"); - component.appendText("\n"); - component.appendText("\n\u00a77Reason: \u00a7rSuspicious account activity/Other"); - component.appendText("\n\u00a77Find out more: \u00a7b\u00a7nhttps://www.hypixel.net/appeal"); - component.appendText("\n"); - component.appendText("\n\u00a77Ban ID: \u00a7r#49871982"); - component.appendText("\n\u00a77Sharing your Ban ID may affect the processing of your appeal!"); - Minecraft.getMinecraft().getNetHandler().getNetworkManager().closeChannel(component); - return; - } - - if (neu.hasSkyblockScoreboard()) { - if (!preloadedItems) { - preloadedItems = true; - List list = new ArrayList<>(neu.manager.getItemInformation().values()); - for (JsonObject json : list) { - itemPreloader.submit(() -> { - ItemStack stack = neu.manager.jsonToStack(json, true, true); - if (stack.getItem() == Items.skull) toPreload.add(stack); - }); - } - } else if (!toPreload.isEmpty()) { - Utils.drawItemStack(toPreload.get(0), -100, -100); - toPreload.remove(0); - } else { - itemPreloader.shutdown(); - } - - for (TextOverlay overlay : OverlayManager.textOverlays) { - overlay.shouldUpdateFrequent = true; - } - } - - boolean longUpdate = false; - long currentTime = System.currentTimeMillis(); - if (currentTime - lastLongUpdate > 1000) { - longUpdate = true; - lastLongUpdate = currentTime; - } - if (!NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) { - DungeonBlocks.tick(); - } - DungeonWin.tick(); - - String containerName = null; - if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - - if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) { - GuiCustomEnchant.getInstance().tick(); - } - } - - if (longUpdate) { - CrystalOverlay.tick(); - FairySouls.tick(); - XPInformation.getInstance().tick(); - ProfileApiSyncer.getInstance().tick(); - ItemCustomizeManager.tick(); - BackgroundBlur.markDirty(); - NPCRetexturing.getInstance().tick(); - StorageOverlay.getInstance().markDirty(); - - if (neu.hasSkyblockScoreboard()) { - for (TextOverlay overlay : OverlayManager.textOverlays) { - overlay.tick(); - } - } - - NotEnoughUpdates.INSTANCE.overlay.redrawItems(); - CapeManager.onTickSlow(); - - NotEnoughUpdates.profileViewer.putNameUuid( - Minecraft.getMinecraft().thePlayer.getName(), - Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "") - ); - - if (NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) { - DungeonBlocks.tick(); - } - - if (System.currentTimeMillis() - SBInfo.getInstance().joinedWorld > 500 && - System.currentTimeMillis() - SBInfo.getInstance().unloadedWorld > 500) { - neu.updateSkyblockScoreboard(); - } - CapeManager.getInstance().tick(); - - if (containerName != null) { - if (!containerName.trim().startsWith("Accessory Bag")) { - AccessoryBagOverlay.resetCache(); - } - } else { - AccessoryBagOverlay.resetCache(); - } - - if (neu.hasSkyblockScoreboard()) { - SBInfo.getInstance().tick(); - lastSkyblockScoreboard = currentTime; - if (!joinedSB) { - joinedSB = true; - - //SBGamemodes.loadFromFile(); - - if (NotEnoughUpdates.INSTANCE.config.notifications.showUpdateMsg) { - displayUpdateMessageIfOutOfDate(); - } - - if (NotEnoughUpdates.INSTANCE.config.notifications.doRamNotif) { - long maxMemoryMB = Runtime.getRuntime().maxMemory() / 1024L / 1024L; - if (maxMemoryMB > 4100) { - notificationDisplayMillis = System.currentTimeMillis(); - notificationLines = new ArrayList<>(); - notificationLines.add(EnumChatFormatting.GRAY + "Too much memory allocated!"); - notificationLines.add(String.format( - EnumChatFormatting.DARK_GRAY + "NEU has detected %03dMB of memory allocated to Minecraft!", - maxMemoryMB - )); - notificationLines.add(EnumChatFormatting.GRAY + "It is recommended to allocated between 2-4GB of memory"); - notificationLines.add( - EnumChatFormatting.GRAY + "More than 4GB MAY cause FPS issues, EVEN if you have 16GB+ available"); - notificationLines.add(""); - notificationLines.add( - EnumChatFormatting.GRAY + "For more information, visit #ram-info in discord.gg/moulberry"); - } - } - - 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")); - } 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.")); - 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("")); - 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("")); - } - } - } - if (currentTime - lastSkyblockScoreboard < 5 * 60 * 1000) { //5 minutes - neu.manager.auctionManager.tick(); - } else { - neu.manager.auctionManager.markNeedsUpdate(); - } - } - - /*if(longUpdate && neu.hasSkyblockScoreboard()) { - if(neu.manager.getCurrentProfile() == null || neu.manager.getCurrentProfile().length() == 0) { - ProfileViewer.Profile profile = NotEnoughUpdates.profileViewer.getProfile(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""), - callback->{}); - if(profile != null) { - String latest = profile.getLatestProfile(); - if(latest != null) { - neu.manager.setCurrentProfileBackup(profile.getLatestProfile()); - } - } - }*/ - /*if(neu.manager.getCurrentProfile() != null && neu.manager.getCurrentProfile().length() > 0) { - HashSet newItem = new HashSet<>(); - if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer && - !(Minecraft.getMinecraft().currentScreen instanceof GuiCrafting)) { - boolean usableContainer = true; - for(ItemStack stack : Minecraft.getMinecraft().thePlayer.openContainer.getInventory()) { - if(stack == null) { - continue; - } - if(stack.hasTagCompound()) { - NBTTagCompound tag = stack.getTagCompound(); - if(tag.hasKey("ExtraAttributes", 10)) { - continue; - } - } - usableContainer = false; - break; - } - if(!usableContainer) { - if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest container = (ContainerChest) chest.inventorySlots; - String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); - - if(containerName.equals("Accessory Bag") || containerName.startsWith("Wardrobe")) { - usableContainer = true; - } - } - } - if(usableContainer) { - for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) { - processUniqueStack(stack, newItem); - } - for(ItemStack stack : Minecraft.getMinecraft().thePlayer.openContainer.getInventory()) { - processUniqueStack(stack, newItem); - } - } - } else { - for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) { - processUniqueStack(stack, newItem); - } - } - newItemAddMap.keySet().retainAll(newItem); - } - }*/ - } - - /*private void processUniqueStack(ItemStack stack, HashSet newItem) { - if(stack != null && stack.hasTagCompound()) { - String internalname = neu.manager.getInternalNameForItem(stack); - if(internalname != null) { - /*ArrayList log = neu.manager.config.collectionLog.value.computeIfAbsent( - neu.manager.getCurrentProfile(), k -> new ArrayList<>()); - if(!log.contains(internalname)) { - newItem.add(internalname); - if(newItemAddMap.containsKey(internalname)) { - if(System.currentTimeMillis() - newItemAddMap.get(internalname) > 1000) { - log.add(internalname); - try { neu.manager.saveConfig(); } catch(IOException ignored) {} - } - } else { - newItemAddMap.put(internalname, System.currentTimeMillis()); - } - } - } - } - }*/ - - @SubscribeEvent(priority = EventPriority.HIGHEST) - public void onRenderEntitySpecials(RenderLivingEvent.Specials.Pre event) { - if (Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer) { - if (((GuiProfileViewer) Minecraft.getMinecraft().currentScreen).getEntityPlayer() == event.entity) { - event.setCanceled(true); - } - } - } - - @SubscribeEvent - public void onRenderGameOverlayPre(RenderGameOverlayEvent.Pre event) { - if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.BOSSHEALTH) && - Minecraft.getMinecraft().currentScreen instanceof GuiContainer && neu.overlay.isUsingMobsFilter()) { - event.setCanceled(true); - } - if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.PLAYER_LIST)) { - GlStateManager.enableDepth(); - } - } - - @SubscribeEvent - public void onRenderGameOverlayPost(RenderGameOverlayEvent.Post event) { - if (neu.hasSkyblockScoreboard() && event.type.equals(RenderGameOverlayEvent.ElementType.ALL)) { - DungeonWin.render(event.partialTicks); - GlStateManager.pushMatrix(); - GlStateManager.translate(0, 0, -200); - for (TextOverlay overlay : OverlayManager.textOverlays) { - if (OverlayManager.dontRenderOverlay != null && - OverlayManager.dontRenderOverlay.isAssignableFrom(overlay.getClass())) { - continue; - } - GlStateManager.translate(0, 0, -1); - GlStateManager.enableDepth(); - overlay.render(); - } - GlStateManager.popMatrix(); - OverlayManager.dontRenderOverlay = null; - } - if (Keyboard.isKeyDown(Keyboard.KEY_X)) { - notificationDisplayMillis = 0; - } - - if (event.type == RenderGameOverlayEvent.ElementType.ALL) { - renderNotification(); - } - - } - - private static void renderNotification() { - - long timeRemaining = 15000 - (System.currentTimeMillis() - notificationDisplayMillis); - boolean display = timeRemaining > 0 || notificationDisplayMillis == -420; - if (display && notificationLines != null && notificationLines.size() > 0) { - int width = 0; - int height = notificationLines.size() * 10 + 10; - - for (String line : notificationLines) { - int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line) + 8; - if (len > width) { - width = len; - } - } - - ScaledResolution sr = Utils.pushGuiScale(2); - - int midX = sr.getScaledWidth() / 2; - int topY = sr.getScaledHeight() * 3 / 4 - height / 2; - RenderUtils.drawFloatingRectDark(midX - width / 2, sr.getScaledHeight() * 3 / 4 - height / 2, width, height); - /*Gui.drawRect(midX-width/2, sr.getScaledHeight()*3/4-height/2, - midX+width/2, sr.getScaledHeight()*3/4+height/2, 0xFF3C3C3C); - Gui.drawRect(midX-width/2+2, sr.getScaledHeight()*3/4-height/2+2, - midX+width/2-2, sr.getScaledHeight()*3/4+height/2-2, 0xFFC8C8C8);*/ - - int xLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth("[X] Close"); - Minecraft.getMinecraft().fontRendererObj.drawString("[X] Close", midX + width / 2f - 3 - xLen, - topY + 3, 0xFFFF5555, false - ); - - if (notificationDisplayMillis > 0) { - Minecraft.getMinecraft().fontRendererObj.drawString((timeRemaining / 1000) + "s", midX - width / 2f + 3, - topY + 3, 0xFFaaaaaa, false - ); - } - - Utils.drawStringCentered(notificationLines.get(0), Minecraft.getMinecraft().fontRendererObj, - midX, topY + 4 + 5, false, -1 - ); - for (int i = 1; i < notificationLines.size(); i++) { - String line = notificationLines.get(i); - Utils.drawStringCentered(line, Minecraft.getMinecraft().fontRendererObj, - midX, topY + 4 + 5 + 2 + i * 10, false, -1 - ); - } - - Utils.pushGuiScale(-1); - } - } - - public static long lastGuiClosed = 0; - - /** - * When opening a GuiContainer, will reset the overlay and load the config. - * When closing a GuiContainer, will save the config. - * Also includes a dev feature used for automatically acquiring crafting information from the "Crafting Table" GUI. - */ - AtomicBoolean missingRecipe = new AtomicBoolean(false); - - @SubscribeEvent - public void onGuiOpen(GuiOpenEvent event) { - NEUApi.disableInventoryButtons = false; - - if ((Minecraft.getMinecraft().currentScreen instanceof GuiScreenElementWrapper || - Minecraft.getMinecraft().currentScreen instanceof GuiItemRecipe) && - event.gui == null && !(Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) && - System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.lastOpenedGui < 500) { - NotEnoughUpdates.INSTANCE.lastOpenedGui = 0; - event.setCanceled(true); - return; - } - - if (!(event.gui instanceof GuiContainer) && Minecraft.getMinecraft().currentScreen != null) { - CalendarOverlay.setEnabled(false); - } - - if (Minecraft.getMinecraft().currentScreen != null) { - lastGuiClosed = System.currentTimeMillis(); - } - - neu.manager.auctionManager.customAH.lastGuiScreenSwitch = System.currentTimeMillis(); - BetterContainers.reset(); - inventoryLoaded = false; - inventoryLoadedTicks = 3; - - if (event.gui == null && neu.manager.auctionManager.customAH.isRenderOverAuctionView() && - !(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) { - event.gui = new CustomAHGui(); - } - - if (!(event.gui instanceof GuiChest || event.gui instanceof GuiEditSign)) { - neu.manager.auctionManager.customAH.setRenderOverAuctionView(false); - } else if (event.gui instanceof GuiChest && (neu.manager.auctionManager.customAH.isRenderOverAuctionView() || - Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) { - GuiChest chest = (GuiChest) event.gui; - ContainerChest container = (ContainerChest) chest.inventorySlots; - String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); - - neu.manager.auctionManager.customAH.setRenderOverAuctionView(containerName.trim().equals("Auction View") || - containerName.trim().equals("BIN Auction View") || containerName.trim().equals("Confirm Bid") || - containerName.trim().equals("Confirm Purchase")); - } - - //OPEN - if (Minecraft.getMinecraft().currentScreen == null - && event.gui instanceof GuiContainer) { - neu.overlay.reset(); - } - if (event.gui != null && NotEnoughUpdates.INSTANCE.config.hidden.dev) { - if (event.gui instanceof GuiChest) { - GuiChest eventGui = (GuiChest) event.gui; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - IInventory lower = cc.getLowerChestInventory(); - ses.schedule(() -> { - if (Minecraft.getMinecraft().currentScreen != event.gui) { - return; - } - if (lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) { - try { - ItemStack res = lower.getStackInSlot(25); - String resInternalname = neu.manager.getInternalNameForItem(res); - - if (lower.getStackInSlot(48) != null) { - String backName = null; - NBTTagCompound tag = lower.getStackInSlot(48).getTagCompound(); - if (tag.hasKey("display", 10)) { - NBTTagCompound nbttagcompound = tag.getCompoundTag("display"); - if (nbttagcompound.getTagId("Lore") == 9) { - NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8); - backName = nbttaglist1.getStringTagAt(0); - } - } - - if (backName != null) { - String[] split = backName.split(" "); - if (split[split.length - 1].contains("Rewards")) { - String col = backName.substring( - split[0].length() + 1, - backName.length() - split[split.length - 1].length() - 1 - ); - - JsonObject json = neu.manager.getItemInformation().get(resInternalname); - json.addProperty("crafttext", "Requires: " + col); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "Added: " + resInternalname)); - neu.manager.writeJsonDefaultDir(json, resInternalname + ".json"); - neu.manager.loadItem(resInternalname); - } - } - } - - /*JsonArray arr = null; - File f = new File(neu.manager.configLocation, "missing.json"); - try(InputStream instream = new FileInputStream(f)) { - BufferedReader reader = new BufferedReader(new InputStreamReader(instream, StandardCharsets.UTF_8)); - JsonObject json = neu.manager.gson.fromJson(reader, JsonObject.class); - arr = json.getAsJsonArray("missing"); - } catch(IOException e) {} - try { - JsonObject json = new JsonObject(); - JsonArray newArr = new JsonArray(); - for(JsonElement e : arr) { - if(!e.getAsString().equals(resInternalname)) { - newArr.add(e); - } - } - json.add("missing", newArr); - neu.manager.writeJson(json, f); - } catch(IOException e) {}*/ - - - - /*JsonObject recipe = new JsonObject(); - - String[] x = {"1","2","3"}; - String[] y = {"A","B","C"}; - - for(int i=0; i<=18; i+=9) { - for(int j=0; j<3; j++) { - ItemStack stack = lower.getStackInSlot(10+i+j); - String internalname = ""; - if(stack != null) { - internalname = neu.manager.getInternalNameForItem(stack); - if(!neu.manager.getItemInformation().containsKey(internalname)) { - neu.manager.writeItemToFile(stack); - } - internalname += ":"+stack.stackSize; - } - recipe.addProperty(y[i/9]+x[j], internalname); - } - } - - JsonObject json = neu.manager.getJsonForItem(res); - json.add("recipe", recipe); - json.addProperty("internalname", resInternalname); - json.addProperty("clickcommand", "viewrecipe"); - json.addProperty("modver", NotEnoughUpdates.VERSION); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname)); - neu.manager.writeJsonDefaultDir(json, resInternalname+".json"); - neu.manager.loadItem(resInternalname);*/ - } catch (Exception e) { - e.printStackTrace(); - } - } - }, 200, TimeUnit.MILLISECONDS); - } - } - } - - /*@SubscribeEvent - public void onPlayerInteract(EntityInteractEvent event) { - if(!event.isCanceled() && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && - Minecraft.getMinecraft().thePlayer.isSneaking() && - Minecraft.getMinecraft().ingameGUI != null) { - if(event.target instanceof EntityPlayer) { - for(NetworkPlayerInfo info : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { - String name = Minecraft.getMinecraft().ingameGUI.getTabList().getPlayerName(info); - if(name.contains("Status: "+EnumChatFormatting.RESET+EnumChatFormatting.BLUE+"Guest")) { - NotEnoughUpdates.INSTANCE.sendChatMessage("/trade " + event.target.getName()); - event.setCanceled(true); - break; - } - } - } - } - }*/ - - private IChatComponent processChatComponent(IChatComponent chatComponent) { - IChatComponent newComponent; - if (chatComponent instanceof ChatComponentText) { - ChatComponentText text = (ChatComponentText) chatComponent; - - newComponent = new ChatComponentText(processText(text.getUnformattedTextForChat())); - newComponent.setChatStyle(text.getChatStyle().createShallowCopy()); - - for (IChatComponent sibling : text.getSiblings()) { - newComponent.appendSibling(processChatComponent(sibling)); - } - } else if (chatComponent instanceof ChatComponentTranslation) { - ChatComponentTranslation trans = (ChatComponentTranslation) chatComponent; - - Object[] args = trans.getFormatArgs(); - Object[] newArgs = new Object[args.length]; - for (int i = 0; i < trans.getFormatArgs().length; i++) { - if (args[i] instanceof IChatComponent) { - newArgs[i] = processChatComponent((IChatComponent) args[i]); - } else { - newArgs[i] = args[i]; - } - } - newComponent = new ChatComponentTranslation(trans.getKey(), newArgs); - - for (IChatComponent sibling : trans.getSiblings()) { - newComponent.appendSibling(processChatComponent(sibling)); - } - } else { - newComponent = chatComponent.createCopy(); - } - - return newComponent; - } - - private String processText(String text) { - if (SBInfo.getInstance().getLocation() == null) return text; - if (!SBInfo.getInstance().getLocation().startsWith("mining_") && - !SBInfo.getInstance().getLocation().equals("crystal_hollows")) - return text; - - if (Minecraft.getMinecraft().thePlayer == null) return text; - if (!NotEnoughUpdates.INSTANCE.config.mining.drillFuelBar) return text; - - return Utils.trimIgnoreColour(text.replaceAll(EnumChatFormatting.DARK_GREEN + "\\S+ Drill Fuel", "")); - } - - private IChatComponent replaceSocialControlsWithPV(IChatComponent chatComponent) { - - if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 > 0 && chatComponent.getChatStyle() != null && - chatComponent.getChatStyle().getChatClickEvent() != null && - chatComponent.getChatStyle().getChatClickEvent().getAction() == ClickEvent.Action.RUN_COMMAND && - NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { - if (chatComponent.getChatStyle().getChatClickEvent().getValue().startsWith("/socialoptions")) { - String username = chatComponent.getChatStyle().getChatClickEvent().getValue().substring(15); - if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 == 1) { - chatComponent.setChatStyle(Utils.createClickStyle( - ClickEvent.Action.RUN_COMMAND, - "/pv " + username, - "" + EnumChatFormatting.YELLOW + "Click to open " + EnumChatFormatting.AQUA + EnumChatFormatting.BOLD + - username + EnumChatFormatting.RESET + EnumChatFormatting.YELLOW + "'s profile in " + - EnumChatFormatting.DARK_PURPLE + EnumChatFormatting.BOLD + "NEU's" + EnumChatFormatting.RESET + - EnumChatFormatting.YELLOW + " profile viewer." - )); - return chatComponent; - } else if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 == 2) { - chatComponent.setChatStyle(Utils.createClickStyle( - ClickEvent.Action.RUN_COMMAND, - "/ah " + username, - "" + EnumChatFormatting.YELLOW + "Click to open " + EnumChatFormatting.AQUA + EnumChatFormatting.BOLD + - username + EnumChatFormatting.RESET + EnumChatFormatting.YELLOW + "'s /ah page" - )); - return chatComponent; - } - } // wanted to add this for guild but guild uses uuid :sad: - } - return chatComponent; - } - - /** - * 1) When receiving "You are playing on profile" messages, will set the current profile. - * 2) When a /viewrecipe command fails (i.e. player does not have recipe unlocked, will open the custom recipe GUI) - * 3) Replaces lobby join notifications when streamer mode is active - */ - @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true) - public void onGuiChat(ClientChatReceivedEvent e) { - if (e.type == 2) { - CrystalMetalDetectorSolver.process(e.message); - e.message = processChatComponent(e.message); - return; - } else if (e.type == 0) { - e.message = replaceSocialControlsWithPV(e.message); - } - - DungeonWin.onChatMessage(e); - - String r = null; - 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 - .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 - .substring("Your profile was changed to: ".length()) - .split(" ")[0].trim()); - } else if (unformatted.startsWith("Your new API key is ")) { - NotEnoughUpdates.INSTANCE.config.apiKey.apiKey = unformatted.substring("Your new API key is ".length()); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + - "[NEU] API Key automatically configured")); - NotEnoughUpdates.INSTANCE.config.apiKey.apiKey = NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.substring(0, 36); - } else if (unformatted.startsWith("Player List Info is now disabled!")) { - SBInfo.getInstance().hasNewTab = false; - } else if (unformatted.startsWith("Player List Info is now enabled!")) { - SBInfo.getInstance().hasNewTab = true; - } - if (e.message.getFormattedText().equals(EnumChatFormatting.RESET.toString() + - EnumChatFormatting.RED + "You haven't unlocked this recipe!" + EnumChatFormatting.RESET)) { - r = EnumChatFormatting.RED + "You haven't unlocked this recipe!"; - } else if (e.message.getFormattedText().startsWith(EnumChatFormatting.RESET.toString() + - EnumChatFormatting.RED + "Invalid recipe ")) { - r = ""; - } else if (unformatted.equals(" NICE! SLAYER BOSS SLAIN!")) { - SlayerOverlay.isSlain = true; - } else if (unformatted.equals(" SLAYER QUEST STARTED!")) { - SlayerOverlay.isSlain = false; - if (timeSinceLastBoss == 0) { - SlayerOverlay.timeSinceLastBoss = System.currentTimeMillis(); - } else { - timeSinceLastBoss2 = timeSinceLastBoss; - timeSinceLastBoss = System.currentTimeMillis(); - } - } else if (unformatted.startsWith(" RNGesus Meter:")) { - RNGMeter = unformatted.substring(" RNGesus Meter: -------------------- ".length()); - } else if (matcher.matches()) { - //matcher.group(1); - SlayerOverlay.slayerLVL = matcher.group(2); - if (!SlayerOverlay.slayerLVL.equals("9")) { - SlayerOverlay.slayerXp = matcher.group(3); - } else { - slayerXp = "maxed"; - } - } else if (unformatted.startsWith("Sending to server") || - (unformatted.startsWith("Your Slayer Quest has been cancelled!"))) { - SlayerOverlay.slayerQuest = false; - SlayerOverlay.unloadOverlayTimer = System.currentTimeMillis(); - } - if (e.message - .getFormattedText() - .contains(EnumChatFormatting.YELLOW + "Visit the Auction House to collect your item!")) { - if (NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid != null && - System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBidMillis < 5000) { - NotEnoughUpdates.INSTANCE.sendChatMessage("/viewauction " + - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.niceAucId( - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid)); - } - } - if (r != null) { - if (neu.manager.failViewItem(r)) { - e.setCanceled(true); - } - missingRecipe.set(true); - } - //System.out.println(e.message); - if (unformatted.startsWith("Sending to server") && - neu.isOnSkyblock() && NotEnoughUpdates.INSTANCE.config.misc.streamerMode && - e.message instanceof ChatComponentText) { - String m = e.message.getFormattedText(); - String m2 = StreamerMode.filterChat(e.message.getFormattedText()); - if (!m.equals(m2)) { - e.message = new ChatComponentText(m2); - } - } - if (unformatted.startsWith("You found ") && SBInfo.getInstance().getLocation() != null && - SBInfo.getInstance().getLocation().equals("crystal_hollows")) { - CrystalMetalDetectorSolver.reset(true); - } - if (unformatted.startsWith("[NPC] Keeper of ") | unformatted.startsWith("[NPC] Professor Robot: ") || - unformatted.startsWith(" ") || unformatted.startsWith("✦") || - unformatted.equals(" You've earned a Crystal Loot Bundle!")) - OverlayManager.crystalHollowOverlay.message(unformatted); - } - - public static boolean drawingGuiScreen = false; - - /** - * Sets hoverInv and focusInv variables, representing whether the NEUOverlay should render behind the inventory when - * (hoverInv == true) and whether mouse/kbd inputs shouldn't be sent to NEUOverlay (focusInv == true). - *

- * If hoverInv is true, will render the overlay immediately (resulting in the inventory being drawn over the GUI) - * If hoverInv is false, the overlay will render in #onGuiScreenDraw (resulting in the GUI being drawn over the inv) - *

- * All of this only matters if players are using gui scale auto which may result in the inventory being drawn - * over the various panes. - */ - @SubscribeEvent - public void onGuiBackgroundDraw(GuiScreenEvent.BackgroundDrawnEvent event) { - if (showNotificationOverInv) { - - renderNotification(); - - } - if ((shouldRenderOverlay(event.gui) || event.gui instanceof CustomAHGui) && neu.isOnSkyblock()) { - ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); - int width = scaledresolution.getScaledWidth(); - - boolean hoverPane = event.getMouseX() < width * neu.overlay.getInfoPaneOffsetFactor() || - event.getMouseX() > width * neu.overlay.getItemPaneOffsetFactor(); - - if (event.gui instanceof GuiContainer) { - try { - int xSize = ((GuiContainer) event.gui).xSize; - int ySize = ((GuiContainer) event.gui).ySize; - int guiLeft = ((GuiContainer) event.gui).guiLeft; - int guiTop = ((GuiContainer) event.gui).guiTop; - - hoverInv = event.getMouseX() > guiLeft && event.getMouseX() < guiLeft + xSize && - event.getMouseY() > guiTop && event.getMouseY() < guiTop + ySize; - - if (hoverPane) { - if (!hoverInv) focusInv = false; - } else { - focusInv = true; - } - } catch (NullPointerException npe) { - focusInv = !hoverPane; - } - } - if (event.gui instanceof GuiItemRecipe) { - GuiItemRecipe guiItemRecipe = ((GuiItemRecipe) event.gui); - hoverInv = event.getMouseX() > guiItemRecipe.guiLeft && - event.getMouseX() < guiItemRecipe.guiLeft + guiItemRecipe.xSize && - event.getMouseY() > guiItemRecipe.guiTop && event.getMouseY() < guiItemRecipe.guiTop + guiItemRecipe.ySize; - - if (hoverPane) { - if (!hoverInv) focusInv = false; - } else { - focusInv = true; - } - } - if (focusInv) { - try { - neu.overlay.render(hoverInv); - } catch (ConcurrentModificationException e) { - e.printStackTrace(); - } - GL11.glTranslatef(0, 0, 10); - } - if (hoverInv) { - renderDungeonChestOverlay(event.gui); - if (NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) { - AccessoryBagOverlay.renderOverlay(); - } - } - } - - drawingGuiScreen = true; - } - - private boolean doInventoryButtons = false; - - @SubscribeEvent - public void onGuiScreenDrawPre(GuiScreenEvent.DrawScreenEvent.Pre event) { - doInventoryButtons = false; - - if (AuctionSearchOverlay.shouldReplace()) { - AuctionSearchOverlay.render(); - event.setCanceled(true); - return; - } - if (RancherBootOverlay.shouldReplace()) { - RancherBootOverlay.render(); - event.setCanceled(true); - return; - } - - String containerName = null; - GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; - if (guiScreen instanceof GuiChest) { - GuiChest eventGui = (GuiChest) guiScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - } - - if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) { - GuiCustomEnchant.getInstance().render(event.renderPartialTicks); - event.setCanceled(true); - return; - } - - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); - boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); - boolean customAhActive = - event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); - - if (storageOverlayActive) { - StorageOverlay.getInstance().render(); - event.setCanceled(true); - return; - } - - if (tradeWindowActive || customAhActive) { - event.setCanceled(true); - - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int width = scaledResolution.getScaledWidth(); - int height = scaledResolution.getScaledHeight(); - - //Dark background - Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680); - - if (event.mouseX < width * neu.overlay.getWidthMult() / 3 || - event.mouseX > width - width * neu.overlay.getWidthMult() / 3) { - if (customAhActive) { - neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY); - } else if (tradeWindowActive) { - TradeWindow.render(event.mouseX, event.mouseY); - } - neu.overlay.render(false); - } else { - neu.overlay.render(false); - if (customAhActive) { - neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY); - } else if (tradeWindowActive) { - TradeWindow.render(event.mouseX, event.mouseY); - } - } - } - - if (CalendarOverlay.isEnabled() || event.isCanceled()) return; - if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) - && event.gui instanceof GuiContainer) { - doInventoryButtons = true; - - int zOffset = 50; - - GlStateManager.translate(0, 0, zOffset); - - int xSize = ((GuiContainer) event.gui).xSize; - int ySize = ((GuiContainer) event.gui).ySize; - int guiLeft = ((GuiContainer) event.gui).guiLeft; - int guiTop = ((GuiContainer) event.gui).guiTop; - - if (!NEUApi.disableInventoryButtons) { - for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { - if (!button.isActive()) continue; - if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; - - int x = guiLeft + button.x; - int y = guiTop + button.y; - if (button.anchorRight) { - x += xSize; - } - if (button.anchorBottom) { - y += ySize; - } - if (AccessoryBagOverlay.isInAccessoryBag()) { - if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { - x += 80 + 28; - } - } - if (NEUOverlay.isRenderingArmorHud()) { - if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) { - x -= 25; - } - } - if (NEUOverlay.isRenderingPetHud()) { - if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) { - x -= 25; - } - } - - GlStateManager.color(1, 1, 1, 1f); - - GlStateManager.enableDepth(); - GlStateManager.enableAlpha(); - Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR); - Utils.drawTexturedRect(x, y, 18, 18, - button.backgroundIndex * 18 / 256f, (button.backgroundIndex * 18 + 18) / 256f, - 18 / 256f, 36 / 256f, GL11.GL_NEAREST - ); - - if (button.icon != null && !button.icon.trim().isEmpty()) { - GuiInvButtonEditor.renderIcon(button.icon, x + 1, y + 1); - } - } - } - GlStateManager.translate(0, 0, -zOffset); - } - } - - private static boolean shouldRenderOverlay(Gui gui) { - boolean validGui = gui instanceof GuiContainer || gui instanceof GuiItemRecipe; - if (gui instanceof GuiChest) { - GuiChest eventGui = (GuiChest) gui; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - if (containerName.trim().equals("Fast Travel")) { - validGui = false; - } - } - return validGui; - } - - private static final ResourceLocation EDITOR = new ResourceLocation("notenoughupdates:invbuttons/editor.png"); - private NEUConfig.InventoryButton buttonHovered = null; - private long buttonHoveredMillis = 0; - public static boolean disableCraftingText = false; - - /** - * Will draw the NEUOverlay over the inventory if focusInv == false. (z-translation of 300 is so that NEUOverlay - * will draw over Items in the inventory (which render at a z value of about 250)) - */ - @SubscribeEvent - public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) { - drawingGuiScreen = false; - disableCraftingText = false; - - String containerName = null; - GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; - if (guiScreen instanceof GuiChest) { - GuiChest eventGui = (GuiChest) guiScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - - if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) - return; - } - - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); - boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); - boolean customAhActive = - event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); - - if (!(tradeWindowActive || storageOverlayActive || customAhActive)) { - if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { - GlStateManager.pushMatrix(); - if (!focusInv) { - GL11.glTranslatef(0, 0, 300); - neu.overlay.render(hoverInv && focusInv); - GL11.glTranslatef(0, 0, -300); - } - GlStateManager.popMatrix(); - } - } - - if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock() && !hoverInv) { - renderDungeonChestOverlay(event.gui); - if (NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) { - AccessoryBagOverlay.renderOverlay(); - } - } - - boolean hoveringButton = false; - if (!doInventoryButtons) return; - if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) && - event.gui instanceof GuiContainer) { - int xSize = ((GuiContainer) event.gui).xSize; - int ySize = ((GuiContainer) event.gui).ySize; - int guiLeft = ((GuiContainer) event.gui).guiLeft; - int guiTop = ((GuiContainer) event.gui).guiTop; - - if (!NEUApi.disableInventoryButtons) { - for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { - if (!button.isActive()) continue; - if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; - - int x = guiLeft + button.x; - int y = guiTop + button.y; - if (button.anchorRight) { - x += xSize; - } - if (button.anchorBottom) { - y += ySize; - } - if (AccessoryBagOverlay.isInAccessoryBag()) { - if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { - x += 80 + 28; - } - } - if (NEUOverlay.isRenderingArmorHud()) { - if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) { - x -= 25; - } - } - if (NEUOverlay.isRenderingPetHud()) { - if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) { - x -= 25; - } - } - - if (x - guiLeft >= 85 && x - guiLeft <= 115 && y - guiTop >= 4 && y - guiTop <= 25) { - disableCraftingText = true; - } - - if (event.mouseX >= x && event.mouseX <= x + 18 && - event.mouseY >= y && event.mouseY <= y + 18) { - hoveringButton = true; - long currentTime = System.currentTimeMillis(); - - if (buttonHovered != button) { - buttonHoveredMillis = currentTime; - buttonHovered = button; - } - - if (currentTime - buttonHoveredMillis > 600) { - String command = button.command.trim(); - if (!command.startsWith("/")) { - command = "/" + command; - } - - Utils.drawHoveringText(Lists.newArrayList("\u00a77" + command), event.mouseX, event.mouseY, - event.gui.width, event.gui.height, -1, Minecraft.getMinecraft().fontRendererObj - ); - } - } - } - } - } - if (!hoveringButton) buttonHovered = null; - - if (AuctionBINWarning.getInstance().shouldShow()) { - AuctionBINWarning.getInstance().render(); - } - } - - private void renderDungeonChestOverlay(GuiScreen gui) { - if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 3) return; - - if (gui instanceof GuiChest && NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc != 2) { - try { - int xSize = ((GuiContainer) gui).xSize; - int ySize = ((GuiContainer) gui).ySize; - int guiLeft = ((GuiContainer) gui).guiLeft; - int guiTop = ((GuiContainer) gui).guiTop; - - GuiChest eventGui = (GuiChest) gui; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - IInventory lower = cc.getLowerChestInventory(); - - ItemStack rewardChest = lower.getStackInSlot(31); - if (rewardChest != null && - rewardChest.getDisplayName().endsWith(EnumChatFormatting.GREEN + "Open Reward Chest")) { - int chestCost = 0; - try { - String line6 = Utils.cleanColour(neu.manager.getLoreFromNBT(rewardChest.getTagCompound())[6]); - StringBuilder cost = new StringBuilder(); - for (int i = 0; i < line6.length(); i++) { - char c = line6.charAt(i); - if ("0123456789".indexOf(c) >= 0) { - cost.append(c); - } - } - if (cost.length() > 0) { - chestCost = Integer.parseInt(cost.toString()); - } - } catch (Exception ignored) { - } - - String missingItem = null; - int totalValue = 0; - HashMap itemValues = new HashMap<>(); - for (int i = 0; i < 5; i++) { - ItemStack item = lower.getStackInSlot(11 + i); - String internal = neu.manager.getInternalNameForItem(item); - if (internal != null) { - internal = internal.replace("\u00CD", "I").replace("\u0130", "I"); - float bazaarPrice = -1; - JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal); - if (bazaarInfo != null && bazaarInfo.has("curr_sell")) { - bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat(); - } - if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000; - - float worth = -1; - if (bazaarPrice > 0) { - worth = bazaarPrice; - } else { - switch (NotEnoughUpdates.INSTANCE.config.dungeons.profitType) { - case 1: - worth = neu.manager.auctionManager.getItemAvgBin(internal); - break; - case 2: - JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); - if (auctionInfo != null) { - if (auctionInfo.has("clean_price")) { - worth = (int) auctionInfo.get("clean_price").getAsFloat(); - } else { - worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); - } - } - break; - default: - worth = neu.manager.auctionManager.getLowestBin(internal); - } - if (worth <= 0) { - worth = neu.manager.auctionManager.getLowestBin(internal); - if (worth <= 0) { - worth = neu.manager.auctionManager.getItemAvgBin(internal); - if (worth <= 0) { - JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); - if (auctionInfo != null) { - if (auctionInfo.has("clean_price")) { - worth = (int) auctionInfo.get("clean_price").getAsFloat(); - } else { - worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); - } - } - } - } - } - } - - if (worth > 0 && totalValue >= 0) { - totalValue += worth; - String display = item.getDisplayName(); - - if (display.contains("Enchanted Book")) { - NBTTagCompound tag = item.getTagCompound(); - if (tag != null && tag.hasKey("ExtraAttributes", 10)) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - NBTTagCompound enchants = ea.getCompoundTag("enchantments"); - - int highestLevel = -1; - for (String enchname : enchants.getKeySet()) { - int level = enchants.getInteger(enchname); - if (level > highestLevel) { - display = EnumChatFormatting.BLUE + WordUtils.capitalizeFully( - enchname.replace("_", " ") - .replace("Ultimate", "") - .trim()) + " " + level; - } - } - } - } - - itemValues.put(display, worth); - } else { - if (totalValue != -1) { - missingItem = internal; - } - totalValue = -1; - } - } - } - - NumberFormat format = NumberFormat.getInstance(Locale.US); - String valueStringBIN1; - String valueStringBIN2; - if (totalValue >= 0) { - valueStringBIN1 = EnumChatFormatting.YELLOW + "Value (BIN): "; - valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins"; - } else { - valueStringBIN1 = EnumChatFormatting.YELLOW + "Can't find BIN: "; - valueStringBIN2 = missingItem; - } - - int profitLossBIN = totalValue - chestCost; - - boolean kismetUsed = false; - // checking for kismet - Slot slot = (eventGui.inventorySlots.getSlot(50)); - if (slot.getHasStack()) { - String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(slot.getStack().getTagCompound()); - for (String line : lore) { - if (line.contains("You already rerolled a chest!")) { - kismetUsed = true; - break; - } - } - } - int kismetPrice = neu.manager.auctionManager.getLowestBin("KISMET_FEATHER"); - String kismetStr = EnumChatFormatting.RED + format.format(kismetPrice) + " coins"; - if (neu.config.dungeons.useKismetOnDungeonProfit) - profitLossBIN = kismetUsed ? profitLossBIN - kismetPrice : profitLossBIN; - - String profitPrefix = EnumChatFormatting.DARK_GREEN.toString(); - String lossPrefix = EnumChatFormatting.RED.toString(); - String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix; - - String plStringBIN; - if (profitLossBIN >= 0) { - plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins"; - } else { - plStringBIN = prefix + "-" + format.format(-profitLossBIN) + " coins"; - } - - if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 1 && !valueStringBIN2.equals(missingItem)) { - int w = Minecraft.getMinecraft().fontRendererObj.getStringWidth(plStringBIN); - GlStateManager.disableLighting(); - GlStateManager.translate(0, 0, 200); - Minecraft.getMinecraft().fontRendererObj.drawString(plStringBIN, guiLeft + xSize - 5 - w, guiTop + 5, - 0xffffffff, true - ); - GlStateManager.translate(0, 0, -200); - return; - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth); - GL11.glColor4f(1, 1, 1, 1); - GlStateManager.disableLighting(); - Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 180, 101, 0, 180 / 256f, 0, 101 / 256f, GL11.GL_NEAREST); - - Utils.renderAlignedString(valueStringBIN1, valueStringBIN2, - guiLeft + xSize + 4 + 10, guiTop + 14, 160 - ); - if (neu.config.dungeons.useKismetOnDungeonProfit && kismetUsed) { - Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Kismet Feather: ", kismetStr, - guiLeft + xSize + 4 + 10, guiTop + 24, 160 - ); - } - if (totalValue >= 0) { - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "Profit/Loss: ", - plStringBIN, - guiLeft + xSize + 4 + 10, - guiTop + (neu.config.dungeons.useKismetOnDungeonProfit ? (kismetUsed ? 34 : 24) : 24), - 160 - ); - } - - int index = 0; - for (Map.Entry entry : itemValues.entrySet()) { - Utils.renderAlignedString( - entry.getKey(), - prefix + - format.format(entry.getValue().intValue()), - guiLeft + xSize + 4 + 10, - guiTop + (neu.config.dungeons.useKismetOnDungeonProfit ? (kismetUsed ? 39 : 29) : 29) + (++index) * 10, - 160 - ); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - public void drawStringShadow(String str, float x, float y, int len) { - for (int xOff = -2; xOff <= 2; xOff++) { - for (int yOff = -2; yOff <= 2; yOff++) { - if (Math.abs(xOff) != Math.abs(yOff)) { - Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(str), - Minecraft.getMinecraft().fontRendererObj, - x + xOff / 2f, y + yOff / 2f, false, len, - new Color(20, 20, 20, 100 / Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB() - ); - } - } - } - - Utils.drawStringCenteredScaledMaxWidth(str, - Minecraft.getMinecraft().fontRendererObj, - x, y, false, len, - new Color(64, 64, 64, 255).getRGB() - ); - } - - /** - * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused. - * Will also cancel the event if if NEUOverlay#mouseInput returns true. - */ - @SubscribeEvent(priority = EventPriority.LOW) - public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) { - if (Mouse.getEventButtonState() && StorageManager.getInstance().onAnyClick()) { - event.setCanceled(true); - 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; - - if (AuctionBINWarning.getInstance().shouldShow()) { - AuctionBINWarning.getInstance().mouseInput(mouseX, mouseY); - event.setCanceled(true); - return; - } - - if (!event.isCanceled()) { - Utils.scrollTooltip(Mouse.getEventDWheel()); - } - if (AuctionSearchOverlay.shouldReplace()) { - AuctionSearchOverlay.mouseEvent(); - event.setCanceled(true); - return; - } - if (RancherBootOverlay.shouldReplace()) { - RancherBootOverlay.mouseEvent(); - event.setCanceled(true); - return; - } - - String containerName = null; - GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; - if (guiScreen instanceof GuiChest) { - GuiChest eventGui = (GuiChest) guiScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - if (containerName.contains(" Profile") && BetterContainers.profileViewerStackIndex != -1 && - eventGui.isMouseOverSlot(cc.inventorySlots.get(BetterContainers.profileViewerStackIndex), mouseX, mouseY) && - Mouse.getEventButton() >= 0) { - event.setCanceled(true); - if (Mouse.getEventButtonState() && eventGui.inventorySlots.inventorySlots.get(22).getStack() != null && - eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound() != null) { - NBTTagCompound tag = eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound(); - if (tag.hasKey("SkullOwner") && tag.getCompoundTag("SkullOwner").hasKey("Name")) { - String username = tag.getCompoundTag("SkullOwner").getString("Name"); - Utils.playPressSound(); - ViewProfileCommand.RUNNABLE.accept(new String[]{username}); - } - } - } - } - - if (GuiCustomEnchant.getInstance().shouldOverride(containerName) && - GuiCustomEnchant.getInstance().mouseInput(mouseX, mouseY)) { - event.setCanceled(true); - return; - } - - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); - boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); - boolean customAhActive = - event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); - - if (storageOverlayActive) { - if (StorageOverlay.getInstance().mouseInput(mouseX, mouseY)) { - event.setCanceled(true); - } - return; - } - - if (tradeWindowActive || customAhActive) { - event.setCanceled(true); - if (customAhActive) { - neu.manager.auctionManager.customAH.handleMouseInput(); - } else if (tradeWindowActive) { - TradeWindow.handleMouseInput(); - } - neu.overlay.mouseInput(); - return; - } - - if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { - if (!NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay || !AccessoryBagOverlay.mouseClick()) { - if (!(hoverInv && focusInv)) { - if (neu.overlay.mouseInput()) { - event.setCanceled(true); - } - } else { - neu.overlay.mouseInputInv(); - } - } - } - if (event.isCanceled()) return; - if (!doInventoryButtons) return; - if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) && - Mouse.getEventButton() >= 0 - && event.gui instanceof GuiContainer) { - int xSize = ((GuiContainer) event.gui).xSize; - int ySize = ((GuiContainer) event.gui).ySize; - int guiLeft = ((GuiContainer) event.gui).guiLeft; - int guiTop = ((GuiContainer) event.gui).guiTop; - if (!NEUApi.disableInventoryButtons) { - for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { - if (!button.isActive()) continue; - if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; - - int x = guiLeft + button.x; - int y = guiTop + button.y; - if (button.anchorRight) { - x += xSize; - } - if (button.anchorBottom) { - y += ySize; - } - if (AccessoryBagOverlay.isInAccessoryBag()) { - if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { - x += 80 + 28; - } - } - if (NEUOverlay.isRenderingArmorHud()) { - if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) { - x -= 25; - } - } - if (NEUOverlay.isRenderingPetHud()) { - if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) { - x -= 25; - } - } - - if (mouseX >= x && mouseX <= x + 18 && mouseY >= y && mouseY <= y + 18) { - if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { - int clickType = NotEnoughUpdates.INSTANCE.config.inventoryButtons.clickType; - if ((clickType == 0 && Mouse.getEventButtonState()) || (clickType == 1 && !Mouse.getEventButtonState())) { - String command = button.command.trim(); - if (!command.startsWith("/")) { - command = "/" + command; - } - if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, command) == 0) { - NotEnoughUpdates.INSTANCE.sendChatMessage(command); - } - } - } else { - event.setCanceled(true); - } - return; - } - } - } - } - } - - ScheduledExecutorService ses = Executors.newScheduledThreadPool(1); - - JsonObject essenceJson = new JsonObject(); - - /** - * Sends a kbd event to NEUOverlay, cancelling if NEUOverlay#keyboardInput returns true. - * Also includes a dev function used for creating custom named json files with recipes. - */ - @SubscribeEvent - public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) { - if (AuctionBINWarning.getInstance().shouldShow()) { - AuctionBINWarning.getInstance().keyboardInput(); - event.setCanceled(true); - return; - } - - if (AuctionSearchOverlay.shouldReplace()) { - AuctionSearchOverlay.keyEvent(); - event.setCanceled(true); - return; - } - if (RancherBootOverlay.shouldReplace()) { - RancherBootOverlay.keyEvent(); - event.setCanceled(true); - return; - } - - String containerName = null; - GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; - - if (guiScreen instanceof GuiChest) { - containerName = ((ContainerChest) ((GuiChest) guiScreen).inventorySlots) - .getLowerChestInventory() - .getDisplayName() - .getUnformattedText(); - } - - if (GuiCustomEnchant.getInstance().shouldOverride(containerName) && - GuiCustomEnchant.getInstance().keyboardInput()) { - event.setCanceled(true); - return; - } - - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); - boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); - boolean customAhActive = - event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); - - if (storageOverlayActive) { - if (StorageOverlay.getInstance().keyboardInput()) { - event.setCanceled(true); - return; - } - } - - if (tradeWindowActive || customAhActive) { - if (customAhActive) { - if (neu.manager.auctionManager.customAH.keyboardInput()) { - event.setCanceled(true); - Minecraft.getMinecraft().dispatchKeypresses(); - } else if (neu.overlay.keyboardInput(focusInv)) { - event.setCanceled(true); - } - } else if (tradeWindowActive) { - TradeWindow.keyboardInput(); - if (Keyboard.getEventKey() != Keyboard.KEY_ESCAPE) { - event.setCanceled(true); - Minecraft.getMinecraft().dispatchKeypresses(); - neu.overlay.keyboardInput(focusInv); - } - } - return; - } - - if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { - if (neu.overlay.keyboardInput(focusInv)) { - event.setCanceled(true); - } - } - if (NotEnoughUpdates.INSTANCE.config.hidden.dev && NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && - Minecraft.getMinecraft().theWorld != null && - Keyboard.getEventKey() == Keyboard.KEY_N && Keyboard.getEventKeyState()) { - GuiScreen gui = Minecraft.getMinecraft().currentScreen; - if (gui instanceof GuiChest) { - GuiChest eventGui = (GuiChest) event.gui; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - IInventory lower = cc.getLowerChestInventory(); - - if (!lower.getDisplayName().getUnformattedText().endsWith("Essence")) return; - - for (int i = 0; i < lower.getSizeInventory(); i++) { - ItemStack stack = lower.getStackInSlot(i); - - String internalname = neu.manager.getInternalNameForItem(stack); - if (internalname != null) { - String[] lore = neu.manager.getLoreFromNBT(stack.getTagCompound()); - - for (String line : lore) { - if (line.contains(":") && (line.startsWith("\u00A77Upgrade to") || - line.startsWith("\u00A77Convert to Dungeon Item"))) { - String[] split = line.split(":"); - String after = Utils.cleanColour(split[1]); - StringBuilder costS = new StringBuilder(); - for (char c : after.toCharArray()) { - if (c >= '0' && c <= '9') { - costS.append(c); - } - } - int cost = Integer.parseInt(costS.toString()); - String[] afterSplit = after.split(" "); - String type = afterSplit[afterSplit.length - 2]; - - if (!essenceJson.has(internalname)) { - essenceJson.add(internalname, new JsonObject()); - } - JsonObject obj = essenceJson.get(internalname).getAsJsonObject(); - obj.addProperty("type", type); - - if (line.startsWith("\u00A77Convert to Dungeon Item")) { - obj.addProperty("dungeonize", cost); - } else if (line.startsWith("\u00A77Upgrade to")) { - int stars = 0; - for (char c : line.toCharArray()) { - if (c == '\u272A') stars++; - } - if (stars > 0) { - obj.addProperty(stars + "", cost); - } - } - } - } - } - } - System.out.println(essenceJson); - } - } - if (NotEnoughUpdates.INSTANCE.config.hidden.dev && NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && - Minecraft.getMinecraft().theWorld != null && - Keyboard.getEventKey() == Keyboard.KEY_O && Keyboard.getEventKeyState()) { - GuiScreen gui = Minecraft.getMinecraft().currentScreen; - if (gui instanceof GuiChest) { - GuiChest eventGui = (GuiChest) event.gui; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - IInventory lower = cc.getLowerChestInventory(); - - if (lower.getStackInSlot(23) != null && - lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) { - ItemStack res = lower.getStackInSlot(25); - String resInternalname = neu.manager.getInternalNameForItem(res); - JTextField tf = new JTextField(); - tf.setText(resInternalname); - tf.addAncestorListener(new RequestFocusListener()); - JOptionPane.showOptionDialog(null, - tf, - "Enter Name:", - JOptionPane.NO_OPTION, - JOptionPane.PLAIN_MESSAGE, - null, new String[]{"Enter"}, "Enter" - ); - resInternalname = tf.getText(); - if (resInternalname.trim().length() == 0) { - return; - } - - JsonObject recipe = new JsonObject(); - - String[] x = {"1", "2", "3"}; - String[] y = {"A", "B", "C"}; - - for (int i = 0; i <= 18; i += 9) { - for (int j = 0; j < 3; j++) { - ItemStack stack = lower.getStackInSlot(10 + i + j); - String internalname = ""; - if (stack != null) { - internalname = neu.manager.getInternalNameForItem(stack); - if (!neu.manager.getItemInformation().containsKey(internalname)) { - neu.manager.writeItemToFile(stack); - } - internalname += ":" + stack.stackSize; - } - recipe.addProperty(y[i / 9] + x[j], internalname); - } - } - - JsonObject json = neu.manager.getJsonForItem(res); - json.add("recipe", recipe); - json.addProperty("internalname", resInternalname); - json.addProperty("clickcommand", "viewrecipe"); - json.addProperty("modver", NotEnoughUpdates.VERSION); - try { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname)); - neu.manager.writeJsonDefaultDir(json, resInternalname + ".json"); - neu.manager.loadItem(resInternalname); - } catch (IOException ignored) { - } - } - } - } - } - - private final HashSet percentStats = new HashSet<>(); - - { - percentStats.add("bonus_attack_speed"); - percentStats.add("crit_damage"); - percentStats.add("crit_chance"); - percentStats.add("sea_creature_chance"); - percentStats.add("ability_damage"); - } - - private String currentRarity = "COMMON"; - private boolean showReforgeStoneStats = true; - private boolean pressedArrowLast = false; - private boolean pressedShiftLast = false; - - private boolean copied = false; - - //just to try and optimize it a bit - private int sbaloaded = -1; - - private boolean isSbaloaded() { - if (sbaloaded == -1) { - if (Loader.isModLoaded("skyblockaddons")) { - sbaloaded = 1; - } else { - sbaloaded = 0; - } - } - return sbaloaded == 1; - } - - @SubscribeEvent(priority = EventPriority.LOW) - public void onItemTooltipLow(ItemTooltipEvent event) { - if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return; - - String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); - if (internalname == null) { - onItemToolTipInternalNameNull(event); - return; - } - - boolean hasEnchantments = - event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").hasKey("enchantments", 10); - Set enchantIds = new HashSet<>(); - if (hasEnchantments) - enchantIds = - event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").getCompoundTag("enchantments").getKeySet(); - - JsonObject enchantsConst = Constants.ENCHANTS; - JsonArray allItemEnchs = null; - Set ignoreFromPool = new HashSet<>(); - if (enchantsConst != null && hasEnchantments && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) { - try { - JsonArray enchantPools = enchantsConst.get("enchant_pools").getAsJsonArray(); - for (JsonElement element : enchantPools) { - Set currentPool = new HashSet<>(); - for (JsonElement poolElement : element.getAsJsonArray()) { - String poolS = poolElement.getAsString(); - currentPool.add(poolS); - } - for (JsonElement poolElement : element.getAsJsonArray()) { - String poolS = poolElement.getAsString(); - if (enchantIds.contains(poolS)) { - ignoreFromPool.addAll(currentPool); - break; - } - } - } - - JsonObject enchantsObj = enchantsConst.get("enchants").getAsJsonObject(); - NBTTagCompound tag = event.itemStack.getTagCompound(); - if (tag != null) { - NBTTagCompound display = tag.getCompoundTag("display"); - if (display.hasKey("Lore", 9)) { - NBTTagList list = display.getTagList("Lore", 8); - out: - for (int i = list.tagCount(); i >= 0; i--) { - String line = list.getStringTagAt(i); - for (int j = 0; j < Utils.rarityArrC.length; j++) { - for (Map.Entry entry : enchantsObj.entrySet()) { - if (line.contains(Utils.rarityArrC[j] + " " + entry.getKey()) || - line.contains(Utils.rarityArrC[j] + " DUNGEON " + entry.getKey())) { - allItemEnchs = entry.getValue().getAsJsonArray(); - break out; - } - } - } - } - } - } - } catch (Exception ignored) { - } - } - - boolean gotToEnchants = false; - boolean passedEnchants = false; - - boolean dungeonProfit = false; - int index = 0; - List newTooltip = new ArrayList<>(); - - for (String line : event.toolTip) { - if (line.endsWith(EnumChatFormatting.DARK_GRAY + "Reforge Stone") && - NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showReforgeStats) { - JsonObject reforgeStones = Constants.REFORGESTONES; - - if (reforgeStones != null && reforgeStones.has(internalname)) { - boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); - if (!pressedShiftLast && shift) { - showReforgeStoneStats = !showReforgeStoneStats; - } - pressedShiftLast = shift; - - newTooltip.add(line); - newTooltip.add(""); - if (!showReforgeStoneStats) { - newTooltip.add(EnumChatFormatting.DARK_GRAY + "[Press SHIFT to show extra info]"); - } else { - newTooltip.add(EnumChatFormatting.DARK_GRAY + "[Press SHIFT to hide extra info]"); - } - - JsonObject reforgeInfo = reforgeStones.get(internalname).getAsJsonObject(); - JsonArray requiredRaritiesArray = reforgeInfo.get("requiredRarities").getAsJsonArray(); - - if (showReforgeStoneStats && requiredRaritiesArray.size() > 0) { - String reforgeName = Utils.getElementAsString(reforgeInfo.get("reforgeName"), ""); - - String[] requiredRarities = new String[requiredRaritiesArray.size()]; - for (int i = 0; i < requiredRaritiesArray.size(); i++) { - requiredRarities[i] = requiredRaritiesArray.get(i).getAsString(); - } - - int rarityIndex = requiredRarities.length - 1; - String rarity = requiredRarities[rarityIndex]; - for (int i = 0; i < requiredRarities.length; i++) { - String rar = requiredRarities[i]; - if (rar.equalsIgnoreCase(currentRarity)) { - rarity = rar; - rarityIndex = i; - break; - } - } - - boolean left = Keyboard.isKeyDown(Keyboard.KEY_LEFT); - boolean right = Keyboard.isKeyDown(Keyboard.KEY_RIGHT); - if (!pressedArrowLast && (left || right)) { - if (left) { - rarityIndex--; - } else if (right) { - rarityIndex++; - } - if (rarityIndex < 0) rarityIndex = 0; - if (rarityIndex >= requiredRarities.length) rarityIndex = requiredRarities.length - 1; - currentRarity = requiredRarities[rarityIndex]; - rarity = currentRarity; - } - pressedArrowLast = left || right; - - JsonElement statsE = reforgeInfo.get("reforgeStats"); - - String rarityFormatted = Utils.rarityArrMap.getOrDefault(rarity, rarity); - - JsonElement reforgeAbilityE = reforgeInfo.get("reforgeAbility"); - String reforgeAbility = null; - if (reforgeAbilityE != null) { - if (reforgeAbilityE.isJsonPrimitive() && reforgeAbilityE.getAsJsonPrimitive().isString()) { - reforgeAbility = Utils.getElementAsString(reforgeInfo.get("reforgeAbility"), ""); - - } else if (reforgeAbilityE.isJsonObject()) { - if (reforgeAbilityE.getAsJsonObject().has(rarity)) { - reforgeAbility = reforgeAbilityE.getAsJsonObject().get(rarity).getAsString(); - } - } - } - - if (reforgeAbility != null && !reforgeAbility.isEmpty()) { - String text = EnumChatFormatting.BLUE + (reforgeName.isEmpty() ? "Bonus: " : reforgeName + " Bonus: ") + - EnumChatFormatting.GRAY + reforgeAbility; - boolean first = true; - for (String s : Minecraft.getMinecraft().fontRendererObj.listFormattedStringToWidth(text, 150)) { - newTooltip.add((first ? "" : " ") + s); - first = false; - } - newTooltip.add(""); - } - - newTooltip.add(EnumChatFormatting.BLUE + "Stats for " + rarityFormatted + - "\u00a79: [\u00a7l\u00a7m< \u00a79Switch\u00a7l\u27a1\u00a79]"); - - if (statsE != null && statsE.isJsonObject()) { - JsonObject stats = statsE.getAsJsonObject(); - - JsonElement statsRarE = stats.get(rarity); - if (statsRarE != null && statsRarE.isJsonObject()) { - - JsonObject statsRar = statsRarE.getAsJsonObject(); - - TreeSet> sorted = new TreeSet<>(Map.Entry.comparingByKey()); - sorted.addAll(statsRar.entrySet()); - - for (Map.Entry entry : sorted) { - if (entry.getValue().isJsonPrimitive() && ((JsonPrimitive) entry.getValue()).isNumber()) { - float statNumF = entry.getValue().getAsFloat(); - String statNumS; - if (statNumF % 1 == 0) { - statNumS = String.valueOf(Math.round(statNumF)); - } else { - statNumS = Utils.floatToString(statNumF, 1); - } - String reforgeNamePretty = WordUtils.capitalizeFully(entry.getKey().replace("_", " ")); - String text = - EnumChatFormatting.GRAY + reforgeNamePretty + ": " + EnumChatFormatting.GREEN + "+" + statNumS; - if (percentStats.contains(entry.getKey())) { - text += "%"; - } - newTooltip.add(" " + text); - } - } - } - } - - JsonElement reforgeCostsE = reforgeInfo.get("reforgeCosts"); - int reforgeCost = -1; - if (reforgeCostsE != null) { - if (reforgeCostsE.isJsonPrimitive() && reforgeCostsE.getAsJsonPrimitive().isNumber()) { - reforgeCost = (int) Utils.getElementAsFloat(reforgeInfo.get("reforgeAbility"), -1); - - } else if (reforgeCostsE.isJsonObject()) { - if (reforgeCostsE.getAsJsonObject().has(rarity)) { - reforgeCost = (int) Utils.getElementAsFloat(reforgeCostsE.getAsJsonObject().get(rarity), -1); - } - } - } - - if (reforgeCost >= 0) { - String text = EnumChatFormatting.BLUE + "Apply Cost: " + EnumChatFormatting.GOLD + - NumberFormat.getNumberInstance().format(reforgeCost) + " coins"; - newTooltip.add(""); - newTooltip.add(text); - } - - } - - continue; - } - - } else if (line.contains("\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune")) { - line = line.replace( - "\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune", - Utils.chromaString("Rainbow Rune", index, false) + EnumChatFormatting.BLUE - ); - } else if (hasEnchantments) { - if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && - NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) { - boolean lineHasEnch = false; - for (String s : enchantIds) { - String enchantName = WordUtils.capitalizeFully(s.replace("_", " ")); - if (line.contains(enchantName)) { - lineHasEnch = true; - break; - } - } - if (lineHasEnch) { - gotToEnchants = true; - } else { - if (gotToEnchants && !passedEnchants && Utils.cleanColour(line).trim().length() == 0) { - if (enchantsConst != null && allItemEnchs != null) { - List missing = new ArrayList<>(); - for (JsonElement enchIdElement : allItemEnchs) { - String enchId = enchIdElement.getAsString(); - if (!enchId.startsWith("ultimate_") && !ignoreFromPool.contains(enchId) && - !enchantIds.contains(enchId)) { - missing.add(enchId); - } - } - if (!missing.isEmpty()) { - newTooltip.add(""); - StringBuilder currentLine = - new StringBuilder(EnumChatFormatting.RED + "Missing: " + EnumChatFormatting.GRAY); - for (int i = 0; i < missing.size(); i++) { - String enchName = WordUtils.capitalizeFully(missing.get(i).replace("_", " ")); - if (currentLine.length() != 0 && - (Utils.cleanColour(currentLine.toString()).length() + enchName.length()) > 40) { - newTooltip.add(currentLine.toString()); - currentLine = new StringBuilder(); - } - if (currentLine.length() != 0 && i != 0) { - currentLine.append(", ").append(enchName); - } else { - currentLine.append(EnumChatFormatting.GRAY).append(enchName); - } - } - if (currentLine.length() != 0) { - newTooltip.add(currentLine.toString()); - } - } - } - passedEnchants = true; - } - } - } - for (String op : NotEnoughUpdates.INSTANCE.config.hidden.enchantColours) { - List colourOps = GuiEnchantColour.splitter.splitToList(op); - String enchantName = GuiEnchantColour.getColourOpIndex(colourOps, 0); - String comparator = GuiEnchantColour.getColourOpIndex(colourOps, 1); - String comparison = GuiEnchantColour.getColourOpIndex(colourOps, 2); - String colourCode = GuiEnchantColour.getColourOpIndex(colourOps, 3); - String modifier = GuiEnchantColour.getColourOpIndex(colourOps, 4); - - int modifierI = GuiEnchantColour.getIntModifier(modifier); - - if (enchantName.length() == 0) continue; - if (comparator.length() == 0) continue; - if (comparison.length() == 0) continue; - if (colourCode.length() == 0) continue; - - int comparatorI = ">=<".indexOf(comparator.charAt(0)); - - int levelToFind = -1; - try { - levelToFind = Integer.parseInt(comparison); - } catch (Exception e) { - continue; - } - - if (comparatorI < 0) continue; - String regexText = "0123456789abcdefz"; - if (isSbaloaded()) { - regexText = regexText + "Z"; - } - - if (regexText.indexOf(colourCode.charAt(0)) < 0) continue; - - //item_lore = item_lore.replaceAll("\\u00A79("+lvl4Max+" IV)", EnumChatFormatting.DARK_PURPLE+"$1"); - //9([a-zA-Z ]+?) ([0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X))(,|$) - Pattern pattern; - try { - pattern = Pattern.compile("(\\u00A79|\\u00A7(9|l)\\u00A7d\\u00A7l)(?" + enchantName + ") " + - "(?[0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV|XVI|XVII|XVIII|XIX|XX))((\\u00A79)?,|( \\u00A78(?:,?[0-9]+)*)?$)"); - } catch (Exception e) { - continue; - } //malformed regex - Matcher matcher = pattern.matcher(line); - int matchCount = 0; - while (matcher.find() && matchCount < 5) { - if (Utils.cleanColour(matcher.group("enchantName")).startsWith(" ")) continue; - - matchCount++; - int level = -1; - String levelStr = matcher.group("level"); - if (levelStr == null) continue; - try { - level = Integer.parseInt(levelStr); - } catch (Exception e) { - switch (levelStr) { - case "I": - level = 1; - break; - case "II": - level = 2; - break; - case "III": - level = 3; - break; - case "IV": - level = 4; - break; - case "V": - level = 5; - break; - case "VI": - level = 6; - break; - case "VII": - level = 7; - break; - case "VIII": - level = 8; - break; - case "IX": - level = 9; - break; - case "X": - level = 10; - break; - case "XI": - level = 11; - break; - case "XII": - level = 12; - break; - case "XIII": - level = 13; - break; - case "XIV": - level = 14; - break; - case "XV": - level = 15; - break; - case "XVI": - level = 16; - break; - case "XVII": - level = 17; - break; - case "XVIII": - level = 18; - break; - case "XIX": - level = 19; - break; - case "XX": - level = 20; - break; - } - } - boolean matches = false; - if (level > 0) { - switch (comparator) { - case ">": - matches = level > levelToFind; - break; - case "=": - matches = level == levelToFind; - break; - case "<": - matches = level < levelToFind; - break; - } - } - if (matches) { - String enchantText = matcher.group("enchantName"); - StringBuilder extraModifiersBuilder = new StringBuilder(); - - if ((modifierI & GuiEnchantColour.BOLD_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.BOLD); - } - if ((modifierI & GuiEnchantColour.ITALIC_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.ITALIC); - } - if ((modifierI & GuiEnchantColour.UNDERLINE_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.UNDERLINE); - } - if ((modifierI & GuiEnchantColour.OBFUSCATED_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.OBFUSCATED); - } - if ((modifierI & GuiEnchantColour.STRIKETHROUGH_MODIFIER) != 0) { - extraModifiersBuilder.append(EnumChatFormatting.STRIKETHROUGH); - } - - String extraMods = extraModifiersBuilder.toString(); - - if (!colourCode.equals("z")) { - line = line.replace( - "\u00A79" + enchantText, - "\u00A7" + colourCode + extraMods + enchantText - ); - line = line.replace( - "\u00A79\u00A7d\u00A7l" + enchantText, - "\u00A7" + colourCode + extraMods + enchantText - ); - line = line.replace( - "\u00A7l\u00A7d\u00A7l" + enchantText, - "\u00A7" + colourCode + extraMods + enchantText - ); - } else { - int offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( - "\\u00A79" + enchantText + ".*", "")); - line = - line.replace("\u00A79" + enchantText, Utils.chromaString(enchantText, offset / 12f + index, false)); - - offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( - "\\u00A79\\u00A7d\\u00A7l" + enchantText + ".*", "")); - line = line.replace("\u00A79\u00A7d\u00A7l" + enchantText, Utils.chromaString(enchantText, - offset / 12f + index, true - )); - offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( - "\\u00A7l\\u00A7d\\u00A7l" + enchantText + ".*", "")); - line = line.replace("\u00A7l\u00A7d\u00A7l" + enchantText, Utils.chromaString(enchantText, - offset / 12f + index, true - )); - } - } - } - } - } - - newTooltip.add(line); - - if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoAucItem) { - if (line.contains(EnumChatFormatting.GRAY + "Buy it now: ") || - line.contains(EnumChatFormatting.GRAY + "Bidder: ") || - line.contains(EnumChatFormatting.GRAY + "Starting bid: ")) { - - if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { - newTooltip.add(""); - newTooltip.add(EnumChatFormatting.GRAY + "[SHIFT for Price Info]"); - } else { - ItemPriceInformation.addToTooltip(newTooltip, internalname, event.itemStack); - } - } - } - - if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 2 && - Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - if (line.contains(EnumChatFormatting.GREEN + "Open Reward Chest")) { - dungeonProfit = true; - } else if (index == 7 && dungeonProfit) { - GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - IInventory lower = cc.getLowerChestInventory(); - - int chestCost = 0; - try { - String line6 = Utils.cleanColour(line); - StringBuilder cost = new StringBuilder(); - for (int i = 0; i < line6.length(); i++) { - char c = line6.charAt(i); - if ("0123456789".indexOf(c) >= 0) { - cost.append(c); - } - } - if (cost.length() > 0) { - chestCost = Integer.parseInt(cost.toString()); - } - } catch (Exception ignored) { - } - - String missingItem = null; - int totalValue = 0; - HashMap itemValues = new HashMap<>(); - for (int i = 0; i < 5; i++) { - ItemStack item = lower.getStackInSlot(11 + i); - String internal = neu.manager.getInternalNameForItem(item); - if (internal != null) { - internal = internal.replace("\u00CD", "I").replace("\u0130", "I"); - float bazaarPrice = -1; - JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal); - if (bazaarInfo != null && bazaarInfo.has("curr_sell")) { - bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat(); - } - if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000; - - float worth = -1; - if (bazaarPrice > 0) { - worth = bazaarPrice; - } else { - switch (NotEnoughUpdates.INSTANCE.config.dungeons.profitType) { - case 1: - worth = neu.manager.auctionManager.getItemAvgBin(internal); - break; - case 2: - JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); - if (auctionInfo != null) { - if (auctionInfo.has("clean_price")) { - worth = (int) auctionInfo.get("clean_price").getAsFloat(); - } else { - worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); - } - } - break; - default: - worth = neu.manager.auctionManager.getLowestBin(internal); - } - if (worth <= 0) { - worth = neu.manager.auctionManager.getLowestBin(internal); - if (worth <= 0) { - worth = neu.manager.auctionManager.getItemAvgBin(internal); - if (worth <= 0) { - JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); - if (auctionInfo != null) { - if (auctionInfo.has("clean_price")) { - worth = (int) auctionInfo.get("clean_price").getAsFloat(); - } else { - worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); - } - } - } - } - } - } - - if (worth > 0 && totalValue >= 0) { - totalValue += worth; - - String display = item.getDisplayName(); - - if (display.contains("Enchanted Book")) { - NBTTagCompound tag = item.getTagCompound(); - if (tag != null && tag.hasKey("ExtraAttributes", 10)) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - NBTTagCompound enchants = ea.getCompoundTag("enchantments"); - - int highestLevel = -1; - for (String enchname : enchants.getKeySet()) { - int level = enchants.getInteger(enchname); - if (level > highestLevel) { - display = EnumChatFormatting.BLUE + WordUtils.capitalizeFully( - enchname.replace("_", " ") - .replace("Ultimate", "") - .trim()) + " " + level; - } - } - } - } - - itemValues.put(display, worth); - } else { - if (totalValue != -1) { - missingItem = internal; - } - totalValue = -1; - } - } - } - - NumberFormat format = NumberFormat.getInstance(Locale.US); - String valueStringBIN1; - String valueStringBIN2; - if (totalValue >= 0) { - valueStringBIN1 = EnumChatFormatting.YELLOW + "Value (BIN): "; - valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins"; - } else { - valueStringBIN1 = EnumChatFormatting.YELLOW + "Can't find BIN: "; - valueStringBIN2 = missingItem; - } - - int profitLossBIN = totalValue - chestCost; - String profitPrefix = EnumChatFormatting.DARK_GREEN.toString(); - String lossPrefix = EnumChatFormatting.RED.toString(); - String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix; - - String plStringBIN; - if (profitLossBIN >= 0) { - plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins"; - } else { - plStringBIN = prefix + "-" + format.format(-profitLossBIN) + " coins"; - } - - String neu = EnumChatFormatting.YELLOW + "[NEU] "; - - newTooltip.add(neu + valueStringBIN1 + " " + valueStringBIN2); - if (totalValue >= 0) { - newTooltip.add(neu + EnumChatFormatting.YELLOW + "Profit/Loss: " + plStringBIN); - } - - for (Map.Entry entry : itemValues.entrySet()) { - newTooltip.add(neu + entry.getKey() + prefix + "+" + - format.format(entry.getValue().intValue())); - } - } - } - - index++; - } - - for (int i = newTooltip.size() - 1; i >= 0; i--) { - String line = Utils.cleanColour(newTooltip.get(i)); - for (int i1 = 0; i1 < Utils.rarityArr.length; i1++) { - if (line.equals(Utils.rarityArr[i1])) { - if (i - 2 < 0) { - break; - } - newTooltip.addAll(i - 1, petToolTipXPExtend(event)); - break; - } - } - } - - pressedShiftLast = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); - pressedArrowLast = Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_RIGHT); - - event.toolTip.clear(); - event.toolTip.addAll(newTooltip); - - HashMap> loreBuckets = new HashMap<>(); - - List hypixelOrder = new ArrayList<>(); - - hypixelOrder.add("attributes"); - hypixelOrder.add("enchants"); - hypixelOrder.add("ability"); - hypixelOrder.add("reforge_bonus"); - hypixelOrder.add("rarity"); - - if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoInvItem) { - ItemPriceInformation.addToTooltip(event.toolTip, internalname, event.itemStack); - } - - if (event.itemStack.getTagCompound() != null && event.itemStack.getTagCompound().getBoolean("NEUHIDEPETTOOLTIP") && - NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip) { - event.toolTip.clear(); - } - } - - private final Pattern xpLevelPattern = Pattern.compile("(.*) (\\xA7e(.*)\\xA76/\\xA7e(.*))"); - - private void onItemToolTipInternalNameNull(ItemTooltipEvent event) { - petToolTipXPExtendPetMenu(event); - } - - private List petToolTipXPExtend(ItemTooltipEvent event) { - List tooltipText = new ArrayList<>(); - if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) { - if (event.itemStack.getTagCompound().hasKey("DisablePetExp")) { - if (event.itemStack.getTagCompound().getBoolean("DisablePetExp")) { - return tooltipText; - } - } - //7 is just a random number i chose, prob no pets with less lines than 7 - if (event.toolTip.size() > 7) { - if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) { - - GuiProfileViewer.PetLevel petlevel = null; - - //this is the item itself - NBTTagCompound tag = event.itemStack.getTagCompound(); - if (tag.hasKey("ExtraAttributes")) { - if (tag.getCompoundTag("ExtraAttributes").hasKey("petInfo")) { - JsonObject petInfo = NotEnoughUpdates.INSTANCE.manager.gson.fromJson( - tag.getCompoundTag("ExtraAttributes").getString("petInfo"), JsonObject.class); - if (petInfo.has("exp") && petInfo.get("exp").isJsonPrimitive()) { - JsonPrimitive exp = petInfo.getAsJsonPrimitive("exp"); - String petName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); - //Utils.getRarityFromInt(Utils.checkItemTypePet(event.toolTip))).getAsInt(); - petlevel = GuiProfileViewer.getPetLevel( - petName, - Utils.getRarityFromInt(Utils.checkItemTypePet(event.toolTip)), - exp.getAsLong() - ); - } - } - } - - if (petlevel != null) { - tooltipText.add(""); - if (petlevel.totalXp > petlevel.maxXP) { - tooltipText.add(EnumChatFormatting.AQUA + "" + EnumChatFormatting.BOLD + "MAX LEVEL"); - } else { - tooltipText.add( - EnumChatFormatting.GRAY + "Progress to Level " + (int) Math.floor(petlevel.level + 1) + ": " + - EnumChatFormatting.YELLOW + Utils.round(petlevel.levelPercentage * 100, 1) + "%"); - int levelpercentage = Math.round(petlevel.levelPercentage * 20); - tooltipText.add( - EnumChatFormatting.DARK_GREEN + String.join("", Collections.nCopies(levelpercentage, "-")) + - EnumChatFormatting.WHITE + String.join("", Collections.nCopies(20 - levelpercentage, "-"))); - tooltipText.add( - EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.levelXp) + - EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + - myFormatter.format(petlevel.currentLevelRequirement) + " EXP"); - } - } - } - } - } - return tooltipText; - } - - private static final String petToolTipRegex = - "((Farming)|(Combat)|(Fishing)|(Mining)|(Foraging)|(Enchanting)|(Alchemy)) ((Mount)|(Pet)|(Morph)).*"; - - private void petToolTipXPExtendPetMenu(ItemTooltipEvent event) { - if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) { - //7 is just a random number i chose, prob no pets with less lines than 7 - if (event.toolTip.size() > 7) { - if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) { - GuiProfileViewer.PetLevel petlevel = null; - - int xpLine = -1; - for (int i = event.toolTip.size() - 1; i >= 0; i--) { - Matcher matcher = xpLevelPattern.matcher(event.toolTip.get(i)); - if (matcher.matches()) { - xpLine = i; - event.toolTip.set(xpLine, matcher.group(1)); - break; - } else if (event.toolTip.get(i).matches("MAX LEVEL")) { - return; - } - } - - PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack( - event.itemStack.getDisplayName(), - NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(event.itemStack.getTagCompound()) - ); - if (pet == null) { - return; - } - petlevel = pet.petLevel; - - if (petlevel == null || xpLine == -1) { - return; - } - - event.toolTip.add( - xpLine + 1, - EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.levelXp) + - EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + - myFormatter.format(petlevel.currentLevelRequirement) - ); - - } - } - } - } - - DecimalFormat myFormatter = new DecimalFormat("###,###.###"); - - /** - * This method does the following: - * Move the pet inventory display tooltip to the left to avoid conflicts - * Remove reforge stats for Legendary items from Hypixel if enabled - * Show NBT data when holding LCONTROL - */ - @SubscribeEvent - public void onItemTooltip(ItemTooltipEvent event) { - if (!neu.isOnSkyblock()) return; - if (event.toolTip == null) return; - //Render the pet inventory display tooltip to the left to avoid things from other mods rendering over the tooltip - if (event.itemStack.getTagCompound() != null && event.itemStack.getTagCompound().getBoolean("NEUPETINVDISPLAY")) { - GlStateManager.translate(-200, 0, 0); - } - - if (event.toolTip.size() > 2 && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.hideDefaultReforgeStats) { - String secondLine = StringUtils.stripControlCodes(event.toolTip.get(1)); - if (secondLine.equals("Reforge Stone")) { - Integer startIndex = null; - Integer cutoffIndex = null; - //loop from the back of the List to find the wanted index sooner - for (int i = event.toolTip.size() - 1; i >= 0; i--) { - //rarity or mining level requirement - String line = StringUtils.stripControlCodes(event.toolTip.get(i)); - if (line.contains("REFORGE STONE") || line.contains("Requires Mining Skill Level")) { - cutoffIndex = i; - } - - //The line where the Hypixel stats start - if (line.contains("(Legendary):")) { - startIndex = i; - break; - } - } - if (startIndex != null && cutoffIndex != null && startIndex < cutoffIndex) { - event.toolTip.subList(startIndex, cutoffIndex).clear(); - } - } - } - - if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) && NotEnoughUpdates.INSTANCE.config.hidden.dev && - event.toolTip.size() > 0 && - event.toolTip.get(event.toolTip.size() - 1).startsWith(EnumChatFormatting.DARK_GRAY + "NBT: ")) { - event.toolTip.remove(event.toolTip.size() - 1); - - StringBuilder sb = new StringBuilder(); - String nbt = event.itemStack.getTagCompound().toString(); - int indent = 0; - for (char c : nbt.toCharArray()) { - boolean newline = false; - if (c == '{' || c == '[') { - indent++; - newline = true; - } else if (c == '}' || c == ']') { - indent--; - sb.append("\n"); - for (int i = 0; i < indent; i++) sb.append(" "); - } else if (c == ',') { - newline = true; - } else if (c == '\"') { - sb.append(EnumChatFormatting.RESET.toString() + EnumChatFormatting.GRAY); - } - - sb.append(c); - if (newline) { - sb.append("\n"); - for (int i = 0; i < indent; i++) sb.append(" "); - } - } - event.toolTip.add(sb.toString()); - if (Keyboard.isKeyDown(Keyboard.KEY_H)) { - if (!copied) { - copied = true; - StringSelection selection = new StringSelection(sb.toString()); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); - } - } else { - copied = false; - } - } else if (NotEnoughUpdates.INSTANCE.packDevEnabled) { - event.toolTip.add(""); - event.toolTip.add(EnumChatFormatting.AQUA + "NEU Pack Dev Info:"); - event.toolTip.add("Press " + EnumChatFormatting.GOLD + "[KEY]" + EnumChatFormatting.GRAY + " to copy line"); - - String internal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); - - boolean k = Keyboard.isKeyDown(Keyboard.KEY_K); - boolean m = Keyboard.isKeyDown(Keyboard.KEY_M); - boolean n = Keyboard.isKeyDown(Keyboard.KEY_N); - - event.toolTip.add( - EnumChatFormatting.AQUA + "Internal Name: " + EnumChatFormatting.GRAY + internal + EnumChatFormatting.GOLD + - " [K]"); - if (!copied && k) { - MiscUtils.copyToClipboard(internal); - } - - if (event.itemStack.getTagCompound() != null) { - NBTTagCompound tag = event.itemStack.getTagCompound(); - - if (tag.hasKey("SkullOwner", 10)) { - GameProfile gameprofile = NBTUtil.readGameProfileFromNBT(tag.getCompoundTag("SkullOwner")); - - if (gameprofile != null) { - event.toolTip.add(EnumChatFormatting.AQUA + "Skull UUID: " + EnumChatFormatting.GRAY + gameprofile.getId() + - EnumChatFormatting.GOLD + " [M]"); - if (!copied && m) { - MiscUtils.copyToClipboard(gameprofile.getId().toString()); - } - - Map map = - Minecraft.getMinecraft().getSkinManager().loadSkinFromCache(gameprofile); - - if (map.containsKey(MinecraftProfileTexture.Type.SKIN)) { - MinecraftProfileTexture profTex = map.get(MinecraftProfileTexture.Type.SKIN); - event.toolTip.add( - EnumChatFormatting.AQUA + "Skull Texture Link: " + EnumChatFormatting.GRAY + profTex.getUrl() + - EnumChatFormatting.GOLD + " [N]"); - - if (!copied && n) { - MiscUtils.copyToClipboard(profTex.getUrl()); - } - } - } - } - } - - copied = k || m || n; - } - } - - @SubscribeEvent - public void onRenderLast(RenderWorldLastEvent event) { - CrystalMetalDetectorSolver.render(event.partialTicks); - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index d1bfed14d1..d9566f0d03 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -1,9 +1,63 @@ package io.github.moulberry.notenoughupdates; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.ascending_overlay; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.close; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.descending_overlay; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.help; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.itemPaneTabArrow; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.item_haschild; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.item_mask; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_alphabetical; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_alphabetical_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_rarity; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_rarity_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_value; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.order_value_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.quickcommand_background; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.rightarrow; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.rightarrow_overlay; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.settings; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_accessory; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_accessory_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_all; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_all_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_armor; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_armor_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_mob; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_mob_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_pet; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_pet_active; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_tool; +import static io.github.moulberry.notenoughupdates.util.GuiTextures.sort_tool_active; + +import java.awt.Color; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + import com.google.common.collect.Lists; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; +import org.lwjgl.util.vector.Vector2f; import io.github.moulberry.notenoughupdates.auction.CustomAHGui; import io.github.moulberry.notenoughupdates.core.BackgroundBlur; import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper; @@ -22,6 +76,7 @@ import io.github.moulberry.notenoughupdates.options.NEUConfigEditor; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.LerpingFloat; +import io.github.moulberry.notenoughupdates.util.NotificationHandler; import io.github.moulberry.notenoughupdates.util.SpecialColour; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; @@ -32,7 +87,11 @@ import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.gui.inventory.GuiInventory; -import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; @@ -56,65 +115,49 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.client.ClientCommandHandler; -import org.lwjgl.input.Keyboard; -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL14; -import org.lwjgl.util.vector.Vector2f; - -import java.awt.Color; -import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import static io.github.moulberry.notenoughupdates.util.GuiTextures.*; public class NEUOverlay extends Gui { - private static final ResourceLocation SUPERGEHEIMNISVERMOGEN = - new ResourceLocation("notenoughupdates:supersecretassets/bald.png"); + private static final ResourceLocation SUPERGEHEIMNISVERMOGEN = new ResourceLocation( + "notenoughupdates:supersecretassets/bald.png"); private static final ResourceLocation SEARCH_BAR = new ResourceLocation("notenoughupdates:search_bar.png"); private static final ResourceLocation SEARCH_BAR_GOLD = new ResourceLocation("notenoughupdates:search_bar_gold.png"); - private static final ResourceLocation ARMOR_DISPLAY = - new ResourceLocation("notenoughupdates:armordisplay/armordisplay.png"); - private static final ResourceLocation ARMOR_DISPLAY_GREY = - new ResourceLocation("notenoughupdates:armordisplay/armordisplay_grey.png"); - private static final ResourceLocation ARMOR_DISPLAY_DARK = - new ResourceLocation("notenoughupdates:armordisplay/armordisplay_phq_dark.png"); - private static final ResourceLocation ARMOR_DISPLAY_FSR = - new ResourceLocation("notenoughupdates:armordisplay/armordisplay_fsr.png"); - private static final ResourceLocation ARMOR_DISPLAY_TRANSPARENT = - new ResourceLocation("notenoughupdates:armordisplay/armordisplay_transparent.png"); - private static final ResourceLocation ARMOR_DISPLAY_TRANSPARENT_PET = - new ResourceLocation("notenoughupdates:armordisplay/armordisplay_transparent_pet.png"); + private static final ResourceLocation ARMOR_DISPLAY = new ResourceLocation( + "notenoughupdates:armordisplay/armordisplay.png"); + private static final ResourceLocation ARMOR_DISPLAY_GREY = new ResourceLocation( + "notenoughupdates:armordisplay/armordisplay_grey.png"); + private static final ResourceLocation ARMOR_DISPLAY_DARK = new ResourceLocation( + "notenoughupdates:armordisplay/armordisplay_phq_dark.png"); + private static final ResourceLocation ARMOR_DISPLAY_FSR = new ResourceLocation( + "notenoughupdates:armordisplay/armordisplay_fsr.png"); + private static final ResourceLocation ARMOR_DISPLAY_TRANSPARENT = new ResourceLocation( + "notenoughupdates:armordisplay/armordisplay_transparent.png"); + private static final ResourceLocation ARMOR_DISPLAY_TRANSPARENT_PET = new ResourceLocation( + "notenoughupdates:armordisplay/armordisplay_transparent_pet.png"); private static final ResourceLocation QUESTION_MARK = new ResourceLocation("notenoughupdates:pv_unknown.png"); - private static final ResourceLocation PET_DISPLAY = - new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo.png"); - private static final ResourceLocation PET_DISPLAY_GREY = - new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_dark.png"); - private static final ResourceLocation PET_DISPLAY_DARK = - new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_phqdark.png"); - private static final ResourceLocation PET_DISPLAY_FSR = - new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_fsr.png"); - private static final ResourceLocation PET_DISPLAY_TRANSPARENT = - new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_transparent.png"); - - private static final ResourceLocation PET_ARMOR_DISPLAY = - new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor.png"); - private static final ResourceLocation PET_ARMOR_DISPLAY_GREY = - new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_dark.png"); - private static final ResourceLocation PET_ARMOR_DISPLAY_DARK = - new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_phqdark.png"); - private static final ResourceLocation PET_ARMOR_DISPLAY_FSR = - new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_fsr.png"); - private static final ResourceLocation PET_ARMOR_DISPLAY_TRANSPARENT = - new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_transparent.png"); + private static final ResourceLocation PET_DISPLAY = new ResourceLocation( + "notenoughupdates:petdisplay/petdisplaysolo.png"); + private static final ResourceLocation PET_DISPLAY_GREY = new ResourceLocation( + "notenoughupdates:petdisplay/petdisplaysolo_dark.png"); + private static final ResourceLocation PET_DISPLAY_DARK = new ResourceLocation( + "notenoughupdates:petdisplay/petdisplaysolo_phqdark.png"); + private static final ResourceLocation PET_DISPLAY_FSR = new ResourceLocation( + "notenoughupdates:petdisplay/petdisplaysolo_fsr.png"); + private static final ResourceLocation PET_DISPLAY_TRANSPARENT = new ResourceLocation( + "notenoughupdates:petdisplay/petdisplaysolo_transparent.png"); + + private static final ResourceLocation PET_ARMOR_DISPLAY = new ResourceLocation( + "notenoughupdates:petdisplay/petdisplayarmor.png"); + private static final ResourceLocation PET_ARMOR_DISPLAY_GREY = new ResourceLocation( + "notenoughupdates:petdisplay/petdisplayarmor_dark.png"); + private static final ResourceLocation PET_ARMOR_DISPLAY_DARK = new ResourceLocation( + "notenoughupdates:petdisplay/petdisplayarmor_phqdark.png"); + private static final ResourceLocation PET_ARMOR_DISPLAY_FSR = new ResourceLocation( + "notenoughupdates:petdisplay/petdisplayarmor_fsr.png"); + private static final ResourceLocation PET_ARMOR_DISPLAY_TRANSPARENT = new ResourceLocation( + "notenoughupdates:petdisplay/petdisplayarmor_transparent.png"); private static boolean renderingArmorHud; private static boolean renderingPetHud; @@ -249,7 +292,7 @@ public void mouseClick(float x, float y, int mouseX, int mouseY) { searchMode = !searchMode; lastSearchMode = System.currentTimeMillis(); if (searchMode && NotEnoughUpdates.INSTANCE.config.hidden.firstTimeSearchFocus) { - NEUEventListener.displayNotification(Lists.newArrayList( + NotificationHandler.displayNotification(Lists.newArrayList( "\u00a7eSearch Highlight", "\u00a77In this mode NEU will gray out non matching items in", "\u00a77your inventory or chests.", @@ -366,8 +409,7 @@ public void render(float x, float y) { } @Override - public void recalculate() { - } + public void recalculate() {} }; } @@ -384,8 +426,7 @@ public int getHeight() { } @Override - public void recalculate() { - } + public void recalculate() {} @Override public void mouseClick(float x, float y, int mouseX, int mouseY) { @@ -398,8 +439,7 @@ public void mouseClick(float x, float y, int mouseX, int mouseY) { } @Override - public void mouseClickOutside() { - } + public void mouseClickOutside() {} @Override public void render(float x, float y) { @@ -439,8 +479,7 @@ public int getHeight() { } @Override - public void recalculate() { - } + public void recalculate() {} @Override public void mouseClick(float x, float y, int mouseX, int mouseY) { @@ -457,8 +496,7 @@ public void mouseClick(float x, float y, int mouseX, int mouseY) { } @Override - public void mouseClickOutside() { - } + public void mouseClickOutside() {} @Override public void render(float x, float y) { @@ -499,16 +537,14 @@ public int getHeight() { } @Override - public void recalculate() { - } + public void recalculate() {} @Override public void mouseClick(float x, float y, int mouseX, int mouseY) { if (!NotEnoughUpdates.INSTANCE.config.toolbar.quickCommands) return; if ((NotEnoughUpdates.INSTANCE.config.toolbar.quickCommandsClickType != 0 && Mouse.getEventButtonState()) || - (NotEnoughUpdates.INSTANCE.config.toolbar.quickCommandsClickType == 0 && - !Mouse.getEventButtonState() && + (NotEnoughUpdates.INSTANCE.config.toolbar.quickCommandsClickType == 0 && !Mouse.getEventButtonState() && Mouse.getEventButton() != -1)) { if (quickCommandStr.contains(":")) { String command = quickCommandStr.split(":")[0].trim(); @@ -523,8 +559,7 @@ public void mouseClick(float x, float y, int mouseX, int mouseY) { } @Override - public void mouseClickOutside() { - } + public void mouseClickOutside() {} @Override public void render(float x, float y) { @@ -582,8 +617,7 @@ public void render(float x, float y) { int mouseX = Mouse.getX() * Utils.peekGuiScale().getScaledWidth() / Minecraft.getMinecraft().displayWidth; int mouseY = Utils.peekGuiScale().getScaledHeight() - - Mouse.getY() * Utils.peekGuiScale().getScaledHeight() / Minecraft.getMinecraft().displayHeight - - 1; + Mouse.getY() * Utils.peekGuiScale().getScaledHeight() / Minecraft.getMinecraft().displayHeight - 1; if (mouseX > x && mouseX < x + bigItemSize) { if (mouseY > y && mouseY < y + bigItemSize) { @@ -619,8 +653,11 @@ public int getPadding() { } private MBGuiGroupAligned createSearchBarGroup() { - List children = - Lists.newArrayList(createSettingsButton(this), createSearchBar(), createHelpButton(this)); + List children = Lists.newArrayList( + createSettingsButton(this), + createSearchBar(), + createHelpButton(this) + ); return new MBGuiGroupAligned(children, false) { public int getPadding() { return getPaddingUnscaled() * 4; @@ -724,9 +761,12 @@ public void showInfo(JsonObject item) { String internalname = item.get("internalname").getAsString(); String name = item.get("displayname").getAsString(); String infoType = item.get("infoType").getAsString(); - displayInformationPane(new TextInfoPane(this, manager, "Loading", "Loading your requested information about " + - name + - ".")); + displayInformationPane(new TextInfoPane( + this, + manager, + "Loading", + "Loading your requested information about " + name + "." + )); infoPaneLoadingJob = InfoPane.create(this, manager, infoType, name, internalname, infoText) .thenAccept(this::displayInformationPane); } @@ -1214,12 +1254,14 @@ private Comparator getItemComparator() { return (o1, o2) -> { //1 (mult) if o1 should appear after o2 //-1 (-mult) if o2 should appear after o1 - if (getFavourites().contains(o1.get("internalname").getAsString()) && - !getFavourites().contains(o2.get("internalname").getAsString())) { + if (getFavourites().contains(o1.get("internalname").getAsString()) && !getFavourites().contains(o2 + .get("internalname") + .getAsString())) { return -1; } - if (!getFavourites().contains(o1.get("internalname").getAsString()) && - getFavourites().contains(o2.get("internalname").getAsString())) { + if (!getFavourites().contains(o1.get("internalname").getAsString()) && getFavourites().contains(o2 + .get("internalname") + .getAsString())) { return 1; } @@ -1295,8 +1337,7 @@ public int checkItemType(JsonArray lore, String... typeMatches) { * Checks whether an item matches the current sort mode. */ public boolean checkMatchesSort(String internalname, JsonObject item) { - if (!NotEnoughUpdates.INSTANCE.config.itemlist.showVanillaItems && - item.has("vanilla") && + if (!NotEnoughUpdates.INSTANCE.config.itemlist.showVanillaItems && item.has("vanilla") && item.get("vanilla").getAsBoolean()) { return false; } @@ -1308,8 +1349,7 @@ public boolean checkMatchesSort(String internalname, JsonObject item) { } else if (getSortMode() == SORT_MODE_PET) { return internalname.matches(petRegex) && item.get("displayname").getAsString().contains("["); } else if (getSortMode() == SORT_MODE_TOOL) { - return checkItemType( - item.get("lore").getAsJsonArray(), + return checkItemType(item.get("lore").getAsJsonArray(), "SWORD", "BOW", "AXE", @@ -1325,9 +1365,7 @@ public boolean checkMatchesSort(String internalname, JsonObject item) { ) >= 0; } else if (getSortMode() == SORT_MODE_ARMOR) { return checkItemType( - item - .get("lore") - .getAsJsonArray(), + item.get("lore").getAsJsonArray(), "HELMET", "CHESTPLATE", "LEGGINGS", @@ -1336,8 +1374,7 @@ public boolean checkMatchesSort(String internalname, JsonObject item) { "DUNGEON CHESTPLATE", "DUNGEON LEGGINGS", "DUNGEON BOOTS" - ) >= - 0; + ) >= 0; } else if (getSortMode() == SORT_MODE_ACCESSORY) { return checkItemType(item.get("lore").getAsJsonArray(), "ACCESSORY", "HATCCESSORY", "DUNGEON ACCESSORY") >= 0; } @@ -1812,7 +1849,9 @@ private boolean isInNamedGui(String guiName) { ContainerChest container = (ContainerChest) chest.inventorySlots; IInventory lower = container.getLowerChestInventory(); String containerName = lower.getDisplayName().getUnformattedText(); - wardrobeOpen = containerName.contains(guiName); + if (containerName.contains(guiName)) { + wardrobeOpen = true; + } else wardrobeOpen = false; } if (guiScreen instanceof GuiInventory) { wardrobeOpen = false; @@ -1855,27 +1894,31 @@ private ItemStack getChestSlotsAsItemStack(int slot) { private int selectedArmor = 9; private int getEquippedArmor() { - if (!isInNamedGui("Wardrobe")) return selectedArmor; - - ItemStack nullTest1 = getChestSlotsAsItemStack(8); - ItemStack nullTest2 = getChestSlotsAsItemStack(17); - ItemStack nullTest3 = getChestSlotsAsItemStack(26); - ItemStack nullTest4 = getChestSlotsAsItemStack(35); - ItemStack nullTest5 = getChestSlotsAsItemStack(44); - if (nullTest1 != null || nullTest2 != null || nullTest3 != null || nullTest4 != null || nullTest5 != null) { - selectedArmor = 9; - } - for (int ii = 1; ii < 5; ii++) { - if (ii != 1 && selectedArmor != 9) continue; - if (getWardrobePage() != ii) continue; - for (int i = 8; i < 54; i += 9) { - ItemStack stack1 = getChestSlotsAsItemStack(i); - if (stack1 == null) continue; - String[] lore1 = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack1.getTagCompound()); - for (String line : lore1) { - if (line.contains("to unequip this armor")) { - selectedArmor = i; - break; + if (isInNamedGui("Wardrobe")) { + ItemStack nullTest1 = getChestSlotsAsItemStack(8); + ItemStack nullTest2 = getChestSlotsAsItemStack(17); + ItemStack nullTest3 = getChestSlotsAsItemStack(26); + ItemStack nullTest4 = getChestSlotsAsItemStack(35); + ItemStack nullTest5 = getChestSlotsAsItemStack(44); + if (nullTest1 != null || nullTest2 != null || nullTest3 != null || nullTest4 != null || nullTest5 != null) { + selectedArmor = 9; + } + for (int ii = 1; ii < 5; ii++) { + if (ii == 1 || selectedArmor == 9) { + if (getWardrobePage() == ii) { + for (int i = 8; i < 54; i += 9) { + ItemStack stack1 = getChestSlotsAsItemStack(i); + if (stack1 != null) { + String[] lore1 = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack1.getTagCompound()); + for (String line : lore1) { + //System.out.println(line); + if (line.contains("to unequip this armor")) { + selectedArmor = i; + break; + } + } + } + } } } } @@ -1922,7 +1965,9 @@ public static boolean isRenderingPetHud() { * Renders the search bar, quick commands, item selection (right), item info (left) and armor hud gui elements. */ public void render(boolean hoverInv) { - if (disabled) return; + if (disabled) { + return; + } renderingArmorHud = false; renderingPetHud = false; GlStateManager.enableDepth(); @@ -1952,9 +1997,7 @@ public void render(boolean hoverInv) { if (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud && NotEnoughUpdates.INSTANCE.config.misc.hidePotionEffect - && - NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && - isWardrobeSystemOnMainServer()) { + && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && isWardrobeSystemOnMainServer()) { if (getWardrobeSlot(1) != null) { slot1 = getWardrobeSlot(4); slot2 = getWardrobeSlot(3); @@ -1977,8 +2020,7 @@ public void render(boolean hoverInv) { } if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 3) { if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 3 && - NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay && - petSlot != null) { + NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay && petSlot != null) { Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_TRANSPARENT_PET); } else { Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_TRANSPARENT); @@ -2010,8 +2052,7 @@ public void render(boolean hoverInv) { EnumChatFormatting.GREEN + "To cache your armour" ); if (mouseX >= ((width - 208) / 2f) && mouseX < ((width - 208) / 2f) + 16) { - if (mouseY >= ((height + 60) / 2f - 105) && - mouseY <= ((height + 60) / 2f - 105) + 70 && + if (mouseY >= ((height + 60) / 2f - 105) && mouseY <= ((height + 60) / 2f - 105) + 70 && NotEnoughUpdates.INSTANCE.config.customArmour.sendWardrobeCommand) { if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { if (Mouse.getEventButtonState()) { @@ -2031,8 +2072,7 @@ public void render(boolean hoverInv) { } if (slot1 != null && slot2 != null && slot3 != null && slot4 != null) { if (mouseX >= ((width - 208) / 2f) && mouseX < ((width - 208) / 2f) + 16) { - if (mouseY >= ((height + 60) / 2f - 105) && - mouseY <= ((height + 60) / 2f - 105) + 70 && + if (mouseY >= ((height + 60) / 2f - 105) && mouseY <= ((height + 60) / 2f - 105) + 70 && NotEnoughUpdates.INSTANCE.config.customArmour.sendWardrobeCommand) { if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { if (Mouse.getEventButtonState()) { @@ -2075,20 +2115,17 @@ public void render(boolean hoverInv) { } if (PetInfoOverlay.getCurrentPet() != null) { if (NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay - && - (NotEnoughUpdates.INSTANCE.manager - .jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get(PetInfoOverlay.getCurrentPet().petType + ";" + PetInfoOverlay.getCurrentPet().rarity.petId)) - .hasDisplayName() - || - NotEnoughUpdates.INSTANCE.manager - .jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get(PetInfoOverlay.getCurrentPet().petType + ";" + (PetInfoOverlay.getCurrentPet().rarity.petId - 1))) - .hasDisplayName()) - && - NotEnoughUpdates.INSTANCE.config.misc.hidePotionEffect && + && (NotEnoughUpdates.INSTANCE.manager + .jsonToStack(NotEnoughUpdates.INSTANCE.manager + .getItemInformation() + .get(PetInfoOverlay.getCurrentPet().petType + ";" + PetInfoOverlay.getCurrentPet().rarity.petId)) + .hasDisplayName() + || NotEnoughUpdates.INSTANCE.manager + .jsonToStack(NotEnoughUpdates.INSTANCE.manager + .getItemInformation() + .get(PetInfoOverlay.getCurrentPet().petType + ";" + (PetInfoOverlay.getCurrentPet().rarity.petId - 1))) + .hasDisplayName()) + && NotEnoughUpdates.INSTANCE.config.misc.hidePotionEffect && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { if (!NotEnoughUpdates.INSTANCE.manager .jsonToStack( @@ -2105,9 +2142,10 @@ public void render(boolean hoverInv) { PetInfoOverlay.getCurrentPet().petType + ";" + PetInfoOverlay.getCurrentPet().rarity.petId)); } petSlot.getTagCompound().setBoolean("NEUPETINVDISPLAY", true); - petSlot - .getTagCompound() - .setBoolean("NEUHIDEPETTOOLTIP", NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip); + petSlot.getTagCompound().setBoolean( + "NEUHIDEPETTOOLTIP", + NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip + ); ItemStack petInfo = petSlot; if (guiScreen instanceof GuiInventory) { @@ -2157,8 +2195,7 @@ public void render(boolean hoverInv) { List tooltipToDisplay = null; if (petInfo != null) { if (mouseX >= ((width - 208) / 2f) && mouseX < ((width - 208) / 2f) + 16) { - if (mouseY >= ((height + 60) / 2f - 105) + 72 && - mouseY <= ((height + 60) / 2f - 105) + 88 && + if (mouseY >= ((height + 60) / 2f - 105) + 72 && mouseY <= ((height + 60) / 2f - 105) + 88 && NotEnoughUpdates.INSTANCE.config.petOverlay.sendPetsCommand) { if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { if (Mouse.getEventButtonState()) { @@ -2308,17 +2345,14 @@ public void render(boolean hoverInv) { int orderIconX = leftSide + getBoxPadding() + getItemBoxXPadding() + i * scaledItemPaddedSize; drawRect(orderIconX, iconTop, scaledITEM_SIZE + orderIconX, iconTop + scaledITEM_SIZE, fg.getRGB()); - Minecraft - .getMinecraft() - .getTextureManager() - .bindTexture(getCompareMode() == i ? orderIconsActive[i] : orderIcons[i]); + Minecraft.getMinecraft().getTextureManager().bindTexture( + getCompareMode() == i ? orderIconsActive[i] : orderIcons[i]); GlStateManager.color(1f, 1f, 1f, 1f); Utils.drawTexturedRect(orderIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE, 0, 1, 0, 1, GL11.GL_NEAREST); - Minecraft - .getMinecraft() - .getTextureManager() - .bindTexture(getCompareAscending().get(i) ? ascending_overlay : descending_overlay); + Minecraft.getMinecraft().getTextureManager().bindTexture(getCompareAscending().get(i) + ? ascending_overlay + : descending_overlay); GlStateManager.color(1f, 1f, 1f, 1f); Utils.drawTexturedRect(orderIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE, 0, 1, 0, 1, GL11.GL_NEAREST); GlStateManager.bindTexture(0); @@ -2341,10 +2375,8 @@ public void render(boolean hoverInv) { for (int i = 0; i < sortIcons.length; i++) { int sortIconX = rightSide - scaledITEM_SIZE - i * scaledItemPaddedSize; drawRect(sortIconX, iconTop, scaledITEM_SIZE + sortIconX, iconTop + scaledITEM_SIZE, fg.getRGB()); - Minecraft - .getMinecraft() - .getTextureManager() - .bindTexture(getSortMode() == i ? sortIconsActive[i] : sortIcons[i]); + Minecraft.getMinecraft().getTextureManager().bindTexture( + getSortMode() == i ? sortIconsActive[i] : sortIcons[i]); GlStateManager.color(1f, 1f, 1f, 1f); Utils.drawTexturedRect(sortIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE, 0, 1, 0, 1, GL11.GL_NEAREST); GlStateManager.bindTexture(0); @@ -2585,8 +2617,7 @@ private void checkFramebufferSizes(int width, int height) { int sw = width * Utils.peekGuiScale().getScaleFactor(); int sh = height * Utils.peekGuiScale().getScaleFactor(); for (int i = 0; i < itemFramebuffers.length; i++) { - if (itemFramebuffers[i] == null || - itemFramebuffers[i].framebufferWidth != sw || + if (itemFramebuffers[i] == null || itemFramebuffers[i].framebufferWidth != sw || itemFramebuffers[i].framebufferHeight != sh) { if (itemFramebuffers[i] == null) { itemFramebuffers[i] = new Framebuffer(sw, sh, true); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index b6ac71a42c..5ad82d56ac 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -1,5 +1,17 @@ package io.github.moulberry.notenoughupdates; +import java.awt.Color; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Set; + import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -8,9 +20,25 @@ import io.github.moulberry.notenoughupdates.core.BackgroundBlur; import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; import io.github.moulberry.notenoughupdates.dungeons.DungeonMap; -import io.github.moulberry.notenoughupdates.miscfeatures.*; +import io.github.moulberry.notenoughupdates.listener.ChatListener; +import io.github.moulberry.notenoughupdates.listener.ItemTooltipListener; +import io.github.moulberry.notenoughupdates.listener.NEUEventListener; +import io.github.moulberry.notenoughupdates.listener.RenderListener; +import io.github.moulberry.notenoughupdates.miscfeatures.CrystalOverlay; +import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects; +import io.github.moulberry.notenoughupdates.miscfeatures.DwarvenMinesWaypoints; +import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; +import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls; +import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper; +import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns; +import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager; +import io.github.moulberry.notenoughupdates.miscfeatures.MiningStuff; +import io.github.moulberry.notenoughupdates.miscfeatures.NullzeeSphere; +import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; +import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking; +import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager; +import io.github.moulberry.notenoughupdates.miscfeatures.SunTzu; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes; -import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBlockSounds; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.DwarvenMinesTextures; import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay; import io.github.moulberry.notenoughupdates.miscgui.InventoryStorageSelector; @@ -24,14 +52,17 @@ import io.github.moulberry.notenoughupdates.util.XPInformation; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.resources.IReloadableResourceManager; import net.minecraft.client.settings.KeyBinding; import net.minecraft.event.ClickEvent; import net.minecraft.scoreboard.ScoreObjective; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; -import net.minecraft.world.biome.*; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraft.world.biome.BiomeGenHell; +import net.minecraft.world.biome.BiomeGenJungle; +import net.minecraft.world.biome.BiomeGenMesa; +import net.minecraft.world.biome.BiomeGenSnow; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.Mod; @@ -40,12 +71,6 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; -import java.awt.*; -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Set; - @Mod(modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION, clientSideOnly = true) public class NotEnoughUpdates { public static final String MODID = "notenoughupdates"; @@ -194,7 +219,6 @@ public void preinit(FMLPreInitializationEvent event) { MinecraftForge.EVENT_BUS.register(new ItemCooldowns()); MinecraftForge.EVENT_BUS.register(new DwarvenMinesWaypoints()); MinecraftForge.EVENT_BUS.register(new FuelBar()); - //MinecraftForge.EVENT_BUS.register(new FancyPortals()); MinecraftForge.EVENT_BUS.register(XPInformation.getInstance()); MinecraftForge.EVENT_BUS.register(OverlayManager.petInfoOverlay); MinecraftForge.EVENT_BUS.register(OverlayManager.timersOverlay); @@ -205,13 +229,23 @@ public void preinit(FMLPreInitializationEvent event) { MinecraftForge.EVENT_BUS.register(new DwarvenMinesTextures()); MinecraftForge.EVENT_BUS.register(CustomBiomes.INSTANCE); - if (Minecraft.getMinecraft().getResourceManager() instanceof IReloadableResourceManager) { - IReloadableResourceManager manager = (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager(); - manager.registerReloadListener(CustomSkulls.getInstance()); - manager.registerReloadListener(NPCRetexturing.getInstance()); - manager.registerReloadListener(new ItemCustomizeManager.ReloadListener()); - manager.registerReloadListener(new CustomBlockSounds.ReloaderListener()); - } + MinecraftForge.EVENT_BUS.register(this); + MinecraftForge.EVENT_BUS.register(new NEUEventListener(this)); + MinecraftForge.EVENT_BUS.register(new ChatListener(this)); + MinecraftForge.EVENT_BUS.register(new ItemTooltipListener(this)); + MinecraftForge.EVENT_BUS.register(new RenderListener(this)); + MinecraftForge.EVENT_BUS.register(new RecipeGenerator(this)); + MinecraftForge.EVENT_BUS.register(CapeManager.getInstance()); + MinecraftForge.EVENT_BUS.register(new EnchantingSolvers()); + MinecraftForge.EVENT_BUS.register(new CalendarOverlay()); + MinecraftForge.EVENT_BUS.register(SBInfo.getInstance()); + MinecraftForge.EVENT_BUS.register(CustomItemEffects.INSTANCE); + MinecraftForge.EVENT_BUS.register(new DungeonMap()); + MinecraftForge.EVENT_BUS.register(new SunTzu()); + MinecraftForge.EVENT_BUS.register(new MiningStuff()); + MinecraftForge.EVENT_BUS.register(new FairySouls()); + MinecraftForge.EVENT_BUS.register(new CrystalOverlay()); + MinecraftForge.EVENT_BUS.register(new ItemCooldowns()); this.commands = new Commands(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java b/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java deleted file mode 100644 index e789e88294..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.github.moulberry.notenoughupdates.collectionlog; - -import java.util.HashMap; -import java.util.List; -import java.util.regex.Pattern; - -public class CollectionConstant { - public static class DropEntry { - public String type; - public Pattern regex; - public HashMap items; - } - - public List dropdata; -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java b/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java deleted file mode 100644 index dac104c602..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java +++ /dev/null @@ -1,111 +0,0 @@ -package io.github.moulberry.notenoughupdates.collectionlog; - -import io.github.moulberry.notenoughupdates.core.BackgroundBlur; -import io.github.moulberry.notenoughupdates.core.GlScissorStack; -import io.github.moulberry.notenoughupdates.util.Utils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.ResourceLocation; -import org.lwjgl.opengl.GL11; - -public class GuiCollectionLog extends GuiScreen { - private static final ResourceLocation COLLECTION_LOG_TEX = new ResourceLocation("notenoughupdates:collectionlog.png"); - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - int width = scaledResolution.getScaledWidth(); - int height = scaledResolution.getScaledHeight(); - - int colwidth = 307; - int colheight = 187; - - int left = width / 2 - colwidth / 2; - int top = height / 2 - colheight / 2; - - BackgroundBlur.renderBlurredBackground(10, width, height, left, top, colwidth, colheight); - super.drawDefaultBackground(); - - Utils.drawStringCentered("\u00a7lCollection Log", fontRendererObj, width / 2, top - 27, true, 0xfff5aa00); - - String[] cats = {"Bosses", "Dragons", "Slayer", "Dungeons"}; - - GlStateManager.enableDepth(); - - GlStateManager.translate(0, 0, 2); - for (int i = 0; i < 4; i++) { - if (i == 0) { - int offset = i == 0 ? 1 : 2; - - Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(left + i * 71, top - 21, 71, 25, - (71 * offset) / 512f, (71 + 71 * offset) / 512f, 211 / 512f, (211 + 25) / 512f, GL11.GL_NEAREST - ); - - Utils.drawStringCentered(cats[i], fontRendererObj, left + i * 71 + 71 / 2, top - 8, true, 0xfff5aa00); - } - } - - GlStateManager.translate(0, 0, -1); - Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(left, top, colwidth, colheight, - 0, colwidth / 512f, 0, colheight / 512f, GL11.GL_NEAREST - ); - - GlScissorStack.push(0, top + 3, width, top + colheight - 6, scaledResolution); - int catIndex = 0; - for (int h = top + 3; h < top + colheight - 6; h += 24) { - catIndex += 2; - - Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(left, h, 100, 24, - 0, 100 / 512f, 187 / 512f, 211 / 512f, GL11.GL_NEAREST - ); - - fontRendererObj.drawString("Thing " + catIndex, left + 5, h + 2, 0xfff5aa00, true); - fontRendererObj.drawString("Thing " + (catIndex + 1), left + 5, h + 14, 0xfff5aa00, true); - } - GlScissorStack.pop(scaledResolution); - - fontRendererObj.drawString("\u00a7lSuperior Dragon", left + 119, top + 8, 0xfff5aa00, true); - fontRendererObj.drawString( - "Obtained: " + EnumChatFormatting.YELLOW + "3/5", - left + 122, - top + 23, - 0xfff5aa00, - true - ); - - String killCountText = "Kills: " + EnumChatFormatting.WHITE + "3"; - //int killCountLen = fontRendererObj.getStringWidth(killCountText); - fontRendererObj.drawString(killCountText, left + 122, top + 68, 0xfff5aa00, true); - - Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(left + colwidth - 196, top, 196, colheight, - (512 - 196) / 512f, 1, 0 / 512f, colheight / 512f, GL11.GL_NEAREST - ); - - GlStateManager.translate(0, 0, -1); - - for (int i = 0; i < 4; i++) { - if (i != 0) { - Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX); - GlStateManager.color(1, 1, 1, 1); - Utils.drawTexturedRect(left + i * 71, top - 21, 71, 25, - 0, 71 / 512f, 211 / 512f, (211 + 25) / 512f, GL11.GL_NEAREST - ); - - Utils.drawStringCentered(cats[i], fontRendererObj, left + i * 71 + 71 / 2, top - 8, true, 0xfff5aa00); - } - } - - super.drawScreen(mouseX, mouseY, partialTicks); - } -} 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 66da4f9f32..7caf09cb5a 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 @@ -3,7 +3,6 @@ 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.miscfeatures.FancyPortals; import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent; @@ -11,24 +10,21 @@ import io.github.moulberry.notenoughupdates.miscgui.GuiPriceGraph; import io.github.moulberry.notenoughupdates.util.SBInfo; import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; -import net.minecraft.util.*; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.EnumParticleTypes; import net.minecraftforge.common.MinecraftForge; -import java.io.File; import java.util.Arrays; import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; public class DevTestCommand extends ClientCommandBase { private static final List DEV_TESTERS = - Arrays.asList("moulberry", "lucycoconut", "ironm00n", "ariyio", "throwpo", "lrg89", "dediamondpro"); + Arrays.asList("moulberry", "lucycoconut", "ironm00n", "ariyio", "throwpo", "lrg89", "dediamondpro", "lulonaut"); private static final String[] DEV_FAIL_STRINGS = { "No.", @@ -48,9 +44,7 @@ public class DevTestCommand extends ClientCommandBase { "", "Ok, this is actually the last message, use the command again and you'll crash I promise" }; - private int devFailIndex = 0; - private final ScheduledExecutorService devES = Executors.newSingleThreadScheduledExecutor(); public DevTestCommand() { super("neudevtest"); @@ -84,10 +78,6 @@ public void printStackTrace() { DEV_FAIL_STRINGS[devFailIndex++])); return; } - /*if(args.length == 1) { - DupePOC.doDupe(args[0]); - return; - }*/ if (args.length >= 1 && args[0].equalsIgnoreCase("profileinfo")) { String currentProfile = SBInfo.getInstance().currentProfile; SBInfo.Gamemode gamemode = SBInfo.getInstance().getGamemodeForProfile(currentProfile); @@ -146,62 +136,6 @@ public void printStackTrace() { double x = Math.floor(Minecraft.getMinecraft().thePlayer.posX) + 0.5f; double z = Math.floor(Minecraft.getMinecraft().thePlayer.posZ) + 0.5f; Minecraft.getMinecraft().thePlayer.setPosition(x, Minecraft.getMinecraft().thePlayer.posY, z); - return; - } - if (args.length == 1 && args[0].equalsIgnoreCase("pansc")) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + - "Taking panorama screenshot")); - - AtomicInteger perspective = new AtomicInteger(0); - FancyPortals.perspectiveId = 0; - - EntityPlayerSP p = Minecraft.getMinecraft().thePlayer; - p.prevRotationYaw = p.rotationYaw = 0; - p.prevRotationPitch = p.rotationPitch = 90; - devES.schedule(new Runnable() { - @Override - public void run() { - Minecraft.getMinecraft().addScheduledTask(() -> { - ScreenShotHelper.saveScreenshot(new File("C:/Users/James/Desktop/"), "pansc-" + perspective.get() + ".png", - Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight, - Minecraft.getMinecraft().getFramebuffer() - ); - }); - if (perspective.incrementAndGet() >= 6) { - FancyPortals.perspectiveId = -1; - return; - } - devES.schedule(() -> { - FancyPortals.perspectiveId = perspective.get(); - if (FancyPortals.perspectiveId == 5) { - p.prevRotationYaw = p.rotationYaw = 0; - p.prevRotationPitch = p.rotationPitch = -90; - } else if (FancyPortals.perspectiveId >= 1 && FancyPortals.perspectiveId <= 4) { - float yaw = 90 * FancyPortals.perspectiveId - 180; - if (yaw > 180) yaw -= 360; - p.prevRotationYaw = p.rotationYaw = yaw; - p.prevRotationPitch = p.rotationPitch = 0; - } - devES.schedule(this, 3000L, TimeUnit.MILLISECONDS); - }, 100L, TimeUnit.MILLISECONDS); - } - }, 3000L, TimeUnit.MILLISECONDS); - - return; } - - /* if(args.length == 1 && args[0].equalsIgnoreCase("update")) { - NEUEventListener.displayUpdateMessageIfOutOfDate(); - } */ - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + - "Executing dubious code")); - /*Minecraft.getMinecraft().thePlayer.rotationYaw = 0; - Minecraft.getMinecraft().thePlayer.rotationPitch = 0; - Minecraft.getMinecraft().thePlayer.setPosition( - Math.floor(Minecraft.getMinecraft().thePlayer.posX) + Float.parseFloat(args[0]), - Minecraft.getMinecraft().thePlayer.posY, - Minecraft.getMinecraft().thePlayer.posZ);*/ - //Hot reload me yay! } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java index 4f85c26efb..5d19d62cda 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java @@ -1,8 +1,8 @@ package io.github.moulberry.notenoughupdates.commands.help; import com.google.common.collect.Lists; -import io.github.moulberry.notenoughupdates.NEUEventListener; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.util.NotificationHandler; import net.minecraft.command.ICommandSender; public class StorageViewerWhyCommand extends ClientCommandBase { @@ -13,7 +13,7 @@ public StorageViewerWhyCommand() { @Override public void processCommand(ICommandSender sender, String[] args) { - NEUEventListener.displayNotification(Lists.newArrayList( + NotificationHandler.displayNotification(Lists.newArrayList( "\u00a7eStorage Viewer", "\u00a77Currently, the storage viewer requires you to click twice", "\u00a77in order to switch between pages. This is because Hypixel", diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java deleted file mode 100644 index 1bde763139..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.github.moulberry.notenoughupdates.commands.misc; - -import io.github.moulberry.notenoughupdates.collectionlog.GuiCollectionLog; -import io.github.moulberry.notenoughupdates.commands.ScreenCommand; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class CollectionLogCommand extends ScreenCommand { - - public CollectionLogCommand() { - super("neucl", GuiCollectionLog::new); - } - - @Override - public List getCommandAliases() { - return Collections.singletonList("collectionlog"); - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java deleted file mode 100644 index d33e560a57..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java +++ /dev/null @@ -1,20 +0,0 @@ -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.gamemodes.GuiGamemodes; -import net.minecraft.command.CommandException; -import net.minecraft.command.ICommandSender; - -public class GamemodesCommand extends ClientCommandBase { - - public GamemodesCommand() { - super("neugamemodes"); - } - - @Override - public void processCommand(ICommandSender sender, String[] args) throws CommandException { - boolean upgradeOverride = args.length == 1 && args[0].equals("upgradeOverride"); - NotEnoughUpdates.INSTANCE.openGui = new GuiGamemodes(upgradeOverride); - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java deleted file mode 100644 index 77305904c9..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java +++ /dev/null @@ -1,323 +0,0 @@ -package io.github.moulberry.notenoughupdates.gamemodes; - -import io.github.moulberry.notenoughupdates.NotEnoughUpdates; -import io.github.moulberry.notenoughupdates.util.Utils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.util.ChatComponentText; -import net.minecraft.util.EnumChatFormatting; -import org.lwjgl.input.Keyboard; -import org.lwjgl.opengl.GL11; - -import java.awt.*; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import static io.github.moulberry.notenoughupdates.util.GuiTextures.*; - -public class GuiGamemodes extends GuiScreen { - private final String currentProfile; - private SBGamemodes.Gamemode currentGamemode = null; - private final boolean upgradeOverride; - - private int guiLeft = 100; - private int guiTop = 100; - private final int xSize = 200; - private final int ySize = 232; - - public GuiGamemodes(boolean upgradeOverride) { - this.currentProfile = NotEnoughUpdates.INSTANCE.manager.getCurrentProfile(); - this.upgradeOverride = upgradeOverride; - } - - private boolean canChange(int from, int to) { - if (from >= to) { - return true; - } else { - return !currentGamemode.locked || upgradeOverride; - } - } - - @Override - public void updateScreen() { - if (this.currentProfile == null) { - Minecraft.getMinecraft().displayGuiScreen(null); - Minecraft.getMinecraft().thePlayer.addChatMessage( - new ChatComponentText(EnumChatFormatting.RED + "Couldn't detect current profile. Maybe try later?")); - } - - if (currentGamemode == null) { - currentGamemode = SBGamemodes.getGamemode(); - if (currentGamemode == null) { - Minecraft.getMinecraft().displayGuiScreen(null); - Minecraft.getMinecraft().thePlayer.addChatMessage( - new ChatComponentText(EnumChatFormatting.RED + "Couldn't automatically detect current profile." + - "If you have only 1 profile, try using /api new so that NEU can detect your profile.")); - } - } - - String currentProfile = NotEnoughUpdates.INSTANCE.manager.getCurrentProfile(); - if (!this.currentProfile.equals(currentProfile)) { - Minecraft.getMinecraft().displayGuiScreen(null); - Minecraft.getMinecraft().thePlayer.addChatMessage( - new ChatComponentText(EnumChatFormatting.RED + "Profile change detected. Closing gamemodes menu.")); - } - } - - @Override - public void handleKeyboardInput() throws IOException { - if (Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { - SBGamemodes.saveToFile(); - } - - super.handleKeyboardInput(); - } - - public void drawStringShadow(String str, float x, float y, int len) { - for (int xOff = -2; xOff <= 2; xOff++) { - for (int yOff = -2; yOff <= 2; yOff++) { - if (Math.abs(xOff) != Math.abs(yOff)) { - Utils.drawStringScaledMaxWidth(Utils.cleanColourNotModifiers(str), - Minecraft.getMinecraft().fontRendererObj, - x + xOff / 2f, y + yOff / 2f, false, len, - new Color(20, 20, 20, 100 / Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB() - ); - } - } - } - - Utils.drawStringScaledMaxWidth(str, - Minecraft.getMinecraft().fontRendererObj, - x, y, false, len, - new Color(64, 64, 64, 255).getRGB() - ); - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - if (mouseButton == 0) { - SBGamemodes.HardcoreMode setHC = SBGamemodes.HardcoreMode.NORMAL; - SBGamemodes.IronmanMode setIM = SBGamemodes.IronmanMode.NORMAL; - int setMod = 0; - - if (mouseX > guiLeft + xSize - 27 && mouseX < guiLeft + xSize - 9) { - if (mouseY > guiTop + 30 && mouseY < guiTop + 30 + 16) { - setHC = SBGamemodes.HardcoreMode.SOFTCORE; - } else if (mouseY > guiTop + 50 && mouseY < guiTop + 50 + 16) { - setHC = SBGamemodes.HardcoreMode.HARDCORE; - } else if (mouseY > guiTop + 80 && mouseY < guiTop + 80 + 16) { - setIM = SBGamemodes.IronmanMode.IRONMAN; - } else if (mouseY > guiTop + 100 && mouseY < guiTop + 100 + 16) { - setIM = SBGamemodes.IronmanMode.IRONMANPLUS; - } else if (mouseY > guiTop + 120 && mouseY < guiTop + 120 + 16) { - setIM = SBGamemodes.IronmanMode.ULTIMATE_IRONMAN; - } else if (mouseY > guiTop + 140 && mouseY < guiTop + 140 + 16) { - setIM = SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS; - } else if (mouseY > guiTop + 170 && mouseY < guiTop + 170 + 16) { - setMod = SBGamemodes.MODIFIER_DEVILISH; - } else if (mouseY > guiTop + 190 && mouseY < guiTop + 190 + 16) { - setMod = SBGamemodes.MODIFIER_NOBANK; - } else if (mouseY > guiTop + 210 && mouseY < guiTop + 210 + 16) { - setMod = SBGamemodes.MODIFIER_SMALLISLAND; - } - } - - if (setHC != SBGamemodes.HardcoreMode.NORMAL) { - if (currentGamemode.hardcoreMode == setHC) { - currentGamemode.hardcoreMode = SBGamemodes.HardcoreMode.NORMAL; - } else { - if (canChange(currentGamemode.hardcoreMode.ordinal(), setHC.ordinal())) { - currentGamemode.hardcoreMode = setHC; - } - } - } else if (setIM != SBGamemodes.IronmanMode.NORMAL) { - if (currentGamemode.ironmanMode == setIM) { - currentGamemode.ironmanMode = SBGamemodes.IronmanMode.NORMAL; - } else { - if (canChange(currentGamemode.ironmanMode.ordinal(), setIM.ordinal())) { - currentGamemode.ironmanMode = setIM; - } - } - } else if (setMod != 0) { - if (canChange(currentGamemode.gamemodeModifiers, currentGamemode.gamemodeModifiers ^ setMod)) { - currentGamemode.gamemodeModifiers ^= setMod; - } - } - } - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - super.drawDefaultBackground(); - - guiLeft = (width - xSize) / 2; - guiTop = (height - ySize) / 2; - - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(gamemodes); - Utils.drawTexturedRect(guiLeft, guiTop, xSize, ySize, GL11.GL_NEAREST); - - if (currentGamemode == null) return; - - Utils.drawStringCentered("NEU Skyblock Gamemodes", Minecraft.getMinecraft().fontRendererObj, - guiLeft + xSize / 2f, guiTop + 14, false, new Color(64, 64, 64).getRGB() - ); - - drawStringShadow(SBGamemodes.HardcoreMode.SOFTCORE.display, guiLeft + 10, guiTop + 30, xSize - 47); - drawStringShadow(SBGamemodes.HardcoreMode.HARDCORE.display, guiLeft + 10, guiTop + 50, xSize - 47); - - drawStringShadow(SBGamemodes.IronmanMode.IRONMAN.display, guiLeft + 10, guiTop + 80, xSize - 47); - drawStringShadow(SBGamemodes.IronmanMode.IRONMANPLUS.display, guiLeft + 10, guiTop + 100, xSize - 47); - drawStringShadow(SBGamemodes.IronmanMode.ULTIMATE_IRONMAN.display, guiLeft + 10, guiTop + 120, xSize - 47); - drawStringShadow(SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS.display, guiLeft + 10, guiTop + 140, xSize - 47); - - drawStringShadow(SBGamemodes.MODIFIER_DEVILISH_DISPLAY, guiLeft + 10, guiTop + 170, xSize - 47); - drawStringShadow(SBGamemodes.MODIFIER_NOBANK_DISPLAY, guiLeft + 10, guiTop + 190, xSize - 47); - drawStringShadow(SBGamemodes.MODIFIER_SMALLISLAND_DISPLAY, guiLeft + 10, guiTop + 210, xSize - 47); - - String tooltipToDisplay = null; - - GlStateManager.color(1, 1, 1, 1); - if (canChange(currentGamemode.hardcoreMode.ordinal(), SBGamemodes.HardcoreMode.SOFTCORE.ordinal())) { - Minecraft.getMinecraft().getTextureManager().bindTexture( - currentGamemode.hardcoreMode == SBGamemodes.HardcoreMode.SOFTCORE ? radial_circle_on : radial_circle_off); - Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 30 - 4, 16, 16, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 30 - 4, 16, 16, GL11.GL_NEAREST); - if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) { - if (mouseY > guiTop + 30 - 4 && mouseY < guiTop + 30 + 12) { - tooltipToDisplay = SBGamemodes.HardcoreMode.SOFTCORE.desc; - } - } - } - if (canChange(currentGamemode.hardcoreMode.ordinal(), SBGamemodes.HardcoreMode.HARDCORE.ordinal())) { - Minecraft.getMinecraft().getTextureManager().bindTexture( - currentGamemode.hardcoreMode == SBGamemodes.HardcoreMode.HARDCORE ? radial_circle_on : radial_circle_off); - Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 50 - 4, 16, 16, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 50 - 4, 16, 16, GL11.GL_NEAREST); - if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) { - if (mouseY > guiTop + 50 - 4 && mouseY < guiTop + 50 + 12) { - tooltipToDisplay = SBGamemodes.HardcoreMode.HARDCORE.desc; - } - } - } - - if (canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.IRONMAN.ordinal())) { - Minecraft.getMinecraft().getTextureManager().bindTexture( - currentGamemode.ironmanMode == SBGamemodes.IronmanMode.IRONMAN ? radial_circle_on : radial_circle_off); - Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 80 - 4, 16, 16, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 80 - 4, 16, 16, GL11.GL_NEAREST); - if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) { - if (mouseY > guiTop + 80 - 4 && mouseY < guiTop + 80 + 12) { - tooltipToDisplay = SBGamemodes.IronmanMode.IRONMAN.desc; - } - } - } - if (canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.IRONMANPLUS.ordinal())) { - Minecraft.getMinecraft().getTextureManager().bindTexture( - currentGamemode.ironmanMode == SBGamemodes.IronmanMode.IRONMANPLUS ? radial_circle_on : radial_circle_off); - Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 100 - 4, 16, 16, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 100 - 4, 16, 16, GL11.GL_NEAREST); - if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) { - if (mouseY > guiTop + 100 - 4 && mouseY < guiTop + 100 + 12) { - tooltipToDisplay = SBGamemodes.IronmanMode.IRONMANPLUS.desc; - } - } - } - if (canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.ULTIMATE_IRONMAN.ordinal())) { - Minecraft.getMinecraft().getTextureManager().bindTexture( - currentGamemode.ironmanMode == SBGamemodes.IronmanMode.ULTIMATE_IRONMAN ? radial_circle_on : radial_circle_off); - Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 120 - 4, 16, 16, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 120 - 4, 16, 16, GL11.GL_NEAREST); - if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) { - if (mouseY > guiTop + 120 - 4 && mouseY < guiTop + 120 + 12) { - tooltipToDisplay = SBGamemodes.IronmanMode.ULTIMATE_IRONMAN.desc; - } - } - } - if (canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS.ordinal())) { - Minecraft.getMinecraft().getTextureManager().bindTexture( - currentGamemode.ironmanMode == SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS - ? radial_circle_on - : radial_circle_off); - Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 140 - 4, 16, 16, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 140 - 4, 16, 16, GL11.GL_NEAREST); - if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) { - if (mouseY > guiTop + 140 - 4 && mouseY < guiTop + 140 + 12) { - tooltipToDisplay = SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS.desc; - } - } - } - - if (canChange( - currentGamemode.gamemodeModifiers, - currentGamemode.gamemodeModifiers ^ SBGamemodes.MODIFIER_DEVILISH - )) { - Minecraft.getMinecraft().getTextureManager().bindTexture( - (currentGamemode.gamemodeModifiers & SBGamemodes.MODIFIER_DEVILISH) != 0 - ? radial_square_on - : radial_square_off); - Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 170 - 4, 16, 16, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 170 - 4, 16, 16, GL11.GL_NEAREST); - if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) { - if (mouseY > guiTop + 170 - 4 && mouseY < guiTop + 170 + 12) { - tooltipToDisplay = SBGamemodes.MODIFIER_DEVILISH_DESC; - } - } - } - if (canChange(currentGamemode.gamemodeModifiers, currentGamemode.gamemodeModifiers ^ SBGamemodes.MODIFIER_NOBANK)) { - Minecraft.getMinecraft().getTextureManager().bindTexture( - (currentGamemode.gamemodeModifiers & SBGamemodes.MODIFIER_NOBANK) != 0 ? radial_square_on : radial_square_off); - Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 190 - 4, 16, 16, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 190 - 4, 16, 16, GL11.GL_NEAREST); - if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) { - if (mouseY > guiTop + 190 - 4 && mouseY < guiTop + 190 + 12) { - tooltipToDisplay = SBGamemodes.MODIFIER_NOBANK_DESC; - } - } - } - if (canChange( - currentGamemode.gamemodeModifiers, - currentGamemode.gamemodeModifiers ^ SBGamemodes.MODIFIER_SMALLISLAND - )) { - Minecraft.getMinecraft().getTextureManager().bindTexture( - (currentGamemode.gamemodeModifiers & SBGamemodes.MODIFIER_SMALLISLAND) != 0 - ? radial_square_on - : radial_square_off); - Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 210 - 4, 16, 16, GL11.GL_NEAREST); - - Minecraft.getMinecraft().getTextureManager().bindTexture(help); - Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 210 - 4, 16, 16, GL11.GL_NEAREST); - if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) { - if (mouseY > guiTop + 210 - 4 && mouseY < guiTop + 210 + 12) { - tooltipToDisplay = SBGamemodes.MODIFIER_SMALLISLAND_DESC; - } - } - } - - if (tooltipToDisplay != null) { - List lines = new ArrayList<>(); - for (String line : tooltipToDisplay.split("\n")) { - lines.add(EnumChatFormatting.GRAY + line); - } - Utils.drawHoveringText(lines, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj); - } - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java deleted file mode 100644 index ddd4a4ba71..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java +++ /dev/null @@ -1,374 +0,0 @@ -package io.github.moulberry.notenoughupdates.gamemodes; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import io.github.moulberry.notenoughupdates.NotEnoughUpdates; -import io.github.moulberry.notenoughupdates.util.SBInfo; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.gui.inventory.GuiChest; -import net.minecraft.inventory.ContainerChest; -import net.minecraft.util.ChatComponentText; -import net.minecraft.util.EnumChatFormatting; -import net.minecraftforge.client.event.ClientChatReceivedEvent; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import java.io.*; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.security.Key; -import java.util.Base64; -import java.util.HashMap; - -public class SBGamemodes { - private static final Gson gson = new Gson(); - - public static final int MODIFIER_DEVILISH = 0b1; - public static final int MODIFIER_NOBANK = 0b10; - public static final int MODIFIER_SMALLISLAND = 0b100; - - public static final String MODIFIER_DEVILISH_DISPLAY = EnumChatFormatting.DARK_PURPLE + "Devilish"; - public static final String MODIFIER_NOBANK_DISPLAY = EnumChatFormatting.RED + "No" + EnumChatFormatting.GOLD + "Bank"; - public static final String MODIFIER_SMALLISLAND_DISPLAY = EnumChatFormatting.GREEN + "SmallIsland"; - - public static final String MODIFIER_DEVILISH_DESC = EnumChatFormatting.DARK_PURPLE + "Devilish\n" + - "You are NOT allowed to use fairy souls."; - public static final String MODIFIER_NOBANK_DESC = EnumChatFormatting.RED + "No" + EnumChatFormatting.GOLD + "Bank\n" + - "You are NOT allowed to use the bank."; - public static final String MODIFIER_SMALLISLAND_DESC = EnumChatFormatting.GREEN + "SmallIsland\n" + - "Your private island is 1/4 the normal size."; - - private static HashMap currentGamemode = new HashMap<>(); - private static long lastDeathExemption = 0; - - public static class Gamemode { - public HardcoreMode hardcoreMode = HardcoreMode.NORMAL; - public IronmanMode ironmanMode = IronmanMode.NORMAL; - public int gamemodeModifiers = 0; - - public boolean locked = true; - } - - public enum HardcoreMode { - NORMAL("Normal", "Normal"), - SOFTCORE(EnumChatFormatting.RED + "Soft" + EnumChatFormatting.DARK_RED + "core\n" + - "You only have 1 life.\nDying will remove your hardcore status.\nDeaths to the void or 'unknown' are exempted.", - "You died.", "You fell into the void" - ), - HARDCORE(EnumChatFormatting.DARK_RED + "Hardcore\n" + - "You only have 1 life.\nDying will remove your hardcore status."); - - public final String display; - public final String desc; - private final String[] exemptions; - - HardcoreMode(String display, String... exemptions) { - this.display = display.split("\n")[0]; - this.desc = display; - this.exemptions = exemptions; - } - - public boolean isExemption(String line) { - for (String exemption : exemptions) { - if (line.contains(exemption)) return true; - } - return false; - } - } - - public enum IronmanMode { - NORMAL("Normal"), - IRONMAN(EnumChatFormatting.WHITE + "Ironman\n" + - "You are NOT allowed to trade or use the auction house.", - "You ", "Auction House", "Auctions Browser", "Auction View" - ), - IRONMANPLUS(EnumChatFormatting.WHITE + "Ironman" + EnumChatFormatting.GOLD + "+\n" + - "You are NOT allowed to trade, use the auction house or bazaar.", - "You ", "Auction House", "Auctions Browser", "Auction View", "Bazaar" - ), - ULTIMATE_IRONMAN(EnumChatFormatting.DARK_AQUA + "Ultimate " + EnumChatFormatting.WHITE + "Ironman\n" + - "You are NOT allowed to trade or use the auction house.\n" + - "You are restricted to 1 inventory. (No containers, no echest, no wardrobe).", - "You ", "Auction House", "Auctions Browser", "Auction View", "Chest", - "Wardrobe", "Weapon Rack", "Shelves" - ), - ULTIMATE_IRONMANPLUS( - EnumChatFormatting.DARK_AQUA + "Ultimate " + EnumChatFormatting.WHITE + "Ironman" + EnumChatFormatting.GOLD + - "+\n" + - "You are NOT allowed to trade, use the auction house or bazaar.\n" + - "You are restricted to 1 inventory. (No containers, no echest, no wardrobe).", - "You ", - "Auction House", - "Auctions Browser", - "Auction View", - "Bazaar", - "Chest", - "Wardrobe", - "Weapon Rack", - "Shelves" - ); - - public final String display; - public final String desc; - private final String[] bannedInventories; - - IronmanMode(String display, String... bannedInventories) { - this.display = display.split("\n")[0]; - this.desc = display; - this.bannedInventories = bannedInventories; - } - - public boolean isBanned(String inventoryName) { - for (String banned : bannedInventories) { - if (inventoryName.contains(banned + " ") || inventoryName.endsWith(banned)) return true; - } - return false; - } - } - - public static Gamemode getGamemode() { - String currentProfile = SBInfo.getInstance().currentProfile; - - if (currentProfile == null || currentProfile.isEmpty()) return null; - - return currentGamemode.computeIfAbsent(currentProfile, k -> new Gamemode()); - } - - public static void loadFromFile() { - File configDir = NotEnoughUpdates.INSTANCE.manager.configLocation; - File gamemodeFile = new File( - configDir, - "gamemodes/gamemodes-" + Minecraft.getMinecraft().thePlayer.getUniqueID().toString() + ".json" - ); - gamemodeFile.getParentFile().mkdirs(); - - if (!gamemodeFile.exists()) { - return; - } - - try ( - BufferedReader reader = new BufferedReader(new InputStreamReader( - new FileInputStream(gamemodeFile), - StandardCharsets.UTF_8 - )) - ) { - String line = reader.readLine(); - String decoded = decrypt(line); - currentGamemode = gson.fromJson(decoded, GamemodeWrapper.class).currentGamemode; - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static class GamemodeWrapper { - private final HashMap currentGamemode; - - public GamemodeWrapper(HashMap currentGamemode) { - this.currentGamemode = currentGamemode; - } - } - - public static void saveToFile() { - File configDir = NotEnoughUpdates.INSTANCE.manager.configLocation; - File gamemodeFile = new File( - configDir, - "gamemodes/gamemodes-" + Minecraft.getMinecraft().thePlayer.getUniqueID().toString() + ".json" - ); - gamemodeFile.getParentFile().mkdirs(); - - try { - gamemodeFile.createNewFile(); - - try ( - BufferedWriter writer = new BufferedWriter( - new OutputStreamWriter(new FileOutputStream(gamemodeFile), StandardCharsets.UTF_8)) - ) { - JsonObject obj = new JsonObject(); - writer.write(encrypt(gson.toJson(new GamemodeWrapper(currentGamemode), GamemodeWrapper.class))); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static Key getKeyFromPlayerUUID() { - byte[] bytes = ByteBuffer.allocate(2 * Long.SIZE / Byte.SIZE) - .putLong(Minecraft.getMinecraft().thePlayer.getUniqueID().getLeastSignificantBits()) - .putLong(Minecraft.getMinecraft().thePlayer.getUniqueID().getMostSignificantBits()) - .array(); - SecretKeySpec key = new SecretKeySpec(bytes, "AES"); - - return key; - } - - public static String encrypt(String value) { - try { - Cipher cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.ENCRYPT_MODE, getKeyFromPlayerUUID()); - String encrypt = Base64.getEncoder().encodeToString(cipher.doFinal(value.getBytes())); - return encrypt; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static String decrypt(String encrypted) { - try { - Cipher cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.DECRYPT_MODE, getKeyFromPlayerUUID()); - byte[] b64Decoded = Base64.getDecoder().decode(encrypted); - byte[] bytes = cipher.doFinal(b64Decoded); - - return new String(bytes); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static void setGamemode(Gamemode gamemode) { - String currentProfile = NotEnoughUpdates.INSTANCE.manager.getCurrentProfile(); - - if (currentProfile == null || currentProfile.isEmpty()) return; - - currentGamemode.put(currentProfile, gamemode); - } - - @SubscribeEvent - public void onPlayerInteract(PlayerInteractEvent event) { - if (getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; - - if (!"Your Island".equals(SBInfo.getInstance().location)) return; - - if ((getGamemode().gamemodeModifiers & MODIFIER_SMALLISLAND) != 0) { - if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { - if (Math.abs(event.pos.getX()) > 40 || Math.abs(event.pos.getZ()) > 40) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "[NPC] Builder" + - EnumChatFormatting.WHITE + ": Sorry, " + Minecraft.getMinecraft().thePlayer.getName() + - ", due to budget cuts your skyblock island is now only 80 blocks wide.")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.AQUA + "(Use " + EnumChatFormatting.YELLOW + "/neugamemodes" + - EnumChatFormatting.AQUA + " if you would like to build further out)")); - - event.setCanceled(true); - } - } - } - } - - @SubscribeEvent - public void onTick(TickEvent.ClientTickEvent event) { - if (event.phase != TickEvent.Phase.START) return; - - if (getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; - - boolean inDungeons = SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals( - "dungeon"); - - getGamemode().locked = !(EnumChatFormatting.YELLOW + "Break a log").equals(SBInfo.getInstance().objective); - - IronmanMode ironmanMode = getGamemode().ironmanMode; - GuiScreen gui = Minecraft.getMinecraft().currentScreen; - if (gui instanceof GuiChest) { - GuiChest eventGui = (GuiChest) gui; - ContainerChest cc = (ContainerChest) eventGui.inventorySlots; - String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); - - if (containerName.equals("Bank") && (getGamemode().gamemodeModifiers & MODIFIER_NOBANK) != 0) { - Minecraft.getMinecraft().thePlayer.closeScreen(); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "[NPC] Banker" + - EnumChatFormatting.WHITE + ": Hi, " + Minecraft.getMinecraft().thePlayer.getName() + - ", you would like to create an account and make a deposit?")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "[NPC] Banker" + - EnumChatFormatting.WHITE + ": Alright, I've invested your money into ...")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[" + - EnumChatFormatting.WHITE + "YouTube" + EnumChatFormatting.RED + "] Nullzee" + - EnumChatFormatting.WHITE + ": Hows it going everyone, welcome to my ultimate bazaar flipping guide ...")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "[NPC] Banker" + - EnumChatFormatting.WHITE + - ": Hmm, it seems as though the economy has crashed. All your money is gone. Poof. Vanished.")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "[IDIOT] You" + - EnumChatFormatting.WHITE + ": ... never again ...")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.AQUA + "(Use " + EnumChatFormatting.YELLOW + "/neugamemodes" + - EnumChatFormatting.AQUA + " if you would like to use the bank)")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - } else if (containerName.equals("Fairy") && (getGamemode().gamemodeModifiers & MODIFIER_DEVILISH) != 0) { - Minecraft.getMinecraft().thePlayer.closeScreen(); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "[NPC] " + EnumChatFormatting.LIGHT_PURPLE + "Tia the Fairy" + - EnumChatFormatting.WHITE + ": Oh no, " + Minecraft.getMinecraft().thePlayer.getName() + - ", you have sold your soul to the devil... please go away!")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.AQUA + "(Use " + EnumChatFormatting.YELLOW + "/neugamemodes" + - EnumChatFormatting.AQUA + " if you would like to use fairy souls)")); - } else if (!inDungeons && ironmanMode.isBanned(containerName)) { - Minecraft.getMinecraft().thePlayer.closeScreen(); - - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.AQUA + "You cannot access this inventory/menu because of your")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - " " + ironmanMode.display + EnumChatFormatting.AQUA + " status!")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.AQUA + "(Use " + EnumChatFormatting.YELLOW + "/neugamemodes" + - EnumChatFormatting.AQUA + " if you would like to downgrade the status)")); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); - } - } - } - - @SubscribeEvent - public void onChatMessage(ClientChatReceivedEvent event) { - if (event.type != 0) return; - - /*if(Keyboard.isKeyDown(Keyboard.KEY_K)) { - boolean has = false; - for(char c : event.message.getFormattedText().toCharArray()) { - if((int)c > 200) { - if(!has) System.out.println("-----START"); - has = true; - System.out.println((int)c); - } - } - if(has) System.out.println("-----END"); - }*/ - if (getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; - - String message = event.message.getFormattedText(); - if (message.contains("\u2620")) { //Death symbol ( ☠ ) - HardcoreMode hardcoreMode = getGamemode().hardcoreMode; - if (hardcoreMode != HardcoreMode.NORMAL) { - if (hardcoreMode.isExemption(message)) { - lastDeathExemption = System.currentTimeMillis(); - } - } - } - - if (System.currentTimeMillis() - lastDeathExemption > 1000 && - message.contains("!") && message.startsWith( - EnumChatFormatting.RESET.toString() + EnumChatFormatting.RED + "You died")) { - if (getGamemode().hardcoreMode != HardcoreMode.NORMAL) { - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED.toString() + EnumChatFormatting.OBFUSCATED + "AAA" + - EnumChatFormatting.RED + " You have lost your " + - getGamemode().hardcoreMode.display + EnumChatFormatting.RED + " status! " + - EnumChatFormatting.RED + EnumChatFormatting.OBFUSCATED + "AAA")); - getGamemode().hardcoreMode = HardcoreMode.NORMAL; - } - } - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java deleted file mode 100644 index bbdbabd2ab..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java +++ /dev/null @@ -1,534 +0,0 @@ -package io.github.moulberry.notenoughupdates.infopanes; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import io.github.moulberry.notenoughupdates.NEUManager; -import io.github.moulberry.notenoughupdates.NEUOverlay; -import io.github.moulberry.notenoughupdates.util.NEUResourceManager; -import io.github.moulberry.notenoughupdates.util.Utils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.shader.Framebuffer; -import net.minecraft.client.shader.Shader; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumChatFormatting; -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; - -import java.awt.*; -import java.util.List; -import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import static io.github.moulberry.notenoughupdates.util.GuiTextures.item_mask; - -public class CollectionLogInfoPane extends ScrollableInfoPane { - private final String mobRegex = ".*?((_MONSTER)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$"; - private final String petRegex = ".*?;[0-4]$"; - - TreeSet items = new TreeSet<>(getItemComparator()); - - private int buttonHover = -1; - - private int previousAcquiredCount = 0; - private int previousScroll = 0; - private int previousX = 0; - private int previousFilter = 0; - - private final long lastUpdate = 0; - - private static final int FILTER_ALL = 0; - private static final int FILTER_WEAPON = 1; - private static final int FILTER_ARMOR = 2; - private static final int FILTER_ACCESSORY = 3; - private static final int FILTER_PET = 4; - private static final int FILTER_DUNGEON = 5; - private static final int FILTER_SLAYER_ZOMBIE = 6; - private static final int FILTER_SLAYER_WOLF = 7; - private static final int FILTER_SLAYER_SPIDER = 8; - private int filterMode = FILTER_ALL; - private final String[] filterPrettyNames = new String[]{ - "ALL", "WEAPON", "ARMOR", - "ACCESSORY", "PET", "DUNGEON", "ZOMBIE SLAYER", "WOLF SLAYER", "SPIDER SLAYER" - }; - - private Framebuffer itemFramebuffer = null; - private Framebuffer itemBGFramebuffer = null; - private Framebuffer itemFramebufferGrayscale = null; - private Shader grayscaleShader = null; - - private final int updateCounter = 0; - - public CollectionLogInfoPane(NEUOverlay overlay, NEUManager manager) { - super(overlay, manager); - refreshItems(); - } - - private boolean loreContains(JsonArray lore, String str) { - for (int i = 0; i < lore.size(); i++) { - String line = lore.get(i).getAsString(); - if (line.contains(str)) return true; - } - return false; - } - - private void refreshItems() { - items.clear(); - for (String internalname : manager.getItemInformation().keySet()) { - if (!manager.auctionManager.isVanillaItem(internalname) && !internalname.matches(mobRegex)) { - JsonObject item = manager.getItemInformation().get(internalname); - JsonArray lore = manager.getItemInformation().get(internalname).get("lore").getAsJsonArray(); - switch (filterMode) { - case FILTER_WEAPON: - if (overlay.checkItemType(lore, "SWORD", "BOW", "WAND") < 0) continue; - break; - case FILTER_ARMOR: - if (overlay.checkItemType(lore, "HELMET", "CHESTPLATE", "LEGGINGS", "BOOTS") < 0) continue; - break; - case FILTER_ACCESSORY: - if (overlay.checkItemType(lore, "ACCESSORY") < 0) continue; - break; - case FILTER_PET: - if (!internalname.matches(petRegex) || !item.get("displayname").getAsString().contains("[")) - continue; - break; - case FILTER_DUNGEON: - if (Utils.checkItemType(lore, true, "DUNGEON") < 0) continue; - break; - case FILTER_SLAYER_ZOMBIE: - if (!item.has("slayer_req") || !item.get("slayer_req").getAsString().startsWith("ZOMBIE")) - continue; - break; - case FILTER_SLAYER_WOLF: - if (!item.has("slayer_req") || !item.get("slayer_req").getAsString().startsWith("WOLF")) - continue; - break; - case FILTER_SLAYER_SPIDER: - if (!item.has("slayer_req") || !item.get("slayer_req").getAsString().startsWith("SPIDER")) - continue; - break; - } - items.add(internalname); - } - } - } - - private Map> getAcquiredItems() { - return null;//manager.config.collectionLog.value; - } - - private Comparator getItemComparator() { - return (o1, o2) -> { - float cost1 = manager.auctionManager.getLowestBin(o1); - float cost2 = manager.auctionManager.getLowestBin(o2); - - if (cost1 == -1) cost1 = manager.auctionManager.getCraftCost(o1).craftCost; - if (cost2 == -1) cost2 = manager.auctionManager.getCraftCost(o2).craftCost; - - if (cost1 < cost2) return 1; - if (cost1 > cost2) return -1; - - return o1.compareTo(o2); - }; - } - - public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) { - super.mouseInput(width, height, mouseX, mouseY, mouseDown); - if (mouseDown) { - if (buttonHover == 0) { - if (Mouse.getEventButton() == 0) { - filterMode++; - if (filterMode >= filterPrettyNames.length) { - filterMode = 0; - } - } else if (Mouse.getEventButton() == 1) { - filterMode--; - if (filterMode < 0) { - filterMode = filterPrettyNames.length - 1; - } - } - } - refreshItems(); - } - } - - public void render( - int width, - int height, - Color bg, - Color fg, - ScaledResolution scaledresolution, - int mouseX, - int mouseY - ) { - int paneWidth = (int) (width / 3 * overlay.getWidthMult()); - int rightSide = (int) (width * overlay.getInfoPaneOffsetFactor()); - int leftSide = rightSide - paneWidth; - int padding = overlay.getBoxPadding(); - - renderDefaultBackground(width, height, bg); - - renderControls(height, padding, leftSide + padding, rightSide - padding, 20, fg); - renderCollectionLog(fg, width, height, leftSide + padding, rightSide - padding, padding + 25, height - padding); - } - - private float getCompletedness() { - int total = items.size(); - int own = 0; - for (String item : items) { - if (getAcquiredItems() != null && - getAcquiredItems().containsKey(manager.getCurrentProfile()) && - getAcquiredItems().get(manager.getCurrentProfile()).contains(item)) { - own++; - } - - } - return own / (float) total; - } - - private final EnumChatFormatting[] rainbow = new EnumChatFormatting[]{ - EnumChatFormatting.RED, - EnumChatFormatting.GOLD, - EnumChatFormatting.YELLOW, - EnumChatFormatting.GREEN, - EnumChatFormatting.AQUA, - EnumChatFormatting.LIGHT_PURPLE, - EnumChatFormatting.DARK_PURPLE - }; - - private String getCompletednessString() { - float completedness = getCompletedness(); - String text = (int) (completedness * 100) + "% Complete"; - if (completedness >= 1) { - StringBuilder rainbowText = new StringBuilder(); - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - int index = (int) (i - System.currentTimeMillis() / 100) % rainbow.length; - if (index < 0) index += rainbow.length; - rainbowText.append(rainbow[index]).append(c); - } - text = rainbowText.toString(); - } - return text; - } - - private void renderControls(int height, int top, int left, int right, int ySize, Color fg) { - ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); - - int mouseX = Mouse.getX() / scaledresolution.getScaleFactor(); - int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor(); - - buttonHover = -1; - - int totalAvailable = right - left; - int controlPadding = 3; - String[] controls = new String[]{ - "Filter: " + filterPrettyNames[filterMode], - getCompletednessString() - }; - int numControls = controls.length; - int available = totalAvailable - (numControls - 1) * controlPadding; - int controlSize = available / numControls; - int extraPadding = (available % controlSize) / 2; - - for (int i = 0; i < numControls; i++) { - int width = controlSize + controlPadding; - int x = left + extraPadding + i * width; - - if (mouseX > x && mouseX < x + controlSize) { - if (mouseY > top && mouseY < top + ySize) { - buttonHover = i; - } - } - - drawRect(x, top, x + controlSize, top + ySize, - new Color(177, 177, 177).getRGB() - ); - drawRect(x + 1, top + 1, x + controlSize, top + ySize, - new Color(50, 50, 50).getRGB() - ); - drawRect(x + 1, top + 1, x + controlSize - 1, top + ySize - 1, fg.getRGB()); - Utils.drawStringCenteredScaledMaxWidth(controls[i], Minecraft.getMinecraft().fontRendererObj, - x + width / 2f, top + ySize / 2f, true, controlSize - 4, Color.WHITE.getRGB() - ); - } - } - - public int getCurrentAcquiredCount() { - if (getAcquiredItems() == null) return 0; - if (!getAcquiredItems().containsKey(manager.getCurrentProfile())) return 0; - return getAcquiredItems().get(manager.getCurrentProfile()).size(); - } - - private void renderCollectionLog(Color fg, int width, int height, int left, int right, int top, int bottom) { - ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); - - int mouseX = Mouse.getX() / scaledresolution.getScaleFactor(); - int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor(); - - if (itemFramebuffer != null && grayscaleShader != null && - (itemFramebuffer.framebufferWidth != width || itemFramebuffer.framebufferHeight != height)) { - grayscaleShader.setProjectionMatrix(Utils.createProjectionMatrix( - width * scaledresolution.getScaleFactor(), height * scaledresolution.getScaleFactor())); - } - - itemFramebuffer = checkFramebufferSizes(itemFramebuffer, width, height, - scaledresolution.getScaleFactor() - ); - itemBGFramebuffer = checkFramebufferSizes(itemBGFramebuffer, width, height, - scaledresolution.getScaleFactor() - ); - itemFramebufferGrayscale = checkFramebufferSizes(itemFramebufferGrayscale, width, height, - scaledresolution.getScaleFactor() - ); - - /*if(!manager.config.cacheRenderedItempane.value || previousAcquiredCount != getCurrentAcquiredCount() || - previousScroll != scrollHeight.getValue() || previousX != left || previousFilter != filterMode || - System.currentTimeMillis() - lastUpdate > 5000) { - lastUpdate = System.currentTimeMillis(); - renderItemsToImage(itemFramebuffer, fg, left+5, right, top+1, bottom); - renderItemBGToImage(itemBGFramebuffer, fg, left+5, right, top+1, bottom); - }*/ - previousAcquiredCount = getCurrentAcquiredCount(); - previousScroll = scrollHeight.getValue(); - previousX = left; - previousFilter = filterMode; - - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - renderFromImage(itemBGFramebuffer, width, height, left, right, top, bottom); - renderFromImage(itemFramebuffer, width, height, left, right, top, bottom); - - if (grayscaleShader == null) { - try { - grayscaleShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()), - "grayscale", - itemFramebuffer, itemFramebufferGrayscale - ); - grayscaleShader.setProjectionMatrix(Utils.createProjectionMatrix( - width * scaledresolution.getScaleFactor(), height * scaledresolution.getScaleFactor())); - } catch (Exception e) { - return; - } - } - - GL11.glPushMatrix(); - grayscaleShader.loadShader(0); - GlStateManager.enableDepth(); - GL11.glPopMatrix(); - - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - - itemFramebufferGrayscale.bindFramebufferTexture(); - - AtomicReference tooltipToDisplay = new AtomicReference<>(null); - - AtomicBoolean isTop = new AtomicBoolean(false); - AtomicInteger lowestY = new AtomicInteger(-1); - - String[] items = getItemList(); - GlStateManager.color(1f, 1f, 1f, 1f); - iterateItemSlots(new ItemSlotConsumer() { - @Override - public void consume(int x, int y, int id) { - if (id < items.length) { - String internalname = items[id]; - if (id == 0) isTop.set(true); - - int leftI = x - 1; - int rightI = x + 17; - int topI = y - 1; - int bottomI = y + 17; - - lowestY.set(Math.max(bottomI, lowestY.get())); - - if (mouseX > leftI && mouseX < rightI) { - if (mouseY > topI && mouseY < bottomI) { - tooltipToDisplay.set(manager.jsonToStack(manager.getItemInformation().get(internalname), true)); - } - } - - if (getAcquiredItems() != null && - getAcquiredItems().containsKey(manager.getCurrentProfile()) && - getAcquiredItems().get(manager.getCurrentProfile()).contains(internalname)) { - return; - } - - topI = Math.max(topI, top); - bottomI = Math.min(bottomI, bottom); - - Utils.drawTexturedRect(leftI, topI, rightI - leftI, bottomI - topI, - leftI / (float) width, rightI / (float) width, - (height - topI) / (float) height, (height - bottomI) / (float) height - ); - } - } - }, left + 5, right, top + 1, bottom); - - if (!isTop.get()) { - if (lowestY.get() == -1) { - scrollHeight.setValue(0); - } else { - int dist = bottom - lowestY.get() - 10; - if (dist > 0) { - scrollHeight.setValue(scrollHeight.getValue() - dist); - } - } - } - - itemFramebufferGrayscale.unbindFramebufferTexture(); - - ItemStack displayStack = tooltipToDisplay.get(); - if (displayStack != null) { - List text = displayStack.getTooltip(Minecraft.getMinecraft().thePlayer, true); - Utils.drawHoveringText(text, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj); - } - } - - private String[] getItemList() { - String[] items_arr = new String[items.size()]; - int i = 0; - for (String internalname : items) { - items_arr[i++] = internalname; - } - return items_arr; - } - - private int limCol(int col) { - return Math.min(255, Math.max(0, col)); - } - - private void renderItems(int left, int right, int top, int bottom) { - String[] items = getItemList(); - iterateItemSlots(new ItemSlotConsumer() { - public void consume(int x, int y, int id) { - if (id < items.length) { - String internalname = items[id]; - - ItemStack stack = manager.jsonToStack(manager.getItemInformation().get(internalname)); - Utils.drawItemStack(stack, x, y); - } - } - }, left, right, top, bottom); - } - - private void renderItemBackgrounds(Color fg, int left, int right, int top, int bottom) { - Color fgCustomOpacity = - null;//new Color(SpecialColour.specialToChromaRGB(manager.config.itemBackgroundColour.value), true); - Color fgGold = null;//new Color(SpecialColour.specialToChromaRGB(manager.config.itemFavouriteColour.value), true); - - String[] items = getItemList(); - iterateItemSlots(new ItemSlotConsumer() { - public void consume(int x, int y, int id) { - if (id < items.length) { - String internalname = items[id]; - - Color color = fgCustomOpacity; - if (getAcquiredItems() != null && - getAcquiredItems().containsKey(manager.getCurrentProfile()) && - getAcquiredItems().get(manager.getCurrentProfile()).contains(internalname)) { - color = fgGold; - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask); - /*if(manager.config.itemStyle.value) { - GlStateManager.color(color.getRed() / 255f, color.getGreen() / 255f, - color.getBlue() / 255f, color.getAlpha() / 255f); - Utils.drawTexturedRect(x - 1, y - 1, overlay.ITEM_SIZE + 2, overlay.ITEM_SIZE + 2, GL11.GL_NEAREST); - } else { - drawRect(x-1, y-1, x+overlay.ITEM_SIZE+1, y+overlay.ITEM_SIZE+1, color.getRGB()); - }*/ - GlStateManager.bindTexture(0); - } - } - }, left, right, top, bottom); - } - - /** - * Checks whether the screen size has changed, if so it reconstructs the itemPane framebuffer and marks that the - * itemPane should be redrawn. - */ - private Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height, int scaleFactor) { - int sw = width * scaleFactor; - int sh = height * scaleFactor; - - if (framebuffer == null || framebuffer.framebufferWidth != sw || framebuffer.framebufferHeight != sh) { - if (framebuffer == null) { - framebuffer = new Framebuffer(sw, sh, true); - } else { - framebuffer.createBindFramebuffer(sw, sh); - } - framebuffer.setFramebufferFilter(GL11.GL_NEAREST); - } - return framebuffer; - } - - private void renderItemsToImage(Framebuffer framebuffer, Color fg, int left, int right, int top, int bottom) { - GL11.glPushMatrix(); - framebuffer.framebufferClear(); - framebuffer.bindFramebuffer(false); - - renderItems(left, right, top, bottom); - - framebuffer.unbindFramebuffer(); - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - GL11.glPopMatrix(); - } - - private void renderItemBGToImage(Framebuffer framebuffer, Color fg, int left, int right, int top, int bottom) { - GL11.glPushMatrix(); - framebuffer.framebufferClear(); - framebuffer.bindFramebuffer(false); - - renderItemBackgrounds(fg, left, right, top, bottom); - - framebuffer.unbindFramebuffer(); - Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true); - GL11.glPopMatrix(); - } - - private void renderFromImage( - Framebuffer framebuffer, - int width, - int height, - int left, - int right, - int top, - int bottom - ) { - framebuffer.bindFramebufferTexture(); - GlStateManager.color(1f, 1f, 1f, 1f); - Utils.drawTexturedRect(left, top, right - left, bottom - top, - left / (float) width, right / (float) width, - (height - top) / (float) height, (height - bottom) / (float) height - ); - framebuffer.unbindFramebufferTexture(); - } - - private abstract static class ItemSlotConsumer { - public abstract void consume(int x, int y, int id); - } - - public void iterateItemSlots(ItemSlotConsumer itemSlotConsumer, int left, int right, int top, int bottom) { - int scrolledTop = top - scrollHeight.getValue(); - - int id = 0; - int extraSize = NEUOverlay.ITEM_SIZE + NEUOverlay.ITEM_PADDING; - for (int y = scrolledTop; y < bottom; y += extraSize) { - for (int x = left; x < right - extraSize; x += extraSize) { - if (y > top - extraSize) { - itemSlotConsumer.consume(x, y, id); - } - if (++id >= items.size()) { - return; - } - } - } - } - - public boolean keyboardInput() { - return false; - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java new file mode 100644 index 0000000000..633cd80f92 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java @@ -0,0 +1,219 @@ +package io.github.moulberry.notenoughupdates.listener; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.dungeons.DungeonWin; +import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver; +import io.github.moulberry.notenoughupdates.miscfeatures.StreamerMode; +import io.github.moulberry.notenoughupdates.overlays.OverlayManager; +import io.github.moulberry.notenoughupdates.overlays.SlayerOverlay; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.event.ClickEvent; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.client.event.ClientChatReceivedEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static io.github.moulberry.notenoughupdates.overlays.SlayerOverlay.*; + +public class ChatListener { + private final NotEnoughUpdates neu; + private static final Pattern SLAYER_XP = Pattern.compile( + " (Spider|Zombie|Wolf|Enderman) Slayer LVL (\\d) - (?:Next LVL in ([\\d,]+) XP!|LVL MAXED OUT!)"); + AtomicBoolean missingRecipe = new AtomicBoolean(false); + + public ChatListener(NotEnoughUpdates neu) { + this.neu = neu; + } + + private String processText(String text) { + if (SBInfo.getInstance().getLocation() == null) return text; + if (!SBInfo.getInstance().getLocation().startsWith("mining_") && !SBInfo.getInstance().getLocation().equals( + "crystal_hollows")) + return text; + + if (Minecraft.getMinecraft().thePlayer == null) return text; + if (!NotEnoughUpdates.INSTANCE.config.mining.drillFuelBar) return text; + + return Utils.trimIgnoreColour(text.replaceAll(EnumChatFormatting.DARK_GREEN + "\\S+ Drill Fuel", "")); + } + + private IChatComponent processChatComponent(IChatComponent chatComponent) { + IChatComponent newComponent; + if (chatComponent instanceof ChatComponentText) { + ChatComponentText text = (ChatComponentText) chatComponent; + + newComponent = new ChatComponentText(processText(text.getUnformattedTextForChat())); + newComponent.setChatStyle(text.getChatStyle().createShallowCopy()); + + for (IChatComponent sibling : text.getSiblings()) { + newComponent.appendSibling(processChatComponent(sibling)); + } + } else if (chatComponent instanceof ChatComponentTranslation) { + ChatComponentTranslation trans = (ChatComponentTranslation) chatComponent; + + Object[] args = trans.getFormatArgs(); + Object[] newArgs = new Object[args.length]; + for (int i = 0; i < trans.getFormatArgs().length; i++) { + if (args[i] instanceof IChatComponent) { + newArgs[i] = processChatComponent((IChatComponent) args[i]); + } else { + newArgs[i] = args[i]; + } + } + newComponent = new ChatComponentTranslation(trans.getKey(), newArgs); + + for (IChatComponent sibling : trans.getSiblings()) { + newComponent.appendSibling(processChatComponent(sibling)); + } + } else { + newComponent = chatComponent.createCopy(); + } + + return newComponent; + } + + private IChatComponent replaceSocialControlsWithPV(IChatComponent chatComponent) { + + if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 > 0 && chatComponent.getChatStyle() != null && + chatComponent.getChatStyle().getChatClickEvent() != null && + chatComponent.getChatStyle().getChatClickEvent().getAction() == ClickEvent.Action.RUN_COMMAND && + NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { + if (chatComponent.getChatStyle().getChatClickEvent().getValue().startsWith("/socialoptions")) { + String username = chatComponent.getChatStyle().getChatClickEvent().getValue().substring(15); + if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 == 1) { + chatComponent.setChatStyle(Utils.createClickStyle( + ClickEvent.Action.RUN_COMMAND, + "/pv " + username, + "" + EnumChatFormatting.YELLOW + "Click to open " + EnumChatFormatting.AQUA + EnumChatFormatting.BOLD + + username + EnumChatFormatting.RESET + EnumChatFormatting.YELLOW + "'s profile in " + + EnumChatFormatting.DARK_PURPLE + EnumChatFormatting.BOLD + "NEU's" + EnumChatFormatting.RESET + + EnumChatFormatting.YELLOW + " profile viewer." + )); + return chatComponent; + } else if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 == 2) { + chatComponent.setChatStyle(Utils.createClickStyle( + ClickEvent.Action.RUN_COMMAND, + "/ah " + username, + "" + EnumChatFormatting.YELLOW + "Click to open " + EnumChatFormatting.AQUA + EnumChatFormatting.BOLD + + username + EnumChatFormatting.RESET + EnumChatFormatting.YELLOW + "'s /ah page" + )); + return chatComponent; + } + } // wanted to add this for guild but guild uses uuid :sad: + } + return chatComponent; + } + + /** + * 1) When receiving "You are playing on profile" messages, will set the current profile. + * 2) When a /viewrecipe command fails (i.e. player does not have recipe unlocked, will open the custom recipe GUI) + * 3) Replaces lobby join notifications when streamer mode is active + */ + @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true) + public void onGuiChat(ClientChatReceivedEvent e) { + if (e.type == 2) { + CrystalMetalDetectorSolver.process(e.message); + e.message = processChatComponent(e.message); + return; + } else if (e.type == 0) { + e.message = replaceSocialControlsWithPV(e.message); + } + + DungeonWin.onChatMessage(e); + + String r = null; + 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 + .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 + .substring("Your profile was changed to: ".length()) + .split(" ")[0].trim()); + } else if (unformatted.startsWith("Your new API key is ")) { + NotEnoughUpdates.INSTANCE.config.apiKey.apiKey = unformatted.substring("Your new API key is ".length()).substring( + 0, + 36 + ); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.YELLOW + "[NEU] API Key automatically configured")); + } else if (unformatted.startsWith("Player List Info is now disabled!")) { + SBInfo.getInstance().hasNewTab = false; + } else if (unformatted.startsWith("Player List Info is now enabled!")) { + SBInfo.getInstance().hasNewTab = true; + } + if (e.message.getFormattedText().equals( + EnumChatFormatting.RESET.toString() + EnumChatFormatting.RED + "You haven't unlocked this recipe!" + + EnumChatFormatting.RESET)) { + r = EnumChatFormatting.RED + "You haven't unlocked this recipe!"; + } else if (e.message.getFormattedText().startsWith( + EnumChatFormatting.RESET.toString() + EnumChatFormatting.RED + "Invalid recipe ")) { + r = ""; + } else if (unformatted.equals(" NICE! SLAYER BOSS SLAIN!")) { + SlayerOverlay.isSlain = true; + } else if (unformatted.equals(" SLAYER QUEST STARTED!")) { + SlayerOverlay.isSlain = false; + if (timeSinceLastBoss == 0) { + SlayerOverlay.timeSinceLastBoss = System.currentTimeMillis(); + } else { + timeSinceLastBoss2 = timeSinceLastBoss; + timeSinceLastBoss = System.currentTimeMillis(); + } + } else if (unformatted.startsWith(" RNGesus Meter:")) { + RNGMeter = unformatted.substring(" RNGesus Meter: -------------------- ".length()); + } else if (matcher.matches()) { + //matcher.group(1); + SlayerOverlay.slayerLVL = matcher.group(2); + if (!SlayerOverlay.slayerLVL.equals("9")) { + SlayerOverlay.slayerXp = matcher.group(3); + } else { + slayerXp = "maxed"; + } + } else if (unformatted.startsWith("Sending to server") || (unformatted.startsWith( + "Your Slayer Quest has been cancelled!"))) { + SlayerOverlay.slayerQuest = false; + SlayerOverlay.unloadOverlayTimer = System.currentTimeMillis(); + } + if (e.message.getFormattedText().contains( + EnumChatFormatting.YELLOW + "Visit the Auction House to collect your item!")) { + if (NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid != null && + System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBidMillis < 5000) { + NotEnoughUpdates.INSTANCE.sendChatMessage("/viewauction " + + NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.niceAucId(NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid)); + } + } + if (r != null) { + if (neu.manager.failViewItem(r)) { + e.setCanceled(true); + } + missingRecipe.set(true); + } + if (unformatted.startsWith("Sending to server") && neu.isOnSkyblock() && + NotEnoughUpdates.INSTANCE.config.misc.streamerMode && e.message instanceof ChatComponentText) { + String m = e.message.getFormattedText(); + String m2 = StreamerMode.filterChat(e.message.getFormattedText()); + if (!m.equals(m2)) { + e.message = new ChatComponentText(m2); + } + } + if (unformatted.startsWith("You found ") && SBInfo.getInstance().getLocation() != null && + SBInfo.getInstance().getLocation().equals("crystal_hollows")) { + CrystalMetalDetectorSolver.reset(true); + } + if (unformatted.startsWith("[NPC] Keeper of ") | unformatted.startsWith("[NPC] Professor Robot: ") || + unformatted.startsWith(" ") || unformatted.startsWith("✦") || unformatted.equals( + " You've earned a Crystal Loot Bundle!")) + OverlayManager.crystalHollowOverlay.message(unformatted); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java new file mode 100644 index 0000000000..5272914320 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java @@ -0,0 +1,980 @@ +package io.github.moulberry.notenoughupdates.listener; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import io.github.moulberry.notenoughupdates.ItemPriceInformation; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.MiscUtils; +import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; +import io.github.moulberry.notenoughupdates.miscgui.GuiEnchantColour; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StringUtils; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.apache.commons.lang3.text.WordUtils; +import org.lwjgl.input.Keyboard; + +import java.awt.*; +import java.awt.datatransfer.StringSelection; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.List; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ItemTooltipListener { + private static final String petToolTipRegex = + "((Farming)|(Combat)|(Fishing)|(Mining)|(Foraging)|(Enchanting)|(Alchemy)) ((Mount)|(Pet)|(Morph)).*"; + private final NotEnoughUpdates neu; + private final Pattern xpLevelPattern = Pattern.compile("(.*) (\\xA7e(.*)\\xA76/\\xA7e(.*))"); + private final HashSet percentStats = new HashSet<>(); + DecimalFormat myFormatter = new DecimalFormat("###,###.###"); + private String currentRarity = "COMMON"; + private boolean copied = false; + private boolean showReforgeStoneStats = true; + private boolean pressedArrowLast = false; + private boolean pressedShiftLast = false; + private int sbaloaded = -1; + + public ItemTooltipListener(NotEnoughUpdates neu) { + this.neu = neu; + percentStats.add("bonus_attack_speed"); + percentStats.add("crit_damage"); + percentStats.add("crit_chance"); + percentStats.add("sea_creature_chance"); + percentStats.add("ability_damage"); + } + + private boolean isSkyblockAddonsLoaded() { + if (sbaloaded == -1) { + if (Loader.isModLoaded("skyblockaddons")) { + sbaloaded = 1; + } else { + sbaloaded = 0; + } + } + return sbaloaded == 1; + } + + @SubscribeEvent(priority = EventPriority.LOW) + public void onItemTooltipLow(ItemTooltipEvent event) { + if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return; + + String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); + if (internalname == null) { + onItemToolTipInternalNameNull(event); + return; + } + + boolean hasEnchantments = event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").hasKey( + "enchantments", + 10 + ); + Set enchantIds = new HashSet<>(); + if (hasEnchantments) + enchantIds = + event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").getCompoundTag("enchantments").getKeySet(); + + JsonObject enchantsConst = Constants.ENCHANTS; + JsonArray allItemEnchs = null; + Set ignoreFromPool = new HashSet<>(); + if (enchantsConst != null && hasEnchantments && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) { + try { + JsonArray enchantPools = enchantsConst.get("enchant_pools").getAsJsonArray(); + for (JsonElement element : enchantPools) { + Set currentPool = new HashSet<>(); + for (JsonElement poolElement : element.getAsJsonArray()) { + String poolS = poolElement.getAsString(); + currentPool.add(poolS); + } + for (JsonElement poolElement : element.getAsJsonArray()) { + String poolS = poolElement.getAsString(); + if (enchantIds.contains(poolS)) { + ignoreFromPool.addAll(currentPool); + break; + } + } + } + + JsonObject enchantsObj = enchantsConst.get("enchants").getAsJsonObject(); + NBTTagCompound tag = event.itemStack.getTagCompound(); + if (tag != null) { + NBTTagCompound display = tag.getCompoundTag("display"); + if (display.hasKey("Lore", 9)) { + NBTTagList list = display.getTagList("Lore", 8); + out: + for (int i = list.tagCount(); i >= 0; i--) { + String line = list.getStringTagAt(i); + for (int j = 0; j < Utils.rarityArrC.length; j++) { + for (Map.Entry entry : enchantsObj.entrySet()) { + if (line.contains(Utils.rarityArrC[j] + " " + entry.getKey()) || line.contains( + Utils.rarityArrC[j] + " DUNGEON " + entry.getKey())) { + allItemEnchs = entry.getValue().getAsJsonArray(); + break out; + } + } + } + } + } + } + } catch (Exception ignored) { + } + } + + boolean gotToEnchants = false; + boolean passedEnchants = false; + + boolean dungeonProfit = false; + int index = 0; + List newTooltip = new ArrayList<>(); + + for (String line : event.toolTip) { + if (line.endsWith(EnumChatFormatting.DARK_GRAY + "Reforge Stone") && + NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showReforgeStats) { + JsonObject reforgeStones = Constants.REFORGESTONES; + + if (reforgeStones != null && reforgeStones.has(internalname)) { + boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + if (!pressedShiftLast && shift) { + showReforgeStoneStats = !showReforgeStoneStats; + } + pressedShiftLast = shift; + + newTooltip.add(line); + newTooltip.add(""); + if (!showReforgeStoneStats) { + newTooltip.add(EnumChatFormatting.DARK_GRAY + "[Press SHIFT to show extra info]"); + } else { + newTooltip.add(EnumChatFormatting.DARK_GRAY + "[Press SHIFT to hide extra info]"); + } + + JsonObject reforgeInfo = reforgeStones.get(internalname).getAsJsonObject(); + JsonArray requiredRaritiesArray = reforgeInfo.get("requiredRarities").getAsJsonArray(); + + if (showReforgeStoneStats && requiredRaritiesArray.size() > 0) { + String reforgeName = Utils.getElementAsString(reforgeInfo.get("reforgeName"), ""); + + String[] requiredRarities = new String[requiredRaritiesArray.size()]; + for (int i = 0; i < requiredRaritiesArray.size(); i++) { + requiredRarities[i] = requiredRaritiesArray.get(i).getAsString(); + } + + int rarityIndex = requiredRarities.length - 1; + String rarity = requiredRarities[rarityIndex]; + for (int i = 0; i < requiredRarities.length; i++) { + String rar = requiredRarities[i]; + if (rar.equalsIgnoreCase(currentRarity)) { + rarity = rar; + rarityIndex = i; + break; + } + } + + boolean left = Keyboard.isKeyDown(Keyboard.KEY_LEFT); + boolean right = Keyboard.isKeyDown(Keyboard.KEY_RIGHT); + if (!pressedArrowLast && (left || right)) { + if (left) { + rarityIndex--; + } else { + rarityIndex++; + } + if (rarityIndex < 0) rarityIndex = 0; + if (rarityIndex >= requiredRarities.length) rarityIndex = requiredRarities.length - 1; + currentRarity = requiredRarities[rarityIndex]; + rarity = currentRarity; + } + pressedArrowLast = left || right; + + JsonElement statsE = reforgeInfo.get("reforgeStats"); + + String rarityFormatted = Utils.rarityArrMap.getOrDefault(rarity, rarity); + + JsonElement reforgeAbilityE = reforgeInfo.get("reforgeAbility"); + String reforgeAbility = null; + if (reforgeAbilityE != null) { + if (reforgeAbilityE.isJsonPrimitive() && reforgeAbilityE.getAsJsonPrimitive().isString()) { + reforgeAbility = Utils.getElementAsString(reforgeInfo.get("reforgeAbility"), ""); + + } else if (reforgeAbilityE.isJsonObject()) { + if (reforgeAbilityE.getAsJsonObject().has(rarity)) { + reforgeAbility = reforgeAbilityE.getAsJsonObject().get(rarity).getAsString(); + } + } + } + + if (reforgeAbility != null && !reforgeAbility.isEmpty()) { + String text = EnumChatFormatting.BLUE + (reforgeName.isEmpty() ? "Bonus: " : reforgeName + " Bonus: ") + + EnumChatFormatting.GRAY + reforgeAbility; + boolean first = true; + for (String s : Minecraft.getMinecraft().fontRendererObj.listFormattedStringToWidth(text, 150)) { + newTooltip.add((first ? "" : " ") + s); + first = false; + } + newTooltip.add(""); + } + + newTooltip.add(EnumChatFormatting.BLUE + "Stats for " + rarityFormatted + + "\u00a79: [\u00a7l\u00a7m< \u00a79Switch\u00a7l\u27a1\u00a79]"); + + if (statsE != null && statsE.isJsonObject()) { + JsonObject stats = statsE.getAsJsonObject(); + + JsonElement statsRarE = stats.get(rarity); + if (statsRarE != null && statsRarE.isJsonObject()) { + + JsonObject statsRar = statsRarE.getAsJsonObject(); + + TreeSet> sorted = new TreeSet<>(Map.Entry.comparingByKey()); + sorted.addAll(statsRar.entrySet()); + + for (Map.Entry entry : sorted) { + if (entry.getValue().isJsonPrimitive() && ((JsonPrimitive) entry.getValue()).isNumber()) { + float statNumF = entry.getValue().getAsFloat(); + String statNumS; + if (statNumF % 1 == 0) { + statNumS = String.valueOf(Math.round(statNumF)); + } else { + statNumS = Utils.floatToString(statNumF, 1); + } + String reforgeNamePretty = WordUtils.capitalizeFully(entry.getKey().replace("_", " ")); + String text = + EnumChatFormatting.GRAY + reforgeNamePretty + ": " + EnumChatFormatting.GREEN + "+" + statNumS; + if (percentStats.contains(entry.getKey())) { + text += "%"; + } + newTooltip.add(" " + text); + } + } + } + } + + JsonElement reforgeCostsE = reforgeInfo.get("reforgeCosts"); + int reforgeCost = -1; + if (reforgeCostsE != null) { + if (reforgeCostsE.isJsonPrimitive() && reforgeCostsE.getAsJsonPrimitive().isNumber()) { + reforgeCost = (int) Utils.getElementAsFloat(reforgeInfo.get("reforgeAbility"), -1); + + } else if (reforgeCostsE.isJsonObject()) { + if (reforgeCostsE.getAsJsonObject().has(rarity)) { + reforgeCost = (int) Utils.getElementAsFloat(reforgeCostsE.getAsJsonObject().get(rarity), -1); + } + } + } + + if (reforgeCost >= 0) { + String text = EnumChatFormatting.BLUE + "Apply Cost: " + EnumChatFormatting.GOLD + + NumberFormat.getNumberInstance().format(reforgeCost) + " coins"; + newTooltip.add(""); + newTooltip.add(text); + } + + } + + continue; + } + + } else if (line.contains("\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune")) { + line = line.replace( + "\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune", + Utils.chromaString("Rainbow Rune", index, false) + EnumChatFormatting.BLUE + ); + } else if (hasEnchantments) { + if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && + NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) { + boolean lineHasEnch = false; + for (String s : enchantIds) { + String enchantName = WordUtils.capitalizeFully(s.replace("_", " ")); + if (line.contains(enchantName)) { + lineHasEnch = true; + break; + } + } + if (lineHasEnch) { + gotToEnchants = true; + } else { + if (gotToEnchants && !passedEnchants && Utils.cleanColour(line).trim().length() == 0) { + if (enchantsConst != null && allItemEnchs != null) { + List missing = new ArrayList<>(); + for (JsonElement enchIdElement : allItemEnchs) { + String enchId = enchIdElement.getAsString(); + if (!enchId.startsWith("ultimate_") && !ignoreFromPool.contains(enchId) && + !enchantIds.contains(enchId)) { + missing.add(enchId); + } + } + if (!missing.isEmpty()) { + newTooltip.add(""); + StringBuilder currentLine = new StringBuilder( + EnumChatFormatting.RED + "Missing: " + EnumChatFormatting.GRAY); + for (int i = 0; i < missing.size(); i++) { + String enchName = WordUtils.capitalizeFully(missing.get(i).replace("_", " ")); + if (currentLine.length() != 0 && + (Utils.cleanColour(currentLine.toString()).length() + enchName.length()) > 40) { + newTooltip.add(currentLine.toString()); + currentLine = new StringBuilder(); + } + if (currentLine.length() != 0 && i != 0) { + currentLine.append(", ").append(enchName); + } else { + currentLine.append(EnumChatFormatting.GRAY).append(enchName); + } + } + if (currentLine.length() != 0) { + newTooltip.add(currentLine.toString()); + } + } + } + passedEnchants = true; + } + } + } + for (String op : NotEnoughUpdates.INSTANCE.config.hidden.enchantColours) { + List colourOps = GuiEnchantColour.splitter.splitToList(op); + String enchantName = GuiEnchantColour.getColourOpIndex(colourOps, 0); + String comparator = GuiEnchantColour.getColourOpIndex(colourOps, 1); + String comparison = GuiEnchantColour.getColourOpIndex(colourOps, 2); + String colourCode = GuiEnchantColour.getColourOpIndex(colourOps, 3); + String modifier = GuiEnchantColour.getColourOpIndex(colourOps, 4); + + int modifierI = GuiEnchantColour.getIntModifier(modifier); + + assert enchantName != null; + if (enchantName.length() == 0) continue; + assert comparator != null; + if (comparator.length() == 0) continue; + assert comparison != null; + if (comparison.length() == 0) continue; + assert colourCode != null; + if (colourCode.length() == 0) continue; + + int comparatorI = ">=<".indexOf(comparator.charAt(0)); + + int levelToFind; + try { + levelToFind = Integer.parseInt(comparison); + } catch (Exception e) { + continue; + } + + if (comparatorI < 0) continue; + String regexText = "0123456789abcdefz"; + if (isSkyblockAddonsLoaded()) { + regexText = regexText + "Z"; + } + + if (regexText.indexOf(colourCode.charAt(0)) < 0) continue; + + //item_lore = item_lore.replaceAll("\\u00A79("+lvl4Max+" IV)", EnumChatFormatting.DARK_PURPLE+"$1"); + //9([a-zA-Z ]+?) ([0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X))(,|$) + Pattern pattern; + try { + pattern = Pattern.compile("(\\u00A79|\\u00A7(9|l)\\u00A7d\\u00A7l)(?" + enchantName + ") " + + "(?[0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV|XVI|XVII|XVIII|XIX|XX))((\\u00A79)?,|( \\u00A78(?:,?[0-9]+)*)?$)"); + } catch (Exception e) { + continue; + } //malformed regex + Matcher matcher = pattern.matcher(line); + int matchCount = 0; + while (matcher.find() && matchCount < 5) { + if (Utils.cleanColour(matcher.group("enchantName")).startsWith(" ")) continue; + + matchCount++; + int level = -1; + String levelStr = matcher.group("level"); + if (levelStr == null) continue; + try { + level = Integer.parseInt(levelStr); + } catch (Exception e) { + switch (levelStr) { + case "I": + level = 1; + break; + case "II": + level = 2; + break; + case "III": + level = 3; + break; + case "IV": + level = 4; + break; + case "V": + level = 5; + break; + case "VI": + level = 6; + break; + case "VII": + level = 7; + break; + case "VIII": + level = 8; + break; + case "IX": + level = 9; + break; + case "X": + level = 10; + break; + case "XI": + level = 11; + break; + case "XII": + level = 12; + break; + case "XIII": + level = 13; + break; + case "XIV": + level = 14; + break; + case "XV": + level = 15; + break; + case "XVI": + level = 16; + break; + case "XVII": + level = 17; + break; + case "XVIII": + level = 18; + break; + case "XIX": + level = 19; + break; + case "XX": + level = 20; + break; + } + } + boolean matches = false; + if (level > 0) { + switch (comparator) { + case ">": + matches = level > levelToFind; + break; + case "=": + matches = level == levelToFind; + break; + case "<": + matches = level < levelToFind; + break; + } + } + if (matches) { + String enchantText = matcher.group("enchantName"); + StringBuilder extraModifiersBuilder = new StringBuilder(); + + if ((modifierI & GuiEnchantColour.BOLD_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.BOLD); + } + if ((modifierI & GuiEnchantColour.ITALIC_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.ITALIC); + } + if ((modifierI & GuiEnchantColour.UNDERLINE_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.UNDERLINE); + } + if ((modifierI & GuiEnchantColour.OBFUSCATED_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.OBFUSCATED); + } + if ((modifierI & GuiEnchantColour.STRIKETHROUGH_MODIFIER) != 0) { + extraModifiersBuilder.append(EnumChatFormatting.STRIKETHROUGH); + } + + String extraMods = extraModifiersBuilder.toString(); + + if (!colourCode.equals("z")) { + line = line.replace("\u00A79" + enchantText, "\u00A7" + colourCode + extraMods + enchantText); + line = line.replace( + "\u00A79\u00A7d\u00A7l" + enchantText, + "\u00A7" + colourCode + extraMods + enchantText + ); + line = line.replace( + "\u00A7l\u00A7d\u00A7l" + enchantText, + "\u00A7" + colourCode + extraMods + enchantText + ); + } else { + int offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( + "\\u00A79" + enchantText + ".*", + "" + )); + line = line.replace( + "\u00A79" + enchantText, + Utils.chromaString(enchantText, offset / 12f + index, false) + ); + + offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( + "\\u00A79\\u00A7d\\u00A7l" + enchantText + ".*", + "" + )); + line = line.replace( + "\u00A79\u00A7d\u00A7l" + enchantText, + Utils.chromaString(enchantText, offset / 12f + index, true) + ); + offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll( + "\\u00A7l\\u00A7d\\u00A7l" + enchantText + ".*", + "" + )); + line = line.replace( + "\u00A7l\u00A7d\u00A7l" + enchantText, + Utils.chromaString(enchantText, offset / 12f + index, true) + ); + } + } + } + } + } + + newTooltip.add(line); + + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoAucItem) { + if (line.contains(EnumChatFormatting.GRAY + "Buy it now: ") || line.contains( + EnumChatFormatting.GRAY + "Bidder: ") || line.contains(EnumChatFormatting.GRAY + "Starting bid: ")) { + + if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { + newTooltip.add(""); + newTooltip.add(EnumChatFormatting.GRAY + "[SHIFT for Price Info]"); + } else { + ItemPriceInformation.addToTooltip(newTooltip, internalname, event.itemStack); + } + } + } + + if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 2 && + Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + if (line.contains(EnumChatFormatting.GREEN + "Open Reward Chest")) { + dungeonProfit = true; + } else if (index == 7 && dungeonProfit) { + GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + int chestCost = 0; + try { + String line6 = Utils.cleanColour(line); + StringBuilder cost = new StringBuilder(); + for (int i = 0; i < line6.length(); i++) { + char c = line6.charAt(i); + if ("0123456789".indexOf(c) >= 0) { + cost.append(c); + } + } + if (cost.length() > 0) { + chestCost = Integer.parseInt(cost.toString()); + } + } catch (Exception ignored) { + } + + String missingItem = null; + int totalValue = 0; + HashMap itemValues = new HashMap<>(); + for (int i = 0; i < 5; i++) { + ItemStack item = lower.getStackInSlot(11 + i); + String internal = neu.manager.getInternalNameForItem(item); + if (internal != null) { + internal = internal.replace("\u00CD", "I").replace("\u0130", "I"); + float bazaarPrice = -1; + JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal); + if (bazaarInfo != null && bazaarInfo.has("curr_sell")) { + bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat(); + } + if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000; + + float worth = -1; + if (bazaarPrice > 0) { + worth = bazaarPrice; + } else { + switch (NotEnoughUpdates.INSTANCE.config.dungeons.profitType) { + case 1: + worth = neu.manager.auctionManager.getItemAvgBin(internal); + break; + case 2: + JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); + if (auctionInfo != null) { + if (auctionInfo.has("clean_price")) { + worth = (int) auctionInfo.get("clean_price").getAsFloat(); + } else { + worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + } + } + break; + default: + worth = neu.manager.auctionManager.getLowestBin(internal); + } + if (worth <= 0) { + worth = neu.manager.auctionManager.getLowestBin(internal); + if (worth <= 0) { + worth = neu.manager.auctionManager.getItemAvgBin(internal); + if (worth <= 0) { + JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); + if (auctionInfo != null) { + if (auctionInfo.has("clean_price")) { + worth = (int) auctionInfo.get("clean_price").getAsFloat(); + } else { + worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + } + } + } + } + } + } + + if (worth > 0 && totalValue >= 0) { + totalValue += worth; + + String display = item.getDisplayName(); + + if (display.contains("Enchanted Book")) { + NBTTagCompound tag = item.getTagCompound(); + if (tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + NBTTagCompound enchants = ea.getCompoundTag("enchantments"); + + int highestLevel = -1; + for (String enchname : enchants.getKeySet()) { + int level = enchants.getInteger(enchname); + if (level > highestLevel) { + display = EnumChatFormatting.BLUE + WordUtils.capitalizeFully(enchname + .replace("_", " ") + .replace("Ultimate", "") + .trim()) + " " + level; + } + } + } + } + + itemValues.put(display, worth); + } else { + if (totalValue != -1) { + missingItem = internal; + } + totalValue = -1; + } + } + } + + NumberFormat format = NumberFormat.getInstance(Locale.US); + String valueStringBIN1; + String valueStringBIN2; + if (totalValue >= 0) { + valueStringBIN1 = EnumChatFormatting.YELLOW + "Value (BIN): "; + valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins"; + } else { + valueStringBIN1 = EnumChatFormatting.YELLOW + "Can't find BIN: "; + valueStringBIN2 = missingItem; + } + + int profitLossBIN = totalValue - chestCost; + String profitPrefix = EnumChatFormatting.DARK_GREEN.toString(); + String lossPrefix = EnumChatFormatting.RED.toString(); + String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix; + + String plStringBIN; + if (profitLossBIN >= 0) { + plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins"; + } else { + plStringBIN = prefix + "-" + format.format(-profitLossBIN) + " coins"; + } + + String neu = EnumChatFormatting.YELLOW + "[NEU] "; + + newTooltip.add(neu + valueStringBIN1 + " " + valueStringBIN2); + if (totalValue >= 0) { + newTooltip.add(neu + EnumChatFormatting.YELLOW + "Profit/Loss: " + plStringBIN); + } + + for (Map.Entry entry : itemValues.entrySet()) { + newTooltip.add(neu + entry.getKey() + prefix + "+" + format.format(entry.getValue().intValue())); + } + } + } + + index++; + } + + for (int i = newTooltip.size() - 1; i >= 0; i--) { + String line = Utils.cleanColour(newTooltip.get(i)); + for (int i1 = 0; i1 < Utils.rarityArr.length; i1++) { + if (line.equals(Utils.rarityArr[i1])) { + if (i - 2 < 0) { + break; + } + newTooltip.addAll(i - 1, petToolTipXPExtend(event)); + break; + } + } + } + + pressedShiftLast = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + pressedArrowLast = Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_RIGHT); + + event.toolTip.clear(); + event.toolTip.addAll(newTooltip); + + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoInvItem) { + ItemPriceInformation.addToTooltip(event.toolTip, internalname, event.itemStack); + } + + if (event.itemStack.getTagCompound() != null && event.itemStack.getTagCompound().getBoolean("NEUHIDEPETTOOLTIP") && + NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip) { + event.toolTip.clear(); + } + } + + private void onItemToolTipInternalNameNull(ItemTooltipEvent event) { + petToolTipXPExtendPetMenu(event); + } + + private List petToolTipXPExtend(ItemTooltipEvent event) { + List tooltipText = new ArrayList<>(); + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) { + if (event.itemStack.getTagCompound().hasKey("DisablePetExp")) { + if (event.itemStack.getTagCompound().getBoolean("DisablePetExp")) { + return tooltipText; + } + } + //7 is just a random number i chose, prob no pets with less lines than 7 + if (event.toolTip.size() > 7) { + if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) { + + GuiProfileViewer.PetLevel petlevel = null; + + //this is the item itself + NBTTagCompound tag = event.itemStack.getTagCompound(); + if (tag.hasKey("ExtraAttributes")) { + if (tag.getCompoundTag("ExtraAttributes").hasKey("petInfo")) { + JsonObject petInfo = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(tag + .getCompoundTag("ExtraAttributes") + .getString("petInfo"), JsonObject.class); + if (petInfo.has("exp") && petInfo.get("exp").isJsonPrimitive()) { + JsonPrimitive exp = petInfo.getAsJsonPrimitive("exp"); + String petName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); + //Utils.getRarityFromInt(Utils.checkItemTypePet(event.toolTip))).getAsInt(); + petlevel = GuiProfileViewer.getPetLevel( + petName, + Utils.getRarityFromInt(Utils.checkItemTypePet(event.toolTip)), + exp.getAsLong() + ); + } + } + } + + if (petlevel != null) { + tooltipText.add(""); + if (petlevel.totalXp > petlevel.maxXP) { + tooltipText.add(EnumChatFormatting.AQUA + "" + EnumChatFormatting.BOLD + "MAX LEVEL"); + } else { + tooltipText.add( + EnumChatFormatting.GRAY + "Progress to Level " + (int) Math.floor(petlevel.level + 1) + ": " + + EnumChatFormatting.YELLOW + Utils.round(petlevel.levelPercentage * 100, 1) + "%"); + int levelpercentage = Math.round(petlevel.levelPercentage * 20); + tooltipText.add( + EnumChatFormatting.DARK_GREEN + String.join("", Collections.nCopies(levelpercentage, "-")) + + EnumChatFormatting.WHITE + String.join("", Collections.nCopies(20 - levelpercentage, "-"))); + tooltipText.add( + EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.levelXp) + + EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + + myFormatter.format(petlevel.currentLevelRequirement) + " EXP"); + } + } + } + } + } + return tooltipText; + } + + private void petToolTipXPExtendPetMenu(ItemTooltipEvent event) { + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) { + //7 is just a random number i chose, prob no pets with less lines than 7 + if (event.toolTip.size() > 7) { + if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) { + GuiProfileViewer.PetLevel petLevel; + + int xpLine = -1; + for (int i = event.toolTip.size() - 1; i >= 0; i--) { + Matcher matcher = xpLevelPattern.matcher(event.toolTip.get(i)); + if (matcher.matches()) { + xpLine = i; + event.toolTip.set(xpLine, matcher.group(1)); + break; + } else if (event.toolTip.get(i).matches("MAX LEVEL")) { + return; + } + } + + PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack( + event.itemStack.getDisplayName(), + NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(event.itemStack.getTagCompound()) + ); + if (pet == null) { + return; + } + petLevel = pet.petLevel; + + if (petLevel == null || xpLine == -1) { + return; + } + + event.toolTip.add( + xpLine + 1, + EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petLevel.levelXp) + + EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + + myFormatter.format(petLevel.currentLevelRequirement) + ); + + } + } + } + } + + /** + * This method does the following: + * Move the pet inventory display tooltip to the left to avoid conflicts + * Remove reforge stats for Legendary items from Hypixel if enabled + * Show NBT data when holding LCONTROL + */ + @SubscribeEvent + public void onItemTooltip(ItemTooltipEvent event) { + if (!neu.isOnSkyblock()) return; + if (event.toolTip == null) return; + //Render the pet inventory display tooltip to the left to avoid things from other mods rendering over the tooltip + if (event.itemStack.getTagCompound() != null && event.itemStack.getTagCompound().getBoolean("NEUPETINVDISPLAY")) { + GlStateManager.translate(-200, 0, 0); + } + + if (event.toolTip.size() > 2 && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.hideDefaultReforgeStats) { + String secondLine = StringUtils.stripControlCodes(event.toolTip.get(1)); + if (secondLine.equals("Reforge Stone")) { + Integer startIndex = null; + Integer cutoffIndex = null; + //loop from the back of the List to find the wanted index sooner + for (int i = event.toolTip.size() - 1; i >= 0; i--) { + //rarity or mining level requirement + String line = StringUtils.stripControlCodes(event.toolTip.get(i)); + if (line.contains("REFORGE STONE") || line.contains("Requires Mining Skill Level")) { + cutoffIndex = i; + } + + //The line where the Hypixel stats start + if (line.contains("(Legendary):")) { + startIndex = i; + break; + } + } + if (startIndex != null && cutoffIndex != null && startIndex < cutoffIndex) { + event.toolTip.subList(startIndex, cutoffIndex).clear(); + } + } + } + + if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) && NotEnoughUpdates.INSTANCE.config.hidden.dev && + event.toolTip.size() > 0 && event.toolTip.get(event.toolTip.size() - 1).startsWith( + EnumChatFormatting.DARK_GRAY + "NBT: ")) { + event.toolTip.remove(event.toolTip.size() - 1); + + StringBuilder sb = new StringBuilder(); + String nbt = event.itemStack.getTagCompound().toString(); + int indent = 0; + for (char c : nbt.toCharArray()) { + boolean newline = false; + if (c == '{' || c == '[') { + indent++; + newline = true; + } else if (c == '}' || c == ']') { + indent--; + sb.append("\n"); + for (int i = 0; i < indent; i++) sb.append(" "); + } else if (c == ',') { + newline = true; + } else if (c == '\"') { + sb.append(EnumChatFormatting.RESET).append(EnumChatFormatting.GRAY); + } + + sb.append(c); + if (newline) { + sb.append("\n"); + for (int i = 0; i < indent; i++) sb.append(" "); + } + } + event.toolTip.add(sb.toString()); + if (Keyboard.isKeyDown(Keyboard.KEY_H)) { + if (!copied) { + copied = true; + StringSelection selection = new StringSelection(sb.toString()); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); + } + } else { + copied = false; + } + } else if (NotEnoughUpdates.INSTANCE.packDevEnabled) { + event.toolTip.add(""); + event.toolTip.add(EnumChatFormatting.AQUA + "NEU Pack Dev Info:"); + event.toolTip.add("Press " + EnumChatFormatting.GOLD + "[KEY]" + EnumChatFormatting.GRAY + " to copy line"); + + String internal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack); + + boolean k = Keyboard.isKeyDown(Keyboard.KEY_K); + boolean m = Keyboard.isKeyDown(Keyboard.KEY_M); + boolean n = Keyboard.isKeyDown(Keyboard.KEY_N); + + event.toolTip.add( + EnumChatFormatting.AQUA + "Internal Name: " + EnumChatFormatting.GRAY + internal + EnumChatFormatting.GOLD + + " [K]"); + if (!copied && k) { + MiscUtils.copyToClipboard(internal); + } + + if (event.itemStack.getTagCompound() != null) { + NBTTagCompound tag = event.itemStack.getTagCompound(); + + if (tag.hasKey("SkullOwner", 10)) { + GameProfile gameprofile = NBTUtil.readGameProfileFromNBT(tag.getCompoundTag("SkullOwner")); + + if (gameprofile != null) { + event.toolTip.add(EnumChatFormatting.AQUA + "Skull UUID: " + EnumChatFormatting.GRAY + gameprofile.getId() + + EnumChatFormatting.GOLD + " [M]"); + if (!copied && m) { + MiscUtils.copyToClipboard(gameprofile.getId().toString()); + } + + Map map = + Minecraft.getMinecraft().getSkinManager().loadSkinFromCache(gameprofile); + + if (map.containsKey(MinecraftProfileTexture.Type.SKIN)) { + MinecraftProfileTexture profTex = map.get(MinecraftProfileTexture.Type.SKIN); + event.toolTip.add( + EnumChatFormatting.AQUA + "Skull Texture Link: " + EnumChatFormatting.GRAY + profTex.getUrl() + + EnumChatFormatting.GOLD + " [N]"); + + if (!copied && n) { + MiscUtils.copyToClipboard(profTex.getUrl()); + } + } + } + } + } + + copied = k || m || n; + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java new file mode 100644 index 0000000000..ffebdd6b7c --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java @@ -0,0 +1,328 @@ +package io.github.moulberry.notenoughupdates.listener; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.BackgroundBlur; +import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; +import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks; +import io.github.moulberry.notenoughupdates.dungeons.DungeonWin; +import io.github.moulberry.notenoughupdates.miscfeatures.*; +import io.github.moulberry.notenoughupdates.miscgui.AccessoryBagOverlay; +import io.github.moulberry.notenoughupdates.miscgui.GuiCustomEnchant; +import io.github.moulberry.notenoughupdates.miscgui.StorageOverlay; +import io.github.moulberry.notenoughupdates.overlays.OverlayManager; +import io.github.moulberry.notenoughupdates.overlays.TextOverlay; +import io.github.moulberry.notenoughupdates.util.*; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiChat; +import net.minecraft.client.gui.GuiScreenBook; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.gui.inventory.GuiEditSign; +import net.minecraft.event.ClickEvent; +import net.minecraft.init.Items; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.input.Keyboard; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static io.github.moulberry.notenoughupdates.util.NotificationHandler.notificationLines; + +public class NEUEventListener { + + private static long notificationDisplayMillis = 0; + private final NotEnoughUpdates neu; + private final ExecutorService itemPreloader = Executors.newFixedThreadPool(10); + private final List toPreload = new ArrayList<>(); + /** + * When opening a GuiContainer, will reset the overlay and load the config. + * When closing a GuiContainer, will save the config. + * Also includes a dev feature used for automatically acquiring crafting information from the "Crafting Table" GUI. + */ + private boolean joinedSB = false; + + private boolean preloadedItems = false; + private long lastLongUpdate = 0; + private long lastSkyblockScoreboard = 0; + + public NEUEventListener(NotEnoughUpdates neu) { + this.neu = neu; + } + + private void displayUpdateMessageIfOutOfDate() { + File repo = neu.manager.repoLocation; + if (repo.exists()) { + File updateJson = new File(repo, "update.json"); + try { + JsonObject o = neu.manager.getJsonFromFile(updateJson); + + String version = o.get("version").getAsString(); + String preVersion = o.get("pre_version").getAsString(); + + boolean shouldUpdate = !NotEnoughUpdates.VERSION.equalsIgnoreCase(version); + boolean shouldPreUpdate = !NotEnoughUpdates.PRE_VERSION.equalsIgnoreCase(preVersion); + + if (o.has("version_id") && o.get("version_id").isJsonPrimitive()) { + int version_id = o.get("version_id").getAsInt(); + shouldUpdate = version_id > NotEnoughUpdates.VERSION_ID; + } + if (o.has("pre_version_id") && o.get("pre_version_id").isJsonPrimitive()) { + int pre_version_id = o.get("pre_version_id").getAsInt(); + shouldPreUpdate = pre_version_id > NotEnoughUpdates.PRE_VERSION_ID; + } + + if (shouldUpdate) { + String update_msg = o.get("update_msg").getAsString(); + + int first_len = -1; + for (String line : update_msg.split("\n")) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int len = fr.getStringWidth(line); + if (first_len == -1) { + first_len = len; + } + int missing_len = first_len - len; + if (missing_len > 0) { + StringBuilder sb = new StringBuilder(line); + for (int i = 0; i < missing_len / 8; i++) { + sb.insert(0, " "); + } + line = sb.toString(); + } + line = line.replaceAll("\\{version}", version); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line)); + } + + neu.displayLinks(o); + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + } else if (shouldPreUpdate && NotEnoughUpdates.VERSION_ID == o.get("version").getAsInt()) { + String pre_update_msg = o.get("pre_update_msg").getAsString(); + + int first_len = -1; + for (String line : pre_update_msg.split("\n")) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int len = fr.getStringWidth(line); + if (first_len == -1) { + first_len = len; + } + int missing_len = first_len - len; + if (missing_len > 0) { + StringBuilder sb = new StringBuilder(line); + for (int i = 0; i < missing_len / 8; i++) { + sb.insert(0, " "); + } + line = sb.toString(); + } + line = line.replaceAll("\\{pre_version}", preVersion); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line)); + } + + neu.displayLinks(o); + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("")); + } + } catch (Exception ignored) { + } + } + } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Unload event) { + NotEnoughUpdates.INSTANCE.saveConfig(); + CrystalMetalDetectorSolver.reset(false); + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + if (Minecraft.getMinecraft().theWorld == null) return; + if (Minecraft.getMinecraft().thePlayer == null) return; + Keyboard.enableRepeatEvents(Minecraft.getMinecraft().currentScreen != null && + (Minecraft.getMinecraft().currentScreen instanceof GuiChat || + Minecraft.getMinecraft().currentScreen instanceof GuiEditSign || + Minecraft.getMinecraft().currentScreen instanceof GuiScreenBook)); + + if ((Keyboard.isKeyDown(Keyboard.KEY_NUMPAD1) && Keyboard.isKeyDown(Keyboard.KEY_NUMPAD4) && Keyboard.isKeyDown( + Keyboard.KEY_NUMPAD9))) { + ChatComponentText component = new ChatComponentText("\u00a7cYou are permanently banned from this server!"); + component.appendText("\n"); + component.appendText("\n\u00a77Reason: \u00a7rSuspicious account activity/Other"); + component.appendText("\n\u00a77Find out more: \u00a7b\u00a7nhttps://www.hypixel.net/appeal"); + component.appendText("\n"); + component.appendText("\n\u00a77Ban ID: \u00a7r#49871982"); + component.appendText("\n\u00a77Sharing your Ban ID may affect the processing of your appeal!"); + Minecraft.getMinecraft().getNetHandler().getNetworkManager().closeChannel(component); + return; + } + + if (neu.hasSkyblockScoreboard()) { + if (!preloadedItems) { + preloadedItems = true; + List list = new ArrayList<>(neu.manager.getItemInformation().values()); + for (JsonObject json : list) { + itemPreloader.submit(() -> { + ItemStack stack = neu.manager.jsonToStack(json, true, true); + if (stack.getItem() == Items.skull) toPreload.add(stack); + }); + } + } else if (!toPreload.isEmpty()) { + Utils.drawItemStack(toPreload.get(0), -100, -100); + toPreload.remove(0); + } else { + itemPreloader.shutdown(); + } + + for (TextOverlay overlay : OverlayManager.textOverlays) { + overlay.shouldUpdateFrequent = true; + } + } + + boolean longUpdate = false; + long currentTime = System.currentTimeMillis(); + if (currentTime - lastLongUpdate > 1000) { + longUpdate = true; + lastLongUpdate = currentTime; + } + if (!NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) { + DungeonBlocks.tick(); + } + DungeonWin.tick(); + + String containerName = null; + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + + if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) { + GuiCustomEnchant.getInstance().tick(); + } + } + + if (longUpdate) { + CrystalOverlay.tick(); + FairySouls.tick(); + XPInformation.getInstance().tick(); + ProfileApiSyncer.getInstance().tick(); + ItemCustomizeManager.tick(); + BackgroundBlur.markDirty(); + NPCRetexturing.getInstance().tick(); + StorageOverlay.getInstance().markDirty(); + + if (neu.hasSkyblockScoreboard()) { + for (TextOverlay overlay : OverlayManager.textOverlays) { + overlay.tick(); + } + } + + NotEnoughUpdates.INSTANCE.overlay.redrawItems(); + CapeManager.onTickSlow(); + + NotEnoughUpdates.profileViewer.putNameUuid( + Minecraft.getMinecraft().thePlayer.getName(), + Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "") + ); + + if (NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) { + DungeonBlocks.tick(); + } + + if (System.currentTimeMillis() - SBInfo.getInstance().joinedWorld > 500 && + System.currentTimeMillis() - SBInfo.getInstance().unloadedWorld > 500) { + neu.updateSkyblockScoreboard(); + } + CapeManager.getInstance().tick(); + + if (containerName != null) { + if (!containerName.trim().startsWith("Accessory Bag")) { + AccessoryBagOverlay.resetCache(); + } + } else { + AccessoryBagOverlay.resetCache(); + } + + if (neu.hasSkyblockScoreboard()) { + SBInfo.getInstance().tick(); + lastSkyblockScoreboard = currentTime; + if (!joinedSB) { + joinedSB = true; + + //SBGamemodes.loadFromFile(); + + if (NotEnoughUpdates.INSTANCE.config.notifications.showUpdateMsg) { + displayUpdateMessageIfOutOfDate(); + } + + if (NotEnoughUpdates.INSTANCE.config.notifications.doRamNotif) { + long maxMemoryMB = Runtime.getRuntime().maxMemory() / 1024L / 1024L; + if (maxMemoryMB > 4100) { + notificationDisplayMillis = System.currentTimeMillis(); + notificationLines = new ArrayList<>(); + notificationLines.add(EnumChatFormatting.GRAY + "Too much memory allocated!"); + notificationLines.add(String.format( + EnumChatFormatting.DARK_GRAY + "NEU has detected %03dMB of memory allocated to Minecraft!", + maxMemoryMB + )); + notificationLines.add(EnumChatFormatting.GRAY + "It is recommended to allocated between 2-4GB of memory"); + notificationLines.add( + EnumChatFormatting.GRAY + "More than 4GB MAY cause FPS issues, EVEN if you have 16GB+ available"); + notificationLines.add(""); + notificationLines.add( + EnumChatFormatting.GRAY + "For more information, visit #ram-info in discord.gg/moulberry"); + } + } + + 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")); + } 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.")); + 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("")); + 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("")); + } + } + } + if (currentTime - lastSkyblockScoreboard < 5 * 60 * 1000) { //5 minutes + neu.manager.auctionManager.tick(); + } else { + neu.manager.auctionManager.markNeedsUpdate(); + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java new file mode 100644 index 0000000000..9c12e7323a --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java @@ -0,0 +1,1183 @@ +package io.github.moulberry.notenoughupdates.listener; + +import com.google.common.collect.Lists; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NEUApi; +import io.github.moulberry.notenoughupdates.NEUOverlay; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.auction.CustomAHGui; +import io.github.moulberry.notenoughupdates.commands.profile.ViewProfileCommand; +import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper; +import io.github.moulberry.notenoughupdates.dungeons.DungeonWin; +import io.github.moulberry.notenoughupdates.miscfeatures.AuctionBINWarning; +import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers; +import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver; +import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager; +import io.github.moulberry.notenoughupdates.miscgui.*; +import io.github.moulberry.notenoughupdates.options.NEUConfig; +import io.github.moulberry.notenoughupdates.overlays.AuctionSearchOverlay; +import io.github.moulberry.notenoughupdates.overlays.OverlayManager; +import io.github.moulberry.notenoughupdates.overlays.RancherBootOverlay; +import io.github.moulberry.notenoughupdates.overlays.TextOverlay; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; +import io.github.moulberry.notenoughupdates.util.NotificationHandler; +import io.github.moulberry.notenoughupdates.util.RequestFocusListener; +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 net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiEditSign; +import net.minecraft.client.gui.inventory.GuiInventory; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +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.minecraftforge.client.ClientCommandHandler; +import net.minecraftforge.client.event.*; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.apache.commons.lang3.text.WordUtils; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import javax.swing.*; +import java.io.IOException; +import java.text.NumberFormat; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import static io.github.moulberry.notenoughupdates.util.GuiTextures.dungeon_chest_worth; + +public class RenderListener { + private static final ResourceLocation EDITOR = new ResourceLocation("notenoughupdates:invbuttons/editor.png"); + public static boolean disableCraftingText = false; + public static boolean drawingGuiScreen = false; + public static long lastGuiClosed = 0; + public static boolean inventoryLoaded = false; + private final NotEnoughUpdates neu; + ScheduledExecutorService ses = Executors.newScheduledThreadPool(1); + JsonObject essenceJson = new JsonObject(); + private boolean hoverInv = false; + private boolean focusInv = false; + private boolean doInventoryButtons = false; + private NEUConfig.InventoryButton buttonHovered = null; + private long buttonHoveredMillis = 0; + private int inventoryLoadedTicks = 0; + private String loadedInvName = ""; + + public RenderListener(NotEnoughUpdates neu) { + this.neu = neu; + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + public void onRenderEntitySpecials(RenderLivingEvent.Specials.Pre event) { + if (Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer) { + if (((GuiProfileViewer) Minecraft.getMinecraft().currentScreen).getEntityPlayer() == event.entity) { + event.setCanceled(true); + } + } + } + + @SubscribeEvent + public void onRenderGameOverlayPre(RenderGameOverlayEvent.Pre event) { + if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.BOSSHEALTH) && + Minecraft.getMinecraft().currentScreen instanceof GuiContainer && neu.overlay.isUsingMobsFilter()) { + event.setCanceled(true); + } + if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.PLAYER_LIST)) { + GlStateManager.enableDepth(); + } + } + + @SubscribeEvent + public void onRenderGameOverlayPost(RenderGameOverlayEvent.Post event) { + if (neu.hasSkyblockScoreboard() && event.type.equals(RenderGameOverlayEvent.ElementType.ALL)) { + DungeonWin.render(event.partialTicks); + GlStateManager.pushMatrix(); + GlStateManager.translate(0, 0, -200); + for (TextOverlay overlay : OverlayManager.textOverlays) { + if (OverlayManager.dontRenderOverlay != null && + OverlayManager.dontRenderOverlay.isAssignableFrom(overlay.getClass())) { + continue; + } + GlStateManager.translate(0, 0, -1); + GlStateManager.enableDepth(); + overlay.render(); + } + GlStateManager.popMatrix(); + OverlayManager.dontRenderOverlay = null; + } + if (Keyboard.isKeyDown(Keyboard.KEY_X)) { + NotificationHandler.notificationDisplayMillis = 0; + } + + if (event.type == RenderGameOverlayEvent.ElementType.ALL) { + NotificationHandler.renderNotification(); + } + + } + + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + if (Minecraft.getMinecraft().theWorld == null) return; + if (Minecraft.getMinecraft().thePlayer == null) return; + + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest cc = (ContainerChest) chest.inventorySlots; + + if (!loadedInvName.equals(cc.getLowerChestInventory().getDisplayName().getUnformattedText())) { + loadedInvName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + inventoryLoaded = false; + inventoryLoadedTicks = 3; + } + + if (!inventoryLoaded) { + if (cc.getLowerChestInventory().getStackInSlot(cc.getLowerChestInventory().getSizeInventory() - 1) != null) { + inventoryLoaded = true; + } else { + for (ItemStack stack : chest.inventorySlots.getInventory()) { + if (stack != null) { + if (--inventoryLoadedTicks <= 0) { + inventoryLoaded = true; + } + break; + } + } + } + } + } else { + inventoryLoaded = false; + inventoryLoadedTicks = 3; + } + + } + + @SubscribeEvent + public void onGuiOpen(GuiOpenEvent event) { + NEUApi.disableInventoryButtons = false; + + if ((Minecraft.getMinecraft().currentScreen instanceof GuiScreenElementWrapper || + Minecraft.getMinecraft().currentScreen instanceof GuiItemRecipe) && event.gui == null && + !(Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) && + System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.lastOpenedGui < 500) { + NotEnoughUpdates.INSTANCE.lastOpenedGui = 0; + event.setCanceled(true); + return; + } + + if (!(event.gui instanceof GuiContainer) && Minecraft.getMinecraft().currentScreen != null) { + CalendarOverlay.setEnabled(false); + } + + if (Minecraft.getMinecraft().currentScreen != null) { + lastGuiClosed = System.currentTimeMillis(); + } + + neu.manager.auctionManager.customAH.lastGuiScreenSwitch = System.currentTimeMillis(); + BetterContainers.reset(); + inventoryLoaded = false; + inventoryLoadedTicks = 3; + + if (event.gui == null && neu.manager.auctionManager.customAH.isRenderOverAuctionView() && + !(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) { + event.gui = new CustomAHGui(); + } + + if (!(event.gui instanceof GuiChest || event.gui instanceof GuiEditSign)) { + neu.manager.auctionManager.customAH.setRenderOverAuctionView(false); + } else if (event.gui instanceof GuiChest && (neu.manager.auctionManager.customAH.isRenderOverAuctionView() || + Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) { + GuiChest chest = (GuiChest) event.gui; + ContainerChest container = (ContainerChest) chest.inventorySlots; + String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); + + neu.manager.auctionManager.customAH.setRenderOverAuctionView( + containerName.trim().equals("Auction View") || containerName.trim().equals("BIN Auction View") || + containerName.trim().equals("Confirm Bid") || containerName.trim().equals("Confirm Purchase")); + } + + //OPEN + if (Minecraft.getMinecraft().currentScreen == null && event.gui instanceof GuiContainer) { + neu.overlay.reset(); + } + if (event.gui != null && NotEnoughUpdates.INSTANCE.config.hidden.dev) { + if (event.gui instanceof GuiChest) { + GuiChest eventGui = (GuiChest) event.gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + ses.schedule(() -> { + if (Minecraft.getMinecraft().currentScreen != event.gui) { + return; + } + if (lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) { + try { + ItemStack res = lower.getStackInSlot(25); + String resInternalname = neu.manager.getInternalNameForItem(res); + + if (lower.getStackInSlot(48) != null) { + String backName = null; + NBTTagCompound tag = lower.getStackInSlot(48).getTagCompound(); + if (tag.hasKey("display", 10)) { + NBTTagCompound nbttagcompound = tag.getCompoundTag("display"); + if (nbttagcompound.getTagId("Lore") == 9) { + NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8); + backName = nbttaglist1.getStringTagAt(0); + } + } + + if (backName != null) { + String[] split = backName.split(" "); + if (split[split.length - 1].contains("Rewards")) { + String col = backName.substring( + split[0].length() + 1, + backName.length() - split[split.length - 1].length() - 1 + ); + + JsonObject json = neu.manager.getItemInformation().get(resInternalname); + json.addProperty("crafttext", "Requires: " + col); + + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "Added: " + resInternalname)); + neu.manager.writeJsonDefaultDir(json, resInternalname + ".json"); + neu.manager.loadItem(resInternalname); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }, 200, TimeUnit.MILLISECONDS); + } + } + } + + /** + * Sets hoverInv and focusInv variables, representing whether the NEUOverlay should render behind the inventory when + * (hoverInv == true) and whether mouse/kbd inputs shouldn't be sent to NEUOverlay (focusInv == true). + *

+ * If hoverInv is true, will render the overlay immediately (resulting in the inventory being drawn over the GUI) + * If hoverInv is false, the overlay will render in #onGuiScreenDraw (resulting in the GUI being drawn over the inv) + *

+ * All of this only matters if players are using gui scale auto which may result in the inventory being drawn + * over the various panes. + */ + @SubscribeEvent + public void onGuiBackgroundDraw(GuiScreenEvent.BackgroundDrawnEvent event) { + if (NotificationHandler.showNotificationOverInv) { + + NotificationHandler.renderNotification(); + + } + if ((NotificationHandler.shouldRenderOverlay(event.gui) || event.gui instanceof CustomAHGui) && + neu.isOnSkyblock()) { + ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledresolution.getScaledWidth(); + + boolean hoverPane = event.getMouseX() < width * neu.overlay.getInfoPaneOffsetFactor() || + event.getMouseX() > width * neu.overlay.getItemPaneOffsetFactor(); + + if (event.gui instanceof GuiContainer) { + try { + int xSize = ((GuiContainer) event.gui).xSize; + int ySize = ((GuiContainer) event.gui).ySize; + int guiLeft = ((GuiContainer) event.gui).guiLeft; + int guiTop = ((GuiContainer) event.gui).guiTop; + + hoverInv = event.getMouseX() > guiLeft && event.getMouseX() < guiLeft + xSize && event.getMouseY() > guiTop && + event.getMouseY() < guiTop + ySize; + + if (hoverPane) { + if (!hoverInv) focusInv = false; + } else { + focusInv = true; + } + } catch (NullPointerException npe) { + focusInv = !hoverPane; + } + } + if (event.gui instanceof GuiItemRecipe) { + GuiItemRecipe guiItemRecipe = ((GuiItemRecipe) event.gui); + hoverInv = event.getMouseX() > guiItemRecipe.guiLeft && + event.getMouseX() < guiItemRecipe.guiLeft + guiItemRecipe.xSize && event.getMouseY() > guiItemRecipe.guiTop && + event.getMouseY() < guiItemRecipe.guiTop + guiItemRecipe.ySize; + + if (hoverPane) { + if (!hoverInv) focusInv = false; + } else { + focusInv = true; + } + } + if (focusInv) { + try { + neu.overlay.render(hoverInv); + } catch (ConcurrentModificationException e) { + e.printStackTrace(); + } + GL11.glTranslatef(0, 0, 10); + } + if (hoverInv) { + renderDungeonChestOverlay(event.gui); + if (NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) { + AccessoryBagOverlay.renderOverlay(); + } + } + } + + drawingGuiScreen = true; + } + + @SubscribeEvent + public void onGuiScreenDrawPre(GuiScreenEvent.DrawScreenEvent.Pre event) { + doInventoryButtons = false; + + if (AuctionSearchOverlay.shouldReplace()) { + AuctionSearchOverlay.render(); + event.setCanceled(true); + return; + } + if (RancherBootOverlay.shouldReplace()) { + RancherBootOverlay.render(); + event.setCanceled(true); + return; + } + + String containerName = null; + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + if (guiScreen instanceof GuiChest) { + GuiChest eventGui = (GuiChest) guiScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + } + + if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) { + GuiCustomEnchant.getInstance().render(event.renderPartialTicks); + event.setCanceled(true); + return; + } + + boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); + boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); + boolean customAhActive = + event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); + + if (storageOverlayActive) { + StorageOverlay.getInstance().render(); + event.setCanceled(true); + return; + } + + if (tradeWindowActive || customAhActive) { + event.setCanceled(true); + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + + //Dark background + Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680); + + if (event.mouseX < width * neu.overlay.getWidthMult() / 3 || + event.mouseX > width - width * neu.overlay.getWidthMult() / 3) { + if (customAhActive) { + neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY); + } else { + TradeWindow.render(event.mouseX, event.mouseY); + } + neu.overlay.render(false); + } else { + neu.overlay.render(false); + if (customAhActive) { + neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY); + } else { + TradeWindow.render(event.mouseX, event.mouseY); + } + } + } + + if (CalendarOverlay.isEnabled() || event.isCanceled()) return; + if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && NotificationHandler.shouldRenderOverlay(event.gui) && + event.gui instanceof GuiContainer) { + doInventoryButtons = true; + + int zOffset = 50; + + GlStateManager.translate(0, 0, zOffset); + + int xSize = ((GuiContainer) event.gui).xSize; + int ySize = ((GuiContainer) event.gui).ySize; + int guiLeft = ((GuiContainer) event.gui).guiLeft; + int guiTop = ((GuiContainer) event.gui).guiTop; + + if (!NEUApi.disableInventoryButtons) { + for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { + if (!button.isActive()) continue; + if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; + + int x = guiLeft + button.x; + int y = guiTop + button.y; + if (button.anchorRight) { + x += xSize; + } + if (button.anchorBottom) { + y += ySize; + } + if (AccessoryBagOverlay.isInAccessoryBag()) { + if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { + x += 80 + 28; + } + } + if (NEUOverlay.isRenderingArmorHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) { + x -= 25; + } + } + if (NEUOverlay.isRenderingPetHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) { + x -= 25; + } + } + + GlStateManager.color(1, 1, 1, 1f); + + GlStateManager.enableDepth(); + GlStateManager.enableAlpha(); + Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR); + Utils.drawTexturedRect( + x, + y, + 18, + 18, + button.backgroundIndex * 18 / 256f, + (button.backgroundIndex * 18 + 18) / 256f, + 18 / 256f, + 36 / 256f, + GL11.GL_NEAREST + ); + + if (button.icon != null && !button.icon.trim().isEmpty()) { + GuiInvButtonEditor.renderIcon(button.icon, x + 1, y + 1); + } + } + } + GlStateManager.translate(0, 0, -zOffset); + } + } + + /** + * Will draw the NEUOverlay over the inventory if focusInv == false. (z-translation of 300 is so that NEUOverlay + * will draw over Items in the inventory (which render at a z value of about 250)) + */ + @SubscribeEvent + public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) { + drawingGuiScreen = false; + disableCraftingText = false; + + String containerName = null; + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + if (guiScreen instanceof GuiChest) { + GuiChest eventGui = (GuiChest) guiScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + + if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) return; + } + + boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); + boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); + boolean customAhActive = + event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); + + if (!(tradeWindowActive || storageOverlayActive || customAhActive)) { + if (NotificationHandler.shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { + GlStateManager.pushMatrix(); + if (!focusInv) { + GL11.glTranslatef(0, 0, 300); + neu.overlay.render(hoverInv && focusInv); + GL11.glTranslatef(0, 0, -300); + } + GlStateManager.popMatrix(); + } + } + + if (NotificationHandler.shouldRenderOverlay(event.gui) && neu.isOnSkyblock() && !hoverInv) { + renderDungeonChestOverlay(event.gui); + if (NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) { + AccessoryBagOverlay.renderOverlay(); + } + } + + boolean hoveringButton = false; + if (!doInventoryButtons) return; + if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && NotificationHandler.shouldRenderOverlay(event.gui) && + event.gui instanceof GuiContainer) { + int xSize = ((GuiContainer) event.gui).xSize; + int ySize = ((GuiContainer) event.gui).ySize; + int guiLeft = ((GuiContainer) event.gui).guiLeft; + int guiTop = ((GuiContainer) event.gui).guiTop; + + if (!NEUApi.disableInventoryButtons) { + for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { + if (!button.isActive()) continue; + if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; + + int x = guiLeft + button.x; + int y = guiTop + button.y; + if (button.anchorRight) { + x += xSize; + } + if (button.anchorBottom) { + y += ySize; + } + if (AccessoryBagOverlay.isInAccessoryBag()) { + if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { + x += 80 + 28; + } + } + if (NEUOverlay.isRenderingArmorHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) { + x -= 25; + } + } + if (NEUOverlay.isRenderingPetHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) { + x -= 25; + } + } + + if (x - guiLeft >= 85 && x - guiLeft <= 115 && y - guiTop >= 4 && y - guiTop <= 25) { + disableCraftingText = true; + } + + if (event.mouseX >= x && event.mouseX <= x + 18 && event.mouseY >= y && event.mouseY <= y + 18) { + hoveringButton = true; + long currentTime = System.currentTimeMillis(); + + if (buttonHovered != button) { + buttonHoveredMillis = currentTime; + buttonHovered = button; + } + + if (currentTime - buttonHoveredMillis > 600) { + String command = button.command.trim(); + if (!command.startsWith("/")) { + command = "/" + command; + } + + Utils.drawHoveringText( + Lists.newArrayList("\u00a77" + command), + event.mouseX, + event.mouseY, + event.gui.width, + event.gui.height, + -1, + Minecraft.getMinecraft().fontRendererObj + ); + } + } + } + } + } + if (!hoveringButton) buttonHovered = null; + + if (AuctionBINWarning.getInstance().shouldShow()) { + AuctionBINWarning.getInstance().render(); + } + } + + private void renderDungeonChestOverlay(GuiScreen gui) { + if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 3) return; + + if (gui instanceof GuiChest && NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc != 2) { + try { + int xSize = ((GuiContainer) gui).xSize; + int guiLeft = ((GuiContainer) gui).guiLeft; + int guiTop = ((GuiContainer) gui).guiTop; + + GuiChest eventGui = (GuiChest) gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + ItemStack rewardChest = lower.getStackInSlot(31); + if (rewardChest != null && rewardChest.getDisplayName().endsWith( + EnumChatFormatting.GREEN + "Open Reward Chest")) { + int chestCost = 0; + try { + String line6 = Utils.cleanColour(neu.manager.getLoreFromNBT(rewardChest.getTagCompound())[6]); + StringBuilder cost = new StringBuilder(); + for (int i = 0; i < line6.length(); i++) { + char c = line6.charAt(i); + if ("0123456789".indexOf(c) >= 0) { + cost.append(c); + } + } + if (cost.length() > 0) { + chestCost = Integer.parseInt(cost.toString()); + } + } catch (Exception ignored) { + } + + String missingItem = null; + int totalValue = 0; + HashMap itemValues = new HashMap<>(); + for (int i = 0; i < 5; i++) { + ItemStack item = lower.getStackInSlot(11 + i); + String internal = neu.manager.getInternalNameForItem(item); + if (internal != null) { + internal = internal.replace("\u00CD", "I").replace("\u0130", "I"); + float bazaarPrice = -1; + JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal); + if (bazaarInfo != null && bazaarInfo.has("curr_sell")) { + bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat(); + } + if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000; + + float worth = -1; + if (bazaarPrice > 0) { + worth = bazaarPrice; + } else { + switch (NotEnoughUpdates.INSTANCE.config.dungeons.profitType) { + case 1: + worth = neu.manager.auctionManager.getItemAvgBin(internal); + break; + case 2: + JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); + if (auctionInfo != null) { + if (auctionInfo.has("clean_price")) { + worth = (int) auctionInfo.get("clean_price").getAsFloat(); + } else { + worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + } + } + break; + default: + worth = neu.manager.auctionManager.getLowestBin(internal); + } + if (worth <= 0) { + worth = neu.manager.auctionManager.getLowestBin(internal); + if (worth <= 0) { + worth = neu.manager.auctionManager.getItemAvgBin(internal); + if (worth <= 0) { + JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal); + if (auctionInfo != null) { + if (auctionInfo.has("clean_price")) { + worth = (int) auctionInfo.get("clean_price").getAsFloat(); + } else { + worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat()); + } + } + } + } + } + } + + if (worth > 0 && totalValue >= 0) { + totalValue += worth; + String display = item.getDisplayName(); + + if (display.contains("Enchanted Book")) { + NBTTagCompound tag = item.getTagCompound(); + if (tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + NBTTagCompound enchants = ea.getCompoundTag("enchantments"); + + int highestLevel = -1; + for (String enchname : enchants.getKeySet()) { + int level = enchants.getInteger(enchname); + if (level > highestLevel) { + display = EnumChatFormatting.BLUE + WordUtils.capitalizeFully(enchname + .replace("_", " ") + .replace("Ultimate", "") + .trim()) + " " + level; + } + } + } + } + + itemValues.put(display, worth); + } else { + if (totalValue != -1) { + missingItem = internal; + } + totalValue = -1; + } + } + } + + NumberFormat format = NumberFormat.getInstance(Locale.US); + String valueStringBIN1; + String valueStringBIN2; + if (totalValue >= 0) { + valueStringBIN1 = EnumChatFormatting.YELLOW + "Value (BIN): "; + valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins"; + } else { + valueStringBIN1 = EnumChatFormatting.YELLOW + "Can't find BIN: "; + valueStringBIN2 = missingItem; + } + + int profitLossBIN = totalValue - chestCost; + + boolean kismetUsed = false; + // checking for kismet + Slot slot = (eventGui.inventorySlots.getSlot(50)); + if (slot.getHasStack()) { + String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(slot.getStack().getTagCompound()); + for (String line : lore) { + if (line.contains("You already rerolled a chest!")) { + kismetUsed = true; + break; + } + } + } + int kismetPrice = neu.manager.auctionManager.getLowestBin("KISMET_FEATHER"); + String kismetStr = EnumChatFormatting.RED + format.format(kismetPrice) + " coins"; + if (neu.config.dungeons.useKismetOnDungeonProfit) + profitLossBIN = kismetUsed ? profitLossBIN - kismetPrice : profitLossBIN; + + String profitPrefix = EnumChatFormatting.DARK_GREEN.toString(); + String lossPrefix = EnumChatFormatting.RED.toString(); + String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix; + + String plStringBIN; + if (profitLossBIN >= 0) { + plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins"; + } else { + plStringBIN = prefix + "-" + format.format(-profitLossBIN) + " coins"; + } + + if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 1 && !valueStringBIN2.equals(missingItem)) { + int w = Minecraft.getMinecraft().fontRendererObj.getStringWidth(plStringBIN); + GlStateManager.disableLighting(); + GlStateManager.translate(0, 0, 200); + Minecraft.getMinecraft().fontRendererObj.drawString( + plStringBIN, + guiLeft + xSize - 5 - w, + guiTop + 5, + 0xffffffff, + true + ); + GlStateManager.translate(0, 0, -200); + return; + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth); + GL11.glColor4f(1, 1, 1, 1); + GlStateManager.disableLighting(); + Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 180, 101, 0, 180 / 256f, 0, 101 / 256f, GL11.GL_NEAREST); + + Utils.renderAlignedString(valueStringBIN1, valueStringBIN2, guiLeft + xSize + 4 + 10, guiTop + 14, 160); + if (neu.config.dungeons.useKismetOnDungeonProfit && kismetUsed) { + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Kismet Feather: ", + kismetStr, + guiLeft + xSize + 4 + 10, + guiTop + 24, + 160 + ); + } + if (totalValue >= 0) { + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Profit/Loss: ", + plStringBIN, + guiLeft + xSize + 4 + 10, + guiTop + (neu.config.dungeons.useKismetOnDungeonProfit ? (kismetUsed ? 34 : 24) : 24), + 160 + ); + } + + int index = 0; + for (Map.Entry entry : itemValues.entrySet()) { + Utils.renderAlignedString( + entry.getKey(), + prefix + format.format(entry.getValue().intValue()), + guiLeft + xSize + 4 + 10, + guiTop + (neu.config.dungeons.useKismetOnDungeonProfit ? (kismetUsed ? 39 : 29) : 29) + (++index) * 10, + 160 + ); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused. + * Will also cancel the event if if NEUOverlay#mouseInput returns true. + */ + @SubscribeEvent(priority = EventPriority.LOW) + public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) { + if (Mouse.getEventButtonState() && StorageManager.getInstance().onAnyClick()) { + event.setCanceled(true); + 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; + + if (AuctionBINWarning.getInstance().shouldShow()) { + AuctionBINWarning.getInstance().mouseInput(mouseX, mouseY); + event.setCanceled(true); + return; + } + + if (!event.isCanceled()) { + Utils.scrollTooltip(Mouse.getEventDWheel()); + } + if (AuctionSearchOverlay.shouldReplace()) { + AuctionSearchOverlay.mouseEvent(); + event.setCanceled(true); + return; + } + if (RancherBootOverlay.shouldReplace()) { + RancherBootOverlay.mouseEvent(); + event.setCanceled(true); + return; + } + + String containerName = null; + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + if (guiScreen instanceof GuiChest) { + GuiChest eventGui = (GuiChest) guiScreen; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + if (containerName.contains(" Profile") && BetterContainers.profileViewerStackIndex != -1 && + eventGui.isMouseOverSlot(cc.inventorySlots.get(BetterContainers.profileViewerStackIndex), mouseX, mouseY) && + Mouse.getEventButton() >= 0) { + event.setCanceled(true); + if (Mouse.getEventButtonState() && eventGui.inventorySlots.inventorySlots.get(22).getStack() != null && + eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound() != null) { + NBTTagCompound tag = eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound(); + if (tag.hasKey("SkullOwner") && tag.getCompoundTag("SkullOwner").hasKey("Name")) { + String username = tag.getCompoundTag("SkullOwner").getString("Name"); + Utils.playPressSound(); + ViewProfileCommand.RUNNABLE.accept(new String[]{username}); + } + } + } + } + + if (GuiCustomEnchant.getInstance().shouldOverride(containerName) && + GuiCustomEnchant.getInstance().mouseInput(mouseX, mouseY)) { + event.setCanceled(true); + return; + } + + boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); + boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); + boolean customAhActive = + event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); + + if (storageOverlayActive) { + if (StorageOverlay.getInstance().mouseInput(mouseX, mouseY)) { + event.setCanceled(true); + } + return; + } + + if (tradeWindowActive || customAhActive) { + event.setCanceled(true); + if (customAhActive) { + neu.manager.auctionManager.customAH.handleMouseInput(); + } else { + TradeWindow.handleMouseInput(); + } + neu.overlay.mouseInput(); + return; + } + + if (NotificationHandler.shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { + if (!NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay || !AccessoryBagOverlay.mouseClick()) { + if (!(hoverInv && focusInv)) { + if (neu.overlay.mouseInput()) { + event.setCanceled(true); + } + } else { + neu.overlay.mouseInputInv(); + } + } + } + if (event.isCanceled()) return; + if (!doInventoryButtons) return; + if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && NotificationHandler.shouldRenderOverlay(event.gui) && + Mouse.getEventButton() >= 0 && event.gui instanceof GuiContainer) { + int xSize = ((GuiContainer) event.gui).xSize; + int ySize = ((GuiContainer) event.gui).ySize; + int guiLeft = ((GuiContainer) event.gui).guiLeft; + int guiTop = ((GuiContainer) event.gui).guiTop; + if (!NEUApi.disableInventoryButtons) { + for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) { + if (!button.isActive()) continue; + if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue; + + int x = guiLeft + button.x; + int y = guiTop + button.y; + if (button.anchorRight) { + x += xSize; + } + if (button.anchorBottom) { + y += ySize; + } + if (AccessoryBagOverlay.isInAccessoryBag()) { + if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) { + x += 80 + 28; + } + } + if (NEUOverlay.isRenderingArmorHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) { + x -= 25; + } + } + if (NEUOverlay.isRenderingPetHud()) { + if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) { + x -= 25; + } + } + + if (mouseX >= x && mouseX <= x + 18 && mouseY >= y && mouseY <= y + 18) { + if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { + int clickType = NotEnoughUpdates.INSTANCE.config.inventoryButtons.clickType; + if ((clickType == 0 && Mouse.getEventButtonState()) || (clickType == 1 && !Mouse.getEventButtonState())) { + String command = button.command.trim(); + if (!command.startsWith("/")) { + command = "/" + command; + } + if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, command) == 0) { + NotEnoughUpdates.INSTANCE.sendChatMessage(command); + } + } + } else { + event.setCanceled(true); + } + return; + } + } + } + } + } + + /** + * Sends a kbd event to NEUOverlay, cancelling if NEUOverlay#keyboardInput returns true. + * Also includes a dev function used for creating custom named json files with recipes. + */ + @SubscribeEvent + public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) { + if (AuctionBINWarning.getInstance().shouldShow()) { + AuctionBINWarning.getInstance().keyboardInput(); + event.setCanceled(true); + return; + } + + if (AuctionSearchOverlay.shouldReplace()) { + AuctionSearchOverlay.keyEvent(); + event.setCanceled(true); + return; + } + if (RancherBootOverlay.shouldReplace()) { + RancherBootOverlay.keyEvent(); + event.setCanceled(true); + return; + } + + String containerName = null; + GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen; + + if (guiScreen instanceof GuiChest) { + containerName = ((ContainerChest) ((GuiChest) guiScreen).inventorySlots) + .getLowerChestInventory() + .getDisplayName() + .getUnformattedText(); + } + + if (GuiCustomEnchant.getInstance().shouldOverride(containerName) && + GuiCustomEnchant.getInstance().keyboardInput()) { + event.setCanceled(true); + return; + } + + boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); + boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); + boolean customAhActive = + event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); + + if (storageOverlayActive) { + if (StorageOverlay.getInstance().keyboardInput()) { + event.setCanceled(true); + return; + } + } + + if (tradeWindowActive || customAhActive) { + if (customAhActive) { + if (neu.manager.auctionManager.customAH.keyboardInput()) { + event.setCanceled(true); + Minecraft.getMinecraft().dispatchKeypresses(); + } else if (neu.overlay.keyboardInput(focusInv)) { + event.setCanceled(true); + } + } else { + TradeWindow.keyboardInput(); + if (Keyboard.getEventKey() != Keyboard.KEY_ESCAPE) { + event.setCanceled(true); + Minecraft.getMinecraft().dispatchKeypresses(); + neu.overlay.keyboardInput(focusInv); + } + } + return; + } + + if (NotificationHandler.shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) { + if (neu.overlay.keyboardInput(focusInv)) { + event.setCanceled(true); + } + } + if (NotEnoughUpdates.INSTANCE.config.hidden.dev && NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && + Minecraft.getMinecraft().theWorld != null && Keyboard.getEventKey() == Keyboard.KEY_N && + Keyboard.getEventKeyState()) { + GuiScreen gui = Minecraft.getMinecraft().currentScreen; + if (gui instanceof GuiChest) { + GuiChest eventGui = (GuiChest) event.gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + if (!lower.getDisplayName().getUnformattedText().endsWith("Essence")) return; + + for (int i = 0; i < lower.getSizeInventory(); i++) { + ItemStack stack = lower.getStackInSlot(i); + + String internalname = neu.manager.getInternalNameForItem(stack); + if (internalname != null) { + String[] lore = neu.manager.getLoreFromNBT(stack.getTagCompound()); + + for (String line : lore) { + if (line.contains(":") && (line.startsWith("\u00A77Upgrade to") || line.startsWith( + "\u00A77Convert to Dungeon Item"))) { + String[] split = line.split(":"); + String after = Utils.cleanColour(split[1]); + StringBuilder costS = new StringBuilder(); + for (char c : after.toCharArray()) { + if (c >= '0' && c <= '9') { + costS.append(c); + } + } + int cost = Integer.parseInt(costS.toString()); + String[] afterSplit = after.split(" "); + String type = afterSplit[afterSplit.length - 2]; + + if (!essenceJson.has(internalname)) { + essenceJson.add(internalname, new JsonObject()); + } + JsonObject obj = essenceJson.get(internalname).getAsJsonObject(); + obj.addProperty("type", type); + + if (line.startsWith("\u00A77Convert to Dungeon Item")) { + obj.addProperty("dungeonize", cost); + } else if (line.startsWith("\u00A77Upgrade to")) { + int stars = 0; + for (char c : line.toCharArray()) { + if (c == '\u272A') stars++; + } + if (stars > 0) { + obj.addProperty(stars + "", cost); + } + } + } + } + } + } + System.out.println(essenceJson); + } + } + if (NotEnoughUpdates.INSTANCE.config.hidden.dev && NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && + Minecraft.getMinecraft().theWorld != null && Keyboard.getEventKey() == Keyboard.KEY_O && + Keyboard.getEventKeyState()) { + GuiScreen gui = Minecraft.getMinecraft().currentScreen; + if (gui instanceof GuiChest) { + GuiChest eventGui = (GuiChest) event.gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + IInventory lower = cc.getLowerChestInventory(); + + if (lower.getStackInSlot(23) != null && lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) { + ItemStack res = lower.getStackInSlot(25); + String resInternalname = neu.manager.getInternalNameForItem(res); + JTextField tf = new JTextField(); + tf.setText(resInternalname); + tf.addAncestorListener(new RequestFocusListener()); + JOptionPane.showOptionDialog( + null, + tf, + "Enter Name:", + JOptionPane.NO_OPTION, + JOptionPane.PLAIN_MESSAGE, + null, + new String[]{"Enter"}, + "Enter" + ); + resInternalname = tf.getText(); + if (resInternalname.trim().length() == 0) { + return; + } + + JsonObject recipe = new JsonObject(); + + String[] x = {"1", "2", "3"}; + String[] y = {"A", "B", "C"}; + + for (int i = 0; i <= 18; i += 9) { + for (int j = 0; j < 3; j++) { + ItemStack stack = lower.getStackInSlot(10 + i + j); + String internalname = ""; + if (stack != null) { + internalname = neu.manager.getInternalNameForItem(stack); + if (!neu.manager.getItemInformation().containsKey(internalname)) { + neu.manager.writeItemToFile(stack); + } + internalname += ":" + stack.stackSize; + } + recipe.addProperty(y[i / 9] + x[j], internalname); + } + } + + JsonObject json = neu.manager.getJsonForItem(res); + json.add("recipe", recipe); + json.addProperty("internalname", resInternalname); + json.addProperty("clickcommand", "viewrecipe"); + json.addProperty("modver", NotEnoughUpdates.VERSION); + try { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname)); + neu.manager.writeJsonDefaultDir(json, resInternalname + ".json"); + neu.manager.loadItem(resInternalname); + } catch (IOException ignored) { + } + } + } + } + } + + @SubscribeEvent + public void onRenderLast(RenderWorldLastEvent event) { + CrystalMetalDetectorSolver.render(event.partialTicks); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java index c1ce229c47..811c30d25f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java @@ -1,8 +1,8 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import com.google.gson.JsonObject; -import io.github.moulberry.notenoughupdates.NEUEventListener; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.listener.RenderListener; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.client.renderer.GlStateManager; @@ -69,7 +69,7 @@ public static int getClickedSlot() { public static void bindHook(TextureManager textureManager, ResourceLocation location) { long currentMillis = System.currentTimeMillis(); - if (isChestOpen() && NEUEventListener.inventoryLoaded) { + if (isChestOpen() && RenderListener.inventoryLoaded) { int invHashcode = lastInvHashcode; if (currentMillis - lastHashcodeCheck > 50) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CollectionLogManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CollectionLogManager.java deleted file mode 100644 index c550ce535d..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CollectionLogManager.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.github.moulberry.notenoughupdates.miscfeatures; - -import io.github.moulberry.notenoughupdates.collectionlog.CollectionConstant; -import io.github.moulberry.notenoughupdates.util.Constants; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.WorldClient; -import net.minecraft.entity.Entity; -import net.minecraft.entity.item.EntityArmorStand; - -import java.util.regex.Matcher; - -public class CollectionLogManager { - private static final CollectionLogManager INSTANCE = new CollectionLogManager(); - - public static CollectionLogManager getInstance() { - return INSTANCE; - } - - public void onEntityMetadataUpdated(int entityId) { - System.out.println("entity created:" + entityId); - WorldClient world = Minecraft.getMinecraft().theWorld; - if (world != null) { - Entity entity = world.getEntityByID(entityId); - - if (entity instanceof EntityArmorStand && entity.hasCustomName()) { - String customName = entity.getName(); - System.out.println("got name:" + customName); - for (CollectionConstant.DropEntry entry : Constants.COLLECTIONLOG.dropdata) { - System.out.println("iter entry"); - if (entry.type.equalsIgnoreCase("itemdrop")) { - Matcher matcher = entry.regex.matcher(customName); - if (matcher.matches()) { - System.out.println("Match found!"); - System.out.println("Count: " + matcher.group("count")); - System.out.println("Name: " + matcher.group("itemname")); - } else { - System.out.println("Doesn't match: " + customName); - } - } - } - } - } - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java deleted file mode 100644 index 12e65e6534..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java +++ /dev/null @@ -1,293 +0,0 @@ -package io.github.moulberry.notenoughupdates.miscfeatures; - -import io.github.moulberry.notenoughupdates.util.Utils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Gui; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.RenderGlobal; -import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.renderer.chunk.CompiledChunk; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.client.renderer.vertex.VertexFormat; -import net.minecraft.client.renderer.vertex.VertexFormatElement; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.network.play.server.S07PacketRespawn; -import net.minecraft.util.MathHelper; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.client.event.RenderLivingEvent; -import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.input.Keyboard; -import org.lwjgl.opengl.GL11; -import org.lwjgl.util.glu.Project; - -import java.nio.ByteBuffer; -import java.util.List; - -public class FancyPortals { - private static final ResourceLocation[] RENDERS = new ResourceLocation[6]; - - static { - for (int i = 0; i < 6; i++) { - RENDERS[i] = new ResourceLocation("notenoughupdates:portal_panoramas/nether/pansc-" + (i + 1) + ".png"); - } - } - - public static int perspectiveId = -1; - - public static boolean overridePerspective() { - if (perspectiveId >= 0 && !Keyboard.isKeyDown(Keyboard.KEY_K)) { - if (perspectiveId == 0) { - GlStateManager.matrixMode(5889); - GlStateManager.loadIdentity(); - GlStateManager.ortho(0.0D, 7, 7, 0.0D, -100D, 100D); - GlStateManager.scale(1, 1, -1); - GlStateManager.matrixMode(5888); - GlStateManager.loadIdentity(); - GlStateManager.translate(3.5F, 3.5F, -1.0F); - GlStateManager.rotate(-90, 1, 0, 0); - } else if (perspectiveId <= 4) { - GlStateManager.matrixMode(5889); - GlStateManager.loadIdentity(); - Project.gluPerspective(90, 1, 0.05F, 160 * MathHelper.SQRT_2); - GlStateManager.matrixMode(5888); - GlStateManager.loadIdentity(); - GlStateManager.rotate(perspectiveId * 90, 0, 1, 0); - GlStateManager.translate(0, -3.5f, 0); - } else { - GlStateManager.matrixMode(5889); - GlStateManager.loadIdentity(); - Project.gluPerspective(90, 1, 0.05F, 160 * MathHelper.SQRT_2); - GlStateManager.matrixMode(5888); - GlStateManager.loadIdentity(); - GlStateManager.rotate(-90, 1, 0, 0); - GlStateManager.translate(0, -3.5f, 0); - } - - return true; - } - return false; - } - - private static WorldRenderer surfaceWorldRenderer = null; - - private static WorldRenderer getSurfaceWorldRenderer() { - if (surfaceWorldRenderer != null && !Keyboard.isKeyDown(Keyboard.KEY_O)) { - return surfaceWorldRenderer; - } - - surfaceWorldRenderer = createSurfaceWorldRenderer(); - - return surfaceWorldRenderer; - } - - private static void drawPoint(WorldRenderer worldRenderer, int x, int y) { - float xDist = 1 - Math.abs(x - 50) / 50f; - float yDist = 1 - Math.abs(y - 50) / 50f; - float distToEdge = Math.min(xDist, yDist); - - float z = 0.4142f; - if (distToEdge < 1 / 3.5f) { - if (y > 50 && yDist < xDist) { - float circleH = 1.414f - distToEdge * 3.5f * 1.414f; - z = (float) Math.sqrt(2f - circleH * circleH); - z *= 0.4142f / 1.4142f; - } else { - float circleH = 1 - distToEdge * 3.5f; - z = (float) Math.sqrt(2f - circleH * circleH) - 1; - } - } - - worldRenderer.pos(x * 7 / 100f, y * 7 / 100f, z).tex(x / 100f, y / 100f).endVertex(); - } - - private static WorldRenderer createSurfaceWorldRenderer() { - WorldRenderer worldRenderer = new WorldRenderer(20 * 100 * 100); - worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - for (int x = 0; x < 100; x++) { - for (int y = 0; y < 100; y++) { - drawPoint(worldRenderer, x, y); - drawPoint(worldRenderer, x, y + 1); - drawPoint(worldRenderer, x + 1, y + 1); - drawPoint(worldRenderer, x + 1, y); - } - } - - return worldRenderer; - } - - private static long overridingRenderMillis = -1; - - public static void onRespawnPacket(S07PacketRespawn packet) { - if (true) return; - if (packet.getDimensionID() != Minecraft.getMinecraft().thePlayer.dimension) { - overridingRenderMillis = System.currentTimeMillis(); - } - } - - public static boolean shouldRenderLoadingScreen() { - return false; - } - - public static boolean shouldRenderWorldOverlay() { - if (overridingRenderMillis > 0) { - if (Minecraft.getMinecraft().theWorld != null && Minecraft.getMinecraft().thePlayer != null) { - RenderGlobal renderGlobal = Minecraft.getMinecraft().renderGlobal; - int loaded = 0; - for (RenderGlobal.ContainerLocalRenderInformation info : renderGlobal.renderInfos) { - CompiledChunk compiledchunk = info.renderChunk.compiledChunk; - - if (compiledchunk != CompiledChunk.DUMMY && !compiledchunk.isEmpty()) { - if (++loaded >= 5) { - overridingRenderMillis = -1; - return false; - } - } - } - } - if (System.currentTimeMillis() - overridingRenderMillis > 1000) { - overridingRenderMillis = -1; - return false; - } - return true; - } - return false; - } - - public static void onUpdateCameraAndRender(float partialTicks, long nanoTime) { - if (overridingRenderMillis > 0) { - if (Minecraft.getMinecraft().theWorld != null && Minecraft.getMinecraft().thePlayer != null) { - Minecraft.getMinecraft().thePlayer.timeInPortal = 0.3f; - Minecraft.getMinecraft().thePlayer.prevTimeInPortal = 0.3f; - } - - GlStateManager.rotate(90, 0, 1, 0); - renderWorld(); - - Minecraft.getMinecraft().ingameGUI.renderGameOverlay(partialTicks); - } - } - - @SubscribeEvent - public void onRenderEntityYeeter(RenderLivingEvent.Pre event) { - /*if(!Keyboard.isKeyDown(Keyboard.KEY_G)) return; - event.setCanceled(true); - if(event.entity instanceof EntityPlayer) { - EntityPlayer player = (EntityPlayer) event.entity; - if(player.getUniqueID().version() == 4) { - event.setCanceled(true); - } - }*/ - } - - private static void renderWorld() { - for (int i = 5; i >= 0; i--) { - GlStateManager.pushMatrix(); - - GlStateManager.disableDepth(); - GlStateManager.disableLighting(); - - GlStateManager.rotate(180, 0, 0, 1); - GlStateManager.rotate(-90, 0, 1, 0); - - if (i != 0) GlStateManager.translate(0, -3.49, 0); - - switch (i) { - case 1: - GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F); - break; - case 2: - GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F); - break; - case 3: - GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); - break; - case 5: - GlStateManager.rotate(90.0F, 1.0F, 0.0F, 0.0F); - break; - case 0: - GlStateManager.rotate(-90.0F, 1.0F, 0.0F, 0.0F); - break; - } - - Minecraft.getMinecraft().getTextureManager().bindTexture(RENDERS[i]); - GlStateManager.color(1, 1, 1, 1); - if (i != 0) GlStateManager.translate(0, 0, 3.49); - - if (i != 0) { - GlStateManager.translate(-3.5f, -3.5f, 0); - WorldRenderer worldRenderer = getSurfaceWorldRenderer(); - VertexFormat vertexformat = worldRenderer.getVertexFormat(); - int stride = vertexformat.getNextOffset(); - ByteBuffer bytebuffer = worldRenderer.getByteBuffer(); - List list = vertexformat.getElements(); - - for (int index = 0; index < list.size(); index++) { - VertexFormatElement vertexformatelement = list.get(index); - vertexformatelement.getUsage().preDraw(vertexformat, index, stride, bytebuffer); - } - - GL11.glDrawArrays(worldRenderer.getDrawMode(), 0, worldRenderer.getVertexCount()); - - for (int index = 0; index < list.size(); index++) { - VertexFormatElement vertexformatelement = list.get(index); - vertexformatelement.getUsage().postDraw(vertexformat, index, stride, bytebuffer); - } - } else { - Utils.drawTexturedRect(-3.5f, -3.5f, 7, 7, i == 0 ? GL11.GL_NEAREST : GL11.GL_LINEAR); - } - - GlStateManager.enableDepth(); - - GlStateManager.popMatrix(); - } - } - - @SubscribeEvent - public void onRenderLast(RenderWorldLastEvent event) { - if (true) return; - if (!Minecraft.getMinecraft().getFramebuffer().isStencilEnabled()) - Minecraft.getMinecraft().getFramebuffer().enableStencil(); - - GL11.glEnable(GL11.GL_STENCIL_TEST); - GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF); - GL11.glStencilOp(GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_REPLACE); - GL11.glStencilMask(0xFF); - GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT); - GlStateManager.enableDepth(); - GlStateManager.enableCull(); - GlStateManager.cullFace(GL11.GL_BACK); - - GL11.glColorMask(false, false, false, false); - - Entity viewer = Minecraft.getMinecraft().getRenderViewEntity(); - double viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * event.partialTicks; - double viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * event.partialTicks; - double viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * event.partialTicks; - GlStateManager.pushMatrix(); - - GlStateManager.translate(-viewerX + 12 + 5 / 16f, -viewerY + 100, -viewerZ + 39); - GlStateManager.rotate(90, 0, 1, 0); - Gui.drawRect(0, 5, 3, 0, 0xffffffff); - GlStateManager.rotate(180, 0, 1, 0); - GlStateManager.translate(-3, 0, -6 / 16f); - Gui.drawRect(0, 5, 3, 0, 0xffffffff); - - GlStateManager.popMatrix(); - - GL11.glColorMask(true, true, true, true); - - // Only pass stencil test if equal to 1 - GL11.glStencilMask(0x00); - GL11.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF); - - GlStateManager.translate(-viewerX + 12, -viewerY + 100, -viewerZ + 37.5f); - - renderWorld(); - - GL11.glDisable(GL11.GL_STENCIL_TEST); - GlStateManager.enableCull(); - } -} 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 cb2b7031b0..281830c32c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java @@ -2,11 +2,11 @@ import com.google.common.collect.Lists; import com.google.gson.*; -import io.github.moulberry.notenoughupdates.NEUEventListener; import io.github.moulberry.notenoughupdates.NEUOverlay; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.config.Position; import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils; +import io.github.moulberry.notenoughupdates.listener.RenderListener; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.overlays.TextOverlay; import io.github.moulberry.notenoughupdates.overlays.TextOverlayStyle; @@ -737,7 +737,7 @@ public static Pet getPetFromStack(String name, String[] lore) { @SubscribeEvent public void onTick(TickEvent.ClientTickEvent event) { - if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && NEUEventListener.inventoryLoaded) { + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && RenderListener.inventoryLoaded) { GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; ContainerChest container = (ContainerChest) chest.inventorySlots; IInventory lower = container.getLowerChestInventory(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java index 8996dc7a42..f2205c49e7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java @@ -3,10 +3,10 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import io.github.moulberry.notenoughupdates.NEUEventListener; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.auction.APIManager; import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.listener.RenderListener; import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; @@ -55,8 +55,7 @@ public class AccessoryBagOverlay { Utils.createItemStack(Items.diamond_sword, EnumChatFormatting.DARK_AQUA + "Total Stat Bonuses", 0 ), - Utils.createItemStack( - Item.getItemFromBlock(Blocks.anvil), + Utils.createItemStack(Item.getItemFromBlock(Blocks.anvil), EnumChatFormatting.DARK_AQUA + "Total Stat Bonuses (from reforges)", 0 ), @@ -95,14 +94,30 @@ public static boolean mouseClick() { int mouseX = Mouse.getX() / scaledResolution.getScaleFactor(); int mouseY = height - Mouse.getY() / scaledResolution.getScaleFactor(); - int xSize = - (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "xSize", "field_146999_f"); - int ySize = - (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "ySize", "field_147000_g"); - int guiLeft = - (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "guiLeft", "field_147003_i"); - int guiTop = - (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "guiTop", "field_147009_r"); + int xSize = (int) Utils.getField( + GuiContainer.class, + Minecraft.getMinecraft().currentScreen, + "xSize", + "field_146999_f" + ); + int ySize = (int) Utils.getField( + GuiContainer.class, + Minecraft.getMinecraft().currentScreen, + "ySize", + "field_147000_g" + ); + int guiLeft = (int) Utils.getField( + GuiContainer.class, + Minecraft.getMinecraft().currentScreen, + "guiLeft", + "field_147003_i" + ); + int guiTop = (int) Utils.getField( + GuiContainer.class, + Minecraft.getMinecraft().currentScreen, + "guiTop", + "field_147009_r" + ); if (mouseX < guiLeft + xSize + 3 || mouseX > guiLeft + xSize + 80 + 28) return false; if (mouseY < guiTop || mouseY > guiTop + 166) return false; @@ -196,8 +211,7 @@ public static void renderBasicOverlay(int x, int y) { } } - Utils.drawStringCenteredScaledMaxWidth( - "# By Rarity", + Utils.drawStringCenteredScaledMaxWidth("# By Rarity", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -230,8 +244,7 @@ public static void renderTotalStatsOverlay(int x, int y) { } } - Utils.drawStringCenteredScaledMaxWidth( - "Total Stats", + Utils.drawStringCenteredScaledMaxWidth("Total Stats", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -278,8 +291,7 @@ public static void renderReforgeStatsOverlay(int x, int y) { } } - Utils.drawStringCenteredScaledMaxWidth( - "Reforge Stats", + Utils.drawStringCenteredScaledMaxWidth("Reforge Stats", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -322,8 +334,7 @@ public static void renderDuplicatesOverlay(int x, int y) { if (duplicates == null) { JsonObject misc = Constants.MISC; if (misc == null) { - Utils.drawStringCenteredScaledMaxWidth( - "Duplicates: ERROR", + Utils.drawStringCenteredScaledMaxWidth("Duplicates: ERROR", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -335,8 +346,7 @@ public static void renderDuplicatesOverlay(int x, int y) { } JsonElement talisman_upgrades_element = misc.get("talisman_upgrades"); if (talisman_upgrades_element == null) { - Utils.drawStringCenteredScaledMaxWidth( - "Duplicates: ERROR", + Utils.drawStringCenteredScaledMaxWidth("Duplicates: ERROR", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -378,8 +388,7 @@ public static void renderDuplicatesOverlay(int x, int y) { } } if (duplicates.isEmpty()) { - Utils.drawStringCenteredScaledMaxWidth( - "No Duplicates", + Utils.drawStringCenteredScaledMaxWidth("No Duplicates", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -388,8 +397,7 @@ public static void renderDuplicatesOverlay(int x, int y) { new Color(80, 80, 80).getRGB() ); } else { - Utils.drawStringCenteredScaledMaxWidth( - "Duplicates: " + duplicates.size(), + Utils.drawStringCenteredScaledMaxWidth("Duplicates: " + duplicates.size(), Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -424,8 +432,7 @@ public static void renderMissingOverlay(int x, int y) { if (missing == null) { JsonObject misc = Constants.MISC; if (misc == null) { - Utils.drawStringCenteredScaledMaxWidth( - "Duplicates: ERROR", + Utils.drawStringCenteredScaledMaxWidth("Duplicates: ERROR", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -437,8 +444,7 @@ public static void renderMissingOverlay(int x, int y) { } JsonElement talisman_upgrades_element = misc.get("talisman_upgrades"); if (talisman_upgrades_element == null) { - Utils.drawStringCenteredScaledMaxWidth( - "Duplicates: ERROR", + Utils.drawStringCenteredScaledMaxWidth("Duplicates: ERROR", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -513,8 +519,7 @@ public static void renderMissingOverlay(int x, int y) { } } if (missing.isEmpty()) { - Utils.drawStringCenteredScaledMaxWidth( - "No Missing", + Utils.drawStringCenteredScaledMaxWidth("No Missing", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -523,8 +528,7 @@ public static void renderMissingOverlay(int x, int y) { new Color(80, 80, 80).getRGB() ); } else { - Utils.drawStringCenteredScaledMaxWidth( - "Missing: " + missing.size(), + Utils.drawStringCenteredScaledMaxWidth("Missing: " + missing.size(), Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -649,8 +653,7 @@ public static void renderMissingOverlay(int x, int y) { private static int mainWeapon = 1; public static void renderOptimizerOverlay(int x, int y) { - Utils.drawStringCenteredScaledMaxWidth( - "Optimizer", + Utils.drawStringCenteredScaledMaxWidth("Optimizer", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 12, @@ -683,8 +686,7 @@ public static void renderOptimizerOverlay(int x, int y) { dark ); - Utils.drawStringCenteredScaledMaxWidth( - "Force 100% CC", + Utils.drawStringCenteredScaledMaxWidth("Force 100% CC", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 27, @@ -696,8 +698,7 @@ public static void renderOptimizerOverlay(int x, int y) { Minecraft.getMinecraft().fontRendererObj, x + 20, y + 37, true, 30, new Color(80, 80, 80).getRGB() ); - Utils.drawStringCenteredScaledMaxWidth( - (forceCC ? EnumChatFormatting.GRAY : EnumChatFormatting.RED) + "NO", + Utils.drawStringCenteredScaledMaxWidth((forceCC ? EnumChatFormatting.GRAY : EnumChatFormatting.RED) + "NO", Minecraft.getMinecraft().fontRendererObj, x + 60, y + 37, @@ -706,8 +707,7 @@ public static void renderOptimizerOverlay(int x, int y) { new Color(80, 80, 80).getRGB() ); - Utils.drawStringCenteredScaledMaxWidth( - "Force 100% ATKSPEED", + Utils.drawStringCenteredScaledMaxWidth("Force 100% ATKSPEED", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 47, @@ -715,8 +715,7 @@ public static void renderOptimizerOverlay(int x, int y) { 70, new Color(80, 80, 80).getRGB() ); - Utils.drawStringCenteredScaledMaxWidth( - (forceAS ? EnumChatFormatting.GREEN : EnumChatFormatting.GRAY) + "YES", + Utils.drawStringCenteredScaledMaxWidth((forceAS ? EnumChatFormatting.GREEN : EnumChatFormatting.GRAY) + "YES", Minecraft.getMinecraft().fontRendererObj, x + 20, y + 57, @@ -724,8 +723,7 @@ public static void renderOptimizerOverlay(int x, int y) { 30, new Color(80, 80, 80).getRGB() ); - Utils.drawStringCenteredScaledMaxWidth( - (forceAS ? EnumChatFormatting.GRAY : EnumChatFormatting.RED) + "NO", + Utils.drawStringCenteredScaledMaxWidth((forceAS ? EnumChatFormatting.GRAY : EnumChatFormatting.RED) + "NO", Minecraft.getMinecraft().fontRendererObj, x + 60, y + 57, @@ -734,8 +732,7 @@ public static void renderOptimizerOverlay(int x, int y) { new Color(80, 80, 80).getRGB() ); - Utils.drawStringCenteredScaledMaxWidth( - "Use God Potion", + Utils.drawStringCenteredScaledMaxWidth("Use God Potion", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 67, @@ -743,8 +740,7 @@ public static void renderOptimizerOverlay(int x, int y) { 70, new Color(80, 80, 80).getRGB() ); - Utils.drawStringCenteredScaledMaxWidth( - (useGodPot ? EnumChatFormatting.GREEN : EnumChatFormatting.GRAY) + "YES", + Utils.drawStringCenteredScaledMaxWidth((useGodPot ? EnumChatFormatting.GREEN : EnumChatFormatting.GRAY) + "YES", Minecraft.getMinecraft().fontRendererObj, x + 20, y + 77, @@ -752,8 +748,7 @@ public static void renderOptimizerOverlay(int x, int y) { 30, new Color(80, 80, 80).getRGB() ); - Utils.drawStringCenteredScaledMaxWidth( - (useGodPot ? EnumChatFormatting.GRAY : EnumChatFormatting.RED) + "NO", + Utils.drawStringCenteredScaledMaxWidth((useGodPot ? EnumChatFormatting.GRAY : EnumChatFormatting.RED) + "NO", Minecraft.getMinecraft().fontRendererObj, x + 60, y + 77, @@ -762,8 +757,7 @@ public static void renderOptimizerOverlay(int x, int y) { new Color(80, 80, 80).getRGB() ); - Utils.drawStringCenteredScaledMaxWidth( - "Use God Potion", + Utils.drawStringCenteredScaledMaxWidth("Use God Potion", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 87, @@ -780,8 +774,7 @@ public static void renderOptimizerOverlay(int x, int y) { true, 30, new Color(80, 80, 80).getRGB() ); - Utils.drawStringCenteredScaledMaxWidth( - "Main Weapon", + Utils.drawStringCenteredScaledMaxWidth("Main Weapon", Minecraft.getMinecraft().fontRendererObj, x + 40, y + 107, @@ -839,7 +832,7 @@ public static boolean isInAccessoryBag() { public static void renderOverlay() { inAccessoryBag = false; - if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && NEUEventListener.inventoryLoaded) { + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && RenderListener.inventoryLoaded) { GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; ContainerChest cc = (ContainerChest) eventGui.inventorySlots; String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java index bce5bfbd7a..2d4d4382b2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java @@ -1,7 +1,6 @@ package io.github.moulberry.notenoughupdates.miscgui; import com.google.common.collect.Lists; -import io.github.moulberry.notenoughupdates.NEUEventListener; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.*; import io.github.moulberry.notenoughupdates.core.config.KeybindHelper; @@ -9,6 +8,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers; import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking; import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager; +import io.github.moulberry.notenoughupdates.util.NotificationHandler; import io.github.moulberry.notenoughupdates.util.SpecialColour; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; @@ -2306,7 +2306,7 @@ private void renderEnchOverlay(Set locations) { public void fastRenderCheck() { if (!OpenGlHelper.isFramebufferEnabled() && NotEnoughUpdates.INSTANCE.config.storageGUI.enableStorageGUI3) { this.fastRender = true; - NEUEventListener.displayNotification(Lists.newArrayList( + NotificationHandler.displayNotification(Lists.newArrayList( "\u00a74Fast Render Warning", "\u00a77Due to the way fast render works, it's not compatible with NEU.", "\u00a77Please disable fast render in your options under", diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java index 2692372672..e98c3330cc 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java @@ -1,16 +1,13 @@ package io.github.moulberry.notenoughupdates.mixins; import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects; -import io.github.moulberry.notenoughupdates.miscfeatures.FancyPortals; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.client.settings.GameSettings; import net.minecraft.entity.Entity; -import net.minecraft.util.MathHelper; import net.minecraftforge.client.ForgeHooksClient; -import org.lwjgl.util.glu.Project; import org.lwjgl.util.vector.Vector3f; import org.spongepowered.asm.lib.Opcodes; import org.spongepowered.asm.mixin.Mixin; @@ -19,20 +16,18 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(EntityRenderer.class) public abstract class MixinEntityRenderer { - @Shadow - protected abstract float getFOVModifier(float partialTicks, boolean useFOVSetting); - @Shadow private Minecraft mc; - @Shadow private float farPlaneDistance; + @Shadow + protected abstract float getFOVModifier(float partialTicks, boolean useFOVSetting); + @Shadow protected abstract void orientCamera(float partialTicks); @@ -50,38 +45,6 @@ public float updateCameraAndRender_mouseSensitivity(GameSettings gameSettings) { return gameSettings.mouseSensitivity * CustomItemEffects.INSTANCE.getSensMultiplier(); } - @Redirect(method = "renderWorldPass", at = @At( - value = "INVOKE", - target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", - remap = false) - ) - public void perspective(float f1, float f2, float f3, float f4) { - if (!FancyPortals.overridePerspective()) { - Project.gluPerspective(f1, f2, f3, f4); - } - } - - @Inject(method = "updateCameraAndRender", at = @At("RETURN")) - public void onUpdateCameraAndRender(float partialTicks, long nanoTime, CallbackInfo ci) { - if (Minecraft.getMinecraft().getRenderViewEntity() == null) return; - - if (FancyPortals.shouldRenderWorldOverlay()) { - GlStateManager.matrixMode(5889); - GlStateManager.loadIdentity(); - Project.gluPerspective(getFOVModifier(partialTicks, true), - (float) mc.displayWidth / (float) this.mc.displayHeight, 0.05F, - farPlaneDistance * MathHelper.SQRT_2 - ); - GlStateManager.matrixMode(5888); - GlStateManager.loadIdentity(); - orientCamera(partialTicks); - - FancyPortals.onUpdateCameraAndRender(partialTicks, nanoTime); - - Minecraft.getMinecraft().entityRenderer.setupOverlayRendering(); - } - } - @Redirect(method = "renderWorldPass", at = @At( value = "INVOKE", target = "Lnet/minecraftforge/client/ForgeHooksClient;dispatchRenderLast(Lnet/minecraft/client/renderer/RenderGlobal;F)V", diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java index 4d1545b68a..9f7d852855 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java @@ -1,8 +1,8 @@ package io.github.moulberry.notenoughupdates.mixins; -import io.github.moulberry.notenoughupdates.NEUEventListener; import io.github.moulberry.notenoughupdates.NEUOverlay; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.listener.RenderListener; import io.github.moulberry.notenoughupdates.miscfeatures.*; import io.github.moulberry.notenoughupdates.miscgui.GuiCustomEnchant; import io.github.moulberry.notenoughupdates.miscgui.StorageOverlay; @@ -100,7 +100,7 @@ public void drawSlot(Slot slot, CallbackInfo ci) { else if (!($this instanceof GuiChest)) BetterContainers.profileViewerStackIndex = -1; - if (slot.getStack() == null && NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) { + if (slot.getStack() == null && NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen) { GlStateManager.pushMatrix(); GlStateManager.translate(0, 0, 100 + Minecraft.getMinecraft().getRenderItem().zLevel); GlStateManager.depthMask(false); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java index 25b036ab5c..7b225d50e2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java @@ -1,7 +1,7 @@ package io.github.moulberry.notenoughupdates.mixins; -import io.github.moulberry.notenoughupdates.NEUEventListener; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.listener.RenderListener; import net.minecraft.client.gui.inventory.GuiInventory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -13,7 +13,7 @@ public class MixinGuiInventory { @Inject(method = "drawGuiContainerForegroundLayer", at = @At("HEAD"), cancellable = true) protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY, CallbackInfo ci) { if (NotEnoughUpdates.INSTANCE.config.inventoryButtons.hideCrafting || - NEUEventListener.disableCraftingText) { + RenderListener.disableCraftingText) { ci.cancel(); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLoadingScreenRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLoadingScreenRenderer.java deleted file mode 100644 index dbdad65a26..0000000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLoadingScreenRenderer.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.github.moulberry.notenoughupdates.mixins; - -import io.github.moulberry.notenoughupdates.miscfeatures.FancyPortals; -import net.minecraft.client.LoadingScreenRenderer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(LoadingScreenRenderer.class) -public class MixinLoadingScreenRenderer { - @Inject(method = "setLoadingProgress", at = @At(value = "HEAD"), cancellable = true) - public void setLoadingProgress(int progress, CallbackInfo ci) { - if (progress < 0 && !FancyPortals.shouldRenderLoadingScreen()) { - ci.cancel(); - } - } -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMouseHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMouseHelper.java index 4d8df94904..ff71ad1ed1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMouseHelper.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMouseHelper.java @@ -1,6 +1,6 @@ package io.github.moulberry.notenoughupdates.mixins; -import io.github.moulberry.notenoughupdates.NEUEventListener; +import io.github.moulberry.notenoughupdates.listener.RenderListener; import net.minecraft.util.MouseHelper; import org.lwjgl.input.Mouse; import org.spongepowered.asm.mixin.Mixin; @@ -12,7 +12,7 @@ public class MixinMouseHelper { @Inject(method = {"ungrabMouseCursor"}, at = {@At("HEAD")}, cancellable = true) public void ungrabMouseCursor(final CallbackInfo ci) { - if (System.currentTimeMillis() - NEUEventListener.lastGuiClosed < 150L) { + if (System.currentTimeMillis() - RenderListener.lastGuiClosed < 150L) { ci.cancel(); Mouse.setGrabbed(false); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java index d47dce2c67..4c2a0485cc 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java @@ -61,11 +61,6 @@ public void handleParticles( } } - @Inject(method = "handleSpawnMob", at = @At("RETURN")) - public void handleSpawnMob(S0FPacketSpawnMob packetIn, CallbackInfo ci) { - //CollectionLogManager.getInstance().onEntityMetadataUpdated(packetIn.getEntityID()); - } - @Inject(method = "handleSetSlot", at = @At("RETURN")) public void handleSetSlot(S2FPacketSetSlot packetIn, CallbackInfo ci) { EnchantingSolvers.processInventoryContents(false); @@ -87,14 +82,6 @@ public void handleOpenWindow(S30PacketWindowItems packetIn, CallbackInfo ci) { StorageManager.getInstance().setItemsPacket(packetIn); } - @Inject(method = "handleRespawn", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/network/PacketThreadUtil;checkThreadAndEnqueue(Lnet/minecraft/network/Packet;Lnet/minecraft/network/INetHandler;Lnet/minecraft/util/IThreadListener;)V", - shift = At.Shift.AFTER)) - public void handleOpenWindow(S07PacketRespawn packetIn, CallbackInfo ci) { - FancyPortals.onRespawnPacket(packetIn); - } - @Inject(method = "handleBlockChange", at = @At("HEAD")) public void handleBlockChange(S23PacketBlockChange packetIn, CallbackInfo ci) { MiningStuff.processBlockChangePacket(packetIn); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java index 630874ab1d..6c432ce36a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java @@ -1,9 +1,9 @@ package io.github.moulberry.notenoughupdates.mixins; -import io.github.moulberry.notenoughupdates.NEUEventListener; import io.github.moulberry.notenoughupdates.NEUOverlay; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.ChromaColour; +import io.github.moulberry.notenoughupdates.listener.RenderListener; import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns; import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager; import net.minecraft.client.Minecraft; @@ -176,7 +176,7 @@ public void renderEffect_blendFunc(int src, int dst) { @Inject(method = "renderItemIntoGUI", at = @At("HEAD")) public void renderItemHead(ItemStack stack, int x, int y, CallbackInfo ci) { - if (NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) { + if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen) { boolean matches = false; GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField(); @@ -202,7 +202,7 @@ public void renderItemHead(ItemStack stack, int x, int y, CallbackInfo ci) { @Inject(method = "renderItemIntoGUI", at = @At("RETURN")) public void renderItemReturn(ItemStack stack, int x, int y, CallbackInfo ci) { if (stack != null && stack.stackSize != 1) return; - if (NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) { + if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen) { boolean matches = false; GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField(); @@ -233,7 +233,7 @@ public void renderItemOverlayIntoGUI( CallbackInfo ci ) { if (stack != null && stack.stackSize != 1) { - if (NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) { + if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen) { boolean matches = false; GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java index bb3b342500..dab4844d71 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java @@ -1,7 +1,6 @@ package io.github.moulberry.notenoughupdates.util; import com.google.gson.*; -import io.github.moulberry.notenoughupdates.collectionlog.CollectionConstant; import java.lang.reflect.Type; import java.util.concurrent.locks.ReentrantLock; @@ -40,7 +39,6 @@ public JsonElement serialize(Pattern src, Type typeOfSrc, JsonSerializationConte public static JsonObject ESSENCECOSTS; public static JsonObject FAIRYSOULS; public static JsonObject REFORGESTONES; - public static CollectionConstant COLLECTIONLOG; private static final ReentrantLock lock = new ReentrantLock(); @@ -59,7 +57,6 @@ public static void reload() { ESSENCECOSTS = Utils.getConstant("essencecosts", gson); FAIRYSOULS = Utils.getConstant("fairy_souls", gson); REFORGESTONES = Utils.getConstant("reforgestones", gson); - //COLLECTIONLOG = Utils.getConstant("collectionlog", gson, CollectionConstant.class); } finally { lock.unlock(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/NotificationHandler.java b/src/main/java/io/github/moulberry/notenoughupdates/util/NotificationHandler.java new file mode 100644 index 0000000000..492c1dd70d --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/NotificationHandler.java @@ -0,0 +1,112 @@ +package io.github.moulberry.notenoughupdates.util; + +import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; +import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.ContainerChest; + +import java.util.List; + +public class NotificationHandler { + public static List notificationLines = null; + public static boolean showNotificationOverInv = false; + public static long notificationDisplayMillis = 0; + + public static void displayNotification(List lines, boolean showForever) { + displayNotification(lines, showForever, false); + } + + public static void displayNotification(List lines, boolean showForever, boolean overInventory) { + if (showForever) { + notificationDisplayMillis = -420; + } else { + notificationDisplayMillis = System.currentTimeMillis(); + } + notificationLines = lines; + showNotificationOverInv = overInventory; + } + + public static void renderNotification() { + long timeRemaining = 15000 - (System.currentTimeMillis() - notificationDisplayMillis); + boolean display = timeRemaining > 0 || notificationDisplayMillis == -420; + if (display && notificationLines != null && notificationLines.size() > 0) { + int width = 0; + int height = notificationLines.size() * 10 + 10; + + for (String line : notificationLines) { + int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line) + 8; + if (len > width) { + width = len; + } + } + + ScaledResolution sr = Utils.pushGuiScale(2); + + int midX = sr.getScaledWidth() / 2; + int topY = sr.getScaledHeight() * 3 / 4 - height / 2; + RenderUtils.drawFloatingRectDark(midX - width / 2, sr.getScaledHeight() * 3 / 4 - height / 2, width, height); + /*Gui.drawRect(midX-width/2, sr.getScaledHeight()*3/4-height/2, + midX+width/2, sr.getScaledHeight()*3/4+height/2, 0xFF3C3C3C); + Gui.drawRect(midX-width/2+2, sr.getScaledHeight()*3/4-height/2+2, + midX+width/2-2, sr.getScaledHeight()*3/4+height/2-2, 0xFFC8C8C8);*/ + + int xLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth("[X] Close"); + Minecraft.getMinecraft().fontRendererObj.drawString( + "[X] Close", + midX + width / 2f - 3 - xLen, + topY + 3, + 0xFFFF5555, + false + ); + + if (notificationDisplayMillis > 0) { + Minecraft.getMinecraft().fontRendererObj.drawString( + (timeRemaining / 1000) + "s", + midX - width / 2f + 3, + topY + 3, + 0xFFaaaaaa, + false + ); + } + + Utils.drawStringCentered( + notificationLines.get(0), + Minecraft.getMinecraft().fontRendererObj, + midX, + topY + 4 + 5, + false, + -1 + ); + for (int i = 1; i < notificationLines.size(); i++) { + String line = notificationLines.get(i); + Utils.drawStringCentered( + line, + Minecraft.getMinecraft().fontRendererObj, + midX, + topY + 4 + 5 + 2 + i * 10, + false, + -1 + ); + } + + Utils.pushGuiScale(-1); + } + } + + public static boolean shouldRenderOverlay(Gui gui) { + boolean validGui = gui instanceof GuiContainer || gui instanceof GuiItemRecipe; + if (gui instanceof GuiChest) { + GuiChest eventGui = (GuiChest) gui; + ContainerChest cc = (ContainerChest) eventGui.inventorySlots; + String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); + if (containerName.trim().equals("Fast Travel")) { + validGui = false; + } + } + return validGui; + } +} From 8b630cb7c39e73346d43b1e083b62b30fc3cde8f Mon Sep 17 00:00:00 2001 From: Lulonaut <67191924+Lulonaut@users.noreply.github.com> Date: Sun, 6 Mar 2022 08:41:22 +0100 Subject: [PATCH 002/222] Add sbcheck to item price warning (#89) --- .../moulberry/notenoughupdates/ItemPriceInformation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java index 1804831b1a..7dac5eb287 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java @@ -86,7 +86,7 @@ public static boolean addToTooltip(List tooltip, String internalname, It long currentTime = System.currentTimeMillis(); long lastUpdate = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLastLowestBinUpdateTime(); //check if info is older than 10 minutes - if (currentTime - lastUpdate > 600 * 1000) { + if (currentTime - lastUpdate > 600 * 1000 && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { tooltip.add(EnumChatFormatting.RED + "[NEU] Price info is outdated."); tooltip.add(EnumChatFormatting.RED + "It will be updated again as soon as possible."); } @@ -336,7 +336,7 @@ public static boolean addToTooltip(List tooltip, String internalname, It } return added; - } else if (auctionInfoErrored) { + } else if (auctionInfoErrored && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) { String message = EnumChatFormatting.RED.toString() + EnumChatFormatting.BOLD + "[NEU] API is down"; if (auctionableItems != null && !auctionableItems.isEmpty()) { if (auctionableItems.contains(internalname)) { From 73fad7064fb47d9d79ccdb3bab5988df1b9eea6f Mon Sep 17 00:00:00 2001 From: CraftyOldMiner <85420839+CraftyOldMiner@users.noreply.github.com> Date: Mon, 7 Mar 2022 21:44:17 -0600 Subject: [PATCH 003/222] Wishing Compass Solver, Metal Detector Solver improvements, add /neudiag, other misc changes (#90) --- .idea/codeStyles/Project.xml | 4 + Update Notes/2.0-Pre31-Release.md | 8 +- Update Notes/2.1.md | 5 + .../notenoughupdates/NotEnoughUpdates.java | 2 + .../notenoughupdates/commands/Commands.java | 1 + .../commands/dev/DevTestCommand.java | 2 +- .../commands/dev/DiagCommand.java | 90 ++++ .../notenoughupdates/core/util/Line.java | 90 ++++ .../listener/ChatListener.java | 2 +- .../listener/NEUEventListener.java | 2 +- .../CrystalMetalDetectorSolver.java | 439 +++++++++++++++--- .../CrystalWishingCompassSolver.java | 329 +++++++++++++ .../mixins/MixinNetHandlerPlayClient.java | 5 + .../notenoughupdates/options/NEUConfig.java | 32 +- .../options/customtypes/NEUDebugFlag.java | 12 + .../options/seperateSections/Mining.java | 8 + .../overlays/CrystalHollowOverlay.java | 54 +++ .../overlays/MiningOverlay.java | 167 ++----- .../notenoughupdates/util/NEUDebugLogger.java | 30 ++ .../notenoughupdates/util/Utils.java | 34 ++ 20 files changed, 1108 insertions(+), 208 deletions(-) create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 6cedf3ffca..c2c5091347 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,5 +1,9 @@ + + diff --git a/Update Notes/2.0-Pre31-Release.md b/Update Notes/2.0-Pre31-Release.md index da4fa3f4b1..dec4e6a1aa 100644 --- a/Update Notes/2.0-Pre31-Release.md +++ b/Update Notes/2.0-Pre31-Release.md @@ -9,9 +9,9 @@ - Added toggle to disable showing the treecap cooldown in item durability. (Lulonaut)# - Added text to inform the user to "/api new" when the /pv doesn't load. - Added support for the new arrows to the PV. -- Improved metal detector location detection logic. (Keebler408) -- Improved metal detector wrong location handling. (Keebler408) -- Added Beacons waypoints for metal detector waypoint locations. (Keebler408) +- Improved metal detector location detection logic. (CraftyOldMiner) +- Improved metal detector wrong location handling. (CraftyOldMiner) +- Added Beacons waypoints for metal detector waypoint locations. (CraftyOldMiner) - Made the PV command block in the right click player menu dynamically choose its position based on a empty slot. (DeDiamondPro) - Added Tab auto completion to the AH search gui. (Lulonaut) @@ -27,7 +27,7 @@ - Fixed not being able to press repeat keys in chat. - Fixed gemstone gauntlet/Divan Drill not being recognised as mining tools. - Fixed morph pets not being recognized by the extended pet info tooltip tweak. -- Fixed wrong commission maxes values for goblin in dwarven mines and the crystal hollows. (Keebler408) +- Fixed wrong commission max values for goblin in dwarven mines and the crystal hollows. (CraftyOldMiner) - Fixed player right click menu command block text appearing on an inventory item. (DeDiamondPro) diff --git a/Update Notes/2.1.md b/Update Notes/2.1.md index 1a120dfb8d..f8130d9208 100644 --- a/Update Notes/2.1.md +++ b/Update Notes/2.1.md @@ -13,6 +13,8 @@ - [Added an armor overlay for the new armor slots](https://cdn.discordapp.com/attachments/832652653292027904/922399046528794634/unknown.png) - Added a pet overlay that shows your active pet in your inventory - [Price graph for items on /ah and /bz](https://cdn.discordapp.com/attachments/896407218151366687/926968296929107999/unknown.png) - DeDiamondPro +- Added wishing compass solver that shows target coordinates using two samples - CraftyOldMiner +- Improved metal detector logic to solve using a single position in most cases using known locations based on Keeper coordinates - CraftyOldMiner ### **Minor Changes:** - Add built-in recipes for forge crafts - nea89 - Add Stranded Villager Trades to the item list - nea89 @@ -56,6 +58,8 @@ - Added custom sounds for crystal hollow gemstones - nea89 - Added custom biomes for crystal hollow areas - nopo - Added a config option to hide the reforge stats for Legendary items from Hypixel on reforge stones - Lulonaut +- Crystal Hollows crystal states are now updated when the Heart of the Mountain menu is opened - CraftyOldMiner +- Added /neudiag command to enable/disable debug logging and dump diagnostic data - CraftyOldMiner ### **Bug Fixes** - Fix wiki pages freezing the entire game - nea89 - Made titanium overlay and waypoints work with dwarven overlay off @@ -85,5 +89,6 @@ - Changed custom_enchant_gui.png to remove top right button - Added 4 new textures for the on/off switches in /neu - Code Cleanup - IRONM00N +- Renamed Keebler408 to CraftyOldMiner ### **Previous change log** https://github.com/NotEnoughUpdates/NotEnoughUpdates/blob/master/Update%20Notes/2.0-Pre31-Release.md diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 5ad82d56ac..0ed68e0663 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -25,6 +25,7 @@ import io.github.moulberry.notenoughupdates.listener.NEUEventListener; import io.github.moulberry.notenoughupdates.listener.RenderListener; import io.github.moulberry.notenoughupdates.miscfeatures.CrystalOverlay; +import io.github.moulberry.notenoughupdates.miscfeatures.CrystalWishingCompassSolver; import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects; import io.github.moulberry.notenoughupdates.miscfeatures.DwarvenMinesWaypoints; import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; @@ -226,6 +227,7 @@ public void preinit(FMLPreInitializationEvent event) { MinecraftForge.EVENT_BUS.register(InventoryStorageSelector.getInstance()); MinecraftForge.EVENT_BUS.register(SlotLocking.getInstance()); MinecraftForge.EVENT_BUS.register(FishingHelper.getInstance()); + MinecraftForge.EVENT_BUS.register(CrystalWishingCompassSolver.getInstance()); MinecraftForge.EVENT_BUS.register(new DwarvenMinesTextures()); MinecraftForge.EVENT_BUS.register(CustomBiomes.INSTANCE); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java index de017cb57c..5c2bf5c028 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java @@ -40,6 +40,7 @@ public Commands() { ClientCommandHandler.instance.registerCommand(new StatsCommand()); ClientCommandHandler.instance.registerCommand(new DevTestCommand()); ClientCommandHandler.instance.registerCommand(new NullzeeSphereCommand()); + ClientCommandHandler.instance.registerCommand(new DiagCommand()); // Repo Commands ClientCommandHandler.instance.registerCommand(new ResetRepoCommand()); 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 7caf09cb5a..53a7894b3e 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 @@ -24,7 +24,7 @@ public class DevTestCommand extends ClientCommandBase { private static final List DEV_TESTERS = - Arrays.asList("moulberry", "lucycoconut", "ironm00n", "ariyio", "throwpo", "lrg89", "dediamondpro", "lulonaut"); + Arrays.asList("moulberry", "lucycoconut", "ironm00n", "ariyio", "throwpo", "lrg89", "dediamondpro", "lulonaut", "craftyoldminer"); private static final String[] DEV_FAIL_STRINGS = { "No.", diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java new file mode 100644 index 0000000000..8826453866 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java @@ -0,0 +1,90 @@ +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.miscfeatures.CrystalMetalDetectorSolver; +import io.github.moulberry.notenoughupdates.miscfeatures.CrystalWishingCompassSolver; +import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +public class DiagCommand extends ClientCommandBase { + public DiagCommand() { + super("neudiag"); + } + + private static final String USAGE_TEXT = EnumChatFormatting.WHITE + + "Usage: /neudiag \n\n" + + "/neudiag metal Metal Detector Solver diagnostics\n" + + "/neudiag wishing Wishing Compass Solver diagnostics\n" + + "/neudiag debug\n" + + " Show current flags\n" + + " Enable/disable flag\n"; + + private void showUsage(ICommandSender sender) { + sender.addChatMessage(new ChatComponentText(USAGE_TEXT)); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if (args.length == 0) { + showUsage(sender); + return; + } + + String command = args[0].toLowerCase(); + switch (command) { + case "metal": + CrystalMetalDetectorSolver.logDiagnosticData(true); + break; + case "wishing": + CrystalWishingCompassSolver.getInstance().logDiagnosticData(true); + break; + case "debug": + if (args.length > 1) { + boolean enablingFlag = true; + String action = args[1]; + switch (action) { + case "disable": + enablingFlag = false; + // falls through + case "enable": + if (args.length != 3) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "You must specify a flag:\n" + + NEUDebugFlag.FLAG_LIST)); + return; + } + + String flagName = args[2].toUpperCase(); + try { + NEUDebugFlag debugFlag = NEUDebugFlag.valueOf(flagName); + if (enablingFlag) { + NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.add(debugFlag); + } else { + NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.remove(debugFlag); + } + } catch (IllegalArgumentException e) { + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + flagName + " is invalid. Valid flags are:\n" + + NEUDebugFlag.FLAG_LIST)); + return; + } + break; + default: + showUsage(sender); + return; + } + } + + sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "Effective debug flags: " + + NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.toString())); + break; + default: + showUsage(sender); + return; + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java new file mode 100644 index 0000000000..fb134e8522 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java @@ -0,0 +1,90 @@ +package io.github.moulberry.notenoughupdates.core.util; + +import net.minecraft.util.Vec3; + +/** + * Represents a line using two points along the line or a segment with endpoints. + */ +public class Line { + private static final double DOUBLE_EPSILON = 4.94065645841247E-324; + public Vec3 point1; + public Vec3 point2; + + public Line(Vec3 first, Vec3 second) { + point1 = first; + point2 = second; + } + + public Vec3 getMidpoint() { + return new Vec3((point1.xCoord + point2.xCoord) / 2.0, + (point1.yCoord + point2.yCoord) / 2.0, + (point1.zCoord + point2.zCoord) / 2.0); + } + + /** + * Calculates the intersection line segment between 2 lines + * Based on http://paulbourke.net/geometry/pointlineplane/calclineline.cs + * + * @return The intersection {@link Line} or {@code null} if no solution found + */ + public Line getIntersectionLineSegment(Line other) + { + Vec3 p1 = this.point1; + Vec3 p2 = this.point2; + Vec3 p3 = other.point1; + Vec3 p4 = other.point2; + Vec3 p13 = p1.subtract(p3); + Vec3 p43 = p4.subtract(p3); + + if (lengthSquared(p43) < DOUBLE_EPSILON) { + return null; + } + + Vec3 p21 = p2.subtract(p1); + if (lengthSquared(p21) < DOUBLE_EPSILON) { + return null; + } + + double d1343 = p13.xCoord * p43.xCoord + p13.yCoord * p43.yCoord + p13.zCoord * p43.zCoord; + double d4321 = p43.xCoord * p21.xCoord + p43.yCoord * p21.yCoord + p43.zCoord * p21.zCoord; + double d1321 = p13.xCoord * p21.xCoord + p13.yCoord * p21.yCoord + p13.zCoord * p21.zCoord; + double d4343 = p43.xCoord * p43.xCoord + p43.yCoord * p43.yCoord + p43.zCoord * p43.zCoord; + double d2121 = p21.xCoord * p21.xCoord + p21.yCoord * p21.yCoord + p21.zCoord * p21.zCoord; + + double denom = d2121 * d4343 - d4321 * d4321; + if (Math.abs(denom) < DOUBLE_EPSILON) { + return null; + } + double numer = d1343 * d4321 - d1321 * d4343; + + double mua = numer / denom; + double mub = (d1343 + d4321 * (mua)) / d4343; + + Line resultSegment = new Line( + new Vec3 ( + (float)(p1.xCoord + mua * p21.xCoord), + (float)(p1.yCoord + mua * p21.yCoord), + (float)(p1.zCoord + mua * p21.zCoord)), + new Vec3 ( + (float)(p3.xCoord + mub * p43.xCoord), + (float)(p3.yCoord + mub * p43.yCoord), + (float)(p3.zCoord + mub * p43.zCoord))); + + return resultSegment; + } + + public Line getImmutable() { + return new Line(point1, point2); + } + + private static double lengthSquared(Vec3 vec) { + return vec.dotProduct(vec); + } + + public String toString() { + return String.format("point1 = %s, point2 = %s, midpoint = %s", + point1 == null ? "NULL" : point1.toString(), + point2 == null ? "NULL" : point2.toString(), + (point1 == null || point2 == null) ? "NULL" : getMidpoint()); + } +} 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 633cd80f92..ebb537dcd1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java @@ -209,7 +209,7 @@ public void onGuiChat(ClientChatReceivedEvent e) { } if (unformatted.startsWith("You found ") && SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals("crystal_hollows")) { - CrystalMetalDetectorSolver.reset(true); + CrystalMetalDetectorSolver.resetSolution(true); } if (unformatted.startsWith("[NPC] Keeper of ") | unformatted.startsWith("[NPC] Professor Robot: ") || unformatted.startsWith(" ") || unformatted.startsWith("✦") || unformatted.equals( 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 ffebdd6b7c..eeb80abd5d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java @@ -140,7 +140,7 @@ private void displayUpdateMessageIfOutOfDate() { @SubscribeEvent public void onWorldLoad(WorldEvent.Unload event) { NotEnoughUpdates.INSTANCE.saveConfig(); - CrystalMetalDetectorSolver.reset(false); + CrystalMetalDetectorSolver.initWorld(); } @SubscribeEvent 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 4586d190ff..27c334adca 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java @@ -2,31 +2,119 @@ import io.github.moulberry.notenoughupdates.NotEnoughUpdates; 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 net.minecraft.client.Minecraft; -import net.minecraft.util.*; +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.Vec3; +import net.minecraft.util.Vec3i; -import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.stream.Collectors; public class CrystalMetalDetectorSolver { private static final Minecraft mc = Minecraft.getMinecraft(); + private static BlockPos prevPlayerPos; private static double prevDistToTreasure = 0; - private static List possibleBlocks = new ArrayList<>(); - private static final List locations = new ArrayList<>(); - + private static HashSet possibleBlocks = new HashSet<>(); + private static final HashMap evaluatedPlayerPositions = new HashMap<>(); + private static BlockPos blockPosIfLastSolutionInvalid; private static Boolean chestRecentlyFound = false; private static long chestLastFoundMillis = 0; + private static final HashSet openedChestPositions = new HashSet<>(); + + // Keeper and Mines of Divan center location info + private static Vec3i minesCenter; + private static boolean visitKeeperMessagePrinted = false; + private static String KEEPER_OF_STRING = "Keeper of "; + private static String DIAMOND_STRING = "diamond"; + private static String LAPIS_STRING = "lapis"; + private static String EMERALD_STRING = "emerald"; + private static String GOLD_STRING = "gold"; + private static final HashMap keeperOffsets = new HashMap() {{ + put(DIAMOND_STRING, new Vec3i(33,0,3)); + put(LAPIS_STRING, new Vec3i(-33,0,-3)); + put(EMERALD_STRING, new Vec3i(-3,0,33)); + put(GOLD_STRING, new Vec3i(3,0,-33)); + }}; + + // Chest offsets from center + private static final HashSet knownChestOffsets = new HashSet<>(Arrays.asList( + -10171958951910L, // x=-38, y=-22, z=26 + 10718829084646L, // x=38, y=-22, z=-26 + -10721714765806L, // x=-40, y=-22, z=18 + -10996458455018L, // x=-41, y=-20, z=22 + -1100920913904L, // x=-5, y=-21, z=16 + 11268584898530L, // x=40, y=-22, z=-30 + -11271269253148L, // x=-42, y=-20, z=-28 + -11546281377832L, // x=-43, y=-22, z=-40 + 11818542038999L, // x=42, y=-19, z=-41 + 12093285728240L, // x=43, y=-21, z=-16 + -1409286164L, // x=-1, y=-22, z=-20 + 1922736062492L, // x=6, y=-21, z=28 + 2197613969419L, // x=7, y=-21, z=11 + 2197613969430L, // x=7, y=-21, z=22 + -3024999153708L, // x=-12, y=-21, z=-44 + 3571936395295L, // x=12, y=-22, z=31 + 3572003504106L, // x=12, y=-22, z=-22 + 3572003504135L, // x=12, y=-21, z=7 + 3572070612949L, // x=12, y=-21, z=-43 + -3574822076373L, // x=-14, y=-21, z=43 + -3574822076394L, // x=-14, y=-21, z=22 + -4399455797228L, // x=-17, y=-21, z=20 + -5224156626944L, // x=-20, y=-22, z=0 + 548346527764L, // x=1, y=-21, z=20 + 5496081743901L, // x=19, y=-22, z=29 + 5770959650816L, // x=20, y=-22, z=0 + 5771093868518L, // x=20, y=-21, z=-26 + -6048790347736L, // x=-23, y=-22, z=40 + 6320849682418L, // x=22, y=-21, z=-14 + -6323668254708L, // x=-24, y=-22, z=12 + 6595593371674L, // x=23, y=-22, z=26 + 6595660480473L, // x=23, y=-22, z=-39 + 6870471278619L, // x=24, y=-22, z=27 + 7145349185553L, // x=25, y=-22, z=17 + 8244995030996L, // x=29, y=-21, z=-44 + -8247679385612L, // x=-31, y=-21, z=-12 + -8247679385640L, // x=-31, y=-21, z=-40 + 8519872937959L, // x=30, y=-21, z=-25 + -8522557292584L, // x=-32, y=-21, z=-40 + -9622068920278L, // x=-36, y=-20, z=42 + -9896946827278L, // x=-37, y=-21, z=-14 + -9896946827286L // x=-37, y=-21, z=-22 + )); public static void process(IChatComponent message) { + if (SBInfo.getInstance().getLocation() == null || + !NotEnoughUpdates.INSTANCE.config.mining.metalDetectorEnabled || + !SBInfo.getInstance().getLocation().equals("crystal_hollows") || + !message.getUnformattedText().contains("TREASURE: ")) { + return; + } + + locateMinesCenterIfNeeded(); + + double distToTreasure = Double.parseDouble(message + .getUnformattedText() + .split("TREASURE: ")[1].split("m")[0].replaceAll("(?!\\.)\\D", "")); + // Delay to keep old chest location from being treated as the new chest location if (chestRecentlyFound) { long currentTimeMillis = System.currentTimeMillis(); if (chestLastFoundMillis == 0) { chestLastFoundMillis = currentTimeMillis; return; - } else if (currentTimeMillis - chestLastFoundMillis < 1000) { + } else if (currentTimeMillis - chestLastFoundMillis < 1000 && distToTreasure < 5.0) { return; } @@ -34,80 +122,239 @@ public static void process(IChatComponent message) { chestRecentlyFound = false; } - if (SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals("crystal_hollows") - && message.getUnformattedText().contains("TREASURE: ")) { - double distToTreasure = Double.parseDouble(message - .getUnformattedText() - .split("TREASURE: ")[1].split("m")[0].replaceAll("(?!\\.)\\D", "")); - if (NotEnoughUpdates.INSTANCE.config.mining.metalDetectorEnabled && prevDistToTreasure == distToTreasure && - prevPlayerPos.getX() == mc.thePlayer.getPosition().getX() && - prevPlayerPos.getY() == mc.thePlayer.getPosition().getY() && - prevPlayerPos.getZ() == mc.thePlayer.getPosition().getZ() && !locations.contains(mc.thePlayer.getPosition())) { - if (possibleBlocks.size() == 0) { - locations.add(mc.thePlayer.getPosition()); - for (int zOffset = (int) Math.floor(-distToTreasure); zOffset <= Math.ceil(distToTreasure); zOffset++) { - for (int y = 65; y <= 75; y++) { - double calculatedDist = 0; - int xOffset = 0; - while (calculatedDist < distToTreasure) { - BlockPos pos = new BlockPos(Math.floor(mc.thePlayer.posX) + xOffset, - y, Math.floor(mc.thePlayer.posZ) + zOffset - ); - calculatedDist = getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)); - if (round(calculatedDist, 1) == distToTreasure && !possibleBlocks.contains(pos) && - treasureAllowed(pos) && mc.theWorld. - getBlockState(pos.add(0, 1, 0)).getBlock().getRegistryName().equals("minecraft:air")) { - possibleBlocks.add(pos); - } - xOffset++; - } - xOffset = 0; - calculatedDist = 0; - while (calculatedDist < distToTreasure) { - BlockPos pos = new BlockPos(Math.floor(mc.thePlayer.posX) - xOffset, - y, Math.floor(mc.thePlayer.posZ) + zOffset - ); - calculatedDist = getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)); - if (round(calculatedDist, 1) == distToTreasure && !possibleBlocks.contains(pos) && - treasureAllowed(pos) && mc.theWorld. - getBlockState(pos.add(0, 1, 0)).getBlock().getRegistryName().equals("minecraft:air")) { - possibleBlocks.add(pos); - } - xOffset++; + if (prevDistToTreasure == distToTreasure && + prevPlayerPos.equals(mc.thePlayer.getPosition()) && + !evaluatedPlayerPositions.keySet().contains(mc.thePlayer.getPosition())) { + if (possibleBlocks.size() == 0) { + evaluatedPlayerPositions.put(mc.thePlayer.getPosition(), distToTreasure); + for (int zOffset = (int) Math.floor(-distToTreasure); zOffset <= Math.ceil(distToTreasure); zOffset++) { + for (int y = 65; y <= 75; y++) { + double calculatedDist = 0; + int xOffset = 0; + while (calculatedDist < distToTreasure) { + BlockPos pos = new BlockPos(Math.floor(mc.thePlayer.posX) + xOffset, + y, Math.floor(mc.thePlayer.posZ) + zOffset); + calculatedDist = getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)); + if (round(calculatedDist, 1) == distToTreasure && treasureAllowed(pos)) { + possibleBlocks.add(pos); } + xOffset++; } - } - sendMessage(); - } else if (possibleBlocks.size() != 1) { - locations.add(mc.thePlayer.getPosition()); - List temp = new ArrayList<>(); - for (BlockPos pos : possibleBlocks) { - if (round(getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)), 1) == distToTreasure) { - temp.add(pos); + xOffset = 0; + calculatedDist = 0; + while (calculatedDist < distToTreasure) { + BlockPos pos = new BlockPos(Math.floor(mc.thePlayer.posX) - xOffset, + y, Math.floor(mc.thePlayer.posZ) + zOffset); + calculatedDist = getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)); + if (round(calculatedDist, 1) == distToTreasure && treasureAllowed(pos)) { + possibleBlocks.add(pos); + } + xOffset++; } } - possibleBlocks = temp; - sendMessage(); - } else { - BlockPos pos = possibleBlocks.get(0); - if (Math.abs(distToTreasure - (getPlayerPos().distanceTo(new Vec3(pos)))) > 5) { - mc.thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.RED + "[NEU] Previous solution is invalid.")); - reset(false); + } + + checkAndDisplaySolutionState(); + } else if (possibleBlocks.size() != 1) { + evaluatedPlayerPositions.put(mc.thePlayer.getPosition().getImmutable(), distToTreasure); + HashSet temp = new HashSet<>(); + for (BlockPos pos : possibleBlocks) { + if (round(getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)), 1) == distToTreasure) { + temp.add(pos); } } + possibleBlocks = temp; + checkAndDisplaySolutionState(); + } else { + BlockPos pos = possibleBlocks.iterator().next(); + if (Math.abs(distToTreasure - (getPlayerPos().distanceTo(new Vec3(pos)))) > 5) { + mc.thePlayer.addChatMessage(new ChatComponentText( + EnumChatFormatting.RED + "[NEU] Previous solution is invalid.")); + blockPosIfLastSolutionInvalid = pos.getImmutable(); + logDiagnosticData(false); + resetSolution(false); + } } + } + + prevPlayerPos = mc.thePlayer.getPosition().getImmutable(); + prevDistToTreasure = distToTreasure; + } + + private static void checkForSingleKnownLocationMatch() { + if (minesCenter == BlockPos.NULL_VECTOR || possibleBlocks.size() < 2) { + return; + } - prevPlayerPos = mc.thePlayer.getPosition(); - prevDistToTreasure = distToTreasure; + HashSet temp = possibleBlocks.stream() + .filter(block -> knownChestOffsets.contains(block.subtract(minesCenter).toLong())) + .collect(Collectors.toCollection(HashSet::new)); + if (temp.size() == 1) { + possibleBlocks = temp; + NEUDebugLogger.log(NEUDebugFlag.METAL, "Known location identified."); + } else if (temp.size() > 1) { + NEUDebugLogger.log(NEUDebugFlag.METAL, temp.size() + " known locations identified:"); } } - public static void reset(Boolean chestFound) { + private static String getFriendlyBlockPositions(Collection positions) { + if (!NEUDebugLogger.isFlagEnabled(NEUDebugFlag.METAL) || positions.size() == 0) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + sb.append("\n"); + for (BlockPos blockPos : positions) { + sb.append("Absolute: " + blockPos.toString()); + if (minesCenter != Vec3i.NULL_VECTOR) { + BlockPos relativeOffset = blockPos.subtract(minesCenter); + sb.append(", Relative: " + relativeOffset.toString() + " (" + relativeOffset.toLong() + ")"); + } + sb.append("\n"); + } + + return sb.toString(); + } + + private static String getFriendlyEvaluatedPositions(HashMap positions) { + if (!NEUDebugLogger.isFlagEnabled(NEUDebugFlag.METAL) || positions.size() == 0) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + sb.append("\n"); + for (BlockPos blockPos : positions.keySet()) { + sb.append("Absolute: " + blockPos.toString()); + if (minesCenter != Vec3i.NULL_VECTOR) { + BlockPos relativeOffset = blockPos.subtract(minesCenter); + sb.append(", Relative: " + relativeOffset.toString() + " (" + relativeOffset.toLong() + ")"); + } + + sb.append(" Distance: "); + sb.append(positions.get(blockPos)); + + sb.append("\n"); + } + + return sb.toString(); + } + + public static void logDiagnosticData(boolean outputAlways) { + if (SBInfo.getInstance().getLocation() == null) { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "[NEU] This command is not available outside SkyBlock")); + return; + } + + if (!NotEnoughUpdates.INSTANCE.config.mining.metalDetectorEnabled) + { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "[NEU] Metal Detector Solver is not enabled.")); + return; + } + + if (!outputAlways && !NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.contains(NEUDebugFlag.METAL)) { + return; + } + + boolean originalDebugFlag = !NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.add(NEUDebugFlag.METAL); + + StringBuilder diagsMessage = new StringBuilder(); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Mines Center: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((minesCenter == Vec3i.NULL_VECTOR) ? "" : minesCenter.toString()); + diagsMessage.append("\n"); + + diagsMessage.append("\n"); + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Previous Player Position: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((prevPlayerPos == null) ? "" : prevPlayerPos.toString()); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Previous Distance To Treasure: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((prevDistToTreasure == 0) ? "" : prevDistToTreasure); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Last Solution Invalid Position: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((blockPosIfLastSolutionInvalid == null) ? "" : blockPosIfLastSolutionInvalid.toString()); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Current Possible Blocks: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append(possibleBlocks.size()); + diagsMessage.append(getFriendlyBlockPositions(possibleBlocks)); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Evaluated player positions: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append(evaluatedPlayerPositions.size()); + diagsMessage.append(getFriendlyEvaluatedPositions(evaluatedPlayerPositions)); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Chest locations not on known list:\n"); + diagsMessage.append(EnumChatFormatting.WHITE); + if (minesCenter != Vec3i.NULL_VECTOR) { + HashSet locationsNotOnKnownList = openedChestPositions + .stream() + .filter(block -> !knownChestOffsets.contains(block.subtract(minesCenter).toLong())) + .map(block -> block.subtract(minesCenter)) + .collect(Collectors.toCollection(HashSet::new)); + if (locationsNotOnKnownList.size() > 0) { + for (BlockPos blockPos : locationsNotOnKnownList) { + diagsMessage.append(String.format( + "%dL,\t\t// x=%d, y=%d, z=%d", + blockPos.toLong(), + blockPos.getX(), + blockPos.getY(), + blockPos.getZ() + )); + } + } + } else { + diagsMessage.append(""); + } + + NEUDebugLogger.log(NEUDebugFlag.METAL, diagsMessage.toString()); + + if (!originalDebugFlag) { + NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.remove(NEUDebugFlag.METAL); + } + } + + public static void resetSolution(Boolean chestFound) { + if (chestFound) { + blockPosIfLastSolutionInvalid = null; + prevPlayerPos = null; + prevDistToTreasure = 0; + if (possibleBlocks.size() == 1) { + openedChestPositions.add(possibleBlocks.iterator().next().getImmutable()); + } + } + chestRecentlyFound = chestFound; possibleBlocks.clear(); - locations.clear(); + evaluatedPlayerPositions.clear(); + } + + public static void initWorld() { + minesCenter = Vec3i.NULL_VECTOR; + visitKeeperMessagePrinted = false; + blockPosIfLastSolutionInvalid = null; + openedChestPositions.clear(); + prevDistToTreasure = 0; + prevPlayerPos = null; + resetSolution(false); } public static void render(float partialTicks) { @@ -117,10 +364,10 @@ public static void render(float partialTicks) { SBInfo.getInstance().location.equals("Mines of Divan")) { if (possibleBlocks.size() == 1) { - BlockPos block = possibleBlocks.get(0); + BlockPos block = possibleBlocks.iterator().next(); RenderUtils.renderBeaconBeam(block.add(0, 1, 0), beaconRGB, 1.0f, partialTicks); - RenderUtils.renderWayPoint("Treasure", possibleBlocks.get(0).add(0, 2.5, 0), partialTicks); + RenderUtils.renderWayPoint("Treasure", possibleBlocks.iterator().next().add(0, 2.5, 0), partialTicks); } else if (possibleBlocks.size() > 1 && NotEnoughUpdates.INSTANCE.config.mining.metalDetectorShowPossible) { for (BlockPos block : possibleBlocks) { RenderUtils.renderBeaconBeam(block.add(0, 1, 0), beaconRGB, 1.0f, partialTicks); @@ -130,19 +377,55 @@ public static void render(float partialTicks) { } } + private static void locateMinesCenterIfNeeded() { + if (minesCenter != Vec3i.NULL_VECTOR) { + return; + } + + List keeperEntities = mc.theWorld.getEntities(EntityArmorStand.class, (entity) -> { + if (!entity.hasCustomName()) return false; + if (entity.getCustomNameTag().contains(KEEPER_OF_STRING)) return true; + return false; + }); + + 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.")); + visitKeeperMessagePrinted = true; + } + return; + } + + EntityArmorStand keeperEntity = keeperEntities.get(0); + String keeperName = keeperEntity.getCustomNameTag(); + NEUDebugLogger.log(NEUDebugFlag.METAL,"Locating center using Keeper: " + + EnumChatFormatting.WHITE + keeperEntity); + String keeperType = keeperName.substring(keeperName.indexOf(KEEPER_OF_STRING) + KEEPER_OF_STRING.length()); + 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.")); + } + private static double round(double value, int precision) { int scale = (int) Math.pow(10, precision); return (double) Math.round(value * scale) / scale; } - private static void sendMessage() { + private static void checkAndDisplaySolutionState() { + if (possibleBlocks.size() == 0) { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Failed to find a solution.")); + logDiagnosticData(false); + resetSolution(false); + return; + } + + checkForSingleKnownLocationMatch(); if (possibleBlocks.size() > 1) { - mc.thePlayer.addChatMessage(new ChatComponentText( - EnumChatFormatting.YELLOW + "[NEU] Need another position to find solution. Possible blocks: " - + possibleBlocks.size())); - } else if (possibleBlocks.size() == 0) { - mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Failed to find solution.")); - reset(false); + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + + "[NEU] Need another position to find solution. Possible blocks: " + possibleBlocks.size())); } else { mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] Found solution.")); } @@ -157,12 +440,16 @@ private static Vec3 getPlayerPos() { } private static boolean treasureAllowed(BlockPos pos) { - return mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:gold_block") || + boolean airAbove = mc.theWorld. + getBlockState(pos.add(0, 1, 0)).getBlock().getRegistryName().equals("minecraft:air"); + boolean allowedBlockType = mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:gold_block") || mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:prismarine") || mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:chest") || mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:stained_glass") || mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:stained_glass_pane") || mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:wool") || mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:stained_hardened_clay"); + boolean knownOffset = knownChestOffsets.contains(pos.subtract(minesCenter).toLong()); + return airAbove & (knownOffset | allowedBlockType); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java new file mode 100644 index 0000000000..25f39c3a7f --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java @@ -0,0 +1,329 @@ +package io.github.moulberry.notenoughupdates.miscfeatures; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.Line; +import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag; +import io.github.moulberry.notenoughupdates.util.NEUDebugLogger; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import net.minecraft.client.Minecraft; +import net.minecraft.event.ClickEvent; +import net.minecraft.event.HoverEvent; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.Vec3; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +public class CrystalWishingCompassSolver { + private static final CrystalWishingCompassSolver INSTANCE = new CrystalWishingCompassSolver(); + public static CrystalWishingCompassSolver getInstance() { + return INSTANCE; + } + + private static final Minecraft mc = Minecraft.getMinecraft(); + private static boolean isSkytilsPresent = false; + + // Crystal Nucleus unbreakable blocks, area coordinates reported by Hypixel server are slightly different + private static final AxisAlignedBB NUCLEUS_BB = new AxisAlignedBB(463, 63, 460, 563, 181, 564); + private static final double MAX_COMPASS_PARTICLE_SPREAD = 16; + + private static BlockPos prevPlayerPos; + private long compassUsedMillis = 0; + private Vec3 firstParticle = null; + private Vec3 lastParticle = null; + private double lastParticleDistanceFromFirst = 0; + private Line firstCompassLine = null; + private Line secondCompassLine = null; + private Vec3 solution = null; + private Line solutionIntersectionLine = null; + + private void resetForNewCompass() { + compassUsedMillis = 0; + firstParticle = null; + lastParticle = null; + lastParticleDistanceFromFirst = 0; + } + + private void resetForNewTarget() { + NEUDebugLogger.log(NEUDebugFlag.WISHING,"Resetting for new target"); + resetForNewCompass(); + firstCompassLine = null; + secondCompassLine = null; + solutionIntersectionLine = null; + prevPlayerPos = null; + solution = null; + } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Unload event) { + resetForNewTarget(); + isSkytilsPresent = Loader.isModLoaded("skytils"); + } + + @SubscribeEvent + public void onPlayerInteract(PlayerInteractEvent event) { + if (!NotEnoughUpdates.INSTANCE.config.mining.wishingCompassSolver || + SBInfo.getInstance().getLocation() == null || + !SBInfo.getInstance().getLocation().equals("crystal_hollows") || + event.entityPlayer != mc.thePlayer || + (event.action != PlayerInteractEvent.Action.RIGHT_CLICK_AIR && + event.action != PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) + ) { + return; + } + + ItemStack heldItem = event.entityPlayer.getHeldItem(); + if (heldItem == null || heldItem.getItem() != Items.skull) { + return; + } + + String heldInternalName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(heldItem); + if (heldInternalName == null || !heldInternalName.equals("WISHING_COMPASS")) { + return; + } + + try { + if (isSolved()) { + resetForNewTarget(); + } + + // 64.0 is an arbitrary value but seems to work well + if (prevPlayerPos != null && prevPlayerPos.distanceSq(mc.thePlayer.getPosition()) < 64.0) { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + + "[NEU] Move a little further before using the wishing compass again.")); + event.setCanceled(true); + return; + } + + prevPlayerPos = mc.thePlayer.getPosition().getImmutable(); + compassUsedMillis = System.currentTimeMillis(); + } catch (Exception e) { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "[NEU] Error processing wishing compass action - see log for details")); + e.printStackTrace(); + } + } + + /* + * Processes particles if the wishing compass was used within the last 5 seconds. + * + * The first and the last particles are used to create a line for each wishing compass + * use that is then used to calculate the target. + * + * Once two lines have been calculated, the shortest line between the two is calculated + * with the midpoint on that line being the wishing compass target. The accuracy of this + * seems to be very high. + * + * The target location varies based on various criteria, including, but not limited to: + * Topaz Crystal (Khazad-dûm) Magma Fields + * Odawa (Jungle Village) Jungle w/no Jungle Key in inventory + * Amethyst Crystal (Jungle Temple) Jungle w/Jungle Key in inventory + * Sapphire Crystal (Lost Precursor City) Precursor Remnants + * Jade Crystal (Mines of Divan) Mithril Deposits + * King Yolkar Goblin Holdout without "King's Scent I" effect + * Goblin Queen Goblin Holdout with "King's Scent I" effect + * Crystal Nucleus All Crystals found and none placed + * per-area structure missing, or because Hypixel. + * Always within 1 block of X=513 Y=106 Z=551. + */ + public void onSpawnParticle( + EnumParticleTypes particleType, + double x, + double y, + double z + ) { + if (!NotEnoughUpdates.INSTANCE.config.mining.wishingCompassSolver || + particleType != EnumParticleTypes.VILLAGER_HAPPY || + !SBInfo.getInstance().getLocation().equals("crystal_hollows") || + isSolved() || + System.currentTimeMillis() - compassUsedMillis > 5000) { + return; + } + + try { + Vec3 particleVec = new Vec3(x, y, z); + if (firstParticle == null) { + firstParticle = particleVec; + return; + } + + double distanceFromFirst = particleVec.distanceTo(firstParticle); + if (distanceFromFirst > MAX_COMPASS_PARTICLE_SPREAD) { + return; + } + + if (distanceFromFirst >= lastParticleDistanceFromFirst) { + lastParticleDistanceFromFirst = distanceFromFirst; + lastParticle = particleVec; + return; + } + + // We get here when the second repetition of particles begins. + // Since the second repetition overlaps with the last few particles + // of the first repetition, the last particle we capture isn't truly the last. + // But that's OK since subsequent particles will be on the same line. + Line line = new Line(firstParticle, lastParticle); + if (firstCompassLine == null) { + firstCompassLine = line; + resetForNewCompass(); + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + + "[NEU] Need another position to determine wishing compass target.")); + return; + } + + secondCompassLine = line; + solutionIntersectionLine = firstCompassLine.getIntersectionLineSegment(secondCompassLine); + if (solutionIntersectionLine == null) { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "[NEU] Unable to determine wishing compass target.")); + logDiagnosticData(false); + return; + } + + solution = solutionIntersectionLine.getMidpoint(); + + if (solution.distanceTo(firstParticle) < 8) { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + + "[NEU] WARNING: Solution is likely incorrect.")); + logDiagnosticData(false); + return; + } + + showSolution(); + } catch (Exception e) { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "[NEU] Exception while calculating wishing compass solution - see log for details")); + e.printStackTrace(); + } + } + + private boolean isSolved() { + return solution != null; + } + + private void showSolution() { + if (solution == null) return; + String description = "[NEU] Wishing compass target: "; + String coordsText = String.format("%.0f %.0f %.0f", + solution.xCoord, + solution.yCoord, + solution.zCoord); + + if (NUCLEUS_BB.isVecInside(solution)) { + description += "Crystal Nucleus (" + coordsText + ")"; + } else { + description += coordsText; + } + + ChatComponentText message = new ChatComponentText(EnumChatFormatting.YELLOW + description); + + if (isSkytilsPresent) { + ChatStyle clickEvent = new ChatStyle().setChatClickEvent( + new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/sthw add WishingTarget " + coordsText)); + clickEvent.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText( + EnumChatFormatting.YELLOW + + "Add Skytils hollows waypoint"))); + message.setChatStyle(clickEvent); + } + + Minecraft.getMinecraft().thePlayer.addChatMessage(message); + } + + public void logDiagnosticData(boolean outputAlways) { + if (SBInfo.getInstance().getLocation() == null) { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "[NEU] This command is not available outside SkyBlock")); + return; + } + + if (!NotEnoughUpdates.INSTANCE.config.mining.wishingCompassSolver) + { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + + "[NEU] Wishing Compass Solver is not enabled.")); + return; + } + + if (!outputAlways && !NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.contains(NEUDebugFlag.WISHING)) { + return; + } + + boolean originalDebugFlag = !NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.add(NEUDebugFlag.WISHING); + + StringBuilder diagsMessage = new StringBuilder(); + + diagsMessage.append("\n"); + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Skytils Present: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append(isSkytilsPresent); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Compass Used Millis: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append(compassUsedMillis); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Compass Used Position: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((prevPlayerPos == null) ? "" : prevPlayerPos.toString()); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("First Particle: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((firstParticle == null) ? "" : firstParticle.toString()); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Last Particle: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((lastParticle == null) ? "" : lastParticle.toString()); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Last Particle Distance From First: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append(lastParticleDistanceFromFirst); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("First Compass Line: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((firstCompassLine == null) ? "" : firstCompassLine.toString()); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Second Compass Line: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((secondCompassLine == null) ? "" : secondCompassLine.toString()); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Intersection Line: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((secondCompassLine == null) ? "" : solutionIntersectionLine); + diagsMessage.append("\n"); + + diagsMessage.append(EnumChatFormatting.AQUA); + diagsMessage.append("Solution: "); + diagsMessage.append(EnumChatFormatting.WHITE); + diagsMessage.append((solution == null) ? "" : solution.toString()); + diagsMessage.append("\n"); + + NEUDebugLogger.log(NEUDebugFlag.WISHING, diagsMessage.toString()); + + if (!originalDebugFlag) { + NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.remove(NEUDebugFlag.WISHING); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java index 4c2a0485cc..f7baffd6bc 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java @@ -47,6 +47,11 @@ public void handleParticles( double xCoord, double yCoord, double zCoord, double xOffset, double yOffset, double zOffset, int[] params ) { + CrystalWishingCompassSolver.getInstance().onSpawnParticle(particleTypes, + xCoord, + yCoord, + zCoord + ); boolean override = FishingHelper.getInstance().onSpawnParticle( particleTypes, xCoord, 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 470b038152..1d03a2d1e2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java @@ -11,8 +11,35 @@ import io.github.moulberry.notenoughupdates.miscgui.GuiEnchantColour; import io.github.moulberry.notenoughupdates.miscgui.GuiInvButtonEditor; import io.github.moulberry.notenoughupdates.miscgui.NEUOverlayPlacements; -import io.github.moulberry.notenoughupdates.options.seperateSections.*; +import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag; +import io.github.moulberry.notenoughupdates.options.seperateSections.AccessoryBag; +import io.github.moulberry.notenoughupdates.options.seperateSections.AHGraph; +import io.github.moulberry.notenoughupdates.options.seperateSections.AHTweaks; +import io.github.moulberry.notenoughupdates.options.seperateSections.ApiKey; +import io.github.moulberry.notenoughupdates.options.seperateSections.Calendar; import io.github.moulberry.notenoughupdates.options.seperateSections.CustomArmour; +import io.github.moulberry.notenoughupdates.options.seperateSections.Dungeons; +import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig; +import io.github.moulberry.notenoughupdates.options.seperateSections.Enchanting; +import io.github.moulberry.notenoughupdates.options.seperateSections.Fishing; +import io.github.moulberry.notenoughupdates.options.seperateSections.ImprovedSBMenu; +import io.github.moulberry.notenoughupdates.options.seperateSections.InventoryButtons; +import io.github.moulberry.notenoughupdates.options.seperateSections.Itemlist; +import io.github.moulberry.notenoughupdates.options.seperateSections.ItemOverlays; +import io.github.moulberry.notenoughupdates.options.seperateSections.LocationEdit; +import io.github.moulberry.notenoughupdates.options.seperateSections.Mining; +import io.github.moulberry.notenoughupdates.options.seperateSections.Misc; +import io.github.moulberry.notenoughupdates.options.seperateSections.MiscOverlays; +import io.github.moulberry.notenoughupdates.options.seperateSections.NeuAuctionHouse; +import io.github.moulberry.notenoughupdates.options.seperateSections.Notifications; +import io.github.moulberry.notenoughupdates.options.seperateSections.PetOverlay; +import io.github.moulberry.notenoughupdates.options.seperateSections.SlayerOverlay; +import io.github.moulberry.notenoughupdates.options.seperateSections.SlotLocking; +import io.github.moulberry.notenoughupdates.options.seperateSections.SkillOverlays; +import io.github.moulberry.notenoughupdates.options.seperateSections.StorageGUI; +import io.github.moulberry.notenoughupdates.options.seperateSections.Toolbar; +import io.github.moulberry.notenoughupdates.options.seperateSections.TooltipTweaks; +import io.github.moulberry.notenoughupdates.options.seperateSections.TradeMenu; import io.github.moulberry.notenoughupdates.overlays.MiningOverlay; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; import io.github.moulberry.notenoughupdates.overlays.TextOverlay; @@ -22,6 +49,7 @@ import org.lwjgl.util.vector.Vector2f; import java.util.ArrayList; +import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -318,6 +346,8 @@ public static class Hidden { @Expose public List inventoryButtons = createDefaultInventoryButtons(); + @Expose + public EnumSet debugFlags = EnumSet.noneOf(NEUDebugFlag.class); @Expose public boolean enableItemEditing = false; @Expose diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java b/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java new file mode 100644 index 0000000000..5b3188d6df --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java @@ -0,0 +1,12 @@ +package io.github.moulberry.notenoughupdates.options.customtypes; + +public enum NEUDebugFlag { + // NOTE: Removing enum values causes gson to remove all debugFlags on load if any removed value is present + METAL, + WISHING, + ; + + public static final String FLAG_LIST = + "METAL - Metal Detector Solver\n" + + "WISHING - Wishing Compass Solver"; +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java index 6ebd7f4228..3af3347a05 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java @@ -665,6 +665,14 @@ public class Mining { @ConfigEditorBoolean public boolean titaniumAlertMustBeVisible = false; + @Expose + @ConfigOption( + name = "Wishing Compass Solver", + desc = "Show wishing compass target coordinates based on two samples" + ) + @ConfigEditorBoolean + public boolean wishingCompassSolver = true; + @ConfigOption( name = "Custom Textures", desc = "" diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/CrystalHollowOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/CrystalHollowOverlay.java index 529f132a9f..ea190323c3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/CrystalHollowOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/CrystalHollowOverlay.java @@ -7,7 +7,10 @@ import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumChatFormatting; import org.lwjgl.util.vector.Vector2f; @@ -49,6 +52,57 @@ public CrystalHollowOverlay( super(position, dummyStrings, styleSupplier); } + private final Pattern hotmCrystalNotFoundPattern = Pattern.compile("(?[a-zA-Z]+) \\u2716 Not Found"); + private final Pattern hotmCrystalNotPlacedPattern = Pattern.compile("(?[a-zA-Z]+) \\u2716 Not Placed"); + private final Pattern hotmCrystalPlacedPattern = Pattern.compile("(?[a-zA-Z]+) \\u2714 Placed"); + + private void updateHotmCrystalState(IInventory lower) { + NEUConfig.HiddenProfileSpecific perProfileConfig = NotEnoughUpdates.INSTANCE.config.getProfileSpecific(); + if (perProfileConfig == null) return; + + ItemStack crystalStateStack = lower.getStackInSlot(50); + if (crystalStateStack == null || !crystalStateStack.hasTagCompound()) { + return; + } + + String name = Utils.cleanColour(crystalStateStack.getDisplayName()).trim(); + if (!name.equals("Crystal Hollows Crystals")) { + return; + } + + String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(crystalStateStack.getTagCompound()); + for (String line : lore) { + if (line == null) { + continue; + } + String cleanLine = Utils.cleanColour(line).trim(); + Matcher hotmCrystalNotPlacedMatcher = hotmCrystalNotPlacedPattern.matcher(cleanLine); + Matcher hotmCrystalNotFoundMatcher = hotmCrystalNotFoundPattern.matcher(cleanLine); + Matcher hotmCrystalPlacedMatcher = hotmCrystalPlacedPattern.matcher(cleanLine); + if (hotmCrystalNotFoundMatcher.matches() && perProfileConfig.crystals.containsKey(hotmCrystalNotFoundMatcher.group("crystal"))) { + perProfileConfig.crystals.put(hotmCrystalNotFoundMatcher.group("crystal"), 0); + } else if (hotmCrystalNotPlacedMatcher.matches() && perProfileConfig.crystals.containsKey(hotmCrystalNotPlacedMatcher.group("crystal"))) { + perProfileConfig.crystals.put(hotmCrystalNotPlacedMatcher.group("crystal"), 1); + } else if (hotmCrystalPlacedMatcher.matches() && perProfileConfig.crystals.containsKey(hotmCrystalPlacedMatcher.group("crystal"))) { + perProfileConfig.crystals.put(hotmCrystalPlacedMatcher.group("crystal"), 2); + } + } + } + + @Override + public void updateFrequent() { + if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { + GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; + ContainerChest container = (ContainerChest) chest.inventorySlots; + IInventory lower = container.getLowerChestInventory(); + String containerName = lower.getDisplayName().getUnformattedText(); + + if (containerName.equals("Heart of the Mountain") && lower.getSizeInventory() >= 54) { + updateHotmCrystalState(lower); + } + } + } + @Override public void update() { overlayStrings = null; 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 bfbe367f4f..96864391c2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java @@ -54,7 +54,7 @@ public void updateFrequent() { String containerName = lower.getDisplayName().getUnformattedText(); if (containerName.equals("Commissions") && lower.getSizeInventory() >= 27) { - UpdateCommissions(lower); + updateCommissions(lower); } else if (containerName.equals("Forge") && lower.getSizeInventory() >= 36) { updateForge(lower); } @@ -127,7 +127,7 @@ private void updateForge(IInventory lower) { } } - private void UpdateCommissions(IInventory lower) { + private void updateCommissions(IInventory lower) { // Get the location (type) of the currently shown commissions ItemStack commTypeStack = lower.getStackInSlot(27); if (commTypeStack == null || !commTypeStack.hasTagCompound()) { @@ -202,93 +202,32 @@ private void UpdateCommissions(IInventory lower) { "\\xA77Time Remaining: \\xA7a((?Completed!)|(((?[0-9]+)d)? ?((?[0-9]+)h)? ?((?[0-9]+)m)? ?((?[0-9]+)s)?))"); private static final Pattern timeRemainingTab = Pattern.compile( ".*[1-5]\\) (?.*): ((?Ready!)|(((?[0-9]+)d)? ?((?[0-9]+)h)? ?((?[0-9]+)m)? ?((?[0-9]+)s)?))"); + private static final Pattern forgesHeaderPattern = Pattern.compile( + "\\xa7r\\xa79\\xa7lForges \\xa7r(?:\\xa7f\\(\\+1 more\\)\\xa7r)?"); @Override public void update() { overlayStrings = null; - NEUConfig.HiddenProfileSpecific hidden = NotEnoughUpdates.INSTANCE.config.getProfileSpecific(); - - - /*if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) { - GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen; - ContainerChest container = (ContainerChest) chest.inventorySlots; - String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); - - - long currentTime = System.currentTimeMillis(); - if(currentTime - lastSkymallSync > 60*1000) { - if(CapeManager.getInstance().lastJsonSync != null) { - JsonObject obj = CapeManager.getInstance().lastJsonSync; - if(obj.has("skymall") && obj.get("skymall").isJsonPrimitive()) { - activeSkymall = obj.get("skymall").getAsString(); - } - } - } - - if(containerName.equals("Heart of the Mountain") && container.getLowerChestInventory().getSizeInventory() > 10) { - System.out.println("HOTM Container"); - ItemStack stack = container.getLowerChestInventory().getStackInSlot(10); - if(stack != null && stack.getDisplayName().equals(GREEN+"Sky Mall")) { - NotEnoughUpdates.INSTANCE.config.hidden.skymallActive = false; - - String[] lines = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound()); - - for(String line : lines) { - if(line.equals("\u00a7aYour Current Effect")) { - System.out.println("Current effect"); - NotEnoughUpdates.INSTANCE.config.hidden.skymallActive = true; - } else if(NotEnoughUpdates.INSTANCE.config.hidden.skymallActive) { - String prevActiveSkymall = activeSkymall; - System.out.println("Setting"); - if(line.contains("Gain \u00a7a+100 \u00a76\u2E15 Mining Speed")) { - activeSkymall = "mining_speed"; - } else if(line.contains("Gain \u00a7a+50 \u00a76\u2618 Mining Fortune")) { - activeSkymall = "mining_fortune"; - } else if(line.contains("Gain \u00a7a+15% \u00a77Powder from mining")) { - activeSkymall = "powder"; - } else if(line.contains("Reduce Pickaxe Ability cooldown")) { - activeSkymall = "pickaxe_ability"; - } else if(line.contains("10x \u00a77chance to find Goblins")) { - activeSkymall = "goblin"; - } else if(line.contains("Gain \u00a7a5x \u00a79Titanium \u00a77drops")) { - activeSkymall = "titanium"; - } else { - System.out.println("Unknown"); - activeSkymall = "unknown"; - } - if(!activeSkymall.equals(prevActiveSkymall)) { - System.out.println("Maybe sending to server"); - if(currentTime - lastSkymallSync > 60*1000) { - lastSkymallSync = currentTime; - System.out.println("Sending to server"); - NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("skymall?"+activeSkymall, (jsonObject) -> { - System.out.println("Success!"); - }, () -> { - System.out.println("Error!"); - }); - } - } - break; - } - } - } - } - }*/ + NEUConfig.HiddenProfileSpecific profileConfig = NotEnoughUpdates.INSTANCE.config.getProfileSpecific(); if (!NotEnoughUpdates.INSTANCE.config.mining.dwarvenOverlay && NotEnoughUpdates.INSTANCE.config.mining.emissaryWaypoints == 0 && !NotEnoughUpdates.INSTANCE.config.mining.titaniumAlert && - NotEnoughUpdates.INSTANCE.config.mining.locWaypoints == 0) return; - //thanks to "Pure Genie#7250" for helping with this (makes tita alert and waypoints work without mine overlay) - if (SBInfo.getInstance().getLocation() == null) return; - if (SBInfo.getInstance().getLocation().equals("mining_3") || SBInfo.getInstance().getLocation().equals( - "crystal_hollows")) { + NotEnoughUpdates.INSTANCE.config.mining.locWaypoints == 0) { + return; + } - overlayStrings = new ArrayList<>(); + // Get commission and forge info even if the overlay isn't going to be rendered since it is used elsewhere + //thanks to "Pure Genie#7250" for helping with this (makes tita alert and waypoints work without mine overlay) + if(SBInfo.getInstance().getLocation() == null) return; + if (SBInfo.getInstance().getLocation().equals("mining_3") || + SBInfo.getInstance().getLocation().equals("crystal_hollows")) { commissionProgress.clear(); - String mithrilPowder = null; - String gemstonePowder = null; + // These strings will be displayed one after the other when the player list is disabled + String mithrilPowder = RED + "[NEU] Failed to get data from your tablist"; + String gemstonePowder = RED + "Please enable player list info in your skyblock settings"; + int forgeInt = 0; boolean commissions = false; boolean forges = false; @@ -298,48 +237,43 @@ public void update() { for (NetworkPlayerInfo info : players) { String name = Minecraft.getMinecraft().ingameGUI.getTabList().getPlayerName(info); if (name.contains("Mithril Powder:")) { - mithrilPowder = DARK_AQUA + Utils.trimIgnoreColour(name).replaceAll("\u00a7[f|F|r]", ""); - continue; - } else if (mithrilPowder == null) { - mithrilPowder = RED + "[NEU] Failed to get data from your tablist"; + mithrilPowder = DARK_AQUA + Utils.trimWhitespaceAndFormatCodes(name).replaceAll("\u00a7[f|F|r]", ""); continue; } if (name.contains("Gemstone Powder:")) { - gemstonePowder = DARK_AQUA + Utils.trimIgnoreColour(name).replaceAll("\u00a7[f|F|r]", ""); - continue; - } else if (gemstonePowder == null) { - gemstonePowder = RED + "Please enable player list info in your skyblock settings"; + gemstonePowder = DARK_AQUA + Utils.trimWhitespaceAndFormatCodes(name).replaceAll("\u00a7[f|F|r]", ""); continue; } - if (name.matches("\\xa7r\\xa79\\xa7lForges \\xa7r(?:\\xa7f\\(\\+1 more\\)\\xa7r)?") && hidden != null) { + Matcher forgesMatcher = forgesHeaderPattern.matcher(name); + if (forgesMatcher.matches() && profileConfig != null) { commissions = false; forges = true; continue; - } else if (name.equals(RESET.toString() + BLUE + BOLD + "Commissions" + RESET) && hidden != null) { + } + + // Commissions appear after Forges, start enumerating Commissions instead of Forges + if (name.equals(RESET.toString() + BLUE + BOLD + "Commissions" + RESET) && profileConfig != null) { commissions = true; forges = false; continue; } - String clean = StringUtils.cleanColour(name); - if (forges && clean.startsWith(" ") && hidden != null) { - char firstChar = clean.trim().charAt(0); + String cleanName = StringUtils.cleanColour(name); + if (forges && cleanName.startsWith(" ") && profileConfig != null) { + char firstChar = cleanName.trim().charAt(0); if (firstChar < '0' || firstChar > '9') { forges = false; } else { if (name.contains("LOCKED")) { ForgeItem item = new ForgeItem(forgeInt, 1, true); - replaceForgeOrAdd(item, hidden.forgeItems, true); + replaceForgeOrAdd(item, profileConfig.forgeItems, true); } else if (name.contains("EMPTY")) { ForgeItem item = new ForgeItem(forgeInt, 0, true); - replaceForgeOrAdd(item, hidden.forgeItems, true); - //forgeStringsEmpty.add(DARK_AQUA+"Forge "+ Utils.trimIgnoreColour(name).replaceAll("\u00a7[f|F|r]", "")); + replaceForgeOrAdd(item, profileConfig.forgeItems, true); } else { - String cleanName = Utils.cleanColour(name); - Matcher matcher = timeRemainingTab.matcher(cleanName); if (matcher.matches()) { @@ -348,7 +282,7 @@ public void update() { if (matcher.group("Ready") != null && !matcher.group("Ready").equals("")) { ForgeItem item = new ForgeItem(Utils.cleanColour(itemName), 0, forgeInt, true); - replaceForgeOrAdd(item, hidden.forgeItems, true); + replaceForgeOrAdd(item, profileConfig.forgeItems, true); } else { long duration = 0; try { @@ -374,15 +308,15 @@ public void update() { forgeInt, true ); - replaceForgeOrAdd(item, hidden.forgeItems, false); + replaceForgeOrAdd(item, profileConfig.forgeItems, false); } } } } forgeInt++; } - } else if (commissions && clean.startsWith(" ") && hidden != null) { - String[] split = clean.trim().split(": "); + } else if (commissions && cleanName.startsWith(" ") && profileConfig != null) { + String[] split = cleanName.trim().split(": "); if (split.length == 2) { if (split[1].endsWith("%")) { try { @@ -400,8 +334,8 @@ public void update() { forges = false; } } + if (!NotEnoughUpdates.INSTANCE.config.mining.dwarvenOverlay) { - overlayStrings = null; return; } @@ -430,22 +364,6 @@ public void update() { } } } - /*boolean hasAny = false; - if(NotEnoughUpdates.INSTANCE.config.mining.dwarvenOverlay) { - overlayStrings.addAll(commissionsStrings); - hasAny = true; - } - if(NotEnoughUpdates.INSTANCE.config.mining.powderOverlay) { - if(mithrilPowder != null) { - if(hasAny) overlayStrings.add(null); - overlayStrings.add(DARK_AQUA+mithrilPowder); - hasAny = true; - } - } - if(NotEnoughUpdates.INSTANCE.config.mining.forgeOverlay) { - if(hasAny) overlayStrings.add(null); - overlayStrings.addAll(forgeStrings); - }*/ String pickaxeCooldown; if (ItemCooldowns.pickaxeUseCooldownMillisRemaining <= 0) { @@ -455,6 +373,7 @@ public void update() { DARK_AQUA + "Pickaxe CD: \u00a7a" + (ItemCooldowns.pickaxeUseCooldownMillisRemaining / 1000) + "s"; } + overlayStrings = new ArrayList<>(); for (int index : NotEnoughUpdates.INSTANCE.config.mining.dwarvenText2) { switch (index) { case 0: @@ -467,8 +386,8 @@ public void update() { overlayStrings.add(gemstonePowder); break; case 3: - if (hidden != null) { - overlayStrings.addAll(getForgeStrings(hidden.forgeItems)); + if (profileConfig != null) { + overlayStrings.addAll(getForgeStrings(profileConfig.forgeItems)); } break; case 4: @@ -479,8 +398,7 @@ public void update() { } } } else { - overlayStrings = new ArrayList<>(); - if (hidden == null) { + if (profileConfig == null) { return; } boolean forgeDisplay = false; @@ -490,16 +408,17 @@ public void update() { } } if (forgeDisplay) { + overlayStrings = new ArrayList<>(); if (NotEnoughUpdates.INSTANCE.config.mining.forgeDisplayEnabledLocations == 1 && !SBInfo.getInstance().isInDungeon) { - overlayStrings.addAll(getForgeStrings(hidden.forgeItems)); + overlayStrings.addAll(getForgeStrings(profileConfig.forgeItems)); } else if (NotEnoughUpdates.INSTANCE.config.mining.forgeDisplayEnabledLocations == 2) { - overlayStrings.addAll(getForgeStrings(hidden.forgeItems)); + overlayStrings.addAll(getForgeStrings(profileConfig.forgeItems)); } } } - if (overlayStrings.isEmpty()) overlayStrings = null; + if (overlayStrings != null && overlayStrings.isEmpty()) overlayStrings = null; } private static List getForgeStrings(List forgeItems) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java new file mode 100644 index 0000000000..d662a872aa --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java @@ -0,0 +1,30 @@ +package io.github.moulberry.notenoughupdates.util; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag; +import net.minecraft.client.Minecraft; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.function.Consumer; + +public class NEUDebugLogger { + private static final Minecraft mc = Minecraft.getMinecraft(); + public static Consumer logMethod = NEUDebugLogger::chatLogger; + + private static void chatLogger(String message) { + mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU DEBUG] " + message)); + } + + public static boolean isFlagEnabled(NEUDebugFlag flag) { + return NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.contains(flag); + } + + public static void log(NEUDebugFlag flag, String message) { + if (logMethod != null && isFlagEnabled(flag)) { + logMethod.accept(message); + } + } +} 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 9b5f62e315..dc88da2f88 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java @@ -301,6 +301,40 @@ public static String trimIgnoreColourEnd(String str) { return ""; } + public static String trimWhitespaceAndFormatCodes(String str) { + int startIndex = indexOfFirstNonWhitespaceNonFormatCode(str); + int endIndex = lastIndexOfNonWhitespaceNonFormatCode(str); + if (startIndex == -1 || endIndex == -1) return ""; + return str.substring(startIndex, endIndex+1); + } + + private static int indexOfFirstNonWhitespaceNonFormatCode(String str) { + int len = str.length(); + for (int i = 0; i < len; i++) { + char ch = str.charAt(i); + if (Character.isWhitespace(ch)) { + continue; + } else if (ch == '\u00a7') { + i++; + continue; + } + return i; + } + return -1; + } + + private static int lastIndexOfNonWhitespaceNonFormatCode(String str) { + for (int i = str.length() - 1; i >= 0; i--) { + char ch = str.charAt(i); + if (Character.isWhitespace(ch) || ch == '\u00a7' || (i > 0 && str.charAt(i - 1) == '\u00a7')) { + continue; + } + return i; + } + + return -1; + } + public static List getRawTooltip(ItemStack stack) { List list = Lists.newArrayList(); String s = stack.getDisplayName(); From 0ef9d7e01ec6696444af53176ab955e0cb0701b0 Mon Sep 17 00:00:00 2001 From: CraftyOldMiner <85420839+CraftyOldMiner@users.noreply.github.com> Date: Sun, 13 Mar 2022 08:15:37 -0500 Subject: [PATCH 004/222] Add .gitattributes, normalize exiting line endings (#91) --- .gitattributes | 14 + .../dungeons/GuiDungeonMapEditor.java | 1694 ++++++++--------- .../seperateSections/AccessoryBag.java | 30 +- .../options/seperateSections/ApiKey.java | 30 +- .../options/seperateSections/Calendar.java | 106 +- .../seperateSections/DungeonMapConfig.java | 284 +-- .../options/seperateSections/Dungeons.java | 458 ++--- .../options/seperateSections/Fishing.java | 414 ++-- .../seperateSections/ImprovedSBMenu.java | 100 +- .../seperateSections/InventoryButtons.java | 70 +- .../seperateSections/ItemOverlays.java | 712 +++---- .../options/seperateSections/Itemlist.java | 220 +-- .../options/seperateSections/Mining.java | 1436 +++++++------- .../options/seperateSections/Misc.java | 286 +-- .../seperateSections/NeuAuctionHouse.java | 90 +- .../seperateSections/Notifications.java | 64 +- .../options/seperateSections/PetOverlay.java | 236 +-- .../seperateSections/SkillOverlays.java | 634 +++--- .../options/seperateSections/SlotLocking.java | 182 +- .../options/seperateSections/StorageGUI.java | 520 ++--- .../options/seperateSections/Toolbar.java | 202 +- .../seperateSections/TooltipTweaks.java | 282 +-- .../options/seperateSections/TradeMenu.java | 52 +- 23 files changed, 4065 insertions(+), 4051 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..c51f397d56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,14 @@ +* text=auto + +# Always Unix-style line endings +*.sh text eol=lf + +# Always Windows-style line endings +*.bat text eol=crlf +*.cmd text eol=crlf + +# Always binary +*.jpg -text +*.ogg -text +*.png -text +*.xcf -text diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java index 41fa366311..e59e0ea1fa 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java @@ -1,847 +1,847 @@ -package io.github.moulberry.notenoughupdates.dungeons; - -import io.github.moulberry.notenoughupdates.NotEnoughUpdates; -import io.github.moulberry.notenoughupdates.core.GuiElementColour; -import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider; -import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption; -import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor; -import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; -import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; -import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField; -import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig; -import io.github.moulberry.notenoughupdates.util.SpecialColour; -import io.github.moulberry.notenoughupdates.util.Utils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.gui.ScaledResolution; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.shader.Framebuffer; -import net.minecraft.client.shader.Shader; -import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.Matrix4f; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Vec4b; -import org.lwjgl.input.Keyboard; -import org.lwjgl.input.Mouse; -import org.lwjgl.opengl.GL11; - -import java.awt.*; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.List; -import java.util.*; - -import static io.github.moulberry.notenoughupdates.util.GuiTextures.*; - -public class GuiDungeonMapEditor extends GuiScreen { - public static final ResourceLocation BACKGROUND = new ResourceLocation( - "notenoughupdates:dungeon_map/editor/background.png"); - public static final ResourceLocation BUTTON = new ResourceLocation("notenoughupdates:dungeon_map/editor/button.png"); - private static final DungeonMap demoMap = new DungeonMap(); - - private int sizeX; - private int sizeY; - private int guiLeft; - private int guiTop; - - private final List