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