aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md6
-rw-r--r--src/main/java/de/cowtipper/cowlection/config/MooConfig.java58
-rw-r--r--src/main/java/de/cowtipper/cowlection/data/DataHelper.java37
-rw-r--r--src/main/java/de/cowtipper/cowlection/data/HySkyBlockStats.java17
-rw-r--r--src/main/java/de/cowtipper/cowlection/data/XpTables.java12
-rw-r--r--src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java11
-rw-r--r--src/main/java/de/cowtipper/cowlection/listener/ChatListener.java11
-rw-r--r--src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java129
-rw-r--r--src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsPartyListener.java9
-rw-r--r--src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java59
-rw-r--r--src/main/resources/assets/cowlection/lang/en_US.lang10
11 files changed, 264 insertions, 95 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ff0a496..3f9bc56 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Added quick lookup for item prices and wiki:
- wiki: hypixel-skyblock.fandom.com (default key: `I` = info)
- item prices: stonks.gg (default key: `P` = price)
+- Display pet exp in pet tooltips
### Changed
- Item age: show timestamp in the local timezone instead of "SkyBlock"-timezone (Eastern Time; also fixed the incorrect 12h ↔ 24h clock conversion)
@@ -30,9 +31,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Dungeon Party Finder (overlay):
- Made party indicators clearer (current, suitable, unideal, unjoinable party)
- Show sizes of parties
- - Mark parties with 'carry' in their notes
+ - Mark parties with 'carry' or 'hyperion' in their notes (disabled by default)
+ - Lookup info when dungeon party is full
- Lookup info when joining another party via Dungeon Party Finder
- - Added active pet + found dungeon secrets to dungeon player lookup
+ - Added active pet + found dungeon secrets + dungeon types (currently only Catacombs) level to dungeon player lookup
### Fixed
- Fixed some possible problems with bad server connection
diff --git a/src/main/java/de/cowtipper/cowlection/config/MooConfig.java b/src/main/java/de/cowtipper/cowlection/config/MooConfig.java
index 2510820..cd7279e 100644
--- a/src/main/java/de/cowtipper/cowlection/config/MooConfig.java
+++ b/src/main/java/de/cowtipper/cowlection/config/MooConfig.java
@@ -73,6 +73,7 @@ public class MooConfig {
private static String tooltipItemAge;
public static boolean tooltipItemAgeShortened;
private static String tooltipItemTimestamp;
+ private static String showPetExp;
private static String numeralSystem;
private static String tooltipAuctionHousePriceEach;
private static String bazaarConnectGraphsNodes;
@@ -91,10 +92,12 @@ public class MooConfig {
public static int dungOverlayGuiScale;
public static boolean dungOverlayTextShadow;
private static String dungPartyFinderPlayerLookup;
+ public static boolean dungPartyFullLookup;
public static boolean dungPartyFinderPartyLookup;
public static boolean dungPartiesSize;
public static int dungClassMin;
- public static boolean dungFilterPartiesWithCarry;
+ private static String dungMarkPartiesWithCarry;
+ private static String dungMarkPartiesWithHyperion;
private static boolean dungFilterPartiesWithArcherDupes;
private static boolean dungFilterPartiesWithBerserkDupes;
private static boolean dungFilterPartiesWithHealerDupes;
@@ -345,6 +348,9 @@ public class MooConfig {
Property propTooltipItemTimestamp = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
"tooltipItemTimestamp", "key press", "Show item creation date", new String[]{"always", "key press", "never"}));
+ Property propShowPetExp = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
+ "showPetExp", "always", "Show pet exp", new String[]{"always", "key press", "never"}));
+
Property propNumeralSystem = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
"numeralSystem", "Arabic: 1, 4, 10", "Use Roman or Arabic numeral system?", new String[]{"Arabic: 1, 4, 10", "Roman: I, IV, X"}));
@@ -463,12 +469,14 @@ public class MooConfig {
" ‣ that do not meet all your criteria: " + EnumChatFormatting.GOLD + "⬛",
" ‣ with someone below a certain class level: " + EnumChatFormatting.RED + EnumChatFormatting.BOLD + "ᐯ" + EnumChatFormatting.RESET,
" ‣ with duplicated roles you specify below: " + EnumChatFormatting.GOLD + "²⁺",
- " ‣ with 'carry' in their notes: " + EnumChatFormatting.AQUA + "carry",
" ‣ that match your criteria: " + EnumChatFormatting.GREEN + "⬛");
Property propDungPartyFinderPlayerLookup = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
"dungPartyFinderPlayerLookup", "as a tooltip", "Show armor + dungeons stats of player joining via party finder as a tooltip or in chat?", new String[]{"as a tooltip", "in chat", "disabled"}));
+ Property propDungPartyFullLookup = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
+ "dungPartyFullLookup", true, "Lookup info when party full?"));
+
Property propDungPartyFinderPartyLookup = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
"dungPartyFinderPartyLookup", true, "Lookup info when joining another party?"));
@@ -481,11 +489,17 @@ public class MooConfig {
.setMinValue(0).setMaxValue(50),
new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.RED + EnumChatFormatting.BOLD + "ᐯ").gray()));
- Property propDungFilterPartiesWithCarry = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
- "dungFilterPartiesWithCarry", true, "Mark parties with carry in the notes"),
+ Property propDungMarkPartiesWithCarry = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
+ "dungMarkPartiesWithCarry", "do not mark", "Mark parties with carry in the notes",
+ new String[]{"suitable " + EnumChatFormatting.GREEN + "⬛", "unideal " + EnumChatFormatting.GOLD + "⬛", "block " + EnumChatFormatting.RED + "⬛", "do not mark"}),
new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.AQUA + "carry"
+ EnumChatFormatting.GRAY + " or " + EnumChatFormatting.GREEN + "carry " + EnumChatFormatting.GRAY + "('free' carries)").gray()));
+ Property propDungMarkPartiesWithHyperion = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
+ "dungMarkPartiesWithHyperion", "do not mark", "Mark parties with hyperion in the notes",
+ new String[]{"suitable " + EnumChatFormatting.GREEN + "⬛", "unideal " + EnumChatFormatting.GOLD + "⬛", "block " + EnumChatFormatting.RED + "⬛", "do not mark"}),
+ new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.AQUA + "hyper").gray()));
+
Property propDungFilterPartiesWithArcherDupes = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
"dungFilterPartiesWithArcherDupes", true, "Mark parties with duplicated Archer class?"),
new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.GOLD + "²⁺" + EnumChatFormatting.YELLOW + "A").gray()));
@@ -535,6 +549,7 @@ public class MooConfig {
tooltipItemAge = propTooltipItemAge.getString();
tooltipItemAgeShortened = propTooltipItemAgeShortened.getBoolean();
tooltipItemTimestamp = propTooltipItemTimestamp.getString();
+ showPetExp = propShowPetExp.getString();
numeralSystem = propNumeralSystem.getString();
tooltipAuctionHousePriceEach = propTooltipAuctionHousePriceEach.getString();
bazaarConnectGraphsNodes = propBazaarConnectGraphsNodes.getString();
@@ -553,10 +568,12 @@ public class MooConfig {
dungOverlayGuiScale = propDungOverlayGuiScale.getInt();
dungOverlayTextShadow = propDungOverlayTextShadow.getBoolean();
dungPartyFinderPlayerLookup = propDungPartyFinderPlayerLookup.getString();
+ dungPartyFullLookup = propDungPartyFullLookup.getBoolean();
dungPartyFinderPartyLookup = propDungPartyFinderPartyLookup.getBoolean();
dungPartiesSize = propDungPartiesSize.getBoolean();
dungClassMin = propDungClassMin.getInt();
- dungFilterPartiesWithCarry = propDungFilterPartiesWithCarry.getBoolean();
+ dungMarkPartiesWithCarry = propDungMarkPartiesWithCarry.getString();
+ dungMarkPartiesWithHyperion = propDungMarkPartiesWithHyperion.getString();
dungFilterPartiesWithArcherDupes = propDungFilterPartiesWithArcherDupes.getBoolean();
dungFilterPartiesWithBerserkDupes = propDungFilterPartiesWithBerserkDupes.getBoolean();
dungFilterPartiesWithHealerDupes = propDungFilterPartiesWithHealerDupes.getBoolean();
@@ -596,6 +613,7 @@ public class MooConfig {
propTooltipItemAge.set(tooltipItemAge);
propTooltipItemAgeShortened.set(tooltipItemAgeShortened);
propTooltipItemTimestamp.set(tooltipItemTimestamp);
+ propShowPetExp.set(showPetExp);
propNumeralSystem.set(numeralSystem);
propTooltipAuctionHousePriceEach.set(tooltipAuctionHousePriceEach);
propBazaarConnectGraphsNodes.set(bazaarConnectGraphsNodes);
@@ -614,10 +632,12 @@ public class MooConfig {
propDungOverlayGuiScale.set(dungOverlayGuiScale);
propDungOverlayTextShadow.set(dungOverlayTextShadow);
propDungPartyFinderPlayerLookup.set(dungPartyFinderPlayerLookup);
+ propDungPartyFullLookup.set(dungPartyFullLookup);
propDungPartyFinderPartyLookup.set(dungPartyFinderPartyLookup);
propDungPartiesSize.set(dungPartiesSize);
propDungClassMin.set(dungClassMin);
- propDungFilterPartiesWithCarry.set(dungFilterPartiesWithCarry);
+ propDungMarkPartiesWithCarry.set(dungMarkPartiesWithCarry);
+ propDungMarkPartiesWithHyperion.set(dungMarkPartiesWithHyperion);
propDungFilterPartiesWithArcherDupes.set(dungFilterPartiesWithArcherDupes);
propDungFilterPartiesWithBerserkDupes.set(dungFilterPartiesWithBerserkDupes);
propDungFilterPartiesWithHealerDupes.set(dungFilterPartiesWithHealerDupes);
@@ -740,6 +760,10 @@ public class MooConfig {
return Setting.get(tooltipItemTimestamp);
}
+ public static Setting getTooltipPetExpDisplay() {
+ return Setting.get(showPetExp);
+ }
+
public static boolean useRomanNumerals() {
return numeralSystem.startsWith("Roman");
}
@@ -773,6 +797,28 @@ public class MooConfig {
return Setting.get(dungPartyFinderPlayerLookup);
}
+ public static DataHelper.PartyType getDungPartyFinderMarkCarry() {
+ return getPartyType(dungMarkPartiesWithCarry);
+ }
+
+ public static DataHelper.PartyType getDungPartyFinderMarkHyperion() {
+ return getPartyType(dungMarkPartiesWithHyperion);
+ }
+
+ private static DataHelper.PartyType getPartyType(String configValue) {
+ String configValueBeginning = configValue.length() >= 5 ? configValue.substring(0, 5) : "invalid";
+ switch (configValueBeginning) {
+ case "suita": // "suitable " + EnumChatFormatting.GREEN + "⬛"
+ return DataHelper.PartyType.SUITABLE;
+ case "unide": // "unideal " + EnumChatFormatting.GOLD + "⬛"
+ return DataHelper.PartyType.UNIDEAL;
+ case "block": // "block " + EnumChatFormatting.RED + "⬛"
+ return DataHelper.PartyType.UNJOINABLE;
+ default: // "do not mark"
+ return DataHelper.PartyType.NONE;
+ }
+ }
+
public static boolean filterDungPartiesWithDupes(DataHelper.DungeonClass dungeonClass) {
switch (dungeonClass) {
case ARCHER:
diff --git a/src/main/java/de/cowtipper/cowlection/data/DataHelper.java b/src/main/java/de/cowtipper/cowlection/data/DataHelper.java
index 028fe62..75c49b0 100644
--- a/src/main/java/de/cowtipper/cowlection/data/DataHelper.java
+++ b/src/main/java/de/cowtipper/cowlection/data/DataHelper.java
@@ -32,6 +32,19 @@ public final class DataHelper {
return Arrays.stream(values(), 0, 5).toArray(SkyBlockRarity[]::new);
}
+ public static SkyBlockRarity getPetRarityByColorCode(String colorCode) {
+ if (MYTHIC.rarityColor.toString().equals(colorCode)) {
+ // special case: Mystic Bat
+ return LEGENDARY;
+ }
+ for (SkyBlockRarity petRarity : getPetRarities()) {
+ if (petRarity.rarityColor.toString().equals(colorCode)) {
+ return petRarity;
+ }
+ }
+ return null;
+ }
+
public EnumChatFormatting getColor() {
return rarityColor;
}
@@ -93,6 +106,30 @@ public final class DataHelper {
}
}
+ public enum PartyType {
+ SUITABLE(0xff22B14C, 240),
+ UNIDEAL(0xffCD8032, 240),
+ UNJOINABLE(0xffEB6E6E, 279),
+ CURRENT(0xff5FDE6C, 240),
+ NONE(0xffFF0000, 279);
+
+ private final float zIndex;
+ private final int color;
+
+ PartyType(int color, float zIndex) {
+ this.color = color;
+ this.zIndex = zIndex;
+ }
+
+ public float getZIndex() {
+ return zIndex;
+ }
+
+ public int getColor() {
+ return color;
+ }
+ }
+
public enum DungeonClass {
@SerializedName("archer") ARCHER('A'),
@SerializedName("berserk") BERSERK('B'),
diff --git a/src/main/java/de/cowtipper/cowlection/data/HySkyBlockStats.java b/src/main/java/de/cowtipper/cowlection/data/HySkyBlockStats.java
index 242c0c3..b65e48c 100644
--- a/src/main/java/de/cowtipper/cowlection/data/HySkyBlockStats.java
+++ b/src/main/java/de/cowtipper/cowlection/data/HySkyBlockStats.java
@@ -338,6 +338,23 @@ public class HySkyBlockStats {
return output;
}
+ public String getDungeonTypesLevels() {
+ StringBuilder dungeonTypesLevels = new StringBuilder();
+ if (dungeon_types != null && !dungeon_types.isEmpty()) {
+ for (Map.Entry<String, HySkyBlockStats.Profile.Dungeons.Type> dungeonType : dungeon_types.entrySet()) {
+ if (dungeonTypesLevels.length() == 0) {
+ dungeonTypesLevels.append(EnumChatFormatting.DARK_GRAY).append(" [").append(EnumChatFormatting.GRAY);
+ } else {
+ dungeonTypesLevels.append(EnumChatFormatting.DARK_GRAY).append(", ").append(EnumChatFormatting.GRAY);
+ }
+ int dungeonTypeLevel = dungeonType.getValue().getLevel();
+ dungeonTypesLevels.append(Utils.fancyCase(dungeonType.getKey().substring(0, 4))).append(" ").append(MooConfig.useRomanNumerals() ? Utils.convertArabicToRoman(dungeonTypeLevel) : dungeonTypeLevel);
+ }
+ dungeonTypesLevels.append(EnumChatFormatting.DARK_GRAY).append("]");
+ }
+ return dungeonTypesLevels.toString();
+ }
+
public static class Type {
private Map<String, Integer> times_played;
private Map<String, Integer> tier_completions;
diff --git a/src/main/java/de/cowtipper/cowlection/data/XpTables.java b/src/main/java/de/cowtipper/cowlection/data/XpTables.java
index 391f90a..158fb66 100644
--- a/src/main/java/de/cowtipper/cowlection/data/XpTables.java
+++ b/src/main/java/de/cowtipper/cowlection/data/XpTables.java
@@ -249,6 +249,18 @@ public class XpTables {
return -1;
}
}
+
+ public static int getTotalExp(DataHelper.SkyBlockRarity rarity, int level, int exp) {
+ TreeSet<Integer> xpToLevels = PET_XP.get(rarity);
+ if (xpToLevels != null) {
+ for (int xpToLevel : xpToLevels) {
+ if (level-- <= 1) {
+ return xpToLevel + exp;
+ }
+ }
+ }
+ return -1;
+ }
}
public enum Dungeoneering {
diff --git a/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java b/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java
index cfacd9d..df3d08f 100644
--- a/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java
+++ b/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java
@@ -27,7 +27,7 @@ public class DungeonCache {
private final Set<String> deadPlayers;
private final Set<String> failedPuzzles;
private final Set<UUID> destroyedCrypts;
- private int cryptsOffset;
+ private int destroyedCryptsInTabList;
private boolean isInDungeon;
private int elapsedMinutes;
@@ -43,7 +43,7 @@ public class DungeonCache {
deadPlayers = new HashSet<>();
failedPuzzles = new HashSet<>();
destroyedCrypts = new HashSet<>();
- cryptsOffset = 0;
+ destroyedCryptsInTabList = 0;
}
public boolean isInDungeon() {
@@ -147,8 +147,7 @@ public class DungeonCache {
String tabListEntry = EnumChatFormatting.getTextWithoutFormattingCodes(tabList.getPlayerName(playerInfo));
if (tabListEntry != null && tabListEntry.startsWith(" Crypts: ")) {
try {
- int cryptsFromTabList = Integer.parseInt(tabListEntry.substring(" Crypts: ".length()).trim());
- cryptsOffset = cryptsFromTabList - destroyedCrypts.size();
+ destroyedCryptsInTabList = Integer.parseInt(tabListEntry.substring(" Crypts: ".length()).trim());
} catch (NumberFormatException | IndexOutOfBoundsException ex) {
// couldn't parse crypts count from tab list
ex.printStackTrace();
@@ -235,7 +234,7 @@ public class DungeonCache {
}
public int getDestroyedCrypts() {
- return destroyedCrypts.size() + cryptsOffset;
+ return destroyedCryptsInTabList > 0 ? destroyedCryptsInTabList : destroyedCrypts.size();
}
public int getElapsedMinutes() {
@@ -248,7 +247,7 @@ public class DungeonCache {
deadPlayers.clear();
failedPuzzles.clear();
destroyedCrypts.clear();
- cryptsOffset = 0;
+ destroyedCryptsInTabList = 0;
elapsedMinutes = 0;
classMilestone = 0;
nextPerformanceSend = 0;
diff --git a/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java b/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java
index 0240938..45b99a7 100644
--- a/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java
+++ b/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java
@@ -17,6 +17,7 @@ import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;
import net.minecraft.util.StringUtils;
+import net.minecraftforge.client.ClientCommandHandler;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.GuiScreenEvent;
@@ -187,6 +188,9 @@ public class ChatListener {
main.getDungeonCache().lookupPartyMembers();
}
}
+ } else if (CredentialStorage.isMooValid && MooConfig.dungPartyFullLookup && message.equals("Dungeon Finder > Your dungeon group is full! Click here to warp to the dungeon!")
+ && (Minecraft.getMinecraft().currentScreen == null || Minecraft.getMinecraft().currentScreen instanceof GuiChat)) {
+ ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/moo dp");
}
if (messageSender != null) {
@@ -210,13 +214,16 @@ public class ChatListener {
HySkyBlockStats.Profile.Member member = activeProfile.getMember(stalkedPlayer.getUuid());
String armorLookupPrefix = " ❈ " + EnumChatFormatting.DARK_GREEN + playerName;
String delimiter = "\n" + (outputAsChatMessages ? " " : "");
- String armorLookupResult = EnumChatFormatting.LIGHT_PURPLE + " ➜ " + EnumChatFormatting.GRAY + dungeonClass + delimiter + String.join(delimiter, member.getArmor());
+
+ HySkyBlockStats.Profile.Dungeons dungeons = member.getDungeons();
+ String dungeonTypesLevels = dungeons != null ? dungeons.getDungeonTypesLevels() : "";
+
+ String armorLookupResult = EnumChatFormatting.LIGHT_PURPLE + " ➜ " + EnumChatFormatting.GRAY + dungeonClass + dungeonTypesLevels + delimiter + String.join(delimiter, member.getArmor());
// active pet:
HySkyBlockStats.Profile.Pet activePet = member.getActivePet();
String petInfo = (outputAsChatMessages ? "\n " : "\n\n") + EnumChatFormatting.GRAY + "Active pet: " + (activePet != null ? activePet.toFancyString() : "" + EnumChatFormatting.DARK_GRAY + EnumChatFormatting.ITALIC + "none");
- HySkyBlockStats.Profile.Dungeons dungeons = member.getDungeons();
String highestFloorCompletions = "\n" + (outputAsChatMessages ? " " : "") + EnumChatFormatting.GRAY + "Completed no dungeons yet";
String skyBlockDetails;
diff --git a/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java b/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java
index 27da9f0..5f25fa7 100644
--- a/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java
+++ b/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java
@@ -5,6 +5,7 @@ import de.cowtipper.cowlection.Cowlection;
import de.cowtipper.cowlection.config.CredentialStorage;
import de.cowtipper.cowlection.config.MooConfig;
import de.cowtipper.cowlection.config.gui.MooConfigGui;
+import de.cowtipper.cowlection.data.DataHelper;
import de.cowtipper.cowlection.data.DataHelper.DungeonClass;
import de.cowtipper.cowlection.handler.DungeonCache;
import de.cowtipper.cowlection.util.GuiHelper;
@@ -283,7 +284,7 @@ public class DungeonsListener {
// not a player skull, don't draw party status indicator
return;
}
- PartyType partyType = PartyType.NONE;
+ DataHelper.PartyType partyType = DataHelper.PartyType.NONE;
List<String> itemTooltip = item.getTooltip(Minecraft.getMinecraft().thePlayer, false);
if (itemTooltip.size() < 5) {
@@ -295,9 +296,9 @@ public class DungeonsListener {
|| lastToolTipLine.startsWith("Requires a Class at Level")
|| lastToolTipLine.startsWith("Requires Catacombs Level")) {
// cannot enter dungeon
- partyType = PartyType.UNJOINABLE;
+ partyType = DataHelper.PartyType.UNJOINABLE;
} else if (lastToolTipLine.endsWith("You are in this party!")) {
- partyType = PartyType.CURRENT;
+ partyType = DataHelper.PartyType.CURRENT;
} else {
Map<DungeonClass, AtomicInteger> dungClassesInParty = new LinkedHashMap<>();
AtomicInteger classCounter = new AtomicInteger();
@@ -305,8 +306,8 @@ public class DungeonsListener {
dungClassesInParty.put(activeDungeonClass, classCounter); // add our own class
int partySize = 5;
- String isCarry = null;
boolean memberTooLowLevel = false;
+ String middleText = null;
for (String toolTipLine : itemTooltip) {
String toolTipLineWithoutFormatting = EnumChatFormatting.getTextWithoutFormattingCodes(toolTipLine);
@@ -323,63 +324,73 @@ public class DungeonsListener {
}
} else if (" Empty".equals(toolTipLineWithoutFormatting)) {
--partySize;
- } else if (MooConfig.dungFilterPartiesWithCarry && toolTipLineWithoutFormatting.startsWith("Note: ")) {
+ } else if (toolTipLineWithoutFormatting.startsWith("Note: ")) {
String partyNote = toolTipLineWithoutFormatting.toLowerCase();
- if (partyNote.contains("carry") || partyNote.contains("carries")) {
- partyType = PartyType.UNIDEAL;
- isCarry = partyNote.contains("free") ? "free" : "paid";
+ DataHelper.PartyType partyTypeCarry = MooConfig.getDungPartyFinderMarkCarry();
+ DataHelper.PartyType partyTypeHyperion = MooConfig.getDungPartyFinderMarkHyperion();
+ if (partyTypeCarry != DataHelper.PartyType.NONE && (partyNote.contains("carry") || partyNote.contains("carries"))) {
+ partyType = partyTypeCarry;
+ if (partyTypeCarry != DataHelper.PartyType.UNJOINABLE) {
+ middleText = (partyNote.contains("free") ? EnumChatFormatting.GREEN : "") + "carry";
+ }
+ } else if (partyTypeHyperion != DataHelper.PartyType.NONE && partyNote.contains("hyp")) {
+ partyType = partyTypeHyperion;
+ if (partyTypeHyperion != DataHelper.PartyType.UNJOINABLE) {
+ middleText = "hyper";
+ }
}
}
}
FontRenderer font = Minecraft.getMinecraft().fontRendererObj;
- if (MooConfig.dungFilterPartiesWithCarry && isCarry != null) {
+ if (partyType != DataHelper.PartyType.UNJOINABLE && middleText != null) {
GlStateManager.pushMatrix();
GlStateManager.translate(0, 0, 281);
double scaleFactor = 0.5;
GlStateManager.scale(scaleFactor, scaleFactor, 0);
- int carryColor = "free".equals(isCarry) ? new Color(85, 240, 85, 255).getRGB() : new Color(85, 240, 240, 255).getRGB();
- font.drawStringWithShadow("carry", (float) ((x + 1) / scaleFactor), (float) ((y + 5) / scaleFactor), carryColor);
+ font.drawStringWithShadow(middleText, (float) ((x + 1) / scaleFactor), (float) ((y + 5) / scaleFactor), new Color(85, 240, 240, 255).getRGB());
GlStateManager.popMatrix();
}
- if (memberTooLowLevel) {
- // at least one party member is lower than the min class level
- partyType = PartyType.UNIDEAL;
- GlStateManager.pushMatrix();
- GlStateManager.translate(0, 0, 280);
- font.drawStringWithShadow(EnumChatFormatting.BOLD + "ᐯ", x + 1, y + 8, new Color(220, 20, 20, 255).getRGB());
- GlStateManager.popMatrix();
- }
- StringBuilder dupedClasses = new StringBuilder();
- for (Map.Entry<DungeonClass, AtomicInteger> partyClassInfo : dungClassesInParty.entrySet()) {
- if (partyClassInfo.getValue().get() > 1 && MooConfig.filterDungPartiesWithDupes(partyClassInfo.getKey())) {
- dupedClasses.append(partyClassInfo.getKey().getShortName());
+ if (partyType != DataHelper.PartyType.UNJOINABLE) {
+ if (memberTooLowLevel) {
+ // at least one party member is lower than the min class level
+ partyType = DataHelper.PartyType.UNIDEAL;
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, 280);
+ font.drawStringWithShadow(EnumChatFormatting.BOLD + "ᐯ", x + 1, y + 8, new Color(220, 20, 20, 255).getRGB());
+ GlStateManager.popMatrix();
+ }
+ StringBuilder dupedClasses = new StringBuilder();
+ for (Map.Entry<DungeonClass, AtomicInteger> partyClassInfo : dungClassesInParty.entrySet()) {
+ if (partyClassInfo.getValue().get() > 1 && MooConfig.filterDungPartiesWithDupes(partyClassInfo.getKey())) {
+ dupedClasses.append(partyClassInfo.getKey().getShortName());
+ }
+ }
+ if (dupedClasses.length() > 0) {
+ // party has class duplicates
+ partyType = DataHelper.PartyType.UNIDEAL;
+ dupedClasses.insert(0, EnumChatFormatting.YELLOW).insert(0, "²⁺"); // 2+
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, 280);
+ double scaleFactor = 0.8;
+ GlStateManager.scale(scaleFactor, scaleFactor, 0);
+ font.drawStringWithShadow(dupedClasses.toString(), (float) (x / scaleFactor), (float) (y / scaleFactor), new Color(255, 170, 0, 255).getRGB());
+ GlStateManager.popMatrix();
+ } else if (!memberTooLowLevel && middleText == null) {
+ // party matches our criteria!
+ partyType = DataHelper.PartyType.SUITABLE;
+ }
+ // add party size indicator
+ if (MooConfig.dungPartiesSize && partySize > 0) {
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, 280);
+ String partySizeIndicator = String.valueOf(partySize);
+ font.drawStringWithShadow(partySizeIndicator, x + 17 - font.getStringWidth(partySizeIndicator), y + 9, 0xffFFFFFF);
+ GlStateManager.popMatrix();
}
- }
- if (dupedClasses.length() > 0) {
- // party has class duplicates
- partyType = PartyType.UNIDEAL;
- dupedClasses.insert(0, EnumChatFormatting.YELLOW).insert(0, "²⁺"); // 2+
-
- GlStateManager.pushMatrix();
- GlStateManager.translate(0, 0, 280);
- double scaleFactor = 0.8;
- GlStateManager.scale(scaleFactor, scaleFactor, 0);
- font.drawStringWithShadow(dupedClasses.toString(), (float) (x / scaleFactor), (float) (y / scaleFactor), new Color(255, 170, 0, 255).getRGB());
- GlStateManager.popMatrix();
- } else if (!memberTooLowLevel && isCarry == null) {
- // party matches our criteria!
- partyType = PartyType.SUITABLE;
- }
- // add party size indicator
- if (MooConfig.dungPartiesSize && partySize > 0) {
- GlStateManager.pushMatrix();
- GlStateManager.translate(0, 0, 280);
- String partySizeIndicator = String.valueOf(partySize);
- font.drawStringWithShadow(partySizeIndicator, x + 17 - font.getStringWidth(partySizeIndicator), y + 9, 0xffFFFFFF);
- GlStateManager.popMatrix();
}
}
- if (partyType != PartyType.CURRENT
+ if (partyType != DataHelper.PartyType.CURRENT
|| (/*partyType == PartyType.CURRENT &&*/ Minecraft.getSystemTime() % 1000 < 600)) {
GlStateManager.pushMatrix();
GlStateManager.translate(0, 0, partyType.getZIndex());
@@ -623,28 +634,4 @@ public class DungeonsListener {
}
}
}
-
- private enum PartyType {
- SUITABLE(0xff32CD32, 240),
- UNIDEAL(0xffCD8032, 240),
- UNJOINABLE(0xffD75B5B, 279),
- CURRENT(0xff5FDE6C, 240),
- NONE(0xffFF0000, 279);
-
- private final float zIndex;
- private final int color;
-
- PartyType(int color, float zIndex) {
- this.color = color;
- this.zIndex = zIndex;
- }
-
- public float getZIndex() {
- return zIndex;
- }
-
- public int getColor() {
- return color;
- }
- }
}
diff --git a/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsPartyListener.java b/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsPartyListener.java
index 84a58ee..a0162d3 100644
--- a/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsPartyListener.java
+++ b/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsPartyListener.java
@@ -246,12 +246,13 @@ public class DungeonsPartyListener {
DataHelper.DungeonClass selectedClass = dungeons.getSelectedClass();
int selectedClassLevel = dungeons.getSelectedClassLevel();
- String classInfo = selectedClass.getName() + " " + (MooConfig.useRomanNumerals() ? Utils.convertArabicToRoman(selectedClassLevel) : selectedClassLevel);
- playerEntry.append(classInfo);
- // insert class data into str:
+ String classAndDungeonTypeInfo = selectedClass.getName() + " " + (MooConfig.useRomanNumerals() ? Utils.convertArabicToRoman(selectedClassLevel) : selectedClassLevel)
+ + dungeons.getDungeonTypesLevels();
+ playerEntry.append(classAndDungeonTypeInfo);
+ // insert class + dungeon type data into str:
String noClassSelected = EnumChatFormatting.ITALIC + "no class selected";
int start = playerTooltip.indexOf(noClassSelected);
- playerTooltip.replace(start, start + noClassSelected.length(), classInfo);
+ playerTooltip.replace(start, start + noClassSelected.length(), classAndDungeonTypeInfo);
// highest floor completions:
playerTooltip.append(dungeons.getHighestFloorCompletions(3, false));
diff --git a/src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java b/src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java
index 5093e9a..524a0c1 100644
--- a/src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java
+++ b/src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java
@@ -4,6 +4,8 @@ import com.mojang.realmsclient.util.Pair;
import de.cowtipper.cowlection.Cowlection;
import de.cowtipper.cowlection.config.MooConfig;
import de.cowtipper.cowlection.config.gui.MooConfigGui;
+import de.cowtipper.cowlection.data.DataHelper;
+import de.cowtipper.cowlection.data.XpTables;
import de.cowtipper.cowlection.util.GuiHelper;
import de.cowtipper.cowlection.util.MooChatComponent;
import de.cowtipper.cowlection.util.Utils;
@@ -51,6 +53,7 @@ public class SkyBlockListener {
private static final Set<String> blackList = new HashSet<>(Arrays.asList("ENCHANTED_BOOK", "RUNE", "PET", "POTION")); // + minions (_GENERATOR_)
private static final Pattern ITEM_COUNT_PREFIXED_PATTERN = Pattern.compile("^(?:§[0-9a-fl-or])*[\\d]+x ");
private static final Pattern ITEM_COUNT_SUFFIXED_PATTERN = Pattern.compile(" (?:§[0-9a-fl-or])*x[\\d]+$");
+ private static final Pattern PET_NAME_PATTERN = Pattern.compile("^§7\\[Lvl (\\d+)] (§[0-9a-f])");
private final NumberFormat numberFormatter;
private final Cowlection main;
@@ -163,6 +166,59 @@ public class SkyBlockListener {
}
}
+ // show total pet exp
+ NBTTagCompound extraAttributes = e.itemStack.getSubCompound("ExtraAttributes", false);
+ if ((MooConfig.getTooltipPetExpDisplay() == MooConfig.Setting.ALWAYS
+ || MooConfig.getTooltipPetExpDisplay() == MooConfig.Setting.SPECIAL && MooConfig.isTooltipToggleKeyBindingPressed())
+ && e.itemStack.getItem() == Items.skull) {
+ if (extraAttributes != null && extraAttributes.hasKey("petInfo")) {
+ // pet in inventory, auction house or similar
+ String petInfo = extraAttributes.getString("petInfo");
+ String expSubstr = "\"exp\":";
+ int beginPetExp = petInfo.indexOf(expSubstr);
+ int endPetExp = petInfo.indexOf(',', beginPetExp);
+ if (beginPetExp > 0 && endPetExp > 0) {
+ try {
+ long petExp = (long) Double.parseDouble(petInfo.substring(beginPetExp + expSubstr.length(), endPetExp));
+ int index = Math.max(0, e.toolTip.size() - (e.showAdvancedItemTooltips ? /* item name & nbt info */ 2 : 0));
+ e.toolTip.add(index, EnumChatFormatting.GRAY + "Pet exp: " + EnumChatFormatting.GOLD + numberFormatter.format(petExp));
+ } catch (NumberFormatException ignored) {
+ // do nothing
+ }
+ }
+ } else if (e.itemStack.getDisplayName().contains("[Lvl ")) {
+ // pet in pets menu
+ for (int i = e.toolTip.size() - 1; i >= 0; i--) {
+ String loreLine = EnumChatFormatting.getTextWithoutFormattingCodes(e.toolTip.get(i));
+ if (loreLine.startsWith("--------------------")) { // exp bar to next level
+ int beginPetExp = loreLine.indexOf(' ');
+ int endPetExp = loreLine.indexOf('/');
+ if (beginPetExp < 0 || endPetExp < 0) {
+ // didn't find pet exp, abort
+ break;
+ }
+ try {
+ int petExp = numberFormatter.parse(loreLine.substring(beginPetExp + 1, endPetExp)).intValue();
+
+ Matcher petNameMatcher = PET_NAME_PATTERN.matcher(e.itemStack.getDisplayName());
+ if (petNameMatcher.find()) {
+ int petLevel = Integer.parseInt(petNameMatcher.group(1));
+ DataHelper.SkyBlockRarity petRarity = DataHelper.SkyBlockRarity.getPetRarityByColorCode(petNameMatcher.group(2));
+ if (petRarity == null) {
+ break;
+ }
+ int totalPetExp = XpTables.Pet.getTotalExp(petRarity, petLevel, petExp);
+ e.toolTip.add(i + 1, EnumChatFormatting.GRAY + "Total pet exp: " + EnumChatFormatting.GOLD + numberFormatter.format(totalPetExp));
+ }
+ } catch (ParseException | NumberFormatException ignored) {
+ // do nothing
+ }
+ break;
+ }
+ }
+ }
+ }
+
// remove unnecessary tooltip entries: dyed leather armor
NBTTagCompound nbtDisplay = e.itemStack.getSubCompound("display", false);
if (!Minecraft.getMinecraft().gameSettings.advancedItemTooltips
@@ -187,7 +243,6 @@ public class SkyBlockListener {
MooConfig.Setting tooltipItemTimestampDisplay = MooConfig.getTooltipItemTimestampDisplay();
// add item age to tooltip
- NBTTagCompound extraAttributes = e.itemStack.getSubCompound("ExtraAttributes", false);
if (extraAttributes != null && extraAttributes.hasKey("timestamp")
&& (tooltipItemAgeDisplay != MooConfig.Setting.DISABLED || tooltipItemTimestampDisplay != MooConfig.Setting.DISABLED)) {
LocalDateTime skyBlockDateTime;
@@ -198,7 +253,7 @@ public class SkyBlockListener {
skyBlockDateTime = LocalDateTime.parse(timestamp, DateTimeFormatter.ofPattern("M/d/yy h:mm a", Locale.US));
} else {
// format: day > month > year + 24 hour clock (very, very rare)
- skyBlockDateTime = LocalDateTime.parse(timestamp, DateTimeFormatter.ofPattern("d/M/yy hh:mm", Locale.US));
+ skyBlockDateTime = LocalDateTime.parse(timestamp, DateTimeFormatter.ofPattern("d/M/yy HH:mm", Locale.US));
}
} catch (DateTimeParseException ignored) {
// unknown/invalid timestamp format
diff --git a/src/main/resources/assets/cowlection/lang/en_US.lang b/src/main/resources/assets/cowlection/lang/en_US.lang
index 53af4a0..93fef62 100644
--- a/src/main/resources/assets/cowlection/lang/en_US.lang
+++ b/src/main/resources/assets/cowlection/lang/en_US.lang
@@ -46,6 +46,8 @@ cowlection.config.tooltipItemAgeShortened=Shorten item age?
cowlection.config.tooltipItemAgeShortened.tooltip=Show shortened (5.8 months) or detailed item age (5 months 24 days)?
cowlection.config.tooltipItemTimestamp=Show item creation date
cowlection.config.tooltipItemTimestamp.tooltip=Show item creation date? Only works for non-stackable items
+cowlection.config.showPetExp=Show pet exp
+cowlection.config.showPetExp.tooltip=Show pet exp?\n§7§oExp for max level pets §f§odon't §7§owork inside the pets menu (but in every other GUI)!
cowlection.config.numeralSystem=Numeral system
cowlection.config.numeralSystem.tooltip=Use Roman or Arabic numeral system?\nThis is currently used to display numbers in the commands /moo stalkSkyBlock and /moo analyzeIsland
cowlection.config.tooltipAuctionHousePriceEach=§7Auction house: §rprice per item
@@ -80,14 +82,18 @@ cowlection.config.dungOverlayTextShadow=Add text shadow
cowlection.config.dungOverlayTextShadow.tooltip=Enable or disable text shadow
cowlection.config.dungPartyFinderPlayerLookup=Show info of joining players §d§l⚷
cowlection.config.dungPartyFinderPlayerLookup.tooltip=Show armor and dungeons stats of player joining via party finder as a tooltip or in chat?\n§d§l⚷ §eRequires a valid API key!
+cowlection.config.dungPartyFullLookup=Lookup info when party full? §d§l⚷
+cowlection.config.dungPartyFullLookup.tooltip=Lookup armor and dungeons stats of each party member when your party is full?\n§7Alternatively: §e/moo dungeon party §7or §e/m dp\n§d§l⚷ §eRequires a valid API key!
cowlection.config.dungPartyFinderPartyLookup=Lookup info when joining another party? §d§l⚷
cowlection.config.dungPartyFinderPartyLookup.tooltip=Lookup armor and dungeons stats of each party member when joining via party finder?\n§7Alternatively: §e/moo dungeon party §7or §e/m dp\n§d§l⚷ §eRequires a valid API key!
cowlection.config.dungPartiesSize=Show party sizes?
cowlection.config.dungPartiesSize.tooltip=Show sizes of parties?
cowlection.config.dungClassMin=Minimum preferred class level
cowlection.config.dungClassMin.tooltip=Marks parties with members with lower class level than this value
-cowlection.config.dungFilterPartiesWithCarry=Mark 'carry' parties?
-cowlection.config.dungFilterPartiesWithCarry.tooltip=Mark parties that have 'carry' in their notes?
+cowlection.config.dungMarkPartiesWithCarry=Mark 'carry' parties?
+cowlection.config.dungMarkPartiesWithCarry.tooltip=Mark parties that have 'carry' in their notes?
+cowlection.config.dungMarkPartiesWithHyperion=Mark 'hyperion' parties?
+cowlection.config.dungMarkPartiesWithHyperion.tooltip=Mark parties that have 'hyperion' in their notes?
cowlection.config.dungFilterPartiesWithArcherDupes=Mark duplicated Archer class?
cowlection.config.dungFilterPartiesWithArcherDupes.tooltip=Mark parties with duplicated Archer class?
cowlection.config.dungFilterPartiesWithBerserkDupes=Mark duplicated Berserk class?