供应器搜索结果唯一时直接上传样板

This commit is contained in:
GaLi 2026-03-25 14:18:58 +08:00
parent 6877145bbb
commit 8d6dc8ef9c
5 changed files with 75 additions and 12 deletions

View File

@ -78,6 +78,10 @@ public class ProviderSelectScreen extends Screen {
// 缓存 Component JSON 解析 // 缓存 Component JSON 解析
private static final Map<String, String> componentCache = new HashMap<>(); private static final Map<String, String> componentCache = new HashMap<>();
private String lastLanguage = ""; // 当前语言版本 private String lastLanguage = ""; // 当前语言版本
private boolean autoUploadRequestedFromProcessingName = false;
private boolean autoUploadAttempted = false;
private int lastExactMatchCount = 0;
private boolean lastFilterUsedFallback = false;
public ProviderSelectScreen(Screen parent, List<Long> ids, List<String> names, List<Integer> emptySlots) { public ProviderSelectScreen(Screen parent, List<Long> ids, List<String> names, List<Integer> emptySlots) {
super(Component.translatable("extendedae_plus.screen.choose_provider.title")); super(Component.translatable("extendedae_plus.screen.choose_provider.title"));
@ -90,6 +94,7 @@ public class ProviderSelectScreen extends Screen {
String recent = RecipeTypeNameConfig.lastProcessingName; String recent = RecipeTypeNameConfig.lastProcessingName;
if (recent != null && !recent.isBlank()) { if (recent != null && !recent.isBlank()) {
this.query = recent; this.query = recent;
this.autoUploadRequestedFromProcessingName = true;
// 用后即清空避免污染下次 // 用后即清空避免污染下次
RecipeTypeNameConfig.lastProcessingName = null; RecipeTypeNameConfig.lastProcessingName = null;
} }
@ -200,6 +205,7 @@ public class ProviderSelectScreen extends Screen {
this.addRenderableWidget(delByCn); this.addRenderableWidget(delByCn);
refreshButtons(); // 初始化完成后刷新按钮状态 refreshButtons(); // 初始化完成后刷新按钮状态
tryAutoUploadIfUniqueMatch();
} }
private void changePage(int delta) { private void changePage(int delta) {
@ -273,9 +279,14 @@ public class ProviderSelectScreen extends Screen {
} }
private void onChoose(int idx) { private void onChoose(int idx) {
onChoose(idx, false);
}
private void onChoose(int idx, boolean showStatusMessage) {
if (idx < 0 || idx >= fIds.size()) return; if (idx < 0 || idx >= fIds.size()) return;
long providerId = fIds.get(idx); long providerId = fIds.get(idx);
ModNetwork.CHANNEL.sendToServer(new UploadEncodedPatternToProviderC2SPacket(providerId)); String providerName = fNames.get(idx);
ModNetwork.CHANNEL.sendToServer(new UploadEncodedPatternToProviderC2SPacket(providerId, showStatusMessage, providerName));
this.onClose(); this.onClose();
} }
@ -323,6 +334,8 @@ public class ProviderSelectScreen extends Screen {
fNames.clear(); fNames.clear();
fTotalSlots.clear(); fTotalSlots.clear();
fCount.clear(); fCount.clear();
lastExactMatchCount = 0;
lastFilterUsedFallback = false;
String q = query == null ? "" : query.trim(); String q = query == null ? "" : query.trim();
String qLower = q.toLowerCase(Locale.ROOT); String qLower = q.toLowerCase(Locale.ROOT);
@ -333,10 +346,12 @@ public class ProviderSelectScreen extends Screen {
fNames.add(name); fNames.add(name);
fTotalSlots.add(gTotalSlots.get(i)); fTotalSlots.add(gTotalSlots.get(i));
fCount.add(gCount.get(i)); fCount.add(gCount.get(i));
lastExactMatchCount++;
} }
} }
// 若查询不为空但没有任何匹配则回退为显示全部避免空列表误导用户 // 若查询不为空但没有任何匹配则回退为显示全部避免空列表误导用户
if (!q.isEmpty() && fIds.isEmpty()) { if (!q.isEmpty() && fIds.isEmpty()) {
lastFilterUsedFallback = true;
for (int i = 0; i < gIds.size(); i++) { for (int i = 0; i < gIds.size(); i++) {
fIds.add(gIds.get(i)); fIds.add(gIds.get(i));
fNames.add(gNames.get(i)); fNames.add(gNames.get(i));
@ -385,6 +400,17 @@ public class ProviderSelectScreen extends Screen {
fCount.addAll(sortedCount); fCount.addAll(sortedCount);
} }
private void tryAutoUploadIfUniqueMatch() {
if (!autoUploadRequestedFromProcessingName || autoUploadAttempted) {
return;
}
autoUploadAttempted = true;
if (query == null || query.isBlank() || lastFilterUsedFallback || lastExactMatchCount != 1 || fIds.size() != 1) {
return;
}
onChoose(0, true);
}
// 优先使用 JEC 的拼音匹配否则回退到大小写不敏感子串匹配 // 优先使用 JEC 的拼音匹配否则回退到大小写不敏感子串匹配
private static Boolean JEC_AVAILABLE = null; private static Boolean JEC_AVAILABLE = null;
private static java.lang.reflect.Method JEC_CONTAINS = null; private static java.lang.reflect.Method JEC_CONTAINS = null;

View File

@ -3,6 +3,7 @@ package com.extendedae_plus.network;
import appeng.menu.me.items.PatternEncodingTermMenu; import appeng.menu.me.items.PatternEncodingTermMenu;
import com.extendedae_plus.util.uploadPattern.ProviderUploadUtil; import com.extendedae_plus.util.uploadPattern.ProviderUploadUtil;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
@ -13,17 +14,27 @@ import java.util.function.Supplier;
*/ */
public class UploadEncodedPatternToProviderC2SPacket { public class UploadEncodedPatternToProviderC2SPacket {
private final long providerId; private final long providerId;
private final boolean showStatusMessage;
private final String providerName;
public UploadEncodedPatternToProviderC2SPacket(long providerId) { public UploadEncodedPatternToProviderC2SPacket(long providerId) {
this(providerId, false, "");
}
public UploadEncodedPatternToProviderC2SPacket(long providerId, boolean showStatusMessage, String providerName) {
this.providerId = providerId; this.providerId = providerId;
this.showStatusMessage = showStatusMessage;
this.providerName = providerName == null ? "" : providerName;
} }
public static void encode(UploadEncodedPatternToProviderC2SPacket msg, FriendlyByteBuf buf) { public static void encode(UploadEncodedPatternToProviderC2SPacket msg, FriendlyByteBuf buf) {
buf.writeLong(msg.providerId); buf.writeLong(msg.providerId);
buf.writeBoolean(msg.showStatusMessage);
buf.writeUtf(msg.providerName, 256);
} }
public static UploadEncodedPatternToProviderC2SPacket decode(FriendlyByteBuf buf) { public static UploadEncodedPatternToProviderC2SPacket decode(FriendlyByteBuf buf) {
return new UploadEncodedPatternToProviderC2SPacket(buf.readLong()); return new UploadEncodedPatternToProviderC2SPacket(buf.readLong(), buf.readBoolean(), buf.readUtf(256));
} }
public static void handle(UploadEncodedPatternToProviderC2SPacket msg, Supplier<NetworkEvent.Context> ctxSupplier) { public static void handle(UploadEncodedPatternToProviderC2SPacket msg, Supplier<NetworkEvent.Context> ctxSupplier) {
@ -32,23 +43,43 @@ public class UploadEncodedPatternToProviderC2SPacket {
ServerPlayer player = ctx.getSender(); ServerPlayer player = ctx.getSender();
if (player == null) return; if (player == null) return;
boolean uploaded = false;
if (ProviderUploadUtil.hasPendingCtrlQPattern(player)) { if (ProviderUploadUtil.hasPendingCtrlQPattern(player)) {
if (ProviderUploadUtil.uploadPendingCtrlQPattern(player, msg.providerId)) { uploaded = ProviderUploadUtil.uploadPendingCtrlQPattern(player, msg.providerId);
return; if (!uploaded) {
ProviderUploadUtil.returnPendingCtrlQPatternToInventory(player);
} }
ProviderUploadUtil.returnPendingCtrlQPatternToInventory(player); sendAutoUploadStatus(player, msg, uploaded);
return; return;
} }
if (player.containerMenu instanceof PatternEncodingTermMenu menu) { if (player.containerMenu instanceof PatternEncodingTermMenu menu) {
if (msg.providerId >= 0) { if (msg.providerId >= 0) {
ProviderUploadUtil.uploadFromEncodingMenuToProvider(player, menu, msg.providerId); uploaded = ProviderUploadUtil.uploadFromEncodingMenuToProvider(player, menu, msg.providerId);
} else { } else {
int index = (int) (-1L - msg.providerId); int index = (int) (-1L - msg.providerId);
ProviderUploadUtil.uploadFromEncodingMenuToProviderByIndex(player, menu, index); uploaded = ProviderUploadUtil.uploadFromEncodingMenuToProviderByIndex(player, menu, index);
} }
} }
sendAutoUploadStatus(player, msg, uploaded);
}); });
ctx.setPacketHandled(true); ctx.setPacketHandled(true);
} }
private static void sendAutoUploadStatus(ServerPlayer player, UploadEncodedPatternToProviderC2SPacket msg, boolean uploaded) {
if (player == null || !msg.showStatusMessage) {
return;
}
String providerDisplayName = msg.providerName == null || msg.providerName.isBlank()
? "#" + msg.providerId
: msg.providerName;
player.sendSystemMessage(Component.translatable(
uploaded
? "extendedae_plus.screen.upload.auto_upload_success"
: "extendedae_plus.screen.upload.auto_upload_failed",
providerDisplayName
));
}
} }

View File

@ -125,6 +125,8 @@
"extendedae_plus.screen.upload.select_provider_first":"Please click the button on the left to select a pattern provider first", "extendedae_plus.screen.upload.select_provider_first":"Please click the button on the left to select a pattern provider first",
"extendedae_plus.screen.upload.invalid_pattern": "Invalid Pattern", "extendedae_plus.screen.upload.invalid_pattern": "Invalid Pattern",
"extendedae_plus.screen.upload.no_network_support": "ExtendedAE network support not found (may be missing or incompatible version)", "extendedae_plus.screen.upload.no_network_support": "ExtendedAE network support not found (may be missing or incompatible version)",
"extendedae_plus.screen.upload.auto_upload_success": "Automatically uploaded to the only matching pattern provider: %s",
"extendedae_plus.screen.upload.auto_upload_failed": "Automatic upload to the pattern provider failed: %s",
"extendedae_plus.screen.open_provider_ui": "Open the target container UI of this provider", "extendedae_plus.screen.open_provider_ui": "Open the target container UI of this provider",
"extendedae_plus.button.choose_provider": "Upload Pattern", "extendedae_plus.button.choose_provider": "Upload Pattern",

View File

@ -124,6 +124,8 @@
"extendedae_plus.screen.upload.select_provider_first": "请先点击左侧按钮选择一个样板供应器", "extendedae_plus.screen.upload.select_provider_first": "请先点击左侧按钮选择一个样板供应器",
"extendedae_plus.screen.upload.invalid_pattern": "无效样板", "extendedae_plus.screen.upload.invalid_pattern": "无效样板",
"extendedae_plus.screen.upload.no_network_support": "未找到 ExtendedAE 网络支持(可能未安装或版本不兼容)", "extendedae_plus.screen.upload.no_network_support": "未找到 ExtendedAE 网络支持(可能未安装或版本不兼容)",
"extendedae_plus.screen.upload.auto_upload_success": "已自动上传到唯一匹配的样板供应器:%s",
"extendedae_plus.screen.upload.auto_upload_failed": "自动上传到样板供应器失败:%s",
"extendedae_plus.screen.open_provider_ui": "打开该供应器目标容器的界面", "extendedae_plus.screen.open_provider_ui": "打开该供应器目标容器的界面",
"extendedae_plus.button.choose_provider":"上传样板", "extendedae_plus.button.choose_provider":"上传样板",

View File

@ -123,6 +123,8 @@
"extendedae_plus.screen.upload.select_provider_first": "請先點選左側按鈕選擇一個樣板供應器", "extendedae_plus.screen.upload.select_provider_first": "請先點選左側按鈕選擇一個樣板供應器",
"extendedae_plus.screen.upload.invalid_pattern": "無效樣板", "extendedae_plus.screen.upload.invalid_pattern": "無效樣板",
"extendedae_plus.screen.upload.no_network_support": "未找到 ExtendedAE 網路支援(可能未安裝或版本不相容)", "extendedae_plus.screen.upload.no_network_support": "未找到 ExtendedAE 網路支援(可能未安裝或版本不相容)",
"extendedae_plus.screen.upload.auto_upload_success": "已自動上傳到唯一匹配的樣板供應器:%s",
"extendedae_plus.screen.upload.auto_upload_failed": "自動上傳到樣板供應器失敗:%s",
"extendedae_plus.screen.open_provider_ui": "開啟該供應器目標容器的介面", "extendedae_plus.screen.open_provider_ui": "開啟該供應器目標容器的介面",
"extendedae_plus.button.choose_provider": "上傳樣板", "extendedae_plus.button.choose_provider": "上傳樣板",