diff options
author | Travis Watkins <amaranth@ubuntu.com> | 2014-02-01 17:42:43 -0600 |
---|---|---|
committer | Travis Watkins <amaranth@ubuntu.com> | 2014-02-01 22:03:04 -0600 |
commit | d7d81fa68fb439c41547d347dd099261ff28af17 (patch) | |
tree | d757441b136df4ebd99c559f138ab958c075f388 /src/main/java/org | |
parent | 4a6a81e72412d822f6047c0139524203081fad6f (diff) | |
download | craftbukkit-d7d81fa68fb439c41547d347dd099261ff28af17.tar craftbukkit-d7d81fa68fb439c41547d347dd099261ff28af17.tar.gz craftbukkit-d7d81fa68fb439c41547d347dd099261ff28af17.tar.lz craftbukkit-d7d81fa68fb439c41547d347dd099261ff28af17.tar.xz craftbukkit-d7d81fa68fb439c41547d347dd099261ff28af17.zip |
Load all already generated chunks via async chunk system
Currently we use the async chunk loading system only when players trigger
chunk loading. If a chunk is loaded for any other reason it goes through
a separate codepath. This means if a player has trigged a chunk load and
before the chunk loads something else wants the same chunk we will load it
twice and throw away the second result. With this change we instead use
the sync processing feature of the AsynchronousExecutor to load the chunk
which will pull it out of the queue if it was already queued to load. This
means we only ever load a chunk once. Because chunk generation is not
thread safe we still fallback to the vanilla chunk loading system if the
chunk does not currently exist.
Diffstat (limited to 'src/main/java/org')
3 files changed, 15 insertions, 24 deletions
diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java index 92fbc4f9..afcf764b 100644 --- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java +++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java @@ -5,7 +5,6 @@ import net.minecraft.server.ChunkProviderServer; import net.minecraft.server.ChunkRegionLoader; import net.minecraft.server.World; import org.bukkit.craftbukkit.util.AsynchronousExecutor; -import org.bukkit.craftbukkit.util.LongHash; public class ChunkIOExecutor { static final int BASE_THREADS = 1; @@ -13,12 +12,12 @@ public class ChunkIOExecutor { private static final AsynchronousExecutor<QueuedChunk, Chunk, Runnable, RuntimeException> instance = new AsynchronousExecutor<QueuedChunk, Chunk, Runnable, RuntimeException>(new ChunkIOProvider(), BASE_THREADS); - public static void waitForChunkLoad(World world, int x, int z) { - instance.get(new QueuedChunk(LongHash.toLong(x, z), null, world, null)); + public static Chunk syncChunkLoad(World world, ChunkRegionLoader loader, ChunkProviderServer provider, int x, int z) { + return instance.getSkipQueue(new QueuedChunk(x, z, loader, world, provider)); } public static void queueChunkLoad(World world, ChunkRegionLoader loader, ChunkProviderServer provider, int x, int z, Runnable runnable) { - instance.add(new QueuedChunk(LongHash.toLong(x, z), loader, world, provider), runnable); + instance.add(new QueuedChunk(x, z, loader, world, provider), runnable); } public static void adjustPoolSize(int players) { diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java index b9de12d8..8feadd11 100644 --- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java +++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java @@ -16,7 +16,7 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu // async stuff public Chunk callStage1(QueuedChunk queuedChunk) throws RuntimeException { ChunkRegionLoader loader = queuedChunk.loader; - Object[] data = loader.loadChunk(queuedChunk.world, LongHash.msw(queuedChunk.coords), LongHash.lsw(queuedChunk.coords)); + Object[] data = loader.loadChunk(queuedChunk.world, queuedChunk.x, queuedChunk.z); if (data != null) { queuedChunk.compound = (NBTTagCompound) data[1]; @@ -30,27 +30,17 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu public void callStage2(QueuedChunk queuedChunk, Chunk chunk) throws RuntimeException { if(chunk == null) { // If the chunk loading failed just do it synchronously (may generate) - queuedChunk.provider.getChunkAt(LongHash.msw(queuedChunk.coords), LongHash.lsw(queuedChunk.coords)); - return; - } - - int x = LongHash.msw(queuedChunk.coords); - int z = LongHash.lsw(queuedChunk.coords); - - // See if someone already loaded this chunk while we were working on it (API, etc) - if (queuedChunk.provider.chunks.containsKey(queuedChunk.coords)) { - // Make sure it isn't queued for unload, we need it - queuedChunk.provider.unloadQueue.remove(queuedChunk.coords); + queuedChunk.provider.originalGetChunkAt(queuedChunk.x, queuedChunk.z); return; } queuedChunk.loader.loadEntities(chunk, queuedChunk.compound.getCompound("Level"), queuedChunk.world); chunk.p = queuedChunk.provider.world.getTime(); - queuedChunk.provider.chunks.put(queuedChunk.coords, chunk); + queuedChunk.provider.chunks.put(LongHash.toLong(queuedChunk.x, queuedChunk.z), chunk); chunk.addEntities(); if (queuedChunk.provider.chunkProvider != null) { - queuedChunk.provider.chunkProvider.recreateStructures(x, z); + queuedChunk.provider.chunkProvider.recreateStructures(queuedChunk.x, queuedChunk.z); } Server server = queuedChunk.provider.world.getServer(); @@ -58,7 +48,7 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(chunk.bukkitChunk, false)); } - chunk.a(queuedChunk.provider, queuedChunk.provider, x, z); + chunk.a(queuedChunk.provider, queuedChunk.provider, queuedChunk.x, queuedChunk.z); } public void callStage3(QueuedChunk queuedChunk, Chunk chunk, Runnable runnable) throws RuntimeException { diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/QueuedChunk.java b/src/main/java/org/bukkit/craftbukkit/chunkio/QueuedChunk.java index 77f56619..842d424f 100644 --- a/src/main/java/org/bukkit/craftbukkit/chunkio/QueuedChunk.java +++ b/src/main/java/org/bukkit/craftbukkit/chunkio/QueuedChunk.java @@ -6,14 +6,16 @@ import net.minecraft.server.NBTTagCompound; import net.minecraft.server.World; class QueuedChunk { - final long coords; + final int x; + final int z; final ChunkRegionLoader loader; final World world; final ChunkProviderServer provider; NBTTagCompound compound; - public QueuedChunk(long coords, ChunkRegionLoader loader, World world, ChunkProviderServer provider) { - this.coords = coords; + public QueuedChunk(int x, int z, ChunkRegionLoader loader, World world, ChunkProviderServer provider) { + this.x = x; + this.z = z; this.loader = loader; this.world = world; this.provider = provider; @@ -21,14 +23,14 @@ class QueuedChunk { @Override public int hashCode() { - return (int) coords ^ world.hashCode(); + return (x * 31 + z * 29) ^ world.hashCode(); } @Override public boolean equals(Object object) { if (object instanceof QueuedChunk) { QueuedChunk other = (QueuedChunk) object; - return coords == other.coords && world == other.world; + return x == other.x && z == other.z && world == other.world; } return false; |