feat: 添加缓存
This commit is contained in:
parent
704f8ebd93
commit
ef4337d2c3
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user