Fix world leak

This commit is contained in:
Jozufozu 2021-10-31 19:50:01 -07:00
parent 46ebdfd43b
commit d2b5b1096b
3 changed files with 34 additions and 1 deletions

View File

@ -53,6 +53,7 @@ public class InstancedRenderDispatcher {
} }
public static void enqueueUpdate(TileEntity te) { public static void enqueueUpdate(TileEntity te) {
if (te.hasLevel() && te.getLevel() instanceof ClientWorld)
getTiles(te.getLevel()).queueUpdate(te); getTiles(te.getLevel()).queueUpdate(te);
} }

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import com.jozufozu.flywheel.backend.Backend; import com.jozufozu.flywheel.backend.Backend;
import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher;
import com.jozufozu.flywheel.util.WorldAttached;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld; 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);
}
}
} }

View File

@ -1,6 +1,10 @@
package com.jozufozu.flywheel.util; package com.jozufozu.flywheel.util;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -12,12 +16,30 @@ import net.minecraft.world.IWorld;
public class WorldAttached<T> { public class WorldAttached<T> {
// weak references to prevent leaking hashmaps when a WorldAttached is GC'd during runtime
static List<WeakReference<Map<IWorld, ?>>> allMaps = new ArrayList<>();
private final Map<IWorld, T> attached; private final Map<IWorld, T> attached;
private final Function<IWorld, T> factory; private final Function<IWorld, T> factory;
public WorldAttached(Function<IWorld, T> factory) { public WorldAttached(Function<IWorld, T> factory) {
this.factory = factory; this.factory = factory;
attached = new HashMap<>(); attached = new HashMap<>();
allMaps.add(new WeakReference<>(attached));
}
public static void invalidateWorld(IWorld world) {
Iterator<WeakReference<Map<IWorld, ?>>> i = allMaps.iterator();
while (i.hasNext()) {
Map<IWorld, ?> 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 @Nonnull