diff --git a/src/main/java/com/extendedae_plus/ExtendedAEPlus.java b/src/main/java/com/extendedae_plus/ExtendedAEPlus.java index 5a6277c..6670527 100644 --- a/src/main/java/com/extendedae_plus/ExtendedAEPlus.java +++ b/src/main/java/com/extendedae_plus/ExtendedAEPlus.java @@ -1,18 +1,13 @@ package com.extendedae_plus; -import appeng.api.storage.StorageCells; import appeng.block.AEBaseEntityBlock; import appeng.blockentity.crafting.CraftingBlockEntity; -import com.extendedae_plus.ae.api.storage.InfinityBigIntegerCellHandler; -import com.extendedae_plus.ae.api.storage.InfinityBigIntegerCellInventory; import com.extendedae_plus.config.ModConfigs; import com.extendedae_plus.init.*; import com.extendedae_plus.network.ModNetwork; -import com.extendedae_plus.util.storage.InfinityStorageManager; import com.mojang.logging.LogUtils; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.Blocks; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; @@ -21,7 +16,6 @@ import net.neoforged.fml.common.Mod; import net.neoforged.fml.config.ModConfig; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.level.LevelEvent; import net.neoforged.neoforge.event.server.ServerStartingEvent; import org.slf4j.Logger; @@ -56,10 +50,6 @@ public class ExtendedAEPlus { // Note that this is necessary if and only if we want *this* class (ExtendedAEPlus) to respond directly to events. // Do not add this line if there are no @SubscribeEvent-annotated functions in this class, like onServerStarting() below. NeoForge.EVENT_BUS.register(this); - NeoForge.EVENT_BUS.addListener(ExtendedAEPlus::onLevelLoad); - - NeoForge.EVENT_BUS.addListener(InfinityBigIntegerCellInventory::onServerTick); - NeoForge.EVENT_BUS.addListener(InfinityBigIntegerCellInventory::onServerStopping); // 注册配置:接入自定义的 ModConfigs modContainer.registerConfig(ModConfig.Type.COMMON, ModConfigs.COMMON_SPEC); @@ -75,7 +65,7 @@ public class ExtendedAEPlus { LOGGER.info("HELLO FROM COMMON SETUP"); // 示例日志,避免引用不存在的模板 Config 字段 LOGGER.info("DIRT BLOCK >> {}", BuiltInRegistries.BLOCK.getKey(Blocks.DIRT)); - StorageCells.addCellHandler(InfinityBigIntegerCellHandler.INSTANCE); + // 绑定 AE2 的 CraftingBlockEntity 到本模组的自定义加速器方块,避免 AEBaseEntityBlock.blockEntityType 为空 event.enqueueWork(() -> { try { @@ -120,13 +110,5 @@ public class ExtendedAEPlus { // Do something when the server starts LOGGER.info("HELLO from server starting"); } - - - // 在世界加载时注册/加载 SavedData - private static void onLevelLoad(LevelEvent.Load event) { - if (event.getLevel() instanceof ServerLevel serverLevel) { - InfinityStorageManager.getForLevel(serverLevel); - } - } } diff --git a/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellHandler.java b/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellHandler.java deleted file mode 100644 index bc7c29c..0000000 --- a/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.extendedae_plus.ae.api.storage; - -import appeng.api.storage.cells.ICellHandler; -import appeng.api.storage.cells.ISaveProvider; -import com.extendedae_plus.ae.items.InfinityBigIntegerCellItem; -import net.minecraft.world.item.ItemStack; - -/** - * InfinityBigIntegerCellHandler - * - * 该类实现 AE2 的 ICellHandler,用于: - * - 判定某个 ItemStack 是否为本 mod 的 Infinity 存储单元 - * - 在 AE2 请求访问或创建存储单元时,创建并返回对应的 StorageCell 实例 - */ -public class InfinityBigIntegerCellHandler implements ICellHandler { - - /** Handler 单例,供注册与调用使用 */ - public static final InfinityBigIntegerCellHandler INSTANCE = new InfinityBigIntegerCellHandler(); - - /** - * 判断给定的 ItemStack 是否为 InfinityBigIntegerCell - */ - @Override - public boolean isCell(ItemStack is) { - return is.getItem() instanceof InfinityBigIntegerCellItem; - } - - /** - * 在 AE2 需要访问或创建存储单元时返回对应的 InfinityBigIntegerCellInventory(StorageCell 实现)。 - * 参数 container 为 AE2 提供的保存回调(ISaveProvider),当 cell 需要持久化时会调用它。 - */ - @Override - public InfinityBigIntegerCellInventory getCellInventory(ItemStack is, ISaveProvider container) { - return InfinityBigIntegerCellInventory.createInventory(is, container); - } -} \ No newline at end of file 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 deleted file mode 100644 index b7e3e14..0000000 --- a/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellInventory.java +++ /dev/null @@ -1,435 +0,0 @@ -package com.extendedae_plus.ae.api.storage; - -import appeng.api.config.Actionable; -import appeng.api.networking.security.IActionSource; -import appeng.api.stacks.AEItemKey; -import appeng.api.stacks.AEKey; -import appeng.api.stacks.KeyCounter; -import appeng.api.storage.cells.CellState; -import appeng.api.storage.cells.ISaveProvider; -import appeng.api.storage.cells.StorageCell; -import com.extendedae_plus.ae.items.InfinityBigIntegerCellItem; -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 net.minecraft.core.HolderLookup; -import net.minecraft.core.component.DataComponents; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.component.CustomData; -import net.neoforged.neoforge.event.server.ServerStoppingEvent; -import net.neoforged.neoforge.event.tick.ServerTickEvent; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.RoundingMode; -import java.text.DecimalFormat; -import java.util.UUID; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * InfinityBigIntegerCellInventory - *

- * 本类实现 AE2 的 StorageCell,表示单个 Infinity 存储单元的运行时数据与行为。 - * 主要职责: - * - 在内存中维护条目映射 (AEKey -> BigInteger 数量) - * - 提供插入/提取/列举/持久化等操作的实现 - * - 通过 UUID 将 ItemStack 与世界级的 SavedData 关联以实现持久化 - *

- * 重要字段: - * - stack: 关联的 ItemStack,NB T 中保存 UUID 与缓存信息 - * - container: AE2 提供的保存回调 (ISaveProvider),用于合并与触发持久化 - * - storedMap: 延迟初始化的内存映射,减少未使用时内存占用 - * - totalStored: 缓存的总数量 (BigInteger),避免频繁全表扫描 - * - isPersisted: 标记内存状态是否已同步到持久层 - */ -public class InfinityBigIntegerCellInventory implements StorageCell { - - // 待持久化队列(用于 debounce:在服务器 tick 中合并持久化) - private static final ConcurrentLinkedQueue PENDING_PERSIST = new ConcurrentLinkedQueue<>(); - // 数字格式化对象,保留两位小数(复用以减少对象分配) - private static final DecimalFormat DF = new DecimalFormat("#.##"); - - // 关联的 ItemStack(含可能的 uuid NBT) - private final ItemStack stack; - // AE2 提供的保存提供者,用于在容器中批量保存时触发回调 - private final ISaveProvider container; - // 内存中的键-数量映射(使用 BigInteger 支持超长数量,延迟初始化) - private Object2ObjectMap storedMap = null; - // 标记是否已持久化到 SavedData - private boolean isPersisted = true; - // 缓存的总存储量,避免每次调用进行全表扫描 - private BigInteger totalStored = BigInteger.ZERO; - - /** - * 私有构造器:通过 createInventory 工厂方法调用 - * - * @param stack 关联的物品堆 - * @param saveProvider AE2 的保存回调(可为 null) - */ - private InfinityBigIntegerCellInventory(ItemStack stack, ISaveProvider saveProvider) { - this.stack = stack; - container = saveProvider; - // 不在构造时创建 storedMap,推迟到实际访问或首次写入时初始化 - this.storedMap = null; - } - - // 创建存储单元库存实例的静态方法 - static InfinityBigIntegerCellInventory createInventory(ItemStack stack, ISaveProvider saveProvider) { - if (stack.getItem() instanceof InfinityBigIntegerCellItem) { - return new InfinityBigIntegerCellInventory(stack, saveProvider); - } - return null; - } - - // 获取全局存储实例 - private static InfinityStorageManager getStorageInstance() { - return InfinityStorageManager.INSTANCE; - } - - // 服务器 tick 回调:合并并执行待持久化项 - public static void onServerTick(ServerTickEvent.Post event) { - // NeoForge 提供 Pre/Post 子类以区分阶段,Post 对应原来的 Phase.END - InfinityBigIntegerCellInventory inv; - // 处理本次 tick 中的全部待持久化项 - while ((inv = PENDING_PERSIST.poll()) != null) { - try { - if (!inv.isPersisted) { - inv.persist(); - } - } catch (Throwable ignored) { - // 忽略单项错误,继续处理其余队列 - } - } - } - - // 在服务器停止时被调用,立即强制持久化队列中的所有实例 - public static void onServerStopping(ServerStoppingEvent event) { - InfinityBigIntegerCellInventory inv; - while ((inv = PENDING_PERSIST.poll()) != null) { - try { - if (!inv.isPersisted) { - inv.persist(); - } - } catch (Throwable ignored) { - // 忽略单项错误,继续尝试持久化其它实例 - } - } - // 额外尝试将全局存储管理器标记为脏以确保 SavedData 被写回(在单人模式下可能直接由系统触发) - try { - var stor = getStorageInstance(); - if (stor != null) stor.setDirty(); - } catch (Throwable ignored) { - } - } - - // 将 BigInteger 格式化为带单位的字符串,保留两位小数 - public static String formatBigInteger(BigInteger number) { - // 使用局部 DF(非线程安全),但 Minecraft 通常在主线程运行 - BigDecimal bd = new BigDecimal(number); - BigDecimal thousand = new BigDecimal(1000); - String[] units = new String[]{"", "K", "M", "G", "T", "P", "E", "Z", "Y"}; - int idx = 0; - while (bd.compareTo(thousand) >= 0 && idx < units.length - 1) { - bd = bd.divide(thousand, 2, RoundingMode.HALF_UP); - idx++; - } - if (idx == 0) { - return bd.setScale(0, RoundingMode.DOWN).toPlainString(); - } - return DF.format(bd.doubleValue()) + units[idx]; - } - - // 获取当前存储单元的数据存储对象 - private InfinityDataStorage getCellStorage() { - if (this.getUUID() == null) { - // 如果没有UUID,返回空存储 - return InfinityDataStorage.EMPTY; - } else { - // 否则获取或创建对应UUID的存储 - return getStorageInstance().getOrCreateCell(getUUID()); - } - } - - // 获取存储单元状态(空/非空) - @Override - public CellState getStatus() { - if (this.getCellStoredMap().isEmpty()) { - return CellState.EMPTY; - } - return CellState.NOT_EMPTY; - } - - // 获取存储单元的待机能耗 - @Override - public double getIdleDrain() { - return 512; - } - - // 获取存储单元的描述(此处返回null,可自定义) - @Override - public Component getDescription() { - return null; - } - - // 判断物品堆栈是否有UUID - public boolean hasUUID() { - CustomData customData = stack.get(DataComponents.CUSTOM_DATA); - if (customData == null) return false; - CompoundTag tag = customData.copyTag(); - return tag != null && tag.contains("uuid"); - } - - // 获取物品堆栈的UUID - public UUID getUUID() { - CustomData customData = stack.get(DataComponents.CUSTOM_DATA); - if (customData == null) return null; - CompoundTag tag = customData.copyTag(); - if (tag != null && tag.contains("uuid")) { - return tag.getUUID("uuid"); - } - return null; - } - - // 获取或初始化存储映射 - private Object2ObjectMap getCellStoredMap() { - if (storedMap == null) { - storedMap = new Object2ObjectOpenHashMap<>(); - this.loadCellStoredMap(); - } - return storedMap; - } - - // 从存储中加载物品映射 - private void loadCellStoredMap() { - boolean corruptedTag = false; // 标记数据是否损坏 - if (!this.hasUUID()) return; - - ListTag keys = this.getCellStorage().keys; - ListTag amounts = this.getCellStorage().amounts; - - int len = Math.min(keys.size(), amounts.size()); - - HolderLookup.Provider registries = getStorageInstance().getRegistries(); - - for (int i = 0; i < len; i++) { - AEKey key = AEKey.fromTagGeneric(registries,keys.getCompound(i)); - CompoundTag amtTag = amounts.getCompound(i); - try { - BigInteger amount; - if (amtTag.contains("l")) { - long v = amtTag.getLong("l"); - amount = BigInteger.valueOf(v); - } else if (amtTag.contains("s")) { - amount = new BigInteger(amtTag.getString("s")); - } else { - corruptedTag = true; - continue; - } - if (amount.compareTo(BigInteger.ZERO) <= 0 || key == null) { - corruptedTag = true; - } else { - // storedMap 已在 getCellStoredMap() 中初始化,直接使用字段以避免额外方法开销 - storedMap.put(key, amount); - // 更新缓存的总数 - totalStored = totalStored.add(amount); - } - } catch (NumberFormatException ex) { - corruptedTag = true; - } - } - // 如果有损坏,保存修正后的数据 - if (corruptedTag) { - this.saveChanges(); - } - } - - // 标记数据需要保存,并通知容器或直接持久化 - private void saveChanges() { - // 标记为未持久化,交由容器或延迟任务合并写入以减少 I/O - isPersisted = false; - if (container != null) { - // 当存在容器时,优先让容器统一处理持久化 - container.saveChanges(); - } else { - // 如果没有容器,入队等待服务器 tick 在主线程统一持久化,避免频繁 I/O - if (!PENDING_PERSIST.contains(this)) { - PENDING_PERSIST.offer(this); - } - } - } - - // 获取所有可用的物品堆栈及其数量 - @Override - public void getAvailableStacks(KeyCounter out) { - BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE); - Object2ObjectMap map = getCellStoredMap(); - for (Object2ObjectMap.Entry entry : map.object2ObjectEntrySet()) { - AEKey key = entry.getKey(); - BigInteger value = entry.getValue(); - - // 当前 KeyCounter 中已有的值(long) - long existing = out.get(key); - - // 将 existing 与当前 value 做 BigInteger 累加并饱和到 Long.MAX_VALUE - BigInteger sum = BigInteger.valueOf(existing).add(value); - long toSet = sum.compareTo(maxLong) > 0 ? Long.MAX_VALUE : sum.longValue(); - - // KeyCounter 没有 set(key,long) 的统一接口暴露(只有 add/remove),所以先移除已存在的值再设置。 - // 为避免读取-写入竞争,我们计算出要新增的 delta 并调用 add(key, delta) - if (existing == Long.MAX_VALUE) { - // 已经饱和,无需再添加 - continue; - } - long delta; - if (toSet == Long.MAX_VALUE) { - delta = Long.MAX_VALUE - existing; - } else { - delta = toSet - existing; - } - if (delta != 0) { - out.add(key, delta); - } - } - } - - // 持久化存储单元数据到全局存储 - @Override - public void persist() { - if (this.isPersisted) - return; - Object2ObjectMap map = this.getCellStoredMap(); - if (map.isEmpty()) { - // 如果存储为空,移除UUID和全局存储中的数据 - if (this.hasUUID()) { - getStorageInstance().removeCell(getUUID()); - // 从 CustomData 中移除缓存字段 - try { - CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> { - tag.remove("uuid"); - tag.remove("total"); - }); - } catch (Throwable ignored) { - } - } - return; - } - // 构建要保存的Key和数量列表(混合表示:long 或 string) - ListTag amountTags = new ListTag(); - ListTag keys = new ListTag(); - for (Object2ObjectMap.Entry entry : map.object2ObjectEntrySet()) { - BigInteger amount = entry.getValue(); - if (amount.compareTo(BigInteger.ZERO) > 0) { - keys.add(entry.getKey().toTagGeneric(getStorageInstance().getRegistries())); - CompoundTag amt = new CompoundTag(); - if (amount.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) <= 0) { - amt.putLong("l", amount.longValue()); - } else { - amt.putString("s", amount.toString()); - } - amountTags.add(amt); - } - } - // 如果没有Key,更新为空存储,否则保存数据 - if (keys.isEmpty()) { - getStorageInstance().updateCell(this.getUUID(), new InfinityDataStorage()); - } else { - // amounts 现在为 CompoundTag 列表 - getStorageInstance().modifyCell(this.getUUID(), keys, amountTags); - } - // 将缓存的 totalStored 同步到 ItemStack 的 CustomData(优先使用 long) - try { - CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> { - if (totalStored.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) <= 0) { - tag.putLong("total", totalStored.longValue()); - } else { - tag.putString("total", totalStored.toString()); - } - // 将当前已存储的不同物品种类数缓存到 CustomData(键名: "types"),用于客户端 tooltip 显示 - int typesCount = this.getCellStoredMap().size(); - tag.putInt("types", typesCount); - }); - } catch (Throwable ignored) { - } - isPersisted = true; - } - - // 插入物品到存储单元 - @Override - public long insert(AEKey what, long amount, Actionable mode, IActionSource source) { - // 数量为0或类型不匹配直接返回 - if (amount == 0) - return 0; - // 不允许存储无限单元自身 - if (what instanceof AEItemKey itemKey && itemKey.getItem() instanceof InfinityBigIntegerCellItem) - return 0; - // 如果没有UUID,生成UUID并初始化存储 - if (!this.hasUUID()) { - UUID id = UUID.randomUUID(); - try { - CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putUUID("uuid", id)); - } catch (Throwable ignored) { - } - getStorageInstance().getOrCreateCell(getUUID()); - // 确保 storedMap 初始化并从持久层加载数据 - this.getCellStoredMap(); - } - Object2ObjectMap map = this.getCellStoredMap(); - BigInteger currentAmount = map.getOrDefault(what, BigInteger.ZERO); - if (mode == Actionable.MODULATE) { - // 实际插入,更新数量并保存 - BigInteger newAmount = currentAmount.add(BigInteger.valueOf(amount)); - map.put(what, newAmount); - // 更新 cached total - totalStored = totalStored.add(BigInteger.valueOf(amount)); - this.saveChanges(); - } - return amount; - } - - // 从存储单元提取物品 - @Override - public long extract(AEKey what, long amount, Actionable mode, IActionSource source) { - Object2ObjectMap map = this.getCellStoredMap(); - BigInteger currentAmount = map.getOrDefault(what, BigInteger.ZERO); - if (currentAmount.compareTo(BigInteger.ZERO) > 0) { - BigInteger requested = BigInteger.valueOf(amount); - if (currentAmount.compareTo(requested) <= 0) { - // 提取全部 - long ret; - if (currentAmount.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { - ret = Long.MAX_VALUE; - } else { - ret = currentAmount.longValue(); - } - if (mode == Actionable.MODULATE) { - map.remove(what); - // 更新 cached total - // 如果 currentAmount 大于 Long.MAX_VALUE,totalStored 减去 currentAmount 会保留大整数 - totalStored = totalStored.subtract(currentAmount); - this.saveChanges(); - } - return ret; - } else { - // 提取部分 - if (mode == Actionable.MODULATE) { - map.put(what, currentAmount.subtract(requested)); - // 更新 cached total - totalStored = totalStored.subtract(requested); - this.saveChanges(); - } - return amount; - } - } - return 0; - } - - // 获取存储单元内所有物品的总数量(格式化字符串) - public String getTotalStorage() { - // 使用缓存的 totalStored,避免每次全表扫描 - return formatBigInteger(totalStored); - } -} diff --git a/src/main/java/com/extendedae_plus/ae/items/InfinityBigIntegerCellItem.java b/src/main/java/com/extendedae_plus/ae/items/InfinityBigIntegerCellItem.java deleted file mode 100644 index 7002ba9..0000000 --- a/src/main/java/com/extendedae_plus/ae/items/InfinityBigIntegerCellItem.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.extendedae_plus.ae.items; - -import com.extendedae_plus.ae.api.storage.InfinityBigIntegerCellInventory; -import com.google.common.base.Preconditions; -import net.minecraft.ChatFormatting; -import net.minecraft.core.component.DataComponents; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.LongTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.component.CustomData; -import org.jetbrains.annotations.NotNull; - -import java.math.BigInteger; -import java.util.List; - -public class InfinityBigIntegerCellItem extends Item { - - public InfinityBigIntegerCellItem() { - super(new Properties().stacksTo(1).fireResistant()); - } - - @Override - public void appendHoverText(ItemStack stack, - @NotNull TooltipContext context, - List tooltip, - @NotNull TooltipFlag tooltipFlag) { - tooltip.add(Component.translatable("tooltip.extendedae_plus.infinity_biginteger_cell.summon1")); - tooltip.add(Component.translatable("tooltip.extendedae_plus.infinity_biginteger_cell.summon2")); - - Preconditions.checkArgument(stack.getItem() == this); - CustomData customData = stack.get(DataComponents.CUSTOM_DATA); - if (customData != null) { - CompoundTag tag = customData.copyTag(); - - if (tag != null && tag.contains("uuid")) { - String uuidStr = tag.getUUID("uuid").toString(); - tooltip.add( - Component.literal("UUID: ") - .withStyle(ChatFormatting.GRAY) - .append(Component.literal(uuidStr).withStyle(ChatFormatting.YELLOW)) - ); - - if (tag.contains("types")) { - try { - int types = tag.getInt("types"); - tooltip.add( - Component.literal("Types: ") - .withStyle(ChatFormatting.GRAY) - .append(Component.literal(String.valueOf(types)).withStyle(ChatFormatting.GREEN)) - ); - } catch (Exception ignored) { - } - } - - if (tag.contains("total")) { - BigInteger total = BigInteger.ZERO; - Tag t = tag.get("total"); - try { - if (t instanceof LongTag) { - total = BigInteger.valueOf(tag.getLong("total")); - } else { - String s = tag.getString("total"); - total = new BigInteger(s); - } - } catch (Exception ignored) { - } - String formatted = InfinityBigIntegerCellInventory.formatBigInteger(total); - tooltip.add( - Component.literal("Byte: ") - .withStyle(ChatFormatting.GRAY) - .append(Component.literal(formatted).withStyle(ChatFormatting.AQUA)) - ); - } - } - } - } -} diff --git a/src/main/java/com/extendedae_plus/init/ModCreativeTabs.java b/src/main/java/com/extendedae_plus/init/ModCreativeTabs.java index 2846159..f07a83b 100644 --- a/src/main/java/com/extendedae_plus/init/ModCreativeTabs.java +++ b/src/main/java/com/extendedae_plus/init/ModCreativeTabs.java @@ -27,7 +27,7 @@ public final class ModCreativeTabs { output.accept(ModItems.ACCELERATOR_256x.get()); output.accept(ModItems.ACCELERATOR_1024x.get()); - output.accept(ModItems.INFINITY_BIGINTEGER_CELL_ITEM.get()); +// output.accept(ModItems.INFINITY_BIGINTEGER_CELL_ITEM.get()); }) .build()); } diff --git a/src/main/java/com/extendedae_plus/init/ModItems.java b/src/main/java/com/extendedae_plus/init/ModItems.java index 113ec98..71a6220 100644 --- a/src/main/java/com/extendedae_plus/init/ModItems.java +++ b/src/main/java/com/extendedae_plus/init/ModItems.java @@ -1,7 +1,6 @@ package com.extendedae_plus.init; import com.extendedae_plus.ExtendedAEPlus; -import com.extendedae_plus.ae.items.InfinityBigIntegerCellItem; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; import net.neoforged.neoforge.registries.DeferredItem; @@ -48,8 +47,8 @@ public final class ModItems { () -> new BlockItem(ModBlocks.ACCELERATOR_1024x.get(), new Item.Properties()) ); - public static final DeferredItem INFINITY_BIGINTEGER_CELL_ITEM = ITEMS.register( - "infinity_biginteger_cell", InfinityBigIntegerCellItem::new - ); +// public static final DeferredItem INFINITY_BIGINTEGER_CELL_ITEM = ITEMS.register( +// "infinity_biginteger_cell", InfinityBigIntegerCellItem::new +// ); } diff --git a/src/main/java/com/extendedae_plus/util/storage/InfinityDataStorage.java b/src/main/java/com/extendedae_plus/util/storage/InfinityDataStorage.java deleted file mode 100644 index 4ef9036..0000000 --- a/src/main/java/com/extendedae_plus/util/storage/InfinityDataStorage.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.extendedae_plus.util.storage; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; - -/** - * InfinityDataStorage - * - * 表示单个 UUID 对应的持久化数据容器,直接映射到世界存档中的一项记录。 - * 数据结构说明: - * - keys: 存放序列化后的 AEKey(每项为 CompoundTag),用于标识不同的存储条目 - * - amounts: 与 keys 一一对应的数量列表(每项为 CompoundTag),采用混合表示: - * - 当数量能放入 long 时,CompoundTag 包含键 "l" 存放 long 值 - * - 当数量超出 long 时,CompoundTag 包含键 "s" 存放 BigInteger 的字符串形式 - * - * 该类提供将内存数据与 NBT 之间互转的辅助方法,供 `SavedData` 在世界保存/加载时调用。 - */ -public class InfinityDataStorage { - - /** 空实例(表示没有数据) */ - public static final InfinityDataStorage EMPTY = new InfinityDataStorage(); - - /** 序列化的键列表(NBT ListTag,元素为 CompoundTag) */ - public ListTag keys; - /** - * 与 keys 对应的数量列表(NBT ListTag,元素为 CompoundTag): - * - 若数量能放入 long,则 CompoundTag 包含键 "l"(long) - * - 否则包含键 "s"(String) 存放 BigInteger 的字符串形式 - */ - public ListTag amounts; - - public InfinityDataStorage() { - this(new ListTag(), new ListTag()); - } - - private InfinityDataStorage(ListTag keys, ListTag amounts) { - this.keys = keys; - this.amounts = amounts; - } - - /** - * 将当前数据封装为 CompoundTag 以写入存档 - */ - public CompoundTag serializeNBT() { - CompoundTag nbt = new CompoundTag(); - nbt.put("keys", keys); - nbt.put("amounts", amounts); - return nbt; - } - - /** - * 从存档读取数据并构造实例 - */ - public static InfinityDataStorage loadFromNBT(CompoundTag nbt) { - ListTag stackKeys = nbt.getList("keys", Tag.TAG_COMPOUND); - // amounts 以 CompoundTag 列表存储,每个 CompoundTag 内含 long 或 String - ListTag stackAmounts = nbt.getList("amounts", Tag.TAG_COMPOUND); - return new InfinityDataStorage(stackKeys, stackAmounts); - } -} diff --git a/src/main/java/com/extendedae_plus/util/storage/InfinityStorageManager.java b/src/main/java/com/extendedae_plus/util/storage/InfinityStorageManager.java deleted file mode 100644 index ea48942..0000000 --- a/src/main/java/com/extendedae_plus/util/storage/InfinityStorageManager.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.extendedae_plus.util.storage; - -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.saveddata.SavedData; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.WeakReference; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -/** - * InfinityStorageManager - *

- * 世界级别的持久化容器,集中管理所有 InfinityBigInteger 存储单元的序列化数据。 - * 功能要点: - * - 在世界加载时从存档恢复所有 cell 的数据 - * - 提供按 UUID 获取/创建单个 cell 的数据容器 - * - 在世界保存时将内存数据打包为 NBT 写回存档 - */ -public class InfinityStorageManager extends SavedData { - private static final Factory FACTORY = new Factory<>(InfinityStorageManager::new, InfinityStorageManager::readNbt); - - /** - * SavedData 文件名常量 - */ - public static final String FILE_NAME = "eap_infinity_biginteger_cells"; - /** - * 全局单例实例(在世界加载时由 InfiniteBigIntegerStorageCell.onLevelLoad 填充) - */ - public static InfinityStorageManager INSTANCE = null; - /** - * UUID -> 数据 的内存映射 - */ - private final Map cells; - - @Nullable - private WeakReference registries; - - public InfinityStorageManager() { - this.cells = new HashMap<>(); - setDirty(); - } - - public InfinityStorageManager(Map cells) { - this.cells = cells; - setDirty(); - } - - /** - * 从 NBT 构造:用于在世界加载时从存档恢复数据 - */ - public InfinityStorageManager(CompoundTag nbt) { - this.cells = new HashMap<>(); - ListTag cellList = nbt.getList("list", CompoundTag.TAG_COMPOUND); - for (int i = 0; i < cellList.size(); i++) { - CompoundTag cell = cellList.getCompound(i); - cells.put(cell.getUUID("uuid"), InfinityDataStorage.loadFromNBT(cell.getCompound("data"))); - } - setDirty(); - } - - /** - * 根据给定的 ServerLevel 获取或创建该世界对应的 SavedData 实例并缓存到 INSTANCE - */ - public static InfinityStorageManager getForLevel(ServerLevel level) { - if (INSTANCE == null && level != null) { - INSTANCE = level.getDataStorage().computeIfAbsent(FACTORY, FILE_NAME); - INSTANCE.registries = new WeakReference<>(level.registryAccess()); - } - return INSTANCE; - } - - public HolderLookup.Provider getRegistries() { - var r = this.registries; - if (r == null) { - throw new IllegalStateException("StorageManager was not initialized properly."); - } - - var registries = r.get(); - if (registries == null) { - throw new IllegalStateException("Using a StorageManager whose server was already closed"); - } - - return registries; - } - - @Override - public @NotNull CompoundTag save(@NotNull CompoundTag nbt, HolderLookup.@NotNull Provider registries) { - // 将内存中的所有 cell 序列化为一个 ListTag - ListTag cellList = new ListTag(); - for (Map.Entry entry : cells.entrySet()) { - CompoundTag cell = new CompoundTag(); - cell.putUUID("uuid", entry.getKey()); - cell.put("data", entry.getValue().serializeNBT()); - cellList.add(cell); - } - nbt.put("list", cellList); - return nbt; - } - - /** - * 更新或添加某个 UUID 对应的数据并标记为脏(需要保存) - */ - public void updateCell(UUID uuid, InfinityDataStorage infinityDataStorage) { - cells.put(uuid, infinityDataStorage); - setDirty(); - } - - /** - * 获取或创建某个 UUID 对应的数据容器 - */ - public InfinityDataStorage getOrCreateCell(UUID uuid) { - if (!cells.containsKey(uuid)) { - updateCell(uuid, new InfinityDataStorage()); - } - return cells.get(uuid); - } - - /** - * 修改某个 UUID 对应的键与数量列表并保存(新的签名,stackAmounts 为 ListTag 字符串列表) - */ - public void modifyCell(UUID cellID, ListTag stackKeys, ListTag stackAmounts) { - InfinityDataStorage cellToModify = getOrCreateCell(cellID); - if (stackKeys != null && stackAmounts != null) { - cellToModify.keys = stackKeys; - cellToModify.amounts = stackAmounts; - } - updateCell(cellID, cellToModify); - } - - /** - * 删除某个 UUID 的持久化记录并标记为脏 - */ - public void removeCell(UUID uuid) { - cells.remove(uuid); - setDirty(); - } - - public static InfinityStorageManager readNbt(CompoundTag nbt, HolderLookup.Provider registries) { - Map cell = new HashMap<>(); - ListTag diskList = nbt.getList("list", CompoundTag.TAG_COMPOUND); - for (int i = 0; i < diskList.size(); i++) { - CompoundTag disk = diskList.getCompound(i); - cell.put(disk.getUUID("uuid"), InfinityDataStorage.loadFromNBT(disk.getCompound("data"))); - } - return new InfinityStorageManager(cell); - } - - public static InfinityStorageManager getInstance(MinecraftServer server) { - ServerLevel world = server.getLevel(ServerLevel.OVERWORLD); - InfinityStorageManager manager = null; - if (world != null) { - manager = world.getDataStorage().computeIfAbsent(FACTORY, FILE_NAME); - } - if (manager != null) { - manager.registries = new WeakReference<>(server.registryAccess()); - } - return manager; - } -}