diff --git a/src/main/java/com/extendedae_plus/api/storage/InfinityBigIntegerCellInventory.java b/src/main/java/com/extendedae_plus/api/storage/InfinityBigIntegerCellInventory.java index 74d001c..ec1d790 100644 --- a/src/main/java/com/extendedae_plus/api/storage/InfinityBigIntegerCellInventory.java +++ b/src/main/java/com/extendedae_plus/api/storage/InfinityBigIntegerCellInventory.java @@ -11,7 +11,6 @@ import appeng.api.storage.cells.CellState; import appeng.api.storage.cells.ISaveProvider; import appeng.api.storage.cells.StorageCell; import appeng.api.upgrades.IUpgradeInventory; -import appeng.core.AELog; import appeng.core.definitions.AEItems; import appeng.util.ConfigInventory; import appeng.util.prioritylist.IPartitionList; @@ -21,9 +20,8 @@ import com.extendedae_plus.util.storage.InfinityConstants; import com.extendedae_plus.util.storage.InfinityDataStorage; import com.extendedae_plus.util.storage.InfinityStorageManager; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; @@ -45,28 +43,21 @@ public class InfinityBigIntegerCellInventory implements StorageCell { private final ISaveProvider container; private final IPartitionList partitionList; private final IncludeExclude partitionListMode; - // 存储物品键和数量的映射 - private Object2ObjectMap AEKey2AmountsMap; // 存储的物品种类数量 private int totalAEKeyType; // 存储的物品总数 private BigInteger totalAEKey2Amounts = BI_ZERO; - // 标记是否已持久化到 SavedData + // 仅用于控制 ItemStack 摘要字段是否需要刷新 private boolean isPersisted = true; private static final BigInteger BI_ZERO = BigInteger.ZERO; private static final BigInteger BI_LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE); - public InfinityBigIntegerCellInventory(InfinityBigIntegerCellItem cell, ItemStack stack, ISaveProvider saveProvider) { - // 保存存储单元类型(InfinityBigIntegerCellItem 实例),用于访问磁盘属性 this.cell = cell; - // 保存物品堆栈,表示磁盘本身,包含运行时的 NBT 数据 this.self = stack; - // 保存提供者,用于触发数据保存 this.container = saveProvider; - // 初始化 storedAmounts 为 null,延迟加载物品数据 - this.AEKey2AmountsMap = null; + var builder = IPartitionList.builder(); var upgrades = this.getUpgradesInventory(); var config = this.getConfigInventory(); @@ -78,13 +69,11 @@ public class InfinityBigIntegerCellInventory implements StorageCell { builder.addAll(config.keySet()); this.partitionListMode = hasInverter ? IncludeExclude.BLACKLIST : IncludeExclude.WHITELIST; this.partitionList = builder.build(); - // 初始化磁盘数据 - initData(); + this.initData(); } // 将 BigInteger 格式化为带单位的字符串,保留两位小数 public static String formatBigInteger(BigInteger number) { - // 使用方法局部的 DecimalFormat,避免静态共享的非线程安全问题 java.text.DecimalFormat df = new java.text.DecimalFormat("#.##"); BigDecimal bd = new BigDecimal(number); BigDecimal thousand = new BigDecimal(1000); @@ -100,237 +89,196 @@ public class InfinityBigIntegerCellInventory implements StorageCell { return df.format(bd.doubleValue()) + units[idx]; } - // 获取磁盘的 InfinityDataStorage 数据 - private InfinityDataStorage getCellStorage() { - // 如果磁盘有 UUID,返回对应的 InfinityDataStorage - if (getUUID() != null) { - return getStorageManagerInstance().getOrCreateCell(getUUID()); - } else { - // 否则返回空的 InfinityDataStorage - return InfinityDataStorage.EMPTY; - } - } - - // 初始化磁盘数据 - private void initData() { - // 如果磁盘有 UUID,加载存储的物品数据 - if (hasUUID()) { - InfinityDataStorage storage = getCellStorage(); - this.totalAEKeyType = storage.amounts.size(); - this.totalAEKey2Amounts = storage.itemCount.equals(BI_ZERO) ? - BI_ZERO : - storage.itemCount; - - } else { - // 否则初始化为空 - this.totalAEKeyType = 0; - this.totalAEKey2Amounts = BI_ZERO; - // 加载物品数据 - getCellStoredMap(); - } - } - - // 获取存储单元的状态(空、部分填充) - @Override - public CellState getStatus() { - // 如果没有存储任何物品,返回空状态 - if (this.getTotalAEKey2Amounts().equals(BI_ZERO)) { - return CellState.EMPTY; - } - // 否则返回满状态 - return CellState.NOT_EMPTY; - } - - // 获取存储单元的待机能耗 - @Override - public double getIdleDrain() { - return 512; - } - - // 持久化存储单元数据到全局存储 - @Override - public void persist() { - if (this.isPersisted) - return; - - if (totalAEKey2Amounts.equals(BI_ZERO)) { - if (hasUUID()) { - getStorageManagerInstance().removeCell(getUUID()); - if (self.hasTag()) { - var tag = self.getTag(); - // remove persisted identifiers and cached summary fields from the ItemStack - tag.remove(InfinityConstants.INFINITY_CELL_UUID); - tag.remove(InfinityConstants.INFINITY_ITEM_TOTAL); - tag.remove(InfinityConstants.INFINITY_ITEM_TYPES); - // backward compat: also remove internal cell item count key if present - tag.remove(InfinityConstants.INFINITY_CELL_ITEM_COUNT); - } - this.isPersisted = true; - initData(); - } - return; - } - - // 创建物品键列表 - ListTag keys = new ListTag(); - // 创建物品数量列表 - ListTag amounts = new ListTag(); - // 初始化物品总数 - BigInteger itemCount = BI_ZERO; - - for (var entry : this.AEKey2AmountsMap.object2ObjectEntrySet()) { - BigInteger amount = entry.getValue(); - // 如果数量大于 0,添加到键和数量列表 - if (amount.compareTo(BI_ZERO) > 0) { - keys.add(entry.getKey().toTagGeneric()); - CompoundTag amountTag = new CompoundTag(); - amountTag.putByteArray("value", amount.toByteArray()); - amounts.add(amountTag); - - itemCount = itemCount.add(amount); - } - } - - if (keys.isEmpty()) { - getStorageManagerInstance().updateCell(getUUID(), new InfinityDataStorage()); - } else { - getStorageManagerInstance().modifyDisk(getUUID(), keys, amounts, itemCount); - } - - // 更新存储的物品种类数量 - this.totalAEKeyType = this.AEKey2AmountsMap.size(); - // 更新存储的物品总数 - this.totalAEKey2Amounts = itemCount; - // 将物品总数与种类数量存入物品堆栈的 NBT(用于快捷查看/tooltip),同时保留旧字段以兼容历史版本 - var tag = self.getOrCreateTag(); - tag.putByteArray(InfinityConstants.INFINITY_ITEM_TOTAL, itemCount.toByteArray()); - tag.putInt(InfinityConstants.INFINITY_ITEM_TYPES, this.totalAEKeyType); - // backward compat storage field (kept for legacy readers) - tag.putByteArray(InfinityConstants.INFINITY_CELL_ITEM_COUNT, itemCount.toByteArray()); - - // 标记数据已持久化 - this.isPersisted = true; - } - - // 获取存储单元的描述(此处返回null,可自定义) @Override public Component getDescription() { return self.getHoverName(); } - // 静态方法,创建存储单元库存 public static InfinityBigIntegerCellInventory createInventory(ItemStack stack, ISaveProvider saveProvider) { - // 检查物品堆栈是否为空 Objects.requireNonNull(stack, "Cannot create cell inventory for null itemstack"); - // 检查物品是否为 IDISKCellItem 类型 if (!(stack.getItem() instanceof InfinityBigIntegerCellItem cell)) { return null; } - // 创建并返回新的 DISKCellInventory 实例 return new InfinityBigIntegerCellInventory(cell, stack, saveProvider); } - // 获取存储的物品总数 + @Override + public CellState getStatus() { + this.refreshCachedStateFromStorage(); + if (this.getTotalAEKey2Amounts().equals(BI_ZERO)) { + return CellState.EMPTY; + } + return CellState.NOT_EMPTY; + } + + @Override + public double getIdleDrain() { + return 512; + } + + @Override + public void persist() { + this.refreshCachedStateFromStorage(); + if (this.isPersisted) { + return; + } + + CompoundTag tag = self.getOrCreateTag(); + if (this.totalAEKey2Amounts.equals(BI_ZERO)) { + tag.remove(InfinityConstants.INFINITY_ITEM_TOTAL); + tag.remove(InfinityConstants.INFINITY_ITEM_TYPES); + // backward compat + tag.remove(InfinityConstants.INFINITY_CELL_ITEM_COUNT); + } else { + byte[] itemCountBytes = this.totalAEKey2Amounts.toByteArray(); + tag.putByteArray(InfinityConstants.INFINITY_ITEM_TOTAL, itemCountBytes); + tag.putInt(InfinityConstants.INFINITY_ITEM_TYPES, this.totalAEKeyType); + tag.putByteArray(InfinityConstants.INFINITY_CELL_ITEM_COUNT, itemCountBytes); + } + + this.isPersisted = true; + } + public BigInteger getTotalAEKey2Amounts() { + this.refreshCachedStateFromStorage(); return this.totalAEKey2Amounts; } - // 获取存储的物品种类数量 public int getTotalAEKeyType() { + this.refreshCachedStateFromStorage(); return this.totalAEKeyType; } - // 判断物品堆栈是否有UUID public boolean hasUUID() { return self.hasTag() && self.getOrCreateTag().contains(InfinityConstants.INFINITY_CELL_UUID); } - // 获取物品堆栈的UUID public UUID getUUID() { if (this.hasUUID()) { return self.getOrCreateTag().getUUID(InfinityConstants.INFINITY_CELL_UUID); + } + return null; + } + + private void refreshCachedStateFromStorage() { + var cellStorage = this.getExistingCellStorage(); + if (cellStorage != null) { + this.totalAEKeyType = cellStorage.amounts.size(); + this.totalAEKey2Amounts = cellStorage.itemCount == null ? BI_ZERO : cellStorage.itemCount; } else { - return null; + this.totalAEKeyType = 0; + this.totalAEKey2Amounts = BI_ZERO; } } - // 获取或初始化存储映射 + private void initData() { + this.refreshCachedStateFromStorage(); + } + private Object2ObjectMap getCellStoredMap() { - if (AEKey2AmountsMap == null) { - AEKey2AmountsMap = new Object2ObjectOpenHashMap<>(512, 0.6f); - this.loadCellStoredMap(); + var cellStorage = this.getExistingCellStorage(); + if (cellStorage == null) { + return Object2ObjectMaps.emptyMap(); } - return AEKey2AmountsMap; + return cellStorage.amounts; } - // 获取所有可用的物品堆栈及其数量 @Override public void getAvailableStacks(KeyCounter out) { - var map = getCellStoredMap(); - if (map == null || map.isEmpty()) { - return; - } - - for (var entry : map.object2ObjectEntrySet()) { + for (var entry : this.getCellStoredMap().object2ObjectEntrySet()) { AEKey key = entry.getKey(); BigInteger amount = entry.getValue(); - // 如果当前要添加的数量本身就超过 Long.MAX_VALUE,直接设为 MAX if (amount.compareTo(BI_LONG_MAX) > 0) { out.set(key, Long.MAX_VALUE); continue; } - long addAmount = amount.longValue(); long existing = out.get(key); - - // 如果已有值已是 MAX,直接跳过 if (existing == Long.MAX_VALUE) { continue; } - // 计算总和,防止溢出 + long addAmount = amount.longValue(); long sum = existing + addAmount; - if (sum < 0 || sum < existing) { // 溢出检测 + if (sum < 0 || sum < existing) { out.set(key, Long.MAX_VALUE); - } else { - out.add(key, addAmount); // 安全添加 + } else if (addAmount != 0) { + out.add(key, addAmount); } } } - // 从存储中加载物品映射 - private void loadCellStoredMap() { - boolean dataCorruption = false; - if (!self.hasTag()) return; - - var keys = getCellStorage().keys; - var amounts = getCellStorage().amounts; - // 数据损坏 - if (keys.size() != amounts.size()) { - AELog.warn("Loading storage cell with mismatched amounts/tags: %d != %d", amounts.size(), keys.size()); - } - // 遍历数量和键,加载到 AEKey2AmountsMap - for (int i = 0; i < amounts.size(); i++) { - AEKey key = AEKey.fromTagGeneric(keys.getCompound(i)); - BigInteger amount = new BigInteger(amounts.getCompound(i).getByteArray("value")); - // 检查数据是否损坏 - if (amount.compareTo(BI_ZERO) <= 0 || key == null) { - dataCorruption = true; - } else { - AEKey2AmountsMap.put(key, amount); - } - } - if (dataCorruption) { - this.saveChanges(); - } - } - - // 获取全局存储实例 - private static InfinityStorageManager getStorageManagerInstance() { + private InfinityStorageManager getStorageManagerInstance() { return ExtendedAEPlus.STORAGE_INSTANCE; } + private InfinityDataStorage getExistingCellStorage() { + UUID uuid = this.getUUID(); + InfinityStorageManager storageManager = this.getStorageManagerInstance(); + if (uuid == null || storageManager == null || !storageManager.hasUUID(uuid)) { + return null; + } + return storageManager.getOrCreateCell(uuid); + } + + private InfinityDataStorage getWritableCellStorage() { + InfinityStorageManager storageManager = this.getStorageManagerInstance(); + if (storageManager == null) { + return null; + } + + UUID uuid = this.getUUID(); + if (uuid == null) { + uuid = this.assignNewUUID(); + } + return storageManager.getOrCreateCell(uuid); + } + + private UUID assignNewUUID() { + CompoundTag tag = self.getOrCreateTag(); + UUID newUUID = UUID.randomUUID(); + tag.putUUID(InfinityConstants.INFINITY_CELL_UUID, newUUID); + return newUUID; + } + + private void clearCellData() { + UUID uuid = this.getUUID(); + InfinityStorageManager storageManager = this.getStorageManagerInstance(); + if (uuid != null && storageManager != null && storageManager.hasUUID(uuid)) { + storageManager.removeCell(uuid); + } + + this.totalAEKeyType = 0; + this.totalAEKey2Amounts = BI_ZERO; + + CompoundTag tag = self.getOrCreateTag(); + tag.remove(InfinityConstants.INFINITY_CELL_UUID); + tag.remove(InfinityConstants.INFINITY_ITEM_TOTAL); + tag.remove(InfinityConstants.INFINITY_ITEM_TYPES); + // backward compat + tag.remove(InfinityConstants.INFINITY_CELL_ITEM_COUNT); + this.isPersisted = true; + + if (this.container != null) { + this.container.saveChanges(); + } + } + + private void saveChanges() { + this.isPersisted = false; + InfinityStorageManager storageManager = this.getStorageManagerInstance(); + if (storageManager != null) { + storageManager.setDirty(); + } + + if (this.container != null) { + this.container.saveChanges(); + } else { + this.persist(); + } + } + private ConfigInventory getConfigInventory() { return this.cell.getConfigInventory(this.self); } @@ -343,94 +291,82 @@ public class InfinityBigIntegerCellInventory implements StorageCell { return this.cell.getFuzzyMode(this.self); } - // 标记数据需要保存,并通知容器或直接持久化 - private void saveChanges() { - // 更新存储的物品种类数量 - this.totalAEKeyType = this.AEKey2AmountsMap.size(); - // 重置物品总数 - this.totalAEKey2Amounts = BI_ZERO; - // 计算物品总数 - for (BigInteger AEKey2Amounts : this.AEKey2AmountsMap.values()) { - this.totalAEKey2Amounts = this.totalAEKey2Amounts.add(AEKey2Amounts); - } - // 标记数据未持久化 - this.isPersisted = false; - // 如果有保存提供者,通知保存 - if (this.container != null) { - this.container.saveChanges(); - } else { - // 否则立即持久化 - this.persist(); - } - } - - // 插入物品到存储单元 @Override public long insert(AEKey what, long amount, Actionable mode, IActionSource source) { - // 数量为0或类型不匹配直接返回 - if (amount == 0){ + if (amount == 0) { return 0; } if (!this.partitionList.matchesFilter(what, this.partitionListMode)) { return 0; } - // 不允许存储有物品的无限单元 if (what instanceof AEItemKey itemKey && itemKey.getItem() instanceof InfinityBigIntegerCellItem && - itemKey.hasTag() - ) { + itemKey.hasTag()) { return 0; } - // 如果没有UUID,尝试在服务器端且存储管理器已就绪时生成UUID并初始化存储 - if (!this.hasUUID()) { - self.getOrCreateTag().putUUID(InfinityConstants.INFINITY_CELL_UUID, UUID.randomUUID()); - getStorageManagerInstance().getOrCreateCell(getUUID()); - loadCellStoredMap(); + var cellStorage = this.getWritableCellStorage(); + if (cellStorage == null) { + return 0; } - // 获取当前物品数量 - BigInteger currentAmount = this.getCellStoredMap().getOrDefault(what, BI_ZERO); + BigInteger currentAmount = cellStorage.amounts.getOrDefault(what, BI_ZERO); if (mode == Actionable.MODULATE) { - // 实际插入,更新数量并保存 - BigInteger newAmount = currentAmount.add(BigInteger.valueOf(amount)); - getCellStoredMap().put(what, newAmount); + BigInteger delta = BigInteger.valueOf(amount); + if (currentAmount.equals(BI_ZERO)) { + this.totalAEKeyType++; + } + + BigInteger newAmount = currentAmount.add(delta); + cellStorage.amounts.put(what, newAmount); + this.totalAEKey2Amounts = this.totalAEKey2Amounts.add(delta); + cellStorage.itemCount = this.totalAEKey2Amounts; this.saveChanges(); } return amount; } - // 从存储单元提取物品 @Override public long extract(AEKey what, long amount, Actionable mode, IActionSource source) { - BigInteger currentAmount = this.getCellStoredMap().getOrDefault(what, BI_ZERO); - // 如果有物品可提取 - if (currentAmount.compareTo(BI_ZERO) > 0) { - - BigInteger requested = BigInteger.valueOf(amount); - - // 如果提取数量大于等于当前数量 - if (requested.compareTo(currentAmount) >= 0) { - if (mode == Actionable.MODULATE) { - getCellStoredMap().remove(what); - this.saveChanges(); - } - return currentAmount.compareTo(BI_LONG_MAX) > 0 ? Long.MAX_VALUE : currentAmount.longValue(); - } else { - // 提取部分数量 - if (mode == Actionable.MODULATE) { - getCellStoredMap().put(what, currentAmount.subtract(requested)); - this.saveChanges(); - } - return requested.longValue(); - } + var cellStorage = this.getExistingCellStorage(); + if (cellStorage == null) { + return 0; } - return 0; + + BigInteger currentAmount = cellStorage.amounts.getOrDefault(what, BI_ZERO); + if (currentAmount.compareTo(BI_ZERO) <= 0) { + return 0; + } + + BigInteger requested = BigInteger.valueOf(amount); + if (requested.compareTo(currentAmount) >= 0) { + if (mode == Actionable.MODULATE) { + cellStorage.amounts.remove(what); + this.totalAEKeyType--; + this.totalAEKey2Amounts = this.totalAEKey2Amounts.subtract(currentAmount); + cellStorage.itemCount = this.totalAEKey2Amounts; + + if (cellStorage.amounts.isEmpty()) { + this.clearCellData(); + } else { + this.saveChanges(); + } + } + return currentAmount.compareTo(BI_LONG_MAX) > 0 ? Long.MAX_VALUE : currentAmount.longValue(); + } + + if (mode == Actionable.MODULATE) { + BigInteger newAmount = currentAmount.subtract(requested); + cellStorage.amounts.put(what, newAmount); + this.totalAEKey2Amounts = this.totalAEKey2Amounts.subtract(requested); + cellStorage.itemCount = this.totalAEKey2Amounts; + this.saveChanges(); + } + return requested.longValue(); } - // 获取存储单元内所有物品的总数量(格式化字符串) public String getTotalStorage() { - // 使用缓存的 totalStored,避免每次全表扫描 + this.refreshCachedStateFromStorage(); return formatBigInteger(totalAEKey2Amounts); } } 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 6462128..02ed76a 100644 --- a/src/main/java/com/extendedae_plus/util/storage/InfinityDataStorage.java +++ b/src/main/java/com/extendedae_plus/util/storage/InfinityDataStorage.java @@ -1,5 +1,9 @@ package com.extendedae_plus.util.storage; +import appeng.api.stacks.AEKey; +import appeng.core.AELog; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -13,36 +17,66 @@ public class InfinityDataStorage { // 定义一个静态常量 EMPTY,表示一个空的 DataStorage 实例,用于默认或占位场景 public static final InfinityDataStorage EMPTY = new InfinityDataStorage(); - public ListTag keys; - public ListTag amounts; + // 运行时权威数据结构,避免在高频路径上反复构造和拆解 NBT + public final Object2ObjectMap amounts; // 存储磁盘中物品的总数,使用 BigInteger 支持大容量 public BigInteger itemCount; public InfinityDataStorage() { - this(new ListTag(), new ListTag(), BigInteger.ZERO); + this(new Object2ObjectOpenHashMap<>(), BigInteger.ZERO); } - private InfinityDataStorage(ListTag keys, ListTag amounts, BigInteger itemCount) { - this.keys = keys; + private InfinityDataStorage(Object2ObjectMap amounts, BigInteger itemCount) { this.amounts = amounts; this.itemCount = itemCount; } - // 将 DataStorage 数据序列化为 NBT 格式 + // 将 DataStorage 数据序列化为 NBT 格式,保持旧版字段结构兼容 public CompoundTag serializeNBT() { CompoundTag nbt = new CompoundTag(); + ListTag keys = new ListTag(); + ListTag amountsTag = new ListTag(); + + for (var entry : this.amounts.object2ObjectEntrySet()) { + BigInteger amount = entry.getValue(); + if (amount == null || amount.compareTo(BigInteger.ZERO) <= 0) { + continue; + } + + keys.add(entry.getKey().toTagGeneric()); + CompoundTag amountTag = new CompoundTag(); + amountTag.putByteArray("value", amount.toByteArray()); + amountsTag.add(amountTag); + } + nbt.put(InfinityConstants.INFINITY_CELL_KEYS, keys); - nbt.put(InfinityConstants.INFINITY_CELL_AMOUNTS, amounts); - nbt.putByteArray(InfinityConstants.INFINITY_CELL_ITEM_COUNT, itemCount.toByteArray()); + nbt.put(InfinityConstants.INFINITY_CELL_AMOUNTS, amountsTag); + nbt.putByteArray(InfinityConstants.INFINITY_CELL_ITEM_COUNT, this.itemCount.toByteArray()); return nbt; } - // 从 NBT 数据反序列化创建 DataStorage 实例 + // 从 NBT 数据反序列化创建 DataStorage 实例,兼容旧版列表式存档结构 public static InfinityDataStorage loadFromNBT(CompoundTag nbt) { ListTag keys = nbt.getList(InfinityConstants.INFINITY_CELL_KEYS, ListTag.TAG_COMPOUND); ListTag amounts = nbt.getList(InfinityConstants.INFINITY_CELL_AMOUNTS, ListTag.TAG_COMPOUND); - BigInteger itemCount = new BigInteger(nbt.getByteArray(InfinityConstants.INFINITY_CELL_ITEM_COUNT)); - // 使用加载的数据创建新的 DataStorage 实例 - return new InfinityDataStorage(keys, amounts, itemCount); + if (keys.size() != amounts.size()) { + AELog.warn("Loading storage cell with mismatched amounts/tags: %d != %d", amounts.size(), keys.size()); + } + + Object2ObjectMap storedAmounts = new Object2ObjectOpenHashMap<>(); + BigInteger computedItemCount = BigInteger.ZERO; + int limit = Math.min(keys.size(), amounts.size()); + for (int i = 0; i < limit; i++) { + AEKey key = AEKey.fromTagGeneric(keys.getCompound(i)); + BigInteger amount = new BigInteger(amounts.getCompound(i).getByteArray("value")); + if (key == null || amount.compareTo(BigInteger.ZERO) <= 0) { + continue; + } + + storedAmounts.put(key, amount); + computedItemCount = computedItemCount.add(amount); + } + + return new InfinityDataStorage(storedAmounts, computedItemCount); } } 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 f27f2a6..ef0615d 100644 --- a/src/main/java/com/extendedae_plus/util/storage/InfinityStorageManager.java +++ b/src/main/java/com/extendedae_plus/util/storage/InfinityStorageManager.java @@ -7,7 +7,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.saveddata.SavedData; import org.jetbrains.annotations.NotNull; -import java.math.BigInteger; import java.util.*; /** @@ -19,25 +18,18 @@ public class InfinityStorageManager extends SavedData { // 存储所有磁盘的Map,键为UUID,值为DataStorage对象 private final Map cells; - - // 构造方法,初始化磁盘Map public InfinityStorageManager() { cells = new HashMap<>(); - // 标记数据为“脏”,确保新创建的实例在下次保存时写入磁盘 this.setDirty(); } - // 私有构造方法,用于从已有Map创建StorageManager private InfinityStorageManager(Map cells) { - // 确保使用已加载的数据 this.cells = cells; - // 标记数据为“脏”,确保新创建的实例在下次保存时写入磁盘 this.setDirty(); } @Override public @NotNull CompoundTag save(@NotNull CompoundTag nbt) { - // 将内存中的所有 cell 序列化为一个 ListTag ListTag cellList = new ListTag(); for (Map.Entry entry : cells.entrySet()) { CompoundTag cell = new CompoundTag(); @@ -46,87 +38,54 @@ public class InfinityStorageManager extends SavedData { cellList.add(cell); } nbt.put(InfinityConstants.INFINITY_CELL_LIST, cellList); - // 写入当前格式版本号,便于未来迁移与兼容判断 nbt.putInt(InfinityConstants.FORMAT_VERSION_FIELD, InfinityConstants.FORMAT_VERSION); return nbt; } - // 静态方法,从 NBT 数据反序列化创建 StorageManager 实例 public static InfinityStorageManager readNbt(CompoundTag nbt) { - // 读取格式版本,缺省视为 1(兼容旧档) int version = nbt.contains(InfinityConstants.FORMAT_VERSION_FIELD) ? nbt.getInt(InfinityConstants.FORMAT_VERSION_FIELD) : 1; Map cells = new HashMap<>(); - // 从 NBT 中获取磁盘数据列表,指定类型为 CompoundTag(TAG_COMPOUND) ListTag cellList = nbt.getList(InfinityConstants.INFINITY_CELL_LIST, CompoundTag.TAG_COMPOUND); - // 遍历 cellList 中的每个 CompoundTag for (int i = 0; i < cellList.size(); i++) { - // 获取当前索引的 CompoundTag,表示单个磁盘的数据 CompoundTag cell = cellList.getCompound(i); - // 从 CompoundTag 中读取 UUID 和 DataStorage 数据,并存入 cells 映射 - cells.put(cell.getUUID(InfinityConstants.INFINITY_CELL_UUID), InfinityDataStorage.loadFromNBT(cell.getCompound(InfinityConstants.INFINITY_CELL_DATA))); + cells.put( + cell.getUUID(InfinityConstants.INFINITY_CELL_UUID), + InfinityDataStorage.loadFromNBT(cell.getCompound(InfinityConstants.INFINITY_CELL_DATA)) + ); } - // 使用加载的 cells 数据创建新的 StorageManager 实例 return new InfinityStorageManager(cells); } - // 返回当前已加载的所有 UUID 的不可变视图,用于命令或调试用途 public Set getAllLoadedUUIDs() { return Collections.unmodifiableSet(cells.keySet()); } - - // 更新或添加某个 UUID 对应的数据并标记为脏(需要保存) public void updateCell(UUID uuid, InfinityDataStorage infinityDataStorage) { cells.put(uuid, infinityDataStorage); - // 标记数据为“脏”,确保修改后的数据会在下次保存时写入磁盘 setDirty(); } - // 删除某个 UUID 的持久化记录并标记为脏 public void removeCell(UUID uuid) { cells.remove(uuid); - // 标记数据为“脏”,确保移除操作会在下次保存时反映到磁盘 setDirty(); } - // 检查指定 UUID 是否存在于 disks 映射中 public boolean hasUUID(UUID uuid) { - // 返回 cells 映射是否包含指定 UUID return cells.containsKey(uuid); } - // 获取或创建某个 UUID 对应的数据容器 public InfinityDataStorage getOrCreateCell(UUID uuid) { - // 检查 cells 映射中是否不存在指定 UUID if (!cells.containsKey(uuid)) { updateCell(uuid, new InfinityDataStorage()); } - // 返回指定 UUID 对应的 DataStorage 对象 return cells.get(uuid); } - // 修改指定 UUID 的磁盘数据,包括堆栈键、数量和总项目数 - public void modifyDisk(UUID uuid, ListTag keys, ListTag amounts, BigInteger itemCount) { - // 获取或创建指定 UUID 的 DataStorage 对象 - InfinityDataStorage cellToModify = getOrCreateCell(uuid); - if (keys != null && amounts != null) { - cellToModify.keys = keys; - cellToModify.amounts = amounts; - } - // 更新 DataStorage 的 itemCount 字段 - cellToModify.itemCount = itemCount; - // 将修改后的 DataStorage 对象更新到 cells 映射 - updateCell(uuid, cellToModify); - } - - // 静态方法,获取 StorageManager 的单例实例 public static InfinityStorageManager getInstance(MinecraftServer server) { ServerLevel world = server.getLevel(ServerLevel.OVERWORLD); - // 使用 DataStorage 的 computeIfAbsent 方法加载或创建 StorageManager 实例 - // 如果数据存在,则调用 readNbt 加载;否则调用默认构造器创建新实例 return world.getDataStorage().computeIfAbsent( InfinityStorageManager::readNbt, InfinityStorageManager::new,