fix: 合成计划界面添加缺少物品遇到流体,mek化学品会出现错误书签
This commit is contained in:
parent
5ca15ac506
commit
121828d8f1
|
|
@ -2,6 +2,8 @@ package com.extendedae_plus.integration.jei;
|
|||
|
||||
import com.extendedae_plus.mixin.jei.accessor.BookmarkOverlayAccessor;
|
||||
import mezz.jei.api.constants.VanillaTypes;
|
||||
import mezz.jei.api.forge.ForgeTypes;
|
||||
import mezz.jei.api.ingredients.IIngredientType;
|
||||
import mezz.jei.api.ingredients.ITypedIngredient;
|
||||
import mezz.jei.api.runtime.IBookmarkOverlay;
|
||||
import mezz.jei.api.runtime.IIngredientListOverlay;
|
||||
|
|
@ -10,8 +12,13 @@ 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.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import org.spongepowered.asm.mixin.Pseudo;
|
||||
|
||||
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;
|
||||
|
|
@ -19,10 +26,12 @@ import java.util.Optional;
|
|||
/**
|
||||
* 线程安全地缓存并访问 JEI Runtime。
|
||||
*/
|
||||
@Pseudo
|
||||
public final class JeiRuntimeProxy {
|
||||
private static volatile IJeiRuntime RUNTIME;
|
||||
|
||||
private JeiRuntimeProxy() {}
|
||||
private JeiRuntimeProxy() {
|
||||
}
|
||||
|
||||
static void setRuntime(IJeiRuntime runtime) {
|
||||
RUNTIME = runtime;
|
||||
|
|
@ -135,9 +144,6 @@ public final class JeiRuntimeProxy {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将物品添加到 JEI 书签
|
||||
*/
|
||||
public static void addBookmark(ItemStack stack) {
|
||||
IJeiRuntime rt = RUNTIME;
|
||||
if (rt == null) return;
|
||||
|
|
@ -154,6 +160,95 @@ 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(ForgeTypes.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.jei.MekanismJEI";
|
||||
Class<?> jeiCls = Class.forName(mekanismJeiClass);
|
||||
Field typeField = getField(clsName, jeiCls);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static @Nullable Field getField(String clsName, Class<?> jeiCls) throws NoSuchFieldException {
|
||||
Field typeField = null;
|
||||
if ("mekanism.api.chemical.gas.GasStack".equals(clsName)) {
|
||||
typeField = jeiCls.getField("TYPE_GAS");
|
||||
} else if ("mekanism.api.chemical.infuse.InfusionStack".equals(clsName)) {
|
||||
typeField = jeiCls.getField("TYPE_INFUSION");
|
||||
} else if ("mekanism.api.chemical.pigment.PigmentStack".equals(clsName)) {
|
||||
typeField = jeiCls.getField("TYPE_PIGMENT");
|
||||
} else if ("mekanism.api.chemical.slurry.SlurryStack".equals(clsName)) {
|
||||
typeField = jeiCls.getField("TYPE_SLURRY");
|
||||
}
|
||||
return typeField;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 JEI 书签移除物品
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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.minecraftforge.fml.ModList;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
|
|
@ -44,9 +47,27 @@ public class CraftConfirmMenuGoBackMixin {
|
|||
// 仅在按住 shift 时为缺失的条目添加 JEI 书签
|
||||
for (CraftingPlanSummaryEntry entry : entries) {
|
||||
if (entry.getMissingAmount() > 0) {
|
||||
JeiRuntimeProxy.addBookmark(entry.getWhat().wrapForDisplayOrFilter());
|
||||
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) {}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,11 +16,12 @@
|
|||
"ae2.accessor.PatternAccessTermScreenAccessor",
|
||||
"ae2.accessor.PatternAccessTermScreenSlotsRowAccessor",
|
||||
"ae2.client.gui.AEBaseScreenMixin",
|
||||
"ae2.client.gui.PatternEncodingTermScreenMixin",
|
||||
"ae2.client.gui.InterfaceScreenMixin",
|
||||
"ae2.client.gui.PatternEncodingTermScreenMixin",
|
||||
"ae2.client.gui.PatternProviderCloseMixin",
|
||||
"ae2.client.gui.PatternProviderScreenMixin",
|
||||
"ae2.client.gui.SlotGridLayoutMixin",
|
||||
"ae2.menu.CraftConfirmMenuGoBackMixin",
|
||||
"extendedae.accessor.GuiExPatternTerminalAccessor",
|
||||
"extendedae.accessor.GuiExPatternTerminalSlotsRowAccessor",
|
||||
"extendedae.client.HighlightButtonMixin",
|
||||
|
|
@ -57,7 +58,6 @@
|
|||
"ae2.helpers.PatternProviderLogicAdvancedMixin",
|
||||
"ae2.helpers.PatternProviderLogicDoublingMixin",
|
||||
"ae2.menu.ContainerPatternEncodingTermMenuMixin",
|
||||
"ae2.menu.CraftConfirmMenuGoBackMixin",
|
||||
"ae2.menu.MEStorageMenuMixin",
|
||||
"ae2.menu.PatternEncodingTermMenuMixin",
|
||||
"ae2.menu.PatternProviderMenuAdvancedMixin",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user