diff --git a/Spigot-API-Patches/0181-PlayerDeathEvent-getItemsToKeep.patch b/Spigot-API-Patches/0181-PlayerDeathEvent-getItemsToKeep.patch index e6ccbb43e4..7c0e2f94d8 100644 --- a/Spigot-API-Patches/0181-PlayerDeathEvent-getItemsToKeep.patch +++ b/Spigot-API-Patches/0181-PlayerDeathEvent-getItemsToKeep.patch @@ -1,4 +1,4 @@ -From 9552cb45732ed2d11f179cdf766996d3c0843001 Mon Sep 17 00:00:00 2001 +From f3ebc45b923294990f9db2b1514d34d7c9a4840f Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 11 Mar 2013 20:04:34 -0400 Subject: [PATCH] PlayerDeathEvent#getItemsToKeep @@ -8,10 +8,10 @@ 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/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index 5b0ef1eb1..b30818177 100644 +index 5b0ef1eb..af6070d1 100644 --- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -@@ -18,6 +18,22 @@ public class PlayerDeathEvent extends EntityDeathEvent { +@@ -18,6 +18,40 @@ public class PlayerDeathEvent extends EntityDeathEvent { private boolean keepLevel = false; private boolean keepInventory = false; @@ -19,9 +19,27 @@ index 5b0ef1eb1..b30818177 100644 + private List itemsToKeep = new java.util.ArrayList<>(); + + /** -+ * A mutable collection to add items that the player should keep on death (Similar to KeepInventory game rule) ++ * A mutable collection to add items that the player should retain in their inventory on death (Similar to KeepInventory game rule) + * + * You MUST remove the item from the .getDrops() collection too or it will duplicate! ++ *
++     *    \@EventHandler(ignoreCancelled = true)
++     *     public void onPlayerDeath(PlayerDeathEvent event) {
++     *         for (Iterator iterator = event.getDrops().iterator(); iterator.hasNext(); ) {
++     *             ItemStack drop = iterator.next();
++     *             List lore = drop.getLore();
++     *             if (lore != null && !lore.isEmpty()) {
++     *                 if (lore.get(0).contains("(SOULBOUND)")) {
++     *                     iterator.remove();
++     *                     event.getItemsToKeep().add(drop);
++     *                 }
++     *             }
++     *         }
++     *     }
++     * 
++ * ++ * Adding an item to this list that the player did not previously have will give them the item on death. ++ * An example case could be a "Note" that "You died at X/Y/Z coordinates" + * + * @return The list to hold items to keep + */ diff --git a/Spigot-Server-Patches/0412-Allow-Saving-of-Oversized-Chunks.patch b/Spigot-Server-Patches/0412-Allow-Saving-of-Oversized-Chunks.patch index e63875f91a..e8e8711d86 100644 --- a/Spigot-Server-Patches/0412-Allow-Saving-of-Oversized-Chunks.patch +++ b/Spigot-Server-Patches/0412-Allow-Saving-of-Oversized-Chunks.patch @@ -1,4 +1,4 @@ -From b676fa2fa828bd7dbaa734620bcf463b8bfcea11 Mon Sep 17 00:00:00 2001 +From a159e031449910796e17ce6bf645972011605b65 Mon Sep 17 00:00:00 2001 From: Aikar Date: Fri, 15 Feb 2019 01:08:19 -0500 Subject: [PATCH] Allow Saving of Oversized Chunks @@ -51,7 +51,7 @@ index 12268f87b..e1f7e06ab 100644 a((NBTBase) nbttagcompound, dataoutput); } diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java -index c20511588..d148ce497 100644 +index c20511588..82f7af46f 100644 --- a/src/main/java/net/minecraft/server/RegionFile.java +++ b/src/main/java/net/minecraft/server/RegionFile.java @@ -78,6 +78,7 @@ public class RegionFile { @@ -96,7 +96,7 @@ index c20511588..d148ce497 100644 if (k1 >= 256) { // Spigot start - if (!ENABLE_EXTENDED_SAVE) return; -+ if (!USE_SPIGOT_OVERSIZED_METHOD) throw new ChunkTooLargeException(i, j, k1); // Paper - throw error instead ++ 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; // Spigot end @@ -212,7 +212,7 @@ index c20511588..d148ce497 100644 // Paper end class ChunkBuffer extends ByteArrayOutputStream { -@@ -387,8 +492,40 @@ public class RegionFile { +@@ -387,8 +492,35 @@ public class RegionFile { this.c = j; } @@ -227,36 +227,31 @@ index c20511588..d148ce497 100644 + int length = out.size(); + + RegionFile.this.a(this.b, this.c, bytes, length); // Paper - change to bytes/length -+ // Paper end + } + } + ++ 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(); ++ // since file IO is single threaded, no benefit to using per-region file buffers/synchronization, we can change that later if it becomes viable. + private static DirectByteArrayOutputStream compressData(byte[] buf, int length) throws IOException { -+ final java.util.zip.Deflater deflater; -+ if (length > 1024 * 512) { -+ deflater = new java.util.zip.Deflater(9); -+ } else if (length > 1024 * 128) { -+ deflater = new java.util.zip.Deflater(8); -+ } else { -+ deflater = new java.util.zip.Deflater(6); -+ } ++ synchronized (deflater) { ++ deflater.setInput(buf, 0, length); ++ deflater.finish(); + -+ -+ deflater.setInput(buf, 0, length); -+ deflater.finish(); -+ -+ DirectByteArrayOutputStream out = new DirectByteArrayOutputStream(length); -+ byte[] buffer = new byte[1024 * (length > 1024 * 124 ? 32 : 16)]; -+ while (!deflater.finished()) { -+ out.write(buffer, 0, deflater.deflate(buffer)); ++ DirectByteArrayOutputStream out = new DirectByteArrayOutputStream(length); ++ while (!deflater.finished()) { ++ out.write(compressionBuffer, 0, deflater.deflate(compressionBuffer)); ++ } ++ out.close(); ++ deflater.reset(); ++ return out; } -+ out.close(); -+ deflater.end(); -+ 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 8c8b7cbab..a17e76d83 100644 +index 8c8b7cbab..17e76815a 100644 --- a/src/main/java/net/minecraft/server/RegionFileCache.java +++ b/src/main/java/net/minecraft/server/RegionFileCache.java @@ -16,6 +16,7 @@ public class RegionFileCache { @@ -267,7 +262,7 @@ index 8c8b7cbab..a17e76d83 100644 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"); -@@ -83,6 +84,125 @@ public class RegionFileCache { +@@ -83,6 +84,135 @@ public class RegionFileCache { public static synchronized boolean hasRegionFile(File file, int i, int j) { return RegionFileCache.cache.containsKey(getRegionFileName(file, i, j)); } @@ -276,7 +271,8 @@ index 8c8b7cbab..a17e76d83 100644 + } + + private static final int DEFAULT_SIZE_THRESHOLD = 1024 * 8; -+ private static final int OVERZEALOUS_THRESHOLD = 1024 * 2; ++ private static final int OVERZEALOUS_TOTAL_THRESHOLD = 1024 * 64; ++ private static final int OVERZEALOUS_THRESHOLD = 1024; + private static int SIZE_THRESHOLD = DEFAULT_SIZE_THRESHOLD; + private static void resetFilterThresholds() { + SIZE_THRESHOLD = Math.max(1024 * 4, Integer.getInteger("Paper.FilterThreshhold", DEFAULT_SIZE_THRESHOLD)); @@ -284,6 +280,11 @@ index 8c8b7cbab..a17e76d83 100644 + static { + resetFilterThresholds(); + } ++ ++ static boolean isOverzealous() { ++ 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); + @@ -333,11 +334,15 @@ index 8c8b7cbab..a17e76d83 100644 + private static void filterChunkList(NBTTagCompound level, NBTTagCompound extra, String key) { + NBTTagList list = level.getList(key, 10); + NBTTagList newList = extra.getList(key, 10); ++ int totalSize = 0; + for (Iterator iterator = list.list.iterator(); iterator.hasNext(); ) { + NBTBase object = iterator.next(); -+ if (getNBTSize(object) > SIZE_THRESHOLD) { ++ int nbtSize = getNBTSize(object); ++ if (nbtSize > SIZE_THRESHOLD || (SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD && totalSize > OVERZEALOUS_TOTAL_THRESHOLD)) { + newList.add(object); + iterator.remove(); ++ } else { ++ totalSize += nbtSize; + } + } + level.set(key, list); @@ -393,7 +398,7 @@ index 8c8b7cbab..a17e76d83 100644 // Paper End public static synchronized void a() { -@@ -108,6 +228,12 @@ public class RegionFileCache { +@@ -108,6 +238,12 @@ 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); @@ -406,7 +411,7 @@ index 8c8b7cbab..a17e76d83 100644 DataInputStream datainputstream = regionfile.a(i & 31, j & 31); -@@ -121,11 +247,14 @@ public class RegionFileCache { +@@ -121,11 +257,14 @@ public class RegionFileCache { @Nullable public static void write(File file, int i, int j, NBTTagCompound nbttagcompound) throws IOException { int attempts = 0; Exception laste = null; while (attempts++ < 5) { try { // Paper