diff options
| author | Kevin <92656833+kevinthegreat1@users.noreply.github.com> | 2025-07-09 14:12:37 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-09 02:12:37 -0400 |
| commit | cb5f8faf39fee4077543c2599120e951be79c5c4 (patch) | |
| tree | 22358532225d9530dcc41f648502de2906ae20aa /src/main/java | |
| parent | 325538abeb2b85bd531b0deae94885838b9ea800 (diff) | |
| download | Skyblocker-cb5f8faf39fee4077543c2599120e951be79c5c4.tar.gz Skyblocker-cb5f8faf39fee4077543c2599120e951be79c5c4.tar.bz2 Skyblocker-cb5f8faf39fee4077543c2599120e951be79c5c4.zip | |
Refactor NEURepoManager (#1480)
* Refactor NEURepoManager
* Clear ItemRepository caches
* Fix import
Diffstat (limited to 'src/main/java')
12 files changed, 354 insertions, 281 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/ItemPickupWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/ItemPickupWidget.java index b6f5265b..9ca0d1b3 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/ItemPickupWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/ItemPickupWidget.java @@ -59,13 +59,12 @@ public class ItemPickupWidget extends ComponentBasedWidget { */ private static ItemStack getItem(String itemName) { if (NEURepoManager.isLoading() || !ItemRepository.filesImported()) return new ItemStack(Items.BARRIER); - return NEURepoManager.NEU_REPO.getItems().getItems() - .values().stream() - .filter(item -> Formatting.strip(item.getDisplayName()).equals(itemName)) + return NEURepoManager.getItemByName(itemName) + .stream() .findFirst() .map(NEUItem::getSkyblockItemId) .map(ItemRepository::getItemStack) - .orElse(new ItemStack(Items.BARRIER)); + .orElseGet(() -> new ItemStack(Items.BARRIER)); } /** diff --git a/src/main/java/de/hysky/skyblocker/skyblock/SackItemAutocomplete.java b/src/main/java/de/hysky/skyblocker/skyblock/SackItemAutocomplete.java index 8646300c..7168b24d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/SackItemAutocomplete.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/SackItemAutocomplete.java @@ -44,7 +44,7 @@ public class SackItemAutocomplete { } private static void loadSackItems() { - try (InputStream stream = NEURepoManager.NEU_REPO.file("constants/sacks.json").stream()) { + try (InputStream stream = NEURepoManager.file("constants/sacks.json").stream()) { JsonObject sacks = JsonParser.parseString(new String(stream.readAllBytes())).getAsJsonObject().getAsJsonObject("sacks"); Set<String> sackItemIds = sacks.entrySet().stream() @@ -56,7 +56,7 @@ public class SackItemAutocomplete { .collect(Collectors.toUnmodifiableSet()); Set<String> sackItems = sackItemIds.stream() .map(neuId -> { - NEUItem stack = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(neuId); + NEUItem stack = NEURepoManager.getItemByNeuId(neuId); return stack != null ? Formatting.strip(stack.getDisplayName()) : neuId; }) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chat/SackMessagePrice.java b/src/main/java/de/hysky/skyblocker/skyblock/chat/SackMessagePrice.java index 57205e6f..565d3346 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chat/SackMessagePrice.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chat/SackMessagePrice.java @@ -9,7 +9,6 @@ import de.hysky.skyblocker.utils.NEURepoManager; import de.hysky.skyblocker.utils.RegexUtils; import io.github.moulberry.repo.data.NEUItem; import it.unimi.dsi.fastutil.objects.*; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientWorldEvents; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.screen.ScreenTexts; import net.minecraft.text.HoverEvent.ShowText; @@ -36,21 +35,9 @@ import java.util.regex.Pattern; public class SackMessagePrice { private static final Pattern ITEM_COUNT_PATTERN = Pattern.compile("([-+][\\d,]+)"); private static final Logger LOGGER = LoggerFactory.getLogger(SackMessagePrice.class); - /** - * <p> - * Cache that holds item name to NEU ID mappings. - * This helps over time when farming similar items in the same world, as it avoids repeated lookups in a very large item list. - * The Sack message is only sent like every 30s in a normal farming case, so there's not much performance impact anyway, but it still helps. - * </p> - * <p> - * Additionally, there are 2 identical hover events per message, and they are processed separately, so this cache will be hit at least once per message, cutting the lookup time in half or more. - * </p> - */ - private static final Object2ObjectOpenHashMap<String, String> NAME_2_ID_CACHE = new Object2ObjectOpenHashMap<>(); @Init public static void init() { - ClientWorldEvents.AFTER_CLIENT_WORLD_CHANGE.register(((client, world) -> NAME_2_ID_CACHE.clear())); ClientReceiveMessageEvents.MODIFY_GAME.register(SackMessagePrice::onMessage); } @@ -156,19 +143,14 @@ public class SackMessagePrice { @Nullable private static String getNeuId(@NotNull String itemName) { - return NAME_2_ID_CACHE.computeIfAbsent(itemName, ignored -> - NEURepoManager.NEU_REPO.getItems() - .getItems() - .values() - .stream() - .filter(item -> Formatting.strip(item.getDisplayName()).equals(itemName)) - .findFirst() - .map(NEUItem::getSkyblockItemId) - .orElseGet(() -> { - LOGGER.warn("Failed to find item ID for item: {}", itemName); - return null; // This won't be entered into the cache, nor will it be used to calculate the price - }) - ); + return NEURepoManager.getItemByName(itemName) + .stream() + .findFirst() + .map(NEUItem::getSkyblockItemId) + .orElseGet(() -> { + LOGGER.warn("Failed to find the NEU item ID for item: {}", itemName); + return null; // This won't be used to calculate the price + }); } @NotNull diff --git a/src/main/java/de/hysky/skyblocker/skyblock/garden/visitor/VisitorHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/garden/visitor/VisitorHelper.java index 49085eb1..b26c44ee 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/garden/visitor/VisitorHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/garden/visitor/VisitorHelper.java @@ -141,9 +141,8 @@ public class VisitorHelper { return cachedItems.computeIfAbsent(cleanName, name -> { if (NEURepoManager.isLoading() || !ItemRepository.filesImported()) return null; - return NEURepoManager.NEU_REPO.getItems().getItems() - .values().stream() - .filter(item -> Formatting.strip(item.getDisplayName()).equals(name)) + return NEURepoManager.getItemByName(itemName) + .stream() .findFirst() .map(NEUItem::getSkyblockItemId) .map(ItemRepository::getItemStack) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/CraftPriceTooltip.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/CraftPriceTooltip.java index 35171251..2dbd65a5 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/CraftPriceTooltip.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/CraftPriceTooltip.java @@ -41,7 +41,7 @@ public class CraftPriceTooltip extends SimpleTooltipAdder { return; } - NEUItem neuItem = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(stack.getNeuName()); + NEUItem neuItem = NEURepoManager.getItemByNeuId(stack.getNeuName()); if (neuItem == null) return; List<NEURecipe> neuRecipes = neuItem.getRecipes(); @@ -87,7 +87,7 @@ public class CraftPriceTooltip extends SimpleTooltipAdder { cachedCraftCosts.put(inputItemName, itemCost); } - NEUItem neuItem = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(inputItemName); + NEUItem neuItem = NEURepoManager.getItemByNeuId(inputItemName); if (neuItem != null) { List<NEURecipe> neuRecipes = neuItem.getRecipes(); if (!neuRecipes.isEmpty()) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java index ac58cdcf..f304d03f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java @@ -7,10 +7,10 @@ import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockRecipe; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.NEURepoManager; import io.github.moulberry.repo.data.NEUCraftingRecipe; +import io.github.moulberry.repo.data.NEUForgeRecipe; import io.github.moulberry.repo.data.NEUItem; import io.github.moulberry.repo.data.NEURecipe; import io.github.moulberry.repo.util.NEUId; -import io.github.moulberry.repo.data.*; import net.minecraft.item.ItemStack; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -20,127 +20,137 @@ import java.util.*; import java.util.stream.Stream; public class ItemRepository { - protected static final Logger LOGGER = LoggerFactory.getLogger(ItemRepository.class); + protected static final Logger LOGGER = LoggerFactory.getLogger(ItemRepository.class); - private static final List<ItemStack> items = new ArrayList<>(); - private static final Map<String, ItemStack> itemsMap = new HashMap<>(); - private static final List<SkyblockRecipe> recipes = new ArrayList<>(); + private static final List<ItemStack> items = new ArrayList<>(); + private static final Map<String, ItemStack> itemsMap = new HashMap<>(); + private static final List<SkyblockRecipe> recipes = new ArrayList<>(); private static final HashMap<String, @NEUId String> bazaarStocks = new HashMap<>(); - private static boolean filesImported = false; - - @Init - public static void init() { - NEURepoManager.runAsyncAfterLoad(ItemStackBuilder::loadPetNums); - NEURepoManager.runAsyncAfterLoad(ItemRepository::importItemFiles); + /** + * Consumers must check this field when accessing `items` and `itemsMap`, or else thread safety is not guaranteed. + */ + private static boolean itemsImported = false; + /** + * Consumers must check this field when accessing `recipes`, or else thread safety is not guaranteed. + */ + private static boolean filesImported = false; + + @Init + public static void init() { + NEURepoManager.runAsyncAfterLoad(ItemStackBuilder::loadPetNums); + NEURepoManager.runAsyncAfterLoad(ItemRepository::importItemFiles); NEURepoManager.runAsyncAfterLoad(ItemRepository::loadBazaarStocks); - } - - private static void importItemFiles() { - NEURepoManager.NEU_REPO.getItems().getItems().values().forEach(ItemRepository::loadItem); - NEURepoManager.NEU_REPO.getItems().getItems().values().forEach(ItemRepository::loadRecipes); - - items.sort((lhs, rhs) -> { - String lhsInternalName = ItemUtils.getItemId(lhs); - String lhsFamilyName = lhsInternalName.replaceAll(".\\d+$", ""); - String rhsInternalName = ItemUtils.getItemId(rhs); - String rhsFamilyName = rhsInternalName.replaceAll(".\\d+$", ""); - if (lhsFamilyName.equals(rhsFamilyName)) { - if (lhsInternalName.length() != rhsInternalName.length()) - return lhsInternalName.length() - rhsInternalName.length(); - else return lhsInternalName.compareTo(rhsInternalName); - } - return lhsFamilyName.compareTo(rhsFamilyName); - }); - filesImported = true; - } - - private static void loadItem(NEUItem item) { - try { - ItemStack stack = ItemStackBuilder.fromNEUItem(item); - StackOverlays.applyOverlay(item, stack); - - items.add(stack); - itemsMap.put(item.getSkyblockItemId(), stack); - } catch (Exception e) { - LOGGER.error("[Skyblocker Item Repo Loader] Failed to load item, please report this! Skyblock Id: {}", item.getSkyblockItemId(), e); - } - } - - private static void loadRecipes(NEUItem item) { - item.getRecipes().stream().map(ItemRepository::toSkyblockRecipe).filter(Objects::nonNull).forEach(recipes::add); - } + } + + private static void importItemFiles() { + itemsImported = false; + filesImported = false; + + items.clear(); + itemsMap.clear(); + recipes.clear(); + + NEURepoManager.forEachItem(ItemRepository::loadItem); + items.sort(Comparator.<ItemStack, String>comparing(stack -> ItemUtils.getItemId(stack).replaceAll(".\\d+$", "")) + .thenComparingInt(stack -> ItemUtils.getItemId(stack).length()) + .thenComparing(ItemUtils::getItemId) + ); + itemsImported = true; + + NEURepoManager.forEachItem(ItemRepository::loadRecipes); + filesImported = true; + } + + private static void loadItem(NEUItem item) { + try { + ItemStack stack = ItemStackBuilder.fromNEUItem(item); + StackOverlays.applyOverlay(item, stack); + + items.add(stack); + itemsMap.put(item.getSkyblockItemId(), stack); + } catch (Exception e) { + LOGGER.error("[Skyblocker Item Repo Loader] Failed to load item, please report this! Skyblock Id: {}", item.getSkyblockItemId(), e); + } + } + + private static void loadRecipes(NEUItem item) { + item.getRecipes().stream().map(ItemRepository::toSkyblockRecipe).filter(Objects::nonNull).forEach(recipes::add); + } private static void loadBazaarStocks() { bazaarStocks.clear(); - NEURepoManager.NEU_REPO.getConstants().getBazaarStocks().getStocks().forEach((String neuId, String skyblockId) -> bazaarStocks.put(skyblockId, neuId)); - } - - public static String getWikiLink(String neuId, boolean useOfficial) { - NEUItem item = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(neuId); - if (item == null || item.getInfo() == null || item.getInfo().isEmpty()) { - return null; - } - - List<String> info = item.getInfo(); - String wikiLink0 = info.getFirst(); - String wikiLink1 = info.size() > 1 ? info.get(1) : ""; - String wikiDomain = useOfficial ? "https://wiki.hypixel.net" : "https://hypixel-skyblock.fandom.com"; - if (wikiLink0.startsWith(wikiDomain)) { - return wikiLink0; - } else if (wikiLink1.startsWith(wikiDomain)) { - return wikiLink1; - } - return null; - } - - public static List<SkyblockRecipe> getRecipesAndUsages(ItemStack stack) { - return Stream.concat(getRecipes(stack), getUsages(stack)).toList(); - } - - public static boolean filesImported() { - return filesImported; - } - - public static void setFilesImported(boolean filesImported) { - ItemRepository.filesImported = filesImported; - } - - public static List<ItemStack> getItems() { - return items; - } - - public static Stream<ItemStack> getItemsStream() { - if (!filesImported) return Stream.empty(); - return items.stream(); - } + NEURepoManager.getConstants().getBazaarStocks().getStocks().forEach((String neuId, String skyblockId) -> bazaarStocks.put(skyblockId, neuId)); + } + + public static String getWikiLink(String neuId, boolean useOfficial) { + NEUItem item = NEURepoManager.getItemByNeuId(neuId); + if (item == null || item.getInfo() == null || item.getInfo().isEmpty()) { + return null; + } + + List<String> info = item.getInfo(); + String wikiLink0 = info.getFirst(); + String wikiLink1 = info.size() > 1 ? info.get(1) : ""; + String wikiDomain = useOfficial ? "https://wiki.hypixel.net" : "https://hypixel-skyblock.fandom.com"; + if (wikiLink0.startsWith(wikiDomain)) { + return wikiLink0; + } else if (wikiLink1.startsWith(wikiDomain)) { + return wikiLink1; + } + return null; + } + + public static List<SkyblockRecipe> getRecipesAndUsages(ItemStack stack) { + return Stream.concat(getRecipes(stack), getUsages(stack)).toList(); + } + + public static boolean filesImported() { + return filesImported; + } + + public static void setFilesImported() { + itemsImported = false; + filesImported = false; + } + + public static List<ItemStack> getItems() { + return itemsImported ? items : List.of(); + } + + public static Stream<ItemStack> getItemsStream() { + return itemsImported ? items.stream() : Stream.empty(); + } public static Map<String, @NEUId String> getBazaarStocks() { + // This is not protected by `filesImported` because it is loaded asynchronously separately from `items`, `itemsMap`, and `recipes`. return bazaarStocks; } - /** - * @param neuId the NEU item id gotten through {@link NEUItem#getSkyblockItemId()}, {@link ItemStack#getNeuName()}, or {@link ItemUtils#getNeuId(ItemStack) ItemTooltip#getNeuName(String, String)} - */ - @Nullable - public static ItemStack getItemStack(String neuId) { - return itemsMap.get(neuId); - } + /** + * @param neuId the NEU item id gotten through {@link NEUItem#getSkyblockItemId()}, {@link ItemStack#getNeuName()}, or {@link ItemUtils#getNeuId(ItemStack) ItemTooltip#getNeuName(String, String)} + */ + @Nullable + public static ItemStack getItemStack(String neuId) { + return itemsImported ? itemsMap.get(neuId) : null; + } - public static Stream<SkyblockRecipe> getRecipesStream() {return recipes.stream(); } + public static Stream<SkyblockRecipe> getRecipesStream() { + return filesImported ? recipes.stream() : Stream.empty(); + } - public static Stream<SkyblockRecipe> getRecipes(ItemStack stack) { - return NEURepoManager.RECIPE_CACHE.getRecipes().getOrDefault(stack.getNeuName(), Set.of()).stream().map(ItemRepository::toSkyblockRecipe).filter(Objects::nonNull); - } + public static Stream<SkyblockRecipe> getRecipes(ItemStack stack) { + return NEURepoManager.getRecipes().getOrDefault(stack.getNeuName(), Set.of()).stream().map(ItemRepository::toSkyblockRecipe).filter(Objects::nonNull); + } - public static Stream<SkyblockRecipe> getUsages(ItemStack stack) { - return NEURepoManager.RECIPE_CACHE.getUsages().getOrDefault(stack.getNeuName(), Set.of()).stream().map(ItemRepository::toSkyblockRecipe).filter(Objects::nonNull); - } + public static Stream<SkyblockRecipe> getUsages(ItemStack stack) { + return NEURepoManager.getUsages().getOrDefault(stack.getNeuName(), Set.of()).stream().map(ItemRepository::toSkyblockRecipe).filter(Objects::nonNull); + } - private static SkyblockRecipe toSkyblockRecipe(NEURecipe neuRecipe) { - return switch (neuRecipe) { - case NEUCraftingRecipe craftingRecipe -> new SkyblockCraftingRecipe(craftingRecipe); - case NEUForgeRecipe forgeRecipe -> new SkyblockForgeRecipe(forgeRecipe); - case null, default -> null; - }; - } + private static SkyblockRecipe toSkyblockRecipe(NEURecipe neuRecipe) { + return switch (neuRecipe) { + case NEUCraftingRecipe craftingRecipe -> new SkyblockCraftingRecipe(craftingRecipe); + case NEUForgeRecipe forgeRecipe -> new SkyblockForgeRecipe(forgeRecipe); + case null, default -> null; + }; + } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java index 636523ca..fe06352e 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java @@ -27,7 +27,7 @@ public class ItemStackBuilder { protected static void loadPetNums() { try { - petNums = NEURepoManager.NEU_REPO.getConstants().getPetNumbers(); + petNums = NEURepoManager.getConstants().getPetNumbers(); } catch (Exception e) { ItemRepository.LOGGER.error("Failed to load petnums.json"); } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/StackOverlays.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/StackOverlays.java index 314ec244..aeaf4f09 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/StackOverlays.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/StackOverlays.java @@ -32,7 +32,7 @@ public class StackOverlays { */ protected static void applyOverlay(NEUItem neuItem, ItemStack stack) { try { - NEURepoFile file = NEURepoManager.NEU_REPO.file(OVERLAY_DIRECTORY + "/" + neuItem.getSkyblockItemId() + ".snbt"); + NEURepoFile file = NEURepoManager.file(OVERLAY_DIRECTORY + "/" + neuItem.getSkyblockItemId() + ".snbt"); //The returned file is null if it does not exist if (file != null) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java index 503155e6..89b49aa2 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java @@ -96,18 +96,16 @@ public class Pet { private ItemStack createIcon() { if (NEURepoManager.isLoading() || !ItemRepository.filesImported()) return Ico.BARRIER; - Map<String, NEUItem> items = NEURepoManager.NEU_REPO.getItems().getItems(); - if (items == null) return Ico.BARRIER; String targetItemId = this.getName() + ";" + (this.getTier() + (heldItem.isPresent() && heldItem.get().equals("PET_ITEM_TIER_BOOST") ? 1 : 0)); - NEUItem item = NEURepoManager.NEU_REPO.getItems().getItems().get(targetItemId); + NEUItem item = NEURepoManager.getItemByNeuId(targetItemId); // For cases life RIFT_FERRET Where it can be tier boosted into a pet that otherwise can't exist if (item == null && heldItem.isPresent() && heldItem.get().equals("PET_ITEM_TIER_BOOST")) { - item = NEURepoManager.NEU_REPO.getItems().getItems().get(getName() + ";" + getTier()); + item = NEURepoManager.getItemByNeuId(getName() + ";" + getTier()); } - return fromNEUItem(item, this.heldItem.map(ItemRepository::getItemStack).orElse(null)); + return item == null ? Ico.BARRIER : fromNEUItem(item, this.heldItem.map(ItemRepository::getItemStack).orElse(null)); } /** @@ -148,7 +146,8 @@ public class Pet { // Skin Head Texture if (skinTexture.isPresent() && skin.isPresent()) { - formattedLore.set(0, Text.of(formattedLore.getFirst().getString() + ", " + Formatting.strip(NEURepoManager.NEU_REPO.getItems().getItems().get("PET_SKIN_" + skin.get()).getDisplayName()))); + NEUItem skinItem = NEURepoManager.getItemByNeuId("PET_SKIN_" + skin.get()); + if (skinItem != null) formattedLore.set(0, Text.of(formattedLore.getFirst().getString() + ", " + Formatting.strip(skinItem.getDisplayName()))); petStack.set(DataComponentTypes.PROFILE, skinTexture.get()); } @@ -169,7 +168,7 @@ public class Pet { * @return Formatted lore with injected stats inserted into the tooltip */ private List<Text> processLore(List<String> lore, ItemStack heldItem) { - Map<String, Map<Rarity, PetNumbers>> petNums = NEURepoManager.NEU_REPO.getConstants().getPetNumbers(); + Map<String, Map<Rarity, PetNumbers>> petNums = NEURepoManager.getConstants().getPetNumbers(); Rarity rarity = Rarity.values()[getTier()]; PetNumbers data = petNums.get(getName()).get(rarity); List<Text> formattedLore = new ArrayList<>(); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/searchoverlay/SearchOverManager.java b/src/main/java/de/hysky/skyblocker/skyblock/searchoverlay/SearchOverManager.java index 721db667..c06e2609 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/searchoverlay/SearchOverManager.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/searchoverlay/SearchOverManager.java @@ -145,7 +145,7 @@ public class SearchOverManager { } //look up id for name - NEUItem neuItem = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(id); + NEUItem neuItem = NEURepoManager.getItemByNeuId(id); if (neuItem != null) { name = Formatting.strip(neuItem.getDisplayName()); bazaarItems.add(name); @@ -158,7 +158,7 @@ public class SearchOverManager { //get auction items try { - Set<@NEUId String> essenceCosts = NEURepoManager.NEU_REPO.getConstants().getEssenceCost().getCosts().keySet(); + Set<@NEUId String> essenceCosts = NEURepoManager.getConstants().getEssenceCost().getCosts().keySet(); if (TooltipInfoType.THREE_DAY_AVERAGE.getData() == null) { TooltipInfoType.THREE_DAY_AVERAGE.run(); } @@ -166,7 +166,7 @@ public class SearchOverManager { String id = entry.getKey(); //look up in NEU repo. id = id.split("[+-]")[0]; - NEUItem neuItem = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(id); + NEUItem neuItem = NEURepoManager.getItemByNeuId(id); if (neuItem != null) { String name = Formatting.strip(neuItem.getDisplayName()); //add names that are pets to the list of pets to work with the lvl 100 button diff --git a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/FairySouls.java b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/FairySouls.java index d695bc19..2c4ec4b8 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/waypoint/FairySouls.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/waypoint/FairySouls.java @@ -71,8 +71,8 @@ public class FairySouls { private static void loadFairySouls() { fairySoulsLoaded = NEURepoManager.runAsyncAfterLoad(() -> { - maxSouls = NEURepoManager.NEU_REPO.getConstants().getFairySouls().getMaxSouls(); - NEURepoManager.NEU_REPO.getConstants().getFairySouls().getSoulLocations().forEach((location, fairiesForLocation) -> fairySouls.put(location, fairiesForLocation.stream().map(coordinate -> new BlockPos(coordinate.getX(), coordinate.getY(), coordinate.getZ())).collect(Collectors.toUnmodifiableMap(pos -> pos, pos -> new FairySoul(pos, TYPE_SUPPLIER, ColorUtils.getFloatComponents(DyeColor.GREEN), ColorUtils.getFloatComponents(DyeColor.RED)))))); + maxSouls = NEURepoManager.getConstants().getFairySouls().getMaxSouls(); + NEURepoManager.getConstants().getFairySouls().getSoulLocations().forEach((location, fairiesForLocation) -> fairySouls.put(location, fairiesForLocation.stream().map(coordinate -> new BlockPos(coordinate.getX(), coordinate.getY(), coordinate.getZ())).collect(Collectors.toUnmodifiableMap(pos -> pos, pos -> new FairySoul(pos, TYPE_SUPPLIER, ColorUtils.getFloatComponents(DyeColor.GREEN), ColorUtils.getFloatComponents(DyeColor.RED)))))); LOGGER.debug("[Skyblocker] Loaded {} fairy souls across {} locations", fairySouls.values().stream().mapToInt(Map::size).sum(), fairySouls.size()); try (BufferedReader reader = Files.newBufferedReader(SkyblockerMod.CONFIG_DIR.resolve("found_fairy_souls.json"))) { diff --git a/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java b/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java index 465a263f..46ff8318 100644 --- a/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java +++ b/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java @@ -1,13 +1,20 @@ package de.hysky.skyblocker.utils; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multimaps; import com.mojang.brigadier.Command; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.events.SkyblockEvents; -import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import de.hysky.skyblocker.utils.scheduler.Scheduler; +import io.github.moulberry.repo.NEUConstants; import io.github.moulberry.repo.NEURecipeCache; +import io.github.moulberry.repo.NEURepoFile; import io.github.moulberry.repo.NEURepository; +import io.github.moulberry.repo.data.NEUItem; +import io.github.moulberry.repo.data.NEURecipe; +import io.github.moulberry.repo.util.NEUId; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.minecraft.client.MinecraftClient; @@ -15,139 +22,216 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket; import net.minecraft.recipe.display.CuttingRecipeDisplay; import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import org.apache.commons.lang3.function.Consumers; +import org.checkerframework.checker.nullness.qual.Nullable; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.TransportException; import org.eclipse.jgit.errors.RepositoryNotFoundException; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.Function; /** * Initializes the NEU repo, which contains item metadata and fairy souls location data. Clones the repo if it does not exist and checks for updates. Use {@link #runAsyncAfterLoad(Runnable)} to run code after the repo is initialized. */ public class NEURepoManager { - private static final Logger LOGGER = LoggerFactory.getLogger(NEURepoManager.class); - public static final String REMOTE_REPO_URL = "https://github.com/NotEnoughUpdates/NotEnoughUpdates-REPO.git"; - /** - * Use {@link #NEU_REPO}. - */ - private static final Path LOCAL_REPO_DIR = SkyblockerMod.CONFIG_DIR.resolve("item-repo"); // TODO rename to NotEnoughUpdates-REPO - private static CompletableFuture<Void> REPO_LOADING = loadRepository().thenAccept(Consumers.nop()); - public static final NEURepository NEU_REPO = NEURepository.of(LOCAL_REPO_DIR); - public static final NEURecipeCache RECIPE_CACHE = NEURecipeCache.forRepo(NEU_REPO); - - /** - * Adds command to update repository manually from ingame. - * <p></p> - * TODO A button could be added to the settings menu that will trigger this command. - */ - @Init - public static void init() { - ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> - dispatcher.register(ClientCommandManager.literal(SkyblockerMod.NAMESPACE) - .then(ClientCommandManager.literal("updateRepository").executes(context -> { - deleteAndDownloadRepository(context.getSource().getPlayer()); - return Command.SINGLE_SUCCESS; - })) - ) - ); - SkyblockEvents.JOIN.register(NEURepoManager::handleRecipeSynchronization); - } - - /** - * load the recipe manually because Hypixel doesn't send any vanilla recipes to the client - */ - private static void handleRecipeSynchronization() { - MinecraftClient client = MinecraftClient.getInstance(); - if (client.world != null && client.getNetworkHandler() != null) { - //FIXME not sure if we even need this - depends on how REI, EMI, and JEI adapt to the changes - SynchronizeRecipesS2CPacket packet = new SynchronizeRecipesS2CPacket(Map.of(), CuttingRecipeDisplay.Grouping.empty()); - - try { - client.getNetworkHandler().onSynchronizeRecipes(packet); - } catch (Exception e) { - LOGGER.info("[Skyblocker NEU Repo] recipe sync error", e); - } - } - } - - public static boolean isLoading() { - return REPO_LOADING != null && !REPO_LOADING.isDone(); - } - - private static CompletableFuture<Boolean> loadRepository() { - return CompletableFuture.supplyAsync(() -> { - boolean success = true; - try { - if (Files.isDirectory(NEURepoManager.LOCAL_REPO_DIR)) { - try (Git localRepo = Git.open(NEURepoManager.LOCAL_REPO_DIR.toFile())) { - localRepo.pull().setRebase(true).call(); - LOGGER.info("[Skyblocker NEU Repo] NEU Repository Updated"); - } - } else { - Git.cloneRepository().setURI(REMOTE_REPO_URL).setDirectory(NEURepoManager.LOCAL_REPO_DIR.toFile()).setBranchesToClone(List.of("refs/heads/master")).setBranch("refs/heads/master").call().close(); - LOGGER.info("[Skyblocker NEU Repo] NEU Repository Downloaded"); - } - } catch (TransportException e) { - LOGGER.error("[Skyblocker NEU Repo] Transport operation failed. Most likely unable to connect to the remote NEU repo on github", e); - success = false; - } catch (RepositoryNotFoundException e) { - LOGGER.warn("[Skyblocker NEU Repo] Local NEU Repository not found or corrupted, downloading new one", e); - Scheduler.INSTANCE.schedule(() -> deleteAndDownloadRepository(MinecraftClient.getInstance().player), 1); - success = false; - } catch (Exception e) { - LOGGER.error("[Skyblocker NEU Repo] Encountered unknown exception while downloading NEU Repository", e); - success = false; - } - - try { - NEU_REPO.reload(); - } catch (Exception e) { - LOGGER.error("[Skyblocker NEU Repo] Encountered unknown exception while loading NEU Repository", e); - success = false; - } - return success; - |
