aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2024-08-02 21:11:14 -0400
committerGitHub <noreply@github.com>2024-08-02 21:11:14 -0400
commit023bf7882b4be983e42c23da286f7d59f0532533 (patch)
tree17193e8f1a514bec16cda21feb23cd6d65a39ce4 /src/main/java
parent19dac2a71603b939ed5ac995e3448f8f07a0c484 (diff)
parent9cd356c1bbba90d16bd05524248bc499fced6963 (diff)
downloadSkyblocker-023bf7882b4be983e42c23da286f7d59f0532533.tar.gz
Skyblocker-023bf7882b4be983e42c23da286f7d59f0532533.tar.bz2
Skyblocker-023bf7882b4be983e42c23da286f7d59f0532533.zip
Merge pull request #845 from Emirlol/egg-finder-esp-fix-raytracing
Add raytracing to the egg finder to make it fairer
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java117
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/PosUtils.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/SkyblockTime.java122
3 files changed, 188 insertions, 55 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java
index 6926fda8..6d390039 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java
@@ -12,6 +12,7 @@ import de.hysky.skyblocker.utils.scheduler.MessageScheduler;
import de.hysky.skyblocker.utils.waypoint.Waypoint;
import it.unimi.dsi.fastutil.objects.ObjectImmutableList;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
@@ -24,7 +25,7 @@ import net.minecraft.text.ClickEvent;
import net.minecraft.text.HoverEvent;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
-import org.apache.commons.lang3.text.WordUtils;
+import org.apache.commons.text.WordUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,18 +40,40 @@ public class EggFinder {
private static final Pattern eggFoundPattern = Pattern.compile("^(?:HOPPITY'S HUNT You found a Chocolate|You have already collected this Chocolate) (Breakfast|Lunch|Dinner)");
private static final Pattern newEggPattern = Pattern.compile("^HOPPITY'S HUNT A Chocolate (Breakfast|Lunch|Dinner) Egg has appeared!$");
private static final Logger logger = LoggerFactory.getLogger("Skyblocker Egg Finder");
+ //This is most likely unnecessary with the addition of the location change packet, but it works fine and might be doing something so might as well keep it
private static final LinkedList<ArmorStandEntity> armorStandQueue = new LinkedList<>();
+ /**
+ * The locations that the egg finder should work while the player is in.
+ */
private static final Location[] possibleLocations = {Location.CRIMSON_ISLE, Location.CRYSTAL_HOLLOWS, Location.DUNGEON_HUB, Location.DWARVEN_MINES, Location.HUB, Location.THE_END, Location.THE_PARK, Location.GOLD_MINE, Location.DEEP_CAVERNS, Location.SPIDERS_DEN, Location.THE_FARMING_ISLAND};
+ /**
+ * Whether the player is in a location where the egg finder should work.
+ * This is set to false upon world change and will be checked with the location change event afterward.
+ */
private static boolean isLocationCorrect = false;
- private EggFinder() {
- }
+ private EggFinder() {}
public static void init() {
- ClientPlayConnectionEvents.JOIN.register((ignored, ignored2, ignored3) -> invalidateState());
+ ClientPlayConnectionEvents.JOIN.register((ignored, ignored2, ignored3) -> isLocationCorrect = false);
SkyblockEvents.LOCATION_CHANGE.register(EggFinder::handleLocationChange);
ClientReceiveMessageEvents.GAME.register(EggFinder::onChatMessage);
WorldRenderEvents.AFTER_TRANSLUCENT.register(EggFinder::renderWaypoints);
+ ClientTickEvents.END_CLIENT_TICK.register(client -> {
+ if (!SkyblockerConfigManager.get().helpers.chocolateFactory.enableEggFinder || client.player == null) return;
+ if (!isLocationCorrect || SkyblockTime.skyblockSeason.get() != SkyblockTime.Season.SPRING) return;
+ for (EggType type : EggType.entries) {
+ Egg egg = type.egg;
+ if (egg != null && !egg.seen && client.player.canSee(egg.entity)) {
+ type.setSeen();
+ }
+ }
+ });
+ SkyblockTime.HOUR_CHANGE.register(hour -> {
+ for (EggType type : EggType.entries) {
+ if (hour == type.resetHour) type.collected = false;
+ }
+ });
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE)
.then(literal("eggFinder")
.then(literal("shareLocation")
@@ -73,7 +96,6 @@ public class EggFinder {
armorStandQueue.clear();
return;
}
-
while (!armorStandQueue.isEmpty()) {
handleArmorStand(armorStandQueue.poll());
}
@@ -87,7 +109,7 @@ public class EggFinder {
if (!SkyblockerConfigManager.get().helpers.chocolateFactory.enableEggFinder) return;
if (SkyblockTime.skyblockSeason.get() != SkyblockTime.Season.SPRING) return;
if (armorStand.hasCustomName() || !armorStand.isInvisible() || !armorStand.shouldHideBasePlate()) return;
- if (Utils.getLocation() == Location.UNKNOWN) { //The location is unknown upon world change and will be changed via /locraw soon, so we can queue it for now
+ if (Utils.getLocation() == Location.UNKNOWN) { //The location is unknown upon world change and will be changed via location change packets soon, so we can queue it for now
armorStandQueue.add(armorStand);
return;
}
@@ -99,7 +121,7 @@ public class EggFinder {
ItemUtils.getHeadTextureOptional(itemStack).ifPresent(texture -> {
for (EggType type : EggType.entries) { //Compare blockPos rather than entity to avoid incorrect matches when the entity just moves rather than a new one being spawned elsewhere
if (texture.equals(type.texture) && (type.egg == null || !type.egg.entity.getBlockPos().equals(armorStand.getBlockPos()))) {
- handleFoundEgg(armorStand, type);
+ type.egg = new Egg(armorStand, new Waypoint(armorStand.getBlockPos().up(2), SkyblockerConfigManager.get().helpers.chocolateFactory.waypointType, ColorUtils.getFloatComponents(type.color)), false);
return;
}
}
@@ -107,34 +129,11 @@ public class EggFinder {
}
}
- private static void invalidateState() {
- if (!SkyblockerConfigManager.get().helpers.chocolateFactory.enableEggFinder) return;
- isLocationCorrect = false;
- for (EggType type : EggType.entries) {
- type.egg = null;
- }
- }
-
- private static void handleFoundEgg(ArmorStandEntity entity, EggType eggType) {
- eggType.egg = new Egg(entity, new Waypoint(entity.getBlockPos().up(2), SkyblockerConfigManager.get().helpers.chocolateFactory.waypointType, ColorUtils.getFloatComponents(eggType.color)));
-
- if (!SkyblockerConfigManager.get().helpers.chocolateFactory.sendEggFoundMessages || System.currentTimeMillis() - eggType.messageLastSent < 1000) return;
- eggType.messageLastSent = System.currentTimeMillis();
- MinecraftClient.getInstance().player.sendMessage(
- Constants.PREFIX.get()
- .append("Found a ")
- .append(Text.literal("Chocolate " + eggType + " Egg")
- .withColor(eggType.color))
- .append(" at " + entity.getBlockPos().up(2).toShortString() + "!")
- .styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/skyblocker eggFinder shareLocation " + entity.getBlockX() + " " + (entity.getBlockY() + 2) + " " + entity.getBlockZ() + " " + eggType))
- .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal("Click to share the location in chat!").formatted(Formatting.GREEN)))));
- }
-
private static void renderWaypoints(WorldRenderContext context) {
if (!SkyblockerConfigManager.get().helpers.chocolateFactory.enableEggFinder) return;
for (EggType type : EggType.entries) {
Egg egg = type.egg;
- if (egg != null && egg.waypoint.shouldRender()) egg.waypoint.render(context);
+ if (egg != null && egg.waypoint.shouldRender() && egg.seen) egg.waypoint.render(context);
}
}
@@ -143,7 +142,9 @@ public class EggFinder {
Matcher matcher = eggFoundPattern.matcher(text.getString());
if (matcher.find()) {
try {
- Egg egg = EggType.valueOf(matcher.group(1).toUpperCase()).egg;
+ EggType eggType = EggType.valueOf(matcher.group(1).toUpperCase());
+ eggType.collected = true;
+ Egg egg = eggType.egg;
if (egg != null) egg.waypoint.setFound();
} catch (IllegalArgumentException e) {
logger.error("[Skyblocker Egg Finder] Failed to find egg type for egg found message. Tried to match against: " + matcher.group(0), e);
@@ -153,43 +154,75 @@ public class EggFinder {
matcher.usePattern(newEggPattern);
if (matcher.find()) {
try {
- EggType.valueOf(matcher.group(1).toUpperCase()).egg = null;
+ EggType.valueOf(matcher.group(1).toUpperCase());
} catch (IllegalArgumentException e) {
logger.error("[Skyblocker Egg Finder] Failed to find egg type for egg spawn message. Tried to match against: " + matcher.group(0), e);
}
}
}
- record Egg(ArmorStandEntity entity, Waypoint waypoint) {}
+ static class Egg {
+ private final ArmorStandEntity entity;
+ private final Waypoint waypoint;
+ private boolean seen;
+
+ Egg(ArmorStandEntity entity, Waypoint waypoint, boolean seen) {
+ this.entity = entity;
+ this.waypoint = waypoint;
+ this.seen = seen;
+ }
+ }
@SuppressWarnings("DataFlowIssue") //Removes that pesky "unboxing of Integer might cause NPE" warning when we already know it's not null
public enum EggType {
- LUNCH(Formatting.BLUE.getColorValue(), "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjU2ODExMiwKICAicHJvZmlsZUlkIiA6ICI3NzUwYzFhNTM5M2Q0ZWQ0Yjc2NmQ4ZGUwOWY4MjU0NiIsCiAgInByb2ZpbGVOYW1lIiA6ICJSZWVkcmVsIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdhZTZkMmQzMWQ4MTY3YmNhZjk1MjkzYjY4YTRhY2Q4NzJkNjZlNzUxZGI1YTM0ZjJjYmM2NzY2YTAzNTZkMGEiCiAgICB9CiAgfQp9"),
- DINNER(Formatting.GREEN.getColorValue(), "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjY0OTcwMSwKICAicHJvZmlsZUlkIiA6ICI3NGEwMzQxNWY1OTI0ZTA4YjMyMGM2MmU1NGE3ZjJhYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZXp6aXIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTVlMzYxNjU4MTlmZDI4NTBmOTg1NTJlZGNkNzYzZmY5ODYzMTMxMTkyODNjMTI2YWNlMGM0Y2M0OTVlNzZhOCIKICAgIH0KICB9Cn0"),
- BREAKFAST(Formatting.GOLD.getColorValue(), "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjY3MzE0OSwKICAicHJvZmlsZUlkIiA6ICJiN2I4ZTlhZjEwZGE0NjFmOTY2YTQxM2RmOWJiM2U4OCIsCiAgInByb2ZpbGVOYW1lIiA6ICJBbmFiYW5hbmFZZzciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTQ5MzMzZDg1YjhhMzE1ZDAzMzZlYjJkZjM3ZDhhNzE0Y2EyNGM1MWI4YzYwNzRmMWI1YjkyN2RlYjUxNmMyNCIKICAgIH0KICB9Cn0");
+ LUNCH(Formatting.BLUE.getColorValue(), 14, "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjU2ODExMiwKICAicHJvZmlsZUlkIiA6ICI3NzUwYzFhNTM5M2Q0ZWQ0Yjc2NmQ4ZGUwOWY4MjU0NiIsCiAgInByb2ZpbGVOYW1lIiA6ICJSZWVkcmVsIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdhZTZkMmQzMWQ4MTY3YmNhZjk1MjkzYjY4YTRhY2Q4NzJkNjZlNzUxZGI1YTM0ZjJjYmM2NzY2YTAzNTZkMGEiCiAgICB9CiAgfQp9"),
+ DINNER(Formatting.GREEN.getColorValue(), 21, "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjY0OTcwMSwKICAicHJvZmlsZUlkIiA6ICI3NGEwMzQxNWY1OTI0ZTA4YjMyMGM2MmU1NGE3ZjJhYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZXp6aXIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTVlMzYxNjU4MTlmZDI4NTBmOTg1NTJlZGNkNzYzZmY5ODYzMTMxMTkyODNjMTI2YWNlMGM0Y2M0OTVlNzZhOCIKICAgIH0KICB9Cn0"),
+ BREAKFAST(Formatting.GOLD.getColorValue(), 7, "ewogICJ0aW1lc3RhbXAiIDogMTcxMTQ2MjY3MzE0OSwKICAicHJvZmlsZUlkIiA6ICJiN2I4ZTlhZjEwZGE0NjFmOTY2YTQxM2RmOWJiM2U4OCIsCiAgInByb2ZpbGVOYW1lIiA6ICJBbmFiYW5hbmFZZzciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTQ5MzMzZDg1YjhhMzE1ZDAzMzZlYjJkZjM3ZDhhNzE0Y2EyNGM1MWI4YzYwNzRmMWI1YjkyN2RlYjUxNmMyNCIKICAgIH0KICB9Cn0");
private Egg egg = null;
public final int color;
public final String texture;
+ public final int resetHour;
+ boolean collected = false;
/*
When a new egg spawns in the player's range, the order of packets/messages goes like this:
- set_equipment -> new egg message -> set_entity_data
+ set_equipment → new egg message → set_entity_data
We have to set the egg to null to prevent the highlight from staying where it was before the new egg spawned,
- and doing so causes the found message to get sent twice. This is the reason for the existence of this field, so that we can not send the 2nd message.
- This doesn't fix the field being set twice, but that's not an issue anyway. It'd be much harder to fix the highlight issue mentioned above if it wasn't being set twice.
+ and doing so causes the found message to get sent twice.
+ This is the reason for the existence of this field, so that we don't send the 2nd message.
+ This doesn't fix the field being set twice, but that's not an issue anyway.
+ It'd be much harder to fix the highlight issue mentioned above if it wasn't being set twice.
*/
private long messageLastSent = 0;
//This is to not create an array each time we iterate over the values
public static final ObjectImmutableList<EggType> entries = ObjectImmutableList.of(EggType.values());
- EggType(int color, String texture) {
+ EggType(int color, int resetHour, String texture) {
this.color = color;
+ this.resetHour = resetHour;
this.texture = texture;
}
+ public void setSeen() {
+ egg.seen = true;
+ if (!SkyblockerConfigManager.get().helpers.chocolateFactory.sendEggFoundMessages || System.currentTimeMillis() - messageLastSent < 1000) return;
+ if (collected) {
+ egg.waypoint.setFound();
+ return;
+ }
+ messageLastSent = System.currentTimeMillis();
+ MinecraftClient.getInstance().player.sendMessage(
+ Constants.PREFIX.get()
+ .append("Found a ")
+ .append(Text.literal("Chocolate " + this + " Egg")
+ .withColor(color))
+ .append(" at " + egg.entity.getBlockPos().up(2).toShortString() + "!")
+ .styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/skyblocker eggFinder shareLocation " + PosUtils.toSpaceSeparatedString(egg.waypoint.pos) + " " + this))
+ .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal("Click to share the location in chat!").formatted(Formatting.GREEN)))));
+ }
+
@Override
- @SuppressWarnings("deprecation") // It's either a new dependency or a deprecated method, and I'd rather use the deprecated method
public String toString() {
return WordUtils.capitalizeFully(this.name());
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/PosUtils.java b/src/main/java/de/hysky/skyblocker/utils/PosUtils.java
index 4ca37a83..b6205088 100644
--- a/src/main/java/de/hysky/skyblocker/utils/PosUtils.java
+++ b/src/main/java/de/hysky/skyblocker/utils/PosUtils.java
@@ -25,4 +25,8 @@ public final class PosUtils {
public static String getPosString(BlockPos blockPos) {
return blockPos.getX() + "," + blockPos.getY() + "," + blockPos.getZ();
}
+
+ public static String toSpaceSeparatedString(BlockPos blockPos) {
+ return blockPos.getX() + " " + blockPos.getY() + " " + blockPos.getZ();
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/SkyblockTime.java b/src/main/java/de/hysky/skyblocker/utils/SkyblockTime.java
index ec3effaf..739fd148 100644
--- a/src/main/java/de/hysky/skyblocker/utils/SkyblockTime.java
+++ b/src/main/java/de/hysky/skyblocker/utils/SkyblockTime.java
@@ -1,6 +1,8 @@
package de.hysky.skyblocker.utils;
import de.hysky.skyblocker.utils.scheduler.Scheduler;
+import net.fabricmc.fabric.api.event.Event;
+import net.fabricmc.fabric.api.event.EventFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -13,39 +15,109 @@ public class SkyblockTime {
public static final AtomicReference<Season> skyblockSeason = new AtomicReference<>(Season.SPRING);
public static final AtomicReference<Month> skyblockMonth = new AtomicReference<>(Month.EARLY_SPRING);
public static final AtomicInteger skyblockDay = new AtomicInteger(0);
+ public static final AtomicInteger skyblockHour = new AtomicInteger(0);
private static final Logger LOGGER = LoggerFactory.getLogger("Skyblocker Time");
+ //All time lengths are in milliseconds
+ public static final double HOUR_LENGTH = 50000;
+ public static final double DAY_LENGTH = HOUR_LENGTH * 24;
+ public static final double MONTH_LENGTH = DAY_LENGTH * 31;
+ public static final double SEASON_LENGTH = MONTH_LENGTH * 3;
+ public static final double YEAR_LENGTH = SEASON_LENGTH * 4;
+
+ public static final Event<OnHourChange> HOUR_CHANGE = EventFactory.createArrayBacked(OnHourChange.class, listeners -> hour -> {
+ for (OnHourChange listener : listeners) {
+ listener.onHourChange(hour);
+ }
+ });
+ public static final Event<OnDayChange> DAY_CHANGE = EventFactory.createArrayBacked(OnDayChange.class, listeners -> day -> {
+ for (OnDayChange listener : listeners) {
+ listener.onDayChange(day);
+ }
+ });
+ public static final Event<OnMonthChange> MONTH_CHANGE = EventFactory.createArrayBacked(OnMonthChange.class, listeners -> month -> {
+ for (OnMonthChange listener : listeners) {
+ listener.onMonthChange(month);
+ }
+ });
+ public static final Event<OnSeasonChange> SEASON_CHANGE = EventFactory.createArrayBacked(OnSeasonChange.class, listeners -> season -> {
+ for (OnSeasonChange listener : listeners) {
+ listener.onSeasonChange(season);
+ }
+ });
+ public static final Event<OnYearChange> YEAR_CHANGE = EventFactory.createArrayBacked(OnYearChange.class, listeners -> year -> {
+ for (OnYearChange listener : listeners) {
+ listener.onYearChange(year);
+ }
+ });
+ public static final Event<OnTimeUpdate> TIME_UPDATE = EventFactory.createArrayBacked(OnTimeUpdate.class, listeners -> (year, season, month, day, hour) -> {
+ for (OnTimeUpdate listener : listeners) {
+ listener.onTimeUpdate(year, season, month, day, hour);
+ }
+ });
+
private SkyblockTime() {
}
+ /**
+ * Updates the time and schedules a cyclic scheduler which will update the time every hour, to be run on the next hour change.
+ */
public static void init() {
updateTime();
- //ScheduleCyclic already runs the task upon scheduling, so there's no need to call updateTime() here
- Scheduler.INSTANCE.schedule(() -> Scheduler.INSTANCE.scheduleCyclic(SkyblockTime::updateTime, 1200 * 20), (int) (1200000 - (getSkyblockMillis() % 1200000)) / 50);
+ //scheduleCyclic already runs the task upon scheduling, so there's no need to call updateTime() in the lambda as well
+ //The division by 50 is to convert the time to ticks
+ Scheduler.INSTANCE.schedule(() -> Scheduler.INSTANCE.scheduleCyclic(SkyblockTime::updateTime, (int) (HOUR_LENGTH / 50)), (int) (HOUR_LENGTH - (getSkyblockMillis() % HOUR_LENGTH)) / 50);
}
public static long getSkyblockMillis() {
return System.currentTimeMillis() - SKYBLOCK_EPOCH;
}
- private static int getSkyblockYear() {
- return (int) (Math.floor(getSkyblockMillis() / 446400000.0) + 1);
+ private static int calculateSkyblockYear() {
+ return (int) (Math.floor(getSkyblockMillis() / YEAR_LENGTH) + 1);
+ }
+
+ private static int calculateSkyblockMonth() {
+ return (int) (Math.floor(getSkyblockMillis() / MONTH_LENGTH) % 12);
}
- private static int getSkyblockMonth() {
- return (int) (Math.floor(getSkyblockMillis() / 37200000.0) % 12);
+ private static int calculateSkyblockDay() {
+ return (int) (Math.floor(getSkyblockMillis() / DAY_LENGTH) % 31 + 1);
}
- private static int getSkyblockDay() {
- return (int) (Math.floor(getSkyblockMillis() / 1200000.0) % 31 + 1);
+ private static int calculateSkyblockHour() {
+ return (int) (Math.floor(getSkyblockMillis() / HOUR_LENGTH) % 24);
}
+ //This could probably be compacted by abstracting the logic into a method that takes a Supplier and a Consumer, etc. but there's really no need
private static void updateTime() {
- skyblockYear.set(getSkyblockYear());
- skyblockSeason.set(Season.values()[getSkyblockMonth() / 3]);
- skyblockMonth.set(Month.values()[getSkyblockMonth()]);
- skyblockDay.set(getSkyblockDay());
- LOGGER.info("[Skyblocker Time] Skyblock time updated to Year {}, Season {}, Month {}, Day {}", skyblockYear.get(), skyblockSeason.get(), skyblockMonth.get(), skyblockDay.get());
+ int year = calculateSkyblockYear();
+ if (skyblockYear.get() != year) {
+ skyblockYear.set(year);
+ YEAR_CHANGE.invoker().onYearChange(year);
+ }
+ Season season = Season.values()[calculateSkyblockMonth() / 3];
+ if (skyblockSeason.get() != season) {
+ skyblockSeason.set(season);
+ SEASON_CHANGE.invoker().onSeasonChange(season);
+ }
+ Month month = Month.values()[calculateSkyblockMonth()];
+ if (skyblockMonth.get() != month) {
+ skyblockMonth.set(month);
+ MONTH_CHANGE.invoker().onMonthChange(month);
+ }
+ int day = calculateSkyblockDay();
+ if (skyblockDay.get() != day) {
+ skyblockDay.set(day);
+ DAY_CHANGE.invoker().onDayChange(day);
+ }
+ int hour = calculateSkyblockHour();
+ if (skyblockHour.get() != hour) {
+ skyblockHour.set(hour);
+ HOUR_CHANGE.invoker().onHourChange(hour);
+ }
+ TIME_UPDATE.invoker().onTimeUpdate(year, season, month, day, hour);
+ LOGGER.info("[Skyblocker Time] Skyblock time updated to Year {}, Season {}, Month {}, Day {}, Hour {}", year, season, month, day, hour);
}
public enum Season {
@@ -58,4 +130,28 @@ public class SkyblockTime {
EARLY_FALL, FALL, LATE_FALL,
EARLY_WINTER, WINTER, LATE_WINTER
}
+
+ public interface OnHourChange {
+ void onHourChange(int hour);
+ }
+
+ public interface OnDayChange {
+ void onDayChange(int day);
+ }
+
+ public interface OnMonthChange {
+ void onMonthChange(Month month);
+ }
+
+ public interface OnSeasonChange {
+ void onSeasonChange(Season season);
+ }
+
+ public interface OnYearChange {
+ void onYearChange(int year);
+ }
+
+ public interface OnTimeUpdate {
+ void onTimeUpdate(int year, Season season, Month month, int day, int hour);
+ }
}