diff options
author | MiniDigger <[email protected]> | 2019-12-13 14:46:45 +0100 |
---|---|---|
committer | Shane Freeder <[email protected]> | 2019-12-13 13:46:45 +0000 |
commit | bd93836d4c9905eee8a5b78468ccb25957c32aa6 (patch) | |
tree | 59bcbf0e5bfa638cf54154e2eb9f8f3d04b7fd1f /removed | |
parent | 4565495711272d986c490a29f618cb6a321653bc (diff) | |
download | Paper-bd93836d4c9905eee8a5b78468ccb25957c32aa6.tar.gz Paper-bd93836d4c9905eee8a5b78468ccb25957c32aa6.zip |
Nuke IOWorker, make stuff compile (#2733)
* remove removed patch cause its not removed anymore
* Nuke IOWorker, oh, and also make it compile
* synchronize writes properly
* Remove note about IOWorker
Diffstat (limited to 'removed')
-rw-r--r-- | removed/1.15/0393-Fix-World-isChunkGenerated-calls.patch | 379 |
1 files changed, 0 insertions, 379 deletions
diff --git a/removed/1.15/0393-Fix-World-isChunkGenerated-calls.patch b/removed/1.15/0393-Fix-World-isChunkGenerated-calls.patch deleted file mode 100644 index 5877458fa3..0000000000 --- a/removed/1.15/0393-Fix-World-isChunkGenerated-calls.patch +++ /dev/null @@ -1,379 +0,0 @@ -From 14f4011c2f16754e3f39826237f4822c3b6446b1 Mon Sep 17 00:00:00 2001 -From: Spottedleaf <[email protected]> -Date: Sat, 15 Jun 2019 08:54:33 -0700 -Subject: [PATCH] Fix World#isChunkGenerated calls - -Optimize World#loadChunk() too -This patch also adds a chunk status cache on region files (note that -its only purpose is to cache the status on DISK) - -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 8689e0f9f..56761afdf 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -28,7 +28,7 @@ public class ChunkProviderServer extends IChunkProvider { - private final WorldServer world; - private final Thread serverThread; - private final LightEngineThreaded lightEngine; -- private final ChunkProviderServer.a serverThreadQueue; -+ public final ChunkProviderServer.a serverThreadQueue; // Paper private -> public - public final PlayerChunkMap playerChunkMap; - private final WorldPersistentData worldPersistentData; - private long lastTickTime; -@@ -109,6 +109,21 @@ public class ChunkProviderServer extends IChunkProvider { - - return playerChunk.getFullChunk(); - } -+ -+ @Nullable -+ public IChunkAccess getChunkAtImmediately(int x, int z) { -+ long k = ChunkCoordIntPair.pair(x, z); -+ -+ // Note: Bypass cache to make this MT-Safe -+ -+ PlayerChunk playerChunk = this.getChunk(k); -+ if (playerChunk == null) { -+ return null; -+ } -+ -+ return playerChunk.getAvailableChunkNow(); -+ -+ } - // Paper end - - @Nullable -diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index e778c2e85..73f93e494 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -410,6 +410,17 @@ public class ChunkRegionLoader { - return nbttagcompound; - } - -+ // Paper start -+ public static ChunkStatus getStatus(NBTTagCompound compound) { -+ if (compound == null) { -+ return null; -+ } -+ -+ // Note: Copied from below -+ return ChunkStatus.getStatus(compound.getCompound("Level").getString("Status")); -+ } -+ // Paper end -+ - public static ChunkStatus.Type a(@Nullable NBTTagCompound nbttagcompound) { - if (nbttagcompound != null) { - ChunkStatus chunkstatus = ChunkStatus.a(nbttagcompound.getCompound("Level").getString("Status")); -diff --git a/src/main/java/net/minecraft/server/ChunkStatus.java b/src/main/java/net/minecraft/server/ChunkStatus.java -index dd1822d6f..e324989b4 100644 ---- a/src/main/java/net/minecraft/server/ChunkStatus.java -+++ b/src/main/java/net/minecraft/server/ChunkStatus.java -@@ -176,6 +176,7 @@ public class ChunkStatus { - return this.s; - } - -+ public ChunkStatus getPreviousStatus() { return this.e(); } // Paper - OBFHELPER - public ChunkStatus e() { - return this.u; - } -@@ -196,6 +197,17 @@ public class ChunkStatus { - return this.y; - } - -+ // Paper start -+ public static ChunkStatus getStatus(String name) { -+ try { -+ // We need this otherwise we return EMPTY for invalid names -+ MinecraftKey key = new MinecraftKey(name); -+ return IRegistry.CHUNK_STATUS.getOptional(key).orElse(null); -+ } catch (Exception ex) { -+ return null; // invalid name -+ } -+ } -+ // Paper end - public static ChunkStatus a(String s) { - return (ChunkStatus) IRegistry.CHUNK_STATUS.get(MinecraftKey.a(s)); - } -diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java -index 14a176d61..98590e233 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunk.java -+++ b/src/main/java/net/minecraft/server/PlayerChunk.java -@@ -70,6 +70,19 @@ public class PlayerChunk { - Either<IChunkAccess, PlayerChunk.Failure> either = (Either<IChunkAccess, PlayerChunk.Failure>) statusFuture.getNow(null); - return either == null ? null : (Chunk) either.left().orElse(null); - } -+ -+ public IChunkAccess getAvailableChunkNow() { -+ // TODO can we just getStatusFuture(EMPTY)? -+ for (ChunkStatus curr = ChunkStatus.FULL, next = curr.getPreviousStatus(); curr != next; curr = next, next = next.getPreviousStatus()) { -+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> future = this.getStatusFutureUnchecked(curr); -+ Either<IChunkAccess, PlayerChunk.Failure> either = future.getNow(null); -+ if (either == null || !either.left().isPresent()) { -+ continue; -+ } -+ return either.left().get(); -+ } -+ return null; -+ } - // Paper end - - public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFutureUnchecked(ChunkStatus chunkstatus) { -diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java -index 6f1e48ba4..eb49e9021 100644 ---- a/src/main/java/net/minecraft/server/PlayerChunkMap.java -+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java -@@ -897,11 +897,61 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { - } - - @Nullable -- private NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { -+ public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public - NBTTagCompound nbttagcompound = this.read(chunkcoordintpair); - -- return nbttagcompound == null ? null : this.getChunkData(this.world.getWorldProvider().getDimensionManager(), this.m, nbttagcompound, chunkcoordintpair, world); // CraftBukkit -+ // Paper start - Cache chunk status on disk -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ nbttagcompound = this.getChunkData(this.world.getWorldProvider().getDimensionManager(), this.m, nbttagcompound, chunkcoordintpair, world); // CraftBukkit -+ if (nbttagcompound == null) { -+ return null; -+ } -+ -+ this.updateChunkStatusOnDisk(chunkcoordintpair, nbttagcompound); -+ -+ return nbttagcompound; -+ // Paper end -+ } -+ -+ // Paper start - chunk status cache "api" -+ public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) { -+ RegionFile regionFile = this.getRegionFileIfLoaded(chunkPos); -+ -+ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } -+ -+ public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException { -+ RegionFile regionFile = this.getRegionFile(chunkPos, false); -+ -+ if (!regionFile.chunkExists(chunkPos)) { -+ return null; -+ } -+ -+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ -+ if (status != null) { -+ return status; -+ } -+ -+ this.readChunkData(chunkPos); -+ -+ return regionFile.getStatusIfCached(chunkPos.x, chunkPos.z); -+ } -+ -+ public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException { -+ RegionFile regionFile = this.getRegionFile(chunkPos, false); -+ -+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound)); -+ } -+ -+ public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) { -+ PlayerChunk chunkHolder = this.pendingUnload.get(ChunkCoordIntPair.pair(chunkX, chunkZ)); -+ return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow(); - } -+ // Paper end - - boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) { - // Spigot start -diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java -index ccc3d6c7a..b487e8060 100644 ---- a/src/main/java/net/minecraft/server/RegionFile.java -+++ b/src/main/java/net/minecraft/server/RegionFile.java -@@ -31,6 +31,30 @@ public class RegionFile implements AutoCloseable { - private final int[] d = new int[1024]; private final int[] timestamps = d; // Paper - OBFHELPER - private final List<Boolean> e; // PAIL freeSectors - -+ // Paper start - Cache chunk status -+ private final ChunkStatus[] statuses = new ChunkStatus[32 * 32]; -+ -+ private boolean closed; -+ -+ // invoked on write/read -+ public void setStatus(int x, int z, ChunkStatus status) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ this.statuses[this.getChunkLocation(new ChunkCoordIntPair(x, z))] = status; -+ } -+ -+ public ChunkStatus getStatusIfCached(int x, int z) { -+ if (this.closed) { -+ // We've used an invalid region file. -+ throw new IllegalStateException("RegionFile is closed"); -+ } -+ final int location = this.getChunkLocation(new ChunkCoordIntPair(x, z)); -+ return this.statuses[location]; -+ } -+ // Paper end -+ - public RegionFile(File file) throws IOException { - this.b = new RandomAccessFile(file, "rw"); - this.file = file; // Spigot // Paper - We need this earlier -@@ -291,6 +315,7 @@ public class RegionFile implements AutoCloseable { - return this.c[this.f(chunkcoordintpair)]; - } - -+ public final boolean chunkExists(ChunkCoordIntPair chunkPos) { return this.d(chunkPos); } // Paper - OBFHELPER - public boolean d(ChunkCoordIntPair chunkcoordintpair) { - return this.getOffset(chunkcoordintpair) != 0; - } -@@ -304,6 +329,7 @@ public class RegionFile implements AutoCloseable { - this.c[j] = i; // Spigot - move this to after the write - } - -+ private final int getChunkLocation(ChunkCoordIntPair chunkcoordintpair) { return this.f(chunkcoordintpair); } // Paper - OBFHELPER - private int f(ChunkCoordIntPair chunkcoordintpair) { - return chunkcoordintpair.j() + chunkcoordintpair.k() * 32; - } -@@ -318,6 +344,7 @@ public class RegionFile implements AutoCloseable { - } - - public void close() throws IOException { -+ this.closed = true; // Paper - this.b.close(); - } - -diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java -index 6f34d8aea..d2b328945 100644 ---- a/src/main/java/net/minecraft/server/RegionFileCache.java -+++ b/src/main/java/net/minecraft/server/RegionFileCache.java -@@ -47,6 +47,12 @@ public abstract class RegionFileCache implements AutoCloseable { - // Paper start - } - -+ // Paper start -+ public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { -+ return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); -+ } -+ // Paper end -+ - public RegionFile getRegionFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { return this.a(chunkcoordintpair, existingOnly); } // Paper - OBFHELPER - private RegionFile a(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit - long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); -@@ -110,6 +116,7 @@ public abstract class RegionFileCache implements AutoCloseable { - try { - NBTCompressedStreamTools.writeNBT(nbttagcompound, out); - out.close(); -+ regionfile.setStatus(chunk.x, chunk.z, ChunkRegionLoader.getStatus(nbttagcompound)); // Paper - cache status on disk - regionfile.setOversized(chunkX, chunkZ, false); - } catch (RegionFile.ChunkTooLargeException ignored) { - printOversizedLog("ChunkTooLarge! Someone is trying to duplicate.", regionfile.file, chunkX, chunkZ); -@@ -127,6 +134,7 @@ public abstract class RegionFileCache implements AutoCloseable { - if (SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD) { - resetFilterThresholds(); - } -+ regionfile.setStatus(chunk.x, chunk.z, ChunkRegionLoader.getStatus(nbttagcompound)); // Paper - cache status on disk - } catch (RegionFile.ChunkTooLargeException e) { - printOversizedLog("ChunkTooLarge even after reduction. Trying in overzealous mode.", regionfile.file, chunkX, chunkZ); - // Eek, major fail. We have retry logic, so reduce threshholds and fall back -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index e42bd2638..2227de3bf 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -18,6 +18,7 @@ import java.util.Objects; - import java.util.Random; - import java.util.Set; - import java.util.UUID; -+import java.util.concurrent.CompletableFuture; - import java.util.function.Predicate; - import java.util.stream.Collectors; - import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -@@ -408,8 +409,22 @@ public class CraftWorld implements World { - - @Override - public boolean isChunkGenerated(int x, int z) { -+ // Paper start - Fix this method -+ if (!Bukkit.isPrimaryThread()) { -+ return CompletableFuture.supplyAsync(() -> { -+ return CraftWorld.this.isChunkGenerated(x, z); -+ }, world.getChunkProvider().serverThreadQueue).join(); -+ } -+ IChunkAccess chunk = world.getChunkProvider().getChunkAtImmediately(x, z); -+ if (chunk == null) { -+ chunk = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); -+ } -+ if (chunk != null) { -+ return chunk instanceof ProtoChunkExtension || chunk instanceof net.minecraft.server.Chunk; -+ } - try { -- return world.getChunkProvider().getChunkAtIfCachedImmediately(x, z) != null || world.getChunkProvider().playerChunkMap.chunkExists(new ChunkCoordIntPair(x, z)); // Paper -+ return world.getChunkProvider().playerChunkMap.getChunkStatusOnDisk(new ChunkCoordIntPair(x, z)) == ChunkStatus.FULL; -+ // Paper end - } catch (IOException ex) { - throw new RuntimeException(ex); - } -@@ -521,20 +536,49 @@ public class CraftWorld implements World { - @Override - public boolean loadChunk(int x, int z, boolean generate) { - org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot -- IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate || isChunkGenerated(x, z) ? ChunkStatus.FULL : ChunkStatus.EMPTY, true); // Paper -+ // Paper start - Optimize this method -+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z); - -- // If generate = false, but the chunk already exists, we will get this back. -- if (chunk instanceof ProtoChunkExtension) { -- // We then cycle through again to get the full chunk immediately, rather than after the ticket addition -- chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); -- } -+ if (!generate) { - -- if (chunk instanceof net.minecraft.server.Chunk) { -- world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE); -- return true; -+ IChunkAccess immediate = world.getChunkProvider().getChunkAtImmediately(x, z); -+ if (immediate == null) { -+ immediate = world.getChunkProvider().playerChunkMap.getUnloadingChunk(x, z); -+ } -+ if (immediate != null) { -+ if (!(immediate instanceof ProtoChunkExtension) && !(immediate instanceof net.minecraft.server.Chunk)) { -+ return false; // not full status -+ } -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkAt(x, z); // make sure we're at ticket level 32 or lower -+ return true; -+ } -+ -+ net.minecraft.server.RegionFile file; -+ try { -+ file = world.getChunkProvider().playerChunkMap.getRegionFile(chunkPos, false); -+ } catch (IOException ex) { -+ throw new RuntimeException(ex); -+ } -+ -+ ChunkStatus status = file.getStatusIfCached(x, z); -+ if (!file.chunkExists(chunkPos) || (status != null && status != ChunkStatus.FULL)) { -+ return false; -+ } -+ -+ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); -+ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.server.Chunk)) { -+ return false; -+ } -+ -+ // fall through to load -+ // we do this so we do not re-read the chunk data on disk - } - -- return false; -+ world.getChunkProvider().addTicket(TicketType.PLUGIN, chunkPos, 1, Unit.INSTANCE); -+ world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); -+ return true; -+ // Paper end - } - - @Override --- -2.24.0 - |