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 JeiGhostIngredientSlot>ingredientSlot)) 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": []
}