diff --git a/Spigot-Server-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/Spigot-Server-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch index 4e2e8be74e..c1e1a69e55 100644 --- a/Spigot-Server-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ b/Spigot-Server-Patches/Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch @@ -16,7 +16,7 @@ intent to remove) and replace it with two new methods, clearly named and documented as to their purpose. diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 57c6455bd8..541461275c 100644 +index 71ad35f710..2341638617 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -28,7 +28,7 @@ index 57c6455bd8..541461275c 100644 public boolean queueHealthUpdatePacket = false; public net.minecraft.server.PacketPlayOutUpdateHealth queuedHealthUpdatePacket; diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index ec760325ba..135d25abd2 100644 +index 8233292688..109c27b647 100644 --- a/src/main/java/net/minecraft/server/PlayerList.java +++ b/src/main/java/net/minecraft/server/PlayerList.java @@ -0,0 +0,0 @@ public abstract class PlayerList { @@ -40,7 +40,7 @@ index ec760325ba..135d25abd2 100644 UserCache usercache = this.server.getUserCache(); GameProfile gameprofile1 = usercache.a(gameprofile.getId()); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -index fbdb2df27d..e1973c5d67 100644 +index 294f3de00c..a3c6032d48 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java @@ -0,0 +0,0 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa @@ -106,7 +106,7 @@ index fbdb2df27d..e1973c5d67 100644 NBTTagCompound data = getData(); if (data == null) return null; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 8d32982c53..a03796cd5e 100644 +index 5f752784d5..90e61097aa 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/Spigot-Server-Patches/Add-Heightmap-API.patch b/Spigot-Server-Patches/Add-Heightmap-API.patch index 62bb64cc85..c94b614b14 100644 --- a/Spigot-Server-Patches/Add-Heightmap-API.patch +++ b/Spigot-Server-Patches/Add-Heightmap-API.patch @@ -5,23 +5,26 @@ Subject: [PATCH] Add Heightmap API diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index b940f95bdb..d20f6ac7e4 100644 +index a038945b36..54a03fb102 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java -@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc +@@ -0,0 +0,0 @@ public abstract class World implements IIBlockAccess, GeneratorAccess, AutoClose } } +- @Override +- public int a(HeightMap.Type heightmap_type, int i, int j) { + public final int getHighestBlockY(final HeightMap.Type heightmap, final int x, final int z) { return this.a(heightmap, x, z); } // Paper - OBFHELPER - public int a(HeightMap.Type heightmap_type, int i, int j) { ++ @Override public int a(HeightMap.Type heightmap_type, int i, int j) { // Paper - OBFHELPER int k; + if (i >= -30000000 && j >= -30000000 && i < 30000000 && j < 30000000) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 40ee34675c..457aa5a3f0 100644 +index 5e672ae2e4..d8ea548383 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -0,0 +0,0 @@ public class CraftWorld implements World { - return world.getHighestBlockYAt(HeightMap.Type.LIGHT_BLOCKING, new BlockPosition(x, 0, z)).getY(); + return world.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING, new BlockPosition(x, 0, z)).getY(); } + // Paper start - Implement heightmap api @@ -31,7 +34,8 @@ index 40ee34675c..457aa5a3f0 100644 + + switch (heightmap) { + case LIGHT_BLOCKING: -+ return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); ++ throw new UnsupportedOperationException(); // TODO ++ //return this.world.getHighestBlockY(HeightMap.Type.LIGHT_BLOCKING, x, z); + case ANY: + return this.world.getHighestBlockY(HeightMap.Type.WORLD_SURFACE, x, z); + case SOLID: diff --git a/Spigot-Server-Patches/Add-PlayerConnectionCloseEvent.patch b/Spigot-Server-Patches/Add-PlayerConnectionCloseEvent.patch index 62a91f493b..3680d5736b 100644 --- a/Spigot-Server-Patches/Add-PlayerConnectionCloseEvent.patch +++ b/Spigot-Server-Patches/Add-PlayerConnectionCloseEvent.patch @@ -34,33 +34,25 @@ how PlayerPreLoginEvent interacts with PlayerConnectionCloseEvent is undefined. diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java -index ca76f2a380..dfe7a029f8 100644 +index 5d46a975e3..9e4bc24058 100644 --- a/src/main/java/net/minecraft/server/LoginListener.java +++ b/src/main/java/net/minecraft/server/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener, ITickable { +@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { private final byte[] e = new byte[4]; private final MinecraftServer server; public final NetworkManager networkManager; - private LoginListener.EnumProtocolState g; + private LoginListener.EnumProtocolState g; public final LoginListener.EnumProtocolState getLoginState() { return this.g; }; // Paper - OBFHELPER private int h; -- private GameProfile i; private void setGameProfile(GameProfile profile) { i = profile; } private GameProfile getGameProfile() { return i; } // Paper - OBFHELPER -+ private GameProfile i; private void setGameProfile(GameProfile profile) { i = profile; } public final GameProfile getGameProfile() { return i; } // Paper - OBFHELPER +- private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } private GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER ++ private GameProfile i; private void setGameProfile(final GameProfile profile) { this.i = profile; } public GameProfile getGameProfile() { return this.i; } // Paper - OBFHELPER private final String j; private SecretKey loginKey; private EntityPlayer l; diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java -index 0b8796d0ae..553637239c 100644 +index 2c28b97d81..1b0643c27f 100644 --- a/src/main/java/net/minecraft/server/NetworkManager.java +++ b/src/main/java/net/minecraft/server/NetworkManager.java -@@ -0,0 +0,0 @@ import io.netty.handler.timeout.TimeoutException; - import io.netty.util.AttributeKey; - import io.netty.util.concurrent.Future; - import io.netty.util.concurrent.GenericFutureListener; -+ - import java.net.SocketAddress; - import java.util.Queue; - import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { this.i().a(new ChatMessage("multiplayer.disconnect.generic", new Object[0])); } diff --git a/Spigot-Server-Patches/Allow-Saving-of-Oversized-Chunks.patch b/Spigot-Server-Patches/Allow-Saving-of-Oversized-Chunks.patch index d0239df3ea..3c4513eb13 100644 --- a/Spigot-Server-Patches/Allow-Saving-of-Oversized-Chunks.patch +++ b/Spigot-Server-Patches/Allow-Saving-of-Oversized-Chunks.patch @@ -31,7 +31,7 @@ this fix, as the data will remain in the oversized file. Once the server returns to a jar with this fix, the data will be restored. diff --git a/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java b/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java -index 12268f87b9..e1f7e06ab2 100644 +index 9fd8a75dae..d49afd622e 100644 --- a/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java +++ b/src/main/java/net/minecraft/server/NBTCompressedStreamTools.java @@ -0,0 +0,0 @@ public class NBTCompressedStreamTools { @@ -50,59 +50,81 @@ index 12268f87b9..e1f7e06ab2 100644 public static void a(NBTTagCompound nbttagcompound, DataOutput dataoutput) throws IOException { a((NBTBase) nbttagcompound, dataoutput); } +diff --git a/src/main/java/net/minecraft/server/NBTTagList.java b/src/main/java/net/minecraft/server/NBTTagList.java +index b7c94fe238..80eea5dfbd 100644 +--- a/src/main/java/net/minecraft/server/NBTTagList.java ++++ b/src/main/java/net/minecraft/server/NBTTagList.java +@@ -0,0 +0,0 @@ import java.util.Objects; + + public class NBTTagList extends NBTList { + +- private List list = Lists.newArrayList(); ++ List list = Lists.newArrayList(); // Paper - private -> package + private byte type = 0; + + public NBTTagList() {} diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java -index c20511588d..82f7af46f8 100644 +index e68f901943..995a893774 100644 --- a/src/main/java/net/minecraft/server/RegionFile.java +++ b/src/main/java/net/minecraft/server/RegionFile.java -@@ -0,0 +0,0 @@ public class RegionFile { - } - header.clear(); - java.nio.IntBuffer headerAsInts = header.asIntBuffer(); -+ initOversizedState(); - // Paper End +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + // Minecraft is limited to 256 sections per chunk. So 1MB. This can easily be overriden. + // So we extend this to use the REAL size when the count is maxed by seeking to that section and reading the length. + private static final boolean ENABLE_EXTENDED_SAVE = Boolean.parseBoolean(System.getProperty("net.minecraft.server.RegionFile.enableExtendedSave", "true")); +- private final File file; ++ final File file; // Paper - private -> package + // Spigot end + private static final byte[] a = new byte[4096]; + private final RandomAccessFile b; private RandomAccessFile getDataFile() { return this.b; } // Paper - OBFHELPER +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + } + header.clear(); + java.nio.IntBuffer headerAsInts = header.asIntBuffer(); ++ initOversizedState(); + // Paper End - for (j = 0; j < 1024; ++j) { -@@ -0,0 +0,0 @@ public class RegionFile { - this.c.seek(j * 4 + 4); // Go back to where we were - } + int k; +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + this.b.seek(j * 4 + 4); // Go back to where we were } -- if (k > 0 && (k >> 8) > 1 && (k >> 8) + (k & 255) <= this.f.size()) { // Paper >= 1 as 0/1 are the headers, and negative isnt valid -+ if (k > 0 && (k >> 8) > 1 && (k >> 8) + (length) <= this.f.size()) { // Paper >= 1 as 0/1 are the headers, and negative isnt valid - for (int l = 0; l < (length); ++l) { - // Spigot end - this.f.set((k >> 8) + l, false); -@@ -0,0 +0,0 @@ public class RegionFile { + } +- if (k > 0 && (k >> 8) > 1 && (k >> 8) + (k & 255) <= this.e.size()) { // Paper >= 1 as 0/1 are the headers, and negative isnt valid ++ if (k > 0 && (k >> 8) > 1 && (k >> 8) + (length) <= this.e.size()) { // Paper >= 1 as 0/1 are the headers, and negative isnt valid + for (int l = 0; l < (length); ++l) { + // Spigot end + this.e.set((k >> 8) + l, false); +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { } @Nullable -- public synchronized DataInputStream a(int i, int j) { -+ public synchronized DataInputStream getReadStream(int i, int j) { return a(i, j); } @Nullable public synchronized DataInputStream a(int i, int j) { // Paper - OBFHELPER - if (this.e(i, j)) { - return null; - } else { -@@ -0,0 +0,0 @@ public class RegionFile { +- public synchronized DataInputStream a(ChunkCoordIntPair chunkcoordintpair) { ++ public synchronized DataInputStream getReadStream(ChunkCoordIntPair chunkcoordintpair) { return this.a(chunkcoordintpair); } public synchronized DataInputStream a(ChunkCoordIntPair chunkcoordintpair) { // Paper - OBFHELPER + try { + int i = this.getOffset(chunkcoordintpair); + +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + } } - @Nullable -- public DataOutputStream c(int i, int j) { -- return this.e(i, j) ? null : new DataOutputStream(new BufferedOutputStream(new DeflaterOutputStream(new RegionFile.ChunkBuffer(i, j)))); -+ public DataOutputStream getWriteStream(int i, int j) { return c(i, j); } @Nullable public DataOutputStream c(int i, int j) { // Paper - OBFHELPER -+ return this.e(i, j) ? null : new DataOutputStream(new RegionFile.ChunkBuffer(i, j)); // Paper - remove middleware, move deflate to .close() for dynamic levels +- public DataOutputStream c(ChunkCoordIntPair chunkcoordintpair) { +- return new DataOutputStream(new BufferedOutputStream(new DeflaterOutputStream(new RegionFile.ChunkBuffer(chunkcoordintpair)))); ++ public DataOutputStream getWriteStream(ChunkCoordIntPair chunkcoordintpair) { return this.c(chunkcoordintpair); } public DataOutputStream c(ChunkCoordIntPair chunkcoordintpair) { // Paper - OBFHELPER ++ return new DataOutputStream(new RegionFile.ChunkBuffer(chunkcoordintpair)); // Paper - remove middleware, move deflate to .close() for dynamic levels } - protected synchronized void a(int i, int j, byte[] abyte, int k) { -@@ -0,0 +0,0 @@ public class RegionFile { + protected synchronized void a(ChunkCoordIntPair chunkcoordintpair, byte[] abyte, int i) { +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - if (k1 >= 256) { + if (i1 >= 256) { // Spigot start -- if (!ENABLE_EXTENDED_SAVE) return; -+ if (!USE_SPIGOT_OVERSIZED_METHOD && !RegionFileCache.isOverzealous()) throw new ChunkTooLargeException(i, j, k1); // Paper - throw error instead - org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.WARNING,"Large Chunk Detected: ({0}, {1}) Size: {2} {3}", new Object[]{i, j, k1, this.b}); -+ if (!ENABLE_EXTENDED_SAVE) return; +- if (!ENABLE_EXTENDED_SAVE) throw new RuntimeException(String.format("Too big to save, %d > 1048576", i)); ++ if (!USE_SPIGOT_OVERSIZED_METHOD && !RegionFileCache.isOverzealous()) throw new ChunkTooLargeException(chunkcoordintpair.x, chunkcoordintpair.z, l); // Paper - throw error instead + org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.WARNING,"Large Chunk Detected: ({0}) Size: {1} {2}", new Object[]{chunkcoordintpair, i1, this.file}); ++ if (!ENABLE_EXTENDED_SAVE) throw new RuntimeException(String.format("Too big to save, %d > 1048576", i)); // Paper - move after our check // Spigot end } -@@ -0,0 +0,0 @@ public class RegionFile { +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { logger.error("Error backing up corrupt file" + file.getAbsolutePath(), e); } } @@ -159,11 +181,11 @@ index c20511588d..82f7af46f8 100644 + } + + private File getOversizedMetaFile() { -+ return new File(getFile().getParentFile(), getFile().getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); ++ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + ".oversized.nbt"); + } + + private File getOversizedFile(int x, int z) { -+ return new File(this.getFile().getParentFile(), this.getFile().getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); ++ return new File(this.file.getParentFile(), this.file.getName().replaceAll("\\.mca$", "") + "_oversized_" + x + "_" + z + ".nbt"); + } + + void writeOversizedData(int x, int z, NBTTagCompound oversizedData) throws IOException { @@ -193,7 +215,7 @@ index c20511588d..82f7af46f8 100644 + } + public class ChunkTooLargeException extends RuntimeException { + public ChunkTooLargeException(int x, int z, int sectors) { -+ super("Chunk " + x + "," + z + " of " + getFile().toString() + " is too large (" + sectors + "/256)"); ++ super("Chunk " + x + "," + z + " of " + RegionFile.this.file.toString() + " is too large (" + sectors + "/255)"); + } + } + private static class DirectByteArrayOutputStream extends ByteArrayOutputStream { @@ -212,12 +234,12 @@ index c20511588d..82f7af46f8 100644 // Paper end class ChunkBuffer extends ByteArrayOutputStream { -@@ -0,0 +0,0 @@ public class RegionFile { - this.c = j; +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + this.b = chunkcoordintpair; } - public void close() { -- RegionFile.this.a(this.b, this.c, this.buf, this.count); +- RegionFile.this.a(this.b, this.buf, this.count); + public void close() throws IOException { + // Paper start - apply dynamic compression + int origLength = this.count; @@ -226,9 +248,9 @@ index c20511588d..82f7af46f8 100644 + byte[] bytes = out.getBuffer(); + int length = out.size(); + -+ RegionFile.this.a(this.b, this.c, bytes, length); // Paper - change to bytes/length -+ } -+ } ++ RegionFile.this.a(this.b, bytes, length); // Paper - change to bytes/length + } + } + + private static final byte[] compressionBuffer = new byte[1024 * 64]; // 64k fits most standard chunks input size even, ideally 1 pass through zlib + private static final java.util.zip.Deflater deflater = new java.util.zip.Deflater(); @@ -245,27 +267,28 @@ index c20511588d..82f7af46f8 100644 + out.close(); + deflater.reset(); + return out; - } - } ++ } ++ } + // Paper end + } diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java -index 8c8b7cbab5..17e76815ad 100644 +index 1b12a16113..6893f3cd34 100644 --- a/src/main/java/net/minecraft/server/RegionFileCache.java +++ b/src/main/java/net/minecraft/server/RegionFileCache.java -@@ -0,0 +0,0 @@ public class RegionFileCache { - - public static final Map cache = new LinkedHashMap(PaperConfig.regionFileCacheSize, 0.75f, true); // Paper - HashMap -> LinkedHashMap - -+ public static synchronized RegionFile getRegionFile(File file, int i, int j) { return a(file, i, j); } // Paper - OBFHELPER - public static synchronized RegionFile a(File file, int i, int j) { - File file1 = new File(file, "region"); - File file2 = new File(file1, "r." + (i >> 5) + "." + (j >> 5) + ".mca"); -@@ -0,0 +0,0 @@ public class RegionFileCache { - public static synchronized boolean hasRegionFile(File file, int i, int j) { - return RegionFileCache.cache.containsKey(getRegionFileName(file, i, j)); +@@ -0,0 +0,0 @@ public abstract class RegionFileCache implements AutoCloseable { + // Paper start } + ++ public RegionFile getRegionFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { return this.a(chunkcoordintpair, existingOnly); } // Paper - OBFHELPER + private RegionFile a(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit + long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); + RegionFile regionfile = (RegionFile) this.cache.getAndMoveToFirst(i); +@@ -0,0 +0,0 @@ public abstract class RegionFileCache implements AutoCloseable { + public synchronized boolean hasRegionFile(File file, int i, int j) { + return cache.containsKey(getRegionFileName(file, i, j)); + } ++ // Paper start + private static void printOversizedLog(String msg, File file, int x, int z) { + org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); + } @@ -285,23 +308,26 @@ index 8c8b7cbab5..17e76815ad 100644 + return SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD; + } + -+ private static void writeRegion(File file, int x, int z, NBTTagCompound nbttagcompound) throws IOException { -+ RegionFile regionfile = getRegionFile(file, x, z); ++ private void writeRegion(ChunkCoordIntPair chunk, NBTTagCompound nbttagcompound) throws IOException { ++ RegionFile regionfile = getRegionFile(chunk, false); + -+ DataOutputStream out = regionfile.getWriteStream(x & 31, z & 31); ++ int chunkX = chunk.x; ++ int chunkZ = chunk.z; ++ ++ DataOutputStream out = regionfile.getWriteStream(chunk); + try { + NBTCompressedStreamTools.writeNBT(nbttagcompound, out); + out.close(); -+ regionfile.setOversized(x, z, false); ++ regionfile.setOversized(chunkX, chunkZ, false); + } catch (RegionFile.ChunkTooLargeException ignored) { -+ printOversizedLog("ChunkTooLarge! Someone is trying to duplicate.", file, x, z); ++ printOversizedLog("ChunkTooLarge! Someone is trying to duplicate.", regionfile.file, chunkX, chunkZ); + // Clone as we are now modifying it, don't want to corrupt the pending save state + nbttagcompound = nbttagcompound.clone(); + // Filter out TileEntities and Entities + NBTTagCompound oversizedData = filterChunkData(nbttagcompound); + //noinspection SynchronizationOnLocalVariableOrMethodParameter + synchronized (regionfile) { -+ out = regionfile.getWriteStream(x & 31, z & 31); ++ out = regionfile.getWriteStream(chunk); + NBTCompressedStreamTools.writeNBT(nbttagcompound, out); + try { + out.close(); @@ -310,13 +336,13 @@ index 8c8b7cbab5..17e76815ad 100644 + resetFilterThresholds(); + } + } catch (RegionFile.ChunkTooLargeException e) { -+ printOversizedLog("ChunkTooLarge even after reduction. Trying in overzealous mode.", file, x, z); ++ printOversizedLog("ChunkTooLarge even after reduction. Trying in overzealous mode.", regionfile.file, chunkX, chunkZ); + // Eek, major fail. We have retry logic, so reduce threshholds and fall back + SIZE_THRESHOLD = OVERZEALOUS_THRESHOLD; + throw e; + } + -+ regionfile.writeOversizedData(x, z, oversizedData); ++ regionfile.writeOversizedData(chunkX, chunkZ, oversizedData); + } + } + } @@ -335,7 +361,7 @@ index 8c8b7cbab5..17e76815ad 100644 + NBTTagList list = level.getList(key, 10); + NBTTagList newList = extra.getList(key, 10); + int totalSize = 0; -+ for (Iterator iterator = list.list.iterator(); iterator.hasNext(); ) { ++ for (java.util.Iterator iterator = list.list.iterator(); iterator.hasNext();) { + NBTBase object = iterator.next(); + int nbtSize = getNBTSize(object); + if (nbtSize > SIZE_THRESHOLD || (SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD && totalSize > OVERZEALOUS_TOTAL_THRESHOLD)) { @@ -350,10 +376,10 @@ index 8c8b7cbab5..17e76815ad 100644 + } + + -+ private static NBTTagCompound readOversizedChunk(RegionFile regionfile, int i, int j) throws IOException { ++ private static NBTTagCompound readOversizedChunk(RegionFile regionfile, ChunkCoordIntPair chunkCoordinate) throws IOException { + synchronized (regionfile) { -+ try (DataInputStream datainputstream = regionfile.getReadStream(i & 31, j & 31)) { -+ NBTTagCompound oversizedData = regionfile.getOversizedData(i, j); ++ try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) { ++ NBTTagCompound oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); + NBTTagCompound chunk = NBTCompressedStreamTools.readNBT(datainputstream); + if (oversizedData == null) { + return chunk; @@ -397,38 +423,73 @@ index 8c8b7cbab5..17e76815ad 100644 + // Paper End - public static synchronized void a() { -@@ -0,0 +0,0 @@ public class RegionFileCache { - // CraftBukkit start - call sites hoisted for synchronization - public static NBTTagCompound read(File file, int i, int j) throws IOException { // Paper - remove synchronization - RegionFile regionfile = a(file, i, j); + @Nullable + public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException { + RegionFile regionfile = this.a(chunkcoordintpair, false); // CraftBukkit + DataInputStream datainputstream = regionfile.a(chunkcoordintpair); + // Paper start -+ if (regionfile.isOversized(i, j)) { -+ printOversizedLog("Loading Oversized Chunk!", file, i, j); -+ return readOversizedChunk(regionfile, i, j); ++ if (regionfile.isOversized(chunkcoordintpair.x, chunkcoordintpair.z)) { ++ printOversizedLog("Loading Oversized Chunk!", regionfile.file, chunkcoordintpair.x, chunkcoordintpair.z); ++ return readOversizedChunk(regionfile, chunkcoordintpair); + } + // Paper end + Throwable throwable = null; - DataInputStream datainputstream = regionfile.a(i & 31, j & 31); + NBTTagCompound nbttagcompound; +@@ -0,0 +0,0 @@ public abstract class RegionFileCache implements AutoCloseable { -@@ -0,0 +0,0 @@ public class RegionFileCache { - @Nullable - public static void write(File file, int i, int j, NBTTagCompound nbttagcompound) throws IOException { + protected void write(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) throws IOException { int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper -- RegionFile regionfile = a(file, i, j); +- RegionFile regionfile = this.a(chunkcoordintpair, false); // CraftBukkit +- DataOutputStream dataoutputstream = regionfile.c(chunkcoordintpair); +- Throwable throwable = null; - -- DataOutputStream dataoutputstream = regionfile.c(i & 31, j & 31); -- NBTCompressedStreamTools.a(nbttagcompound, (java.io.DataOutput) dataoutputstream); -- dataoutputstream.close(); -+ writeRegion(file, i, j, nbttagcompound); // Paper - moved to own method +- try { +- NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); +- } catch (Throwable throwable1) { +- throwable = throwable1; +- throw throwable1; +- } finally { +- if (dataoutputstream != null) { +- if (throwable != null) { +- try { +- dataoutputstream.close(); +- } catch (Throwable throwable2) { +- throwable.addSuppressed(throwable2); +- } +- } else { +- dataoutputstream.close(); +- } +- } +- +- } + // Paper start -+// RegionFile regionfile = a(file, i, j); ++ this.writeRegion(chunkcoordintpair, nbttagcompound); ++// RegionFile regionfile = this.a(chunkcoordintpair, false); // CraftBukkit ++// DataOutputStream dataoutputstream = regionfile.c(chunkcoordintpair); ++// Throwable throwable = null; +// -+// DataOutputStream dataoutputstream = regionfile.c(i & 31, j & 31); -+// NBTCompressedStreamTools.a(nbttagcompound, (java.io.DataOutput) dataoutputstream); -+// dataoutputstream.close(); ++// try { ++// NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream); ++// } catch (Throwable throwable1) { ++// throwable = throwable1; ++// throw throwable1; ++// } finally { ++// if (dataoutputstream != null) { ++// if (throwable != null) { ++// try { ++// dataoutputstream.close(); ++// } catch (Throwable throwable2) { ++// throwable.addSuppressed(throwable2); ++// } ++// } else { ++// dataoutputstream.close(); ++// } ++// } ++// ++// } + // Paper end - // Paper start - laste = null; break; // Paper - } catch (Exception exception) { + + } catch (Exception ex) { + laste = ex; -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Allow-login-events-to-fire-only-after-the-server-plu.patch b/Spigot-Server-Patches/Allow-login-events-to-fire-only-after-the-server-plu.patch index 089d0c850b..d92496e833 100644 --- a/Spigot-Server-Patches/Allow-login-events-to-fire-only-after-the-server-plu.patch +++ b/Spigot-Server-Patches/Allow-login-events-to-fire-only-after-the-server-plu.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Allow login events to fire only after the server plugins are Event threads will simply block until they're ready to accept. diff --git a/src/main/java/net/minecraft/server/LoginListener.java b/src/main/java/net/minecraft/server/LoginListener.java -index dfe7a029f8..503f665820 100644 +index 9e4bc24058..028c23dbe6 100644 --- a/src/main/java/net/minecraft/server/LoginListener.java +++ b/src/main/java/net/minecraft/server/LoginListener.java -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener, ITickable { +@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { } } @@ -47,7 +47,7 @@ index dfe7a029f8..503f665820 100644 // Spigot start public class LoginHandler { -@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener, ITickable { +@@ -0,0 +0,0 @@ public class LoginListener implements PacketLoginInListener { return; } // Paper end @@ -56,15 +56,15 @@ index dfe7a029f8..503f665820 100644 java.net.InetAddress address = ((java.net.InetSocketAddress) networkManager.getSocketAddress()).getAddress(); java.util.UUID uniqueId = i.getId(); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index d6250c4722..8db5c6a351 100644 +index b790472347..c28b0738dd 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati - this.x = 0; - // CraftBukkit Start +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant -Date: Sun, 24 Mar 2019 18:52:31 +0000 -Subject: [PATCH] Don't update entity trackers for worlds without players - -PlayerList#moveToWorld already untracks the player from the player list, -meaning that we do not need to worry about this untracking players -who've left the world, The server also untracks a player during -disconnect, handing yet another case. - -If we don't need to untrack players who've left the world, it should be -reasonably save to do this, as we're not going to be performing any -server->client updates here, which is what this code is intended to do, -and all players should be untracked. - -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index ce39ea09e8..b93fccf919 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati - - this.methodProfiler.exit(); - this.methodProfiler.enter("tracker"); -- worldserver.getTracker().updatePlayers(); -+ if (playerList.players.size() > 0) worldserver.getTracker().updatePlayers(); // Paper - No players, why spend time tracking them? (See patch) - this.methodProfiler.exit(); - this.methodProfiler.exit(); - worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions --- \ No newline at end of file diff --git a/Spigot-Server-Patches/Entity-getEntitySpawnReason.patch b/Spigot-Server-Patches/Entity-getEntitySpawnReason.patch index 3d1f597809..63dd5cf895 100644 --- a/Spigot-Server-Patches/Entity-getEntitySpawnReason.patch +++ b/Spigot-Server-Patches/Entity-getEntitySpawnReason.patch @@ -9,21 +9,8 @@ Pre existing entities will return NATURAL if it was a non persistenting Living Entity, SPAWNER for spawners, or DEFAULT since data was not stored. -diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index 7734712af9..dce52ac0fa 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -0,0 +0,0 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - while (iterator.hasNext()) { - Entity entity1 = (Entity) iterator.next(); - -- a(entity1, generatoraccess); -+ a(entity1, generatoraccess, reason); // Paper - } - } - diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index a678dc89c8..581c78e003 100644 +index f945a2df48..cad8613a9b 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke @@ -59,7 +46,7 @@ index a678dc89c8..581c78e003 100644 + if (spawnReason == null) { + if (spawnedViaMobSpawner) { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER; -+ } else if (this instanceof EntityInsentient && this instanceof IAnimal && !((EntityInsentient) this).isTypeNotPersistent()) { ++ } else if (this instanceof EntityInsentient && (this instanceof EntityAnimal || this instanceof EntityFish) && !((EntityInsentient) this).isTypeNotPersistent(0.0)) { + if (!nbttagcompound.getBoolean("PersistenceRequired")) { + spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL; + } @@ -71,46 +58,33 @@ index a678dc89c8..581c78e003 100644 // Paper end } catch (Throwable throwable) { -diff --git a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java -index b2d2de7f81..af38e5396e 100644 ---- a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java -+++ b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java -@@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { - } - } - // Paper end -- Entity entity = ChunkRegionLoader.a(nbttagcompound, world, d3, d4, d5, false); -+ Entity entity = ChunkRegionLoader.spawnEntity(nbttagcompound, world, d3, d4, d5, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER); // Paper - - if (entity == null) { - this.i(); diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index b1630137ec..df416e3b59 100644 +index 7d93715424..3d1c910ccf 100644 --- a/src/main/java/net/minecraft/server/PlayerList.java +++ b/src/main/java/net/minecraft/server/PlayerList.java @@ -0,0 +0,0 @@ public abstract class PlayerList { + // CraftBukkit start + WorldServer finalWorldServer = worldserver; + Entity entity = EntityTypes.a(nbttagcompound1.getCompound("Entity"), finalWorldServer, (entity1) -> { +- return !finalWorldServer.addEntitySerialized(entity1) ? null : entity1; ++ return !finalWorldServer.addEntitySerialized(entity1, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity1; // Paper + // CraftBukkit end + }); - if (nbttagcompound != null && nbttagcompound.hasKeyOfType("RootVehicle", 10)) { - NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("RootVehicle"); -- Entity entity = ChunkRegionLoader.a(nbttagcompound1.getCompound("Entity"), worldserver, true); -+ Entity entity = ChunkRegionLoader.spawnEntity(nbttagcompound1.getCompound("Entity"), worldserver, true, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT); // Paper - - if (entity != null) { - UUID uuid = nbttagcompound1.a("Attach"); -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index e280b58531..0e8025d311 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc - - public boolean addEntity(Entity entity, SpawnReason spawnReason) { // Changed signature, added SpawnReason - // Paper start -+ if (entity.spawnReason == null) entity.spawnReason = spawnReason; - if (regionLimited != null) { - return regionLimited.addEntity(entity, spawnReason); - } +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index 6d8fb12903..c555478e82 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -0,0 +0,0 @@ public class WorldServer extends World { + // CraftBukkit start + private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { + org.spigotmc.AsyncCatcher.catchOp( "entity add"); // Spigot ++ if (entity.spawnReason == null) entity.spawnReason = spawnReason; // Paper + if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper + if (entity.dead) { + // Paper start diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java -index a0e1a70d43..a12dd4779d 100644 +index 65621f9661..1a5b62cf4b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { @@ -118,6 +92,7 @@ index a0e1a70d43..a12dd4779d 100644 return getHandle().spawnedViaMobSpawner; } + ++ @Override + public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason getEntitySpawnReason() { + return getHandle().spawnReason; + } diff --git a/Spigot-Server-Patches/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch b/Spigot-Server-Patches/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch index 6fcf2398d9..f1e8fb3374 100644 --- a/Spigot-Server-Patches/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch +++ b/Spigot-Server-Patches/Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch @@ -24,7 +24,7 @@ Instead we opt to remove the check entirely so that the event fires for all piston types. diff --git a/src/main/java/net/minecraft/server/BlockPiston.java b/src/main/java/net/minecraft/server/BlockPiston.java -index dbe0ff33a0..0109484e0a 100644 +index 170a339eda..a5573f21fc 100644 --- a/src/main/java/net/minecraft/server/BlockPiston.java +++ b/src/main/java/net/minecraft/server/BlockPiston.java @@ -0,0 +0,0 @@ public class BlockPiston extends BlockDirectional { diff --git a/Spigot-Server-Patches/Fire-event-on-GS4-query.patch b/Spigot-Server-Patches/Fire-event-on-GS4-query.patch index 664a720d49..71a05460ff 100644 --- a/Spigot-Server-Patches/Fire-event-on-GS4-query.patch +++ b/Spigot-Server-Patches/Fire-event-on-GS4-query.patch @@ -5,53 +5,53 @@ Subject: [PATCH] Fire event on GS4 query diff --git a/src/main/java/net/minecraft/server/RemoteConnectionThread.java b/src/main/java/net/minecraft/server/RemoteConnectionThread.java -index d875b799ac..bcc36bbbfa 100644 +index 66bfbcf02b..d821ef9a75 100644 --- a/src/main/java/net/minecraft/server/RemoteConnectionThread.java +++ b/src/main/java/net/minecraft/server/RemoteConnectionThread.java @@ -0,0 +0,0 @@ public abstract class RemoteConnectionThread implements Runnable { - private static final Logger h = LogManager.getLogger(); + private static final Logger LOGGER = LogManager.getLogger(); private static final AtomicInteger i = new AtomicInteger(0); protected boolean a; -- protected IMinecraftServer b; -+ protected IMinecraftServer b; protected IMinecraftServer getServer() { return b; } // Paper - OBFHELPER +- protected final IMinecraftServer b; ++ protected final IMinecraftServer b; protected IMinecraftServer getServer() { return this.b; } // Paper - OBFHELPER protected final String c; protected Thread d; - protected int e = 5; + protected final int e = 5; @@ -0,0 +0,0 @@ public abstract class RemoteConnectionThread implements Runnable { - this.b.f(s); + this.b.g(s); } -+ protected int getPlayerCount() { return d(); } // Paper - OBFHELPER ++ protected int getPlayerCount() { return this.d(); } // Paper - OBFHELPER protected int d() { return this.b.getPlayerCount(); } diff --git a/src/main/java/net/minecraft/server/RemoteStatusListener.java b/src/main/java/net/minecraft/server/RemoteStatusListener.java -index 7dd81564a2..fd981931b0 100644 +index ddb4ba4899..3770334fc4 100644 --- a/src/main/java/net/minecraft/server/RemoteStatusListener.java +++ b/src/main/java/net/minecraft/server/RemoteStatusListener.java @@ -0,0 +0,0 @@ public class RemoteStatusListener extends RemoteConnectionThread { private long h; - private int i; + private final int i; - private final int j; - private final int k; - private final String l; - private final String m; -+ private final int j; private int getServerPort() { return j; } // Paper - OBFHELPER -+ private final int k; private int getMaxPlayers() { return k; } // Paper - OBFHELPER -+ private final String l; private String getMotd() { return l; } // Paper - OBFHELPER -+ private final String m; private String getWorldName() { return m; } // Paper - OBFHELPER ++ private final int j; private int getServerPort() { return this.j; } // Paper - OBFHELPER ++ private final int k; private int getMaxPlayers() { return this.k; } // Paper - OBFHELPER ++ private final String l; private String getMotd() { return this.l; } // Paper - OBFHELPER ++ private final String m; private String getWorldName() { return this.m; } // Paper - OBFHELPER private DatagramSocket n; private final byte[] o = new byte[1460]; private DatagramPacket p; private final Map q; - private String r; -+ private String r; private String getServerHost() { return r; } // Paper - OBFHELPER ++ private String r; private String getServerHost() { return this.r; } // Paper - OBFHELPER private String s; private final Map t; private final long u; - private final RemoteStatusReply v; -+ private final RemoteStatusReply v; private RemoteStatusReply getCachedFullResponse() { return v; } // Paper - OBFHELPER ++ private final RemoteStatusReply v; private RemoteStatusReply getCachedFullResponse() { return this.v; } // Paper - OBFHELPER private long w; public RemoteStatusListener(IMinecraftServer iminecraftserver) { @@ -184,14 +184,14 @@ index 7dd81564a2..fd981931b0 100644 } } diff --git a/src/main/java/net/minecraft/server/RemoteStatusReply.java b/src/main/java/net/minecraft/server/RemoteStatusReply.java -index 848b5c3f0e..9e8c8b3df2 100644 +index 848b5c3f0e..73efea7e13 100644 --- a/src/main/java/net/minecraft/server/RemoteStatusReply.java +++ b/src/main/java/net/minecraft/server/RemoteStatusReply.java @@ -0,0 +0,0 @@ public class RemoteStatusReply { this.b.write(abyte, 0, abyte.length); } -+ public void writeString(String string) throws IOException { a(string); } // Paper - OBFHELPER ++ public void writeString(String string) throws IOException { this.a(string); } // Paper - OBFHELPER public void a(String s) throws IOException { this.b.writeBytes(s); this.b.write(0); @@ -206,12 +206,12 @@ index 848b5c3f0e..9e8c8b3df2 100644 + } + // Paper end -+ public void writeInt(int i) throws IOException { a(i); } // Paper - OBFHELPER ++ public void writeInt(int i) throws IOException { this.a(i); } // Paper - OBFHELPER public void a(int i) throws IOException { this.b.write(i); } -+ public void writeShort(short i) throws IOException { a(i); } // Paper - OBFHELPER ++ public void writeShort(short i) throws IOException { this.a(i); } // Paper - OBFHELPER public void a(short short0) throws IOException { this.b.writeShort(Short.reverseBytes(short0)); } diff --git a/Spigot-Server-Patches/Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch b/Spigot-Server-Patches/Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch index 645c8c4b31..091c970f97 100644 --- a/Spigot-Server-Patches/Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch +++ b/Spigot-Server-Patches/Fix-Custom-Shapeless-Custom-Crafting-Recipes.patch @@ -10,59 +10,57 @@ This made the Bukkit RecipeChoice API not work for Shapeless. This reimplements vanilla logic using the same test logic as Shaped diff --git a/src/main/java/net/minecraft/server/ShapelessRecipes.java b/src/main/java/net/minecraft/server/ShapelessRecipes.java -index 819b4ac2da..ea4083a45a 100644 +index 070fc1e3ec..691e697d68 100644 --- a/src/main/java/net/minecraft/server/ShapelessRecipes.java +++ b/src/main/java/net/minecraft/server/ShapelessRecipes.java -@@ -0,0 +0,0 @@ public class ShapelessRecipes implements IRecipe { - AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager(); - int i = 0; +@@ -0,0 +0,0 @@ public class ShapelessRecipes implements RecipeCrafting { + AutoRecipeStackManager autorecipestackmanager = new AutoRecipeStackManager(); + int i = 0; -+ // Paper start -+ java.util.List providedItems = new java.util.ArrayList<>(); -+ co.aikar.util.Counter matchedProvided = new co.aikar.util.Counter<>(); -+ co.aikar.util.Counter matchedIngredients = new co.aikar.util.Counter<>(); -+ // Paper end - for (int j = 0; j < iinventory.n(); ++j) { - for (int k = 0; k < iinventory.U_(); ++k) { - ItemStack itemstack = iinventory.getItem(k + j * iinventory.U_()); ++ // Paper start ++ java.util.List providedItems = new java.util.ArrayList<>(); ++ co.aikar.util.Counter matchedProvided = new co.aikar.util.Counter<>(); ++ co.aikar.util.Counter matchedIngredients = new co.aikar.util.Counter<>(); ++ // Paper end + for (int j = 0; j < inventorycrafting.getSize(); ++j) { + ItemStack itemstack = inventorycrafting.getItem(j); - if (!itemstack.isEmpty()) { -- ++i; -- autorecipestackmanager.b(new ItemStack(itemstack.getItem())); -+ // Paper start -+ itemstack = itemstack.cloneItemStack(); -+ providedItems.add(itemstack); -+ for (RecipeItemStack ingredient : ingredients) { -+ if (ingredient.test(itemstack)) { -+ matchedProvided.increment(itemstack); -+ matchedIngredients.increment(ingredient); -+ } -+ } -+ // Paper end - } - } - } -- -- return i == this.ingredients.size() && autorecipestackmanager.a(this, (IntList) null); -+ // Paper start -+ java.util.List ingredients = new java.util.ArrayList<>(this.ingredients); -+ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed()); -+ ingredients.sort(java.util.Comparator.comparingInt((RecipeItemStack c) -> (int) matchedIngredients.getCount(c))); -+ -+ PROVIDED: -+ for (ItemStack provided : providedItems) { -+ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { -+ RecipeItemStack ingredient = itIngredient.next(); -+ if (ingredient.test(provided)) { -+ itIngredient.remove(); -+ continue PROVIDED; + if (!itemstack.isEmpty()) { +- ++i; +- autorecipestackmanager.a(itemstack, 1); ++ // Paper start ++ itemstack = itemstack.cloneItemStack(); ++ providedItems.add(itemstack); ++ for (RecipeItemStack ingredient : ingredients) { ++ if (ingredient.test(itemstack)) { ++ matchedProvided.increment(itemstack); ++ matchedIngredients.increment(ingredient); + } + } -+ return false; -+ } -+ return ingredients.isEmpty(); -+ // Paper end ++ // Paper end + } } + +- return i == this.ingredients.size() && autorecipestackmanager.a(this, (IntList) null); ++ // Paper start ++ java.util.List ingredients = new java.util.ArrayList<>(this.ingredients); ++ providedItems.sort(java.util.Comparator.comparingInt((ItemStack c) -> (int) matchedProvided.getCount(c)).reversed()); ++ ingredients.sort(java.util.Comparator.comparingInt((RecipeItemStack c) -> (int) matchedIngredients.getCount(c))); ++ ++ PROVIDED: ++ for (ItemStack provided : providedItems) { ++ for (Iterator itIngredient = ingredients.iterator(); itIngredient.hasNext(); ) { ++ RecipeItemStack ingredient = itIngredient.next(); ++ if (ingredient.test(provided)) { ++ itIngredient.remove(); ++ continue PROVIDED; ++ } ++ } ++ return false; ++ } ++ return ingredients.isEmpty(); ++ // Paper end } + public ItemStack a(InventoryCrafting inventorycrafting) { -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Fix-NPE-from-sign-placement.patch b/Spigot-Server-Patches/Fix-NPE-from-sign-placement.patch deleted file mode 100644 index 40b59fcb1e..0000000000 --- a/Spigot-Server-Patches/Fix-NPE-from-sign-placement.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Wed, 17 Apr 2019 00:48:59 +0100 -Subject: [PATCH] Fix NPE from sign placement - -This fixes issues with upstreams changes to solve a private issue on -their side, as signs are placed, they may replace existing blocks, e.g. -grass, which breaks upstreams assumption that the sign is always placed -adjacent to a surface - -diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java -index f5d9b4abc2..fdbe9a2adc 100644 ---- a/src/main/java/net/minecraft/server/EntityHuman.java -+++ b/src/main/java/net/minecraft/server/EntityHuman.java -@@ -0,0 +0,0 @@ public abstract class EntityHuman extends EntityLiving { - public EntityFishingHook hookedFish; - // Paper start - public boolean affectsSpawning = true; -+ public BlockPosition openingSign = null; // Paper - fix NPE when opening signs - // Paper end - // Paper start - Player view distance API - private int viewDistance = -1; -diff --git a/src/main/java/net/minecraft/server/ItemSign.java b/src/main/java/net/minecraft/server/ItemSign.java -index 11045ee1e1..7808aed0c0 100644 ---- a/src/main/java/net/minecraft/server/ItemSign.java -+++ b/src/main/java/net/minecraft/server/ItemSign.java -@@ -0,0 +0,0 @@ public class ItemSign extends ItemBlockWallable { - if (!world.isClientSide && !flag && entityhuman != null) { - // CraftBukkit start - SPIGOT-4678 - // entityhuman.openSign((TileEntitySign) world.getTileEntity(blockposition)); -+ entityhuman.openingSign = blockposition; // Paper - fix NPE when opening signs - ItemSign.openSign = true; - // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java -index f8d82a0276..ccc0826bc6 100644 ---- a/src/main/java/net/minecraft/server/ItemStack.java -+++ b/src/main/java/net/minecraft/server/ItemStack.java -@@ -0,0 +0,0 @@ public final class ItemStack { - // SPIGOT-4678 - if (this.item instanceof ItemSign && ItemSign.openSign) { - ItemSign.openSign = false; -- entityhuman.openSign((TileEntitySign) world.getTileEntity(new BlockActionContext(itemactioncontext).getClickPosition())); -+ // Paper start - fix NPE when opening signs -+ if (entityhuman.openingSign != null) { -+ entityhuman.openSign((TileEntitySign) world.getTileEntity(entityhuman.openingSign)); -+ entityhuman.openingSign = null; -+ } -+ // Paper end - } - - // SPIGOT-1288 - play sound stripped from ItemBlock --- \ No newline at end of file diff --git a/Spigot-Server-Patches/Fix-PlayerEditBookEvent.patch b/Spigot-Server-Patches/Fix-PlayerEditBookEvent.patch index a06078d73c..24c499b3b9 100644 --- a/Spigot-Server-Patches/Fix-PlayerEditBookEvent.patch +++ b/Spigot-Server-Patches/Fix-PlayerEditBookEvent.patch @@ -10,24 +10,22 @@ it impossible to properly cancel the event or modify the book meta cancelled writing diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 5c041c48fa..f63943f29f 100644 +index 15fb7ed608..71d10f9b9c 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { - - this.player.setSlot(enumitemslot, CraftEventFactory.handleEditBookEvent(player, enumitemslot, itemstack1, itemstack2)); // CraftBukkit - } else { -- ItemStack old = itemstack1.cloneItemStack(); // CraftBukkit -- itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8)); -- CraftEventFactory.handleEditBookEvent(player, enumitemslot, old, itemstack1); // CraftBukkit -+ // Paper start - dont mutate players current item, set it from the event -+ ItemStack newBook = itemstack1.cloneItemStack(); -+ newBook.getOrCreateTagAndSet("pages", (NBTBase) itemstack.getTag().getList("pages", 8)); -+ this.player.setSlot(enumitemslot, CraftEventFactory.handleEditBookEvent(player, enumitemslot, itemstack1, newBook)); -+ // Paper end - } -+ player.getBukkitEntity().updateInventory(); // Paper - fix client desync when event is cancelled +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { + itemstack2.a("pages", (NBTBase) nbttaglist); + this.player.a(packetplayinbedit.d(), CraftEventFactory.handleEditBookEvent(player, enumitemslot, itemstack1, itemstack2)); // CraftBukkit + } else { +- ItemStack old = itemstack1.cloneItemStack(); // CraftBukkit +- itemstack1.a("pages", (NBTBase) itemstack.getTag().getList("pages", 8)); +- CraftEventFactory.handleEditBookEvent(player, enumitemslot, old, itemstack1); // CraftBukkit ++ // Paper start - dont mutate players current item, set it from the event ++ ItemStack newBook = itemstack1.cloneItemStack(); ++ newBook.getOrCreateTagAndSet("pages", (NBTBase)itemstack.getTag().getList("pages", 8)); ++ this.player.setSlot(enumitemslot, CraftEventFactory.handleEditBookEvent(player, enumitemslot, itemstack1, newBook)); ++ // Paper end } - } + -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Fix-sign-edit-memory-leak.patch b/Spigot-Server-Patches/Fix-sign-edit-memory-leak.patch index daf5ea3bf9..455bb45855 100644 --- a/Spigot-Server-Patches/Fix-sign-edit-memory-leak.patch +++ b/Spigot-Server-Patches/Fix-sign-edit-memory-leak.patch @@ -6,23 +6,23 @@ Subject: [PATCH] Fix sign edit memory leak when a player edits a sign, a reference to their Entity is never cleand up. diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index f63943f29f..b193fbab47 100644 +index 71d10f9b9c..60f77ac3df 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { TileEntitySign tileentitysign = (TileEntitySign) tileentity; -- if (!tileentitysign.d() || tileentitysign.e() != this.player) { -+ if (!tileentitysign.d() || tileentitysign.signEditor == null || !tileentitysign.signEditor.equals(this.player.getUniqueID())) { // Paper +- if (!tileentitysign.c() || tileentitysign.d() != this.player) { ++ if (!tileentitysign.c() || tileentitysign.signEditor == null || !tileentitysign.signEditor.equals(this.player.getUniqueID())) { this.minecraftServer.warning("Player " + this.player.getDisplayName().getString() + " just tried to change non-editable sign"); this.sendPacket(tileentity.getUpdatePacket()); // CraftBukkit return; diff --git a/src/main/java/net/minecraft/server/TileEntitySign.java b/src/main/java/net/minecraft/server/TileEntitySign.java -index c2bcbbbab9..fdb771317a 100644 +index 4165c6d11a..7abf533c58 100644 --- a/src/main/java/net/minecraft/server/TileEntitySign.java +++ b/src/main/java/net/minecraft/server/TileEntitySign.java -@@ -0,0 +0,0 @@ public class TileEntitySign extends TileEntity implements ICommandListener { +@@ -0,0 +0,0 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // // Paper start - Strip invalid unicode from signs on load private static final boolean keepInvalidUnicode = Boolean.getBoolean("Paper.keepInvalidUnicode"); // Allow people to keep their bad unicode if they really want it private boolean privateUnicodeRemoved = false; @@ -30,16 +30,16 @@ index c2bcbbbab9..fdb771317a 100644 // Paper end public TileEntitySign() { -@@ -0,0 +0,0 @@ public class TileEntitySign extends TileEntity implements ICommandListener { +@@ -0,0 +0,0 @@ public class TileEntitySign extends TileEntity implements ICommandListener { // } public void a(EntityHuman entityhuman) { -- this.g = entityhuman; +- this.j = entityhuman; + // Paper start + //this.g = entityhuman; + signEditor = entityhuman != null ? entityhuman.getUniqueID() : null; + // Paper end } - public EntityHuman e() { + public EntityHuman d() { -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Handle-Excessive-Signs-in-Chunks-creating-too-large-.patch b/Spigot-Server-Patches/Handle-Excessive-Signs-in-Chunks-creating-too-large-.patch index 9b1c84e23d..5938ae354d 100644 --- a/Spigot-Server-Patches/Handle-Excessive-Signs-in-Chunks-creating-too-large-.patch +++ b/Spigot-Server-Patches/Handle-Excessive-Signs-in-Chunks-creating-too-large-.patch @@ -11,7 +11,7 @@ Use -DPaper.excessiveSignsLimit=500 to configure that limit, or -1 to disable the limit and let your players be abused. diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java -index 553637239c..30f646e421 100644 +index 1b0643c27f..4766f7b773 100644 --- a/src/main/java/net/minecraft/server/NetworkManager.java +++ b/src/main/java/net/minecraft/server/NetworkManager.java @@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { @@ -29,7 +29,7 @@ index 553637239c..30f646e421 100644 + } - // Paper start - Async-Anti-Xray - Stop dispatching further packets and return false if the peeked packet is a chunk packet which is not ready + private void sendPacketQueue() { this.o(); } // Paper - OBFHELPER diff --git a/src/main/java/net/minecraft/server/Packet.java b/src/main/java/net/minecraft/server/Packet.java index 2d8e6a2f4a..8d0965a053 100644 --- a/src/main/java/net/minecraft/server/Packet.java @@ -43,31 +43,33 @@ index 2d8e6a2f4a..8d0965a053 100644 return false; } diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java -index 4a57e8a3ec..eb54bdb642 100644 +index 58eccd9c63..ef71a1feb3 100644 --- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java @@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - this.ready = true; // Paper - Async-Anti-Xray - Set the ready flag to true - } + + public PacketPlayOutMapChunk() {} + // Paper start + private final java.util.List extraPackets = new java.util.ArrayList<>(); + private static final int SKIP_EXCESSIVE_SIGNS_LIMIT = Integer.getInteger("Paper.excessiveSignsLimit", 500); ++ ++ @Override + public java.util.List getExtraPackets() { + return extraPackets; + } + // Paper end public PacketPlayOutMapChunk(Chunk chunk, int i) { - ChunkPacketInfo chunkPacketInfo = chunk.world.chunkPacketBlockController.getChunkPacketInfo(this, chunk, i); // Paper - Anti-Xray - Add chunk packet info - this.a = chunk.locX; + ChunkCoordIntPair chunkcoordintpair = chunk.getPos(); + @@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - this.c = this.writeChunk(new PacketDataSerializer(this.h()), chunk, flag, i, chunkPacketInfo); // Paper - Anti-Xray - Add chunk packet info - this.e = Lists.newArrayList(); - Iterator iterator = chunk.getTileEntities().entrySet().iterator(); + this.c = this.a(new PacketDataSerializer(this.i()), chunk, i); + this.f = Lists.newArrayList(); + iterator = chunk.getTileEntities().entrySet().iterator(); + int totalSigns = 0; // Paper while (iterator.hasNext()) { - Entry entry = (Entry) iterator.next(); + entry = (Entry) iterator.next(); @@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { int j = blockposition.getY() >> 4; @@ -75,13 +77,12 @@ index 4a57e8a3ec..eb54bdb642 100644 + // Paper start - send signs separately + if (tileentity instanceof TileEntitySign) { + if (SKIP_EXCESSIVE_SIGNS_LIMIT < 0 || ++totalSigns < SKIP_EXCESSIVE_SIGNS_LIMIT) { -+ extraPackets.add(tileentity.getUpdatePacket()); ++ this.extraPackets.add(tileentity.getUpdatePacket()); + } + continue; + } + // Paper end -+ - NBTTagCompound nbttagcompound = tileentity.aa_(); + NBTTagCompound nbttagcompound = tileentity.b(); if (tileentity instanceof TileEntitySkull) { TileEntitySkull.sanitizeTileEntityUUID(nbttagcompound); } // Paper -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch b/Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch index 62be27e19f..f29d6c4e8b 100644 --- a/Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch +++ b/Spigot-Server-Patches/Handle-Large-Packets-disconnecting-client.patch @@ -7,7 +7,7 @@ If a players inventory is too big to send in a single packet, split the inventory set into multiple packets instead. diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java -index c536979140..0b8796d0ae 100644 +index 38386d5886..2c28b97d81 100644 --- a/src/main/java/net/minecraft/server/NetworkManager.java +++ b/src/main/java/net/minecraft/server/NetworkManager.java @@ -0,0 +0,0 @@ public class NetworkManager extends SimpleChannelInboundHandler> { @@ -24,7 +24,7 @@ index c536979140..0b8796d0ae 100644 + } + // Paper end if (throwable instanceof SkipEncodeException) { - NetworkManager.g.debug("Skipping packet due to errors", throwable.getCause()); + NetworkManager.LOGGER.debug("Skipping packet due to errors", throwable.getCause()); } else { diff --git a/src/main/java/net/minecraft/server/Packet.java b/src/main/java/net/minecraft/server/Packet.java index 601d4d0fa2..2d8e6a2f4a 100644 @@ -44,7 +44,7 @@ index 601d4d0fa2..2d8e6a2f4a 100644 return false; } diff --git a/src/main/java/net/minecraft/server/PacketEncoder.java b/src/main/java/net/minecraft/server/PacketEncoder.java -index 2aa805eef1..4f7bc186aa 100644 +index 63c4dbd327..b0cfef52cb 100644 --- a/src/main/java/net/minecraft/server/PacketEncoder.java +++ b/src/main/java/net/minecraft/server/PacketEncoder.java @@ -0,0 +0,0 @@ public class PacketEncoder extends MessageToByteEncoder> { @@ -80,20 +80,20 @@ index 2aa805eef1..4f7bc186aa 100644 + // Paper end } diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java -index 8e35d14f97..4a57e8a3ec 100644 +index d19a30ad87..58eccd9c63 100644 --- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java +++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java @@ -0,0 +0,0 @@ public class PacketPlayOutMapChunk implements Packet { - this.c = packetdataserializer.g(); - int i = packetdataserializer.g(); + this.d = packetdataserializer.l(); + int i = packetdataserializer.i(); - if (i > 2097152) { + if (i > 2097152) { // Paper - if this changes, update PacketEncoder throw new RuntimeException("Chunk Packet trying to allocate too much memory on read."); } else { - this.d = new byte[i]; + this.e = new byte[i]; diff --git a/src/main/java/net/minecraft/server/PacketPlayOutWindowItems.java b/src/main/java/net/minecraft/server/PacketPlayOutWindowItems.java -index 706d843859..c0d8f8b428 100644 +index f7c3655671..631234324d 100644 --- a/src/main/java/net/minecraft/server/PacketPlayOutWindowItems.java +++ b/src/main/java/net/minecraft/server/PacketPlayOutWindowItems.java @@ -0,0 +0,0 @@ public class PacketPlayOutWindowItems implements Packet { diff --git a/Spigot-Server-Patches/Handle-bad-chunks-more-gracefully.patch b/Spigot-Server-Patches/Handle-bad-chunks-more-gracefully.patch index 74fb6efbbe..25f03b622d 100644 --- a/Spigot-Server-Patches/Handle-bad-chunks-more-gracefully.patch +++ b/Spigot-Server-Patches/Handle-bad-chunks-more-gracefully.patch @@ -15,45 +15,47 @@ Should Mojang choose to alter this behavior in the future, this change will simply defer to whatever that new behavior is. diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java -index 17e76815ad..369aaa84c4 100644 +index 6893f3cd34..717b0b1f08 100644 --- a/src/main/java/net/minecraft/server/RegionFileCache.java +++ b/src/main/java/net/minecraft/server/RegionFileCache.java -@@ -0,0 +0,0 @@ public class RegionFileCache { - private static NBTTagCompound readOversizedChunk(RegionFile regionfile, int i, int j) throws IOException { +@@ -0,0 +0,0 @@ public abstract class RegionFileCache implements AutoCloseable { + private static NBTTagCompound readOversizedChunk(RegionFile regionfile, ChunkCoordIntPair chunkCoordinate) throws IOException { synchronized (regionfile) { - try (DataInputStream datainputstream = regionfile.getReadStream(i & 31, j & 31)) { -- NBTTagCompound oversizedData = regionfile.getOversizedData(i, j); + try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) { +- NBTTagCompound oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); - NBTTagCompound chunk = NBTCompressedStreamTools.readNBT(datainputstream); + // Paper start - Handle bad chunks more gracefully - also handle similarly with oversized data + NBTTagCompound oversizedData = null; + + try { -+ oversizedData = regionfile.getOversizedData(i, j); ++ oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z); + } catch (Exception ex) {} + + NBTTagCompound chunk; ++ + try { -+ chunk = NBTCompressedStreamTools.readNBT(datainputstream); -+ } catch (Exception ex) { ++ chunk = NBTCompressedStreamTools.readNBT(datainputstream); ++ } catch (final Exception ex) { + return null; + } + // Paper end if (oversizedData == null) { return chunk; } -@@ -0,0 +0,0 @@ public class RegionFileCache { - return null; - } +@@ -0,0 +0,0 @@ public abstract class RegionFileCache implements AutoCloseable { -- return NBTCompressedStreamTools.a(datainputstream); -+ // Paper start - Handle bad chunks more gracefully -+ try { -+ return NBTCompressedStreamTools.a(datainputstream); -+ } catch (Exception ex) { -+ return null; -+ } -+ // Paper end - } + try { + if (datainputstream != null) { +- nbttagcompound = NBTCompressedStreamTools.a(datainputstream); +- return nbttagcompound; ++ // Paper start - Handle bad chunks more gracefully ++ try { ++ return NBTCompressedStreamTools.a(datainputstream); ++ } catch (Exception ex) { ++ return null; ++ } ++ // Paper end + } - @Nullable + nbttagcompound = null; -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Implement-PlayerPostRespawnEvent.patch b/Spigot-Server-Patches/Implement-PlayerPostRespawnEvent.patch index 504e831e1a..d6571cff24 100644 --- a/Spigot-Server-Patches/Implement-PlayerPostRespawnEvent.patch +++ b/Spigot-Server-Patches/Implement-PlayerPostRespawnEvent.patch @@ -5,12 +5,12 @@ Subject: [PATCH] Implement PlayerPostRespawnEvent diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index df416e3b59..012238ac2b 100644 +index 3d1c910ccf..6c7289f037 100644 --- a/src/main/java/net/minecraft/server/PlayerList.java +++ b/src/main/java/net/minecraft/server/PlayerList.java @@ -0,0 +0,0 @@ public abstract class PlayerList { + // this.a(entityplayer1, entityplayer, worldserver); // CraftBukkit - removed - BlockPosition blockposition1; + // Paper start + boolean isBedSpawn = false; @@ -23,7 +23,7 @@ index df416e3b59..012238ac2b 100644 + //boolean isBedSpawn = false; Paper - moved up CraftWorld cworld = (CraftWorld) this.server.server.getWorld(entityplayer.spawnWorld); if (cworld != null && blockposition != null) { - blockposition1 = EntityHuman.getBed(cworld.getHandle(), blockposition, flag1); + Optional optional = EntityHuman.getBed(cworld.getHandle(), blockposition, flag1); @@ -0,0 +0,0 @@ public abstract class PlayerList { location = respawnEvent.getRespawnLocation(); diff --git a/Spigot-Server-Patches/Lazy-init-world-storage-in-CraftOfflinePlayer.patch b/Spigot-Server-Patches/Lazy-init-world-storage-in-CraftOfflinePlayer.patch index 61b7aa393c..d475e43e10 100644 --- a/Spigot-Server-Patches/Lazy-init-world-storage-in-CraftOfflinePlayer.patch +++ b/Spigot-Server-Patches/Lazy-init-world-storage-in-CraftOfflinePlayer.patch @@ -8,7 +8,7 @@ worlds loaded. This is typically a rare occurrence but probably one that should be covered as best we can. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java -index 698cfb918b..fbdb2df27d 100644 +index 24b06a0b7e..294f3de00c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java @@ -0,0 +0,0 @@ import org.bukkit.plugin.Plugin; diff --git a/Spigot-Server-Patches/Limit-Client-Sign-length-more.patch b/Spigot-Server-Patches/Limit-Client-Sign-length-more.patch index 83e67d05cc..b805d7479f 100644 --- a/Spigot-Server-Patches/Limit-Client-Sign-length-more.patch +++ b/Spigot-Server-Patches/Limit-Client-Sign-length-more.patch @@ -22,10 +22,10 @@ it only impacts data sent from the client. Set -DPaper.maxSignLength=XX to change limit or -1 to disable diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index b193fbab47..188e450a13 100644 +index 60f77ac3df..39a040a2a0 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { private int E; private int receivedMovePackets; private int processedMovePackets; @@ -33,7 +33,7 @@ index b193fbab47..188e450a13 100644 private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) { -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { String[] lines = new String[4]; for (int i = 0; i < astring.length; ++i) { diff --git a/Spigot-Server-Patches/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch b/Spigot-Server-Patches/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch index 756e11adf4..aa5e3b5540 100644 --- a/Spigot-Server-Patches/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch +++ b/Spigot-Server-Patches/MC-145260-Fix-Whitelist-On-Off-inconsistency.patch @@ -11,19 +11,19 @@ everything to the Whitelist object. https://github.com/PaperMC/Paper/issues/1880 diff --git a/src/main/java/net/minecraft/server/JsonList.java b/src/main/java/net/minecraft/server/JsonList.java -index b7cde4d418..949039f89a 100644 +index c169d01762..55bc4b265d 100644 --- a/src/main/java/net/minecraft/server/JsonList.java +++ b/src/main/java/net/minecraft/server/JsonList.java @@ -0,0 +0,0 @@ public class JsonList> { return this.e; } -+ public void setEnabled(boolean flag) { a(flag); } // Paper - OBFHeLPER ++ public void setEnabled(boolean flag) { this.a(flag); } // Paper - OBFHeLPER public void a(boolean flag) { this.e = flag; } diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java -index 135d25abd2..408c382d2a 100644 +index 109c27b647..6939b5ce1e 100644 --- a/src/main/java/net/minecraft/server/PlayerList.java +++ b/src/main/java/net/minecraft/server/PlayerList.java @@ -0,0 +0,0 @@ public abstract class PlayerList { @@ -31,8 +31,8 @@ index 135d25abd2..408c382d2a 100644 // CraftBukkit end public IPlayerFileData playerFileData; - private boolean hasWhitelist; -+ //private boolean hasWhitelist; // Paper - moved to whitelist object so not duplicated - protected int maxPlayers; ++ //private boolean hasWhitelist; + protected final int maxPlayers; private int s; private EnumGamemode t; @@ -0,0 +0,0 @@ public abstract class PlayerList { diff --git a/Spigot-Server-Patches/Make-region-files-more-reliable-to-write-to.patch b/Spigot-Server-Patches/Make-region-files-more-reliable-to-write-to.patch index 9783fd3b97..f7dde12bf1 100644 --- a/Spigot-Server-Patches/Make-region-files-more-reliable-to-write-to.patch +++ b/Spigot-Server-Patches/Make-region-files-more-reliable-to-write-to.patch @@ -37,76 +37,77 @@ affect save performance if the startup flag is used (especially on HDDs). diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java -index 82f7af46f8..e5659980b3 100644 +index 995a893774..66d87d64b5 100644 --- a/src/main/java/net/minecraft/server/RegionFile.java +++ b/src/main/java/net/minecraft/server/RegionFile.java -@@ -0,0 +0,0 @@ public class RegionFile { - private RandomAccessFile c;private RandomAccessFile getDataFile() { return c; } // Paper - OBFHELPER - private final int[] d = new int[1024];private int[] offsets = d; // Paper - OBFHELPER - private final int[] e = new int[1024];private int[] timestamps = e; // Paper - OBFHELPER -- private List f; -+ private List f; private List getFreeSectors() { return this.f; } // Paper - OBFHELPER - private int g; - private long h; +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + private final RandomAccessFile b; private RandomAccessFile getDataFile() { return this.b; } // Paper - OBFHELPER + private final int[] c = new int[1024]; private int[] offsets = c; // Paper - OBFHELPER + private final int[] d = new int[1024];private int[] timestamps = d; // Paper - OBFHELPER +- private final List e; ++ private final List e; private List getFreeSectors() { return this.e; } // Paper - OBFHELPER -@@ -0,0 +0,0 @@ public class RegionFile { - protected synchronized void a(int i, int j, byte[] abyte, int k) { + public RegionFile(File file) throws IOException { + this.b = new RandomAccessFile(file, "rw"); +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + protected synchronized void a(ChunkCoordIntPair chunkcoordintpair, byte[] abyte, int i) { try { - int l = this.getOffset(i, j); -- int i1 = l >> 8; -- int j1 = l & 255; -+ int i1 = l >> 8; final int oldSectorOffset = i1; // Paper - store variable for later -+ int j1 = l & 255; final int oldSectorCount; // Paper - store variable for later + int j = this.getOffset(chunkcoordintpair); +- int k = j >> 8; +- int l = j & 255; ++ int k = j >> 8; final int oldSectorOffset = k; // Paper - store variable for later ++ int l = j & 255; final int oldSectorCount; // Paper - store variable for later // Spigot start - if (j1 == 255) { - this.c.seek(i1 * 4096); - j1 = (this.c.readInt() + 4) / 4096 + 1; + if (l == 255) { + this.b.seek(k * 4096); +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { } // Spigot end -+ oldSectorCount = j1; // Paper - store variable for later (watch out for re-assignments of j1) - int k1 = (k + 5) / 4096 + 1; + int i1 = (i + 5) / 4096 + 1; ++ oldSectorCount = l; // Paper - store variable for later (watch out for re-assignments of l) - if (k1 >= 256) { -@@ -0,0 +0,0 @@ public class RegionFile { + if (i1 >= 256) { + // Spigot start +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { // Spigot end } -- if (i1 != 0 && j1 == k1) { -+ if (false && i1 != 0 && j1 == k1) { // Paper - We never want to overrite old data - this.a(i1, abyte, k); +- if (k != 0 && l == i1) { ++ if (false && k != 0 && l == i1) { // Paper - We never want to overrite old data + this.a(k, abyte, i); } else { - int l1; + int j1; -- for (l1 = 0; l1 < j1; ++l1) { -- this.f.set(i1 + l1, true); +- for (j1 = 0; j1 < l; ++j1) { +- this.e.set(k + j1, true); - } + // Paper - We do not free old sectors until we are done writing the new chunk data - l1 = this.f.indexOf(true); - int i2 = 0; -@@ -0,0 +0,0 @@ public class RegionFile { + j1 = this.e.indexOf(true); + int k1 = 0; +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { - if (i2 >= k1) { - i1 = l1; -- this.a(i, j, l1 << 8 | (k1 > 255 ? 255 : k1)); // Spigot -+ //this.a(i, j, l1 << 8 | (k1 > 255 ? 255 : k1)); // Spigot // Paper - We only write to header after we've written chunk data + if (k1 >= i1) { + k = j1; +- this.a(chunkcoordintpair, j1 << 8 | (i1 > 255 ? 255 : i1)); // Spigot ++ //this.a(chunkcoordintpair, j1 << 8 | (i1 > 255 ? 255 : i1)); // Spigot // Paper - We only write to header after we've written chunk data - for (j2 = 0; j2 < k1; ++j2) { - this.f.set(i1 + j2, false); + for (l1 = 0; l1 < i1; ++l1) { + this.e.set(k + l1, false); } -- this.a(i1, abyte, k); -+ this.writeChunk(i, j,i1 << 8 | (k1 > 255 ? 255 : k1), i1, abyte, k); // Paper - Ensure we do not corrupt region files +- this.a(k, abyte, i); ++ this.writeChunk(chunkcoordintpair, j1 << 8 | (i1 > 255 ? 255 : i1), k, abyte, i); // Paper - Ensure we do not corrupt region files } else { - this.c.seek(this.c.length()); - i1 = this.f.size(); -@@ -0,0 +0,0 @@ public class RegionFile { + this.b.seek(this.b.length()); + k = this.e.size(); +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + this.e.add(false); } - this.g += 4096 * k1; -- this.a(i1, abyte, k); -- this.a(i, j, i1 << 8 | (k1 > 255 ? 255 : k1)); // Spigot -+ this.writeChunk(i, j, i1 << 8 | (k1 > 255 ? 255 : k1), i1, abyte, k); // Paper - Ensure we do not corrupt region files +- this.a(k, abyte, i); +- this.a(chunkcoordintpair, k << 8 | (i1 > 255 ? 255 : i1)); // Spigot ++ this.writeChunk(chunkcoordintpair, k << 8 | (i1 > 255 ? 255 : i1), k, abyte, i); // Paper - Ensure we do not corrupt region files + } + + // Paper start - Now that we've written the new chunk we can free the old data @@ -116,41 +117,45 @@ index 82f7af46f8..e5659980b3 100644 + // Paper end } - this.b(i, j, (int) (SystemUtils.getTimeMillis() / 1000L)); -@@ -0,0 +0,0 @@ public class RegionFile { + this.b(chunkcoordintpair, (int) (SystemUtils.getTimeMillis() / 1000L)); +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { } + private void writeChunkData(final int sectorOffset, final byte[] data, final int dataLength) throws IOException { this.a(sectorOffset, data, dataLength); } // Paper - OBFHELPER private void a(int i, byte[] abyte, int j) throws IOException { - this.c.seek((long) (i * 4096)); -- this.c.writeInt(j + 1); -- this.c.writeByte(2); + this.b.seek((long) (i * 4096)); +- this.b.writeInt(j + 1); +- this.b.writeByte(2); + this.writeIntAndByte(j + 1, (byte)2); // Paper - Avoid 4 io write calls - this.c.write(abyte, 0, j); + this.b.write(abyte, 0, j); } -@@ -0,0 +0,0 @@ public class RegionFile { - return this.getOffset(i, j) != 0; +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + return this.getOffset(chunkcoordintpair) != 0; } -+ private void updateChunkHeader(final int x, final int z, final int offset) throws IOException { this.a(x, z, offset); } // Paper - OBFHELPER - private void a(int i, int j, int k) throws IOException { - this.d[i + j * 32] = k; - this.c.seek((long) ((i + j * 32) * 4)); -- this.c.writeInt(k); -+ this.writeInt(k); // Paper - Avoid 3 io write calls ++ private void updateChunkHeader(ChunkCoordIntPair chunkcoordintpair, final int offset) throws IOException { this.a(chunkcoordintpair, offset); } // Paper - OBFHELPER + private void a(ChunkCoordIntPair chunkcoordintpair, int i) throws IOException { + int j = this.f(chunkcoordintpair); + + this.c[j] = i; + this.b.seek((long) (j * 4)); +- this.b.writeInt(i); ++ this.writeInt(i); // Paper - Avoid 3 io write calls } - private void b(int i, int j, int k) throws IOException { - this.e[i + j * 32] = k; - this.c.seek((long) (4096 + (i + j * 32) * 4)); -- this.c.writeInt(k); -+ this.writeInt(k); // Paper - Avoid 3 io write calls + private int f(ChunkCoordIntPair chunkcoordintpair) { +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { + + this.d[j] = i; + this.b.seek((long) (4096 + j * 4)); +- this.b.writeInt(i); ++ this.writeInt(i); // Paper - Avoid 3 io write calls } public void close() throws IOException { -@@ -0,0 +0,0 @@ public class RegionFile { +@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable { } // Paper start @@ -165,7 +170,7 @@ index 82f7af46f8..e5659980b3 100644 + private final java.nio.ByteBuffer scratchBuffer = java.nio.ByteBuffer.allocate(8); + + private void writeInt(final int value) throws IOException { -+ synchronized (scratchBuffer) { ++ synchronized (this.scratchBuffer) { + this.scratchBuffer.putInt(0, value); + this.getDataFile().write(this.scratchBuffer.array(), 0, 4); + } @@ -173,18 +178,18 @@ index 82f7af46f8..e5659980b3 100644 + + // writes v1 then v2 + private void writeIntAndByte(final int v1, final byte v2) throws IOException { -+ synchronized (scratchBuffer) { ++ synchronized (this.scratchBuffer) { + this.scratchBuffer.putInt(0, v1); + this.scratchBuffer.put(4, v2); + this.getDataFile().write(this.scratchBuffer.array(), 0, 5); + } + } + -+ private void writeChunk(final int x, final int z, final int chunkHeaderData, ++ private void writeChunk(final ChunkCoordIntPair chunk, final int chunkHeaderData, + final int chunkOffset, final byte[] chunkData, final int chunkDataLength) throws IOException { + this.writeChunkData(chunkOffset, chunkData, chunkDataLength); + this.syncRegionFile(); // Sync is required to ensure the previous data is written successfully -+ this.updateChunkHeader(x, z, chunkHeaderData); ++ this.updateChunkHeader(chunk, chunkHeaderData); + this.syncRegionFile(); // Ensure header changes go through + } + diff --git a/Spigot-Server-Patches/Mob-Spawner-API-Enhancements.patch b/Spigot-Server-Patches/Mob-Spawner-API-Enhancements.patch index d52b0d1f33..75cf26f579 100644 --- a/Spigot-Server-Patches/Mob-Spawner-API-Enhancements.patch +++ b/Spigot-Server-Patches/Mob-Spawner-API-Enhancements.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Mob Spawner API Enhancements diff --git a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java -index af38e5396e..b0fbd4f6d8 100644 +index 96080b6c73..c0f5a55120 100644 --- a/src/main/java/net/minecraft/server/MobSpawnerAbstract.java +++ b/src/main/java/net/minecraft/server/MobSpawnerAbstract.java @@ -0,0 +0,0 @@ public abstract class MobSpawnerAbstract { @@ -82,7 +82,7 @@ index af38e5396e..b0fbd4f6d8 100644 nbttagcompound.setShort("MaxNearbyEntities", (short) this.maxNearbyEntities); nbttagcompound.setShort("RequiredPlayerRange", (short) this.requiredPlayerRange); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -index aa63b854d1..a3be2b141e 100644 +index 5c4c3c70c7..e78e3804ba 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java @@ -0,0 +0,0 @@ public class CraftCreatureSpawner extends CraftBlockEntityState -Date: Sun, 24 Mar 2019 01:01:32 -0400 -Subject: [PATCH] Only count Natural Spawned mobs towards natural spawn mob - limit - -This resolves the super common complaint about mobs not spawning. - -This was ultimately a flaw in the vanilla count algorithim that allows -spawners and other misc mobs to count against the mob limit, which are -not bounded, and can prevent the entire world from spawning new. - -I believe Bukkits changes around persistence may of actually made it -worse than vanilla. - -This should fully solve all of the issues around it so that only natural -influences natural spawns. - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index a70a64070e..bfd690eccd 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -@@ -0,0 +0,0 @@ public class PaperWorldConfig { - log("Using vanilla redstone algorithm."); - } - } -+ -+ public boolean countAllMobsForSpawning = false; -+ private void countAllMobsForSpawning() { -+ countAllMobsForSpawning = getBoolean("count-all-mobs-for-spawning", false); -+ if (countAllMobsForSpawning) { -+ log("Counting all mobs for spawning. Mob farms may reduce natural spawns elsewhere in world."); -+ } else { -+ log("Using improved mob spawn limits (Only Natural Spawns impact spawn limits for more natural spawns)"); -+ } -+ } - } -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldEntityList.java b/src/main/java/com/destroystokyo/paper/PaperWorldEntityList.java -index a10a5bc138..a5a63f8004 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperWorldEntityList.java -+++ b/src/main/java/com/destroystokyo/paper/PaperWorldEntityList.java -@@ -0,0 +0,0 @@ import net.minecraft.server.IAnimal; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.World; - import net.minecraft.server.WorldServer; -+import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; - - import java.util.ArrayList; - import java.util.Collection; -@@ -0,0 +0,0 @@ public class PaperWorldEntityList extends ArrayList { - } - - public void updateEntityCount(Entity entity, int amt) { -- if (!(entity instanceof IAnimal)) return; -+ // Only count natural spawns so that mob -+ if (!(entity instanceof IAnimal) || ( -+ !world.paperConfig.countAllMobsForSpawning && -+ entity.spawnReason != SpawnReason.NATURAL && -+ entity.spawnReason != SpawnReason.CHUNK_GEN -+ )) return; - - if (entity instanceof EntityInsentient) { - EntityInsentient entityinsentient = (EntityInsentient) entity; --- \ No newline at end of file diff --git a/Spigot-Server-Patches/Optimize-Captured-TileEntity-Lookup.patch b/Spigot-Server-Patches/Optimize-Captured-TileEntity-Lookup.patch index f2cde082e1..0091c6e3a2 100644 --- a/Spigot-Server-Patches/Optimize-Captured-TileEntity-Lookup.patch +++ b/Spigot-Server-Patches/Optimize-Captured-TileEntity-Lookup.patch @@ -10,10 +10,10 @@ Optimize to check if the captured list even has values in it, and also to just do a get call since the value can never be null. diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 0e8025d311..b940f95bdb 100644 +index de0ed95083..a038945b36 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java -@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc +@@ -0,0 +0,0 @@ public abstract class World implements IIBlockAccess, GeneratorAccess, AutoClose return null; } else { // CraftBukkit start @@ -28,6 +28,6 @@ index 0e8025d311..b940f95bdb 100644 - TileEntity tileentity = null; + //TileEntity tileentity = null; // Paper - move up - if (this.J) { - tileentity = this.E(blockposition); + if (this.tickingTileEntities) { + tileentity = this.B(blockposition); -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Optimize-GameRules-to-use-LinkedHashMap.patch b/Spigot-Server-Patches/Optimize-GameRules-to-use-LinkedHashMap.patch index dc4efa93aa..35b1ed9bf9 100644 --- a/Spigot-Server-Patches/Optimize-GameRules-to-use-LinkedHashMap.patch +++ b/Spigot-Server-Patches/Optimize-GameRules-to-use-LinkedHashMap.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Optimize GameRules to use LinkedHashMap Previously TreeMap was used which has poor get(K) performance. diff --git a/src/main/java/net/minecraft/server/GameRules.java b/src/main/java/net/minecraft/server/GameRules.java -index fd2a4f1b8c..0bd5e02a28 100644 +index 3de9d264db..c6a8004745 100644 --- a/src/main/java/net/minecraft/server/GameRules.java +++ b/src/main/java/net/minecraft/server/GameRules.java @@ -0,0 +0,0 @@ import javax.annotation.Nullable; diff --git a/Spigot-Server-Patches/Optimize-Persistent-Data-Loading.patch b/Spigot-Server-Patches/Optimize-Persistent-Data-Loading.patch index 83d418912d..3397854502 100644 --- a/Spigot-Server-Patches/Optimize-Persistent-Data-Loading.patch +++ b/Spigot-Server-Patches/Optimize-Persistent-Data-Loading.patch @@ -14,54 +14,47 @@ These files take a long time to convert on large worlds and crashes the server. Additionally, cache the result of a file being missing so we don't keep spam checking it. diff --git a/src/main/java/net/minecraft/server/WorldPersistentData.java b/src/main/java/net/minecraft/server/WorldPersistentData.java -index 8d51af2867..e86d382c8d 100644 +index 47a4ea9985..62081349f1 100644 --- a/src/main/java/net/minecraft/server/WorldPersistentData.java +++ b/src/main/java/net/minecraft/server/WorldPersistentData.java +@@ -0,0 +0,0 @@ public class WorldPersistentData { + this.c = datafixer; + this.d = file; + } ++ private static final PersistentBase NO_RESULT = new ForcedChunk(); // Paper + + private File a(String s) { + return new File(this.d, s + ".dat"); @@ -0,0 +0,0 @@ public class WorldPersistentData { @Nullable - public T a(Function function, String s) { + public T b(Supplier supplier, String s) { + if ("Mineshaft_index".equals(s) || "Mineshaft".equals(s)) return null; // Paper - mineshaft is useless data - T persistentbase = (T) this.data.get(s); // Paper - decompile fix + PersistentBase persistentbase = (PersistentBase) this.data.get(s); - if (persistentbase == null && this.e != null) { + if (persistentbase == null) { @@ -0,0 +0,0 @@ public class WorldPersistentData { - persistentbase = function.apply(s); // Paper - decompile fix - persistentbase.a(a(this.e, this.b, s, 1631).getCompound("data")); + + persistentbase.a(nbttagcompound.getCompound("data")); this.data.put(s, persistentbase); - } + } else this.data.put(s, NO_RESULT); // Paper } catch (Exception exception) { - WorldPersistentData.a.error("Error loading saved data: {}", s, exception); + WorldPersistentData.LOGGER.error("Error loading saved data: {}", s, exception); } } -- return persistentbase; -+ return persistentbase == NO_RESULT ? null : persistentbase; // Paper +- return (T) persistentbase; // Paper - decompile fix ++ return (T) persistentbase == NO_RESULT ? null : (T) persistentbase; // Paper - decompile fix // Paper } -+ private static final PersistentBase NO_RESULT = new ForcedChunk("chunks"); // Paper - public void a(String s, PersistentBase persistentbase) { - this.data.put(s, persistentbase); + public void a(PersistentBase persistentbase) { @@ -0,0 +0,0 @@ public class WorldPersistentData { } - public static NBTTagCompound a(IDataManager idatamanager, DimensionManager dimensionmanager, String s, int i) throws IOException { + public NBTTagCompound a(String s, int i) throws IOException { + if ("Mineshaft".equals(s) || "Mineshaft_index".equals(s)) return new NBTTagCompound(); // Paper - File file = idatamanager.getDataFile(dimensionmanager, s); - FileInputStream fileinputstream = new FileInputStream(file); + File file = this.a(s); + PushbackInputStream pushbackinputstream = new PushbackInputStream(new FileInputStream(file), 2); Throwable throwable = null; -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 5c2421ac38..ee071ba2f6 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -0,0 +0,0 @@ public class WorldServer extends World implements IAsyncTaskHandler { - this.P(); - this.Q(); - this.getWorldBorder().a(minecraftserver.au()); -- MCUtil.scheduleAsyncTask(() -> this.getChunkProvider().chunkLoader.getPersistentStructureLegacy(dimensionmanager, worldMaps)); // Paper -+ MCUtil.scheduleAsyncTask(() -> this.getChunkProvider().chunkLoader.getPersistentStructureLegacy(worldProvider.getDimensionManager(), worldMaps)); // Paper - } - - public WorldServer i_() { -- \ No newline at end of file diff --git a/Spigot-Server-Patches/PlayerDeathEvent-getItemsToKeep.patch b/Spigot-Server-Patches/PlayerDeathEvent-getItemsToKeep.patch index 1b940a6f7f..73ab7cf0d5 100644 --- a/Spigot-Server-Patches/PlayerDeathEvent-getItemsToKeep.patch +++ b/Spigot-Server-Patches/PlayerDeathEvent-getItemsToKeep.patch @@ -8,7 +8,7 @@ Exposes a mutable array on items a player should keep on death Example Usage: https://gist.github.com/aikar/5bb202de6057a051a950ce1f29feb0b4 diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 1d37300832..b9d0c0f740 100644 +index f4ee78efc6..84159cd7ee 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { @@ -55,9 +55,9 @@ index 1d37300832..b9d0c0f740 100644 + } + // Paper end + + @Override public void die(DamageSource damagesource) { boolean flag = this.world.getGameRules().getBoolean("showDeathMessages"); - // CraftBukkit start - fire PlayerDeathEvent @@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { this.releaseShoulderEntities(); // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. @@ -70,8 +70,6 @@ index 1d37300832..b9d0c0f740 100644 + processKeep(event, null); + // Paper end } -+ - this.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.DEATH); // Paper + this.setSpectatorTarget(this); // Remove spectated target - // CraftBukkit end -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Prevent-Enderman-from-loading-chunks.patch b/Spigot-Server-Patches/Prevent-Enderman-from-loading-chunks.patch index 953376403e..98e485075b 100644 --- a/Spigot-Server-Patches/Prevent-Enderman-from-loading-chunks.patch +++ b/Spigot-Server-Patches/Prevent-Enderman-from-loading-chunks.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Prevent Enderman from loading chunks diff --git a/src/main/java/net/minecraft/server/EntityEnderman.java b/src/main/java/net/minecraft/server/EntityEnderman.java -index e4aba0e0a8..9450404428 100644 +index de2d995349..f08f139e97 100644 --- a/src/main/java/net/minecraft/server/EntityEnderman.java +++ b/src/main/java/net/minecraft/server/EntityEnderman.java @@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster { @@ -16,8 +16,8 @@ index e4aba0e0a8..9450404428 100644 + IBlockData iblockdata = world.getTypeIfLoaded(blockposition); // Paper + if (iblockdata == null) return; // Paper Block block = iblockdata.getBlock(); - MovingObjectPosition movingobjectposition = world.rayTrace(new Vec3D((double) ((float) MathHelper.floor(this.enderman.locX) + 0.5F), (double) ((float) j + 0.5F), (double) ((float) MathHelper.floor(this.enderman.locZ) + 0.5F)), new Vec3D((double) ((float) i + 0.5F), (double) ((float) j + 0.5F), (double) ((float) k + 0.5F)), FluidCollisionOption.NEVER, true, false); - boolean flag = movingobjectposition != null && movingobjectposition.getBlockPosition().equals(blockposition); + Vec3D vec3d = new Vec3D((double) MathHelper.floor(this.enderman.locX) + 0.5D, (double) j + 0.5D, (double) MathHelper.floor(this.enderman.locZ) + 0.5D); + Vec3D vec3d1 = new Vec3D((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); @@ -0,0 +0,0 @@ public class EntityEnderman extends EntityMonster { int j = MathHelper.floor(this.a.locY + random.nextDouble() * 2.0D); int k = MathHelper.floor(this.a.locZ - 1.0D + random.nextDouble() * 2.0D); @@ -25,7 +25,7 @@ index e4aba0e0a8..9450404428 100644 - IBlockData iblockdata = world.getType(blockposition); + IBlockData iblockdata = world.getTypeIfLoaded(blockposition); // Paper + if (iblockdata == null) return; // Paper - IBlockData iblockdata1 = world.getType(blockposition.down()); + BlockPosition blockposition1 = blockposition.down(); + IBlockData iblockdata1 = world.getType(blockposition1); IBlockData iblockdata2 = Block.getValidBlockForPosition(getEnderman().getCarried(), getEnderman().world, blockposition); // Paper - Fix MC-124320 - -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Prevent-rayTrace-from-loading-chunks.patch b/Spigot-Server-Patches/Prevent-rayTrace-from-loading-chunks.patch index c822f0d748..3897f3b4c8 100644 --- a/Spigot-Server-Patches/Prevent-rayTrace-from-loading-chunks.patch +++ b/Spigot-Server-Patches/Prevent-rayTrace-from-loading-chunks.patch @@ -6,28 +6,34 @@ Subject: [PATCH] Prevent rayTrace from loading chunks ray tracing into an unloaded chunk should be treated as a miss this saves a ton of lag for when AI tries to raytrace near unloaded chunks. -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 7721dfee65..1454af710e 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc - int i1 = MathHelper.floor(d1); - int j1 = MathHelper.floor(d2); - BlockPosition blockposition = new BlockPosition(l, i1, j1); -- IBlockData iblockdata = this.getType(blockposition); -+ IBlockData iblockdata = this.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata == null) return null; // Paper - Fluid fluid = this.getFluid(blockposition); - boolean flag2; - boolean flag3; -@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc - i1 = MathHelper.floor(d1) - (enumdirection == EnumDirection.UP ? 1 : 0); - j1 = MathHelper.floor(d2) - (enumdirection == EnumDirection.SOUTH ? 1 : 0); - blockposition = new BlockPosition(l, i1, j1); -- IBlockData iblockdata1 = this.getType(blockposition); -+ IBlockData iblockdata1 = this.getTypeIfLoaded(blockposition); // Paper -+ if (iblockdata1 == null) return null; // Paper - Fluid fluid1 = this.getFluid(blockposition); +diff --git a/src/main/java/net/minecraft/server/IBlockAccess.java b/src/main/java/net/minecraft/server/IBlockAccess.java +index 8753bea614..039f27312a 100644 +--- a/src/main/java/net/minecraft/server/IBlockAccess.java ++++ b/src/main/java/net/minecraft/server/IBlockAccess.java +@@ -0,0 +0,0 @@ public interface IBlockAccess { - if (!flag || iblockdata1.getMaterial() == Material.PORTAL || !iblockdata1.getCollisionShape(this, blockposition).isEmpty()) { + default MovingObjectPositionBlock rayTrace(RayTrace raytrace) { + return (MovingObjectPositionBlock) a(raytrace, (raytrace1, blockposition) -> { +- IBlockData iblockdata = this.getType(blockposition); ++ // Paper start - Prevent raytrace from loading chunks ++ IBlockData iblockdata = ((World)this).getTypeIfLoaded(blockposition); ++ if (iblockdata == null) { ++ // copied the last function parameter (listed below) ++ Vec3D vec3d = raytrace1.b().d(raytrace1.a()); ++ ++ return MovingObjectPositionBlock.a(raytrace1.a(), EnumDirection.a(vec3d.x, vec3d.y, vec3d.z), new BlockPosition(raytrace1.a())); ++ } ++ // Paper end + Fluid fluid = this.getFluid(blockposition); + Vec3D vec3d = raytrace1.b(); + Vec3D vec3d1 = raytrace1.a(); +@@ -0,0 +0,0 @@ public interface IBlockAccess { + double d13 = d10 * (i1 > 0 ? 1.0D - MathHelper.h(d4) : MathHelper.h(d4)); + double d14 = d11 * (j1 > 0 ? 1.0D - MathHelper.h(d5) : MathHelper.h(d5)); + +- Object object; ++ T object; // Paper - decompile fix (TODO move to mcdev) + + do { + if (d12 > 1.0D && d13 > 1.0D && d14 > 1.0D) { -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Server-Tick-Events.patch b/Spigot-Server-Patches/Server-Tick-Events.patch index a13549962c..a71592ca12 100644 --- a/Spigot-Server-Patches/Server-Tick-Events.patch +++ b/Spigot-Server-Patches/Server-Tick-Events.patch @@ -6,20 +6,20 @@ Subject: [PATCH] Server Tick Events Fires event at start and end of a server tick diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index b93fccf919..d6250c4722 100644 +index e90cf0629a..b790472347 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer implements IAsyncTaskHandler, IMojangStati +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant= 600) { + ++this.bF; + if (this.bF >= 600) { this.startDrownedConversion(300); + this.lastTick = MinecraftServer.currentTick; // Paper - Make sure this is set at start of process - GH-1887 } } else { - this.bI = -1; + this.bF = -1; -- \ No newline at end of file diff --git a/Spigot-Server-Patches/Update-entity-Metadata-for-all-tracked-players.patch b/Spigot-Server-Patches/Update-entity-Metadata-for-all-tracked-players.patch index ec9c2d3668..755eda1d53 100644 --- a/Spigot-Server-Patches/Update-entity-Metadata-for-all-tracked-players.patch +++ b/Spigot-Server-Patches/Update-entity-Metadata-for-all-tracked-players.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Update entity Metadata for all tracked players diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 188e450a13..c1ee63271e 100644 +index 39a040a2a0..c1d1621d9e 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable { +@@ -0,0 +0,0 @@ public class PlayerConnection implements PacketListenerPlayIn { if (event.isCancelled() || this.player.inventory.getItemInHand() == null || this.player.inventory.getItemInHand().getItem() != origItem) { // Refresh the current entity metadata diff --git a/Spigot-Server-Patches/Use-proper-max-length-when-serialising-BungeeCord-te.patch b/Spigot-Server-Patches/Use-proper-max-length-when-serialising-BungeeCord-te.patch index 797c4b6b61..ecdb4f728c 100644 --- a/Spigot-Server-Patches/Use-proper-max-length-when-serialising-BungeeCord-te.patch +++ b/Spigot-Server-Patches/Use-proper-max-length-when-serialising-BungeeCord-te.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Use proper max length when serialising BungeeCord text diff --git a/src/main/java/net/minecraft/server/PacketPlayOutChat.java b/src/main/java/net/minecraft/server/PacketPlayOutChat.java -index eba6aadad7..3a332e980d 100644 +index 0ab611564e..f7b2095bb7 100644 --- a/src/main/java/net/minecraft/server/PacketPlayOutChat.java +++ b/src/main/java/net/minecraft/server/PacketPlayOutChat.java @@ -0,0 +0,0 @@ package net.minecraft.server; diff --git a/Spigot-Server-Patches/Workaround-for-vehicle-tracking-issue-on-disconnect.patch b/Spigot-Server-Patches/Workaround-for-vehicle-tracking-issue-on-disconnect.patch index a89a7170bd..19bf9a1c7d 100644 --- a/Spigot-Server-Patches/Workaround-for-vehicle-tracking-issue-on-disconnect.patch +++ b/Spigot-Server-Patches/Workaround-for-vehicle-tracking-issue-on-disconnect.patch @@ -5,12 +5,12 @@ Subject: [PATCH] Workaround for vehicle tracking issue on disconnect diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java -index 541461275c..1d37300832 100644 +index 2341638617..f4ee78efc6 100644 --- a/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/src/main/java/net/minecraft/server/EntityPlayer.java @@ -0,0 +0,0 @@ public class EntityPlayer extends EntityHuman implements ICrafting { public void n() { - this.cB = true; + this.ct = true; this.ejectPassengers(); + + // Paper start - Workaround an issue where the vehicle doesn't track the passenger disconnection dismount. @@ -19,7 +19,7 @@ index 541461275c..1d37300832 100644 + } + // Paper end + - if (this.sleeping) { - this.a(true, false, false); + if (this.isSleeping()) { + this.wakeup(true, false, false); } -- \ No newline at end of file diff --git a/Spigot-Server-Patches/don-t-NPE-on-dimensionmanager-toString.patch b/Spigot-Server-Patches/don-t-NPE-on-dimensionmanager-toString.patch index 1c3c6265a3..daca0699a2 100644 --- a/Spigot-Server-Patches/don-t-NPE-on-dimensionmanager-toString.patch +++ b/Spigot-Server-Patches/don-t-NPE-on-dimensionmanager-toString.patch @@ -14,23 +14,23 @@ this is not super elegant, but is the only route that promises not to break stuff. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 9c5b79920f..e5242f9f87 100644 +index b05d7b0e87..7cc0c7c162 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -0,0 +0,0 @@ public final class CraftServer implements Server { - } worlddata.checkName(name); // CraftBukkit - Migration did not rewrite the level.dat; This forces 1.8 to take the last loaded world as respawn (in this case the end) -- DimensionManager internalDimension = new DimensionManager(dimension, name, name, () -> DimensionManager.a(creator.environment().getId()).e()); + DimensionManager actualDimension = DimensionManager.a(creator.environment().getId()); +- DimensionManager internalDimension = new DimensionManager(dimension, name, name, (w, manager) -> actualDimension.getWorldProvider(w), actualDimension.hasSkyLight()); + // Paper start - override toString -+ DimensionManager internalDimension = new DimensionManager(dimension, name, name, () -> DimensionManager.a(creator.environment().getId()).e()) { ++ DimensionManager internalDimension = new DimensionManager(dimension, name, name, (w, manager) -> actualDimension.getWorldProvider(w), actualDimension.hasSkyLight()) { + @Override + public String toString() { + return name; + } + }; + // Paper end - WorldServer internal = (WorldServer) new WorldServer(console, sdm, persistentcollection, worlddata, internalDimension, console.methodProfiler, creator.environment(), generator).i_(); + WorldServer internal = (WorldServer) new WorldServer(console, console.executorService, sdm, worlddata, internalDimension, console.getMethodProfiler(), getServer().worldLoadListenerFactory.create(11), creator.environment(), generator); if (!(worlds.containsKey(name.toLowerCase(java.util.Locale.ENGLISH)))) { -- \ No newline at end of file diff --git a/Spigot-Server-Patches/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch b/Spigot-Server-Patches/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch index 65f9519a56..7c07640e5c 100644 --- a/Spigot-Server-Patches/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch +++ b/Spigot-Server-Patches/don-t-go-below-0-for-pickupDelay-breaks-picking-up-i.patch @@ -6,7 +6,7 @@ Subject: [PATCH] don't go below 0 for pickupDelay, breaks picking up items vanilla checks for == 0 diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java -index e723bd339e..5f6e813724 100644 +index c5fefa060b..43fc790a61 100644 --- a/src/main/java/net/minecraft/server/EntityItem.java +++ b/src/main/java/net/minecraft/server/EntityItem.java @@ -0,0 +0,0 @@ public class EntityItem extends Entity { diff --git a/Spigot-Server-Patches/limit-the-range-at-which-we-ll-consider-an-attackabl.patch b/Spigot-Server-Patches/limit-the-range-at-which-we-ll-consider-an-attackabl.patch deleted file mode 100644 index ab44aa910d..0000000000 --- a/Spigot-Server-Patches/limit-the-range-at-which-we-ll-consider-an-attackabl.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Shane Freeder -Date: Tue, 13 Nov 2018 14:01:00 +0000 -Subject: [PATCH] limit the range at which we'll consider an attackable target - -This patch aims to ensure that MCP World#getNearestAttackablePlayer -will not trigger chunk loads due to PathfinderGoalNearestAttackableTarget -performing a ray trace operation by pre-checking the maximum limit; - -Given that the implementation shows that the limit should only ever -decrease when set, allowing us to skip further checks earlier on -when looking for an attackable entity - -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 645af17a58..7721dfee65 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -0,0 +0,0 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc - for (int i = 0; i < this.players.size(); ++i) { - EntityHuman entityhuman1 = (EntityHuman) this.players.get(i); - -+ // Paper start -+ // move distance check up, if set, check distance^2 is less than XZlimit^2, continue -+ // 4th method param is XZlimit (at least at the time of commit) -+ double d6 = entityhuman1.d(d0, entityhuman1.locY, d2); -+ if (d3 < 0.0D || d6 < d3 * d3) - if (!entityhuman1.abilities.isInvulnerable && entityhuman1.isAlive() && !entityhuman1.isSpectator() && (predicate == null || predicate.test(entityhuman1))) { -- double d6 = entityhuman1.d(d0, entityhuman1.locY, d2); -+ // Paper end - double d7 = d3; - - if (entityhuman1.isSneaking()) { --- \ No newline at end of file