aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorAlex <8379108+Alex33856@users.noreply.github.com>2025-07-24 16:04:24 -0400
committerGitHub <noreply@github.com>2025-07-24 16:04:24 -0400
commitab85baafd92ea6f46a879005adb5a40629bbd64d (patch)
tree92403035f1f2771b683f22d656ef5dd049a3310a /src/main/java
parent4126dccbb67f4afd2eae791e61fde6526a9ca7c5 (diff)
downloadSkyblocker-ab85baafd92ea6f46a879005adb5a40629bbd64d.tar.gz
Skyblocker-ab85baafd92ea6f46a879005adb5a40629bbd64d.tar.bz2
Skyblocker-ab85baafd92ea6f46a879005adb5a40629bbd64d.zip
REI /viewrecipe Crafting, Skyblock Info Display (#1496)
* Skyblock Info Display + /viewrecipe Crafting * Don't register global display generator if already there * Check if /viewrecipe failed, use similar system for item price lookup failure * Exclude Forge recipes * Update comment * Update Item Price Lookup keybind translation
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockTransferHandler.java81
-rw-r--r--src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockerREIClientPlugin.java20
-rw-r--r--src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoCategory.java114
-rw-r--r--src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoDisplay.java47
-rw-r--r--src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoDisplayGenerator.java23
-rw-r--r--src/main/java/de/hysky/skyblocker/compatibility/rei/recipe/SkyblockRecipeCategory.java (renamed from src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java)2
-rw-r--r--src/main/java/de/hysky/skyblocker/compatibility/rei/recipe/SkyblockRecipeDisplay.java (renamed from src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java)2
-rw-r--r--src/main/java/de/hysky/skyblocker/compatibility/rei/recipe/SkyblockRecipeDisplayGenerator.java (renamed from src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplayGenerator.java)2
8 files changed, 286 insertions, 5 deletions
diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockTransferHandler.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockTransferHandler.java
new file mode 100644
index 00000000..8272a474
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockTransferHandler.java
@@ -0,0 +1,81 @@
+package de.hysky.skyblocker.compatibility.rei;
+
+import de.hysky.skyblocker.compatibility.rei.info.SkyblockInfoCategory;
+import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe;
+import de.hysky.skyblocker.utils.NEURepoManager;
+import de.hysky.skyblocker.utils.scheduler.MessageScheduler;
+import de.hysky.skyblocker.utils.scheduler.Scheduler;
+import io.github.moulberry.repo.data.NEUCraftingRecipe;
+import me.shedaniel.rei.api.client.registry.transfer.TransferHandler;
+import me.shedaniel.rei.api.common.category.CategoryIdentifier;
+import me.shedaniel.rei.api.common.entry.EntryIngredient;
+import me.shedaniel.rei.api.common.entry.EntryStack;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
+import net.minecraft.item.ItemStack;
+import net.minecraft.text.Text;
+
+public class SkyblockTransferHandler implements TransferHandler {
+ private static final int MAX_FAIL_COUNT = 5;
+
+ private String FAILED_ITEM;
+ private int FAIL_COUNT;
+
+ @Override
+ public ApplicabilityResult checkApplicable(Context context) {
+ // Only work on our displays
+ CategoryIdentifier<?> identifier = context.getDisplay().getCategoryIdentifier();
+ if (identifier != CategoryIdentifier.of(SkyblockCraftingRecipe.IDENTIFIER) && identifier != CategoryIdentifier.of(SkyblockInfoCategory.IDENTIFIER))
+ return ApplicabilityResult.createNotApplicable();
+
+ EntryIngredient ingredient = context.getDisplay().getOutputEntries().getFirst();
+ EntryStack<?> entryStack = ingredient.getFirst();
+ if (!(entryStack.getValue() instanceof ItemStack itemStack))
+ return ApplicabilityResult.createNotApplicable();
+
+ // Not applicable if it has 0 recipes, or no crafting recipe
+ String neuId = itemStack.getNeuName();
+ if (!NEURepoManager.getRecipes().containsKey(neuId) || NEURepoManager.getRecipes().get(neuId).stream().noneMatch(recipe -> recipe instanceof NEUCraftingRecipe))
+ return ApplicabilityResult.createApplicableWithError(Text.translatable("skyblocker.rei.transfer.noRecipe"));
+
+ return ApplicabilityResult.createApplicable();
+
+ }
+
+ private boolean hasFailed(String skyblockId) {
+ if (skyblockId.equals(FAILED_ITEM)) {
+ if (FAIL_COUNT < MAX_FAIL_COUNT) {
+ FAIL_COUNT += 1;
+ return true;
+ }
+
+ FAILED_ITEM = "";
+ FAIL_COUNT = 0;
+ }
+ return false;
+ }
+
+ private void checkScreen(String skyblockId) {
+ Screen currentScreen = MinecraftClient.getInstance().currentScreen;
+ if (!(currentScreen instanceof GenericContainerScreen)) {
+ FAIL_COUNT = 0;
+ FAILED_ITEM = skyblockId;
+ }
+ }
+
+ @Override
+ public Result handle(Context context) {
+ EntryIngredient ingredient = context.getDisplay().getOutputEntries().getFirst();
+ EntryStack<?> entryStack = ingredient.getFirst();
+ if (!(entryStack.getValue() instanceof ItemStack itemStack)) return Result.createNotApplicable();
+
+ String skyblockId = itemStack.getSkyblockId();
+ if (hasFailed(skyblockId)) return Result.createFailed(Text.translatable("skyblocker.rei.transfer.failed"));
+ if (!context.isActuallyCrafting()) return Result.createSuccessful();
+
+ MessageScheduler.INSTANCE.sendMessageAfterCooldown("/viewrecipe " + skyblockId, false);
+ Scheduler.INSTANCE.schedule(() -> checkScreen(skyblockId), 5);
+ return Result.createSuccessful();
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockerREIClientPlugin.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockerREIClientPlugin.java
index 59a694f6..febcf032 100644
--- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockerREIClientPlugin.java
+++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockerREIClientPlugin.java
@@ -1,5 +1,9 @@
package de.hysky.skyblocker.compatibility.rei;
+import de.hysky.skyblocker.compatibility.rei.info.SkyblockInfoCategory;
+import de.hysky.skyblocker.compatibility.rei.info.SkyblockInfoDisplayGenerator;
+import de.hysky.skyblocker.compatibility.rei.recipe.SkyblockRecipeCategory;
+import de.hysky.skyblocker.compatibility.rei.recipe.SkyblockRecipeDisplayGenerator;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
import de.hysky.skyblocker.mixins.accessors.HandledScreenAccessor;
import de.hysky.skyblocker.skyblock.garden.visitor.VisitorHelper;
@@ -15,6 +19,7 @@ import me.shedaniel.rei.api.client.registry.category.CategoryRegistry;
import me.shedaniel.rei.api.client.registry.display.DisplayRegistry;
import me.shedaniel.rei.api.client.registry.entry.EntryRegistry;
import me.shedaniel.rei.api.client.registry.screen.ExclusionZones;
+import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
import me.shedaniel.rei.api.common.util.EntryStacks;
import net.minecraft.client.gui.screen.Screen;
@@ -29,19 +34,24 @@ import java.util.List;
*/
public class SkyblockerREIClientPlugin implements REIClientPlugin {
- @Override
+ @Override
public void registerCategories(CategoryRegistry categoryRegistry) {
if (!SkyblockerConfigManager.get().general.itemList.enableItemList) return;
categoryRegistry.addWorkstations(CategoryIdentifier.of(SkyblockCraftingRecipe.IDENTIFIER), EntryStacks.of(Items.CRAFTING_TABLE));
categoryRegistry.addWorkstations(CategoryIdentifier.of(SkyblockForgeRecipe.IDENTIFIER), EntryStacks.of(Items.ANVIL));
categoryRegistry.add(new SkyblockRecipeCategory(SkyblockCraftingRecipe.IDENTIFIER, Text.translatable("emi.category.skyblocker.skyblock_crafting"), ItemUtils.getSkyblockerStack(), 73));
categoryRegistry.add(new SkyblockRecipeCategory(SkyblockForgeRecipe.IDENTIFIER, Text.translatable("emi.category.skyblocker.skyblock_forge"), ItemUtils.getSkyblockerForgeStack(), 84));
+
+ categoryRegistry.add(new SkyblockInfoCategory());
}
@Override
public void registerDisplays(DisplayRegistry displayRegistry) {
if (!SkyblockerConfigManager.get().general.itemList.enableItemList) return;
- displayRegistry.registerGlobalDisplayGenerator(new SkyblockRecipeDisplayGenerator());
+ if (displayRegistry.getGlobalDisplayGenerators().stream().noneMatch(generator -> generator instanceof SkyblockRecipeDisplayGenerator))
+ displayRegistry.registerGlobalDisplayGenerator(new SkyblockRecipeDisplayGenerator());
+ if (displayRegistry.getGlobalDisplayGenerators().stream().noneMatch(generator -> generator instanceof SkyblockInfoDisplayGenerator))
+ displayRegistry.registerGlobalDisplayGenerator(new SkyblockInfoDisplayGenerator());
}
@Override
@@ -66,6 +76,12 @@ public class SkyblockerREIClientPlugin implements REIClientPlugin {
}
@Override
+ public void registerTransferHandlers(TransferHandlerRegistry registry) {
+ if (!SkyblockerConfigManager.get().general.itemList.enableItemList) return;
+ registry.register(new SkyblockTransferHandler());
+ }
+
+ @Override
public double getPriority() {
return -50;
}
diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoCategory.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoCategory.java
new file mode 100644
index 00000000..d1e48458
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoCategory.java
@@ -0,0 +1,114 @@
+package de.hysky.skyblocker.compatibility.rei.info;
+
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.skyblock.item.ItemPrice;
+import de.hysky.skyblocker.skyblock.item.WikiLookup;
+import de.hysky.skyblocker.skyblock.itemlist.ItemRepository;
+import de.hysky.skyblocker.utils.render.gui.AbstractCustomHypixelGUI;
+import de.hysky.skyblocker.utils.scheduler.Scheduler;
+import me.shedaniel.math.Point;
+import me.shedaniel.math.Rectangle;
+import me.shedaniel.rei.api.client.gui.Renderer;
+import me.shedaniel.rei.api.client.gui.widgets.Slot;
+import me.shedaniel.rei.api.client.gui.widgets.Widget;
+import me.shedaniel.rei.api.client.gui.widgets.Widgets;
+import me.shedaniel.rei.api.client.registry.display.DisplayCategory;
+import me.shedaniel.rei.api.common.category.CategoryIdentifier;
+import me.shedaniel.rei.api.common.entry.EntryStack;
+import me.shedaniel.rei.api.common.util.EntryStacks;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.ingame.GenericContainerScreen;
+import net.minecraft.client.gui.widget.ButtonWidget;
+import net.minecraft.client.gui.widget.DirectionalLayoutWidget;
+import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SkyblockInfoCategory implements DisplayCategory<SkyblockInfoDisplay> {
+ private static final int REI_SLOT_HEIGHT = 18;
+ private static final int OFFSET = 10;
+ private static final int RED_ERROR_COLOR = 0xFFFF5555;
+ private static final EntryStack<ItemStack> ICON = EntryStacks.of(new ItemStack(Items.CHEST));
+
+ public static final Identifier IDENTIFIER = Identifier.of(SkyblockerMod.NAMESPACE, "skyblock_info");
+
+ @Override
+ public CategoryIdentifier<? extends SkyblockInfoDisplay> getCategoryIdentifier() {
+ return CategoryIdentifier.of(IDENTIFIER);
+ }
+
+ @Override
+ public Text getTitle() {
+ return Text.translatable("emi.category.skyblocker.skyblock_info");
+ }
+
+ @Override
+ public Renderer getIcon() {
+ return ICON;
+ }
+
+ private ButtonWidget getWikiLookupButton(Text text, boolean isOfficial, ItemStack itemStack, ClientPlayerEntity player) {
+ ButtonWidget btn = ButtonWidget.builder(text, (button) -> WikiLookup.openWiki(itemStack, player, isOfficial)).build();
+
+ if (ItemRepository.getWikiLink(itemStack.getNeuName(), isOfficial) == null) {
+ btn.setMessage(btn.getMessage().copy().withColor(RED_ERROR_COLOR));
+ btn.active = false;
+ }
+
+ return btn;
+ }
+
+ private boolean checkScreen() {
+ Screen currentScreen = MinecraftClient.getInstance().currentScreen;
+ return currentScreen instanceof GenericContainerScreen || currentScreen instanceof AbstractCustomHypixelGUI<?>;
+ }
+
+ @Override
+ public List<Widget> setupDisplay(SkyblockInfoDisplay display, Rectangle bounds) {
+ List<Widget> widgets = new ArrayList<>();
+ EntryStack<?> entryStack = display.getInputEntries().getFirst().getFirst();
+ if (!(entryStack.getValue() instanceof ItemStack itemStack)) return widgets;
+
+ widgets.add(Widgets.createRecipeBase(bounds));
+ Slot slot = Widgets.createSlot(new Point(bounds.getCenterX() - 9 + 1, bounds.y + 1 + OFFSET / 2)).entry(entryStack);
+ widgets.add(slot);
+
+ ClientPlayerEntity player = MinecraftClient.getInstance().player;
+ DirectionalLayoutWidget layoutWidget = DirectionalLayoutWidget.vertical();
+ layoutWidget.setPosition(bounds.x + OFFSET, bounds.y + OFFSET + REI_SLOT_HEIGHT);
+
+ layoutWidget.add(ButtonWidget.builder(Text.translatable("key.itemPriceLookup"), (button) -> {
+ ItemPrice.itemPriceLookup(player, itemStack);
+
+ Scheduler.INSTANCE.schedule(() -> {
+ if (checkScreen()) return;
+ button.setMessage(Text.translatable("skyblocker.rei.skyblockInfo.failedToFind").withColor(RED_ERROR_COLOR));
+ button.active = false;
+ }, 10);
+ }).build());
+
+ layoutWidget.add(getWikiLookupButton(Text.translatable("key.wikiLookup.official"), true, itemStack, player));
+ layoutWidget.add(getWikiLookupButton(Text.translatable("key.wikiLookup.fandom"), false, itemStack, player));
+
+ layoutWidget.forEachChild(child -> widgets.add(Widgets.wrapVanillaWidget(child)));
+ layoutWidget.refreshPositions();
+
+ return widgets;
+ }
+
+ @Override
+ public int getDisplayHeight() {
+ return 3 * ButtonWidget.DEFAULT_HEIGHT + REI_SLOT_HEIGHT + 2 * OFFSET;
+ }
+
+ @Override
+ public int getDisplayWidth(SkyblockInfoDisplay display) {
+ return 150 + 20;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoDisplay.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoDisplay.java
new file mode 100644
index 00000000..22714941
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoDisplay.java
@@ -0,0 +1,47 @@
+package de.hysky.skyblocker.compatibility.rei.info;
+
+import de.hysky.skyblocker.SkyblockerMod;
+import me.shedaniel.rei.api.common.category.CategoryIdentifier;
+import me.shedaniel.rei.api.common.display.Display;
+import me.shedaniel.rei.api.common.display.DisplaySerializer;
+import me.shedaniel.rei.api.common.entry.EntryIngredient;
+import me.shedaniel.rei.api.common.util.EntryStacks;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.Identifier;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Optional;
+
+public class SkyblockInfoDisplay implements Display {
+ private final ItemStack displayItem;
+
+ public SkyblockInfoDisplay(ItemStack item) {
+ this.displayItem = item;
+ }
+
+ @Override
+ public List<EntryIngredient> getInputEntries() {
+ return List.of(EntryIngredient.of(EntryStacks.of(displayItem)));
+ }
+
+ @Override
+ public List<EntryIngredient> getOutputEntries() {
+ return List.of(EntryIngredient.of(EntryStacks.of(displayItem)));
+ }
+
+ @Override
+ public CategoryIdentifier<?> getCategoryIdentifier() {
+ return CategoryIdentifier.of(Identifier.of(SkyblockerMod.NAMESPACE, "skyblock_info"));
+ }
+
+ @Override
+ public Optional<Identifier> getDisplayLocation() {
+ return Optional.empty();
+ }
+
+ @Override
+ public @Nullable DisplaySerializer<? extends Display> getSerializer() {
+ return null;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoDisplayGenerator.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoDisplayGenerator.java
new file mode 100644
index 00000000..2b440220
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/info/SkyblockInfoDisplayGenerator.java
@@ -0,0 +1,23 @@
+package de.hysky.skyblocker.compatibility.rei.info;
+
+import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator;
+import me.shedaniel.rei.api.common.entry.EntryStack;
+import net.minecraft.item.ItemStack;
+
+import java.util.List;
+import java.util.Optional;
+
+public class SkyblockInfoDisplayGenerator implements DynamicDisplayGenerator<SkyblockInfoDisplay> {
+ @Override
+ public Optional<List<SkyblockInfoDisplay>> getRecipeFor(EntryStack<?> entry) {
+ if (!(entry.getValue() instanceof ItemStack entryStack)) return Optional.empty();
+ if (entryStack.getSkyblockId().isEmpty()) return Optional.empty();
+ entryStack.setCount(1);
+ return Optional.of(List.of(new SkyblockInfoDisplay(entryStack)));
+ }
+
+ @Override
+ public Optional<List<SkyblockInfoDisplay>> getUsageFor(EntryStack<?> entry) {
+ return getRecipeFor(entry);
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/recipe/SkyblockRecipeCategory.java
index 0460a1cf..167bafcf 100644
--- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java
+++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/recipe/SkyblockRecipeCategory.java
@@ -1,4 +1,4 @@
-package de.hysky.skyblocker.compatibility.rei;
+package de.hysky.skyblocker.compatibility.rei.recipe;
import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockRecipe;
import me.shedaniel.math.Point;
diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/recipe/SkyblockRecipeDisplay.java
index 44d44011..640497c0 100644
--- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java
+++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/recipe/SkyblockRecipeDisplay.java
@@ -1,4 +1,4 @@
-package de.hysky.skyblocker.compatibility.rei;
+package de.hysky.skyblocker.compatibility.rei.recipe;
import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockRecipe;
import me.shedaniel.rei.api.common.category.CategoryIdentifier;
diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplayGenerator.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/recipe/SkyblockRecipeDisplayGenerator.java
index 2b9775c6..6ac36288 100644
--- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplayGenerator.java
+++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/recipe/SkyblockRecipeDisplayGenerator.java
@@ -1,4 +1,4 @@
-package de.hysky.skyblocker.compatibility.rei;
+package de.hysky.skyblocker.compatibility.rei.recipe;
import de.hysky.skyblocker.skyblock.itemlist.ItemRepository;
import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator;