More progression on patches

This commit is contained in:
Shane Freeder 2019-12-12 20:58:07 +00:00
parent d8a0622602
commit b0dc983f21
No known key found for this signature in database
GPG key ID: A3F61EA5A085289C
30 changed files with 678 additions and 243 deletions

View file

@ -1,4 +1,4 @@
From 35a49b435ebe8feda6702c2a358e9b26c2da3c61 Mon Sep 17 00:00:00 2001
From 207bb124c37c659b47420cfbd7e924e5e3149e55 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Wed, 30 Mar 2016 19:36:20 -0400
Subject: [PATCH] MC Dev fixes
@ -278,6 +278,46 @@ index a2bbca22b..c8512f9f4 100644
if (pathfindertargetcondition.a(entityliving, t0)) {
list1.add(t0);
diff --git a/src/main/java/net/minecraft/server/IOWorker.java b/src/main/java/net/minecraft/server/IOWorker.java
index a986f2912..c5658c077 100644
--- a/src/main/java/net/minecraft/server/IOWorker.java
+++ b/src/main/java/net/minecraft/server/IOWorker.java
@@ -46,7 +46,7 @@ public class IOWorker implements AutoCloseable {
if (throwable != null) {
completablefuture.completeExceptionally(throwable);
} else {
- completablefuture.complete((Object) null);
+ completablefuture.complete(null); // Paper - Decompile fix
}
});
@@ -106,7 +106,7 @@ public class IOWorker implements AutoCloseable {
}));
completablefuture1.whenComplete((object, throwable) -> {
- completablefuture.complete((Object) null);
+ completablefuture.complete(null); // Paper - decompile fix
});
};
});
@@ -165,7 +165,7 @@ public class IOWorker implements AutoCloseable {
private void a(ChunkCoordIntPair chunkcoordintpair, IOWorker.a ioworker_a) {
try {
this.e.write(chunkcoordintpair, ioworker_a.a);
- ioworker_a.b.complete((Object) null);
+ ioworker_a.b.complete(null); // Paper - decompile fix
} catch (Exception exception) {
IOWorker.LOGGER.error("Failed to store chunk {}", chunkcoordintpair, exception);
ioworker_a.b.completeExceptionally(exception);
@@ -176,7 +176,7 @@ public class IOWorker implements AutoCloseable {
private void g() {
try {
this.e.close();
- this.h.complete((Object) null);
+ this.h.complete(null); // Paper - decompile fix
} catch (Exception exception) {
IOWorker.LOGGER.error("Failed to close storage", exception);
this.h.completeExceptionally(exception);
diff --git a/src/main/java/net/minecraft/server/LootSelectorEntry.java b/src/main/java/net/minecraft/server/LootSelectorEntry.java
index 59bb53543..3ed6a1e78 100644
--- a/src/main/java/net/minecraft/server/LootSelectorEntry.java
@ -525,5 +565,5 @@ index 55fe7625a..19e68a783 100644
t0.a(nbttagcompound.getCompound("data"));
--
2.24.0
2.24.1

View file

@ -1,4 +1,4 @@
From 76350e71db13e90ec5c7bea7f2953edd181e825f Mon Sep 17 00:00:00 2001
From d1c2226c691007cd5409244b74ed91ca98fb0231 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 28 Mar 2016 20:55:47 -0400
Subject: [PATCH] MC Utils
@ -400,6 +400,19 @@ index 3b0877080..0dff02352 100644
default int h(BlockPosition blockposition) {
return this.getType(blockposition).h();
}
diff --git a/src/main/java/net/minecraft/server/IOWorker.java b/src/main/java/net/minecraft/server/IOWorker.java
index c5658c077..b90baef0f 100644
--- a/src/main/java/net/minecraft/server/IOWorker.java
+++ b/src/main/java/net/minecraft/server/IOWorker.java
@@ -22,7 +22,7 @@ public class IOWorker implements AutoCloseable {
private final Thread b;
private final AtomicBoolean c = new AtomicBoolean();
private final Queue<Runnable> d = Queues.newConcurrentLinkedQueue();
- private final RegionFileCache e;
+ private final RegionFileCache e; public RegionFileCache getRegionFileCache() { return e; } // Paper - OBFHELPER
private final Map<ChunkCoordIntPair, IOWorker.a> f = Maps.newLinkedHashMap();
private boolean g = true;
private CompletableFuture<Void> h = new CompletableFuture();
diff --git a/src/main/java/net/minecraft/server/IWorldReader.java b/src/main/java/net/minecraft/server/IWorldReader.java
index ba315131e..cbe2aa4c0 100644
--- a/src/main/java/net/minecraft/server/IWorldReader.java

View file

@ -0,0 +1,377 @@
From 6b1cddcc1971812cc32743d91d699a91261d839c 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 f138b112f..e9cd44fae 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 6371f2f5b..961228e9d 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -391,6 +391,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 efdf611e6..134a4f0b7 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/IChunkLoader.java b/src/main/java/net/minecraft/server/IChunkLoader.java
index f0a052eec..2f95174fc 100644
--- a/src/main/java/net/minecraft/server/IChunkLoader.java
+++ b/src/main/java/net/minecraft/server/IChunkLoader.java
@@ -8,7 +8,7 @@ import javax.annotation.Nullable;
public class IChunkLoader implements AutoCloseable {
- private final IOWorker a;
+ private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER
protected final DataFixer b;
@Nullable
private PersistentStructureLegacy c;
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 43d9a5634..6f2cca07e 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 4379434f6..8e2208422 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -898,11 +898,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.l, nbttagcompound, chunkcoordintpair, world); // CraftBukkit
+ // Paper start - Cache chunk status on disk
+ if (nbttagcompound == null) {
+ return null;
+ }
+
+ nbttagcompound = this.getChunkData(this.world.getWorldProvider().getDimensionManager(), this.l, 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.getIOWorker().getRegionFileCache().getRegionFileIfLoaded(chunkPos);
+
+ return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
+ }
+
+ public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException {
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(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.getIOWorker().getRegionFileCache().getFile(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 5d2cbbad2..7eb87c517 100644
--- a/src/main/java/net/minecraft/server/RegionFile.java
+++ b/src/main/java/net/minecraft/server/RegionFile.java
@@ -33,6 +33,30 @@ public class RegionFile implements AutoCloseable {
private final IntBuffer h;
private final RegionFileBitSet 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, File file1) throws IOException {
this(file.toPath(), file1.toPath(), RegionFileCompression.b);
}
@@ -344,11 +368,13 @@ public class RegionFile implements AutoCloseable {
return this.getOffset(chunkcoordintpair) != 0;
}
+ private final int getChunkLocation(ChunkCoordIntPair chunkcoordintpair) { return this.g(chunkcoordintpair); } // Paper - OBFHELPER
private static int g(ChunkCoordIntPair chunkcoordintpair) {
return chunkcoordintpair.j() + chunkcoordintpair.k() * 32;
}
public void close() throws IOException {
+ this.closed = true; // Paper
try {
this.c();
} finally {
diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java
index 57ce53cfd..1a6be7c6d 100644
--- a/src/main/java/net/minecraft/server/RegionFileCache.java
+++ b/src/main/java/net/minecraft/server/RegionFileCache.java
@@ -18,7 +18,14 @@ public final class RegionFileCache implements AutoCloseable {
this.b = file;
}
- private RegionFile getFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit
+
+ // Paper start
+ public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) {
+ 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
long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i);
@@ -86,6 +93,7 @@ public final class RegionFileCache implements AutoCloseable {
try {
NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream);
+ regionfile.setStatus(chunkcoordintpair.x, chunkcoordintpair.z, ChunkRegionLoader.getStatus(nbttagcompound)); // Paper - cache status on disk
} catch (Throwable throwable1) {
throwable = throwable1;
throw throwable1;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index b1ae19be7..7d509856b 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;
@@ -409,8 +410,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.read(new ChunkCoordIntPair(x, z)) != null; // Paper (TODO check if the first part can be removed)
+ return world.getChunkProvider().playerChunkMap.getChunkStatusOnDisk(new ChunkCoordIntPair(x, z)) == ChunkStatus.FULL;
+ // Paper end
} catch (IOException ex) {
throw new RuntimeException(ex);
}
@@ -522,20 +537,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.getIOWorker().getRegionFileCache().getFile(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.1

View file

@ -1,4 +1,4 @@
From 07551ce735f8c62bc07a180b666ea6ad9368e404 Mon Sep 17 00:00:00 2001
From f2e3f2bd5e5df98d49b2da4acf61f4556185d3ef Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 15 Jun 2019 10:28:25 -0700
Subject: [PATCH] Show blockstate location if we failed to read it

View file

@ -1,4 +1,4 @@
From 6b453ebf22ad7ede563e5cd0560b097e264d115b Mon Sep 17 00:00:00 2001
From 538fc4cb63c6281c1424dbb1c161e5a8f9f9e0b6 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Fri, 21 Jun 2019 14:42:48 -0700
Subject: [PATCH] Log other thread in DataPaletteBlock lock failure

View file

@ -1,4 +1,4 @@
From dc460bf237dd914ca9485c60ffde346f290fa9fc Mon Sep 17 00:00:00 2001
From 1520f4ce0ecc7afa9db856bc7ab16923dbe51d4d Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sat, 22 Jun 2019 04:20:47 -0700
Subject: [PATCH] Use ChunkStatus cache when saving protochunks
@ -7,7 +7,7 @@ The cache should contain the chunk status when saving. If not it
will load it.
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 4379434f6..93729eea2 100644
index 8e2208422..cbab813d9 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -775,8 +775,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {

View file

@ -1,4 +1,4 @@
From 5772233362f877a05c3f2ac98a102723e701ea65 Mon Sep 17 00:00:00 2001
From 6af2036c7be6a6b165b5e8a88ed9de26748b03f2 Mon Sep 17 00:00:00 2001
From: stonar96 <minecraft.stonar96@gmail.com>
Date: Mon, 20 Aug 2018 03:03:58 +0200
Subject: [PATCH] Anti-Xray
@ -1194,7 +1194,7 @@ index 14ec31f0a..863a2222f 100644
}
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index 6371f2f5b..17cacafe7 100644
index 961228e9d..a950ad801 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -57,7 +57,7 @@ public class ChunkRegionLoader {
@ -1533,10 +1533,10 @@ index 47710067a..ef7ade797 100644
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 43d9a5634..615d27863 100644
index 6f2cca07e..7a1578afa 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -163,6 +163,11 @@ public class PlayerChunk {
@@ -176,6 +176,11 @@ public class PlayerChunk {
World world = chunk.getWorld();
if (this.dirtyCount == 64) {
@ -1548,7 +1548,7 @@ index 43d9a5634..615d27863 100644
this.s = -1;
}
@@ -195,7 +200,7 @@ public class PlayerChunk {
@@ -208,7 +213,7 @@ public class PlayerChunk {
this.a(world, blockposition);
}
} else if (this.dirtyCount == 64) {
@ -1558,7 +1558,7 @@ index 43d9a5634..615d27863 100644
this.a(new PacketPlayOutMultiBlockChange(this.dirtyCount, this.dirtyBlocks, chunk), false);
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 93729eea2..fc6436c4f 100644
index cbab813d9..6a54ccb86 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -540,7 +540,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -1570,7 +1570,7 @@ index 93729eea2..fc6436c4f 100644
}, this.executor);
}
@@ -1201,7 +1201,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1251,7 +1251,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
private void a(EntityPlayer entityplayer, Packet<?>[] apacket, Chunk chunk) {
if (apacket[0] == null) {

View file

@ -1,4 +1,4 @@
From 960288ec426082f000ad1defb38518f42a70a6a0 Mon Sep 17 00:00:00 2001
From d6b3a9d00583ae9f1c817cf2357385828b4c77f7 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sun, 24 Mar 2019 01:01:32 -0400
Subject: [PATCH] Only count Natural Spawned mobs towards natural spawn mob

View file

@ -1,4 +1,4 @@
From 291a6e7746ad8a74727c820e144e634197bcd63d Mon Sep 17 00:00:00 2001
From fe80434c15e830414fa1dd4ff75dbe4ac61da0b0 Mon Sep 17 00:00:00 2001
From: Lucavon <lucavonlp@gmail.com>
Date: Tue, 23 Jul 2019 20:29:20 -0500
Subject: [PATCH] Configurable projectile relative velocity

View file

@ -1,4 +1,4 @@
From e645f66b705efad107d9836e81944d476077750b Mon Sep 17 00:00:00 2001
From 56f78814b12ea4c6d20d61805f929ad16a4e0210 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 28 Jul 2019 00:51:11 +0100
Subject: [PATCH] Mark entities as being ticked when notifying navigation

View file

@ -1,4 +1,4 @@
From a4df21cb5dc107cff27108049b3a49e2af89bc65 Mon Sep 17 00:00:00 2001
From 48db1f915770a15bad559a4d889daf1c9c8a7bb1 Mon Sep 17 00:00:00 2001
From: kickash32 <kickash32@gmail.com>
Date: Tue, 30 Jul 2019 03:17:16 +0500
Subject: [PATCH] offset item frame ticking

View file

@ -1,4 +1,4 @@
From f3e7d4a4a9eaa8387255e654db4d164c6cc0cc5b Mon Sep 17 00:00:00 2001
From 804237b1d74d70816cc3b2d5defe825ecfd8feb8 Mon Sep 17 00:00:00 2001
From: CullanP <cullanpage@gmail.com>
Date: Thu, 3 Mar 2016 02:13:38 -0600
Subject: [PATCH] Avoid hopper searches if there are no items

View file

@ -1,4 +1,4 @@
From 9090684e6b50628d9833921e66027887c7906bde Mon Sep 17 00:00:00 2001
From 3b24ccb35b244f98490f2bcef8e3737ea63ce55e Mon Sep 17 00:00:00 2001
From: TheGreatKetchup <TheGreatKetchup@users.noreply.github.com>
Date: Thu, 1 Aug 2019 21:24:30 -0400
Subject: [PATCH] Fixed MC-156852

View file

@ -1,8 +1,11 @@
From f50b22a006bec81218b6cdaa1f7162cc17d9d74b Mon Sep 17 00:00:00 2001
From 867219c4f28a3b9b5ea9dfe010569d45b620f1e1 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
@ -161,7 +164,7 @@ index 3a79cde59..8de6c4816 100644
public static Timing getTickList(WorldServer worldserver, String timingsType) {
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index c88b5e9dd..93c0c422d 100644
index 546a1cfe0..1d7d1ffbf 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -1,5 +1,6 @@
@ -171,7 +174,7 @@ index c88b5e9dd..93c0c422d 100644
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
@@ -388,4 +389,64 @@ public class PaperConfig {
@@ -364,4 +365,64 @@ public class PaperConfig {
maxBookPageSize = getInt("settings.book-size.page-max", maxBookPageSize);
maxBookTotalSizeMultiplier = getDouble("settings.book-size.total-multiplier", maxBookTotalSizeMultiplier);
}
@ -2359,7 +2362,7 @@ index 000000000..59d73bfad
+
+}
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 56761afdf..277c2245d 100644
index e9cd44fae..1f6b1c4f1 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -124,11 +124,137 @@ public class ChunkProviderServer extends IChunkProvider {
@ -2514,7 +2517,7 @@ index 56761afdf..277c2245d 100644
this.world.timings.chunkAwait.stopTiming(); // Paper
} // Paper
ichunkaccess = (IChunkAccess) ((Either) completablefuture.join()).map((ichunkaccess1) -> {
@@ -641,11 +772,12 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -640,11 +771,12 @@ public class ChunkProviderServer extends IChunkProvider {
protected boolean executeNext() {
// CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task
try {
@ -2529,7 +2532,7 @@ index 56761afdf..277c2245d 100644
} finally {
playerChunkMap.callbackExecutor.run();
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index a02807411..98cc4efcf 100644
index a950ad801..26f1a4b09 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
@ -2570,7 +2573,7 @@ index a02807411..98cc4efcf 100644
ChunkGenerator<?> chunkgenerator = worldserver.getChunkProvider().getChunkGenerator();
WorldChunkManager worldchunkmanager = chunkgenerator.getWorldChunkManager();
NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level");
@@ -66,7 +89,9 @@ public class ChunkRegionLoader {
@@ -49,7 +72,9 @@ public class ChunkRegionLoader {
LightEngine lightengine = chunkproviderserver.getLightEngine();
if (flag) {
@ -2580,8 +2583,8 @@ index a02807411..98cc4efcf 100644
+ }); // Paper - delay this task since we're executing off-main
}
for (int k = 0; k < nbttaglist.size(); ++k) {
@@ -82,16 +107,30 @@ public class ChunkRegionLoader {
for (int i = 0; i < nbttaglist.size(); ++i) {
@@ -65,16 +90,30 @@ public class ChunkRegionLoader {
achunksection[b0] = chunksection;
}
@ -2615,7 +2618,7 @@ index a02807411..98cc4efcf 100644
}
}
}
@@ -194,7 +233,7 @@ public class ChunkRegionLoader {
@@ -177,7 +216,7 @@ public class ChunkRegionLoader {
}
if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) {
@ -2624,7 +2627,7 @@ index a02807411..98cc4efcf 100644
} else {
ProtoChunk protochunk1 = (ProtoChunk) object;
@@ -233,11 +272,83 @@ public class ChunkRegionLoader {
@@ -216,11 +255,83 @@ public class ChunkRegionLoader {
protochunk1.a(worldgenstage_features, BitSet.valueOf(nbttagcompound5.getByteArray(s1)));
}
@ -2709,16 +2712,16 @@ index a02807411..98cc4efcf 100644
ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos();
NBTTagCompound nbttagcompound = new NBTTagCompound();
NBTTagCompound nbttagcompound1 = new NBTTagCompound();
@@ -246,7 +357,7 @@ public class ChunkRegionLoader {
@@ -229,7 +340,7 @@ public class ChunkRegionLoader {
nbttagcompound.set("Level", nbttagcompound1);
nbttagcompound1.setInt("xPos", chunkcoordintpair.x);
nbttagcompound1.setInt("zPos", chunkcoordintpair.z);
- nbttagcompound1.setLong("LastUpdate", worldserver.getTime());
+ nbttagcompound1.setLong("LastUpdate", asyncsavedata != null ? asyncsavedata.worldTime : worldserver.getTime()); // Paper - async chunk unloading
nbttagcompound1.setLong("InhabitedTime", ichunkaccess.q());
nbttagcompound1.setLong("InhabitedTime", ichunkaccess.getInhabitedTime());
nbttagcompound1.setString("Status", ichunkaccess.getChunkStatus().d());
ChunkConverter chunkconverter = ichunkaccess.p();
@@ -262,14 +373,22 @@ public class ChunkRegionLoader {
@@ -245,14 +356,22 @@ public class ChunkRegionLoader {
NBTTagCompound nbttagcompound2;
@ -2745,9 +2748,9 @@ index a02807411..98cc4efcf 100644
if (chunksection != Chunk.a || nibblearray != null || nibblearray1 != null) {
nbttagcompound2 = new NBTTagCompound();
nbttagcompound2.setByte("Y", (byte) (i & 255));
@@ -334,10 +453,10 @@ public class ChunkRegionLoader {
@@ -315,10 +434,10 @@ public class ChunkRegionLoader {
// Paper start
if ((int)Math.floor(entity.locX) >> 4 != chunk.getPos().x || (int)Math.floor(entity.locZ) >> 4 != chunk.getPos().z) {
if ((int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) {
LogManager.getLogger().warn(entity + " is not in this chunk, skipping save. This a bug fix to a vanilla bug. Do not report this to PaperMC please.");
- toUpdate.add(entity);
+ if (asyncsavedata == null) toUpdate.add(entity); // todo fix this broken code, entityJoinedWorld wont work in this case!
@ -2758,7 +2761,7 @@ index a02807411..98cc4efcf 100644
continue;
}
// Paper end
@@ -373,24 +492,32 @@ public class ChunkRegionLoader {
@@ -354,24 +473,32 @@ public class ChunkRegionLoader {
}
nbttagcompound1.set("Entities", nbttaglist2);
@ -2798,7 +2801,7 @@ index a02807411..98cc4efcf 100644
nbttagcompound1.set("PostProcessing", a(ichunkaccess.l()));
diff --git a/src/main/java/net/minecraft/server/ChunkStatus.java b/src/main/java/net/minecraft/server/ChunkStatus.java
index e324989b4..abb0d69d2 100644
index 134a4f0b7..88f167461 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 {
@ -2810,7 +2813,7 @@ index e324989b4..abb0d69d2 100644
return ChunkStatus.r.getInt(chunkstatus.c());
}
diff --git a/src/main/java/net/minecraft/server/IAsyncTaskHandler.java b/src/main/java/net/minecraft/server/IAsyncTaskHandler.java
index d521d25cf..84024e6ba 100644
index 721021791..f7156acb8 100644
--- a/src/main/java/net/minecraft/server/IAsyncTaskHandler.java
+++ b/src/main/java/net/minecraft/server/IAsyncTaskHandler.java
@@ -91,7 +91,7 @@ public abstract class IAsyncTaskHandler<R extends Runnable> implements Mailbox<R
@ -2823,7 +2826,7 @@ index d521d25cf..84024e6ba 100644
;
}
diff --git a/src/main/java/net/minecraft/server/IChunkLoader.java b/src/main/java/net/minecraft/server/IChunkLoader.java
index 3f14392e6..39f6ddb1d 100644
index 2f95174fc..1025e01d5 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;
@ -2837,18 +2840,18 @@ index 3f14392e6..39f6ddb1d 100644
import java.util.function.Supplier;
import javax.annotation.Nullable;
@@ -10,7 +14,9 @@ public class IChunkLoader extends RegionFileCache {
@@ -11,7 +15,9 @@ public class IChunkLoader implements AutoCloseable {
private final IOWorker a; public IOWorker getIOWorker() { return a; } // Paper - OBFHELPER
protected final DataFixer b;
@Nullable
- private PersistentStructureLegacy a;
+ private volatile PersistentStructureLegacy a; // Paper - async chunk loading
- private PersistentStructureLegacy c;
+ private volatile PersistentStructureLegacy c; // Paper - async chunk loading
+
+ private final Object persistentDataLock = new Object(); // Paper
public IChunkLoader(File file, DataFixer datafixer) {
super(file);
@@ -21,14 +27,18 @@ public class IChunkLoader extends RegionFileCache {
this.b = datafixer;
@@ -22,18 +28,23 @@ public class IChunkLoader implements AutoCloseable {
private boolean check(ChunkProviderServer cps, int x, int z) throws IOException {
ChunkCoordIntPair pos = new ChunkCoordIntPair(x, z);
if (cps != null) {
@ -2860,42 +2863,57 @@ index 3f14392e6..39f6ddb1d 100644
}
}
if (this.chunkExists(pos)) {
- NBTTagCompound nbt = read(pos);
- NBTTagCompound nbt = read(pos);
- if (nbt != null) {
- NBTTagCompound level = nbt.getCompound("Level");
- if (level.getBoolean("TerrainPopulated")) {
- return true;
- }
+
+ // Paper start - prioritize
+ NBTTagCompound nbt = cps == null ? read(pos) :
+ com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.loadChunkData((WorldServer)cps.getWorld(), x, z,
+ com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGHER_PRIORITY, false, true).chunkData;
+ // Paper end
if (nbt != null) {
NBTTagCompound level = nbt.getCompound("Level");
if (level.getBoolean("TerrainPopulated")) {
@@ -65,11 +75,13 @@ public class IChunkLoader extends RegionFileCache {
+ if (nbt != null) {
+ NBTTagCompound level = nbt.getCompound("Level");
+ if (level.getBoolean("TerrainPopulated")) {
+ return true;
+ }
ChunkStatus status = ChunkStatus.a(level.getString("Status"));
if (status != null && status.b(ChunkStatus.FEATURES)) {
@@ -64,11 +75,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")) {
+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading
if (this.a == null) {
this.a = PersistentStructureLegacy.a(dimensionmanager.getType(), (WorldPersistentData) supplier.get()); // CraftBukkit - getType
if (this.c == null) {
this.c = PersistentStructureLegacy.a(dimensionmanager.getType(), (WorldPersistentData) supplier.get()); // CraftBukkit - getType
}
nbttagcompound = this.a.a(nbttagcompound);
nbttagcompound = this.c.a(nbttagcompound);
+ } // Paper - Async chunk loading
}
}
@@ -89,7 +101,9 @@ public class IChunkLoader extends RegionFileCache {
public void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException {
super.write(chunkcoordintpair, nbttagcompound);
if (this.a != null) {
@@ -89,10 +102,12 @@ public class IChunkLoader implements AutoCloseable {
return this.a.a(chunkcoordintpair);
}
- public void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) {
+ 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);
if (this.c != null) {
- this.c.a(chunkcoordintpair.pair());
+ synchronized (this.persistentDataLock) { // Paper - Async chunk loading
this.a.a(chunkcoordintpair.pair());
+ } // Paper - Async chunk loading
+ this.c.a(chunkcoordintpair.pair()); } // Paper - Async chunk loading}
}
}
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index 23d1935dd..14f8b6104 100644
index 25a87c2d3..c02c53b50 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 {
@ -2909,10 +2927,10 @@ index 23d1935dd..14f8b6104 100644
+ }
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 5238a1a7c..0b0058138 100644
index 8e15aba7f..edb3a6035 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -780,6 +780,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -788,6 +788,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
this.getUserCache().c(false); // Paper
}
// Spigot end
@ -2921,7 +2939,7 @@ index 5238a1a7c..0b0058138 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 cafb5d883..53a290e8b 100644
index 8471920b8..04429a274 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;
@ -2943,7 +2961,7 @@ index cafb5d883..53a290e8b 100644
this.e = t0;
this.b = i;
diff --git a/src/main/java/net/minecraft/server/NibbleArray.java b/src/main/java/net/minecraft/server/NibbleArray.java
index 90c096876..eb2c06155 100644
index ed8c4a87b..996c83263 100644
--- a/src/main/java/net/minecraft/server/NibbleArray.java
+++ b/src/main/java/net/minecraft/server/NibbleArray.java
@@ -71,6 +71,7 @@ public class NibbleArray {
@ -2955,7 +2973,7 @@ index 90c096876..eb2c06155 100644
return this.a == null ? new NibbleArray() : new NibbleArray((byte[]) this.a.clone());
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index af934ef8b..34d0ab0d5 100644
index 7a1578afa..0fb9c1e44 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -310,7 +310,7 @@ public class PlayerChunk {
@ -2981,37 +2999,37 @@ index af934ef8b..34d0ab0d5 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 a5df9fee6..6b36bbe87 100644
index 6a54ccb86..66bd402e9 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -62,7 +62,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -63,7 +63,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
private final LightEngineThreaded lightEngine;
private final IAsyncTaskHandler<Runnable> executor;
public final ChunkGenerator<?> chunkGenerator;
- private final Supplier<WorldPersistentData> m;
+ private final Supplier<WorldPersistentData> m; public final Supplier<WorldPersistentData> getWorldPersistentDataSupplier() { return this.m; } // Paper - OBFHELPER
private final VillagePlace n;
- private final Supplier<WorldPersistentData> l;
+ private final Supplier<WorldPersistentData> l; public final Supplier<WorldPersistentData> getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER
private final VillagePlace m;
public final LongSet unloadQueue;
private boolean updatingChunksModified;
@@ -72,7 +72,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -73,7 +73,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
public final WorldLoadListener worldLoadListener;
public final PlayerChunkMap.a chunkDistanceManager; public final PlayerChunkMap.a getChunkMapDistanceManager() { return this.chunkDistanceManager; } // Paper - OBFHELPER
private final AtomicInteger v;
private final AtomicInteger u;
- private final DefinedStructureManager definedStructureManager;
+ public final DefinedStructureManager definedStructureManager; // Paper - private -> public
private final File x;
private final File w;
private final PlayerMap playerMap;
public final Int2ObjectMap<PlayerChunkMap.EntityTracker> trackedEntities;
@@ -133,7 +133,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getWorldProvider().g(), threadedmailbox1, this.q.a(threadedmailbox1, false));
@@ -134,7 +134,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.lightEngine = new LightEngineThreaded(ilightaccess, this, this.world.getWorldProvider().f(), threadedmailbox1, this.p.a(threadedmailbox1, false));
this.chunkDistanceManager = new PlayerChunkMap.a(executor, iasynctaskhandler);
this.m = supplier;
- this.n = new VillagePlace(new File(this.x, "poi"), datafixer);
+ this.n = new VillagePlace(new File(this.x, "poi"), datafixer, this.world); // Paper
this.l = supplier;
- this.m = new VillagePlace(new File(this.w, "poi"), datafixer);
+ this.m = new VillagePlace(new File(this.w, "poi"), datafixer, this.world); // Paper
this.setViewDistance(i);
}
@@ -180,7 +180,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -181,7 +181,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
@Nullable
@ -3020,15 +3038,15 @@ index a5df9fee6..6b36bbe87 100644
return (PlayerChunk) this.visibleChunks.get(i);
}
@@ -293,6 +293,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -294,6 +294,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@Override
public void close() throws IOException {
this.q.close();
this.p.close();
+ this.world.asyncChunkTaskManager.close(true); // Paper - Required since we're closing regionfiles in the next line
this.n.close();
this.m.close();
super.close();
}
@@ -313,7 +314,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -314,7 +315,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
shouldSave = ((Chunk) ichunkaccess).lastSaved + world.paperConfig.autoSavePeriod <= world.getTime();
}
@ -3037,7 +3055,7 @@ index a5df9fee6..6b36bbe87 100644
++savedThisTick;
playerchunk.m();
}
@@ -345,7 +346,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -346,7 +347,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return (IChunkAccess) completablefuture.join();
}).filter((ichunkaccess) -> {
return ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk;
@ -3046,14 +3064,15 @@ index a5df9fee6..6b36bbe87 100644
mutableboolean.setTrue();
});
} while (mutableboolean.isTrue());
@@ -353,17 +354,19 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -354,6 +355,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.b(() -> {
return true;
});
+ this.world.asyncChunkTaskManager.flush(); // Paper - flush to preserve behavior compat with pre-async behaviour
PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.x.getName());
this.i();
PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.w.getName());
} else {
this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> {
@@ -361,11 +363,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error
if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) {
@ -3067,13 +3086,13 @@ index a5df9fee6..6b36bbe87 100644
}
}
@@ -373,11 +376,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -375,11 +378,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
protected void unloadChunks(BooleanSupplier booleansupplier) {
GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler();
+ try (Timing ignored = this.world.timings.poiUnload.startTiming()) { // Paper
gameprofilerfiller.enter("poi");
this.n.a(booleansupplier);
this.m.a(booleansupplier);
+ } // Paper
gameprofilerfiller.exitEnter("chunk_unload");
if (!this.world.isSavingDisabled()) {
@ -3083,7 +3102,7 @@ index a5df9fee6..6b36bbe87 100644
}
gameprofilerfiller.exit();
@@ -418,6 +425,60 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -419,6 +426,60 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
@ -3144,7 +3163,7 @@ index a5df9fee6..6b36bbe87 100644
private void a(long i, PlayerChunk playerchunk) {
CompletableFuture<IChunkAccess> completablefuture = playerchunk.getChunkSave();
Consumer<IChunkAccess> consumer = (ichunkaccess) -> { // CraftBukkit - decompile error
@@ -431,13 +492,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -432,13 +493,20 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
((Chunk) ichunkaccess).setLoaded(false);
}
@ -3166,7 +3185,7 @@ index a5df9fee6..6b36bbe87 100644
this.lightEngine.a(ichunkaccess.getPos());
this.lightEngine.queueUpdate();
this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null);
@@ -507,26 +575,30 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -508,26 +576,31 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
}
@ -3187,23 +3206,22 @@ index a5df9fee6..6b36bbe87 100644
+ if (ioThrowable != null) {
+ com.destroystokyo.paper.io.IOUtil.rethrow(ioThrowable);
}
-
- if (nbttagcompound != null) {
- boolean flag = nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8);
-
- if (flag) {
- ProtoChunk protochunk = ChunkRegionLoader.loadChunk(this.world, this.definedStructureManager, this.n, chunkcoordintpair, nbttagcompound);
- ProtoChunk protochunk = ChunkRegionLoader.loadChunk(this.world, this.definedStructureManager, this.m, chunkcoordintpair, nbttagcompound);
-
- protochunk.setLastSaved(this.world.getTime());
- return Either.left(protochunk);
- }
-
- PlayerChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkcoordintpair);
+ this.getVillagePlace().loadInData(chunkcoordintpair, chunkHolder.poiData);
+ chunkHolder.tasks.forEach(Runnable::run);
+ // Paper - async load completes this
+ // Paper end
+
- PlayerChunkMap.LOGGER.error("Chunk file at {} is missing level data, skipping", chunkcoordintpair);
+ // Paper start - This is done async
+ if (chunkHolder.protoChunk != null) {
+ chunkHolder.protoChunk.setLastSaved(this.world.getTime());
@ -3213,7 +3231,7 @@ index a5df9fee6..6b36bbe87 100644
} catch (ReportedException reportedexception) {
Throwable throwable = reportedexception.getCause();
@@ -540,7 +612,27 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -541,7 +614,27 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
return Either.left(new ProtoChunk(chunkcoordintpair, ChunkConverter.a, this.world)); // Paper - Anti-Xray
@ -3242,8 +3260,8 @@ index a5df9fee6..6b36bbe87 100644
}
private CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> b(PlayerChunk playerchunk, ChunkStatus chunkstatus) {
@@ -752,18 +844,43 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return this.v.get();
@@ -753,18 +846,43 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return this.u.get();
}
+ // Paper start - async chunk io
@ -3271,14 +3289,14 @@ index a5df9fee6..6b36bbe87 100644
+ // Paper end
+
public boolean saveChunk(IChunkAccess ichunkaccess) {
- this.n.a(ichunkaccess.getPos());
- this.m.a(ichunkaccess.getPos());
+ // Paper start - async param
+ return this.saveChunk(ichunkaccess, false);
+ }
+ public boolean saveChunk(IChunkAccess ichunkaccess, boolean async) {
+ try (co.aikar.timings.Timing ignored = this.world.timings.chunkSave.startTiming()) {
+ NBTTagCompound poiData = this.getVillagePlace().getData(ichunkaccess.getPos()); // Paper
+ //this.n.a(ichunkaccess.getPos()); // Delay
+ //this.m.a(ichunkaccess.getPos()); // Delay
+ // Paper end
if (!ichunkaccess.isNeedsSaving()) {
return false;
@ -3294,7 +3312,7 @@ index a5df9fee6..6b36bbe87 100644
ichunkaccess.setLastSaved(this.world.getTime());
ichunkaccess.setNeedsSaving(false);
@@ -774,27 +891,33 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -775,27 +893,33 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
NBTTagCompound nbttagcompound;
if (chunkstatus.getType() != ChunkStatus.Type.LEVELCHUNK) {
@ -3316,7 +3334,7 @@ index a5df9fee6..6b36bbe87 100644
+ } // Paper
+ try (co.aikar.timings.Timing ignored1 = this.world.timings.chunkSaveDataSerialization.startTiming()) { // Paper
nbttagcompound = ChunkRegionLoader.saveChunk(this.world, ichunkaccess);
- this.write(chunkcoordintpair, nbttagcompound);
- this.a(chunkcoordintpair, nbttagcompound);
- return true;
+ } // Paper
+ return this.writeDataAsync(ichunkaccess.getPos(), poiData, nbttagcompound, async); // Paper - Async chunk io
@ -3331,7 +3349,7 @@ index a5df9fee6..6b36bbe87 100644
}
protected void setViewDistance(int i) {
@@ -898,6 +1021,42 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -899,6 +1023,42 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
}
@ -3374,31 +3392,11 @@ index a5df9fee6..6b36bbe87 100644
@Nullable
public NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException { // Paper - private -> public
NBTTagCompound nbttagcompound = this.read(chunkcoordintpair);
@@ -920,12 +1079,42 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
// Paper start - chunk status cache "api"
public ChunkStatus getChunkStatusOnDiskIfCached(ChunkCoordIntPair chunkPos) {
+ // Paper start - async chunk save for unload
+ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z);
+ if (unloadingChunk != null) {
+ return unloadingChunk.getChunkStatus();
+ }
+ // Paper end
+ // Paper start - async io
+ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE
+ .getPendingWrite(this.world, chunkPos.x, chunkPos.z, false);
+
+ if (inProgressWrite != null) {
+ return ChunkRegionLoader.getStatus(inProgressWrite);
+ }
+ // Paper end
+
RegionFile regionFile = this.getRegionFileIfLoaded(chunkPos);
return regionFile == null ? null : regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
@@ -927,27 +1087,47 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
public ChunkStatus getChunkStatusOnDisk(ChunkCoordIntPair chunkPos) throws IOException {
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
+ // Paper start - async chunk save for unload
+ IChunkAccess unloadingChunk = this.world.asyncChunkTaskManager.getChunkInSaveProgress(chunkPos.x, chunkPos.z);
+ if (unloadingChunk != null) {
@ -3407,22 +3405,31 @@ index a5df9fee6..6b36bbe87 100644
+ // Paper end
+ // Paper start - async io
+ NBTTagCompound inProgressWrite = com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE
+ .getPendingWrite(this.world, chunkPos.x, chunkPos.z, false);
+
+ .getPendingWrite(this.world, chunkPos.x, chunkPos.z, false);
- if (!regionFile.chunkExists(chunkPos)) {
- return null;
+ if (inProgressWrite != null) {
+ return ChunkRegionLoader.getStatus(inProgressWrite);
+ }
}
+ // Paper end
+ synchronized (this) { // Paper - async io
RegionFile regionFile = this.getRegionFile(chunkPos, false);
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
+
+ if (!regionFile.chunkExists(chunkPos)) {
+ return null;
+ }
if (!regionFile.chunkExists(chunkPos)) {
@@ -937,18 +1126,56 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
if (status != null) {
return status;
- ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
+ ChunkStatus status = regionFile.getStatusIfCached(chunkPos.x, chunkPos.z);
- if (status != null) {
- return status;
+ if (status != null) {
+ return status;
+ }
+ // Paper start - async io
}
+ // Paper start - async io
+ }
- this.readChunkData(chunkPos);
+ NBTTagCompound compound = this.readChunkData(chunkPos);
@ -3433,13 +3440,21 @@ index a5df9fee6..6b36bbe87 100644
}
public void updateChunkStatusOnDisk(ChunkCoordIntPair chunkPos, @Nullable NBTTagCompound compound) throws IOException {
+ synchronized (this) { // Paper - async io
RegionFile regionFile = this.getRegionFile(chunkPos, false);
- RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
+ synchronized (this) {
+ RegionFile regionFile = this.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
+ } // Paper - async io
- regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
+ regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkRegionLoader.getStatus(compound));
+ }
}
public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) {
@@ -956,6 +1136,39 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
// Paper end
+
+ // Paper start - async io
+ // this function will not load chunk data off disk to check for status
+ // ret null for unknown, empty for empty status on disk or absent from disk
@ -3463,7 +3478,7 @@ index a5df9fee6..6b36bbe87 100644
+ synchronized (world.getChunkProvider().playerChunkMap) {
+ net.minecraft.server.RegionFile file;
+ try {
+ file = world.getChunkProvider().playerChunkMap.getRegionFile(chunkPos, false);
+ file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
@ -3471,75 +3486,67 @@ index a5df9fee6..6b36bbe87 100644
+ return !file.chunkExists(chunkPos) ? ChunkStatus.EMPTY : file.getStatusIfCached(x, z);
+ }
+ }
+ // Paper end
+
public IChunkAccess getUnloadingChunk(int chunkX, int chunkZ) {
PlayerChunk chunkHolder = this.pendingUnload.get(ChunkCoordIntPair.pair(chunkX, chunkZ));
return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow();
@@ -1296,6 +1523,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
boolean isOutsideOfRange(ChunkCoordIntPair chunkcoordintpair) {
// Spigot start
return isOutsideOfRange(chunkcoordintpair, false);
@@ -1300,6 +1513,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
+ public VillagePlace getVillagePlace() { return this.h(); } // Paper - OBFHELPER
protected VillagePlace h() {
return this.n;
return this.m;
}
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
index a8c8ace46..22144eb00 100644
index 7eb87c517..551e91869 100644
--- a/src/main/java/net/minecraft/server/RegionFile.java
+++ b/src/main/java/net/minecraft/server/RegionFile.java
@@ -343,7 +343,7 @@ public class RegionFile implements AutoCloseable {
this.d[j] = i; // Spigot - move this to after the write
@@ -373,7 +373,7 @@ public class RegionFile implements AutoCloseable {
return chunkcoordintpair.j() + chunkcoordintpair.k() * 32;
}
- public void close() throws IOException {
+ public synchronized void close() throws IOException { // Paper - synchronize
+ public synchronized void close() throws IOException { // Paper - Synchronized
this.closed = true; // Paper
this.b.close();
}
try {
this.c();
diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java
index d2b328945..d3d610742 100644
index 1a6be7c6d..9a0fdec47 100644
--- a/src/main/java/net/minecraft/server/RegionFileCache.java
+++ b/src/main/java/net/minecraft/server/RegionFileCache.java
@@ -48,13 +48,13 @@ public abstract class RegionFileCache implements AutoCloseable {
}
@@ -20,7 +20,7 @@ public final class RegionFileCache implements AutoCloseable {
// Paper start
- public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) {
+ public synchronized RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { // Paper - synchronize for async io
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
+ private synchronized RegionFile a(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit // Paper - synchronize for async io
long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ());
RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i);
@@ -338,7 +338,7 @@ public abstract class RegionFileCache implements AutoCloseable {
@@ -138,7 +138,7 @@ public final class RegionFileCache implements AutoCloseable {
}
// CraftBukkit start
- public boolean chunkExists(ChunkCoordIntPair pos) throws IOException {
+ public synchronized boolean chunkExists(ChunkCoordIntPair pos) throws IOException { // Paper - synchronize
copyIfNeeded(pos.x, pos.z); // Paper
RegionFile regionfile = a(pos, true);
RegionFile regionfile = getFile(pos, true);
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 4b3e0c0f0..04b7dab64 100644
index db9f0196b..e7ea04861 100644
--- a/src/main/java/net/minecraft/server/RegionFileSection.java
+++ b/src/main/java/net/minecraft/server/RegionFileSection.java
@@ -24,7 +24,7 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
@@ -25,7 +25,7 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
private static final Logger LOGGER = LogManager.getLogger();
private final Long2ObjectMap<Optional<R>> b = new Long2ObjectOpenHashMap();
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;
@@ -39,8 +39,8 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
@@ -40,8 +40,8 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
}
protected void a(BooleanSupplier booleansupplier) {
@ -3550,7 +3557,7 @@ index 4b3e0c0f0..04b7dab64 100644
this.d(chunkcoordintpair);
}
@@ -94,7 +94,12 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
@@ -95,7 +95,12 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
}
private void b(ChunkCoordIntPair chunkcoordintpair) {
@ -3564,7 +3571,7 @@ index 4b3e0c0f0..04b7dab64 100644
}
@Nullable
@@ -142,7 +147,7 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
@@ -143,7 +148,7 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
}
private void d(ChunkCoordIntPair chunkcoordintpair) {
@ -3573,7 +3580,7 @@ index 4b3e0c0f0..04b7dab64 100644
NBTBase nbtbase = (NBTBase) dynamic.getValue();
if (nbtbase instanceof NBTTagCompound) {
@@ -157,6 +162,20 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
@@ -154,6 +159,20 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
}
@ -3594,7 +3601,7 @@ index 4b3e0c0f0..04b7dab64 100644
private <T> Dynamic<T> a(ChunkCoordIntPair chunkcoordintpair, DynamicOps<T> dynamicops) {
Map<T, T> map = Maps.newHashMap();
@@ -193,9 +212,9 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
@@ -190,9 +209,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) {
@ -3606,9 +3613,9 @@ index 4b3e0c0f0..04b7dab64 100644
this.d(chunkcoordintpair);
return;
}
@@ -203,4 +222,21 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
}
@@ -204,4 +223,21 @@ public class RegionFileSection<R extends MinecraftSerializable> implements AutoC
public void close() throws IOException {
this.b.close();
}
+
+ // Paper start - get data function
@ -3629,7 +3636,7 @@ index 4b3e0c0f0..04b7dab64 100644
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/server/TicketType.java b/src/main/java/net/minecraft/server/TicketType.java
index 9c114d2d3..e3150f85a 100644
index 335b64435..481d95480 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> {
@ -3641,12 +3648,12 @@ index 9c114d2d3..e3150f85a 100644
public static <T> TicketType<T> a(String s, Comparator<T> comparator) {
return new TicketType<>(s, comparator, 0L);
diff --git a/src/main/java/net/minecraft/server/VillagePlace.java b/src/main/java/net/minecraft/server/VillagePlace.java
index 316959064..0e98b7803 100644
index c999f8c9b..b59ef1a63 100644
--- a/src/main/java/net/minecraft/server/VillagePlace.java
+++ b/src/main/java/net/minecraft/server/VillagePlace.java
@@ -20,8 +20,16 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
@@ -24,8 +24,16 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
private final VillagePlace.a a = new VillagePlace.a();
private final LongSet b = new LongOpenHashSet();
+ private final WorldServer world; // Paper
+
@ -3661,7 +3668,7 @@ index 316959064..0e98b7803 100644
}
public void a(BlockPosition blockposition, VillagePlaceType villageplacetype) {
@@ -121,7 +129,23 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
@@ -129,7 +137,23 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
@Override
public void a(BooleanSupplier booleansupplier) {
@ -3686,7 +3693,7 @@ index 316959064..0e98b7803 100644
this.a.a();
}
@@ -207,6 +231,42 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
@@ -229,6 +253,42 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
}
}
@ -3730,10 +3737,10 @@ index 316959064..0e98b7803 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 133095665..5e0f6a105 100644
index 8ea9b34a1..fecbe7914 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -79,6 +79,79 @@ public class WorldServer extends World {
@@ -81,6 +81,79 @@ public class WorldServer extends World {
return new Throwable(entity + " Added to world at " + new java.util.Date());
}
@ -3813,7 +3820,7 @@ index 133095665..5e0f6a105 100644
// Add env and gen to constructor
public WorldServer(MinecraftServer minecraftserver, Executor executor, WorldNBTStorage worldnbtstorage, WorldData worlddata, DimensionManager dimensionmanager, GameProfilerFiller gameprofilerfiller, WorldLoadListener worldloadlistener, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
super(worlddata, dimensionmanager, (world, worldprovider) -> {
@@ -122,6 +195,8 @@ public class WorldServer extends World {
@@ -124,6 +197,8 @@ public class WorldServer extends World {
this.mobSpawnerTrader = this.worldProvider.getDimensionManager().getType() == DimensionManager.OVERWORLD ? new MobSpawnerTrader(this) : null; // CraftBukkit - getType()
this.getServer().addWorld(this.getWorld()); // CraftBukkit
@ -3823,16 +3830,16 @@ index 133095665..5e0f6a105 100644
// CraftBukkit start
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 2227de3bf..243722b67 100644
index 7d509856b..7abad24f0 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -554,22 +554,23 @@ public class CraftWorld implements World {
@@ -555,22 +555,23 @@ public class CraftWorld implements World {
return true;
}
- net.minecraft.server.RegionFile file;
- try {
- file = world.getChunkProvider().playerChunkMap.getRegionFile(chunkPos, false);
- file = world.getChunkProvider().playerChunkMap.getIOWorker().getRegionFileCache().getFile(chunkPos, false);
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- }
@ -3858,8 +3865,8 @@ index 2227de3bf..243722b67 100644
// fall through to load
// we do this so we do not re-read the chunk data on disk
@@ -2344,6 +2345,25 @@ public class CraftWorld implements World {
return persistentRaid.a.values().stream().map(CraftRaid::new).collect(Collectors.toList());
@@ -2354,6 +2355,25 @@ public class CraftWorld implements World {
return persistentRaid.raids.values().stream().map(CraftRaid::new).collect(Collectors.toList());
}
+ // Paper start
@ -3913,5 +3920,5 @@ index a1d93200e..6ca0ebfde 100644
log.log( Level.SEVERE, "------------------------------" );
//
--
2.24.0
2.24.1

View file

@ -1,4 +1,4 @@
From b0adc134e06f684b0d3fa9a17033c9eee9906da0 Mon Sep 17 00:00:00 2001
From 74d4e0d23d00c6094227c4af53d951b7db41866a Mon Sep 17 00:00:00 2001
From: kickash32 <kickash32@gmail.com>
Date: Mon, 3 Jun 2019 02:02:39 -0400
Subject: [PATCH] Implement alternative item-despawn-rate

View file

@ -1,4 +1,4 @@
From 89e83fa62fab94319e8639bbdadf0c9656bcaef1 Mon Sep 17 00:00:00 2001
From 4e401f46a0da7fb3e383d51e6a23e7e09db0dd88 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@burngames.net>
Date: Sun, 14 Jul 2019 21:05:03 -0500
Subject: [PATCH] Do less work if we have a custom Bukkit generator
@ -7,10 +7,10 @@ If the Bukkit generator already has a spawn, use it immediately instead
of spending time generating one that we won't use
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 8ea9b34a1..7b89b509a 100644
index fecbe7914..a08308a12 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -707,12 +707,13 @@ public class WorldServer extends World {
@@ -782,12 +782,13 @@ public class WorldServer extends World {
} else if (this.worldData.getType() == WorldType.DEBUG_ALL_BLOCK_STATES) {
this.worldData.setSpawn(BlockPosition.ZERO.up());
} else {
@ -30,7 +30,7 @@ index 8ea9b34a1..7b89b509a 100644
// CraftBukkit start
if (this.generator != null) {
Random rand = new Random(this.getSeed());
@@ -729,6 +730,13 @@ public class WorldServer extends World {
@@ -804,6 +805,13 @@ public class WorldServer extends World {
}
// CraftBukkit end

View file

@ -1,4 +1,4 @@
From 239628e9cf816978cd8a390b2584aa8d484f279e Mon Sep 17 00:00:00 2001
From 1d6c2900cc2fd68d9a667492a50bf5b9a4fc925f Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Tue, 13 Aug 2019 06:35:17 -0700
Subject: [PATCH] Fix MC-158900

View file

@ -1,31 +1,29 @@
From e091c4269f0c72f45f9a3de946e7777bc83933d0 Mon Sep 17 00:00:00 2001
From 86be231a037cbcb9e168afa85e02d3dd83fcc97b Mon Sep 17 00:00:00 2001
From: kickash32 <kickash32@gmail.com>
Date: Mon, 19 Aug 2019 01:27:58 +0500
Subject: [PATCH] implement optional per player mob spawns
diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java
index 3a79cde59..431534f4f 100644
index 8de6c4816..e25544f11 100644
--- a/src/main/java/co/aikar/timings/WorldTimingsHandler.java
+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java
@@ -63,6 +63,8 @@ public class WorldTimingsHandler {
@@ -62,6 +62,7 @@ public class WorldTimingsHandler {
public final Timing miscMobSpawning;
public final Timing chunkRangeCheckBig;
public final Timing chunkRangeCheckSmall;
+ public final Timing playerMobDistanceMapUpdate;
+
public WorldTimingsHandler(World server) {
String name = server.worldData.getName() +" - ";
@@ -122,6 +124,8 @@ public class WorldTimingsHandler {
public final Timing poiUnload;
public final Timing chunkUnload;
@@ -133,6 +134,7 @@ public class WorldTimingsHandler {
miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc");
chunkRangeCheckBig = Timings.ofSafe(name + "Chunk Tick Range - Big");
chunkRangeCheckSmall = Timings.ofSafe(name + "Chunk Tick Range - Small");
+
+ playerMobDistanceMapUpdate = Timings.ofSafe(name + "Per Player Mob Spawning - Distance Map Update");
}
public static Timing getTickList(WorldServer worldserver, String timingsType) {
poiUnload = Timings.ofSafe(name + "Chunk unload - POI");
chunkUnload = Timings.ofSafe(name + "Chunk unload - Chunk");
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index d0f5b2ab7..f63525d67 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@ -547,10 +545,10 @@ index 000000000..4f13d3ff8
+ }
+}
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index f138b112f..109c6ada8 100644
index 1f6b1c4f1..cbe4b23e1 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -408,7 +408,22 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -554,7 +554,22 @@ public class ChunkProviderServer extends IChunkProvider {
this.world.timings.countNaturalMobs.startTiming(); // Paper - timings
int l = this.chunkMapDistance.b();
EnumCreatureType[] aenumcreaturetype = EnumCreatureType.values();
@ -574,7 +572,7 @@ index f138b112f..109c6ada8 100644
this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings
this.world.getMethodProfiler().exit();
@@ -473,8 +488,23 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -619,8 +634,23 @@ public class ChunkProviderServer extends IChunkProvider {
if (enumcreaturetype != EnumCreatureType.MISC && (!enumcreaturetype.c() || this.allowAnimals) && (enumcreaturetype.c() || this.allowMonsters) && (!enumcreaturetype.d() || flag2)) {
int k1 = limit * l / ChunkProviderServer.b; // CraftBukkit - use per-world limits
@ -645,7 +643,7 @@ index d49ad0308..2fb04e3e9 100644
return this.bb;
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index fc6436c4f..9915c2443 100644
index 66bd402e9..041fedcfa 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -78,7 +78,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -660,7 +658,7 @@ index fc6436c4f..9915c2443 100644
public final CallbackExecutor callbackExecutor = new CallbackExecutor();
@@ -136,6 +137,24 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.l = supplier;
this.m = new VillagePlace(new File(this.w, "poi"), datafixer);
this.m = new VillagePlace(new File(this.w, "poi"), datafixer, this.world); // Paper
this.setViewDistance(i);
+ this.playerMobDistanceMap = this.world.paperConfig.perPlayerMobSpawns ? new com.destroystokyo.paper.util.PlayerMobDistanceMap() : null; // Paper
+ }
@ -757,10 +755,10 @@ index e168c528c..56dabbc15 100644
@Nullable
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 7b89b509a..fd42390d4 100644
index a08308a12..4da5c8982 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -923,7 +923,20 @@ public class WorldServer extends World {
@@ -998,7 +998,20 @@ public class WorldServer extends World {
}
public Object2IntMap<EnumCreatureType> l() {
@ -782,7 +780,7 @@ index 7b89b509a..fd42390d4 100644
ObjectIterator objectiterator = this.entitiesById.values().iterator();
while (objectiterator.hasNext()) {
@@ -948,11 +961,16 @@ public class WorldServer extends World {
@@ -1023,11 +1036,16 @@ public class WorldServer extends World {
continue;
}
// Paper end
@ -802,5 +800,5 @@ index 7b89b509a..fd42390d4 100644
@Override
--
2.17.1
2.24.1

View file

@ -1,11 +1,11 @@
From fb0baab3741afc9ca8a94a729e69c0d0cd9270de Mon Sep 17 00:00:00 2001
From cb90df7c7d0d0a81be49f2aea7ef317d2408ef3b Mon Sep 17 00:00:00 2001
From: kickash32 <kickash32@gmail.com>
Date: Mon, 19 Aug 2019 19:42:35 +0500
Subject: [PATCH] Prevent consuming the wrong itemstack
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index 1b5acf77e..d04ea03bc 100644
index aa0118a7c..4690ef840 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -2890,10 +2890,13 @@ public abstract class EntityLiving extends Entity {

View file

@ -1,4 +1,4 @@
From c87228b4a333ccebd69a817b127b39cf09d18a14 Mon Sep 17 00:00:00 2001
From 8ff3bafc29dfc11e923bb86432794bfd106b6c8f Mon Sep 17 00:00:00 2001
From: kickash32 <kickash32@gmail.com>
Date: Wed, 21 Aug 2019 23:57:32 +0500
Subject: [PATCH] only add passanger entities once from spawners

View file

@ -1,4 +1,4 @@
From d0f11a5cd0400709f143f80aafd4432f51bd5b06 Mon Sep 17 00:00:00 2001
From 828a7c3535eb0e5f5b5200743c8e542b1395c238 Mon Sep 17 00:00:00 2001
From: Michael Himing <mhiming@gmail.com>
Date: Mon, 9 Sep 2019 13:21:17 +1000
Subject: [PATCH] Fix nether portal creation

View file

@ -1,4 +1,4 @@
From d2c96cd65fa38113fc91591b2d62bbbad12e019c Mon Sep 17 00:00:00 2001
From 4ea9cf8cd97ba06ad09271b7f139293726ab61df Mon Sep 17 00:00:00 2001
From: Byteflux <byte@byteflux.net>
Date: Wed, 2 Mar 2016 02:17:54 -0600
Subject: [PATCH] Generator Settings

View file

@ -1,4 +1,4 @@
From b94bbd71db373ef1099062dc8a7a046675a85e58 Mon Sep 17 00:00:00 2001
From 3c9973d39ac3b4fd3fbe7fb79de0e48e93ae9de1 Mon Sep 17 00:00:00 2001
From: Phoenix616 <mail@moep.tv>
Date: Sun, 15 Sep 2019 11:32:32 -0500
Subject: [PATCH] Fix zero-tick instant grow farms MC-113809
@ -45,7 +45,7 @@ index c482aad3e..02c548dd9 100644
int i = this.b(worldserver, blockposition) + 1;
diff --git a/src/main/java/net/minecraft/server/BlockCactus.java b/src/main/java/net/minecraft/server/BlockCactus.java
index 4c82fe335..44ce67eb8 100644
index e0974e256..3524fcb92 100644
--- a/src/main/java/net/minecraft/server/BlockCactus.java
+++ b/src/main/java/net/minecraft/server/BlockCactus.java
@@ -21,6 +21,7 @@ public class BlockCactus extends Block {
@ -81,10 +81,10 @@ index 55b07444e..3bc3c5aa2 100644
for (i = 1; worldserver.getType(blockposition.down(i)).getBlock() == this; ++i) {
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index fd42390d4..4c53f8063 100644
index 4da5c8982..b15fb2b63 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -603,7 +603,9 @@ public class WorldServer extends World {
@@ -678,7 +678,9 @@ public class WorldServer extends World {
IBlockData iblockdata = this.getType(nextticklistentry.a);
if (iblockdata.getBlock() == nextticklistentry.b()) {
@ -95,5 +95,5 @@ index fd42390d4..4c53f8063 100644
}
--
2.17.1
2.24.1

View file

@ -1,4 +1,4 @@
From 73a0d079796aba53e42b420ff913425da4ac2ded Mon Sep 17 00:00:00 2001
From d3111a6f265a2e5c00d8ad2af14ee199ab1af5d4 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Tue, 24 Sep 2019 16:03:00 -0700
Subject: [PATCH] Fix MC-161754

View file

@ -1,4 +1,4 @@
From f723f1253331573ac4ce13e7d058525122971fa9 Mon Sep 17 00:00:00 2001
From 4dfb47aa6a180f1434d9704e164c1e6261786dad Mon Sep 17 00:00:00 2001
From: wea_ondara <wea_ondara@alpenblock.net>
Date: Thu, 10 Oct 2019 11:29:42 +0200
Subject: [PATCH] Performance improvement for Chunk.getEntities

View file

@ -1,4 +1,4 @@
From 8783648a82e2eab90215942e6d11e39754345399 Mon Sep 17 00:00:00 2001
From 27992b8d3ae285409e31a19738a2cbbfdbdd71df Mon Sep 17 00:00:00 2001
From: MisterErwin <git@askarian.net>
Date: Wed, 30 Oct 2019 16:57:54 +0100
Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and
@ -6,10 +6,10 @@ Subject: [PATCH] Fix spawning of hanging entities that are not ItemFrames and
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index b1ae19be7..cd519a546 100644
index 7abad24f0..73e987671 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1755,7 +1755,12 @@ public class CraftWorld implements World {
@@ -1800,7 +1800,12 @@ public class CraftWorld implements World {
height = 9;
}

View file

@ -1,4 +1,4 @@
From 5e78d0d353c8f2ff964045c24f4d4cda5db56677 Mon Sep 17 00:00:00 2001
From 60e3e0eea1101a1051eae557cf50ae777180319a Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Sat, 20 Apr 2019 19:47:34 -0500
Subject: [PATCH] Expose the internal current tick

View file

@ -1,11 +1,11 @@
From e67d6afa674eaf53579e5776b5726d5984fda48e Mon Sep 17 00:00:00 2001
From e6a5a6c1ab381478ddf24920052cdfeb4c66498d Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Wed, 9 Oct 2019 21:51:43 -0500
Subject: [PATCH] Fix stuck in sneak when changing worlds (MC-10657)
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 19ba79c65..453f02561 100644
index c9492ed37..95a5643a6 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -946,6 +946,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting {

View file

@ -1,4 +1,4 @@
From 7ef6304dd7223769140767de11372d070f6c7728 Mon Sep 17 00:00:00 2001
From 70cde0b9dac1d0a9adca3a68c8d3eca49831aca4 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <blake.galbreath@gmail.com>
Date: Wed, 9 Oct 2019 21:46:15 -0500
Subject: [PATCH] Add option to disable pillager patrols

View file

@ -1,4 +1,4 @@
From 265310d0510556ead2756e093e16cf2b1dfa35ba Mon Sep 17 00:00:00 2001
From 642eba593e0020c47db91ab5c26bed1659c9c596 Mon Sep 17 00:00:00 2001
From: Lukasz Derlatka <toranktto@gmail.com>
Date: Mon, 11 Nov 2019 16:08:13 +0100
Subject: [PATCH] Fix AssertionError when player hand set to empty type
@ -7,7 +7,7 @@ Fixes an AssertionError when setting the player's item in hand to null or a new
Fixes GH-2718
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index d04ea03bc..5431f8a8d 100644
index 4690ef840..90fc7febe 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -1885,6 +1885,7 @@ public abstract class EntityLiving extends Entity {