From 8f4a735e432b8189fc9d8cbf38d649d87272d34b Mon Sep 17 00:00:00 2001 From: GaLi <3096147684@qq.com> Date: Sun, 1 Mar 2026 16:23:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=84=E7=90=86=E4=B9=A6=E7=AD=BE=E5=88=86?= =?UTF-8?q?=E6=94=AF=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/event/CtrlQPatternKeyHandler.java | 97 +++++++++++++++++-- .../integration/jei/JeiBookmarkBridge.java | 25 +++++ 2 files changed, 116 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/extendedae_plus/client/event/CtrlQPatternKeyHandler.java b/src/main/java/com/extendedae_plus/client/event/CtrlQPatternKeyHandler.java index e00b6b2..46b7b49 100644 --- a/src/main/java/com/extendedae_plus/client/event/CtrlQPatternKeyHandler.java +++ b/src/main/java/com/extendedae_plus/client/event/CtrlQPatternKeyHandler.java @@ -166,11 +166,16 @@ public class CtrlQPatternKeyHandler { private static void handleCraftingRecipeBookmark(Object recipeBookmark) { try { // 1. 获取配方ID - var getRecipeUidMethod = recipeBookmark.getClass().getMethod("getRecipeUid"); - net.minecraft.resources.ResourceLocation recipeId = - (net.minecraft.resources.ResourceLocation) getRecipeUidMethod.invoke(recipeBookmark); + net.minecraft.resources.ResourceLocation recipeId = getRecipeIdCompat(recipeBookmark); if (recipeId == null) { + Minecraft mc = Minecraft.getInstance(); + if (mc.player != null) { + mc.player.displayClientMessage( + Component.translatable("message.extendedae_plus.recipe_not_found"), + true + ); + } return; } @@ -219,6 +224,17 @@ public class CtrlQPatternKeyHandler { ); // 如果找不到,尝试通过配方输出物品查找 + if (recipeInfos.isEmpty()) { + try { + var getDisplayIngredientMethod = recipeBookmark.getClass().getMethod("getDisplayIngredient"); + Object displayIngredient = getDisplayIngredientMethod.invoke(recipeBookmark); + if (displayIngredient instanceof ITypedIngredient typedIngredient) { + recipeInfos = RecipeFinderUtil.findRecipesByIngredient(typedIngredient); + } + } catch (Throwable ignored) { + } + } + if (recipeInfos.isEmpty()) { var getRecipeOutputMethod = recipeBookmark.getClass().getMethod("getRecipeOutput"); Object recipeOutput = getRecipeOutputMethod.invoke(recipeBookmark); @@ -277,10 +293,15 @@ public class CtrlQPatternKeyHandler { */ private static void handleProcessingRecipeBookmark(Object recipeBookmark) { try { - var getRecipeUidMethod = recipeBookmark.getClass().getMethod("getRecipeUid"); - net.minecraft.resources.ResourceLocation recipeId = - (net.minecraft.resources.ResourceLocation) getRecipeUidMethod.invoke(recipeBookmark); + net.minecraft.resources.ResourceLocation recipeId = getRecipeIdCompat(recipeBookmark); if (recipeId == null) { + Minecraft mc = Minecraft.getInstance(); + if (mc.player != null) { + mc.player.displayClientMessage( + Component.translatable("message.extendedae_plus.recipe_not_found"), + true + ); + } return; } @@ -313,6 +334,17 @@ public class CtrlQPatternKeyHandler { JeiRuntimeProxy.getIngredientUnderMouse().orElse(null) ); + if (recipeInfos.isEmpty()) { + try { + var getDisplayIngredientMethod = recipeBookmark.getClass().getMethod("getDisplayIngredient"); + Object displayIngredient = getDisplayIngredientMethod.invoke(recipeBookmark); + if (displayIngredient instanceof ITypedIngredient typedIngredient) { + recipeInfos = RecipeFinderUtil.findRecipesByIngredient(typedIngredient); + } + } catch (Throwable ignored) { + } + } + if (recipeInfos.isEmpty()) { var getRecipeOutputMethod = recipeBookmark.getClass().getMethod("getRecipeOutput"); Object recipeOutput = getRecipeOutputMethod.invoke(recipeBookmark); @@ -359,6 +391,59 @@ public class CtrlQPatternKeyHandler { } } + private static net.minecraft.resources.ResourceLocation getRecipeIdCompat(Object recipeBookmark) { + if (recipeBookmark == null) { + return null; + } + + // JEI 1.20 分支 + try { + var getRecipeUidMethod = recipeBookmark.getClass().getMethod("getRecipeUid"); + Object recipeId = getRecipeUidMethod.invoke(recipeBookmark); + if (recipeId instanceof net.minecraft.resources.ResourceLocation rl) { + return rl; + } + } catch (Throwable ignored) { + } + + // JEI 1.21+ 分支 + try { + Object recipe = recipeBookmark.getClass().getMethod("getRecipe").invoke(recipeBookmark); + Object recipeCategory = recipeBookmark.getClass().getMethod("getRecipeCategory").invoke(recipeBookmark); + if (recipe != null && recipeCategory != null) { + try { + Object recipeId = recipeCategory.getClass().getMethod("getRegistryName", Object.class).invoke(recipeCategory, recipe); + if (recipeId instanceof net.minecraft.resources.ResourceLocation rl) { + return rl; + } + } catch (Throwable ignored) { + for (var m : recipeCategory.getClass().getMethods()) { + if (!"getRegistryName".equals(m.getName()) || m.getParameterCount() != 1) { + continue; + } + Object recipeId = m.invoke(recipeCategory, recipe); + if (recipeId instanceof net.minecraft.resources.ResourceLocation rl) { + return rl; + } + } + } + } + } catch (Throwable ignored) { + } + + // 字段兜底 + try { + var f = recipeBookmark.getClass().getDeclaredField("recipeUid"); + f.setAccessible(true); + Object recipeId = f.get(recipeBookmark); + if (recipeId instanceof net.minecraft.resources.ResourceLocation rl) { + return rl; + } + } catch (Throwable ignored) { + } + return null; + } + private static void setLastProcessingNameFromRecipe(Object recipeBase) { String name = null; if (recipeBase instanceof Recipe recipe) { diff --git a/src/main/java/com/extendedae_plus/integration/jei/JeiBookmarkBridge.java b/src/main/java/com/extendedae_plus/integration/jei/JeiBookmarkBridge.java index e855d5b..1f24f2c 100644 --- a/src/main/java/com/extendedae_plus/integration/jei/JeiBookmarkBridge.java +++ b/src/main/java/com/extendedae_plus/integration/jei/JeiBookmarkBridge.java @@ -9,6 +9,7 @@ import mezz.jei.api.runtime.IBookmarkOverlay; import mezz.jei.api.runtime.IJeiRuntime; import mezz.jei.gui.bookmarks.BookmarkList; import mezz.jei.gui.bookmarks.IngredientBookmark; +import mezz.jei.gui.input.MouseUtil; import mezz.jei.gui.overlay.elements.IElement; import net.minecraft.world.item.ItemStack; import net.minecraftforge.fluids.FluidStack; @@ -173,6 +174,30 @@ public final class JeiBookmarkBridge { if (!(bookmarkOverlay instanceof BookmarkOverlayAccessor accessor)) { return Optional.empty(); } + + // 优先路径:直接从鼠标下 clickable 元素提取 bookmark(避免 typedIngredient equals 误判) + try { + var overlayObj = (Object) bookmarkOverlay; + var streamObj = overlayObj.getClass() + .getMethod("getIngredientUnderMouse", double.class, double.class) + .invoke(overlayObj, MouseUtil.getX(), MouseUtil.getY()); + if (streamObj instanceof java.util.stream.Stream stream) { + Object clickable = stream.findFirst().orElse(null); + if (clickable != null) { + Object element = clickable.getClass().getMethod("getElement").invoke(clickable); + if (element != null) { + Object bookmarkOpt = element.getClass().getMethod("getBookmark").invoke(element); + if (bookmarkOpt instanceof Optional b && b.isPresent()) { + Object bookmark = b.get(); + if (bookmark != null && "RecipeBookmark".equals(bookmark.getClass().getSimpleName())) { + return Optional.of(bookmark); + } + } + } + } + } + } catch (Throwable ignored) { + } // 获取鼠标下的元素 Optional> ingredientOpt = bookmarkOverlay.getIngredientUnderMouse();