diff --git a/src/main/java/com/extendedae_plus/client/InputEvents.java b/src/main/java/com/extendedae_plus/client/InputEvents.java index 6a921a4..e52cb36 100644 --- a/src/main/java/com/extendedae_plus/client/InputEvents.java +++ b/src/main/java/com/extendedae_plus/client/InputEvents.java @@ -33,10 +33,7 @@ public final class InputEvents { if (!ModList.get().isLoaded("jei")) { return; } - // 若 JEI 运行时尚未就绪,跳过 - if (JeiRuntimeProxy.get() == null) { - return; - } + // 注意:不要在 try/catch 之外直接访问 JEI 运行时,避免类加载崩溃 // 优先处理:Shift + 左键(拉取或下单) if (event.getButton() == GLFW.GLFW_MOUSE_BUTTON_LEFT && Screen.hasShiftDown()) { try { @@ -103,9 +100,7 @@ public final class InputEvents { if (!ModList.get().isLoaded("jei")) { return; } - if (JeiRuntimeProxy.get() == null) { - return; - } + // 注意:不要在 try/catch 之外直接访问 JEI 运行时,避免类加载崩溃 if (event.getKeyCode() != GLFW.GLFW_KEY_F) return; // 仅当鼠标确实悬停在 JEI 配料上时触发 diff --git a/src/main/java/com/extendedae_plus/integration/jei/JeiRuntimeProxy.java b/src/main/java/com/extendedae_plus/integration/jei/JeiRuntimeProxy.java index bc5276e..38c3541 100644 --- a/src/main/java/com/extendedae_plus/integration/jei/JeiRuntimeProxy.java +++ b/src/main/java/com/extendedae_plus/integration/jei/JeiRuntimeProxy.java @@ -1,24 +1,16 @@ 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; import mezz.jei.api.runtime.IJeiRuntime; -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; @@ -131,48 +123,35 @@ public final class JeiRuntimeProxy { } /** - * 获取JEI书签列表 + * 获取 JEI 书签列表。为避免在未安装 JEI GUI 时崩溃,使用反射委托到桥接类。 */ public static List> getBookmarkList() { - IJeiRuntime rt = RUNTIME; - if (rt == null) return Collections.emptyList(); - IBookmarkOverlay bookmarkOverlay = rt.getBookmarkOverlay(); - if (bookmarkOverlay instanceof BookmarkOverlayAccessor accessor) { - BookmarkList bookmarkList = accessor.eap$getBookmarkList(); - return bookmarkList.getElements().stream().map(IElement::getTypedIngredient).toList(); + try { + Class bridge = Class.forName("com.extendedae_plus.integration.jei.JeiBookmarkBridge"); + var m = bridge.getMethod("getBookmarkList"); + @SuppressWarnings("unchecked") + List> list = (List>) m.invoke(null); + return list == null ? Collections.emptyList() : list; + } catch (Throwable ignored) { + return Collections.emptyList(); } - return Collections.emptyList(); } public static void addBookmark(ItemStack stack) { - IJeiRuntime rt = RUNTIME; - if (rt == null) return; - - IBookmarkOverlay overlay = rt.getBookmarkOverlay(); - if (overlay instanceof BookmarkOverlayAccessor accessor) { - BookmarkList list = accessor.eap$getBookmarkList(); - Optional> typedOpt = rt.getIngredientManager() - .createTypedIngredient(VanillaTypes.ITEM_STACK, stack); - typedOpt.ifPresent(typed -> { - IngredientBookmark bookmark = IngredientBookmark.create(typed, rt.getIngredientManager()); - list.add(bookmark); // add 内部会自动保存到配置 - }); + try { + Class bridge = Class.forName("com.extendedae_plus.integration.jei.JeiBookmarkBridge"); + var m = bridge.getMethod("addBookmark", ItemStack.class); + m.invoke(null, stack); + } catch (Throwable ignored) { } } 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> typedOpt = rt.getIngredientManager() - .createTypedIngredient(ForgeTypes.FLUID_STACK, fluidStack); - typedOpt.ifPresent(typed -> { - IngredientBookmark bookmark = IngredientBookmark.create(typed, rt.getIngredientManager()); - list.add(bookmark); // add 内部会自动保存到配置 - }); + try { + Class bridge = Class.forName("com.extendedae_plus.integration.jei.JeiBookmarkBridge"); + var m = bridge.getMethod("addBookmark", FluidStack.class); + m.invoke(null, fluidStack); + } catch (Throwable ignored) { } } @@ -180,91 +159,25 @@ public final class JeiRuntimeProxy { * 如果存在 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(); - } + try { + Class bridge = Class.forName("com.extendedae_plus.integration.jei.JeiBookmarkBridge"); + var m = bridge.getMethod("addBookmark", Object.class); + m.invoke(null, chemicalStack); + } catch (Throwable ignored) { } } - 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; - } + // Note: helper methods moved to bridge to avoid referencing JEI GUI at class load time. /** - * 从 JEI 书签移除物品 + * 从 JEI 书签移除物品(反射委托) */ public static void removeBookmark(ItemStack stack) { - IJeiRuntime rt = RUNTIME; - if (rt == null) return; - - IBookmarkOverlay overlay = rt.getBookmarkOverlay(); - if (overlay instanceof BookmarkOverlayAccessor accessor) { - BookmarkList list = accessor.eap$getBookmarkList(); - Optional> typedOpt = rt.getIngredientManager() - .createTypedIngredient(VanillaTypes.ITEM_STACK, stack); - typedOpt.ifPresent(typed -> { - IngredientBookmark bookmark = IngredientBookmark.create(typed, rt.getIngredientManager()); - list.remove(bookmark); - }); + try { + Class bridge = Class.forName("com.extendedae_plus.integration.jei.JeiBookmarkBridge"); + var m = bridge.getMethod("removeBookmark", ItemStack.class); + m.invoke(null, stack); + } catch (Throwable ignored) { } } }