aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/cowtipper
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/cowtipper')
-rw-r--r--src/main/java/de/cowtipper/cowlection/command/MooCommand.java21
-rw-r--r--src/main/java/de/cowtipper/cowlection/config/DungeonOverlayGuiConfig.java129
-rw-r--r--src/main/java/de/cowtipper/cowlection/config/MooConfig.java21
-rw-r--r--src/main/java/de/cowtipper/cowlection/config/MooGuiConfig.java3
-rw-r--r--src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java131
-rw-r--r--src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java79
6 files changed, 356 insertions, 28 deletions
diff --git a/src/main/java/de/cowtipper/cowlection/command/MooCommand.java b/src/main/java/de/cowtipper/cowlection/command/MooCommand.java
index d47617a..91d1932 100644
--- a/src/main/java/de/cowtipper/cowlection/command/MooCommand.java
+++ b/src/main/java/de/cowtipper/cowlection/command/MooCommand.java
@@ -5,6 +5,7 @@ import de.cowtipper.cowlection.Cowlection;
import de.cowtipper.cowlection.command.exception.ApiContactException;
import de.cowtipper.cowlection.command.exception.InvalidPlayerNameException;
import de.cowtipper.cowlection.command.exception.MooCommandException;
+import de.cowtipper.cowlection.config.DungeonOverlayGuiConfig;
import de.cowtipper.cowlection.config.MooConfig;
import de.cowtipper.cowlection.config.MooGuiConfig;
import de.cowtipper.cowlection.data.*;
@@ -150,13 +151,19 @@ public class MooCommand extends CommandBase {
.append(EnumChatFormatting.RED).append("Unknown minion ").append(EnumChatFormatting.YELLOW).append("(new or with minion skin) ").append(tierColor).append(minionTier);
});
main.getChatHelper().sendMessage(EnumChatFormatting.YELLOW, analysisResults.toString());
- } else if (args[0].equalsIgnoreCase("deaths")) {
+ } else if (args[0].equalsIgnoreCase("dungeon") || args[0].equalsIgnoreCase("dung")) {
DungeonCache dungeonCache = main.getDungeonCache();
- if (dungeonCache.isInDungeon()) {
- dungeonCache.sendDeathCounts();
+ if (args.length == 2 && args[1].equalsIgnoreCase("gui")) {
+ // edit dungeon gui
+ new TickDelay(() -> Minecraft.getMinecraft().displayGuiScreen(new DungeonOverlayGuiConfig(main)), 1); // delay by 1 tick, because the chat closing would close the new gui instantly as well.
+ } else if (dungeonCache.isInDungeon()) {
+ dungeonCache.sendDungeonPerformance();
} else {
- throw new MooCommandException(EnumChatFormatting.DARK_RED + "Looks like you're not in a dungeon...");
+ throw new MooCommandException(EnumChatFormatting.DARK_RED + "Looks like you're not in a dungeon... However, you can edit the Dungeon Performance overlay with " + EnumChatFormatting.RED + "/" + getCommandName() + " dungeon gui");
}
+ } else if (args[0].equalsIgnoreCase("dungeonGui") || args[0].equalsIgnoreCase("guiDungeon")
+ || args[0].equalsIgnoreCase("guiDung") || args[0].equalsIgnoreCase("dungGui")) {
+ new TickDelay(() -> Minecraft.getMinecraft().displayGuiScreen(new DungeonOverlayGuiConfig(main)), 1); // delay by 1 tick, because the chat closing would close the new gui instantly as well.
} else if (args[0].equalsIgnoreCase("add")) {
handleBestFriendAdd(args);
} else if (args[0].equalsIgnoreCase("remove")) {
@@ -524,7 +531,6 @@ public class MooCommand extends CommandBase {
} else if (main.getFriendsHandler().getBestFriends().size() >= 100) {
throw new MooCommandException(EnumChatFormatting.RED + "The best friends list is limited to 100 players. Remove some with " + EnumChatFormatting.WHITE + "/" + getCommandName() + " remove <name> " + EnumChatFormatting.RED + "first");
} else {
- // TODO Add check if 'best friend' is on normal friend list
main.getChatHelper().sendMessage(EnumChatFormatting.GOLD, "Fetching " + EnumChatFormatting.YELLOW + args[1] + EnumChatFormatting.GOLD + "'s unique user id. This may take a few seconds...");
// add friend async
main.getFriendsHandler().addBestFriend(args[1]);
@@ -594,7 +600,8 @@ public class MooCommand extends CommandBase {
.appendSibling(createCmdHelpEntry("stalk", "Get info of player's status"))
.appendSibling(createCmdHelpEntry("stalkskyblock", "Get info of player's SkyBlock stats"))
.appendSibling(createCmdHelpEntry("analyzeIsland", "Analyze a SkyBlock private island"))
- .appendSibling(createCmdHelpEntry("deaths", "SkyBlock Dungeons: death counts"))
+ .appendSibling(createCmdHelpEntry("dungeon", "SkyBlock Dungeons: display current dungeon performance"))
+ .appendSibling(createCmdHelpEntry("dungeonGui", "SkyBlock Dungeons: edit dungeon performance GUI"))
.appendSibling(createCmdHelpEntry("add", "Add best friends"))
.appendSibling(createCmdHelpEntry("remove", "Remove best friends"))
.appendSibling(createCmdHelpEntry("list", "View list of best friends"))
@@ -635,7 +642,7 @@ public class MooCommand extends CommandBase {
public List<String> addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) {
if (args.length == 1) {
return getListOfStringsMatchingLastWord(args,
- /* friends & other players */ "stalk", "askPolitelyWhereTheyAre", "stalkskyblock", "skyblockstalk", "askPolitelyAboutTheirSkyBlockProgress", "analyzeIsland", "deaths", "add", "remove", "list", "online", "nameChangeCheck", "toggle",
+ /* friends & other players */ "stalk", "askPolitelyWhereTheyAre", "stalkskyblock", "skyblockstalk", "askPolitelyAboutTheirSkyBlockProgress", "analyzeIsland", "dungeon", "dungeonGui", "guiDungeon", "add", "remove", "list", "online", "nameChangeCheck", "toggle",
/* miscellaneous */ "config", "search", "guiscale", "rr", "shrug", "apikey",
/* update mod */ "update", "updateHelp", "version", "directory",
/* help */ "help");
diff --git a/src/main/java/de/cowtipper/cowlection/config/DungeonOverlayGuiConfig.java b/src/main/java/de/cowtipper/cowlection/config/DungeonOverlayGuiConfig.java
new file mode 100644
index 0000000..18478f5
--- /dev/null
+++ b/src/main/java/de/cowtipper/cowlection/config/DungeonOverlayGuiConfig.java
@@ -0,0 +1,129 @@
+package de.cowtipper.cowlection.config;
+
+import de.cowtipper.cowlection.Cowlection;
+import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.fml.client.config.GuiButtonExt;
+import net.minecraftforge.fml.client.config.GuiCheckBox;
+import net.minecraftforge.fml.client.config.GuiSlider;
+import org.apache.commons.lang3.StringUtils;
+import org.lwjgl.input.Keyboard;
+
+import java.io.IOException;
+
+public class DungeonOverlayGuiConfig extends GuiScreen {
+ private final Cowlection main;
+ private GuiCheckBox checkBoxShowOverlay;
+ private GuiSlider sliderX;
+ private GuiSlider sliderY;
+ private GuiSlider sliderGuiScale;
+ private GuiButtonExt buttonCancel;
+ private GuiButtonExt buttonSave;
+ private final boolean wasDungOverlayEnabled;
+ private final int previousPositionX;
+ private final int previousPositionY;
+ private final int previousGuiScale;
+
+ public DungeonOverlayGuiConfig(Cowlection main) {
+ this.main = main;
+ wasDungOverlayEnabled = MooConfig.dungOverlayEnabled;
+ previousPositionX = MooConfig.dungOverlayPositionX;
+ previousPositionY = MooConfig.dungOverlayPositionY;
+ previousGuiScale = MooConfig.dungOverlayGuiScale;
+ }
+
+ @Override
+ public void initGui() {
+ int maxX = this.width - fontRendererObj.getStringWidth(StringUtils.repeat('#', 15));
+ int maxY = this.height - fontRendererObj.FONT_HEIGHT * 5; // 5 = max lines output
+ int startX = Math.min(maxX, this.previousPositionX);
+ int startY = Math.min(maxY, this.previousPositionY);
+
+ this.buttonList.add(this.checkBoxShowOverlay = new GuiCheckBox(30, this.width / 2 - 50, this.height / 2 - 30, " Show overlay", MooConfig.dungOverlayEnabled));
+ this.buttonList.add(sliderX = new GuiSlider(20, this.width / 2 - 150, this.height / 2 - 12, 300, 20, "x = ", "", 0, maxX, startX, false, true));
+ this.buttonList.add(sliderY = new GuiSlider(21, this.width / 2 - 150, this.height / 2 + 12, 300, 20, "y = ", "", 0, maxY, startY, false, true));
+ this.buttonList.add(sliderGuiScale = new GuiSlider(22, this.width / 2 - 100, this.height / 2 + 37, 200, 20, "GUI scale: ", "%", 50, 200, MooConfig.dungOverlayGuiScale, false, true));
+ this.buttonList.add(this.buttonCancel = new GuiButtonExt(31, this.width / 2 - 150, this.height / 2 + 65, 80, 20, EnumChatFormatting.RED + "Cancel"));
+ this.buttonList.add(this.buttonSave = new GuiButtonExt(32, this.width / 2 + 70, this.height / 2 + 65, 80, 20, EnumChatFormatting.GREEN + "Save"));
+ if (!MooConfig.dungOverlayEnabled) {
+ sliderX.enabled = false;
+ sliderY.enabled = false;
+ sliderGuiScale.enabled = false;
+ }
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ // draw background
+ int padding = 20;
+ this.drawGradientRect(this.width / 2 - 150 - padding, this.height / 2 - 40 - fontRendererObj.FONT_HEIGHT - padding,
+ this.width / 2 + 150 + padding, this.height / 2 + 65 + 20 + fontRendererObj.FONT_HEIGHT + padding,
+ -1072689136, -804253680);
+
+ // draw gui elements
+ String title = "Dungeon Performance Overlay Settings";
+ this.drawCenteredString(this.fontRendererObj, EnumChatFormatting.BOLD + title, this.width / 2, this.height / 2 - 40 - fontRendererObj.FONT_HEIGHT, 0x00ffffff);
+
+ GlStateManager.pushMatrix();
+ float scaleFactor = 0.75f;
+ GlStateManager.scale(scaleFactor, scaleFactor, 0);
+ String hint = "(" + EnumChatFormatting.GOLD + EnumChatFormatting.ITALIC + "Note: " + EnumChatFormatting.RESET + "Destroyed Crypts can only be detected up to ~50 blocks away from the player)";
+ this.drawCenteredString(this.fontRendererObj, hint, (int) ((this.width / 2) * (1 / scaleFactor)), (int) ((this.height / 2 + 95) * (1 / scaleFactor)), 0x00cccccc);
+ GlStateManager.popMatrix();
+
+ super.drawScreen(mouseX, mouseY, partialTicks);
+
+ if (checkBoxShowOverlay.enabled) {
+ MooConfig.dungOverlayPositionX = sliderX.getValueInt();
+ MooConfig.dungOverlayPositionY = sliderY.getValueInt();
+ MooConfig.dungOverlayGuiScale = sliderGuiScale.getValueInt();
+ }
+ }
+
+ @Override
+ protected void keyTyped(char typedChar, int keyCode) throws IOException {
+ if (keyCode == Keyboard.KEY_ESCAPE) {
+ resetDungeonOverlayPosition();
+ }
+ super.keyTyped(typedChar, keyCode);
+ }
+
+ @Override
+ protected void actionPerformed(GuiButton button) throws IOException {
+ if (button == buttonCancel) {
+ resetDungeonOverlayPosition();
+ closeGui();
+ } else if (button == buttonSave) {
+ if (wasDungOverlayEnabled != checkBoxShowOverlay.isChecked() || previousPositionX != sliderX.getValueInt() || previousPositionY != sliderY.getValueInt() || previousGuiScale != sliderGuiScale.getValueInt()) {
+ main.getConfig().syncFromFields();
+ if (wasDungOverlayEnabled != checkBoxShowOverlay.isChecked()) {
+ main.getChatHelper().sendMessage(EnumChatFormatting.GREEN, "The dungeon performance overlay is now " + (checkBoxShowOverlay.isChecked() ? EnumChatFormatting.DARK_GREEN + "enabled" : EnumChatFormatting.DARK_RED + "disabled"));
+ } else {
+ main.getChatHelper().sendMessage(EnumChatFormatting.GREEN, "Saved new size and position of the dungeon performance overlay!");
+ }
+ }
+ closeGui();
+ } else if (button == checkBoxShowOverlay) {
+ sliderX.enabled = checkBoxShowOverlay.isChecked();
+ sliderY.enabled = checkBoxShowOverlay.isChecked();
+ sliderGuiScale.enabled = checkBoxShowOverlay.isChecked();
+ MooConfig.dungOverlayEnabled = checkBoxShowOverlay.isChecked();
+ }
+ }
+
+ private void resetDungeonOverlayPosition() {
+ MooConfig.dungOverlayEnabled = wasDungOverlayEnabled;
+ MooConfig.dungOverlayPositionX = previousPositionX;
+ MooConfig.dungOverlayPositionY = previousPositionY;
+ MooConfig.dungOverlayGuiScale = previousGuiScale;
+ }
+
+ private void closeGui() {
+ this.mc.displayGuiScreen(null);
+ if (this.mc.currentScreen == null) {
+ this.mc.setIngameFocus();
+ }
+ }
+}
diff --git a/src/main/java/de/cowtipper/cowlection/config/MooConfig.java b/src/main/java/de/cowtipper/cowlection/config/MooConfig.java
index 9cbe1b9..628850b 100644
--- a/src/main/java/de/cowtipper/cowlection/config/MooConfig.java
+++ b/src/main/java/de/cowtipper/cowlection/config/MooConfig.java
@@ -46,6 +46,10 @@ public class MooConfig {
public static int[] dungClassRange;
public static boolean dungFilterPartiesWithDupes;
public static String dungItemQualityPos;
+ public static boolean dungOverlayEnabled;
+ public static int dungOverlayGuiScale;
+ public static int dungOverlayPositionX;
+ public static int dungOverlayPositionY;
// logs search config
public static String[] logsDirs;
private static String defaultStartDate;
@@ -153,7 +157,14 @@ public class MooConfig {
"dungFilterPartiesWithDupes", false, "Mark parties with duplicated classes?"), true);
Property propDungItemQualityPos = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT,
"dungItemQualityPos", "top", "Position of item quality in tooltip", new String[]{"top", "bottom"}), true);
-
+ Property propDungOverlayEnabled = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT,
+ "dungOverlayEnabled", true, "Enable Dungeon performance overlay?"), false);
+ Property propDungOverlayPositionX = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT,
+ "dungGuiPositionX", 5, "Dungeon performance overlay position: x value", -1, 10000), false);
+ Property propDungOverlayPositionY = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT,
+ "dungGuiPositionY", 5, "Dungeon performance overlay position: y value", -1, 5000), false);
+ Property propDungOverlayGuiScale = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT,
+ "dungOverlayGuiScale", 100, "Dungeon performance overlay GUI scale", 50, 200), false);
cfg.setCategoryPropertyOrder(Configuration.CATEGORY_CLIENT, propOrderGeneral);
// config section: log files search
@@ -187,6 +198,10 @@ public class MooConfig {
dungClassRange = propDungClassRange.getIntList();
dungFilterPartiesWithDupes = propDungFilterPartiesWithDupes.getBoolean();
dungItemQualityPos = propDungItemQualityPos.getString();
+ dungOverlayEnabled = propDungOverlayEnabled.getBoolean();
+ dungOverlayPositionX = propDungOverlayPositionX.getInt();
+ dungOverlayPositionY = propDungOverlayPositionY.getInt();
+ dungOverlayGuiScale = propDungOverlayGuiScale.getInt();
// logs search config
logsDirs = propLogsDirs.getStringList();
@@ -212,6 +227,10 @@ public class MooConfig {
propDungClassRange.set(dungClassRange);
propDungFilterPartiesWithDupes.set(dungFilterPartiesWithDupes);
propDungItemQualityPos.set(dungItemQualityPos);
+ propDungOverlayEnabled.set(dungOverlayEnabled);
+ propDungOverlayPositionX.set(dungOverlayPositionX);
+ propDungOverlayPositionY.set(dungOverlayPositionY);
+ propDungOverlayGuiScale.set(dungOverlayGuiScale);
// logs search config
propLogsDirs.set(logsDirs);
diff --git a/src/main/java/de/cowtipper/cowlection/config/MooGuiConfig.java b/src/main/java/de/cowtipper/cowlection/config/MooGuiConfig.java
index 3c650b8..3db7cf3 100644
--- a/src/main/java/de/cowtipper/cowlection/config/MooGuiConfig.java
+++ b/src/main/java/de/cowtipper/cowlection/config/MooGuiConfig.java
@@ -2,7 +2,6 @@ package de.cowtipper.cowlection.config;
import de.cowtipper.cowlection.Cowlection;
import de.cowtipper.cowlection.search.GuiTooltip;
-import de.cowtipper.cowlection.util.Utils;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
@@ -31,7 +30,7 @@ public class MooGuiConfig extends GuiConfig {
false,
false,
EnumChatFormatting.BOLD + "Configuration for " + Cowlection.MODNAME);
- titleLine2 = EnumChatFormatting.GRAY + Utils.toRealPath(MooConfig.getConfig().getConfigFile());
+ titleLine2 = EnumChatFormatting.GRAY + GuiConfig.getAbridgedConfigPath(MooConfig.getConfig().toString());
}
private static List<IConfigElement> getConfigElements() {
diff --git a/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java b/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java
index 7cef4cd..5c868c9 100644
--- a/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java
+++ b/src/main/java/de/cowtipper/cowlection/handler/DungeonCache.java
@@ -2,51 +2,148 @@ package de.cowtipper.cowlection.handler;
import de.cowtipper.cowlection.Cowlection;
import de.cowtipper.cowlection.util.TickDelay;
+import net.minecraft.client.Minecraft;
+import net.minecraft.scoreboard.Score;
+import net.minecraft.scoreboard.ScoreObjective;
+import net.minecraft.scoreboard.ScorePlayerTeam;
+import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.util.EnumChatFormatting;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.*;
import java.util.stream.Collectors;
public class DungeonCache {
- private boolean isInDungeon;
- private final Map<String, Integer> deathCounter;
private final Cowlection main;
+ private final Map<String, Integer> deathCounter;
+ private final Set<String> failedPuzzles;
+ private final Set<UUID> destroyedCrypts;
+
+ private boolean isInDungeon;
+ private int elapsedMinutes;
+ private long lastScoreboardCheck;
public DungeonCache(Cowlection main) {
this.main = main;
deathCounter = new HashMap<>();
+ failedPuzzles = new HashSet<>();
+ destroyedCrypts = new HashSet<>();
+ }
+
+ public boolean isInDungeon() {
+ return isInDungeon;
}
public void onDungeonEntered() {
isInDungeon = true;
- deathCounter.clear();
+ resetCounters();
}
public void onDungeonLeft() {
isInDungeon = false;
- deathCounter.clear();
+ resetCounters();
+ }
+
+ public void sendDungeonPerformance() {
+ String dungeonPerformance;
+ boolean hasPointPenalty = false;
+ if (deathCounter.isEmpty()) {
+ dungeonPerformance = EnumChatFormatting.GOLD + "☠ Deaths: " + EnumChatFormatting.WHITE + "none \\o/";
+ } else {
+ hasPointPenalty = true;
+ String deaths = deathCounter.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(deathEntry -> " " + EnumChatFormatting.WHITE + deathEntry.getKey() + ": " + EnumChatFormatting.LIGHT_PURPLE + deathEntry.getValue())
+ .collect(Collectors.joining("\n"));
+ dungeonPerformance = EnumChatFormatting.RED + "☠ " + EnumChatFormatting.BOLD + "Deaths: " + EnumChatFormatting.DARK_RED + "-" + (getTotalDeaths() * 2) + " Skill points\n" + deaths;
+ }
+ if (failedPuzzles.size() > 0) {
+ hasPointPenalty = true;
+ dungeonPerformance += "\n" + EnumChatFormatting.RED + "Failed puzzles: " + EnumChatFormatting.LIGHT_PURPLE + failedPuzzles.size() + EnumChatFormatting.RED + " (" + EnumChatFormatting.DARK_RED + "-" + failedPuzzles.size() * 14 + " Skill points" + EnumChatFormatting.RED + ")";
+ }
+
+ if (hasPointPenalty) {
+ dungeonPerformance += "\n" + EnumChatFormatting.LIGHT_PURPLE + "➜ " + EnumChatFormatting.RED + EnumChatFormatting.BOLD + "Skill " + EnumChatFormatting.RED + "score penalty: " + EnumChatFormatting.DARK_RED + getSkillScorePenalty() + " points";
+ }
+ main.getChatHelper().sendMessage(EnumChatFormatting.WHITE, dungeonPerformance);
+ }
+
+ public void updateElapsedMinutesFromScoreboard() {
+ long now = System.currentTimeMillis();
+ if (now - lastScoreboardCheck > 10000) { // run every 10 seconds
+ lastScoreboardCheck = now;
+ Scoreboard scoreboard = Minecraft.getMinecraft().theWorld.getScoreboard();
+ ScoreObjective scoreboardSidebar = scoreboard.getObjectiveInDisplaySlot(1);
+ if (scoreboardSidebar != null) {
+ Collection<Score> scoreboardLines = scoreboard.getSortedScores(scoreboardSidebar);
+ for (Score line : scoreboardLines) {
+ ScorePlayerTeam scorePlayerTeam = scoreboard.getPlayersTeam(line.getPlayerName());
+ if (scorePlayerTeam != null) {
+ String lineWithoutFormatting = EnumChatFormatting.getTextWithoutFormattingCodes(scorePlayerTeam.getColorPrefix() + scorePlayerTeam.getColorSuffix());
+
+ if (lineWithoutFormatting.startsWith("Time Elapsed:")) {
+ // dungeon timer: 05m22s
+ String timeString = lineWithoutFormatting.substring(lineWithoutFormatting.lastIndexOf(' ') + 1);
+ try {
+ elapsedMinutes = (Integer.parseInt(timeString.substring(0, timeString.indexOf('m'))));
+ } catch (NumberFormatException ex) {
+ // couldn't parse dungeon time from scoreboard
+ ex.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ }
}
+ // setter/adder
public void addDeath(String playerName) {
int previousPlayerDeaths = deathCounter.getOrDefault(playerName, 0);
deathCounter.put(playerName, previousPlayerDeaths + 1);
- new TickDelay(this::sendDeathCounts, 1);
+ new TickDelay(this::sendDungeonPerformance, 1);
}
- public boolean isInDungeon() {
- return isInDungeon;
+ public void addFailedPuzzle(String text) {
+ failedPuzzles.add(text);
}
- public void sendDeathCounts() {
- if (deathCounter.isEmpty()) {
- main.getChatHelper().sendMessage(EnumChatFormatting.GOLD, "☠ Deaths: " + EnumChatFormatting.WHITE + "none \\o/");
- } else {
- String deaths = deathCounter.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(deathEntry -> " " + EnumChatFormatting.WHITE + deathEntry.getKey() + ": " + EnumChatFormatting.LIGHT_PURPLE + deathEntry.getValue())
- .collect(Collectors.joining("\n"));
- main.getChatHelper().sendMessage(EnumChatFormatting.RED, "☠ " + EnumChatFormatting.BOLD + "Deaths:\n" + deaths);
+ public boolean addDestroyedCrypt(UUID uuid) {
+ return destroyedCrypts.add(uuid);
+ }
+
+ // getter
+ public int getMaxSkillScore() {
+ return 100 - getSkillScorePenalty();
+ }
+
+ private int getSkillScorePenalty() {
+ return getTotalDeaths() * 2 + failedPuzzles.size() * 14;
+ }
+
+ public int getTotalDeaths() {
+ int totalDeaths = 0;
+ for (int deathCount : deathCounter.values()) {
+ totalDeaths += deathCount;
}
+ return totalDeaths;
+ }
+
+ public int getFailedPuzzles() {
+ return failedPuzzles.size();
+ }
+
+ public int getDestroyedCrypts() {
+ return destroyedCrypts.size();
+ }
+
+ public int getElapsedMinutes() {
+ return elapsedMinutes;
+ }
+
+ // resetter
+ private void resetCounters() {
+ deathCounter.clear();
+ failedPuzzles.clear();
+ destroyedCrypts.clear();
+ elapsedMinutes = 0;
}
}
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 02d221e..8ba2354 100644
--- a/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java
+++ b/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java
@@ -1,9 +1,12 @@
package de.cowtipper.cowlection.listener.skyblock;
import de.cowtipper.cowlection.Cowlection;
+import de.cowtipper.cowlection.config.DungeonOverlayGuiConfig;
import de.cowtipper.cowlection.config.MooConfig;
+import de.cowtipper.cowlection.handler.DungeonCache;
import de.cowtipper.cowlection.util.TickDelay;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.inventory.Container;
@@ -20,11 +23,14 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.MathHelper;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.client.event.GuiScreenEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.event.entity.player.PlayerSetSpawnEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import net.minecraftforge.fml.relauncher.Side;
import org.apache.commons.lang3.StringUtils;
import org.lwjgl.input.Keyboard;
@@ -363,6 +369,7 @@ public class DungeonsListener {
String lineWithoutFormatting = EnumChatFormatting.getTextWithoutFormattingCodes(scorePlayerTeam.getColorPrefix() + scorePlayerTeam.getColorSuffix());
if (lineWithoutFormatting.startsWith(" ⏣")) {
+ // current location: dungeon or outside?
boolean isInDungeonNow = lineWithoutFormatting.startsWith(" ⏣ The Catacombs");
if (!wasInDungeon && isInDungeonNow) {
@@ -392,7 +399,77 @@ public class DungeonsListener {
main.getDungeonCache().addDeath(playerName);
} else if (text.trim().equals("> EXTRA STATS <")) {
// dungeon "end screen"
- new TickDelay(() -> main.getDungeonCache().sendDeathCounts(), 5);
+ new TickDelay(() -> main.getDungeonCache().sendDungeonPerformance(), 5);
+ } else if (text.startsWith("PUZZLE FAIL!")) {
+ // Skill: failed puzzle
+ main.getDungeonCache().addFailedPuzzle(text);
+ }
+ }
+ }
+
+
+ @SubscribeEvent
+ public void onPlayerTick(TickEvent.PlayerTickEvent e) {
+ if (e.phase != TickEvent.Phase.END && e.side != Side.CLIENT && e.type != TickEvent.Type.PLAYER) {
+ return;
+ }
+ if ("Crypt Undead".equals(e.player.getName())) {
+ boolean isNewDestroyedCrypt = main.getDungeonCache().addDestroyedCrypt(e.player.getUniqueID());
+ if (isNewDestroyedCrypt) {
+ main.getLogger().info("[Dungeon Bonus Score] Crypt Undead spawned @ " + e.player.getPosition() + " - distance to player: " + Math.sqrt(e.player.getPosition().distanceSq(Minecraft.getMinecraft().thePlayer.getPosition())));
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderGameOverlay(RenderGameOverlayEvent.Post e) {
+ if (e.type == RenderGameOverlayEvent.ElementType.EXPERIENCE) {
+ DungeonCache dungeonCache = main.getDungeonCache();
+
+ if (dungeonCache.isInDungeon()) {
+ dungeonCache.updateElapsedMinutesFromScoreboard();
+ }
+
+ boolean isConfigGui = Minecraft.getMinecraft().currentScreen instanceof DungeonOverlayGuiConfig;
+ if (MooConfig.dungOverlayEnabled && dungeonCache.isInDungeon() || isConfigGui) {
+ ArrayList<String> dungeonPerformanceEntries = new ArrayList<>();
+ int maxSkillScore = dungeonCache.getMaxSkillScore();
+ int totalDeaths = dungeonCache.getTotalDeaths();
+ int failedPuzzles = dungeonCache.getFailedPuzzles();
+ int destroyedCrypts = dungeonCache.getDestroyedCrypts();
+ int elapsedMinutes = dungeonCache.getElapsedMinutes();
+
+ dungeonPerformanceEntries.add("Max Skill score: " + (maxSkillScore == 100 ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) + maxSkillScore + " / 100");
+ if (totalDeaths > 0 || isConfigGui) {
+ dungeonPerformanceEntries.add(" Deaths: " + EnumChatFormatting.RED + totalDeaths);
+ }
+ if (failedPuzzles > 0 || isConfigGui) {
+ dungeonPerformanceEntries.add(" Failed Puzzles: " + EnumChatFormatting.RED + failedPuzzles);
+ }
+ dungeonPerformanceEntries.add("Destroyed Crypts: " + (destroyedCrypts >= 5 ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) + destroyedCrypts + " / 5");
+ EnumChatFormatting color = EnumChatFormatting.GREEN;
+ if (elapsedMinutes > 20) {
+ color = EnumChatFormatting.DARK_RED;
+ } else if (elapsedMinutes > 18) {
+ color = EnumChatFormatting.RED;
+ } else if (elapsedMinutes > 15) {
+ color = EnumChatFormatting.YELLOW;
+ }
+ dungeonPerformanceEntries.add("Elapsed Minutes: " + color + elapsedMinutes + (elapsedMinutes > 15 && elapsedMinutes <= 20 ? EnumChatFormatting.RED + " (> 20 mins = point penalty)" : ""));
+ if (elapsedMinutes > 20) {
+ dungeonPerformanceEntries.add(EnumChatFormatting.GOLD + " Time penalty: " + EnumChatFormatting.RED + ((int) (2.2 * (elapsedMinutes - 20))) + " points");
+ }
+
+ FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
+ GlStateManager.pushMatrix();
+ float scaleFactor = MooConfig.dungOverlayGuiScale / 100f;
+ GlStateManager.scale(scaleFactor, scaleFactor, 0);
+ for (int line = 0; line < dungeonPerformanceEntries.size(); line++) {
+ String dungeonPerformanceEntry = dungeonPerformanceEntries.get(line);
+ int yPos = MooConfig.dungOverlayPositionY + fontRenderer.FONT_HEIGHT * line + 2;
+ fontRenderer.drawString(dungeonPerformanceEntry, MooConfig.dungOverlayPositionX, yPos, 0xffFFAA00);
+ }
+ GlStateManager.popMatrix();
}
}
}