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 appeng.menu.slot.OptionalFakeSlot;
|
||||||
import com.extendedae_plus.ae.parts.EntitySpeedTickerPart;
|
import com.extendedae_plus.ae.parts.EntitySpeedTickerPart;
|
||||||
import com.extendedae_plus.ae.screen.EntitySpeedTickerScreen;
|
import com.extendedae_plus.ae.screen.EntitySpeedTickerScreen;
|
||||||
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.entitySpeed.ConfigParsingUtils;
|
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.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraftforge.registries.ForgeRegistries;
|
import net.minecraftforge.registries.ForgeRegistries;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实体加速器菜单,负责管理客户端与服务端的数据同步,处理加速卡、能量卡和目标方块的状态。
|
* 实体加速器菜单,负责管理客户端与服务端的数据同步,处理加速卡、能量卡和目标方块的状态。
|
||||||
*/
|
*/
|
||||||
|
|
@ -135,8 +132,8 @@ public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String blockId = ForgeRegistries.BLOCKS.getKey(target.getBlockState().getBlock()).toString();
|
String blockId = ForgeRegistries.BLOCKS.getKey(target.getBlockState().getBlock()).toString();
|
||||||
this.multiplier = ConfigParsingUtils.getMultiplierForBlock(blockId, List.of(ModConfig.INSTANCE.entityTickerMultipliers));
|
this.multiplier = ConfigParsingUtils.getMultiplierForBlock(blockId);
|
||||||
this.targetBlacklisted = ConfigParsingUtils.isBlockBlacklisted(blockId, List.of(ModConfig.INSTANCE.entityTickerBlackList));
|
this.targetBlacklisted = ConfigParsingUtils.isBlockBlacklisted(blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实体加速器部件,用于加速目标方块实体的 tick 速率,消耗 AE 网络能量,支持加速卡和能量卡升级。
|
* 实体加速器部件,用于加速目标方块实体的 tick 速率,消耗 AE 网络能量,支持加速卡和能量卡升级。
|
||||||
|
|
@ -231,7 +230,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
}
|
}
|
||||||
|
|
||||||
String blockId = ForgeRegistries.BLOCKS.getKey(blockEntity.getBlockState().getBlock()).toString();
|
String blockId = ForgeRegistries.BLOCKS.getKey(blockEntity.getBlockState().getBlock()).toString();
|
||||||
if (ConfigParsingUtils.isBlockBlacklisted(blockId, List.of(ModConfig.INSTANCE.entityTickerBlackList))) {
|
if (ConfigParsingUtils.isBlockBlacklisted(blockId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,7 +251,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTick
|
||||||
|
|
||||||
// 使用 PowerUtils 的缓存获取能耗,并应用方块特定的倍率
|
// 使用 PowerUtils 的缓存获取能耗,并应用方块特定的倍率
|
||||||
double requiredPower = PowerUtils.getCachedPower(cachedSpeed, cachedEnergyCardCount)
|
double requiredPower = PowerUtils.getCachedPower(cachedSpeed, cachedEnergyCardCount)
|
||||||
* ConfigParsingUtils.getMultiplierForBlock(blockId, List.of(ModConfig.INSTANCE.entityTickerMultipliers));
|
* ConfigParsingUtils.getMultiplierForBlock(blockId);
|
||||||
if (!extractPower(requiredPower)) {
|
if (!extractPower(requiredPower)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
package com.extendedae_plus.util.entitySpeed;
|
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.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.Pattern;
|
||||||
import java.util.regex.PatternSyntaxException;
|
import java.util.regex.PatternSyntaxException;
|
||||||
|
|
||||||
|
|
@ -14,14 +19,28 @@ import static com.extendedae_plus.util.Logger.EAP$LOGGER;
|
||||||
public final class ConfigParsingUtils {
|
public final class ConfigParsingUtils {
|
||||||
private ConfigParsingUtils() {}
|
private ConfigParsingUtils() {}
|
||||||
|
|
||||||
public static final class MultiplierEntry {
|
public record MultiplierEntry(Pattern pattern, double multiplier) { }
|
||||||
public final Pattern pattern;
|
|
||||||
public final double multiplier;
|
|
||||||
|
|
||||||
public MultiplierEntry(Pattern pattern, double multiplier) {
|
// 直接引用配置
|
||||||
this.pattern = pattern;
|
private static final Supplier<String[]> BLACKLIST_SUPPLIER = () -> ModConfig.INSTANCE.entityTickerBlackList;
|
||||||
this.multiplier = multiplier;
|
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) {
|
public static boolean isBlockBlacklisted(String blockId) {
|
||||||
if (blockId == null) return false;
|
if (blockId == null || BLACKLIST_SUPPLIER.get() == null || BLACKLIST_SUPPLIER.get().length == 0) {
|
||||||
return getCachedBlacklist(blacklist).stream().anyMatch(p -> p.matcher(blockId).matches());
|
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) {
|
public static double getMultiplierForBlock(String blockId) {
|
||||||
if (blockId == null) return 1.0;
|
if (blockId == null || MULTIPLIERS_SUPPLIER.get() == null || MULTIPLIERS_SUPPLIER.get().length == 0) {
|
||||||
double maxMultiplier = 1.0;
|
return 1.0;
|
||||||
for (MultiplierEntry me : getCachedMultiplierEntries(multipliers)) {
|
|
||||||
if (me.pattern.matcher(blockId).matches()) {
|
|
||||||
maxMultiplier = Math.max(maxMultiplier, me.multiplier);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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;
|
if (raw == null) return out;
|
||||||
for (String s : raw) {
|
for (String s : raw) {
|
||||||
if (s == null || s.trim().isEmpty()) continue;
|
if (s == null || s.trim().isEmpty()) continue;
|
||||||
|
String trimmed = s.trim();
|
||||||
try {
|
try {
|
||||||
out.add(compilePattern(s));
|
out.put(trimmed, compilePattern(trimmed));
|
||||||
} catch (IllegalArgumentException e) {
|
} 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;
|
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;
|
if (raw == null) return out;
|
||||||
for (String s : raw) {
|
for (String s : raw) {
|
||||||
MultiplierEntry me = parseMultiplierEntry(s);
|
if (s == null || s.trim().isEmpty()) continue;
|
||||||
if (me != null) out.add(me);
|
String trimmed = s.trim();
|
||||||
|
MultiplierEntry me = parseMultiplierEntry(trimmed);
|
||||||
|
if (me != null) out.put(trimmed, me);
|
||||||
}
|
}
|
||||||
return out;
|
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) {
|
private static Map<String, Pattern> getCachedBlacklist() {
|
||||||
List<String> normalized = normalizeSource(source);
|
String[] source = BLACKLIST_SUPPLIER.get();
|
||||||
if (cachedBlacklist != null && listEquals(cachedBlacklistSourceSnapshot, normalized)) {
|
if (cachedBlacklist != null && Arrays.equals(cachedBlacklistSourceSnapshot, source)) {
|
||||||
return Collections.unmodifiableList(cachedBlacklist);
|
return Collections.unmodifiableMap(cachedBlacklist);
|
||||||
}
|
}
|
||||||
synchronized (CACHE_LOCK) {
|
synchronized (CACHE_LOCK) {
|
||||||
if (cachedBlacklist == null || !listEquals(cachedBlacklistSourceSnapshot, normalized)) {
|
if (cachedBlacklist == null || !Arrays.equals(cachedBlacklistSourceSnapshot, source)) {
|
||||||
cachedBlacklist = compilePatterns(normalized);
|
cachedBlacklist = compilePatterns(source);
|
||||||
cachedBlacklistSourceSnapshot = normalized.isEmpty() ? Collections.emptyList() : new ArrayList<>(normalized);
|
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) {
|
private static Map<String, MultiplierEntry> getCachedMultiplierEntries() {
|
||||||
List<String> normalized = normalizeSource(source);
|
String[] source = MULTIPLIERS_SUPPLIER.get();
|
||||||
if (cachedMultiplierEntries != null && listEquals(cachedMultiplierSourceSnapshot, normalized)) {
|
if (cachedMultiplierEntries != null && Arrays.equals(cachedMultiplierSourceSnapshot, source)) {
|
||||||
return Collections.unmodifiableList(cachedMultiplierEntries);
|
return Collections.unmodifiableMap(cachedMultiplierEntries);
|
||||||
}
|
}
|
||||||
synchronized (CACHE_LOCK) {
|
synchronized (CACHE_LOCK) {
|
||||||
if (cachedMultiplierEntries == null || !listEquals(cachedMultiplierSourceSnapshot, normalized)) {
|
if (cachedMultiplierEntries == null || !Arrays.equals(cachedMultiplierSourceSnapshot, source)) {
|
||||||
cachedMultiplierEntries = parseMultiplierList(normalized);
|
cachedMultiplierEntries = parseMultiplierList(source);
|
||||||
cachedMultiplierSourceSnapshot = normalized.isEmpty() ? Collections.emptyList() : new ArrayList<>(normalized);
|
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() {
|
public static void reload() {
|
||||||
synchronized (CACHE_LOCK) {
|
synchronized (CACHE_LOCK) {
|
||||||
|
|
@ -215,6 +238,9 @@ public final class ConfigParsingUtils {
|
||||||
cachedMultiplierEntries = null;
|
cachedMultiplierEntries = null;
|
||||||
cachedBlacklistSourceSnapshot = null;
|
cachedBlacklistSourceSnapshot = null;
|
||||||
cachedMultiplierSourceSnapshot = null;
|
cachedMultiplierSourceSnapshot = null;
|
||||||
|
blacklistResultCache.clear();
|
||||||
|
multiplierResultCache.clear();
|
||||||
|
callCounter.set(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user