aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md6
-rw-r--r--src/main/java/de/cowtipper/cowlection/config/MooConfig.java65
-rw-r--r--src/main/java/de/cowtipper/cowlection/data/HyPlayerData.java10
-rw-r--r--src/main/java/de/cowtipper/cowlection/data/HySkyBlockStats.java9
-rw-r--r--src/main/java/de/cowtipper/cowlection/listener/ChatListener.java34
-rw-r--r--src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java114
-rw-r--r--src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsPartyListener.java51
-rw-r--r--src/main/java/de/cowtipper/cowlection/util/GuiHelper.java1
-rw-r--r--src/main/resources/assets/cowlection/lang/en_US.lang10
9 files changed, 241 insertions, 59 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6601a31..30a9330 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Improved 'being on SkyBlock' detection
- gave scoreboard more time to get detected
- also added config option to always (or never) enable SkyBlock event listeners
+- Dungeon Party Finder (overlay):
+ - Made party indicators clearer (current, suitable, unideal, unjoinable party)
+ - Show sizes of parties
+ - Mark parties with 'carry' in their notes
+ - Lookup info when joining another party via Dungeon Party Finder (disabled by default)
+ - Added active pet + found dungeon secrets 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 2adfcb7..f666181 100644
--- a/src/main/java/de/cowtipper/cowlection/config/MooConfig.java
+++ b/src/main/java/de/cowtipper/cowlection/config/MooConfig.java
@@ -85,13 +85,16 @@ public class MooConfig {
public static int dungOverlayPositionY;
public static int dungOverlayGuiScale;
public static boolean dungOverlayTextShadow;
- public static int dungClassMin;
- public static boolean dungFilterPartiesWithArcherDupes;
- public static boolean dungFilterPartiesWithBerserkDupes;
- public static boolean dungFilterPartiesWithHealerDupes;
- public static boolean dungFilterPartiesWithMageDupes;
- public static boolean dungFilterPartiesWithTankDupes;
private static String dungPartyFinderPlayerLookup;
+ public static boolean dungPartyFinderPartyLookup;
+ public static boolean dungPartiesSize;
+ public static int dungClassMin;
+ public static boolean dungFilterPartiesWithCarry;
+ private static boolean dungFilterPartiesWithArcherDupes;
+ private static boolean dungFilterPartiesWithBerserkDupes;
+ private static boolean dungFilterPartiesWithHealerDupes;
+ private static boolean dungFilterPartiesWithMageDupes;
+ private static boolean dungFilterPartiesWithTankDupes;
private static Configuration cfg = null;
private static final List<MooConfigCategory> configCategories = new ArrayList<>();
@@ -435,38 +438,52 @@ public class MooConfig {
"to make it easier to find the perfect party:",
"",
"Marks parties...",
- " ‣ you cannot join: " + EnumChatFormatting.RED + "⬛" + EnumChatFormatting.RESET + " (red carpet)",
- " ‣ with someone below a certain class level: " + EnumChatFormatting.RED + EnumChatFormatting.BOLD + "ᐯ" + EnumChatFormatting.RESET,
- " ‣ with duplicated roles you specify below: " + EnumChatFormatting.GOLD + "²⁺",
- " ‣ that match your criteria: " + EnumChatFormatting.GREEN + "⬛" + EnumChatFormatting.RESET + " (green carpet)");
+ " ‣ you cannot join: " + EnumChatFormatting.RED + "⬛",
+ " ‣ 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 propDungPartyFinderPartyLookup = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
+ "dungPartyFinderPartyLookup", false, "Lookup info when joining another party?"));
+
+ Property propDungPartiesSize = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
+ "dungPartiesSize", true, "Show size of parties?"),
+ new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.WHITE + "1 - 4").gray()));
Property propDungClassMin = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
"dungClassMin", 0, "Marks parties with members with lower class level than this value")
.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"),
+ new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.AQUA + "carry"
+ + EnumChatFormatting.GRAY + " or " + EnumChatFormatting.GREEN + "carry " + EnumChatFormatting.GRAY + "('free' carries)").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 + "²⁺A").gray()));
+ new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.GOLD + "²⁺" + EnumChatFormatting.YELLOW + "A").gray()));
Property propDungFilterPartiesWithBerserkDupes = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
"dungFilterPartiesWithBerserkDupes", false, "Mark parties with duplicated Berserk class?"),
- new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.GOLD + "²⁺B").gray()));
+ new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.GOLD + "²⁺" + EnumChatFormatting.YELLOW + "B").gray()));
Property propDungFilterPartiesWithHealerDupes = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
"dungFilterPartiesWithHealerDupes", false, "Mark parties with duplicated Healer class?"),
- new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.GOLD + "²⁺H").gray()));
+ new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.GOLD + "²⁺" + EnumChatFormatting.YELLOW + "H").gray()));
Property propDungFilterPartiesWithMageDupes = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
"dungFilterPartiesWithMageDupes", false, "Mark parties with duplicated Mage class?"),
- new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.GOLD + "²⁺M").gray()));
+ new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.GOLD + "²⁺" + EnumChatFormatting.YELLOW + "M").gray()));
Property propDungFilterPartiesWithTankDupes = subCat.addConfigEntry(cfg.get(configCat.getConfigName(),
"dungFilterPartiesWithTankDupes", false, "Mark parties with duplicated Tank class?"),
- new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.GOLD + "²⁺T").gray()));
-
- 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"}));
+ new MooConfigPreview(new MooChatComponent("Marked with: " + EnumChatFormatting.GOLD + "²⁺" + EnumChatFormatting.YELLOW + "T").gray()));
boolean modifiedMooCmdAlias = false;
String mooCmdAliasPreChange = mooCmdAlias;
@@ -510,13 +527,16 @@ public class MooConfig {
dungOverlayPositionY = propDungOverlayPositionY.getInt();
dungOverlayGuiScale = propDungOverlayGuiScale.getInt();
dungOverlayTextShadow = propDungOverlayTextShadow.getBoolean();
+ dungPartyFinderPlayerLookup = propDungPartyFinderPlayerLookup.getString();
+ dungPartyFinderPartyLookup = propDungPartyFinderPartyLookup.getBoolean();
+ dungPartiesSize = propDungPartiesSize.getBoolean();
dungClassMin = propDungClassMin.getInt();
+ dungFilterPartiesWithCarry = propDungFilterPartiesWithCarry.getBoolean();
dungFilterPartiesWithArcherDupes = propDungFilterPartiesWithArcherDupes.getBoolean();
dungFilterPartiesWithBerserkDupes = propDungFilterPartiesWithBerserkDupes.getBoolean();
dungFilterPartiesWithHealerDupes = propDungFilterPartiesWithHealerDupes.getBoolean();
dungFilterPartiesWithMageDupes = propDungFilterPartiesWithMageDupes.getBoolean();
dungFilterPartiesWithTankDupes = propDungFilterPartiesWithTankDupes.getBoolean();
- dungPartyFinderPlayerLookup = propDungPartyFinderPlayerLookup.getString();
if (!StringUtils.equals(mooCmdAliasPreChange, mooCmdAlias)) {
@@ -564,13 +584,16 @@ public class MooConfig {
propDungOverlayPositionY.set(dungOverlayPositionY);
propDungOverlayGuiScale.set(dungOverlayGuiScale);
propDungOverlayTextShadow.set(dungOverlayTextShadow);
+ propDungPartyFinderPlayerLookup.set(dungPartyFinderPlayerLookup);
+ propDungPartyFinderPartyLookup.set(dungPartyFinderPartyLookup);
+ propDungPartiesSize.set(dungPartiesSize);
propDungClassMin.set(dungClassMin);
+ propDungFilterPartiesWithCarry.set(dungFilterPartiesWithCarry);
propDungFilterPartiesWithArcherDupes.set(dungFilterPartiesWithArcherDupes);
propDungFilterPartiesWithBerserkDupes.set(dungFilterPartiesWithBerserkDupes);
propDungFilterPartiesWithHealerDupes.set(dungFilterPartiesWithHealerDupes);
propDungFilterPartiesWithMageDupes.set(dungFilterPartiesWithMageDupes);
propDungFilterPartiesWithTankDupes.set(dungFilterPartiesWithTankDupes);
- propDungPartyFinderPlayerLookup.set(dungPartyFinderPlayerLookup);
if (saveToFile && cfg.hasChanged()) {
boolean isPlayerIngame = Minecraft.getMinecraft().thePlayer != null;
@@ -695,9 +718,11 @@ public class MooConfig {
public static boolean isTooltipToggleKeyBindingPressed() {
return tooltipToggleKeyBinding > 0 && Keyboard.isKeyDown(tooltipToggleKeyBinding);
}
+
public static boolean isLookupWikiKeyBindingPressed() {
return lookupWikiKeyBinding > 0 && Keyboard.isKeyDown(lookupWikiKeyBinding);
}
+
public static boolean isLookupPriceKeyBindingPressed() {
return lookupPriceKeyBinding > 0 && Keyboard.isKeyDown(lookupPriceKeyBinding);
}
diff --git a/src/main/java/de/cowtipper/cowlection/data/HyPlayerData.java b/src/main/java/de/cowtipper/cowlection/data/HyPlayerData.java
index 96c3325..5a7c168 100644
--- a/src/main/java/de/cowtipper/cowlection/data/HyPlayerData.java
+++ b/src/main/java/de/cowtipper/cowlection/data/HyPlayerData.java
@@ -2,6 +2,8 @@ package de.cowtipper.cowlection.data;
import net.minecraft.util.EnumChatFormatting;
+import java.util.Map;
+
@SuppressWarnings("unused")
public class HyPlayerData {
private String displayname;
@@ -14,6 +16,7 @@ public class HyPlayerData {
private long lastLogin;
private long lastLogout;
private String mostRecentGameType;
+ private Map<String, Integer> achievements;
/**
* No-args constructor for GSON
@@ -41,6 +44,13 @@ public class HyPlayerData {
return DataHelper.GameType.getFancyName(mostRecentGameType);
}
+ public int getAchievement(String achievementName) {
+ if (achievements != null) {
+ return achievements.getOrDefault(achievementName, 0);
+ }
+ return 0;
+ }
+
public boolean hasNeverJoinedHypixel() {
// example player that has never joined Hypixel (as of April 2020): Joe
return rank == null && lastLogin == 0;
diff --git a/src/main/java/de/cowtipper/cowlection/data/HySkyBlockStats.java b/src/main/java/de/cowtipper/cowlection/data/HySkyBlockStats.java
index 7ebd894..242c0c3 100644
--- a/src/main/java/de/cowtipper/cowlection/data/HySkyBlockStats.java
+++ b/src/main/java/de/cowtipper/cowlection/data/HySkyBlockStats.java
@@ -200,6 +200,15 @@ public class HySkyBlockStats {
return pets;
}
+ public Pet getActivePet() {
+ for (Pet pet : pets) {
+ if (pet.isActive()) {
+ return pet;
+ }
+ }
+ return null;
+ }
+
public List<String> getArmor() {
NBTTagCompound nbt = inv_armor.getDecodedData();
List<String> armorList = new ArrayList<>();
diff --git a/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java b/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java
index 0f61bb2..43f49fe 100644
--- a/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java
+++ b/src/main/java/de/cowtipper/cowlection/listener/ChatListener.java
@@ -1,6 +1,7 @@
package de.cowtipper.cowlection.listener;
import de.cowtipper.cowlection.Cowlection;
+import de.cowtipper.cowlection.config.CredentialStorage;
import de.cowtipper.cowlection.config.MooConfig;
import de.cowtipper.cowlection.data.Friend;
import de.cowtipper.cowlection.data.HySkyBlockStats;
@@ -175,7 +176,9 @@ public class ChatListener {
messageSender = partyOrGameInviteMatcher.group(1);
} else if (dungeonPartyFinderJoinedMatcher.find()) {
messageSender = dungeonPartyFinderJoinedMatcher.group(1);
- if (MooConfig.getDungPartyFinderPlayerLookupDisplay() != MooConfig.Setting.DISABLED && !messageSender.equals(Minecraft.getMinecraft().thePlayer.getName())) {
+ if (CredentialStorage.isMooValid && !messageSender.equals(Minecraft.getMinecraft().thePlayer.getName())
+ && MooConfig.getDungPartyFinderPlayerLookupDisplay() != MooConfig.Setting.DISABLED) {
+ // another player joined via Dungeon Party Finder
String dungeonClass = dungeonPartyFinderJoinedMatcher.group(2) + " Lvl " + dungeonPartyFinderJoinedMatcher.group(3);
getDungeonPartyMemberDetails(messageSender, dungeonClass);
}
@@ -200,29 +203,48 @@ public class ChatListener {
boolean outputAsChatMessages = MooConfig.getDungPartyFinderPlayerLookupDisplay() == MooConfig.Setting.TEXT;
HySkyBlockStats.Profile.Member member = activeProfile.getMember(stalkedPlayer.getUuid());
- MooChatComponent armorLookupComponent;
String armorLookupPrefix = " ❈ " + EnumChatFormatting.DARK_GREEN + playerName;
String delimiter = "\n" + (outputAsChatMessages ? " " : "");
String armorLookupResult = EnumChatFormatting.LIGHT_PURPLE + " ➜ " + EnumChatFormatting.GRAY + dungeonClass + 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;
if (outputAsChatMessages) {
// highest floor completions:
if (dungeons != null && dungeons.hasPlayed()) {
highestFloorCompletions = dungeons.getHighestFloorCompletions(1, true).toString();
}
- armorLookupComponent = new MooChatComponent(armorLookupPrefix + armorLookupResult + highestFloorCompletions).green();
+ skyBlockDetails = armorLookupPrefix + armorLookupResult + petInfo + highestFloorCompletions;
} else {
// as a tooltip: == MooConfig.Setting.TOOLTIP
if (dungeons != null && dungeons.hasPlayed()) {
// highest floor completions:
highestFloorCompletions = dungeons.getHighestFloorCompletions(3, false).toString();
}
- armorLookupComponent = new MooChatComponent(armorLookupPrefix + EnumChatFormatting.GREEN + (playerName.endsWith("s") ? "'" : "'s") + " dungeons info (hover me)").green()
- .setHover(new MooChatComponent(EnumChatFormatting.BOLD + playerName + armorLookupResult + highestFloorCompletions));
+ skyBlockDetails = EnumChatFormatting.BOLD + playerName + armorLookupResult + petInfo + highestFloorCompletions;
}
- main.getChatHelper().sendMessage(armorLookupComponent.setSuggestCommand("/p kick " + playerName, outputAsChatMessages));
+
+ ApiUtils.fetchHyPlayerDetails(stalkedPlayer, hyPlayerData -> {
+ String foundDungeonsSecrets = "";
+ if (hyPlayerData != null) {
+ foundDungeonsSecrets = "\n" + (outputAsChatMessages ? " " : "") + EnumChatFormatting.GRAY + "Found secrets: " + EnumChatFormatting.GOLD + hyPlayerData.getAchievement("skyblock_treasure_hunter");
+ }
+
+ MooChatComponent armorLookupComponent;
+ if (outputAsChatMessages) {
+ armorLookupComponent = new MooChatComponent(skyBlockDetails + foundDungeonsSecrets).green();
+ } else {
+ armorLookupComponent = new MooChatComponent(armorLookupPrefix + EnumChatFormatting.GREEN + (playerName.endsWith("s") ? "'" : "'s") + " dungeons info (hover me)").green()
+ .setHover(new MooChatComponent(skyBlockDetails + foundDungeonsSecrets));
+ }
+ main.getChatHelper().sendMessage(armorLookupComponent.setSuggestCommand("/p kick " + playerName, outputAsChatMessages));
+ });
}
});
}
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 ba48367..918c63d 100644
--- a/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java
+++ b/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java
@@ -2,6 +2,7 @@ package de.cowtipper.cowlection.listener.skyblock;
import com.mojang.realmsclient.util.Pair;
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.DungeonClass;
@@ -12,15 +13,13 @@ import de.cowtipper.cowlection.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SoundCategory;
import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.renderer.RenderHelper;
-import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
-import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.ItemSkull;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
@@ -50,7 +49,7 @@ public class DungeonsListener {
/**
* example: (space)Robin_Hood: Archer (42)
*/
- private final Pattern DUNGEON_PARTY_FINDER_PLAYER = Pattern.compile("^ (?:\\w+): ([A-Za-z]+) \\((\\d+)\\)$");
+ private final Pattern DUNGEON_PARTY_FINDER_PLAYER = Pattern.compile("^ (\\w+): ([A-Za-z]+) \\((\\d+)\\)$");
/**
* examples: "Floor: Entrance", "Floor: Floor 4", "Floor: Floor IV"
*/
@@ -284,7 +283,7 @@ public class DungeonsListener {
// not a player skull, don't draw party status indicator
return;
}
- ItemStack indicatorItem = null;
+ PartyType partyType = PartyType.NONE;
List<String> itemTooltip = item.getTooltip(Minecraft.getMinecraft().thePlayer, false);
if (itemTooltip.size() < 5) {
@@ -296,35 +295,58 @@ public class DungeonsListener {
|| lastToolTipLine.startsWith("Requires a Class at Level")
|| lastToolTipLine.startsWith("Requires Catacombs Level")) {
// cannot enter dungeon
- indicatorItem = new ItemStack(Blocks.carpet, 1, EnumDyeColor.RED.getMetadata());
+ partyType = PartyType.UNJOINABLE;
} else if (lastToolTipLine.endsWith("You are in this party!")) {
- indicatorItem = new ItemStack(Items.leather, 1);
+ partyType = PartyType.CURRENT;
} else {
Map<DungeonClass, AtomicInteger> dungClassesInParty = new LinkedHashMap<>();
AtomicInteger classCounter = new AtomicInteger();
classCounter.incrementAndGet();
dungClassesInParty.put(activeDungeonClass, classCounter); // add our own class
+ int partySize = 5;
+ String isCarry = null;
boolean memberTooLowLevel = false;
for (String toolTipLine : itemTooltip) {
- Matcher playerDetailMatcher = DUNGEON_PARTY_FINDER_PLAYER.matcher(EnumChatFormatting.getTextWithoutFormattingCodes(toolTipLine));
+ String toolTipLineWithoutFormatting = EnumChatFormatting.getTextWithoutFormattingCodes(toolTipLine);
+ Matcher playerDetailMatcher = DUNGEON_PARTY_FINDER_PLAYER.matcher(toolTipLineWithoutFormatting);
if (playerDetailMatcher.matches()) {
- String className = playerDetailMatcher.group(1);
+ String className = playerDetailMatcher.group(2);
DungeonClass clazz = DungeonClass.get(className);
dungClassesInParty.putIfAbsent(clazz, new AtomicInteger(0));
dungClassesInParty.get(clazz).incrementAndGet();
- int classLevel = MathHelper.parseIntWithDefault(playerDetailMatcher.group(2), 100);
+ int classLevel = MathHelper.parseIntWithDefault(playerDetailMatcher.group(3), 100);
if (classLevel < MooConfig.dungClassMin) {
memberTooLowLevel = true;
}
+ } else if (" Empty".equals(toolTipLineWithoutFormatting)) {
+ --partySize;
+ } else if (MooConfig.dungFilterPartiesWithCarry && toolTipLineWithoutFormatting.startsWith("Note: ")) {
+ String partyNote = toolTipLineWithoutFormatting.toLowerCase();
+ if (partyNote.contains("carry") || partyNote.contains("carries")) {
+ partyType = PartyType.UNIDEAL;
+ isCarry = partyNote.contains("free") ? "free" : "paid";
+ }
}
}
+ FontRenderer font = Minecraft.getMinecraft().fontRendererObj;
+ if (MooConfig.dungFilterPartiesWithCarry && isCarry != 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);
+ 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);
- Minecraft.getMinecraft().fontRendererObj.drawStringWithShadow(EnumChatFormatting.BOLD + "ᐯ", x + 1, y + 8, new Color(220, 20, 20, 255).getRGB());
+ font.drawStringWithShadow(EnumChatFormatting.BOLD + "ᐯ", x + 1, y + 8, new Color(220, 20, 20, 255).getRGB());
GlStateManager.popMatrix();
}
StringBuilder dupedClasses = new StringBuilder();
@@ -334,25 +356,35 @@ public class DungeonsListener {
}
}
if (dupedClasses.length() > 0) {
- dupedClasses.insert(0, EnumChatFormatting.RED).insert(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);
- Minecraft.getMinecraft().fontRendererObj.drawStringWithShadow(dupedClasses.toString(), (float) (x / scaleFactor), (float) (y / scaleFactor), new Color(255, 170, 0, 255).getRGB());
+ font.drawStringWithShadow(dupedClasses.toString(), (float) (x / scaleFactor), (float) (y / scaleFactor), new Color(255, 170, 0, 255).getRGB());
GlStateManager.popMatrix();
- } else if (!memberTooLowLevel) {
+ } else if (!memberTooLowLevel && isCarry == null) {
// party matches our criteria!
- indicatorItem = new ItemStack(Blocks.carpet, 1, EnumDyeColor.LIME.getMetadata());
+ 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 (indicatorItem != null) {
- GlStateManager.enableRescaleNormal();
- RenderHelper.enableGUIStandardItemLighting();
- Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(indicatorItem, x, y);
- RenderHelper.disableStandardItemLighting();
- GlStateManager.disableRescaleNormal();
+ if (partyType != PartyType.CURRENT
+ || (/*partyType == PartyType.CURRENT &&*/ Minecraft.getSystemTime() % 1000 < 600)) {
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, partyType.getZIndex());
+ Gui.drawRect(x, y, x + 16, y + 16, partyType.getColor());
+ GlStateManager.popMatrix();
}
}
@@ -454,11 +486,25 @@ public class DungeonsListener {
if (hoveredSlot != null && hoveredSlot.getHasStack()) {
// clicked on an item
List<String> itemToolTip = hoveredSlot.getStack().getTooltip(Minecraft.getMinecraft().thePlayer, false);
- if (itemToolTip.size() < 5) {
+ if (itemToolTip.size() < 5 || hoveredSlot.getStack().getItem() != Items.skull) {
// not a valid dungeon party tooltip
return;
}
extractQueuedFloorNr(itemToolTip, DUNGEON_PARTY_FINDER_FLOOR);
+
+ if (CredentialStorage.isMooValid && MooConfig.dungPartyFinderPartyLookup) {
+ List<String> partyMembers = new ArrayList<>();
+ for (String toolTipLine : itemToolTip) {
+ String toolTipLineWithoutFormatting = EnumChatFormatting.getTextWithoutFormattingCodes(toolTipLine);
+ Matcher playerDetailMatcher = DUNGEON_PARTY_FINDER_PLAYER.matcher(toolTipLineWithoutFormatting);
+ if (playerDetailMatcher.matches()) {
+ partyMembers.add(playerDetailMatcher.group(1));
+ }
+ }
+ if (partyMembers.size() > 0) {
+ new DungeonsPartyListener(main, partyMembers);
+ }
+ }
}
} else if (inventory.getName().equals("Group Builder")) {
// get dungeon floor nr when creating a dungeon party for party finder
@@ -582,4 +628,28 @@ 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 ed6906a..775634d 100644
--- a/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsPartyListener.java
+++ b/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsPartyListener.java
@@ -8,12 +8,14 @@ import de.cowtipper.cowlection.data.HySkyBlockStats;
import de.cowtipper.cowlection.util.ApiUtils;
import de.cowtipper.cowlection.util.MooChatComponent;
import de.cowtipper.cowlection.util.Utils;
+import net.minecraft.client.Minecraft;
import net.minecraft.util.EnumChatFormatting;
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;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
@@ -34,15 +36,28 @@ public class DungeonsPartyListener {
private final AtomicInteger pendingApiRequests = new AtomicInteger();
private final ConcurrentHashMap<String, Optional<UUID>> partyMembers = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, HySkyBlockStats> partyMemberStats = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap<String, Integer> partyMemberFoundDungeonSecrets = new ConcurrentHashMap<>();
public DungeonsPartyListener(Cowlection main) {
if (nextStep == Step.STOP) { // prevent double-registration of this listener
nextStep = Step.START;
this.main = main;
+ // get party members by parsing output of /party list:
MinecraftForge.EVENT_BUS.register(this);
}
}
+ public DungeonsPartyListener(Cowlection main, List<String> partyMembers) {
+ if (nextStep == Step.STOP) { // prevent double-registration of this listener
+ this.main = main;
+ nextStep = Step.AWAITING_API_RESPONSE;
+ for (String partyMember : partyMembers) {
+ this.partyMembers.put(partyMember, Optional.empty());
+ }
+ getDungeonPartyStats();
+ }
+ }
+
// priority = highest to ignore other mods modifying the chat output
@SubscribeEvent(priority = EventPriority.HIGHEST, receiveCanceled = true)
public void onMessageReceived(ClientChatReceivedEvent e) {
@@ -130,16 +145,28 @@ public class DungeonsPartyListener {
private void getDungeonPartyStats() {
for (String partyMemberName : partyMembers.keySet()) {
pendingApiRequests.incrementAndGet();
+ pendingApiRequests.incrementAndGet();
ApiUtils.fetchFriendData(partyMemberName, partyMember -> {
// (1) send Mojang API request to get uuid
if (partyMember != null && !partyMember.equals(Friend.FRIEND_NOT_FOUND)) {
partyMembers.put(partyMemberName, Optional.ofNullable(partyMember.getUuid()));
+
ApiUtils.fetchSkyBlockStats(partyMember, hySkyBlockStats -> {
// (2) once completed, request SkyBlock stats
- int apiRequestsLeft = pendingApiRequests.decrementAndGet();
partyMemberStats.put(partyMemberName, hySkyBlockStats);
- if (apiRequestsLeft == 0) {
+ if (pendingApiRequests.decrementAndGet() == 0) {
+ // (3) wait for all requests to finish
+ // (4) once completed extract relevant data
+ nextStep = Step.SEND_PARTY_STATS;
+ sendDungeonPartyStats();
+ }
+ });
+ ApiUtils.fetchHyPlayerDetails(partyMember, hyPlayerData -> {
+ // (2) once completed, request player stats
+ partyMemberFoundDungeonSecrets.put(partyMemberName, (hyPlayerData != null ? hyPlayerData.getAchievement("skyblock_treasure_hunter") : 0));
+
+ if (pendingApiRequests.decrementAndGet() == 0) {
// (3) wait for all requests to finish
// (4) once completed extract relevant data
nextStep = Step.SEND_PARTY_STATS;
@@ -149,23 +176,24 @@ public class DungeonsPartyListener {
} else {
// player not found (nicked?)
pendingApiRequests.decrementAndGet();
+ pendingApiRequests.decrementAndGet();
}
});
}
}
private void sendDungeonPartyStats() {
+ String thePlayerName = Minecraft.getMinecraft().thePlayer.getName();
MooChatComponent dungeonsParty = new MooChatComponent("Dungeons party").gold().bold();
StringBuilder playerEntry = new StringBuilder();
StringBuilder playerTooltip = new StringBuilder();
String partyMemberName = "";
for (Map.Entry<String, Optional<UUID>> partyMember : partyMembers.entrySet()) {
- partyMemberName = partyMember.getKey();
if (playerEntry.length() > 0) {
// append previous data
MooChatComponent dungeonPartyEntry = new MooChatComponent(playerEntry.toString())
- .setSuggestCommand("/p kick " + partyMemberName, false);
+ .setSuggestCommand((partyMemberName.equals(thePlayerName) ? "/boop " : "/p kick ") + partyMemberName, false);
if (playerTooltip.length() > 0) {
dungeonPartyEntry.setHover(new MooChatComponent(playerTooltip.toString()));
}
@@ -174,6 +202,7 @@ public class DungeonsPartyListener {
playerEntry.setLength(0);
playerTooltip.setLength(0);
}
+ partyMemberName = partyMember.getKey();
String errorNamePrefix = " " + EnumChatFormatting.RED + partyMemberName + EnumChatFormatting.LIGHT_PURPLE + " ➜ " + EnumChatFormatting.GRAY + EnumChatFormatting.ITALIC;
if (!partyMember.getValue().isPresent()) {
@@ -185,7 +214,6 @@ public class DungeonsPartyListener {
// player name:
playerEntry.append(" ").append(EnumChatFormatting.DARK_GREEN).append(partyMemberName).append(EnumChatFormatting.LIGHT_PURPLE).append(" ➜ ").append(EnumChatFormatting.GRAY);
-
HySkyBlockStats sbStats = partyMemberStats.get(partyMemberName);
if (sbStats != null && sbStats.isSuccess()) {
HySkyBlockStats.Profile activeProfile = sbStats.getActiveProfile(uuid);
@@ -199,9 +227,13 @@ public class DungeonsPartyListener {
// ^ abort if any of the above failed, otherwise visualize API data:
HySkyBlockStats.Profile.Member member = activeProfile.getMember(uuid);
- // append player name + class and class level + armor
+ // active pet:
+ HySkyBlockStats.Profile.Pet activePet = member.getActivePet();
+
+ // append player name + class and class level + armor + active pet
playerTooltip.append(EnumChatFormatting.WHITE).append(EnumChatFormatting.BOLD).append(partyMemberName).append(EnumChatFormatting.LIGHT_PURPLE).append(" ➜ ").append(EnumChatFormatting.GRAY).append(EnumChatFormatting.ITALIC).append("no class selected")
- .append("\n").append(String.join("\n", member.getArmor()));
+ .append("\n").append(String.join("\n", member.getArmor()))
+ .append("\n\n").append(EnumChatFormatting.GRAY).append("Active pet: ").append(activePet != null ? activePet.toFancyString() : "" + EnumChatFormatting.DARK_GRAY + EnumChatFormatting.ITALIC + "none");
HySkyBlockStats.Profile.Dungeons dungeons = member.getDungeons();
boolean hasNotPlayedDungeons = dungeons == null || !dungeons.hasPlayed();
@@ -221,13 +253,16 @@ public class DungeonsPartyListener {
// highest floor completions:
playerTooltip.append(dungeons.getHighestFloorCompletions(3, false));
+
+ // found dungeon secrets:
+ playerTooltip.append("\n").append(EnumChatFormatting.GRAY).append("Found secrets: ").append(EnumChatFormatting.GOLD).append(partyMemberFoundDungeonSecrets.getOrDefault(partyMemberName, 0));
} else {
playerEntry.setLength(0);
playerEntry.append(errorNamePrefix).append("API error").append(sbStats != null && sbStats.getCause() != null ? ": " + sbStats.getCause() : "");
}
}
MooChatComponent dungeonPartyEntry = new MooChatComponent(playerEntry.toString())
- .setSuggestCommand("/p kick " + partyMemberName, false);
+ .setSuggestCommand((partyMemberName.equals(thePlayerName) ? "/boop " : "/p kick ") + partyMemberName, false);
if (playerTooltip.length() > 0) {
dungeonPartyEntry.setHover(new MooChatComponent(playerTooltip.toString()));
}
diff --git a/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java b/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java
index 8ce23e5..decc579 100644
--- a/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java
+++ b/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java
@@ -5,7 +5,6 @@ import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
-import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
diff --git a/src/main/resources/assets/cowlection/lang/en_US.lang b/src/main/resources/assets/cowlection/lang/en_US.lang
index 0972533..fc8b2e0 100644
--- a/src/main/resources/assets/cowlection/lang/en_US.lang
+++ b/src/main/resources/assets/cowlection/lang/en_US.lang
@@ -70,8 +70,16 @@ cowlection.config.dungOverlayGuiScale=Overlay Gui Scale
cowlection.config.dungOverlayGuiScale.tooltip=Adjust the size of the dungeon performance overlay (50%%-200%%)
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.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.dungFilterPartiesWithArcherDupes=Mark duplicated Archer class?
cowlection.config.dungFilterPartiesWithArcherDupes.tooltip=Mark parties with duplicated Archer class?
cowlection.config.dungFilterPartiesWithBerserkDupes=Mark duplicated Berserk class?
@@ -82,8 +90,6 @@ cowlection.config.dungFilterPartiesWithMageDupes=Mark duplicated Mage class?
cowlection.config.dungFilterPartiesWithMageDupes.tooltip=Mark parties with duplicated Mage class?
cowlection.config.dungFilterPartiesWithTankDupes=Mark duplicated Tank class?
cowlection.config.dungFilterPartiesWithTankDupes.tooltip=Mark parties with duplicated Tank class?
-cowlection.config.dungPartyFinderPlayerLookup=Show armor + dungeons stats of joining player... §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.commands.generic.exception=%s
key.cowlection.category=Cowlection
key.cowlection.moo=Open Command