处理书签分支完成

This commit is contained in:
GaLi 2026-03-01 16:23:56 +08:00
parent b87b74929e
commit 8f4a735e43
2 changed files with 116 additions and 6 deletions

View File

@ -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) {

View File

@ -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<ITypedIngredient<?>> ingredientOpt = bookmarkOverlay.getIngredientUnderMouse();