Merge 2b9e425b33 into ebbc0f2464
This commit is contained in:
commit
8b4eb8e690
|
|
@ -105,6 +105,13 @@ public final class ModConfig {
|
|||
})
|
||||
public boolean patternTerminalShowSlotsDefault = true;
|
||||
|
||||
@Configurable
|
||||
@Configurable.Comment(value = {
|
||||
"样板终端默认是否合并空槽位",
|
||||
"开启后只会显示到最后一个有物品的槽位之后的一个空槽位(直到占满供应器所有槽位)"
|
||||
})
|
||||
public boolean patternTerminalMergeEmptySlotsDefault = true;
|
||||
|
||||
@Configurable
|
||||
@Configurable.Comment(value = {
|
||||
"实体加速器能量消耗基础值"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package com.extendedae_plus.mixin.extendedae.accessor;
|
||||
|
||||
import appeng.client.gui.me.patternaccess.PatternContainerRecord;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
@Mixin(targets = "com.glodblock.github.extendedae.client.gui.GuiExPatternTerminal$SlotsRow", remap = false)
|
||||
public interface GuiExPatternTerminalSlotsRowAccessor {
|
||||
@Accessor("container")
|
||||
PatternContainerRecord getContainer();
|
||||
|
||||
@Accessor("offset")
|
||||
int getOffset();
|
||||
|
||||
@Accessor("slots")
|
||||
int getSlots();
|
||||
}
|
||||
|
|
@ -38,6 +38,8 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.extendedae_plus.mixin.extendedae.accessor.GuiExPatternTerminalSlotsRowAccessor;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
|
@ -70,7 +72,13 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen<AEBaseMenu>
|
|||
/* ----- eap 自有字段 ----- */
|
||||
@Unique private final Map<Integer, Button> openUIButtons = new HashMap<>();
|
||||
@Unique private IconButton eap$toggleSlotsButton;
|
||||
@Unique private boolean eap$showSlots = false; // 默认由配置初始化
|
||||
@Unique private IconButton eap$mergeEmptySlotsButton;
|
||||
|
||||
@Unique private static Boolean eap$lastShowSlotsState = null;
|
||||
@Unique private static Boolean eap$lastMergeEmptySlotsState = null;
|
||||
|
||||
@Unique private boolean eap$showSlots = true;
|
||||
@Unique private boolean eap$mergeEmptySlots = true;
|
||||
@Unique private long currentlyChoicePatterProvider = -1; // 当前选择的样板供应器ID
|
||||
|
||||
// 按钮更新/缓存状态,避免每帧重建
|
||||
|
|
@ -78,6 +86,7 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen<AEBaseMenu>
|
|||
@Unique private int lastScroll = Integer.MIN_VALUE;
|
||||
@Unique private int lastRowsSize = Integer.MIN_VALUE;
|
||||
@Unique private int lastVisibleRows = Integer.MIN_VALUE;
|
||||
@Unique private Map<Long, Integer> eap$slotsToShowMap = new HashMap<>();
|
||||
|
||||
public GuiExPatternTerminalMixin(AEBaseMenu menu, Inventory playerInventory, Component title, ScreenStyle style) {
|
||||
super(menu, playerInventory, title, style);
|
||||
|
|
@ -182,12 +191,20 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen<AEBaseMenu>
|
|||
/* ----- 构造注入:创建切换按钮(只设置状态并触发一次 refresh) ----- */
|
||||
@Inject(method = "<init>", at = @At("TAIL"), remap = false)
|
||||
private void injectConstructor(CallbackInfo ci) {
|
||||
// 初始化默认显示状态
|
||||
this.eap$showSlots = ModConfig.INSTANCE.patternTerminalShowSlotsDefault;
|
||||
// 初始化默认显示状态(如果是第一次打开,从 Config 读取,否则使用上次的状态)
|
||||
if (eap$lastShowSlotsState == null) {
|
||||
eap$lastShowSlotsState = ModConfig.INSTANCE.patternTerminalShowSlotsDefault;
|
||||
}
|
||||
if (eap$lastMergeEmptySlotsState == null) {
|
||||
eap$lastMergeEmptySlotsState = ModConfig.INSTANCE.patternTerminalMergeEmptySlotsDefault;
|
||||
}
|
||||
this.eap$showSlots = eap$lastShowSlotsState;
|
||||
this.eap$mergeEmptySlots = eap$lastMergeEmptySlotsState;
|
||||
|
||||
// 创建切换槽位显示的按钮(只切换状态并触发一次 refresh)
|
||||
this.eap$toggleSlotsButton = new IconButton((b) -> {
|
||||
this.eap$showSlots = !this.eap$showSlots;
|
||||
eap$lastShowSlotsState = this.eap$showSlots;
|
||||
// 标记需要更新按钮与高亮映射
|
||||
this.buttonsDirty = true;
|
||||
this.refreshList();
|
||||
|
|
@ -199,11 +216,28 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen<AEBaseMenu>
|
|||
}
|
||||
};
|
||||
|
||||
// 创建合并空项按钮(只切换状态并触发一次 refresh)
|
||||
this.eap$mergeEmptySlotsButton = new IconButton((b) -> {
|
||||
this.eap$mergeEmptySlots = !this.eap$mergeEmptySlots;
|
||||
eap$lastMergeEmptySlotsState = this.eap$mergeEmptySlots;
|
||||
// 标记需要更新按钮与高亮映射
|
||||
this.buttonsDirty = true;
|
||||
this.refreshList();
|
||||
this.resetScrollbar();
|
||||
}) {
|
||||
@Override
|
||||
protected Icon getIcon() {
|
||||
return eap$mergeEmptySlots ? Icon.PATTERN_TERMINAL_NOT_FULL : Icon.PATTERN_TERMINAL_ALL;
|
||||
}
|
||||
};
|
||||
|
||||
// 设置按钮提示文本
|
||||
this.eap$toggleSlotsButton.setTooltip(Tooltip.create(Component.translatable("gui.expatternprovider.toggle_slots")));
|
||||
this.eap$mergeEmptySlotsButton.setTooltip(Tooltip.create(Component.translatable("gui.expatternprovider.merge_empty_slots")));
|
||||
|
||||
// 添加到左侧工具栏
|
||||
this.addToLeftToolbar(this.eap$toggleSlotsButton);
|
||||
this.addToLeftToolbar(this.eap$mergeEmptySlotsButton);
|
||||
}
|
||||
|
||||
@Inject(method = "refreshList", at = @At("HEAD"), remap = false)
|
||||
|
|
@ -214,6 +248,12 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen<AEBaseMenu>
|
|||
this.eap$showSlots ? "gui.expatternprovider.hide_slots" : "gui.expatternprovider.show_slots"
|
||||
)));
|
||||
}
|
||||
if (this.eap$mergeEmptySlotsButton != null) {
|
||||
Component tooltip = Component.translatable(
|
||||
this.eap$mergeEmptySlots ? "gui.expatternprovider.unmerge_empty_slots" : "gui.expatternprovider.merge_empty_slots"
|
||||
);
|
||||
this.eap$mergeEmptySlotsButton.setTooltip(Tooltip.create(tooltip));
|
||||
}
|
||||
// 清理并标记需要重建 UI 按钮(但不在此处做重建)
|
||||
this.openUIButtons.values().forEach(this::removeWidget);
|
||||
this.openUIButtons.clear();
|
||||
|
|
@ -226,51 +266,104 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen<AEBaseMenu>
|
|||
*/
|
||||
@Inject(method = "refreshList", at = @At("TAIL"), remap = false)
|
||||
private void onRefreshListEnd(CallbackInfo ci) {
|
||||
if (!this.eap$showSlots) {
|
||||
if (!this.eap$showSlots || this.eap$mergeEmptySlots) {
|
||||
try {
|
||||
HashMap<Integer, HighlightButton> newHighlightBtns = new HashMap<>();
|
||||
int newIndex = 0;
|
||||
ArrayList<Object> newRows = new ArrayList<>();
|
||||
this.eap$slotsToShowMap.clear();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<Object> typedRows = (ArrayList<Object>) rows;
|
||||
|
||||
// 遍历 rows,保留 GroupHeaderRow 并尝试复用 highlightBtns(原 index -> 按钮)
|
||||
for (int i = 0; i < rows.size(); i++) {
|
||||
Object row = rows.get(i);
|
||||
String className = row.getClass().getSimpleName();
|
||||
for (int i = 0; i < typedRows.size(); i++) {
|
||||
Object row = typedRows.get(i);
|
||||
String fullClassName = row.getClass().getName();
|
||||
System.out.println("EAP Debug: Processing Row " + i + ": " + fullClassName);
|
||||
|
||||
if (className.equals("GroupHeaderRow")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ArrayList<Object> typedRows = (ArrayList<Object>) rows;
|
||||
typedRows.set(newIndex, row);
|
||||
|
||||
// 原 highlightBtns 在原实现中是放在 GroupHeaderRow 之后第一个 SlotsRow 的 index(i+1)
|
||||
// 尝试复用原映射中 i+1 的按钮(若存在)
|
||||
if (highlightBtns.containsKey(i + 1)) {
|
||||
HighlightButton button = highlightBtns.get(i + 1);
|
||||
newHighlightBtns.put(newIndex, button);
|
||||
if (fullClassName.endsWith(".GuiExPatternTerminal$GroupHeaderRow")) {
|
||||
int headerOldIndex = i;
|
||||
int headerNewIndex = newRows.size();
|
||||
newRows.add(row);
|
||||
|
||||
// 逻辑:如果 !eap$showSlots,则 HighlightButton 放于 Header 位置
|
||||
if (!this.eap$showSlots && highlightBtns.containsKey(headerOldIndex + 1)) {
|
||||
newHighlightBtns.put(headerNewIndex, highlightBtns.get(headerOldIndex + 1));
|
||||
}
|
||||
} else if (fullClassName.endsWith(".GuiExPatternTerminal$SlotsRow") && this.eap$showSlots) {
|
||||
try {
|
||||
GuiExPatternTerminalSlotsRowAccessor accessor = (GuiExPatternTerminalSlotsRowAccessor) row;
|
||||
PatternContainerRecord container = accessor.getContainer();
|
||||
Long serverId = container.getServerId();
|
||||
|
||||
Integer slotsToShow = this.eap$slotsToShowMap.get(serverId);
|
||||
if (slotsToShow == null) {
|
||||
var inv = container.getInventory();
|
||||
int lastNonEmpty = -1;
|
||||
for (int j = 0; j < inv.size(); j++) {
|
||||
if (!inv.getStackInSlot(j).isEmpty()) {
|
||||
lastNonEmpty = j;
|
||||
}
|
||||
}
|
||||
slotsToShow = Math.min(inv.size(), lastNonEmpty + 2);
|
||||
this.eap$slotsToShowMap.put(serverId, slotsToShow);
|
||||
}
|
||||
|
||||
newIndex++;
|
||||
int offset = accessor.getOffset();
|
||||
if (offset < slotsToShow) {
|
||||
int availableSlots = Math.min(accessor.getSlots(), slotsToShow - offset);
|
||||
int currentRowIndex = newRows.size();
|
||||
|
||||
if (availableSlots == accessor.getSlots()) {
|
||||
newRows.add(row);
|
||||
} else {
|
||||
Object newSlotsRow = eap$createSlotsRow(container, offset, availableSlots);
|
||||
if (newSlotsRow != null) {
|
||||
newRows.add(newSlotsRow);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果 showSlots 为真,HighlightButton 应位于 SlotsRow 位置(通常是第一个)
|
||||
if (highlightBtns.containsKey(i)) {
|
||||
newHighlightBtns.put(currentRowIndex, highlightBtns.get(i));
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
// Unrecognized row type, keep it just in case? Or maybe it's the superclass row type?
|
||||
newRows.add(row);
|
||||
}
|
||||
// SlotsRow:跳过,不保留
|
||||
}
|
||||
|
||||
// 移除多余行
|
||||
while (rows.size() > newIndex) {
|
||||
rows.remove(rows.size() - 1);
|
||||
}
|
||||
|
||||
// 更新 highlightBtns:清理旧 map 并复用 new map
|
||||
typedRows.clear();
|
||||
typedRows.addAll(newRows);
|
||||
highlightBtns.clear();
|
||||
highlightBtns.putAll(newHighlightBtns);
|
||||
|
||||
// 强制刷新滚动条(一次)
|
||||
this.resetScrollbar();
|
||||
} catch (Exception ignored) {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// 标记按钮需要重建(因为 rows 结构可能已改变)
|
||||
this.buttonsDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过反射创建 AE2 的 SlotsRow record
|
||||
*/
|
||||
@Unique
|
||||
private Object eap$createSlotsRow(PatternContainerRecord container, int offset, int slots) {
|
||||
try {
|
||||
Class<?> slotsRowCls = Class.forName("com.glodblock.github.extendedae.client.gui.GuiExPatternTerminal$SlotsRow");
|
||||
Constructor<?> ctor = slotsRowCls.getDeclaredConstructors()[0];
|
||||
ctor.setAccessible(true);
|
||||
return ctor.newInstance(container, offset, slots);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drawFG 优化:仅在需要时创建/移除按钮;每帧只更新可见按钮的位置与可见性。
|
||||
*/
|
||||
|
|
@ -281,6 +374,37 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen<AEBaseMenu>
|
|||
int rowsSize = rows.size();
|
||||
int visRows = this.visibleRows;
|
||||
|
||||
// Handle dynamic auto-expansion
|
||||
if (this.eap$mergeEmptySlots && this.eap$showSlots) {
|
||||
boolean needsRefresh = false;
|
||||
for (Object row : this.rows) {
|
||||
if (row.getClass().getName().endsWith(".GuiExPatternTerminal$SlotsRow")) {
|
||||
GuiExPatternTerminalSlotsRowAccessor accessor = (GuiExPatternTerminalSlotsRowAccessor) row;
|
||||
PatternContainerRecord container = accessor.getContainer();
|
||||
Long serverId = container.getServerId();
|
||||
Integer cachedSlots = this.eap$slotsToShowMap.get(serverId);
|
||||
if (cachedSlots != null) {
|
||||
var inv = container.getInventory();
|
||||
int lastNonEmpty = -1;
|
||||
for (int j = 0; j < inv.size(); j++) {
|
||||
if (!inv.getStackInSlot(j).isEmpty()) {
|
||||
lastNonEmpty = j;
|
||||
}
|
||||
}
|
||||
int currentSlotsToShow = Math.min(inv.size(), lastNonEmpty + 2);
|
||||
if (currentSlotsToShow != cachedSlots) {
|
||||
needsRefresh = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needsRefresh) {
|
||||
this.eap$slotsToShowMap.clear();
|
||||
net.minecraft.client.Minecraft.getInstance().execute(this::refreshList);
|
||||
}
|
||||
}
|
||||
|
||||
// 当列表或滚动或 visibleRows 发生变化时,重建或清理按钮(按需)
|
||||
boolean needFullUpdate = this.buttonsDirty
|
||||
|| currentScroll != lastScroll
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
"gui.expatternprovider.toggle_slots": "Toggle Slots",
|
||||
"gui.expatternprovider.hide_slots": "Hide Slots",
|
||||
"gui.expatternprovider.show_slots": "Show Slots",
|
||||
"gui.expatternprovider.merge_empty_slots": "Merge Empty Slots",
|
||||
"gui.expatternprovider.unmerge_empty_slots": "Unmerge Empty Slots",
|
||||
"gui.expatternprovider.clear_selection": "Clear Selection",
|
||||
"gui.extendedae_plus.global.toggle_blocking": "Toggle Blocking Mode",
|
||||
"gui.extendedae_plus.global.toggle_adv_blocking": "Toggle Advanced Blocking",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
"gui.expatternprovider.toggle_slots": "切换槽位显示",
|
||||
"gui.expatternprovider.hide_slots": "隐藏槽位",
|
||||
"gui.expatternprovider.show_slots": "显示槽位",
|
||||
"gui.expatternprovider.merge_empty_slots": "合并空槽位",
|
||||
"gui.expatternprovider.unmerge_empty_slots": "取消合并空槽位",
|
||||
"gui.expatternprovider.clear_selection": "取消选择",
|
||||
"gui.extendedae_plus.global.toggle_blocking": "切换阻挡模式",
|
||||
"gui.extendedae_plus.global.toggle_adv_blocking": "切换高级阻挡",
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
"ae2.menu.CraftConfirmMenuGoBackMixin",
|
||||
"extendedae.accessor.GuiExPatternTerminalAccessor",
|
||||
"extendedae.accessor.GuiExPatternTerminalGroupHeaderRowAccessor",
|
||||
"extendedae.accessor.GuiExPatternTerminalSlotsRowAccessor",
|
||||
"extendedae.accessor.HighlightButtonAccessor",
|
||||
"extendedae.client.HighlightButtonMixin",
|
||||
"extendedae.client.gui.GuiExPatternProviderMixin",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user