From 61cff67716453f32efb71bbd237aa3e83e940147 Mon Sep 17 00:00:00 2001 From: GaLicn <3096147684@qq.com> Date: Sat, 16 Aug 2025 03:16:49 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0gtceu=E7=9A=84=E5=8F=8D?= =?UTF-8?q?=E5=B0=84=E8=8E=B7=E5=8F=96=E9=85=8D=E6=96=B9=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/ui/ProviderSelectScreen.java | 17 +++- .../EncodePatternTransferHandlerMixin.java | 27 +++++- .../util/ExtendedAEPatternUploadUtil.java | 85 ++++++++++++++++++- 3 files changed, 121 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/extendedae_plus/client/ui/ProviderSelectScreen.java b/src/main/java/com/extendedae_plus/client/ui/ProviderSelectScreen.java index 53e3c07..3ab550a 100644 --- a/src/main/java/com/extendedae_plus/client/ui/ProviderSelectScreen.java +++ b/src/main/java/com/extendedae_plus/client/ui/ProviderSelectScreen.java @@ -9,6 +9,7 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import java.util.ArrayList; +import java.util.Objects; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -84,6 +85,8 @@ public class ProviderSelectScreen extends Screen { } searchBox.setValue(query); searchBox.setResponder(text -> { + // 只有当输入真正发生变化时,才重置页码与过滤 + if (Objects.equals(text, query)) return; query = text; page = 0; applyFilter(); @@ -132,9 +135,10 @@ public class ProviderSelectScreen extends Screen { private void changePage(int delta) { int newPage = page + delta; if (newPage < 0) return; - if (newPage * PAGE_SIZE >= Math.max(1, fIds.size())) return; + if (newPage * PAGE_SIZE >= fIds.size()) return; page = newPage; - init(); + // 避免在回调中直接重建 UI,改为下帧刷新 + needsRefresh = true; } private String buildLabel(int idx) { @@ -210,6 +214,15 @@ public class ProviderSelectScreen extends Screen { fCount.add(gCount.get(i)); } } + // 若查询不为空但没有任何匹配,则回退为显示全部,避免“空列表”误导用户 + if (!q.isEmpty() && fIds.isEmpty()) { + for (int i = 0; i < gIds.size(); i++) { + fIds.add(gIds.get(i)); + fNames.add(gNames.get(i)); + fTotalSlots.add(gTotalSlots.get(i)); + fCount.add(gCount.get(i)); + } + } } // 优先使用 JEC 的拼音匹配,否则回退到大小写不敏感子串匹配 diff --git a/src/main/java/com/extendedae_plus/mixin/jei/EncodePatternTransferHandlerMixin.java b/src/main/java/com/extendedae_plus/mixin/jei/EncodePatternTransferHandlerMixin.java index cd57956..ce242f1 100644 --- a/src/main/java/com/extendedae_plus/mixin/jei/EncodePatternTransferHandlerMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/jei/EncodePatternTransferHandlerMixin.java @@ -28,10 +28,29 @@ public abstract class EncodePatternTransferHandlerMixin { boolean doTransfer, CallbackInfoReturnable cir) { if (!doTransfer) return; - if (!(recipeBase instanceof Recipe recipe)) return; - // 仅记录处理配方(非 3x3 合成) - if (EncodingHelper.isSupportedCraftingRecipe(recipe)) return; - String name = ExtendedAEPatternUploadUtil.mapRecipeTypeToCn(recipe); + String name = null; + if (recipeBase instanceof Recipe recipe) { + // 仅记录处理配方(非 3x3 合成) + if (EncodingHelper.isSupportedCraftingRecipe(recipe)) return; + name = ExtendedAEPatternUploadUtil.mapRecipeTypeToSearchKey(recipe); + } else if (recipeBase instanceof com.gregtechceu.gtceu.api.recipe.GTRecipe gtRecipe) { + // GTCEu 专用:从 GTRecipeType 提取注册ID并映射为中文或path + name = ExtendedAEPatternUploadUtil.mapGTCEuRecipeToSearchKey(gtRecipe); + } else if ("com.gregtechceu.gtceu.integration.jei.recipe.GTRecipeWrapper".equals(recipeBase.getClass().getName())) { + // 通过反射处理 GTCEu JEI 包装类,避免硬依赖 + try { + var field = recipeBase.getClass().getField("recipe"); // public final GTRecipe recipe; + Object inner = field.get(recipeBase); + if (inner instanceof com.gregtechceu.gtceu.api.recipe.GTRecipe gtRecipeInner) { + name = ExtendedAEPatternUploadUtil.mapGTCEuRecipeToSearchKey(gtRecipeInner); + } + } catch (Throwable ignored) { + // 反射失败则继续走通用回退 + } + } else { + // 非原版 Recipe 的 JEI 条目,尝试从类名/包名推导关键词 + name = ExtendedAEPatternUploadUtil.deriveSearchKeyFromUnknownRecipe(recipeBase); + } if (name != null && !name.isBlank()) { ExtendedAEPatternUploadUtil.setLastProcessingName(name); } diff --git a/src/main/java/com/extendedae_plus/util/ExtendedAEPatternUploadUtil.java b/src/main/java/com/extendedae_plus/util/ExtendedAEPatternUploadUtil.java index 96286bb..b13969e 100644 --- a/src/main/java/com/extendedae_plus/util/ExtendedAEPatternUploadUtil.java +++ b/src/main/java/com/extendedae_plus/util/ExtendedAEPatternUploadUtil.java @@ -138,11 +138,92 @@ public class ExtendedAEPatternUploadUtil { case "campfire_cooking": return "营火"; default: - // 其他模组类型,返回路径名,必要时可再做表扩展 - return path; + // 其他模组类型,若未配置中文则返回原始ID(namespace:path)作为英文回退 + return id; } } + /** + * 供搜索使用的关键字映射: + * - 有中文映射则返回中文; + * - 否则返回配方类型的 path(不含命名空间),例如 assembler。 + */ + public static String mapRecipeTypeToSearchKey(Recipe recipe) { + if (recipe == null) return null; + RecipeType type = recipe.getType(); + ResourceLocation key = BuiltInRegistries.RECIPE_TYPE.getKey(type); + if (key == null) return null; + String custom = CUSTOM_NAMES.get(key); + if (custom != null && !custom.isBlank()) { + return custom; + } + return key.getPath(); + } + + /** + * GTCEu 的 GTRecipe -> 搜索关键字 + * 优先自定义中文映射;其次使用注册ID的 path;最后回退到完整ID字符串。 + */ + public static String mapGTCEuRecipeToSearchKey(com.gregtechceu.gtceu.api.recipe.GTRecipe gtRecipe) { + if (gtRecipe == null) return null; + try { + // GTRecipeType.toString() 返回 registryName.toString() 即 namespace:path + String idStr = String.valueOf(gtRecipe.getType()); + if (idStr == null || idStr.isBlank()) return null; + ResourceLocation rl = new ResourceLocation(idStr); + // 1) 配置优先 + String custom = CUSTOM_NAMES.get(rl); + if (custom != null && !custom.isBlank()) return custom; + // 2) 返回 path 作为搜索关键字 + String path = rl.getPath(); + return (path != null && !path.isBlank()) ? path : idStr; + } catch (Throwable t) { + return null; + } + } + + /** + * 当 JEI 传入的 recipeBase 不是原版 Recipe 时,根据类的包名/类名推导一个尽量可用的搜索关键字。 + * 例如:"moe.gregtech.recipe.SomeAssemblerRecipe" -> "gtceu assembler" + */ + public static String deriveSearchKeyFromUnknownRecipe(Object recipeBase) { + if (recipeBase == null) return null; + try { + Class cls = recipeBase.getClass(); + String simple = cls.getSimpleName(); + String pkg = cls.getName(); + + String ns = null; + String lower = pkg.toLowerCase(); + if (lower.contains("gtceu")) ns = "gtceu"; + else if (lower.contains("gregtech")) ns = "gregtech"; + else if (lower.contains("projecte")) ns = "projecte"; + else if (lower.contains("create")) ns = "create"; + else if (lower.contains("immersiveengineering")) ns = "immersive"; + + String token = toSearchToken(simple); + if (ns != null && token != null && !token.isBlank()) return ns + " " + token; + return token != null && !token.isBlank() ? token : ns; + } catch (Throwable ignored) { + return null; + } + } + + private static String toSearchToken(String simpleName) { + if (simpleName == null || simpleName.isBlank()) return null; + // 去掉常见后缀 + String s = simpleName + .replaceAll("Recipe$", "") + .replaceAll("Recipes$", "") + .replaceAll("Category$", "") + .replaceAll("JEI$", ""); + // 驼峰转空格并小写 + s = s.replaceAll("(?