fix:回退无限存储元件修复
This commit is contained in:
parent
3039add611
commit
d316c5f039
|
|
@ -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);
|
||||
}
|
||||
|
||||
// 插入物品到存储单元
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Level>.
|
||||
* 全局单例实例(在世界加载时由 InfiniteBigIntegerStorageCell.onLevelLoad 填充)
|
||||
*/
|
||||
private static final Map<ResourceKey<Level>, 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<Level> 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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user