优化上传按钮代码;调整命名、调整结构、调整AEBaseScreenMixin内部分内容

This commit is contained in:
C-H716 2025-10-30 10:59:41 +08:00
parent 06271999c7
commit e868495a8a
6 changed files with 161 additions and 182 deletions

View File

@ -6,7 +6,6 @@ import appeng.client.Point;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.StackWithBounds;
import appeng.client.gui.TextOverride;
import appeng.client.gui.implementations.PatternProviderScreen;
import appeng.client.gui.me.crafting.CraftingCPUScreen;
import appeng.client.gui.style.PaletteColor;
import appeng.client.gui.style.ScreenStyle;
@ -29,10 +28,8 @@ import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.renderer.Rect2i;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.contents.TranslatableContents;
import net.minecraft.world.inventory.Slot;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@ -82,15 +79,10 @@ public abstract class AEBaseScreenMixin {
}
/**
* 重写renderSlot方法为所有可见的样板槽位添加数量显示
* 为所有可见的样板槽位添加数量显示
*/
@Inject(method = "renderSlot", at = @At("TAIL"))
private void eap$renderSlotAmounts(GuiGraphics guiGraphics, Slot s, CallbackInfo ci) {
// 只处理AppEngSlot类型的槽位
if (!(s instanceof AppEngSlot appEngSlot)) {
return;
}
@Inject(method = "renderAppEngSlot", at = @At("TAIL"), remap = false)
private void eap$renderSlotAmounts(GuiGraphics guiGraphics, AppEngSlot appEngSlot, CallbackInfo ci) {
// 检查槽位是否可见且有效
if (!appEngSlot.isActive() || !appEngSlot.isSlotEnabled()) {
return;
@ -114,20 +106,13 @@ public abstract class AEBaseScreenMixin {
try {
var details = PatternDetailsHelper.decodePattern(itemStack, Minecraft.getInstance().level, false);
try {
if (details != null && details.getOutputs() != null && details.getOutputs().length > 0) {
AEKey key = details.getOutputs()[0].what();
if (key != null && ClientPatternHighlightStore.hasHighlight(key)) {
try {
GuiUtil.drawSlotRainbowHighlight(guiGraphics, s.x, s.y);
} catch (Throwable ignored) {
}
}
if (details != null && details.getOutputs() != null && details.getOutputs().length > 0) {
AEKey key = details.getOutputs()[0].what();
if (key != null && ClientPatternHighlightStore.hasHighlight(key)) {
GuiUtil.drawSlotRainbowHighlight(guiGraphics, appEngSlot.x, appEngSlot.y);
}
} catch (Throwable ignore) {
}
} catch (Throwable ignore) {
}
} catch (Throwable ignore) {}
}
// AEBaseScreen.drawText 完成某个文本绘制后若该文本为样板标签则紧接着绘制页码
@ -186,19 +171,4 @@ public abstract class AEBaseScreenMixin {
guiGraphics.pose().popPose();
} catch (Throwable ignored) {}
}
@Shadow(remap = false)
protected void setTextContent(String id, Component content) {}
@Inject(method = "updateBeforeRender", at = @At("RETURN"), remap = false)
private void onUpdateBeforeRender(CallbackInfo ci) {
try {
if (((Object) this) instanceof PatternProviderScreen<?> screen) {
Component t = screen.getTitle();
if (t != null && !t.getString().isEmpty()) {
this.setTextContent(AEBaseScreen.TEXT_ID_DIALOG_TITLE, t);
}
}
} catch (Throwable ignored) {}
}
}

View File

@ -1,17 +1,16 @@
package com.extendedae_plus.mixin.ae2.client.gui;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.Icon;
import appeng.client.gui.me.items.PatternEncodingTermScreen;
import appeng.client.gui.style.ScreenStyle;
import appeng.client.gui.style.WidgetStyle;
import appeng.client.gui.widgets.IconButton;
import appeng.menu.AEBaseMenu;
import com.extendedae_plus.init.ModNetwork;
import com.extendedae_plus.mixin.accessor.AbstractContainerScreenAccessor;
import com.extendedae_plus.mixin.accessor.ScreenAccessor;
import com.extendedae_plus.mixin.ae2.accessor.AEBaseScreenAccessor;
import com.extendedae_plus.network.provider.RequestProvidersListC2SPacket;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Tooltip;
import net.minecraft.client.renderer.Rect2i;
@ -24,167 +23,132 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* 在图样编码终端界面加入一个上传按钮
* 点击后把当前已编码样板上传到任意可用的样板供应器服务端自动选择
* 通过解析 AE2 样式中 encodePattern 的坐标将按钮放在其左侧紧挨位置
* 点击后把当前已编码样板上传到任意可用的样板供应器
* 按钮位于 encodePattern 左侧
*/
@Mixin(AEBaseScreen.class)
public abstract class PatternEncodingTermScreenMixin<T extends AEBaseMenu> {
@SuppressWarnings({"AddedMixinMembersNamePattern"})
@Mixin(PatternEncodingTermScreen.class)
public abstract class PatternEncodingTermScreenMixin {
@Unique private IconButton eap$uploadBtn;
// 只创建按钮
@Inject(method = "<init>", at = @At("TAIL"))
private void eap$createUploadButton(CallbackInfo ci) {
if (eap$uploadBtn == null) {
eap$uploadBtn = createUploadButton();
}
addButtonToScreen();
}
// 每帧更新按钮位置并确保加入屏幕
@Inject(method = "updateBeforeRender", at = @At("TAIL"), remap = false)
private void eap$ensureUploadButton(CallbackInfo ci) {
if (eap$uploadBtn == null) return;
updateUploadButtonPosition();
addButtonToScreen();
}
@Unique
private IconButton eap$uploadBtn;
private IconButton createUploadButton() {
IconButton btn = new IconButton(button ->
ModNetwork.CHANNEL.sendToServer(new RequestProvidersListC2SPacket())
) {
private final float eap$scale = 0.75f;
@Inject(method = "init", at = @At("TAIL"))
private void eap$addUploadButton(CallbackInfo ci) {
// 仅在图样编码终端界面中添加按钮
if (!(((Object) this) instanceof PatternEncodingTermScreen)) {
return;
}
// 复用已存在的按钮实例避免重复创建
if (eap$uploadBtn == null) {
eap$uploadBtn = new IconButton(btn -> ModNetwork.CHANNEL
.sendToServer(new RequestProvidersListC2SPacket())) {
private final float eap$scale = 0.75f; // 12x12
@Override
public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partial) {
if (!this.visible) return;
@Override
protected Icon getIcon() {
return Icon.ARROW_UP;
var icon = this.getIcon();
var blitter = icon.getBlitter();
if (!this.active) blitter.opacity(0.5f);
this.width = Math.round(16 * eap$scale);
this.height = Math.round(16 * eap$scale);
RenderSystem.disableDepthTest();
RenderSystem.enableBlend();
if (isFocused()) {
guiGraphics.fill(getX() - 1, getY() - 1, getX() + width + 1, getY(), 0xFFFFFFFF);
guiGraphics.fill(getX() - 1, getY(), getX(), getY() + height, 0xFFFFFFFF);
guiGraphics.fill(getX() + width, getY(), getX() + width + 1, getY() + height, 0xFFFFFFFF);
guiGraphics.fill(getX() - 1, getY() + height, getX() + width + 1, getY() + height + 1, 0xFFFFFFFF);
}
@Override
public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partial) {
// 参照 AE2 IconButton 实现改为自定义缩放
if (this.visible) {
var icon = this.getIcon();
var blitter = icon.getBlitter();
if (!this.active) {
blitter.opacity(0.5f);
}
// 动态更新宽高用于聚焦边框/命中框
this.width = Math.round(16 * eap$scale);
this.height = Math.round(16 * eap$scale);
com.mojang.blaze3d.systems.RenderSystem.disableDepthTest();
com.mojang.blaze3d.systems.RenderSystem.enableBlend();
if (isFocused()) {
guiGraphics.fill(getX() - 1, getY() - 1, getX() + width + 1, getY(), 0xFFFFFFFF);
guiGraphics.fill(getX() - 1, getY(), getX(), getY() + height, 0xFFFFFFFF);
guiGraphics.fill(getX() + width, getY(), getX() + width + 1, getY() + height, 0xFFFFFFFF);
guiGraphics.fill(getX() - 1, getY() + height, getX() + width + 1, getY() + height + 1, 0xFFFFFFFF);
}
var pose = guiGraphics.pose();
pose.pushPose();
pose.translate(getX(), getY(), 0.0F);
pose.scale(eap$scale, eap$scale, 1.f);
if (!this.isDisableBackground()) {
Icon.TOOLBAR_BUTTON_BACKGROUND.getBlitter().dest(0, 0).blit(guiGraphics);
}
blitter.dest(0, 0).blit(guiGraphics);
pose.popPose();
com.mojang.blaze3d.systems.RenderSystem.enableDepthTest();
}
var pose = guiGraphics.pose();
pose.pushPose();
pose.translate(getX(), getY(), 0.0F);
pose.scale(eap$scale, eap$scale, 1.f);
if (!this.isDisableBackground()) {
Icon.TOOLBAR_BUTTON_BACKGROUND.getBlitter().dest(0, 0).blit(guiGraphics);
}
blitter.dest(0, 0).blit(guiGraphics);
pose.popPose();
@Override
public Rect2i getTooltipArea() {
return new Rect2i(getX(), getY(), Math.round(16 * eap$scale), Math.round(16 * eap$scale));
}
};
eap$uploadBtn.setTooltip(Tooltip.create(Component.translatable("extendedae_plus.button.choose_provider")));
}
RenderSystem.enableDepthTest();
}
// 解析 encodePattern 的样式位置
@Override
public Rect2i getTooltipArea() {
return new Rect2i(getX(), getY(), Math.round(16 * eap$scale), Math.round(16 * eap$scale));
}
@Override
protected Icon getIcon() {
return Icon.ARROW_UP;
}
};
btn.setTooltip(Tooltip.create(Component.translatable("extendedae_plus.button.choose_provider")));
return btn;
}
@Unique
private void updateUploadButtonPosition() {
if (eap$uploadBtn == null) return;
AbstractContainerScreenAccessor<?> screen = (AbstractContainerScreenAccessor<?>) this;
try {
ScreenStyle style = ((AEBaseScreenAccessor<?>) (Object) this).eap$getStyle();
ScreenStyle style = ((AEBaseScreenAccessor<?>) this).eap$getStyle();
WidgetStyle ws = style.getWidget("encodePattern");
int leftPos = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getLeftPos();
int topPos = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getTopPos();
int imageWidth = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getImageWidth();
int imageHeight = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getImageHeight();
Rect2i bounds = new Rect2i(leftPos, topPos, imageWidth, imageHeight);
var bounds = new Rect2i(
screen.eap$getLeftPos(),
screen.eap$getTopPos(),
screen.eap$getImageWidth(),
screen.eap$getImageHeight()
);
var pos = ws.resolve(bounds);
int baseW = ws.getWidth() > 0 ? ws.getWidth() : 16;
int baseH = ws.getHeight() > 0 ? ws.getHeight() : 16;
int targetW = Math.max(10, Math.round(baseW * 0.75f));
int targetH = Math.max(10, Math.round(baseH * 0.75f));
// 缩小为原尺寸的 0.75稍微变大于 8x8
eap$uploadBtn.setWidth(targetW);
eap$uploadBtn.setHeight(targetH);
// 仍位于其左侧但整体向右微移减小间距 2px
eap$uploadBtn.setX(pos.getX() - targetW); // 原为 -targetW - 2再右移 2px
eap$uploadBtn.setX(pos.getX() - targetW);
eap$uploadBtn.setY(pos.getY());
} catch (Throwable t) {
// 回退放在界面右侧大致位置避免不可见
int leftPos = screen.eap$getLeftPos();
int topPos = screen.eap$getTopPos();
int imageWidth = screen.eap$getImageWidth();
eap$uploadBtn.setWidth(12);
eap$uploadBtn.setHeight(12);
int leftPos = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getLeftPos();
int topPos = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getTopPos();
int imageWidth = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getImageWidth();
eap$uploadBtn.setX(leftPos + imageWidth - 12 - 8 + 2); // 向右微移 2px
eap$uploadBtn.setX(leftPos + imageWidth - 14);
eap$uploadBtn.setY(topPos + 88);
}
}
// 直接向 renderables / children 列表添加避免依赖受保护方法
var accessor = (ScreenAccessor) (Object) this;
@Unique
private void addButtonToScreen() {
var accessor = (ScreenAccessor) this;
var renderables = accessor.eap$getRenderables();
var children = accessor.eap$getChildren();
if (!renderables.contains(eap$uploadBtn)) {
renderables.add(eap$uploadBtn);
}
if (!children.contains(eap$uploadBtn)) {
children.add(eap$uploadBtn);
}
}
@Inject(method = "containerTick", at = @At("TAIL"))
private void eap$ensureUploadButton(CallbackInfo ci) {
if (!(((Object) this) instanceof PatternEncodingTermScreen)) {
return;
}
if (eap$uploadBtn == null) {
return;
}
var renderables2 = ((ScreenAccessor) (Object) this).eap$getRenderables();
if (!renderables2.contains(eap$uploadBtn)) {
// 被其它模组清空/替换后重新计算一次位置并补回
try {
ScreenStyle style = ((AEBaseScreenAccessor<?>) (Object) this).eap$getStyle();
WidgetStyle ws = style.getWidget("encodePattern");
int leftPos = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getLeftPos();
int topPos = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getTopPos();
int imageWidth = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getImageWidth();
int imageHeight = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getImageHeight();
Rect2i bounds = new Rect2i(leftPos, topPos, imageWidth, imageHeight);
var pos = ws.resolve(bounds);
int baseW = ws.getWidth() > 0 ? ws.getWidth() : 16;
int baseH = ws.getHeight() > 0 ? ws.getHeight() : 16;
int targetW = Math.max(10, Math.round(baseW * 0.75f));
int targetH = Math.max(10, Math.round(baseH * 0.75f));
eap$uploadBtn.setWidth(targetW);
eap$uploadBtn.setHeight(targetH);
eap$uploadBtn.setX(pos.getX() - targetW); // 原为 -targetW - 2再右移 2px
eap$uploadBtn.setY(pos.getY());
} catch (Throwable t) {
int leftPos = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getLeftPos();
int topPos = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getTopPos();
int imageWidth = ((AbstractContainerScreenAccessor<?>) (Object) this).eap$getImageWidth();
eap$uploadBtn.setWidth(12);
eap$uploadBtn.setHeight(12);
eap$uploadBtn.setX(leftPos + imageWidth - 12 - 8 + 2);
eap$uploadBtn.setY(topPos + 88);
}
var accessor2 = (ScreenAccessor) (Object) this;
var r = accessor2.eap$getRenderables();
var c = accessor2.eap$getChildren();
if (!r.contains(eap$uploadBtn)) {
r.add(eap$uploadBtn);
}
if (!c.contains(eap$uploadBtn)) {
c.add(eap$uploadBtn);
}
}
if (!renderables.contains(eap$uploadBtn)) renderables.add(eap$uploadBtn);
if (!children.contains(eap$uploadBtn)) children.add(eap$uploadBtn);
}
}

View File

@ -1,4 +1,4 @@
package com.extendedae_plus.mixin.ae2.client.gui;
package com.extendedae_plus.mixin.ae2.client.gui.patternProvider;
import appeng.client.gui.implementations.PatternProviderScreen;
import com.extendedae_plus.content.ClientPatternHighlightStore;
@ -8,8 +8,11 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* 关闭样板供应器界面的时候清除样板的高亮
*/
@Mixin(value = AbstractContainerScreen.class)
public class PatternProviderCloseMixin {
public class PatternProviderHighlightCleanupMixin {
@Inject(method = "removed", at = @At("HEAD"))
private void onRemoved(CallbackInfo ci) {
try {

View File

@ -0,0 +1,30 @@
package com.extendedae_plus.mixin.ae2.client.gui.patternProvider;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.implementations.PatternProviderScreen;
import appeng.client.gui.style.ScreenStyle;
import appeng.menu.implementations.PatternProviderMenu;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PatternProviderScreen.class)
public abstract class PatternProviderScreenMixin<C extends PatternProviderMenu> extends AEBaseScreen<C> {
public PatternProviderScreenMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) {
super(menu, playerInventory, title, style);
}
/**
* 显示样板供应器的customName
*/
@Inject(method = "updateBeforeRender", at = @At("RETURN"), remap = false)
private void onUpdateBeforeRender(CallbackInfo ci) {
Component t = this.getTitle();
if (!t.getString().isEmpty()) {
this.setTextContent(AEBaseScreen.TEXT_ID_DIALOG_TITLE, t);
}
}
}

View File

@ -1,4 +1,4 @@
package com.extendedae_plus.mixin.ae2.client.gui;
package com.extendedae_plus.mixin.ae2.client.gui.patternProvider;
import appeng.api.config.YesNo;
import appeng.client.gui.AEBaseScreen;
@ -32,12 +32,12 @@ import static com.extendedae_plus.util.GuiUtil.createToggle;
import static com.extendedae_plus.util.Logger.EAP$LOGGER;
/**
* AE2 原版样板供应器界面添加高级阻挡模式按钮
* AE2 原版样板供应器界面添加智能系列按钮
* - 位于左侧工具栏
* - 点击仅发送 C2S 切换请求状态由 AE2 @GuiSync 回传决定
*/
@Mixin(PatternProviderScreen.class)
public abstract class PatternProviderScreenMixin<C extends PatternProviderMenu> extends AEBaseScreen<C> {
public abstract class PatternProviderSmartFeaturesMixin<C extends PatternProviderMenu> extends AEBaseScreen<C> {
// 高级阻挡模式切换按钮
@Unique private SettingToggleButton<YesNo> eap$AdvancedBlockingToggle;
@ -53,7 +53,7 @@ public abstract class PatternProviderScreenMixin<C extends PatternProviderMenu>
// 当前智能翻倍上限
@Unique private int eap$PerProviderScalingLimit = 0;
public PatternProviderScreenMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) {
public PatternProviderSmartFeaturesMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) {
super(menu, playerInventory, title, style);
}
@ -210,4 +210,15 @@ public abstract class PatternProviderScreenMixin<C extends PatternProviderMenu>
}
}
}
/**
* 显示样板供应器的customName
*/
@Inject(method = "updateBeforeRender", at = @At("RETURN"), remap = false)
private void onUpdateBeforeRender(CallbackInfo ci) {
Component t = this.getTitle();
if (!t.getString().isEmpty()) {
this.setTextContent(AEBaseScreen.TEXT_ID_DIALOG_TITLE, t);
}
}
}

View File

@ -16,9 +16,10 @@
"ae2.client.gui.AEBaseScreenMixin",
"ae2.client.gui.InterfaceScreenMixin",
"ae2.client.gui.PatternEncodingTermScreenMixin",
"ae2.client.gui.PatternProviderCloseMixin",
"ae2.client.gui.PatternProviderScreenMixin",
"ae2.client.gui.SlotGridLayoutMixin",
"ae2.client.gui.patternProvider.PatternProviderHighlightCleanupMixin",
"ae2.client.gui.patternProvider.PatternProviderScreenMixin",
"ae2.client.gui.patternProvider.PatternProviderSmartFeaturesMixin",
"ae2.compat.PatternProviderScreenCompatMixin",
"ae2.items.QuartzCuttingKnifeItemMixin",
"ae2.menu.CraftConfirmMenuGoBackMixin",