一、调整样板供应器状态控制器界面样式,使用ae背景图片
二、添加全局设置样板供应器级别翻倍限制
This commit is contained in:
C-H716 2026-06-03 21:04:04 +08:00
parent 75817040a2
commit 5d704a2b3e
5 changed files with 308 additions and 45 deletions

View File

@ -1,109 +1,228 @@
package com.extendedae_plus.client.screen; package com.extendedae_plus.client.screen;
import appeng.client.gui.Icon;
import com.extendedae_plus.init.ModNetwork; import com.extendedae_plus.init.ModNetwork;
import com.extendedae_plus.menu.NetworkPatternControllerMenu; import com.extendedae_plus.menu.NetworkPatternControllerMenu;
import com.extendedae_plus.network.provider.GlobalToggleProviderModesC2SPacket; 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.GuiGraphics;
import net.minecraft.client.gui.components.Button; 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.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import org.jetbrains.annotations.NotNull;
public class GlobalProviderModesScreen extends AbstractContainerScreen<NetworkPatternControllerMenu> { public class GlobalProviderModesScreen extends AbstractContainerScreen<NetworkPatternControllerMenu> {
private static final Component CUSTOM_TITLE = Component.translatable("block.extendedae_plus.network_pattern_controller"); 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) { public GlobalProviderModesScreen(NetworkPatternControllerMenu menu, Inventory inv, Component title) {
super(menu, inv, title); super(menu, inv, title);
this.imageWidth = 240; this.imageWidth = IMAGE_WIDTH;
this.imageHeight = 140; this.imageHeight = IMAGE_HEIGHT;
} }
@Override @Override
protected void init() { protected void init() {
super.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三个单项切换 int centerX = this.leftPos + this.imageWidth / 2;
addRenderableWidget(Button.builder(Component.translatable("gui.extendedae_plus.global.toggle_blocking"), b -> 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( ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket(
GlobalToggleProviderModesC2SPacket.Op.TOGGLE, GlobalToggleProviderModesC2SPacket.Op.TOGGLE,
GlobalToggleProviderModesC2SPacket.Op.NOOP, GlobalToggleProviderModesC2SPacket.Op.NOOP,
GlobalToggleProviderModesC2SPacket.Op.NOOP, GlobalToggleProviderModesC2SPacket.Op.NOOP,
this.menu.getBlockEntityPos() 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( ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket(
GlobalToggleProviderModesC2SPacket.Op.NOOP, GlobalToggleProviderModesC2SPacket.Op.NOOP,
GlobalToggleProviderModesC2SPacket.Op.TOGGLE, GlobalToggleProviderModesC2SPacket.Op.TOGGLE,
GlobalToggleProviderModesC2SPacket.Op.NOOP, GlobalToggleProviderModesC2SPacket.Op.NOOP,
this.menu.getBlockEntityPos() 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( ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket(
GlobalToggleProviderModesC2SPacket.Op.NOOP, GlobalToggleProviderModesC2SPacket.Op.NOOP,
GlobalToggleProviderModesC2SPacket.Op.NOOP, GlobalToggleProviderModesC2SPacket.Op.NOOP,
GlobalToggleProviderModesC2SPacket.Op.TOGGLE, GlobalToggleProviderModesC2SPacket.Op.TOGGLE,
this.menu.getBlockEntityPos() this.menu.getBlockEntityPos()
))).bounds(x + (w + s) * 2, y, w, h).build()); ))));
// 行2一键全开/全关 addRenderableWidget(new AEStyleButton(row2X, row2Y, BTN_W, BTN_H,
int y2 = y + h + 12; Component.translatable("gui.extendedae_plus.global.all_on"), b ->
// 第二行两列按钮总宽并居中
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 ->
ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket( ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket(
GlobalToggleProviderModesC2SPacket.Op.SET_TRUE, GlobalToggleProviderModesC2SPacket.Op.SET_TRUE,
GlobalToggleProviderModesC2SPacket.Op.SET_TRUE, GlobalToggleProviderModesC2SPacket.Op.SET_TRUE,
GlobalToggleProviderModesC2SPacket.Op.SET_TRUE, GlobalToggleProviderModesC2SPacket.Op.SET_TRUE,
this.menu.getBlockEntityPos() 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( ModNetwork.CHANNEL.sendToServer(new GlobalToggleProviderModesC2SPacket(
GlobalToggleProviderModesC2SPacket.Op.SET_FALSE, GlobalToggleProviderModesC2SPacket.Op.SET_FALSE,
GlobalToggleProviderModesC2SPacket.Op.SET_FALSE, GlobalToggleProviderModesC2SPacket.Op.SET_FALSE,
GlobalToggleProviderModesC2SPacket.Op.SET_FALSE, GlobalToggleProviderModesC2SPacket.Op.SET_FALSE,
this.menu.getBlockEntityPos() 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 @Override
protected void renderBg(GuiGraphics gfx, float partialTicks, int mouseX, int mouseY) { protected void renderBg(GuiGraphics gfx, float partialTicks, int mouseX, int mouseY) {
// 半透明全屏遮罩避免底层 HUD准星/物品栏文字透出 // 将256x256背景图压缩/拉伸到界面尺寸
gfx.fill(0, 0, this.width, this.height, 0xC0000000); gfx.blit(BACKGROUND, this.leftPos, this.topPos, this.imageWidth, this.imageHeight, 0, 0, 256, 256, 256, 256);
// 在按钮区域绘制一个半透明面板提升可读性
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);
} }
@Override @Override
public void render(GuiGraphics gfx, int mouseX, int mouseY, float partialTicks) { public void render(@NotNull GuiGraphics gfx, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(gfx);
super.render(gfx, mouseX, mouseY, 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 @Override
protected void renderLabels(GuiGraphics gfx, int mouseX, int mouseY) { protected void renderLabels(GuiGraphics gfx, int mouseX, int mouseY) {
// 不绘制默认的玩家物品栏标题例如物品栏避免与自定义面板重叠 gfx.drawString(this.font, CUSTOM_TITLE, 8, 6, 0x404040, false);
// 标题已在 render() 中手动绘制 }
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);
}
}
}
} }
} }

View File

@ -131,6 +131,12 @@ public final class ModNetwork {
.consumerNetworkThread(GlobalToggleProviderModesC2SPacket::handle) .consumerNetworkThread(GlobalToggleProviderModesC2SPacket::handle)
.add(); .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) CHANNEL.messageBuilder(ToggleEntityTickerC2SPacket.class, nextId(), NetworkDirection.PLAY_TO_SERVER)
.encoder(ToggleEntityTickerC2SPacket::encode) .encoder(ToggleEntityTickerC2SPacket::encode)
.decoder(ToggleEntityTickerC2SPacket::decode) .decoder(ToggleEntityTickerC2SPacket::decode)

View File

@ -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;
}
}

View File

@ -8,6 +8,9 @@
"gui.extendedae_plus.global.toggle_smart_doubling": "Toggle Smart Doubling", "gui.extendedae_plus.global.toggle_smart_doubling": "Toggle Smart Doubling",
"gui.extendedae_plus.global.all_on": "All On", "gui.extendedae_plus.global.all_on": "All On",
"gui.extendedae_plus.global.all_off": "All Off", "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", "gui.extendedae.pattern_page": "Page %s/%s",
"itemGroup.extendedae_plus.main": "ExtendedAE Plus", "itemGroup.extendedae_plus.main": "ExtendedAE Plus",

View File

@ -8,6 +8,9 @@
"gui.extendedae_plus.global.toggle_smart_doubling": "切换智能翻倍", "gui.extendedae_plus.global.toggle_smart_doubling": "切换智能翻倍",
"gui.extendedae_plus.global.all_on": "全部开启", "gui.extendedae_plus.global.all_on": "全部开启",
"gui.extendedae_plus.global.all_off": "全部关闭", "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页", "gui.extendedae.pattern_page": "第%s页/%s页",
"itemGroup.extendedae_plus.main": "扩展AE Plus", "itemGroup.extendedae_plus.main": "扩展AE Plus",