diff --git a/src/main/java/dev/modzuozhi/mixin/ChunkMapEntityMapMixin.java b/src/main/java/dev/modzuozhi/mixin/ChunkMapEntityMapMixin.java new file mode 100644 index 0000000..0f67450 --- /dev/null +++ b/src/main/java/dev/modzuozhi/mixin/ChunkMapEntityMapMixin.java @@ -0,0 +1,34 @@ +package dev.modzuozhi.mixin; + +import dev.modzuozhi.core.collection.Int2ObjectConcurrentHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import net.minecraft.server.level.ChunkMap; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +/** + * 实体跟踪表({@code ChunkMap.entityMap})并发化(借鉴 MCMT/Async 思路,独立实现)。 + *

+ * {@code entityMap}({@code Int2ObjectOpenHashMap})记录所有被跟踪实体。 + * 维度并行下存在两条不同线程的访问路径: + *

+ * fastutil {@code Int2ObjectOpenHashMap} 遍历与修改并发 → 迭代器损坏({@code wrapped=null} + * NPE)→ 移动包处理失败刷屏 → 主线程 {@code Can't keep up} → 玩家"连接中断"掉线(实测: + * 大量女仆/召唤物生成时快速跑图必现)。 + *

+ * 修复:用 {@link Int2ObjectConcurrentHashMap}(内部 {@code ConcurrentHashMap},弱一致迭代) + * 替换 {@code entityMap} 实例({@code @Shadow} 初始值替换,与 {@code EntityLookupMixin}/ + * {@code PoiSectionMixin} 相同的已验证模式)。遍历与增删并发不再抛 NPE/CME,纯加固, + * 不改变任何 tick 归属与调度逻辑。 + */ +@Mixin(ChunkMap.class) +public abstract class ChunkMapEntityMapMixin { + + @Shadow + private final Int2ObjectMap entityMap = new Int2ObjectConcurrentHashMap<>(); +} diff --git a/src/main/resources/dimensionalripper.mixins.json b/src/main/resources/dimensionalripper.mixins.json index 9995018..7b8335f 100644 --- a/src/main/resources/dimensionalripper.mixins.json +++ b/src/main/resources/dimensionalripper.mixins.json @@ -11,6 +11,7 @@ "BlockableEventLoopPollMixin", "BlockDropCaptureMixin", "BrainMixin", + "ChunkMapEntityMapMixin", "ChunkMapLoadOffloadMixin", "ClassInstanceMultiMapMixin", "CollectingNeighborUpdaterMixin",