From d316c5f0393bfd148349c72277c5e3fa5f8b40e0 Mon Sep 17 00:00:00 2001 From: C-H716 <1536152356@qq.com> Date: Tue, 16 Sep 2025 22:02:13 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E5=9B=9E=E9=80=80=E6=97=A0?= =?UTF-8?q?=E9=99=90=E5=AD=98=E5=82=A8=E5=85=83=E4=BB=B6=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../InfinityBigIntegerCellInventory.java | 49 +++++-------------- .../util/storage/InfinityDataStorage.java | 32 ++---------- .../util/storage/InfinityStorageManager.java | 36 +++----------- 3 files changed, 24 insertions(+), 93 deletions(-) diff --git a/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellInventory.java b/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellInventory.java index 7e2216f..19273c4 100644 --- a/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellInventory.java +++ b/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellInventory.java @@ -26,7 +26,6 @@ import java.math.RoundingMode; import java.text.DecimalFormat; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; /** * InfinityBigIntegerCellInventory @@ -92,9 +91,9 @@ public class InfinityBigIntegerCellInventory implements StorageCell { return null; } - // 获取全局存储实例(尽量安全地获取任意已注册的世界实例) + // 获取全局存储实例 private static InfinityStorageManager getStorageInstance() { - return InfinityStorageManager.getAnyInstance(); + return InfinityStorageManager.INSTANCE; } // 服务器 tick 回调:合并并执行待持久化项 @@ -134,12 +133,10 @@ public class InfinityBigIntegerCellInventory implements StorageCell { private InfinityDataStorage getCellStorage() { if (this.getUUID() == null) { // 如果没有UUID,返回空存储 - return InfinityDataStorage.empty(); + return InfinityDataStorage.EMPTY; } else { - // 否则获取或创建对应UUID的存储,若管理器不可用则返回空存储以避免 NPE - InfinityStorageManager mgr = getStorageInstance(); - if (mgr == null) return InfinityDataStorage.empty(); - return mgr.getOrCreateCell(getUUID()); + // 否则获取或创建对应UUID的存储 + return getStorageInstance().getOrCreateCell(getUUID()); } } @@ -190,11 +187,8 @@ public class InfinityBigIntegerCellInventory implements StorageCell { private void loadCellStoredMap() { boolean corruptedTag = false; // 标记数据是否损坏 if (!stack.hasTag()) return; - // 在加载前重置缓存,避免重复累计 - totalStored = BigInteger.ZERO; - InfinityDataStorage storage = this.getCellStorage(); - ListTag keys = storage.getKeys(); - ListTag amounts = storage.getAmounts(); + ListTag keys = this.getCellStorage().keys; + ListTag amounts = this.getCellStorage().amounts; int len = Math.min(keys.size(), amounts.size()); for (int i = 0; i < len; i++) { AEKey key = AEKey.fromTagGeneric(keys.getCompound(i)); @@ -229,8 +223,6 @@ public class InfinityBigIntegerCellInventory implements StorageCell { } // 标记数据需要保存,并通知容器或直接持久化 - private final AtomicBoolean queued = new AtomicBoolean(false); - private void saveChanges() { // 标记为未持久化,交由容器或延迟任务合并写入以减少 I/O isPersisted = false; @@ -239,7 +231,7 @@ public class InfinityBigIntegerCellInventory implements StorageCell { container.saveChanges(); } else { // 如果没有容器,入队等待服务器 tick 在主线程统一持久化,避免频繁 I/O - if (queued.compareAndSet(false, true)) { + if (!PENDING_PERSIST.contains(this)) { PENDING_PERSIST.offer(this); } } @@ -266,21 +258,13 @@ public class InfinityBigIntegerCellInventory implements StorageCell { if (map.isEmpty()) { // 如果存储为空,移除UUID和全局存储中的数据 if (this.hasUUID()) { - InfinityStorageManager mgr = getStorageInstance(); - if (mgr != null) mgr.removeCell(getUUID()); + getStorageInstance().removeCell(getUUID()); if (stack.getTag() != null) { stack.getTag().remove("uuid"); // 移除缓存的 total 字段 stack.getTag().remove("total"); } - // 清理 queued 标志并标记已持久化 - queued.set(false); - isPersisted = true; - return; } - // 无 UUID 且为空,不需要做额外操作,但确保已标记为已持久化 - queued.set(false); - isPersisted = true; return; } // 构建要保存的Key和数量列表(混合表示:long 或 string) @@ -300,16 +284,11 @@ public class InfinityBigIntegerCellInventory implements StorageCell { } } // 如果没有Key,更新为空存储,否则保存数据 - InfinityStorageManager mgr = getStorageInstance(); - if (mgr == null) { - // 无可用存储管理器,跳过持久化(保留内存状态) + if (keys.isEmpty()) { + getStorageInstance().updateCell(this.getUUID(), new InfinityDataStorage()); } else { - if (keys.isEmpty()) { - mgr.updateCell(this.getUUID(), new InfinityDataStorage()); - } else { - // amounts 现在为 CompoundTag 列表 - mgr.modifyCell(this.getUUID(), keys, amountTags); - } + // amounts 现在为 CompoundTag 列表 + getStorageInstance().modifyCell(this.getUUID(), keys, amountTags); } // 将缓存的 totalStored 同步到 ItemStack 的 NBT,优先使用 long if (stack.getOrCreateTag() != null) { @@ -320,8 +299,6 @@ public class InfinityBigIntegerCellInventory implements StorageCell { } } isPersisted = true; - // 持久化完成后,清除 queued 标志 - queued.set(false); } // 插入物品到存储单元 diff --git a/src/main/java/com/extendedae_plus/util/storage/InfinityDataStorage.java b/src/main/java/com/extendedae_plus/util/storage/InfinityDataStorage.java index 0a44d87..4ef9036 100644 --- a/src/main/java/com/extendedae_plus/util/storage/InfinityDataStorage.java +++ b/src/main/java/com/extendedae_plus/util/storage/InfinityDataStorage.java @@ -18,17 +18,17 @@ import net.minecraft.nbt.Tag; */ public class InfinityDataStorage { - // 不再暴露可变的共享实例,避免多个调用方修改同一 ListTag 导致交叉污染 - private static final InfinityDataStorage TRUE_EMPTY = new InfinityDataStorage(new ListTag(), new ListTag()); + /** 空实例(表示没有数据) */ + public static final InfinityDataStorage EMPTY = new InfinityDataStorage(); /** 序列化的键列表(NBT ListTag,元素为 CompoundTag) */ - private ListTag keys; + public ListTag keys; /** * 与 keys 对应的数量列表(NBT ListTag,元素为 CompoundTag): * - 若数量能放入 long,则 CompoundTag 包含键 "l"(long) * - 否则包含键 "s"(String) 存放 BigInteger 的字符串形式 */ - private ListTag amounts; + public ListTag amounts; public InfinityDataStorage() { this(new ListTag(), new ListTag()); @@ -39,14 +39,6 @@ public class InfinityDataStorage { this.amounts = amounts; } - /** - * 返回一个空的不可共享实例(调用方若需要可变副本请自行复制) - */ - public static InfinityDataStorage empty() { - // 返回一个新的实例以避免共享可变对象被篡改 - return new InfinityDataStorage(new ListTag(), new ListTag()); - } - /** * 将当前数据封装为 CompoundTag 以写入存档 */ @@ -66,20 +58,4 @@ public class InfinityDataStorage { ListTag stackAmounts = nbt.getList("amounts", Tag.TAG_COMPOUND); return new InfinityDataStorage(stackKeys, stackAmounts); } - - public ListTag getKeys() { - return keys; - } - - public ListTag getAmounts() { - return amounts; - } - - public void setKeys(ListTag keys) { - this.keys = keys; - } - - public void setAmounts(ListTag amounts) { - this.amounts = amounts; - } } diff --git a/src/main/java/com/extendedae_plus/util/storage/InfinityStorageManager.java b/src/main/java/com/extendedae_plus/util/storage/InfinityStorageManager.java index 1b36fbd..e24a5ab 100644 --- a/src/main/java/com/extendedae_plus/util/storage/InfinityStorageManager.java +++ b/src/main/java/com/extendedae_plus/util/storage/InfinityStorageManager.java @@ -2,16 +2,13 @@ package com.extendedae_plus.util.storage; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; -import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.Level; import net.minecraft.world.level.saveddata.SavedData; import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; /** * InfinityStorageManager @@ -29,9 +26,9 @@ public class InfinityStorageManager extends SavedData { */ public static final String FILE_NAME = "eap_infinity_biginteger_cells"; /** - * Per-world instances to avoid cross-world leakage. Keyed by world ResourceKey. + * 全局单例实例(在世界加载时由 InfiniteBigIntegerStorageCell.onLevelLoad 填充) */ - private static final Map, InfinityStorageManager> INSTANCES = new ConcurrentHashMap<>(); + public static InfinityStorageManager INSTANCE = null; /** * UUID -> 数据 的内存映射 */ @@ -57,29 +54,10 @@ public class InfinityStorageManager extends SavedData { * 根据给定的 ServerLevel 获取或创建该世界对应的 SavedData 实例并缓存到 INSTANCE */ public static InfinityStorageManager getForLevel(ServerLevel level) { - if (level == null) return null; - ResourceKey key = level.dimension(); - InfinityStorageManager mgr = INSTANCES.get(key); - if (mgr == null) { - mgr = level.getDataStorage().computeIfAbsent(InfinityStorageManager::new, InfinityStorageManager::new, FILE_NAME); - INSTANCES.put(key, mgr); + if (INSTANCE == null && level != null) { + INSTANCE = level.getDataStorage().computeIfAbsent(InfinityStorageManager::new, InfinityStorageManager::new, FILE_NAME); } - return mgr; - } - - /** - * 返回任何现有实例,作为无法访问 ServerLevel 的代码路径的安全回退。 - */ - public static InfinityStorageManager getAnyInstance() { - return INSTANCES.values().stream().findFirst().orElse(null); - } - - /** - * 删除世界的实例(在世界卸载时调用) - */ - public static void removeForLevel(ServerLevel level) { - if (level == null) return; - INSTANCES.remove(level.dimension()); + return INSTANCE; } @Override @@ -120,8 +98,8 @@ public class InfinityStorageManager extends SavedData { public void modifyCell(UUID cellID, ListTag stackKeys, ListTag stackAmounts) { InfinityDataStorage cellToModify = getOrCreateCell(cellID); if (stackKeys != null && stackAmounts != null) { - cellToModify.setKeys(stackKeys); - cellToModify.setAmounts(stackAmounts); + cellToModify.keys = stackKeys; + cellToModify.amounts = stackAmounts; } updateCell(cellID, cellToModify); }