mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-26 12:36:07 +01:00
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
This commit is contained in:
parent
4565495711
commit
bd93836d4c
@ -1,11 +1,8 @@
|
|||||||
From 867219c4f28a3b9b5ea9dfe010569d45b620f1e1 Mon Sep 17 00:00:00 2001
|
From 783755ca4f609df8e98ca724b6efa576e29bd117 Mon Sep 17 00:00:00 2001
|
||||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||||
Date: Sat, 13 Jul 2019 09:23:10 -0700
|
Date: Sat, 13 Jul 2019 09:23:10 -0700
|
||||||
Subject: [PATCH] Asynchronous chunk IO and loading
|
Subject: [PATCH] Asynchronous chunk IO and loading
|
||||||
|
|
||||||
THIS PATCH NEEDS RE-EVALUTING AND WILL LIKELY NOT WORK AS-IS RIGHT THIS SECOND
|
|
||||||
- Pending investigation of IOWorker changes (Will do this when not too tired)
|
|
||||||
|
|
||||||
This patch re-adds a file IO thread as well as shoving de-serializing
|
This patch re-adds a file IO thread as well as shoving de-serializing
|
||||||
chunk NBT data onto worker threads. This patch also will shove
|
chunk NBT data onto worker threads. This patch also will shove
|
||||||
chunk data serialization onto the same worker threads when the chunk
|
chunk data serialization onto the same worker threads when the chunk
|
||||||
@ -2826,10 +2823,10 @@ index 721021791..f7156acb8 100644
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
diff --git a/src/main/java/net/minecraft/server/IChunkLoader.java b/src/main/java/net/minecraft/server/IChunkLoader.java
|
diff --git a/src/main/java/net/minecraft/server/IChunkLoader.java b/src/main/java/net/minecraft/server/IChunkLoader.java
|
||||||
index 2f95174fc..1025e01d5 100644
|
index 2f95174fc..134c76065 100644
|
||||||
--- a/src/main/java/net/minecraft/server/IChunkLoader.java
|
--- a/src/main/java/net/minecraft/server/IChunkLoader.java
|
||||||
+++ b/src/main/java/net/minecraft/server/IChunkLoader.java
|
+++ b/src/main/java/net/minecraft/server/IChunkLoader.java
|
||||||
@@ -3,6 +3,10 @@ package net.minecraft.server;
|
@@ -3,37 +3,49 @@ package net.minecraft.server;
|
||||||
import com.mojang.datafixers.DataFixer;
|
import com.mojang.datafixers.DataFixer;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -2840,8 +2837,11 @@ index 2f95174fc..1025e01d5 100644
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@@ -11,7 +15,9 @@ public class IChunkLoader implements AutoCloseable {
|
-public class IChunkLoader implements AutoCloseable {
|
||||||
private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER
|
+public class IChunkLoader extends RegionFileCache implements AutoCloseable {
|
||||||
|
|
||||||
|
- private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER
|
||||||
|
+// private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER - nuke IOWorker
|
||||||
protected final DataFixer b;
|
protected final DataFixer b;
|
||||||
@Nullable
|
@Nullable
|
||||||
- private PersistentStructureLegacy c;
|
- private PersistentStructureLegacy c;
|
||||||
@ -2850,8 +2850,13 @@ index 2f95174fc..1025e01d5 100644
|
|||||||
+ private final Object persistentDataLock = new Object(); // Paper
|
+ private final Object persistentDataLock = new Object(); // Paper
|
||||||
|
|
||||||
public IChunkLoader(File file, DataFixer datafixer) {
|
public IChunkLoader(File file, DataFixer datafixer) {
|
||||||
|
+ super(file);
|
||||||
this.b = datafixer;
|
this.b = datafixer;
|
||||||
@@ -22,18 +28,23 @@ public class IChunkLoader implements AutoCloseable {
|
- this.a = new IOWorker(new RegionFileCache(file), "chunk");
|
||||||
|
+// this.a = new IOWorker(new RegionFileCache(file), "chunk"); // Paper - nuke IOWorker
|
||||||
|
}
|
||||||
|
|
||||||
|
// CraftBukkit start
|
||||||
private boolean check(ChunkProviderServer cps, int x, int z) throws IOException {
|
private boolean check(ChunkProviderServer cps, int x, int z) throws IOException {
|
||||||
ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z);
|
ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z);
|
||||||
if (cps != null) {
|
if (cps != null) {
|
||||||
@ -2883,7 +2888,7 @@ index 2f95174fc..1025e01d5 100644
|
|||||||
|
|
||||||
ChunkStatus status = ChunkStatus.a(level.getString("Status"));
|
ChunkStatus status = ChunkStatus.a(level.getString("Status"));
|
||||||
if (status != null && status.b(ChunkStatus.FEATURES)) {
|
if (status != null && status.b(ChunkStatus.FEATURES)) {
|
||||||
@@ -64,11 +75,13 @@ public class IChunkLoader implements AutoCloseable {
|
@@ -64,11 +76,13 @@ public class IChunkLoader implements AutoCloseable {
|
||||||
if (i < 1493) {
|
if (i < 1493) {
|
||||||
nbttagcompound = GameProfileSerializer.a(this.b, DataFixTypes.CHUNK, nbttagcompound, i, 1493);
|
nbttagcompound = GameProfileSerializer.a(this.b, DataFixTypes.CHUNK, nbttagcompound, i, 1493);
|
||||||
if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) {
|
if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) {
|
||||||
@ -2897,14 +2902,26 @@ index 2f95174fc..1025e01d5 100644
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +102,12 @@ public class IChunkLoader implements AutoCloseable {
|
@@ -84,24 +98,28 @@ public class IChunkLoader implements AutoCloseable {
|
||||||
return this.a.a(chunkcoordintpair);
|
return nbttagcompound.hasKeyOfType("DataVersion", 99) ? nbttagcompound.getInt("DataVersion") : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- @Nullable
|
||||||
|
- public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException {
|
||||||
|
- return this.a.a(chunkcoordintpair);
|
||||||
|
- }
|
||||||
|
-
|
||||||
- public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) {
|
- public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) {
|
||||||
|
- this.a.a(chunkcoordintpair, nbttagcompound);
|
||||||
|
+// Paper start - nuke IOWorker
|
||||||
|
+// @Nullable
|
||||||
|
+// public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException {
|
||||||
|
+// return this.a.a(chunkcoordintpair);
|
||||||
|
+// }
|
||||||
|
+//
|
||||||
+ public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER
|
+ public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER
|
||||||
+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety)
|
+ public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety)
|
||||||
this.a.a(chunkcoordintpair, nbttagcompound);
|
+ super.write(chunkcoordintpair, nbttagcompound);
|
||||||
if (this.c != null) {
|
if (this.c != null) {
|
||||||
- this.c.a(chunkcoordintpair.pair());
|
- this.c.a(chunkcoordintpair.pair());
|
||||||
+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading
|
+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading
|
||||||
@ -2912,6 +2929,24 @@ index 2f95174fc..1025e01d5 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
-
|
||||||
|
- public void i() {
|
||||||
|
- this.a.a().join();
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- public void close() throws IOException {
|
||||||
|
- this.a.close();
|
||||||
|
- }
|
||||||
|
+//
|
||||||
|
+// public void i() {
|
||||||
|
+// this.a.a().join();
|
||||||
|
+// }
|
||||||
|
+//
|
||||||
|
+// public void close() throws IOException {
|
||||||
|
+// this.a.close();
|
||||||
|
+// }
|
||||||
|
+// Paper end
|
||||||
|
}
|
||||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
||||||
index 25a87c2d3..c02c53b50 100644
|
index 25a87c2d3..c02c53b50 100644
|
||||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||||
@ -2939,7 +2974,7 @@ index 8e15aba7f..edb3a6035 100644
|
|||||||
|
|
||||||
public String getServerIp() {
|
public String getServerIp() {
|
||||||
diff --git a/src/main/java/net/minecraft/server/NextTickListEntry.java b/src/main/java/net/minecraft/server/NextTickListEntry.java
|
diff --git a/src/main/java/net/minecraft/server/NextTickListEntry.java b/src/main/java/net/minecraft/server/NextTickListEntry.java
|
||||||
index 8471920b8..04429a274 100644
|
index e9c405fb5..33cfeabde 100644
|
||||||
--- a/src/main/java/net/minecraft/server/NextTickListEntry.java
|
--- a/src/main/java/net/minecraft/server/NextTickListEntry.java
|
||||||
+++ b/src/main/java/net/minecraft/server/NextTickListEntry.java
|
+++ b/src/main/java/net/minecraft/server/NextTickListEntry.java
|
||||||
@@ -4,7 +4,7 @@ import java.util.Comparator;
|
@@ -4,7 +4,7 @@ import java.util.Comparator;
|
||||||
@ -2999,7 +3034,7 @@ index 7a1578afa..0fb9c1e44 100644
|
|||||||
completablefuture = (CompletableFuture) this.statusFutures.get(i);
|
completablefuture = (CompletableFuture) this.statusFutures.get(i);
|
||||||
if (completablefuture != null) {
|
if (completablefuture != null) {
|
||||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||||
index 6a54ccb86..66bd402e9 100644
|
index 6a54ccb86..fce37d0d6 100644
|
||||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||||
@@ -63,7 +63,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
@@ -63,7 +63,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||||
@ -3064,15 +3099,16 @@ index 6a54ccb86..66bd402e9 100644
|
|||||||
mutableboolean.setTrue();
|
mutableboolean.setTrue();
|
||||||
});
|
});
|
||||||
} while (mutableboolean.isTrue());
|
} while (mutableboolean.isTrue());
|
||||||
@@ -354,6 +355,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
@@ -354,18 +355,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||||
this.b(() -> {
|
this.b(() -> {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
- this.i();
|
||||||
+ this.world.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour
|
+ this.world.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour
|
||||||
this.i();
|
+// this.i(); // Paper - nuke IOWorker
|
||||||
PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName());
|
PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName());
|
||||||
} else {
|
} else {
|
||||||
@@ -361,11 +363,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> {
|
||||||
IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error
|
IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error
|
||||||
|
|
||||||
if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) {
|
if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) {
|
||||||
@ -3392,7 +3428,14 @@ index 6a54ccb86..66bd402e9 100644
|
|||||||
@Nullable
|
@Nullable
|
||||||
public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public
|
public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public
|
||||||
NBTTagCompound nbttagcompound = this.read(chunkcoordintpair);
|
NBTTagCompound nbttagcompound = this.read(chunkcoordintpair);
|
||||||
@@ -927,27 +1087,47 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
@@ -921,33 +1081,53 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||||
|
|
||||||
|
// Paper start - chunk status cache "api"
|
||||||
|
public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) {
|
||||||
|
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos);
|
||||||
|
+ RegionFile regionFile = this.getRegionFileIfLoaded(chunkPos);
|
||||||
|
|
||||||
|
return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException {
|
public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException {
|
||||||
@ -3414,7 +3457,7 @@ index 6a54ccb86..66bd402e9 100644
|
|||||||
}
|
}
|
||||||
+ // Paper end
|
+ // Paper end
|
||||||
+ synchronized (this) { // Paper - async io
|
+ synchronized (this) { // Paper - async io
|
||||||
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
|
+ RegionFile regionFile = this.getFile(chunkPos, false);
|
||||||
+
|
+
|
||||||
+ if (!regionFile.chunkExists(chunkPos)) {
|
+ if (!regionFile.chunkExists(chunkPos)) {
|
||||||
+ return null;
|
+ return null;
|
||||||
@ -3442,7 +3485,7 @@ index 6a54ccb86..66bd402e9 100644
|
|||||||
public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException {
|
public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException {
|
||||||
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
|
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
|
||||||
+ synchronized (this) {
|
+ synchronized (this) {
|
||||||
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
|
+ RegionFile regionFile = this.getFile(chunkPos, false);
|
||||||
|
|
||||||
- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
|
- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
|
||||||
+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
|
+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
|
||||||
@ -3478,7 +3521,7 @@ index 6a54ccb86..66bd402e9 100644
|
|||||||
+ synchronized (world.getChunkProvider().playerChunkMap) {
|
+ synchronized (world.getChunkProvider().playerChunkMap) {
|
||||||
+ net.minecraft.server.RegionFile file;
|
+ net.minecraft.server.RegionFile file;
|
||||||
+ try {
|
+ try {
|
||||||
+ file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
|
+ file = world.getChunkProvider().playerChunkMap.getFile(chunkPos, false);
|
||||||
+ } catch (IOException ex) {
|
+ } catch (IOException ex) {
|
||||||
+ throw new RuntimeException(ex);
|
+ throw new RuntimeException(ex);
|
||||||
+ }
|
+ }
|
||||||
@ -3499,9 +3542,18 @@ index 6a54ccb86..66bd402e9 100644
|
|||||||
return this.m;
|
return this.m;
|
||||||
}
|
}
|
||||||
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
|
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
|
||||||
index 7eb87c517..551e91869 100644
|
index 7eb87c517..b252684c2 100644
|
||||||
--- a/src/main/java/net/minecraft/server/RegionFile.java
|
--- a/src/main/java/net/minecraft/server/RegionFile.java
|
||||||
+++ b/src/main/java/net/minecraft/server/RegionFile.java
|
+++ b/src/main/java/net/minecraft/server/RegionFile.java
|
||||||
|
@@ -218,7 +218,7 @@ public class RegionFile implements AutoCloseable {
|
||||||
|
return (i + 4096 - 1) / 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
- public boolean b(ChunkCoordIntPair chunkcoordintpair) {
|
||||||
|
+ public synchronized boolean b(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronized
|
||||||
|
int i = this.getOffset(chunkcoordintpair);
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
@@ -373,7 +373,7 @@ public class RegionFile implements AutoCloseable {
|
@@ -373,7 +373,7 @@ public class RegionFile implements AutoCloseable {
|
||||||
return chunkcoordintpair.j() + chunkcoordintpair.k() * 32;
|
return chunkcoordintpair.j() + chunkcoordintpair.k() * 32;
|
||||||
}
|
}
|
||||||
@ -3512,10 +3564,19 @@ index 7eb87c517..551e91869 100644
|
|||||||
try {
|
try {
|
||||||
this.c();
|
this.c();
|
||||||
diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java
|
diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java
|
||||||
index 1a6be7c6d..9a0fdec47 100644
|
index 1a6be7c6d..386f47dc8 100644
|
||||||
--- a/src/main/java/net/minecraft/server/RegionFileCache.java
|
--- a/src/main/java/net/minecraft/server/RegionFileCache.java
|
||||||
+++ b/src/main/java/net/minecraft/server/RegionFileCache.java
|
+++ b/src/main/java/net/minecraft/server/RegionFileCache.java
|
||||||
@@ -20,7 +20,7 @@ public final class RegionFileCache implements AutoCloseable {
|
@@ -9,7 +9,7 @@ import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
-public final class RegionFileCache implements AutoCloseable {
|
||||||
|
+public class RegionFileCache implements AutoCloseable { // Paper - no final
|
||||||
|
|
||||||
|
public final Long2ObjectLinkedOpenHashMap<RegionFile> cache = new Long2ObjectLinkedOpenHashMap();
|
||||||
|
private final File b;
|
||||||
|
@@ -20,12 +20,12 @@ public final class RegionFileCache implements AutoCloseable {
|
||||||
|
|
||||||
|
|
||||||
// Paper start
|
// Paper start
|
||||||
@ -3524,6 +3585,21 @@ index 1a6be7c6d..9a0fdec47 100644
|
|||||||
return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()));
|
return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Paper end
|
||||||
|
- public RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public
|
||||||
|
+ public synchronized RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - private > public, synchronize
|
||||||
|
long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
|
||||||
|
RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i);
|
||||||
|
|
||||||
|
@@ -126,7 +126,7 @@ public final class RegionFileCache implements AutoCloseable {
|
||||||
|
// Paper end
|
||||||
|
}
|
||||||
|
|
||||||
|
- public void close() throws IOException {
|
||||||
|
+ public synchronized void close() throws IOException { // Paper -> synchronized
|
||||||
|
ObjectIterator objectiterator = this.cache.values().iterator();
|
||||||
|
|
||||||
|
while (objectiterator.hasNext()) {
|
||||||
@@ -138,7 +138,7 @@ public final class RegionFileCache implements AutoCloseable {
|
@@ -138,7 +138,7 @@ public final class RegionFileCache implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3534,19 +3610,35 @@ index 1a6be7c6d..9a0fdec47 100644
|
|||||||
|
|
||||||
return regionfile != null ? regionfile.chunkExists(pos) : false;
|
return regionfile != null ? regionfile.chunkExists(pos) : false;
|
||||||
diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java
|
diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java
|
||||||
index db9f0196b..e7ea04861 100644
|
index db9f0196b..a6d8ef5eb 100644
|
||||||
--- a/src/main/java/net/minecraft/server/RegionFileSection.java
|
--- a/src/main/java/net/minecraft/server/RegionFileSection.java
|
||||||
+++ b/src/main/java/net/minecraft/server/RegionFileSection.java
|
+++ b/src/main/java/net/minecraft/server/RegionFileSection.java
|
||||||
@@ -25,7 +25,7 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
@@ -20,28 +20,29 @@ import javax.annotation.Nullable;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
-public class RegionFileSection<R extends MinecraftSerializable> implements AutoCloseable {
|
||||||
|
+public class RegionFileSection<R extends MinecraftSerializable> extends RegionFileCache implements AutoCloseable { // Paper - nuke IOWorker
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger();
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
private final IOWorker b;
|
- private final IOWorker b;
|
||||||
|
+// private final IOWorker b;
|
||||||
private final Long2ObjectMap<Optional<R>> c = new Long2ObjectOpenHashMap();
|
private final Long2ObjectMap<Optional<R>> c = new Long2ObjectOpenHashMap();
|
||||||
- private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet();
|
- private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet();
|
||||||
+ protected final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> protected
|
+ protected final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> protected
|
||||||
private final BiFunction<Runnable, Dynamic<?>, R> e;
|
private final BiFunction<Runnable, Dynamic<?>, R> e;
|
||||||
private final Function<Runnable, R> f;
|
private final Function<Runnable, R> f;
|
||||||
private final DataFixer g;
|
private final DataFixer g;
|
||||||
@@ -40,8 +40,8 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
private final DataFixTypes h;
|
||||||
|
|
||||||
|
public RegionFileSection(File file, BiFunction<Runnable, Dynamic<?>, R> bifunction, Function<Runnable, R> function, DataFixer datafixer, DataFixTypes datafixtypes) {
|
||||||
|
+ super(file); // Paper - nuke IOWorker
|
||||||
|
this.e = bifunction;
|
||||||
|
this.f = function;
|
||||||
|
this.g = datafixer;
|
||||||
|
this.h = datafixtypes;
|
||||||
|
- this.b = new IOWorker(new RegionFileCache(file), file.getName());
|
||||||
|
+// this.b = new IOWorker(new RegionFileCache(file), file.getName()); // Paper - nuke IOWorker
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void a(BooleanSupplier booleansupplier) {
|
protected void a(BooleanSupplier booleansupplier) {
|
||||||
@ -3557,7 +3649,7 @@ index db9f0196b..e7ea04861 100644
|
|||||||
|
|
||||||
this.d(chunkcoordintpair);
|
this.d(chunkcoordintpair);
|
||||||
}
|
}
|
||||||
@@ -95,7 +95,12 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
@@ -95,13 +96,18 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
||||||
}
|
}
|
||||||
|
|
||||||
private void b(ChunkCoordIntPair chunkcoordintpair) {
|
private void b(ChunkCoordIntPair chunkcoordintpair) {
|
||||||
@ -3571,7 +3663,14 @@ index db9f0196b..e7ea04861 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -143,7 +148,7 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
private NBTTagCompound c(ChunkCoordIntPair chunkcoordintpair) {
|
||||||
|
try {
|
||||||
|
- return this.b.a(chunkcoordintpair);
|
||||||
|
+ return this.read(chunkcoordintpair); // Paper - nuke IOWorker
|
||||||
|
} catch (IOException ioexception) {
|
||||||
|
RegionFileSection.LOGGER.error("Error reading chunk {} data from disk", chunkcoordintpair, ioexception);
|
||||||
|
return null;
|
||||||
|
@@ -143,17 +149,31 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
||||||
}
|
}
|
||||||
|
|
||||||
private void d(ChunkCoordIntPair chunkcoordintpair) {
|
private void d(ChunkCoordIntPair chunkcoordintpair) {
|
||||||
@ -3580,7 +3679,11 @@ index db9f0196b..e7ea04861 100644
|
|||||||
NBTBase nbtbase = (NBTBase) dynamic.getValue();
|
NBTBase nbtbase = (NBTBase) dynamic.getValue();
|
||||||
|
|
||||||
if (nbtbase instanceof NBTTagCompound) {
|
if (nbtbase instanceof NBTTagCompound) {
|
||||||
@@ -154,6 +159,20 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
- this.b.a(chunkcoordintpair, (NBTTagCompound) nbtbase);
|
||||||
|
+ try { this.write(chunkcoordintpair, (NBTTagCompound) nbtbase); } catch (IOException ioexception) { RegionFileSection.LOGGER.error("Error writing data to disk", ioexception); } // Paper - nuke IOWorker // TODO make this write async
|
||||||
|
} else {
|
||||||
|
RegionFileSection.LOGGER.error("Expected compound tag, got {}", nbtbase);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3601,7 +3704,7 @@ index db9f0196b..e7ea04861 100644
|
|||||||
private <T> Dynamic<T> a(ChunkCoordIntPair chunkcoordintpair, DynamicOps<T> dynamicops) {
|
private <T> Dynamic<T> a(ChunkCoordIntPair chunkcoordintpair, DynamicOps<T> dynamicops) {
|
||||||
Map<T, T> map = Maps.newHashMap();
|
Map<T, T> map = Maps.newHashMap();
|
||||||
|
|
||||||
@@ -190,9 +209,9 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
@@ -190,9 +210,9 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
||||||
public void a(ChunkCoordIntPair chunkcoordintpair) {
|
public void a(ChunkCoordIntPair chunkcoordintpair) {
|
||||||
if (!this.d.isEmpty()) {
|
if (!this.d.isEmpty()) {
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
@ -3613,10 +3716,17 @@ index db9f0196b..e7ea04861 100644
|
|||||||
this.d(chunkcoordintpair);
|
this.d(chunkcoordintpair);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -204,4 +223,21 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
@@ -201,7 +221,26 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
||||||
public void close() throws IOException {
|
|
||||||
this.b.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- public void close() throws IOException {
|
||||||
|
- this.b.close();
|
||||||
|
+// Paper start - nuke IOWorker
|
||||||
|
+// public void close() throws IOException {
|
||||||
|
+// this.b.close();
|
||||||
|
+// }
|
||||||
|
+// Paper end
|
||||||
+
|
+
|
||||||
+ // Paper start - get data function
|
+ // Paper start - get data function
|
||||||
+ public NBTTagCompound getData(ChunkCoordIntPair chunkcoordintpair) {
|
+ public NBTTagCompound getData(ChunkCoordIntPair chunkcoordintpair) {
|
||||||
@ -3632,7 +3742,7 @@ index db9f0196b..e7ea04861 100644
|
|||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ return null;
|
+ return null;
|
||||||
+ }
|
}
|
||||||
+ // Paper end
|
+ // Paper end
|
||||||
}
|
}
|
||||||
diff --git a/src/main/java/net/minecraft/server/TicketType.java b/src/main/java/net/minecraft/server/TicketType.java
|
diff --git a/src/main/java/net/minecraft/server/TicketType.java b/src/main/java/net/minecraft/server/TicketType.java
|
||||||
@ -3737,7 +3847,7 @@ index c999f8c9b..b59ef1a63 100644
|
|||||||
|
|
||||||
HAS_SPACE(VillagePlaceRecord::d), IS_OCCUPIED(VillagePlaceRecord::e), ANY((villageplacerecord) -> {
|
HAS_SPACE(VillagePlaceRecord::d), IS_OCCUPIED(VillagePlaceRecord::e), ANY((villageplacerecord) -> {
|
||||||
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
||||||
index 8ea9b34a1..fecbe7914 100644
|
index 049d4ef4e..59b2fc629 100644
|
||||||
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
||||||
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
||||||
@@ -81,6 +81,79 @@ public class WorldServer extends World {
|
@@ -81,6 +81,79 @@ public class WorldServer extends World {
|
||||||
@ -3762,7 +3872,7 @@ index 8ea9b34a1..fecbe7914 100644
|
|||||||
+ RegionFile file;
|
+ RegionFile file;
|
||||||
+
|
+
|
||||||
+ try {
|
+ try {
|
||||||
+ file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getRegionFile(new ChunkCoordIntPair(chunkX, chunkZ), false);
|
+ file = WorldServer.this.getChunkProvider().playerChunkMap.getVillagePlace().getFile(new ChunkCoordIntPair(chunkX, chunkZ), false);
|
||||||
+ } catch (java.io.IOException ex) {
|
+ } catch (java.io.IOException ex) {
|
||||||
+ throw new RuntimeException(ex);
|
+ throw new RuntimeException(ex);
|
||||||
+ }
|
+ }
|
||||||
@ -3797,7 +3907,7 @@ index 8ea9b34a1..fecbe7914 100644
|
|||||||
+ RegionFile file;
|
+ RegionFile file;
|
||||||
+
|
+
|
||||||
+ try {
|
+ try {
|
||||||
+ file = WorldServer.this.getChunkProvider().playerChunkMap.getRegionFile(new ChunkCoordIntPair(chunkX, chunkZ), false);
|
+ file = WorldServer.this.getChunkProvider().playerChunkMap.getFile(new ChunkCoordIntPair(chunkX, chunkZ), false);
|
||||||
+ } catch (java.io.IOException ex) {
|
+ } catch (java.io.IOException ex) {
|
||||||
+ throw new RuntimeException(ex);
|
+ throw new RuntimeException(ex);
|
||||||
+ }
|
+ }
|
||||||
@ -3920,5 +4030,5 @@ index a1d93200e..6ca0ebfde 100644
|
|||||||
log.log( Level.SEVERE, "------------------------------" );
|
log.log( Level.SEVERE, "------------------------------" );
|
||||||
//
|
//
|
||||||
--
|
--
|
||||||
2.24.1
|
2.17.1
|
||||||
|
|
||||||
|
@ -1,379 +0,0 @@
|
|||||||
From 14f4011c2f16754e3f39826237f4822c3b6446b1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
||||||
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
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user