aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/OtherLocationsCategory.java6
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/PetCache.java56
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dwarven/PowderMiningTracker.java58
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/end/EndHudWidget.java7
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/end/TheEnd.java134
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/ItemCooldowns.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java98
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/AccessoriesHelper.java50
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/slayers/SlayerTimer.java53
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/tabhud/widget/ComponentBasedWidget.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/Utils.java9
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/profile/ProfiledData.java169
12 files changed, 265 insertions, 381 deletions
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/OtherLocationsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/OtherLocationsCategory.java
index 259e91d9..c7fa6cb2 100644
--- a/src/main/java/de/hysky/skyblocker/config/categories/OtherLocationsCategory.java
+++ b/src/main/java/de/hysky/skyblocker/config/categories/OtherLocationsCategory.java
@@ -134,11 +134,7 @@ public class OtherLocationsCategory {
.option(ButtonOption.createBuilder()
.name(Text.translatable("skyblocker.config.otherLocations.end.resetName"))
.text(Text.translatable("skyblocker.config.otherLocations.end.resetText"))
- .action((screen, opt) -> {
- TheEnd.zealotsKilled = 0;
- TheEnd.zealotsSinceLastEye = 0;
- TheEnd.eyes = 0;
- })
+ .action((screen, opt) -> TheEnd.PROFILES_STATS.put(TheEnd.EndStats.EMPTY))
.build())
.option(Option.<Boolean>createBuilder()
.name(Text.translatable("skyblocker.config.otherLocations.end.muteEndermanSounds"))
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java b/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java
index 35fea3fa..603f1017 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java
@@ -1,41 +1,27 @@
package de.hysky.skyblocker.skyblock;
-import com.google.gson.JsonParser;
-import com.mojang.logging.LogUtils;
-import com.mojang.serialization.Codec;
-import com.mojang.serialization.JsonOps;
import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.annotations.Init;
import de.hysky.skyblocker.skyblock.item.PetInfo;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
-import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import de.hysky.skyblocker.utils.profile.ProfiledData;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import org.jetbrains.annotations.Nullable;
-import org.slf4j.Logger;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
-import java.util.concurrent.CompletableFuture;
/**
- * Doesn't work with auto pet right now because thats complicated.
+ * Doesn't work with auto pet right now because that's complicated.
* <p>
* Want support? Ask the Admins for a Mod API event or open your pets menu.
*/
public class PetCache {
- private static final Logger LOGGER = LogUtils.getLogger();
private static final Path FILE = SkyblockerMod.CONFIG_DIR.resolve("pet_cache.json");
- private static final Object2ObjectOpenHashMap<String, Object2ObjectOpenHashMap<String, PetInfo>> CACHED_PETS = new Object2ObjectOpenHashMap<>();
- public static final Codec<Object2ObjectOpenHashMap<String, Object2ObjectOpenHashMap<String, PetInfo>>> SERIALIZATION_CODEC = Codec.unboundedMap(Codec.STRING,
- Codec.unboundedMap(Codec.STRING, PetInfo.CODEC).xmap(Object2ObjectOpenHashMap::new, Object2ObjectOpenHashMap::new)
- ).xmap(Object2ObjectOpenHashMap::new, Object2ObjectOpenHashMap::new);
+ private static final ProfiledData<PetInfo> CACHED_PETS = new ProfiledData<>(FILE, PetInfo.CODEC, true, true);
/**
* Used in case the server lags to prevent the screen tick check from overwriting the clicked pet logic
@@ -44,7 +30,7 @@ public class PetCache {
@Init
public static void init() {
- load();
+ CACHED_PETS.load();
ScreenEvents.BEFORE_INIT.register((_client, screen, _scaledWidth, _scaledHeight) -> {
if (Utils.isOnSkyblock() && screen instanceof GenericContainerScreen genericContainerScreen) {
@@ -70,27 +56,6 @@ public class PetCache {
});
}
- private static void load() {
- CompletableFuture.runAsync(() -> {
- try (BufferedReader reader = Files.newBufferedReader(FILE)) {
- CACHED_PETS.putAll(SERIALIZATION_CODEC.parse(JsonOps.INSTANCE, JsonParser.parseReader(reader)).getOrThrow());
- } catch (NoSuchFileException ignored) {
- } catch (Exception e) {
- LOGGER.error("[Skyblocker Pet Cache] Failed to load saved pet!", e);
- }
- });
- }
-
- private static void save() {
- CompletableFuture.runAsync(() -> {
- try (BufferedWriter writer = Files.newBufferedWriter(FILE)) {
- SkyblockerMod.GSON.toJson(SERIALIZATION_CODEC.encodeStart(JsonOps.INSTANCE, CACHED_PETS).getOrThrow(), writer);
- } catch (Exception e) {
- LOGGER.error("[Skyblocker Pet Cache] Failed to save pet data to the cache!", e);
- }
- });
- }
-
public static void handlePetEquip(Slot slot, int slotId) {
//Ignore inventory clicks
if (slotId >= 0 && slotId <= 53) {
@@ -112,24 +77,19 @@ public class PetCache {
shouldLook4Pets = false;
- Object2ObjectOpenHashMap<String, PetInfo> playerData = CACHED_PETS.computeIfAbsent(Utils.getUndashedUuid(), _uuid -> new Object2ObjectOpenHashMap<>());
-
//Handle deselecting pets
if (clicked && getCurrentPet() != null && getCurrentPet().uuid().orElse("").equals(petInfo.uuid().orElse(""))) {
- playerData.remove(profileId);
+ CACHED_PETS.remove();
} else {
- playerData.put(profileId, petInfo);
+ CACHED_PETS.put(petInfo);
}
- save();
+ CACHED_PETS.save();
}
}
@Nullable
public static PetInfo getCurrentPet() {
- String uuid = Utils.getUndashedUuid();
- String profileId = Utils.getProfileId();
-
- return CACHED_PETS.containsKey(uuid) && CACHED_PETS.get(uuid).containsKey(profileId) ? CACHED_PETS.get(uuid).get(profileId) : null;
+ return CACHED_PETS.get();
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/PowderMiningTracker.java b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/PowderMiningTracker.java
index 5459d955..121422d5 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dwarven/PowderMiningTracker.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dwarven/PowderMiningTracker.java
@@ -1,9 +1,6 @@
package de.hysky.skyblocker.skyblock.dwarven;
-import com.google.gson.JsonElement;
import com.mojang.serialization.Codec;
-import com.mojang.serialization.JsonOps;
-import com.mojang.serialization.codecs.UnboundedMapCodec;
import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.annotations.Init;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
@@ -16,10 +13,10 @@ import de.hysky.skyblocker.utils.CodecUtils;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Location;
import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.profile.ProfiledData;
import it.unimi.dsi.fastutil.doubles.DoubleBooleanPair;
import it.unimi.dsi.fastutil.objects.*;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
-import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.hud.ChatHud;
@@ -33,9 +30,9 @@ import org.jetbrains.annotations.Unmodifiable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.text.NumberFormat;
+import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -47,27 +44,16 @@ public class PowderMiningTracker {
private static final Pattern GEMSTONE_SYMBOLS = Pattern.compile("[α☘☠✎✧❁❂❈❤⸕] ");
private static final Pattern REWARD_PATTERN = Pattern.compile(" {4}(.*?) ?x?([\\d,]*)");
private static final Codec<Object2IntMap<String>> REWARDS_CODEC = CodecUtils.object2IntMapCodec(Codec.STRING);
- // Doesn't matter if the codec outputs a java map instead of a fastutils map, it's only used in #putAll anyway so the contents are copied over
- private static final UnboundedMapCodec<String, Object2IntMap<String>> ALL_REWARDS_CODEC = Codec.unboundedMap(Codec.STRING, REWARDS_CODEC);
private static final Object2ObjectArrayMap<String, String> NAME2ID_MAP = new Object2ObjectArrayMap<>(50);
// This constructor takes in a comparator that is triggered to decide where to add the element in the tree map
// This causes it to be sorted at all times. This is for rendering them in a sort of easy-to-read manner.
- private static final Object2IntAVLTreeMap<Text> SHOWN_REWARDS = new Object2IntAVLTreeMap<>((o1, o2) -> {
- String o1String = o1.getString();
- String o2String = o2.getString();
- int priority1 = comparePriority(o1String);
- int priority2 = comparePriority(o2String);
- if (priority1 != priority2) return Integer.compare(priority1, priority2);
- return o1String.compareTo(o2String);
- });
+ private static final Object2IntAVLTreeMap<Text> SHOWN_REWARDS = new Object2IntAVLTreeMap<>(Comparator.<Text>comparingInt(text -> comparePriority(text.getString())).thenComparing(Text::getString));
/**
* Holds the total reward maps for all accounts and profiles. {@link #currentProfileRewards} is a subset of this map, updated on profile change.
- *
- * @implNote This is a map from (account uuid + "+" + profile uuid) to itemId/amount map.
*/
- private static final Object2ObjectArrayMap<String, Object2IntMap<String>> ALL_REWARDS = new Object2ObjectArrayMap<>();
+ private static final ProfiledData<Object2IntMap<String>> ALL_REWARDS = new ProfiledData<>(getRewardFilePath(), REWARDS_CODEC);
/**
* <p>
@@ -98,8 +84,7 @@ public class PowderMiningTracker {
if (isEnabled()) recalculatePrices();
});
- ClientLifecycleEvents.CLIENT_STARTED.register(PowderMiningTracker::loadRewards);
- ClientLifecycleEvents.CLIENT_STOPPING.register(PowderMiningTracker::saveRewards);
+ ALL_REWARDS.init();
SkyblockEvents.PROFILE_CHANGE.register(PowderMiningTracker::onProfileChange);
SkyblockEvents.PROFILE_INIT.register(PowderMiningTracker::onProfileInit);
@@ -163,7 +148,7 @@ public class PowderMiningTracker {
private static void onProfileInit(String profileId) {
if (!isEnabled()) return;
- currentProfileRewards = ALL_REWARDS.computeIfAbsent(getCombinedId(profileId), k -> new Object2IntArrayMap<>());
+ currentProfileRewards = ALL_REWARDS.computeIfAbsent(Object2IntArrayMap::new);
recalculateAll();
}
@@ -247,33 +232,6 @@ public class PowderMiningTracker {
return Object2ObjectMaps.unmodifiable(NAME2ID_MAP);
}
- private static void loadRewards(MinecraftClient client) {
- if (Files.notExists(getRewardFilePath())) return;
- try {
- String jsonString = Files.readString(getRewardFilePath());
- JsonElement json = SkyblockerMod.GSON.fromJson(jsonString, JsonElement.class);
- ALL_REWARDS.clear();
- ALL_REWARDS.putAll(ALL_REWARDS_CODEC.decode(JsonOps.INSTANCE, json).getOrThrow().getFirst());
- LOGGER.info("Loaded powder mining rewards from file.");
- } catch (Exception e) {
- LOGGER.error("Failed to load powder mining rewards from file!", e);
- }
- }
-
- private static void saveRewards(MinecraftClient client) {
- try {
- String jsonString = ALL_REWARDS_CODEC.encodeStart(JsonOps.INSTANCE, ALL_REWARDS).getOrThrow().toString();
- if (Files.notExists(getRewardFilePath())) {
- Files.createDirectories(getRewardFilePath().getParent()); // Create all parent directories if they don't exist
- Files.createFile(getRewardFilePath());
- }
- Files.writeString(getRewardFilePath(), jsonString);
- LOGGER.info("Saved powder mining rewards to file.");
- } catch (Exception e) {
- LOGGER.error("Failed to save powder mining rewards to file!", e);
- }
- }
-
static {
NAME2ID_MAP.put("Gemstone Powder", "GEMSTONE_POWDER"); // Not an actual item, but since we're using IDs for mapping to colored text we need to have this here
@@ -347,10 +305,6 @@ public class PowderMiningTracker {
return SkyblockerMod.CONFIG_DIR.resolve("reward-trackers/powder-mining.json");
}
- private static String getCombinedId(String profileUuid) {
- return Utils.getUndashedUuid() + "+" + profileUuid;
- }
-
private static void render(DrawContext context, RenderTickCounter tickCounter) {
if (Utils.getLocation() != Location.CRYSTAL_HOLLOWS || !isEnabled()) return;
int y = MinecraftClient.getInstance().getWindow().getScaledHeight() / 2 - 100;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudWidget.java
index a4b183f7..ddfc892f 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudWidget.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/end/EndHudWidget.java
@@ -68,10 +68,11 @@ public class EndHudWidget extends ComponentBasedWidget {
public void updateContent() {
// Zealots
if (SkyblockerConfigManager.get().otherLocations.end.zealotKillsEnabled) {
+ TheEnd.EndStats endStats = TheEnd.PROFILES_STATS.putIfAbsent(TheEnd.EndStats.EMPTY);
addComponent(new IcoTextComponent(ENDERMAN_HEAD, Text.literal("Zealots").formatted(Formatting.BOLD)));
- addComponent(new PlainTextComponent(Text.translatable("skyblocker.end.hud.zealotsSinceLastEye", TheEnd.zealotsSinceLastEye)));
- addComponent(new PlainTextComponent(Text.translatable("skyblocker.end.hud.zealotsTotalKills", TheEnd.zealotsKilled)));
- String avg = TheEnd.eyes == 0 ? "???" : DECIMAL_FORMAT.format((float) TheEnd.zealotsKilled / TheEnd.eyes);
+ addComponent(new PlainTextComponent(Text.translatable("skyblocker.end.hud.zealotsSinceLastEye", endStats.zealotsSinceLastEye())));
+ addComponent(new PlainTextComponent(Text.translatable("skyblocker.end.hud.zealotsTotalKills", endStats.totalZealotKills())));
+ String avg = endStats.eyes() == 0 ? "???" : DECIMAL_FORMAT.format((float) endStats.totalZealotKills() / endStats.eyes());
addComponent(new PlainTextComponent(Text.translatable("skyblocker.end.hud.avgKillsPerEye", avg)));
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/end/TheEnd.java b/src/main/java/de/hysky/skyblocker/skyblock/end/TheEnd.java
index bbbc29e4..a87ac6d9 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/end/TheEnd.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/end/TheEnd.java
@@ -1,16 +1,16 @@
package de.hysky.skyblocker.skyblock.end;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
+import com.mojang.serialization.Codec;
+import com.mojang.serialization.codecs.RecordCodecBuilder;
import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.annotations.Init;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.events.SkyblockEvents;
import de.hysky.skyblocker.utils.ColorUtils;
import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.profile.ProfiledData;
import de.hysky.skyblocker.utils.waypoint.Waypoint;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents;
-import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
@@ -30,29 +30,16 @@ import net.minecraft.util.math.ChunkPos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.*;
-import java.util.concurrent.CompletableFuture;
public class TheEnd {
protected static final Logger LOGGER = LoggerFactory.getLogger(TheEnd.class);
+ private static final Path FILE = SkyblockerMod.CONFIG_DIR.resolve("end.json");
public static Set<UUID> hitZealots = new HashSet<>();
- public static int zealotsSinceLastEye = 0;
- public static int zealotsKilled = 0;
- public static int eyes = 0;
- /**
- * needs to be saved?
- */
- private static boolean dirty = false;
- private static String currentProfile = "";
- private static JsonObject PROFILES_STATS;
+ public static ProfiledData<EndStats> PROFILES_STATS = new ProfiledData<>(FILE, EndStats.CODEC);
- private static final Path FILE = SkyblockerMod.CONFIG_DIR.resolve("end.json");
public static List<ProtectorLocation> protectorLocations = List.of(
new ProtectorLocation(-649, -219, Text.translatable("skyblocker.end.hud.protectorLocations.left")),
new ProtectorLocation(-644, -269, Text.translatable("skyblocker.end.hud.protectorLocations.front")),
@@ -86,20 +73,12 @@ public class TheEnd {
if (isProtectorHere(world, protectorLocation)) break;
}
}
- if (currentProfile.isEmpty()) load(); // Wacky fix for when you join skyblock, and you are directly in the end (profile id isn't parsed yet most of the time)
}
-
-
});
+ // Fix for when you join skyblock, and you are directly in the end
+ SkyblockEvents.PROFILE_CHANGE.register((prev, profile) -> EndHudWidget.getInstance().update());
// Reset when changing island
- SkyblockEvents.LOCATION_CHANGE.register(location -> {
- resetLocation();
- save();
- load();
- EndHudWidget.getInstance().update();
- });
- // Save when leaving as well
- ClientLifecycleEvents.CLIENT_STOPPING.register((client) -> save());
+ SkyblockEvents.LOCATION_CHANGE.register(location -> resetLocation());
ClientReceiveMessageEvents.GAME.register((message, overlay) -> {
if (!Utils.isInTheEnd() || overlay) return;
@@ -115,7 +94,7 @@ public class TheEnd {
});
WorldRenderEvents.AFTER_TRANSLUCENT.register(TheEnd::renderWaypoint);
- ClientLifecycleEvents.CLIENT_STARTED.register((client -> loadFile()));
+ PROFILES_STATS.init();
}
private static void checkAllProtectorLocations() {
@@ -153,15 +132,13 @@ public class TheEnd {
public static void onEntityDeath(Entity entity) {
if (!(entity instanceof EndermanEntity enderman) || !isZealot(enderman)) return;
if (hitZealots.contains(enderman.getUuid())) {
- //MinecraftClient.getInstance().player.sendMessage(Text.literal("You killed a zealot!!!"));
+ EndStats stats = PROFILES_STATS.putIfAbsent(EndStats.EMPTY);
if (isSpecialZealot(enderman)) {
- zealotsSinceLastEye = 0;
- eyes++;
- }
- else zealotsSinceLastEye++;
- zealotsKilled++;
- dirty = true;
- hitZealots.remove(enderman.getUuid());
+ PROFILES_STATS.put(new EndStats(stats.totalZealotKills() + 1, 0, stats.eyes() + 1));
+ } else {
+ PROFILES_STATS.put(new EndStats(stats.totalZealotKills() + 1, stats.zealotsSinceLastEye() + 1, stats.eyes()));
+ }
+ hitZealots.remove(enderman.getUuid());
EndHudWidget.getInstance().update();
}
}
@@ -183,82 +160,21 @@ public class TheEnd {
return isZealot(enderman) && enderman.getCarriedBlock() != null && enderman.getCarriedBlock().isOf(Blocks.END_PORTAL_FRAME);
}
- /**
- * Loads if needed
- */
- public static void load() {
- if (!Utils.isOnSkyblock() || Utils.getProfileId().isEmpty()) return;
- String id = MinecraftClient.getInstance().getSession().getUuidOrNull().toString().replaceAll("-", "");
- String profile = Utils.getProfileId();
- if (!profile.equals(currentProfile) && PROFILES_STATS != null) {
- currentProfile = profile;
- JsonElement jsonElement = PROFILES_STATS.get(id);
- if (jsonElement == null) return;
- JsonElement jsonElement1 = jsonElement.getAsJsonObject().get(profile);
- if (jsonElement1 == null) return;
- zealotsKilled = jsonElement1.getAsJsonObject().get("totalZealotKills").getAsInt();
- zealotsSinceLastEye = jsonElement1.getAsJsonObject().get("zealotsSinceLastEye").getAsInt();
- eyes = jsonElement1.getAsJsonObject().get("eyes").getAsInt();
- EndHudWidget.getInstance().update();
- }
- }
-
- private static void loadFile() {
- CompletableFuture.runAsync(() -> {
- try (BufferedReader reader = Files.newBufferedReader(FILE)) {
- PROFILES_STATS = SkyblockerMod.GSON.fromJson(reader, JsonObject.class);
- LOGGER.debug("[Skyblocker End] Loaded end stats");
- } catch (NoSuchFileException ignored) {
- PROFILES_STATS = new JsonObject();
- } catch (Exception e) {
- LOGGER.error("[Skyblocker End] Failed to load end stats", e);
- }
- });
- }
-
- /**
- * Saves if dirty
- */
- public static void save() {
- if (dirty && PROFILES_STATS != null) {
- String uuid = MinecraftClient.getInstance().getSession().getUuidOrNull().toString().replaceAll("-", "");
- JsonObject jsonObject = PROFILES_STATS.getAsJsonObject(uuid);
- if (jsonObject == null) {
- PROFILES_STATS.add(uuid, new JsonObject());
- jsonObject = PROFILES_STATS.getAsJsonObject(uuid);
- }
-
- jsonObject.add(currentProfile, new JsonObject());
- JsonElement jsonElement1 = jsonObject.get(currentProfile);
-
- jsonElement1.getAsJsonObject().addProperty("totalZealotKills", zealotsKilled);
- jsonElement1.getAsJsonObject().addProperty("zealotsSinceLastEye", zealotsSinceLastEye);
- jsonElement1.getAsJsonObject().addProperty("eyes", eyes);
-
- if (Utils.isOnSkyblock()) {
- CompletableFuture.runAsync(TheEnd::performSave);
- } else {
- performSave();
- }
- }
- }
-
- private static void performSave() {
- try (BufferedWriter writer = Files.newBufferedWriter(FILE)) {
- SkyblockerMod.GSON.toJson(PROFILES_STATS, writer);
- LOGGER.info("[Skyblocker End] Saved end stats");
- dirty = false;
- } catch (Exception e) {
- LOGGER.error("[Skyblocker End] Failed to save end stats", e);
- }
- }
-
- private static void renderWaypoint(WorldRenderContext context) {
+ private static void renderWaypoint(WorldRenderContext context) {
if (!SkyblockerConfigManager.get().otherLocations.end.waypoint) return;
if (currentProtectorLocation == null || stage != 5) return;
currentProtectorLocation.waypoint().render(context);
}
+ public record EndStats(int totalZealotKills, int zealotsSinceLastEye, int eyes) {
+ private static final Codec<EndStats> CODEC = RecordCodecBuilder.create(instance -> instance.group(
+ Codec.INT.fieldOf("totalZealotKills").forGetter(EndStats::totalZealotKills),
+ Codec.INT.fieldOf("zealotsSinceLastEye").forGetter(EndStats::zealotsSinceLastEye),
+ Codec.INT.fieldOf("eyes").forGetter(EndStats::eyes)
+ ).apply(instance, EndStats::new));
+ public static final EndStats EMPTY = new EndStats(0, 0, 0);
+ }
+
public record ProtectorLocation(int x, int z, Text name, Waypoint waypoint) {
public ProtectorLocation(int x, int z, Text name) {
this(x, z, name, new Waypoint(new BlockPos(x, 0, z), Waypoint.Type.WAYPOINT, ColorUtils.getFloatComponents(DyeColor.MAGENTA)));
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemCooldowns.java b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemCooldowns.java
index cf0356bc..f9dd1705 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/ItemCooldowns.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/ItemCooldowns.java
@@ -58,7 +58,7 @@ public class ItemCooldowns {
public static void updateCooldown() {
PetInfo pet = PetCache.getCurrentPet();
- if (pet != null && pet.tier().equals("LEGENDARY")) {
+ if (pet != null && pet.tier().equals(SkyblockItemRarity.LEGENDARY)) {
monkeyExp = pet.exp();
monkeyLevel = 0;
@@ -172,4 +172,4 @@ public class ItemCooldowns {
return this.isOnCooldown() ? (float) this.getRemainingCooldown() / cooldown : 0.0f;
}
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java b/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java
index 7adda957..84ceb82c 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java
@@ -6,22 +6,22 @@ import com.google.gson.JsonParser;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.serialization.Codec;
-import com.mojang.serialization.JsonOps;
import com.mojang.serialization.codecs.RecordCodecBuilder;
+import com.mojang.util.UndashedUuid;
import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.annotations.Init;
+import de.hysky.skyblocker.events.SkyblockEvents;
import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.Http;
import de.hysky.skyblocker.utils.Http.ApiResponse;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
-import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import de.hysky.skyblocker.utils.profile.ProfiledData;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
-import net.minecraft.client.MinecraftClient;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.*;
@@ -31,15 +31,11 @@ import net.minecraft.util.collection.DefaultedList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.Base64;
import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
@@ -48,7 +44,7 @@ import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.lit
public class MuseumItemCache {
private static final Logger LOGGER = LoggerFactory.getLogger(MuseumItemCache.class);
private static final Path CACHE_FILE = SkyblockerMod.CONFIG_DIR.resolve("museum_item_cache.json");
- private static final Map<String, Object2ObjectOpenHashMap<String, ProfileMuseumData>> MUSEUM_ITEM_CACHE = new Object2ObjectOpenHashMap<>();
+ private static final ProfiledData<ProfileMuseumData> MUSEUM_ITEM_CACHE = new ProfiledData<>(CACHE_FILE, ProfileMuseumData.CODEC, true, true);
private static final String ERROR_LOG_TEMPLATE = "[Skyblocker] Failed to refresh museum item data for profile {}";
public static final String DONATION_CONFIRMATION_SCREEN_TITLE = "Confirm Donation";
private static final int CONFIRM_DONATION_BUTTON_SLOT = 20;
@@ -57,8 +53,9 @@ public class MuseumItemCache {
@Init
public static void init() {
- ClientLifecycleEvents.CLIENT_STARTED.register(MuseumItemCache::load);
+ ClientLifecycleEvents.CLIENT_STARTED.register(client -> loaded = MUSEUM_ITEM_CACHE.load());
ClientCommandRegistrationCallback.EVENT.register(MuseumItemCache::registerCommands);
+ SkyblockEvents.PROFILE_CHANGE.register((prev, profile) -> tick());
}
private static void registerCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
@@ -76,30 +73,6 @@ public class MuseumItemCache {
}))));
}
- private static void load(MinecraftClient client) {
- loaded = CompletableFuture.runAsync(() -> {
- try (BufferedReader reader = Files.newBufferedReader(CACHE_FILE)) {
- Map<String, Object2ObjectOpenHashMap<String, ProfileMuseumData>> cachedData = ProfileMuseumData.SERIALIZATION_CODEC.parse(JsonOps.INSTANCE, JsonParser.parseReader(reader)).getOrThrow();
-
- MUSEUM_ITEM_CACHE.putAll(cachedData);
- LOGGER.info("[Skyblocker] Loaded museum items cache");
- } catch (NoSuchFileException ignored) {
- } catch (IOException e) {
- LOGGER.error("[Skyblocker] Failed to load cached museum items", e);
- }
- });
- }
-
- private static void save() {
- CompletableFuture.runAsync(() -> {
- try (BufferedWriter writer = Files.newBufferedWriter(CACHE_FILE)) {
- SkyblockerMod.GSON.toJson(ProfileMuseumData.SERIALIZATION_CODEC.encodeStart(JsonOps.INSTANCE, MUSEUM_ITEM_CACHE).getOrThrow(), writer);
- } catch (IOException e) {
- LOGGER.error("[Skyblocker] Failed to save cached museum items!", e);
- }
- });
- }
-
public static void handleClick(Slot slot, int slotId, DefaultedList<Slot> slots) {
if (slotId == CONFIRM_DONATION_BUTTON_SLOT) {
//Slots 0 to 17 can have items, well not all but thats the general range
@@ -111,24 +84,19 @@ public class MuseumItemCache {
String profileId = Utils.getProfileId();
if (!itemId.isEmpty() && !profileId.isEmpty()) {
- String uuid = Utils.getUndashedUuid();
- //Be safe about access to avoid NPEs
- Map<String, ProfileMuseumData> playerData = MUSEUM_ITEM_CACHE.computeIfAbsent(uuid, _uuid -> new Object2ObjectOpenHashMap<>());
- playerData.putIfAbsent(profileId, ProfileMuseumData.EMPTY.get());
-
- playerData.get(profileId).collectedItemIds().add(itemId);
- save();
+ MUSEUM_ITEM_CACHE.putIfAbsent(ProfileMuseumData.EMPTY.get()).collectedItemIds().add(itemId);
+ MUSEUM_ITEM_CACHE.save();
}
}
}
}
}
- private static void updateData4ProfileMember(String uuid, String profileId) {
+ private static void updateData4ProfileMember(UUID uuid, String profileId) {
updateData4ProfileMember(uuid, profileId, null);
}
- private static void updateData4ProfileMember(String uuid, String profileId, FabricClientCommandSource source) {
+ private static void updateData4ProfileMember(UUID uuid, String profileId, FabricClientCommandSource source) {
CompletableFuture.runAsync(() -> {
try (ApiResponse response = Http.sendHypixelRequest("skyblock/museum", "?profile=" + profileId)) {
//The request was successful
@@ -136,8 +104,9 @@ public class MuseumItemCache {
JsonObject profileData = JsonParser.parseString(response.content()).getAsJsonObject();
JsonObject members = profileData.getAsJsonObject("members");
- if (members.has(uuid)) {
- JsonObject memberData = members.get(uuid).getAsJsonObject();
+ String uuidString = UndashedUuid.toString(uuid);
+ if (members.has(uuidString)) {
+ JsonObject memberData = members.get(uuidString).getAsJsonObject();
//We call them sets because it could either be a singular item or an entire armour set
Map<String, JsonElement> donatedSets = memberData.get("items").getAsJsonObject().asMap();
@@ -161,8 +130,8 @@ public class MuseumItemCache {
}
}
- MUSEUM_ITEM_CACHE.get(uuid).put(profileId, new ProfileMuseumData(System.currentTimeMillis(), itemIds));
- save();
+ MUSEUM_ITEM_CACHE.put(uuid, profileId, new ProfileMuseumData(System.currentTimeMillis(), itemIds));
+ MUSEUM_ITEM_CACHE.save();
if (source != null) source.sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.museum.resyncSuccess")));
@@ -194,21 +163,18 @@ public class MuseumItemCache {
});
}
- private static void putEmpty(String uuid, String profileId) {
+ private static void putEmpty(UUID uuid, String profileId) {
//Only put new data if they didn't have any before
- if (!MUSEUM_ITEM_CACHE.get(uuid).containsKey(profileId)) {
- MUSEUM_ITEM_CACHE.get(uuid).put(profileId, new ProfileMuseumData(System.currentTimeMillis(), ObjectOpenHashSet.of()));
- }
-
- save();
+ MUSEUM_ITEM_CACHE.computeIfAbsent(uuid, profileId, () -> new ProfileMuseumData(System.currentTimeMillis(), ObjectOpenHashSet.of()));
+ MUSEUM_ITEM_CACHE.save();
}
private static boolean tryResync(FabricClientCommandSource source) {
- String uuid = Utils.getUndashedUuid();
+ UUID uuid = Utils.getUuid();
String profileId = Utils.getProfileId();
//Only allow resyncing if the data is actually present yet, otherwise the player needs to swap servers for the tick method to be called
- if (loaded.isDone() && !profileId.isEmpty() && MUSEUM_ITEM_CACHE.containsKey(uuid) && MUSEUM_ITEM_CACHE.get(uuid).containsKey(profileId) && MUSEUM_ITEM_CACHE.get(uuid).get(profileId).canResync()) {
+ if (loaded.isDone() && !profileId.isEmpty() && MUSEUM_ITEM_CACHE.containsKey() && MUSEUM_ITEM_CACHE.get().canResync()) {
updateData4ProfileMember(uuid, profileId, source);
return true;
@@ -220,22 +186,18 @@ public class MuseumItemCache {
/**
* The cache is ticked upon switching Skyblock servers. Only loads from the API if the profile wasn't cached yet.
*/
- public static void tick(String profileId) {
- String uuid = Utils.getUndashedUuid();
+ public static void tick() {
+ UUID uuid = Utils.getUuid();
- if (loaded.isDone() && (!MUSEUM_ITEM_CACHE.containsKey(uuid) || !MUSEUM_ITEM_CACHE.getOrDefault(uuid, new Object2ObjectOpenHashMap<>()).containsKey(profileId))) {
- Map<String, ProfileMuseumData> playerData = MUSEUM_ITEM_CACHE.computeIfAbsent(uuid, _uuid -> new Object2ObjectOpenHashMap<>());
- playerData.putIfAbsent(profileId, ProfileMuseumData.EMPTY.get());
+ if (loaded.isDone() && !MUSEUM_ITEM_CACHE.containsKey()) {
+ MUSEUM_ITEM_CACHE.putIfAbsent(ProfileMuseumData.EMPTY.get());
- updateData4ProfileMember(uuid, profileId);
+ updateData4ProfileMember(uuid, Utils.getProfileId());
}
}
public static boolean hasItemInMuseum(String id) {
- String uuid = Utils.getUndashedUuid();
- ObjectOpenHashSet<String> collectedItemIds = (!MUSEUM_ITEM_CACHE.containsKey(uuid) || Utils.getProfileId().isBlank() || !MUSEUM_ITEM_CACHE.get(uuid).containsKey(Utils.getProfileId())) ? null : MUSEUM_ITEM_CACHE.get(uuid).get(Utils.getProfileId()).collectedItemIds();
-
- return collectedItemIds != null && collectedItemIds.contains(id);
+ return MUSEUM_ITEM_CACHE.containsKey() && MUSEUM_ITEM_CACHE.get().collectedItemIds().contains(id);
}
private record ProfileMuseumData(long lastResync, ObjectOpenHashSet<String> collectedItemIds) {
@@ -246,12 +208,8 @@ public class MuseumItemCache {
Codec.STRING.listOf()
.xmap(ObjectOpenHashSet::new, ObjectArrayList::new)
.fieldOf("collectedItemIds")
- .forGetter(i -> new ObjectOpenHashSet<>(i.collectedItemIds()))
+ .forGetter(ProfileMuseumData::collectedItemIds)
).apply(instance, ProfileMuseumData::new));
- //Mojang's internal Codec impleme