From 558248edb5e4ca9c96d1c4976a6940fd377fd6aa Mon Sep 17 00:00:00 2001 From: viciscat <51047087+viciscat@users.noreply.github.com> Date: Thu, 18 Jul 2024 17:07:12 +0200 Subject: [PATCH 1/6] item list shenanigans --- .../compatibility/emi/SkyblockEmiRecipe.java | 2 +- .../emi/SkyblockerEMIPlugin.java | 2 +- .../compatibility/rei/SkyblockCategory.java | 84 ----- .../rei/SkyblockCraftingDisplay.java | 40 --- .../rei/SkyblockCraftingDisplayGenerator.java | 72 ---- .../rei/SkyblockRecipeCategory.java | 95 ++++++ .../rei/SkyblockRecipeDisplay.java | 40 +++ .../rei/SkyblockRecipeDisplayGenerator.java | 27 ++ .../rei/SkyblockerREIClientPlugin.java | 23 +- .../mixins/CreeperEntityAccessor.java | 13 + .../skyblock/itemlist/EntityCreator.java | 314 ++++++++++++++++++ .../skyblock/itemlist/ItemRepository.java | 68 ++-- .../itemlist/SearchResultsWidget.java | 3 +- .../itemlist/SkyblockCraftingRecipe.java | 61 ---- .../recipes/SkyblockCraftingRecipe.java | 92 +++++ .../itemlist/recipes/SkyblockForgeRecipe.java | 77 +++++ .../recipes/SkyblockMobDropRecipe.java | 123 +++++++ .../itemlist/recipes/SkyblockRecipe.java | 80 +++++ .../skyblocker/utils/NEURepoManager.java | 2 + .../assets/skyblocker/lang/en_us.json | 2 +- src/main/resources/skyblocker.mixins.json | 5 +- 21 files changed, 930 insertions(+), 295 deletions(-) delete mode 100644 src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCategory.java delete mode 100644 src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCraftingDisplay.java delete mode 100644 src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCraftingDisplayGenerator.java create mode 100644 src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java create mode 100644 src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java create mode 100644 src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplayGenerator.java create mode 100644 src/main/java/de/hysky/skyblocker/mixins/CreeperEntityAccessor.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/itemlist/EntityCreator.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockCraftingRecipe.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockMobDropRecipe.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java diff --git a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java index 7f102fc1e5..6ea0f46c3f 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java @@ -1,6 +1,6 @@ package de.hysky.skyblocker.compatibility.emi; -import de.hysky.skyblocker.skyblock.itemlist.SkyblockCraftingRecipe; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; import dev.emi.emi.api.recipe.EmiCraftingRecipe; import dev.emi.emi.api.recipe.EmiRecipeCategory; import dev.emi.emi.api.stack.EmiIngredient; diff --git a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java index 9d5a2a46c0..a7c67267d3 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java @@ -28,6 +28,6 @@ public void register(EmiRegistry registry) { }); registry.addCategory(SKYBLOCK); registry.addWorkstation(SKYBLOCK, EmiStack.of(Items.CRAFTING_TABLE)); - ItemRepository.getRecipesStream().map(SkyblockEmiRecipe::new).forEach(registry::addRecipe); + ItemRepository.getRecipesStreamOld().map(SkyblockEmiRecipe::new).forEach(registry::addRecipe); } } diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCategory.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCategory.java deleted file mode 100644 index 1474c8bea7..0000000000 --- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCategory.java +++ /dev/null @@ -1,84 +0,0 @@ -package de.hysky.skyblocker.compatibility.rei; - -import com.google.common.collect.Lists; -import de.hysky.skyblocker.utils.ItemUtils; -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.Label; -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.EntryIngredient; -import me.shedaniel.rei.api.common.util.EntryStacks; -import net.minecraft.text.Text; - -import java.util.ArrayList; -import java.util.List; - -/** - * Skyblock recipe category class for REI - */ -public class SkyblockCategory implements DisplayCategory { - @Override - public CategoryIdentifier getCategoryIdentifier() { - return SkyblockerREIClientPlugin.SKYBLOCK; - } - - @Override - public Text getTitle() { - return Text.translatable("emi.category.skyblocker.skyblock"); - } - - @Override - public Renderer getIcon() { - return EntryStacks.of(ItemUtils.getSkyblockerStack()); - } - - @Override - public int getDisplayHeight() { - return 73; - } - - /** - * Draws display for SkyblockCraftingDisplay - * - * @param display the display - * @param bounds the bounds of the display, configurable with overriding the width, height methods. - */ - @Override - public List setupDisplay(SkyblockCraftingDisplay display, Rectangle bounds) { - List out = new ArrayList<>(); - out.add(Widgets.createRecipeBase(bounds)); - - Point startPoint; - if (!display.getCraftText().isEmpty() && display.getCraftText() != null) { - startPoint = new Point(bounds.getCenterX() - 58, bounds.getCenterY() - 31); - } - else { - startPoint = new Point(bounds.getCenterX() - 58, bounds.getCenterY() - 26); - } - Point resultPoint = new Point(startPoint.x + 95, startPoint.y + 19); - out.add(Widgets.createArrow(new Point(startPoint.x + 60, startPoint.y + 18))); - out.add(Widgets.createResultSlotBackground(resultPoint)); - - // Generate Slots - List input = display.getInputEntries(); - List slots = Lists.newArrayList(); - for (int y = 0; y < 3; y++) - for (int x = 0; x < 3; x++) - slots.add(Widgets.createSlot(new Point(startPoint.x + 1 + x * 18, startPoint.y + 1 + y * 18)).markInput()); - for (int i = 0; i < input.size(); i++) { - slots.get(i).entries(input.get(i)).markInput(); - } - out.addAll(slots); - out.add(Widgets.createSlot(resultPoint).entries(display.getOutputEntries().getFirst()).disableBackground().markOutput()); - - // Add craftingText Label - Label craftTextLabel = Widgets.createLabel(new Point(bounds.getCenterX(), startPoint.y + 55), Text.of(display.getCraftText())); - out.add(craftTextLabel); - return out; - } -} diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCraftingDisplay.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCraftingDisplay.java deleted file mode 100644 index 7cd712f259..0000000000 --- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCraftingDisplay.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.hysky.skyblocker.compatibility.rei; - - -import me.shedaniel.rei.api.common.category.CategoryIdentifier; -import me.shedaniel.rei.api.common.display.SimpleGridMenuDisplay; -import me.shedaniel.rei.api.common.display.basic.BasicDisplay; -import me.shedaniel.rei.api.common.entry.EntryIngredient; - -import java.util.List; - -/** - * Skyblock Crafting Recipe display class for REI - */ -public class SkyblockCraftingDisplay extends BasicDisplay implements SimpleGridMenuDisplay { - private final String craftText; - - public SkyblockCraftingDisplay(List input, List output, String craftText) { - super(input, output); - this.craftText = craftText; - } - - public String getCraftText() { - return craftText; - } - - @Override - public int getWidth() { - return 3; - } - - @Override - public int getHeight() { - return 3; - } - - @Override - public CategoryIdentifier getCategoryIdentifier() { - return SkyblockerREIClientPlugin.SKYBLOCK; - } -} \ No newline at end of file diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCraftingDisplayGenerator.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCraftingDisplayGenerator.java deleted file mode 100644 index 33cee20bd6..0000000000 --- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockCraftingDisplayGenerator.java +++ /dev/null @@ -1,72 +0,0 @@ -package de.hysky.skyblocker.compatibility.rei; - -import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; -import de.hysky.skyblocker.skyblock.itemlist.SkyblockCraftingRecipe; -import de.hysky.skyblocker.utils.ItemUtils; -import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator; -import me.shedaniel.rei.api.common.entry.EntryIngredient; -import me.shedaniel.rei.api.common.entry.EntryStack; -import me.shedaniel.rei.api.common.util.EntryStacks; -import net.minecraft.item.ItemStack; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -public class SkyblockCraftingDisplayGenerator implements DynamicDisplayGenerator { - - @Override - public Optional> getRecipeFor(EntryStack entry) { - if (!(entry.getValue() instanceof ItemStack)) return Optional.empty(); - EntryStack inputItem = EntryStacks.of((ItemStack) entry.getValue()); - List filteredRecipes = ItemRepository.getRecipesStream() - .filter(recipe -> { - ItemStack itemStack = inputItem.getValue(); - ItemStack itemStack1 = recipe.getResult(); - return ItemUtils.getItemId(itemStack1).equals(ItemUtils.getItemId(itemStack)); - }) - .toList(); - - return Optional.of(generateDisplays(filteredRecipes)); - } - - @Override - public Optional> getUsageFor(EntryStack entry) { - if (!(entry.getValue() instanceof ItemStack)) return Optional.empty(); - EntryStack inputItem = EntryStacks.of((ItemStack) entry.getValue()); - List filteredRecipes = ItemRepository.getRecipesStream() - .filter(recipe -> { - for (ItemStack item : recipe.getGrid()) { - if(!ItemUtils.getItemId(item).isEmpty()) { - ItemStack itemStack = inputItem.getValue(); - if (ItemUtils.getItemId(item).equals(ItemUtils.getItemId(itemStack))) return true; - } - } - return false; - }) - .toList(); - return Optional.of(generateDisplays(filteredRecipes)); - } - - /** - * Generate Displays from a list of recipes - */ - private List generateDisplays(List recipes) { - List displays = new ArrayList<>(); - for (SkyblockCraftingRecipe recipe : recipes) { - List inputs = new ArrayList<>(); - List outputs = new ArrayList<>(); - - ArrayList> inputEntryStacks = new ArrayList<>(); - recipe.getGrid().forEach((item) -> inputEntryStacks.add(EntryStacks.of(item))); - - for (EntryStack entryStack : inputEntryStacks) { - inputs.add(EntryIngredient.of(entryStack)); - } - outputs.add(EntryIngredient.of(EntryStacks.of(recipe.getResult()))); - - displays.add(new SkyblockCraftingDisplay(inputs, outputs, recipe.getCraftText())); - } - return displays; - } -} diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java new file mode 100644 index 0000000000..efd6f4ee7b --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java @@ -0,0 +1,95 @@ +package de.hysky.skyblocker.compatibility.rei; + +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockRecipe; +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.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.util.EntryStacks; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.ScreenPos; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +import java.util.ArrayList; +import java.util.List; + +public class SkyblockRecipeCategory implements DisplayCategory { + + private final Identifier identifier; + private final Text title; + private final ItemStack icon; + private final int height; + + public SkyblockRecipeCategory(Identifier identifier, Text title, ItemStack icon, int height) { + this.identifier = identifier; + this.title = title; + this.icon = icon; + this.height = height; + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return CategoryIdentifier.of(identifier); + } + + @Override + public int getDisplayHeight() { + return height; + } + + @Override + public Text getTitle() { + return title; + } + + @Override + public Renderer getIcon() { + return EntryStacks.of(icon); + } + + @Override + public List setupDisplay(SkyblockRecipeDisplay display, Rectangle bounds) { + List out = new ArrayList<>(); + out.add(Widgets.createRecipeBase(bounds)); + SkyblockRecipe recipe = display.getRecipe(); + for (SkyblockRecipe.RecipeSlot inputSlot : recipe.getInputSlots(bounds.getWidth(), bounds.getHeight())) { + out.add(Widgets.createSlot(new Point(inputSlot.x() + bounds.getX(), inputSlot.y() + bounds.getY())) + .markInput() + .backgroundEnabled(inputSlot.showBackground()) + .entry(EntryStacks.of(inputSlot.stack()))); + } + for (SkyblockRecipe.RecipeSlot outputSlot : recipe.getOutputSlots(bounds.getWidth(), bounds.getHeight())) { + out.add(Widgets.createSlot(new Point(outputSlot.x() + bounds.getX(), outputSlot.y() + bounds.getY())) + .markOutput() + .backgroundEnabled(outputSlot.showBackground()) + .entry(EntryStacks.of(outputSlot.stack()))); + } + out.add(Widgets.withBounds(new Widget() { + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + MatrixStack matrices = context.getMatrices(); + matrices.push(); + matrices.translate(bounds.getX(), bounds.getY(), 0.f); + recipe.render(context, bounds.getWidth(), bounds.getHeight(), mouseX - bounds.getX(), mouseY - bounds.getY()); + matrices.pop(); + } + + @Override + public List children() { + return List.of(); + } + })); + ScreenPos arrowLocation = recipe.getArrowLocation(bounds.getWidth(), bounds.getHeight()); + if (arrowLocation != null) + out.add(Widgets.createArrow(new Point(arrowLocation.x() + bounds.getX(), arrowLocation.y() + bounds.getY()))); + out.add(Widgets.createLabel(new Point(bounds.getCenterX(), bounds.getCenterY() + 24), recipe.getExtraText())); + return out; + } +} diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java new file mode 100644 index 0000000000..bf2eaa17de --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java @@ -0,0 +1,40 @@ +package de.hysky.skyblocker.compatibility.rei; + +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockRecipe; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.EntryStacks; +import net.minecraft.util.Identifier; + +import java.util.List; + +public class SkyblockRecipeDisplay implements Display { + + private final Identifier category; + private final SkyblockRecipe recipe; + + public SkyblockRecipeDisplay(SkyblockRecipe recipe) { + this.category = recipe.getCategoryIdentifier(); + this.recipe = recipe; + } + + @Override + public List getInputEntries() { + return recipe.getInputs().stream().map(EntryStacks::of).map(EntryIngredient::of).toList(); + } + + @Override + public List getOutputEntries() { + return recipe.getOutputs().stream().map(EntryStacks::of).map(EntryIngredient::of).toList(); + } + + public SkyblockRecipe getRecipe() { + return recipe; + } + + @Override + public CategoryIdentifier getCategoryIdentifier() { + return CategoryIdentifier.of(category); + } +} diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplayGenerator.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplayGenerator.java new file mode 100644 index 0000000000..fa4787dfb7 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplayGenerator.java @@ -0,0 +1,27 @@ +package de.hysky.skyblocker.compatibility.rei; + +import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; +import de.hysky.skyblocker.utils.ItemUtils; +import de.hysky.skyblocker.utils.NEURepoManager; +import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator; +import me.shedaniel.rei.api.common.entry.EntryStack; +import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes; +import net.minecraft.item.ItemStack; + +import java.util.List; +import java.util.Optional; + +public class SkyblockRecipeDisplayGenerator implements DynamicDisplayGenerator { + + @Override + public Optional> getRecipeFor(EntryStack entry) { + if (!(entry.getValue() instanceof ItemStack entryStack)) return Optional.empty(); + return Optional.of(ItemRepository.getRecipes(entryStack).map(SkyblockRecipeDisplay::new).toList()); + } + + @Override + public Optional> getUsageFor(EntryStack entry) { + if (!(entry.getValue() instanceof ItemStack entryStack)) return Optional.empty(); + return Optional.of(ItemRepository.getUsages(entryStack).map(SkyblockRecipeDisplay::new).toList()); + } +} 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 7ed322a061..8146ebd846 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockerREIClientPlugin.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockerREIClientPlugin.java @@ -1,34 +1,47 @@ package de.hysky.skyblocker.compatibility.rei; -import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockForgeRecipe; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockMobDropRecipe; +import de.hysky.skyblocker.utils.ItemUtils; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; 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.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.util.EntryStacks; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import net.minecraft.text.Text; /** * REI integration */ public class SkyblockerREIClientPlugin implements REIClientPlugin { - public static final CategoryIdentifier SKYBLOCK = CategoryIdentifier.of(SkyblockerMod.NAMESPACE, "skyblock"); @Override public void registerCategories(CategoryRegistry categoryRegistry) { - categoryRegistry.addWorkstations(SKYBLOCK, EntryStacks.of(Items.CRAFTING_TABLE)); - categoryRegistry.add(new SkyblockCategory()); + if (FabricLoader.getInstance().isModLoaded("firmament")) return; + categoryRegistry.addWorkstations(CategoryIdentifier.of(SkyblockCraftingRecipe.IDENTIFIER), EntryStacks.of(Items.CRAFTING_TABLE)); + categoryRegistry.addWorkstations(CategoryIdentifier.of(SkyblockForgeRecipe.IDENTIFIER), EntryStacks.of(Items.ANVIL)); + //categoryRegistry.addWorkstations(CategoryIdentifier.of(SkyblockMobDropRecipe.IDENTIFIER), EntryStacks.of(Items.ANVIL)); + categoryRegistry.add(new SkyblockRecipeCategory(SkyblockCraftingRecipe.IDENTIFIER, Text.translatable("emi.category.skyblocker.skyblock"), ItemUtils.getSkyblockerStack(), 73)); + categoryRegistry.add(new SkyblockRecipeCategory(SkyblockForgeRecipe.IDENTIFIER, Text.literal("Dwarven Forge (Skyblock)"), new ItemStack(Items.FURNACE), 84)); + categoryRegistry.add(new SkyblockRecipeCategory(SkyblockMobDropRecipe.IDENTIFIER, Text.literal("Mob Drops (Skyblock)"), new ItemStack(Items.DIAMOND_SWORD), 73)); } @Override public void registerDisplays(DisplayRegistry displayRegistry) { - displayRegistry.registerDisplayGenerator(SKYBLOCK, new SkyblockCraftingDisplayGenerator()); + if (FabricLoader.getInstance().isModLoaded("firmament")) return; + displayRegistry.registerGlobalDisplayGenerator(new SkyblockRecipeDisplayGenerator()); } @Override public void registerEntries(EntryRegistry entryRegistry) { + if (FabricLoader.getInstance().isModLoaded("firmament")) return; + entryRegistry.removeEntryIf(entryStack -> true); entryRegistry.addEntries(ItemRepository.getItemsStream().map(EntryStacks::of).toList()); } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/CreeperEntityAccessor.java b/src/main/java/de/hysky/skyblocker/mixins/CreeperEntityAccessor.java new file mode 100644 index 0000000000..99566409dd --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/mixins/CreeperEntityAccessor.java @@ -0,0 +1,13 @@ +package de.hysky.skyblocker.mixins; + +import net.minecraft.entity.data.TrackedData; +import net.minecraft.entity.mob.CreeperEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(CreeperEntity.class) +public interface CreeperEntityAccessor { + + @Accessor("CHARGED") + static TrackedData getCharged() { throw new RuntimeException();} +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/EntityCreator.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/EntityCreator.java new file mode 100644 index 0000000000..c11d24fb6b --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/EntityCreator.java @@ -0,0 +1,314 @@ +package de.hysky.skyblocker.skyblock.itemlist; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.authlib.GameProfile; +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.mixins.CreeperEntityAccessor; +import de.hysky.skyblocker.utils.ItemUtils; +import de.hysky.skyblocker.utils.NEURepoManager; +import io.github.moulberry.repo.data.NEUItem; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.util.DefaultSkinHelper; +import net.minecraft.client.util.SkinTextures; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.component.ComponentChanges; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.DyedColorComponent; +import net.minecraft.component.type.ProfileComponent; +import net.minecraft.entity.*; +import net.minecraft.entity.boss.WitherEntity; +import net.minecraft.entity.mob.CreeperEntity; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.entity.passive.AbstractHorseEntity; +import net.minecraft.entity.player.PlayerModelPart; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public class EntityCreator { + + public static final Map> ID_TO_TYPE = Map.ofEntries( + Map.entry("Zombie", EntityType.ZOMBIE), + Map.entry("Chicken", EntityType.CHICKEN), + Map.entry("Slime", EntityType.SLIME), + Map.entry("Wolf", EntityType.WOLF), + Map.entry("Skeleton", EntityType.SKELETON), + Map.entry("Creeper", EntityType.CREEPER), + Map.entry("Ocelot", EntityType.OCELOT), + Map.entry("Blaze", EntityType.BLAZE), + Map.entry("Rabbit", EntityType.RABBIT), + Map.entry("Sheep", EntityType.SHEEP), + Map.entry("Horse", EntityType.HORSE), + Map.entry("Eisengolem", EntityType.IRON_GOLEM), + Map.entry("Silverfish", EntityType.SILVERFISH), + Map.entry("Witch", EntityType.WITCH), + Map.entry("Endermite", EntityType.ENDERMITE), + Map.entry("Snowman", EntityType.SNOW_GOLEM), + Map.entry("Villager", EntityType.VILLAGER), + Map.entry("Guardian", EntityType.GUARDIAN), + Map.entry("ArmorStand", EntityType.ARMOR_STAND), + Map.entry("Squid", EntityType.SQUID), + Map.entry("Bat", EntityType.BAT), + Map.entry("Spider", EntityType.SPIDER), + Map.entry("CaveSpider", EntityType.CAVE_SPIDER), + Map.entry("Pigman", EntityType.ZOMBIFIED_PIGLIN), + Map.entry("Ghast", EntityType.GHAST), + Map.entry("MagmaCube", EntityType.MAGMA_CUBE), + Map.entry("Wither", EntityType.WITHER), + Map.entry("Enderman", EntityType.ENDERMAN), + Map.entry("Mooshroom", EntityType.MOOSHROOM), + Map.entry("WitherSkeleton", EntityType.WITHER_SKELETON), + Map.entry("Cow", EntityType.COW), + Map.entry("Dragon", EntityType.ENDER_DRAGON), + Map.entry("Pig", EntityType.PIG), + Map.entry("Giant", EntityType.GIANT) + ); + + public static @Nullable LivingEntity createEntity(String jsonFilePath) { + JsonObject object; + try (BufferedReader reader = Files.newBufferedReader(NEURepoManager.NEU_REPO.getBaseFolder().resolve(jsonFilePath.replace("neurepo:", "")))) { + object = SkyblockerMod.GSON.fromJson(reader, JsonObject.class); + } catch (IOException ignored) { + return null; + } + + return createEntityFromJson(object); + } + + public static @Nullable LivingEntity createEntityFromJson(JsonObject object) { + LivingEntity entity; + MinecraftClient client = MinecraftClient.getInstance(); + if (client.world == null) return null; + if ("Player".equals(object.get("entity").getAsString())) { + entity = new EditablePlayer(client.world); + } else { + EntityType type = ID_TO_TYPE.get(object.get("entity").getAsString()); + if (type == null) return null; + entity = (LivingEntity) type.create(client.world); + } + if (entity == null) return null; + if (object.has("modifiers")) { + for (JsonElement jsonElement : object.getAsJsonArray("modifiers")) { + JsonObject modifier = jsonElement.getAsJsonObject(); + switch (modifier.get("type").getAsString()) { + case "age" -> makeEntitySmol(entity, modifier); + case "equipment" -> addEquipment(entity, modifier); + case "riding" -> riding(entity, modifier); + case "charged" -> { + if (entity instanceof CreeperEntity creeper) creeper.getDataTracker().set(CreeperEntityAccessor.getCharged(), true); + } + case "name" -> { + entity.setCustomName(Text.literal(modifier.get("name").getAsString())); + entity.setCustomNameVisible(true); + } + case "witherdata" -> wither(entity, modifier); + case "invisible" -> entity.setInvisible(!modifier.has("invisible") || modifier.get("invisible").getAsBoolean()); + case "horse" -> { + LivingEntity horsey = horsey(entity, modifier); + if (horsey != null) entity = horsey; + } + case "playerdata" -> player(entity, modifier); + default -> {} + } + } + } + return entity; + } + + public static void makeEntitySmol(LivingEntity entity, JsonObject modifier) { + if (modifier.has("isBaby") && modifier.get("isBaby").getAsBoolean() && entity instanceof MobEntity mob) { + mob.setBaby(true); + } + } + + private static ItemStack createLeatherThingy(Item item, String color) { + return new ItemStack(RegistryEntry.of(item), 1, ComponentChanges.builder().add(DataComponentTypes.DYED_COLOR, new DyedColorComponent(Integer.parseInt(color, 16), false)).build()); + } + + public static void addEquipment(LivingEntity entity, JsonObject modifier) { + Map fields = Map.of( + "helmet", EquipmentSlot.HEAD, + "chestplate", EquipmentSlot.CHEST, + "leggings", EquipmentSlot.LEGS, + "feet", EquipmentSlot.FEET, + "hand", EquipmentSlot.MAINHAND + ); + + for (Map.Entry entry : fields.entrySet()) { + if (!modifier.has(entry.getKey())) continue; + String s = modifier.get(entry.getKey()).getAsString(); + if (s.contains("#")) { + String[] split = s.split("#", 2); + ItemStack toEquip = switch (split[0]) { + case "SKULL" -> new ItemStack(RegistryEntry.of(Items.PLAYER_HEAD), 1, ComponentChanges.builder().add( + DataComponentTypes.PROFILE, new ProfileComponent(Optional.empty(), Optional.empty(), ItemUtils.propertyMapWithTexture(split[1]))).build()); + case "LEATHER_HELMET" -> createLeatherThingy(Items.LEATHER_HELMET, split[1]); + case "LEATHER_CHESTPLATE" -> createLeatherThingy(Items.LEATHER_CHESTPLATE, split[1]); + case "LEATHER_LEGGINGS" -> createLeatherThingy(Items.LEATHER_LEGGINGS, split[1]); + case "LEATHER_BOOTS" -> createLeatherThingy(Items.LEATHER_BOOTS, split[1]); + case null, default -> ItemStack.EMPTY; + }; + entity.equipStack(entry.getValue(), toEquip); + } else { + NEUItem id = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(s); + if (id == null) continue; + ItemStack stack = ItemStackBuilder.fromNEUItem(id); + entity.equipStack(entry.getValue(), stack); + } + } + } + + public static void riding(LivingEntity entity, JsonObject modifier) { + LivingEntity entityFromJson = createEntityFromJson(modifier); + if (entityFromJson == null) return; + entity.startRiding(entityFromJson, true); + } + + public static void wither(LivingEntity entity, JsonObject modifier) { + if (!(entity instanceof WitherEntity wither)) return; + if (modifier.has("tiny") && modifier.get("tiny").getAsBoolean()) { + wither.setInvulTimer(800); + } else wither.setInvulTimer(0); + if (modifier.has("armored") && modifier.get("armored").getAsBoolean()) { + wither.setHealth(1); + } else wither.setHealth(9999999); + + } + + public static LivingEntity horsey(LivingEntity entity, JsonObject modifier) { + if (!(entity instanceof AbstractHorseEntity horse)) return null; + if (modifier.has("kind")) { + final ClientWorld world = MinecraftClient.getInstance().world; + switch (modifier.get("kind").getAsString()) { + case "skeleton" -> horse = EntityType.SKELETON_HORSE.create(world); + case "zombie" -> horse = EntityType.ZOMBIE_HORSE.create(world); + case "donkey" -> horse = EntityType.DONKEY.create(world); + case "mule" -> horse = EntityType.MULE.create(world); + } + } + if (horse == null) return null; + if (modifier.has("armor")) { + if (modifier.isJsonNull()) horse.equipStack(EquipmentSlot.BODY, null); + else horse.equipStack(EquipmentSlot.BODY, switch (modifier.get("armor").getAsString()) { + case "diamond" -> new ItemStack(Items.DIAMOND_HORSE_ARMOR); + case "gold" -> new ItemStack(Items.GOLDEN_HORSE_ARMOR); + case "iron" -> new ItemStack(Items.IRON_HORSE_ARMOR); + case null, default -> ItemStack.EMPTY; + }); + } + if (modifier.has("saddled") && modifier.get("saddled").getAsBoolean()) { + horse.saddle(Items.SADDLE.getDefaultStack(), null); + } + return entity; + } + + public static void player(LivingEntity entity, JsonObject modifier) { + if (!(entity instanceof EditablePlayer player)) return; + if (modifier.has("cape")) { + player.setCape(Identifier.of(modifier.get("cape").getAsString())); + } + if (modifier.has("skin")) { + player.setSkin(Identifier.of(modifier.get("skin").getAsString())); + } + if (modifier.has("slim")) { + player.setSlim(modifier.get("slim").getAsBoolean()); + } + if (modifier.has("parts")) { + JsonElement jsonElement = modifier.get("parts"); + if (jsonElement.isJsonPrimitive() && jsonElement.getAsJsonPrimitive().isBoolean()) { + player.setSecondLayer((byte) (jsonElement.getAsBoolean() ? -1 : 0)); + } else { + int bits = 0; + JsonObject obj = jsonElement.getAsJsonObject(); + for (Map.Entry part : obj.entrySet()) { + PlayerModelPart modelPart = PlayerModelPart.valueOf(part.getKey()); + if (part.getValue().getAsBoolean()) { + bits |= modelPart.getBitFlag(); + } else { + bits &= ~modelPart.getBitFlag(); + } + } + player.setSecondLayer((byte) bits); + } + + } + + } + + private static class EditablePlayer extends AbstractClientPlayerEntity { + + private SkinTextures textures = DefaultSkinHelper.getSkinTextures(getGameProfile()); + + public EditablePlayer(ClientWorld world) { + super(world, new GameProfile(UUID.randomUUID(), "")); + setCustomName(Text.empty()); + } + + public void setCape(Identifier cape) { + textures = new SkinTextures( + textures.texture(), + textures.textureUrl(), + cape, + textures.elytraTexture(), + textures.model(), + textures.secure()); + } + + public void setSlim(boolean slim) { + textures = new SkinTextures( + textures.texture(), + textures.textureUrl(), + textures.capeTexture(), + textures.elytraTexture(), + slim ? SkinTextures.Model.SLIM : SkinTextures.Model.WIDE, + textures.secure()); + } + + public void setSkin(Identifier skin) { + textures = new SkinTextures( + skin, + textures.textureUrl(), + textures.capeTexture(), + textures.elytraTexture(), + textures.model(), + textures.secure()); + } + + public void setSecondLayer(byte bytes) { + getDataTracker().set(PLAYER_MODEL_PARTS, bytes); + } + + @Override + public SkinTextures getSkinTextures() { + return textures; + } + + @Override + public Text getName() { + return getCustomName(); + } + + @Override + public boolean isSpectator() { + return false; + } + + @Override + public boolean isCreative() { + return false; + } + } +} 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 8c071f5979..8b748e4284 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java @@ -2,21 +2,22 @@ import de.hysky.skyblocker.annotations.Init; import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockForgeRecipe; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockMobDropRecipe; +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.NEUItem; -import io.github.moulberry.repo.data.NEURecipe; +import io.github.moulberry.repo.data.*; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.function.Function; import java.util.stream.Stream; public class ItemRepository { @@ -24,7 +25,7 @@ public class ItemRepository { private static final List items = new ArrayList<>(); private static final Map itemsMap = new HashMap<>(); - private static final List recipes = new ArrayList<>(); + private static final List recipes = new ArrayList<>(); private static boolean filesImported = false; @Init @@ -64,8 +65,10 @@ private static void loadItem(NEUItem item) { private static void loadRecipes(NEUItem item) { for (NEURecipe recipe : item.getRecipes()) { - if (recipe instanceof NEUCraftingRecipe neuCraftingRecipe) { - recipes.add(SkyblockCraftingRecipe.fromNEURecipe(neuCraftingRecipe)); + switch (recipe) { + case NEUCraftingRecipe craftingRecipe -> recipes.add(new SkyblockCraftingRecipe(craftingRecipe)); + case NEUForgeRecipe forgeRecipe -> recipes.add(new SkyblockForgeRecipe(forgeRecipe)); + case null, default -> {} } } } @@ -88,20 +91,8 @@ public static String getWikiLink(String neuId) { return null; } - public static List getRecipes(String neuId) { - List result = new ArrayList<>(); - for (SkyblockCraftingRecipe recipe : recipes) { - if (ItemUtils.getItemId(recipe.getResult()).equals(neuId)) result.add(recipe); - } - for (SkyblockCraftingRecipe recipe : recipes) { - for (ItemStack ingredient : recipe.getGrid()) { - if (!ingredient.getItem().equals(Items.AIR) && ItemUtils.getItemId(ingredient).equals(neuId)) { - result.add(recipe); - break; - } - } - } - return result; + public static List getRecipesPmd(String neuId) { + return List.of(); } public static boolean filesImported() { @@ -121,15 +112,36 @@ public static Stream getItemsStream() { } /** - * @param neuId the NEU item id gotten through {@link NEUItem#getSkyblockItemId()}, {@link ItemStack#getNeuName()}, or {@link ItemUtils#getNeuId(String, String) ItemTooltip#getNeuName(String, String)} + * @param neuId the NEU item id gotten through {@link NEUItem#getSkyblockItemId()}, {@link ItemStack#getNeuName()}, or {@link ItemTooltip#getNeuName(String, String) ItemTooltip#getNeuName(String, String)} */ @Nullable public static ItemStack getItemStack(String neuId) { return itemsMap.get(neuId); } - public static Stream getRecipesStream() { - return recipes.stream(); + @Deprecated + public static Stream getRecipesStreamOld() { + return Stream.of(); + } + + @Deprecated + public static Stream getRecipesStream() {return recipes.stream(); } + + public static Stream getRecipes(ItemStack stack) { + return NEURepoManager.RECIPE_CACHE.getRecipes().getOrDefault(stack.getNeuName(), Set.of()).stream().map(ItemRepository::toSkyblockRecipe).filter(Objects::nonNull); + } + + public static Stream getUsages(ItemStack stack) { + return NEURepoManager.RECIPE_CACHE.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 NEUMobDropRecipe mobDropRecipe -> new SkyblockMobDropRecipe(mobDropRecipe); + case null, default -> null; + }; } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java index c4de2be075..ef5f5abe31 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java @@ -1,6 +1,7 @@ package de.hysky.skyblocker.skyblock.itemlist; import com.mojang.blaze3d.systems.RenderSystem; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; import de.hysky.skyblocker.utils.ItemUtils; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; @@ -189,7 +190,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { if (internalName.isEmpty()) { continue; } - List recipes = ItemRepository.getRecipes(internalName); + List recipes = ItemRepository.getRecipesPmd(internalName); if (!recipes.isEmpty()) { this.recipeResults = recipes; this.currentPage = 0; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SkyblockCraftingRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SkyblockCraftingRecipe.java index bc6d797751..e69de29bb2 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SkyblockCraftingRecipe.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SkyblockCraftingRecipe.java @@ -1,61 +0,0 @@ -package de.hysky.skyblocker.skyblock.itemlist; - -import de.hysky.skyblocker.utils.ItemUtils; -import io.github.moulberry.repo.data.NEUCraftingRecipe; -import io.github.moulberry.repo.data.NEUIngredient; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.util.Identifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -public class SkyblockCraftingRecipe { - private static final Logger LOGGER = LoggerFactory.getLogger(SkyblockCraftingRecipe.class); - private final String craftText; - private final List grid = new ArrayList<>(9); - private ItemStack result; - - public SkyblockCraftingRecipe(String craftText) { - this.craftText = craftText; - } - - public static SkyblockCraftingRecipe fromNEURecipe(NEUCraftingRecipe neuCraftingRecipe) { - SkyblockCraftingRecipe recipe = new SkyblockCraftingRecipe(neuCraftingRecipe.getExtraText() != null ? neuCraftingRecipe.getExtraText() : ""); - for (NEUIngredient input : neuCraftingRecipe.getInputs()) { - recipe.grid.add(getItemStack(input)); - } - recipe.result = getItemStack(neuCraftingRecipe.getOutput()); - return recipe; - } - - private static ItemStack getItemStack(NEUIngredient input) { - if (input != NEUIngredient.SENTINEL_EMPTY) { - ItemStack stack = ItemRepository.getItemStack(input.getItemId()); - if (stack != null) { - return stack.copyWithCount((int) input.getAmount()); - } else { - LOGGER.warn("[Skyblocker Recipe] Unable to find item {}", input.getItemId()); - } - } - return Items.AIR.getDefaultStack(); - } - - public List getGrid() { - return grid; - } - - public ItemStack getResult() { - return result; - } - - public String getCraftText() { - return craftText; - } - - public Identifier getId() { - return Identifier.of("skyblock", ItemUtils.getItemId(getResult()).toLowerCase().replace(';', '_') + "_" + getResult().getCount()); - } -} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockCraftingRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockCraftingRecipe.java new file mode 100644 index 0000000000..be6084e00a --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockCraftingRecipe.java @@ -0,0 +1,92 @@ +package de.hysky.skyblocker.skyblock.itemlist.recipes; + +import de.hysky.skyblocker.SkyblockerMod; +import io.github.moulberry.repo.data.NEUCraftingRecipe; +import io.github.moulberry.repo.data.NEUIngredient; +import net.minecraft.client.gui.ScreenPos; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class SkyblockCraftingRecipe implements SkyblockRecipe { + + public static final Identifier IDENTIFIER = Identifier.of(SkyblockerMod.NAMESPACE, "skyblock_crafting"); + + private final Text craftText; + private final List grid = new ArrayList<>(9); + private final ItemStack result; + + public SkyblockCraftingRecipe(NEUCraftingRecipe neuCraftingRecipe) { + this.craftText = neuCraftingRecipe.getExtraText() != null ? Text.literal(neuCraftingRecipe.getExtraText()) : Text.empty(); + for (NEUIngredient input : neuCraftingRecipe.getInputs()) { + grid.add(SkyblockRecipe.getItemStack(input)); + } + result = SkyblockRecipe.getItemStack(neuCraftingRecipe.getOutput()); + } + + public static SkyblockCraftingRecipe fromNEURecipe(NEUCraftingRecipe neuCraftingRecipe) { + return new SkyblockCraftingRecipe(neuCraftingRecipe); + } + + + + public List getGrid() { + return grid; + } + + public ItemStack getResult() { + return result; + } + + public String getCraftText() { + return "remove this"; + } + + @Override + public List getInputSlots(int width, int height) { + ScreenPos start = new ScreenPos(width / 2 - 58, height / 2 - (getExtraText().getString().isEmpty() ? 26: 31)); + List toReturn = new ArrayList<>(9); + for (int i = 0; i < grid.size(); i++) { + int x = i % 3; + int y = i / 3; + toReturn.add(new RecipeSlot(start.x() + 1 + x * 18, start.y() + 1 + y * 18, grid.get(i))); + } + return toReturn; + } + + @Override + public List getOutputSlots(int width, int height) { + ScreenPos start = new ScreenPos(width / 2 - 58, height / 2 - (getExtraText().getString().isEmpty() ? 26: 31)); + return List.of(new RecipeSlot(start.x() + 95, start.y() + 19, result)); + } + + @Override + public List getInputs() { + return grid; + } + + @Override + public List getOutputs() { + return List.of(result); + } + + @Override + public Text getExtraText() { + return craftText; + } + + @Override + public Identifier getCategoryIdentifier() { + return SkyblockCraftingRecipe.IDENTIFIER; + } + + @Override + public @Nullable ScreenPos getArrowLocation(int width, int height) { + ScreenPos start = new ScreenPos(width / 2 - 58, height / 2 - (getExtraText().getString().isEmpty() ? 26: 31)); + return new ScreenPos(start.x() + 60, start.y() + 18); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java new file mode 100644 index 0000000000..aec21a76ed --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java @@ -0,0 +1,77 @@ +package de.hysky.skyblocker.skyblock.itemlist.recipes; + +import de.hysky.skyblocker.SkyblockerMod; +import io.github.moulberry.repo.data.NEUForgeRecipe; +import net.minecraft.client.gui.ScreenPos; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class SkyblockForgeRecipe implements SkyblockRecipe { + + public static final Identifier IDENTIFIER = Identifier.of(SkyblockerMod.NAMESPACE, "skyblock_forge"); + + private final List inputs; + private final ItemStack output; + + public SkyblockForgeRecipe(NEUForgeRecipe forgeRecipe) { + inputs = forgeRecipe.getInputs().stream().map(SkyblockRecipe::getItemStack).toList(); + output = SkyblockRecipe.getItemStack(forgeRecipe.getOutputStack()); + } + + + @Override + public List getInputSlots(int width, int height) { + List out = new ArrayList<>(); + int centerX = width / 2; + int centerY = height / 2; + float radius = getRadius(); + for (int i = 0; i < inputs.size(); i++) { + float angle = 2 * MathHelper.PI * (float) i / (float) inputs.size(); + int x = (int) (MathHelper.cos(angle) * radius); + int y = (int) (MathHelper.sin(angle) * radius); + out.add(new RecipeSlot(Math.max(centerX / 2, (int) radius + 14) - 9 + x, centerY - 9 + y, inputs.get(i))); + } + return out; + } + + private float getRadius() { + return Math.max(26 * inputs.size() / (2 * MathHelper.PI), 20); + } + + @Override + public List getOutputSlots(int width, int height) { + return List.of(new RecipeSlot(width / 2 + 37, height / 2 - 9, output)); + } + + @Override + public List getInputs() { + return inputs; + } + + @Override + public List getOutputs() { + return List.of(output); + } + + @Override + public Text getExtraText() { + return Text.empty(); + } + + @Override + public Identifier getCategoryIdentifier() { + return IDENTIFIER; + } + + @Override + public @Nullable ScreenPos getArrowLocation(int width, int height) { + float v = (3 * width) / 4.f; + return new ScreenPos((int) ((v + getRadius() + 9 + 37 - 24) / 2), height / 2 - 9); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockMobDropRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockMobDropRecipe.java new file mode 100644 index 0000000000..5ea2e0aeac --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockMobDropRecipe.java @@ -0,0 +1,123 @@ +package de.hysky.skyblocker.skyblock.itemlist.recipes; + +import com.mojang.blaze3d.systems.RenderSystem; +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.skyblock.itemlist.EntityCreator; +import de.hysky.skyblocker.utils.ItemUtils; +import io.github.moulberry.repo.data.NEUMobDropRecipe; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.LoreComponent; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.List; + +public class SkyblockMobDropRecipe implements SkyblockRecipe { + + public static final Identifier IDENTIFIER = Identifier.of(SkyblockerMod.NAMESPACE, "skyblock_drops"); + + private final List drops = new ArrayList<>(); + private final @Nullable LivingEntity entity; + + public SkyblockMobDropRecipe(NEUMobDropRecipe mobDropRecipe) { + for (NEUMobDropRecipe.Drop drop : mobDropRecipe.getDrops()) { + ItemStack itemStack = SkyblockRecipe.getItemStack(drop.getDropItem()); + ArrayList texts = new ArrayList<>(ItemUtils.getLore(itemStack)); + if (drop.getChance() != null) texts.add(Text.literal(drop.getChance())); + itemStack.set(DataComponentTypes.LORE, new LoreComponent(texts)); + drops.add(itemStack); + } + if (mobDropRecipe.getRender().startsWith("@")) entity = EntityCreator.createEntity(mobDropRecipe.getRender().substring(1)); + else { + EntityType type = EntityCreator.ID_TO_TYPE.get(mobDropRecipe.getRender()); + if (type != null) entity = (LivingEntity) type.create(MinecraftClient.getInstance().world); + else entity = null; + } + } + + @Override + public List getInputSlots(int width, int height) { + return List.of(); + } + + @Override + public List getOutputSlots(int width, int height) { + List out = new ArrayList<>(); + int maxPerRow = (width / 2 - 4) / 18; + for (int i = 0; i < drops.size(); i++) { + int x = width / 2 + (i % maxPerRow) * 18; + int y = 4 + (i / maxPerRow) * 18; + out.add(new RecipeSlot(x, y, drops.get(i), false)); + } + return out; + } + + @Override + public List getInputs() { + return List.of(); + } + + @Override + public List getOutputs() { + return drops; + } + + private void drawEntityNoScissors(DrawContext context, int x1, int y1, int x2, int y2, int size, float f, float mouseX, float mouseY, LivingEntity entity) { + float g = (float)(x1 + x2) / 2.0F; + float h = (float)(y1 + y2) / 2.0F; + float i = (float)Math.atan((g - mouseX) / 40.0F); + float j = (float)Math.atan((h - mouseY) / 40.0F); + Quaternionf quaternionf = new Quaternionf().rotateZ((float) Math.PI); + Quaternionf quaternionf2 = new Quaternionf().rotateX(j * 20.0F * (float) (Math.PI / 180.0)); + quaternionf.mul(quaternionf2); + float k = entity.bodyYaw; + float l = entity.getYaw(); + float m = entity.getPitch(); + float n = entity.prevHeadYaw; + float o = entity.headYaw; + entity.bodyYaw = 180.0F + i * 20.0F; + entity.setYaw(180.0F + i * 40.0F); + entity.setPitch(-j * 20.0F); + entity.headYaw = entity.getYaw(); + entity.prevHeadYaw = entity.getYaw(); + float p = entity.getScale(); + Vector3f vector3f = new Vector3f(0.0F, entity.getHeight() / 2.0F + f * p, 0.0F); + float q = (float)size / p; + InventoryScreen.drawEntity(context, g, h, q, vector3f, quaternionf, quaternionf2, entity); + entity.bodyYaw = k; + entity.setYaw(l); + entity.setPitch(m); + entity.prevHeadYaw = n; + entity.headYaw = o; + } + + @Override + public void render(DrawContext context, int width, int height, double mouseX, double mouseY) { + if (entity == null) return; + + drawEntityNoScissors( + context, 4, 4, height - 4, width / 2 - 4, + 24, 0.0625F, (int) mouseX, (int) mouseY, entity); + } + + @Override + public Text getExtraText() { + return Text.empty(); + } + + @Override + public Identifier getCategoryIdentifier() { + return IDENTIFIER; + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java new file mode 100644 index 0000000000..a41ecbb54a --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java @@ -0,0 +1,80 @@ +package de.hysky.skyblocker.skyblock.itemlist.recipes; + +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; +import io.github.moulberry.repo.data.NEUIngredient; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.ScreenPos; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public interface SkyblockRecipe { + + Logger LOGGER = LoggerFactory.getLogger(SkyblockCraftingRecipe.class); + + + + static ItemStack getItemStack(NEUIngredient input) { + if (input != NEUIngredient.SENTINEL_EMPTY) { + ItemStack stack = ItemRepository.getItemStack(input.getItemId()); + if (stack != null) { + return stack.copyWithCount((int) input.getAmount()); + } else { + LOGGER.warn("[Skyblocker Recipe] Unable to find item {}", input.getItemId()); + } + } + return Items.AIR.getDefaultStack(); + } + + /** + * @param width the available area's width + * @param height the available area's height + * @return list of slots + */ + List getInputSlots(int width, int height); + + /** + * @param width the available area's width + * @param height the available area's height + * @return list of slots + */ + List getOutputSlots(int width, int height); + + default @Nullable ScreenPos getArrowLocation(int width, int height) { + return null; + } + + List getInputs(); + List getOutputs(); + + /** + * Render some extra things, i.e an entity + * @param width available width + * @param height available height + * @param mouseX mouse x + * @param mouseY mouse y + */ + default void render(DrawContext context, int width, int height, double mouseX, double mouseY) {}; + + /** + * Extra text like collection requirements + * @return the text + */ + Text getExtraText(); + + Identifier getCategoryIdentifier(); + + record RecipeSlot(int x, int y, ItemStack stack, boolean showBackground) { + public RecipeSlot(int x, int y, ItemStack stack) { + this(x, y, stack, true); + } + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java b/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java index 87e19ccf44..dc639a286d 100644 --- a/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java +++ b/src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java @@ -6,6 +6,7 @@ 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.NEURecipeCache; import io.github.moulberry.repo.NEURepository; import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; @@ -37,6 +38,7 @@ public class NEURepoManager { private static final Path LOCAL_REPO_DIR = SkyblockerMod.CONFIG_DIR.resolve("item-repo"); // TODO rename to NotEnoughUpdates-REPO private static CompletableFuture 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. diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index e9b558cbed..cbb984e029 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -1126,5 +1126,5 @@ "skyblocker.profileviewer.inventory.inactive.description.backpack": "The selected backpack", "skyblocker.profileviewer.inventory.inactive.description.general": "does not contain this slot", - "emi.category.skyblocker.skyblock": "Skyblock" + "emi.category.skyblocker.skyblock": "Crafting (Skyblock)" } diff --git a/src/main/resources/skyblocker.mixins.json b/src/main/resources/skyblocker.mixins.json index 57eea120e3..603abfe3fa 100644 --- a/src/main/resources/skyblocker.mixins.json +++ b/src/main/resources/skyblocker.mixins.json @@ -61,5 +61,8 @@ ], "injectors": { "defaultRequire": 1 - } + }, + "mixins": [ + "CreeperEntityAccessor" + ] } From 2d292facf74ed2cc085c79c4d814ef177049e224 Mon Sep 17 00:00:00 2001 From: viciscat <51047087+viciscat@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:30:04 +0200 Subject: [PATCH 2/6] emi, finish forge and recipe book --- build.gradle | 5 +- gradle.properties | 2 +- .../compatibility/emi/SkyblockEmiRecipe.java | 56 +++- .../emi/SkyblockerEMIPlugin.java | 26 +- .../jei/SkyblockCraftingRecipeCategory.java | 2 +- .../jei/SkyblockerJEIPlugin.java | 5 +- .../rei/SkyblockerREIClientPlugin.java | 7 +- .../skyblock/itemlist/EntityCreator.java | 314 ------------------ .../skyblock/itemlist/ItemRepository.java | 9 +- .../itemlist/SearchResultsWidget.java | 100 ++++-- .../itemlist/SkyblockCraftingRecipe.java | 0 .../recipes/SkyblockCraftingRecipe.java | 19 +- .../itemlist/recipes/SkyblockForgeRecipe.java | 42 ++- .../recipes/SkyblockMobDropRecipe.java | 123 ------- .../itemlist/recipes/SkyblockRecipe.java | 21 +- .../assets/skyblocker/lang/en_us.json | 3 +- .../assets/skyblocker/lang/it_it.json | 2 +- .../assets/skyblocker/lang/pt_br.json | 2 +- .../assets/skyblocker/lang/ru_ru.json | 2 +- .../assets/skyblocker/lang/zh_cn.json | 2 +- .../assets/skyblocker/lang/zh_tw.json | 2 +- .../skyblocker/textures/gui/emi_icons.png | Bin 0 -> 654 bytes .../skyblocker/textures/gui/sprites/arrow.png | Bin 0 -> 219 bytes 23 files changed, 211 insertions(+), 533 deletions(-) delete mode 100644 src/main/java/de/hysky/skyblocker/skyblock/itemlist/EntityCreator.java delete mode 100644 src/main/java/de/hysky/skyblocker/skyblock/itemlist/SkyblockCraftingRecipe.java delete mode 100644 src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockMobDropRecipe.java create mode 100644 src/main/resources/assets/skyblocker/textures/gui/emi_icons.png create mode 100644 src/main/resources/assets/skyblocker/textures/gui/sprites/arrow.png diff --git a/build.gradle b/build.gradle index f162af0065..d62bb954d0 100644 --- a/build.gradle +++ b/build.gradle @@ -160,11 +160,12 @@ dependencies { // REI modCompileOnly "me.shedaniel:RoughlyEnoughItems-api-fabric:${project.rei_version}" - //modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}" + modCompileOnly "me.shedaniel:RoughlyEnoughItems-api:${project.rei_version}" + modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}" // EMI modCompileOnly "dev.emi:emi-fabric:${project.emi_version}:api" - //modLocalRuntime "dev.emi:emi-fabric:${project.emi_version}" + modLocalRuntime "dev.emi:emi-fabric:${project.emi_version}" // JEI (Using modrinth repo since official release is in mojmap and doesn't work) modCompileOnly "maven.modrinth:jei:${project.jei_version}-fabric" diff --git a/gradle.properties b/gradle.properties index b9b2872dee..3f0cc29703 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,7 @@ hm_api_version=1.0.1+1.21.1 ## Mod Menu (https://modrinth.com/mod/modmenu/versions) mod_menu_version = 11.0.0-beta.1 ## REI (https://modrinth.com/mod/rei/versions?l=fabric) -rei_version = 13.0.666 +rei_version = 16.0.754 ## EMI (https://modrinth.com/mod/emi/versions) emi_version = 1.1.10+1.21 ## JEI (https://modrinth.com/mod/jei/versions) diff --git a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java index 6ea0f46c3f..b9881bc681 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java @@ -1,35 +1,69 @@ package de.hysky.skyblocker.compatibility.emi; -import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; -import dev.emi.emi.api.recipe.EmiCraftingRecipe; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockRecipe; +import dev.emi.emi.api.recipe.EmiRecipe; import dev.emi.emi.api.recipe.EmiRecipeCategory; +import dev.emi.emi.api.render.EmiTexture; import dev.emi.emi.api.stack.EmiIngredient; import dev.emi.emi.api.stack.EmiStack; import dev.emi.emi.api.widget.WidgetHolder; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.ScreenPos; import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; -public class SkyblockEmiRecipe extends EmiCraftingRecipe { - private final String craftText; +import java.util.List; - public SkyblockEmiRecipe(SkyblockCraftingRecipe recipe) { - super(recipe.getGrid().stream().map(EmiStack::of).map(EmiIngredient.class::cast).toList(), EmiStack.of(recipe.getResult()), recipe.getId()); - this.craftText = recipe.getCraftText(); +public class SkyblockEmiRecipe implements EmiRecipe { + private final Text craftText; + private final SkyblockRecipe recipe; + + public SkyblockEmiRecipe(SkyblockRecipe recipe) { + this.craftText = recipe.getExtraText(); + this.recipe = recipe; } @Override public EmiRecipeCategory getCategory() { - return SkyblockerEMIPlugin.SKYBLOCK; + return SkyblockerEMIPlugin.IDENTIFIER_CATEGORY_MAP.get(recipe.getCategoryIdentifier()); + } + + @Override + public @Nullable Identifier getId() { + return recipe.getRecipeIdentifier(); + } + + @Override + public List getInputs() { + return recipe.getInputs().stream().map(EmiStack::of).map(EmiIngredient.class::cast).toList(); + } + + @Override + public List getOutputs() { + return recipe.getOutputs().stream().map(EmiStack::of).toList(); + } + + @Override + public int getDisplayWidth() { + return 118; } @Override public int getDisplayHeight() { - return super.getDisplayHeight() + (craftText.isEmpty() ? 0 : 10); + return 54 + (craftText.getString().isEmpty() ? 0 : 10); } @Override public void addWidgets(WidgetHolder widgets) { - super.addWidgets(widgets); - widgets.addText(Text.of(craftText), 59 - MinecraftClient.getInstance().textRenderer.getWidth(craftText) / 2, 55, 0xFFFFFF, true); + ScreenPos arrowLocation = recipe.getArrowLocation(getDisplayWidth(), getDisplayHeight()); + if (arrowLocation != null) widgets.addTexture(EmiTexture.EMPTY_ARROW, arrowLocation.x(), arrowLocation.y()); + widgets.addText(craftText, 59 - MinecraftClient.getInstance().textRenderer.getWidth(craftText) / 2, 55, 0xFFFFFF, true); + for (SkyblockRecipe.RecipeSlot inputSlot : recipe.getInputSlots(getDisplayWidth(), getDisplayHeight())) { + widgets.addSlot(EmiStack.of(inputSlot.stack()), inputSlot.x(), inputSlot.y()); + } + for (SkyblockRecipe.RecipeSlot outputSlot : recipe.getOutputSlots(getDisplayWidth(), getDisplayHeight())) { + widgets.addSlot(EmiStack.of(outputSlot.stack()), outputSlot.x(), outputSlot.y()).recipeContext(this); + } } } diff --git a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java index a7c67267d3..bb1e7b09e9 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java @@ -2,6 +2,8 @@ import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockForgeRecipe; import de.hysky.skyblocker.utils.ItemUtils; import dev.emi.emi.api.EmiPlugin; import dev.emi.emi.api.EmiRegistry; @@ -12,22 +14,32 @@ import net.minecraft.item.Items; import net.minecraft.util.Identifier; +import java.util.Map; + /** * EMI integration */ public class SkyblockerEMIPlugin implements EmiPlugin { - public static final Identifier SIMPLIFIED_TEXTURES = Identifier.of("emi", "textures/gui/widgets.png"); - // TODO: Custom simplified texture for Skyblock - public static final EmiRecipeCategory SKYBLOCK = new EmiRecipeCategory(Identifier.of(SkyblockerMod.NAMESPACE, "skyblock"), EmiStack.of(ItemUtils.getSkyblockerStack()), new EmiTexture(SIMPLIFIED_TEXTURES, 240, 240, 16, 16)); + public static final Identifier SIMPLIFIED_TEXTURES = Identifier.of(SkyblockerMod.NAMESPACE, "textures/gui/emi_icons.png"); + + public static final EmiRecipeCategory SKYBLOCK_CRAFTING = new EmiRecipeCategory(SkyblockCraftingRecipe.IDENTIFIER, EmiStack.of(Items.CRAFTING_TABLE), new EmiTexture(SIMPLIFIED_TEXTURES, 0, 0, 16, 16)); + public static final EmiRecipeCategory SKYBLOCK_FORGE = new EmiRecipeCategory(SkyblockForgeRecipe.IDENTIFIER, EmiStack.of(Items.LAVA_BUCKET), new EmiTexture(SIMPLIFIED_TEXTURES, 16, 0, 16, 16)); + + protected static final Map IDENTIFIER_CATEGORY_MAP = Map.of( + SkyblockCraftingRecipe.IDENTIFIER, SKYBLOCK_CRAFTING, + SkyblockForgeRecipe.IDENTIFIER, SKYBLOCK_FORGE + ); @Override public void register(EmiRegistry registry) { ItemRepository.getItemsStream().map(EmiStack::of).forEach(emiStack -> { registry.addEmiStack(emiStack); - registry.setDefaultComparison(emiStack, Comparison.compareComponents()); + registry.setDefaultComparison(emiStack, Comparison.compareData(emiStack1 -> ItemUtils.getItemId(emiStack1.getItemStack()))); }); - registry.addCategory(SKYBLOCK); - registry.addWorkstation(SKYBLOCK, EmiStack.of(Items.CRAFTING_TABLE)); - ItemRepository.getRecipesStreamOld().map(SkyblockEmiRecipe::new).forEach(registry::addRecipe); + registry.addCategory(SKYBLOCK_CRAFTING); + registry.addCategory(SKYBLOCK_FORGE); + registry.addWorkstation(SKYBLOCK_CRAFTING, EmiStack.of(Items.CRAFTING_TABLE)); + registry.addWorkstation(SKYBLOCK_CRAFTING, EmiStack.of(Items.LAVA_BUCKET)); + ItemRepository.getRecipesStream().map(SkyblockEmiRecipe::new).forEach(registry::addRecipe); } } diff --git a/src/main/java/de/hysky/skyblocker/compatibility/jei/SkyblockCraftingRecipeCategory.java b/src/main/java/de/hysky/skyblocker/compatibility/jei/SkyblockCraftingRecipeCategory.java index c08155a5d5..edafd7a60b 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/jei/SkyblockCraftingRecipeCategory.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/jei/SkyblockCraftingRecipeCategory.java @@ -15,7 +15,7 @@ public class SkyblockCraftingRecipeCategory extends CraftingRecipeCategory { @SuppressWarnings({"unchecked", "RedundantCast", "rawtypes"}) private static final RecipeType> SKYBLOCK_RECIPE = new RecipeType<>(Identifier.of(SkyblockerMod.NAMESPACE, "skyblock"), (Class>) (Class) RecipeEntry.class); - private final Text title = Text.translatable("emi.category.skyblocker.skyblock"); + private final Text title = Text.translatable("emi.category.skyblocker.skyblock_crafting"); private final IDrawable icon; public SkyblockCraftingRecipeCategory(IGuiHelper guiHelper) { diff --git a/src/main/java/de/hysky/skyblocker/compatibility/jei/SkyblockerJEIPlugin.java b/src/main/java/de/hysky/skyblocker/compatibility/jei/SkyblockerJEIPlugin.java index a1e57682af..592afccf32 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/jei/SkyblockerJEIPlugin.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/jei/SkyblockerJEIPlugin.java @@ -2,6 +2,7 @@ import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; import de.hysky.skyblocker.utils.datafixer.ItemStackComponentizationFixer; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; @@ -48,8 +49,8 @@ public void registerCategories(@NotNull IRecipeCategoryRegistration registration @Override public void registerRecipes(@NotNull IRecipeRegistration registration) { registration.getIngredientManager().addIngredientsAtRuntime(VanillaTypes.ITEM_STACK, ItemRepository.getItems()); - registration.addRecipes(skyblockCraftingRecipeCategory.getRecipeType(), ItemRepository.getRecipesStream().map(recipe -> - new RecipeEntry(recipe.getId(), new ShapedRecipe("", CraftingRecipeCategory.MISC, RawShapedRecipe.create(Map.of( + registration.addRecipes(skyblockCraftingRecipeCategory.getRecipeType(), ItemRepository.getRecipesStream().filter(skyblockRecipe -> skyblockRecipe instanceof SkyblockCraftingRecipe).map(SkyblockCraftingRecipe.class::cast).map(recipe -> + new RecipeEntry(recipe.getRecipeIdentifier(), new ShapedRecipe("", CraftingRecipeCategory.MISC, RawShapedRecipe.create(Map.of( 'a', Ingredient.ofStacks(recipe.getGrid().get(0)), 'b', Ingredient.ofStacks(recipe.getGrid().get(1)), 'c', Ingredient.ofStacks(recipe.getGrid().get(2)), 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 8146ebd846..d3515b3e30 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockerREIClientPlugin.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockerREIClientPlugin.java @@ -3,7 +3,6 @@ import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockForgeRecipe; -import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockMobDropRecipe; import de.hysky.skyblocker.utils.ItemUtils; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; import me.shedaniel.rei.api.client.registry.category.CategoryRegistry; @@ -26,10 +25,8 @@ public void registerCategories(CategoryRegistry categoryRegistry) { if (FabricLoader.getInstance().isModLoaded("firmament")) return; categoryRegistry.addWorkstations(CategoryIdentifier.of(SkyblockCraftingRecipe.IDENTIFIER), EntryStacks.of(Items.CRAFTING_TABLE)); categoryRegistry.addWorkstations(CategoryIdentifier.of(SkyblockForgeRecipe.IDENTIFIER), EntryStacks.of(Items.ANVIL)); - //categoryRegistry.addWorkstations(CategoryIdentifier.of(SkyblockMobDropRecipe.IDENTIFIER), EntryStacks.of(Items.ANVIL)); - categoryRegistry.add(new SkyblockRecipeCategory(SkyblockCraftingRecipe.IDENTIFIER, Text.translatable("emi.category.skyblocker.skyblock"), ItemUtils.getSkyblockerStack(), 73)); - categoryRegistry.add(new SkyblockRecipeCategory(SkyblockForgeRecipe.IDENTIFIER, Text.literal("Dwarven Forge (Skyblock)"), new ItemStack(Items.FURNACE), 84)); - categoryRegistry.add(new SkyblockRecipeCategory(SkyblockMobDropRecipe.IDENTIFIER, Text.literal("Mob Drops (Skyblock)"), new ItemStack(Items.DIAMOND_SWORD), 73)); + 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"), new ItemStack(Items.FURNACE), 84)); } @Override diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/EntityCreator.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/EntityCreator.java deleted file mode 100644 index c11d24fb6b..0000000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/EntityCreator.java +++ /dev/null @@ -1,314 +0,0 @@ -package de.hysky.skyblocker.skyblock.itemlist; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.mojang.authlib.GameProfile; -import de.hysky.skyblocker.SkyblockerMod; -import de.hysky.skyblocker.mixins.CreeperEntityAccessor; -import de.hysky.skyblocker.utils.ItemUtils; -import de.hysky.skyblocker.utils.NEURepoManager; -import io.github.moulberry.repo.data.NEUItem; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.util.DefaultSkinHelper; -import net.minecraft.client.util.SkinTextures; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.component.ComponentChanges; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.DyedColorComponent; -import net.minecraft.component.type.ProfileComponent; -import net.minecraft.entity.*; -import net.minecraft.entity.boss.WitherEntity; -import net.minecraft.entity.mob.CreeperEntity; -import net.minecraft.entity.mob.MobEntity; -import net.minecraft.entity.passive.AbstractHorseEntity; -import net.minecraft.entity.player.PlayerModelPart; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.registry.entry.RegistryEntry; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.Nullable; - -import java.io.BufferedReader; -import java.io.IOException; -import java.nio.file.Files; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; - -public class EntityCreator { - - public static final Map> ID_TO_TYPE = Map.ofEntries( - Map.entry("Zombie", EntityType.ZOMBIE), - Map.entry("Chicken", EntityType.CHICKEN), - Map.entry("Slime", EntityType.SLIME), - Map.entry("Wolf", EntityType.WOLF), - Map.entry("Skeleton", EntityType.SKELETON), - Map.entry("Creeper", EntityType.CREEPER), - Map.entry("Ocelot", EntityType.OCELOT), - Map.entry("Blaze", EntityType.BLAZE), - Map.entry("Rabbit", EntityType.RABBIT), - Map.entry("Sheep", EntityType.SHEEP), - Map.entry("Horse", EntityType.HORSE), - Map.entry("Eisengolem", EntityType.IRON_GOLEM), - Map.entry("Silverfish", EntityType.SILVERFISH), - Map.entry("Witch", EntityType.WITCH), - Map.entry("Endermite", EntityType.ENDERMITE), - Map.entry("Snowman", EntityType.SNOW_GOLEM), - Map.entry("Villager", EntityType.VILLAGER), - Map.entry("Guardian", EntityType.GUARDIAN), - Map.entry("ArmorStand", EntityType.ARMOR_STAND), - Map.entry("Squid", EntityType.SQUID), - Map.entry("Bat", EntityType.BAT), - Map.entry("Spider", EntityType.SPIDER), - Map.entry("CaveSpider", EntityType.CAVE_SPIDER), - Map.entry("Pigman", EntityType.ZOMBIFIED_PIGLIN), - Map.entry("Ghast", EntityType.GHAST), - Map.entry("MagmaCube", EntityType.MAGMA_CUBE), - Map.entry("Wither", EntityType.WITHER), - Map.entry("Enderman", EntityType.ENDERMAN), - Map.entry("Mooshroom", EntityType.MOOSHROOM), - Map.entry("WitherSkeleton", EntityType.WITHER_SKELETON), - Map.entry("Cow", EntityType.COW), - Map.entry("Dragon", EntityType.ENDER_DRAGON), - Map.entry("Pig", EntityType.PIG), - Map.entry("Giant", EntityType.GIANT) - ); - - public static @Nullable LivingEntity createEntity(String jsonFilePath) { - JsonObject object; - try (BufferedReader reader = Files.newBufferedReader(NEURepoManager.NEU_REPO.getBaseFolder().resolve(jsonFilePath.replace("neurepo:", "")))) { - object = SkyblockerMod.GSON.fromJson(reader, JsonObject.class); - } catch (IOException ignored) { - return null; - } - - return createEntityFromJson(object); - } - - public static @Nullable LivingEntity createEntityFromJson(JsonObject object) { - LivingEntity entity; - MinecraftClient client = MinecraftClient.getInstance(); - if (client.world == null) return null; - if ("Player".equals(object.get("entity").getAsString())) { - entity = new EditablePlayer(client.world); - } else { - EntityType type = ID_TO_TYPE.get(object.get("entity").getAsString()); - if (type == null) return null; - entity = (LivingEntity) type.create(client.world); - } - if (entity == null) return null; - if (object.has("modifiers")) { - for (JsonElement jsonElement : object.getAsJsonArray("modifiers")) { - JsonObject modifier = jsonElement.getAsJsonObject(); - switch (modifier.get("type").getAsString()) { - case "age" -> makeEntitySmol(entity, modifier); - case "equipment" -> addEquipment(entity, modifier); - case "riding" -> riding(entity, modifier); - case "charged" -> { - if (entity instanceof CreeperEntity creeper) creeper.getDataTracker().set(CreeperEntityAccessor.getCharged(), true); - } - case "name" -> { - entity.setCustomName(Text.literal(modifier.get("name").getAsString())); - entity.setCustomNameVisible(true); - } - case "witherdata" -> wither(entity, modifier); - case "invisible" -> entity.setInvisible(!modifier.has("invisible") || modifier.get("invisible").getAsBoolean()); - case "horse" -> { - LivingEntity horsey = horsey(entity, modifier); - if (horsey != null) entity = horsey; - } - case "playerdata" -> player(entity, modifier); - default -> {} - } - } - } - return entity; - } - - public static void makeEntitySmol(LivingEntity entity, JsonObject modifier) { - if (modifier.has("isBaby") && modifier.get("isBaby").getAsBoolean() && entity instanceof MobEntity mob) { - mob.setBaby(true); - } - } - - private static ItemStack createLeatherThingy(Item item, String color) { - return new ItemStack(RegistryEntry.of(item), 1, ComponentChanges.builder().add(DataComponentTypes.DYED_COLOR, new DyedColorComponent(Integer.parseInt(color, 16), false)).build()); - } - - public static void addEquipment(LivingEntity entity, JsonObject modifier) { - Map fields = Map.of( - "helmet", EquipmentSlot.HEAD, - "chestplate", EquipmentSlot.CHEST, - "leggings", EquipmentSlot.LEGS, - "feet", EquipmentSlot.FEET, - "hand", EquipmentSlot.MAINHAND - ); - - for (Map.Entry entry : fields.entrySet()) { - if (!modifier.has(entry.getKey())) continue; - String s = modifier.get(entry.getKey()).getAsString(); - if (s.contains("#")) { - String[] split = s.split("#", 2); - ItemStack toEquip = switch (split[0]) { - case "SKULL" -> new ItemStack(RegistryEntry.of(Items.PLAYER_HEAD), 1, ComponentChanges.builder().add( - DataComponentTypes.PROFILE, new ProfileComponent(Optional.empty(), Optional.empty(), ItemUtils.propertyMapWithTexture(split[1]))).build()); - case "LEATHER_HELMET" -> createLeatherThingy(Items.LEATHER_HELMET, split[1]); - case "LEATHER_CHESTPLATE" -> createLeatherThingy(Items.LEATHER_CHESTPLATE, split[1]); - case "LEATHER_LEGGINGS" -> createLeatherThingy(Items.LEATHER_LEGGINGS, split[1]); - case "LEATHER_BOOTS" -> createLeatherThingy(Items.LEATHER_BOOTS, split[1]); - case null, default -> ItemStack.EMPTY; - }; - entity.equipStack(entry.getValue(), toEquip); - } else { - NEUItem id = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId(s); - if (id == null) continue; - ItemStack stack = ItemStackBuilder.fromNEUItem(id); - entity.equipStack(entry.getValue(), stack); - } - } - } - - public static void riding(LivingEntity entity, JsonObject modifier) { - LivingEntity entityFromJson = createEntityFromJson(modifier); - if (entityFromJson == null) return; - entity.startRiding(entityFromJson, true); - } - - public static void wither(LivingEntity entity, JsonObject modifier) { - if (!(entity instanceof WitherEntity wither)) return; - if (modifier.has("tiny") && modifier.get("tiny").getAsBoolean()) { - wither.setInvulTimer(800); - } else wither.setInvulTimer(0); - if (modifier.has("armored") && modifier.get("armored").getAsBoolean()) { - wither.setHealth(1); - } else wither.setHealth(9999999); - - } - - public static LivingEntity horsey(LivingEntity entity, JsonObject modifier) { - if (!(entity instanceof AbstractHorseEntity horse)) return null; - if (modifier.has("kind")) { - final ClientWorld world = MinecraftClient.getInstance().world; - switch (modifier.get("kind").getAsString()) { - case "skeleton" -> horse = EntityType.SKELETON_HORSE.create(world); - case "zombie" -> horse = EntityType.ZOMBIE_HORSE.create(world); - case "donkey" -> horse = EntityType.DONKEY.create(world); - case "mule" -> horse = EntityType.MULE.create(world); - } - } - if (horse == null) return null; - if (modifier.has("armor")) { - if (modifier.isJsonNull()) horse.equipStack(EquipmentSlot.BODY, null); - else horse.equipStack(EquipmentSlot.BODY, switch (modifier.get("armor").getAsString()) { - case "diamond" -> new ItemStack(Items.DIAMOND_HORSE_ARMOR); - case "gold" -> new ItemStack(Items.GOLDEN_HORSE_ARMOR); - case "iron" -> new ItemStack(Items.IRON_HORSE_ARMOR); - case null, default -> ItemStack.EMPTY; - }); - } - if (modifier.has("saddled") && modifier.get("saddled").getAsBoolean()) { - horse.saddle(Items.SADDLE.getDefaultStack(), null); - } - return entity; - } - - public static void player(LivingEntity entity, JsonObject modifier) { - if (!(entity instanceof EditablePlayer player)) return; - if (modifier.has("cape")) { - player.setCape(Identifier.of(modifier.get("cape").getAsString())); - } - if (modifier.has("skin")) { - player.setSkin(Identifier.of(modifier.get("skin").getAsString())); - } - if (modifier.has("slim")) { - player.setSlim(modifier.get("slim").getAsBoolean()); - } - if (modifier.has("parts")) { - JsonElement jsonElement = modifier.get("parts"); - if (jsonElement.isJsonPrimitive() && jsonElement.getAsJsonPrimitive().isBoolean()) { - player.setSecondLayer((byte) (jsonElement.getAsBoolean() ? -1 : 0)); - } else { - int bits = 0; - JsonObject obj = jsonElement.getAsJsonObject(); - for (Map.Entry part : obj.entrySet()) { - PlayerModelPart modelPart = PlayerModelPart.valueOf(part.getKey()); - if (part.getValue().getAsBoolean()) { - bits |= modelPart.getBitFlag(); - } else { - bits &= ~modelPart.getBitFlag(); - } - } - player.setSecondLayer((byte) bits); - } - - } - - } - - private static class EditablePlayer extends AbstractClientPlayerEntity { - - private SkinTextures textures = DefaultSkinHelper.getSkinTextures(getGameProfile()); - - public EditablePlayer(ClientWorld world) { - super(world, new GameProfile(UUID.randomUUID(), "")); - setCustomName(Text.empty()); - } - - public void setCape(Identifier cape) { - textures = new SkinTextures( - textures.texture(), - textures.textureUrl(), - cape, - textures.elytraTexture(), - textures.model(), - textures.secure()); - } - - public void setSlim(boolean slim) { - textures = new SkinTextures( - textures.texture(), - textures.textureUrl(), - textures.capeTexture(), - textures.elytraTexture(), - slim ? SkinTextures.Model.SLIM : SkinTextures.Model.WIDE, - textures.secure()); - } - - public void setSkin(Identifier skin) { - textures = new SkinTextures( - skin, - textures.textureUrl(), - textures.capeTexture(), - textures.elytraTexture(), - textures.model(), - textures.secure()); - } - - public void setSecondLayer(byte bytes) { - getDataTracker().set(PLAYER_MODEL_PARTS, bytes); - } - - @Override - public SkinTextures getSkinTextures() { - return textures; - } - - @Override - public Text getName() { - return getCustomName(); - } - - @Override - public boolean isSpectator() { - return false; - } - - @Override - public boolean isCreative() { - return false; - } - } -} 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 8b748e4284..fd4cc33dfe 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java @@ -5,19 +5,16 @@ import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip; import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockForgeRecipe; -import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockMobDropRecipe; 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.*; import net.minecraft.item.ItemStack; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; -import java.util.function.Function; import java.util.stream.Stream; public class ItemRepository { @@ -91,8 +88,8 @@ public static String getWikiLink(String neuId) { return null; } - public static List getRecipesPmd(String neuId) { - return List.of(); + public static List getRecipesAndUsages(ItemStack stack) { + return Stream.concat(getRecipes(stack), getUsages(stack)).toList(); } public static boolean filesImported() { @@ -124,7 +121,6 @@ public static Stream getRecipesStreamOld() { return Stream.of(); } - @Deprecated public static Stream getRecipesStream() {return recipes.stream(); } public static Stream getRecipes(ItemStack stack) { @@ -139,7 +135,6 @@ private static SkyblockRecipe toSkyblockRecipe(NEURecipe neuRecipe) { return switch (neuRecipe) { case NEUCraftingRecipe craftingRecipe -> new SkyblockCraftingRecipe(craftingRecipe); case NEUForgeRecipe forgeRecipe -> new SkyblockForgeRecipe(forgeRecipe); - case NEUMobDropRecipe mobDropRecipe -> new SkyblockMobDropRecipe(mobDropRecipe); case null, default -> null; }; } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java index ef5f5abe31..c60ef69aff 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java @@ -1,15 +1,19 @@ package de.hysky.skyblocker.skyblock.itemlist; import com.mojang.blaze3d.systems.RenderSystem; -import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; +import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockRecipe; import de.hysky.skyblocker.utils.ItemUtils; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.Drawable; import net.minecraft.client.gui.Element; +import net.minecraft.client.gui.ScreenPos; import net.minecraft.client.gui.screen.ButtonTextures; +import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.widget.ToggleButtonWidget; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.LoreComponent; import net.minecraft.item.ItemStack; @@ -26,6 +30,8 @@ public class SearchResultsWidget implements Drawable, Element { private static final ButtonTextures PAGE_FORWARD_TEXTURES = new ButtonTextures(Identifier.ofVanilla("recipe_book/page_forward"), Identifier.ofVanilla("recipe_book/page_forward_highlighted")); private static final ButtonTextures PAGE_BACKWARD_TEXTURES = new ButtonTextures(Identifier.ofVanilla("recipe_book/page_backward"), Identifier.ofVanilla("recipe_book/page_backward_highlighted")); + private static final Identifier SLOT_TEXTURE = Identifier.ofVanilla("container/slot"); + private static final Identifier ARROW_TEXTURE = Identifier.of(SkyblockerMod.NAMESPACE, "arrow"); private static final int COLS = 5; private static final int MAX_TEXT_WIDTH = 124; private static final String ELLIPSIS = "..."; @@ -35,9 +41,10 @@ public class SearchResultsWidget implements Drawable, Element { private final int parentY; private final List searchResults = new ArrayList<>(); - private List recipeResults = new ArrayList<>(); + private List recipeResults = new ArrayList<>(); private String searchText = null; private final List resultButtons = new ArrayList<>(); + private final List recipeSlots = new ArrayList<>(); private final ToggleButtonWidget nextPageButton; private final ToggleButtonWidget prevPageButton; private int currentPage = 0; @@ -90,20 +97,13 @@ protected void updateSearchResult(String searchText) { } private void updateButtons() { + recipeSlots.clear(); if (this.displayRecipes) { - SkyblockCraftingRecipe recipe = this.recipeResults.get(this.currentPage); + SkyblockRecipe recipe = this.recipeResults.get(this.currentPage); for (ResultButtonWidget button : resultButtons) button.clearItemStack(); - resultButtons.get(5).setItemStack(recipe.getGrid().getFirst()); - resultButtons.get(6).setItemStack(recipe.getGrid().get(1)); - resultButtons.get(7).setItemStack(recipe.getGrid().get(2)); - resultButtons.get(10).setItemStack(recipe.getGrid().get(3)); - resultButtons.get(11).setItemStack(recipe.getGrid().get(4)); - resultButtons.get(12).setItemStack(recipe.getGrid().get(5)); - resultButtons.get(15).setItemStack(recipe.getGrid().get(6)); - resultButtons.get(16).setItemStack(recipe.getGrid().get(7)); - resultButtons.get(17).setItemStack(recipe.getGrid().get(8)); - resultButtons.get(14).setItemStack(recipe.getResult()); + recipeSlots.addAll(recipe.getInputSlots(125, 75)); + recipeSlots.addAll(recipe.getOutputSlots(125, 75)); } else { for (int i = 0; i < resultButtons.size(); ++i) { int index = this.currentPage * resultButtons.size() + i; @@ -123,15 +123,21 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { RenderSystem.disableDepthTest(); if (this.displayRecipes) { //Craft text - usually a requirement for the recipe - String craftText = this.recipeResults.get(this.currentPage).getCraftText(); + SkyblockRecipe recipe = this.recipeResults.get(this.currentPage); + Text craftText = recipe.getExtraText(); if (textRenderer.getWidth(craftText) > MAX_TEXT_WIDTH) { - drawTooltip(textRenderer, context, craftText, this.parentX + 11, this.parentY + 31, mouseX, mouseY); - craftText = textRenderer.trimToWidth(craftText, MAX_TEXT_WIDTH) + ELLIPSIS; + drawTooltip(textRenderer, context, craftText, this.parentX + 11, this.parentY + 31 + 100 - 9, mouseX, mouseY); + craftText = Text.of(textRenderer.trimToWidth(craftText, MAX_TEXT_WIDTH) + ELLIPSIS); } - context.drawTextWithShadow(textRenderer, craftText, this.parentX + 11, this.parentY + 31, 0xffffffff); + context.drawTextWithShadow(textRenderer, craftText, this.parentX + 11, this.parentY + 31 + 100 - 9, 0xffffffff); + + // Recipe category + Text category = Text.translatable("emi.category.skyblocker." + recipe.getCategoryIdentifier().getPath()); + context.drawTextWithShadow(textRenderer, category, this.parentX + 11, this.parentY + 31, -1); //Item name - Text resultText = this.recipeResults.get(this.currentPage).getResult().getName(); + // TODO fix if we add recipes with multiple outputs + Text resultText = recipe.getOutputs().getFirst().getName(); if (textRenderer.getWidth(resultText) > MAX_TEXT_WIDTH) { drawTooltip(textRenderer, context, resultText, this.parentX + 11, this.parentY + 43, mouseX, mouseY); StringVisitable trimmed = StringVisitable.concat(textRenderer.trimToWidth(resultText, MAX_TEXT_WIDTH), StringVisitable.plain(ELLIPSIS)); @@ -142,8 +148,21 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { context.drawTextWithShadow(textRenderer, resultText, this.parentX + 11, this.parentY + 43, 0xffffffff); } + MatrixStack matrices = context.getMatrices(); + matrices.push(); + matrices.translate(parentX + 11, parentY + 31 + 25, 0); + for (SkyblockRecipe.RecipeSlot recipeSlot : recipeSlots) { + if (recipeSlot.showBackground()) context.drawGuiTexture(SLOT_TEXTURE, recipeSlot.x(), recipeSlot.y(), 18, 18); + context.drawItem(recipeSlot.stack(), recipeSlot.x() + 1, recipeSlot.y() + 1); + } + + ScreenPos arrowLocation = recipe.getArrowLocation(125, 75); + if (arrowLocation != null) context.drawGuiTexture(ARROW_TEXTURE, arrowLocation.x(), arrowLocation.y(), 24, 16); + + matrices.pop(); + //Arrow pointing to result item from the recipe - context.drawTextWithShadow(textRenderer, "▶", this.parentX + 96, this.parentY + 90, 0xaaffffff); + //context.drawTextWithShadow(textRenderer, "▶", this.parentX + 96, this.parentY + 90, 0xaaffffff); } for (ResultButtonWidget button : resultButtons) button.render(context, mouseX, mouseY, delta); @@ -180,6 +199,16 @@ public void drawTooltip(DrawContext context, int mouseX, int mouseY) { for (ResultButtonWidget button : resultButtons) if (button.isMouseOver(mouseX, mouseY)) button.renderTooltip(context, mouseX, mouseY); + for (SkyblockRecipe.RecipeSlot recipeSlot : recipeSlots) { + int shiftedMouseX = mouseX - parentX - 11; + int shiftedMouseY = mouseY - parentY - 31 - 25; + if (isMouseOverSlot(recipeSlot, shiftedMouseX, shiftedMouseY)) { + MinecraftClient client = MinecraftClient.getInstance(); + if (client.currentScreen == null) continue; + List tooltip = Screen.getTooltipFromItem(client, recipeSlot.stack()); + client.currentScreen.setTooltip(tooltip.stream().map(Text::asOrderedText).toList()); + } + } RenderSystem.enableDepthTest(); } @@ -190,16 +219,18 @@ public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { if (internalName.isEmpty()) { continue; } - List recipes = ItemRepository.getRecipesPmd(internalName); - if (!recipes.isEmpty()) { - this.recipeResults = recipes; - this.currentPage = 0; - this.pageCount = recipes.size(); - this.displayRecipes = true; - this.updateButtons(); - } + fetchRecipesAndUpdate(button.itemStack); return true; } + for (SkyblockRecipe.RecipeSlot recipeSlot : recipeSlots) { + int shiftedMouseX = (int) (mouseX - parentX - 11); + int shiftedMouseY = (int) (mouseY - parentY - 31 - 25); + if (isMouseOverSlot(recipeSlot, shiftedMouseX, shiftedMouseY)) { + + fetchRecipesAndUpdate(recipeSlot.stack()); + return true; + } + } if (this.prevPageButton.mouseClicked(mouseX, mouseY, mouseButton)) { --this.currentPage; this.updateButtons(); @@ -213,6 +244,21 @@ public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { return false; } + private static boolean isMouseOverSlot(SkyblockRecipe.RecipeSlot recipeSlot, int mouseX, int mouseY) { + return recipeSlot.x() <= mouseX && mouseX < recipeSlot.x() + 18 && recipeSlot.y() <= mouseY && mouseY < recipeSlot.y() + 18; + } + + private void fetchRecipesAndUpdate(ItemStack recipeSlot) { + List recipes = ItemRepository.getRecipesAndUsages(recipeSlot); + if (!recipes.isEmpty()) { + this.recipeResults = recipes; + this.currentPage = 0; + this.pageCount = recipes.size(); + this.displayRecipes = true; + this.updateButtons(); + } + } + private boolean focused = false; @Override diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SkyblockCraftingRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SkyblockCraftingRecipe.java deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockCraftingRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockCraftingRecipe.java index be6084e00a..444cc40f09 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockCraftingRecipe.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockCraftingRecipe.java @@ -1,6 +1,7 @@ package de.hysky.skyblocker.skyblock.itemlist.recipes; import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.utils.ItemUtils; import io.github.moulberry.repo.data.NEUCraftingRecipe; import io.github.moulberry.repo.data.NEUIngredient; import net.minecraft.client.gui.ScreenPos; @@ -28,12 +29,6 @@ public SkyblockCraftingRecipe(NEUCraftingRecipe neuCraftingRecipe) { result = SkyblockRecipe.getItemStack(neuCraftingRecipe.getOutput()); } - public static SkyblockCraftingRecipe fromNEURecipe(NEUCraftingRecipe neuCraftingRecipe) { - return new SkyblockCraftingRecipe(neuCraftingRecipe); - } - - - public List getGrid() { return grid; } @@ -42,13 +37,9 @@ public ItemStack getResult() { return result; } - public String getCraftText() { - return "remove this"; - } - @Override public List getInputSlots(int width, int height) { - ScreenPos start = new ScreenPos(width / 2 - 58, height / 2 - (getExtraText().getString().isEmpty() ? 26: 31)); + ScreenPos start = new ScreenPos(width / 2 - 58, height / 2 - (getExtraText().getString().isEmpty() ? 27: 32)); List toReturn = new ArrayList<>(9); for (int i = 0; i < grid.size(); i++) { int x = i % 3; @@ -84,6 +75,12 @@ public Identifier getCategoryIdentifier() { return SkyblockCraftingRecipe.IDENTIFIER; } + @Override + public Identifier getRecipeIdentifier() { + return Identifier.of("skyblock", ItemUtils.getItemId(getResult()).toLowerCase().replace(';', '_') + "_" + getResult().getCount()); + + } + @Override public @Nullable ScreenPos getArrowLocation(int width, int height) { ScreenPos start = new ScreenPos(width / 2 - 58, height / 2 - (getExtraText().getString().isEmpty() ? 26: 31)); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java index aec21a76ed..728eca62ff 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java @@ -1,15 +1,17 @@ package de.hysky.skyblocker.skyblock.itemlist.recipes; import de.hysky.skyblocker.SkyblockerMod; +import de.hysky.skyblocker.utils.ItemUtils; import io.github.moulberry.repo.data.NEUForgeRecipe; import net.minecraft.client.gui.ScreenPos; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; import net.minecraft.util.Identifier; -import net.minecraft.util.math.MathHelper; import org.jetbrains.annotations.Nullable; +import org.joml.Vector2i; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class SkyblockForgeRecipe implements SkyblockRecipe { @@ -30,23 +32,36 @@ public List getInputSlots(int width, int height) { List out = new ArrayList<>(); int centerX = width / 2; int centerY = height / 2; - float radius = getRadius(); + + Vector2i radius = getRadius(); + int startX = (int) (centerX / 2.f - (radius.x / 2.f) * 18); + int startY = (int) (centerY - (radius.y / 2.f) * 18); + for (int i = 0; i < inputs.size(); i++) { - float angle = 2 * MathHelper.PI * (float) i / (float) inputs.size(); - int x = (int) (MathHelper.cos(angle) * radius); - int y = (int) (MathHelper.sin(angle) * radius); - out.add(new RecipeSlot(Math.max(centerX / 2, (int) radius + 14) - 9 + x, centerY - 9 + y, inputs.get(i))); + int x = startX + (i % radius.x) * 18; + int y = startY + (i / radius.x) * 18; + out.add(new RecipeSlot(x, y, inputs.get(i))); } return out; } - private float getRadius() { - return Math.max(26 * inputs.size() / (2 * MathHelper.PI), 20); + private Vector2i getRadius() { + int gridWidth; + int gridHeight; + + int sqrt = gridHeight = gridWidth = (int) Math.sqrt(inputs.size()); + float percentage = (inputs.size() - sqrt * sqrt) / (float) ((sqrt+1)*(sqrt+1) - sqrt*sqrt); + + if (percentage > 0.005f) { + gridWidth++; + if (percentage > 0.6) gridHeight++; + } + return new Vector2i(gridWidth, gridHeight); } @Override public List getOutputSlots(int width, int height) { - return List.of(new RecipeSlot(width / 2 + 37, height / 2 - 9, output)); + return Collections.singletonList(new RecipeSlot(Math.max(3 * width / 4, width / 2 + 30), height / 2 - 9, output)); } @Override @@ -56,7 +71,7 @@ public List getInputs() { @Override public List getOutputs() { - return List.of(output); + return Collections.singletonList(output); } @Override @@ -69,9 +84,12 @@ public Identifier getCategoryIdentifier() { return IDENTIFIER; } + public Identifier getRecipeIdentifier() { + return Identifier.of("skyblock", ItemUtils.getItemId(output).toLowerCase().replace(';', '_') + "_" + output.getCount()); + } + @Override public @Nullable ScreenPos getArrowLocation(int width, int height) { - float v = (3 * width) / 4.f; - return new ScreenPos((int) ((v + getRadius() + 9 + 37 - 24) / 2), height / 2 - 9); + return new ScreenPos(width / 2, height / 2 - 9); } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockMobDropRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockMobDropRecipe.java deleted file mode 100644 index 5ea2e0aeac..0000000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockMobDropRecipe.java +++ /dev/null @@ -1,123 +0,0 @@ -package de.hysky.skyblocker.skyblock.itemlist.recipes; - -import com.mojang.blaze3d.systems.RenderSystem; -import de.hysky.skyblocker.SkyblockerMod; -import de.hysky.skyblocker.skyblock.itemlist.EntityCreator; -import de.hysky.skyblocker.utils.ItemUtils; -import io.github.moulberry.repo.data.NEUMobDropRecipe; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.ingame.InventoryScreen; -import net.minecraft.component.DataComponentTypes; -import net.minecraft.component.type.LoreComponent; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.Nullable; -import org.joml.Quaternionf; -import org.joml.Vector3f; - -import java.util.ArrayList; -import java.util.List; - -public class SkyblockMobDropRecipe implements SkyblockRecipe { - - public static final Identifier IDENTIFIER = Identifier.of(SkyblockerMod.NAMESPACE, "skyblock_drops"); - - private final List drops = new ArrayList<>(); - private final @Nullable LivingEntity entity; - - public SkyblockMobDropRecipe(NEUMobDropRecipe mobDropRecipe) { - for (NEUMobDropRecipe.Drop drop : mobDropRecipe.getDrops()) { - ItemStack itemStack = SkyblockRecipe.getItemStack(drop.getDropItem()); - ArrayList texts = new ArrayList<>(ItemUtils.getLore(itemStack)); - if (drop.getChance() != null) texts.add(Text.literal(drop.getChance())); - itemStack.set(DataComponentTypes.LORE, new LoreComponent(texts)); - drops.add(itemStack); - } - if (mobDropRecipe.getRender().startsWith("@")) entity = EntityCreator.createEntity(mobDropRecipe.getRender().substring(1)); - else { - EntityType type = EntityCreator.ID_TO_TYPE.get(mobDropRecipe.getRender()); - if (type != null) entity = (LivingEntity) type.create(MinecraftClient.getInstance().world); - else entity = null; - } - } - - @Override - public List getInputSlots(int width, int height) { - return List.of(); - } - - @Override - public List getOutputSlots(int width, int height) { - List out = new ArrayList<>(); - int maxPerRow = (width / 2 - 4) / 18; - for (int i = 0; i < drops.size(); i++) { - int x = width / 2 + (i % maxPerRow) * 18; - int y = 4 + (i / maxPerRow) * 18; - out.add(new RecipeSlot(x, y, drops.get(i), false)); - } - return out; - } - - @Override - public List getInputs() { - return List.of(); - } - - @Override - public List getOutputs() { - return drops; - } - - private void drawEntityNoScissors(DrawContext context, int x1, int y1, int x2, int y2, int size, float f, float mouseX, float mouseY, LivingEntity entity) { - float g = (float)(x1 + x2) / 2.0F; - float h = (float)(y1 + y2) / 2.0F; - float i = (float)Math.atan((g - mouseX) / 40.0F); - float j = (float)Math.atan((h - mouseY) / 40.0F); - Quaternionf quaternionf = new Quaternionf().rotateZ((float) Math.PI); - Quaternionf quaternionf2 = new Quaternionf().rotateX(j * 20.0F * (float) (Math.PI / 180.0)); - quaternionf.mul(quaternionf2); - float k = entity.bodyYaw; - float l = entity.getYaw(); - float m = entity.getPitch(); - float n = entity.prevHeadYaw; - float o = entity.headYaw; - entity.bodyYaw = 180.0F + i * 20.0F; - entity.setYaw(180.0F + i * 40.0F); - entity.setPitch(-j * 20.0F); - entity.headYaw = entity.getYaw(); - entity.prevHeadYaw = entity.getYaw(); - float p = entity.getScale(); - Vector3f vector3f = new Vector3f(0.0F, entity.getHeight() / 2.0F + f * p, 0.0F); - float q = (float)size / p; - InventoryScreen.drawEntity(context, g, h, q, vector3f, quaternionf, quaternionf2, entity); - entity.bodyYaw = k; - entity.setYaw(l); - entity.setPitch(m); - entity.prevHeadYaw = n; - entity.headYaw = o; - } - - @Override - public void render(DrawContext context, int width, int height, double mouseX, double mouseY) { - if (entity == null) return; - - drawEntityNoScissors( - context, 4, 4, height - 4, width / 2 - 4, - 24, 0.0625F, (int) mouseX, (int) mouseY, entity); - } - - @Override - public Text getExtraText() { - return Text.empty(); - } - - @Override - public Identifier getCategoryIdentifier() { - return IDENTIFIER; - } -} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java index a41ecbb54a..0ba870c625 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockRecipe.java @@ -1,24 +1,28 @@ package de.hysky.skyblocker.skyblock.itemlist.recipes; -import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import io.github.moulberry.repo.data.NEUIngredient; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.ScreenPos; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.LoreComponent; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.screen.slot.Slot; import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.text.NumberFormat; import java.util.List; +import java.util.Locale; public interface SkyblockRecipe { - Logger LOGGER = LoggerFactory.getLogger(SkyblockCraftingRecipe.class); + Logger LOGGER = LoggerFactory.getLogger(SkyblockRecipe.class); + NumberFormat NUMBER_FORMAT = NumberFormat.getInstance(Locale.US); @@ -27,6 +31,13 @@ static ItemStack getItemStack(NEUIngredient input) { ItemStack stack = ItemRepository.getItemStack(input.getItemId()); if (stack != null) { return stack.copyWithCount((int) input.getAmount()); + } else if (input.getItemId().equals("SKYBLOCK_COIN")) { + ItemStack itemStack = new ItemStack(Items.GOLD_NUGGET); + itemStack.set(DataComponentTypes.ITEM_NAME, Text.literal("Skyblock Coins").formatted(Formatting.GOLD)); + itemStack.set(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, true); + String format = NUMBER_FORMAT.format(input.getAmount()); + itemStack.set(DataComponentTypes.LORE, new LoreComponent(List.of(Text.literal(format).formatted(Formatting.GOLD).append(Text.literal(" coins."))))); + return itemStack; } else { LOGGER.warn("[Skyblocker Recipe] Unable to find item {}", input.getItemId()); } @@ -62,7 +73,7 @@ static ItemStack getItemStack(NEUIngredient input) { * @param mouseX mouse x * @param mouseY mouse y */ - default void render(DrawContext context, int width, int height, double mouseX, double mouseY) {}; + default void render(DrawContext context, int width, int height, double mouseX, double mouseY) {} /** * Extra text like collection requirements @@ -72,6 +83,8 @@ static ItemStack getItemStack(NEUIngredient input) { Identifier getCategoryIdentifier(); + Identifier getRecipeIdentifier(); + record RecipeSlot(int x, int y, ItemStack stack, boolean showBackground) { public RecipeSlot(int x, int y, ItemStack stack) { this(x, y, stack, true); diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index cbb984e029..9513cfaf21 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -1126,5 +1126,6 @@ "skyblocker.profileviewer.inventory.inactive.description.backpack": "The selected backpack", "skyblocker.profileviewer.inventory.inactive.description.general": "does not contain this slot", - "emi.category.skyblocker.skyblock": "Crafting (Skyblock)" + "emi.category.skyblocker.skyblock_crafting": "Crafting (Skyblock)", + "emi.category.skyblocker.skyblock_forge": "Dwarven Forge (Skyblock)" } diff --git a/src/main/resources/assets/skyblocker/lang/it_it.json b/src/main/resources/assets/skyblocker/lang/it_it.json index 76ad6635a9..6019e98f63 100644 --- a/src/main/resources/assets/skyblocker/lang/it_it.json +++ b/src/main/resources/assets/skyblocker/lang/it_it.json @@ -73,7 +73,7 @@ "skyblocker.end.hud.protectorLocations.left": "Sinistra", "skyblocker.end.hud.protectorLocations.front": "Davanti", "skyblocker.end.hud.protectorLocations.center": "Centro", - "emi.category.skyblocker.skyblock": "Skyblock", + "emi.category.skyblocker.skyblock_crafting": "Skyblock", "text.skyblocker.quit_config_sure": "Sei sicuro di voler uscire dalle impostazioni? Le modifiche non verranno salvate!", "skyblocker.config.general.enableTips": "Attiva Suggerimenti", "skyblocker.config.helpers.experiments.enableChronomatronSolver": "Attiva Risolutore per Chronomatron", diff --git a/src/main/resources/assets/skyblocker/lang/pt_br.json b/src/main/resources/assets/skyblocker/lang/pt_br.json index 248775959d..9a49e61f2b 100644 --- a/src/main/resources/assets/skyblocker/lang/pt_br.json +++ b/src/main/resources/assets/skyblocker/lang/pt_br.json @@ -83,7 +83,7 @@ "skyblocker.shortcuts.config": "Configurações de atalhos", "skyblocker.shortcuts.new": "Novo Atalho", "skyblocker.shortcuts.deleteQuestion": "Você tem certeza que quer remover esse atalho?", - "emi.category.skyblocker.skyblock": "Skyblock", + "emi.category.skyblocker.skyblock_crafting": "Skyblock", "skyblocker.config.uiAndVisuals.backpackPreviewWithoutShift": "Ver preview da mochila sem segurar Shift", "skyblocker.shortcuts.commandSuggestionTooltip": "Devido às limitações do Minecraft, sugestões de comando vai apenas funcionar após entrando em um novo mundo.", "skyblocker.shortcuts.deleteWarning": "Atalho '%s' vai ser perdido para sempre! (Por um longo tempo!)", diff --git a/src/main/resources/assets/skyblocker/lang/ru_ru.json b/src/main/resources/assets/skyblocker/lang/ru_ru.json index 77bb3db083..4ddb9d417c 100644 --- a/src/main/resources/assets/skyblocker/lang/ru_ru.json +++ b/src/main/resources/assets/skyblocker/lang/ru_ru.json @@ -592,7 +592,7 @@ "skyblocker.partyFinder.noParties": "Ничего не найдено. Печалька :(", "skyblocker.partyFinder.loadingError": "Если вы смотрите на это более 5 секунд, то что-то, наверное, пошло не так...", "skyblocker.waypoints.ordered.import.coleWeight.groupAlreadyExists": "§cУже существует упорядоченная группа меток под именем\"%s\", пожалуйста, выберите другое имя для импорта ваших меток.", - "emi.category.skyblocker.skyblock": "Скайблок", + "emi.category.skyblocker.skyblock_crafting": "Скайблок", "skyblocker.waypoints.ordered.import.skyblocker.fail": "§cНе удалось импортировать метки из формата Skyblocker Ordered Waypoints. Убедитесь, что данные меток скопированы в буфер обмена!", "skyblocker.crimson.kuudra.lowArrowPoison": "Мало Отравленных стрел!", "skyblocker.partyFinder.deList": "Нажми чтобы выйти из поиска", diff --git a/src/main/resources/assets/skyblocker/lang/zh_cn.json b/src/main/resources/assets/skyblocker/lang/zh_cn.json index 3b89f23727..8444fb5747 100644 --- a/src/main/resources/assets/skyblocker/lang/zh_cn.json +++ b/src/main/resources/assets/skyblocker/lang/zh_cn.json @@ -503,7 +503,7 @@ "skyblocker.config.helpers.enableNewYearCakesHelper.@Tooltip": "以绿色高亮显示缺少的新年蛋糕、红色高亮显示已有的蛋糕。\n\n需要至少打开一次蛋糕背包才能生效。", "skyblocker.config.slayer.vampireSlayer.maniaUpdateFrequency.@Tooltip": "值越低,更新越频繁,可能会导致卡顿。", "skyblocker.config.general.itemInfoDisplay.attributeShardInfo": "显示Attribute Ahard信息", - "emi.category.skyblocker.skyblock": "Skyblock", + "emi.category.skyblocker.skyblock_crafting": "Skyblock", "skyblocker.config.uiAndVisuals.fancyCraftingTable": "炫酷的工作台UI", "skyblocker.config.general.itemTooltip.enableAccessoriesHelper.@Tooltip[0]": "当将鼠标悬停在某个饰品上时,你将得知是否已经拥有它,以及它与当前的饰品相比更差还是更好。状态列表:", "skyblocker.config.general.itemTooltip.enableAccessoriesHelper": "启用饰品助手", diff --git a/src/main/resources/assets/skyblocker/lang/zh_tw.json b/src/main/resources/assets/skyblocker/lang/zh_tw.json index 71f28fb8d8..9973af682a 100644 --- a/src/main/resources/assets/skyblocker/lang/zh_tw.json +++ b/src/main/resources/assets/skyblocker/lang/zh_tw.json @@ -504,7 +504,7 @@ "skyblocker.config.general.itemTooltip.enableAccessoriesHelper.@Tooltip[1]": "你已擁有該系列中最高級的飾品。", "skyblocker.config.general.itemTooltip.enableAccessoriesHelper.@Tooltip[3]": "該飾品可以升級。 同時顯示目前擁有該系列中哪個等級的飾品。", "skyblocker.config.general.itemTooltip.enableAccessoriesHelper.@Tooltip[5]": "你沒有該系列的飾品。", - "emi.category.skyblocker.skyblock": "Skyblock", + "emi.category.skyblocker.skyblock_crafting": "Skyblock", "skyblocker.config.uiAndVisuals.titleContainer": "標題容器", "skyblocker.config.general.itemTooltip.enableAccessoriesHelper.@Tooltip[0]": "當將滑鼠懸停在某個飾品上時,你將得知是否已經擁有它,以及它與當前的飾品相比更差還是更好。 狀態列表:", "skyblocker.config.general.itemTooltip.enableAccessoriesHelper.@Tooltip[2]": "該飾品是現有同系列飾品升級後的版本。 同時展示了該飾品在其係列中的等級。", diff --git a/src/main/resources/assets/skyblocker/textures/gui/emi_icons.png b/src/main/resources/assets/skyblocker/textures/gui/emi_icons.png new file mode 100644 index 0000000000000000000000000000000000000000..7d5761ec665dfb1ebb2ef51ee6b924ccf120ee8d GIT binary patch literal 654 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G!U;i$lZxy-8q?;Kn_c~qpu?a z!^VE@KZ&eBK4*bPWHAE+-(e7DJf6QIg@J)d+0(@_q$2L^&AUO54S3it9QwWgbKbt5 zBRg^va;G`GoKu|aIqkN#<=@Jmn|I!+xEWHBx>WoJ>#>D)QXis?|E`o@nfoB{OTs#y z7uD&L+?SSTRsX7ODBfGkdcytZ&4)78!s)*EKJH)hg-QLCLD-L%7TIr(a$dE&%RlGw z*ZO%!EUo!Ioe5a~jrsXbsed;cW%PSL`owcQ{I{@ICX9ncM&M$l`Tx zXU|?N_2F+^_TQk&Rok@~`Cq(aIuUGX*A@Om=!E5TMw^BEM5^X~oN0W3^O&N~9jp81 zr*dtxRr(C;&S%*d%-g=6LGoCQPk!h<$&iYm#|7$rUhh9ie6B4He)-N!e(e{g=evIi zZjk#|{{QlNo~-ZkC*!s<_A4~s%)V`ICM$ncsc`kBEmqrV_<-R!g1`gI7`=MNTbhTC T>V94r4)VCCtDnm{r-UW|Zlk(r literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/skyblocker/textures/gui/sprites/arrow.png b/src/main/resources/assets/skyblocker/textures/gui/sprites/arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..02731ed0534a4a4476ee06b540023293866929ba GIT binary patch literal 219 zcmeAS@N?(olHy`uVBq!ia0vp^5Nn{1`c>;VwT>t<7|Mcn81q&7c18bg=d#Wz Gp$P!fFiBzn literal 0 HcmV?d00001 From 2f011fdf2f04b559936955f2cf33de9d20fd9155 Mon Sep 17 00:00:00 2001 From: viciscat <51047087+viciscat@users.noreply.github.com> Date: Wed, 21 Aug 2024 12:23:57 +0200 Subject: [PATCH 3/6] remove emi runtime --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index d62bb954d0..fd86588e0a 100644 --- a/build.gradle +++ b/build.gradle @@ -165,7 +165,7 @@ dependencies { // EMI modCompileOnly "dev.emi:emi-fabric:${project.emi_version}:api" - modLocalRuntime "dev.emi:emi-fabric:${project.emi_version}" + //modLocalRuntime "dev.emi:emi-fabric:${project.emi_version}" // JEI (Using modrinth repo since official release is in mojmap and doesn't work) modCompileOnly "maven.modrinth:jei:${project.jei_version}-fabric" From d552b6a03585088c5bb0da184af053d2fb3dede0 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sun, 8 Sep 2024 14:28:00 -0400 Subject: [PATCH 4/6] Refactor recipe --- .../emi/SkyblockerEMIPlugin.java | 3 +- .../rei/SkyblockRecipeCategory.java | 31 +++++++++---------- .../rei/SkyblockRecipeDisplay.java | 3 ++ .../skyblock/itemlist/ItemRepository.java | 13 +------- .../itemlist/SearchResultsWidget.java | 6 ++-- 5 files changed, 22 insertions(+), 34 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java index bb1e7b09e9..a50273b256 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java @@ -4,7 +4,6 @@ import de.hysky.skyblocker.skyblock.itemlist.ItemRepository; import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockCraftingRecipe; import de.hysky.skyblocker.skyblock.itemlist.recipes.SkyblockForgeRecipe; -import de.hysky.skyblocker.utils.ItemUtils; import dev.emi.emi.api.EmiPlugin; import dev.emi.emi.api.EmiRegistry; import dev.emi.emi.api.recipe.EmiRecipeCategory; @@ -34,7 +33,7 @@ public class SkyblockerEMIPlugin implements EmiPlugin { public void register(EmiRegistry registry) { ItemRepository.getItemsStream().map(EmiStack::of).forEach(emiStack -> { registry.addEmiStack(emiStack); - registry.setDefaultComparison(emiStack, Comparison.compareData(emiStack1 -> ItemUtils.getItemId(emiStack1.getItemStack()))); + registry.setDefaultComparison(emiStack, Comparison.compareData(emiStack1 -> emiStack1.getItemStack().getSkyblockId())); }); registry.addCategory(SKYBLOCK_CRAFTING); registry.addCategory(SKYBLOCK_FORGE); diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java index efd6f4ee7b..98146d2395 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeCategory.java @@ -9,8 +9,6 @@ import me.shedaniel.rei.api.client.registry.display.DisplayCategory; import me.shedaniel.rei.api.common.category.CategoryIdentifier; import me.shedaniel.rei.api.common.util.EntryStacks; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.Element; import net.minecraft.client.gui.ScreenPos; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; @@ -20,6 +18,9 @@ import java.util.ArrayList; import java.util.List; +/** + * Skyblock recipe category class for REI + */ public class SkyblockRecipeCategory implements DisplayCategory { private final Identifier identifier; @@ -54,6 +55,12 @@ public Renderer getIcon() { return EntryStacks.of(icon); } + /** + * Draws display for SkyblockCraftingDisplay + * + * @param display the display + * @param bounds the bounds of the display, configurable with overriding the width, height methods. + */ @Override public List setupDisplay(SkyblockRecipeDisplay display, Rectangle bounds) { List out = new ArrayList<>(); @@ -71,20 +78,12 @@ public List setupDisplay(SkyblockRecipeDisplay display, Rectangle bounds .backgroundEnabled(outputSlot.showBackground()) .entry(EntryStacks.of(outputSlot.stack()))); } - out.add(Widgets.withBounds(new Widget() { - @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { - MatrixStack matrices = context.getMatrices(); - matrices.push(); - matrices.translate(bounds.getX(), bounds.getY(), 0.f); - recipe.render(context, bounds.getWidth(), bounds.getHeight(), mouseX - bounds.getX(), mouseY - bounds.getY()); - matrices.pop(); - } - - @Override - public List children() { - return List.of(); - } + out.add(Widgets.wrapRenderer((Rectangle) null, (context, bounds1, mouseX, mouseY, delta) -> { + MatrixStack matrices = context.getMatrices(); + matrices.push(); + matrices.translate(bounds.getX(), bounds.getY(), 0.f); + recipe.render(context, bounds.getWidth(), bounds.getHeight(), mouseX - bounds.getX(), mouseY - bounds.getY()); + matrices.pop(); })); ScreenPos arrowLocation = recipe.getArrowLocation(bounds.getWidth(), bounds.getHeight()); if (arrowLocation != null) diff --git a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java index bf2eaa17de..c5316ed966 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/rei/SkyblockRecipeDisplay.java @@ -9,6 +9,9 @@ import java.util.List; +/** + * Skyblock Crafting Recipe display class for REI + */ public class SkyblockRecipeDisplay implements Display { private final Identifier category; 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 fd4cc33dfe..cc9a819fbf 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java @@ -61,13 +61,7 @@ private static void loadItem(NEUItem item) { } private static void loadRecipes(NEUItem item) { - for (NEURecipe recipe : item.getRecipes()) { - switch (recipe) { - case NEUCraftingRecipe craftingRecipe -> recipes.add(new SkyblockCraftingRecipe(craftingRecipe)); - case NEUForgeRecipe forgeRecipe -> recipes.add(new SkyblockForgeRecipe(forgeRecipe)); - case null, default -> {} - } - } + item.getRecipes().stream().map(ItemRepository::toSkyblockRecipe).filter(Objects::nonNull).forEach(recipes::add); } public static String getWikiLink(String neuId) { @@ -116,11 +110,6 @@ public static ItemStack getItemStack(String neuId) { return itemsMap.get(neuId); } - @Deprecated - public static Stream getRecipesStreamOld() { - return Stream.of(); - } - public static Stream getRecipesStream() {return recipes.stream(); } public static Stream getRecipes(ItemStack stack) { diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java index c60ef69aff..87b62e2187 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java @@ -160,9 +160,6 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { if (arrowLocation != null) context.drawGuiTexture(ARROW_TEXTURE, arrowLocation.x(), arrowLocation.y(), 24, 16); matrices.pop(); - - //Arrow pointing to result item from the recipe - //context.drawTextWithShadow(textRenderer, "▶", this.parentX + 96, this.parentY + 90, 0xaaffffff); } for (ResultButtonWidget button : resultButtons) button.render(context, mouseX, mouseY, delta); @@ -213,7 +210,7 @@ public void drawTooltip(DrawContext context, int mouseX, int mouseY) { } public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { - for (ResultButtonWidget button : resultButtons) + for (ResultButtonWidget button : resultButtons) { if (button.mouseClicked(mouseX, mouseY, mouseButton)) { String internalName = ItemUtils.getItemId(button.itemStack); if (internalName.isEmpty()) { @@ -222,6 +219,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { fetchRecipesAndUpdate(button.itemStack); return true; } + } for (SkyblockRecipe.RecipeSlot recipeSlot : recipeSlots) { int shiftedMouseX = (int) (mouseX - parentX - 11); int shiftedMouseY = (int) (mouseY - parentY - 31 - 25); From 92cb9ef13b8580145b35b3a12fe415c179eee828 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sun, 8 Sep 2024 14:49:05 -0400 Subject: [PATCH 5/6] Render forge recipe duration --- .../itemlist/recipes/SkyblockForgeRecipe.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java index 728eca62ff..cc87308f87 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/recipes/SkyblockForgeRecipe.java @@ -3,6 +3,8 @@ import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.utils.ItemUtils; import io.github.moulberry.repo.data.NEUForgeRecipe; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.ScreenPos; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; @@ -20,10 +22,12 @@ public class SkyblockForgeRecipe implements SkyblockRecipe { private final List inputs; private final ItemStack output; + private final int duration; public SkyblockForgeRecipe(NEUForgeRecipe forgeRecipe) { inputs = forgeRecipe.getInputs().stream().map(SkyblockRecipe::getItemStack).toList(); output = SkyblockRecipe.getItemStack(forgeRecipe.getOutputStack()); + duration = forgeRecipe.getDuration(); } @@ -92,4 +96,12 @@ public Identifier getRecipeIdentifier() { public @Nullable ScreenPos getArrowLocation(int width, int height) { return new ScreenPos(width / 2, height / 2 - 9); } + + @Override + public void render(DrawContext context, int width, int height, double mouseX, double mouseY) { + // Render the duration of the recipe in hours by dividing by 3600 + ScreenPos arrowLocation = getArrowLocation(width, height); + if (arrowLocation != null) + context.drawCenteredTextWithShadow(MinecraftClient.getInstance().textRenderer, String.format("%d h", duration / 3600), arrowLocation.x() + 12, arrowLocation.y() - 10, 0xFFFFFF); + } } From 2349885122c801957247b85181fb5a3dc6918b93 Mon Sep 17 00:00:00 2001 From: viciscat <51047087+viciscat@users.noreply.github.com> Date: Tue, 17 Sep 2024 18:07:46 +0200 Subject: [PATCH 6/6] Multiple things Remove unused accessor Remove REI runtime Make EMI and recipe book call render method of a recipe --- build.gradle | 4 ++-- .../compatibility/emi/SkyblockEmiRecipe.java | 1 + .../skyblocker/mixins/CreeperEntityAccessor.java | 13 ------------- .../skyblock/itemlist/SearchResultsWidget.java | 2 ++ src/main/resources/skyblocker.mixins.json | 5 +---- 5 files changed, 6 insertions(+), 19 deletions(-) delete mode 100644 src/main/java/de/hysky/skyblocker/mixins/CreeperEntityAccessor.java diff --git a/build.gradle b/build.gradle index fd86588e0a..a3ee50abdd 100644 --- a/build.gradle +++ b/build.gradle @@ -161,7 +161,7 @@ dependencies { // REI modCompileOnly "me.shedaniel:RoughlyEnoughItems-api-fabric:${project.rei_version}" modCompileOnly "me.shedaniel:RoughlyEnoughItems-api:${project.rei_version}" - modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}" + //modRuntimeOnly "me.shedaniel:RoughlyEnoughItems-fabric:${project.rei_version}" // EMI modCompileOnly "dev.emi:emi-fabric:${project.emi_version}:api" @@ -287,4 +287,4 @@ publishing { // The repositories here will be used for publishing your artifact, not for // retrieving dependencies. } -} \ No newline at end of file +} diff --git a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java index b9881bc681..281867f153 100644 --- a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java +++ b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java @@ -65,5 +65,6 @@ public void addWidgets(WidgetHolder widgets) { for (SkyblockRecipe.RecipeSlot outputSlot : recipe.getOutputSlots(getDisplayWidth(), getDisplayHeight())) { widgets.addSlot(EmiStack.of(outputSlot.stack()), outputSlot.x(), outputSlot.y()).recipeContext(this); } + widgets.addDrawable(0, 0, getDisplayWidth(), getDisplayHeight(), (draw, mouseX, mouseY, delta) -> recipe.render(draw, getDisplayWidth(), getDisplayHeight(), mouseX, mouseY)); } } diff --git a/src/main/java/de/hysky/skyblocker/mixins/CreeperEntityAccessor.java b/src/main/java/de/hysky/skyblocker/mixins/CreeperEntityAccessor.java deleted file mode 100644 index 99566409dd..0000000000 --- a/src/main/java/de/hysky/skyblocker/mixins/CreeperEntityAccessor.java +++ /dev/null @@ -1,13 +0,0 @@ -package de.hysky.skyblocker.mixins; - -import net.minecraft.entity.data.TrackedData; -import net.minecraft.entity.mob.CreeperEntity; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(CreeperEntity.class) -public interface CreeperEntityAccessor { - - @Accessor("CHARGED") - static TrackedData getCharged() { throw new RuntimeException();} -} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java index 87b62e2187..84edcbdb2a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/SearchResultsWidget.java @@ -159,6 +159,8 @@ public void render(DrawContext context, int mouseX, int mouseY, float delta) { ScreenPos arrowLocation = recipe.getArrowLocation(125, 75); if (arrowLocation != null) context.drawGuiTexture(ARROW_TEXTURE, arrowLocation.x(), arrowLocation.y(), 24, 16); + recipe.render(context, 125, 75, mouseX, mouseY); + matrices.pop(); } for (ResultButtonWidget button : resultButtons) diff --git a/src/main/resources/skyblocker.mixins.json b/src/main/resources/skyblocker.mixins.json index 603abfe3fa..57eea120e3 100644 --- a/src/main/resources/skyblocker.mixins.json +++ b/src/main/resources/skyblocker.mixins.json @@ -61,8 +61,5 @@ ], "injectors": { "defaultRequire": 1 - }, - "mixins": [ - "CreeperEntityAccessor" - ] + } }