fix: 合成计划界面添加缺少物品遇到流体,mek化学品会出现错误书签

This commit is contained in:
C-H716 2025-09-20 23:29:10 +08:00
parent e45bcf87b0
commit 3968b26217
2 changed files with 104 additions and 7 deletions

View File

@ -2,7 +2,9 @@ package com.extendedae_plus.integration.jei;
import com.extendedae_plus.mixin.jei.accessor.BookmarkOverlayAccessor;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.ingredients.IIngredientType;
import mezz.jei.api.ingredients.ITypedIngredient;
import mezz.jei.api.neoforge.NeoForgeTypes;
import mezz.jei.api.runtime.IBookmarkOverlay;
import mezz.jei.api.runtime.IIngredientListOverlay;
import mezz.jei.api.runtime.IJeiRuntime;
@ -10,8 +12,12 @@ import mezz.jei.gui.bookmarks.BookmarkList;
import mezz.jei.gui.bookmarks.IngredientBookmark;
import mezz.jei.gui.overlay.elements.IElement;
import net.minecraft.world.item.ItemStack;
import net.neoforged.fml.ModList;
import net.neoforged.neoforge.fluids.FluidStack;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@ -155,6 +161,83 @@ public final class JeiRuntimeProxy {
}
}
public static void addBookmark(FluidStack fluidStack) {
IJeiRuntime rt = RUNTIME;
if (rt == null) return;
IBookmarkOverlay overlay = rt.getBookmarkOverlay();
if (overlay instanceof BookmarkOverlayAccessor accessor) {
BookmarkList list = accessor.eap$getBookmarkList();
Optional<ITypedIngredient<FluidStack>> typedOpt = rt.getIngredientManager()
.createTypedIngredient(NeoForgeTypes.FLUID_STACK, fluidStack);
typedOpt.ifPresent(typed -> {
IngredientBookmark<FluidStack> bookmark = IngredientBookmark.create(typed, rt.getIngredientManager());
list.add(bookmark); // add 内部会自动保存到配置
});
}
}
/**
* 如果存在 Mekanism/appmek则将 Mekanism 化学堆栈添加到 JEI 书签
*/
public static void addBookmark(Object chemicalStack) {
if (!ModList.get().isLoaded("mekanism") && !ModList.get().isLoaded("appmek")) return;
IJeiRuntime rt = RUNTIME;
if (rt == null) return;
IBookmarkOverlay overlay = rt.getBookmarkOverlay();
if (overlay instanceof BookmarkOverlayAccessor accessor) {
BookmarkList list = accessor.eap$getBookmarkList();
try {
if (chemicalStack == null) return;
// Determine Mekanism JEI ingredient type constant by runtime class name
String clsName = chemicalStack.getClass().getName();
String mekanismJeiClass = "mekanism.client.recipe_viewer.jei.MekanismJEI";
Class<?> jeiCls = Class.forName(mekanismJeiClass);
Field typeField = null;
if ("mekanism.api.chemical.ChemicalStack".equals(clsName)) {
typeField = jeiCls.getField("TYPE_CHEMICAL");
}
if (typeField == null) return;
Object typeConst = typeField.get(null);
// Use ingredient manager reflectively to create a typed ingredient
Object ingredientManager = rt.getIngredientManager();
Method createTypedIngredient = ingredientManager.getClass().getMethod("createTypedIngredient", IIngredientType.class, Object.class);
Object opt = createTypedIngredient.invoke(ingredientManager, typeConst, chemicalStack);
if (!(opt instanceof Optional<?> typedOpt)) return;
if (typedOpt.isPresent()) {
Object typed = typedOpt.get();
// Find a compatible static create(...) method on IngredientBookmark where
// the second parameter is assignable from the actual ingredientManager instance.
Method createMethod = null;
for (Method m : IngredientBookmark.class.getMethods()) {
if (!m.getName().equals("create")) continue;
Class<?>[] params = m.getParameterTypes();
if (params.length != 2) continue;
// first param should accept the typed ingredient
boolean firstOk = params[0].isAssignableFrom(typed.getClass()) || params[0].isAssignableFrom(ITypedIngredient.class);
boolean secondOk = params[1].isAssignableFrom(ingredientManager.getClass());
if (firstOk && secondOk) {
createMethod = m;
break;
}
}
if (createMethod != null) {
Object bookmark = createMethod.invoke(null, typed, ingredientManager);
if (bookmark != null) {
list.add((IngredientBookmark) bookmark);
}
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
/**
* JEI 书签移除物品
*/

View File

@ -1,10 +1,13 @@
package com.extendedae_plus.mixin.ae2.menu;
import appeng.api.stacks.AEFluidKey;
import appeng.api.stacks.AEItemKey;
import appeng.menu.me.crafting.CraftConfirmMenu;
import appeng.menu.me.crafting.CraftingPlanSummary;
import appeng.menu.me.crafting.CraftingPlanSummaryEntry;
import com.extendedae_plus.integration.jei.JeiRuntimeProxy;
import net.minecraft.client.gui.screens.Screen;
import net.neoforged.fml.ModList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -42,13 +45,24 @@ public class CraftConfirmMenuGoBackMixin {
// 为缺失的条目添加 JEI 书签
for (CraftingPlanSummaryEntry entry : entries) {
if (entry.getMissingAmount() > 0) {
try {
var display = entry.getWhat().wrapForDisplayOrFilter();
if (display != null && !display.isEmpty()) {
// wrapForDisplayOrFilter 返回 ItemStack
JeiRuntimeProxy.addBookmark(display);
}
} catch (Throwable ignored) {}
var what = entry.getWhat();
if (what instanceof AEItemKey aeItemKey) {
JeiRuntimeProxy.addBookmark(aeItemKey.getReadOnlyStack());
} else if (what instanceof AEFluidKey aeFluidKey) {
JeiRuntimeProxy.addBookmark(aeFluidKey.toStack(1000));
} else if (ModList.get().isLoaded("appmek") && ModList.get().isLoaded("mekanism")) {
try {
if (what != null) {
// avoid compile-time dependency on MekanismKey by reflection
Class<?> mekanismKeyCls = Class.forName("me.ramidzkh.mekae2.ae2.MekanismKey");
if (mekanismKeyCls.isInstance(what)) {
java.lang.reflect.Method m = mekanismKeyCls.getMethod("getStack");
Object stack = m.invoke(what);
JeiRuntimeProxy.addBookmark(stack);
}
}
} catch (Throwable ignored) {}
}
}
}
} catch (Throwable ignored) {}