aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorRime <81419447+Emirlol@users.noreply.github.com>2024-08-13 22:09:51 +0300
committerRime <81419447+Emirlol@users.noreply.github.com>2024-08-13 22:09:51 +0300
commit37136d199a74d2dff5c27632170c7a3a5a2944e4 (patch)
tree1852d48bdb92d4878654fc89e9a0f1494d8b757a /src/main/java
parent6e6b19356140a047d44d3135e78caf8566d1cd10 (diff)
downloadSkyblocker-37136d199a74d2dff5c27632170c7a3a5a2944e4.tar.gz
Skyblocker-37136d199a74d2dff5c27632170c7a3a5a2944e4.tar.bz2
Skyblocker-37136d199a74d2dff5c27632170c7a3a5a2944e4.zip
Change mayor & minister parsing and storing
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/SkyblockerMod.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScore.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/mayors/JerryTimer.java3
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/Utils.java69
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/mayor/Mayor.java18
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/mayor/MayorUtils.java99
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/mayor/Minister.java14
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/mayor/Perk.java13
8 files changed, 150 insertions, 72 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
index 405827e0..ac84b5e1 100644
--- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
+++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
@@ -58,6 +58,7 @@ import de.hysky.skyblocker.skyblock.waypoint.*;
import de.hysky.skyblocker.utils.*;
import de.hysky.skyblocker.utils.chat.ChatMessageListener;
import de.hysky.skyblocker.utils.discord.DiscordRPCManager;
+import de.hysky.skyblocker.utils.mayor.MayorUtils;
import de.hysky.skyblocker.utils.render.RenderHelper;
import de.hysky.skyblocker.utils.render.culling.OcclusionCulling;
import de.hysky.skyblocker.utils.container.ContainerSolverManager;
@@ -215,6 +216,7 @@ public class SkyblockerMod implements ClientModInitializer {
SlotTextManager.init();
BazaarHelper.init();
MobGlow.init();
+ MayorUtils.init();
SlayerEntitiesGlow.init();
Scheduler.INSTANCE.scheduleCyclic(Utils::update, 20);
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScore.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScore.java
index eb214022..f470d5ad 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScore.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScore.java
@@ -9,6 +9,7 @@ import de.hysky.skyblocker.skyblock.tabhud.util.PlayerListMgr;
import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.ProfileUtils;
import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.mayor.MayorUtils;
import de.hysky.skyblocker.utils.scheduler.MessageScheduler;
import de.hysky.skyblocker.utils.scheduler.Scheduler;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
@@ -19,7 +20,6 @@ import net.minecraft.entity.mob.ZombieEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.collection.DefaultedList;
-import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -151,7 +151,7 @@ public class DungeonScore {
setCurrentFloor();
dungeonStarted = true;
puzzleCount = getPuzzleCount();
- isMayorPaul = StringUtils.equalsAny("Paul", Utils.getMayor(), Utils.getMinister());
+ isMayorPaul = MayorUtils.getMayor().perks().stream().anyMatch(perk -> perk.name().equals("EZPZ")) || MayorUtils.getMinister().perk().name().equals("EZPZ");
startingTime = System.currentTimeMillis();
floorRequirement = FloorRequirement.valueOf(currentFloor);
floorHasMimics = MIMIC_FLOORS_PATTERN.matcher(currentFloor).matches();
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/mayors/JerryTimer.java b/src/main/java/de/hysky/skyblocker/skyblock/mayors/JerryTimer.java
index 7131a567..4945c0bc 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/mayors/JerryTimer.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/mayors/JerryTimer.java
@@ -3,6 +3,7 @@ package de.hysky.skyblocker.skyblock.mayors;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.mayor.MayorUtils;
import de.hysky.skyblocker.utils.scheduler.Scheduler;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
import net.minecraft.client.MinecraftClient;
@@ -20,7 +21,7 @@ public final class JerryTimer {
//Example message: "§b ☺ §eThere is a §aGreen Jerry§e!"
//There are various formats, all of which start with the "§b ☺ " prefix and contain the word "<color> Jerry"
ClientReceiveMessageEvents.GAME.register((message, overlay) -> {
- if (overlay || !Utils.getMayor().equals("Jerry") || !SkyblockerConfigManager.get().helpers.jerry.enableJerryTimer) return;
+ if (overlay || !MayorUtils.getMayor().name().equals("Jerry") || !SkyblockerConfigManager.get().helpers.jerry.enableJerryTimer) return;
String text = message.getString();
//This part of hypixel still uses legacy text formatting, so we can't directly check for the actual text
if (!text.startsWith("§b ☺ ") || !text.contains("Jerry")) return;
diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java
index 8336561f..73861f24 100644
--- a/src/main/java/de/hysky/skyblocker/utils/Utils.java
+++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java
@@ -6,7 +6,6 @@ import com.mojang.util.UndashedUuid;
import de.hysky.skyblocker.events.SkyblockEvents;
import de.hysky.skyblocker.mixins.accessors.MessageHandlerAccessor;
import de.hysky.skyblocker.skyblock.item.MuseumItemCache;
-import de.hysky.skyblocker.utils.scheduler.Scheduler;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.azureaaron.hmapi.data.server.Environment;
@@ -27,14 +26,12 @@ import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Util;
-import org.apache.http.client.HttpResponseException;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Instant;
import java.util.Collections;
-import java.util.concurrent.CompletableFuture;
/**
* Utility variables and methods for retrieving Skyblock related information.
@@ -77,10 +74,6 @@ public class Utils {
private static String locationRaw = "";
@NotNull
private static String map = "";
- private static boolean mayorTickScheduled = false;
- private static int mayorTickRetryAttempts = 0;
- private static String mayor = "";
- private static String minister = "";
/**
* @implNote The parent text will always be empty, the actual text content is inside the text's siblings.
@@ -193,30 +186,7 @@ public class Utils {
return map;
}
- /**
- * @return the current mayor as cached on skyblock join.
- */
- @NotNull
- public static String getMayor() {
- return mayor;
- }
-
- /**
- * @return the current minister as cached on skyblock join.
- */
- @NotNull
- public static String getMinister() {
- return minister;
- }
-
public static void init() {
- SkyblockEvents.JOIN.register(() -> {
- if (!mayorTickScheduled) {
- tickMayorCache();
- scheduleMayorTick();
- mayorTickScheduled = true;
- }
- });
ClientReceiveMessageEvents.ALLOW_GAME.register(Utils::onChatMessage);
ClientReceiveMessageEvents.GAME_CANCELED.register(Utils::onChatMessage); // Somehow this works even though onChatMessage returns a boolean
ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> onDisconnect());
@@ -505,45 +475,6 @@ public class Utils {
return true;
}
- private static void scheduleMayorTick() {
- long currentYearMillis = SkyblockTime.getSkyblockMillis() % 446400000L; //446400000ms is 1 year, 105600000ms is the amount of time from early spring 1st to late spring 27th
- // If current time is past late spring 27th, the next mayor change is at next year's spring 27th, otherwise it's at this year's spring 27th
- long millisUntilNextMayorChange = currentYearMillis > 105600000L ? 446400000L - currentYearMillis + 105600000L : 105600000L - currentYearMillis;
- Scheduler.INSTANCE.schedule(Utils::tickMayorCache, (int) (millisUntilNextMayorChange / 50) + 5 * 60 * 20); // 5 extra minutes to allow the cache to expire. This is a simpler than checking age and subtracting from max age and rescheduling again.
- }
-
- private static void tickMayorCache() {
- CompletableFuture.supplyAsync(() -> {
- try {
- Http.ApiResponse response = Http.sendCacheableGetRequest("https://api.hypixel.net/v2/resources/skyblock/election", null); //Authentication is not required for this endpoint
- if (!response.ok()) throw new HttpResponseException(response.statusCode(), response.content());
- JsonObject json = JsonParser.parseString(response.content()).getAsJsonObject();
- if (!json.get("success").getAsBoolean()) throw new RuntimeException("Request failed!"); //Can't find a more appropriate exception to throw here.
- return json.get("mayor").getAsJsonObject();
- } catch (Exception e) {
- throw new RuntimeException(e); //Wrap the exception to be handled by the exceptionally block
- }
- }).exceptionally(throwable -> {
- LOGGER.error("[Skyblocker] Failed to get mayor status!", throwable.getCause());
- if (mayorTickRetryAttempts < 5) {
- int minutes = 5 << mayorTickRetryAttempts; //5, 10, 20, 40, 80 minutes
- mayorTickRetryAttempts++;
- LOGGER.warn("[Skyblocker] Retrying in {} minutes.", minutes);
- Scheduler.INSTANCE.schedule(Utils::tickMayorCache, minutes * 60 * 20);
- } else {
- LOGGER.warn("[Skyblocker] Failed to get mayor status after 5 retries! Stopping further retries until next reboot.");
- }
- return new JsonObject(); //Have to return a value for the thenAccept block.
- }).thenAccept(result -> {
- if (!result.isEmpty()) {
- mayor = result.get("name").getAsString();
- minister = result.getAsJsonObject("minister").get("name").getAsString();
- LOGGER.info("[Skyblocker] Mayor set to {}, minister set to {}.", mayor, minister);
- scheduleMayorTick(); //Ends up as a cyclic task with finer control over scheduled time
- }
- });
- }
-
/**
* Used to avoid triggering things like chat rules or chat listeners infinitely, do not use otherwise.
* <p>
diff --git a/src/main/java/de/hysky/skyblocker/utils/mayor/Mayor.java b/src/main/java/de/hysky/skyblocker/utils/mayor/Mayor.java
new file mode 100644
index 00000000..eeade3bf
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/mayor/Mayor.java
@@ -0,0 +1,18 @@
+package de.hysky.skyblocker.utils.mayor;
+
+import it.unimi.dsi.fastutil.objects.ObjectLists;
+
+import java.util.List;
+
+/**
+ * Represents a mayor as retrieved from the API.
+ * @param key The key of the mayor.
+ * @param name The name of the mayor.
+ * @param perks The perks of the mayor.
+ */
+public record Mayor(String key, String name, List<Perk> perks) {
+ /**
+ * An empty mayor. Allows for better null safety.
+ */
+ public static final Mayor EMPTY = new Mayor("", "", ObjectLists.emptyList());
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/mayor/MayorUtils.java b/src/main/java/de/hysky/skyblocker/utils/mayor/MayorUtils.java
new file mode 100644
index 00000000..0a8f6342
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/mayor/MayorUtils.java
@@ -0,0 +1,99 @@
+package de.hysky.skyblocker.utils.mayor;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import de.hysky.skyblocker.events.SkyblockEvents;
+import de.hysky.skyblocker.utils.Http;
+import de.hysky.skyblocker.utils.SkyblockTime;
+import de.hysky.skyblocker.utils.scheduler.Scheduler;
+import org.apache.http.client.HttpResponseException;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.CompletableFuture;
+
+public class MayorUtils {
+ private static Mayor mayor = Mayor.EMPTY;
+ private static Minister minister = Minister.EMPTY;
+ private static boolean mayorTickScheduled = false;
+ private static int mayorTickRetryAttempts = 0;
+ private static final Logger LOGGER = LoggerFactory.getLogger(MayorUtils.class);
+
+ private MayorUtils() {}
+
+ @NotNull
+ public static Mayor getMayor() {
+ return mayor;
+ }
+
+ @NotNull
+ public static Minister getMinister() {
+ return minister;
+ }
+
+ public static void init() {
+ SkyblockEvents.JOIN.register(() -> {
+ if (!mayorTickScheduled) {
+ tickMayorCache();
+ scheduleMayorTick();
+ mayorTickScheduled = true;
+ }
+ });
+ }
+
+ private static void scheduleMayorTick() {
+ long currentYearMillis = SkyblockTime.getSkyblockMillis() % 446400000L; //446400000ms is 1 year, 105600000ms is the amount of time from early spring 1st to late spring 27th
+ // If current time is past late spring 27th, the next mayor change is at next year's spring 27th, otherwise it's at this year's spring 27th
+ long millisUntilNextMayorChange = currentYearMillis > 105600000L ? 446400000L - currentYearMillis + 105600000L : 105600000L - currentYearMillis;
+ Scheduler.INSTANCE.schedule(MayorUtils::tickMayorCache, (int) (millisUntilNextMayorChange / 50) + 5 * 60 * 20); // 5 extra minutes to allow the cache to expire. This is a simpler than checking age and subtracting from max age and rescheduling again.
+ }
+
+ private static void tickMayorCache() {
+ CompletableFuture.supplyAsync(() -> {
+ try {
+ Http.ApiResponse response = Http.sendCacheableGetRequest("https://api.hypixel.net/v2/resources/skyblock/election", null); //Authentication is not required for this endpoint
+ if (!response.ok()) throw new HttpResponseException(response.statusCode(), response.content());
+ JsonObject json = JsonParser.parseString(response.content()).getAsJsonObject();
+ if (!json.get("success").getAsBoolean()) throw new RuntimeException("Request failed!"); //Can't find a more appropriate exception to throw here.
+ return json.get("mayor").getAsJsonObject();
+ } catch (Exception e) {
+ throw new RuntimeException(e); //Wrap the exception to be handled by the exceptionally block
+ }
+ }).exceptionally(throwable -> {
+ LOGGER.error("[Skyblocker] Failed to get mayor status!", throwable.getCause());
+ if (mayorTickRetryAttempts < 5) {
+ int minutes = 5 << mayorTickRetryAttempts; //5, 10, 20, 40, 80 minutes
+ mayorTickRetryAttempts++;
+ LOGGER.warn("[Skyblocker] Retrying in {} minutes.", minutes);
+ Scheduler.INSTANCE.schedule(MayorUtils::tickMayorCache, minutes * 60 * 20);
+ } else {
+ LOGGER.warn("[Skyblocker] Failed to get mayor status after 5 retries! Stopping further retries until next reboot.");
+ }
+ return new JsonObject(); //Have to return a value for the thenAccept block.
+ }).thenAccept(result -> {
+ if (!result.isEmpty()) {
+ mayor = new Mayor(result.get("key").getAsString(),
+ result.get("name").getAsString(),
+ result.getAsJsonArray("perks")
+ .asList()
+ .stream()
+ .map(JsonElement::getAsJsonObject)
+ .map(object -> new Perk(object.get("name").getAsString(), object.get("description").getAsString()))
+ .toList());
+ JsonObject ministerObject = result.getAsJsonObject("minister");
+ minister = new Minister(ministerObject.get("key").getAsString(),
+ ministerObject.get("name").getAsString(),
+ ministerObject.getAsJsonArray("perk")
+ .asList()
+ .stream()
+ .map(JsonElement::getAsJsonObject)
+ .map(object -> new Perk(object.get("name").getAsString(), object.get("description").getAsString()))
+ .findFirst().orElse(Perk.EMPTY));
+ LOGGER.info("[Skyblocker] Mayor set to {}, minister set to {}.", mayor.name(), minister.name());
+ scheduleMayorTick(); //Ends up as a cyclic task with finer control over scheduled time
+ }
+ });
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/mayor/Minister.java b/src/main/java/de/hysky/skyblocker/utils/mayor/Minister.java
new file mode 100644
index 00000000..13638b39
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/mayor/Minister.java
@@ -0,0 +1,14 @@
+package de.hysky.skyblocker.utils.mayor;
+
+/**
+ * Represents a minister as retrieved from the API.
+ * @param key The key of the minister.
+ * @param name The name of the minister.
+ * @param perk The perk of the minister.
+ */
+public record Minister(String key, String name, Perk perk) {
+ /**
+ * An empty minister. Allows for better null safety.
+ */
+ public static final Minister EMPTY = new Minister("", "", Perk.EMPTY);
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/mayor/Perk.java b/src/main/java/de/hysky/skyblocker/utils/mayor/Perk.java
new file mode 100644
index 00000000..a2dc1700
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/mayor/Perk.java
@@ -0,0 +1,13 @@
+package de.hysky.skyblocker.utils.mayor;
+
+/**
+ * Represents a mayor perk.
+ * @param name The name of the perk.
+ * @param description The description of the perk. This will include the formatting codes that are used in the game.
+ */
+public record Perk(String name, String description) {
+ /**
+ * An empty perk. Allows for better null safety.
+ */
+ public static Perk EMPTY = new Perk("", "");
+}