diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java index 1db796450..2d1dfefd4 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/InstancedRenderDispatcher.java @@ -53,7 +53,8 @@ public class InstancedRenderDispatcher { } public static void enqueueUpdate(TileEntity te) { - getTiles(te.getLevel()).queueUpdate(te); + if (te.hasLevel() && te.getLevel() instanceof ClientWorld) + getTiles(te.getLevel()).queueUpdate(te); } public static void enqueueUpdate(Entity entity) { diff --git a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java index 0f6e9da62..4a3a73063 100644 --- a/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java +++ b/src/main/java/com/jozufozu/flywheel/event/ForgeEvents.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.util.WorldAttached; import net.minecraft.client.Minecraft; import net.minecraft.client.world.ClientWorld; @@ -45,4 +46,13 @@ public class ForgeEvents { } } + @SubscribeEvent + public static void onUnloadWorld(WorldEvent.Unload event) { + IWorld world = event.getWorld(); + + if (Backend.isFlywheelWorld(world)) { + WorldAttached.invalidateWorld(world); + } + } + } diff --git a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java index a91acb0e8..21a864314 100644 --- a/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java +++ b/src/main/java/com/jozufozu/flywheel/util/WorldAttached.java @@ -1,6 +1,10 @@ package com.jozufozu.flywheel.util; +import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -12,12 +16,30 @@ import net.minecraft.world.IWorld; public class WorldAttached { + // weak references to prevent leaking hashmaps when a WorldAttached is GC'd during runtime + static List>> allMaps = new ArrayList<>(); private final Map attached; private final Function factory; public WorldAttached(Function factory) { this.factory = factory; attached = new HashMap<>(); + allMaps.add(new WeakReference<>(attached)); + } + + public static void invalidateWorld(IWorld world) { + Iterator>> i = allMaps.iterator(); + while (i.hasNext()) { + Map map = i.next() + .get(); + if (map == null) { + // If the map has been GC'd, remove the weak reference + i.remove(); + } else { + // Prevent leaks + map.remove(world); + } + } } @Nonnull