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() {
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.ModMenuTypes;
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.PowerUtils;
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.BlockEntityType;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.registries.ForgeRegistries;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
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>
*/
public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTickable, MenuProvider, IUpgradeableObject {
public static final ResourceLocation MODEL_BASE = new ResourceLocation(
ExtendedAEPlus.MODID, "part/entity_speed_ticker_part");
public static final ResourceLocation MODEL_BASE = new ResourceLocation(ExtendedAEPlus.MODID, "part/entity_speed_ticker_part");
@PartModels
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
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 Method cachedFEExtractMethod;
private static volatile MethodHandle cachedFEExtractHandle;
private static volatile boolean FE_UNAVAILABLE;
// 静态块初始化缓存
static {
cachedAttempts = ModConfig.INSTANCE.prioritizeDiskEnergy ? new boolean[]{true, false, true} : new boolean[]{false, true, true};
if (ModList.get().isLoaded("appflux")) {
if (ModCheckUtils.isLoaded(ModCheckUtils.MODID_APPFLUX)) {
try {
Class<?> helperClass = Class.forName("com.extendedae_plus.util.FluxEnergyHelper");
cachedFEExtractMethod = helperClass.getMethod(
"extractFE",
IEnergyService.class,
MEStorage.class,
long.class,
IActionSource.class
);
Method method = helperClass.getMethod("extractFE", IEnergyService.class, MEStorage.class, long.class, IActionSource.class);
cachedFEExtractHandle = MethodHandles.lookup().unreflect(method);
FE_UNAVAILABLE = false;
} catch (Exception e) {
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() {
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;
}
@ -148,7 +133,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
*
* @param sufficient 是否能量充足
*/
private void updateNetworkEnergySufficient(boolean sufficient) {
private void setNetworkEnergySufficient(boolean sufficient) {
this.networkEnergySufficient = sufficient;
if (menu != null) {
menu.setNetworkEnergySufficient(sufficient);
@ -248,8 +233,8 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
* @param blockEntity 目标方块实体
* @param <T> 方块实体类型
*/
private <T extends BlockEntity> void ticker(@NotNull T blockEntity) {
if (!isValidForTicking()) {
private <T extends BlockEntity> void ticker(@Nullable T blockEntity) {
if (blockEntity == null || !isValidForTicking()) {
return;
}
@ -324,12 +309,6 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
return PowerUtils.computeProductWithCap(getUpgrades(), 8);
}
/**
* 提取网络能量并更新状态优先从 AE2 网络提取 AE 能量不足时从磁盘提取 FE 能量
*
* @param requiredPower 所需能量AE 单位
* @return 是否成功提取足够能量
*/
/**
* 提取网络能量并更新状态优先从 AE2 网络提取 AE 能量不足时从磁盘提取 FE 能量
* @param requiredPower 所需能量AE 单位
@ -352,10 +331,10 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
if (simulated >= requiredPower) {
double extracted = energyService.extractAEPower(requiredPower, Actionable.MODULATE, PowerMultiplier.CONFIG);
boolean sufficient = extracted >= requiredPower;
updateNetworkEnergySufficient(sufficient);
setNetworkEnergySufficient(sufficient);
return sufficient;
}
updateNetworkEnergySufficient(false);
setNetworkEnergySufficient(false);
// 如果没成功且不是优先磁盘能量再尝试 FE
if (!preferDiskEnergy) {
@ -366,22 +345,22 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
}
private boolean tryExtractFE(IEnergyService energyService, MEStorage storage, double requiredPower, IActionSource source) {
if (FE_UNAVAILABLE || cachedFEExtractMethod == null) {
updateNetworkEnergySufficient(false);
if (FE_UNAVAILABLE || cachedFEExtractHandle == null) {
setNetworkEnergySufficient(false);
return false;
}
try {
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) {
updateNetworkEnergySufficient(true);
setNetworkEnergySufficient(true);
return true;
}
} catch (Exception e) {
}catch (Throwable e) {
// 如果反射调用失败标记为不可用避免下次继续尝试
FE_UNAVAILABLE = true;
}
updateNetworkEnergySufficient(false);
setNetworkEnergySufficient(false);
return false;
}

View File

@ -1,7 +1,6 @@
package com.extendedae_plus.config;
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;
@ -14,17 +13,12 @@ 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)
public final class ModConfig {
public static ModConfig INSTANCE;
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() {
synchronized (lock) {
@ -149,6 +143,7 @@ public final class ModConfig {
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) {
@ -159,29 +154,20 @@ public final class ModConfig {
synchronized (PowerUtils.class) {
PowerUtils.initializeCaches();
}
}, 1000, TimeUnit.MILLISECONDS); // 1000ms 防抖
}, DEBOUNCE_INTERVAL, 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);
}
}
}

View File

@ -29,21 +29,21 @@ public class MixinConditions implements IMixinConfigPlugin {
// === MAE2 兼容 ===
if (mixinClassName.contains("CraftingCPUClusterMixin")) {
boolean shouldApply = !ModCheckUtils.isLoaded(ModCheckUtils.MODID_MAE2);
log(mixinClassName, "MAE2", shouldApply);
log(mixinClassName, ModCheckUtils.MODID_MAE2, shouldApply);
return shouldApply;
}
// === AAE 兼容 ===
if (mixinClassName.startsWith("com.extendedae_plus.mixin.advancedae")) {
boolean shouldApply = ModCheckUtils.isLoaded(ModCheckUtils.MODID_AAE);
log(mixinClassName, "aae", shouldApply);
log(mixinClassName, ModCheckUtils.MODID_AAE, shouldApply);
return shouldApply;
}
// === GuideME 版本兼容 ===
if (mixinClassName.startsWith("com.extendedae_plus.mixin.guideme.")) {
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;
}