feat: 内嵌configuration用于配置界面显示

This commit is contained in:
C-H716 2025-09-14 20:07:52 +08:00
parent 71351ec9c1
commit 6d45627cbe
22 changed files with 205 additions and 360 deletions

View File

@ -41,5 +41,6 @@ ExtendedAE Plus 是一个面向 Applied Energistics 2 与 ExtendedAE 的功能
- Applied Energistics 2AE2MIT License
- SpongePowered MixinMIT License
- Configurationby TomaMIT License
请查阅各上游项目以获取完整与最新的许可证信息。第三方组件的许可证与版权归其各自作者所有。

View File

@ -1,6 +1,7 @@
plugins {
id 'dev.architectury.loom' version '1.10-SNAPSHOT'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '8.1.1'
}
group = project.maven_group
@ -80,7 +81,7 @@ dependencies {
annotationProcessor "org.spongepowered:mixin:${mixin_version}:processor"
modCompileOnly "curse.maven:applied-flux-965012:${applied_flux_version}"
modCompileOnly "curse.maven:applied-flux-965012:${applied_flux_version}"
modCompileOnly "curse.maven:mega-cells-622112:${mega_cells_version}"
modCompileOnly "curse.maven:jade-324717:${jade_version}"
@ -115,6 +116,10 @@ dependencies {
modRuntimeOnly "curse.maven:geckolib-388172:6920925"
//mclib运行时
forgeRuntimeLibrary "com.eliotlash.mclib:mclib:20"
// compileOnly
include "curse.maven:configuration-444699:4710266"
modImplementation "curse.maven:configuration-444699:4710266"
}
allprojects {

View File

@ -2,7 +2,7 @@ package com.extendedae_plus;
import appeng.menu.locator.MenuLocators;
import com.extendedae_plus.client.ClientRegistrar;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import com.extendedae_plus.init.*;
import com.extendedae_plus.menu.locator.CuriosItemLocator;
import net.minecraft.resources.ResourceLocation;
@ -11,10 +11,7 @@ import net.minecraftforge.client.event.ModelEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@ -49,9 +46,9 @@ public class ExtendedAEPlus {
// 注册到Forge事件总线
MinecraftForge.EVENT_BUS.register(this);
// 注册通用配置
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModConfigs.COMMON_SPEC);
ModConfig.init();
// ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModConfigs.COMMON_SPEC);
}
/**
@ -89,7 +86,7 @@ public class ExtendedAEPlus {
public static void onClientSetup(final FMLClientSetupEvent event) {
// 直接在此处执行客户端一次性注册UI/屏幕/渲染器绑定
// 注册客户端配置界面
ClientRegistrar.registerConfigScreen();
// ClientRegistrar.registerConfigScreen();
// InitScreens 的注册委托给 ClientRegistrar便于集中管理客户端注册逻辑
ClientRegistrar.registerInitScreens();

View File

@ -6,7 +6,7 @@ import appeng.menu.implementations.UpgradeableMenu;
import appeng.menu.slot.OptionalFakeSlot;
import com.extendedae_plus.ae.parts.EntitySpeedTickerPart;
import com.extendedae_plus.ae.screen.EntitySpeedTickerScreen;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.init.ModMenuTypes;
import com.extendedae_plus.util.ConfigParsingUtils;
@ -16,6 +16,8 @@ import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.List;
// 实体加速器菜单负责与客户端界面同步数据
public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart> {
@GuiSync(716) public boolean accelerateEnabled = true;
@ -62,7 +64,7 @@ public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart
BlockEntity target = getHost().getLevel().getBlockEntity(getHost().getBlockEntity().getBlockPos().relative(getHost().getSide()));
if (target != null) {
String blockId = ForgeRegistries.BLOCKS.getKey(target.getBlockState().getBlock()).toString();
for (ConfigParsingUtils.MultiplierEntry me : ConfigParsingUtils.getCachedMultiplierEntries(ModConfigs.EntitySpeedTickerMultipliers.get())) {
for (ConfigParsingUtils.MultiplierEntry me : ConfigParsingUtils.getCachedMultiplierEntries(List.of(ModConfig.INSTANCE.entityTickerMultipliers))) {
if (me.pattern.matcher(blockId).matches()) {
mult = Math.max(mult, me.multiplier);
}

View File

@ -19,7 +19,7 @@ import appeng.parts.PartModel;
import appeng.parts.automation.UpgradeablePart;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.ae.menu.EntitySpeedTickerMenu;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.init.ModMenuTypes;
import com.extendedae_plus.util.ConfigParsingUtils;
@ -198,7 +198,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
String blockId = Objects.requireNonNull(ForgeRegistries.BLOCKS.getKey(blockEntity.getBlockState().getBlock())).toString();
// 使用工具类的缓存接口工具类内部负责懒加载/线程安全
List<Pattern> compiledBlacklist = ConfigParsingUtils.getCachedBlacklist(ModConfigs.EntitySpeedTickerBlackList.get());
List<Pattern> compiledBlacklist = ConfigParsingUtils.getCachedBlacklist(List.of(ModConfig.INSTANCE.entityTickerBlackList));
for (Pattern p : compiledBlacklist) {
if (p.matcher(blockId).matches()) return;
}
@ -228,7 +228,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
int speed = (int) product;
double multiplier = 1.0;
for (ConfigParsingUtils.MultiplierEntry me : ConfigParsingUtils.getCachedMultiplierEntries(ModConfigs.EntitySpeedTickerMultipliers.get())) {
for (ConfigParsingUtils.MultiplierEntry me : ConfigParsingUtils.getCachedMultiplierEntries(List.of(ModConfig.INSTANCE.entityTickerMultipliers))) {
if (me.pattern.matcher(blockId).matches()) {
multiplier = Math.max(multiplier, me.multiplier);
}

View File

@ -14,8 +14,6 @@ import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.init.ModMenuTypes;
import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraftforge.client.ConfigScreenHandler;
import net.minecraftforge.fml.ModLoadingContext;
/**
* 客户端模型注册 formed 模型注册为内置模型
@ -76,12 +74,12 @@ public final class ClientRegistrar {
* 仅客户端 Mods 菜单注册配置界面入口
* 将对 Screen 的引用限制在客户端侧避免服务端类加载
*/
public static void registerConfigScreen() {
// ModConfigScreen 的引用放在此处确保仅在 Dist.CLIENT 下解析该类
ModLoadingContext.get().registerExtensionPoint(
ConfigScreenHandler.ConfigScreenFactory.class,
() -> new ConfigScreenHandler.ConfigScreenFactory(
(mc, parent) -> new ModConfigScreen(parent))
);
}
// public static void registerConfigScreen() {
// // ModConfigScreen 的引用放在此处确保仅在 Dist.CLIENT 下解析该类
// ModLoadingContext.get().registerExtensionPoint(
// ConfigScreenHandler.ConfigScreenFactory.class,
// () -> new ConfigScreenHandler.ConfigScreenFactory(
// (mc, parent) -> new ModConfigScreen(parent))
// );
// }
}

View File

@ -1,172 +0,0 @@
package com.extendedae_plus.client;
import com.extendedae_plus.config.ModConfigs;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.CycleButton;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
public class ModConfigScreen extends Screen {
private final Screen parent;
// 输入控件
private EditBox pageMultiplierBox;
private EditBox wirelessMaxRangeBox;
private CycleButton<Boolean> crossDimToggle;
private CycleButton<Boolean> providerRoundRobinToggle;
private EditBox smartScalingMaxMulBox;
private EditBox smartScalingMinBenefitBox;
private CycleButton<Boolean> showEncoderToggle;
private CycleButton<Boolean> patternTerminalShowSlotsToggle;
public ModConfigScreen(Screen parent) {
super(Component.translatable("screen.extendedae_plus.title"));
this.parent = parent;
}
@Override
protected void init() {
int centerX = this.width / 2;
int y = this.height / 6 + 24; // 起始高度整体更上方
int row = 0;
int rowHeight = 26;
int boxWidth = 150;
// 左右两列左侧标签起点右侧输入控件起点
int leftX = centerX - 170;
int rightX = centerX + 20;
// pageMultiplier: Int 1-64
pageMultiplierBox = new EditBox(this.font, rightX, y + row * rowHeight, boxWidth, 20, Component.translatable("config.extendedae_plus.pageMultiplier"));
pageMultiplierBox.setValue(String.valueOf(ModConfigs.PAGE_MULTIPLIER.get()));
pageMultiplierBox.setFilter(s -> s.matches("\\d*") && parseIntOrDefault(s, 1) >= 1 && parseIntOrDefault(s, 64) <= 64);
this.addRenderableWidget(pageMultiplierBox);
row++;
// wirelessMaxRange: Double 1-4096
wirelessMaxRangeBox = new EditBox(this.font, rightX, y + row * rowHeight, boxWidth, 20, Component.translatable("config.extendedae_plus.wirelessMaxRange"));
wirelessMaxRangeBox.setValue(String.valueOf(ModConfigs.WIRELESS_MAX_RANGE.get()));
wirelessMaxRangeBox.setFilter(s -> s.isEmpty() || s.matches("\\d*(\\.\\d*)?"));
this.addRenderableWidget(wirelessMaxRangeBox);
row++;
// cross dim toggle
crossDimToggle = this.addRenderableWidget(createToggle(rightX, y + row * rowHeight, boxWidth, 20, ModConfigs.WIRELESS_CROSS_DIM_ENABLE.get()));
row++;
// provider round-robin toggle (smart doubling)
providerRoundRobinToggle = this.addRenderableWidget(createToggle(rightX, y + row * rowHeight, boxWidth, 20, ModConfigs.PROVIDER_ROUND_ROBIN_ENABLE.get()));
row++;
// smartScalingMaxMultiplier: Int 0-1048576 (0 means unlimited)
smartScalingMaxMulBox = new EditBox(this.font, rightX, y + row * rowHeight, boxWidth, 20, Component.translatable("config.extendedae_plus.smartScalingMaxMultiplier"));
smartScalingMaxMulBox.setValue(String.valueOf(ModConfigs.SMART_SCALING_MAX_MULTIPLIER.get()));
smartScalingMaxMulBox.setFilter(s -> s.matches("\\d*") && parseIntOrDefault(s, 0) >= 0 && parseIntOrDefault(s, 1048576) <= 1048576);
this.addRenderableWidget(smartScalingMaxMulBox);
row++;
// smartScalingMinBenefitFactor: Int 1-1024
smartScalingMinBenefitBox = new EditBox(this.font, rightX, y + row * rowHeight, boxWidth, 20, Component.translatable("config.extendedae_plus.smartScalingMinBenefitFactor"));
smartScalingMinBenefitBox.setValue(String.valueOf(ModConfigs.SMART_SCALING_MIN_BENEFIT_FACTOR.get()));
smartScalingMinBenefitBox.setFilter(s -> s.matches("\\d*") && parseIntOrDefault(s, 1) >= 1 && parseIntOrDefault(s, 1024) <= 1024);
this.addRenderableWidget(smartScalingMinBenefitBox);
row++;
// show encoder pattern player toggle
showEncoderToggle = this.addRenderableWidget(createToggle(rightX, y + row * rowHeight, boxWidth, 20, ModConfigs.SHOW_ENCOD_PATTERN_PLAYER.get()));
row++;
// pattern terminal show slots default toggle
patternTerminalShowSlotsToggle = this.addRenderableWidget(createToggle(rightX, y + row * rowHeight, boxWidth, 20, ModConfigs.PATTERN_TERMINAL_SHOW_SLOTS_DEFAULT.get()));
row++;
// 按钮保存返回
int btnW = 100;
int gap = 8;
int buttonsY = y + row * rowHeight + 18;
this.addRenderableWidget(Button.builder(Component.translatable("gui.done"), b -> saveAndClose())
.pos(centerX - btnW - gap/2, buttonsY)
.size(btnW, 20)
.build());
this.addRenderableWidget(Button.builder(Component.translatable("gui.cancel"), b -> onClose())
.pos(centerX + gap/2, buttonsY)
.size(btnW, 20)
.build());
}
private void saveAndClose() {
// 读取与校验
int pageMul = clamp(parseIntOrDefault(pageMultiplierBox.getValue(), ModConfigs.PAGE_MULTIPLIER.get()), 1, 64);
double maxRange = clamp(parseDoubleOrDefault(wirelessMaxRangeBox.getValue(), ModConfigs.WIRELESS_MAX_RANGE.get()), 1.0, 4096.0);
boolean crossDim = crossDimToggle.getValue();
boolean providerRoundRobin = providerRoundRobinToggle.getValue();
int smartMaxMul = clamp(parseIntOrDefault(smartScalingMaxMulBox.getValue(), ModConfigs.SMART_SCALING_MAX_MULTIPLIER.get()), 0, 1048576);
int smartMinBenefit = clamp(parseIntOrDefault(smartScalingMinBenefitBox.getValue(), ModConfigs.SMART_SCALING_MIN_BENEFIT_FACTOR.get()), 1, 1024);
boolean showEncoder = showEncoderToggle.getValue();
boolean patternShowSlots = patternTerminalShowSlotsToggle.getValue();
// 应用到 Forge 配置值
ModConfigs.PAGE_MULTIPLIER.set(pageMul);
ModConfigs.WIRELESS_MAX_RANGE.set(maxRange);
ModConfigs.WIRELESS_CROSS_DIM_ENABLE.set(crossDim);
ModConfigs.PROVIDER_ROUND_ROBIN_ENABLE.set(providerRoundRobin);
ModConfigs.SMART_SCALING_MAX_MULTIPLIER.set(smartMaxMul);
ModConfigs.SMART_SCALING_MIN_BENEFIT_FACTOR.set(smartMinBenefit);
ModConfigs.SHOW_ENCOD_PATTERN_PLAYER.set(showEncoder);
ModConfigs.PATTERN_TERMINAL_SHOW_SLOTS_DEFAULT.set(patternShowSlots);
// Forge 会在合适的时机写回到配置文件部分改动可能需要重启游戏或世界才完全生效
onClose();
}
// Helper to create a boolean on/off CycleButton which shows localized on/off text
private CycleButton<Boolean> createToggle(int x, int y, int width, int height, boolean initial) {
CycleButton<Boolean> btn = CycleButton.onOffBuilder(initial)
.create(x, y, width, height, Component.empty(), (b, v) -> b.setMessage(Component.translatable(v ? "config.extendedae_plus.state_on" : "config.extendedae_plus.state_off")));
btn.setMessage(Component.translatable(initial ? "config.extendedae_plus.state_on" : "config.extendedae_plus.state_off"));
return btn;
}
@Override
public void onClose() {
Minecraft.getInstance().setScreen(parent);
}
@Override
public void render(GuiGraphics g, int mouseX, int mouseY, float partialTick) {
this.renderBackground(g);
super.render(g, mouseX, mouseY, partialTick);
int centerX = this.width / 2;
int y = this.height / 6 + 24;
int rowHeight = 26;
int labelColor = 0xFFFFFF;
int leftX = centerX - 170; // 标签左列位置
// 标题
g.drawCenteredString(this.font, this.title, centerX, y - 28, 0xFFFFFF);
// 每行标签
g.drawString(this.font, Component.translatable("config.extendedae_plus.pageMultiplier_with_range"), leftX, y + 0 * rowHeight + 6, labelColor, false);
g.drawString(this.font, Component.translatable("config.extendedae_plus.wirelessMaxRange_with_range"), leftX, y + 1 * rowHeight + 6, labelColor, false);
g.drawString(this.font, Component.translatable("config.extendedae_plus.wirelessCrossDimEnable"), leftX, y + 2 * rowHeight + 6, labelColor, false);
g.drawString(this.font, Component.translatable("config.extendedae_plus.providerRoundRobinEnable"), leftX, y + 3 * rowHeight + 6, labelColor, false);
g.drawString(this.font, Component.translatable("config.extendedae_plus.smartScalingMaxMultiplier_with_range"), leftX, y + 4 * rowHeight + 6, labelColor, false);
g.drawString(this.font, Component.translatable("config.extendedae_plus.smartScalingMinBenefitFactor"), leftX, y + 5 * rowHeight + 6, labelColor, false);
g.drawString(this.font, Component.translatable("config.extendedae_plus.showEncoderPatternPlayer"), leftX, y + 6 * rowHeight + 6, labelColor, false);
g.drawString(this.font, Component.translatable("config.extendedae_plus.patternTerminalShowSlotsDefault"), leftX, y + 7 * rowHeight + 6, labelColor, false);
}
private static int parseIntOrDefault(String s, int def) {
try { return Integer.parseInt(s); } catch (Exception e) { return def; }
}
private static double parseDoubleOrDefault(String s, double def) {
try { return Double.parseDouble(s); } catch (Exception e) { return def; }
}
private static int clamp(int v, int min, int max) { return Math.max(min, Math.min(max, v)); }
private static double clamp(double v, double min, double max) { return Math.max(min, Math.min(max, v)); }
}

View File

@ -0,0 +1,120 @@
package com.extendedae_plus.config;
import com.extendedae_plus.ExtendedAEPlus;
import dev.toma.configuration.Configuration;
import dev.toma.configuration.config.Config;
import dev.toma.configuration.config.Configurable;
import dev.toma.configuration.config.format.ConfigFormats;
@Config(id = ExtendedAEPlus.MODID)
public final class ModConfig {
public static ModConfig INSTANCE;
private static final Object lock = new Object();
public static void init() {
synchronized (lock) {
if (INSTANCE == null) {
INSTANCE = Configuration.registerConfig(ModConfig.class, ConfigFormats.yaml()).getConfigInstance();
}
}
}
@Configurable
@Configurable.Comment(value = {
"扩展样板供应器总槽位容量的倍率。",
"基础为36每页仍显示36格倍率会增加总页数/总容量。",
"建议范围 1-16"
})
@Configurable.Synchronized
@Configurable.Range(min = 1, max = 64)
public int pageMultiplier = 1;
@Configurable
@Configurable.Comment(value = {
"无线收发器最大连接距离(单位:方块)",
"从端与主端的直线距离需小于等于该值才会建立连接"
})
@Configurable.Synchronized
@Configurable.DecimalRange(min = 1, max = 4096)
public double wirelessMaxRange = 256.0;
@Configurable
@Configurable.Comment(value = {
"是否允许无线收发器跨维度建立连接",
"开启后,从端可连接到不同维度的主端(忽略距离限制)"
})
@Configurable.Synchronized
public boolean wirelessCrossDimEnable = true;
@Configurable
@Configurable.Comment(value = {
"智能倍增时是否对样板供应器轮询分配",
"仅多个供应器有相同样板时生效,开启后请求会均分到所有可用供应器,关闭则全部分配给单一供应器",
"注意:所有相关供应器需开启智能倍增,否则可能失效"
})
@Configurable.Synchronized
public boolean providerRoundRobinEnable = true;
@Configurable
@Configurable.Comment(value = {
"智能倍增的最大倍数0 表示不限制)",
"此倍数是针对单次样板产出的放大倍数上限,用于限制一次推送中按倍增缩放的规模"
})
@Configurable.Synchronized
@Configurable.Range(min = 0, max = Integer.MAX_VALUE)
public int smartScalingMaxMultiplier = 0;
@Configurable
@Configurable.Comment(value = {
"智能倍增最小收益因子(默认 4",
"当目标请求量小于 perOperationTarget * 此因子 时,智能倍增将不被启用以避免无意义包装"
})
@Configurable.Synchronized
@Configurable.Range(min = 1, max = 1024)
public int smartScalingMinBenefitFactor = 4;
@Configurable
@Configurable.Comment(value = {
"是否显示样板编码玩家",
"开启后将在样板 HoverText 上添加样板的编码玩家"
})
public boolean showEncoderPatternPlayer = true;
@Configurable
@Configurable.Comment(value = {
"样板终端默认是否显示槽位",
"影响进入界面时SlotsRow的默认可见性仅影响客户端显示"
})
public boolean patternTerminalShowSlotsDefault = true;
@Configurable
@Configurable.Comment(value = {
"实体加速器能量消耗基础值"
})
@Configurable.Range(min = 0, max = Integer.MAX_VALUE)
@Configurable.Synchronized
public int entityTickerCost = 512;
@Configurable
@Configurable.Comment(value = {
"实体加速器黑名单:匹配的方块将不会被加速。支持通配符/正则例如minecraft:*",
"格式:全名或通配符/正则字符串,例如 'minecraft:chest'、'minecraft:*'、'modid:.*_fluid'"
})
@Configurable.Synchronized
public String[] entityTickerBlackList = {
};
@Configurable
@Configurable.Comment(value = {
"额外消耗倍率配置:为某些方块设置额外能量倍率,格式 'modid:blockid multiplier',例如 'minecraft:chest 2x'",
"支持通配符/正则匹配(例如 'minecraft:* 2x' 会对整个命名空间生效)。"
})
@Configurable.Synchronized
public String[] entityTickerMultipliers = {
};
}

View File

@ -1,111 +0,0 @@
package com.extendedae_plus.config;
import net.minecraftforge.common.ForgeConfigSpec;
public final class ModConfigs {
public static final ForgeConfigSpec COMMON_SPEC;
public static final ForgeConfigSpec.IntValue PAGE_MULTIPLIER;
public static final ForgeConfigSpec.DoubleValue WIRELESS_MAX_RANGE;
public static final ForgeConfigSpec.BooleanValue WIRELESS_CROSS_DIM_ENABLE;
public static final ForgeConfigSpec.BooleanValue SHOW_ENCOD_PATTERN_PLAYER;
public static final ForgeConfigSpec.BooleanValue PROVIDER_ROUND_ROBIN_ENABLE;
public static final ForgeConfigSpec.BooleanValue PATTERN_TERMINAL_SHOW_SLOTS_DEFAULT;
public static final ForgeConfigSpec.IntValue SMART_SCALING_MAX_MULTIPLIER;
public static final ForgeConfigSpec.IntValue SMART_SCALING_MIN_BENEFIT_FACTOR;
public static final ForgeConfigSpec.IntValue EntitySpeedTickerCost;
public static final ForgeConfigSpec.ConfigValue<java.util.List<? extends String>> EntitySpeedTickerBlackList;
public static final ForgeConfigSpec.ConfigValue<java.util.List<? extends String>> EntitySpeedTickerMultipliers;
static {
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
builder.push("extendedae_plus");
PAGE_MULTIPLIER = builder
.comment(
"扩展样板供应器总槽位容量的倍率。",
"基础为36每页仍显示36格倍率会增加总页数/总容量。",
"建议范围 1-16")
.defineInRange("pageMultiplier", 1, 1, 64);
// 无线收发器最大连接距离单位方块
// 一对多从端连接主端时将以该值作为范围限制
WIRELESS_MAX_RANGE = builder
.comment(
"无线收发器最大连接距离(单位:方块)",
"从端与主端的直线距离需小于等于该值才会建立连接。")
.defineInRange("wirelessMaxRange", 256.0D, 1.0D, 4096.0D);
// 是否允许跨维度连接忽略维度差异进行频道传输
WIRELESS_CROSS_DIM_ENABLE = builder
.comment(
"是否允许无线收发器跨维度建立连接",
"开启后,从端可连接到不同维度的主端(忽略距离限制)")
.define("wirelessCrossDimEnable", true);
SHOW_ENCOD_PATTERN_PLAYER = builder
.comment(
"是否显示样板编码玩家",
"开启后将在样板 HoverText 上添加样板的编码玩家"
)
.define("showEncoderPatternPlayer", true);
// 智能倍增后是否在样板供应器间轮询分配请求量开启 provider 均分关闭不拆分
PROVIDER_ROUND_ROBIN_ENABLE = builder
.comment(
"智能倍增时是否对样板供应器轮询分配",
"仅多个供应器有相同样板时生效,开启后请求会均分到所有可用供应器,关闭则全部分配给单一供应器",
"注意:所有相关供应器需开启智能倍增,否则可能失效",
"默认: true")
.define("providerRoundRobinEnable", true);
// 智能倍增的最大倍数以单次样板产出为单位
// 0 表示不限制>0 表示最大倍增倍数上限例如 64 表示最多放大到 64
SMART_SCALING_MAX_MULTIPLIER = builder
.comment(
"智能倍增的最大倍数0 表示不限制)",
"此倍数是针对单次样板产出的放大倍数上限,用于限制一次推送中按倍增缩放的规模")
.defineInRange("smartScalingMaxMultiplier", 0, 0, 1048576);
// 智能倍增最小收益因子 requestedAmount < perOperationTarget * 此因子则不启用缩放默认 4
SMART_SCALING_MIN_BENEFIT_FACTOR = builder
.comment(
"智能倍增最小收益因子(默认 4",
"当目标请求量小于 perOperationTarget * 此因子 时,智能倍增将不被启用以避免无意义包装")
.defineInRange("smartScalingMinBenefitFactor", 4, 1, 1024);
// 模式访问终端ExtendedAE 图样终端默认是否显示槽位渲染SlotsRow
// true: 默认显示可通过界面按钮临时隐藏false: 默认隐藏可通过按钮显示
PATTERN_TERMINAL_SHOW_SLOTS_DEFAULT = builder
.comment(
"样板终端默认是否显示槽位",
"影响进入界面时SlotsRow的默认可见性仅影响客户端显示"
)
.define("patternTerminalShowSlotsDefault", true);
builder.push("EntitySpeedTicker");
EntitySpeedTickerCost = builder
.comment("实体加速器的能量消耗基础值")
.defineInRange("EntityTickerCost", 512, 0, Integer.MAX_VALUE);
EntitySpeedTickerBlackList = builder
.comment(
"实体加速器黑名单:匹配的方块将不会被加速。支持通配符/正则例如minecraft:*",
"格式:全名或通配符/正则字符串,例如 'minecraft:chest'、'minecraft:*'、'modid:.*_fluid'"
)
.defineList("EntityTickerBlackList", java.util.List.of(), o -> o instanceof String);
EntitySpeedTickerMultipliers = builder
.comment(
"额外消耗倍率配置:为某些方块设置额外能量倍率,格式 'modid:blockid multiplier',例如 'minecraft:chest 2x'",
"支持通配符/正则匹配(例如 'minecraft:* 2x' 会对整个命名空间生效)。"
)
.defineList("EntityTickerMultipliers", java.util.List.of(), o -> o instanceof String);
builder.pop();
builder.pop();
COMMON_SPEC = builder.build();
}
private ModConfigs() {}
}

View File

@ -1,7 +1,7 @@
package com.extendedae_plus.mixin.ae2;
import appeng.crafting.pattern.EncodedPatternItem;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
@ -20,7 +20,7 @@ public class EncodedPatternItemMixin {
// 客户端 HoverText 显示样板的编码玩家
@Inject(method = "appendHoverText", at = @At("TAIL"))
public void epp$appendHoverText(ItemStack stack, Level level, List<Component> lines, TooltipFlag advancedTooltips, CallbackInfo ci){
if (stack.hasTag() && ModConfigs.SHOW_ENCOD_PATTERN_PLAYER.get()) {
if (stack.hasTag() && ModConfig.INSTANCE.showEncoderPatternPlayer) {
CompoundTag tag = stack.getOrCreateTag();
String name = tag.getString("encodePlayer");
lines.add(Component.translatable("extendedae_plus.pattern.hovertext.player", name).withStyle(ChatFormatting.GRAY));

View File

@ -10,7 +10,7 @@ import appeng.crafting.CraftingTreeProcess;
import appeng.crafting.pattern.AEProcessingPattern;
import appeng.me.service.CraftingService;
import com.extendedae_plus.api.SmartDoublingAwarePattern;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import com.extendedae_plus.content.ScaledProcessingPattern;
import com.extendedae_plus.util.PatternScaler;
import com.extendedae_plus.util.RequestedAmountHolder;
@ -58,7 +58,7 @@ public abstract class CraftingTreeProcessMixin {
// 根据配置决定是否在 provider 间轮询分配请求量默认开启
long perProvider = 1L;
if (!ModConfigs.PROVIDER_ROUND_ROBIN_ENABLE.get()) {
if (!ModConfig.INSTANCE.providerRoundRobinEnable) {
// 关闭轮询直接使用完整请求量不需要查询 provider 列表
perProvider = requested;
if (perProvider <= 0) perProvider = 1L;

View File

@ -6,7 +6,7 @@ import appeng.client.gui.style.ScreenStyle;
import appeng.menu.SlotSemantics;
import com.extendedae_plus.NewIcon;
import com.extendedae_plus.api.ExPatternButtonsAccessor;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import com.glodblock.github.extendedae.client.button.ActionEPPButton;
import com.glodblock.github.extendedae.client.gui.GuiExPatternProvider;
import com.glodblock.github.extendedae.container.ContainerExPatternProvider;
@ -64,7 +64,7 @@ public abstract class GuiExPatternProviderMixin extends PatternProviderScreen<Co
private int getMaxPage() {
// 优先使用配置倍数
try {
int cfg = ModConfigs.PAGE_MULTIPLIER.get();
int cfg = ModConfig.INSTANCE.pageMultiplier;
if (cfg > 1) return cfg;
} catch (Throwable ignored) {}
try {
@ -123,7 +123,7 @@ public abstract class GuiExPatternProviderMixin extends PatternProviderScreen<Co
// 计算并下发 maxPage配置优先其次按槽位总数计算
int totalSlots = this.getMenu().getSlots(SlotSemantics.ENCODED_PATTERN).size();
int cfgPages = 1;
try { cfgPages = Math.max(1, ModConfigs.PAGE_MULTIPLIER.get()); } catch (Throwable ignored) {}
try { cfgPages = Math.max(1, ModConfig.INSTANCE.pageMultiplier); } catch (Throwable ignored) {}
int calcPages = Math.max(1, (int) Math.ceil(totalSlots / (double) SLOTS_PER_PAGE));
int desiredMaxPage = Math.max(cfgPages, calcPages);
LOGGER.info("[EAP] GuiExPatternProvider init: totalSlots={}, cfgPages={}, calcPages={}, desiredMaxPage={}", totalSlots, cfgPages, calcPages, desiredMaxPage);

View File

@ -8,7 +8,7 @@ import appeng.client.gui.style.ScreenStyle;
import appeng.client.gui.widgets.AETextField;
import appeng.client.gui.widgets.IconButton;
import appeng.menu.AEBaseMenu;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import com.extendedae_plus.init.ModNetwork;
import com.extendedae_plus.mixin.extendedae.accessor.GuiExPatternTerminalAccessor;
import com.extendedae_plus.network.OpenProviderUiC2SPacket;
@ -259,7 +259,7 @@ public abstract class GuiExPatternTerminalMixin extends AEBaseScreen<AEBaseMenu>
private void injectConstructor(CallbackInfo ci) {
// 根据配置初始化默认显示/隐藏状态
try {
this.eap$showSlots = ModConfigs.PATTERN_TERMINAL_SHOW_SLOTS_DEFAULT.get();
this.eap$showSlots = ModConfig.INSTANCE.patternTerminalShowSlotsDefault;
} catch (Throwable ignored) {
}
// 创建切换槽位显示的按钮

View File

@ -1,6 +1,6 @@
package com.extendedae_plus.mixin.extendedae.common;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import com.glodblock.github.extendedae.common.parts.PartExPatternProvider;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -18,7 +18,7 @@ public abstract class PartExPatternProviderMixin {
index = 2
)
private int eap$multiplyCapacity(int original) {
int mult = ModConfigs.PAGE_MULTIPLIER.get();
int mult = ModConfig.INSTANCE.pageMultiplier;
if (mult < 1) mult = 1;
if (mult > 64) mult = 64;
return Math.max(1, original) * mult;

View File

@ -1,6 +1,6 @@
package com.extendedae_plus.mixin.extendedae.common;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import com.glodblock.github.extendedae.common.tileentities.TileExPatternProvider;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -18,7 +18,7 @@ public abstract class TileExPatternProviderMixin {
index = 2
)
private int eap$multiplyCapacity(int original) {
int mult = ModConfigs.PAGE_MULTIPLIER.get();
int mult = ModConfig.INSTANCE.pageMultiplier;
if (mult < 1) mult = 1;
if (mult > 64) mult = 64;
return Math.max(1, original) * mult;

View File

@ -4,7 +4,7 @@ import appeng.api.stacks.AEKey;
import appeng.api.stacks.GenericStack;
import appeng.crafting.pattern.AEProcessingPattern;
import com.extendedae_plus.api.SmartDoublingAwarePattern;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import com.extendedae_plus.content.ScaledProcessingPattern;
public final class PatternScaler {
@ -56,7 +56,7 @@ public final class PatternScaler {
}
// 小请求绕过若请求量小且不会带来收益则不启用缩放返回 null
try {
int minBenefit = ModConfigs.SMART_SCALING_MIN_BENEFIT_FACTOR.get();
int minBenefit = ModConfig.INSTANCE.smartScalingMinBenefitFactor;
if (minBenefit > 1 && requestedAmount > 0 && requestedAmount < perOperationTarget * (long) minBenefit) {
return null;
}
@ -65,7 +65,7 @@ public final class PatternScaler {
}
// 应用配置的最大倍数上限0 表示不限制
try {
int maxMul = ModConfigs.SMART_SCALING_MAX_MULTIPLIER.get();
int maxMul = ModConfig.INSTANCE.smartScalingMaxMultiplier;
if (maxMul > 0 && multiplier > maxMul) {
multiplier = maxMul;
}

View File

@ -1,7 +1,7 @@
package com.extendedae_plus.util;
import com.extendedae_plus.ae.definitions.upgrades.EntitySpeedCardItem;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
/**
* 用于计算实体加速器的能耗与加速倍率的工具类
@ -90,7 +90,7 @@ public final class PowerUtils {
*/
public static double computeFinalPowerForProduct(long product, int energyCardCount) {
if (product <= 1L) return 0.0;
double base = ModConfigs.EntitySpeedTickerCost.get();
double base = ModConfig.INSTANCE.entityTickerCost;
// 计算以2为底的对数用于分档与公式
double log2 = Math.log(product) / Math.log(2.0);
@ -121,7 +121,7 @@ public final class PowerUtils {
}
public static double getRawPower(int speedCardCount) {
double base = ModConfigs.EntitySpeedTickerCost.get();
double base = ModConfig.INSTANCE.entityTickerCost;
return base * getGrowthFactor(speedCardCount);
}

View File

@ -1,6 +1,6 @@
package com.extendedae_plus.wireless;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
@ -63,7 +63,7 @@ public final class WirelessMasterRegistry {
}
private static boolean useGlobal() {
return ModConfigs.WIRELESS_CROSS_DIM_ENABLE.get();
return ModConfig.INSTANCE.wirelessCrossDimEnable;
}
private record Key(ResourceKey<Level> dim, long freq) {

View File

@ -3,7 +3,7 @@ package com.extendedae_plus.wireless;
import appeng.api.networking.GridHelper;
import appeng.api.networking.IGridNode;
import appeng.me.service.helpers.ConnectionWrapper;
import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.config.ModConfig;
import net.minecraft.server.level.ServerLevel;
import java.util.Objects;
@ -64,12 +64,12 @@ public class WirelessSlaveLink {
shutdown = false;
distance = 0.0D;
boolean crossDim = ModConfigs.WIRELESS_CROSS_DIM_ENABLE.get();
boolean crossDim = ModConfig.INSTANCE.wirelessCrossDimEnable;
if (master != null && !master.isEndpointRemoved() && (crossDim || master.getServerLevel() == level)) {
if (!crossDim) {
distance = Math.sqrt(master.getBlockPos().distSqr(host.getBlockPos()));
}
double maxRange = ModConfigs.WIRELESS_MAX_RANGE.get();
double maxRange = ModConfig.INSTANCE.wirelessMaxRange;
if (crossDim || distance <= maxRange) {
// 保持/建立连接
try {

View File

@ -64,19 +64,21 @@
"extendedae_plus.tooltip.master_mode": "Mode: %s",
"extendedae_plus.tooltip.locked": "Locked: %s",
"screen.extendedae_plus.title": "ExtendedAE Plus Config",
"config.extendedae_plus.pageMultiplier": "Pattern Provider Page Multiplier",
"config.extendedae_plus.pageMultiplier_with_range": "Pattern Provider Page Multiplier (1-64)",
"config.extendedae_plus.wirelessMaxRange": "Wireless Max Range",
"config.extendedae_plus.wirelessMaxRange_with_range": "Wireless Max Range (1-4096)",
"config.extendedae_plus.wirelessCrossDimEnable": "Allow Wireless Cross-Dimension",
"config.extendedae_plus.providerRoundRobinEnable": "Enable Provider Round-Robin (Smart Doubling)",
"config.extendedae_plus.state_on": "On",
"config.extendedae_plus.state_off": "Off",
"config.extendedae_plus.showEncoderPatternPlayer": "Show Encoded Pattern Player",
"config.extendedae_plus.patternTerminalShowSlotsDefault": "Pattern Terminal Show Slots By Default",
"config.extendedae_plus.smartScalingMaxMultiplier": "Smart Scaling Max Multiplier",
"config.extendedae_plus.smartScalingMaxMultiplier_with_range": "Smart Scaling Max Multiplier (0 = Unlimited)",
"config.extendedae_plus.smartScalingMinBenefitFactor": "Smart Scaling Min Benefit Factor (default 4)"
"config.screen.extendedae_plus": "ExtendedAE Plus Config",
"config.extendedae_plus.option.pageMultiplier": "Pattern Provider Page Multiplier",
"config.extendedae_plus.option.pageMultiplier_with_range": "Pattern Provider Page Multiplier",
"config.extendedae_plus.option.wirelessMaxRange": "Wireless Max Range",
"config.extendedae_plus.option.wirelessMaxRange_with_range": "Wireless Max Range",
"config.extendedae_plus.option.wirelessCrossDimEnable": "Allow Wireless Cross-Dimension",
"config.extendedae_plus.option.providerRoundRobinEnable": "Enable Provider Round-Robin (Smart Doubling)",
"config.extendedae_plus.option.state_on": "On",
"config.extendedae_plus.option.state_off": "Off",
"config.extendedae_plus.option.showEncoderPatternPlayer": "Show Encoded Pattern Player",
"config.extendedae_plus.option.patternTerminalShowSlotsDefault": "Pattern Terminal Show Slots By Default",
"config.extendedae_plus.option.smartScalingMaxMultiplier": "Smart Scaling Max Multiplier",
"config.extendedae_plus.option.smartScalingMaxMultiplier_with_range": "Smart Scaling Max Multiplier",
"config.extendedae_plus.option.smartScalingMinBenefitFactor": "Smart Scaling Min Benefit Factor",
"config.extendedae_plus.option.entityTickerCost": "Entity Ticker Base Energy Cost",
"config.extendedae_plus.option.entityTickerBlackList": "Entity Ticker Blacklist",
"config.extendedae_plus.option.entityTickerMultipliers": "Entity Ticker Extra Consumption Multipliers"
}

View File

@ -64,19 +64,21 @@
"extendedae_plus.tooltip.master_mode": "模式: %s",
"extendedae_plus.tooltip.locked": "锁定状态: %s",
"screen.extendedae_plus.title": "ExtendedAE Plus 配置",
"config.extendedae_plus.pageMultiplier": "扩展样板供应器槽位倍率",
"config.extendedae_plus.pageMultiplier_with_range": "扩展样板供应器槽位倍率 (1-64)",
"config.extendedae_plus.wirelessMaxRange": "无线最大距离",
"config.extendedae_plus.wirelessMaxRange_with_range": "无线最大距离 (1-4096)",
"config.extendedae_plus.wirelessCrossDimEnable": "无线收发器允许跨维度连接",
"config.extendedae_plus.providerRoundRobinEnable": "启用样板供应器轮询分配(智能翻倍)",
"config.extendedae_plus.state_on": "开",
"config.extendedae_plus.state_off": "关",
"config.extendedae_plus.showEncoderPatternPlayer": "显示样板编码玩家",
"config.extendedae_plus.patternTerminalShowSlotsDefault": "样板终端默认显示槽位",
"config.extendedae_plus.smartScalingMaxMultiplier": "智能倍增最大倍数",
"config.extendedae_plus.smartScalingMaxMultiplier_with_range": "智能倍增最大倍数 (0为不限制)",
"config.extendedae_plus.smartScalingMinBenefitFactor": "智能倍增最小收益因子 (默认 4)"
"config.screen.extendedae_plus": "ExtendedAE Plus 配置",
"config.extendedae_plus.option.pageMultiplier": "扩展样板供应器槽位倍率",
"config.extendedae_plus.option.pageMultiplier_with_range": "扩展样板供应器槽位倍率",
"config.extendedae_plus.option.wirelessMaxRange": "无线最大距离",
"config.extendedae_plus.option.wirelessMaxRange_with_range": "无线最大距离",
"config.extendedae_plus.option.wirelessCrossDimEnable": "无线收发器允许跨维度连接",
"config.extendedae_plus.option.providerRoundRobinEnable": "启用样板供应器轮询分配(智能翻倍)",
"config.extendedae_plus.option.state_on": "开",
"config.extendedae_plus.option.state_off": "关",
"config.extendedae_plus.option.showEncoderPatternPlayer": "显示样板编码玩家",
"config.extendedae_plus.option.patternTerminalShowSlotsDefault": "样板终端默认显示槽位",
"config.extendedae_plus.option.smartScalingMaxMultiplier": "智能倍增最大倍数",
"config.extendedae_plus.option.smartScalingMaxMultiplier_with_range": "智能倍增最大倍数",
"config.extendedae_plus.option.smartScalingMinBenefitFactor": "智能倍增最小收益因子",
"config.extendedae_plus.option.entityTickerCost": "实体加速器能量消耗基础值",
"config.extendedae_plus.option.entityTickerBlackList": "实体加速器黑名单",
"config.extendedae_plus.option.entityTickerMultipliers": "实体加速器额外消耗倍率"
}

View File

@ -30,6 +30,7 @@
],
"mixins": [
"ae2.AEProcessingPatternMixin",
"ae2.CraftingCalculationMixin",
"ae2.CraftingCPUClusterMixin",
"ae2.EncodedPatternItemMixin",
"ae2.accessor.MEStorageMenuAccessor",