diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/shipyard_entities/MixinPersistentEntitySectionManager.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/shipyard_entities/MixinPersistentEntitySectionManager.java index fbbaf3831..e330afdf9 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/shipyard_entities/MixinPersistentEntitySectionManager.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/shipyard_entities/MixinPersistentEntitySectionManager.java @@ -1,17 +1,24 @@ package org.valkyrienskies.mod.mixin.feature.shipyard_entities; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; +import java.util.function.LongPredicate; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; import net.minecraft.world.level.entity.EntitySectionStorage; import net.minecraft.world.level.entity.PersistentEntitySectionManager; +import net.minecraft.world.level.entity.Visibility; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; import org.valkyrienskies.mod.mixinducks.world.OfLevel; @Mixin(PersistentEntitySectionManager.class) -public class MixinPersistentEntitySectionManager implements OfLevel { +public abstract class MixinPersistentEntitySectionManager implements OfLevel { @Shadow @Final EntitySectionStorage sectionStorage; @@ -29,4 +36,40 @@ public void setLevel(final Level level) { this.level = level; ((OfLevel) this.sectionStorage).setLevel(level); } + + @Shadow + @Final + private LongSet chunksToUnload; + + @Shadow + @Final + private Long2ObjectMap chunkVisibility; + + @Shadow + private boolean processChunkUnload(final long l) { + throw new IllegalStateException("This should not be invoked"); + } + + /** + * This fixes this function randomly crashing. I'm not sure why but the removeIf() function is buggy + */ + @Redirect( + method = "processUnloads", + at = @At( + value = "INVOKE", + target = "Lit/unimi/dsi/fastutil/longs/LongSet;removeIf(Ljava/util/function/LongPredicate;)Z" + ) + ) + private boolean replaceProcessUnloads(final LongSet instance, final LongPredicate longPredicate) { + final LongSet toRemove = new LongOpenHashSet(); + for (final long key : this.chunksToUnload) { + if (this.chunkVisibility.get(key) != Visibility.HIDDEN) { + toRemove.add(key); + } else if (this.processChunkUnload(key)) { + toRemove.add(key); + } + } + chunksToUnload.removeAll(toRemove); + return !toRemove.isEmpty(); + } }