调整按钮到合适位置

This commit is contained in:
GaLicn 2025-08-14 00:24:07 +08:00
parent 4b243461cf
commit ad8a7ac930
3 changed files with 101 additions and 11 deletions

View File

@ -1,17 +1,16 @@
package com.extendedae_plus.mixin;
import com.extendedae_plus.mixin.accessor.AEBaseScreenAccessor;
import appeng.client.gui.me.items.PatternEncodingTermScreen;
import appeng.client.gui.widgets.IconButton;
import appeng.client.gui.Icon;
import appeng.client.gui.style.ScreenStyle;
import appeng.menu.me.items.PatternEncodingTermMenu;
import appeng.parts.encoding.EncodingMode;
import appeng.menu.SlotSemantics;
import net.minecraft.client.gui.components.Tooltip;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.Slot;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@ -20,6 +19,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.glodblock.github.extendedae.network.EPPNetworkHandler;
import com.glodblock.github.glodium.network.packet.CGenericPacket;
import com.extendedae_plus.mixin.accessor.ScreenAccessor;
import com.extendedae_plus.mixin.accessor.AEBaseScreenAccessor;
/**
* AE2 PatternEncodingTermScreen 界面中给编码按钮旁添加一个上传到矩阵按钮
@ -30,10 +31,12 @@ public abstract class GuiPatternEncodingTermMixin<C extends PatternEncodingTermM
@Unique
private IconButton epp$uploadButton;
@Unique
private boolean epp$addedWidget = false;
@Unique
private boolean epp$usingToolbar = false;
// 通过 Accessor 调用 AEBaseScreen#addToLeftToolbar
// 在构造函数尾部创建按钮实例仅创建不添加
// 在构造函数尾部创建按钮实例并加入普通部件列表
@Inject(method = "<init>", at = @At("TAIL"), remap = false)
private void epp$onInit(C menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
// 选择一个合适的图标占位AE2 暂无显式上传图标这里先用 PATTERN_ACCESS_SHOW
@ -62,9 +65,81 @@ public abstract class GuiPatternEncodingTermMixin<C extends PatternEncodingTermM
};
this.epp$uploadButton.setTooltip(Tooltip.create(Component.translatable("extendedae_plus.upload_to_matrix")));
System.out.println("[EAE+][Client] Created upload button in PatternEncodingTermScreen ctor tail");
// 直接在构造尾部加入左侧工具栏避免目标类未覆写 init 导致的注入不到
((AEBaseScreenAccessor) (Object) this).epp$addToLeftToolbar(this.epp$uploadButton);
System.out.println("[EAE+][Client] Added upload button to left toolbar in ctor tail");
// 注意此处不立即添加到 Screen等到 updateBeforeRender 首帧再添加避免在构造期调用导致异常
this.epp$uploadButton.visible = false; // 初始隐藏等待定位
}
// 在每帧渲染前定位按钮到已编码样板槽位的左侧
@Inject(method = "updateBeforeRender", at = @At("TAIL"), remap = false)
private void epp$positionUploadButton(CallbackInfo ci) {
try {
if (this.epp$uploadButton == null) {
return;
}
// 首帧尝试将按钮加入到 Screen 的可渲染部件中
if (!this.epp$addedWidget) {
try {
((ScreenAccessor)(Object)this).epp$invokeAddRenderableWidget(this.epp$uploadButton);
this.epp$addedWidget = true;
this.epp$usingToolbar = false;
System.out.println("[EAE+][Client] Added upload button as normal widget in first updateBeforeRender");
} catch (Throwable t) {
System.out.println("[EAE+][Client] addRenderableWidget failed, fallback to left toolbar: " + t);
try {
((AEBaseScreenAccessor)(Object)this).epp$addToLeftToolbar(this.epp$uploadButton);
this.epp$addedWidget = true;
this.epp$usingToolbar = true;
this.epp$uploadButton.visible = true;
System.out.println("[EAE+][Client] Fallback added to left toolbar");
} catch (Throwable t2) {
System.out.println("[EAE+][Client] Fallback addToLeftToolbar also failed: " + t2);
// 放弃添加避免死循环
this.epp$addedWidget = true;
}
}
}
// 仅在合成模式下显示按钮与上传逻辑一致
var self = (PatternEncodingTermScreen<?>) (Object) this;
var menu = (PatternEncodingTermMenu) self.getMenu();
if (menu == null) {
return;
}
boolean craftingMode = menu.getMode() == EncodingMode.CRAFTING;
Slot encoded = null;
for (Slot s : menu.slots) {
var sem = menu.getSlotSemantic(s);
if (sem == SlotSemantics.ENCODED_PATTERN) {
encoded = s;
break;
}
}
// 如果退回到左侧工具栏显示则不做定位
if (this.epp$usingToolbar) {
return;
}
if (craftingMode && encoded != null) {
int slotX = self.getGuiLeft() + encoded.x;
int slotY = self.getGuiTop() + encoded.y;
int bw = this.epp$uploadButton.getWidth();
int bh = this.epp$uploadButton.getHeight();
int gap = 3;
this.epp$uploadButton.setX(slotX - gap - bw);
this.epp$uploadButton.setY(slotY + (18 - bh) / 2);
this.epp$uploadButton.visible = true;
// 可选当槽位有编码图样时启用
this.epp$uploadButton.active = !encoded.getItem().isEmpty();
} else {
this.epp$uploadButton.visible = false;
}
} catch (Throwable t) {
System.out.println("[EAE+][Client] updateBeforeRender positioning failed: " + t);
}
}
}

View File

@ -0,0 +1,14 @@
package com.extendedae_plus.mixin.accessor;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.Renderable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(Screen.class)
public interface ScreenAccessor {
@Invoker("addRenderableWidget")
<T extends GuiEventListener & Renderable & NarratableEntry> T epp$invokeAddRenderableWidget(T widget);
}

View File

@ -9,7 +9,8 @@
"GuiExPatternTerminalMixin",
"HighlightButtonMixin",
"GuiPatternEncodingTermMixin",
"accessor.AEBaseScreenAccessor"
"accessor.AEBaseScreenAccessor",
"accessor.ScreenAccessor"
],
"mixins": [
"ContainerExPatternProviderMixin",