aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/thatgravyboat/skyblockhud/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/thatgravyboat/skyblockhud/handlers')
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/BossbarHandler.java36
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/CooldownHandler.java121
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/CrystalWaypoints.java196
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/CurrencyHandler.java86
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/HeldItemHandler.java31
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/MapHandler.java206
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/NpcDialogue.java131
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/SlayerHandler.java130
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/TimeHandler.java28
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/WarpHandler.java179
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/mapicons/DwarvenIcons.java39
-rw-r--r--src/main/java/com/thatgravyboat/skyblockhud/handlers/mapicons/HubIcons.java55
12 files changed, 1238 insertions, 0 deletions
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/BossbarHandler.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/BossbarHandler.java
new file mode 100644
index 000000000..d605d8102
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/BossbarHandler.java
@@ -0,0 +1,36 @@
+package com.thatgravyboat.skyblockhud.handlers;
+
+import com.thatgravyboat.skyblockhud.SkyblockHud;
+import com.thatgravyboat.skyblockhud.location.LocationHandler;
+import com.thatgravyboat.skyblockhud.location.Locations;
+import com.thatgravyboat.skyblockhud.utils.Utils;
+import net.minecraft.entity.boss.BossStatus;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+public class BossbarHandler {
+
+ public static boolean bossBarRendered = true;
+
+ @SubscribeEvent(priority = EventPriority.LOWEST)
+ public void onBossbarRender(RenderGameOverlayEvent.Pre event) {
+ if (event.type == RenderGameOverlayEvent.ElementType.BOSSHEALTH && BossStatus.bossName != null) {
+ bossBarRendered = !event.isCanceled();
+ if (!SkyblockHud.config.main.bossShiftHud) {
+ bossBarRendered = false;
+ }
+ String bossName = Utils.removeColor(BossStatus.bossName);
+ if (SkyblockHud.config.renderer.hideBossBar && !LocationHandler.getCurrentLocation().equals(Locations.CATACOMBS)) {
+ if (bossName.equalsIgnoreCase("wither")) {
+ event.setCanceled(true);
+ bossBarRendered = false;
+ }
+ if (bossName.toLowerCase().startsWith("objective:")) {
+ event.setCanceled(true);
+ bossBarRendered = false;
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/CooldownHandler.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/CooldownHandler.java
new file mode 100644
index 000000000..7f382d56d
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/CooldownHandler.java
@@ -0,0 +1,121 @@
+package com.thatgravyboat.skyblockhud.handlers;
+
+import com.google.common.collect.Sets;
+import com.thatgravyboat.skyblockhud.SkyblockHud;
+import com.thatgravyboat.skyblockhud.api.item.IAbility;
+import com.thatgravyboat.skyblockhud.utils.Utils;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import net.minecraft.client.Minecraft;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+
+public class CooldownHandler {
+
+ private static final Pattern ABILITY_REGEX = Pattern.compile("\u00A76Ability: (.*) \u00A7e\u00A7lRIGHT CLICK .* \u00A78Cooldown: \u00A7a(\\d*)s");
+
+ private static final Map<String, Cooldown> COOLDOWNS = new HashMap<>();
+
+ private static final Set<String> CUSTOM_HANDLED_COOLDOWNS = Sets.newHashSet("Mining Speed Boost");
+
+ public static Matcher getAbility(NBTTagCompound nbt) {
+ if (nbt != null && nbt.hasKey("ExtraAttributes") && nbt.getCompoundTag("ExtraAttributes").hasKey("uuid") && nbt.hasKey("display")) {
+ NBTTagCompound display = nbt.getCompoundTag("display");
+ if (display != null && display.hasKey("Lore")) {
+ NBTTagList lore = display.getTagList("Lore", 8);
+ List<String> loreList = new ArrayList<>();
+ for (int i = 0; i < lore.tagCount(); i++) {
+ String loreLine = lore.getStringTagAt(i).trim();
+ if (!loreLine.isEmpty()) loreList.add(loreLine);
+ }
+ Matcher abilityMatcher = ABILITY_REGEX.matcher(String.join(" ", loreList));
+ if (abilityMatcher.find()) {
+ return abilityMatcher;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static void addCooldown(String id, int time) {
+ COOLDOWNS.putIfAbsent(id, new Cooldown(time * 20));
+ }
+
+ private static void addCooldown(IAbility ability, boolean isForced) {
+ if (isForced || !CUSTOM_HANDLED_COOLDOWNS.contains(ability.getAbility())) {
+ addCooldown(ability.getAbility(), ability.getAbilityTime());
+ }
+ }
+
+ @SubscribeEvent(priority = EventPriority.HIGHEST)
+ public void onChat(ClientChatReceivedEvent event) {
+ String message = Utils.removeColor(event.message.getUnformattedText());
+ if (event.type != 2 && message.equals("You used your Mining Speed Boost Pickaxe Ability!")) {
+ if (Minecraft.getMinecraft().thePlayer.getHeldItem() != null) {
+ IAbility ability = (IAbility) (Object) Minecraft.getMinecraft().thePlayer.getHeldItem();
+ if (ability.getAbility().equals("Mining Speed Boost")) {
+ addCooldown("Mining Speed Boost", ability.getAbilityTime());
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void tick(TickEvent.ClientTickEvent event) {
+ if (SkyblockHud.config.misc.hideItemCooldowns) return;
+ if (event.phase.equals(TickEvent.Phase.END)) {
+ COOLDOWNS.values().forEach(Cooldown::tick);
+ COOLDOWNS.entrySet().removeIf(entry -> entry.getValue().isOver());
+ }
+ }
+
+ @SubscribeEvent
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ if (SkyblockHud.config.misc.hideItemCooldowns) return;
+ if (event.action.equals(PlayerInteractEvent.Action.RIGHT_CLICK_AIR) || event.action.equals(PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK)) {
+ if (event.entityPlayer.getHeldItem() != null) {
+ IAbility ability = (IAbility) ((Object) event.entityPlayer.getHeldItem());
+ if (ability.getAbility() != null) {
+ addCooldown(ability, false);
+ }
+ }
+ }
+ }
+
+ public static float getAbilityTime(ItemStack stack) {
+ IAbility ability = (IAbility) ((Object) stack);
+ if (ability.getAbility() != null) {
+ return COOLDOWNS.containsKey(ability.getAbility()) ? COOLDOWNS.get(ability.getAbility()).getTime() : -1f;
+ }
+ return -1f;
+ }
+
+ private static class Cooldown {
+
+ public int current;
+ public final int end;
+
+ Cooldown(int end) {
+ this.end = end;
+ }
+
+ public boolean isOver() {
+ return current >= end;
+ }
+
+ public void tick() {
+ current++;
+ }
+
+ public float getTime() {
+ return current / (float) end;
+ }
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/CrystalWaypoints.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/CrystalWaypoints.java
new file mode 100644
index 000000000..bab57f8e1
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/CrystalWaypoints.java
@@ -0,0 +1,196 @@
+package com.thatgravyboat.skyblockhud.handlers;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.thatgravyboat.skyblockhud.SkyblockHud;
+import com.thatgravyboat.skyblockhud.api.events.LocationChangeEvent;
+import com.thatgravyboat.skyblockhud.commands.SimpleCommand;
+import com.thatgravyboat.skyblockhud.location.LocationCategory;
+import com.thatgravyboat.skyblockhud.location.LocationHandler;
+import com.thatgravyboat.skyblockhud.location.Locations;
+import com.thatgravyboat.skyblockhud.utils.Utils;
+import java.awt.*;
+import java.awt.datatransfer.StringSelection;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.event.HoverEvent;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatStyle;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.client.event.RenderWorldLastEvent;
+import net.minecraftforge.event.entity.EntityJoinWorldEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+public class CrystalWaypoints {
+
+ public static final Pattern LOCATION_MESSAGE_REGEX = Pattern.compile("\\{(.*) : \\((-?\\d+)/(-?\\d+)/(-?\\d+)\\)}");
+
+ public static final HashMap<String, BlockPos> waypoints = new HashMap<>();
+
+ private static final Set<Locations> IMPORTANT_WAYPOINTS = Sets.newHashSet(Locations.GOBLINQUEENSDEN, Locations.LOSTPRECURSORCITY, Locations.JUNGLETEMPLE, Locations.MINESOFDIVAN, Locations.KHAZADDM, Locations.FAIRYGROTTO);
+
+ @SubscribeEvent
+ public void onRenderLast(RenderWorldLastEvent event) {
+ GlStateManager.disableCull();
+ GlStateManager.disableDepth();
+ waypoints.forEach((text, pos) -> Utils.renderWaypointText(text, pos, event.partialTicks));
+ GlStateManager.enableCull();
+ GlStateManager.enableDepth();
+ }
+
+ @SubscribeEvent
+ public void onWorldChange(EntityJoinWorldEvent event) {
+ if (event.entity == Minecraft.getMinecraft().thePlayer) {
+ waypoints.clear();
+ }
+ }
+
+ @SubscribeEvent
+ public void onLocationChange(LocationChangeEvent event) {
+ if (!event.newLocation.getCategory().equals(LocationCategory.CRYSTALHOLLOWS)) {
+ waypoints.clear();
+ } else if (!waypoints.containsKey("Crystal Nucleus") && SkyblockHud.config.mining.autoWaypoint) {
+ waypoints.put("Crystal Nucleus", new BlockPos(512.5, 106.5, 512.5));
+ }
+ if (IMPORTANT_WAYPOINTS.contains(event.newLocation) && SkyblockHud.config.mining.autoWaypoint) {
+ if (!waypoints.containsKey(event.newLocation.getDisplayName())) {
+ waypoints.put(event.newLocation.getDisplayName(), Minecraft.getMinecraft().thePlayer.getPosition());
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onChatMessage(ClientChatReceivedEvent event) {
+ if (event.type != 2 && LocationHandler.getCurrentLocation().getCategory().equals(LocationCategory.CRYSTALHOLLOWS)) {
+ Matcher matcher = LOCATION_MESSAGE_REGEX.matcher(event.message.getUnformattedText());
+ if (!matcher.find()) return;
+ ChatStyle style = new ChatStyle();
+ style.setParentStyle(event.message.getChatStyle());
+ ClickEvent.Action action = SkyblockHud.config.mining.chatWaypointMode == 0 ? ClickEvent.Action.RUN_COMMAND : ClickEvent.Action.SUGGEST_COMMAND;
+ style.setChatClickEvent(new ClickEvent(action, "/sbhpoints addat " + matcher.group(2) + " " + matcher.group(3) + " " + matcher.group(4) + " " + matcher.group(1)));
+ style.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentText("Click to add waypoint!").setChatStyle(new ChatStyle().setBold(true))));
+ event.message.setChatStyle(style);
+ }
+ }
+
+ private static String copyWayPoint(String name) {
+ BlockPos pos = waypoints.get(name);
+ if (pos == null) {
+ return null;
+ }
+ return "{" + name + " : (" + pos.getX() + "/" + pos.getY() + "/" + pos.getZ() + ")}";
+ }
+
+ public static class WaypointCommand extends SimpleCommand {
+
+ public WaypointCommand() {
+ super(
+ "sbhpoints",
+ new ProcessCommandRunnable() {
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) {
+ if (args.length == 0) return;
+ String subCommand = args[0].toLowerCase();
+ String name = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
+ switch (subCommand) {
+ case "add":
+ if (LocationHandler.getCurrentLocation().getCategory().equals(LocationCategory.CRYSTALHOLLOWS)) {
+ if (!CrystalWaypoints.waypoints.containsKey(name) && name.length() > 1) {
+ CrystalWaypoints.waypoints.put(name, sender.getPosition().add(0.5, 0.5, 0.5));
+ } else if (name.length() < 2) {
+ sbhMessage(sender, "Waypoint name needs to be longer than 1");
+ } else {
+ sbhMessage(sender, "Waypoint already exists!");
+ }
+ }
+ break;
+ case "remove":
+ if (LocationHandler.getCurrentLocation().getCategory().equals(LocationCategory.CRYSTALHOLLOWS)) {
+ if (CrystalWaypoints.waypoints.containsKey(name)) {
+ CrystalWaypoints.waypoints.remove(name);
+ } else {
+ sbhMessage(sender, "Waypoint doesnt exist!");
+ }
+ }
+ break;
+ case "move":
+ if (LocationHandler.getCurrentLocation().getCategory().equals(LocationCategory.CRYSTALHOLLOWS)) {
+ if (CrystalWaypoints.waypoints.containsKey(name)) {
+ CrystalWaypoints.waypoints.put(name, sender.getPosition().add(0.5, 0.5, 0.5));
+ } else {
+ sbhMessage(sender, "Waypoint doesnt exist!");
+ }
+ }
+ break;
+ case "clear":
+ CrystalWaypoints.waypoints.clear();
+ break;
+ case "addat":
+ if (LocationHandler.getCurrentLocation().getCategory().equals(LocationCategory.CRYSTALHOLLOWS)) {
+ name = String.join(" ", Arrays.copyOfRange(args, 4, args.length));
+ try {
+ if (!CrystalWaypoints.waypoints.containsKey(name)) {
+ CrystalWaypoints.waypoints.put(name, parseBlockPos(sender, args, 1, true));
+ } else if (name.length() < 2) {
+ sbhMessage(sender, "Waypoint name needs to be longer than 1");
+ } else {
+ sbhMessage(sender, "Waypoint already exists!");
+ }
+ } catch (Exception e) {
+ sbhMessage(sender, "Error!");
+ }
+ }
+ break;
+ case "copy":
+ String copyText = copyWayPoint(name);
+ if (copyText == null) {
+ sbhMessage(sender, "No waypoint with that name!");
+ break;
+ }
+ StringSelection clipboard = new StringSelection(copyText);
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(clipboard, clipboard);
+ break;
+ case "send":
+ String sendText = copyWayPoint(name);
+ if (sendText == null) {
+ sbhMessage(sender, "No waypoint with that name!");
+ break;
+ }
+ Minecraft.getMinecraft().thePlayer.sendChatMessage(sendText);
+ break;
+ }
+ }
+ },
+ new TabCompleteRunnable() {
+ @Override
+ public List<String> tabComplete(ICommandSender sender, String[] args, BlockPos pos) {
+ if (args.length == 2 && Utils.equalsIgnoreCaseAnyOf(args[0], "remove", "copy", "move", "send")) {
+ return getListOfStringsMatchingLastWord(args, waypoints.keySet());
+ }
+ if (args.length == 1) {
+ return getListOfStringsMatchingLastWord(args, Lists.newArrayList("add", "clear", "remove", "copy", "addat", "move", "send"));
+ }
+ if (args.length > 1 && args[0].equalsIgnoreCase("addat")) {
+ return func_175771_a(args, 1, pos);
+ }
+ return null;
+ }
+ }
+ );
+ }
+
+ private static void sbhMessage(ICommandSender sender, String message) {
+ sender.addChatMessage(new ChatComponentText("[" + EnumChatFormatting.RED + EnumChatFormatting.BOLD + "SkyBlockHud" + EnumChatFormatting.RESET + "] : " + EnumChatFormatting.GRAY + message));
+ }
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/CurrencyHandler.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/CurrencyHandler.java
new file mode 100644
index 000000000..7bbfaa074
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/CurrencyHandler.java
@@ -0,0 +1,86 @@
+package com.thatgravyboat.skyblockhud.handlers;
+
+import com.thatgravyboat.skyblockhud.api.events.SidebarLineUpdateEvent;
+import com.thatgravyboat.skyblockhud.api.events.SidebarPostEvent;
+import com.thatgravyboat.skyblockhud.utils.Utils;
+import java.math.RoundingMode;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.regex.Pattern;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+public class CurrencyHandler {
+
+ private static int bits = 0;
+ private static double coins = 0;
+
+ public static void setBits(int amount) {
+ bits = amount;
+ }
+
+ public static void setCoins(double amount) {
+ coins = amount;
+ }
+
+ public static int getBits() {
+ return bits;
+ }
+
+ public static double getCoins() {
+ return coins;
+ }
+
+ @SubscribeEvent
+ public void onSidebarLineUpdate(SidebarLineUpdateEvent event) {
+ if (Utils.removeColor(event.formattedLine.toLowerCase().trim()).contains("purse:") || Utils.removeColor(event.formattedLine.toLowerCase().trim()).contains("piggy:")) {
+ CurrencyHandler.checkCoins(event.formattedLine);
+ }
+ if (Utils.removeColor(event.formattedLine.toLowerCase().trim()).contains("bits:") && !event.formattedLine.toLowerCase().contains("(")) {
+ CurrencyHandler.checkBits(event.formattedLine);
+ }
+ }
+
+ @SubscribeEvent
+ public void onSidebarPost(SidebarPostEvent event) {
+ if (!Arrays.toString(event.arrayScores).toLowerCase().contains("bits:")) {
+ CurrencyHandler.setBits(0);
+ }
+ }
+
+ public static String getCoinsFormatted() {
+ DecimalFormat formatter = new DecimalFormat("#,###.0", DecimalFormatSymbols.getInstance(Locale.CANADA));
+ String output = formatter.format(getCoins());
+ if (output.equals(".0")) output = "0.0"; else if (output.equals(",0")) output = "0,0";
+ return output;
+ }
+
+ public static String getBitsFormatted() {
+ DecimalFormat formatter = new DecimalFormat("#.#", DecimalFormatSymbols.getInstance(Locale.CANADA));
+ formatter.setRoundingMode(RoundingMode.FLOOR);
+ return getBits() > 999 ? formatter.format((double) getBits() / 1000) + "k" : String.valueOf(getBits());
+ }
+
+ public static void checkCoins(String formatedScoreboardLine) {
+ String purse = Utils.removeWhiteSpaceAndRemoveWord(Utils.removeColor(formatedScoreboardLine.toLowerCase().trim()), Utils.removeColor(formatedScoreboardLine.toLowerCase().trim()).contains("purse:") ? "purse:" : "piggy:").replace(",", "");
+ if (!purse.contains("(") && !purse.contains("+")) {
+ try {
+ double coins = Double.parseDouble(Pattern.compile("[^0-9.]").matcher(purse).replaceAll(""));
+ CurrencyHandler.setCoins(coins);
+ } catch (IllegalArgumentException ex) {
+ System.out.println("Failed to parse purse, please report to ThatGravyBoat. Purse Text: " + purse);
+ }
+ }
+ }
+
+ public static void checkBits(String formatedScoreboardLine) {
+ String bits = Utils.removeWhiteSpaceAndRemoveWord(Utils.removeColor(formatedScoreboardLine.toLowerCase().trim()), "bits:").replace(",", "");
+ try {
+ int bit = Integer.parseInt(Pattern.compile("[^0-9]").matcher(bits).replaceAll(""));
+ CurrencyHandler.setBits(bit);
+ } catch (IllegalArgumentException ex) {
+ System.out.println("Failed to parse bits, please report to ThatGravyBoat. Bits Text: " + bits);
+ }
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/HeldItemHandler.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/HeldItemHandler.java
new file mode 100644
index 000000000..2feef3817
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/HeldItemHandler.java
@@ -0,0 +1,31 @@
+package com.thatgravyboat.skyblockhud.handlers;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.item.ItemStack;
+
+public class HeldItemHandler extends Gui {
+
+ private static final Pattern MANA_COST_REGEX = Pattern.compile("Mana Cost: \u00A73([0-9]+)");
+
+ public static boolean hasManaCost(ItemStack stack) {
+ if (stack == null) return false;
+ if (!stack.hasTagCompound()) return false;
+ if (!stack.getTagCompound().hasKey("display")) return false;
+ if (!stack.getTagCompound().getCompoundTag("display").hasKey("Lore")) return false;
+ String lore = stack.getTagCompound().getCompoundTag("display").getTagList("Lore", 8).toString();
+ return MANA_COST_REGEX.matcher(lore).find();
+ }
+
+ public static int getManaCost(ItemStack stack) {
+ String lore = stack.getTagCompound().getCompoundTag("display").getTagList("Lore", 8).toString();
+ Matcher matcher = MANA_COST_REGEX.matcher(lore);
+ if (matcher.find()) {
+ try {
+ return Integer.parseInt(matcher.group(1));
+ } catch (Exception ignored) {}
+ }
+ return 0;
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/MapHandler.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/MapHandler.java
new file mode 100644
index 000000000..937a5a498
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/MapHandler.java
@@ -0,0 +1,206 @@
+package com.thatgravyboat.skyblockhud.handlers;
+
+import static com.thatgravyboat.skyblockhud.GuiTextures.mapOverlay;
+
+import com.thatgravyboat.skyblockhud.SkyblockHud;
+import com.thatgravyboat.skyblockhud.config.KeyBindings;
+import com.thatgravyboat.skyblockhud.config.SBHConfig;
+import com.thatgravyboat.skyblockhud.core.config.Position;
+import com.thatgravyboat.skyblockhud.handlers.mapicons.DwarvenIcons;
+import com.thatgravyboat.skyblockhud.handlers.mapicons.HubIcons;
+import com.thatgravyboat.skyblockhud.location.LocationHandler;
+import com.thatgravyboat.skyblockhud.utils.Utils;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import javax.vecmath.Vector2f;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.settings.GameSettings;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.lwjgl.opengl.GL11;
+
+public class MapHandler {
+
+ public enum MapIconTypes {
+ SHOPS,
+ MISC,
+ NPC,
+ INFO,
+ QUEST
+ }
+
+ public static class MapIcon {
+
+ public Vector2f position;
+ public ResourceLocation icon;
+ public String tooltip;
+ public String command;
+ public MapIconTypes type;
+
+ public MapIcon(Vector2f pos, ResourceLocation icon, String tooltip, MapIconTypes type) {
+ this(pos, icon, tooltip, type, "");
+ }
+
+ public MapIcon(Vector2f pos, ResourceLocation icon, String tooltip, MapIconTypes type, String command) {
+ this.position = pos;
+ this.icon = icon;
+ this.tooltip = tooltip;
+ this.type = type;
+ this.command = command;
+ }
+
+ public boolean cantRender() {
+ SBHConfig.Map mapConfig = SkyblockHud.config.map;
+ if (mapConfig.showInfoIcons && type.equals(MapIconTypes.INFO)) return false; else if (mapConfig.showMiscIcons && type.equals(MapIconTypes.MISC)) return false; else if (mapConfig.showNpcIcons && type.equals(MapIconTypes.NPC)) return false; else if (mapConfig.showQuestIcons && type.equals(MapIconTypes.QUEST)) return false; else return (!mapConfig.showShopIcons || !type.equals(MapIconTypes.SHOPS));
+ }
+ }
+
+ public enum Maps {
+ HUB(0.5f, 494, 444, 294, 218, 294, 224, new ResourceLocation("skyblockhud", "maps/hub.png"), HubIcons.hubIcons),
+ MUSHROOM(1.0f, 318, 316, -84, 605, -84, 612, new ResourceLocation("skyblockhud", "maps/mushroom.png"), Collections.emptyList()),
+ SPIDERS(1.0f, 270, 238, 400, 362, 400, 364, new ResourceLocation("skyblockhud", "maps/spidersden.png"), Collections.emptyList()),
+ NETHER(0.5f, 257, 371, 436, 732, 433, 736, new ResourceLocation("skyblockhud", "maps/fort.png"), Collections.emptyList()),
+ BARN(1.5f, 135, 130, -82, 320, -81, 318, new ResourceLocation("skyblockhud", "maps/barn.png"), Collections.emptyList()),
+ DWARVEN(0.5f, 409, 461, 206, 160, 202, 166, new ResourceLocation("skyblockhud", "maps/dwarven.png"), DwarvenIcons.dwarvenIcons),
+ CRYSTAL(0.5f, 624, 624, -202, -215.7, -202, -212, new ResourceLocation("skyblockhud", "maps/crystal.png"), Collections.emptyList()),
+ PARK(1f, 211, 230, 480, 133, 478, 134, new ResourceLocation("skyblockhud", "maps/park.png"), Collections.emptyList());
+
+ public float scaleFactor;
+ public int width;
+ public int height;
+ public double xMiniOffset;
+ public double yMiniOffset;
+ public double xOffset;
+ public double yOffset;
+ public ResourceLocation mapTexture;
+ public List<MapIcon> icons;
+
+ Maps(float scaleFactor, int width, int height, double xMiniOffset, double yMiniOffset, double xOffset, double yOffset, ResourceLocation mapTexture, List<MapIcon> icons) {
+ this.scaleFactor = scaleFactor;
+ this.width = width;
+ this.height = height;
+ this.xMiniOffset = xMiniOffset;
+ this.yMiniOffset = yMiniOffset;
+ this.xOffset = xOffset;
+ this.yOffset = yOffset;
+ this.mapTexture = mapTexture;
+ this.icons = icons;
+ }
+ }
+
+ @SubscribeEvent
+ public void renderOverlay(RenderGameOverlayEvent.Post event) {
+ if (Utils.overlayShouldRender(event.type, SkyblockHud.hasSkyblockScoreboard(), SkyblockHud.config.map.showMiniMap)) {
+ Minecraft mc = Minecraft.getMinecraft();
+ if (mc.currentScreen instanceof MapScreen) return;
+ if (LocationHandler.getCurrentLocation().getCategory().getMap() == null) return;
+ if (mc.thePlayer != null) {
+ MapHandler.Maps map = LocationHandler.getCurrentLocation().getCategory().getMap();
+ mc.renderEngine.bindTexture(mapOverlay);
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
+ Position pos = SkyblockHud.config.map.miniMapPosition;
+ Gui.drawModalRectWithCustomSizedTexture(pos.getAbsX(event.resolution, 72), pos.getAbsY(event.resolution, 72), 72, 0, 72, 72, 256, 256);
+ mc.renderEngine.bindTexture(map.mapTexture);
+
+ double x = mc.thePlayer.getPosition().getX() + map.xMiniOffset;
+ double z = mc.thePlayer.getPosition().getZ() + map.yMiniOffset;
+ float u = (float) ((x / (map.width / 256f)) - 33f);
+ float v = (float) ((z / (map.height / 256f)) - 28f);
+
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);
+
+ Gui.drawModalRectWithCustomSizedTexture(pos.getAbsX(event.resolution, 72) + 4, pos.getAbsY(event.resolution, 72) + 2, u, v, 64, 64, 256, 256);
+
+ if (SkyblockHud.config.map.showPlayerLocation) {
+ mc.fontRendererObj.drawString("\u2022", pos.getAbsX(event.resolution, 72) + 36, pos.getAbsY(event.resolution, 72) + 34, 0xff0000, false);
+ }
+
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
+ mc.renderEngine.bindTexture(mapOverlay);
+ Gui.drawModalRectWithCustomSizedTexture(pos.getAbsX(event.resolution, 72), pos.getAbsY(event.resolution, 72), 0, 0, 72, 72, 256, 256);
+ String keyCode = GameSettings.getKeyDisplayString(KeyBindings.map.getKeyCode());
+ Utils.drawStringCenteredScaled(keyCode, mc.fontRendererObj, pos.getAbsX(event.resolution, 64) + (pos.rightAligned(event.resolution, 72) ? 50 : 58), pos.getAbsY(event.resolution, 72) + 66, false, 6, 0xFFFFFF);
+ BlockPos playerPos = mc.thePlayer.getPosition();
+ String position = String.format("%d/%d/%d", playerPos.getX(), playerPos.getY(), playerPos.getZ());
+ Utils.drawStringCenteredScaled(position, mc.fontRendererObj, pos.getAbsX(event.resolution, 64) + (pos.rightAligned(event.resolution, 72) ? 21 : 29), pos.getAbsY(event.resolution, 72) + 66, false, 36, 0xFFFFFF);
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void clientTick(TickEvent.ClientTickEvent event) {
+ if (KeyBindings.map.isPressed() && LocationHandler.getCurrentLocation().getCategory().getMap() != null && SkyblockHud.hasSkyblockScoreboard()) SkyblockHud.screenToOpen = new MapScreen();
+ }
+
+ public static class MapScreen extends GuiScreen {
+
+ public MapHandler.Maps map = LocationHandler.getCurrentLocation().getCategory().getMap();
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
+ this.drawWorldBackground(0);
+ this.mc.renderEngine.bindTexture(map.mapTexture);
+ float mapX = (width / 2f) - ((map.width / 2f) * map.scaleFactor);
+ float mapY = (height / 2f) - ((map.height / 2f) * map.scaleFactor);
+ Gui.drawModalRectWithCustomSizedTexture((int) mapX, (int) mapY, 0, 0, (int) (map.width * map.scaleFactor), (int) (map.height * map.scaleFactor), (int) (map.width * map.scaleFactor), (int) (map.height * map.scaleFactor));
+ drawIcons((int) mapX, (int) mapY);
+ if (this.mc.thePlayer != null && SkyblockHud.config.map.showPlayerLocation) {
+ double x = this.mc.thePlayer.getPosition().getX() + map.xOffset;
+ double z = this.mc.thePlayer.getPosition().getZ() + map.yOffset;
+ fontRendererObj.drawString("\u2022", (int) (x * map.scaleFactor + mapX), (int) (z * map.scaleFactor + mapY), 0xff0000);
+ }
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
+ onTooltip(mouseX, mouseY, (int) mapX, (int) mapY);
+ }
+
+ public void drawIcons(int startX, int startY) {
+ if (map.icons == null) return;
+ for (MapIcon icon : map.icons) {
+ if (icon.cantRender()) continue;
+ GlStateManager.enableBlend();
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
+ this.mc.renderEngine.bindTexture(icon.icon);
+ double x = ((icon.position.x + map.xOffset) * map.scaleFactor) + startX - 4;
+ double y = ((icon.position.y + map.yOffset) * map.scaleFactor) + startY - 4;
+ Gui.drawModalRectWithCustomSizedTexture((int) x, (int) y, 0, 0, 8, 8, 8, 8);
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+ }
+
+ public void onTooltip(int mouseX, int mouseY, int startX, int startY) {
+ if (map.icons == null) return;
+ for (MapIcon icon : map.icons) {
+ if (icon.cantRender()) continue;
+ if (Utils.inRangeInclusive(mouseX, (int) ((icon.position.x + map.xOffset) * map.scaleFactor) + startX - 4, (int) ((icon.position.x + map.xOffset) * map.scaleFactor) + startX + 4) && Utils.inRangeInclusive(mouseY, (int) ((icon.position.y + map.yOffset) * map.scaleFactor) + startY - 4, (int) ((icon.position.y + map.yOffset) * map.scaleFactor) + startY + 4)) {
+ drawHoveringText(Arrays.asList(icon.tooltip.split("\n")), mouseX, mouseY);
+ break;
+ }
+ }
+ }
+
+ @Override
+ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) {
+ int mapX = (int) ((width / 2f) - ((map.width / 2f) * map.scaleFactor));
+ int mapY = (int) ((height / 2f) - ((map.height / 2f) * map.scaleFactor));
+ for (MapIcon icon : map.icons) {
+ if (icon.cantRender()) continue;
+ if (Utils.inRangeInclusive(mouseX, (int) ((icon.position.x + map.xOffset) * map.scaleFactor) + mapX - 4, (int) ((icon.position.x + map.xOffset) * map.scaleFactor) + mapX + 4) && Utils.inRangeInclusive(mouseY, (int) ((icon.position.y + map.yOffset) * map.scaleFactor) + mapY - 4, (int) ((icon.position.y + map.yOffset) * map.scaleFactor) + mapY + 4)) {
+ if (!icon.command.isEmpty()) {
+ this.mc.thePlayer.sendChatMessage("/" + icon.command);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/NpcDialogue.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/NpcDialogue.java
new file mode 100644
index 000000000..9a7679fde
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/NpcDialogue.java
@@ -0,0 +1,131 @@
+package com.thatgravyboat.skyblockhud.handlers;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.thatgravyboat.skyblockhud.SkyblockHud;
+import com.thatgravyboat.skyblockhud.textures.Textures;
+import com.thatgravyboat.skyblockhud.utils.Utils;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.resources.IResourceManager;
+import net.minecraft.client.resources.IResourceManagerReloadListener;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+
+public class NpcDialogue implements IResourceManagerReloadListener {
+
+ public static final Pattern NPC_DIALOGUE_REGEX = Pattern.compile("\\[NPC] (.*): (.*)");
+
+ private static final Gson gson = new GsonBuilder().create();
+ private static final Map<String, ResourceLocation> NPCS = new HashMap<>();
+
+ private static boolean showDialogue = false;
+ private static int ticks = 0;
+
+ private static final Queue<Dialogue> DIALOGUE = new ArrayDeque<>();
+ private static Dialogue currentDialogue = null;
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if (event.phase.equals(TickEvent.Phase.START) || SkyblockHud.config.misc.hideDialogueBox) return;
+ if (showDialogue) ticks++; else ticks = 0;
+
+ if (showDialogue && ticks % 60 == 0) {
+ currentDialogue = DIALOGUE.poll();
+
+ if (currentDialogue == null) {
+ showDialogue = false;
+ }
+ }
+ }
+
+ @SubscribeEvent(priority = EventPriority.LOWEST)
+ public void onChat(ClientChatReceivedEvent event) {
+ if (event.type != 2 && !SkyblockHud.config.misc.hideDialogueBox) {
+ String message = Utils.removeColor(event.message.getUnformattedText());
+ if (message.toLowerCase(Locale.ENGLISH).startsWith("[npc]")) {
+ Matcher matcher = NPC_DIALOGUE_REGEX.matcher(message);
+ if (matcher.find()) {
+ showDialogue = true;
+ event.setCanceled(true);
+
+ Dialogue dialogue = new Dialogue(matcher.group(1), matcher.group(2));
+ if (currentDialogue == null) currentDialogue = dialogue; else DIALOGUE.add(dialogue);
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void renderOverlay(RenderGameOverlayEvent.Post event) {
+ if (Utils.overlayShouldRender(event.type, SkyblockHud.hasSkyblockScoreboard(), showDialogue, !SkyblockHud.config.misc.hideDialogueBox)) {
+ Minecraft mc = Minecraft.getMinecraft();
+ mc.renderEngine.bindTexture(Textures.texture.dialogue);
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
+
+ int x = SkyblockHud.config.misc.dialoguePos.getAbsX(event.resolution, 182) - 91;
+ int y = SkyblockHud.config.misc.dialoguePos.getAbsY(event.resolution, 68);
+
+ Gui.drawModalRectWithCustomSizedTexture(x, y, 0, 0, 182, 68, 256, 256);
+
+ String npcID = currentDialogue.name.toLowerCase(Locale.ENGLISH).replace(" ", "_");
+
+ if (NPCS.containsKey(npcID)) {
+ mc.renderEngine.bindTexture(NPCS.get(npcID));
+ Gui.drawModalRectWithCustomSizedTexture(x + 4, y + 4, 0, 0, 32, 60, 128, 128);
+ }
+
+ FontRenderer font = mc.fontRendererObj;
+
+ font.drawString(currentDialogue.name, x + 40, y + 10, 0xffffff);
+
+ for (int i = 0; i < currentDialogue.dialogue.size(); i++) {
+ Utils.drawStringScaled(currentDialogue.dialogue.get(i), font, x + 40, y + 10 + font.FONT_HEIGHT + 6 + (i * font.FONT_HEIGHT + 3), false, 0xffffff, 0.75f);
+ }
+ }
+ }
+
+ @Override
+ public void onResourceManagerReload(IResourceManager resourceManager) {
+ NPCS.clear();
+ try {
+ ResourceLocation npcs = new ResourceLocation("skyblockhud:data/npc_textures.json");
+ InputStream is = resourceManager.getResource(npcs).getInputStream();
+
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
+ for (JsonElement npc : gson.fromJson(reader, JsonObject.class).getAsJsonArray("npcs")) {
+ JsonObject npcObject = npc.getAsJsonObject();
+ String npcName = npcObject.get("name").getAsString();
+ ResourceLocation rl = new ResourceLocation(npcObject.get("texture").getAsString());
+ NPCS.put(npcName.toLowerCase(Locale.ENGLISH).replace(" ", "_"), rl);
+ }
+ }
+ } catch (Exception ignored) {}
+ }
+
+ static class Dialogue {
+
+ public List<String> dialogue;
+ public String name;
+
+ public Dialogue(String name, String dialogue) {
+ this.dialogue = Minecraft.getMinecraft().fontRendererObj.listFormattedStringToWidth(dialogue, 160);
+ this.name = name;
+ }
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/SlayerHandler.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/SlayerHandler.java
new file mode 100644
index 000000000..4a1f4e698
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/SlayerHandler.java
@@ -0,0 +1,130 @@
+package com.thatgravyboat.skyblockhud.handlers;
+
+import com.thatgravyboat.skyblockhud.api.events.SidebarLineUpdateEvent;
+import com.thatgravyboat.skyblockhud.api.events.SidebarPostEvent;
+import com.thatgravyboat.skyblockhud.api.events.SkyBlockEntityKilled;
+import com.thatgravyboat.skyblockhud.utils.Utils;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+public class SlayerHandler {
+
+ private static final Pattern KILLS_REGEX = Pattern.compile("(\\d+)/(\\d+) kills?");
+ private static final Pattern SLAYER_PATTERN = Pattern.compile("Talk to Maddox to claim your ([A-Za-z]+) Slayer XP!");
+
+ public enum slayerTypes {
+ ZOMBIE(34, "Revenant Horror"),
+ WOLF(42, "Sven Packmaster"),
+ SPIDER(50, "Tarantula Broodfather"),
+ VOIDGLOOMSERAPH(58, "Voidgloom Seraph"),
+ NONE(0, "");
+
+ private final String displayName;
+ private final int x;
+
+ slayerTypes(int x, String displayName) {
+ this.displayName = displayName;
+ this.x = x;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public int getX() {
+ return x;
+ }
+ }
+
+ public static slayerTypes currentSlayer = slayerTypes.NONE;
+ public static int slayerTier = 0;
+ public static boolean isDoingSlayer = false;
+ public static int progress = 0;
+ public static int maxKills = 0;
+ public static boolean bossSlain = false;
+ public static boolean isKillingBoss = false;
+
+ public static void clearSlayer() {
+ currentSlayer = slayerTypes.NONE;
+ isDoingSlayer = false;
+ progress = 0;
+ maxKills = 0;
+ bossSlain = false;
+ isKillingBoss = false;
+ }
+
+ @SubscribeEvent
+ public void onSidebarPost(SidebarPostEvent event) {
+ String arrayString = Arrays.toString(event.arrayScores);
+ isDoingSlayer = Arrays.toString(event.arrayScores).contains("Slayer Quest");
+ if (isDoingSlayer && (currentSlayer.equals(slayerTypes.NONE) || !arrayString.replace(" ", "").contains(currentSlayer.getDisplayName().replace(" ", "") + Utils.intToRomanNumeral(slayerTier)))) {
+ for (int i = 0; i < event.scores.size(); i++) {
+ String line = event.scores.get(i);
+ if (line.contains("Slayer Quest") && event.scores.size() > 3) {
+ String slayer = event.scores.get(i - 1).toLowerCase();
+ SlayerHandler.slayerTypes selectedSlayer = SlayerHandler.slayerTypes.NONE;
+ for (slayerTypes types : slayerTypes.values()) {
+ if (slayer.contains(types.displayName.toLowerCase(Locale.ENGLISH))) {
+ selectedSlayer = types;
+ break;
+ }
+ }
+ SlayerHandler.currentSlayer = selectedSlayer;
+ SlayerHandler.slayerTier = Utils.whatRomanNumeral(slayer.replace(selectedSlayer.getDisplayName().toLowerCase(), "").replace(" ", ""));
+ break;
+ }
+ }
+ }
+
+ if (!isDoingSlayer) {
+ clearSlayer();
+ }
+ }
+
+ @SubscribeEvent
+ public void onSidebarLineUpdate(SidebarLineUpdateEvent event) {
+ if (!isDoingSlayer && event.formattedLine.equals("Slayer Quest")) isDoingSlayer = true;
+
+ if (isDoingSlayer) {
+ String line = event.formattedLine.toLowerCase();
+ Matcher killMatcher = KILLS_REGEX.matcher(line);
+
+ if (killMatcher.find()) {
+ SlayerHandler.bossSlain = false;
+ SlayerHandler.isKillingBoss = false;
+ try {
+ progress = Integer.parseInt(killMatcher.group(1));
+ } catch (Exception ignored) {}
+ try {
+ maxKills = Integer.parseInt(killMatcher.group(2));
+ } catch (Exception ignored) {}
+ } else if (line.contains("slay the boss")) {
+ SlayerHandler.bossSlain = false;
+ SlayerHandler.isKillingBoss = true;
+ SlayerHandler.maxKills = 0;
+ SlayerHandler.progress = 0;
+ } else if (line.contains("boss slain")) {
+ SlayerHandler.isKillingBoss = false;
+ SlayerHandler.maxKills = 0;
+ SlayerHandler.progress = 0;
+ SlayerHandler.bossSlain = true;
+ }
+ }
+ }
+
+ @SubscribeEvent(priority = EventPriority.HIGHEST)
+ public void onChatMessage(ClientChatReceivedEvent event) {
+ if (event.type != 2) {
+ Matcher slayerMatcher = SLAYER_PATTERN.matcher(Utils.removeColor(event.message.getUnformattedText()));
+ if (slayerMatcher.find()) {
+ MinecraftForge.EVENT_BUS.post(new SkyBlockEntityKilled(slayerMatcher.group(1).toUpperCase(Locale.ENGLISH) + "_SLAYER", null));
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/TimeHandler.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/TimeHandler.java
new file mode 100644
index 000000000..f1aa22295
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/TimeHandler.java
@@ -0,0 +1,28 @@
+package com.thatgravyboat.skyblockhud.handlers;
+
+import com.thatgravyboat.skyblockhud.api.events.SidebarLineUpdateEvent;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import java.util.regex.Pattern;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.apache.logging.log4j.LogManager;
+
+public class TimeHandler {
+
+ public static long time;
+
+ @SubscribeEvent
+ public void onSidebarLineUpdate(SidebarLineUpdateEvent event) {
+ if (Pattern.matches("([0-9]*):([0-9]*)(pm|am)", event.formattedLine.toLowerCase().trim())) {
+ boolean isPm = event.formattedLine.toLowerCase().trim().endsWith("pm");
+ SimpleDateFormat parseFormat = new SimpleDateFormat("hh:mm a", Locale.CANADA);
+ String currentTimeString = event.formattedLine.replace(" ", "").replace(isPm ? "pm" : "am", isPm ? " pm" : " am");
+ try {
+ time = (parseFormat.parse(currentTimeString).getTime() - parseFormat.parse("00:00 am").getTime()) / 1000L;
+ } catch (ParseException ignored) {
+ LogManager.getLogger().warn("timeformat error: " + currentTimeString);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/WarpHandler.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/WarpHandler.java
new file mode 100644
index 000000000..77a4199ad
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/WarpHandler.java
@@ -0,0 +1,179 @@
+package com.thatgravyboat.skyblockhud.handlers;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.SetMultimap;
+import com.google.gson.*;
+import com.thatgravyboat.skyblockhud.SkyblockHud;
+import com.thatgravyboat.skyblockhud.api.events.ProfileJoinedEvent;
+import com.thatgravyboat.skyblockhud.api.events.ProfileSwitchedEvent;
+import com.thatgravyboat.skyblockhud.mixins.GuiChestAccessor;
+import com.thatgravyboat.skyblockhud.utils.Utils;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraftforge.client.event.GuiOpenEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+public class WarpHandler {
+
+ private static String profile = null;
+ private static File warpConfig;
+ private static final Gson GSON = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create();
+ private static final SetMultimap<String, Warp> PLAYER_WARPS = HashMultimap.create();
+
+ public static Collection<Warp> getWarps() {
+ return PLAYER_WARPS.get(profile);
+ }
+
+ @SubscribeEvent
+ public void profileChange(ProfileSwitchedEvent event) {
+ if (profile != null && !profile.equals(event.profile)) {
+ load();
+ }
+ profile = event.profile;
+ }
+
+ @SubscribeEvent
+ public void profileJoined(ProfileJoinedEvent event) {
+ if (profile != null && !profile.equals(event.profile)) {
+ load();
+ }
+ profile = event.profile;
+ }
+
+ @SubscribeEvent
+ public void onGuiClosed(GuiOpenEvent event) {
+ boolean changed = false;
+ GuiScreen currentScreen = Minecraft.getMinecraft().currentScreen;
+ if (currentScreen instanceof GuiChest) {
+ GuiChestAccessor accessor = (GuiChestAccessor) currentScreen;
+ if (accessor.getLowerChestInventory().getDisplayName().getUnformattedText().contains("Fast Travel")) {
+ for (int i = 9; i < Math.min(36, accessor.getLowerChestInventory().getSizeInventory()); i++) {
+ ItemStack stack = accessor.getLowerChestInventory().getStackInSlot(i);
+ if (stack != null && stack.getItem().equals(Items.skull) && stack.getTagCompound().hasKey("display")) {
+ NBTTagList lore = stack.getTagCompound().getCompoundTag("display").getTagList("Lore", 8);
+
+ String warpLine = Utils.removeColor(lore.getStringTagAt(0)).trim();
+
+ if (warpLine.equals("Unknown island!")) continue;
+
+ String disabledLine = Utils.removeColor(lore.getStringTagAt(lore.tagCount() - 1)).trim();
+
+ Warp warp = Warp.fromId(warpLine.replace("/warp", "").trim());
+
+ if (warp != null && !disabledLine.equals("Warp not unlocked!")) {
+ if (PLAYER_WARPS.put(profile, warp)) {
+ changed = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (changed) save();
+ }
+
+ public static void save() {
+ JsonObject json = new JsonObject();
+ JsonArray array = new JsonArray();
+ PLAYER_WARPS
+ .asMap()
+ .forEach((profile, warps) -> {
+ JsonObject profileObject = new JsonObject();
+ profileObject.addProperty("profile", profile);
+ JsonArray warpArray = new JsonArray();
+ warps.forEach(warp -> warpArray.add(new JsonPrimitive(warp.name())));
+ profileObject.add("warps", warpArray);
+ array.add(profileObject);
+ });
+ json.add("profileWarps", array);
+
+ warpConfig = new File(SkyblockHud.configDirectory, "sbh-warps.json");
+
+ try {
+ warpConfig.createNewFile();
+ try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(warpConfig), StandardCharsets.UTF_8))) {
+ writer.write(GSON.toJson(json));
+ }
+ } catch (IOException ignored) {}
+ }
+
+ public static boolean load() {
+ warpConfig = new File(SkyblockHud.configDirectory, "sbh-warps.json");
+
+ try {
+ if (warpConfig.createNewFile()) return true;
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(warpConfig), StandardCharsets.UTF_8))) {
+ JsonObject json = GSON.fromJson(reader, JsonObject.class);
+ json
+ .get("profileWarps")
+ .getAsJsonArray()
+ .forEach(jsonElement -> {
+ JsonObject profileObject = jsonElement.getAsJsonObject();
+ List<Warp> warps = new ArrayList<>();
+ profileObject
+ .get("warps")
+ .getAsJsonArray()
+ .forEach(warpId -> {
+ Warp warp = Warp.safeValueOf(warpId.getAsString());
+ if (warp != null) warps.add(warp);
+ });
+ PLAYER_WARPS.putAll(profileObject.get("profile").getAsString(), warps);
+ });
+ }
+ } catch (Exception ignored) {}
+ return false;
+ }
+
+ public enum Warp {
+ HUB("hub"),
+ PRIVATE("home"),
+ SPIDERSDEN("spider"),
+ BLAZINGFORTRESS("nether"),
+ THEEND("end"),
+ THEPARK("park"),
+ GOLDMINE("gold"),
+ DEEPCAVERNS("deep"),
+ DWARVENMINES("mines"),
+ THEBARN("barn"),
+ MUSHROOMDESERT("desert"),
+ THECASTLE("castle"),
+ SIRIUSSHACK("da"),
+ GRAVEYARDCAVES("crypt"),
+ SPIDERSNEST("nest"),
+ MAGMACUBE("magma"),
+ DRAGONNEST("drag"),
+ JUNGLE("jungle"),
+ HOWLINGCAVE("howl"),
+ DUNGEONHUB("dungeon_hub");
+
+ public String warpId;
+
+ Warp(String warpId) {
+ this.warpId = warpId;
+ }
+
+ public static Warp fromId(String id) {
+ for (Warp value : Warp.values()) {
+ if (value.warpId.equals(id)) return value;
+ }
+ return null;
+ }
+
+ public static Warp safeValueOf(String value) {
+ try {
+ return Warp.valueOf(value);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/mapicons/DwarvenIcons.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/mapicons/DwarvenIcons.java
new file mode 100644
index 000000000..211ed4b68
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/mapicons/DwarvenIcons.java
@@ -0,0 +1,39 @@
+package com.thatgravyboat.skyblockhud.handlers.mapicons;
+
+import com.thatgravyboat.skyblockhud.handlers.MapHandler;
+import com.thatgravyboat.skyblockhud.utils.ComponentBuilder;
+import java.util.ArrayList;
+import java.util.List;
+import javax.vecmath.Vector2f;
+import net.minecraft.util.ResourceLocation;
+
+public class DwarvenIcons {
+
+ public static List<MapHandler.MapIcon> dwarvenIcons = new ArrayList<>();
+
+ static {
+ setupNpcIcons();
+ setupMiscIcons();
+ setupInfoIcons();
+ setupShopIcons();
+ setupQuestIcons();
+ }
+
+ private static void setupNpcIcons() {
+ dwarvenIcons.add(new MapHandler.MapIcon(new Vector2f(181, 135), new ResourceLocation("skyblockhud", "maps/icons/puzzle.png"), new ComponentBuilder().nl("Puzzler", 'a', 'l').nl("Description", 'l').nl("The Puzzler gives you a small puzzle each day to solve and").nl("gives you 1000 mithril powder.").build(), MapHandler.MapIconTypes.NPC));
+ }
+
+ private static void setupMiscIcons() {}
+
+ private static void setupInfoIcons() {
+ dwarvenIcons.add(new MapHandler.MapIcon(new Vector2f(129, 187), new ResourceLocation("skyblockhud", "maps/icons/crown.png"), new ComponentBuilder().nl("King", 'a', 'l').nl("Description", 'l').nl("The King allows you to first start commissions and if you click").nl("each king which change every skyblock day you will get").nl("the King Talisman.").nl().apd("Click to open HOTM", '6', 'l').build(), MapHandler.MapIconTypes.INFO, "hotm"));
+ }
+
+ private static void setupShopIcons() {
+ dwarvenIcons.add(new MapHandler.MapIcon(new Vector2f(4, 8), new ResourceLocation("skyblockhud", "maps/icons/blacksmith.png"), new ComponentBuilder().nl("Forge", 'a', 'l').nl("Description", 'l').nl("The Forge is where you can go craft special items").nl("and fuel your drill.").nl("NPCS", 'c', 'l').nl(" Forger - Allows you to forge special items").nl(" Jotraeline Greatforge - Allows you to refuel your drill.").nl().apd("Click to warp", '6', 'l').build(), MapHandler.MapIconTypes.SHOPS, "warpforge"));
+ }
+
+ private static void setupQuestIcons() {
+ dwarvenIcons.add(new MapHandler.MapIcon(new Vector2f(67, 204), new ResourceLocation("skyblockhud", "maps/icons/special.png"), new ComponentBuilder().nl("Royal Resident", 'a', 'l').nl("The Royal Resident is a quest where you right").nl("click them for a bit to obtain and if you continue").nl("to right click them for about 7 hours it will give").apd("the achievement Royal Conversation.").build(), MapHandler.MapIconTypes.QUEST));
+ }
+}
diff --git a/src/main/java/com/thatgravyboat/skyblockhud/handlers/mapicons/HubIcons.java b/src/main/java/com/thatgravyboat/skyblockhud/handlers/mapicons/HubIcons.java
new file mode 100644
index 000000000..7de7d92cf
--- /dev/null
+++ b/src/main/java/com/thatgravyboat/skyblockhud/handlers/mapicons/HubIcons.java
@@ -0,0 +1,55 @@
+package com.thatgravyboat.skyblockhud.handlers.mapicons;
+
+import com.thatgravyboat.skyblockhud.handlers.MapHandler;
+import com.thatgravyboat.skyblockhud.utils.ComponentBuilder;
+import java.util.ArrayList;
+import java.util.List;
+import javax.vecmath.Vector2f;
+import net.minecraft.util.ResourceLocation;
+
+public class HubIcons {
+
+ public static List<MapHandler.MapIcon> hubIcons = new ArrayList<>();
+
+ static {
+ setupNpcIcons();
+ setupMiscIcons();
+ setupInfoIcons();
+ setupShopIcons();
+ setupQuestIcons();
+ }
+
+ private static void setupNpcIcons() {
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(-2, -34), new ResourceLocation("skyblockhud", "maps/icons/special.png"), new ComponentBuilder().nl("Event Hut", 'a', 'l').nl("Description", 'l').nl("The Event Hut is where special event npcs").nl("are during some events.").nl("NPC'S", 'c', 'l').nl(" Baker - During New Years").nl(" Jerry - While Winter Island is opened").nl(" Fear Mongerer - During Spooky Festival").apd(" Oringo - During Traveling Zoo").build(), MapHandler.MapIconTypes.NPC));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(135, 142), new ResourceLocation("skyblockhud", "maps/icons/fairy.png"), new ComponentBuilder().nl("Fairy", 'a', 'l').nl("Description", 'l').nl("The Fairy is where you go when you find fairy souls").apd("to trade them in to get permanent stat upgrades.").build(), MapHandler.MapIconTypes.NPC));
+ }
+
+ private static void setupShopIcons() {
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(-50, -22), new ResourceLocation("skyblockhud", "maps/icons/building.png"), new ComponentBuilder().nl("Builder's House", 'a', 'l').nl("NPCS", 'c', 'l').nl(" Wool Weaver").nl(" Builder").apd(" Mad Redstone Engineer").build(), MapHandler.MapIconTypes.SHOPS));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(-78, -46), new ResourceLocation("skyblockhud", "maps/icons/bar.png"), new ComponentBuilder().nl("Tavern", 'a', 'l').nl("NPCS", 'c', 'l').nl(" Bartender").nl(" Maddox the slayer").nl("Description", 'l').nl("The Tavern is where maddox the slayer is located you can").nl("start slayer quests with them to unlock").apd("new items the more slayer bosses you kill.").build(), MapHandler.MapIconTypes.SHOPS));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(36, -82), new ResourceLocation("skyblockhud", "maps/icons/vet.png"), new ComponentBuilder().nl("Vet", 'a', 'l').nl("NPCS", 'c', 'l').nl(" Bea").nl(" Zog").nl(" Kat").nl(" George").nl("Description", 'l').nl("The Vet is where you go to upgrade your pet").nl("at Kat or to buy pet upgrade items from Zog").nl("or trade in your pet at George and if you're").apd("a new player you can buy a bee pet from Bea.").build(), MapHandler.MapIconTypes.SHOPS));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(58, -73), new ResourceLocation("skyblockhud", "maps/icons/fishing_merchant.png"), new ComponentBuilder().nl("Fishing Merchant", 'a', 'l').nl("Description", 'l').nl("The Fishing Merchant allows you to buy").nl("fishing related items and he has his friend").nl("joe whose in the house hes setup").apd("in front of who sells sponges.").build(), MapHandler.MapIconTypes.SHOPS));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(46, -53), new ResourceLocation("skyblockhud", "maps/icons/witch.png"), new ComponentBuilder().nl("Alchemist", 'a', 'l').nl("Description", 'l').nl("The Alchemist allows you to buy").apd("potion making related items").build(), MapHandler.MapIconTypes.SHOPS));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(-4, -128), new ResourceLocation("skyblockhud", "maps/icons/metal_merchants.png"), new ComponentBuilder().nl("Blacksmith Merchants", 'a', 'l').nl("Merchants", 'c', 'l').nl(" Weaponsmith - Weapon Related Items").nl(" Armorsmith - Armor Related Items").apd(" Mine Merchant - Mining Related Items").build(), MapHandler.MapIconTypes.SHOPS));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(-30, -120), new ResourceLocation("skyblockhud", "maps/icons/blacksmith.png"), new ComponentBuilder().nl("Blacksmith", 'a', 'l').nl("NPCS", 'c', 'l').nl(" Blacksmith").nl(" Dusk").nl(" Smithmonger").nl("Description", 'l').nl("The Blacksmith lets you reforge your items").nl("while the Smithmonger allows you to buy reforge stones").apd("and Dusk allows you to combine and apply runes.").build(), MapHandler.MapIconTypes.SHOPS));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(124, 180), new ResourceLocation("skyblockhud", "maps/icons/dark_bar.png"), new ComponentBuilder().nl("Dark Bar", 'a', 'l').nl("NPCS", 'c', 'l').nl(" Shifty").nl(" Lucius").nl("Description", 'l').nl("The Dark Bar is where you can buy special").nl("brews from Shifty and you can buy special").nl("items from Lucius after buying a certain").apd("amount of items from the Dark Auction.").build(), MapHandler.MapIconTypes.SHOPS));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(92, 185), new ResourceLocation("skyblockhud", "maps/icons/dark_ah.png"), new ComponentBuilder().nl("Dark Auction", 'a', 'l').nl("Description", 'l').nl("The Dark Auction allows you to buy").nl("super special items from Sirius the").apd("auctioneer in a special auction.").build(), MapHandler.MapIconTypes.SHOPS));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(-245, 52), new ResourceLocation("skyblockhud", "maps/icons/scroll.png"), new ComponentBuilder().nl("Lonely Philosopher", 'a', 'l').nl("Shop", '6', 'l').nl(" Travel Scroll to Hub Castle").nl().nl(" Cost").nl(" 150,000 Coins", '6').nl().apd(" Requires ").apd("MVP", 'b').apd("+", 'c').build(), MapHandler.MapIconTypes.SHOPS));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(24, -38), new ResourceLocation("skyblockhud", "maps/icons/tux.png"), new ComponentBuilder().nl("Fashion Shop", 'a', 'l').nl("NPCS", 'c', 'l').nl(" Wool Weaver").nl(" Builder").apd(" Mad Redstone Engineer").build(), MapHandler.MapIconTypes.SHOPS));
+ }
+
+ private static void setupMiscIcons() {
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(-24, -53), new ResourceLocation("skyblockhud", "maps/icons/bank.png"), new ComponentBuilder().nl("Bank", 'a', 'l').nl("Description", 'l').nl("The Bank is where you can store your money on skyblock").apd("you can also store some items in the vault.").build(), MapHandler.MapIconTypes.MISC));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(-26, -80), new ResourceLocation("skyblockhud", "maps/icons/ah.png"), new ComponentBuilder().nl("Auction House", 'a', 'l').nl("Description", 'l').nl("The Auction House is where you can auction off your").apd("precious items in skyblock to make a profit.").build(), MapHandler.MapIconTypes.MISC));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(-38, -66), new ResourceLocation("skyblockhud", "maps/icons/bazaar.png"), new ComponentBuilder().nl("Bazaar", 'a', 'l').nl("Description", 'l').nl("The Bazaar is where you can sell specific items").nl("on a sort of stock market and request and").apd("sell items at a specific price.").build(), MapHandler.MapIconTypes.MISC));
+ }
+
+ private static void setupInfoIcons() {
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(8, -95), new ResourceLocation("skyblockhud", "maps/icons/community.png"), new ComponentBuilder().nl("Community Center", 'a', 'l').nl("Description", 'l').nl("The Community Center is where you can vote").nl("for your favorite election candidate,").nl("access the community shop, upgrade your").apd("account, and help with city projects.").build(), MapHandler.MapIconTypes.INFO));
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(150, 45), new ResourceLocation("skyblockhud", "maps/icons/fishing.png"), new ComponentBuilder().nl("Fisherman's Hut", 'a', 'l').nl("Description", 'l').nl("This is a spot where people regularly").nl("do their fishing, this is one").apd("of many spots.").build(), MapHandler.MapIconTypes.INFO));
+ }
+
+ private static void setupQuestIcons() {
+ hubIcons.add(new MapHandler.MapIcon(new Vector2f(-8, -10), new ResourceLocation("skyblockhud", "maps/icons/painter.png"), new ComponentBuilder().nl("Marco", 'a', 'l').nl("Description", 'l').nl("Marco is an NPC that has no other uses").nl("besides giving you a spray can for").apd("completing a quest.").build(), MapHandler.MapIconTypes.QUEST));
+ }
+}