From 1490f73b5f261aac7b38f00772ff6bc29855a7d8 Mon Sep 17 00:00:00 2001 From: C-H716 <1536152356@qq.com> Date: Thu, 18 Sep 2025 14:32:38 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=9D=E8=AF=81=E5=81=9C=E6=AD=A2?= =?UTF-8?q?=E6=97=B6=E5=BC=BA=E5=88=B6=E6=8C=81=E4=B9=85=E5=8C=96=E6=97=A0?= =?UTF-8?q?=E9=99=90=E5=AD=98=E5=82=A8=E5=85=83=E4=BB=B6=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/extendedae_plus/ExtendedAEPlus.java | 4 ++ .../InfinityBigIntegerCellInventory.java | 43 +++++++++++-------- .../extendedae_plus/ae/client/gui/Icon.java | 33 -------------- 3 files changed, 29 insertions(+), 51 deletions(-) delete mode 100644 src/main/java/com/extendedae_plus/ae/client/gui/Icon.java diff --git a/src/main/java/com/extendedae_plus/ExtendedAEPlus.java b/src/main/java/com/extendedae_plus/ExtendedAEPlus.java index 6a84267..25d675e 100644 --- a/src/main/java/com/extendedae_plus/ExtendedAEPlus.java +++ b/src/main/java/com/extendedae_plus/ExtendedAEPlus.java @@ -3,6 +3,7 @@ package com.extendedae_plus; import appeng.api.storage.StorageCells; import appeng.menu.locator.MenuLocators; import com.extendedae_plus.ae.api.storage.InfinityBigIntegerCellHandler; +import com.extendedae_plus.ae.api.storage.InfinityBigIntegerCellInventory; import com.extendedae_plus.client.ClientRegistrar; import com.extendedae_plus.config.ModConfig; import com.extendedae_plus.init.*; @@ -54,6 +55,9 @@ public class ExtendedAEPlus { MinecraftForge.EVENT_BUS.addListener(ExtendedAEPlus::onLevelLoad); // 注册通用配置 ModConfig.init(); + // 注册 InfinityBigIntegerCellInventory 的事件监听(tick flush 与停止时 flush) + MinecraftForge.EVENT_BUS.addListener(InfinityBigIntegerCellInventory::onServerTick); + MinecraftForge.EVENT_BUS.addListener(InfinityBigIntegerCellInventory::onServerStopping); // ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModConfigs.COMMON_SPEC); } diff --git a/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellInventory.java b/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellInventory.java index d46cf2d..2cbb417 100644 --- a/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellInventory.java +++ b/src/main/java/com/extendedae_plus/ae/api/storage/InfinityBigIntegerCellInventory.java @@ -17,8 +17,8 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.server.ServerStoppingEvent; import java.math.BigDecimal; import java.math.BigInteger; @@ -27,6 +27,7 @@ import java.text.DecimalFormat; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedQueue; +import static com.extendedae_plus.util.ExtendedAELogger.LOGGER; /** * InfinityBigIntegerCellInventory *

@@ -50,15 +51,6 @@ public class InfinityBigIntegerCellInventory implements StorageCell { // 数字格式化对象,保留两位小数(复用以减少对象分配) private static final DecimalFormat DF = new DecimalFormat("#.##"); - static { - // 在类加载时注册服务器 tick 监听器,用于在主线程合并写入 - try { - MinecraftForge.EVENT_BUS.addListener(InfinityBigIntegerCellInventory::onServerTick); - } catch (Throwable ignored) { - // 保守降级:若注册失败,不阻塞实例化 - } - } - // 关联的 ItemStack(含可能的 uuid NBT) private final ItemStack stack; // AE2 提供的保存提供者,用于在容器中批量保存时触发回调 @@ -97,7 +89,7 @@ public class InfinityBigIntegerCellInventory implements StorageCell { } // 服务器 tick 回调:合并并执行待持久化项 - private static void onServerTick(TickEvent.ServerTickEvent event) { + public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase != TickEvent.Phase.END) return; InfinityBigIntegerCellInventory inv; // 处理本次 tick 中的全部待持久化项 @@ -107,11 +99,32 @@ public class InfinityBigIntegerCellInventory implements StorageCell { inv.persist(); } } catch (Throwable ignored) { - // 忽略单项错误,继续处理其余队列 + LOGGER.info("InfinityBigIntegerCellInventory onServerTick error: {}", ignored.getMessage()); } } } + // 在服务器停止时被调用,立即强制持久化队列中的所有实例 + public static void onServerStopping(ServerStoppingEvent event) { + InfinityBigIntegerCellInventory inv; + while ((inv = PENDING_PERSIST.poll()) != null) { + try { + if (!inv.isPersisted) { + inv.persist(); + } + } catch (Throwable ignored) { + LOGGER.info("InfinityBigIntegerCellInventory onServerStopping error1: {}", ignored.getMessage()); + } + } + // 额外尝试将全局存储管理器标记为脏以确保 SavedData 被写回(在单人模式下可能直接由系统触发) + try { + var stor = getStorageInstance(); + if (stor != null) stor.setDirty(); + } catch (Throwable ignored) { + LOGGER.info("InfinityBigIntegerCellInventory onServerStopping error2: {}", ignored.getMessage()); + } + } + // 将 BigInteger 格式化为带单位的字符串,保留两位小数 public static String formatBigInteger(BigInteger number) { // 使用局部 DF(非线程安全),但 Minecraft 通常在主线程运行 @@ -240,12 +253,6 @@ public class InfinityBigIntegerCellInventory implements StorageCell { // 获取所有可用的物品堆栈及其数量 @Override public void getAvailableStacks(KeyCounter out) { - // 使用饱和(saturating)加法将 BigInteger 值转换为 long 并安全地累加到 KeyCounter 中。 - // 问题背景:当同一物品存在于多个 cell 中,AE2 的 KeyCounter 使用 long 来记录数量, - // 若简单将单个 cell 的超长值截断为 Long.MAX_VALUE 并直接 add,多个 cell 的合并会导致 - // 原本代表 "大于 long" 的值被重复添加而导致读取异常。解决方案:每次向 KeyCounter 添加前, - // 先读取当前计数器中的已有值(long),并使用 BigInteger 做饱和加法后再写回为 long,避免中间溢出。 - BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE); Object2ObjectMap map = getCellStoredMap(); for (Object2ObjectMap.Entry entry : map.object2ObjectEntrySet()) { diff --git a/src/main/java/com/extendedae_plus/ae/client/gui/Icon.java b/src/main/java/com/extendedae_plus/ae/client/gui/Icon.java deleted file mode 100644 index 9574df3..0000000 --- a/src/main/java/com/extendedae_plus/ae/client/gui/Icon.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.extendedae_plus.ae.client.gui; - -import appeng.client.gui.style.Blitter; -import com.extendedae_plus.ExtendedAEPlus; -import net.minecraft.resources.ResourceLocation; - -public enum Icon { - REDSTONE_LOW(0, 0), - REDSTONE_HIGH(16, 0); - - public final int x; - public final int y; - public final int width; - public final int height; - public static final ResourceLocation TEXTURE = new ResourceLocation(ExtendedAEPlus.MODID, "textures/guis/states.png"); - public static final int TEXTURE_WIDTH = 256; - public static final int TEXTURE_HEIGHT = 256; - - private Icon(int x, int y) { - this(x, y, 16, 16); - } - - private Icon(int x, int y, int width, int height) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - - public Blitter getBlitter() { - return Blitter.texture(TEXTURE, TEXTURE_WIDTH, TEXTURE_HEIGHT).src(this.x, this.y, this.width, this.height); - } -}