diff --git a/src/main/java/gregtech/api/util/JEIUtil.java b/src/main/java/gregtech/api/util/JEIUtil.java new file mode 100644 index 00000000000..08077c0a462 --- /dev/null +++ b/src/main/java/gregtech/api/util/JEIUtil.java @@ -0,0 +1,29 @@ +package gregtech.api.util; + +import net.minecraft.enchantment.EnchantmentData; + +import com.cleanroommc.modularui.integration.jei.JeiGhostIngredientSlot; +import com.cleanroommc.modularui.integration.jei.ModularUIJeiPlugin; +import mezz.jei.Internal; + +public class JEIUtil { + + /** + * Check if the player is currently hovering over a valid ingredient for this slot.
+ * Will always return false is JEI is not installed. + */ + public static boolean hoveringOverIngredient(JeiGhostIngredientSlot jeiGhostIngredientSlot) { + if (!Mods.JustEnoughItems.isModLoaded()) return false; + return ModularUIJeiPlugin.hoveringOverIngredient(jeiGhostIngredientSlot); + } + + public static Object getBookStackIfEnchantment(Object ingredient) { + if (ingredient instanceof EnchantmentData enchantmentData) { + return Internal.getIngredientRegistry() + .getIngredientHelper(enchantmentData) + .getCheatItemStack(enchantmentData); + } + + return ingredient; + } +} diff --git a/src/main/java/gregtech/client/utils/RenderUtil.java b/src/main/java/gregtech/client/utils/RenderUtil.java index e62f32d9c07..8b93f3f54ee 100644 --- a/src/main/java/gregtech/client/utils/RenderUtil.java +++ b/src/main/java/gregtech/client/utils/RenderUtil.java @@ -1,7 +1,7 @@ package gregtech.client.utils; import gregtech.api.gui.resources.TextureArea; -import gregtech.api.util.Mods; +import gregtech.api.util.JEIUtil; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; @@ -29,8 +29,11 @@ import codechicken.lib.vec.Matrix4; import com.cleanroommc.modularui.api.MCHelper; import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.GuiDraw; import com.cleanroommc.modularui.integration.jei.JeiGhostIngredientSlot; -import com.cleanroommc.modularui.integration.jei.ModularUIJeiPlugin; +import com.cleanroommc.modularui.theme.WidgetSlotTheme; +import com.cleanroommc.modularui.theme.WidgetTheme; +import com.cleanroommc.modularui.utils.Color; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; @@ -43,6 +46,7 @@ public class RenderUtil { private static final Deque scissorFrameStack = new ArrayDeque<>(); + public static final int defaultSlotHoverColor = Color.withAlpha(Color.WHITE.main, 0x60); public static void useScissor(int x, int y, int width, int height, Runnable codeBlock) { pushScissorFrame(x, y, width, height); @@ -716,14 +720,39 @@ public void put(int element, float @NotNull... data) { return getTextureMap().getMissingSprite(); } - public static void handleJeiGhostHighlight(IWidget slot) { - if (!Mods.JustEnoughItems.isModLoaded()) return; - if (!(slot instanceof JeiGhostIngredientSlotingredientSlot)) return; - if (ModularUIJeiPlugin.hasDraggingGhostIngredient() || - ModularUIJeiPlugin.hoveringOverIngredient(ingredientSlot)) { - GlStateManager.colorMask(true, true, true, false); - ingredientSlot.drawHighlight(slot.getArea(), slot.isHovering()); - GlStateManager.colorMask(true, true, true, true); + public static void drawSlotOverlay(@NotNull IWidget slot, int overlayColor) { + GlStateManager.colorMask(true, true, true, false); + GuiDraw.drawRect(1, 1, slot.getArea().w() - 2, slot.getArea().h() - 2, overlayColor); + GlStateManager.colorMask(true, true, true, true); + } + + public static void drawSlotOverlay(@NotNull IWidget slot, WidgetTheme widgetTheme) { + drawSlotOverlay(slot, widgetTheme instanceof WidgetSlotTheme slotTheme ? slotTheme.getSlotHoverColor() : + defaultSlotHoverColor); + } + + public static void handleSlotOverlay(@NotNull IWidget slot, @NotNull WidgetTheme widgetTheme) { + if (slot.isHovering()) { + drawSlotOverlay(slot, widgetTheme); + } + } + + public static < + T extends IWidget & JeiGhostIngredientSlot> void drawJEIGhostSlotOverlay(@NotNull T jeiGhostIngredientSlot) { + GlStateManager.colorMask(true, true, true, false); + jeiGhostIngredientSlot.drawHighlight(jeiGhostIngredientSlot.getArea(), jeiGhostIngredientSlot.isHovering()); + GlStateManager.colorMask(true, true, true, true); + } + + public static < + T extends IWidget & JeiGhostIngredientSlot> boolean handleJEIGhostSlotOverlay(@NotNull T jeiGhostIngredientSlot, + @NotNull WidgetTheme widgetTheme) { + if (JEIUtil.hoveringOverIngredient(jeiGhostIngredientSlot)) { + drawJEIGhostSlotOverlay(jeiGhostIngredientSlot); + return true; } + + handleSlotOverlay(jeiGhostIngredientSlot, widgetTheme); + return false; } } diff --git a/src/main/java/gregtech/common/mui/widget/GTFluidSlot.java b/src/main/java/gregtech/common/mui/widget/GTFluidSlot.java index 79c31bd31cd..ebf9175a8c4 100644 --- a/src/main/java/gregtech/common/mui/widget/GTFluidSlot.java +++ b/src/main/java/gregtech/common/mui/widget/GTFluidSlot.java @@ -4,7 +4,6 @@ import gregtech.api.util.GTUtility; import gregtech.client.utils.RenderUtil; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; @@ -116,13 +115,7 @@ public void draw(ModularGuiContext context, WidgetSlotTheme widgetTheme) { this.textRenderer.draw(amount); } - if (isHovering()) { - GlStateManager.colorMask(true, true, true, false); - GuiDraw.drawRect(1, 1, getArea().w() - 2, getArea().h() - 2, widgetTheme.getSlotHoverColor()); - GlStateManager.colorMask(true, true, true, true); - } - - RenderUtil.handleJeiGhostHighlight(this); + RenderUtil.handleJEIGhostSlotOverlay(this, widgetTheme); } @Override diff --git a/src/main/java/gregtech/common/mui/widget/workbench/CraftingInputSlot.java b/src/main/java/gregtech/common/mui/widget/workbench/CraftingInputSlot.java index 0e883aa9bd6..3c718d2e90c 100644 --- a/src/main/java/gregtech/common/mui/widget/workbench/CraftingInputSlot.java +++ b/src/main/java/gregtech/common/mui/widget/workbench/CraftingInputSlot.java @@ -1,6 +1,7 @@ package gregtech.common.mui.widget.workbench; import gregtech.api.util.GTUtility; +import gregtech.api.util.JEIUtil; import gregtech.client.utils.RenderUtil; import gregtech.common.metatileentities.storage.CraftingRecipeLogic; @@ -102,15 +103,21 @@ public void onMouseDrag(int mouseButton, long timeSinceClick) { @Override public void draw(ModularGuiContext context, WidgetTheme widgetTheme) { ItemStack itemstack = this.syncHandler.getStack(); + boolean jeiIngredientBeingHovered = JEIUtil.hoveringOverIngredient(this); + if (!itemstack.isEmpty()) { - if (!this.hasIngredients) { + if (!jeiIngredientBeingHovered && !this.hasIngredients) { RenderUtil.renderRect(0, 0, 18, 18, 200, 0x80FF0000); } RenderUtil.renderItem(itemstack, 1, 1, 16, 16); } - RenderUtil.handleJeiGhostHighlight(this); + if (jeiIngredientBeingHovered) { + RenderUtil.drawJEIGhostSlotOverlay(this); + } else { + RenderUtil.handleSlotOverlay(this, widgetTheme); + } } @Override @@ -128,6 +135,7 @@ public void setGhostIngredient(@NotNull ItemStack ingredient) { @Override public @Nullable ItemStack castGhostIngredientIfValid(@NotNull Object ingredient) { + ingredient = JEIUtil.getBookStackIfEnchantment(ingredient); return areAncestorsEnabled() && ingredient instanceof ItemStack ? (ItemStack) ingredient : null; } diff --git a/src/main/java/gregtech/common/mui/widget/workbench/CraftingOutputSlot.java b/src/main/java/gregtech/common/mui/widget/workbench/CraftingOutputSlot.java index db766fe50bf..6576008a0c5 100644 --- a/src/main/java/gregtech/common/mui/widget/workbench/CraftingOutputSlot.java +++ b/src/main/java/gregtech/common/mui/widget/workbench/CraftingOutputSlot.java @@ -72,9 +72,8 @@ public boolean isValidSyncHandler(SyncHandler syncHandler) { @Override public void draw(ModularGuiContext context, WidgetTheme widgetTheme) { ItemStack itemstack = this.syncHandler.getOutputStack(); - if (itemstack.isEmpty()) return; - RenderUtil.renderItem(itemstack, 1, 1, 16, 16); + RenderUtil.handleSlotOverlay(this, widgetTheme); } @Override diff --git a/src/main/java/gregtech/common/mui/widget/workbench/RecipeMemorySlot.java b/src/main/java/gregtech/common/mui/widget/workbench/RecipeMemorySlot.java index 2d24eea1d83..b33d71ee40c 100644 --- a/src/main/java/gregtech/common/mui/widget/workbench/RecipeMemorySlot.java +++ b/src/main/java/gregtech/common/mui/widget/workbench/RecipeMemorySlot.java @@ -45,20 +45,23 @@ public RecipeMemorySlot(CraftingRecipeMemory memory, int index) { @Override public void draw(ModularGuiContext context, WidgetTheme widgetTheme) { - ItemStack itemstack = this.memory.getRecipeOutputAtIndex(this.index); - if (itemstack.isEmpty()) return; - - int cachedCount = itemstack.getCount(); - itemstack.setCount(1); // required to not render the amount overlay - RenderUtil.renderItem(itemstack, 1, 1, 16, 16); - itemstack.setCount(cachedCount); - - // noinspection DataFlowIssue - if (this.memory.getRecipeAtIndex(this.index).isRecipeLocked()) { - GlStateManager.disableDepth(); - GTGuiTextures.RECIPE_LOCK.draw(context, 10, 1, 8, 8, widgetTheme); - GlStateManager.enableDepth(); + ItemStack itemStack = this.memory.getRecipeOutputAtIndex(this.index); + + if (!itemStack.isEmpty()) { + int cachedCount = itemStack.getCount(); + itemStack.setCount(1); // required to not render the amount overlay + RenderUtil.renderItem(itemStack, 1, 1, 16, 16); + itemStack.setCount(cachedCount); + + // noinspection DataFlowIssue + if (this.memory.getRecipeAtIndex(this.index).isRecipeLocked()) { + GlStateManager.disableDepth(); + GTGuiTextures.RECIPE_LOCK.draw(context, 10, 1, 8, 8, widgetTheme); + GlStateManager.enableDepth(); + } } + + RenderUtil.handleSlotOverlay(this, widgetTheme); } @Override diff --git a/src/main/java/gregtech/mixins/mui2/ItemSlotMixin.java b/src/main/java/gregtech/mixins/mui2/ItemSlotMixin.java new file mode 100644 index 00000000000..1f7bddb0573 --- /dev/null +++ b/src/main/java/gregtech/mixins/mui2/ItemSlotMixin.java @@ -0,0 +1,41 @@ +package gregtech.mixins.mui2; + +import gregtech.api.util.JEIUtil; + +import net.minecraft.item.ItemStack; + +import com.cleanroommc.modularui.integration.jei.ModularUIJeiPlugin; +import com.cleanroommc.modularui.widgets.ItemSlot; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import mezz.jei.gui.ghost.GhostIngredientDrag; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +// TODO: remove once MUI PR 146 merges into a release we use +@Mixin(value = ItemSlot.class, remap = false) +public abstract class ItemSlotMixin { + + @Shadow + public abstract @Nullable ItemStack castGhostIngredientIfValid(@NotNull Object ingredient); + + @Redirect(method = "draw", + at = @At(value = "INVOKE", + target = "Lcom/cleanroommc/modularui/integration/jei/ModularUIJeiPlugin;hasDraggingGhostIngredient()Z")) + private boolean onlyHighlightOnValidDrag() { + GhostIngredientDrag ingredientDrag = ModularUIJeiPlugin.getGhostDrag(); + if (ingredientDrag == null) return false; + Object ingredient = ingredientDrag.getIngredient(); + if (ingredient == null) return false; + return castGhostIngredientIfValid(ingredient) != null; + } + + @WrapMethod(method = "castGhostIngredientIfValid(Ljava/lang/Object;)Lnet/minecraft/item/ItemStack;") + public @Nullable ItemStack addSupportForEnchantedBooks(Object ingredient, Operation original) { + return original.call(JEIUtil.getBookStackIfEnchantment(ingredient)); + } +} diff --git a/src/main/java/gregtech/mixins/mui2/ModularUIJeiPluginMixin.java b/src/main/java/gregtech/mixins/mui2/ModularUIJeiPluginMixin.java new file mode 100644 index 00000000000..2f0853cb4f1 --- /dev/null +++ b/src/main/java/gregtech/mixins/mui2/ModularUIJeiPluginMixin.java @@ -0,0 +1,22 @@ +package gregtech.mixins.mui2; + +import com.cleanroommc.modularui.integration.jei.JeiGhostIngredientSlot; +import com.cleanroommc.modularui.integration.jei.ModularUIJeiPlugin; +import mezz.jei.config.Config; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(value = ModularUIJeiPlugin.class) +public class ModularUIJeiPluginMixin { + + // TODO: remove this mixin when the fix from Brachy makes it into a release we use + @Inject(method = "hoveringOverIngredient", at = @At(value = "HEAD"), remap = false, cancellable = true) + private static void cancelIfCheatsOn(JeiGhostIngredientSlot ingredientSlot, + CallbackInfoReturnable cir) { + if (Config.isCheatItemsEnabled()) { + cir.setReturnValue(false); + } + } +} diff --git a/src/main/resources/mixins.gregtech.mui2.json b/src/main/resources/mixins.gregtech.mui2.json index 10684de90fb..fccde409ebd 100644 --- a/src/main/resources/mixins.gregtech.mui2.json +++ b/src/main/resources/mixins.gregtech.mui2.json @@ -15,7 +15,9 @@ "RichTextCompilerMixin" ], "client": [ - "LangKeyMixin" + "LangKeyMixin", + "ModularUIJeiPluginMixin", + "ItemSlotMixin" ], "server": [] }