优化 ProviderSelectScreen:按钮池化、缓存 Component JSON、封装 Group、搜索/翻页只刷新按钮及添加翻译键

This commit is contained in:
C-H716 2025-10-23 22:49:49 +08:00
parent f04c6297f9
commit a22b932b0c
9 changed files with 137 additions and 102 deletions

View File

@ -6,8 +6,7 @@ import net.minecraft.server.level.ServerLevel;
/** /**
* 无线端点最小接口 * 无线端点最小接口
* 你的无线收发器方块实体需实现该接口 * 无线收发器方块实体需实现该接口以便无线逻辑能够获取世界位置与 AE2 节点
* 以便无线逻辑能够获取世界位置与 AE2 节点
*/ */
public interface IWirelessEndpoint { public interface IWirelessEndpoint {
/** 返回方块所在的服务端世界(避免与 BlockEntity#getLevel 冲突) */ /** 返回方块所在的服务端世界(避免与 BlockEntity#getLevel 冲突) */

View File

@ -1,12 +0,0 @@
package com.extendedae_plus.api.bridge;
import appeng.api.upgrades.IUpgradeInventory;
import appeng.menu.ToolboxMenu;
public interface IUpgradableMenu {
ToolboxMenu getToolbox();
IUpgradeInventory getUpgrades();
default boolean hasUpgrade(net.minecraft.world.level.ItemLike upgradeCard) {
return getUpgrades().isInstalled(upgradeCard);
}
}

View File

@ -1,8 +1,8 @@
package com.extendedae_plus.client.ui; package com.extendedae_plus.client.screen;
import com.extendedae_plus.init.ModNetwork; import com.extendedae_plus.init.ModNetwork;
import com.extendedae_plus.network.SetWirelessFrequencyC2SPacket; import com.extendedae_plus.network.SetWirelessFrequencyC2SPacket;
import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
@ -83,7 +83,7 @@ public class FrequencyInputScreen extends Screen {
} }
@Override @Override
public void render(net.minecraft.client.gui.GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) { public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(guiGraphics); this.renderBackground(guiGraphics);
super.render(guiGraphics, mouseX, mouseY, partialTicks); super.render(guiGraphics, mouseX, mouseY, partialTicks);

View File

@ -3,13 +3,14 @@ package com.extendedae_plus.client.screen;
import com.extendedae_plus.init.ModNetwork; import com.extendedae_plus.init.ModNetwork;
import com.extendedae_plus.menu.NetworkPatternControllerMenu; import com.extendedae_plus.menu.NetworkPatternControllerMenu;
import com.extendedae_plus.network.provider.GlobalToggleProviderModesC2SPacket; import com.extendedae_plus.network.provider.GlobalToggleProviderModesC2SPacket;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
public class GlobalProviderModesScreen extends AbstractContainerScreen<NetworkPatternControllerMenu> { public class GlobalProviderModesScreen extends AbstractContainerScreen<NetworkPatternControllerMenu> {
private static final Component CUSTOM_TITLE = Component.literal("样板供应器状态控制器"); private static final Component CUSTOM_TITLE = Component.translatable("block.extendedae_plus.network_pattern_controller");
public GlobalProviderModesScreen(NetworkPatternControllerMenu menu, Inventory inv, Component title) { public GlobalProviderModesScreen(NetworkPatternControllerMenu menu, Inventory inv, Component title) {
super(menu, inv, title); super(menu, inv, title);
this.imageWidth = 240; this.imageWidth = 240;
@ -75,7 +76,7 @@ public class GlobalProviderModesScreen extends AbstractContainerScreen<NetworkPa
} }
@Override @Override
protected void renderBg(net.minecraft.client.gui.GuiGraphics gfx, float partialTicks, int mouseX, int mouseY) { protected void renderBg(GuiGraphics gfx, float partialTicks, int mouseX, int mouseY) {
// 半透明全屏遮罩避免底层 HUD准星/物品栏文字透出 // 半透明全屏遮罩避免底层 HUD准星/物品栏文字透出
gfx.fill(0, 0, this.width, this.height, 0xC0000000); gfx.fill(0, 0, this.width, this.height, 0xC0000000);
@ -88,20 +89,20 @@ public class GlobalProviderModesScreen extends AbstractContainerScreen<NetworkPa
gfx.fill(panelLeft, panelTop, panelRight, panelBottom, 0xA01E1E1E); gfx.fill(panelLeft, panelTop, panelRight, panelBottom, 0xA01E1E1E);
// 边框 // 边框
gfx.fill(panelLeft, panelTop, panelRight, panelTop + 1, 0x80FFFFFF); gfx.fill(panelLeft, panelTop, panelRight, panelTop + 1, 0x80FFFFFF);
gfx.fill(panelLeft, panelBottom - 1, panelRight, panelBottom, 0x80000000); gfx.fill(panelLeft, panelBottom - 1, panelRight, panelBottom, 0x80FFFFFF);
gfx.fill(panelLeft, panelTop, panelLeft + 1, panelBottom, 0x80FFFFFF); gfx.fill(panelLeft, panelTop, panelLeft + 1, panelBottom, 0x80FFFFFF);
gfx.fill(panelRight - 1, panelTop, panelRight, panelBottom, 0x80000000); gfx.fill(panelRight - 1, panelTop, panelRight, panelBottom, 0x80FFFFFF);
} }
@Override @Override
public void render(net.minecraft.client.gui.GuiGraphics gfx, int mouseX, int mouseY, float partialTicks) { public void render(GuiGraphics gfx, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(gfx); this.renderBackground(gfx);
super.render(gfx, mouseX, mouseY, partialTicks); super.render(gfx, mouseX, mouseY, partialTicks);
gfx.drawString(this.font, CUSTOM_TITLE, this.leftPos + 10, this.topPos + 8, 0xFFFFFF, false); gfx.drawString(this.font, CUSTOM_TITLE, this.leftPos + 10, this.topPos + 8, 0xFFFFFF, false);
} }
@Override @Override
protected void renderLabels(net.minecraft.client.gui.GuiGraphics gfx, int mouseX, int mouseY) { protected void renderLabels(GuiGraphics gfx, int mouseX, int mouseY) {
// 不绘制默认的玩家物品栏标题例如物品栏避免与自定义面板重叠 // 不绘制默认的玩家物品栏标题例如物品栏避免与自定义面板重叠
// 标题已在 render() 中手动绘制 // 标题已在 render() 中手动绘制
} }

View File

@ -1,7 +1,8 @@
package com.extendedae_plus.client.ui; package com.extendedae_plus.client.screen;
import com.extendedae_plus.init.ModNetwork; import com.extendedae_plus.init.ModNetwork;
import com.extendedae_plus.network.UploadEncodedPatternToProviderC2SPacket; import com.extendedae_plus.network.UploadEncodedPatternToProviderC2SPacket;
import com.extendedae_plus.util.ExtendedAEPatternUploadUtil;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.gui.components.EditBox;
@ -22,10 +23,10 @@ public class ProviderSelectScreen extends Screen {
private final List<Integer> emptySlots; private final List<Integer> emptySlots;
// 分组后的数据同名合并 // 分组后的数据同名合并
private final List<Long> gIds = new ArrayList<>(); // 代表条目使用的 providerId选择空位数最多的那个 private final List<Long> gIds = new ArrayList<>(); // 代表条目使用的 providerId选择空位数最多的那个
private final List<String> gNames = new ArrayList<>(); // 分组名供应器名称 private final List<String> gNames = new ArrayList<>(); // 分组名供应器名称
private final List<Integer> gTotalSlots = new ArrayList<>(); // 该名称下供应器空位总和 private final List<Integer> gTotalSlots = new ArrayList<>(); // 该名称下供应器空位总和
private final List<Integer> gCount = new ArrayList<>(); // 该名称下供应器数量 private final List<Integer> gCount = new ArrayList<>(); // 该名称下供应器数量
// 过滤后的数据由查询生成 // 过滤后的数据由查询生成
private final List<Long> fIds = new ArrayList<>(); private final List<Long> fIds = new ArrayList<>();
@ -38,12 +39,19 @@ public class ProviderSelectScreen extends Screen {
// 中文名输入框用于添加映射 // 中文名输入框用于添加映射
private EditBox cnInput; private EditBox cnInput;
private String query = ""; private String query = "";
private boolean needsRefresh = false;
private int page = 0; private int page = 0;
private static final int PAGE_SIZE = 6; private static final int PAGE_SIZE = 6;
// 按钮池
private final List<Button> entryButtons = new ArrayList<>(); private final List<Button> entryButtons = new ArrayList<>();
private final int[] buttonIndexMap = new int[PAGE_SIZE]; // 映射到 fIds 的索引
// 缓存 Component JSON 解析
private static final Map<String, String> componentCache = new HashMap<>();
private Button prevButton;
private Button nextButton;
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"));
@ -53,11 +61,11 @@ public class ProviderSelectScreen extends Screen {
this.emptySlots = emptySlots; this.emptySlots = emptySlots;
// 如果有来自 JEI 的最近处理名称则作为初始查询 // 如果有来自 JEI 的最近处理名称则作为初始查询
try { try {
String recent = com.extendedae_plus.util.ExtendedAEPatternUploadUtil.lastProcessingName; String recent = ExtendedAEPatternUploadUtil.lastProcessingName;
if (recent != null && !recent.isBlank()) { if (recent != null && !recent.isBlank()) {
this.query = recent; this.query = recent;
// 用后即清空避免污染下次 // 用后即清空避免污染下次
com.extendedae_plus.util.ExtendedAEPatternUploadUtil.lastProcessingName = null; ExtendedAEPatternUploadUtil.lastProcessingName = null;
} }
} catch (Throwable ignored) {} } catch (Throwable ignored) {}
buildGroups(); buildGroups();
@ -88,42 +96,40 @@ public class ProviderSelectScreen extends Screen {
query = text; query = text;
page = 0; page = 0;
applyFilter(); applyFilter();
// 避免在回调中直接重建 UI延迟到下一次 tick refreshButtons();
needsRefresh = true;
}); });
this.addRenderableWidget(searchBox); this.addRenderableWidget(searchBox);
int start = page * PAGE_SIZE; // 初始化按钮池
int end = Math.min(start + PAGE_SIZE, fIds.size());
int buttonWidth = 240; int buttonWidth = 240;
int buttonHeight = 20; int buttonHeight = 20;
int gap = 5; int gap = 5;
for (int i = 0; i < PAGE_SIZE; i++) {
for (int i = start; i < end; i++) { int btnIdx = i;
int idx = i; Button btn = Button.builder(Component.literal(""), b -> {
String label = buildLabel(idx); int actualIdx = buttonIndexMap[btnIdx];
Button btn = Button.builder(Component.literal(label), b -> onChoose(idx)) if (actualIdx >= 0 && actualIdx < fIds.size()) {
.bounds(centerX - buttonWidth / 2, startY + (i - start) * (buttonHeight + gap), buttonWidth, buttonHeight) onChoose(actualIdx);
}
}).bounds(centerX - buttonWidth / 2, startY + i * (buttonHeight + gap), buttonWidth, buttonHeight)
.build(); .build();
entryButtons.add(btn); entryButtons.add(btn);
buttonIndexMap[i] = -1; // 初始化为无效索引
this.addRenderableWidget(btn); this.addRenderableWidget(btn);
} }
// 分页按钮 // 分页按钮
int navY = startY + PAGE_SIZE * (buttonHeight + gap) + 10; int navY = startY + PAGE_SIZE * (buttonHeight + gap) + 10;
Button prev = Button.builder(Component.literal("<"), b -> changePage(-1)) prevButton = Button.builder(Component.literal("<"), b -> changePage(-1))
.bounds(centerX - 60, navY, 20, 20) .bounds(centerX - 60, navY, 20, 20)
.build(); .build();
Button next = Button.builder(Component.literal(">"), b -> changePage(1)) nextButton = Button.builder(Component.literal(">"), b -> changePage(1))
.bounds(centerX + 40, navY, 20, 20) .bounds(centerX + 40, navY, 20, 20)
.build(); .build();
prev.active = page > 0; this.addRenderableWidget(prevButton);
next.active = (page + 1) * PAGE_SIZE < fIds.size(); this.addRenderableWidget(nextButton);
this.addRenderableWidget(prev);
this.addRenderableWidget(next);
// 重载映射按钮热重载 recipe_type_names.json移至下一行与关闭按钮并排 // 映射按钮和输入框
Button reload = Button.builder(Component.translatable("extendedae_plus.screen.reload_mapping"), b -> reloadMapping()) Button reload = Button.builder(Component.translatable("extendedae_plus.screen.reload_mapping"), b -> reloadMapping())
.bounds(centerX - 130, navY + 30, 80, 20) .bounds(centerX - 130, navY + 30, 80, 20)
.build(); .build();
@ -141,13 +147,13 @@ public class ProviderSelectScreen extends Screen {
// 增加映射按钮使用当前搜索关键字 -> 中文 // 增加映射按钮使用当前搜索关键字 -> 中文
Button addMap = Button.builder(Component.translatable("extendedae_plus.screen.add_mapping"), b -> addMappingFromUI()) Button addMap = Button.builder(Component.translatable("extendedae_plus.screen.add_mapping"), b -> addMappingFromUI())
.bounds(centerX + 175, navY + 30, 60, 20) .bounds(centerX + 175, navY + 30, 80, 20)
.build(); .build();
this.addRenderableWidget(addMap); this.addRenderableWidget(addMap);
// 删除映射按中文值精确匹配删除按钮 // 删除映射按中文值精确匹配删除按钮
Button delByCn = Button.builder(Component.literal("删除映射"), b -> deleteMappingByCnFromUI()) Button delByCn = Button.builder(Component.translatable("extendedae_plus.screen.delete_mapping"), b -> deleteMappingByCnFromUI())
.bounds(centerX + 240, navY + 30, 60, 20) .bounds(centerX + 240, navY + 30, 80, 20)
.build(); .build();
this.addRenderableWidget(delByCn); this.addRenderableWidget(delByCn);
@ -156,29 +162,50 @@ public class ProviderSelectScreen extends Screen {
.bounds(centerX - 40, navY + 30, 80, 20) .bounds(centerX - 40, navY + 30, 80, 20)
.build(); .build();
this.addRenderableWidget(close); this.addRenderableWidget(close);
refreshButtons(); // 初始化完成后刷新按钮状态
} }
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 || newPage * PAGE_SIZE >= fIds.size()) return;
if (newPage * PAGE_SIZE >= fIds.size()) return;
page = newPage; page = newPage;
// 避免在回调中直接重建 UI改为下帧刷新 refreshButtons();
needsRefresh = true; }
private void refreshButtons() {
int start = page * PAGE_SIZE;
int end = Math.min(start + PAGE_SIZE, fIds.size());
for (int i = 0; i < PAGE_SIZE; i++) {
Button btn = entryButtons.get(i);
int idx = start + i;
if (idx < end) {
btn.visible = true;
btn.active = true;
btn.setMessage(Component.literal(buildLabel(idx)));
buttonIndexMap[i] = idx;
} else {
btn.visible = false;
btn.active = false;
buttonIndexMap[i] = -1;
}
}
if (prevButton != null) prevButton.active = page > 0;
if (nextButton != null) nextButton.active = fIds.size() > (page + 1) * PAGE_SIZE;
} }
private void reloadMapping() { private void reloadMapping() {
try { try {
com.extendedae_plus.util.ExtendedAEPatternUploadUtil.loadRecipeTypeNames(); ExtendedAEPatternUploadUtil.loadRecipeTypeNames();
var player = Minecraft.getInstance().player; var player = Minecraft.getInstance().player;
if (player != null) { if (player != null) {
player.sendSystemMessage(Component.literal("ExtendedAE Plus: 已重载映射表")); player.sendSystemMessage(Component.translatable("extendedae_plus.screen.reload_mapping_success"));
} }
// 重载后不强制刷新筛选但如需立即应用到名称匹配可手动编辑搜索框或翻页 // 重载后不强制刷新筛选但如需立即应用到名称匹配可手动编辑搜索框或翻页
} catch (Throwable t) { } catch (Throwable t) {
var player = Minecraft.getInstance().player; var player = Minecraft.getInstance().player;
if (player != null) { if (player != null) {
player.sendSystemMessage(Component.literal("ExtendedAE Plus: 重载映射表失败: " + t.getClass().getSimpleName())); player.sendSystemMessage(Component.translatable("extendedae_plus.screen.reload_mapping_fail", t.getClass().getSimpleName()));
} }
} }
} }
@ -187,18 +214,20 @@ public class ProviderSelectScreen extends Screen {
* 将服务器发送的名称可能是 Component JSON反序列化为本地化文本 * 将服务器发送的名称可能是 Component JSON反序列化为本地化文本
*/ */
private String deserializeComponentName(String name) { private String deserializeComponentName(String name) {
try { return componentCache.computeIfAbsent(name, k -> {
// 如果名称是 JSON 格式的 Component反序列化后获取本地化文本 try {
if (name.startsWith("{") || name.startsWith("\"")) { // 如果名称是 JSON 格式的 Component反序列化后获取本地化文本
Component component = Component.Serializer.fromJson(name); if (name.startsWith("{") || name.startsWith("\"")) {
if (component != null) { Component component = Component.Serializer.fromJson(name);
return component.getString(); if (component != null) {
return component.getString();
}
} }
} catch (Exception ignored) {
// 如果不是 JSON 或解析失败使用原始字符串
} }
} catch (Exception e) { return name;
// 如果不是 JSON 或解析失败使用原始字符串 });
}
return name;
} }
private String buildLabel(int idx) { private String buildLabel(int idx) {
@ -237,15 +266,13 @@ public class ProviderSelectScreen extends Screen {
// Component JSON 转换为本地化文本用于分组键 // Component JSON 转换为本地化文本用于分组键
String groupKey = deserializeComponentName(name); String groupKey = deserializeComponentName(name);
map.compute(groupKey, (k, g) -> {
Group g = map.computeIfAbsent(groupKey, k -> new Group()); if (g == null) {
g.count++; return new Group(id, slots);
g.totalSlots += Math.max(0, slots); }
// 挑选空位最多的作为代表 id若并列保留先到者 g.merge(id, slots);
if (slots > g.bestSlots) { return g;
g.bestSlots = slots; });
g.bestId = id;
}
} }
for (Map.Entry<String, Group> e : map.entrySet()) { for (Map.Entry<String, Group> e : map.entrySet()) {
String name = e.getKey(); String name = e.getKey();
@ -257,11 +284,29 @@ public class ProviderSelectScreen extends Screen {
} }
} }
private static class Group { private static class Group {
long bestId = Long.MIN_VALUE; long bestId;
int bestSlots = Integer.MIN_VALUE; int bestSlots;
int totalSlots = 0; int totalSlots;
int count = 0; int count;
Group(long id, int slots) {
this.bestId = id;
this.bestSlots = slots;
this.totalSlots = Math.max(0, slots);
this.count = 1;
}
void merge(long id, int slots) {
count++;
totalSlots += Math.max(0, slots);
// 挑选空位最多的作为代表 id若并列保留先到者
if (slots > bestSlots) {
bestSlots = slots;
bestId = id;
}
}
} }
private void applyFilter() { private void applyFilter() {
@ -270,9 +315,11 @@ public class ProviderSelectScreen extends Screen {
fTotalSlots.clear(); fTotalSlots.clear();
fCount.clear(); fCount.clear();
String q = query == null ? "" : query.trim(); String q = query == null ? "" : query.trim();
String qLower = q.toLowerCase(Locale.ROOT);
for (int i = 0; i < gIds.size(); i++) { for (int i = 0; i < gIds.size(); i++) {
String name = gNames.get(i); String name = gNames.get(i);
if (q.isEmpty() || nameMatches(name, q)) { if (q.isEmpty() || nameMatches(name, q, qLower)) {
fIds.add(gIds.get(i)); fIds.add(gIds.get(i));
fNames.add(name); fNames.add(name);
fTotalSlots.add(gTotalSlots.get(i)); fTotalSlots.add(gTotalSlots.get(i));
@ -294,9 +341,10 @@ public class ProviderSelectScreen extends Screen {
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;
private static boolean nameMatches(String name, String key) { private static boolean nameMatches(String name, String key, String keyLower) {
if (name == null) return false; if (name == null) return false;
if (key == null || key.isEmpty()) return true; if (key == null || key.isEmpty()) return true;
try { try {
if (JEC_AVAILABLE == null) { if (JEC_AVAILABLE == null) {
try { try {
@ -312,16 +360,14 @@ public class ProviderSelectScreen extends Screen {
Object r = JEC_CONTAINS.invoke(null, name, key); Object r = JEC_CONTAINS.invoke(null, name, key);
if (r instanceof Boolean && (Boolean) r) return true; if (r instanceof Boolean && (Boolean) r) return true;
// 再尝试大小写不敏感双方转为小写重新匹配 // 再尝试大小写不敏感双方转为小写重新匹配
String nL = name.toLowerCase(); Object r2 = JEC_CONTAINS.invoke(null, name.toLowerCase(Locale.ROOT), keyLower);
String kL = key.toLowerCase();
Object r2 = JEC_CONTAINS.invoke(null, nL, kL);
if (r2 instanceof Boolean && (Boolean) r2) return true; if (r2 instanceof Boolean && (Boolean) r2) return true;
} }
} catch (Throwable ignored) { } catch (Throwable ignored) {
// 回退 // 回退
} }
// 默认大小写不敏感子串 // 默认大小写不敏感子串
return name.toLowerCase().contains(key.toLowerCase()); return name.toLowerCase(Locale.ROOT).contains(keyLower);
} }
@Override @Override
@ -355,7 +401,7 @@ public class ProviderSelectScreen extends Screen {
this.query = ""; this.query = "";
this.page = 0; this.page = 0;
applyFilter(); applyFilter();
this.needsRefresh = true; refreshButtons();
return true; return true;
} }
} }
@ -371,11 +417,6 @@ public class ProviderSelectScreen extends Screen {
if (cnInput != null) { if (cnInput != null) {
cnInput.tick(); cnInput.tick();
} }
if (needsRefresh) {
needsRefresh = false;
// 重新构建当前屏幕内容
init();
}
} }
private void addMappingFromUI() { private void addMappingFromUI() {
@ -390,7 +431,7 @@ public class ProviderSelectScreen extends Screen {
if (player != null) player.sendSystemMessage(Component.literal("请输入中文名称")); if (player != null) player.sendSystemMessage(Component.literal("请输入中文名称"));
return; return;
} }
boolean ok = com.extendedae_plus.util.ExtendedAEPatternUploadUtil.addOrUpdateAliasMapping(key, val); boolean ok = ExtendedAEPatternUploadUtil.addOrUpdateAliasMapping(key, val);
if (ok) { if (ok) {
if (player != null) player.sendSystemMessage(Component.literal("已添加/更新映射: " + key + " -> " + val)); if (player != null) player.sendSystemMessage(Component.literal("已添加/更新映射: " + key + " -> " + val));
// 将刚添加的中文名写入搜索框作为当前查询 // 将刚添加的中文名写入搜索框作为当前查询
@ -402,7 +443,7 @@ public class ProviderSelectScreen extends Screen {
applyFilter(); applyFilter();
// 回到第一页以展示最新筛选结果 // 回到第一页以展示最新筛选结果
page = 0; page = 0;
needsRefresh = true; refreshButtons();
} else { } else {
if (player != null) player.sendSystemMessage(Component.literal("写入映射失败")); if (player != null) player.sendSystemMessage(Component.literal("写入映射失败"));
} }
@ -416,11 +457,12 @@ public class ProviderSelectScreen extends Screen {
if (player != null) player.sendSystemMessage(Component.literal("请输入中文名称后再删除映射")); if (player != null) player.sendSystemMessage(Component.literal("请输入中文名称后再删除映射"));
return; return;
} }
int removed = com.extendedae_plus.util.ExtendedAEPatternUploadUtil.removeMappingsByCnValue(val); int removed = ExtendedAEPatternUploadUtil.removeMappingsByCnValue(val);
if (removed > 0) { if (removed > 0) {
if (player != null) player.sendSystemMessage(Component.literal("已删除 " + removed + " 条映射,中文= " + val)); if (player != null) player.sendSystemMessage(Component.literal("已删除 " + removed + " 条映射,中文= " + val));
applyFilter(); applyFilter();
needsRefresh = true; page = 0;
refreshButtons();
} else { } else {
if (player != null) player.sendSystemMessage(Component.literal("未找到中文为 '" + val + "' 的映射")); if (player != null) player.sendSystemMessage(Component.literal("未找到中文为 '" + val + "' 的映射"));
} }

View File

@ -1,11 +1,10 @@
package com.extendedae_plus.hooks; package com.extendedae_plus.hooks;
import appeng.block.crafting.CraftingUnitBlock;
import appeng.util.InteractionUtil; import appeng.util.InteractionUtil;
import com.extendedae_plus.ExtendedAEPlus; import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.client.ui.FrequencyInputScreen; import com.extendedae_plus.client.screen.FrequencyInputScreen;
import com.extendedae_plus.content.wireless.WirelessTransceiverBlockEntity; import com.extendedae_plus.content.wireless.WirelessTransceiverBlockEntity;
import appeng.block.crafting.CraftingUnitBlock;
import appeng.blockentity.crafting.CraftingBlockEntity;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;

View File

@ -1,6 +1,6 @@
package com.extendedae_plus.network.provider; package com.extendedae_plus.network.provider;
import com.extendedae_plus.client.ui.ProviderSelectScreen; import com.extendedae_plus.client.screen.ProviderSelectScreen;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;

View File

@ -49,7 +49,10 @@
"extendedae_plus.upload_to_matrix.fail_no_matrix": "No formed assembly matrix found in the current network", "extendedae_plus.upload_to_matrix.fail_no_matrix": "No formed assembly matrix found in the current network",
"extendedae_plus.upload_to_matrix.fail_full": "The assembly matrix pattern inventory is full or cannot insert", "extendedae_plus.upload_to_matrix.fail_full": "The assembly matrix pattern inventory is full or cannot insert",
"extendedae_plus.screen.reload_mapping": "Reload Mapping", "extendedae_plus.screen.reload_mapping": "Reload Mapping",
"extendedae_plus.screen.reload_mapping_success": "Overloading mapping successful",
"extendedae_plus.screen.reload_mapping_fail": "Overloading mapping failed: %s",
"extendedae_plus.screen.add_mapping": "Add Mapping", "extendedae_plus.screen.add_mapping": "Add Mapping",
"extendedae_plus.screen.delete_mapping": "Delete Mapping",
"extendedae_plus.screen.cn_name": "Chinese Name", "extendedae_plus.screen.cn_name": "Chinese Name",
"extendedae_plus.button.choose_provider": "Upload Pattern", "extendedae_plus.button.choose_provider": "Upload Pattern",
"extendedae_plus.pattern.hovertext.player": "Encoded by %s", "extendedae_plus.pattern.hovertext.player": "Encoded by %s",

View File

@ -50,7 +50,10 @@
"extendedae_plus.upload_to_matrix.fail_no_matrix": "未在当前网络中找到已成型的装配矩阵", "extendedae_plus.upload_to_matrix.fail_no_matrix": "未在当前网络中找到已成型的装配矩阵",
"extendedae_plus.upload_to_matrix.fail_full": "装配矩阵的样板仓已满或无法插入", "extendedae_plus.upload_to_matrix.fail_full": "装配矩阵的样板仓已满或无法插入",
"extendedae_plus.screen.reload_mapping": "重载映射", "extendedae_plus.screen.reload_mapping": "重载映射",
"extendedae_plus.screen.reload_mapping_success": "重载映射成功",
"extendedae_plus.screen.reload_mapping_fail": "重载映射失败: %s",
"extendedae_plus.screen.add_mapping": "增加映射", "extendedae_plus.screen.add_mapping": "增加映射",
"extendedae_plus.screen.delete_mapping": "删除映射",
"extendedae_plus.screen.cn_name": "中文名", "extendedae_plus.screen.cn_name": "中文名",
"extendedae_plus.button.choose_provider":"上传样板", "extendedae_plus.button.choose_provider":"上传样板",
"extendedae_plus.pattern.hovertext.player": "由 %s 编码", "extendedae_plus.pattern.hovertext.player": "由 %s 编码",