feat: 实体加速器优化

This commit is contained in:
C-H716 2025-10-23 02:51:53 +08:00
parent d0155c2a96
commit f04c6297f9
4 changed files with 27 additions and 62 deletions

View File

@ -148,7 +148,7 @@ public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart
*/ */
private void updateNetworkEnergyStatus() { private void updateNetworkEnergyStatus() {
if (!isClientSide() && getHost() != null) { if (!isClientSide() && getHost() != null) {
this.networkEnergySufficient = getHost().isNetworkEnergySufficient(); this.networkEnergySufficient = getHost().getNetworkEnergySufficient();
} }
} }

View File

@ -27,6 +27,7 @@ import com.extendedae_plus.config.ModConfig;
import com.extendedae_plus.init.ModItems; import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.init.ModMenuTypes; import com.extendedae_plus.init.ModMenuTypes;
import com.extendedae_plus.util.Logger; import com.extendedae_plus.util.Logger;
import com.extendedae_plus.util.ModCheckUtils;
import com.extendedae_plus.util.entitySpeed.ConfigParsingUtils; import com.extendedae_plus.util.entitySpeed.ConfigParsingUtils;
import com.extendedae_plus.util.entitySpeed.PowerUtils; import com.extendedae_plus.util.entitySpeed.PowerUtils;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -41,11 +42,12 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method; import java.lang.reflect.Method;
/** /**
@ -53,8 +55,7 @@ import java.lang.reflect.Method;
* 灵感来源于 <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");
@PartModels @PartModels
public static final PartModel MODELS_OFF = new PartModel(MODEL_BASE, new ResourceLocation(ExtendedAEPlus.MODID, "part/entity_speed_ticker_off")); public static final PartModel MODELS_OFF = new PartModel(MODEL_BASE, new ResourceLocation(ExtendedAEPlus.MODID, "part/entity_speed_ticker_off"));
@ -63,27 +64,20 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
@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"));
private static volatile boolean[] cachedAttempts; private static volatile MethodHandle cachedFEExtractHandle;
private static volatile Method cachedFEExtractMethod;
private static volatile boolean FE_UNAVAILABLE; private static volatile boolean FE_UNAVAILABLE;
// 静态块初始化缓存 // 静态块初始化缓存
static { static {
cachedAttempts = ModConfig.INSTANCE.prioritizeDiskEnergy ? new boolean[]{true, false, true} : new boolean[]{false, true, true}; if (ModCheckUtils.isLoaded(ModCheckUtils.MODID_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");
cachedFEExtractMethod = helperClass.getMethod( Method method = helperClass.getMethod("extractFE", IEnergyService.class, MEStorage.class, long.class, IActionSource.class);
"extractFE", cachedFEExtractHandle = MethodHandles.lookup().unreflect(method);
IEnergyService.class,
MEStorage.class,
long.class,
IActionSource.class
);
FE_UNAVAILABLE = false; FE_UNAVAILABLE = false;
} catch (Exception e) { } catch (Exception e) {
FE_UNAVAILABLE = true; FE_UNAVAILABLE = true;
cachedFEExtractHandle = null;
} }
} }
} }
@ -114,15 +108,6 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
); );
} }
/**
* 更新缓存的 attempts 数组 ModConfig 调用
*/
public static void updateCachedAttempts(boolean prioritizeDiskEnergy) {
synchronized (EntitySpeedTickerPart.class) {
cachedAttempts = prioritizeDiskEnergy ? new boolean[]{true, false, true} : new boolean[]{false, true, 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;
} }
@ -139,7 +124,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
} }
} }
public boolean isNetworkEnergySufficient() { public boolean getNetworkEnergySufficient() {
return this.networkEnergySufficient; return this.networkEnergySufficient;
} }
@ -148,7 +133,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
* *
* @param sufficient 是否能量充足 * @param sufficient 是否能量充足
*/ */
private void updateNetworkEnergySufficient(boolean sufficient) { private void setNetworkEnergySufficient(boolean sufficient) {
this.networkEnergySufficient = sufficient; this.networkEnergySufficient = sufficient;
if (menu != null) { if (menu != null) {
menu.setNetworkEnergySufficient(sufficient); menu.setNetworkEnergySufficient(sufficient);
@ -248,8 +233,8 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
* @param blockEntity 目标方块实体 * @param blockEntity 目标方块实体
* @param <T> 方块实体类型 * @param <T> 方块实体类型
*/ */
private <T extends BlockEntity> void ticker(@NotNull T blockEntity) { private <T extends BlockEntity> void ticker(@Nullable T blockEntity) {
if (!isValidForTicking()) { if (blockEntity == null || !isValidForTicking()) {
return; return;
} }
@ -324,12 +309,6 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
return PowerUtils.computeProductWithCap(getUpgrades(), 8); return PowerUtils.computeProductWithCap(getUpgrades(), 8);
} }
/**
* 提取网络能量并更新状态优先从 AE2 网络提取 AE 能量不足时从磁盘提取 FE 能量
*
* @param requiredPower 所需能量AE 单位
* @return 是否成功提取足够能量
*/
/** /**
* 提取网络能量并更新状态优先从 AE2 网络提取 AE 能量不足时从磁盘提取 FE 能量 * 提取网络能量并更新状态优先从 AE2 网络提取 AE 能量不足时从磁盘提取 FE 能量
* @param requiredPower 所需能量AE 单位 * @param requiredPower 所需能量AE 单位
@ -352,10 +331,10 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
if (simulated >= requiredPower) { if (simulated >= requiredPower) {
double extracted = energyService.extractAEPower(requiredPower, Actionable.MODULATE, PowerMultiplier.CONFIG); double extracted = energyService.extractAEPower(requiredPower, Actionable.MODULATE, PowerMultiplier.CONFIG);
boolean sufficient = extracted >= requiredPower; boolean sufficient = extracted >= requiredPower;
updateNetworkEnergySufficient(sufficient); setNetworkEnergySufficient(sufficient);
return sufficient; return sufficient;
} }
updateNetworkEnergySufficient(false); setNetworkEnergySufficient(false);
// 如果没成功且不是优先磁盘能量再尝试 FE // 如果没成功且不是优先磁盘能量再尝试 FE
if (!preferDiskEnergy) { if (!preferDiskEnergy) {
@ -366,22 +345,22 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
} }
private boolean tryExtractFE(IEnergyService energyService, MEStorage storage, double requiredPower, IActionSource source) { private boolean tryExtractFE(IEnergyService energyService, MEStorage storage, double requiredPower, IActionSource source) {
if (FE_UNAVAILABLE || cachedFEExtractMethod == null) { if (FE_UNAVAILABLE || cachedFEExtractHandle == null) {
updateNetworkEnergySufficient(false); setNetworkEnergySufficient(false);
return false; return false;
} }
try { try {
long feRequired = (long) requiredPower << 1; // 1 AE = 2 FE long feRequired = (long) requiredPower << 1; // 1 AE = 2 FE
long feExtracted = (long) cachedFEExtractMethod.invoke(null, energyService, storage, feRequired, source); long feExtracted = (long) cachedFEExtractHandle.invokeExact(null, energyService, storage, feRequired, source);
if (feExtracted >= feRequired) { if (feExtracted >= feRequired) {
updateNetworkEnergySufficient(true); setNetworkEnergySufficient(true);
return true; return true;
} }
} catch (Exception e) { }catch (Throwable e) {
// 如果反射调用失败标记为不可用避免下次继续尝试 // 如果反射调用失败标记为不可用避免下次继续尝试
FE_UNAVAILABLE = true; FE_UNAVAILABLE = true;
} }
updateNetworkEnergySufficient(false); setNetworkEnergySufficient(false);
return false; return false;
} }

View File

@ -1,7 +1,6 @@
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.ConfigParsingUtils;
import com.extendedae_plus.util.entitySpeed.PowerUtils; import com.extendedae_plus.util.entitySpeed.PowerUtils;
import dev.toma.configuration.Configuration; import dev.toma.configuration.Configuration;
@ -14,17 +13,12 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; 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) {
@ -149,6 +143,7 @@ public final class ModConfig {
private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor(); private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> pendingPowerTask; private static ScheduledFuture<?> pendingPowerTask;
private static final Object POWER_LOCK = new Object(); private static final Object POWER_LOCK = new Object();
private static final long DEBOUNCE_INTERVAL = 1000; // 防抖间隔单位毫秒
private void onEntityTickerCostUpdate(int newValue, IValidationHandler handler) { private void onEntityTickerCostUpdate(int newValue, IValidationHandler handler) {
synchronized (POWER_LOCK) { synchronized (POWER_LOCK) {
@ -159,29 +154,20 @@ public final class ModConfig {
synchronized (PowerUtils.class) { synchronized (PowerUtils.class) {
PowerUtils.initializeCaches(); PowerUtils.initializeCaches();
} }
}, 1000, TimeUnit.MILLISECONDS); // 1000ms 防抖 }, DEBOUNCE_INTERVAL, TimeUnit.MILLISECONDS); // 1000ms 防抖
} }
} }
private void onEntityTickerBlackListUpdate(String[] newValue, IValidationHandler handler) { private void onEntityTickerBlackListUpdate(String[] newValue, IValidationHandler handler) {
synchronized (ConfigParsingUtils.class) { synchronized (ConfigParsingUtils.class) {
EAP$LOGGER.info("onEntityTickerBlackListUpdate");
ConfigParsingUtils.reload(); ConfigParsingUtils.reload();
} }
} }
private void onEntityTickerMultipliersUpdate(String[] newValue, IValidationHandler handler) { private void onEntityTickerMultipliersUpdate(String[] newValue, IValidationHandler handler) {
synchronized (ConfigParsingUtils.class) { synchronized (ConfigParsingUtils.class) {
EAP$LOGGER.info("onEntityTickerMultipliersUpdate");
ConfigParsingUtils.reload(); ConfigParsingUtils.reload();
} }
} }
private void onPrioritizeDiskEnergyUpdate(boolean newValue, dev.toma.configuration.client.IValidationHandler handler) {
synchronized (EntitySpeedTickerPart.class) {
EAP$LOGGER.info("onPrioritizeDiskEnergyUpdate");
EntitySpeedTickerPart.updateCachedAttempts(newValue);
}
}
} }

View File

@ -29,21 +29,21 @@ public class MixinConditions implements IMixinConfigPlugin {
// === MAE2 兼容 === // === MAE2 兼容 ===
if (mixinClassName.contains("CraftingCPUClusterMixin")) { if (mixinClassName.contains("CraftingCPUClusterMixin")) {
boolean shouldApply = !ModCheckUtils.isLoaded(ModCheckUtils.MODID_MAE2); boolean shouldApply = !ModCheckUtils.isLoaded(ModCheckUtils.MODID_MAE2);
log(mixinClassName, "MAE2", shouldApply); log(mixinClassName, ModCheckUtils.MODID_MAE2, shouldApply);
return shouldApply; return shouldApply;
} }
// === AAE 兼容 === // === AAE 兼容 ===
if (mixinClassName.startsWith("com.extendedae_plus.mixin.advancedae")) { if (mixinClassName.startsWith("com.extendedae_plus.mixin.advancedae")) {
boolean shouldApply = ModCheckUtils.isLoaded(ModCheckUtils.MODID_AAE); boolean shouldApply = ModCheckUtils.isLoaded(ModCheckUtils.MODID_AAE);
log(mixinClassName, "aae", shouldApply); log(mixinClassName, ModCheckUtils.MODID_AAE, shouldApply);
return shouldApply; return shouldApply;
} }
// === GuideME 版本兼容 === // === GuideME 版本兼容 ===
if (mixinClassName.startsWith("com.extendedae_plus.mixin.guideme.")) { if (mixinClassName.startsWith("com.extendedae_plus.mixin.guideme.")) {
boolean shouldApply = ModCheckUtils.isLoadedAndLowerThan(ModCheckUtils.MODID_GUIDEME, "20.1.14"); boolean shouldApply = ModCheckUtils.isLoadedAndLowerThan(ModCheckUtils.MODID_GUIDEME, "20.1.14");
logVersion(mixinClassName, "GuideME", ModCheckUtils.getVersion(ModCheckUtils.MODID_GUIDEME), "20.1.14", shouldApply); logVersion(mixinClassName, ModCheckUtils.MODID_GUIDEME, ModCheckUtils.getVersion(ModCheckUtils.MODID_GUIDEME), "20.1.14", shouldApply);
return shouldApply; return shouldApply;
} }