feat: 添加缓存

This commit is contained in:
C-H716 2025-09-29 19:53:33 +08:00
parent 704f8ebd93
commit ef4337d2c3
3 changed files with 106 additions and 84 deletions

View File

@ -6,7 +6,6 @@ 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.ModConfig;
import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.init.ModMenuTypes;
import com.extendedae_plus.util.entitySpeed.ConfigParsingUtils;
@ -17,8 +16,6 @@ import net.minecraft.world.inventory.Slot;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.List;
/**
* 实体加速器菜单负责管理客户端与服务端的数据同步处理加速卡能量卡和目标方块的状态
*/
@ -135,8 +132,8 @@ public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart
return;
}
String blockId = ForgeRegistries.BLOCKS.getKey(target.getBlockState().getBlock()).toString();
this.multiplier = ConfigParsingUtils.getMultiplierForBlock(blockId, List.of(ModConfig.INSTANCE.entityTickerMultipliers));
this.targetBlacklisted = ConfigParsingUtils.isBlockBlacklisted(blockId, List.of(ModConfig.INSTANCE.entityTickerBlackList));
this.multiplier = ConfigParsingUtils.getMultiplierForBlock(blockId);
this.targetBlacklisted = ConfigParsingUtils.isBlockBlacklisted(blockId);
}
/**

View File

@ -45,7 +45,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Method;
import java.util.List;
/**
* 实体加速器部件用于加速目标方块实体的 tick 速率消耗 AE 网络能量支持加速卡和能量卡升级
@ -231,7 +230,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
}
String blockId = ForgeRegistries.BLOCKS.getKey(blockEntity.getBlockState().getBlock()).toString();
if (ConfigParsingUtils.isBlockBlacklisted(blockId, List.of(ModConfig.INSTANCE.entityTickerBlackList))) {
if (ConfigParsingUtils.isBlockBlacklisted(blockId)) {
return;
}
@ -252,7 +251,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
// 使用 PowerUtils 的缓存获取能耗并应用方块特定的倍率
double requiredPower = PowerUtils.getCachedPower(cachedSpeed, cachedEnergyCardCount)
* ConfigParsingUtils.getMultiplierForBlock(blockId, List.of(ModConfig.INSTANCE.entityTickerMultipliers));
* ConfigParsingUtils.getMultiplierForBlock(blockId);
if (!extractPower(requiredPower)) {
return;
}

View File

@ -1,8 +1,13 @@
package com.extendedae_plus.util.entitySpeed;
import java.util.ArrayList;
import com.extendedae_plus.config.ModConfig;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@ -14,14 +19,28 @@ import static com.extendedae_plus.util.Logger.EAP$LOGGER;
public final class ConfigParsingUtils {
private ConfigParsingUtils() {}
public static final class MultiplierEntry {
public final Pattern pattern;
public final double multiplier;
public record MultiplierEntry(Pattern pattern, double multiplier) { }
public MultiplierEntry(Pattern pattern, double multiplier) {
this.pattern = pattern;
this.multiplier = multiplier;
}
// 直接引用配置
private static final Supplier<String[]> BLACKLIST_SUPPLIER = () -> ModConfig.INSTANCE.entityTickerBlackList;
private static final Supplier<String[]> MULTIPLIERS_SUPPLIER = () -> ModConfig.INSTANCE.entityTickerMultipliers;
// 缓存字段
private static volatile Map<String, Pattern> cachedBlacklist = null;
private static volatile Map<String, MultiplierEntry> cachedMultiplierEntries = null;
private static volatile String[] cachedBlacklistSourceSnapshot = null;
private static volatile String[] cachedMultiplierSourceSnapshot = null;
private static volatile Map<String, Boolean> blacklistResultCache = new HashMap<>();
private static volatile Map<String, Double> multiplierResultCache = new HashMap<>();
private static final Object CACHE_LOCK = new Object();
private static final AtomicLong callCounter = new AtomicLong(0);
private static final long CHECK_INTERVAL = 100;
/*
初始化缓存在模组加载时调用
*/
static {
reload();
}
/**
@ -98,116 +117,120 @@ public final class ConfigParsingUtils {
/**
* 检查方块是否在黑名单中
*/
public static boolean isBlockBlacklisted(String blockId, List<? extends String> blacklist) {
if (blockId == null) return false;
return getCachedBlacklist(blacklist).stream().anyMatch(p -> p.matcher(blockId).matches());
public static boolean isBlockBlacklisted(String blockId) {
if (blockId == null || BLACKLIST_SUPPLIER.get() == null || BLACKLIST_SUPPLIER.get().length == 0) {
return false;
}
checkConfigChange();
return blacklistResultCache.computeIfAbsent(blockId, id ->
getCachedBlacklist().values().stream().anyMatch(p -> p.matcher(id).matches())
);
}
/**
* 获取方块的倍率
*/
public static double getMultiplierForBlock(String blockId, List<? extends String> multipliers) {
if (blockId == null) return 1.0;
double maxMultiplier = 1.0;
for (MultiplierEntry me : getCachedMultiplierEntries(multipliers)) {
if (me.pattern.matcher(blockId).matches()) {
maxMultiplier = Math.max(maxMultiplier, me.multiplier);
}
public static double getMultiplierForBlock(String blockId) {
if (blockId == null || MULTIPLIERS_SUPPLIER.get() == null || MULTIPLIERS_SUPPLIER.get().length == 0) {
return 1.0;
}
return maxMultiplier;
checkConfigChange();
return multiplierResultCache.computeIfAbsent(blockId, id -> {
double maxMultiplier = 1.0;
for (MultiplierEntry me : getCachedMultiplierEntries().values()) {
if (me.pattern.matcher(id).matches()) {
maxMultiplier = Math.max(maxMultiplier, me.multiplier);
}
}
return maxMultiplier;
});
}
public static List<Pattern> compilePatterns(List<? extends String> raw) {
List<Pattern> out = new ArrayList<>();
/**
* 编译黑名单配置为 Map
*/
public static Map<String, Pattern> compilePatterns(String[] raw) {
Map<String, Pattern> out = new HashMap<>();
if (raw == null) return out;
for (String s : raw) {
if (s == null || s.trim().isEmpty()) continue;
String trimmed = s.trim();
try {
out.add(compilePattern(s));
out.put(trimmed, compilePattern(trimmed));
} catch (IllegalArgumentException e) {
EAP$LOGGER.warn("Failed to compile pattern '{}': {}", s, e.getMessage());
EAP$LOGGER.warn("Failed to compile pattern '{}': {}", trimmed, e.getMessage());
}
}
return out;
}
public static List<MultiplierEntry> parseMultiplierList(List<? extends String> raw) {
List<MultiplierEntry> out = new ArrayList<>();
/**
* 解析倍率配置为 Map
*/
public static Map<String, MultiplierEntry> parseMultiplierList(String[] raw) {
Map<String, MultiplierEntry> out = new HashMap<>();
if (raw == null) return out;
for (String s : raw) {
MultiplierEntry me = parseMultiplierEntry(s);
if (me != null) out.add(me);
if (s == null || s.trim().isEmpty()) continue;
String trimmed = s.trim();
MultiplierEntry me = parseMultiplierEntry(trimmed);
if (me != null) out.put(trimmed, me);
}
return out;
}
// ------------------ 全局缓存与接口 ------------------
private static volatile List<Pattern> cachedBlacklist = null;
private static volatile List<MultiplierEntry> cachedMultiplierEntries = null;
private static volatile List<String> cachedBlacklistSourceSnapshot = null;
private static volatile List<String> cachedMultiplierSourceSnapshot = null;
private static final Object CACHE_LOCK = new Object();
/**
* 获取已解析并缓存的黑名单线程安全懒加载
*/
public static List<Pattern> getCachedBlacklist(List<? extends String> source) {
List<String> normalized = normalizeSource(source);
if (cachedBlacklist != null && listEquals(cachedBlacklistSourceSnapshot, normalized)) {
return Collections.unmodifiableList(cachedBlacklist);
private static Map<String, Pattern> getCachedBlacklist() {
String[] source = BLACKLIST_SUPPLIER.get();
if (cachedBlacklist != null && Arrays.equals(cachedBlacklistSourceSnapshot, source)) {
return Collections.unmodifiableMap(cachedBlacklist);
}
synchronized (CACHE_LOCK) {
if (cachedBlacklist == null || !listEquals(cachedBlacklistSourceSnapshot, normalized)) {
cachedBlacklist = compilePatterns(normalized);
cachedBlacklistSourceSnapshot = normalized.isEmpty() ? Collections.emptyList() : new ArrayList<>(normalized);
if (cachedBlacklist == null || !Arrays.equals(cachedBlacklistSourceSnapshot, source)) {
cachedBlacklist = compilePatterns(source);
cachedBlacklistSourceSnapshot = source == null ? new String[0] : source.clone();
}
return Collections.unmodifiableList(cachedBlacklist);
return Collections.unmodifiableMap(cachedBlacklist);
}
}
/**
* 获取已解析并缓存的倍率列表线程安全懒加载
*/
public static List<MultiplierEntry> getCachedMultiplierEntries(List<? extends String> source) {
List<String> normalized = normalizeSource(source);
if (cachedMultiplierEntries != null && listEquals(cachedMultiplierSourceSnapshot, normalized)) {
return Collections.unmodifiableList(cachedMultiplierEntries);
private static Map<String, MultiplierEntry> getCachedMultiplierEntries() {
String[] source = MULTIPLIERS_SUPPLIER.get();
if (cachedMultiplierEntries != null && Arrays.equals(cachedMultiplierSourceSnapshot, source)) {
return Collections.unmodifiableMap(cachedMultiplierEntries);
}
synchronized (CACHE_LOCK) {
if (cachedMultiplierEntries == null || !listEquals(cachedMultiplierSourceSnapshot, normalized)) {
cachedMultiplierEntries = parseMultiplierList(normalized);
cachedMultiplierSourceSnapshot = normalized.isEmpty() ? Collections.emptyList() : new ArrayList<>(normalized);
if (cachedMultiplierEntries == null || !Arrays.equals(cachedMultiplierSourceSnapshot, source)) {
cachedMultiplierEntries = parseMultiplierList(source);
cachedMultiplierSourceSnapshot = source == null ? new String[0] : source.clone();
}
return Collections.unmodifiableList(cachedMultiplierEntries);
return Collections.unmodifiableMap(cachedMultiplierEntries);
}
}
// Normalize the incoming source list: trim entries, drop blanks, keep stable ordering
private static List<String> normalizeSource(java.util.List<? extends String> source) {
List<String> out = new ArrayList<>();
if (source == null) return out;
for (String s : source) {
if (s == null) continue;
String t = s.trim();
if (t.isEmpty()) continue;
out.add(t);
}
return out;
}
// Null-safe equality for two lists of strings. Uses size + element equals.
private static boolean listEquals(List<String> a, List<String> b) {
if (a == b) return true;
if (a == null || b == null) return false;
if (a.size() != b.size()) return false;
for (int i = 0; i < a.size(); i++) {
if (!a.get(i).equals(b.get(i))) return false;
}
return true;
}
/**
* 清空缓存下一次获取时将重新从提供的源解析或调用方可以重新调用 getter
* 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();
}
}
}
}
/**
* 清空缓存下一次获取时将重新解析
*/
public static void reload() {
synchronized (CACHE_LOCK) {
@ -215,6 +238,9 @@ public final class ConfigParsingUtils {
cachedMultiplierEntries = null;
cachedBlacklistSourceSnapshot = null;
cachedMultiplierSourceSnapshot = null;
blacklistResultCache.clear();
multiplierResultCache.clear();
callCounter.set(0);
}
}
}