ExtendedAE_Plus/src/main/java/com/extendedae_plus/config/ModConfig.java
范翰德202509 7c2286cd68 feat: Add Ctrl+Q quick pattern creation from JEI
Implement a new keybind (Ctrl+Q) to quickly create AE2 patterns from JEI items.

Features:
- Press Ctrl+Q while hovering over any item in JEI to create patterns instantly
- Intelligent recipe selection (prioritizes crafting recipes)
- Support Shift+Ctrl+Q to search recipes where item is used as input
- JEI bookmark priority system for ingredient selection
- Smart pattern placement (crafting patterns drop, processing patterns to inventory)
- Consumes blank pattern from player inventory with auto-refund on failure

Configuration:
- ctrlQConsumeBlankPattern: Toggle blank pattern consumption (default: true)
- ctrlQExtractFromNetwork: Extract patterns from AE network (default: true, WIP)

Technical changes:
- Add CtrlQPatternKeyHandler for client-side key handling
- Add CreateCtrlQPatternC2SPacket for C2S network communication
- Add RecipeFinderUtil with priority sorting
- Add ModKeybindings for keybind registration
- Update ModConfig with new options
- Register network packet in ModNetwork
- Add English translations

Code quality:
- Cleaned up debug logs
- Removed local development configuration
2026-02-22 11:28:52 +08:00

194 lines
7.6 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.extendedae_plus.config;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.util.entitySpeed.ConfigParsingUtils;
import com.extendedae_plus.util.entitySpeed.PowerUtils;
import dev.toma.configuration.Configuration;
import dev.toma.configuration.client.IValidationHandler;
import dev.toma.configuration.config.Config;
import dev.toma.configuration.config.Configurable;
import dev.toma.configuration.config.format.ConfigFormats;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@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 = {
"设置AE构建合成计划过程中的 wait/notify 次数,提升吞吐但会降低调度响应性"
})
@Configurable.Synchronized
@Configurable.Range(min = 100, max = Integer.MAX_VALUE)
public int craftingPauseThreshold = 100000;
@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 = {
"无线收发器待机能耗",
"无线收发器的基础待机能耗AE/t同时作用于普通与标签无线收发器"
})
@Configurable.Synchronized
@Configurable.DecimalRange(min = 0, max = Double.MAX_VALUE)
public double wirelessTransceiverIdlePower = 100.0;
@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 = {
"是否显示样板编码玩家",
"开启后将在样板 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
@Configurable.ValueUpdateCallback(method = "onEntityTickerCostUpdate")
public int entityTickerCost = 512;
@Configurable
@Configurable.Comment(value = {
"是否优先从磁盘提取FE能量仅当Applied Flux模组存在时生效",
"开启后将优先尝试从磁盘提取FE能量反之优先消耗AE网络中的能量"
})
@Configurable.Synchronized
public boolean prioritizeDiskEnergy = true;
@Configurable
@Configurable.Comment(value = {
"实体加速器黑名单:匹配的方块将不会被加速。支持通配符/正则例如minecraft:*",
"格式:全名或通配符/正则字符串,例如 'minecraft:chest'、'minecraft:*'、'modid:.*_fluid'"
})
@Configurable.Synchronized
@Configurable.ValueUpdateCallback(method = "onEntityTickerBlackListUpdate")
public String[] entityTickerBlackList = {};
@Configurable
@Configurable.Comment(value = {
"额外消耗倍率配置:为某些方块设置额外能量倍率,格式 'modid:blockid multiplier',例如 'minecraft:chest 2x'",
"支持通配符/正则匹配(例如 'minecraft:* 2x' 会对整个命名空间生效)。"
})
@Configurable.Synchronized
@Configurable.ValueUpdateCallback(method = "onEntityTickerMultipliersUpdate")
public String[] entityTickerMultipliers = {};
private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> pendingPowerTask;
private static final Object POWER_LOCK = new Object();
private static final long DEBOUNCE_INTERVAL = 1000; // 防抖间隔,单位:毫秒
private void onEntityTickerCostUpdate(int newValue, IValidationHandler handler) {
synchronized (POWER_LOCK) {
if (pendingPowerTask != null) {
pendingPowerTask.cancel(false);
}
pendingPowerTask = EXECUTOR.schedule(() -> {
synchronized (PowerUtils.class) {
PowerUtils.initializeCaches();
}
}, DEBOUNCE_INTERVAL, TimeUnit.MILLISECONDS); // 1000ms 防抖
}
}
private void onEntityTickerBlackListUpdate(String[] newValue, IValidationHandler handler) {
synchronized (ConfigParsingUtils.class) {
ConfigParsingUtils.reload();
}
}
private void onEntityTickerMultipliersUpdate(String[] newValue, IValidationHandler handler) {
synchronized (ConfigParsingUtils.class) {
ConfigParsingUtils.reload();
}
}
// ==================== Ctrl+Q 快速样板配置 ====================
@Configurable
@Configurable.Comment(value = {
"Ctrl+Q创建样板是否消耗空白样板",
"true: 从玩家背包或AE网络消耗空白样板",
"false: 不消耗空白样板,直接创建(整合包/服务器管理员可配置)"
})
@Configurable.Synchronized
public boolean ctrlQConsumeBlankPattern = true;
@Configurable
@Configurable.Comment(value = {
"Ctrl+Q创建样板是否优先从AE网络提取空白样板",
"true: 优先从AE网络提取网络无货才从背包消耗",
"false: 仅从玩家背包消耗",
"注意需要玩家持有或装备无线终端才能访问AE网络"
})
@Configurable.Synchronized
public boolean ctrlQExtractFromNetwork = true;
}