feat: 更新实体加速器相关配置缓存刷新机制
This commit is contained in:
parent
636050039d
commit
e7add431ce
|
|
@ -51,7 +51,7 @@ import java.lang.reflect.Method;
|
||||||
* 实体加速器部件,用于加速目标方块实体的 tick 速率,消耗 AE 网络能量,支持加速卡和能量卡升级。
|
* 实体加速器部件,用于加速目标方块实体的 tick 速率,消耗 AE 网络能量,支持加速卡和能量卡升级。
|
||||||
* 灵感来源于 <a href="https://github.com/GilbertzRivi/crazyae2addons">Crazy AE2 Addons</a>。
|
* 灵感来源于 <a href="https://github.com/GilbertzRivi/crazyae2addons">Crazy AE2 Addons</a>。
|
||||||
*/
|
*/
|
||||||
public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTickable, MenuProvider, IUpgradeableObject {
|
public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTickable, MenuProvider, IUpgradeableObject {
|
||||||
public static final ResourceLocation MODEL_BASE = new ResourceLocation(
|
public static final ResourceLocation MODEL_BASE = new ResourceLocation(
|
||||||
ExtendedAEPlus.MODID, "part/entity_speed_ticker_part");
|
ExtendedAEPlus.MODID, "part/entity_speed_ticker_part");
|
||||||
|
|
||||||
|
|
@ -62,18 +62,14 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
@PartModels
|
@PartModels
|
||||||
public static final PartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, new ResourceLocation(ExtendedAEPlus.MODID, "part/entity_speed_ticker_has_channel"));
|
public static final PartModel MODELS_HAS_CHANNEL = new PartModel(MODEL_BASE, new ResourceLocation(ExtendedAEPlus.MODID, "part/entity_speed_ticker_has_channel"));
|
||||||
|
|
||||||
public EntitySpeedTickerMenu menu; // 当前打开的菜单实例
|
private static volatile boolean[] cachedAttempts;
|
||||||
private boolean networkEnergySufficient = true; // 网络能量是否充足
|
|
||||||
private int cachedSpeed = -1; // 缓存的加速倍率
|
|
||||||
private int cachedEnergyCardCount = -1; // 缓存的能量卡数量
|
|
||||||
private BlockEntity cachedTarget = null;
|
|
||||||
private BlockPos cachedTargetPos = null;
|
|
||||||
|
|
||||||
private static volatile Method cachedFEExtractMethod;
|
private static volatile Method cachedFEExtractMethod;
|
||||||
private static volatile boolean FE_UNAVAILABLE;
|
private static volatile boolean FE_UNAVAILABLE;
|
||||||
|
|
||||||
// ===== 静态块:反射初始化 FE 方法 =====
|
// 静态块:初始化缓存
|
||||||
static {
|
static {
|
||||||
|
cachedAttempts = ModConfig.INSTANCE.prioritizeDiskEnergy ? new boolean[]{false, true, true} : new boolean[]{true, false, true};
|
||||||
if (ModList.get().isLoaded("appflux")) {
|
if (ModList.get().isLoaded("appflux")) {
|
||||||
try {
|
try {
|
||||||
Class<?> helperClass = Class.forName("com.extendedae_plus.util.FluxEnergyHelper");
|
Class<?> helperClass = Class.forName("com.extendedae_plus.util.FluxEnergyHelper");
|
||||||
|
|
@ -90,8 +86,17 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EntitySpeedTickerMenu menu; // 当前打开的菜单实例
|
||||||
|
private boolean networkEnergySufficient = true; // 网络能量是否充足
|
||||||
|
private int cachedSpeed = -1; // 缓存的加速倍率
|
||||||
|
private int cachedEnergyCardCount = -1; // 缓存的能量卡数量
|
||||||
|
private BlockEntity cachedTarget = null;
|
||||||
|
private BlockPos cachedTargetPos = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造函数,初始化部件并设置网络节点属性。
|
* 构造函数,初始化部件并设置网络节点属性。
|
||||||
|
*
|
||||||
* @param partItem 部件物品
|
* @param partItem 部件物品
|
||||||
*/
|
*/
|
||||||
public EntitySpeedTickerPart(IPartItem<?> partItem) {
|
public EntitySpeedTickerPart(IPartItem<?> partItem) {
|
||||||
|
|
@ -108,17 +113,26 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新缓存的 attempts 数组,由 ModConfig 调用。
|
||||||
|
*/
|
||||||
|
public static void updateCachedAttempts(boolean prioritizeDiskEnergy) {
|
||||||
|
synchronized (EntitySpeedTickerPart.class) {
|
||||||
|
cachedAttempts = prioritizeDiskEnergy ? new boolean[]{false, true, true} : new boolean[]{true, false, true};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getAccelerateEnabled() {
|
public boolean getAccelerateEnabled() {
|
||||||
return this.getConfigManager().getSetting(com.extendedae_plus.ae.api.config.Settings.ACCELERATE) == YesNo.YES;
|
return this.getConfigManager().getSetting(com.extendedae_plus.ae.api.config.Settings.ACCELERATE) == YesNo.YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置加速开关状态并通知菜单。
|
* 设置加速开关状态并通知菜单。
|
||||||
|
*
|
||||||
* @param enabled 是否启用加速
|
* @param enabled 是否启用加速
|
||||||
*/
|
*/
|
||||||
public void setAccelerateEnabled(boolean enabled) {
|
public void setAccelerateEnabled(boolean enabled) {
|
||||||
this.getConfigManager().putSetting(com.extendedae_plus.ae.api.config.Settings.ACCELERATE, enabled ? YesNo.YES : YesNo.NO);
|
this.getConfigManager().putSetting(com.extendedae_plus.ae.api.config.Settings.ACCELERATE, enabled ? YesNo.YES : YesNo.NO);
|
||||||
// 是否启用加速
|
|
||||||
if (menu != null) {
|
if (menu != null) {
|
||||||
menu.setAccelerateEnabled(enabled);
|
menu.setAccelerateEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
@ -130,6 +144,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新网络能量充足状态并通知菜单。
|
* 更新网络能量充足状态并通知菜单。
|
||||||
|
*
|
||||||
* @param sufficient 是否能量充足
|
* @param sufficient 是否能量充足
|
||||||
*/
|
*/
|
||||||
private void updateNetworkEnergySufficient(boolean sufficient) {
|
private void updateNetworkEnergySufficient(boolean sufficient) {
|
||||||
|
|
@ -141,6 +156,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前状态的渲染模型。
|
* 获取当前状态的渲染模型。
|
||||||
|
*
|
||||||
* @return 当前状态的模型
|
* @return 当前状态的模型
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -156,9 +172,10 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理玩家右键激活部件,打开菜单。
|
* 处理玩家右键激活部件,打开菜单。
|
||||||
|
*
|
||||||
* @param player 玩家
|
* @param player 玩家
|
||||||
* @param hand 手
|
* @param hand 手
|
||||||
* @param pos 点击位置
|
* @param pos 点击位置
|
||||||
* @return 总是返回 true
|
* @return 总是返回 true
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -171,6 +188,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定义部件的碰撞箱。
|
* 定义部件的碰撞箱。
|
||||||
|
*
|
||||||
* @param bch 碰撞辅助器
|
* @param bch 碰撞辅助器
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -181,6 +199,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取定时请求,指定 tick 频率。
|
* 获取定时请求,指定 tick 频率。
|
||||||
|
*
|
||||||
* @param iGridNode 网络节点
|
* @param iGridNode 网络节点
|
||||||
* @return TickingRequest 对象
|
* @return TickingRequest 对象
|
||||||
*/
|
*/
|
||||||
|
|
@ -205,7 +224,8 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网络定时回调,处理目标方块实体的加速。
|
* 网络定时回调,处理目标方块实体的加速。
|
||||||
* @param iGridNode 网络节点
|
*
|
||||||
|
* @param iGridNode 网络节点
|
||||||
* @param ticksSinceLastCall 距离上次调用的 tick 数
|
* @param ticksSinceLastCall 距离上次调用的 tick 数
|
||||||
* @return TickRateModulation.IDLE
|
* @return TickRateModulation.IDLE
|
||||||
*/
|
*/
|
||||||
|
|
@ -223,8 +243,9 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对目标方块实体执行加速 tick 操作。
|
* 对目标方块实体执行加速 tick 操作。
|
||||||
|
*
|
||||||
* @param blockEntity 目标方块实体
|
* @param blockEntity 目标方块实体
|
||||||
* @param <T> 方块实体类型
|
* @param <T> 方块实体类型
|
||||||
*/
|
*/
|
||||||
private <T extends BlockEntity> void ticker(@NotNull T blockEntity) {
|
private <T extends BlockEntity> void ticker(@NotNull T blockEntity) {
|
||||||
if (!isValidForTicking()) {
|
if (!isValidForTicking()) {
|
||||||
|
|
@ -241,7 +262,6 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果缓存未初始化(第一次 tick),计算并更新缓存
|
|
||||||
if (cachedEnergyCardCount == -1 || cachedSpeed == -1) {
|
if (cachedEnergyCardCount == -1 || cachedSpeed == -1) {
|
||||||
this.cachedEnergyCardCount = getUpgrades().getInstalledUpgrades(AEItems.ENERGY_CARD);
|
this.cachedEnergyCardCount = getUpgrades().getInstalledUpgrades(AEItems.ENERGY_CARD);
|
||||||
this.cachedSpeed = calculateSpeed();
|
this.cachedSpeed = calculateSpeed();
|
||||||
|
|
@ -251,7 +271,6 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 PowerUtils 的缓存获取能耗,并应用方块特定的倍率
|
|
||||||
double requiredPower = PowerUtils.getCachedPower(cachedSpeed, cachedEnergyCardCount)
|
double requiredPower = PowerUtils.getCachedPower(cachedSpeed, cachedEnergyCardCount)
|
||||||
* ConfigParsingUtils.getMultiplierForBlock(blockId);
|
* ConfigParsingUtils.getMultiplierForBlock(blockId);
|
||||||
if (!extractPower(requiredPower)) {
|
if (!extractPower(requiredPower)) {
|
||||||
|
|
@ -263,6 +282,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查网络节点是否有效。
|
* 检查网络节点是否有效。
|
||||||
|
*
|
||||||
* @return 是否可以执行 tick
|
* @return 是否可以执行 tick
|
||||||
*/
|
*/
|
||||||
private boolean isValidForTicking() {
|
private boolean isValidForTicking() {
|
||||||
|
|
@ -280,8 +300,10 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
cachedTarget = getLevel().getBlockEntity(targetPos);
|
cachedTarget = getLevel().getBlockEntity(targetPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取目标方块实体的 ticker。
|
* 获取目标方块实体的 ticker。
|
||||||
|
*
|
||||||
* @param blockEntity 目标方块实体
|
* @param blockEntity 目标方块实体
|
||||||
* @return ticker 或 null
|
* @return ticker 或 null
|
||||||
*/
|
*/
|
||||||
|
|
@ -292,6 +314,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算加速倍率。
|
* 计算加速倍率。
|
||||||
|
*
|
||||||
* @return 生效的加速倍率
|
* @return 生效的加速倍率
|
||||||
*/
|
*/
|
||||||
private int calculateSpeed() {
|
private int calculateSpeed() {
|
||||||
|
|
@ -302,6 +325,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提取网络能量并更新状态,优先从 AE2 网络提取 AE 能量,不足时从磁盘提取 FE 能量。
|
* 提取网络能量并更新状态,优先从 AE2 网络提取 AE 能量,不足时从磁盘提取 FE 能量。
|
||||||
|
*
|
||||||
* @param requiredPower 所需能量(AE 单位)
|
* @param requiredPower 所需能量(AE 单位)
|
||||||
* @return 是否成功提取足够能量
|
* @return 是否成功提取足够能量
|
||||||
*/
|
*/
|
||||||
|
|
@ -310,11 +334,8 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
MEStorage storage = getMainNode().getGrid().getStorageService().getInventory();
|
MEStorage storage = getMainNode().getGrid().getStorageService().getInventory();
|
||||||
IActionSource source = IActionSource.ofMachine(this);
|
IActionSource source = IActionSource.ofMachine(this);
|
||||||
|
|
||||||
// 优先级:FE(如果优先磁盘) -> AE -> FE(如果未优先磁盘)
|
for (int i = 0; i < cachedAttempts.length; i++) {
|
||||||
boolean[] attempts = ModConfig.INSTANCE.prioritizeDiskEnergy ? new boolean[]{true, false, true} : new boolean[]{false, true, false};
|
if (!cachedAttempts[i]) continue;
|
||||||
|
|
||||||
for (int i = 0; i < attempts.length; i++) {
|
|
||||||
if (!attempts[i]) continue;
|
|
||||||
if (i == 0 || i == 2) { // FE 提取
|
if (i == 0 || i == 2) { // FE 提取
|
||||||
if (!FE_UNAVAILABLE && cachedFEExtractMethod != null) {
|
if (!FE_UNAVAILABLE && cachedFEExtractMethod != null) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -329,10 +350,14 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // AE 提取
|
} else { // AE 提取
|
||||||
double extracted = energyService.extractAEPower(requiredPower, Actionable.MODULATE, PowerMultiplier.CONFIG);
|
double simulated = energyService.extractAEPower(requiredPower, Actionable.SIMULATE, PowerMultiplier.CONFIG);
|
||||||
if (extracted >= requiredPower) {
|
if (simulated >= requiredPower) {
|
||||||
updateNetworkEnergySufficient(true);
|
double extracted = energyService.extractAEPower(requiredPower, Actionable.MODULATE, PowerMultiplier.CONFIG);
|
||||||
return true;
|
boolean sufficient = extracted >= requiredPower;
|
||||||
|
updateNetworkEnergySufficient(sufficient);
|
||||||
|
if (sufficient) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -342,14 +367,14 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行加速 tick 操作。
|
* 执行加速 tick 操作。
|
||||||
|
*
|
||||||
* @param blockEntity 目标方块实体
|
* @param blockEntity 目标方块实体
|
||||||
* @param ticker 方块实体 ticker
|
* @param ticker 方块实体 ticker
|
||||||
* @param speed 加速倍率
|
* @param speed 加速倍率
|
||||||
*/
|
*/
|
||||||
private <T extends BlockEntity> void performTicks(T blockEntity,
|
private <T extends BlockEntity> void performTicks(T blockEntity,
|
||||||
BlockEntityTicker<T> ticker,
|
BlockEntityTicker<T> ticker,
|
||||||
int speed) {
|
int speed) {
|
||||||
// 执行 speed-1 次额外 tick(原生 tick 已包含 1 次)
|
|
||||||
for (int i = 0; i < speed - 1; i++) {
|
for (int i = 0; i < speed - 1; i++) {
|
||||||
ticker.tick(
|
ticker.tick(
|
||||||
blockEntity.getLevel(),
|
blockEntity.getLevel(),
|
||||||
|
|
@ -372,9 +397,10 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建菜单实例。
|
* 创建菜单实例。
|
||||||
* @param containerId 容器ID
|
*
|
||||||
|
* @param containerId 容器ID
|
||||||
* @param playerInventory 玩家背包
|
* @param playerInventory 玩家背包
|
||||||
* @param player 玩家
|
* @param player 玩家
|
||||||
* @return 菜单实例
|
* @return 菜单实例
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -386,6 +412,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取升级卡槽数量。
|
* 获取升级卡槽数量。
|
||||||
|
*
|
||||||
* @return 升级卡槽数量
|
* @return 升级卡槽数量
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,30 @@
|
||||||
package com.extendedae_plus.config;
|
package com.extendedae_plus.config;
|
||||||
|
|
||||||
import com.extendedae_plus.ExtendedAEPlus;
|
import com.extendedae_plus.ExtendedAEPlus;
|
||||||
|
import com.extendedae_plus.ae.parts.EntitySpeedTickerPart;
|
||||||
|
import com.extendedae_plus.util.entitySpeed.ConfigParsingUtils;
|
||||||
|
import com.extendedae_plus.util.entitySpeed.PowerUtils;
|
||||||
import dev.toma.configuration.Configuration;
|
import dev.toma.configuration.Configuration;
|
||||||
|
import dev.toma.configuration.client.IValidationHandler;
|
||||||
import dev.toma.configuration.config.Config;
|
import dev.toma.configuration.config.Config;
|
||||||
import dev.toma.configuration.config.Configurable;
|
import dev.toma.configuration.config.Configurable;
|
||||||
import dev.toma.configuration.config.format.ConfigFormats;
|
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;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
import static com.extendedae_plus.util.Logger.EAP$LOGGER;
|
||||||
|
|
||||||
@Config(id = ExtendedAEPlus.MODID)
|
@Config(id = ExtendedAEPlus.MODID)
|
||||||
public final class ModConfig {
|
public final class ModConfig {
|
||||||
|
|
||||||
public static ModConfig INSTANCE;
|
public static ModConfig INSTANCE;
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
|
private static final long DEBOUNCE_INTERVAL = 1000; // 防抖间隔,单位:毫秒
|
||||||
|
private static final AtomicLong lastUpdateTime = new AtomicLong(0);
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
|
|
@ -21,6 +33,7 @@ public final class ModConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configurable
|
@Configurable
|
||||||
@Configurable.Comment(value = {
|
@Configurable.Comment(value = {
|
||||||
"扩展样板供应器总槽位容量的倍率。",
|
"扩展样板供应器总槽位容量的倍率。",
|
||||||
|
|
@ -95,6 +108,7 @@ public final class ModConfig {
|
||||||
})
|
})
|
||||||
@Configurable.Range(min = 0, max = Integer.MAX_VALUE)
|
@Configurable.Range(min = 0, max = Integer.MAX_VALUE)
|
||||||
@Configurable.Synchronized
|
@Configurable.Synchronized
|
||||||
|
@Configurable.ValueUpdateCallback(method = "onEntityTickerCostUpdate")
|
||||||
public int entityTickerCost = 512;
|
public int entityTickerCost = 512;
|
||||||
|
|
||||||
@Configurable
|
@Configurable
|
||||||
|
|
@ -103,9 +117,8 @@ public final class ModConfig {
|
||||||
"格式:全名或通配符/正则字符串,例如 'minecraft:chest'、'minecraft:*'、'modid:.*_fluid'"
|
"格式:全名或通配符/正则字符串,例如 'minecraft:chest'、'minecraft:*'、'modid:.*_fluid'"
|
||||||
})
|
})
|
||||||
@Configurable.Synchronized
|
@Configurable.Synchronized
|
||||||
public String[] entityTickerBlackList = {
|
@Configurable.ValueUpdateCallback(method = "onEntityTickerBlackListUpdate")
|
||||||
|
public String[] entityTickerBlackList = {};
|
||||||
};
|
|
||||||
|
|
||||||
@Configurable
|
@Configurable
|
||||||
@Configurable.Comment(value = {
|
@Configurable.Comment(value = {
|
||||||
|
|
@ -113,9 +126,8 @@ public final class ModConfig {
|
||||||
"支持通配符/正则匹配(例如 'minecraft:* 2x' 会对整个命名空间生效)。"
|
"支持通配符/正则匹配(例如 'minecraft:* 2x' 会对整个命名空间生效)。"
|
||||||
})
|
})
|
||||||
@Configurable.Synchronized
|
@Configurable.Synchronized
|
||||||
public String[] entityTickerMultipliers = {
|
@Configurable.ValueUpdateCallback(method = "onEntityTickerMultipliersUpdate")
|
||||||
|
public String[] entityTickerMultipliers = {};
|
||||||
};
|
|
||||||
|
|
||||||
@Configurable
|
@Configurable
|
||||||
@Configurable.Comment(value = {
|
@Configurable.Comment(value = {
|
||||||
|
|
@ -131,5 +143,45 @@ public final class ModConfig {
|
||||||
"开启后,将优先尝试从磁盘提取FE能量;反之优先消耗AE网络中的能量"
|
"开启后,将优先尝试从磁盘提取FE能量;反之优先消耗AE网络中的能量"
|
||||||
})
|
})
|
||||||
@Configurable.Synchronized
|
@Configurable.Synchronized
|
||||||
|
@Configurable.ValueUpdateCallback(method = "onPrioritizeDiskEnergyUpdate")
|
||||||
public boolean prioritizeDiskEnergy = true;
|
public boolean prioritizeDiskEnergy = true;
|
||||||
|
|
||||||
|
private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
private static ScheduledFuture<?> pendingPowerTask;
|
||||||
|
private static final Object POWER_LOCK = new Object();
|
||||||
|
|
||||||
|
private void onEntityTickerCostUpdate(int newValue, IValidationHandler handler) {
|
||||||
|
synchronized (POWER_LOCK) {
|
||||||
|
if (pendingPowerTask != null) {
|
||||||
|
pendingPowerTask.cancel(false);
|
||||||
|
}
|
||||||
|
pendingPowerTask = EXECUTOR.schedule(() -> {
|
||||||
|
synchronized (PowerUtils.class) {
|
||||||
|
PowerUtils.initializeCaches();
|
||||||
|
}
|
||||||
|
}, 1000, TimeUnit.MILLISECONDS); // 1000ms 防抖
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void onEntityTickerBlackListUpdate(String[] newValue, IValidationHandler handler) {
|
||||||
|
synchronized (ConfigParsingUtils.class) {
|
||||||
|
EAP$LOGGER.info("onEntityTickerBlackListUpdate");
|
||||||
|
ConfigParsingUtils.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onEntityTickerMultipliersUpdate(String[] newValue, IValidationHandler handler) {
|
||||||
|
synchronized (ConfigParsingUtils.class) {
|
||||||
|
EAP$LOGGER.info("onEntityTickerMultipliersUpdate");
|
||||||
|
ConfigParsingUtils.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPrioritizeDiskEnergyUpdate(boolean newValue, dev.toma.configuration.client.IValidationHandler handler) {
|
||||||
|
synchronized (EntitySpeedTickerPart.class) {
|
||||||
|
EAP$LOGGER.info("onPrioritizeDiskEnergyUpdate");
|
||||||
|
EntitySpeedTickerPart.updateCachedAttempts(newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +85,6 @@ public abstract class PatternProviderLogicCompatMixin implements IUpgradeableObj
|
||||||
private void eap$onAppfluxUpgradesChanged(CallbackInfo ci) {
|
private void eap$onAppfluxUpgradesChanged(CallbackInfo ci) {
|
||||||
try {
|
try {
|
||||||
if (UpgradeSlotCompat.shouldEnableChannelCard()) {
|
if (UpgradeSlotCompat.shouldEnableChannelCard()) {
|
||||||
Logger.EAP$LOGGER.info("监听到appflux升级变化,处理频道卡");
|
|
||||||
// 升级变更,重置并尝试初始化频道卡
|
// 升级变更,重置并尝试初始化频道卡
|
||||||
eap$compatLastChannel = -1;
|
eap$compatLastChannel = -1;
|
||||||
eap$compatHasInitialized = false;
|
eap$compatHasInitialized = false;
|
||||||
|
|
@ -100,13 +99,9 @@ public abstract class PatternProviderLogicCompatMixin implements IUpgradeableObj
|
||||||
at = @At("TAIL"))
|
at = @At("TAIL"))
|
||||||
private void eap$compatInitUpgrades(IManagedGridNode mainNode, PatternProviderLogicHost host, int patternInventorySize, CallbackInfo ci) {
|
private void eap$compatInitUpgrades(IManagedGridNode mainNode, PatternProviderLogicHost host, int patternInventorySize, CallbackInfo ci) {
|
||||||
try {
|
try {
|
||||||
Logger.EAP$LOGGER.info("兼容性PatternProviderLogic初始化被调用");
|
|
||||||
|
|
||||||
boolean upgradeSlots = UpgradeSlotCompat.shouldEnableUpgradeSlots();
|
boolean upgradeSlots = UpgradeSlotCompat.shouldEnableUpgradeSlots();
|
||||||
boolean channelCard = UpgradeSlotCompat.shouldEnableChannelCard();
|
boolean channelCard = UpgradeSlotCompat.shouldEnableChannelCard();
|
||||||
|
|
||||||
Logger.EAP$LOGGER.info("升级槽功能: {}, 频道卡功能: {}", upgradeSlots, channelCard);
|
|
||||||
|
|
||||||
if (upgradeSlots) {
|
if (upgradeSlots) {
|
||||||
// 只有在升级槽功能启用时才创建升级槽
|
// 只有在升级槽功能启用时才创建升级槽
|
||||||
this.eap$compatUpgrades = UpgradeInventories.forMachine(
|
this.eap$compatUpgrades = UpgradeInventories.forMachine(
|
||||||
|
|
@ -114,12 +109,9 @@ public abstract class PatternProviderLogicCompatMixin implements IUpgradeableObj
|
||||||
1,
|
1,
|
||||||
this::eap$compatOnUpgradesChanged
|
this::eap$compatOnUpgradesChanged
|
||||||
);
|
);
|
||||||
Logger.EAP$LOGGER.info("创建了完整的升级槽");
|
|
||||||
} else if (channelCard) {
|
} else if (channelCard) {
|
||||||
// 如果装了appflux,我们不创建自己的升级槽,而是监听appflux的升级槽
|
// 如果装了appflux,我们不创建自己的升级槽,而是监听appflux的升级槽
|
||||||
Logger.EAP$LOGGER.info("装了appflux,将监听其升级槽来处理频道卡");
|
|
||||||
} else {
|
} else {
|
||||||
Logger.EAP$LOGGER.info("跳过升级槽创建");
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.EAP$LOGGER.error("兼容性升级初始化失败", e);
|
Logger.EAP$LOGGER.error("兼容性升级初始化失败", e);
|
||||||
|
|
@ -188,7 +180,6 @@ public abstract class PatternProviderLogicCompatMixin implements IUpgradeableObj
|
||||||
} else {
|
} else {
|
||||||
// 装了appflux时,这个方法不应该被调用,因为appflux的Mixin会覆盖它
|
// 装了appflux时,这个方法不应该被调用,因为appflux的Mixin会覆盖它
|
||||||
// 但是为了安全起见,返回空的升级槽
|
// 但是为了安全起见,返回空的升级槽
|
||||||
Logger.EAP$LOGGER.debug("装了appflux时getUpgrades被调用,这不应该发生");
|
|
||||||
return UpgradeInventories.empty();
|
return UpgradeInventories.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -250,7 +241,6 @@ public abstract class PatternProviderLogicCompatMixin implements IUpgradeableObj
|
||||||
if (this instanceof IUpgradeableObject) {
|
if (this instanceof IUpgradeableObject) {
|
||||||
IUpgradeableObject upgradeableThis = (IUpgradeableObject) this;
|
IUpgradeableObject upgradeableThis = (IUpgradeableObject) this;
|
||||||
upgrades = upgradeableThis.getUpgrades();
|
upgrades = upgradeableThis.getUpgrades();
|
||||||
Logger.EAP$LOGGER.debug("从appflux获取到升级槽: {}", upgrades != null);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.EAP$LOGGER.error("获取appflux升级槽失败", e);
|
Logger.EAP$LOGGER.error("获取appflux升级槽失败", e);
|
||||||
|
|
@ -262,7 +252,6 @@ public abstract class PatternProviderLogicCompatMixin implements IUpgradeableObj
|
||||||
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
|
if (!stack.isEmpty() && stack.getItem() == ModItems.CHANNEL_CARD.get()) {
|
||||||
channel = ChannelCardItem.getChannel(stack);
|
channel = ChannelCardItem.getChannel(stack);
|
||||||
found = true;
|
found = true;
|
||||||
Logger.EAP$LOGGER.info("找到频道卡,频道: {}", channel);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,8 @@ public class AppfluxPatternProviderLogicMixin {
|
||||||
at = @At("TAIL"))
|
at = @At("TAIL"))
|
||||||
private void eap$modifyAppfluxUpgradeSlots(IManagedGridNode mainNode, PatternProviderLogicHost host, int patternInventorySize, CallbackInfo ci) {
|
private void eap$modifyAppfluxUpgradeSlots(IManagedGridNode mainNode, PatternProviderLogicHost host, int patternInventorySize, CallbackInfo ci) {
|
||||||
try {
|
try {
|
||||||
Logger.EAP$LOGGER.info("AppfluxPatternProviderLogicMixin被调用!");
|
|
||||||
|
|
||||||
// 只有当appflux存在且不启用我们的升级槽时才修改数量
|
// 只有当appflux存在且不启用我们的升级槽时才修改数量
|
||||||
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots() && UpgradeSlotCompat.shouldEnableChannelCard()) {
|
if (!UpgradeSlotCompat.shouldEnableUpgradeSlots() && UpgradeSlotCompat.shouldEnableChannelCard()) {
|
||||||
Logger.EAP$LOGGER.info("尝试修改appflux升级槽数量为2个");
|
|
||||||
|
|
||||||
// 使用反射找到appflux的升级槽字段并替换
|
// 使用反射找到appflux的升级槽字段并替换
|
||||||
try {
|
try {
|
||||||
Field upgradesField = this.getClass().getDeclaredField("af_$upgrades");
|
Field upgradesField = this.getClass().getDeclaredField("af_$upgrades");
|
||||||
|
|
@ -41,8 +37,6 @@ public class AppfluxPatternProviderLogicMixin {
|
||||||
IUpgradeInventory currentUpgrades = (IUpgradeInventory) upgradesField.get(this);
|
IUpgradeInventory currentUpgrades = (IUpgradeInventory) upgradesField.get(this);
|
||||||
|
|
||||||
if (currentUpgrades != null) {
|
if (currentUpgrades != null) {
|
||||||
Logger.EAP$LOGGER.info("找到appflux升级槽,当前大小: {}", currentUpgrades.size());
|
|
||||||
|
|
||||||
// 创建新的2槽升级槽
|
// 创建新的2槽升级槽
|
||||||
IUpgradeInventory newUpgrades = UpgradeInventories.forMachine(
|
IUpgradeInventory newUpgrades = UpgradeInventories.forMachine(
|
||||||
host.getTerminalIcon().getItem(),
|
host.getTerminalIcon().getItem(),
|
||||||
|
|
@ -66,7 +60,6 @@ public class AppfluxPatternProviderLogicMixin {
|
||||||
|
|
||||||
// 替换升级槽
|
// 替换升级槽
|
||||||
upgradesField.set(this, newUpgrades);
|
upgradesField.set(this, newUpgrades);
|
||||||
Logger.EAP$LOGGER.info("成功将appflux升级槽替换为2个槽");
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.EAP$LOGGER.error("反射修改appflux升级槽失败", e);
|
Logger.EAP$LOGGER.error("反射修改appflux升级槽失败", e);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.regex.PatternSyntaxException;
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
|
@ -33,8 +32,6 @@ public final class ConfigParsingUtils {
|
||||||
private static volatile Map<String, Boolean> blacklistResultCache = new HashMap<>();
|
private static volatile Map<String, Boolean> blacklistResultCache = new HashMap<>();
|
||||||
private static volatile Map<String, Double> multiplierResultCache = new HashMap<>();
|
private static volatile Map<String, Double> multiplierResultCache = new HashMap<>();
|
||||||
private static final Object CACHE_LOCK = new Object();
|
private static final Object CACHE_LOCK = new Object();
|
||||||
private static final AtomicLong callCounter = new AtomicLong(0);
|
|
||||||
private static final long CHECK_INTERVAL = 100;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
初始化缓存,在模组加载时调用
|
初始化缓存,在模组加载时调用
|
||||||
|
|
@ -121,7 +118,6 @@ public final class ConfigParsingUtils {
|
||||||
if (blockId == null || BLACKLIST_SUPPLIER.get() == null || BLACKLIST_SUPPLIER.get().length == 0) {
|
if (blockId == null || BLACKLIST_SUPPLIER.get() == null || BLACKLIST_SUPPLIER.get().length == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
checkConfigChange();
|
|
||||||
return blacklistResultCache.computeIfAbsent(blockId, id ->
|
return blacklistResultCache.computeIfAbsent(blockId, id ->
|
||||||
getCachedBlacklist().values().stream().anyMatch(p -> p.matcher(id).matches())
|
getCachedBlacklist().values().stream().anyMatch(p -> p.matcher(id).matches())
|
||||||
);
|
);
|
||||||
|
|
@ -134,7 +130,6 @@ public final class ConfigParsingUtils {
|
||||||
if (blockId == null || MULTIPLIERS_SUPPLIER.get() == null || MULTIPLIERS_SUPPLIER.get().length == 0) {
|
if (blockId == null || MULTIPLIERS_SUPPLIER.get() == null || MULTIPLIERS_SUPPLIER.get().length == 0) {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
checkConfigChange();
|
|
||||||
return multiplierResultCache.computeIfAbsent(blockId, id -> {
|
return multiplierResultCache.computeIfAbsent(blockId, id -> {
|
||||||
double maxMultiplier = 1.0;
|
double maxMultiplier = 1.0;
|
||||||
for (MultiplierEntry me : getCachedMultiplierEntries().values()) {
|
for (MultiplierEntry me : getCachedMultiplierEntries().values()) {
|
||||||
|
|
@ -213,22 +208,6 @@ public final class ConfigParsingUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 每 100 次调用检查配置是否变化。
|
|
||||||
*/
|
|
||||||
private static void checkConfigChange() {
|
|
||||||
if (callCounter.incrementAndGet() % CHECK_INTERVAL == 0) {
|
|
||||||
String[] currentBlacklist = BLACKLIST_SUPPLIER.get();
|
|
||||||
String[] currentMultipliers = MULTIPLIERS_SUPPLIER.get();
|
|
||||||
synchronized (CACHE_LOCK) {
|
|
||||||
if (cachedBlacklistSourceSnapshot == null || !Arrays.equals(cachedBlacklistSourceSnapshot, currentBlacklist) ||
|
|
||||||
cachedMultiplierSourceSnapshot == null || !Arrays.equals(cachedMultiplierSourceSnapshot, currentMultipliers)) {
|
|
||||||
reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空缓存,下一次获取时将重新解析。
|
* 清空缓存,下一次获取时将重新解析。
|
||||||
*/
|
*/
|
||||||
|
|
@ -240,7 +219,6 @@ public final class ConfigParsingUtils {
|
||||||
cachedMultiplierSourceSnapshot = null;
|
cachedMultiplierSourceSnapshot = null;
|
||||||
blacklistResultCache.clear();
|
blacklistResultCache.clear();
|
||||||
multiplierResultCache.clear();
|
multiplierResultCache.clear();
|
||||||
callCounter.set(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,7 +9,6 @@ import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用于计算实体加速器的能耗与加速倍率的工具类
|
* 用于计算实体加速器的能耗与加速倍率的工具类
|
||||||
|
|
@ -17,12 +16,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
public final class PowerUtils {
|
public final class PowerUtils {
|
||||||
private static final int[] VALID_MULTIPLIERS = {2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
|
private static final int[] VALID_MULTIPLIERS = {2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
|
||||||
private static final int[] VALID_ENERGY_CARD_COUNTS = {0, 1, 2, 3, 4, 5, 6, 7, 8};
|
private static final int[] VALID_ENERGY_CARD_COUNTS = {0, 1, 2, 3, 4, 5, 6, 7, 8};
|
||||||
private static final AtomicInteger checkCounter = new AtomicInteger(0); // 原子计数器
|
|
||||||
private static final int CHECK_COUNTER_THRESHOLD = 100; // 配置检查阈值
|
|
||||||
private static final int CHECK_COUNTER_RESET_THRESHOLD = 10000; // 计数器重置阈值
|
|
||||||
private static volatile Map<Integer, Map<Integer, Double>> powerCache = new HashMap<>();
|
private static volatile Map<Integer, Map<Integer, Double>> powerCache = new HashMap<>();
|
||||||
private static volatile Map<Integer, Double> ratioCache = new HashMap<>();
|
private static volatile Map<Integer, Double> ratioCache = new HashMap<>();
|
||||||
private static volatile int lastEntityTickerCost = -1;
|
|
||||||
|
|
||||||
// 静态初始化块,预计算缓存
|
// 静态初始化块,预计算缓存
|
||||||
static {
|
static {
|
||||||
|
|
@ -34,7 +29,7 @@ public final class PowerUtils {
|
||||||
/**
|
/**
|
||||||
* 初始化所有可能的缓存条目
|
* 初始化所有可能的缓存条目
|
||||||
*/
|
*/
|
||||||
private static void initializeCaches() {
|
public static void initializeCaches() {
|
||||||
synchronized (PowerUtils.class) {
|
synchronized (PowerUtils.class) {
|
||||||
powerCache.clear();
|
powerCache.clear();
|
||||||
ratioCache.clear();
|
ratioCache.clear();
|
||||||
|
|
@ -54,7 +49,6 @@ public final class PowerUtils {
|
||||||
}
|
}
|
||||||
powerCache.put(product, energyCardMap);
|
powerCache.put(product, energyCardMap);
|
||||||
}
|
}
|
||||||
lastEntityTickerCost = ModConfig.INSTANCE.entityTickerCost;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,17 +125,6 @@ public final class PowerUtils {
|
||||||
*/
|
*/
|
||||||
public static double getCachedPower(int product, int energyCardCount) {
|
public static double getCachedPower(int product, int energyCardCount) {
|
||||||
if (product <= 1) return 0.0;
|
if (product <= 1) return 0.0;
|
||||||
// 每 100 次调用检查一次配置
|
|
||||||
if (checkCounter.getAndIncrement() % CHECK_COUNTER_THRESHOLD == 0) {
|
|
||||||
checkCounter.set(checkCounter.get() % CHECK_COUNTER_RESET_THRESHOLD);
|
|
||||||
if (lastEntityTickerCost != ModConfig.INSTANCE.entityTickerCost) {
|
|
||||||
synchronized (PowerUtils.class) {
|
|
||||||
if (lastEntityTickerCost != ModConfig.INSTANCE.entityTickerCost) {
|
|
||||||
initializeCaches();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Map<Integer, Double> energyCardMap = powerCache.get(product);
|
Map<Integer, Double> energyCardMap = powerCache.get(product);
|
||||||
if (energyCardMap == null) return 0.0;
|
if (energyCardMap == null) return 0.0;
|
||||||
Double cachedPower = energyCardMap.get(energyCardCount);
|
Double cachedPower = energyCardMap.get(energyCardCount);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user