Updated Upstream (CraftBukkit/Spigot)

Upstream has released updates that appears to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

CraftBukkit Changes:
7033f180 Hoist out synchronisation from ChunkRegionLoader

Spigot Changes:
500ff5d4 Rebuild patches

Additional Paper changes:
Fixed Versioned World Folders to not synchronize on ChunkRegionLoader
Optimized Save Queue even more to use a Long2ObjectOpenHashmap for save map
Add World#getXIfLoaded to IWorldReader to expose it to more places
This commit is contained in:
Aikar 2018-09-10 22:38:42 -04:00
parent b86056bae2
commit 6711724fae
11 changed files with 120 additions and 78 deletions

View file

@ -6,7 +6,7 @@ Subject: [PATCH] Add Debug Entities option to debug dupe uuid issues
Add -Ddebug.entities=true to your JVM flags to gain more information
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 58f7489ebd..d974cb5c61 100644
index 064bd4133a..7d8f723968 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke

View file

@ -6,7 +6,7 @@ Subject: [PATCH] Add World Util Methods
Methods that can be used for other patches to help improve logic.
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 68f845986..dcd122d8b 100644
index 68f8459861..dcd122d8b5 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -0,0 +0,0 @@ public class Chunk implements IChunkAccess {
@ -17,8 +17,44 @@ index 68f845986..dcd122d8b 100644
public int a(BlockPosition blockposition, int i) {
return this.a(blockposition, i, this.world.o().g());
}
diff --git a/src/main/java/net/minecraft/server/IWorldReader.java b/src/main/java/net/minecraft/server/IWorldReader.java
index ac85986a1a..06c5a54254 100644
--- a/src/main/java/net/minecraft/server/IWorldReader.java
+++ b/src/main/java/net/minecraft/server/IWorldReader.java
@@ -0,0 +0,0 @@ public interface IWorldReader extends IBlockAccess {
}
int getLightLevel(BlockPosition var1, int var2);
+ // Paper start
+ default @Nullable
+ IBlockData getTypeIfLoaded(BlockPosition var1) {
+ return isLoaded(var1) ? getType(var1) : null;
+ }
+
+ default @Nullable
+ Block getBlockIfLoaded(BlockPosition var1) {
+ return isLoaded(var1) ? getType(var1).getBlock() : null;
+ }
+
+ default @Nullable
+ Material getMaterialIfLoaded(BlockPosition var1) {
+ return isLoaded(var1) ? getType(var1).getMaterial() : null;
+ }
+ // Paper end
boolean isChunkLoaded(int var1, int var2, boolean var3);
@@ -0,0 +0,0 @@ public interface IWorldReader extends IBlockAccess {
WorldBorder worldborder = this.getWorldBorder();
boolean flag1 = worldborder.b() < (double)i && (double)j < worldborder.d() && worldborder.c() < (double)i1 && (double)j1 < worldborder.e();
VoxelShapeBitSet voxelshapebitset = new VoxelShapeBitSet(j - i, l - k, j1 - i1);
- Predicate predicate = (voxelshape3) -> {
+ Predicate<VoxelShape> predicate = (voxelshape3) -> { // Paper - decompile fix
return !voxelshape3.b() && VoxelShapes.c(voxelshape, voxelshape3, OperatorBoolean.AND);
};
Stream stream = StreamSupport.stream(BlockPosition.MutableBlockPosition.b(i, k, i1, j - 1, l - 1, j1 - 1).spliterator(), false).map((blockposition$mutableblockposition) -> {
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 561bcd07b..94872593b 100644
index 561bcd07b3..94872593b1 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc

View file

@ -8,7 +8,7 @@ Adds a command line flag to enable stats on how chunk saves are processing.
Stats on current queue, how many was processed and how many were queued.
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 87744dcbfc..355186c111 100644
index 8acbd7bbff..edb4f2bb65 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
@ -54,7 +54,7 @@ index 87744dcbfc..355186c111 100644
return false;
}
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index 2415404d69..f099b91f7a 100644
index fc8f7574cf..94ed728c0e 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
@ -73,13 +73,13 @@ index 2415404d69..f099b91f7a 100644
// CraftBukkit start - Add async variant, provide compatibility
@Nullable
@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
protected void a(ChunkCoordIntPair chunkcoordintpair, Supplier<NBTTagCompound> nbttagcompound) { // Spigot
this.saveMap.put(chunkcoordintpair.asLong(), nbttagcompound); // Paper
queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements
+ queuedSaves++; // Paper
FileIOThread.a().a(this);
}
protected void a(ChunkCoordIntPair chunkcoordintpair, Supplier<NBTTagCompound> nbttagcompound) { // Spigot
+ queuedSaves++; // Paper
synchronized (this.b) { // Paper - synchronize while modifying the map
queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements
this.b.put(chunkcoordintpair, nbttagcompound);
@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
// Paper end
ChunkCoordIntPair chunkcoordintpair = chunk.coords; // Paper - Chunk queue improvements

View file

@ -40,8 +40,20 @@ index 0d68ffd75a..fd00c320ce 100644
+ if (enableFileIOThreadSleep) Bukkit.getLogger().info("Enabled sleeping between chunk saves, beware of memory issues");
+ }
}
diff --git a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
index d9608121b6..d7a6700936 100644
--- a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
+++ b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
@@ -0,0 +0,0 @@ public class ChunkCoordIntPair {
this.z = (int)(i >> 32);
}
+ public long asLong() { return a(); } // Paper
public long a() {
return a(this.x, this.z);
}
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index 2e9bd0949a..1dbcedbf94 100644
index f969c036f3..e831ea1429 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -0,0 +0,0 @@ import java.util.function.Consumer;
@ -77,16 +89,26 @@ index 2e9bd0949a..1dbcedbf94 100644
+ // Paper end
+
private static final Logger a = LogManager.getLogger();
private final Map<ChunkCoordIntPair, Supplier<NBTTagCompound>> b = java.util.Collections.synchronizedMap(Maps.newHashMap()); // CraftBukkit // Spigot
- private final Map<ChunkCoordIntPair, Supplier<NBTTagCompound>> b = Maps.newHashMap();
+ private final it.unimi.dsi.fastutil.longs.Long2ObjectMap<Supplier<NBTTagCompound>> saveMap = it.unimi.dsi.fastutil.longs.Long2ObjectMaps.synchronize(new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>()); // Paper
private final File c;
private final DataFixer d;
private PersistentStructureLegacy e;
@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
@Nullable
private NBTTagCompound a(DimensionManager dimensionmanager, @Nullable PersistentCollection persistentcollection, int i, int j, @Nullable GeneratorAccess generatoraccess) throws IOException {
- NBTTagCompound nbttagcompound = SupplierUtils.getIfExists(this.b.get(new ChunkCoordIntPair(i, j))); // Spigot
+ NBTTagCompound nbttagcompound = SupplierUtils.getIfExists(this.saveMap.get(ChunkCoordIntPair.asLong(i, j))); // Spigot // Paper
if (nbttagcompound != null) {
return nbttagcompound;
@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
}
};
}
-
- this.a(chunkcoordintpair, SupplierUtils.createUnivaluedSupplier(completion, unloaded && this.b.size() < SAVE_QUEUE_TARGET_SIZE));
+ this.a(chunkcoordintpair, SupplierUtils.createUnivaluedSupplier(completion, unloaded)); // Paper - Remove save queue target size
+ // Paper end
// Spigot end
} catch (Exception exception) {
ChunkRegionLoader.a.error("Failed to save chunk", exception);
@ -95,10 +117,8 @@ index 2e9bd0949a..1dbcedbf94 100644
protected void a(ChunkCoordIntPair chunkcoordintpair, Supplier<NBTTagCompound> nbttagcompound) { // Spigot
- this.b.put(chunkcoordintpair, nbttagcompound);
+ synchronized (this.b) { // Paper - synchronize while modifying the map
+ queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements
+ this.b.put(chunkcoordintpair, nbttagcompound);
+ }
+ this.saveMap.put(chunkcoordintpair.asLong(), nbttagcompound); // Paper
+ queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements
FileIOThread.a().a(this);
}
@ -106,7 +126,6 @@ index 2e9bd0949a..1dbcedbf94 100644
}
private boolean processSaveQueueEntry(boolean logCompletion) {
- synchronized (this.b) { // CraftBukkit
- Iterator iterator = this.b.entrySet().iterator();
- if (!iterator.hasNext()) {
+ // Paper start - Chunk queue improvements
@ -140,25 +159,17 @@ index 2e9bd0949a..1dbcedbf94 100644
RegionFileCache.write(this.c, chunkcoordintpair.x, chunkcoordintpair.z, SupplierUtils.getIfExists(nbttagcompound)); // Spigot
+ // Paper start remove from map only if this was the latest version of the chunk
+ synchronized (this.b) {
+ synchronized (this.saveMap) {
+ long k = chunkcoordintpair.asLong();
+ // This will not equal if a newer version is still pending - wait until newest is saved to remove
+ if (this.b.get(chunkcoordintpair) == chunk.compoundSupplier) {
+ this.b.remove(chunkcoordintpair);
+ if (this.saveMap.get(k) == chunk.compoundSupplier) {
+ this.saveMap.remove(k);
+ }
+ }
+ // Paper end
/*
NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream);
dataoutputstream.close();
@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
return true;
}
}
- } // CraftBukkit
+ // } // CraftBukkit // Paper
}
private ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) {
diff --git a/src/main/java/net/minecraft/server/FileIOThread.java b/src/main/java/net/minecraft/server/FileIOThread.java
index a3aba244af..97917551a4 100644
--- a/src/main/java/net/minecraft/server/FileIOThread.java

View file

@ -8,7 +8,7 @@ Vanilla will double add Spider Jockeys to the world, so ignore already added.
Also add debug if something else tries to, and abort before world gets bad state
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index 1dbcedbf94..8e14f8c56c 100644
index e831ea1429..d40d9d1173 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {

View file

@ -44,7 +44,7 @@ index fbebd4591c..b941676829 100644
public Chunk a(Object object) {
return this.a(((Long) object).longValue());
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 6b041f06e4..1a1daf36b7 100644
index d73034f329..b1e6901090 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
@ -77,12 +77,12 @@ index 6b041f06e4..1a1daf36b7 100644
this.asyncTaskHandler.postToMainThread(chunk::addEntities);
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
this.saveChunk(chunk, true); // Spigot
this.saveChunk(chunk, true); // Spigot
}
this.chunks.remove(chunk.chunkKey);
- this.lastChunk = null;
+ // this.lastChunk = null; // Paper
}
this.chunks.remove(chunk.chunkKey);
- this.lastChunk = null;
+ //this.lastChunk = null; // Paper
return true;
}
// CraftBukkit end
--

View file

@ -18,7 +18,7 @@ an invalid entity.
This should reduce log occurrences of dupe uuid messages.
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index ec94b9fe57..e6ede2cc25 100644
index 4f9be4b86d..f22532f071 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {

View file

@ -59,7 +59,7 @@ index bcdf4f91d8..c457d07110 100644
+ }
}
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index e6ede2cc25..93bc613958 100644
index f22532f071..7db075b731 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
@ -71,29 +71,40 @@ index e6ede2cc25..93bc613958 100644
+ private final File actualWorld;
+ private final boolean useAltWorld;
+
+ private synchronized void copyIfNeeded(int x, int z) {
+ private void copyIfNeeded(int x, int z) {
+ if (!useAltWorld) {
+ return;
+ }
+ if (RegionFileCache.hasRegionFile(this.actualWorld, x, z)) {
+ return;
+ }
+ File actual = RegionFileCache.getRegionFileName(this.actualWorld, x, z);
+ File template = RegionFileCache.getRegionFileName(this.templateWorld, x, z);
+ if (!actual.exists() && template.exists()) {
+ try {
+ //a.info("Copying" + template + " to " + actual);
+ java.nio.file.Files.copy(template.toPath(), actual.toPath(), java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
+ } catch (IOException e1) {
+ LogManager.getLogger().error("Error copying " + template + " to " + actual, e1);
+ MinecraftServer.getServer().safeShutdown();
+ org.spigotmc.SneakyThrow.sneaky(e1);
+ synchronized (RegionFileCache.class) {
+ if (RegionFileCache.hasRegionFile(this.actualWorld, x, z)) {
+ return;
+ }
+ File actual = RegionFileCache.getRegionFileName(this.actualWorld, x, z);
+ File template = RegionFileCache.getRegionFileName(this.templateWorld, x, z);
+ if (!actual.exists() && template.exists()) {
+ try {
+ //a.info("Copying" + template + " to " + actual);
+ java.nio.file.Files.copy(template.toPath(), actual.toPath(), java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
+ } catch (IOException e1) {
+ LogManager.getLogger().error("Error copying " + template + " to " + actual, e1);
+ MinecraftServer.getServer().safeShutdown();
+ org.spigotmc.SneakyThrow.sneaky(e1);
+ }
+ }
+ }
+ }
+
+ public boolean chunkExists(int x, int z) {
+ if (this.saveMap.containsKey(ChunkCoordIntPair.asLong(x, z))) {
+ return true;
+ }
+ copyIfNeeded(x, z);
+ return RegionFileCache.chunkExists(this.actualWorld, x, z);
+ }
+ // Paper end
public ChunkRegionLoader(File file, DataFixer datafixer) {
+ // Paper
+ // Paper start
+ this.actualWorld = file;
+ if (com.destroystokyo.paper.PaperConfig.useVersionedWorld) {
+ this.useAltWorld = true;
@ -129,25 +140,9 @@ index e6ede2cc25..93bc613958 100644
@Nullable
private NBTTagCompound a(DimensionManager dimensionmanager, @Nullable PersistentCollection persistentcollection, int i, int j, @Nullable GeneratorAccess generatoraccess) throws IOException {
+ copyIfNeeded(i, j); // Paper
NBTTagCompound nbttagcompound = SupplierUtils.getIfExists(this.b.get(new ChunkCoordIntPair(i, j))); // Spigot
NBTTagCompound nbttagcompound = SupplierUtils.getIfExists(this.saveMap.get(ChunkCoordIntPair.asLong(i, j))); // Spigot // Paper
if (nbttagcompound != null) {
@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
}
}
+ public boolean chunkExists(int x, int z) {
+ ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(x, z);
+ if (this.b.containsKey(chunkcoordintpair)) {
+ return true;
+ }
+ copyIfNeeded(x, z);
+ return RegionFileCache.chunkExists(this.actualWorld, x, z);
+ }
+
@Nullable
protected Object[] a(GeneratorAccess generatoraccess, int i, int j, NBTTagCompound nbttagcompound) { // CraftBukkit - return Chunk -> Object[]
if (nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8)) {
diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java
index 15666325ea..3501b87f75 100644
--- a/src/main/java/net/minecraft/server/RegionFileCache.java

View file

@ -348,7 +348,7 @@ index e3d1761b49..fbebd4591c 100644
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 9e805c5d22..0034956af9 100644
index 3045d6d063..68212aa26e 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -0,0 +0,0 @@ public class ChunkProviderServer implements IChunkProvider {
@ -389,7 +389,7 @@ index 9e805c5d22..0034956af9 100644
this.chunkLoader.saveChunk(this.world, ichunkaccess, unloaded); // Spigot
} catch (IOException ioexception) {
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index 664b167bb2..2e9bd0949a 100644
index df07b2b889..f969c036f3 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -0,0 +0,0 @@

@ -1 +1 @@
Subproject commit 022b8c350a223f092e4fdbdce8ffb682f412fb29
Subproject commit 7033f180e0f1f300f6e85beda70cb396200a219a

@ -1 +1 @@
Subproject commit 145a37ae8c1032ac0dd0ea0a9f93c235ab2a6423
Subproject commit 500ff5d408d9ce45b6a0819777fc7ad4779f32e4