diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java index c2d18289bb3..cce86326eb4 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/server/level/ServerLevelMixin.java @@ -55,6 +55,7 @@ import net.minecraft.world.level.storage.WorldData; import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec3; +import org.objectweb.asm.Opcodes; import org.spongepowered.api.ResourceKey; import org.spongepowered.api.Sponge; import org.spongepowered.api.block.BlockSnapshot; @@ -128,6 +129,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerLevel // @formatter:off @Shadow @Final private ServerLevelData serverLevelData; + @Shadow private int emptyTime; @Shadow @Nonnull public abstract MinecraftServer shadow$getServer(); @Shadow protected abstract void shadow$saveLevelData(); @@ -441,6 +443,25 @@ public void save(@Nullable final ProgressListener progress, final boolean flush, this.impl$recentTickTimes[this.shadow$getServer().getTickCount() % 100] = postTickTime - this.impl$preTickTime; } + @Inject( + method = "tick", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/server/level/ServerLevel;emptyTime:I", + opcode = Opcodes.PUTFIELD, + shift = At.Shift.AFTER + ) + ) + private void impl$unloadBlockEntities(final BooleanSupplier param0, final CallbackInfo ci) { + // This code fixes block entity memory leak + // https://github.com/SpongePowered/Sponge/pull/3689 + if (this.emptyTime >= 300 && !this.blockEntitiesToUnload.isEmpty()) { + this.tickableBlockEntities.removeAll(this.blockEntitiesToUnload); + this.blockEntityList.removeAll(this.blockEntitiesToUnload); + this.blockEntitiesToUnload.clear(); + } + } + private void impl$setWorldOnBorder() { ((WorldBorderBridge) this.shadow$getWorldBorder()).bridge$setAssociatedWorld(this.bridge$getKey()); } diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java index 9f971e60b70..3d26ffe4a43 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/level/LevelMixin.java @@ -66,6 +66,7 @@ import org.spongepowered.common.util.DataUtil; import org.spongepowered.math.vector.Vector3d; +import java.util.List; import java.util.function.Predicate; @Mixin(net.minecraft.world.level.Level.class) @@ -77,6 +78,9 @@ public abstract class LevelMixin implements LevelBridge, LevelAccessor { @Shadow protected float rainLevel; @Shadow protected float oThunderLevel; @Shadow protected float thunderLevel; + @Shadow @Final public List blockEntityList; + @Shadow @Final public List tickableBlockEntities; + @Shadow @Final protected List blockEntitiesToUnload; @Shadow public abstract LevelData shadow$getLevelData(); @Shadow public abstract void shadow$updateSkyBrightness();