From e23a93bab7678b54d57062908dd0e9b780b8ba3f Mon Sep 17 00:00:00 2001
From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com>
Date: Sun, 17 Sep 2023 21:47:37 -0400
Subject: Refactor FairySouls and Relics

---
 .../xmrvizzy/skyblocker/skyblock/FairySouls.java   |  68 +++++------
 .../skyblocker/skyblock/spidersden/Relics.java     | 130 ++++++++++++++-------
 .../resources/assets/skyblocker/lang/en_us.json    |  14 ++-
 3 files changed, 128 insertions(+), 84 deletions(-)

(limited to 'src/main')

diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/FairySouls.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/FairySouls.java
index 5ad6eb83..fcd6be7a 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/FairySouls.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/FairySouls.java
@@ -41,6 +41,7 @@ public class FairySouls {
     private static final Map<String, Set<BlockPos>> fairySouls = new HashMap<>();
     private static final Map<String, Map<String, Set<BlockPos>>> foundFairies = new HashMap<>();
 
+    @SuppressWarnings("UnusedReturnValue")
     public static CompletableFuture<Void> runAsyncAfterFairySoulsLoad(Runnable runnable) {
         if (fairySoulsLoaded == null) {
             LOGGER.error("Fairy Souls have not being initialized yet! Please ensure the Fairy Souls module is initialized before modules calling this method in SkyblockerMod#onInitializeClient. This error can be safely ignore in a test environment.");
@@ -56,9 +57,9 @@ public class FairySouls {
     public static void init() {
         loadFairySouls();
         ClientLifecycleEvents.CLIENT_STOPPING.register(FairySouls::saveFoundFairySouls);
-        ClientReceiveMessageEvents.GAME.register(FairySouls::onChatMessage);
-        WorldRenderEvents.AFTER_TRANSLUCENT.register(FairySouls::render);
         ClientCommandRegistrationCallback.EVENT.register(FairySouls::registerCommands);
+        WorldRenderEvents.AFTER_TRANSLUCENT.register(FairySouls::render);
+        ClientReceiveMessageEvents.GAME.register(FairySouls::onChatMessage);
     }
 
     private static void loadFairySouls() {
@@ -126,17 +127,17 @@ public class FairySouls {
 
     private static void registerCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
         dispatcher.register(literal(SkyblockerMod.NAMESPACE)
-            .then(literal("fairySouls")
-                .then(literal("markAllInCurrentIslandFound").executes(context -> {
-                    FairySouls.markAllFairiesOnCurrentIslandFound();
-                    context.getSource().sendFeedback(Text.translatable("skyblocker.fairySouls.markAllFound"));
-                    return 1;
-                }))
-                .then(literal("markAllInCurrentIslandMissing").executes(context -> {
-                    FairySouls.markAllFairiesOnCurrentIslandMissing();
-                    context.getSource().sendFeedback(Text.translatable("skyblocker.fairySouls.markAllMissing"));
-                    return 1;
-                }))));
+                .then(literal("fairySouls")
+                        .then(literal("markAllInCurrentIslandFound").executes(context -> {
+                            FairySouls.markAllFairiesOnCurrentIslandFound();
+                            context.getSource().sendFeedback(Text.translatable("skyblocker.fairySouls.markAllFound"));
+                            return 1;
+                        }))
+                        .then(literal("markAllInCurrentIslandMissing").executes(context -> {
+                            FairySouls.markAllFairiesOnCurrentIslandMissing();
+                            context.getSource().sendFeedback(Text.translatable("skyblocker.fairySouls.markAllMissing"));
+                            return 1;
+                        }))));
     }
 
     private static void render(WorldRenderContext context) {
@@ -144,7 +145,7 @@ public class FairySouls {
 
         if (fairySoulsConfig.enableFairySoulsHelper && fairySoulsLoaded.isDone() && fairySouls.containsKey(Utils.getLocationRaw())) {
             for (BlockPos fairySoulPos : fairySouls.get(Utils.getLocationRaw())) {
-                boolean fairySoulNotFound = isFairySoulNotFound(fairySoulPos);
+                boolean fairySoulNotFound = isFairySoulMissing(fairySoulPos);
                 if (!fairySoulsConfig.highlightFoundSouls && !fairySoulNotFound || fairySoulsConfig.highlightOnlyNearbySouls && fairySoulPos.getSquaredDistance(context.camera().getPos()) > 2500) {
                     continue;
                 }
@@ -154,18 +155,6 @@ public class FairySouls {
         }
     }
 
-    private static boolean isFairySoulNotFound(BlockPos fairySoulPos) {
-        Map<String, Set<BlockPos>> foundFairiesForProfile = foundFairies.get(Utils.getProfile());
-        if (foundFairiesForProfile == null) {
-            return true;
-        }
-        Set<BlockPos> foundFairiesForProfileAndLocation = foundFairiesForProfile.get(Utils.getLocationRaw());
-        if (foundFairiesForProfileAndLocation == null) {
-            return true;
-        }
-        return !foundFairiesForProfileAndLocation.contains(fairySoulPos);
-    }
-
     private static void onChatMessage(Text text, boolean overlay) {
         String message = text.getString();
         if (message.equals("You have already found that Fairy Soul!") || message.equals("§d§lSOUL! §fYou found a §dFairy Soul§f!")) {
@@ -174,19 +163,32 @@ public class FairySouls {
     }
 
     private static void markClosestFairyFound() {
+        if (!fairySoulsLoaded.isDone()) return;
         PlayerEntity player = MinecraftClient.getInstance().player;
         if (player == null) {
             LOGGER.warn("[Skyblocker] Failed to mark closest fairy soul as found because player is null");
             return;
         }
         fairySouls.get(Utils.getLocationRaw()).stream()
-            .filter(FairySouls::isFairySoulNotFound)
-            .min(Comparator.comparingDouble(fairySoulPos -> fairySoulPos.getSquaredDistance(player.getPos())))
-            .filter(fairySoulPos -> fairySoulPos.getSquaredDistance(player.getPos()) <= 16)
-            .ifPresent(fairySoulPos -> {
-                initializeFoundFairiesForCurrentProfileAndLocation();
-                foundFairies.get(Utils.getProfile()).get(Utils.getLocationRaw()).add(fairySoulPos);
-            });
+                .filter(FairySouls::isFairySoulMissing)
+                .min(Comparator.comparingDouble(fairySoulPos -> fairySoulPos.getSquaredDistance(player.getPos())))
+                .filter(fairySoulPos -> fairySoulPos.getSquaredDistance(player.getPos()) <= 16)
+                .ifPresent(fairySoulPos -> {
+                    initializeFoundFairiesForCurrentProfileAndLocation();
+                    foundFairies.get(Utils.getProfile()).get(Utils.getLocationRaw()).add(fairySoulPos);
+                });
+    }
+
+    private static boolean isFairySoulMissing(BlockPos fairySoulPos) {
+        Map<String, Set<BlockPos>> foundFairiesForProfile = foundFairies.get(Utils.getProfile());
+        if (foundFairiesForProfile == null) {
+            return true;
+        }
+        Set<BlockPos> foundFairiesForProfileAndLocation = foundFairiesForProfile.get(Utils.getLocationRaw());
+        if (foundFairiesForProfileAndLocation == null) {
+            return true;
+        }
+        return !foundFairiesForProfileAndLocation.contains(fairySoulPos);
     }
 
     public static void markAllFairiesOnCurrentIslandFound() {
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/spidersden/Relics.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/spidersden/Relics.java
index 885d5d1c..12ce0715 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/spidersden/Relics.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/spidersden/Relics.java
@@ -4,16 +4,20 @@ import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
+import com.mojang.brigadier.CommandDispatcher;
 import me.xmrvizzy.skyblocker.SkyblockerMod;
 import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
 import me.xmrvizzy.skyblocker.utils.PosUtils;
 import me.xmrvizzy.skyblocker.utils.Utils;
 import me.xmrvizzy.skyblocker.utils.render.RenderHelper;
+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.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;
 import net.minecraft.client.MinecraftClient;
+import net.minecraft.command.CommandRegistryAccess;
 import net.minecraft.entity.player.PlayerEntity;
 import net.minecraft.text.Text;
 import net.minecraft.util.DyeColor;
@@ -24,50 +28,58 @@ import org.slf4j.LoggerFactory;
 
 import java.io.*;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
+
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
 
 public class Relics {
     private static final Logger LOGGER = LoggerFactory.getLogger(Relics.class);
+    private static CompletableFuture<Void> relicsLoaded;
+    @SuppressWarnings({"unused", "FieldCanBeLocal"})
     private static int totalRelics = 0;
     private static final List<BlockPos> relics = new ArrayList<>();
     private static final Map<String, Set<BlockPos>> foundRelics = new HashMap<>();
 
     public static void init() {
-        ClientLifecycleEvents.CLIENT_STARTED.register(Relics::onClientStarted);
+        ClientLifecycleEvents.CLIENT_STARTED.register(Relics::loadRelics);
         ClientLifecycleEvents.CLIENT_STOPPING.register(Relics::saveFoundRelics);
-        ClientReceiveMessageEvents.GAME.register(Relics::onChatMessage);
+        ClientCommandRegistrationCallback.EVENT.register(Relics::registerCommands);
         WorldRenderEvents.AFTER_TRANSLUCENT.register(Relics::render);
+        ClientReceiveMessageEvents.GAME.register(Relics::onChatMessage);
     }
 
-    private static void onClientStarted(MinecraftClient client) {
-        try (BufferedReader reader = client.getResourceManager().openAsReader(new Identifier(SkyblockerMod.NAMESPACE, "spidersden/relics.json"))) {
-            for (Map.Entry<String, JsonElement> json : JsonParser.parseReader(reader).getAsJsonObject().asMap().entrySet()) {
-                if (json.getKey().equals("total")) {
-                    totalRelics = json.getValue().getAsInt();
-                } else if (json.getKey().equals("locations")) {
-                    for (JsonElement locationJson : json.getValue().getAsJsonArray().asList()) {
-                        JsonObject posData = locationJson.getAsJsonObject();
-                        relics.add(new BlockPos(posData.get("x").getAsInt(), posData.get("y").getAsInt(), posData.get("z").getAsInt()));
+    private static void loadRelics(MinecraftClient client) {
+        relicsLoaded = CompletableFuture.runAsync(() -> {
+            try (BufferedReader reader = client.getResourceManager().openAsReader(new Identifier(SkyblockerMod.NAMESPACE, "spidersden/relics.json"))) {
+                for (Map.Entry<String, JsonElement> json : JsonParser.parseReader(reader).getAsJsonObject().asMap().entrySet()) {
+                    if (json.getKey().equals("total")) {
+                        totalRelics = json.getValue().getAsInt();
+                    } else if (json.getKey().equals("locations")) {
+                        for (JsonElement locationJson : json.getValue().getAsJsonArray().asList()) {
+                            JsonObject posData = locationJson.getAsJsonObject();
+                            relics.add(new BlockPos(posData.get("x").getAsInt(), posData.get("y").getAsInt(), posData.get("z").getAsInt()));
+                        }
                     }
                 }
+                LOGGER.info("[Skyblocker] Loaded relics locations");
+            } catch (IOException e) {
+                LOGGER.error("[Skyblocker] Failed to load relics locations", e);
             }
-            LOGGER.info("[Skyblocker] Loaded relics locations");
-        } catch (IOException e) {
-            LOGGER.error("[Skyblocker] Failed to load relics locations", e);
-        }
 
-        try (BufferedReader reader = new BufferedReader(new FileReader(SkyblockerMod.CONFIG_DIR.resolve("found_relics.json").toFile()))) {
-            for (Map.Entry<String, JsonElement> profileJson : JsonParser.parseReader(reader).getAsJsonObject().asMap().entrySet()) {
-                Set<BlockPos> foundRelicsForProfile = new HashSet<>();
-                for (JsonElement foundRelicsJson : profileJson.getValue().getAsJsonArray().asList()) {
-                    foundRelicsForProfile.add(PosUtils.parsePosString(foundRelicsJson.getAsString()));
+            try (BufferedReader reader = new BufferedReader(new FileReader(SkyblockerMod.CONFIG_DIR.resolve("found_relics.json").toFile()))) {
+                for (Map.Entry<String, JsonElement> profileJson : JsonParser.parseReader(reader).getAsJsonObject().asMap().entrySet()) {
+                    Set<BlockPos> foundRelicsForProfile = new HashSet<>();
+                    for (JsonElement foundRelicsJson : profileJson.getValue().getAsJsonArray().asList()) {
+                        foundRelicsForProfile.add(PosUtils.parsePosString(foundRelicsJson.getAsString()));
+                    }
+                    foundRelics.put(profileJson.getKey(), foundRelicsForProfile);
                 }
-                foundRelics.put(profileJson.getKey(), foundRelicsForProfile);
+                LOGGER.debug("[Skyblocker] Loaded found relics");
+            } catch (FileNotFoundException ignored) {
+            } catch (IOException e) {
+                LOGGER.error("[Skyblocker] Failed to load found relics", e);
             }
-            LOGGER.debug("[Skyblocker] Loaded found relics");
-        } catch (FileNotFoundException ignored) {
-        } catch (IOException e) {
-            LOGGER.error("[Skyblocker] Failed to load found relics", e);
-        }
+        });
     }
 
     private static void saveFoundRelics(MinecraftClient client) {
@@ -87,44 +99,72 @@ public class Relics {
         }
     }
 
-    private static void onChatMessage(Text text, boolean overlay) {
-        String message = text.getString();
-        if (message.equals("You've already found this relic!") || message.startsWith("+10,000 Coins! (") && message.endsWith("/28 Relics)")) {
-            markClosestRelicFound();
-        }
+    private static void registerCommands(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
+        dispatcher.register(literal(SkyblockerMod.NAMESPACE)
+                .then(literal("relics")
+                        .then(literal("markAllFound").executes(context -> {
+                            Relics.markAllFound();
+                            context.getSource().sendFeedback(Text.translatable("skyblocker.relics.markAllFound"));
+                            return 1;
+                        }))
+                        .then(literal("markAllMissing").executes(context -> {
+                            Relics.markAllMissing();
+                            context.getSource().sendFeedback(Text.translatable("skyblocker.relics.markAllMissing"));
+                            return 1;
+                        }))));
     }
 
     private static void render(WorldRenderContext context) {
         SkyblockerConfig.Relics config = SkyblockerConfig.get().locations.spidersDen.relics;
 
-        if (config.enableRelicsHelper && Utils.getLocationRaw().equals("combat_1")) {
+        if (config.enableRelicsHelper && relicsLoaded.isDone() && Utils.getLocationRaw().equals("combat_1")) {
             for (BlockPos fairySoulPos : relics) {
-                boolean isRelicFound = isRelicFound(fairySoulPos);
-                if (isRelicFound && !config.highlightFoundRelics) continue;
-                float[] colorComponents = isRelicFound ? DyeColor.BROWN.getColorComponents() : DyeColor.YELLOW.getColorComponents();
+                boolean isRelicMissing = isRelicMissing(fairySoulPos);
+                if (!isRelicMissing && !config.highlightFoundRelics) continue;
+                float[] colorComponents = isRelicMissing ? DyeColor.YELLOW.getColorComponents() : DyeColor.BROWN.getColorComponents();
                 RenderHelper.renderFilledThroughWallsWithBeaconBeam(context, fairySoulPos, colorComponents, 0.5F);
             }
         }
     }
 
-    private static boolean isRelicFound(BlockPos pos) {
-        Set<BlockPos> foundRelicsForProfile = foundRelics.get(Utils.getProfile());
-        return (foundRelicsForProfile == null) ? false : foundRelicsForProfile.contains(pos);
+    private static void onChatMessage(Text text, boolean overlay) {
+        String message = text.getString();
+        if (message.equals("You've already found this relic!") || message.startsWith("+10,000 Coins! (") && message.endsWith("/28 Relics)")) {
+            markClosestRelicFound();
+        }
     }
 
     private static void markClosestRelicFound() {
+        if (!relicsLoaded.isDone()) return;
         PlayerEntity player = MinecraftClient.getInstance().player;
         if (player == null) {
             LOGGER.warn("[Skyblocker] Failed to mark closest relic as found because player is null");
             return;
         }
         relics.stream()
-            .filter((relicPos) -> !Relics.isRelicFound(relicPos))
-            .min(Comparator.comparingDouble(relicPos -> relicPos.getSquaredDistance(player.getPos())))
-            .filter(relicPos -> relicPos.getSquaredDistance(player.getPos()) <= 16)
-            .ifPresent(relicPos -> {
-                foundRelics.computeIfAbsent(Utils.getProfile(), profileKey -> new HashSet<>());
-                foundRelics.get(Utils.getProfile()).add(relicPos);
-            });
+                .filter(Relics::isRelicMissing)
+                .min(Comparator.comparingDouble(relicPos -> relicPos.getSquaredDistance(player.getPos())))
+                .filter(relicPos -> relicPos.getSquaredDistance(player.getPos()) <= 16)
+                .ifPresent(relicPos -> {
+                    foundRelics.computeIfAbsent(Utils.getProfile(), profileKey -> new HashSet<>());
+                    foundRelics.get(Utils.getProfile()).add(relicPos);
+                });
+    }
+
+    private static boolean isRelicMissing(BlockPos relicPos) {
+        Set<BlockPos> foundRelicsForProfile = foundRelics.get(Utils.getProfile());
+        return foundRelicsForProfile == null || !foundRelicsForProfile.contains(relicPos);
+    }
+
+    private static void markAllFound() {
+        foundRelics.computeIfAbsent(Utils.getProfile(), profileKey -> new HashSet<>());
+        foundRelics.get(Utils.getProfile()).addAll(relics);
+    }
+
+    private static void markAllMissing() {
+        Set<BlockPos> foundRelicsForProfile = foundRelics.get(Utils.getProfile());
+        if (foundRelicsForProfile != null) {
+            foundRelicsForProfile.clear();
+        }
     }
 }
diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json
index d8d10507..273cbb31 100644
--- a/src/main/resources/assets/skyblocker/lang/en_us.json
+++ b/src/main/resources/assets/skyblocker/lang/en_us.json
@@ -209,10 +209,10 @@
   "text.autoconfig.skyblocker.option.locations.barn": "Barn",
   "text.autoconfig.skyblocker.option.locations.barn.solveHungryHiker": "Solve Hungry Hiker",
   "text.autoconfig.skyblocker.option.locations.barn.solveTreasureHunter": "Solve Treasure Hunter",
-  "text.autoconfig.skyblocker.option.locations.spidersden": "Spider's Den",
-  "text.autoconfig.skyblocker.option.locations.spidersden.relics": "Hidden Relics Helper",
-  "text.autoconfig.skyblocker.option.locations.spidersden.relics.enableRelicsHelper": "Enable Hidden Relics Helper",
-  "text.autoconfig.skyblocker.option.locations.spidersden.relics.highlightFoundRelics": "Highlight found relics",
+  "text.autoconfig.skyblocker.option.locations.spidersDen": "Spider's Den",
+  "text.autoconfig.skyblocker.option.locations.spidersDen.relics": "Hidden Relics Helper",
+  "text.autoconfig.skyblocker.option.locations.spidersDen.relics.enableRelicsHelper": "Enable Hidden Relics Helper",
+  "text.autoconfig.skyblocker.option.locations.spidersDen.relics.highlightFoundRelics": "Highlight found relics",
   "text.autoconfig.skyblocker.option.locations.dungeons": "Dungeons",
   "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints": "Dungeon Secret Waypoints",
   "text.autoconfig.skyblocker.option.locations.dungeons.secretWaypoints.enableSecretWaypoints": "Enable Dungeon Secret Waypoints",
@@ -330,8 +330,10 @@
   "skyblocker.rift.iceNow": "Ice now!",
   "skyblocker.rift.mania": "Mania!",
   "skyblocker.rift.stakeNow": "Stake now!",
-  "skyblocker.fairySouls.markAllFound": "Marked all fairy souls in the current island as found",
-  "skyblocker.fairySouls.markAllMissing": "Marked all fairy souls in the current island as missing",
+  "skyblocker.fairySouls.markAllFound": "§b[§6Skyblocker§b] §rMarked all fairy souls in the current island as found",
+  "skyblocker.fairySouls.markAllMissing": "§b[§6Skyblocker§b] §rMarked all fairy souls in the current island as missing",
+  "skyblocker.relics.markAllFound": "§b[§6Skyblocker§b] §rMarked all relics as found",
+  "skyblocker.relics.markAllMissing": "§b[§6Skyblocker§b] §rMarked all relics as missing",
   "skyblocker.shortcuts.config": "Shortcuts Config",
   "skyblocker.shortcuts.notLoaded": "§c§lShortcuts not loaded yet",
   "skyblocker.shortcuts.command.target": "Target Command",
-- 
cgit