Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hidden relic helper #316

Merged
merged 5 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import me.xmrvizzy.skyblocker.skyblock.rift.TheRift;
import me.xmrvizzy.skyblocker.skyblock.shortcut.Shortcuts;
import me.xmrvizzy.skyblocker.skyblock.special.SpecialEffects;
import me.xmrvizzy.skyblocker.skyblock.spidersden.Relics;
import me.xmrvizzy.skyblocker.skyblock.tabhud.TabHud;
import me.xmrvizzy.skyblocker.skyblock.tabhud.screenbuilder.ScreenMaster;
import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr;
Expand Down Expand Up @@ -74,6 +75,7 @@ public void onInitializeClient() {
ItemRegistry.init();
NEURepo.init();
FairySouls.init();
Relics.init();
BackpackPreview.init();
QuickNav.init();
DwarvenHud.init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ public static class BarPositions {
public BarPosition defenceBarPosition = BarPosition.LAYER1;
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
public BarPosition experienceBarPosition = BarPosition.LAYER1;

}

public enum BarPosition {
Expand Down Expand Up @@ -315,6 +314,7 @@ public static class Fishing {
public static class FairySouls {
public boolean enableFairySoulsHelper = false;
public boolean highlightFoundSouls = true;
@ConfigEntry.Gui.Tooltip()
public boolean highlightOnlyNearbySouls = false;
}

Expand Down Expand Up @@ -449,6 +449,10 @@ public static class Locations {
@ConfigEntry.Category("rift")
@ConfigEntry.Gui.CollapsibleObject()
public Rift rift = new Rift();

@ConfigEntry.Category("spidersden")
@ConfigEntry.Gui.CollapsibleObject()
public SpidersDen spidersDen = new SpidersDen();
}

public static class Dungeons {
Expand Down Expand Up @@ -561,6 +565,17 @@ public static class Rift {
public int mcGrubberStacks = 0;
}

public static class SpidersDen {
@ConfigEntry.Category("relics")
@ConfigEntry.Gui.CollapsibleObject()
public Relics relics = new Relics();
}

public static class Relics {
public boolean enableRelicsHelper = false;
public boolean highlightFoundRelics = true;
}

public static class Slayer {
@ConfigEntry.Category("vampire")
@ConfigEntry.Gui.CollapsibleObject()
Expand Down
119 changes: 65 additions & 54 deletions src/main/java/me/xmrvizzy/skyblocker/skyblock/FairySouls.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@
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.NEURepo;
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 @@ -37,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 @@ -50,9 +55,16 @@ public static int getFairySoulsSize(@Nullable String location) {
}

public static void init() {
loadFairySouls();
ClientLifecycleEvents.CLIENT_STOPPING.register(FairySouls::saveFoundFairySouls);
ClientCommandRegistrationCallback.EVENT.register(FairySouls::registerCommands);
WorldRenderEvents.AFTER_TRANSLUCENT.register(FairySouls::render);
ClientReceiveMessageEvents.GAME.register(FairySouls::onChatMessage);
}

private static void loadFairySouls() {
fairySoulsLoaded = NEURepo.runAsyncAfterLoad(() -> {
try {
BufferedReader reader = new BufferedReader(new FileReader(NEURepo.LOCAL_REPO_DIR.resolve("constants").resolve("fairy_souls.json").toFile()));
try (BufferedReader reader = new BufferedReader(new FileReader(NEURepo.LOCAL_REPO_DIR.resolve("constants").resolve("fairy_souls.json").toFile()))) {
for (Map.Entry<String, JsonElement> fairySoulJson : JsonParser.parseReader(reader).getAsJsonObject().asMap().entrySet()) {
if (fairySoulJson.getKey().equals("//") || fairySoulJson.getKey().equals("Max Souls")) {
if (fairySoulJson.getKey().equals("Max Souls")) {
Expand All @@ -62,80 +74,78 @@ public static void init() {
}
ImmutableSet.Builder<BlockPos> fairySoulsForLocation = ImmutableSet.builder();
for (JsonElement fairySoul : fairySoulJson.getValue().getAsJsonArray().asList()) {
fairySoulsForLocation.add(parseBlockPos(fairySoul));
fairySoulsForLocation.add(PosUtils.parsePosString(fairySoul.getAsString()));
}
fairySouls.put(fairySoulJson.getKey(), fairySoulsForLocation.build());
}
reader = new BufferedReader(new FileReader(SkyblockerMod.CONFIG_DIR.resolve("found_fairy_souls.json").toFile()));
LOGGER.debug("[Skyblocker] Loaded fairy soul locations");
} catch (IOException e) {
LOGGER.error("[Skyblocker] Failed to load fairy soul locations", e);
}

try (BufferedReader reader = new BufferedReader(new FileReader(SkyblockerMod.CONFIG_DIR.resolve("found_fairy_souls.json").toFile()))) {
for (Map.Entry<String, JsonElement> foundFairiesForProfileJson : JsonParser.parseReader(reader).getAsJsonObject().asMap().entrySet()) {
Map<String, Set<BlockPos>> foundFairiesForProfile = new HashMap<>();
for (Map.Entry<String, JsonElement> foundFairiesForLocationJson : foundFairiesForProfileJson.getValue().getAsJsonObject().asMap().entrySet()) {
Set<BlockPos> foundFairiesForLocation = new HashSet<>();
for (JsonElement foundFairy : foundFairiesForLocationJson.getValue().getAsJsonArray().asList()) {
foundFairiesForLocation.add(parseBlockPos(foundFairy));
foundFairiesForLocation.add(PosUtils.parsePosString(foundFairy.getAsString()));
}
foundFairiesForProfile.put(foundFairiesForLocationJson.getKey(), foundFairiesForLocation);
}
foundFairies.put(foundFairiesForProfileJson.getKey(), foundFairiesForProfile);
}
reader.close();
LOGGER.debug("[Skyblocker] Loaded found fairy souls");
} catch (FileNotFoundException ignored) {
} catch (IOException e) {
LOGGER.error("Failed to load found fairy souls", e);
} catch (Exception e) {
LOGGER.error("Encountered unknown exception loading fairy souls", e);
LOGGER.error("[Skyblocker] Failed to load found fairy souls", e);
}
});

ClientLifecycleEvents.CLIENT_STOPPING.register(FairySouls::saveFoundFairySouls);
WorldRenderEvents.AFTER_TRANSLUCENT.register(FairySouls::render);
ClientReceiveMessageEvents.GAME.register(FairySouls::onChatMessage);
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> dispatcher.register(literal(SkyblockerMod.NAMESPACE)
.then(literal("fairySouls")
.then(literal("markAllInCurrentIslandFound").executes(context -> {
FairySouls.markAllFairiesFound();
context.getSource().sendFeedback(Text.translatable("skyblocker.fairySouls.markAllFound"));
return 1;
}))
.then(literal("markAllInCurrentIslandMissing").executes(context -> {
FairySouls.markAllFairiesNotFound();
context.getSource().sendFeedback(Text.translatable("skyblocker.fairySouls.markAllMissing"));
return 1;
})))));
}

private static BlockPos parseBlockPos(JsonElement posJson) {
String[] posArray = posJson.getAsString().split(",");
return new BlockPos(Integer.parseInt(posArray[0]), Integer.parseInt(posArray[1]), Integer.parseInt(posArray[2]));
}

public static void saveFoundFairySouls(MinecraftClient client) {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(SkyblockerMod.CONFIG_DIR.resolve("found_fairy_souls.json").toFile()));
private static void saveFoundFairySouls(MinecraftClient client) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(SkyblockerMod.CONFIG_DIR.resolve("found_fairy_souls.json").toFile()))) {
JsonObject foundFairiesJson = new JsonObject();
for (Map.Entry<String, Map<String, Set<BlockPos>>> foundFairiesForProfile : foundFairies.entrySet()) {
JsonObject foundFairiesForProfileJson = new JsonObject();
for (Map.Entry<String, Set<BlockPos>> foundFairiesForLocation : foundFairiesForProfile.getValue().entrySet()) {
JsonArray foundFairiesForLocationJson = new JsonArray();
for (BlockPos foundFairy : foundFairiesForLocation.getValue()) {
foundFairiesForLocationJson.add(foundFairy.getX() + "," + foundFairy.getY() + "," + foundFairy.getZ());
foundFairiesForLocationJson.add(PosUtils.getPosString(foundFairy));
}
foundFairiesForProfileJson.add(foundFairiesForLocation.getKey(), foundFairiesForLocationJson);
}
foundFairiesJson.add(foundFairiesForProfile.getKey(), foundFairiesForProfileJson);
}
SkyblockerMod.GSON.toJson(foundFairiesJson, writer);
writer.close();
LOGGER.info("[Skyblocker] Saved found fairy souls");
} catch (IOException e) {
LOGGER.error("Failed to write found fairy souls to file.");
LOGGER.error("[Skyblocker] Failed to write found fairy souls to file", e);
}
}

public static void render(WorldRenderContext context) {
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;
}))));
}

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 @@ -145,33 +155,22 @@ public 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);
}

public static void onChatMessage(Text text, boolean overlay) {
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!")) {
markClosestFairyFound();
}
}

private static void markClosestFairyFound() {
if (!fairySoulsLoaded.isDone()) return;
PlayerEntity player = MinecraftClient.getInstance().player;
if (player == null) {
LOGGER.warn("Failed to mark closest fairy soul as found because player is 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)
.filter(FairySouls::isFairySoulMissing)
.min(Comparator.comparingDouble(fairySoulPos -> fairySoulPos.getSquaredDistance(player.getPos())))
.filter(fairySoulPos -> fairySoulPos.getSquaredDistance(player.getPos()) <= 16)
.ifPresent(fairySoulPos -> {
Expand All @@ -180,12 +179,24 @@ private static void markClosestFairyFound() {
});
}

public static void markAllFairiesFound() {
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() {
initializeFoundFairiesForCurrentProfileAndLocation();
foundFairies.get(Utils.getProfile()).get(Utils.getLocationRaw()).addAll(fairySouls.get(Utils.getLocationRaw()));
}

public static void markAllFairiesNotFound() {
public static void markAllFairiesOnCurrentIslandMissing() {
Map<String, Set<BlockPos>> foundFairiesForProfile = foundFairies.get(Utils.getProfile());
if (foundFairiesForProfile != null) {
foundFairiesForProfile.remove(Utils.getLocationRaw());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ protected static void loadShortcuts() {
LOGGER.info("[Skyblocker] Loaded {} command shortcuts and {} command argument shortcuts", commands.size(), commandArgs.size());
} catch (FileNotFoundException e) {
registerDefaultShortcuts();
LOGGER.warn("[Skyblocker] Shortcuts file not found, using default shortcuts. This is normal when using for the first time.", e);
LOGGER.warn("[Skyblocker] Shortcuts file not found, using default shortcuts. This is normal when using for the first time.");
} catch (IOException e) {
LOGGER.error("[Skyblocker] Failed to load shortcuts file", e);
}
Expand Down