Check for empty dimensions outside of chunk unloading loop, culling worlds without needing chunk unloads to trigger it. (#4704)

This commit is contained in:
Ben Staddon 2018-04-01 08:54:22 +01:00 committed by LexManos
parent b8e411674b
commit 4c1167c96d
3 changed files with 53 additions and 24 deletions

View File

@ -72,7 +72,7 @@
Iterator<Long> iterator = this.field_73248_b.iterator();
for (int i = 0; i < 100 && iterator.hasNext(); iterator.remove())
@@ -234,10 +267,15 @@
@@ -234,6 +267,7 @@
if (chunk != null && chunk.field_189550_d)
{
chunk.func_76623_d();
@ -80,11 +80,12 @@
this.func_73242_b(chunk);
this.func_73243_a(chunk);
this.field_73244_f.remove(olong);
++i;
+ if (field_73244_f.size() == 0 && net.minecraftforge.common.ForgeChunkManager.getPersistentChunksFor(this.field_73251_h).size() == 0 && !this.field_73251_h.field_73011_w.func_186058_p().shouldLoadSpawn()){
+ net.minecraftforge.common.DimensionManager.unloadWorld(this.field_73251_h.field_73011_w.getDimension());
+ break;
+ }
}
@@ -242,6 +276,8 @@
}
}
+ if (this.field_73244_f.isEmpty()) net.minecraftforge.common.DimensionManager.unloadWorld(this.field_73251_h.field_73011_w.getDimension());
+
this.field_73247_e.func_75817_a();
}

View File

@ -32,7 +32,9 @@ import java.util.concurrent.ConcurrentMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntListIterator;
import org.apache.logging.log4j.Level;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.ints.IntSets;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Lists;
@ -50,7 +52,6 @@ import net.minecraft.world.WorldServer;
import net.minecraft.world.WorldServerMulti;
import net.minecraft.world.storage.ISaveHandler;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import javax.annotation.Nullable;
@ -68,13 +69,15 @@ public class DimensionManager
}
}
private static Hashtable<Integer, WorldServer> worlds = new Hashtable<Integer, WorldServer>();
private static boolean hasInit = false;
private static Hashtable<Integer, Dimension> dimensions = new Hashtable<Integer, Dimension>();
private static IntArrayList unloadQueue = new IntArrayList();
private static BitSet dimensionMap = new BitSet(Long.SIZE << 4);
private static ConcurrentMap<World, World> weakWorldMap = new MapMaker().weakKeys().weakValues().<World,World>makeMap();
private static Multiset<Integer> leakedWorlds = HashMultiset.create();
private static final Hashtable<Integer, WorldServer> worlds = new Hashtable<>();
private static final Hashtable<Integer, Dimension> dimensions = new Hashtable<>();
private static final IntSet keepLoaded = IntSets.synchronize(new IntOpenHashSet());
private static final IntArrayList unloadQueue = new IntArrayList();
private static final BitSet dimensionMap = new BitSet(Long.SIZE << 4);
private static final ConcurrentMap<World, World> weakWorldMap = new MapMaker().weakKeys().weakValues().makeMap();
private static final Multiset<Integer> leakedWorlds = HashMultiset.create();
/**
* Returns a list of dimensions associated with this DimensionType.
@ -299,13 +302,35 @@ public class DimensionManager
}
/**
* Queues a dimension to unload.
* If the dimension is already queued, it will reset the delay to unload
* Sets if a dimension should stay loaded.
* @param dim the dimension ID
* @param keep whether or not the dimension should be kept loaded
* @return true iff the dimension's status changed
*/
public static boolean keepDimensionLoaded(int dim, boolean keep)
{
return keep ? keepLoaded.add(dim) : keepLoaded.remove(dim);
}
private static boolean canUnloadWorld(WorldServer world)
{
return ForgeChunkManager.getPersistentChunksFor(world).isEmpty()
&& world.playerEntities.isEmpty()
&& !world.provider.getDimensionType().shouldLoadSpawn()
&& !keepLoaded.contains(world.provider.getDimension());
}
/**
* Queues a dimension to unload, if it can be unloaded.
* If the dimension is already queued, it will reset the delay to unload.
* @param id The id of the dimension
*/
public static void unloadWorld(int id)
{
if(!unloadQueue.contains(id))
WorldServer world = worlds.get(id);
if (world == null || !canUnloadWorld(world)) return;
if (!unloadQueue.contains(id))
{
FMLLog.log.debug("Queueing dimension {} to unload", id);
unloadQueue.add(id);
@ -337,7 +362,8 @@ public class DimensionManager
WorldServer w = worlds.get(id);
queueIterator.remove();
dimension.ticksWaited = 0;
if (w == null || !ForgeChunkManager.getPersistentChunksFor(w).isEmpty() || !w.playerEntities.isEmpty() || dimension.type.shouldLoadSpawn()) //Don't unload the world if the status changed
// Don't unload the world if the status changed
if (w == null || !canUnloadWorld(w))
{
FMLLog.log.debug("Aborting unload for dimension {} as status changed", id);
continue;

View File

@ -41,7 +41,7 @@ public class ChunkGenWorker implements IWorker
private final int notificationFrequency;
private int lastNotification = 0;
private int genned = 0;
private Boolean loadSpawn;
private Boolean keepingLoaded;
public ChunkGenWorker(ICommandSender listener, BlockPos start, int total, int dim, int interval)
{
@ -116,10 +116,9 @@ public class ChunkGenWorker implements IWorker
}
}
// While we work we don't want to cause world load spam so pause unloading the world.
if (loadSpawn == null)
if (keepingLoaded == null)
{
loadSpawn = world.provider.getDimensionType().shouldLoadSpawn();
world.provider.getDimensionType().setLoadSpawn(true);
keepingLoaded = DimensionManager.keepDimensionLoaded(dim, true);
}
if (++lastNotification >= notificationFrequency)
@ -159,7 +158,10 @@ public class ChunkGenWorker implements IWorker
if (queue.size() == 0)
{
listener.sendMessage(TextComponentHelper.createComponentTranslation(listener, "commands.forge.gen.complete", genned, total, dim));
DimensionManager.getProviderType(dim).setLoadSpawn(loadSpawn);
if (keepingLoaded != null && keepingLoaded)
{
DimensionManager.keepDimensionLoaded(dim, false);
}
}
}
}