aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorKevin <92656833+kevinthegreat1@users.noreply.github.com>2024-04-03 22:51:32 -0400
committerGitHub <noreply@github.com>2024-04-03 22:51:32 -0400
commitbbf544b63a8bb06395f8120c615f36657b64c18d (patch)
treefd7384f271d54998353050d1f4c54e2309e963b3 /src/main
parent97a5b8a5e37f9c6701d1096d21912c270e65715e (diff)
parent69d925788dcb7ef23157acdd97e184b66f08e622 (diff)
downloadSkyblocker-bbf544b63a8bb06395f8120c615f36657b64c18d.tar.gz
Skyblocker-bbf544b63a8bb06395f8120c615f36657b64c18d.tar.bz2
Skyblocker-bbf544b63a8bb06395f8120c615f36657b64c18d.zip
Merge pull request #613 from AzureAaron/accessories-helper
Accessories Helper
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/de/hysky/skyblocker/SkyblockerMod.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java3
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java10
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/AccessoriesHelper.java222
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java24
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java31
-rw-r--r--src/main/resources/assets/skyblocker/lang/en_us.json7
7 files changed, 292 insertions, 7 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
index 64f1bf37..4b562574 100644
--- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
+++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
@@ -26,6 +26,7 @@ import de.hysky.skyblocker.skyblock.garden.FarmingHud;
import de.hysky.skyblocker.skyblock.garden.LowerSensitivity;
import de.hysky.skyblocker.skyblock.garden.VisitorHelper;
import de.hysky.skyblocker.skyblock.item.*;
+import de.hysky.skyblocker.skyblock.item.tooltip.AccessoriesHelper;
import de.hysky.skyblocker.skyblock.item.tooltip.BackpackPreview;
import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip;
import de.hysky.skyblocker.skyblock.itemlist.ItemRepository;
@@ -103,6 +104,7 @@ public class SkyblockerMod implements ClientModInitializer {
PlayerHeadHashCache.init();
HotbarSlotLock.init();
ItemTooltip.init();
+ AccessoriesHelper.init();
WikiLookup.init();
FairySouls.init();
Relics.init();
diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java
index 644e97f2..06ac748a 100644
--- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java
+++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java
@@ -561,6 +561,9 @@ public class SkyblockerConfig {
@SerialEntry
public boolean enableExoticTooltip = true;
+
+ @SerialEntry
+ public boolean enableAccessoriesHelper = true;
}
public static class ItemInfoDisplay {
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java
index adcb27a1..e310cb85 100644
--- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java
+++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java
@@ -449,6 +449,16 @@ public class GeneralCategory {
newValue -> config.general.itemTooltip.enableExoticTooltip = newValue)
.controller(ConfigUtils::createBooleanController)
.build())
+ .option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper"))
+ .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[0]"), Text.literal("\n\n✔ Collected").formatted(Formatting.GREEN), Text.translatable("text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[1]"),
+ Text.literal("\n✦ Upgrade").withColor(0x218bff), Text.translatable("text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[2]"), Text.literal("\n↑ Upgradable").withColor(0xf8d048), Text.translatable("text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[3]"),
+ Text.literal("\n↓ Downgrade").formatted(Formatting.GRAY), Text.translatable("text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[4]"), Text.literal("\n✖ Missing").formatted(Formatting.RED), Text.translatable("text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[5]")))
+ .binding(defaults.general.itemTooltip.enableAccessoriesHelper,
+ () -> config.general.itemTooltip.enableAccessoriesHelper,
+ newValue -> config.general.itemTooltip.enableAccessoriesHelper = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
.build())
//Item Info Display
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/AccessoriesHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/AccessoriesHelper.java
new file mode 100644
index 00000000..69bc6f1c
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/AccessoriesHelper.java
@@ -0,0 +1,222 @@
+package de.hysky.skyblocker.skyblock.item.tooltip;
+
+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.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalInt;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Predicate;
+import java.util.function.ToIntFunction;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import org.slf4j.Logger;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.mojang.logging.LogUtils;
+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.utils.ItemUtils;
+import de.hysky.skyblocker.utils.Utils;
+import it.unimi.dsi.fastutil.Pair;
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
+import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
+import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
+import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
+import net.minecraft.screen.GenericContainerScreenHandler;
+import net.minecraft.screen.slot.Slot;
+
+public class AccessoriesHelper {
+ private static final Logger LOGGER = LogUtils.getLogger();
+ private static final Path FILE = SkyblockerMod.CONFIG_DIR.resolve("collected_accessories.json");
+ private static final Pattern ACCESSORY_BAG_TITLE = Pattern.compile("Accessory Bag \\((?<page>\\d+)/\\d+\\)");
+ //UUID -> Profile Id & Data
+ private static final Object2ObjectOpenHashMap<String, Object2ObjectOpenHashMap<String, ProfileAccessoryData>> COLLECTED_ACCESSORIES = new Object2ObjectOpenHashMap<>();
+ private static final Predicate<String> NON_EMPTY = s -> !s.isEmpty();
+ private static final Predicate<Accessory> HAS_FAMILY = Accessory::hasFamily;
+ private static final ToIntFunction<Accessory> ACCESSORY_TIER = Accessory::tier;
+
+ private static Map<String, Accessory> ACCESSORY_DATA = new Object2ObjectOpenHashMap<>();
+ //remove??
+ private static CompletableFuture<Void> loaded;
+
+ public static void init() {
+ ClientLifecycleEvents.CLIENT_STARTED.register((_client) -> load());
+ ClientLifecycleEvents.CLIENT_STOPPING.register((_client) -> save());
+ ScreenEvents.BEFORE_INIT.register((_client, screen, _scaledWidth, _scaledHeight) -> {
+ if (Utils.isOnSkyblock() && TooltipInfoType.ACCESSORIES.isTooltipEnabled() && !Utils.getProfileId().isEmpty() && screen instanceof GenericContainerScreen genericContainerScreen) {
+ Matcher matcher = ACCESSORY_BAG_TITLE.matcher(genericContainerScreen.getTitle().getString());
+
+ if (matcher.matches()) {
+ ScreenEvents.afterTick(screen).register(_screen -> {
+ GenericContainerScreenHandler handler = genericContainerScreen.getScreenHandler();
+
+ collectAccessories(handler.slots.subList(0, handler.getRows() * 9), Integer.parseInt(matcher.group("page")));
+ });
+ }
+ }
+ });
+ }
+
+ //Note: JsonOps.COMPRESSED must be used if you're using maps with non-string keys
+ private static void load() {
+ loaded = CompletableFuture.runAsync(() -> {
+ try (BufferedReader reader = Files.newBufferedReader(FILE)) {
+ COLLECTED_ACCESSORIES.putAll(ProfileAccessoryData.SERIALIZATION_CODEC.parse(JsonOps.COMPRESSED, JsonParser.parseReader(reader)).result().orElseThrow());
+ } catch (NoSuchFileException ignored) {
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker Accessory Helper] Failed to load accessory file!", e);
+ }
+ });
+ }
+
+ private static void save() {
+ try (BufferedWriter writer = Files.newBufferedWriter(FILE)) {
+ SkyblockerMod.GSON.toJson(ProfileAccessoryData.SERIALIZATION_CODEC.encodeStart(JsonOps.COMPRESSED, COLLECTED_ACCESSORIES).result().orElseThrow(), writer);
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker Accessory Helper] Failed to save accessory file!", e);
+ }
+ }
+
+ private static void collectAccessories(List<Slot> slots, int page) {
+ //Is this even needed?
+ if (!loaded.isDone()) return;
+
+ List<String> accessoryIds = slots.stream()
+ .map(Slot::getStack)
+ .map(ItemUtils::getItemId)
+ .filter(NON_EMPTY)
+ .toList();
+
+ String uuid = UndashedUuid.toString(MinecraftClient.getInstance().getSession().getUuidOrNull());
+
+ COLLECTED_ACCESSORIES.computeIfAbsent(uuid, _uuid -> new Object2ObjectOpenHashMap<>()).computeIfAbsent(Utils.getProfileId(), profileId -> ProfileAccessoryData.createDefault()).pages()
+ .put(page, new ObjectOpenHashSet<>(accessoryIds));
+ }
+
+ static Pair<AccessoryReport, String> calculateReport4Accessory(String accessoryId) {
+ if (!ACCESSORY_DATA.containsKey(accessoryId) || Utils.getProfileId().isEmpty()) return Pair.of(AccessoryReport.INELIGIBLE, null);
+
+ Accessory accessory = ACCESSORY_DATA.get(accessoryId);
+ String uuid = UndashedUuid.toString(MinecraftClient.getInstance().getSession().getUuidOrNull());
+ Set<Accessory> collectedAccessories = COLLECTED_ACCESSORIES.computeIfAbsent(uuid, _uuid -> new Object2ObjectOpenHashMap<>()).computeIfAbsent(Utils.getProfileId(), profileId -> ProfileAccessoryData.createDefault()).pages().values().stream()
+ .flatMap(ObjectOpenHashSet::stream)
+ .filter(ACCESSORY_DATA::containsKey)
+ .map(ACCESSORY_DATA::get)
+ .collect(Collectors.toSet());
+
+ //If the player has this accessory, and it doesn't belong to a family
+ if (collectedAccessories.contains(accessory) && accessory.family().isEmpty()) return Pair.of(AccessoryReport.HAS_HIGHEST_TIER, null);
+
+ Predicate<Accessory> HAS_SAME_FAMILY = accessory::hasSameFamily;
+ Set<Accessory> collectedAccessoriesInTheSameFamily = collectedAccessories.stream()
+ .filter(HAS_FAMILY)
+ .filter(HAS_SAME_FAMILY)
+ .collect(Collectors.toSet());
+
+ //If the player doesn't have any collected accessories with same family
+ if (collectedAccessoriesInTheSameFamily.isEmpty()) return Pair.of(AccessoryReport.MISSING, null);
+
+ Set<Accessory> accessoriesInTheSameFamily = ACCESSORY_DATA.values().stream()
+ .filter(HAS_FAMILY)
+ .filter(HAS_SAME_FAMILY)
+ .collect(Collectors.toSet());
+
+ ///If the player has the highest tier accessory in this family
+ //Take the accessories in the same family as {@code accessory}, then get the one with the highest tier
+ Optional<Accessory> highestTierOfFamily = accessoriesInTheSameFamily.stream()
+ .max(Comparator.comparingInt(ACCESSORY_TIER));
+ int maxTierInFamily = highestTierOfFamily.orElse(Accessory.EMPTY).tier();
+
+ if (collectedAccessoriesInTheSameFamily.stream().anyMatch(ca -> ca.tier() == maxTierInFamily)) return Pair.of(AccessoryReport.HAS_HIGHEST_TIER, null);
+
+ //If this accessory is a higher tier than all the other collected accessories in the same family
+ OptionalInt highestTierOfAllCollectedInFamily = collectedAccessoriesInTheSameFamily.stream()
+ .mapToInt(ACCESSORY_TIER)
+ .max();
+
+ if (accessory.tier() > highestTierOfAllCollectedInFamily.getAsInt()) return Pair.of(AccessoryReport.IS_GREATER_TIER, String.format("(%d→%d/%d)", highestTierOfAllCollectedInFamily.orElse(0), accessory.tier(), maxTierInFamily));
+
+ //If this accessory is a lower tier than one already obtained from same family
+ if (accessory.tier() < highestTierOfAllCollectedInFamily.getAsInt()) return Pair.of(AccessoryReport.OWNS_BETTER_TIER, String.format("(%d→%d/%d)", highestTierOfAllCollectedInFamily.orElse(0), accessory.tier(), maxTierInFamily));
+
+ //If there is an accessory in the same family that has a higher tier
+ //Take the accessories in the same family, then check if there is an accessory whose tier is greater than {@code accessory}
+ boolean hasGreaterTierInFamily = accessoriesInTheSameFamily.stream()
+ .anyMatch(ca -> ca.tier() > accessory.tier());
+
+ if (hasGreaterTierInFamily) return Pair.of(AccessoryReport.HAS_GREATER_TIER, String.format("(%d/%d)", highestTierOfAllCollectedInFamily.orElse(0), maxTierInFamily));
+
+ return Pair.of(AccessoryReport.MISSING, null);
+ }
+
+ static void refreshData(JsonObject data) {
+ try {
+ ACCESSORY_DATA = Accessory.MAP_CODEC.parse(JsonOps.INSTANCE, data).result().orElseThrow();
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker Accessory Helper] Failed to parse data!", e);
+ }
+ }
+
+ private record ProfileAccessoryData(Int2ObjectOpenHashMap<ObjectOpenHashSet<String>> pages) {
+ private static final Codec<ProfileAccessoryData> CODEC = RecordCodecBuilder.create(instance -> instance.group(
+ Codec.unboundedMap(Codec.INT, Codec.STRING.listOf().xmap(ObjectOpenHashSet::new, ObjectArrayList::new))
+ .xmap(Int2ObjectOpenHashMap::new, Int2ObjectOpenHashMap::new).fieldOf("pages").forGetter(ProfileAccessoryData::pages))
+ .apply(instance, ProfileAccessoryData::new));
+ private static final Codec<Object2ObjectOpenHashMap<String, Object2ObjectOpenHashMap<String, ProfileAccessoryData>>> SERIALIZATION_CODEC = Codec.unboundedMap(Codec.STRING, Codec.unboundedMap(Codec.STRING, CODEC)
+ .xmap(Object2ObjectOpenHashMap::new, Object2ObjectOpenHashMap::new))
+ .xmap(Object2ObjectOpenHashMap::new, Object2ObjectOpenHashMap::new);
+
+ private static ProfileAccessoryData createDefault() {
+ return new ProfileAccessoryData(new Int2ObjectOpenHashMap<>());
+ }
+ }
+
+ /**
+ * @author AzureAaron
+ * @implSpec <a href="https://github.com/AzureAaron/aaron-mod/blob/1.20/src/main/java/net/azureaaron/mod/commands/MagicalPowerCommand.java#L475">Aaron's Mod</a>
+ */
+ private record Accessory(String id, Optional<String> family, int tier) {
+ private static final Codec<Accessory> CODEC = RecordCodecBuilder.create(instance -> instance.group(
+ Codec.STRING.fieldOf("id").forGetter(Accessory::id),
+ Codec.STRING.optionalFieldOf("family").forGetter(Accessory::family),
+ Codec.INT.optionalFieldOf("tier", 0).forGetter(Accessory::tier))
+ .apply(instance, Accessory::new));
+ private static final Codec<Map<String, Accessory>> MAP_CODEC = Codec.unboundedMap(Codec.STRING, CODEC);
+ private static final Accessory EMPTY = new Accessory("", Optional.empty(), 0);
+
+ private boolean hasFamily() {
+ return family.isPresent();
+ }
+
+ private boolean hasSameFamily(Accessory other) {
+ return other.family().equals(this.family);
+ }
+ }
+
+ enum AccessoryReport {
+ HAS_HIGHEST_TIER, //You've collected the highest tier - Collected
+ IS_GREATER_TIER, //This accessory is an upgrade from the one in the same family that you already have - Upgrade -- Shows you what tier this accessory is in its family
+ HAS_GREATER_TIER, //This accessory has a higher tier upgrade - Upgradable -- Shows you the highest tier accessory you've collected in that family
+ OWNS_BETTER_TIER, //You've collected an accessory in this family with a higher tier - Downgrade -- Shows you the highest tier accessory you've collected in that family
+ MISSING, //You don't have any accessories in this family - Missing
+ INELIGIBLE
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java
index 1b3f402d..637aea22 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java
@@ -5,10 +5,12 @@ import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.config.SkyblockerConfig;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.skyblock.item.MuseumItemCache;
+import de.hysky.skyblocker.skyblock.item.tooltip.AccessoriesHelper.AccessoryReport;
import de.hysky.skyblocker.utils.Constants;
import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.Utils;
import de.hysky.skyblocker.utils.scheduler.Scheduler;
+import it.unimi.dsi.fastutil.Pair;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.DyeableItem;
@@ -238,6 +240,27 @@ public class ItemTooltip {
}
}
}
+
+ if (TooltipInfoType.ACCESSORIES.isTooltipEnabledAndHasOrNullWarning(internalID)) {
+ Pair<AccessoryReport, String> report = AccessoriesHelper.calculateReport4Accessory(internalID);
+
+ if (report.left() != AccessoryReport.INELIGIBLE) {
+ MutableText title = Text.literal(String.format("%-19s", "Accessory: ")).withColor(0xf57542);
+
+ Text stateText = switch (report.left()) {
+ case HAS_HIGHEST_TIER -> Text.literal("✔ Collected").formatted(Formatting.GREEN);
+ case IS_GREATER_TIER -> Text.literal("✦ Upgrade ").withColor(0x218bff).append(Text.literal(report.right()).withColor(0xf8f8ff));
+ case HAS_GREATER_TIER -> Text.literal("↑ Upgradable ").withColor(0xf8d048).append(Text.literal(report.right()).withColor(0xf8f8ff));
+ case OWNS_BETTER_TIER -> Text.literal("↓ Downgrade ").formatted(Formatting.GRAY).append(Text.literal(report.right()).withColor(0xf8f8ff));
+ case MISSING -> Text.literal("✖ Missing").formatted(Formatting.RED);
+
+ //Should never be the case
+ default -> Text.literal("? Unknown").formatted(Formatting.GRAY);
+ };
+
+ lines.add(title.append(stateText));
+ }
+ }
}
private static void addExoticTooltip(List<Text> lines, String internalID, NbtCompound nbt, String colorHex, String expectedHex, String existingTooltip) {
@@ -390,6 +413,7 @@ public class ItemTooltip {
TooltipInfoType.MOTES.downloadIfEnabled(futureList);
TooltipInfoType.MUSEUM.downloadIfEnabled(futureList);
TooltipInfoType.COLOR.downloadIfEnabled(futureList);
+ TooltipInfoType.ACCESSORIES.downloadIfEnabled(futureList);
CompletableFuture.allOf(futureList.toArray(CompletableFuture[]::new)).exceptionally(e -> {
LOGGER.error("Encountered unknown error while downloading tooltip data", e);
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java
index 4aba040d..6edee8d6 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java
@@ -6,13 +6,15 @@ import de.hysky.skyblocker.config.SkyblockerConfig;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.utils.Http;
import de.hysky.skyblocker.utils.Utils;
-import org.jetbrains.annotations.Nullable;
import java.net.http.HttpHeaders;
import java.util.List;
import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
import java.util.function.Predicate;
+import org.jetbrains.annotations.Nullable;
+
public enum TooltipInfoType implements Runnable {
NPC("https://hysky.de/api/npcprice", itemTooltip -> itemTooltip.enableNPCPrice, true),
BAZAAR("https://hysky.de/api/bazaar", itemTooltip -> itemTooltip.enableBazaarPrice || SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().general.chestValue.enableChestValue, itemTooltip -> itemTooltip.enableBazaarPrice, false),
@@ -22,7 +24,8 @@ public enum TooltipInfoType implements Runnable {
MOTES("https://hysky.de/api/motesprice", itemTooltip -> itemTooltip.enableMotesPrice, itemTooltip -> itemTooltip.enableMotesPrice && Utils.isInTheRift(), true),
OBTAINED(itemTooltip -> itemTooltip.enableObtainedDate),
MUSEUM("https://hysky.de/api/museum", itemTooltip -> itemTooltip.enableMuseumInfo, true),
- COLOR("https://hysky.de/api/color", itemTooltip -> itemTooltip.enableExoticTooltip, true);
+ COLOR("https://hysky.de/api/color", itemTooltip -> itemTooltip.enableExoticTooltip, true),
+ ACCESSORIES("https://hysky.de/api/accessories", itemTooltip -> itemTooltip.enableAccessoriesHelper, true, AccessoriesHelper::refreshData);
private final String address;
private final Predicate<SkyblockerConfig.ItemTooltip> dataEnabled;
@@ -30,12 +33,23 @@ public enum TooltipInfoType implements Runnable {
private JsonObject data;
private final boolean cacheable;
private long hash;
+ private final Consumer<JsonObject> callback;
/**
* Use this for when you're adding tooltip info that has no data associated with it
*/
TooltipInfoType(Predicate<SkyblockerConfig.ItemTooltip> enabled) {
- this(null, itemTooltip -> false, enabled, null, false);
+ this(null, itemTooltip -> false, enabled, false, null);
+ }
+
+ /**
+ * @param address the address to download the data from
+ * @param enabled the predicate to check if the data should be downloaded and the tooltip should be shown
+ * @param cacheable whether the data should be cached
+ * @param callback called when the {@code data} is refreshed
+ */
+ TooltipInfoType(String address, Predicate<SkyblockerConfig.ItemTooltip> enabled, boolean cacheable, Consumer<JsonObject> callback) {
+ this(address, enabled, enabled, cacheable, callback);
}
/**
@@ -44,7 +58,7 @@ public enum TooltipInfoType implements Runnable {
* @param cacheable whether the data should be cached
*/
TooltipInfoType(String address, Predicate<SkyblockerConfig.ItemTooltip> enabled, boolean cacheable) {
- this(address, enabled, enabled, null, cacheable);
+ this(address, enabled, enabled, cacheable, null);
}
/**
@@ -54,7 +68,7 @@ public enum TooltipInfoType implements Runnable {
* @param cacheable whether the data should be cached
*/
TooltipInfoType(String address, Predicate<SkyblockerConfig.ItemTooltip> dataEnabled, Predicate<SkyblockerConfig.ItemTooltip> tooltipEnabled, boolean cacheable) {
- this(address, dataEnabled, tooltipEnabled, null, cacheable);
+ this(address, dataEnabled, tooltipEnabled, cacheable, null);
}
/**
@@ -64,12 +78,13 @@ public enum TooltipInfoType implements Runnable {
* @param data the data
* @param cacheable whether the data should be cached
*/
- TooltipInfoType(String address, Predicate<SkyblockerConfig.ItemTooltip> dataEnabled, Predicate<SkyblockerConfig.ItemTooltip> tooltipEnabled, @Nullable JsonObject data, boolean cacheable) {
+ TooltipInfoType(String address, Predicate<SkyblockerConfig.ItemTooltip> dataEnabled, Predicate<SkyblockerConfig.ItemTooltip> tooltipEnabled, boolean cacheable, @Nullable Consumer<JsonObject> callback) {
this.address = address;
this.dataEnabled = dataEnabled;
this.tooltipEnabled = tooltipEnabled;
- this.data = data;
+ this.data = null;
this.cacheable = cacheable;
+ this.callback = callback;
}
/**
@@ -146,6 +161,8 @@ public enum TooltipInfoType implements Runnable {
else this.hash = hash;
}
data = SkyblockerMod.GSON.fromJson(Http.sendGetRequest(address), JsonObject.class);
+
+ if (callback != null) callback.accept(data);
} catch (Exception e) {
ItemTooltip.LOGGER.warn("[Skyblocker] Failed to download " + this + " prices!", e);
}
diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json
index 9ed5e4d0..4587a647 100644
--- a/src/main/resources/assets/skyblocker/lang/en_us.json
+++ b/src/main/resources/assets/skyblocker/lang/en_us.json
@@ -90,6 +90,13 @@
"text.autoconfig.skyblocker.option.general.itemTooltip.enableMuseumInfo.@Tooltip": "If this item is donatable to the museum, then the item's category in the musuem is displayed. It also displays a marker indicating whether you've donated that item to your musuem or not (freebies not yet supported).\n\nMake sure to enable your Museum API for accurate information!",
"text.autoconfig.skyblocker.option.general.itemTooltip.enableExoticTooltip": "Enable Exotic Tooltip",
"text.autoconfig.skyblocker.option.general.itemTooltip.enableExoticTooltip.@Tooltip": "Displays the type of exotic below the item's name if an armor piece is exotic.",
+ "text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper": "Enable Accessories Helper",
+ "text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[0]": "When hovering over an accessory you are informed about whether you already have it or not, and whether it's worse than what you have already collected or better. List of Statuses:",
+ "text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[1]": "You have the highest tier accessory from that family.",
+ "text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[2]": "This accessory is an upgrade from the one in the same family that you already have. Also shows you what tier this accessory is in it's family.",
+ "text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[3]": "This accessory can be upgraded. Also tells you what tier of accessory you have in that family.",
+ "text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[4]": "You already own an accessory in the same family that is better than this one. Also tells you what tier of accessory you have in that family.",
+ "text.autoconfig.skyblocker.option.general.itemTooltip.enableAccessoriesHelper.@Tooltip[5]": "You don't own any accessory from this family.",
"text.autoconfig.skyblocker.option.general.dungeonQuality": "Dungeon Quality",
"text.autoconfig.skyblocker.option.general.dungeonQuality.@Tooltip": "Displays quality and tier of dungeon drops from mobs.\n\n\nReminder:\nTier 1-3 dropped from F1-F3\nTier 4-7 dropped from F4-F7 or M1-M4\nTier 8-10 are dropped only from M5-M7",
"text.autoconfig.skyblocker.option.general.enableNewYearCakesHelper": "Enable New Year Cakes Helper",