mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 16:37:43 +01:00
Update leaf's asynch chunk io patch
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,244 +0,0 @@
|
|||||||
From d7a653379c6a6446a42907cd03e9d1348844f893 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
||||||
Date: Mon, 8 Jul 2019 03:24:59 -0700
|
|
||||||
Subject: [PATCH] Asynchronous chunk loading api
|
|
||||||
|
|
||||||
---
|
|
||||||
.../minecraft/server/ChunkProviderServer.java | 134 ++++++++++++++++++
|
|
||||||
.../net/minecraft/server/ChunkStatus.java | 1 +
|
|
||||||
.../java/net/minecraft/server/MCUtil.java | 5 +
|
|
||||||
.../java/net/minecraft/server/RegionFile.java | 2 +-
|
|
||||||
.../java/net/minecraft/server/TicketType.java | 1 +
|
|
||||||
.../org/bukkit/craftbukkit/CraftWorld.java | 19 +--
|
|
||||||
6 files changed, 152 insertions(+), 10 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
||||||
index db9113994e..b46285ecdc 100644
|
|
||||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
||||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
||||||
@@ -147,6 +147,140 @@ public class ChunkProviderServer extends IChunkProvider {
|
|
||||||
return playerChunk.getAvailableChunkNow();
|
|
||||||
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ private long asyncLoadSeqCounter;
|
|
||||||
+
|
|
||||||
+ public void getChunkAtAsynchronously(int x, int z, boolean gen, java.util.function.Consumer<Chunk> onComplete) {
|
|
||||||
+ if (Thread.currentThread() != this.serverThread) {
|
|
||||||
+ this.serverThreadQueue.execute(() -> {
|
|
||||||
+ this.getChunkAtAsynchronously(x, z, gen, onComplete);
|
|
||||||
+ });
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ long k = ChunkCoordIntPair.pair(x, z);
|
|
||||||
+ ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(x, z);
|
|
||||||
+
|
|
||||||
+ IChunkAccess ichunkaccess;
|
|
||||||
+
|
|
||||||
+ // try cache
|
|
||||||
+ for (int l = 0; l < 4; ++l) {
|
|
||||||
+ if (k == this.cachePos[l] && ChunkStatus.FULL == this.cacheStatus[l]) {
|
|
||||||
+ ichunkaccess = this.cacheChunk[l];
|
|
||||||
+ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime
|
|
||||||
+
|
|
||||||
+ // move to first in cache
|
|
||||||
+
|
|
||||||
+ for (int i1 = 3; i1 > 0; --i1) {
|
|
||||||
+ this.cachePos[i1] = this.cachePos[i1 - 1];
|
|
||||||
+ this.cacheStatus[i1] = this.cacheStatus[i1 - 1];
|
|
||||||
+ this.cacheChunk[i1] = this.cacheChunk[i1 - 1];
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ this.cachePos[0] = k;
|
|
||||||
+ this.cacheStatus[0] = ChunkStatus.FULL;
|
|
||||||
+ this.cacheChunk[0] = ichunkaccess;
|
|
||||||
+
|
|
||||||
+ onComplete.accept((Chunk)ichunkaccess);
|
|
||||||
+
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (gen) {
|
|
||||||
+ this.bringToFullStatusAsync(x, z, chunkPos, onComplete);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ IChunkAccess current = this.getChunkAtImmediately(x, z); // we want to bypass ticket restrictions
|
|
||||||
+ if (current != null) {
|
|
||||||
+ if (!(current instanceof ProtoChunkExtension) && !(current instanceof net.minecraft.server.Chunk)) {
|
|
||||||
+ onComplete.accept(null); // the chunk is not gen'd
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ // we know the chunk is at full status here (either in read-only mode or the real thing)
|
|
||||||
+ this.bringToFullStatusAsync(x, z, chunkPos, onComplete);
|
|
||||||
+ return;
|
|
||||||
+ } else {
|
|
||||||
+ RegionFile file;
|
|
||||||
+
|
|
||||||
+ try {
|
|
||||||
+ file = this.world.getChunkProvider().playerChunkMap.getRegionFile(chunkPos, false);
|
|
||||||
+ } catch (IOException ex) {
|
|
||||||
+ throw new RuntimeException(ex);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ChunkStatus status;
|
|
||||||
+ if (!file.chunkExists(chunkPos) || ((status = file.getStatusIfCached(x, z)) != null && status != ChunkStatus.FULL)) {
|
|
||||||
+ onComplete.accept(null); // cached status says not generated, or data does not exist on disk
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ if (status == ChunkStatus.FULL) {
|
|
||||||
+ // at this stage we know it is fully generated, but is on disk
|
|
||||||
+ this.bringToFullStatusAsync(x, z, chunkPos, onComplete);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // at this stage we don't know what status the chunk is in
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // here we don't know what status it is and we're not supposed to generate
|
|
||||||
+ // so we asynchronously load empty status
|
|
||||||
+
|
|
||||||
+ this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.EMPTY, (IChunkAccess chunk) -> {
|
|
||||||
+ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.server.Chunk)) {
|
|
||||||
+ // the chunk on disk was not a full status chunk
|
|
||||||
+ onComplete.accept(null);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ this.bringToFullStatusAsync(x, z, chunkPos, onComplete); // bring to full status if required
|
|
||||||
+ });
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ private void bringToFullStatusAsync(int x, int z, ChunkCoordIntPair chunkPos, java.util.function.Consumer<Chunk> onComplete) {
|
|
||||||
+ this.bringToStatusAsync(x, z, chunkPos, ChunkStatus.FULL, (java.util.function.Consumer)onComplete);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ private void bringToStatusAsync(int x, int z, ChunkCoordIntPair chunkPos, ChunkStatus status, java.util.function.Consumer<IChunkAccess> onComplete) {
|
|
||||||
+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> future = this.getChunkFutureMainThread(x, z, status, true);
|
|
||||||
+ long identifier = this.asyncLoadSeqCounter++;
|
|
||||||
+ int ticketLevel = MCUtil.getTicketLevelFor(status);
|
|
||||||
+ this.addTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier);
|
|
||||||
+
|
|
||||||
+ future.whenCompleteAsync((Either<IChunkAccess, PlayerChunk.Failure> either, Throwable throwable) -> {
|
|
||||||
+ // either left -> success
|
|
||||||
+ // either right -> failure
|
|
||||||
+
|
|
||||||
+ if (throwable != null) {
|
|
||||||
+ throw new RuntimeException(throwable);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ this.removeTicketAtLevel(TicketType.ASYNC_LOAD, chunkPos, ticketLevel, identifier);
|
|
||||||
+ this.addTicketAtLevel(TicketType.UNKNOWN, chunkPos, ticketLevel, chunkPos); // allow unloading
|
|
||||||
+
|
|
||||||
+ Optional<PlayerChunk.Failure> failure = either.right();
|
|
||||||
+
|
|
||||||
+ if (failure.isPresent()) {
|
|
||||||
+ // failure
|
|
||||||
+ throw new IllegalStateException("Chunk failed to load: " + failure.get().toString());
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ onComplete.accept(either.left().get());
|
|
||||||
+
|
|
||||||
+ }, this.serverThreadQueue);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public <T> void addTicketAtLevel(TicketType<T> ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) {
|
|
||||||
+ this.chunkMapDistance.addTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public <T> void removeTicketAtLevel(TicketType<T> ticketType, ChunkCoordIntPair chunkPos, int ticketLevel, T identifier) {
|
|
||||||
+ this.chunkMapDistance.removeTicketAtLevel(ticketType, chunkPos, ticketLevel, identifier);
|
|
||||||
+ }
|
|
||||||
// Paper end
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/ChunkStatus.java b/src/main/java/net/minecraft/server/ChunkStatus.java
|
|
||||||
index e324989b46..abb0d69d2f 100644
|
|
||||||
--- a/src/main/java/net/minecraft/server/ChunkStatus.java
|
|
||||||
+++ b/src/main/java/net/minecraft/server/ChunkStatus.java
|
|
||||||
@@ -153,6 +153,7 @@ public class ChunkStatus {
|
|
||||||
return ChunkStatus.q.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
+ public static int getTicketLevelOffset(ChunkStatus status) { return ChunkStatus.a(status); } // Paper - OBFHELPER
|
|
||||||
public static int a(ChunkStatus chunkstatus) {
|
|
||||||
return ChunkStatus.r.getInt(chunkstatus.c());
|
|
||||||
}
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
|
|
||||||
index 23d1935dd5..14f8b61042 100644
|
|
||||||
--- a/src/main/java/net/minecraft/server/MCUtil.java
|
|
||||||
+++ b/src/main/java/net/minecraft/server/MCUtil.java
|
|
||||||
@@ -530,4 +530,9 @@ public final class MCUtil {
|
|
||||||
out.print(fileData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ public static int getTicketLevelFor(ChunkStatus status) {
|
|
||||||
+ // TODO make sure the constant `33` is correct on future updates. See getChunkAt(int, int, ChunkStatus, boolean)
|
|
||||||
+ return 33 + ChunkStatus.getTicketLevelOffset(status);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
|
|
||||||
index 66c8b0307f..3e80f6c53e 100644
|
|
||||||
--- a/src/main/java/net/minecraft/server/RegionFile.java
|
|
||||||
+++ b/src/main/java/net/minecraft/server/RegionFile.java
|
|
||||||
@@ -310,7 +310,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 chunkExists(ChunkCoordIntPair chunkPos) { return this.d(chunkPos); } // Paper - OBFHELPER
|
|
||||||
public boolean d(ChunkCoordIntPair chunkcoordintpair) {
|
|
||||||
return this.getOffset(chunkcoordintpair) != 0;
|
|
||||||
}
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/TicketType.java b/src/main/java/net/minecraft/server/TicketType.java
|
|
||||||
index 5acb0732c3..0ed2d2fbf9 100644
|
|
||||||
--- a/src/main/java/net/minecraft/server/TicketType.java
|
|
||||||
+++ b/src/main/java/net/minecraft/server/TicketType.java
|
|
||||||
@@ -22,6 +22,7 @@ public class TicketType<T> {
|
|
||||||
public static final TicketType<Unit> PLUGIN = a("plugin", (a, b) -> 0); // CraftBukkit
|
|
||||||
public static final TicketType<org.bukkit.plugin.Plugin> PLUGIN_TICKET = a("plugin_ticket", (plugin1, plugin2) -> plugin1.getClass().getName().compareTo(plugin2.getClass().getName())); // Craftbukkit
|
|
||||||
public static final TicketType<Integer> ANTIXRAY = a("antixray", Integer::compareTo); // Paper - Anti-Xray
|
|
||||||
+ public static final TicketType<Long> ASYNC_LOAD = a("async_load", Long::compareTo); // Paper
|
|
||||||
|
|
||||||
public static <T> TicketType<T> a(String s, Comparator<T> comparator) {
|
|
||||||
return new TicketType<>(s, comparator, 0L);
|
|
||||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
||||||
index c5321c5076..7691f23316 100644
|
|
||||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
||||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
||||||
@@ -2323,16 +2323,17 @@ public class CraftWorld implements World {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<Chunk> getChunkAtAsync(int x, int z, boolean gen) {
|
|
||||||
- // TODO placeholder
|
|
||||||
- if (Bukkit.isPrimaryThread()) {
|
|
||||||
- return CompletableFuture.completedFuture(getChunkAtGen(x, z, gen));
|
|
||||||
- } else {
|
|
||||||
- CompletableFuture<Chunk> ret = new CompletableFuture<>();
|
|
||||||
- net.minecraft.server.MinecraftServer.getServer().scheduleOnMain(() -> {
|
|
||||||
- ret.complete(getChunkAtGen(x, z, gen));
|
|
||||||
- });
|
|
||||||
- return ret;
|
|
||||||
+ net.minecraft.server.Chunk immediate = this.world.getChunkProvider().getChunkAtIfLoadedImmediately(x, z);
|
|
||||||
+ if (immediate != null) {
|
|
||||||
+ return CompletableFuture.completedFuture(immediate.bukkitChunk);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ CompletableFuture<Chunk> ret = new CompletableFuture<>();
|
|
||||||
+ this.world.getChunkProvider().getChunkAtAsynchronously(x, z, gen, (net.minecraft.server.Chunk chunk) -> {
|
|
||||||
+ ret.complete(chunk == null ? null : chunk.bukkitChunk);
|
|
||||||
+ });
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
}
|
|
||||||
// Paper end
|
|
||||||
|
|
||||||
--
|
|
||||||
2.20.1
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
From 854429ab6cd52dfd88f48b40206055b8790085f0 Mon Sep 17 00:00:00 2001
|
From 3ff085046cf1d3efc53b2dec884c4d5b75cd0df3 Mon Sep 17 00:00:00 2001
|
||||||
From: kickash32 <kickash32@gmail.com>
|
From: kickash32 <kickash32@gmail.com>
|
||||||
Date: Tue, 11 Jun 2019 22:22:16 -0400
|
Date: Tue, 11 Jun 2019 22:22:16 -0400
|
||||||
Subject: [PATCH] Implement optional per player mob spawns
|
Subject: [PATCH] Implement optional per player mob spawns
|
||||||
@@ -29,10 +29,10 @@ index ff520d9e86..5ed02f6485 100644
|
|||||||
public boolean asynchronous;
|
public boolean asynchronous;
|
||||||
public EngineMode engineMode;
|
public EngineMode engineMode;
|
||||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||||
index f6a6421140..770ee018fe 100644
|
index 4f7c442264..9f6c362dd1 100644
|
||||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||||
@@ -586,9 +586,21 @@ public class ChunkProviderServer extends IChunkProvider {
|
@@ -582,9 +582,21 @@ public class ChunkProviderServer extends IChunkProvider {
|
||||||
// Paper start - only allow spawns upto the limit per chunk and update count afterwards
|
// Paper start - only allow spawns upto the limit per chunk and update count afterwards
|
||||||
int currEntityCount = object2intmap.getInt(enumcreaturetype);
|
int currEntityCount = object2intmap.getInt(enumcreaturetype);
|
||||||
int difference = k1 - currEntityCount;
|
int difference = k1 - currEntityCount;
|
||||||
@@ -57,7 +57,7 @@ index f6a6421140..770ee018fe 100644
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 6ca98b7ad5..56e60e0ce1 100644
|
index f25ca782b9..a235df4185 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
|
||||||
@@ -105,6 +105,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
@@ -105,6 +105,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||||
@@ -68,7 +68,7 @@ index 6ca98b7ad5..56e60e0ce1 100644
|
|||||||
private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) {
|
private static double a(ChunkCoordIntPair chunkcoordintpair, Entity entity) {
|
||||||
double d0 = (double) (chunkcoordintpair.x * 16 + 8);
|
double d0 = (double) (chunkcoordintpair.x * 16 + 8);
|
||||||
double d1 = (double) (chunkcoordintpair.z * 16 + 8);
|
double d1 = (double) (chunkcoordintpair.z * 16 + 8);
|
||||||
@@ -1131,6 +1132,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
@@ -1157,6 +1158,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ index af397dd1f7..5e001733a9 100644
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
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 f0380c5df4..0c4fd5ca4d 100644
|
index f7597d499f..2410db3353 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
|
||||||
@@ -17,6 +17,9 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
@@ -17,6 +17,9 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
@@ -188,7 +188,7 @@ index f0380c5df4..0c4fd5ca4d 100644
|
|||||||
|
|
||||||
// CraftBukkit start
|
// CraftBukkit start
|
||||||
private int tickPosition;
|
private int tickPosition;
|
||||||
@@ -930,6 +934,7 @@ public class WorldServer extends World {
|
@@ -932,6 +936,7 @@ public class WorldServer extends World {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object2IntMap<EnumCreatureType> l() {
|
public Object2IntMap<EnumCreatureType> l() {
|
||||||
@@ -196,7 +196,7 @@ index f0380c5df4..0c4fd5ca4d 100644
|
|||||||
Object2IntMap<EnumCreatureType> object2intmap = new Object2IntOpenHashMap();
|
Object2IntMap<EnumCreatureType> object2intmap = new Object2IntOpenHashMap();
|
||||||
ObjectIterator objectiterator = this.entitiesById.values().iterator();
|
ObjectIterator objectiterator = this.entitiesById.values().iterator();
|
||||||
|
|
||||||
@@ -957,13 +962,47 @@ public class WorldServer extends World {
|
@@ -959,13 +964,47 @@ public class WorldServer extends World {
|
||||||
}
|
}
|
||||||
// Paper end
|
// Paper end
|
||||||
object2intmap.mergeInt(enumcreaturetype, 1, Integer::sum);
|
object2intmap.mergeInt(enumcreaturetype, 1, Integer::sum);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
From 4c6e788cb3b1158e8955dccd8434939ebe1a026a Mon Sep 17 00:00:00 2001
|
From dc255f32785831cfa041105a377ea880926762f8 Mon Sep 17 00:00:00 2001
|
||||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||||
Date: Sat, 13 Jul 2019 15:56:22 -0500
|
Date: Sat, 13 Jul 2019 15:56:22 -0500
|
||||||
Subject: [PATCH] Tulips change fox type
|
Subject: [PATCH] Tulips change fox type
|
||||||
Reference in New Issue
Block a user