抽离按钮组件;调整扩展样板供应器样板翻倍按钮

This commit is contained in:
C-H716 2025-10-29 18:09:23 +08:00
parent c75c2dea33
commit 945692b33f
2 changed files with 152 additions and 162 deletions

View File

@ -4,10 +4,10 @@ import appeng.client.gui.Icon;
import appeng.client.gui.implementations.PatternProviderScreen;
import appeng.client.gui.style.ScreenStyle;
import appeng.menu.SlotSemantics;
import com.extendedae_plus.ae.client.gui.NewIcon;
import com.extendedae_plus.api.IExPatternButton;
import com.extendedae_plus.api.IExPatternPage;
import com.extendedae_plus.config.ModConfig;
import com.extendedae_plus.util.ScaleButtonHelper;
import com.glodblock.github.extendedae.client.button.ActionEPPButton;
import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider;
import com.glodblock.github.extendedae.container.ContainerExPatternProvider;
@ -21,17 +21,22 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
@SuppressWarnings({"AddedMixinMembersNamePattern"})
@Mixin(GuiExPatternProvider.class)
public abstract class GuiExPatternProviderMixin extends PatternProviderScreen<ContainerExPatternProvider> implements IExPatternButton, IExPatternPage {
// 跟踪上次屏幕尺寸处理 GUI 缩放/窗口大小变化后按钮丢失问题
// 翻页按钮
@Unique public ActionEPPButton nextPage;
@Unique public ActionEPPButton prevPage;
// 屏幕尺寸跟踪防止按钮丢失
@Unique private int eap$lastScreenWidth = -1;
@Unique private int eap$lastScreenHeight = -1;
@Unique private int eap$currentPage = 0;
@Unique private int eap$maxPageLocal = 1;
// 集合管理的倍增/除法按钮
@Unique
private int eap$currentPage = 0;
@Unique
private int eap$maxPageLocal = 1;
private List<ActionEPPButton> scaleButtons;
public GuiExPatternProviderMixin(ContainerExPatternProvider menu, Inventory playerInventory, Component title, ScreenStyle style) {
super(menu, playerInventory, title, style);
@ -39,37 +44,23 @@ public abstract class GuiExPatternProviderMixin extends PatternProviderScreen<Co
@Override
public int eap$getCurrentPage() {
// 优先使用本地 GUI 维护的页码
return Math.max(0, eap$currentPage % Math.max(1, eap$maxPageLocal));
}
@Override
public int eap$getMaxPageLocal() {
// 优先使用配置倍数
return this.eap$maxPageLocal;
}
public ActionEPPButton nextPage;
public ActionEPPButton prevPage;
public ActionEPPButton x2Button;
public ActionEPPButton divideBy2Button;
public ActionEPPButton x5Button;
public ActionEPPButton divideBy5Button;
public ActionEPPButton x10Button;
public ActionEPPButton divideBy10Button;
// 在构造器返回后初始化按钮与翻页控制
@Inject(method = "<init>", at = @At("RETURN"))
private void injectInit(ContainerExPatternProvider menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
this.eap$maxPageLocal = ModConfig.INSTANCE.pageMultiplier;
// 翻页按钮当存在多页时显示支持仅由配置决定的空白页
// 翻页按钮左侧工具栏
if (eap$maxPageLocal > 1) {
this.prevPage = new ActionEPPButton((b) -> {
int currentPage = eap$getCurrentPage();
int maxPage = Math.max(this.eap$maxPageLocal, eap$getMaxPageLocal());
// 同步到本地 GUI 页码
this.eap$currentPage = (currentPage - 1 + maxPage) % maxPage;
// 强制重排放在更新本地页码之后确保布局读取到新页
@ -81,8 +72,6 @@ public abstract class GuiExPatternProviderMixin extends PatternProviderScreen<Co
this.nextPage = new ActionEPPButton((b) -> {
int currentPage = eap$getCurrentPage();
int maxPage = Math.max(this.eap$maxPageLocal, eap$getMaxPageLocal());
// 同步到本地 GUI 页码
this.eap$currentPage = (currentPage + 1) % maxPage;
// 强制重排放在更新本地页码之后确保布局读取到新页
@ -91,160 +80,64 @@ public abstract class GuiExPatternProviderMixin extends PatternProviderScreen<Co
this.hoveredSlot = null;
}, Icon.ARROW_RIGHT);
// 恢复到 AE2 左侧工具栏
this.addToLeftToolbar(this.nextPage);
this.addToLeftToolbar(this.prevPage);
}
// 倍增/除法按钮通过 ExtendedAE 的通用包派发
this.x2Button = new ActionEPPButton((b) -> {
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("multiply2"));
}, NewIcon.MULTIPLY2);
this.x2Button.setVisibility(true);
// 使用 ScaleButtonHelper 创建布局并返回集合
this.scaleButtons = ScaleButtonHelper.createAndLayout(
this.leftPos + this.imageWidth, // baseX 右侧外缘
this.topPos + 50, // baseY
22, // spacing
ScaleButtonHelper.Side.RIGHT, // 右侧布局
(divide, factor) -> { // 点击事件回调
String action = (divide ? "divide" : "multiply") + factor;
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket(action));
}
);
this.divideBy2Button = new ActionEPPButton((b) -> {
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("divide2"));
}, NewIcon.DIVIDE2);
this.divideBy2Button.setVisibility(true);
this.x10Button = new ActionEPPButton((b) -> {
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("multiply10"));
}, NewIcon.MULTIPLY10);
this.x10Button.setVisibility(true);
this.divideBy10Button = new ActionEPPButton((b) -> {
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("divide10"));
}, NewIcon.DIVIDE10);
this.divideBy10Button.setVisibility(true);
this.divideBy5Button = new ActionEPPButton((b) -> {
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("divide5"));
}, NewIcon.DIVIDE5);
this.divideBy5Button.setVisibility(true);
this.x5Button = new ActionEPPButton((b) -> {
EPPNetworkHandler.INSTANCE.sendToServer(new CGenericPacket("multiply5"));
}, NewIcon.MULTIPLY5);
this.x5Button.setVisibility(true);
// 注册可渲染按钮
this.addRenderableWidget(this.divideBy2Button);
this.addRenderableWidget(this.x2Button);
this.addRenderableWidget(this.divideBy5Button);
this.addRenderableWidget(this.x5Button);
this.addRenderableWidget(this.divideBy10Button);
this.addRenderableWidget(this.x10Button);
// 注册所有倍增/除法按钮
this.scaleButtons.forEach(this::addRenderableWidget);
}
@Override
public void eap$updateButtonsLayout() {
// 只处理按钮可见性与定位不再强制 showPage 或挪动 Slot 坐标避免与原布局/tooltip 冲突
if (nextPage != null && prevPage != null) {
this.nextPage.setVisibility(true);
this.prevPage.setVisibility(true);
}
if (x2Button != null) {
this.x2Button.setVisibility(true);
}
if (divideBy2Button != null) {
this.divideBy2Button.setVisibility(true);
}
if (x10Button != null) {
this.x10Button.setVisibility(true);
}
if (divideBy10Button != null) {
this.divideBy10Button.setVisibility(true);
}
if (divideBy5Button != null) {
this.divideBy5Button.setVisibility(true);
}
if (x5Button != null) {
this.x5Button.setVisibility(true);
// 1. 设置倍增/除法按钮可见性并确保在 renderables
for (ActionEPPButton b : scaleButtons) {
if (b != null) {
b.setVisibility(true);
if (!this.renderables.contains(b)) this.addRenderableWidget(b);
}
}
// 若从 JEI 配方界面返回后Screen renderables/children 可能被清空导致按钮丢失
// 这里在每帧保证这些按钮存在于渲染列表中不存在则重新注册
try {
if (this.divideBy2Button != null && !this.renderables.contains(this.divideBy2Button)) {
this.addRenderableWidget(this.divideBy2Button);
}
if (this.x2Button != null && !this.renderables.contains(this.x2Button)) {
this.addRenderableWidget(this.x2Button);
}
if (this.divideBy5Button != null && !this.renderables.contains(this.divideBy5Button)) {
this.addRenderableWidget(this.divideBy5Button);
}
if (this.x5Button != null && !this.renderables.contains(this.x5Button)) {
this.addRenderableWidget(this.x5Button);
}
if (this.divideBy10Button != null && !this.renderables.contains(this.divideBy10Button)) {
this.addRenderableWidget(this.divideBy10Button);
}
if (this.x10Button != null && !this.renderables.contains(this.x10Button)) {
this.addRenderableWidget(this.x10Button);
}
} catch (Throwable ignored) {}
// 如果屏幕尺寸发生变化窗口/GUI缩放重新注册右侧外列的自定义按钮翻页按钮由左侧工具栏托管
// 2. 屏幕尺寸变化时重新注册按钮防止丢失
if (this.width != eap$lastScreenWidth || this.height != eap$lastScreenHeight) {
eap$lastScreenWidth = this.width;
eap$lastScreenHeight = this.height;
try {
if (this.divideBy2Button != null) {
this.removeWidget(this.divideBy2Button);
this.addRenderableWidget(this.divideBy2Button);
for (ActionEPPButton b : scaleButtons) {
if (b != null) {
this.removeWidget(b);
this.addRenderableWidget(b);
}
if (this.x2Button != null) {
this.removeWidget(this.x2Button);
this.addRenderableWidget(this.x2Button);
}
if (this.divideBy5Button != null) {
this.removeWidget(this.divideBy5Button);
this.addRenderableWidget(this.divideBy5Button);
}
if (this.x5Button != null) {
this.removeWidget(this.x5Button);
this.addRenderableWidget(this.x5Button);
}
if (this.divideBy10Button != null) {
this.removeWidget(this.divideBy10Button);
this.addRenderableWidget(this.divideBy10Button);
}
if (this.x10Button != null) {
this.removeWidget(this.x10Button);
this.addRenderableWidget(this.x10Button);
}
} catch (Throwable ignored) {}
}
}
// 定位到 GUI 右缘外侧一点使用绝对屏幕坐标
int bx = this.leftPos + this.imageWidth + 1; // 向右平移 1px 到面板外侧
int by = this.topPos + 50; // 向下偏移25px (从20改为45)
int spacing = 22;
// 翻页按钮交由左侧工具栏布局无需手动定位
if (this.divideBy2Button != null) {
this.divideBy2Button.setX(bx);
this.divideBy2Button.setY(by);
}
if (this.x2Button != null) {
this.x2Button.setX(bx);
this.x2Button.setY(by + spacing);
}
if (this.divideBy5Button != null) {
this.divideBy5Button.setX(bx);
this.divideBy5Button.setY(by + spacing * 2);
}
if (this.x5Button != null) {
this.x5Button.setX(bx);
this.x5Button.setY(by + spacing * 3);
}
if (this.divideBy10Button != null) {
this.divideBy10Button.setX(bx);
this.divideBy10Button.setY(by + spacing * 4);
}
if (this.x10Button != null) {
this.x10Button.setX(bx);
this.x10Button.setY(by + spacing * 5);
// 3. 使用工具类统一布局倍增/除法按钮
if (!scaleButtons.isEmpty()) {
ScaleButtonHelper.layoutButtons(
new ScaleButtonHelper.ScaleButtonSet(
scaleButtons.get(1), // multiply2
scaleButtons.get(0), // divide2
scaleButtons.get(3), // multiply5
scaleButtons.get(2), // divide5
scaleButtons.get(5), // multiply10
scaleButtons.get(4) // divide10
),
this.leftPos + this.imageWidth,
this.topPos + 50,
22,
ScaleButtonHelper.Side.RIGHT
);
}
}
}
}

View File

@ -0,0 +1,97 @@
package com.extendedae_plus.util;
import com.extendedae_plus.ae.client.gui.NewIcon;
import com.glodblock.github.extendedae.client.button.ActionEPPButton;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
/**
* 工具类统一管理倍增/除法按钮的创建注册与布局
*/
public final class ScaleButtonHelper {
private ScaleButtonHelper() {}
/**
* 创建六个倍增/除法按钮
*
* @param handler 回调参数 (divide, factor)
* @return ScaleButtonSet
*/
public static ScaleButtonSet createButtons(BiConsumer<Boolean, Integer> handler) {
ActionEPPButton div2 = new ActionEPPButton(b -> handler.accept(true, 2), NewIcon.DIVIDE2);
ActionEPPButton x2 = new ActionEPPButton(b -> handler.accept(false, 2), NewIcon.MULTIPLY2);
ActionEPPButton div5 = new ActionEPPButton(b -> handler.accept(true, 5), NewIcon.DIVIDE5);
ActionEPPButton x5 = new ActionEPPButton(b -> handler.accept(false, 5), NewIcon.MULTIPLY5);
ActionEPPButton div10 = new ActionEPPButton(b -> handler.accept(true, 10), NewIcon.DIVIDE10);
ActionEPPButton x10 = new ActionEPPButton(b -> handler.accept(false, 10), NewIcon.MULTIPLY10);
for (var b : List.of(x2, div2, x5, div5, x10, div10)) {
b.setVisibility(true);
b.setTooltip(null);
}
return new ScaleButtonSet(x2, div2, x5, div5, x10, div10);
}
/**
* 返回六个按钮的集合便于注册/渲染
*/
public static List<ActionEPPButton> all(ScaleButtonSet set) {
return new ArrayList<>(List.of(
set.divide2(), set.multiply2(),
set.divide5(), set.multiply5(),
set.divide10(), set.multiply10()
));
}
/**
* GUI 外侧统一布局按钮
*/
public static void layoutButtons(ScaleButtonSet set, int baseX, int baseY, int spacing, Side side) {
int bx = baseX + (side == Side.LEFT ? -1 : 1);
int by = baseY;
set.divide2().setX(bx);
set.divide2().setY(by);
set.multiply2().setX(bx);
set.multiply2().setY(by + spacing);
set.divide5().setX(bx);
set.divide5().setY(by + spacing * 2);
set.multiply5().setX(bx);
set.multiply5().setY(by + spacing * 3);
set.divide10().setX(bx);
set.divide10().setY(by + spacing * 4);
set.multiply10().setX(bx);
set.multiply10().setY(by + spacing * 5);
}
/**
* 创建并返回集合同时直接布局
*
* @param baseX 基准 X
* @param baseY 基准 Y
* @param spacing 间距
* @param side 左侧/右侧
* @param handler 点击回调
* @return 按钮集合
*/
public static List<ActionEPPButton> createAndLayout(int baseX, int baseY, int spacing, Side side, BiConsumer<Boolean, Integer> handler) {
ScaleButtonSet set = createButtons(handler);
layoutButtons(set, baseX, baseY, spacing, side);
return all(set);
}
public enum Side {LEFT, RIGHT}
public record ScaleButtonSet(
ActionEPPButton multiply2,
ActionEPPButton divide2,
ActionEPPButton multiply5,
ActionEPPButton divide5,
ActionEPPButton multiply10,
ActionEPPButton divide10
) {
}
}