aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hysky/skyblocker/utils/Utils.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/utils/Utils.java')
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/Utils.java61
1 files changed, 43 insertions, 18 deletions
diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java
index 7a00c1a0..051110b2 100644
--- a/src/main/java/de/hysky/skyblocker/utils/Utils.java
+++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java
@@ -3,7 +3,6 @@ package de.hysky.skyblocker.utils;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
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;
@@ -22,11 +21,11 @@ import net.minecraft.scoreboard.*;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
+import org.apache.http.client.HttpResponseException;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.IOException;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
@@ -77,7 +76,8 @@ public class Utils {
private static boolean canSendLocRaw = false;
//This is required to prevent the location change event from being fired twice.
private static boolean locationChanged = true;
-
+ private static boolean mayorTickScheduled = false;
+ private static int mayorTickRetryAttempts = 0;
private static String mayor = "";
/**
@@ -194,11 +194,16 @@ public class Utils {
}
public static void init() {
- SkyblockEvents.JOIN.register(() -> tickMayorCache(false));
+ SkyblockEvents.JOIN.register(() -> {
+ if (!mayorTickScheduled) {
+ tickMayorCache();
+ scheduleMayorTick();
+ mayorTickScheduled = true;
+ }
+ });
ClientPlayConnectionEvents.JOIN.register(Utils::onClientWorldJoin);
ClientReceiveMessageEvents.ALLOW_GAME.register(Utils::onChatMessage);
ClientReceiveMessageEvents.GAME_CANCELED.register(Utils::onChatMessage); // Somehow this works even though onChatMessage returns a boolean
- Scheduler.INSTANCE.scheduleCyclic(() -> tickMayorCache(true), 24_000, true); // Update every 20 minutes
}
/**
@@ -361,8 +366,8 @@ public class Utils {
// TODO: Combine with `ChocolateFactorySolver.formatTime` and move into `SkyblockTime`.
public static Text getDurationText(int timeInSeconds) {
int seconds = timeInSeconds % 60;
- int minutes = (timeInSeconds/60) % 60;
- int hours = (timeInSeconds/3600);
+ int minutes = (timeInSeconds / 60) % 60;
+ int hours = (timeInSeconds / 3600);
MutableText time = Text.empty();
if (hours > 0) {
@@ -486,27 +491,47 @@ public class Utils {
location = Location.UNKNOWN;
}
- private static void tickMayorCache(boolean refresh) {
- if (!mayor.isEmpty() && !refresh) return;
+ 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 {
- JsonObject json = JsonParser.parseString(Http.sendGetRequest("https://api.hypixel.net/v2/resources/skyblock/election")).getAsJsonObject();
- if (json.get("success").getAsBoolean()) return json.get("mayor").getAsJsonObject().get("name").getAsString();
- throw new IOException(json.get("cause").getAsString());
+ 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().get("name").getAsString();
} catch (Exception e) {
- LOGGER.error("[Skyblocker] Failed to get mayor status!", 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 * 1 << 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 ""; //Have to return a value for the thenAccept block.
+ }).thenAccept(result -> {
+ if (!result.isEmpty()) {
+ mayor = result;
+ LOGGER.info("[Skyblocker] Mayor set to {}.", mayor);
+ scheduleMayorTick(); //Ends up as a cyclic task with finer control over scheduled time
}
- return "";
- }).thenAccept(s -> {
- if (!s.isEmpty()) mayor = s;
});
-
}
/**
* Used to avoid triggering things like chat rules or chat listeners infinitely, do not use otherwise.
- *
+ * <p>
* Bypasses MessageHandler#onGameMessage
*/
public static void sendMessageToBypassEvents(Text message) {