配方书签功能移植
This commit is contained in:
parent
88370db511
commit
b5ac0b6fbe
|
|
@ -123,6 +123,10 @@ public final class CtrlQPatternKeyHandler {
|
||||||
try {
|
try {
|
||||||
ResourceLocation recipeId = getRecipeId(recipeBookmark);
|
ResourceLocation recipeId = getRecipeId(recipeBookmark);
|
||||||
if (recipeId == null) {
|
if (recipeId == null) {
|
||||||
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
if (mc.player != null) {
|
||||||
|
mc.player.displayClientMessage(Component.translatable("message.extendedae_plus.recipe_not_found"), true);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,6 +168,10 @@ public final class CtrlQPatternKeyHandler {
|
||||||
try {
|
try {
|
||||||
ResourceLocation recipeId = getRecipeId(recipeBookmark);
|
ResourceLocation recipeId = getRecipeId(recipeBookmark);
|
||||||
if (recipeId == null) {
|
if (recipeId == null) {
|
||||||
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
if (mc.player != null) {
|
||||||
|
mc.player.displayClientMessage(Component.translatable("message.extendedae_plus.recipe_not_found"), true);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,6 +228,18 @@ public final class CtrlQPatternKeyHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var getDisplayIngredientMethod = recipeBookmark.getClass().getMethod("getDisplayIngredient");
|
||||||
|
Object displayIngredient = getDisplayIngredientMethod.invoke(recipeBookmark);
|
||||||
|
if (displayIngredient instanceof ITypedIngredient<?> typed) {
|
||||||
|
List<RecipeInfo> infos = RecipeFinderUtil.findRecipesByIngredient(typed);
|
||||||
|
if (!infos.isEmpty()) {
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var getRecipeOutputMethod = recipeBookmark.getClass().getMethod("getRecipeOutput");
|
var getRecipeOutputMethod = recipeBookmark.getClass().getMethod("getRecipeOutput");
|
||||||
Object recipeOutput = getRecipeOutputMethod.invoke(recipeBookmark);
|
Object recipeOutput = getRecipeOutputMethod.invoke(recipeBookmark);
|
||||||
|
|
@ -241,6 +261,11 @@ public final class CtrlQPatternKeyHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ResourceLocation getRecipeId(Object recipeBookmark) {
|
private static ResourceLocation getRecipeId(Object recipeBookmark) {
|
||||||
|
if (recipeBookmark == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// JEI 1.20 兼容分支
|
||||||
try {
|
try {
|
||||||
var getRecipeUidMethod = recipeBookmark.getClass().getMethod("getRecipeUid");
|
var getRecipeUidMethod = recipeBookmark.getClass().getMethod("getRecipeUid");
|
||||||
Object recipeId = getRecipeUidMethod.invoke(recipeBookmark);
|
Object recipeId = getRecipeUidMethod.invoke(recipeBookmark);
|
||||||
|
|
@ -249,6 +274,43 @@ public final class CtrlQPatternKeyHandler {
|
||||||
}
|
}
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JEI 1.21+:从 recipeCategory.getRegistryName(recipe) 获取
|
||||||
|
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 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 ResourceLocation rl) {
|
||||||
|
return rl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 反射字段兜底(JEI 内部 RecipeBookmark 存在 recipeUid 字段)
|
||||||
|
try {
|
||||||
|
var f = recipeBookmark.getClass().getDeclaredField("recipeUid");
|
||||||
|
f.setAccessible(true);
|
||||||
|
Object recipeId = f.get(recipeBookmark);
|
||||||
|
if (recipeId instanceof ResourceLocation rl) {
|
||||||
|
return rl;
|
||||||
|
}
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,4 +378,3 @@ public final class CtrlQPatternKeyHandler {
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,32 @@ public final class JeiRuntimeProxy {
|
||||||
Object overlay = rt.getClass().getMethod("getBookmarkOverlay").invoke(rt);
|
Object overlay = rt.getClass().getMethod("getBookmarkOverlay").invoke(rt);
|
||||||
if (overlay == null) return Optional.empty();
|
if (overlay == null) return Optional.empty();
|
||||||
|
|
||||||
|
// JEI 1.21 优先路径:直接拿鼠标下 clickable element 的 bookmark
|
||||||
|
try {
|
||||||
|
double mouseX = getGuiMouseX();
|
||||||
|
double mouseY = getGuiMouseY();
|
||||||
|
Object clickableStream = overlay.getClass()
|
||||||
|
.getMethod("getIngredientUnderMouse", double.class, double.class)
|
||||||
|
.invoke(overlay, mouseX, mouseY);
|
||||||
|
if (clickableStream instanceof java.util.stream.Stream<?> stream) {
|
||||||
|
Object firstClickable = stream.findFirst().orElse(null);
|
||||||
|
if (firstClickable != null) {
|
||||||
|
Object element = firstClickable.getClass().getMethod("getElement").invoke(firstClickable);
|
||||||
|
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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兼容回退:基于 typed ingredient 匹配 bookmarkList 元素
|
||||||
Object ingredientOpt = overlay.getClass().getMethod("getIngredientUnderMouse").invoke(overlay);
|
Object ingredientOpt = overlay.getClass().getMethod("getIngredientUnderMouse").invoke(overlay);
|
||||||
if (!(ingredientOpt instanceof Optional<?> opt) || opt.isEmpty()) return Optional.empty();
|
if (!(ingredientOpt instanceof Optional<?> opt) || opt.isEmpty()) return Optional.empty();
|
||||||
Object hoveredIngredient = opt.get();
|
Object hoveredIngredient = opt.get();
|
||||||
|
|
@ -189,6 +215,40 @@ public final class JeiRuntimeProxy {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static double getGuiMouseX() {
|
||||||
|
try {
|
||||||
|
Class<?> mcCls = Class.forName("net.minecraft.client.Minecraft");
|
||||||
|
Object mc = mcCls.getMethod("getInstance").invoke(null);
|
||||||
|
Object mouseHandler = mcCls.getField("mouseHandler").get(mc);
|
||||||
|
Object window = mcCls.getMethod("getWindow").invoke(mc);
|
||||||
|
|
||||||
|
double xpos = (double) mouseHandler.getClass().getMethod("xpos").invoke(mouseHandler);
|
||||||
|
int guiW = (int) window.getClass().getMethod("getGuiScaledWidth").invoke(window);
|
||||||
|
int screenW = (int) window.getClass().getMethod("getScreenWidth").invoke(window);
|
||||||
|
if (screenW <= 0) return xpos;
|
||||||
|
return xpos * ((double) guiW / (double) screenW);
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
return 0.0D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double getGuiMouseY() {
|
||||||
|
try {
|
||||||
|
Class<?> mcCls = Class.forName("net.minecraft.client.Minecraft");
|
||||||
|
Object mc = mcCls.getMethod("getInstance").invoke(null);
|
||||||
|
Object mouseHandler = mcCls.getField("mouseHandler").get(mc);
|
||||||
|
Object window = mcCls.getMethod("getWindow").invoke(mc);
|
||||||
|
|
||||||
|
double ypos = (double) mouseHandler.getClass().getMethod("ypos").invoke(mouseHandler);
|
||||||
|
int guiH = (int) window.getClass().getMethod("getGuiScaledHeight").invoke(window);
|
||||||
|
int screenH = (int) window.getClass().getMethod("getScreenHeight").invoke(window);
|
||||||
|
if (screenH <= 0) return ypos;
|
||||||
|
return ypos * ((double) guiH / (double) screenH);
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
return 0.0D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void addBookmark(ItemStack stack) {
|
public static void addBookmark(ItemStack stack) {
|
||||||
Object rt = RUNTIME;
|
Object rt = RUNTIME;
|
||||||
if (rt == null || stack == null || stack.isEmpty()) return;
|
if (rt == null || stack == null || stack.isEmpty()) return;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user