Compare commits
4 Commits
master
...
develop/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d704a2b3e | ||
|
|
75817040a2 | ||
|
|
00ff25cc05 | ||
|
|
8213dddf8d |
|
|
@ -0,0 +1,14 @@
|
|||
package com.extendedae_plus.api;
|
||||
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
|
||||
/**
|
||||
* 用于在 AEBaseScreen.drawBG 中渲染输入框背景的回调接口
|
||||
*/
|
||||
public interface IInputBackgroundRenderer {
|
||||
/**
|
||||
* 在背景层绘制输入框外部背景
|
||||
* @param guiGraphics 图形上下文
|
||||
*/
|
||||
void eap$renderInputBackground(GuiGraphics guiGraphics);
|
||||
}
|
||||
|
|
@ -1,109 +1,228 @@
|
|||
package com.extendedae_plus.client.screen;
|
||||
|
||||
import appeng.client.gui.Icon;
|
||||
import com.extendedae_plus.init.ModNetwork;
|
||||
import com.extendedae_plus.menu.NetworkPatternControllerMenu;
|
||||
import com.extendedae_plus.network.provider.GlobalToggleProviderModesC2SPacket;
|
||||
import com.extendedae_plus.network.provider.SetGlobalScalingLimitC2SPacket;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class GlobalProviderModesScreen extends AbstractContainerScreen<NetworkPatternControllerMenu> {
|
||||
private static final Component CUSTOM_TITLE = Component.translatable("block.extendedae_plus.network_pattern_controller");
|
||||
private static final ResourceLocation BACKGROUND = new ResourceLocation("ae2", "textures/guis/background.png");
|
||||
|
||||
private EditBox inputField;
|
||||
private static final int INPUT_WIDTH = 50;
|
||||
private static final int INPUT_HEIGHT = 14;
|
||||
|
||||
// 布局常量
|
||||
private static final int IMAGE_WIDTH = 210;
|
||||
private static final int IMAGE_HEIGHT = 165;
|
||||
private static final int BTN_W = 62;
|
||||
private static final int BTN_H = 18;
|
||||
private static final int BTN_SPACING = 6;
|
||||
private static final int START_Y = 25;
|
||||
private static final int LABEL_INPUT_SPACING = 18;
|
||||
|
||||
public GlobalProviderModesScreen(NetworkPatternControllerMenu menu, Inventory inv, Component title) {
|
||||
super(menu, inv, title);
|
||||
this.imageWidth = 240;
|
||||
this.imageHeight = 140;
|
||||
this.imageWidth = IMAGE_WIDTH;
|
||||
this.imageHeight = IMAGE_HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
int w = 70; // 按钮宽
|
||||
int h = 20; // 按钮高
|
||||
int s = 8; // 按钮间距
|
||||
int y = this.topPos + 28; // 第一行 Y
|
||||
// 计算三列按钮的左侧起点,使其在面板内水平居中
|
||||
int totalW3 = w * 3 + s * 2;
|
||||
int x = this.leftPos + (this.imageWidth - totalW3) / 2;
|
||||
|
||||
// 行1:三个单项切换
|
||||
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.toggle_blocking"), b ->
|
||||
int centerX = this.leftPos + this.imageWidth / 2;
|
||||
int row1Y = this.topPos + START_Y;
|
||||
int row2Y = row1Y + BTN_H + BTN_SPACING;
|
||||
int row3Y = row2Y + BTN_H + BTN_SPACING;
|
||||
|
||||
int totalWidth3 = BTN_W * 3 + BTN_SPACING * 2;
|
||||
int row1X = centerX - totalWidth3 / 2;
|
||||
|
||||
int totalWidth2 = BTN_W * 2 + BTN_SPACING;
|
||||
int row2X = centerX - totalWidth2 / 2;
|
||||
|
||||
addRenderableWidget(new AEStyleButton(row1X, row1Y, BTN_W, BTN_H,
|
||||
Component.translatable("gui.extendedae_plus.global.toggle_blocking"), b ->
|
||||
ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket(
|
||||
GlobalToggleProviderModesC2SPacket.Op.TOGGLE,
|
||||
GlobalToggleProviderModesC2SPacket.Op.NOOP,
|
||||
GlobalToggleProviderModesC2SPacket.Op.NOOP,
|
||||
this.menu.getBlockEntityPos()
|
||||
))).bounds(x, y, w, h).build());
|
||||
))));
|
||||
|
||||
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.toggle_adv_blocking"), b ->
|
||||
addRenderableWidget(new AEStyleButton(row1X + BTN_W + BTN_SPACING, row1Y, BTN_W, BTN_H,
|
||||
Component.translatable("gui.extendedae_plus.global.toggle_adv_blocking"), b ->
|
||||
ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket(
|
||||
GlobalToggleProviderModesC2SPacket.Op.NOOP,
|
||||
GlobalToggleProviderModesC2SPacket.Op.TOGGLE,
|
||||
GlobalToggleProviderModesC2SPacket.Op.NOOP,
|
||||
this.menu.getBlockEntityPos()
|
||||
))).bounds(x + w + s, y, w, h).build());
|
||||
))));
|
||||
|
||||
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.toggle_smart_doubling"), b ->
|
||||
addRenderableWidget(new AEStyleButton(row1X + (BTN_W + BTN_SPACING) * 2, row1Y, BTN_W, BTN_H,
|
||||
Component.translatable("gui.extendedae_plus.global.toggle_smart_doubling"), b ->
|
||||
ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket(
|
||||
GlobalToggleProviderModesC2SPacket.Op.NOOP,
|
||||
GlobalToggleProviderModesC2SPacket.Op.NOOP,
|
||||
GlobalToggleProviderModesC2SPacket.Op.TOGGLE,
|
||||
this.menu.getBlockEntityPos()
|
||||
))).bounds(x + (w + s) * 2, y, w, h).build());
|
||||
))));
|
||||
|
||||
// 行2:一键全开/全关
|
||||
int y2 = y + h + 12;
|
||||
// 第二行:两列按钮,总宽并居中
|
||||
int totalW2 = w * 2 + s;
|
||||
int x2 = this.leftPos + (this.imageWidth - totalW2) / 2;
|
||||
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.all_on"), b ->
|
||||
addRenderableWidget(new AEStyleButton(row2X, row2Y, BTN_W, BTN_H,
|
||||
Component.translatable("gui.extendedae_plus.global.all_on"), b ->
|
||||
ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket(
|
||||
GlobalToggleProviderModesC2SPacket.Op.SET_TRUE,
|
||||
GlobalToggleProviderModesC2SPacket.Op.SET_TRUE,
|
||||
GlobalToggleProviderModesC2SPacket.Op.SET_TRUE,
|
||||
this.menu.getBlockEntityPos()
|
||||
))).bounds(x2, y2, w, h).build());
|
||||
))));
|
||||
|
||||
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.all_off"), b ->
|
||||
addRenderableWidget(new AEStyleButton(row2X + BTN_W + BTN_SPACING, row2Y, BTN_W, BTN_H,
|
||||
Component.translatable("gui.extendedae_plus.global.all_off"), b ->
|
||||
ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket(
|
||||
GlobalToggleProviderModesC2SPacket.Op.SET_FALSE,
|
||||
GlobalToggleProviderModesC2SPacket.Op.SET_FALSE,
|
||||
GlobalToggleProviderModesC2SPacket.Op.SET_FALSE,
|
||||
this.menu.getBlockEntityPos()
|
||||
))).bounds(x2 + w + s, y2, w, h).build());
|
||||
))));
|
||||
|
||||
// 输入框区域 - 整体居中布局
|
||||
int inputRowY = row3Y + LABEL_INPUT_SPACING;
|
||||
int labelWidth = this.font.width(Component.translatable("gui.extendedae_plus.global.supplier_doubling_limit"));
|
||||
int totalWidth = labelWidth + 8 + INPUT_WIDTH + 6 + 16; // 标签 + 间距 + 输入框 + 间距 + 按钮
|
||||
int startX = centerX - totalWidth / 2;
|
||||
int labelX = startX;
|
||||
int inputX = startX + labelWidth + 8;
|
||||
int confirmX = inputX + INPUT_WIDTH + 6;
|
||||
|
||||
inputField = createInputField(inputX, inputRowY + 1);
|
||||
this.addRenderableWidget(inputField);
|
||||
|
||||
addRenderableWidget(new AEConfirmButton(confirmX, inputRowY,
|
||||
Component.translatable("gui.extendedae_plus.global.confirm_tooltip"), b -> {
|
||||
String value = inputField.getValue();
|
||||
// 数据校验:解析并发送有效数值
|
||||
try {
|
||||
String sValue = (value == null || value.isBlank()) ? "0" : value.replaceFirst("^0+(?=.)", "");
|
||||
int limit = Integer.parseInt(sValue);
|
||||
ModNetwork.CHANNEL.sendToServer(new SetGlobalScalingLimitC2SPacket(limit, this.menu.getBlockEntityPos()));
|
||||
} catch (NumberFormatException ignored) {
|
||||
// 输入值无效,重置为0
|
||||
inputField.setValue("0");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private EditBox createInputField(int x, int y) {
|
||||
EditBox input = new EditBox(this.font, x, y, INPUT_WIDTH, INPUT_HEIGHT, Component.empty());
|
||||
input.setMaxLength(6);
|
||||
input.setBordered(true);
|
||||
input.setValue("0");
|
||||
input.setTextColor(0xFFFFFF);
|
||||
// 添加数据校验响应器
|
||||
input.setResponder(s -> {
|
||||
try {
|
||||
String sValue = (s == null || s.isBlank()) ? "0" : s.replaceFirst("^0+(?=.)", "");
|
||||
if (!sValue.equals(s)) {
|
||||
input.setValue(sValue);
|
||||
}
|
||||
Integer.parseInt(sValue); // 验证是否为有效整数
|
||||
} catch (Throwable ignored) {
|
||||
// 输入无效,重置为0
|
||||
input.setValue("0");
|
||||
}
|
||||
});
|
||||
return input;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg(GuiGraphics gfx, float partialTicks, int mouseX, int mouseY) {
|
||||
// 半透明全屏遮罩,避免底层 HUD(准星/物品栏文字)透出
|
||||
gfx.fill(0, 0, this.width, this.height, 0xC0000000);
|
||||
|
||||
// 在按钮区域绘制一个半透明面板,提升可读性
|
||||
int pad = 6;
|
||||
int panelLeft = this.leftPos - pad;
|
||||
int panelTop = this.topPos - pad;
|
||||
int panelRight = this.leftPos + this.imageWidth + pad;
|
||||
int panelBottom = this.topPos + this.imageHeight + pad;
|
||||
gfx.fill(panelLeft, panelTop, panelRight, panelBottom, 0xA01E1E1E);
|
||||
// 边框
|
||||
gfx.fill(panelLeft, panelTop, panelRight, panelTop + 1, 0x80FFFFFF);
|
||||
gfx.fill(panelLeft, panelBottom - 1, panelRight, panelBottom, 0x80FFFFFF);
|
||||
gfx.fill(panelLeft, panelTop, panelLeft + 1, panelBottom, 0x80FFFFFF);
|
||||
gfx.fill(panelRight - 1, panelTop, panelRight, panelBottom, 0x80FFFFFF);
|
||||
// 将256x256背景图压缩/拉伸到界面尺寸
|
||||
gfx.blit(BACKGROUND, this.leftPos, this.topPos, this.imageWidth, this.imageHeight, 0, 0, 256, 256, 256, 256);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics gfx, int mouseX, int mouseY, float partialTicks) {
|
||||
this.renderBackground(gfx);
|
||||
public void render(@NotNull GuiGraphics gfx, int mouseX, int mouseY, float partialTicks) {
|
||||
super.render(gfx, mouseX, mouseY, partialTicks);
|
||||
gfx.drawString(this.font, CUSTOM_TITLE, this.leftPos + 10, this.topPos + 8, 0xFFFFFF, false);
|
||||
|
||||
int centerX = this.leftPos + this.imageWidth / 2;
|
||||
int row1Y = this.topPos + START_Y;
|
||||
int row2Y = row1Y + BTN_H + BTN_SPACING;
|
||||
int row3Y = row2Y + BTN_H + BTN_SPACING;
|
||||
int inputRowY = row3Y + LABEL_INPUT_SPACING;
|
||||
|
||||
// 计算居中位置并绘制标签
|
||||
int labelWidth = this.font.width(Component.translatable("gui.extendedae_plus.global.supplier_doubling_limit"));
|
||||
int totalWidth = labelWidth + 8 + INPUT_WIDTH + 6 + 16;
|
||||
int startX = centerX - totalWidth / 2;
|
||||
int labelX = startX;
|
||||
gfx.drawString(this.font, Component.translatable("gui.extendedae_plus.global.supplier_doubling_limit"), labelX, inputRowY + 4, 0x000000, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderLabels(GuiGraphics gfx, int mouseX, int mouseY) {
|
||||
// 不绘制默认的玩家物品栏标题(例如“物品栏”),避免与自定义面板重叠
|
||||
// 标题已在 render() 中手动绘制
|
||||
gfx.drawString(this.font, CUSTOM_TITLE, 8, 6, 0x404040, false);
|
||||
}
|
||||
|
||||
private static class AEStyleButton extends Button {
|
||||
private static final int TEXT_COLOR = 0xFFFFFF;
|
||||
private static final int BTN_BG = 0xFF3A3A3A;
|
||||
private static final int BTN_BG_HOVER = 0xFF4A4A4A;
|
||||
private static final int BTN_BORDER_LIGHT = 0xFFAAAAAA;
|
||||
private static final int BTN_BORDER_DARK = 0xFF555555;
|
||||
|
||||
public AEStyleButton(int x, int y, int width, int height, Component message, OnPress onPress) {
|
||||
super(x, y, width, height, message, onPress, DEFAULT_NARRATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderWidget(@NotNull GuiGraphics guiGraphics, int mouseX, int mouseY, float partial) {
|
||||
if (this.visible) {
|
||||
int bgColor = isHovered() && this.active ? BTN_BG_HOVER : BTN_BG;
|
||||
|
||||
// 填充背景
|
||||
guiGraphics.fill(getX(), getY(), getX() + width, getY() + height, bgColor);
|
||||
guiGraphics.fill(getX(), getY(), getX() + width, getY() + 1, BTN_BORDER_LIGHT);
|
||||
guiGraphics.fill(getX(), getY(), getX() + 1, getY() + height, BTN_BORDER_LIGHT);
|
||||
guiGraphics.fill(getX() + width - 1, getY(), getX() + width, getY() + height, BTN_BORDER_DARK);
|
||||
guiGraphics.fill(getX(), getY() + height - 1, getX() + width, getY() + height, BTN_BORDER_DARK);
|
||||
renderString(guiGraphics, Minecraft.getInstance().font, TEXT_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class AEConfirmButton extends Button {
|
||||
private final Component tooltip;
|
||||
|
||||
public AEConfirmButton(int x, int y, Component tooltip, OnPress onPress) {
|
||||
super(x, y, 16, 16, Component.empty(), onPress, DEFAULT_NARRATION);
|
||||
this.tooltip = tooltip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderWidget(@NotNull GuiGraphics guiGraphics, int mouseX, int mouseY, float partial) {
|
||||
if (this.visible) {
|
||||
Icon icon = Icon.VALID;
|
||||
Icon.TOOLBAR_BUTTON_BACKGROUND.getBlitter().dest(getX(), getY()).blit(guiGraphics);
|
||||
icon.getBlitter().dest(getX(), getY()).blit(guiGraphics);
|
||||
|
||||
// 绘制 Tooltip
|
||||
if (isHovered()) {
|
||||
guiGraphics.renderTooltip(Minecraft.getInstance().font, tooltip, mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,12 @@ import com.extendedae_plus.init.ModNetwork;
|
|||
import com.extendedae_plus.network.UploadEncodedPatternToProviderC2SPacket;
|
||||
import com.extendedae_plus.network.pattern.CancelPendingPatternC2SPacket;
|
||||
import com.extendedae_plus.util.uploadPattern.RecipeTypeNameConfig;
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
|
|
@ -15,7 +20,15 @@ import net.minecraftforge.fml.loading.FMLPaths;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
|
@ -75,11 +88,12 @@ public class ProviderSelectScreen extends Screen {
|
|||
|
||||
// 页面
|
||||
private int page = 0;
|
||||
private static final int PAGE_SIZE = 6;
|
||||
private static final int MIN_PAGE_SIZE = 4;
|
||||
private int pageSize = 6;
|
||||
|
||||
// 按钮池
|
||||
private final List<Button> entryButtons = new ArrayList<>();
|
||||
private final int[] buttonIndexMap = new int[PAGE_SIZE]; // 映射到 fIds 的索引
|
||||
private int[] buttonIndexMap = new int[pageSize]; // 映射到 fIds 的索引
|
||||
|
||||
// 缓存 Component JSON 解析
|
||||
private static final Map<String, String> componentCache = new HashMap<>();
|
||||
|
|
@ -113,7 +127,23 @@ public class ProviderSelectScreen extends Screen {
|
|||
entryButtons.clear();
|
||||
|
||||
int centerX = this.width / 2;
|
||||
int startY = this.height / 2 - 70;
|
||||
|
||||
// 动态计算页面大小,确保所有元素都能显示
|
||||
// 布局结构:搜索框(30) + 条目按钮 + 分页按钮(30) + 切换按钮(30) + 其他按钮(20) + 边距(40)
|
||||
int buttonHeight = 20;
|
||||
int gap = 5;
|
||||
int entryUnitHeight = buttonHeight + gap;
|
||||
int reservedHeight = 30 + 30 + 30 + 20 + 40;
|
||||
int availableHeight = this.height - reservedHeight;
|
||||
this.pageSize = Math.max(MIN_PAGE_SIZE, availableHeight / entryUnitHeight);
|
||||
|
||||
// 动态计算起始高度,使内容垂直居中
|
||||
int totalEntriesHeight = this.pageSize * entryUnitHeight;
|
||||
int contentHeight = 30 + totalEntriesHeight + 30 + 30 + 20;
|
||||
int startY = (this.height - contentHeight) / 2 + 30;
|
||||
|
||||
// 重新初始化按钮索引映射数组
|
||||
this.buttonIndexMap = new int[this.pageSize];
|
||||
|
||||
// 搜索框(置于条目上方)
|
||||
if (searchBox == null) {
|
||||
|
|
@ -137,9 +167,7 @@ public class ProviderSelectScreen extends Screen {
|
|||
|
||||
// 初始化按钮池
|
||||
int buttonWidth = 240;
|
||||
int buttonHeight = 20;
|
||||
int gap = 5;
|
||||
for (int i = 0; i < PAGE_SIZE; i++) {
|
||||
for (int i = 0; i < this.pageSize; i++) {
|
||||
int btnIdx = i;
|
||||
Button btn = Button.builder(Component.literal(""), b -> {
|
||||
int actualIdx = buttonIndexMap[btnIdx];
|
||||
|
|
@ -154,7 +182,7 @@ public class ProviderSelectScreen extends Screen {
|
|||
}
|
||||
|
||||
// 分页按钮
|
||||
int navY = startY + PAGE_SIZE * (buttonHeight + gap) + 10;
|
||||
int navY = startY + this.pageSize * (buttonHeight + gap) + 10;
|
||||
prevButton = Button.builder(Component.literal("<"), b -> changePage(-1))
|
||||
.bounds(centerX - 60, navY, 20, 20)
|
||||
.build();
|
||||
|
|
@ -174,16 +202,22 @@ public class ProviderSelectScreen extends Screen {
|
|||
int totalWidth = btnWidth2 + btnGap + inputWidth + btnGap + btnWidth2 * 2 + btnGap + btnWidth2;
|
||||
int startX = centerX - totalWidth / 2;
|
||||
|
||||
int toggleX = startX + btnWidth2 + btnGap + inputWidth + btnGap + btnWidth2 + btnGap;
|
||||
// 两个切换按钮从关闭按钮左侧开始,平分剩余空间(到删除映射按钮右侧)
|
||||
int toggleStartX = startX + btnWidth2 + btnGap + inputWidth + btnGap;
|
||||
// 删除映射按钮的右侧位置 = 重载 + 间距 + 输入框 + 间距 + 关闭 + 间距 + 添加 + 间距 + 删除
|
||||
int delByCnEndX = startX + btnWidth2 + btnGap + inputWidth + btnGap + btnWidth2 + btnGap + btnWidth2 + btnGap + btnWidth2;
|
||||
int toggleAvailableWidth = delByCnEndX - toggleStartX;
|
||||
int toggleGap = 5;
|
||||
int toggleWidth = (toggleAvailableWidth - toggleGap) / 2;
|
||||
int toggleY = navY + 30;
|
||||
|
||||
this.processingButtonsToggleButton = Button.builder(buildProcessingButtonsToggleLabel(), b -> toggleProcessingButtons())
|
||||
.bounds(toggleX, toggleY, btnWidth2, 20)
|
||||
.bounds(toggleStartX, toggleY, toggleWidth, 20)
|
||||
.build();
|
||||
this.addRenderableWidget(this.processingButtonsToggleButton);
|
||||
|
||||
this.autoUploadToggleButton = Button.builder(buildAutoUploadToggleLabel(), b -> toggleAutoUploadUniqueMatch())
|
||||
.bounds(toggleX + btnWidth2 + btnGap, toggleY, btnWidth2, 20)
|
||||
.bounds(toggleStartX + toggleWidth + toggleGap, toggleY, toggleWidth, 20)
|
||||
.build();
|
||||
this.addRenderableWidget(this.autoUploadToggleButton);
|
||||
|
||||
|
|
@ -227,15 +261,15 @@ public class ProviderSelectScreen extends Screen {
|
|||
|
||||
private void changePage(int delta) {
|
||||
int newPage = page + delta;
|
||||
if (newPage < 0 || newPage * PAGE_SIZE >= fIds.size()) return;
|
||||
if (newPage < 0 || newPage * pageSize >= fIds.size()) return;
|
||||
page = newPage;
|
||||
refreshButtons();
|
||||
}
|
||||
|
||||
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++) {
|
||||
int start = page * pageSize;
|
||||
int end = Math.min(start + pageSize, fIds.size());
|
||||
for (int i = 0; i < pageSize; i++) {
|
||||
Button btn = entryButtons.get(i);
|
||||
int idx = start + i;
|
||||
if (idx < end) {
|
||||
|
|
@ -250,7 +284,7 @@ public class ProviderSelectScreen extends Screen {
|
|||
}
|
||||
}
|
||||
if (prevButton != null) prevButton.active = page > 0;
|
||||
if (nextButton != null) nextButton.active = fIds.size() > (page + 1) * PAGE_SIZE;
|
||||
if (nextButton != null) nextButton.active = fIds.size() > (page + 1) * pageSize;
|
||||
}
|
||||
|
||||
private void reloadMapping() {
|
||||
|
|
|
|||
|
|
@ -131,6 +131,12 @@ public final class ModNetwork {
|
|||
.consumerNetworkThread(GlobalToggleProviderModesC2SPacket::handle)
|
||||
.add();
|
||||
|
||||
CHANNEL.messageBuilder(SetGlobalScalingLimitC2SPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER)
|
||||
.encoder(SetGlobalScalingLimitC2SPacket::encode)
|
||||
.decoder(SetGlobalScalingLimitC2SPacket::decode)
|
||||
.consumerNetworkThread(SetGlobalScalingLimitC2SPacket::handle)
|
||||
.add();
|
||||
|
||||
CHANNEL.messageBuilder(ToggleEntityTickerC2SPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER)
|
||||
.encoder(ToggleEntityTickerC2SPacket::encode)
|
||||
.decoder(ToggleEntityTickerC2SPacket::decode)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@ package com.extendedae_plus.mixin.advancedae.client.gui;
|
|||
|
||||
import appeng.api.config.YesNo;
|
||||
import appeng.client.gui.AEBaseScreen;
|
||||
import appeng.client.gui.Icon;
|
||||
import appeng.client.gui.style.ScreenStyle;
|
||||
import appeng.client.gui.widgets.AETextField;
|
||||
import appeng.client.gui.widgets.SettingToggleButton;
|
||||
import com.extendedae_plus.api.IInputBackgroundRenderer;
|
||||
import com.extendedae_plus.api.advancedBlocking.IPatternProviderMenuAdvancedSync;
|
||||
import com.extendedae_plus.api.smartDoubling.IPatternProviderMenuDoublingSync;
|
||||
import com.extendedae_plus.init.ModNetwork;
|
||||
|
|
@ -11,9 +14,8 @@ import com.extendedae_plus.network.provider.SetPerProviderScalingLimitC2SPacket;
|
|||
import com.extendedae_plus.network.provider.ToggleAdvancedBlockingC2SPacket;
|
||||
import com.extendedae_plus.network.provider.ToggleSmartDoublingC2SPacket;
|
||||
import com.extendedae_plus.util.GuiUtil;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.components.Tooltip;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.pedroksl.advanced_ae.client.gui.AdvPatternProviderScreen;
|
||||
|
|
@ -24,31 +26,35 @@ 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.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.extendedae_plus.util.GuiUtil.createToggle;
|
||||
import static com.extendedae_plus.util.Logger.EAP$LOGGER;
|
||||
|
||||
/**
|
||||
* 为高级ae样板供应器界面添加“高级阻挡模式”按钮。
|
||||
* 为高级ae样板供应器界面添加"高级阻挡模式"按钮。
|
||||
* - 位于左侧工具栏
|
||||
* - 点击仅发送 C2S 切换请求;状态由 AE2 @GuiSync 回传决定
|
||||
*/
|
||||
@Mixin(AdvPatternProviderScreen.class)
|
||||
public abstract class AdvPatternProviderScreenMixin extends AEBaseScreen<AdvPatternProviderMenu> {
|
||||
public abstract class AdvPatternProviderScreenMixin extends AEBaseScreen<AdvPatternProviderMenu> implements IInputBackgroundRenderer {
|
||||
// 高级阻挡模式切换按钮
|
||||
@Unique private SettingToggleButton<YesNo> eap$AdvancedBlockingToggle;
|
||||
// 智能翻倍切换按钮
|
||||
@Unique private SettingToggleButton<YesNo> eap$SmartDoublingToggle;
|
||||
// 智能翻倍上限输入框
|
||||
@Unique private EditBox eap$PerProviderLimitInput;
|
||||
|
||||
@Unique private AETextField eap$PerProviderLimitInput;
|
||||
// 当前高级阻挡模式是否启用
|
||||
@Unique private boolean eap$AdvancedBlockingEnabled = false;
|
||||
// 当前智能翻倍是否启用
|
||||
@Unique private boolean eap$SmartDoublingEnabled = false;
|
||||
// 当前智能翻倍上限
|
||||
@Unique private int eap$PerProviderScalingLimit = 0;
|
||||
@Unique private int eap$inputBgX;
|
||||
@Unique private int eap$inputBgY;
|
||||
@Unique private int eap$inputBgW;
|
||||
@Unique private int eap$inputBgH;
|
||||
|
||||
public AdvPatternProviderScreenMixin(AdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style) {
|
||||
super(menu, playerInventory, title, style);
|
||||
|
|
@ -104,15 +110,14 @@ public abstract class AdvPatternProviderScreenMixin extends AEBaseScreen<AdvPatt
|
|||
this.eap$SmartDoublingToggle.set(eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO);
|
||||
this.addToLeftToolbar(this.eap$SmartDoublingToggle);
|
||||
|
||||
// 缩放上限输入框(使用 GuiUtil 抽离)
|
||||
this.eap$PerProviderLimitInput = GuiUtil.createPerProviderLimitInput(this.font, this.eap$PerProviderScalingLimit, limit -> {
|
||||
// 缩放上限输入框
|
||||
this.eap$PerProviderLimitInput = GuiUtil.createPerProviderLimitInput(this.style, this.font, this.eap$PerProviderScalingLimit, limit -> {
|
||||
this.eap$PerProviderScalingLimit = limit;
|
||||
ModNetwork.CHANNEL.sendToServer(new SetPerProviderScalingLimitC2SPacket(limit));
|
||||
});
|
||||
this.addRenderableWidget(this.eap$PerProviderLimitInput);
|
||||
}
|
||||
|
||||
/* ---------------------------- 注入点 ---------------------------- */
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void eap$onInit(AdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
|
||||
// 初始化时同步服务端状态并创建控件
|
||||
|
|
@ -165,31 +170,43 @@ public abstract class AdvPatternProviderScreenMixin extends AEBaseScreen<AdvPatt
|
|||
}
|
||||
|
||||
if (this.eap$SmartDoublingEnabled) {
|
||||
// 智能翻倍启用时,确保输入框可见
|
||||
if (!this.renderables.contains(this.eap$PerProviderLimitInput)) {
|
||||
this.addRenderableWidget(this.eap$PerProviderLimitInput);
|
||||
}
|
||||
// 未聚焦且内容为空时,显示0
|
||||
if (!focused && this.eap$PerProviderLimitInput.getValue().trim().isEmpty()) {
|
||||
this.eap$PerProviderLimitInput.setValue("0");
|
||||
}
|
||||
|
||||
// 定位输入框到智能翻倍按钮左侧
|
||||
Button ref = eap$SmartDoublingToggle;
|
||||
if (ref != null) {
|
||||
int ex = ref.getX() - this.eap$PerProviderLimitInput.getWidth() - 5;
|
||||
int ey = ref.getY() + 2;
|
||||
this.eap$PerProviderLimitInput.setX(ex);
|
||||
this.eap$PerProviderLimitInput.setY(ey);
|
||||
int visualWidth = this.eap$PerProviderLimitInput.getWidth() + 4 + this.font.width("_");
|
||||
int visualHeight = 16;
|
||||
int padding = 2;
|
||||
int ex = ref.getX() - visualWidth - 5 - padding;
|
||||
int ey = ref.getY() + (ref.getHeight() - visualHeight) / 2 - padding + 4;
|
||||
this.eap$PerProviderLimitInput.setX(ex + padding);
|
||||
this.eap$PerProviderLimitInput.setY(ey + padding);
|
||||
this.eap$inputBgX = ex;
|
||||
this.eap$inputBgY = ey;
|
||||
this.eap$inputBgW = visualWidth + padding * 2;
|
||||
this.eap$inputBgH = visualHeight + padding * 2;
|
||||
}
|
||||
|
||||
// 设置 tooltip
|
||||
String cur = this.eap$PerProviderLimitInput.getValue();
|
||||
if (cur.isBlank()) cur = "0";
|
||||
this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(Component.translatable("extendedae_plus.gui.per_provider_limit.tooltip", cur)));
|
||||
this.eap$PerProviderLimitInput.setTooltipMessage(Collections.singletonList(Component.translatable("extendedae_plus.gui.per_provider_limit.tooltip", cur)));
|
||||
} else {
|
||||
// 智能翻倍未启用时,移除输入框
|
||||
this.removeWidget(this.eap$PerProviderLimitInput);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eap$renderInputBackground(GuiGraphics guiGraphics) {
|
||||
if (this.eap$SmartDoublingEnabled
|
||||
&& this.eap$PerProviderLimitInput != null && this.eap$PerProviderLimitInput.isVisible()) {
|
||||
Icon.TOOLBAR_BUTTON_BACKGROUND.getBlitter()
|
||||
.dest(this.eap$inputBgX - 5, this.eap$inputBgY - 3, this.eap$inputBgW + 6, this.eap$inputBgH - 2)
|
||||
.blit(guiGraphics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@ package com.extendedae_plus.mixin.advancedae.client.gui;
|
|||
|
||||
import appeng.api.config.YesNo;
|
||||
import appeng.client.gui.AEBaseScreen;
|
||||
import appeng.client.gui.Icon;
|
||||
import appeng.client.gui.style.ScreenStyle;
|
||||
import appeng.client.gui.widgets.AETextField;
|
||||
import appeng.client.gui.widgets.SettingToggleButton;
|
||||
import com.extendedae_plus.api.IInputBackgroundRenderer;
|
||||
import com.extendedae_plus.api.advancedBlocking.IPatternProviderMenuAdvancedSync;
|
||||
import com.extendedae_plus.api.smartDoubling.IPatternProviderMenuDoublingSync;
|
||||
import com.extendedae_plus.init.ModNetwork;
|
||||
|
|
@ -11,9 +14,8 @@ import com.extendedae_plus.network.provider.SetPerProviderScalingLimitC2SPacket;
|
|||
import com.extendedae_plus.network.provider.ToggleAdvancedBlockingC2SPacket;
|
||||
import com.extendedae_plus.network.provider.ToggleSmartDoublingC2SPacket;
|
||||
import com.extendedae_plus.util.GuiUtil;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.components.Tooltip;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.pedroksl.advanced_ae.client.gui.SmallAdvPatternProviderScreen;
|
||||
|
|
@ -25,31 +27,35 @@ 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.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.extendedae_plus.util.GuiUtil.createToggle;
|
||||
import static com.extendedae_plus.util.Logger.EAP$LOGGER;
|
||||
|
||||
/**
|
||||
* 为高级ae样板供应器界面添加“高级阻挡模式”按钮。
|
||||
* 为高级ae样板供应器界面添加"高级阻挡模式"按钮。
|
||||
* - 位于左侧工具栏
|
||||
* - 点击仅发送 C2S 切换请求;状态由 AE2 @GuiSync 回传决定
|
||||
*/
|
||||
@Mixin(SmallAdvPatternProviderScreen.class)
|
||||
public abstract class SmallAdvPatternProviderScreenMixin extends AEBaseScreen<SmallAdvPatternProviderMenu> {
|
||||
public abstract class SmallAdvPatternProviderScreenMixin extends AEBaseScreen<SmallAdvPatternProviderMenu> implements IInputBackgroundRenderer {
|
||||
// 高级阻挡模式切换按钮
|
||||
@Unique private SettingToggleButton<YesNo> eap$AdvancedBlockingToggle;
|
||||
// 智能翻倍切换按钮
|
||||
@Unique private SettingToggleButton<YesNo> eap$SmartDoublingToggle;
|
||||
// 智能翻倍上限输入框
|
||||
@Unique private EditBox eap$PerProviderLimitInput;
|
||||
|
||||
@Unique private AETextField eap$PerProviderLimitInput;
|
||||
// 当前高级阻挡模式是否启用
|
||||
@Unique private boolean eap$AdvancedBlockingEnabled = false;
|
||||
// 当前智能翻倍是否启用
|
||||
@Unique private boolean eap$SmartDoublingEnabled = false;
|
||||
// 当前智能翻倍上限
|
||||
@Unique private int eap$PerProviderScalingLimit = 0;
|
||||
@Unique private int eap$inputBgX;
|
||||
@Unique private int eap$inputBgY;
|
||||
@Unique private int eap$inputBgW;
|
||||
@Unique private int eap$inputBgH;
|
||||
|
||||
public SmallAdvPatternProviderScreenMixin(SmallAdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style) {
|
||||
super(menu, playerInventory, title, style);
|
||||
|
|
@ -105,15 +111,14 @@ public abstract class SmallAdvPatternProviderScreenMixin extends AEBaseScreen<Sm
|
|||
this.eap$SmartDoublingToggle.set(eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO);
|
||||
this.addToLeftToolbar(this.eap$SmartDoublingToggle);
|
||||
|
||||
// 缩放上限输入框(使用 GuiUtil 抽离)
|
||||
this.eap$PerProviderLimitInput = GuiUtil.createPerProviderLimitInput(this.font, this.eap$PerProviderScalingLimit, limit -> {
|
||||
// 缩放上限输入框
|
||||
this.eap$PerProviderLimitInput = GuiUtil.createPerProviderLimitInput(this.style, this.font, this.eap$PerProviderScalingLimit, limit -> {
|
||||
this.eap$PerProviderScalingLimit = limit;
|
||||
ModNetwork.CHANNEL.sendToServer(new SetPerProviderScalingLimitC2SPacket(limit));
|
||||
});
|
||||
this.addRenderableWidget(this.eap$PerProviderLimitInput);
|
||||
}
|
||||
|
||||
/* ---------------------------- 注入点 ---------------------------- */
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void eap$onInit(SmallAdvPatternProviderMenu menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
|
||||
// 初始化时同步服务端状态并创建控件
|
||||
|
|
@ -166,31 +171,43 @@ public abstract class SmallAdvPatternProviderScreenMixin extends AEBaseScreen<Sm
|
|||
}
|
||||
|
||||
if (this.eap$SmartDoublingEnabled) {
|
||||
// 智能翻倍启用时,确保输入框可见
|
||||
if (!this.renderables.contains(this.eap$PerProviderLimitInput)) {
|
||||
this.addRenderableWidget(this.eap$PerProviderLimitInput);
|
||||
}
|
||||
// 未聚焦且内容为空时,显示0
|
||||
if (!focused && this.eap$PerProviderLimitInput.getValue().trim().isEmpty()) {
|
||||
this.eap$PerProviderLimitInput.setValue("0");
|
||||
}
|
||||
|
||||
// 定位输入框到智能翻倍按钮左侧
|
||||
Button ref = eap$SmartDoublingToggle;
|
||||
if (ref != null) {
|
||||
int ex = ref.getX() - this.eap$PerProviderLimitInput.getWidth() - 5;
|
||||
int ey = ref.getY() + 2;
|
||||
this.eap$PerProviderLimitInput.setX(ex);
|
||||
this.eap$PerProviderLimitInput.setY(ey);
|
||||
int visualWidth = this.eap$PerProviderLimitInput.getWidth() + 4 + this.font.width("_");
|
||||
int visualHeight = 16;
|
||||
int padding = 2;
|
||||
int ex = ref.getX() - visualWidth - 5 - padding;
|
||||
int ey = ref.getY() + (ref.getHeight() - visualHeight) / 2 - padding + 4;
|
||||
this.eap$PerProviderLimitInput.setX(ex + padding);
|
||||
this.eap$PerProviderLimitInput.setY(ey + padding);
|
||||
this.eap$inputBgX = ex;
|
||||
this.eap$inputBgY = ey;
|
||||
this.eap$inputBgW = visualWidth + padding * 2;
|
||||
this.eap$inputBgH = visualHeight + padding * 2;
|
||||
}
|
||||
|
||||
// 设置 tooltip
|
||||
String cur = this.eap$PerProviderLimitInput.getValue();
|
||||
if (cur.isBlank()) cur = "0";
|
||||
this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(Component.translatable("extendedae_plus.gui.per_provider_limit.tooltip", cur)));
|
||||
this.eap$PerProviderLimitInput.setTooltipMessage(Collections.singletonList(Component.translatable("extendedae_plus.gui.per_provider_limit.tooltip", cur)));
|
||||
} else {
|
||||
// 智能翻倍未启用时,移除输入框
|
||||
this.removeWidget(this.eap$PerProviderLimitInput);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eap$renderInputBackground(GuiGraphics guiGraphics) {
|
||||
if (this.eap$SmartDoublingEnabled
|
||||
&& this.eap$PerProviderLimitInput != null && this.eap$PerProviderLimitInput.isVisible()) {
|
||||
Icon.TOOLBAR_BUTTON_BACKGROUND.getBlitter()
|
||||
.dest(this.eap$inputBgX - 5, this.eap$inputBgY - 3, this.eap$inputBgW + 6, this.eap$inputBgH - 2)
|
||||
.blit(guiGraphics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import appeng.client.gui.style.ScreenStyle;
|
|||
import appeng.client.gui.style.Text;
|
||||
import appeng.menu.slot.AppEngSlot;
|
||||
import com.extendedae_plus.api.IExPatternPage;
|
||||
import com.extendedae_plus.api.IInputBackgroundRenderer;
|
||||
import com.extendedae_plus.content.ClientPatternHighlightStore;
|
||||
import com.extendedae_plus.init.ModNetwork;
|
||||
import com.extendedae_plus.mixin.ae2.accessor.AEBaseScreenAccessor;
|
||||
|
|
@ -226,4 +227,12 @@ public abstract class AEBaseScreenMixin {
|
|||
guiGraphics.pose().popPose();
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
@Inject(method = "drawBG", at = @At("TAIL"), remap = false)
|
||||
private void eap$renderInputBackground(GuiGraphics guiGraphics, int offsetX, int offsetY, int mouseX, int mouseY, float partialTicks, CallbackInfo ci) {
|
||||
Object self = this;
|
||||
if (self instanceof IInputBackgroundRenderer renderer) {
|
||||
renderer.eap$renderInputBackground(guiGraphics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,14 @@ package com.extendedae_plus.mixin.ae2.client.gui.patternProvider;
|
|||
|
||||
import appeng.api.config.YesNo;
|
||||
import appeng.client.gui.AEBaseScreen;
|
||||
import appeng.client.gui.Icon;
|
||||
import appeng.client.gui.implementations.PatternProviderScreen;
|
||||
import appeng.client.gui.style.ScreenStyle;
|
||||
import appeng.client.gui.widgets.AETextField;
|
||||
import appeng.client.gui.widgets.SettingToggleButton;
|
||||
import appeng.menu.implementations.PatternProviderMenu;
|
||||
import com.extendedae_plus.api.IExPatternButton;
|
||||
import com.extendedae_plus.api.IInputBackgroundRenderer;
|
||||
import com.extendedae_plus.api.advancedBlocking.IPatternProviderMenuAdvancedSync;
|
||||
import com.extendedae_plus.api.smartDoubling.IPatternProviderMenuDoublingSync;
|
||||
import com.extendedae_plus.init.ModNetwork;
|
||||
|
|
@ -15,9 +18,8 @@ import com.extendedae_plus.network.provider.ToggleAdvancedBlockingC2SPacket;
|
|||
import com.extendedae_plus.network.provider.ToggleSmartDoublingC2SPacket;
|
||||
import com.extendedae_plus.util.GuiUtil;
|
||||
import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.components.Tooltip;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
|
@ -26,32 +28,36 @@ 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.Collections;
|
||||
import java.util.List;
|
||||
|
||||
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 PatternProviderSmartFeaturesMixin<C extends PatternProviderMenu> extends AEBaseScreen<C> {
|
||||
public abstract class PatternProviderSmartFeaturesMixin<C extends PatternProviderMenu> extends AEBaseScreen<C> implements IInputBackgroundRenderer {
|
||||
|
||||
// 高级阻挡模式切换按钮
|
||||
@Unique private SettingToggleButton<YesNo> eap$AdvancedBlockingToggle;
|
||||
// 智能翻倍切换按钮
|
||||
@Unique private SettingToggleButton<YesNo> eap$SmartDoublingToggle;
|
||||
// 智能翻倍上限输入框
|
||||
@Unique private EditBox eap$PerProviderLimitInput;
|
||||
|
||||
@Unique private AETextField eap$PerProviderLimitInput;
|
||||
// 当前高级阻挡模式是否启用
|
||||
@Unique private boolean eap$AdvancedBlockingEnabled = false;
|
||||
// 当前智能翻倍是否启用
|
||||
@Unique private boolean eap$SmartDoublingEnabled = false;
|
||||
// 当前智能翻倍上限
|
||||
@Unique private int eap$PerProviderScalingLimit = 0;
|
||||
@Unique private int eap$inputBgX;
|
||||
@Unique private int eap$inputBgY;
|
||||
@Unique private int eap$inputBgW;
|
||||
@Unique private int eap$inputBgH;
|
||||
|
||||
public PatternProviderSmartFeaturesMixin(C menu, Inventory playerInventory, Component title, ScreenStyle style) {
|
||||
super(menu, playerInventory, title, style);
|
||||
|
|
@ -107,15 +113,14 @@ public abstract class PatternProviderSmartFeaturesMixin<C extends PatternProvide
|
|||
this.eap$SmartDoublingToggle.set(eap$SmartDoublingEnabled ? YesNo.YES : YesNo.NO);
|
||||
this.addToLeftToolbar(this.eap$SmartDoublingToggle);
|
||||
|
||||
// 缩放上限输入框(使用 GuiUtil 抽离)
|
||||
this.eap$PerProviderLimitInput = GuiUtil.createPerProviderLimitInput(this.font, this.eap$PerProviderScalingLimit, limit -> {
|
||||
// 缩放上限输入框
|
||||
this.eap$PerProviderLimitInput = GuiUtil.createPerProviderLimitInput(this.style, this.font, this.eap$PerProviderScalingLimit, limit -> {
|
||||
this.eap$PerProviderScalingLimit = limit;
|
||||
ModNetwork.CHANNEL.sendToServer(new SetPerProviderScalingLimitC2SPacket(limit));
|
||||
});
|
||||
this.addRenderableWidget(this.eap$PerProviderLimitInput);
|
||||
}
|
||||
|
||||
/* ---------------------------- 注入点 ---------------------------- */
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
private void eap$onInit(C menu, Inventory playerInventory, Component title, ScreenStyle style, CallbackInfo ci) {
|
||||
// 初始化时同步服务端状态并创建控件
|
||||
|
|
@ -169,30 +174,32 @@ public abstract class PatternProviderSmartFeaturesMixin<C extends PatternProvide
|
|||
}
|
||||
|
||||
if (this.eap$SmartDoublingEnabled) {
|
||||
// 智能翻倍启用时,确保输入框可见
|
||||
if (!this.renderables.contains(this.eap$PerProviderLimitInput)) {
|
||||
this.addRenderableWidget(this.eap$PerProviderLimitInput);
|
||||
}
|
||||
// 未聚焦且内容为空时,显示0
|
||||
if (!focused && this.eap$PerProviderLimitInput.getValue().trim().isEmpty()) {
|
||||
this.eap$PerProviderLimitInput.setValue("0");
|
||||
}
|
||||
|
||||
// 定位输入框到智能翻倍按钮左侧
|
||||
Button ref = eap$SmartDoublingToggle;
|
||||
if (ref != null) {
|
||||
int ex = ref.getX() - this.eap$PerProviderLimitInput.getWidth() - 5;
|
||||
int ey = ref.getY() + 2;
|
||||
this.eap$PerProviderLimitInput.setX(ex);
|
||||
this.eap$PerProviderLimitInput.setY(ey);
|
||||
int visualWidth = this.eap$PerProviderLimitInput.getWidth() + 4 + this.font.width("_");
|
||||
int visualHeight = 16;
|
||||
int padding = 2;
|
||||
int ex = ref.getX() - visualWidth - 5 - padding;
|
||||
int ey = ref.getY() + (ref.getHeight() - visualHeight) / 2 - padding + 4;
|
||||
this.eap$PerProviderLimitInput.setX(ex + padding);
|
||||
this.eap$PerProviderLimitInput.setY(ey + padding);
|
||||
this.eap$inputBgX = ex;
|
||||
this.eap$inputBgY = ey;
|
||||
this.eap$inputBgW = visualWidth + padding * 2;
|
||||
this.eap$inputBgH = visualHeight + padding * 2;
|
||||
}
|
||||
|
||||
// 设置 tooltip
|
||||
String cur = this.eap$PerProviderLimitInput.getValue();
|
||||
if (cur.isBlank()) cur = "0";
|
||||
this.eap$PerProviderLimitInput.setTooltip(Tooltip.create(Component.translatable("extendedae_plus.gui.per_provider_limit.tooltip", cur)));
|
||||
this.eap$PerProviderLimitInput.setTooltipMessage(Collections.singletonList(Component.translatable("extendedae_plus.gui.per_provider_limit.tooltip", cur)));
|
||||
} else {
|
||||
// 智能翻倍未启用时,移除输入框
|
||||
this.removeWidget(this.eap$PerProviderLimitInput);
|
||||
}
|
||||
}
|
||||
|
|
@ -221,4 +228,14 @@ public abstract class PatternProviderSmartFeaturesMixin<C extends PatternProvide
|
|||
this.setTextContent(AEBaseScreen.TEXT_ID_DIALOG_TITLE, t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eap$renderInputBackground(GuiGraphics guiGraphics) {
|
||||
if (this.eap$SmartDoublingEnabled
|
||||
&& this.eap$PerProviderLimitInput != null && this.eap$PerProviderLimitInput.isVisible()) {
|
||||
Icon.TOOLBAR_BUTTON_BACKGROUND.getBlitter()
|
||||
.dest(this.eap$inputBgX - 5, this.eap$inputBgY - 3, this.eap$inputBgW + 6, this.eap$inputBgH - 2)
|
||||
.blit(guiGraphics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,132 @@
|
|||
package com.extendedae_plus.network.provider;
|
||||
|
||||
import appeng.api.networking.IGrid;
|
||||
import appeng.blockentity.crafting.PatternProviderBlockEntity;
|
||||
import appeng.helpers.patternprovider.PatternProviderLogic;
|
||||
import appeng.helpers.patternprovider.PatternProviderLogicHost;
|
||||
import appeng.parts.crafting.PatternProviderPart;
|
||||
import com.extendedae_plus.api.smartDoubling.ISmartDoublingHolder;
|
||||
import com.extendedae_plus.content.controller.NetworkPatternControllerBlockEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* C2S: 设置网络中所有样板供应器的翻倍限制值
|
||||
*/
|
||||
public class SetGlobalScalingLimitC2SPacket {
|
||||
private final int limit;
|
||||
private final BlockPos controllerPos;
|
||||
|
||||
public SetGlobalScalingLimitC2SPacket(int limit, BlockPos controllerPos) {
|
||||
this.limit = limit;
|
||||
this.controllerPos = controllerPos;
|
||||
}
|
||||
|
||||
public static void encode(SetGlobalScalingLimitC2SPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeInt(msg.limit);
|
||||
buf.writeBlockPos(msg.controllerPos);
|
||||
}
|
||||
|
||||
public static SetGlobalScalingLimitC2SPacket decode(FriendlyByteBuf buf) {
|
||||
int limit = buf.readInt();
|
||||
BlockPos pos = buf.readBlockPos();
|
||||
return new SetGlobalScalingLimitC2SPacket(limit, pos);
|
||||
}
|
||||
|
||||
public static void handle(SetGlobalScalingLimitC2SPacket msg, Supplier<NetworkEvent.Context> ctxSupplier) {
|
||||
var ctx = ctxSupplier.get();
|
||||
ctx.enqueueWork(() -> {
|
||||
ServerPlayer player = ctx.getSender();
|
||||
if (player == null) return;
|
||||
|
||||
var level = player.serverLevel();
|
||||
var be = level.getBlockEntity(msg.controllerPos);
|
||||
if (!(be instanceof NetworkPatternControllerBlockEntity controller)) return;
|
||||
var node = controller.getGridNode(null);
|
||||
if (node == null) return;
|
||||
IGrid grid = node.getGrid();
|
||||
if (grid == null) return;
|
||||
|
||||
int affected = applyToAllProviders(grid, msg.limit);
|
||||
player.displayClientMessage(Component.translatable("extendedae_plus.chat.pattern_provider.global_scaling_limit_applied", affected, msg.limit), true);
|
||||
});
|
||||
ctx.setPacketHandled(true);
|
||||
}
|
||||
|
||||
private static int applyToAllProviders(IGrid grid, int limit) {
|
||||
int affected = 0;
|
||||
Set<PatternProviderLogic> all = new HashSet<>();
|
||||
|
||||
// 方块形式的样板供应器
|
||||
try {
|
||||
Set<PatternProviderBlockEntity> blocksAll = grid.getMachines(PatternProviderBlockEntity.class);
|
||||
Set<PatternProviderBlockEntity> blocksActive = grid.getActiveMachines(PatternProviderBlockEntity.class);
|
||||
for (PatternProviderBlockEntity be : blocksAll) if (be != null && be.getLogic() != null) all.add(be.getLogic());
|
||||
for (PatternProviderBlockEntity be : blocksActive) if (be != null && be.getLogic() != null) all.add(be.getLogic());
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
// Part 形式的样板供应器
|
||||
try {
|
||||
Set<PatternProviderPart> partsAll = grid.getMachines(PatternProviderPart.class);
|
||||
Set<PatternProviderPart> partsActive = grid.getActiveMachines(PatternProviderPart.class);
|
||||
for (PatternProviderPart part : partsAll) if (part != null && part.getLogic() != null) all.add(part.getLogic());
|
||||
for (PatternProviderPart part : partsActive) if (part != null && part.getLogic() != null) all.add(part.getLogic());
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
// 兼容 PatternProviderLogicHost
|
||||
try {
|
||||
Set<PatternProviderLogicHost> hostsAll = grid.getMachines(PatternProviderLogicHost.class);
|
||||
Set<PatternProviderLogicHost> hostsActive = grid.getActiveMachines(PatternProviderLogicHost.class);
|
||||
for (PatternProviderLogicHost host : hostsAll) if (host != null && host.getLogic() != null) all.add(host.getLogic());
|
||||
for (PatternProviderLogicHost host : hostsActive) if (host != null && host.getLogic() != null) all.add(host.getLogic());
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
// 兼容 ExtendedAE
|
||||
collectByClassName(grid, all, "com.glodblock.github.extendedae.common.parts.PartExPatternProvider");
|
||||
collectByClassName(grid, all, "com.glodblock.github.extendedae.common.tileentities.TileExPatternProvider");
|
||||
|
||||
for (PatternProviderLogic logic : all) {
|
||||
if (applyToLogic(logic, limit)) affected++;
|
||||
}
|
||||
return affected;
|
||||
}
|
||||
|
||||
private static void collectByClassName(IGrid grid, Set<PatternProviderLogic> out, String className) {
|
||||
try {
|
||||
Class<?> cls = Class.forName(className);
|
||||
Set<?> all = grid.getMachines((Class) cls);
|
||||
Set<?> active = grid.getActiveMachines((Class) cls);
|
||||
for (Object o : all) addLogicIfPresent(out, o);
|
||||
for (Object o : active) addLogicIfPresent(out, o);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
private static void addLogicIfPresent(Set<PatternProviderLogic> out, Object o) {
|
||||
try {
|
||||
if (o instanceof PatternProviderLogicHost host) {
|
||||
var logic = host.getLogic();
|
||||
if (logic != null) out.add(logic);
|
||||
return;
|
||||
}
|
||||
var m = o.getClass().getMethod("getLogic");
|
||||
Object ret = m.invoke(o);
|
||||
if (ret instanceof PatternProviderLogic logic) out.add(logic);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
private static boolean applyToLogic(PatternProviderLogic logic, int limit) {
|
||||
if (logic instanceof ISmartDoublingHolder holder) {
|
||||
holder.eap$setProviderSmartDoublingLimit(limit);
|
||||
logic.saveChanges();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@ import appeng.api.crafting.PatternDetailsHelper;
|
|||
import appeng.api.stacks.GenericStack;
|
||||
import appeng.client.gui.me.patternaccess.PatternContainerRecord;
|
||||
import appeng.client.gui.me.patternaccess.PatternSlot;
|
||||
import appeng.client.gui.style.ScreenStyle;
|
||||
import appeng.client.gui.widgets.AETextField;
|
||||
import appeng.client.gui.widgets.SettingToggleButton;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
|
|
@ -208,14 +210,16 @@ public class GuiUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* 创建用于每个提供者缩放上限的输入框,包含值清洗与回调处理
|
||||
* 创建用于每个提供者缩放上限的输入框,使用 AE2 原生样式
|
||||
* @param style ScreenStyle 用于获取颜色配置
|
||||
* @param font 字体对象
|
||||
* @param initialValue 初始数值
|
||||
* @param onCommit 当值解析成功后回调(以 int 形式提供)
|
||||
*/
|
||||
public static EditBox createPerProviderLimitInput(Font font, int initialValue, IntConsumer onCommit) {
|
||||
EditBox input = new EditBox(font, 0, 0, 28, 12, Component.literal("Limit"));
|
||||
public static AETextField createPerProviderLimitInput(ScreenStyle style, Font font, int initialValue, IntConsumer onCommit) {
|
||||
AETextField input = new AETextField(style, font, 0, 0, 32, 16);
|
||||
input.setMaxLength(6);
|
||||
input.setBordered(false);
|
||||
input.setValue(String.valueOf(initialValue));
|
||||
input.setResponder(s -> {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
"gui.extendedae_plus.global.toggle_smart_doubling": "Toggle Smart Doubling",
|
||||
"gui.extendedae_plus.global.all_on": "All On",
|
||||
"gui.extendedae_plus.global.all_off": "All Off",
|
||||
"gui.extendedae_plus.global.supplier_doubling_limit": "Supplier Doubling Limit:",
|
||||
"gui.extendedae_plus.global.confirm_tooltip": "Confirm doubling limit value",
|
||||
"extendedae_plus.chat.pattern_provider.global_scaling_limit_applied": "Set scaling limit to %2$s for %1$s providers",
|
||||
"gui.extendedae.pattern_page": "Page %s/%s",
|
||||
|
||||
"itemGroup.extendedae_plus.main": "ExtendedAE Plus",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
"gui.extendedae_plus.global.toggle_smart_doubling": "切换智能翻倍",
|
||||
"gui.extendedae_plus.global.all_on": "全部开启",
|
||||
"gui.extendedae_plus.global.all_off": "全部关闭",
|
||||
"gui.extendedae_plus.global.supplier_doubling_limit": "供应器翻倍限制设置:",
|
||||
"gui.extendedae_plus.global.confirm_tooltip": "确认设置翻倍限制数值",
|
||||
"extendedae_plus.chat.pattern_provider.global_scaling_limit_applied": "已为 %s 个供应器设置翻倍限制为 %s",
|
||||
"gui.extendedae.pattern_page": "第%s页/%s页",
|
||||
|
||||
"itemGroup.extendedae_plus.main": "扩展AE Plus",
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 471 B After Width: | Height: | Size: 455 B |
Binary file not shown.
|
Before Width: | Height: | Size: 467 B After Width: | Height: | Size: 426 B |
Loading…
Reference in New Issue
Block a user