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>
|
||||
Date: Sat, 13 Jul 2019 09:23:10 -0700
|
||||
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
|
||||
chunk NBT data onto worker threads. This patch also will shove
|
||||
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
|
||||
index 2f95174fc..1025e01d5 100644
|
||||
index 2f95174fc..134c76065 100644
|
||||
--- a/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 java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -2840,8 +2837,11 @@ index 2f95174fc..1025e01d5 100644
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -11,7 +15,9 @@ public class IChunkLoader implements AutoCloseable {
|
||||
private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER
|
||||
-public class IChunkLoader implements AutoCloseable {
|
||||
+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;
|
||||
@Nullable
|
||||
- private PersistentStructureLegacy c;
|
||||
@ -2850,8 +2850,13 @@ index 2f95174fc..1025e01d5 100644
|
||||
+ private final Object persistentDataLock = new Object(); // Paper
|
||||
|
||||
public IChunkLoader(File file, DataFixer datafixer) {
|
||||
+ super(file);
|
||||
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 {
|
||||
ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z);
|
||||
if (cps != null) {
|
||||
@ -2883,7 +2888,7 @@ index 2f95174fc..1025e01d5 100644
|
||||
|
||||
ChunkStatus status = ChunkStatus.a(level.getString("Status"));
|
||||
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) {
|
||||
nbttagcompound = GameProfileSerializer.a(this.b, DataFixTypes.CHUNK, nbttagcompound, i, 1493);
|
||||
if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) {
|
||||
@ -2897,14 +2902,26 @@ index 2f95174fc..1025e01d5 100644
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,10 +102,12 @@ public class IChunkLoader implements AutoCloseable {
|
||||
return this.a.a(chunkcoordintpair);
|
||||
@@ -84,24 +98,28 @@ public class IChunkLoader implements AutoCloseable {
|
||||
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) {
|
||||
- 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 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) {
|
||||
- this.c.a(chunkcoordintpair.pair());
|
||||
+ 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
|
||||
index 25a87c2d3..c02c53b50 100644
|
||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
||||
@ -2939,7 +2974,7 @@ index 8e15aba7f..edb3a6035 100644
|
||||
|
||||
public String getServerIp() {
|
||||
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
|
||||
+++ b/src/main/java/net/minecraft/server/NextTickListEntry.java
|
||||
@@ -4,7 +4,7 @@ import java.util.Comparator;
|
||||
@ -2999,7 +3034,7 @@ index 7a1578afa..0fb9c1e44 100644
|
||||
completablefuture = (CompletableFuture) this.statusFutures.get(i);
|
||||
if (completablefuture != null) {
|
||||
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
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -63,7 +63,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
@ -3064,15 +3099,16 @@ index 6a54ccb86..66bd402e9 100644
|
||||
mutableboolean.setTrue();
|
||||
});
|
||||
} 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(() -> {
|
||||
return true;
|
||||
});
|
||||
- this.i();
|
||||
+ 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());
|
||||
} 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
|
||||
|
||||
if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) {
|
||||
@ -3392,7 +3428,14 @@ index 6a54ccb86..66bd402e9 100644
|
||||
@Nullable
|
||||
public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public
|
||||
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 {
|
||||
@ -3414,7 +3457,7 @@ index 6a54ccb86..66bd402e9 100644
|
||||
}
|
||||
+ // Paper end
|
||||
+ synchronized (this) { // Paper - async io
|
||||
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
|
||||
+ RegionFile regionFile = this.getFile(chunkPos, false);
|
||||
+
|
||||
+ if (!regionFile.chunkExists(chunkPos)) {
|
||||
+ return null;
|
||||
@ -3442,7 +3485,7 @@ index 6a54ccb86..66bd402e9 100644
|
||||
public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException {
|
||||
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
|
||||
+ 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));
|
||||
@ -3478,7 +3521,7 @@ index 6a54ccb86..66bd402e9 100644
|
||||
+ synchronized (world.getChunkProvider().playerChunkMap) {
|
||||
+ net.minecraft.server.RegionFile file;
|
||||
+ try {
|
||||
+ file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
|
||||
+ file = world.getChunkProvider().playerChunkMap.getFile(chunkPos, false);
|
||||
+ } catch (IOException ex) {
|
||||
+ throw new RuntimeException(ex);
|
||||
+ }
|
||||
@ -3499,9 +3542,18 @@ index 6a54ccb86..66bd402e9 100644
|
||||
return this.m;
|
||||
}
|
||||
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
|
||||
+++ 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 {
|
||||
return chunkcoordintpair.j() + chunkcoordintpair.k() * 32;
|
||||
}
|
||||
@ -3512,10 +3564,19 @@ index 7eb87c517..551e91869 100644
|
||||
try {
|
||||
this.c();
|
||||
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
|
||||
+++ 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
|
||||
@ -3524,6 +3585,21 @@ index 1a6be7c6d..9a0fdec47 100644
|
||||
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 {
|
||||
}
|
||||
|
||||
@ -3534,19 +3610,35 @@ index 1a6be7c6d..9a0fdec47 100644
|
||||
|
||||
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
|
||||
index db9f0196b..e7ea04861 100644
|
||||
index db9f0196b..a6d8ef5eb 100644
|
||||
--- a/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 final IOWorker b;
|
||||
- private final IOWorker b;
|
||||
+// private final IOWorker b;
|
||||
private final Long2ObjectMap<Optional<R>> c = new Long2ObjectOpenHashMap();
|
||||
- private final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet();
|
||||
+ protected final LongLinkedOpenHashSet d = new LongLinkedOpenHashSet(); // Paper - private -> protected
|
||||
private final BiFunction<Runnable, Dynamic<?>, R> e;
|
||||
private final Function<Runnable, R> f;
|
||||
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) {
|
||||
@ -3557,7 +3649,7 @@ index db9f0196b..e7ea04861 100644
|
||||
|
||||
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) {
|
||||
@ -3571,7 +3663,14 @@ index db9f0196b..e7ea04861 100644
|
||||
}
|
||||
|
||||
@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) {
|
||||
@ -3580,7 +3679,11 @@ index db9f0196b..e7ea04861 100644
|
||||
NBTBase nbtbase = (NBTBase) dynamic.getValue();
|
||||
|
||||
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) {
|
||||
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) {
|
||||
if (!this.d.isEmpty()) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
@ -3613,10 +3716,17 @@ index db9f0196b..e7ea04861 100644
|
||||
this.d(chunkcoordintpair);
|
||||
return;
|
||||
}
|
||||
@@ -204,4 +223,21 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
||||
public void close() throws IOException {
|
||||
this.b.close();
|
||||
@@ -201,7 +221,26 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
|
||||
|
||||
}
|
||||
|
||||
- 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
|
||||
+ public NBTTagCompound getData(ChunkCoordIntPair chunkcoordintpair) {
|
||||
@ -3632,7 +3742,7 @@ index db9f0196b..e7ea04861 100644
|
||||
+ }
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
}
|
||||
+ // Paper end
|
||||
}
|
||||
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) -> {
|
||||
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
|
||||
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
@@ -81,6 +81,79 @@ public class WorldServer extends World {
|
||||
@ -3762,7 +3872,7 @@ index 8ea9b34a1..fecbe7914 100644
|
||||
+ RegionFile file;
|
||||
+
|
||||
+ 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) {
|
||||
+ throw new RuntimeException(ex);
|
||||
+ }
|
||||
@ -3797,7 +3907,7 @@ index 8ea9b34a1..fecbe7914 100644
|
||||
+ RegionFile file;
|
||||
+
|
||||
+ 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) {
|
||||
+ throw new RuntimeException(ex);
|
||||
+ }
|
||||
@ -3920,5 +4030,5 @@ index a1d93200e..6ca0ebfde 100644
|
||||
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