Skip to content

Commit

Permalink
Refactor FairySouls and Relics
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinthegreat1 committed Sep 18, 2023
1 parent b0f8a76 commit e23a93b
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 84 deletions.
68 changes: 35 additions & 33 deletions src/main/java/me/xmrvizzy/skyblocker/skyblock/FairySouls.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
Expand All @@ -56,9 +57,9 @@ public static int getFairySoulsSize(@Nullable String location) {
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() {
Expand Down Expand Up @@ -126,25 +127,25 @@ private static void saveFoundFairySouls(MinecraftClient client) {

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) {
SkyblockerConfig.FairySouls fairySoulsConfig = SkyblockerConfig.get().general.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;
}
Expand All @@ -154,18 +155,6 @@ private static void render(WorldRenderContext context) {
}
}

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!")) {
Expand All @@ -174,19 +163,32 @@ private static void onChatMessage(Text text, boolean overlay) {
}

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() {
Expand Down
130 changes: 85 additions & 45 deletions src/main/java/me/xmrvizzy/skyblocker/skyblock/spidersden/Relics.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@
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;
Expand All @@ -24,50 +28,58 @@

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) {
Expand All @@ -87,44 +99,72 @@ private static void saveFoundRelics(MinecraftClient client) {
}
}

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();
}
}
}
Loading

0 comments on commit e23a93b

Please sign in to comment.