添加gtceu的反射获取配方方法名

This commit is contained in:
GaLicn 2025-08-16 03:16:49 +08:00
parent bb32277fa5
commit 61cff67716
3 changed files with 121 additions and 8 deletions

View File

@ -9,6 +9,7 @@ import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -84,6 +85,8 @@ public class ProviderSelectScreen extends Screen {
} }
searchBox.setValue(query); searchBox.setValue(query);
searchBox.setResponder(text -> { searchBox.setResponder(text -> {
// 只有当输入真正发生变化时才重置页码与过滤
if (Objects.equals(text, query)) return;
query = text; query = text;
page = 0; page = 0;
applyFilter(); applyFilter();
@ -132,9 +135,10 @@ public class ProviderSelectScreen extends Screen {
private void changePage(int delta) { private void changePage(int delta) {
int newPage = page + delta; int newPage = page + delta;
if (newPage < 0) return; if (newPage < 0) return;
if (newPage * PAGE_SIZE >= Math.max(1, fIds.size())) return; if (newPage * PAGE_SIZE >= fIds.size()) return;
page = newPage; page = newPage;
init(); // 避免在回调中直接重建 UI改为下帧刷新
needsRefresh = true;
} }
private String buildLabel(int idx) { private String buildLabel(int idx) {
@ -210,6 +214,15 @@ public class ProviderSelectScreen extends Screen {
fCount.add(gCount.get(i)); 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 的拼音匹配否则回退到大小写不敏感子串匹配 // 优先使用 JEC 的拼音匹配否则回退到大小写不敏感子串匹配

View File

@ -28,10 +28,29 @@ public abstract class EncodePatternTransferHandlerMixin {
boolean doTransfer, boolean doTransfer,
CallbackInfoReturnable<IRecipeTransferError> cir) { CallbackInfoReturnable<IRecipeTransferError> cir) {
if (!doTransfer) return; if (!doTransfer) return;
if (!(recipeBase instanceof Recipe<?> recipe)) return; String name = null;
// 仅记录处理配方 3x3 合成 if (recipeBase instanceof Recipe<?> recipe) {
if (EncodingHelper.isSupportedCraftingRecipe(recipe)) return; // 仅记录处理配方 3x3 合成
String name = ExtendedAEPatternUploadUtil.mapRecipeTypeToCn(recipe); 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()) { if (name != null && !name.isBlank()) {
ExtendedAEPatternUploadUtil.setLastProcessingName(name); ExtendedAEPatternUploadUtil.setLastProcessingName(name);
} }

View File

@ -138,11 +138,92 @@ public class ExtendedAEPatternUploadUtil {
case "campfire_cooking": case "campfire_cooking":
return "营火"; return "营火";
default: default:
// 其他模组类型返回路径名必要时可再做表扩展 // 其他模组类型若未配置中文则返回原始IDnamespace:path作为英文回退
return 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("(?<!^)([A-Z])", " $1").toLowerCase();
// 取首个关键词
s = s.trim();
return s;
}
/** /**
* 获取玩家当前的样板访问终端菜单支持ExtendedAE和原版AE2 * 获取玩家当前的样板访问终端菜单支持ExtendedAE和原版AE2
* *