diff --git a/patches/api/0003-Test-changes.patch b/patches/api/0003-Test-changes.patch index ad90260609..08d0ec7654 100644 --- a/patches/api/0003-Test-changes.patch +++ b/patches/api/0003-Test-changes.patch @@ -8,6 +8,7 @@ Subject: [PATCH] Test changes - Ignore package-private methods for nullability annotations - Add excludes for classes which don't pass +Co-authored-by: Riley Park Co-authored-by: Jake Potrebic diff --git a/build.gradle.kts b/build.gradle.kts @@ -143,10 +144,25 @@ index 0000000000000000000000000000000000000000..756acf231b1b076b08046d86992ba7ce + +} diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 4ac3dd977e75cd8464163351d306e037ee32cb48..8f35cda0d67ec66646c6096a5bf1c84891b8b0fd 100644 +index 4ac3dd977e75cd8464163351d306e037ee32cb48..c26ea217927ba77611e6ae93f8df50a83bceb3dd 100644 --- a/src/test/java/org/bukkit/AnnotationTest.java +++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -40,7 +40,17 @@ public class AnnotationTest { +@@ -29,7 +29,13 @@ public class AnnotationTest { + "Lorg/jetbrains/annotations/Nullable;", + "Lorg/jetbrains/annotations/NotNull;", + "Lorg/jetbrains/annotations/Contract;", +- "Lorg/bukkit/UndefinedNullability;" ++ "Lorg/bukkit/UndefinedNullability;", ++ // Paper start ++ "Lorg/checkerframework/checker/nullness/qual/MonotonicNonNull;", ++ "Lorg/checkerframework/checker/nullness/qual/NonNull;", ++ "Lorg/checkerframework/checker/nullness/qual/Nullable;", ++ "Lorg/checkerframework/checker/nullness/qual/PolyNull;", ++ // Paper end + }; + + private static final String[] EXCLUDED_CLASSES = { +@@ -40,7 +46,17 @@ public class AnnotationTest { "org/bukkit/util/io/Wrapper", "org/bukkit/plugin/java/PluginClassLoader", // Generic functional interface @@ -165,7 +181,7 @@ index 4ac3dd977e75cd8464163351d306e037ee32cb48..8f35cda0d67ec66646c6096a5bf1c848 }; @Test -@@ -67,14 +77,40 @@ public class AnnotationTest { +@@ -67,14 +83,40 @@ public class AnnotationTest { } if (mustBeAnnotated(Type.getReturnType(method.desc)) && !isWellAnnotated(method.invisibleAnnotations)) { @@ -176,7 +192,7 @@ index 4ac3dd977e75cd8464163351d306e037ee32cb48..8f35cda0d67ec66646c6096a5bf1c848 + } else if (method.invisibleTypeAnnotations != null) { + dance: for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.invisibleTypeAnnotations) { + final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef); -+ if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_RETURN && java.util.Arrays.binarySearch(ACCEPTED_ANNOTATIONS, invisibleTypeAnnotation.desc) >= 0) { ++ if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_RETURN && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) { + warn = false; + break dance; // cha cha real smooth + } @@ -197,7 +213,7 @@ index 4ac3dd977e75cd8464163351d306e037ee32cb48..8f35cda0d67ec66646c6096a5bf1c848 + if (method.invisibleTypeAnnotations != null) { + for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.invisibleTypeAnnotations) { + final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef); -+ if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_FORMAL_PARAMETER && ref.getTypeParameterIndex() == i && java.util.Arrays.binarySearch(ACCEPTED_ANNOTATIONS, invisibleTypeAnnotation.desc) >= 0) { ++ if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_FORMAL_PARAMETER && ref.getTypeParameterIndex() == i && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) { + continue dancing; + } + } @@ -206,7 +222,7 @@ index 4ac3dd977e75cd8464163351d306e037ee32cb48..8f35cda0d67ec66646c6096a5bf1c848 ParameterNode paramNode = parameters == null ? null : parameters.get(i); String paramName = paramNode == null ? null : paramNode.name; -@@ -91,13 +127,18 @@ public class AnnotationTest { +@@ -91,13 +133,18 @@ public class AnnotationTest { Collections.sort(errors); @@ -229,7 +245,7 @@ index 4ac3dd977e75cd8464163351d306e037ee32cb48..8f35cda0d67ec66646c6096a5bf1c848 } private static void collectClasses(@NotNull File from, @NotNull Map to) throws IOException { -@@ -140,6 +181,11 @@ public class AnnotationTest { +@@ -140,6 +187,11 @@ public class AnnotationTest { // Exceptions are excluded return false; } @@ -241,7 +257,7 @@ index 4ac3dd977e75cd8464163351d306e037ee32cb48..8f35cda0d67ec66646c6096a5bf1c848 for (String excludedClass : EXCLUDED_CLASSES) { if (excludedClass.equals(clazz.name)) { -@@ -152,7 +198,7 @@ public class AnnotationTest { +@@ -152,7 +204,7 @@ public class AnnotationTest { private static boolean isMethodIncluded(@NotNull ClassNode clazz, @NotNull MethodNode method, @NotNull Map allClasses) { // Exclude private, synthetic and deprecated methods @@ -250,7 +266,7 @@ index 4ac3dd977e75cd8464163351d306e037ee32cb48..8f35cda0d67ec66646c6096a5bf1c848 return false; } -@@ -170,11 +216,30 @@ public class AnnotationTest { +@@ -170,11 +222,30 @@ public class AnnotationTest { if ("".equals(method.name) && isAnonymous(clazz)) { return false; } @@ -272,12 +288,12 @@ index 4ac3dd977e75cd8464163351d306e037ee32cb48..8f35cda0d67ec66646c6096a5bf1c848 + return true; + } + } -+ + +- private static boolean isWellAnnotated(@Nullable List annotations) { + return false; + } + // Paper end - -- private static boolean isWellAnnotated(@Nullable List annotations) { ++ + private static boolean isWellAnnotated(@Nullable List annotations) { // Paper if (annotations == null) { return false; diff --git a/patches/api/0005-Adventure.patch b/patches/api/0005-Adventure.patch index feb599b6db..aba39bbe77 100644 --- a/patches/api/0005-Adventure.patch +++ b/patches/api/0005-Adventure.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park +From: Riley Park Date: Fri, 29 Jan 2021 17:21:55 +0100 Subject: [PATCH] Adventure @@ -155,23 +155,21 @@ index 0000000000000000000000000000000000000000..ffe0a921cc1ebbb95104f22b57e0e3af +} diff --git a/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java b/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java new file mode 100644 -index 0000000000000000000000000000000000000000..9adeb880f7948f937891d83e256c808b5eb40a27 +index 0000000000000000000000000000000000000000..2ad76b1751ba707f7ae0d283aa1cbaf6c9619da9 --- /dev/null +++ b/src/main/java/io/papermc/paper/chat/ViewerUnawareImpl.java -@@ -0,0 +1,38 @@ +@@ -0,0 +1,35 @@ +package io.papermc.paper.chat; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; -+import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; + +sealed class ViewerUnawareImpl implements ChatRenderer, ChatRenderer.ViewerUnaware permits ViewerUnawareImpl.Default { -+ + private final ViewerUnaware unaware; -+ -+ private @MonotonicNonNull Component message; ++ private @Nullable Component message; + + ViewerUnawareImpl(final ViewerUnaware unaware) { + this.unaware = unaware; @@ -191,7 +189,6 @@ index 0000000000000000000000000000000000000000..9adeb880f7948f937891d83e256c808b + } + + static final class Default extends ViewerUnawareImpl implements ChatRenderer.Default { -+ + Default(final ViewerUnaware unaware) { + super(unaware); + } @@ -752,7 +749,7 @@ index 0000000000000000000000000000000000000000..6e94562d79206d88b74b53814f9423f1 + } +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 446e4d21c5b9b624e633875df62160a7351517d9..0084898567e8bb74fa271b65b56523a5c26d387c 100644 +index 446e4d21c5b9b624e633875df62160a7351517d9..16ec0cd908659d6d53e565281b8db9f81951277d 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -358,7 +358,9 @@ public final class Bukkit { @@ -779,7 +776,7 @@ index 446e4d21c5b9b624e633875df62160a7351517d9..0084898567e8bb74fa271b65b56523a5 + * @param message the message + * @return the number of players + */ -+ public static int broadcast(@NotNull net.kyori.adventure.text.Component message) { ++ public static int broadcast(net.kyori.adventure.text.@NotNull Component message) { + return server.broadcast(message); + } /** @@ -789,7 +786,7 @@ index 446e4d21c5b9b624e633875df62160a7351517d9..0084898567e8bb74fa271b65b56523a5 * permissibles} must have to receive the broadcast * @return number of message recipients */ -+ public static int broadcast(@NotNull net.kyori.adventure.text.Component message, @NotNull String permission) { ++ public static int broadcast(net.kyori.adventure.text.@NotNull Component message, @NotNull String permission) { + return server.broadcast(message, permission); + } + // Paper end @@ -819,7 +816,7 @@ index 446e4d21c5b9b624e633875df62160a7351517d9..0084898567e8bb74fa271b65b56523a5 * @see InventoryType#isCreatable() */ @NotNull -+ public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull net.kyori.adventure.text.Component title) { ++ public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, net.kyori.adventure.text.@NotNull Component title) { + return server.createInventory(owner, type, title); + } + // Paper end @@ -866,7 +863,7 @@ index 446e4d21c5b9b624e633875df62160a7351517d9..0084898567e8bb74fa271b65b56523a5 * @throws IllegalArgumentException if the size is not a multiple of 9 */ @NotNull -+ public static Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull net.kyori.adventure.text.Component title) throws IllegalArgumentException { ++ public static Inventory createInventory(@Nullable InventoryHolder owner, int size, net.kyori.adventure.text.@NotNull Component title) throws IllegalArgumentException { + return server.createInventory(owner, size, title); + } + // Paper end @@ -897,7 +894,7 @@ index 446e4d21c5b9b624e633875df62160a7351517d9..0084898567e8bb74fa271b65b56523a5 * when the merchant inventory is viewed * @return a new merchant */ -+ public static @NotNull Merchant createMerchant(@Nullable net.kyori.adventure.text.Component title) { ++ public static @NotNull Merchant createMerchant(net.kyori.adventure.text.@Nullable Component title) { + return server.createMerchant(title); + } + // Paper start @@ -942,21 +939,21 @@ index 446e4d21c5b9b624e633875df62160a7351517d9..0084898567e8bb74fa271b65b56523a5 } + // Paper start -+ /** -+ * Gets the default message that is displayed when the server is stopped. -+ * -+ * @return the shutdown message -+ */ -+ public static @Nullable net.kyori.adventure.text.Component shutdownMessage() { -+ return server.shutdownMessage(); -+ } -+ // Paper end /** * Gets the default message that is displayed when the server is stopped. * * @return the shutdown message -+ * @deprecated in favour of {@link #shutdownMessage()} */ ++ public static net.kyori.adventure.text.@Nullable Component shutdownMessage() { ++ return server.shutdownMessage(); ++ } ++ // Paper end ++ /** ++ * Gets the default message that is displayed when the server is stopped. ++ * ++ * @return the shutdown message ++ * @deprecated in favour of {@link #shutdownMessage()} ++ */ @Nullable + @Deprecated // Paper public static String getShutdownMessage() { @@ -993,7 +990,7 @@ index 32c92621c2c15eec14c50965f5ecda00c46e6c80..e076d447da62445764a9776ee2554c07 + // Paper end } diff --git a/src/main/java/org/bukkit/Nameable.java b/src/main/java/org/bukkit/Nameable.java -index fee814e01a653d2b53c56e8b566383ca44aa5346..b71b780792b672b37c8fe65d43489b860a227381 100644 +index fee814e01a653d2b53c56e8b566383ca44aa5346..4904a7ec9fcbbc5cb41e07267426b45c60ec655e 100644 --- a/src/main/java/org/bukkit/Nameable.java +++ b/src/main/java/org/bukkit/Nameable.java @@ -4,6 +4,30 @@ import org.jetbrains.annotations.Nullable; @@ -1008,7 +1005,7 @@ index fee814e01a653d2b53c56e8b566383ca44aa5346..b71b780792b672b37c8fe65d43489b86 + * + * @return the custom name + */ -+ @Nullable net.kyori.adventure.text.Component customName(); ++ net.kyori.adventure.text.@Nullable Component customName(); + + /** + * Sets the custom name. @@ -1021,7 +1018,7 @@ index fee814e01a653d2b53c56e8b566383ca44aa5346..b71b780792b672b37c8fe65d43489b86 + * + * @param customName the custom name to set + */ -+ void customName(final @Nullable net.kyori.adventure.text.Component customName); ++ void customName(final net.kyori.adventure.text.@Nullable Component customName); + // Paper end + /** @@ -1119,7 +1116,7 @@ index c559f38fdb92cfee9f2e0ffb7088d1cf74a7f73d..a42f1d53340e4073038d46b7fabf5d44 + // Paper end } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 52dd3148ae2a3480982593dc627ef7eede52bc5a..892e03189957b0072827be4fd485dd98352334e8 100644 +index 52dd3148ae2a3480982593dc627ef7eede52bc5a..0a333c1439b3623d38029b88ce6d5ff159ae1ddd 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -59,13 +59,13 @@ import org.jetbrains.annotations.Nullable; @@ -1175,7 +1172,7 @@ index 52dd3148ae2a3480982593dc627ef7eede52bc5a..892e03189957b0072827be4fd485dd98 + * @param message the message + * @return the number of players + */ -+ int broadcast(@NotNull net.kyori.adventure.text.Component message); ++ int broadcast(net.kyori.adventure.text.@NotNull Component message); + + /** + * Broadcasts the specified message to every user with the given @@ -1186,7 +1183,7 @@ index 52dd3148ae2a3480982593dc627ef7eede52bc5a..892e03189957b0072827be4fd485dd98 + * permissibles} must have to receive the broadcast + * @return number of message recipients + */ -+ int broadcast(@NotNull net.kyori.adventure.text.Component message, @NotNull String permission); ++ int broadcast(net.kyori.adventure.text.@NotNull Component message, @NotNull String permission); + // Paper end /** @@ -1203,7 +1200,7 @@ index 52dd3148ae2a3480982593dc627ef7eede52bc5a..892e03189957b0072827be4fd485dd98 * @see InventoryType#isCreatable() */ @NotNull -+ Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull net.kyori.adventure.text.Component title); ++ Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, net.kyori.adventure.text.@NotNull Component title); + // Paper end + + /** @@ -1236,11 +1233,21 @@ index 52dd3148ae2a3480982593dc627ef7eede52bc5a..892e03189957b0072827be4fd485dd98 Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title); /** -@@ -1151,6 +1209,22 @@ public interface Server extends PluginMessageRecipient { +@@ -1151,6 +1209,7 @@ public interface Server extends PluginMessageRecipient { @NotNull Inventory createInventory(@Nullable InventoryHolder owner, int size) throws IllegalArgumentException; + // Paper start + /** + * Creates an empty inventory of type {@link InventoryType#CHEST} with the + * specified size and title. +@@ -1163,8 +1222,26 @@ public interface Server extends PluginMessageRecipient { + * @throws IllegalArgumentException if the size is not a multiple of 9 + */ + @NotNull ++ Inventory createInventory(@Nullable InventoryHolder owner, int size, net.kyori.adventure.text.@NotNull Component title) throws IllegalArgumentException; ++ // Paper end ++ + /** + * Creates an empty inventory of type {@link InventoryType#CHEST} with the + * specified size and title. @@ -1251,22 +1258,10 @@ index 52dd3148ae2a3480982593dc627ef7eede52bc5a..892e03189957b0072827be4fd485dd98 + * viewed + * @return a new inventory + * @throws IllegalArgumentException if the size is not a multiple of 9 -+ */ -+ @NotNull -+ Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull net.kyori.adventure.text.Component title) throws IllegalArgumentException; -+ // Paper end -+ - /** - * Creates an empty inventory of type {@link InventoryType#CHEST} with the - * specified size and title. -@@ -1161,10 +1235,13 @@ public interface Server extends PluginMessageRecipient { - * viewed - * @return a new inventory - * @throws IllegalArgumentException if the size is not a multiple of 9 + * @deprecated in favour of {@link #createInventory(InventoryHolder, int, net.kyori.adventure.text.Component)} - */ ++ */ + @Deprecated // Paper - @NotNull ++ @NotNull Inventory createInventory(@Nullable InventoryHolder owner, int size, @NotNull String title) throws IllegalArgumentException; + // Paper start @@ -1277,7 +1272,7 @@ index 52dd3148ae2a3480982593dc627ef7eede52bc5a..892e03189957b0072827be4fd485dd98 * when the merchant inventory is viewed * @return a new merchant */ -+ @NotNull Merchant createMerchant(@Nullable net.kyori.adventure.text.Component title); ++ @NotNull Merchant createMerchant(net.kyori.adventure.text.@Nullable Component title); + // Paper start + /** + * Creates an empty merchant. @@ -1302,7 +1297,7 @@ index 52dd3148ae2a3480982593dc627ef7eede52bc5a..892e03189957b0072827be4fd485dd98 + * + * @return the server's MOTD + */ -+ @NotNull net.kyori.adventure.text.Component motd(); ++ net.kyori.adventure.text.@NotNull Component motd(); + // Paper end + /** @@ -1316,19 +1311,19 @@ index 52dd3148ae2a3480982593dc627ef7eede52bc5a..892e03189957b0072827be4fd485dd98 String getMotd(); + // Paper start -+ /** -+ * Gets the default message that is displayed when the server is stopped. -+ * -+ * @return the shutdown message -+ */ -+ @Nullable net.kyori.adventure.text.Component shutdownMessage(); -+ // Paper end /** * Gets the default message that is displayed when the server is stopped. * * @return the shutdown message -+ * @deprecated in favour of {@link #shutdownMessage()} */ ++ net.kyori.adventure.text.@Nullable Component shutdownMessage(); ++ // Paper end ++ /** ++ * Gets the default message that is displayed when the server is stopped. ++ * ++ * @return the shutdown message ++ * @deprecated in favour of {@link #shutdownMessage()} ++ */ @Nullable + @Deprecated // Paper String getShutdownMessage(); @@ -1355,7 +1350,7 @@ index 52dd3148ae2a3480982593dc627ef7eede52bc5a..892e03189957b0072827be4fd485dd98 throw new UnsupportedOperationException("Not supported yet."); } diff --git a/src/main/java/org/bukkit/Sound.java b/src/main/java/org/bukkit/Sound.java -index 5676389bb85607112194fd9a6741ab88254d18bb..fad12a883046010274c8b44426096bfe4703bcc3 100644 +index 5676389bb85607112194fd9a6741ab88254d18bb..5035c525ab40ebdde3da7fe85f5bdf6a26f6cfc0 100644 --- a/src/main/java/org/bukkit/Sound.java +++ b/src/main/java/org/bukkit/Sound.java @@ -10,7 +10,7 @@ import org.jetbrains.annotations.NotNull; @@ -1367,15 +1362,14 @@ index 5676389bb85607112194fd9a6741ab88254d18bb..fad12a883046010274c8b44426096bfe AMBIENT_BASALT_DELTAS_ADDITIONS("ambient.basalt_deltas.additions"), AMBIENT_BASALT_DELTAS_LOOP("ambient.basalt_deltas.loop"), -@@ -1478,4 +1478,12 @@ public enum Sound implements Keyed { +@@ -1478,4 +1478,11 @@ public enum Sound implements Keyed { public NamespacedKey getKey() { return key; } + + // Paper start -+ @NotNull + @Override -+ public net.kyori.adventure.key.@org.checkerframework.checker.nullness.qual.NonNull Key key() { ++ public net.kyori.adventure.key.@NotNull Key key() { + return this.key; + } + // Paper end @@ -1477,7 +1471,7 @@ index 98b9818fa10be7a36e862b3afafc9ed2d0a64209..ed57cd69d88504b78782271c9a3d423a * Returns a list of entities within a bounding box centered around a * Location. diff --git a/src/main/java/org/bukkit/block/CommandBlock.java b/src/main/java/org/bukkit/block/CommandBlock.java -index 372c0bd5a4d7800a11c24c95e39fe376a96232bf..73dce588d1f7a5048300073bf8c2b14d6da1e857 100644 +index 372c0bd5a4d7800a11c24c95e39fe376a96232bf..9c88be68b4f403d0500cb607394b3a1646675ef7 100644 --- a/src/main/java/org/bukkit/block/CommandBlock.java +++ b/src/main/java/org/bukkit/block/CommandBlock.java @@ -33,7 +33,9 @@ public interface CommandBlock extends TileState { @@ -1507,7 +1501,7 @@ index 372c0bd5a4d7800a11c24c95e39fe376a96232bf..73dce588d1f7a5048300073bf8c2b14d + * + * @return Name of this CommandBlock. + */ -+ public @NotNull net.kyori.adventure.text.Component name(); ++ public net.kyori.adventure.text.@NotNull Component name(); + + /** + * Sets the name of this CommandBlock. The name is used with commands @@ -1516,25 +1510,60 @@ index 372c0bd5a4d7800a11c24c95e39fe376a96232bf..73dce588d1f7a5048300073bf8c2b14d + * + * @param name New name for this CommandBlock. + */ -+ public void name(@Nullable net.kyori.adventure.text.Component name); ++ public void name(net.kyori.adventure.text.@Nullable Component name); + // Paper end } diff --git a/src/main/java/org/bukkit/block/Sign.java b/src/main/java/org/bukkit/block/Sign.java -index ab6b0ec328e94bf65a0dafd0403e5ee3b870296c..c8d37184d8e882a4084a1bfef85faa330588600b 100644 +index ab6b0ec328e94bf65a0dafd0403e5ee3b870296c..f87bdb2757760d95038d1a1cf6e7f5b2cff91432 100644 --- a/src/main/java/org/bukkit/block/Sign.java +++ b/src/main/java/org/bukkit/block/Sign.java -@@ -7,13 +7,48 @@ import org.jetbrains.annotations.NotNull; +@@ -7,14 +7,14 @@ import org.jetbrains.annotations.NotNull; * Represents a captured state of either a SignPost or a WallSign. */ public interface Sign extends TileState, Colorable { +- + // Paper start + /** + * Gets all the lines of text currently on this sign. + * + * @return Array of Strings containing each line of text + */ + @NotNull +- public String[] getLines(); ++ public java.util.List lines(); + + /** + * Gets the line of text at the specified index. +@@ -22,11 +22,11 @@ public interface Sign extends TileState, Colorable { + * For example, getLine(0) will return the first line of text. + * + * @param index Line number to get the text from, starting at 0 +- * @return Text on the given line + * @throws IndexOutOfBoundsException Thrown when the line does not exist ++ * @return Text on the given line + */ + @NotNull +- public String getLine(int index) throws IndexOutOfBoundsException; ++ public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException; + + /** + * Sets the line of text at the specified index. +@@ -38,6 +38,45 @@ public interface Sign extends TileState, Colorable { + * @param line New text to set at the specified index + * @throws IndexOutOfBoundsException If the index is out of the range 0..3 + */ ++ public void line(int index, net.kyori.adventure.text.@NotNull Component line) throws IndexOutOfBoundsException; ++ // Paper end ++ + /** + * Gets all the lines of text currently on this sign. + * + * @return Array of Strings containing each line of text ++ * @deprecated in favour of {@link #lines()} + */ + @NotNull -+ public java.util.List lines(); ++ @Deprecated // Paper ++ public String[] getLines(); + + /** + * Gets the line of text at the specified index. @@ -1542,11 +1571,13 @@ index ab6b0ec328e94bf65a0dafd0403e5ee3b870296c..c8d37184d8e882a4084a1bfef85faa33 + * For example, getLine(0) will return the first line of text. + * + * @param index Line number to get the text from, starting at 0 -+ * @throws IndexOutOfBoundsException Thrown when the line does not exist + * @return Text on the given line ++ * @throws IndexOutOfBoundsException Thrown when the line does not exist ++ * @deprecated in favour of {@link #line(int)} + */ + @NotNull -+ public net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException; ++ @Deprecated // Paper ++ public String getLine(int index) throws IndexOutOfBoundsException; + + /** + * Sets the line of text at the specified index. @@ -1557,44 +1588,14 @@ index ab6b0ec328e94bf65a0dafd0403e5ee3b870296c..c8d37184d8e882a4084a1bfef85faa33 + * @param index Line number to set the text at, starting from 0 + * @param line New text to set at the specified index + * @throws IndexOutOfBoundsException If the index is out of the range 0..3 -+ */ -+ public void line(int index, @NotNull net.kyori.adventure.text.Component line) throws IndexOutOfBoundsException; -+ // Paper end - - /** - * Gets all the lines of text currently on this sign. - * - * @return Array of Strings containing each line of text -+ * @deprecated in favour of {@link #lines()} - */ - @NotNull -+ @Deprecated // Paper - public String[] getLines(); - - /** -@@ -24,8 +59,10 @@ public interface Sign extends TileState, Colorable { - * @param index Line number to get the text from, starting at 0 - * @return Text on the given line - * @throws IndexOutOfBoundsException Thrown when the line does not exist -+ * @deprecated in favour of {@link #line(int)} - */ - @NotNull -+ @Deprecated // Paper - public String getLine(int index) throws IndexOutOfBoundsException; - - /** -@@ -37,7 +74,9 @@ public interface Sign extends TileState, Colorable { - * @param index Line number to set the text at, starting from 0 - * @param line New text to set at the specified index - * @throws IndexOutOfBoundsException If the index is out of the range 0..3 + * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} - */ ++ */ + @Deprecated // Paper public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException; /** diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 80209bb88a0294d4eedc78509533a6257315d856..caa29be46e8541b69ec47c181eb3320d6515b544 100644 +index 80209bb88a0294d4eedc78509533a6257315d856..75759131bd94b672bec4cd8e271ebff1ad391cba 100644 --- a/src/main/java/org/bukkit/command/Command.java +++ b/src/main/java/org/bukkit/command/Command.java @@ -32,7 +32,7 @@ public abstract class Command { @@ -1659,7 +1660,7 @@ index 80209bb88a0294d4eedc78509533a6257315d856..caa29be46e8541b69ec47c181eb3320d + * + * @return the permission message + */ -+ public @Nullable net.kyori.adventure.text.Component permissionMessage() { ++ public net.kyori.adventure.text.@Nullable Component permissionMessage() { + return this.permissionMessage; + } + @@ -1668,7 +1669,7 @@ index 80209bb88a0294d4eedc78509533a6257315d856..caa29be46e8541b69ec47c181eb3320d + * + * @param permissionMessage the permission message + */ -+ public void permissionMessage(@Nullable net.kyori.adventure.text.Component permissionMessage) { ++ public void permissionMessage(net.kyori.adventure.text.@Nullable Component permissionMessage) { + this.permissionMessage = permissionMessage; + } + // Paper end @@ -1683,11 +1684,11 @@ index 80209bb88a0294d4eedc78509533a6257315d856..caa29be46e8541b69ec47c181eb3320d + broadcastCommandMessage(source, net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message), sendToSource); + } + -+ public static void broadcastCommandMessage(@NotNull CommandSender source, @NotNull net.kyori.adventure.text.Component message) { ++ public static void broadcastCommandMessage(@NotNull CommandSender source, net.kyori.adventure.text.@NotNull Component message) { + broadcastCommandMessage(source, message, true); + } + -+ public static void broadcastCommandMessage(@NotNull CommandSender source, @NotNull net.kyori.adventure.text.Component message, boolean sendToSource) { ++ public static void broadcastCommandMessage(@NotNull CommandSender source, net.kyori.adventure.text.@NotNull Component message, boolean sendToSource) { + net.kyori.adventure.text.TextComponent.Builder result = net.kyori.adventure.text.Component.text() + .color(net.kyori.adventure.text.format.NamedTextColor.WHITE) + .decoration(net.kyori.adventure.text.format.TextDecoration.ITALIC, false) @@ -1713,7 +1714,7 @@ index 80209bb88a0294d4eedc78509533a6257315d856..caa29be46e8541b69ec47c181eb3320d if (sendToSource && !(source instanceof ConsoleCommandSender)) { source.sendMessage(message); diff --git a/src/main/java/org/bukkit/command/CommandSender.java b/src/main/java/org/bukkit/command/CommandSender.java -index 284be63a125624a8ae43d2c164aede810ce6bfe5..5e7f8822a17459583d9950dc09e3888f492bfd87 100644 +index 284be63a125624a8ae43d2c164aede810ce6bfe5..63ec8f2b31e5040eb8d7c7edad011b1976e1e5a3 100644 --- a/src/main/java/org/bukkit/command/CommandSender.java +++ b/src/main/java/org/bukkit/command/CommandSender.java @@ -6,12 +6,13 @@ import org.bukkit.permissions.Permissible; @@ -1806,10 +1807,10 @@ index 284be63a125624a8ae43d2c164aede810ce6bfe5..5e7f8822a17459583d9950dc09e3888f + * + * @return Name of the sender + */ -+ public @NotNull net.kyori.adventure.text.Component name(); ++ public net.kyori.adventure.text.@NotNull Component name(); + + @Override -+ default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity identity, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { ++ default void sendMessage(final net.kyori.adventure.identity.@NotNull Identity identity, final net.kyori.adventure.text.@NotNull Component message, final net.kyori.adventure.audience.@NotNull MessageType type) { + this.sendMessage(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(message)); + } + @@ -1849,7 +1850,7 @@ index a542c4bb3c973bbe4b976642feccde6a4d90cb7b..ef870b864c1e36032b54b31f3f85707e pluginCmds.add(newCmd); diff --git a/src/main/java/org/bukkit/command/ProxiedCommandSender.java b/src/main/java/org/bukkit/command/ProxiedCommandSender.java -index fcc34b640265f4dccb46b9f09466ab8e1d96043e..74599b4ee0518481c0e3a5f6ab2f5302837f1ae3 100644 +index fcc34b640265f4dccb46b9f09466ab8e1d96043e..5c813ac024f675951159a59d88d8baa0d49840e9 100644 --- a/src/main/java/org/bukkit/command/ProxiedCommandSender.java +++ b/src/main/java/org/bukkit/command/ProxiedCommandSender.java @@ -3,7 +3,7 @@ package org.bukkit.command; @@ -1867,7 +1868,7 @@ index fcc34b640265f4dccb46b9f09466ab8e1d96043e..74599b4ee0518481c0e3a5f6ab2f5302 + // Paper start + @Override -+ default void sendMessage(final @NotNull net.kyori.adventure.identity.Identity source, final @NotNull net.kyori.adventure.text.Component message, final @NotNull net.kyori.adventure.audience.MessageType type) { ++ default void sendMessage(final net.kyori.adventure.identity.@NotNull Identity source, final net.kyori.adventure.text.@NotNull Component message, final net.kyori.adventure.audience.@NotNull MessageType type) { + net.kyori.adventure.audience.ForwardingAudience.Single.super.sendMessage(source, message, type); + } + @@ -1879,7 +1880,7 @@ index fcc34b640265f4dccb46b9f09466ab8e1d96043e..74599b4ee0518481c0e3a5f6ab2f5302 + // Paper end } diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java -index e2800dc97af5bbb02c555069285a0fa155a9799d..5744a9f432ec75f6b6b1991ff488dffb9591c934 100644 +index e2800dc97af5bbb02c555069285a0fa155a9799d..2dc749936df6168073a5bb9f9051d55f8589ac62 100644 --- a/src/main/java/org/bukkit/enchantments/Enchantment.java +++ b/src/main/java/org/bukkit/enchantments/Enchantment.java @@ -299,6 +299,19 @@ public abstract class Enchantment implements Keyed { @@ -1897,7 +1898,7 @@ index e2800dc97af5bbb02c555069285a0fa155a9799d..5744a9f432ec75f6b6b1991ff488dffb + * @param level the level of the enchantment to show + * @return the name of the enchantment with {@code level} applied + */ -+ public abstract @NotNull net.kyori.adventure.text.Component displayName(int level); ++ public abstract net.kyori.adventure.text.@NotNull Component displayName(int level); + // Paper end @Override @@ -1919,7 +1920,7 @@ index 9566e4306ada5e82dede0f002aa06da12c44996b..4d5f0837bd0e02a30c943d8969fb6b13 + // Paper end } diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java -index 281518d6e1f67722134e22d89b71106aae0c4397..0a539af95e1bd331cec241403a15e4e6dbf6d996 100644 +index 281518d6e1f67722134e22d89b71106aae0c4397..d5be25c62b2eb90f8e171646b460fef04cf2a470 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java @@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable; @@ -1943,7 +1944,7 @@ index 281518d6e1f67722134e22d89b71106aae0c4397..0a539af95e1bd331cec241403a15e4e6 + * + * @return the team display name + */ -+ @NotNull net.kyori.adventure.text.Component teamDisplayName(); ++ net.kyori.adventure.text.@NotNull Component teamDisplayName(); + + @NotNull + @Override @@ -1953,7 +1954,7 @@ index 281518d6e1f67722134e22d89b71106aae0c4397..0a539af95e1bd331cec241403a15e4e6 + // Paper end } diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index c60e1fc1cad1b9889a508602df84840723b7b966..59c1a3a137bd8f469353273cb98afae024b1e6ef 100644 +index c60e1fc1cad1b9889a508602df84840723b7b966..fbf56bcc4540f7f1a8ced7cc2cd96e291c1ac273 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -39,7 +39,28 @@ import org.jetbrains.annotations.Nullable; @@ -1965,7 +1966,7 @@ index c60e1fc1cad1b9889a508602df84840723b7b966..59c1a3a137bd8f469353273cb98afae0 + + // Paper start + @Override -+ default @NotNull net.kyori.adventure.identity.Identity identity() { ++ default net.kyori.adventure.identity.@NotNull Identity identity() { + return net.kyori.adventure.identity.Identity.identity(this.getUniqueId()); + } + @@ -1974,14 +1975,14 @@ index c60e1fc1cad1b9889a508602df84840723b7b966..59c1a3a137bd8f469353273cb98afae0 + * + * @return the display name + */ -+ @NotNull net.kyori.adventure.text.Component displayName(); ++ net.kyori.adventure.text.@NotNull Component displayName(); + + /** + * Sets the "friendly" name to display of this player. + * + * @param displayName the display name to set + */ -+ void displayName(final @Nullable net.kyori.adventure.text.Component displayName); ++ void displayName(final net.kyori.adventure.text.@Nullable Component displayName); + // Paper end /** @@ -2013,28 +2014,28 @@ index c60e1fc1cad1b9889a508602df84840723b7b966..59c1a3a137bd8f469353273cb98afae0 + * + * @param name new player list name + */ -+ void playerListName(@Nullable net.kyori.adventure.text.Component name); ++ void playerListName(net.kyori.adventure.text.@Nullable Component name); + + /** + * Gets the name that is shown on the in-game player list. + * + * @return the player list name + */ -+ @NotNull net.kyori.adventure.text.Component playerListName(); ++ net.kyori.adventure.text.@NotNull Component playerListName(); + + /** + * Gets the currently displayed player list header for this player. + * + * @return player list header or null + */ -+ @Nullable net.kyori.adventure.text.Component playerListHeader(); ++ net.kyori.adventure.text.@Nullable Component playerListHeader(); + + /** + * Gets the currently displayed player list footer for this player. + * + * @return player list footer or null + */ -+ @Nullable net.kyori.adventure.text.Component playerListFooter(); ++ net.kyori.adventure.text.@Nullable Component playerListFooter(); + // Paper end /** * Gets the name that is shown on the player list. @@ -2125,53 +2126,35 @@ index c60e1fc1cad1b9889a508602df84840723b7b966..59c1a3a137bd8f469353273cb98afae0 + * + * @param message kick message + */ -+ void kick(final @Nullable net.kyori.adventure.text.Component message); ++ void kick(final net.kyori.adventure.text.@Nullable Component message); + // Paper end + /** * Says a message (or runs a command). * -@@ -573,6 +659,90 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -573,6 +659,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ public void sendEquipmentChange(@NotNull LivingEntity entity, @NotNull Map items); + // Paper start -+ /** -+ * Send a sign change. This fakes a sign change packet for a user at -+ * a certain location. This will not actually change the world in any way. -+ * This method will use a sign at the location's block or a faked sign -+ * sent via -+ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. -+ *

-+ * If the client does not have a sign at the given location it will -+ * display an error message to the user. -+ * -+ * @param loc the location of the sign -+ * @param lines the new text on the sign or null to clear it -+ * @throws IllegalArgumentException if location is null -+ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 -+ */ + /** + * Send a sign change. This fakes a sign change packet for a user at + * a certain location. This will not actually change the world in any way. +@@ -588,7 +675,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException if location is null + * @throws IllegalArgumentException if lines is non-null and has a length less than 4 + */ +- public void sendSignChange(@NotNull Location loc, @Nullable String[] lines) throws IllegalArgumentException; + default void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines) throws IllegalArgumentException { + this.sendSignChange(loc, lines, DyeColor.BLACK); + } -+ -+ /** -+ * Send a sign change. This fakes a sign change packet for a user at -+ * a certain location. This will not actually change the world in any way. -+ * This method will use a sign at the location's block or a faked sign -+ * sent via -+ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. -+ *

-+ * If the client does not have a sign at the given location it will -+ * display an error message to the user. -+ * -+ * @param loc the location of the sign -+ * @param lines the new text on the sign or null to clear it -+ * @param dyeColor the color of the sign -+ * @throws IllegalArgumentException if location is null -+ * @throws IllegalArgumentException if dyeColor is null -+ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 -+ */ + + /** + * Send a sign change. This fakes a sign change packet for a user at +@@ -607,6 +696,91 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * @throws IllegalArgumentException if dyeColor is null + * @throws IllegalArgumentException if lines is non-null and has a length less than 4 + */ + default void sendSignChange(@NotNull Location loc, @Nullable java.util.List lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException { + this.sendSignChange(loc, lines, dyeColor, false); + } @@ -2219,25 +2202,43 @@ index c60e1fc1cad1b9889a508602df84840723b7b966..59c1a3a137bd8f469353273cb98afae0 + throws IllegalArgumentException; + // Paper end + - /** - * Send a sign change. This fakes a sign change packet for a user at - * a certain location. This will not actually change the world in any way. -@@ -587,7 +757,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param lines the new text on the sign or null to clear it - * @throws IllegalArgumentException if location is null - * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ /** ++ * Send a sign change. This fakes a sign change packet for a user at ++ * a certain location. This will not actually change the world in any way. ++ * This method will use a sign at the location's block or a faked sign ++ * sent via ++ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. ++ *

++ * If the client does not have a sign at the given location it will ++ * display an error message to the user. ++ * ++ * @param loc the location of the sign ++ * @param lines the new text on the sign or null to clear it ++ * @throws IllegalArgumentException if location is null ++ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 + * @deprecated in favour of {@link #sendSignChange(org.bukkit.Location, java.util.List)} - */ ++ */ + @Deprecated // Paper - public void sendSignChange(@NotNull Location loc, @Nullable String[] lines) throws IllegalArgumentException; - - /** -@@ -606,7 +778,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @throws IllegalArgumentException if location is null - * @throws IllegalArgumentException if dyeColor is null - * @throws IllegalArgumentException if lines is non-null and has a length less than 4 ++ public void sendSignChange(@NotNull Location loc, @Nullable String[] lines) throws IllegalArgumentException; ++ ++ /** ++ * Send a sign change. This fakes a sign change packet for a user at ++ * a certain location. This will not actually change the world in any way. ++ * This method will use a sign at the location's block or a faked sign ++ * sent via ++ * {@link #sendBlockChange(org.bukkit.Location, org.bukkit.Material, byte)}. ++ *

++ * If the client does not have a sign at the given location it will ++ * display an error message to the user. ++ * ++ * @param loc the location of the sign ++ * @param lines the new text on the sign or null to clear it ++ * @param dyeColor the color of the sign ++ * @throws IllegalArgumentException if location is null ++ * @throws IllegalArgumentException if dyeColor is null ++ * @throws IllegalArgumentException if lines is non-null and has a length less than 4 + * @deprecated in favour of {@link #sendSignChange(org.bukkit.Location, java.util.List, org.bukkit.DyeColor)} - */ ++ */ + @Deprecated // Paper public void sendSignChange(@NotNull Location loc, @Nullable String[] lines, @NotNull DyeColor dyeColor) throws IllegalArgumentException; @@ -2260,7 +2261,7 @@ index c60e1fc1cad1b9889a508602df84840723b7b966..59c1a3a137bd8f469353273cb98afae0 * @param url The URL from which the client will download the resource * pack. The string must contain only US-ASCII characters and should * be encoded as per RFC 1738. -@@ -1145,8 +1322,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM +@@ -1145,8 +1322,57 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @throws IllegalArgumentException Thrown if the hash is not 20 bytes * long. */ @@ -2268,25 +2269,6 @@ index c60e1fc1cad1b9889a508602df84840723b7b966..59c1a3a137bd8f469353273cb98afae0 public void setResourcePack(@NotNull String url, @Nullable byte[] hash, @Nullable String prompt); + // Paper start - /** - * Request that the player's client download and switch resource packs. - *

-@@ -1182,6 +1361,54 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - * @param hash The sha1 hash sum of the resource pack file which is used - * to apply a cached version of the pack directly without downloading - * if it is available. Hast to be 20 bytes long! -+ * @param prompt The optional custom prompt message to be shown to client. -+ * @throws IllegalArgumentException Thrown if the URL is null. -+ * @throws IllegalArgumentException Thrown if the URL is too long. The -+ * length restriction is an implementation specific arbitrary value. -+ * @throws IllegalArgumentException Thrown if the hash is not 20 bytes -+ * long. -+ */ -+ default void setResourcePack(@NotNull String url, byte @Nullable [] hash, net.kyori.adventure.text.@Nullable Component prompt) { -+ this.setResourcePack(url, hash, prompt, false); -+ } -+ // Paper end -+ + /** + * Request that the player's client download and switch resource packs. + *

@@ -2316,16 +2298,35 @@ index c60e1fc1cad1b9889a508602df84840723b7b966..59c1a3a137bd8f469353273cb98afae0 + * pack correctly. + * + * -+ * @deprecated in favour of {@link #setResourcePack(String, byte[], Component, boolean)} + * @param url The URL from which the client will download the resource + * pack. The string must contain only US-ASCII characters and should + * be encoded as per RFC 1738. + * @param hash The sha1 hash sum of the resource pack file which is used + * to apply a cached version of the pack directly without downloading + * if it is available. Hast to be 20 bytes long! - * @param force If true, the client will be disconnected from the server - * when it declines to use the resource pack. - * @throws IllegalArgumentException Thrown if the URL is null. ++ * @param prompt The optional custom prompt message to be shown to client. ++ * @throws IllegalArgumentException Thrown if the URL is null. ++ * @throws IllegalArgumentException Thrown if the URL is too long. The ++ * length restriction is an implementation specific arbitrary value. ++ * @throws IllegalArgumentException Thrown if the hash is not 20 bytes ++ * long. ++ */ ++ default void setResourcePack(@NotNull String url, byte @Nullable [] hash, net.kyori.adventure.text.@Nullable Component prompt) { ++ this.setResourcePack(url, hash, prompt, false); ++ } ++ // Paper end ++ + /** + * Request that the player's client download and switch resource packs. + *

+@@ -1176,6 +1402,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + * pack correctly. + * + * ++ * @deprecated in favour of {@link #setResourcePack(String, byte[], Component, boolean)} + * @param url The URL from which the client will download the resource + * pack. The string must contain only US-ASCII characters and should + * be encoded as per RFC 1738. @@ -1236,8 +1463,57 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @throws IllegalArgumentException Thrown if the hash is not 20 bytes * long. @@ -2499,7 +2500,7 @@ index c60e1fc1cad1b9889a508602df84840723b7b966..59c1a3a137bd8f469353273cb98afae0 throw new UnsupportedOperationException("Not supported yet."); } diff --git a/src/main/java/org/bukkit/entity/TextDisplay.java b/src/main/java/org/bukkit/entity/TextDisplay.java -index a0ee539a46bcdf49ea750318374d393e9ef3ce68..112fa7a324bc1e49a4ebb0c8f46866a3c02ab984 100644 +index a0ee539a46bcdf49ea750318374d393e9ef3ce68..fc4fe1ca764050dbdb0bb697cf4c147bd60f5a81 100644 --- a/src/main/java/org/bukkit/entity/TextDisplay.java +++ b/src/main/java/org/bukkit/entity/TextDisplay.java @@ -13,17 +13,37 @@ public interface TextDisplay extends Display { @@ -2527,14 +2528,14 @@ index a0ee539a46bcdf49ea750318374d393e9ef3ce68..112fa7a324bc1e49a4ebb0c8f46866a3 + * + * @return the displayed text + */ -+ @NotNull net.kyori.adventure.text.Component text(); ++ net.kyori.adventure.text.@NotNull Component text(); + + /** + * Sets the displayed text. + * + * @param text the new text + */ -+ void text(@Nullable net.kyori.adventure.text.Component text); ++ void text(net.kyori.adventure.text.@Nullable Component text); + // Paper end + /** @@ -2555,7 +2556,7 @@ index 63c80b4ee1f7adc8a9efc3b607993104b1991f90..91cab8b13d5bba34007f124838b32a1d } diff --git a/src/main/java/org/bukkit/event/block/SignChangeEvent.java b/src/main/java/org/bukkit/event/block/SignChangeEvent.java -index 7190db11eff7d48df8a99f405a9dbaefdfa76e3d..1268066e30ddb0cd3792ea4b3de894eb04196669 100644 +index 7190db11eff7d48df8a99f405a9dbaefdfa76e3d..c40536f781393cb39e6a1a4ba6e780713d5dc126 100644 --- a/src/main/java/org/bukkit/event/block/SignChangeEvent.java +++ b/src/main/java/org/bukkit/event/block/SignChangeEvent.java @@ -16,12 +16,25 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { @@ -2586,18 +2587,55 @@ index 7190db11eff7d48df8a99f405a9dbaefdfa76e3d..1268066e30ddb0cd3792ea4b3de894eb } /** -@@ -34,14 +47,52 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { +@@ -34,14 +47,14 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { return player; } + // Paper start + /** + * Gets all of the lines of text from the sign involved in this event. + * + * @return the String array for the sign's lines new text + */ +- @NotNull +- public String[] getLines() { +- return lines; ++ public @NotNull java.util.List lines() { ++ return this.adventure$lines; + } + + /** +@@ -53,9 +66,8 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { + * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 + * or < 0} + */ +- @Nullable +- public String getLine(int index) throws IndexOutOfBoundsException { +- return lines[index]; ++ public net.kyori.adventure.text.@Nullable Component line(int index) throws IndexOutOfBoundsException { ++ return this.adventure$lines.get(index); + } + + /** +@@ -66,8 +78,51 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { + * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 + * or < 0} + */ ++ public void line(int index, net.kyori.adventure.text.@Nullable Component line) throws IndexOutOfBoundsException { ++ this.adventure$lines.set(index, line); ++ } ++ // Paper end ++ + /** + * Gets all of the lines of text from the sign involved in this event. + * + * @return the String array for the sign's lines new text ++ * @deprecated in favour of {@link #lines()} + */ -+ public @NotNull java.util.List lines() { -+ return this.adventure$lines; ++ @NotNull ++ @Deprecated // Paper ++ public String[] getLines() { ++ return adventure$lines.stream().map(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection()::serialize).toArray(String[]::new); // Paper + } + + /** @@ -2608,9 +2646,12 @@ index 7190db11eff7d48df8a99f405a9dbaefdfa76e3d..1268066e30ddb0cd3792ea4b3de894eb + * provided index + * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 + * or < 0} ++ * @deprecated in favour of {@link #line(int)} + */ -+ public @Nullable net.kyori.adventure.text.Component line(int index) throws IndexOutOfBoundsException { -+ return this.adventure$lines.get(index); ++ @Nullable ++ @Deprecated // Paper ++ public String getLine(int index) throws IndexOutOfBoundsException { ++ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.adventure$lines.get(index)); // Paper + } + + /** @@ -2620,46 +2661,8 @@ index 7190db11eff7d48df8a99f405a9dbaefdfa76e3d..1268066e30ddb0cd3792ea4b3de894eb + * @param line text to set + * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 + * or < 0} -+ */ -+ public void line(int index, @Nullable net.kyori.adventure.text.Component line) throws IndexOutOfBoundsException { -+ this.adventure$lines.set(index, line); -+ } -+ // Paper end -+ - /** - * Gets all of the lines of text from the sign involved in this event. - * - * @return the String array for the sign's lines new text -+ * @deprecated in favour of {@link #lines()} - */ - @NotNull -+ @Deprecated // Paper - public String[] getLines() { -- return lines; -+ return adventure$lines.stream().map(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection()::serialize).toArray(String[]::new); // Paper - } - - /** -@@ -52,10 +103,12 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - * provided index - * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 - * or < 0} -+ * @deprecated in favour of {@link #line(int)} - */ - @Nullable -+ @Deprecated // Paper - public String getLine(int index) throws IndexOutOfBoundsException { -- return lines[index]; -+ return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.adventure$lines.get(index)); // Paper - } - - /** -@@ -65,9 +118,11 @@ public class SignChangeEvent extends BlockEvent implements Cancellable { - * @param line text to set - * @throws IndexOutOfBoundsException thrown when the provided index is {@literal > 3 - * or < 0} + * @deprecated in favour of {@link #line(int, net.kyori.adventure.text.Component)} - */ ++ */ + @Deprecated // Paper public void setLine(int index, @Nullable String line) throws IndexOutOfBoundsException { - lines[index] = line; @@ -2668,7 +2671,7 @@ index 7190db11eff7d48df8a99f405a9dbaefdfa76e3d..1268066e30ddb0cd3792ea4b3de894eb @Override diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index 3c2ea8fec3a748cab7f5ad9100d12bd8213ec6c9..1f1df82c9bcf18bad1187e3f24ede1901d91c06f 100644 +index 3c2ea8fec3a748cab7f5ad9100d12bd8213ec6c9..a803bfea5400b3578bb4cf3261874e873b6467d9 100644 --- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java @@ -12,25 +12,48 @@ import org.jetbrains.annotations.Nullable; @@ -2684,11 +2687,11 @@ index 3c2ea8fec3a748cab7f5ad9100d12bd8213ec6c9..1f1df82c9bcf18bad1187e3f24ede190 + public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage) { + this(player, drops, droppedExp, 0, adventure$deathMessage, null); + } -+ + + public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { + this(player, drops, droppedExp, newExp, 0, 0, adventure$deathMessage, deathMessage); + } - ++ + public PlayerDeathEvent(@NotNull final Player player, @NotNull final List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, @Nullable final net.kyori.adventure.text.Component adventure$deathMessage, @Nullable String deathMessage) { + super(player, drops, droppedExp); + this.newExp = newExp; @@ -2720,56 +2723,59 @@ index 3c2ea8fec3a748cab7f5ad9100d12bd8213ec6c9..1f1df82c9bcf18bad1187e3f24ede190 } @NotNull -@@ -39,25 +62,55 @@ public class PlayerDeathEvent extends EntityDeathEvent { +@@ -39,13 +62,15 @@ public class PlayerDeathEvent extends EntityDeathEvent { return (Player) entity; } + // Paper start -+ /** -+ * Set the death message that will appear to everyone on the server. -+ * -+ * @param deathMessage Message to appear to other players on the server. -+ */ -+ public void deathMessage(@Nullable net.kyori.adventure.text.Component deathMessage) { -+ this.deathMessage = null; -+ this.adventure$deathMessage = deathMessage; -+ } -+ -+ /** -+ * Get the death message that will appear to everyone on the server. -+ * -+ * @return Message to appear to other players on the server. -+ */ -+ public @Nullable net.kyori.adventure.text.Component deathMessage() { -+ return this.adventure$deathMessage; -+ } -+ // Paper end -+ /** * Set the death message that will appear to everyone on the server. * * @param deathMessage Message to appear to other players on the server. -+ * @deprecated in favour of {@link #deathMessage(net.kyori.adventure.text.Component)} */ -+ @Deprecated // Paper - public void setDeathMessage(@Nullable String deathMessage) { - this.deathMessage = deathMessage; -+ this.adventure$deathMessage = deathMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(deathMessage) : null; // Paper +- public void setDeathMessage(@Nullable String deathMessage) { +- this.deathMessage = deathMessage; ++ public void deathMessage(net.kyori.adventure.text.@Nullable Component deathMessage) { ++ this.deathMessage = null; ++ this.adventure$deathMessage = deathMessage; } /** - * Get the death message that will appear to everyone on the server. +@@ -53,11 +78,39 @@ public class PlayerDeathEvent extends EntityDeathEvent { * * @return Message to appear to other players on the server. -+ * @deprecated in favour of {@link #deathMessage()} */ - @Nullable -+ @Deprecated // Paper - public String getDeathMessage() { +- @Nullable +- public String getDeathMessage() { - return deathMessage; -+ return this.deathMessage != null ? this.deathMessage : (this.adventure$deathMessage != null ? getDeathMessageString(this.adventure$deathMessage) : null); // Paper ++ public net.kyori.adventure.text.@Nullable Component deathMessage() { ++ return this.adventure$deathMessage; ++ } ++ // Paper end ++ ++ /** ++ * Set the death message that will appear to everyone on the server. ++ * ++ * @param deathMessage Message to appear to other players on the server. ++ * @deprecated in favour of {@link #deathMessage(net.kyori.adventure.text.Component)} ++ */ ++ @Deprecated // Paper ++ public void setDeathMessage(@Nullable String deathMessage) { ++ this.deathMessage = deathMessage; ++ this.adventure$deathMessage = deathMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(deathMessage) : null; // Paper } -- + ++ /** ++ * Get the death message that will appear to everyone on the server. ++ * ++ * @return Message to appear to other players on the server. ++ * @deprecated in favour of {@link #deathMessage()} ++ */ ++ @Nullable ++ @Deprecated // Paper ++ public String getDeathMessage() { ++ return this.deathMessage != null ? this.deathMessage : (this.adventure$deathMessage != null ? getDeathMessageString(this.adventure$deathMessage) : null); // Paper ++ } + // Paper start //TODO: add translation API to drop String deathMessage in favor of just Adventure + private static String getDeathMessageString(net.kyori.adventure.text.Component component) { + return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(component); @@ -2779,7 +2785,7 @@ index 3c2ea8fec3a748cab7f5ad9100d12bd8213ec6c9..1f1df82c9bcf18bad1187e3f24ede190 * Gets how much EXP the Player should have at respawn. *

diff --git a/src/main/java/org/bukkit/event/inventory/InventoryType.java b/src/main/java/org/bukkit/event/inventory/InventoryType.java -index 8573f5d1b14e27f4ba4de5f68e74f83d8329371b..456eb20f8d603b1ebbaa11b8832e56c08406b7c9 100644 +index 4fb754cd7fd9b668029e2311cfaad774bb47cf80..99a45a698882acd47c725183a1f199eb1643f6e8 100644 --- a/src/main/java/org/bukkit/event/inventory/InventoryType.java +++ b/src/main/java/org/bukkit/event/inventory/InventoryType.java @@ -151,6 +151,18 @@ public enum InventoryType { @@ -2794,7 +2800,7 @@ index 8573f5d1b14e27f4ba4de5f68e74f83d8329371b..456eb20f8d603b1ebbaa11b8832e56c0 + * + * @return the inventory's default title + */ -+ public @NotNull net.kyori.adventure.text.Component defaultTitle() { ++ public net.kyori.adventure.text.@NotNull Component defaultTitle() { + return defaultTitleComponent; + } + // Paper end @@ -2872,23 +2878,32 @@ index 9866c07c999f46cb585709804aaad710c3031d5a..c7c45e2de8cca1bf8b8e12752e08db62 return message; } -@@ -95,16 +96,66 @@ public class AsyncPlayerPreLoginEvent extends Event { +@@ -95,29 +96,81 @@ public class AsyncPlayerPreLoginEvent extends Event { * * @param message New kick message */ - public void setKickMessage(@NotNull final String message) { + public void kickMessage(@NotNull final net.kyori.adventure.text.Component message) { -+ this.message = message; -+ } -+ -+ /** -+ * Disallows the player from logging in, with the given reason -+ * -+ * @param result New result for disallowing the player -+ * @param message Kick message to display to the user -+ */ + this.message = message; + } + +- /** +- * Allows the player to log in +- */ +- public void allow() { +- result = Result.ALLOWED; +- message = ""; +- } +- + /** + * Disallows the player from logging in, with the given reason + * + * @param result New result for disallowing the player + * @param message Kick message to display to the user + */ +- public void disallow(@NotNull final Result result, @NotNull final String message) { + public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { -+ this.result = result; + this.result = result; this.message = message; } @@ -2931,30 +2946,30 @@ index 9866c07c999f46cb585709804aaad710c3031d5a..c7c45e2de8cca1bf8b8e12752e08db62 + this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper + } + - /** - * Allows the player to log in - */ - public void allow() { - result = Result.ALLOWED; -- message = ""; ++ /** ++ * Allows the player to log in ++ */ ++ public void allow() { ++ result = Result.ALLOWED; + message = net.kyori.adventure.text.Component.empty(); // Paper - } - - /** -@@ -112,10 +163,12 @@ public class AsyncPlayerPreLoginEvent extends Event { - * - * @param result New result for disallowing the player - * @param message Kick message to display to the user ++ } ++ ++ /** ++ * Disallows the player from logging in, with the given reason ++ * ++ * @param result New result for disallowing the player ++ * @param message Kick message to display to the user + * @deprecated in favour of {@link #disallow(org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} - */ ++ */ + @Deprecated // Paper - public void disallow(@NotNull final Result result, @NotNull final String message) { - this.result = result; -- this.message = message; ++ public void disallow(@NotNull final Result result, @NotNull final String message) { ++ this.result = result; + this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper - } - ++ } ++ /** + * Disallows the player from logging in, with the given reason + * @@ -130,7 +183,7 @@ public class AsyncPlayerPreLoginEvent extends Event { @Deprecated public void disallow(@NotNull final PlayerPreLoginEvent.Result result, @NotNull final String message) { @@ -2990,75 +3005,80 @@ index 793b661b6d2d05de3d7f4fc26a4c018a2af58e62..f6d3b817de3001f04ea4554c7c39a129 player = who; diff --git a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -index d06684aba7688ce06777dbd837a46856a9d7767f..4af1d064fcb57773dfa8f6ad40d6482973f8e1a8 100644 +index d06684aba7688ce06777dbd837a46856a9d7767f..3e1e7cd0415509da4dd887db59efa55011b1dab4 100644 --- a/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java +++ b/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java -@@ -10,30 +10,60 @@ import org.jetbrains.annotations.Nullable; +@@ -10,21 +10,27 @@ import org.jetbrains.annotations.Nullable; */ public class PlayerJoinEvent extends PlayerEvent { private static final HandlerList handlers = new HandlerList(); - private String joinMessage; +- +- public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final String joinMessage) { + // Paper start + private net.kyori.adventure.text.Component joinMessage; + public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final net.kyori.adventure.text.Component joinMessage) { -+ super(playerJoined); -+ this.joinMessage = joinMessage; -+ } + super(playerJoined); + this.joinMessage = joinMessage; + } + @Deprecated // Paper end - public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final String joinMessage) { - super(playerJoined); ++ public PlayerJoinEvent(@NotNull final Player playerJoined, @Nullable final String joinMessage) { ++ super(playerJoined); + this.joinMessage = joinMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null; // Paper end + } + + // Paper start + /** + * Gets the join message to send to all online players + * + * @return string join message. Can be null + */ +- @Nullable +- public String getJoinMessage() { +- return joinMessage; ++ public net.kyori.adventure.text.@Nullable Component joinMessage() { ++ return this.joinMessage; + } + + /** +@@ -32,9 +38,33 @@ public class PlayerJoinEvent extends PlayerEvent { + * + * @param joinMessage join message. If null, no message will be sent + */ +- public void setJoinMessage(@Nullable String joinMessage) { ++ public void joinMessage(net.kyori.adventure.text.@Nullable Component joinMessage) { + this.joinMessage = joinMessage; + } ++ // Paper end ++ + /** + * Gets the join message to send to all online players + * + * @return string join message. Can be null ++ * @deprecated in favour of {@link #joinMessage()} + */ -+ public @Nullable net.kyori.adventure.text.Component joinMessage() { -+ return this.joinMessage; ++ @Nullable ++ @Deprecated // Paper ++ public String getJoinMessage() { ++ return this.joinMessage == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.joinMessage); // Paper + } + + /** + * Sets the join message to send to all online players + * + * @param joinMessage join message. If null, no message will be sent -+ */ -+ public void joinMessage(@Nullable net.kyori.adventure.text.Component joinMessage) { - this.joinMessage = joinMessage; - } -+ // Paper end - - /** - * Gets the join message to send to all online players - * - * @return string join message. Can be null -+ * @deprecated in favour of {@link #joinMessage()} - */ - @Nullable -+ @Deprecated // Paper - public String getJoinMessage() { -- return joinMessage; -+ return this.joinMessage == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.joinMessage); // Paper - } - - /** - * Sets the join message to send to all online players - * - * @param joinMessage join message. If null, no message will be sent + * @deprecated in favour of {@link #joinMessage(net.kyori.adventure.text.Component)} - */ ++ */ + @Deprecated // Paper - public void setJoinMessage(@Nullable String joinMessage) { -- this.joinMessage = joinMessage; ++ public void setJoinMessage(@Nullable String joinMessage) { + this.joinMessage = joinMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(joinMessage) : null; // Paper - } ++ } @NotNull + @Override diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -index 2f6ca42330675733b2b4132cbb66e433788d05d5..efbf4b657c99ce3a5096d041d275af9ccaea7911 100644 +index 2f6ca42330675733b2b4132cbb66e433788d05d5..997b06c19a5277656521e0e298f2958c209f1da1 100644 --- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java +++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java @@ -10,35 +10,84 @@ import org.jetbrains.annotations.NotNull; @@ -3091,7 +3111,7 @@ index 2f6ca42330675733b2b4132cbb66e433788d05d5..efbf4b657c99ce3a5096d041d275af9c + * + * @return string kick reason + */ -+ public @NotNull net.kyori.adventure.text.Component leaveMessage() { ++ public net.kyori.adventure.text.@NotNull Component leaveMessage() { + return this.leaveMessage; + } + @@ -3100,7 +3120,7 @@ index 2f6ca42330675733b2b4132cbb66e433788d05d5..efbf4b657c99ce3a5096d041d275af9c + * + * @param leaveMessage leave message + */ -+ public void leaveMessage(@NotNull net.kyori.adventure.text.Component leaveMessage) { ++ public void leaveMessage(net.kyori.adventure.text.@NotNull Component leaveMessage) { + this.leaveMessage = leaveMessage; + } + @@ -3109,7 +3129,7 @@ index 2f6ca42330675733b2b4132cbb66e433788d05d5..efbf4b657c99ce3a5096d041d275af9c * * @return string kick reason */ -+ public @NotNull net.kyori.adventure.text.Component reason() { ++ public net.kyori.adventure.text.@NotNull Component reason() { + return this.kickReason; + } + @@ -3118,7 +3138,7 @@ index 2f6ca42330675733b2b4132cbb66e433788d05d5..efbf4b657c99ce3a5096d041d275af9c + * + * @param kickReason kick reason + */ -+ public void reason(@NotNull net.kyori.adventure.text.Component kickReason) { ++ public void reason(net.kyori.adventure.text.@NotNull Component kickReason) { + this.kickReason = kickReason; + } + // Paper end @@ -3212,7 +3232,7 @@ index 36b436e145a7215682b692a87ab894df25752c1d..ebd499c1a2d11ea068e8c374edbc3967 return locale; } diff --git a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java -index 084ca8cfcb7381bfa4fa6280748cf9b81210a9c1..95c53d934f928d25f7b20cfbf2e5faa3df31ddc4 100644 +index 084ca8cfcb7381bfa4fa6280748cf9b81210a9c1..62fb782baad5c80a3daaa557c0faa674c58a98cf 100644 --- a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java +++ b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java @@ -17,7 +17,7 @@ public class PlayerLoginEvent extends PlayerEvent { @@ -3224,7 +3244,7 @@ index 084ca8cfcb7381bfa4fa6280748cf9b81210a9c1..95c53d934f928d25f7b20cfbf2e5faa3 private final InetAddress realAddress; // Spigot /** -@@ -53,12 +53,52 @@ public class PlayerLoginEvent extends PlayerEvent { +@@ -53,13 +53,53 @@ public class PlayerLoginEvent extends PlayerEvent { * @param result The result status for this event * @param message The message to be displayed if result denies login * @param realAddress the actual, unspoofed connecting address @@ -3232,8 +3252,8 @@ index 084ca8cfcb7381bfa4fa6280748cf9b81210a9c1..95c53d934f928d25f7b20cfbf2e5faa3 */ + @Deprecated // Paper public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final String message, @NotNull final InetAddress realAddress) { // Spigot - this(player, hostname, address, realAddress); // Spigot - this.result = result; ++ this(player, hostname, address, realAddress); // Spigot ++ this.result = result; + this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper + } + @@ -3250,18 +3270,18 @@ index 084ca8cfcb7381bfa4fa6280748cf9b81210a9c1..95c53d934f928d25f7b20cfbf2e5faa3 + * @param realAddress the actual, unspoofed connecting address + */ + public PlayerLoginEvent(@NotNull final Player player, @NotNull String hostname, @NotNull final InetAddress address, @NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message, @NotNull final InetAddress realAddress) { // Spigot -+ this(player, hostname, address, realAddress); // Spigot -+ this.result = result; -+ this.message = message; -+ } -+ + this(player, hostname, address, realAddress); // Spigot + this.result = result; + this.message = message; + } + + /** + * Gets the current kick message that will be used if getResult() != + * Result.ALLOWED + * + * @return Current kick message + */ -+ public @NotNull net.kyori.adventure.text.Component kickMessage() { ++ public net.kyori.adventure.text.@NotNull Component kickMessage() { + return this.message; + } + @@ -3270,13 +3290,14 @@ index 084ca8cfcb7381bfa4fa6280748cf9b81210a9c1..95c53d934f928d25f7b20cfbf2e5faa3 + * + * @param message New kick message + */ -+ public void kickMessage(@NotNull net.kyori.adventure.text.Component message) { - this.message = message; - } ++ public void kickMessage(net.kyori.adventure.text.@NotNull Component message) { ++ this.message = message; ++ } + // Paper end - ++ // Spigot start /** + * Gets the connection address of this player, regardless of whether it has been spoofed or not. @@ -96,19 +136,23 @@ public class PlayerLoginEvent extends PlayerEvent { * Result.ALLOWED * @@ -3373,7 +3394,7 @@ index fb066251f793ec3b41bfc075b9478901b15ee549..6800132c6288b4588fd02b08d26f016c return message; } -@@ -72,16 +73,51 @@ public class PlayerPreLoginEvent extends Event { +@@ -72,28 +73,65 @@ public class PlayerPreLoginEvent extends Event { * * @param message New kick message */ @@ -3382,16 +3403,25 @@ index fb066251f793ec3b41bfc075b9478901b15ee549..6800132c6288b4588fd02b08d26f016c this.message = message; } -+ /** -+ * Disallows the player from logging in, with the given reason -+ * -+ * @param result New result for disallowing the player -+ * @param message Kick message to display to the user -+ */ +- /** +- * Allows the player to log in +- */ +- public void allow() { +- result = Result.ALLOWED; +- message = ""; +- } +- + /** + * Disallows the player from logging in, with the given reason + * + * @param result New result for disallowing the player + * @param message Kick message to display to the user + */ +- public void disallow(@NotNull final Result result, @NotNull final String message) { + public void disallow(@NotNull final Result result, @NotNull final net.kyori.adventure.text.Component message) { -+ this.result = result; -+ this.message = message; -+ } + this.result = result; + this.message = message; + } + // Paper end + /** + * Gets the current kick message that will be used if getResult() != @@ -3417,35 +3447,34 @@ index fb066251f793ec3b41bfc075b9478901b15ee549..6800132c6288b4588fd02b08d26f016c + this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper + } + - /** - * Allows the player to log in - */ - public void allow() { - result = Result.ALLOWED; -- message = ""; ++ /** ++ * Allows the player to log in ++ */ ++ public void allow() { ++ result = Result.ALLOWED; + message = net.kyori.adventure.text.Component.empty(); // Paper - } - - /** -@@ -89,10 +125,12 @@ public class PlayerPreLoginEvent extends Event { - * - * @param result New result for disallowing the player - * @param message Kick message to display to the user ++ } ++ ++ /** ++ * Disallows the player from logging in, with the given reason ++ * ++ * @param result New result for disallowing the player ++ * @param message Kick message to display to the user + * @deprecated in favour of {@link #disallow(org.bukkit.event.player.PlayerPreLoginEvent.Result, net.kyori.adventure.text.Component)} - */ ++ */ + @Deprecated // Paper - public void disallow(@NotNull final Result result, @NotNull final String message) { - this.result = result; -- this.message = message; ++ public void disallow(@NotNull final Result result, @NotNull final String message) { ++ this.result = result; + this.message = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(message); // Paper - } ++ } /** + * Gets the player's name. diff --git a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -index d70c25f404e994766a9ebce89a917c8d0719777c..0395ca85a466f6356259078d3bad48b2ce6e57b7 100644 +index d70c25f404e994766a9ebce89a917c8d0719777c..14b27eaaf744736b3e56bb1383481df98a218c43 100644 --- a/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java +++ b/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java -@@ -10,30 +10,59 @@ import org.jetbrains.annotations.Nullable; +@@ -10,9 +10,15 @@ import org.jetbrains.annotations.Nullable; */ public class PlayerQuitEvent extends PlayerEvent { private static final HandlerList handlers = new HandlerList(); @@ -3454,62 +3483,61 @@ index d70c25f404e994766a9ebce89a917c8d0719777c..0395ca85a466f6356259078d3bad48b2 + @Deprecated // Paper public PlayerQuitEvent(@NotNull final Player who, @Nullable final String quitMessage) { - super(who); ++ super(who); + this.quitMessage = quitMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(quitMessage) : null; // Paper + } + // Paper start + public PlayerQuitEvent(@NotNull final Player who, @Nullable final net.kyori.adventure.text.Component quitMessage) { -+ super(who); -+ this.quitMessage = quitMessage; -+ } + super(who); + this.quitMessage = quitMessage; + } +@@ -22,8 +28,7 @@ public class PlayerQuitEvent extends PlayerEvent { + * + * @return string quit message + */ +- @Nullable +- public String getQuitMessage() { ++ public net.kyori.adventure.text.@Nullable Component quitMessage() { + return quitMessage; + } + +@@ -32,9 +37,33 @@ public class PlayerQuitEvent extends PlayerEvent { + * + * @param quitMessage quit message + */ +- public void setQuitMessage(@Nullable String quitMessage) { ++ public void quitMessage(net.kyori.adventure.text.@Nullable Component quitMessage) { + this.quitMessage = quitMessage; + } ++ // Paper end + + /** + * Gets the quit message to send to all online players + * + * @return string quit message ++ * @deprecated in favour of {@link #quitMessage()} + */ -+ public @Nullable net.kyori.adventure.text.Component quitMessage() { -+ return quitMessage; ++ @Nullable ++ @Deprecated // Paper ++ public String getQuitMessage() { ++ return this.quitMessage == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.quitMessage); // Paper + } + + /** + * Sets the quit message to send to all online players + * + * @param quitMessage quit message -+ */ -+ public void quitMessage(@Nullable net.kyori.adventure.text.Component quitMessage) { - this.quitMessage = quitMessage; - } -+ // Paper end - - /** - * Gets the quit message to send to all online players - * - * @return string quit message -+ * @deprecated in favour of {@link #quitMessage()} - */ - @Nullable -+ @Deprecated // Paper - public String getQuitMessage() { -- return quitMessage; -+ return this.quitMessage == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.quitMessage); // Paper - } - - /** - * Sets the quit message to send to all online players - * - * @param quitMessage quit message + * @deprecated in favour of {@link #quitMessage(net.kyori.adventure.text.Component)} - */ ++ */ + @Deprecated // Paper - public void setQuitMessage(@Nullable String quitMessage) { -- this.quitMessage = quitMessage; ++ public void setQuitMessage(@Nullable String quitMessage) { + this.quitMessage = quitMessage != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(quitMessage) : null; // Paper - } ++ } @NotNull + @Override diff --git a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java -index 03bfca9d368bbe4b7c1353d52c883e756bf69bda..943d324435350d3f16fad3e21cb472a01a3ff60b 100644 +index 03bfca9d368bbe4b7c1353d52c883e756bf69bda..1bfd8ba2a9fa16f2084ad36515644f6af79fdced 100644 --- a/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java +++ b/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java @@ -18,7 +18,7 @@ import org.jetbrains.annotations.NotNull; @@ -3534,11 +3562,11 @@ index 03bfca9d368bbe4b7c1353d52c883e756bf69bda..943d324435350d3f16fad3e21cb472a0 + } + + @Deprecated -+ public BroadcastMessageEvent(@NotNull net.kyori.adventure.text.Component message, @NotNull Set recipients) { ++ public BroadcastMessageEvent(net.kyori.adventure.text.@NotNull Component message, @NotNull Set recipients) { + this(false, message, recipients); + } + -+ public BroadcastMessageEvent(boolean isAsync, @NotNull net.kyori.adventure.text.Component message, @NotNull Set recipients) { ++ public BroadcastMessageEvent(boolean isAsync, net.kyori.adventure.text.@NotNull Component message, @NotNull Set recipients) { + // Paper end super(isAsync); this.message = message; @@ -3550,7 +3578,7 @@ index 03bfca9d368bbe4b7c1353d52c883e756bf69bda..943d324435350d3f16fad3e21cb472a0 + * + * @return Message to broadcast + */ -+ public @NotNull net.kyori.adventure.text.Component message() { ++ public net.kyori.adventure.text.@NotNull Component message() { + return this.message; + } + @@ -3559,7 +3587,7 @@ index 03bfca9d368bbe4b7c1353d52c883e756bf69bda..943d324435350d3f16fad3e21cb472a0 + * + * @param message New message to broadcast + */ -+ public void message(@NotNull net.kyori.adventure.text.Component message) { ++ public void message(net.kyori.adventure.text.@NotNull Component message) { + this.message = message; + } + // Paper end @@ -3591,7 +3619,7 @@ index 03bfca9d368bbe4b7c1353d52c883e756bf69bda..943d324435350d3f16fad3e21cb472a0 /** diff --git a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java -index 5adbe0514129abf3cfbc4b29a213f522359fe2e1..732d8d0436dc76cff33394b43452ff8f7a9b7fab 100644 +index 5adbe0514129abf3cfbc4b29a213f522359fe2e1..72ebc29db42d08d1d0361dba462fc8a573fbf918 100644 --- a/src/main/java/org/bukkit/event/server/ServerListPingEvent.java +++ b/src/main/java/org/bukkit/event/server/ServerListPingEvent.java @@ -22,7 +22,7 @@ public class ServerListPingEvent extends ServerEvent implements Iterable @@ -3621,9 +3649,9 @@ index 5adbe0514129abf3cfbc4b29a213f522359fe2e1..732d8d0436dc76cff33394b43452ff8f + @Deprecated // Paper protected ServerListPingEvent(@NotNull final String hostname, @NotNull final InetAddress address, @NotNull final String motd, final int maxPlayers) { super(true); - this.numPlayers = MAGIC_PLAYER_COUNT; - this.hostname = hostname; - this.address = address; ++ this.numPlayers = MAGIC_PLAYER_COUNT; ++ this.hostname = hostname; ++ this.address = address; + this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(motd); // Paper + this.maxPlayers = maxPlayers; + } @@ -3637,10 +3665,10 @@ index 5adbe0514129abf3cfbc4b29a213f522359fe2e1..732d8d0436dc76cff33394b43452ff8f + Preconditions.checkArgument(numPlayers >= 0, "Cannot have negative number of players online (%s)", numPlayers); + this.hostname = hostname; + this.address = address; - this.motd = motd; ++ this.motd = motd; + this.numPlayers = numPlayers; - this.maxPlayers = maxPlayers; - } ++ this.maxPlayers = maxPlayers; ++ } + /** + * This constructor is intended for implementations that provide the + * {@link #iterator()} method, thus provided the {@link #getNumPlayers()} @@ -3666,19 +3694,19 @@ index 5adbe0514129abf3cfbc4b29a213f522359fe2e1..732d8d0436dc76cff33394b43452ff8f + * @param motd the message of the day + * @param maxPlayers the max number of players + */ -+ protected ServerListPingEvent(final @NotNull String hostname, final @NotNull InetAddress address, final @NotNull net.kyori.adventure.text.Component motd, final int maxPlayers) { -+ this.numPlayers = MAGIC_PLAYER_COUNT; -+ this.hostname = hostname; -+ this.address = address; -+ this.motd = motd; -+ this.maxPlayers = maxPlayers; -+ } ++ protected ServerListPingEvent(final @NotNull String hostname, final @NotNull InetAddress address, final net.kyori.adventure.text.@NotNull Component motd, final int maxPlayers) { + this.numPlayers = MAGIC_PLAYER_COUNT; + this.hostname = hostname; + this.address = address; + this.motd = motd; + this.maxPlayers = maxPlayers; + } + /** + * Get the message of the day message. + * + * @return the message of the day + */ -+ public @NotNull net.kyori.adventure.text.Component motd() { ++ public net.kyori.adventure.text.@NotNull Component motd() { + return motd; + } + /** @@ -3686,7 +3714,7 @@ index 5adbe0514129abf3cfbc4b29a213f522359fe2e1..732d8d0436dc76cff33394b43452ff8f + * + * @param motd the message of the day + */ -+ public void motd(@NotNull net.kyori.adventure.text.Component motd) { ++ public void motd(net.kyori.adventure.text.@NotNull Component motd) { + this.motd = motd; + } + // Paper end @@ -3779,7 +3807,7 @@ index f89d71b77d1200314df6ca23614d5ca6fb15ceb3..af4a7ce37eb10bab06eadb6583c7894b + // Paper end } diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index d80b0a52968920b990a75cff85e436a16d782500..9da047582e9648d84875b6d3c136960bbb97b70e 100644 +index d80b0a52968920b990a75cff85e436a16d782500..9d327f0832c40d4a8d212346284274f6cf78834f 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable; @@ -3808,13 +3836,13 @@ index d80b0a52968920b990a75cff85e436a16d782500..9da047582e9648d84875b6d3c136960b + * + * @return display name of the {@link ItemStack} + */ -+ public @NotNull net.kyori.adventure.text.Component displayName() { ++ public net.kyori.adventure.text.@NotNull Component displayName() { + return Bukkit.getServer().getItemFactory().displayName(this); + } + // Paper end } diff --git a/src/main/java/org/bukkit/inventory/meta/BookMeta.java b/src/main/java/org/bukkit/inventory/meta/BookMeta.java -index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64af0edfb2 100644 +index 94852d50e88d0594b84b581cd627174043629995..be7c2cfc757e4dd15927be850739d401958fb227 100644 --- a/src/main/java/org/bukkit/inventory/meta/BookMeta.java +++ b/src/main/java/org/bukkit/inventory/meta/BookMeta.java @@ -10,7 +10,7 @@ import org.jetbrains.annotations.Nullable; @@ -3826,12 +3854,13 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 /** * Represents the generation (or level of copying) of a written book -@@ -119,6 +119,118 @@ public interface BookMeta extends ItemMeta { +@@ -119,16 +119,60 @@ public interface BookMeta extends ItemMeta { */ boolean hasPages(); + // Paper start -+ /** + /** +- * Gets the specified page in the book. The given page must exist. + * Gets the title of the book. + *

+ * Plugins should check that hasTitle() returns true before calling this @@ -3839,9 +3868,8 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 + * + * @return the title of the book + */ -+ @Nullable + @Override -+ net.kyori.adventure.text.Component title(); ++ net.kyori.adventure.text.@Nullable Component title(); + + /** + * Sets the title of the book. @@ -3851,9 +3879,9 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 + * @param title the title to set + * @return the same {@link BookMeta} instance + */ -+ @NotNull ++ @org.jetbrains.annotations.Contract(value = "_ -> this", pure = false) + @Override -+ @org.checkerframework.common.returnsreceiver.qual.This BookMeta title(@Nullable net.kyori.adventure.text.Component title); ++ @NotNull BookMeta title(net.kyori.adventure.text.@Nullable Component title); + + /** + * Gets the author of the book. @@ -3863,9 +3891,8 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 + * + * @return the author of the book + */ -+ @Nullable + @Override -+ net.kyori.adventure.text.Component author(); ++ net.kyori.adventure.text.@Nullable Component author(); + + /** + * Sets the author of the book. Removes author when given null. @@ -3873,19 +3900,101 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 + * @param author the author to set + * @return the same {@link BookMeta} instance + */ -+ @NotNull ++ @org.jetbrains.annotations.Contract(value = "_ -> this", pure = false) + @Override -+ @org.checkerframework.common.returnsreceiver.qual.This BookMeta author(@Nullable net.kyori.adventure.text.Component author); ++ @NotNull BookMeta author(net.kyori.adventure.text.@Nullable Component author); + + /** + * Gets the specified page in the book. The page must exist. + *

+ * Pages are 1-indexed. + * + * @param page the page number to get, in range [1, getPageCount()] + * @return the page from the book + */ +- @NotNull +- String getPage(int page); ++ net.kyori.adventure.text.@NotNull Component page(int page); + + /** + * Sets the specified page in the book. Pages of the book must be +@@ -142,31 +186,7 @@ public interface BookMeta extends ItemMeta { + * @param page the page number to set, in range [1, getPageCount()] + * @param data the data to set for that page + */ +- void setPage(int page, @NotNull String data); +- +- /** +- * Gets all the pages in the book. +- * +- * @return list of all the pages in the book +- */ +- @NotNull +- List getPages(); +- +- /** +- * Clears the existing book pages, and sets the book to use the provided +- * pages. Maximum 100 pages with 256 characters per page. +- * +- * @param pages A list of pages to set the book to use +- */ +- void setPages(@NotNull List pages); +- +- /** +- * Clears the existing book pages, and sets the book to use the provided +- * pages. Maximum 50 pages with 256 characters per page. +- * +- * @param pages A list of strings, each being a page +- */ +- void setPages(@NotNull String... pages); ++ void page(int page, net.kyori.adventure.text.@NotNull Component data); + + /** + * Adds new pages to the end of the book. Up to a maximum of 50 pages with +@@ -174,6 +194,101 @@ public interface BookMeta extends ItemMeta { + * + * @param pages A list of strings, each being a page + */ ++ void addPages(net.kyori.adventure.text.@NotNull Component @NotNull ... pages); ++ ++ interface BookMetaBuilder extends Builder { ++ ++ @Override ++ @NotNull BookMetaBuilder title(net.kyori.adventure.text.@Nullable Component title); ++ ++ @Override ++ @NotNull BookMetaBuilder author(net.kyori.adventure.text.@Nullable Component author); ++ ++ @Override ++ @NotNull BookMetaBuilder addPage(net.kyori.adventure.text.@NotNull Component page); ++ ++ @Override ++ @NotNull BookMetaBuilder pages(net.kyori.adventure.text.@NotNull Component @NotNull ... pages); ++ ++ @Override ++ @NotNull BookMetaBuilder pages(java.util.@NotNull Collection pages); ++ ++ @Override ++ @NotNull BookMeta build(); ++ } ++ ++ @Override ++ @NotNull BookMetaBuilder toBuilder(); ++ ++ // Paper end ++ ++ /** ++ * Gets the specified page in the book. The given page must exist. + *

+ * Pages are 1-indexed. + * + * @param page the page number to get, in range [1, getPageCount()] + * @return the page from the book ++ * @deprecated in favour of {@link #page(int)} + */ -+ @NotNull net.kyori.adventure.text.Component page(int page); ++ @NotNull ++ @Deprecated // Paper ++ String getPage(int page); + + /** + * Sets the specified page in the book. Pages of the book must be @@ -3898,115 +4007,53 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 + * + * @param page the page number to set, in range [1, getPageCount()] + * @param data the data to set for that page ++ * @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)} + */ -+ void page(int page, @NotNull net.kyori.adventure.text.Component data); ++ @Deprecated // Paper ++ void setPage(int page, @NotNull String data); ++ ++ /** ++ * Gets all the pages in the book. ++ * ++ * @return list of all the pages in the book ++ * @deprecated in favour of {@link #pages()} ++ */ ++ @NotNull ++ @Deprecated // Paper ++ List getPages(); ++ ++ /** ++ * Clears the existing book pages, and sets the book to use the provided ++ * pages. Maximum 100 pages with 256 characters per page. ++ * ++ * @param pages A list of pages to set the book to use ++ * @deprecated in favour of {@link #pages(List)} ++ */ ++ @Deprecated // Paper ++ void setPages(@NotNull List pages); ++ ++ /** ++ * Clears the existing book pages, and sets the book to use the provided ++ * pages. Maximum 50 pages with 256 characters per page. ++ * ++ * @param pages A list of strings, each being a page ++ * @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)} ++ */ ++ @Deprecated // Paper ++ void setPages(@NotNull String... pages); + + /** + * Adds new pages to the end of the book. Up to a maximum of 50 pages with + * 256 characters per page. + * + * @param pages A list of strings, each being a page -+ */ -+ void addPages(@NotNull net.kyori.adventure.text.Component... pages); -+ -+ interface BookMetaBuilder extends Builder { -+ -+ @NotNull -+ @Override -+ BookMetaBuilder title(@Nullable net.kyori.adventure.text.Component title); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder author(@Nullable net.kyori.adventure.text.Component author); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder addPage(@NotNull net.kyori.adventure.text.Component page); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder pages(@NotNull net.kyori.adventure.text.Component... pages); -+ -+ @NotNull -+ @Override -+ BookMetaBuilder pages(@NotNull java.util.Collection pages); -+ -+ @NotNull -+ @Override -+ BookMeta build(); -+ } -+ -+ @Override -+ @org.checkerframework.checker.nullness.qual.NonNull -+ BookMetaBuilder toBuilder(); -+ -+ // Paper end -+ - /** - * Gets the specified page in the book. The given page must exist. - *

-@@ -126,8 +238,10 @@ public interface BookMeta extends ItemMeta { - * - * @param page the page number to get, in range [1, getPageCount()] - * @return the page from the book -+ * @deprecated in favour of {@link #page(int)} - */ - @NotNull -+ @Deprecated // Paper - String getPage(int page); - - /** -@@ -141,15 +255,19 @@ public interface BookMeta extends ItemMeta { - * - * @param page the page number to set, in range [1, getPageCount()] - * @param data the data to set for that page -+ * @deprecated in favour of {@link #page(int, net.kyori.adventure.text.Component)} - */ -+ @Deprecated // Paper - void setPage(int page, @NotNull String data); - - /** - * Gets all the pages in the book. - * - * @return list of all the pages in the book -+ * @deprecated in favour of {@link #pages()} - */ - @NotNull -+ @Deprecated // Paper - List getPages(); - - /** -@@ -157,7 +275,9 @@ public interface BookMeta extends ItemMeta { - * pages. Maximum 100 pages with 256 characters per page. - * - * @param pages A list of pages to set the book to use -+ * @deprecated in favour of {@link #pages(List)} - */ -+ @Deprecated // Paper - void setPages(@NotNull List pages); - - /** -@@ -165,7 +285,9 @@ public interface BookMeta extends ItemMeta { - * pages. Maximum 50 pages with 256 characters per page. - * - * @param pages A list of strings, each being a page -+ * @deprecated in favour of {@link #pages(net.kyori.adventure.text.Component...)} - */ -+ @Deprecated // Paper - void setPages(@NotNull String... pages); - - /** -@@ -173,7 +295,9 @@ public interface BookMeta extends ItemMeta { - * 256 characters per page. - * - * @param pages A list of strings, each being a page + * @deprecated in favour of {@link #addPages(net.kyori.adventure.text.Component...)} - */ ++ */ + @Deprecated // Paper void addPage(@NotNull String... pages); /** -@@ -195,8 +319,10 @@ public interface BookMeta extends ItemMeta { +@@ -195,8 +310,10 @@ public interface BookMeta extends ItemMeta { * * @param page the page number to get * @return the page from the book @@ -4017,7 +4064,7 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 public BaseComponent[] getPage(int page) { throw new UnsupportedOperationException("Not supported yet."); } -@@ -210,7 +336,9 @@ public interface BookMeta extends ItemMeta { +@@ -210,7 +327,9 @@ public interface BookMeta extends ItemMeta { * * @param page the page number to set * @param data the data to set for that page @@ -4027,7 +4074,7 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 public void setPage(int page, @Nullable BaseComponent... data) { throw new UnsupportedOperationException("Not supported yet."); } -@@ -219,8 +347,10 @@ public interface BookMeta extends ItemMeta { +@@ -219,8 +338,10 @@ public interface BookMeta extends ItemMeta { * Gets all the pages in the book. * * @return list of all the pages in the book @@ -4038,7 +4085,7 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 public List getPages() { throw new UnsupportedOperationException("Not supported yet."); } -@@ -230,7 +360,9 @@ public interface BookMeta extends ItemMeta { +@@ -230,7 +351,9 @@ public interface BookMeta extends ItemMeta { * pages. Maximum 50 pages with 256 characters per page. * * @param pages A list of pages to set the book to use @@ -4048,7 +4095,7 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 public void setPages(@NotNull List pages) { throw new UnsupportedOperationException("Not supported yet."); } -@@ -240,7 +372,9 @@ public interface BookMeta extends ItemMeta { +@@ -240,7 +363,9 @@ public interface BookMeta extends ItemMeta { * pages. Maximum 50 pages with 256 characters per page. * * @param pages A list of component arrays, each being a page @@ -4058,7 +4105,7 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 public void setPages(@NotNull BaseComponent[]... pages) { throw new UnsupportedOperationException("Not supported yet."); } -@@ -250,7 +384,9 @@ public interface BookMeta extends ItemMeta { +@@ -250,7 +375,9 @@ public interface BookMeta extends ItemMeta { * with 256 characters per page. * * @param pages A list of component arrays, each being a page @@ -4069,7 +4116,7 @@ index 94852d50e88d0594b84b581cd627174043629995..36bcbb3f3acedf7ebecbf6f6b358cf64 throw new UnsupportedOperationException("Not supported yet."); } diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java -index 2fbb0b7640dd9b9b0e70d4bc60fbb0310d5ec250..7476bfb8f26ce541cd10feaaeaf0f9b17e46bee8 100644 +index 2fbb0b7640dd9b9b0e70d4bc60fbb0310d5ec250..049c70c935fd7a781280d223f74bbbf87223f505 100644 --- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java @@ -31,6 +31,24 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste @@ -4084,14 +4131,14 @@ index 2fbb0b7640dd9b9b0e70d4bc60fbb0310d5ec250..7476bfb8f26ce541cd10feaaeaf0f9b1 + * + * @return the display name + */ -+ @Nullable net.kyori.adventure.text.Component displayName(); ++ net.kyori.adventure.text.@Nullable Component displayName(); + + /** + * Sets the display name. + * + * @param displayName the display name to set + */ -+ void displayName(final @Nullable net.kyori.adventure.text.Component displayName); ++ void displayName(final net.kyori.adventure.text.@Nullable Component displayName); + // Paper end + /** @@ -4163,7 +4210,7 @@ index 2fbb0b7640dd9b9b0e70d4bc60fbb0310d5ec250..7476bfb8f26ce541cd10feaaeaf0f9b1 /** diff --git a/src/main/java/org/bukkit/map/MapCursor.java b/src/main/java/org/bukkit/map/MapCursor.java -index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ca763b231749f108b6773040a5c6109378b21b31 100644 +index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..762d8a53bbfa82edcd725a52d630b61c40503d67 100644 --- a/src/main/java/org/bukkit/map/MapCursor.java +++ b/src/main/java/org/bukkit/map/MapCursor.java @@ -10,7 +10,7 @@ public final class MapCursor { @@ -4184,7 +4231,7 @@ index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ca763b231749f108b6773040a5c61093 } /** -@@ -37,7 +37,7 @@ public final class MapCursor { +@@ -37,9 +37,30 @@ public final class MapCursor { * @param visible Whether the cursor is visible by default. */ public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible) { @@ -4192,24 +4239,6 @@ index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ca763b231749f108b6773040a5c61093 + this(x, y, direction, type, visible, (String) null); // Paper } - /** -@@ -49,7 +49,7 @@ public final class MapCursor { - * @param type The type (color/style) of the map cursor. - * @param visible Whether the cursor is visible by default. - * @param caption cursor caption -- * @deprecated Magic value -+ * @deprecated Magic value. Use {@link #MapCursor(byte, byte, byte, byte, boolean, net.kyori.adventure.text.Component)} - */ - @Deprecated - public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable String caption) { -@@ -58,8 +58,42 @@ public final class MapCursor { - setDirection(direction); - setRawType(type); - this.visible = visible; -- this.caption = caption; -+ this.caption = caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(caption); // Paper - } -+ // Paper start + /** + * Initialize the map cursor. + * @@ -4219,14 +4248,35 @@ index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ca763b231749f108b6773040a5c61093 + * @param type The type (color/style) of the map cursor. + * @param visible Whether the cursor is visible by default. + * @param caption cursor caption -+ * @deprecated Magic value ++ * @deprecated Magic value. Use {@link #MapCursor(byte, byte, byte, byte, boolean, net.kyori.adventure.text.Component)} + */ + @Deprecated -+ public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { -+ this.x = x; this.y = y; this.visible = visible; this.caption = caption; ++ public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable String caption) { ++ this.x = x; ++ this.y = y; + setDirection(direction); + setRawType(type); ++ this.visible = visible; ++ this.caption = caption == null ? null : net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(caption); // Paper + } ++ // Paper start + /** + * Initialize the map cursor. + * +@@ -52,14 +73,27 @@ public final class MapCursor { + * @deprecated Magic value + */ + @Deprecated +- public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, @Nullable String caption) { +- this.x = x; +- this.y = y; ++ public MapCursor(byte x, byte y, byte direction, byte type, boolean visible, net.kyori.adventure.text.@Nullable Component caption) { ++ this.x = x; this.y = y; this.visible = visible; this.caption = caption; + setDirection(direction); + setRawType(type); +- this.visible = visible; +- this.caption = caption; + } + /** + * Initialize the map cursor. + * @@ -4237,7 +4287,7 @@ index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ca763b231749f108b6773040a5c61093 + * @param visible Whether the cursor is visible by default. + * @param caption cursor caption + */ -+ public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { ++ public MapCursor(byte x, byte y, byte direction, @NotNull Type type, boolean visible, net.kyori.adventure.text.@Nullable Component caption) { + this.x = x; this.y = y; this.visible = visible; this.caption = caption; + setDirection(direction); + setType(type); @@ -4260,12 +4310,12 @@ index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ca763b231749f108b6773040a5c61093 } + // Paper start -+ /** -+ * Gets the caption on this cursor. -+ * -+ * @return caption -+ */ -+ public @Nullable net.kyori.adventure.text.Component caption() { + /** + * Gets the caption on this cursor. + * + * @return caption + */ ++ public net.kyori.adventure.text.@Nullable Component caption() { + return this.caption; + } + /** @@ -4273,16 +4323,16 @@ index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ca763b231749f108b6773040a5c61093 + * + * @param caption new caption + */ -+ public void caption(@Nullable net.kyori.adventure.text.Component caption) { ++ public void caption(net.kyori.adventure.text.@Nullable Component caption) { + this.caption = caption; + } + // Paper end - /** - * Gets the caption on this cursor. - * - * @return caption ++ /** ++ * Gets the caption on this cursor. ++ * ++ * @return caption + * @deprecated in favour of {@link #caption()} - */ ++ */ @Nullable + @Deprecated // Paper public String getCaption() { @@ -4304,7 +4354,7 @@ index 83354b2a38b6261b172b91c1008dcf3313cc4a8f..ca763b231749f108b6773040a5c61093 /** diff --git a/src/main/java/org/bukkit/map/MapCursorCollection.java b/src/main/java/org/bukkit/map/MapCursorCollection.java -index 4dba721aefe4fc6699b3b4bfa7ecb0b19c2a2a1a..01dec2c877df58c9dc22445e8b1f9ce2e53066da 100644 +index 4dba721aefe4fc6699b3b4bfa7ecb0b19c2a2a1a..6bc28d000f538ecbf249467ff3e87e3f4fea963e 100644 --- a/src/main/java/org/bukkit/map/MapCursorCollection.java +++ b/src/main/java/org/bukkit/map/MapCursorCollection.java @@ -117,4 +117,22 @@ public final class MapCursorCollection { @@ -4325,7 +4375,7 @@ index 4dba721aefe4fc6699b3b4bfa7ecb0b19c2a2a1a..01dec2c877df58c9dc22445e8b1f9ce2 + * @deprecated Magic value + */ + @Deprecated -+ public @NotNull MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, @Nullable net.kyori.adventure.text.Component caption) { ++ public @NotNull MapCursor addCursor(int x, int y, byte direction, byte type, boolean visible, net.kyori.adventure.text.@Nullable Component caption) { + return addCursor(new MapCursor((byte) x, (byte) y, direction, type, visible, caption)); + } + // Paper end @@ -4388,21 +4438,22 @@ index 03ca87a1cbace2459174bb7bb8847bda766e80c5..b37938745f916b5f0111b07b1a1c9752 * Returns the name of the plugin. *

diff --git a/src/main/java/org/bukkit/scoreboard/Objective.java b/src/main/java/org/bukkit/scoreboard/Objective.java -index 2ff3a11f1f9c115722ea224873e7eb6dc6dc63e6..474274fdffe4041bf4bfb146fcc66424eb5be78a 100644 +index 2ff3a11f1f9c115722ea224873e7eb6dc6dc63e6..86a0a6f9e8487d6dfaf60876ace3dcc9b4722826 100644 --- a/src/main/java/org/bukkit/scoreboard/Objective.java +++ b/src/main/java/org/bukkit/scoreboard/Objective.java @@ -19,14 +19,35 @@ public interface Objective { */ @NotNull String getName() throws IllegalStateException; +- + // Paper start -+ /** -+ * Gets the name displayed to players for this objective -+ * -+ * @return this objective's display name -+ * @throws IllegalStateException if this objective has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.Component displayName() throws IllegalStateException; + /** + * Gets the name displayed to players for this objective + * + * @return this objective's display name + * @throws IllegalStateException if this objective has been unregistered + */ ++ net.kyori.adventure.text.@NotNull Component displayName() throws IllegalStateException; + /** + * Sets the name displayed to players for this objective. + * @@ -4412,16 +4463,16 @@ index 2ff3a11f1f9c115722ea224873e7eb6dc6dc63e6..474274fdffe4041bf4bfb146fcc66424 + * @throws IllegalArgumentException if displayName is longer than 128 + * characters. + */ -+ void displayName(@Nullable net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException; ++ void displayName(net.kyori.adventure.text.@Nullable Component displayName) throws IllegalStateException, IllegalArgumentException; + // Paper end - - /** - * Gets the name displayed to players for this objective - * - * @return this objective's display name - * @throws IllegalStateException if this objective has been unregistered ++ ++ /** ++ * Gets the name displayed to players for this objective ++ * ++ * @return this objective's display name ++ * @throws IllegalStateException if this objective has been unregistered + * @deprecated in favour of {@link #displayName()} - */ ++ */ @NotNull + @Deprecated // Paper String getDisplayName() throws IllegalStateException; @@ -4438,7 +4489,7 @@ index 2ff3a11f1f9c115722ea224873e7eb6dc6dc63e6..474274fdffe4041bf4bfb146fcc66424 /** diff --git a/src/main/java/org/bukkit/scoreboard/Scoreboard.java b/src/main/java/org/bukkit/scoreboard/Scoreboard.java -index a15183f302de42956d8965efe5f0585fc2cd030e..ef3e729caf430b08cdf2d680d5a137a1ba56c1c5 100644 +index a15183f302de42956d8965efe5f0585fc2cd030e..ebb72912c1f8431606162b0643f6289203331253 100644 --- a/src/main/java/org/bukkit/scoreboard/Scoreboard.java +++ b/src/main/java/org/bukkit/scoreboard/Scoreboard.java @@ -27,6 +27,92 @@ public interface Scoreboard { @@ -4466,7 +4517,7 @@ index a15183f302de42956d8965efe5f0585fc2cd030e..ef3e729caf430b08cdf2d680d5a137a1 + */ + @NotNull + @Deprecated -+ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @Nullable net.kyori.adventure.text.Component displayName) throws IllegalArgumentException; ++ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, net.kyori.adventure.text.@Nullable Component displayName) throws IllegalArgumentException; + /** + * Registers an Objective on this Scoreboard + * @@ -4489,7 +4540,7 @@ index a15183f302de42956d8965efe5f0585fc2cd030e..ef3e729caf430b08cdf2d680d5a137a1 + */ + @NotNull + @Deprecated -+ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, @Nullable net.kyori.adventure.text.Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException; ++ Objective registerNewObjective(@NotNull String name, @NotNull String criteria, net.kyori.adventure.text.@Nullable Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException; + /** + * Registers an Objective on this Scoreboard + * @@ -4508,7 +4559,7 @@ index a15183f302de42956d8965efe5f0585fc2cd030e..ef3e729caf430b08cdf2d680d5a137a1 + * exists + */ + @NotNull -+ Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, @Nullable net.kyori.adventure.text.Component displayName) throws IllegalArgumentException; ++ Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, net.kyori.adventure.text.@Nullable Component displayName) throws IllegalArgumentException; + /** + * Registers an Objective on this Scoreboard + * @@ -4529,7 +4580,7 @@ index a15183f302de42956d8965efe5f0585fc2cd030e..ef3e729caf430b08cdf2d680d5a137a1 + * exists + */ + @NotNull -+ Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, @Nullable net.kyori.adventure.text.Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException; ++ Objective registerNewObjective(@NotNull String name, @NotNull Criteria criteria, net.kyori.adventure.text.@Nullable Component displayName, @NotNull RenderType renderType) throws IllegalArgumentException; + // Paper end /** @@ -4573,21 +4624,22 @@ index a15183f302de42956d8965efe5f0585fc2cd030e..ef3e729caf430b08cdf2d680d5a137a1 /** diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java -index 0db7fe1b9fe5621ceed3f4f046691e359f5949dd..47b10df619ad2520b9bb673e2220f36391680f1b 100644 +index 0db7fe1b9fe5621ceed3f4f046691e359f5949dd..4d625f79ba2e3fe074feade98f7c1bc2798cb82e 100644 --- a/src/main/java/org/bukkit/scoreboard/Team.java +++ b/src/main/java/org/bukkit/scoreboard/Team.java @@ -22,14 +22,100 @@ public interface Team { */ @NotNull String getName() throws IllegalStateException; +- + // Paper start -+ /** -+ * Gets the name displayed to entries for this team -+ * -+ * @return Team display name -+ * @throws IllegalStateException if this team has been unregistered -+ */ -+ @NotNull net.kyori.adventure.text.Component displayName() throws IllegalStateException; + /** + * Gets the name displayed to entries for this team + * + * @return Team display name + * @throws IllegalStateException if this team has been unregistered + */ ++ net.kyori.adventure.text.@NotNull Component displayName() throws IllegalStateException; + + /** + * Sets the name displayed to entries for this team @@ -4595,7 +4647,7 @@ index 0db7fe1b9fe5621ceed3f4f046691e359f5949dd..47b10df619ad2520b9bb673e2220f363 + * @param displayName New display name + * @throws IllegalStateException if this team has been unregistered + */ -+ void displayName(@Nullable net.kyori.adventure.text.Component displayName) throws IllegalStateException, IllegalArgumentException; ++ void displayName(net.kyori.adventure.text.@Nullable Component displayName) throws IllegalStateException, IllegalArgumentException; + + /** + * Gets the prefix prepended to the display of entries on this team. @@ -4603,7 +4655,7 @@ index 0db7fe1b9fe5621ceed3f4f046691e359f5949dd..47b10df619ad2520b9bb673e2220f363 + * @return Team prefix + * @throws IllegalStateException if this team has been unregistered + */ -+ @NotNull net.kyori.adventure.text.Component prefix() throws IllegalStateException; ++ net.kyori.adventure.text.@NotNull Component prefix() throws IllegalStateException; + + /** + * Sets the prefix prepended to the display of entries on this team. @@ -4613,7 +4665,7 @@ index 0db7fe1b9fe5621ceed3f4f046691e359f5949dd..47b10df619ad2520b9bb673e2220f363 + * characters + * @throws IllegalStateException if this team has been unregistered + */ -+ void prefix(@Nullable net.kyori.adventure.text.Component prefix) throws IllegalStateException, IllegalArgumentException; ++ void prefix(net.kyori.adventure.text.@Nullable Component prefix) throws IllegalStateException, IllegalArgumentException; + + /** + * Gets the suffix appended to the display of entries on this team. @@ -4621,7 +4673,7 @@ index 0db7fe1b9fe5621ceed3f4f046691e359f5949dd..47b10df619ad2520b9bb673e2220f363 + * @return the team's current suffix + * @throws IllegalStateException if this team has been unregistered + */ -+ @NotNull net.kyori.adventure.text.Component suffix() throws IllegalStateException; ++ net.kyori.adventure.text.@NotNull Component suffix() throws IllegalStateException; + + /** + * Sets the suffix appended to the display of entries on this team. @@ -4631,7 +4683,7 @@ index 0db7fe1b9fe5621ceed3f4f046691e359f5949dd..47b10df619ad2520b9bb673e2220f363 + * characters + * @throws IllegalStateException if this team has been unregistered + */ -+ void suffix(@Nullable net.kyori.adventure.text.Component suffix) throws IllegalStateException, IllegalArgumentException; ++ void suffix(net.kyori.adventure.text.@Nullable Component suffix) throws IllegalStateException, IllegalArgumentException; + + /** + * Checks if the team has a color specified @@ -4652,7 +4704,7 @@ index 0db7fe1b9fe5621ceed3f4f046691e359f5949dd..47b10df619ad2520b9bb673e2220f363 + * @throws IllegalStateException if the team doesn't have a color + * @see #hasColor() + */ -+ @NotNull net.kyori.adventure.text.format.TextColor color() throws IllegalStateException; ++ net.kyori.adventure.text.format.@NotNull TextColor color() throws IllegalStateException; + + /** + * Sets the color of the team. @@ -4662,16 +4714,16 @@ index 0db7fe1b9fe5621ceed3f4f046691e359f5949dd..47b10df619ad2520b9bb673e2220f363 + * + * @param color new color, null for no color + */ -+ void color(@Nullable net.kyori.adventure.text.format.NamedTextColor color); ++ void color(net.kyori.adventure.text.format.@Nullable NamedTextColor color); + // Paper end - - /** - * Gets the name displayed to entries for this team - * - * @return Team display name - * @throws IllegalStateException if this team has been unregistered ++ ++ /** ++ * Gets the name displayed to entries for this team ++ * ++ * @return Team display name ++ * @throws IllegalStateException if this team has been unregistered + * @deprecated in favour of {@link #displayName()} - */ ++ */ @NotNull + @Deprecated // Paper String getDisplayName() throws IllegalStateException; @@ -4787,29 +4839,3 @@ index 0000000000000000000000000000000000000000..70c575077d204e4b36d07559f6a8d952 + assertTrue(set1.contains(key)); + } +} -diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 8f35cda0d67ec66646c6096a5bf1c84891b8b0fd..9825db30d42701aad5d9970bbb989fbff0142fb1 100644 ---- a/src/test/java/org/bukkit/AnnotationTest.java -+++ b/src/test/java/org/bukkit/AnnotationTest.java -@@ -26,6 +26,12 @@ import org.objectweb.asm.tree.ParameterNode; - public class AnnotationTest { - - private static final String[] ACCEPTED_ANNOTATIONS = { -+ // Paper start -+ "Lorg/checkerframework/checker/nullness/qual/Nullable;", -+ "Lorg/checkerframework/checker/nullness/qual/NonNull;", -+ "Lorg/checkerframework/checker/nullness/qual/PolyNull;", -+ "Lorg/checkerframework/checker/nullness/qual/MonotonicNonNull;", -+ // Paper end - "Lorg/jetbrains/annotations/Nullable;", - "Lorg/jetbrains/annotations/NotNull;", - "Lorg/jetbrains/annotations/Contract;", -@@ -105,7 +111,7 @@ public class AnnotationTest { - if (method.invisibleTypeAnnotations != null) { - for (final org.objectweb.asm.tree.TypeAnnotationNode invisibleTypeAnnotation : method.invisibleTypeAnnotations) { - final org.objectweb.asm.TypeReference ref = new org.objectweb.asm.TypeReference(invisibleTypeAnnotation.typeRef); -- if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_FORMAL_PARAMETER && ref.getTypeParameterIndex() == i && java.util.Arrays.binarySearch(ACCEPTED_ANNOTATIONS, invisibleTypeAnnotation.desc) >= 0) { -+ if (ref.getSort() == org.objectweb.asm.TypeReference.METHOD_FORMAL_PARAMETER && ref.getTypeParameterIndex() == i && java.util.Arrays.asList(ACCEPTED_ANNOTATIONS).contains(invisibleTypeAnnotation.desc)) { - continue dancing; - } - } diff --git a/patches/api/0008-Paper-Plugins.patch b/patches/api/0008-Paper-Plugins.patch index f62a996f4b..708554a590 100644 --- a/patches/api/0008-Paper-Plugins.patch +++ b/patches/api/0008-Paper-Plugins.patch @@ -2194,7 +2194,7 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..302319acbc257a075adfb78d9f5c49fd - javaPlugin.init(loader, loader.server, description, dataFolder, file, this); + javaPlugin.init(null, org.bukkit.Bukkit.getServer(), description, dataFolder, file, this); // Paper -+ } + } + + // Paper start + @Override @@ -2219,7 +2219,7 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..302319acbc257a075adfb78d9f5c49fd + Class serializable = clazz.asSubclass(org.bukkit.configuration.serialization.ConfigurationSerializable.class); + org.bukkit.configuration.serialization.ConfigurationSerialization.unregisterClass(serializable); + } - } ++ } + + @Override + public @Nullable io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup getGroup() { diff --git a/patches/api/0010-Timings-v2.patch b/patches/api/0010-Timings-v2.patch index d6cb969402..1b4abe69e4 100644 --- a/patches/api/0010-Timings-v2.patch +++ b/patches/api/0010-Timings-v2.patch @@ -2791,7 +2791,7 @@ index 0000000000000000000000000000000000000000..5989ee21297935651b0edd44b8239e65 + } +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 0084898567e8bb74fa271b65b56523a5c26d387c..e24589a4cb42b0163e4a1455b8b11d7130b5cd41 100644 +index 16ec0cd908659d6d53e565281b8db9f81951277d..92b3c40959eac827ed8861fec8658e57f2910628 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -802,7 +802,6 @@ public final class Bukkit { @@ -2803,7 +2803,7 @@ index 0084898567e8bb74fa271b65b56523a5c26d387c..e24589a4cb42b0163e4a1455b8b11d71 /** diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 892e03189957b0072827be4fd485dd98352334e8..ac087402c90dad4b3c499fcf8507e50e9099cea5 100644 +index 0a333c1439b3623d38029b88ce6d5ff159ae1ddd..bce277cd3a452769cd86dc017a2e548a170d6acc 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -1768,6 +1768,26 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @@ -2886,7 +2886,7 @@ index 0000000000000000000000000000000000000000..f9a00aecca5ec41b460bf41dfe1c6969 + } +} diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index caa29be46e8541b69ec47c181eb3320d6515b544..6fd341482d5250ad814e870360e40b52427f799a 100644 +index 75759131bd94b672bec4cd8e271ebff1ad391cba..5cfd88eec9bf02e83d77b6fce1a5c14b7687f48b 100644 --- a/src/main/java/org/bukkit/command/Command.java +++ b/src/main/java/org/bukkit/command/Command.java @@ -33,7 +33,8 @@ public abstract class Command { @@ -3392,7 +3392,7 @@ index 516d7fc7812aac343782861d0d567f54aa578c2a..00000000000000000000000000000000 - // Spigot end -} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index baf0887ec941533f8007f2c7f7ab78f16b45bd74..8d8a540c844e5365eed75a87db197a8fd4249bcd 100644 +index fbf56bcc4540f7f1a8ced7cc2cd96e291c1ac273..8602b96bfc860ff1fea4c1c7a3655ce3a9516cf4 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -2077,7 +2077,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM @@ -3400,12 +3400,12 @@ index baf0887ec941533f8007f2c7f7ab78f16b45bd74..8d8a540c844e5365eed75a87db197a8f public void sendMessage(@NotNull net.md_5.bungee.api.ChatMessageType position, @Nullable java.util.UUID sender, @NotNull net.md_5.bungee.api.chat.BaseComponent... components) { throw new UnsupportedOperationException("Not supported yet."); + -+ } + } + + // Paper start + public int getPing() { + throw new UnsupportedOperationException( "Not supported yet." ); - } ++ } + // Paper end } @@ -3611,7 +3611,8 @@ index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..123647bb10fc89508437d7a0bd3fd31d public CustomTimingsHandler(@NotNull String name) { - this(name, null); - } -- ++ Timing timing; + - public CustomTimingsHandler(@NotNull String name, @Nullable CustomTimingsHandler parent) { - this.name = name; - this.parent = parent; @@ -3634,7 +3635,16 @@ index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..123647bb10fc89508437d7a0bd3fd31d - long avg = time / count; - - printStream.println(" " + timings.name + " Time: " + time + " Count: " + count + " Avg: " + avg + " Violations: " + timings.violations); -- } ++ new AuthorNagException("Deprecated use of CustomTimingsHandler. Please Switch to Timings.of ASAP").printStackTrace(); ++ try { ++ final Method ofSafe = TimingsManager.class.getDeclaredMethod("getHandler", String.class, String.class, Timing.class); ++ ofSafe.setAccessible(true); ++ timing = (Timing) ofSafe.invoke(null,"Minecraft", "(Deprecated API) " + name, null); ++ } catch (Exception e) { ++ e.printStackTrace(); ++ Bukkit.getLogger().log(Level.SEVERE, "This handler could not be registered"); ++ timing = Timings.NULL_HANDLER; + } - printStream.println("# Version " + Bukkit.getVersion()); - int entities = 0; - int livingEntities = 0; @@ -3644,8 +3654,9 @@ index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..123647bb10fc89508437d7a0bd3fd31d - } - printStream.println("# Entities " + entities); - printStream.println("# LivingEntities " + livingEntities); -- } -- ++ handler = timing; + } + - /** - * Resets all timings. - */ @@ -3657,7 +3668,9 @@ index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..123647bb10fc89508437d7a0bd3fd31d - } - TimingsCommand.timingStart = System.nanoTime(); - } -- ++ public void startTiming() { handler.startTiming(); } ++ public void stopTiming() { handler.stopTiming(); } + - /** - * Ticked every tick by CraftBukkit to count the number of times a timer - * caused TPS loss. @@ -3673,8 +3686,7 @@ index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..123647bb10fc89508437d7a0bd3fd31d - } - } - } -+ Timing timing; - +- - /** - * Starts timing to track a section of code. - */ @@ -3685,19 +3697,9 @@ index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..123647bb10fc89508437d7a0bd3fd31d - if (parent != null && ++parent.timingDepth == 1) { - parent.start = start; - } -+ new AuthorNagException("Deprecated use of CustomTimingsHandler. Please Switch to Timings.of ASAP").printStackTrace(); -+ try { -+ final Method ofSafe = TimingsManager.class.getDeclaredMethod("getHandler", String.class, String.class, Timing.class); -+ ofSafe.setAccessible(true); -+ timing = (Timing) ofSafe.invoke(null,"Minecraft", "(Deprecated API) " + name, null); -+ } catch (Exception e) { -+ e.printStackTrace(); -+ Bukkit.getLogger().log(Level.SEVERE, "This handler could not be registered"); -+ timing = Timings.NULL_HANDLER; - } -+ handler = timing; - } - +- } +- } +- - /** - * Stops timing a section of code. - */ @@ -3716,9 +3718,7 @@ index 44badfedcc3fdc26bdc293b85d8c781d6f659faa..123647bb10fc89508437d7a0bd3fd31d - } - } - } -+ public void startTiming() { handler.startTiming(); } -+ public void stopTiming() { handler.stopTiming(); } - +- - /** - * Reset this timer, setting all values to zero. - */ diff --git a/patches/api/0039-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/api/0039-EntityRegainHealthEvent-isFastRegen-API.patch index f06ee13d15..f2bf91f480 100644 --- a/patches/api/0039-EntityRegainHealthEvent-isFastRegen-API.patch +++ b/patches/api/0039-EntityRegainHealthEvent-isFastRegen-API.patch @@ -8,7 +8,7 @@ diff --git a/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java index 8feb6698f9630f099be99e52d1149cd6bc615197..d51d2ec1d04d9ea8a25a70d0d856f2355ebfcb4a 100644 --- a/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java +++ b/src/main/java/org/bukkit/event/entity/EntityRegainHealthEvent.java -@@ -13,12 +13,31 @@ public class EntityRegainHealthEvent extends EntityEvent implements Cancellable +@@ -13,13 +13,32 @@ public class EntityRegainHealthEvent extends EntityEvent implements Cancellable private boolean cancelled; private double amount; private final RegainReason regainReason; @@ -25,8 +25,8 @@ index 8feb6698f9630f099be99e52d1149cd6bc615197..d51d2ec1d04d9ea8a25a70d0d856f235 this.amount = amount; this.regainReason = regainReason; + this.isFastRegen = isFastRegen; // Paper -+ } -+ + } + + // Paper start - Add getter for isFastRegen + /** + * Is this event a result of the fast regeneration mechanic @@ -35,8 +35,9 @@ index 8feb6698f9630f099be99e52d1149cd6bc615197..d51d2ec1d04d9ea8a25a70d0d856f235 + */ + public boolean isFastRegen() { + return isFastRegen; - } ++ } + // Paper end - ++ /** * Gets the amount of regained health + * diff --git a/patches/api/0065-Add-getI18NDisplayName-API.patch b/patches/api/0065-Add-getI18NDisplayName-API.patch index 529bea034e..b21d6e25c4 100644 --- a/patches/api/0065-Add-getI18NDisplayName-API.patch +++ b/patches/api/0065-Add-getI18NDisplayName-API.patch @@ -32,11 +32,11 @@ index af4a7ce37eb10bab06eadb6583c7894b3ec55ae6..159e5a908b35b84b7fabc36581e093d9 // Paper end } diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index 9da047582e9648d84875b6d3c136960bbb97b70e..87f7942082ad943a97058f58c09ea2fe9caf5bfe 100644 +index 9d327f0832c40d4a8d212346284274f6cf78834f..09a36df6edce2a283df80c67d5ef62da7ff73555 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -618,5 +618,20 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat - public @NotNull net.kyori.adventure.text.Component displayName() { + public net.kyori.adventure.text.@NotNull Component displayName() { return Bukkit.getServer().getItemFactory().displayName(this); } + diff --git a/patches/api/0075-AsyncTabCompleteEvent.patch b/patches/api/0075-AsyncTabCompleteEvent.patch index ebb7553005..b8062adfca 100644 --- a/patches/api/0075-AsyncTabCompleteEvent.patch +++ b/patches/api/0075-AsyncTabCompleteEvent.patch @@ -578,7 +578,7 @@ index 270e6d8ad4358baa256cee5f16cff281f063ce3b..4a3451af454295ac3e1b688e6665cad9 @Override diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 9825db30d42701aad5d9970bbb989fbff0142fb1..2cb81e6d253d70388da15c9d07b630277d486c70 100644 +index c26ea217927ba77611e6ae93f8df50a83bceb3dd..06e96e5c98f1a7a68c8b4b5e527314c1aa774e38 100644 --- a/src/test/java/org/bukkit/AnnotationTest.java +++ b/src/test/java/org/bukkit/AnnotationTest.java @@ -48,6 +48,8 @@ public class AnnotationTest { diff --git a/patches/api/0080-Ability-to-apply-mending-to-XP-API.patch b/patches/api/0080-Ability-to-apply-mending-to-XP-API.patch index f2305d7a9d..2f780e2e68 100644 --- a/patches/api/0080-Ability-to-apply-mending-to-XP-API.patch +++ b/patches/api/0080-Ability-to-apply-mending-to-XP-API.patch @@ -10,7 +10,7 @@ of giving the player experience points. Both an API To standalone mend, and apply mending logic to .giveExp has been added. diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 2f2cce2a8b4b26fbe85da10f55f7313112b05435..af92443e50b66e526d382c820e1b2e27c6e1b461 100644 +index dbe15267053cfd6bdac093f798dda1cb5aff02c4..95130fde38e7fcec4139fac97df25d82e0a79587 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1128,12 +1128,33 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM @@ -18,21 +18,21 @@ index 2f2cce2a8b4b26fbe85da10f55f7313112b05435..af92443e50b66e526d382c820e1b2e27 public void resetPlayerWeather(); + // Paper start -+ /** -+ * Gives the player the amount of experience specified. -+ * -+ * @param amount Exp amount to give -+ */ -+ public default void giveExp(int amount) { -+ giveExp(amount, false); -+ } /** * Gives the player the amount of experience specified. * * @param amount Exp amount to give -+ * @param applyMending Mend players items with mending, with same behavior as picking up orbs. calls {@link #applyMending(int)} */ - public void giveExp(int amount); ++ public default void giveExp(int amount) { ++ giveExp(amount, false); ++ } ++ /** ++ * Gives the player the amount of experience specified. ++ * ++ * @param amount Exp amount to give ++ * @param applyMending Mend players items with mending, with same behavior as picking up orbs. calls {@link #applyMending(int)} ++ */ + public void giveExp(int amount, boolean applyMending); + + /** diff --git a/patches/api/0110-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch b/patches/api/0110-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch index 71a82a8eae..ca44e557bb 100644 --- a/patches/api/0110-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch +++ b/patches/api/0110-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch @@ -18,7 +18,7 @@ index d4d7ad9c3c953680342c121f39ddaef476549047..719d0d878320c1903b44076053989ba9 + public void setConsumeArrow(boolean consumeArrow) { + this.setConsumeItem(consumeArrow); + } -+ + + @Deprecated + public boolean getConsumeArrow() { + return this.shouldConsumeItem(); @@ -33,7 +33,7 @@ index d4d7ad9c3c953680342c121f39ddaef476549047..719d0d878320c1903b44076053989ba9 + public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @NotNull final Entity projectile, final float force) { + this(shooter, bow, new ItemStack(org.bukkit.Material.AIR), projectile, force); + } - ++ + @Deprecated + public EntityShootBowEvent(@NotNull final LivingEntity shooter, @Nullable final ItemStack bow, @NotNull ItemStack arrowItem, @NotNull final Entity projectile, final float force) { + this(shooter, bow, arrowItem, projectile, EquipmentSlot.HAND, force, true); diff --git a/patches/api/0139-Inventory-removeItemAnySlot.patch b/patches/api/0139-Inventory-removeItemAnySlot.patch index 25b79cf6bd..9fc8227226 100644 --- a/patches/api/0139-Inventory-removeItemAnySlot.patch +++ b/patches/api/0139-Inventory-removeItemAnySlot.patch @@ -8,7 +8,7 @@ diff --git a/src/main/java/org/bukkit/inventory/Inventory.java b/src/main/java/o index 5576a6a8df8c95164bf2dde45d756ce8b7ec957a..f1a48eab1a357ae64545e1f1dc941c383cff8707 100644 --- a/src/main/java/org/bukkit/inventory/Inventory.java +++ b/src/main/java/org/bukkit/inventory/Inventory.java -@@ -104,7 +104,9 @@ public interface Inventory extends Iterable { +@@ -104,7 +104,37 @@ public interface Inventory extends Iterable { public HashMap addItem(@NotNull ItemStack... items) throws IllegalArgumentException; /** @@ -16,25 +16,6 @@ index 5576a6a8df8c95164bf2dde45d756ce8b7ec957a..f1a48eab1a357ae64545e1f1dc941c38 + * Removes the given ItemStacks from the storage contents of the inventory. + * For removing ItemStacks from the inventories that have other content groups, + * like Player inventories, see {@link #removeItemAnySlot(ItemStack...)}. - *

- * It will try to remove 'as much as possible' from the types and amounts - * you give as arguments. -@@ -121,10 +123,39 @@ public interface Inventory extends Iterable { - * @param items The ItemStacks to remove - * @return A HashMap containing items that couldn't be removed. - * @throws IllegalArgumentException if items is null -+ * @see #removeItemAnySlot(ItemStack...) - */ - @NotNull - public HashMap removeItem(@NotNull ItemStack... items) throws IllegalArgumentException; - -+ // Paper start -+ /** -+ * Searches all possible inventory slots in order to remove the given ItemStacks. -+ *

-+ * Similar to {@link Inventory#removeItem(ItemStack...)} in behavior, except this -+ * method will check all possible slots in the inventory, rather than just the main -+ * storage contents. + *

+ * It will try to remove 'as much as possible' from the types and amounts + * you give as arguments. @@ -51,11 +32,28 @@ index 5576a6a8df8c95164bf2dde45d756ce8b7ec957a..f1a48eab1a357ae64545e1f1dc941c38 + * @param items The ItemStacks to remove + * @return A HashMap containing items that couldn't be removed. + * @throws IllegalArgumentException if items is null ++ * @see #removeItemAnySlot(ItemStack...) + */ + @NotNull ++ public HashMap removeItem(@NotNull ItemStack... items) throws IllegalArgumentException; ++ ++ // Paper start ++ /** ++ * Searches all possible inventory slots in order to remove the given ItemStacks. ++ *

++ * Similar to {@link Inventory#removeItem(ItemStack...)} in behavior, except this ++ * method will check all possible slots in the inventory, rather than just the main ++ * storage contents. + *

+ * It will try to remove 'as much as possible' from the types and amounts + * you give as arguments. +@@ -123,7 +153,8 @@ public interface Inventory extends Iterable { + * @throws IllegalArgumentException if items is null + */ + @NotNull +- public HashMap removeItem(@NotNull ItemStack... items) throws IllegalArgumentException; + public HashMap removeItemAnySlot(@NotNull ItemStack... items) throws IllegalArgumentException; + // Paper end -+ + /** * Returns all ItemStacks from the inventory - * diff --git a/patches/api/0267-Expand-world-key-API.patch b/patches/api/0267-Expand-world-key-API.patch index c3176669fa..e49ddc7083 100644 --- a/patches/api/0267-Expand-world-key-API.patch +++ b/patches/api/0267-Expand-world-key-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Expand world key API diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index ceb8d207843df5ddc852d44928286648a652eedb..197cf8cdd3d51c3e01ec737981601f37764315c6 100644 +index 95a981218615b9ed167a317aaa5224e9613aa42a..244c836dd24cb49f6219634e3f323befcd68d9da 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -811,6 +811,18 @@ public final class Bukkit { @@ -56,7 +56,7 @@ index 2fa3de66107162ccaa158b369e2c4a926ecaff92..aa534b1a9a1fb84a2fbd4b372f313bb4 // Paper end } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 02b898d441c42771903d5839c3cde544b1a25778..1a3b4f20c7126caf8a34040028f735083bf47150 100644 +index 3327810c2ae80b47f6ccbc5b2034b880a774879f..8390b1d4718a4c67d222e19609462d20c36506b7 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -671,6 +671,17 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @@ -104,16 +104,20 @@ index cbe6b3a1ba7b04826d97c3558e8eb4e5ba11f92f..cbdcac688afb7c13dd7058fa522bbd2c private final String name; private long seed; private World.Environment environment = World.Environment.NORMAL; -@@ -28,13 +29,80 @@ public class WorldCreator { +@@ -28,14 +29,81 @@ public class WorldCreator { * @param name Name of the world that will be created */ public WorldCreator(@NotNull String name) { - if (name == null) { - throw new IllegalArgumentException("World name cannot be null"); +- } +- +- this.name = name; +- this.seed = (new Random()).nextLong(); + // Paper start + this(name, getWorldKey(name)); -+ } -+ + } + + private static NamespacedKey getWorldKey(String name) { + final String mainLevelName = Bukkit.getUnsafe().getMainLevelName(); + if (name.equals(mainLevelName)) { @@ -124,10 +128,9 @@ index cbe6b3a1ba7b04826d97c3558e8eb4e5ba11f92f..cbdcac688afb7c13dd7058fa522bbd2c + return NamespacedKey.minecraft("the_end"); + } else { + return NamespacedKey.minecraft(name.toLowerCase(java.util.Locale.ENGLISH).replace(" ", "_")); - } ++ } + } - -- this.name = name; ++ + /** + * Creates an empty WorldCreator for the given world name and key + * @@ -139,7 +142,7 @@ index cbe6b3a1ba7b04826d97c3558e8eb4e5ba11f92f..cbdcac688afb7c13dd7058fa522bbd2c + throw new IllegalArgumentException("World name and key cannot be null"); + } + this.name = levelName; - this.seed = (new Random()).nextLong(); ++ this.seed = (new Random()).nextLong(); + this.key = worldKey; + } + @@ -183,8 +186,9 @@ index cbe6b3a1ba7b04826d97c3558e8eb4e5ba11f92f..cbdcac688afb7c13dd7058fa522bbd2c + @NotNull + public static WorldCreator ofKey(@NotNull NamespacedKey worldKey) { + return new WorldCreator(worldKey); - } ++ } + // Paper end - ++ /** * Copies the options from the specified world + * diff --git a/patches/api/0288-More-Enchantment-API.patch b/patches/api/0288-More-Enchantment-API.patch index 50fae967ae..0ccfe049b4 100644 --- a/patches/api/0288-More-Enchantment-API.patch +++ b/patches/api/0288-More-Enchantment-API.patch @@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..e6a40c1fcea761bd66743b50e3da3d14 + } +} diff --git a/src/main/java/org/bukkit/enchantments/Enchantment.java b/src/main/java/org/bukkit/enchantments/Enchantment.java -index 0264c2f9a3977b6d47994b1e1b0240b312e5bf65..69a048eb4e48c92db70c3d6b6aa4ae96326b9705 100644 +index 1b6f42ff632b1f3f5034c825e99b72f389a890b4..4cfe8501368f601fdd4203570f4e6a8f6f9685e6 100644 --- a/src/main/java/org/bukkit/enchantments/Enchantment.java +++ b/src/main/java/org/bukkit/enchantments/Enchantment.java @@ -273,11 +273,7 @@ public abstract class Enchantment implements Keyed, net.kyori.adventure.translat @@ -53,7 +53,7 @@ index 0264c2f9a3977b6d47994b1e1b0240b312e5bf65..69a048eb4e48c92db70c3d6b6aa4ae96 @@ -311,6 +307,46 @@ public abstract class Enchantment implements Keyed, net.kyori.adventure.translat * @return the name of the enchantment with {@code level} applied */ - public abstract @NotNull net.kyori.adventure.text.Component displayName(int level); + public abstract net.kyori.adventure.text.@NotNull Component displayName(int level); + + /** + * Checks if this enchantment can be found in villager trades. diff --git a/patches/api/0290-ItemStack-editMeta.patch b/patches/api/0290-ItemStack-editMeta.patch index b3170677e6..4b652c8977 100644 --- a/patches/api/0290-ItemStack-editMeta.patch +++ b/patches/api/0290-ItemStack-editMeta.patch @@ -1,11 +1,11 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park +From: Riley Park Date: Sun, 23 May 2021 05:04:28 -0700 Subject: [PATCH] ItemStack#editMeta diff --git a/src/main/java/org/bukkit/inventory/ItemStack.java b/src/main/java/org/bukkit/inventory/ItemStack.java -index b731ac4f6cd82d8476e4040a2204f58b0f63a0d3..84ea952cdee1eaec5572641e09fdd85930ddeb47 100644 +index ffde4d11d4d5e783afb77bc2e96cf71113b2eb25..c5579710f73e9b8d407d5b8d698d2543a25a752d 100644 --- a/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/src/main/java/org/bukkit/inventory/ItemStack.java @@ -547,6 +547,50 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat diff --git a/patches/api/0295-Add-PlayerKickEvent-causes.patch b/patches/api/0295-Add-PlayerKickEvent-causes.patch index 8e6394f9c3..bc035c363f 100644 --- a/patches/api/0295-Add-PlayerKickEvent-causes.patch +++ b/patches/api/0295-Add-PlayerKickEvent-causes.patch @@ -5,13 +5,13 @@ Subject: [PATCH] Add PlayerKickEvent causes diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 6c4d148202c3378e361fd8068c00cc0b67d6dc1e..b834537b1fa7ee349d10fe1ac5aa7e7dca4e35f7 100644 +index b49620af0edcf10e7f74d616dcb4fb775308308f..bf5eeaffb7983c6a849ee80df0b78230d3cce42b 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -249,6 +249,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @param message kick message */ - void kick(final @Nullable net.kyori.adventure.text.Component message); + void kick(final net.kyori.adventure.text.@Nullable Component message); + + /** + * Kicks player with custom kick message and cause. @@ -19,12 +19,12 @@ index 6c4d148202c3378e361fd8068c00cc0b67d6dc1e..b834537b1fa7ee349d10fe1ac5aa7e7d + * @param message kick message + * @param cause kick cause + */ -+ void kick(final @Nullable net.kyori.adventure.text.Component message, @NotNull org.bukkit.event.player.PlayerKickEvent.Cause cause); ++ void kick(final net.kyori.adventure.text.@Nullable Component message, org.bukkit.event.player.PlayerKickEvent.@NotNull Cause cause); // Paper end /** diff --git a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java -index efbf4b657c99ce3a5096d041d275af9ccaea7911..5c968a0867223925b7eb5d6e04dbc33c41b7be6b 100644 +index 997b06c19a5277656521e0e298f2958c209f1da1..2eb13c049fa917d41fa9ad17fdec9ec4c33701a8 100644 --- a/src/main/java/org/bukkit/event/player/PlayerKickEvent.java +++ b/src/main/java/org/bukkit/event/player/PlayerKickEvent.java @@ -12,6 +12,7 @@ public class PlayerKickEvent extends PlayerEvent implements Cancellable { diff --git a/patches/api/0321-Add-more-advancement-API.patch b/patches/api/0321-Add-more-advancement-API.patch index 2fd6d7a372..1fce73dab5 100644 --- a/patches/api/0321-Add-more-advancement-API.patch +++ b/patches/api/0321-Add-more-advancement-API.patch @@ -194,8 +194,12 @@ index 17527c2f7bd5b8a5528388a53f2472bc1869c7f3..3f6b9e59c2ea38031ca74962e02d710f + * recipes. * - * This includes it's name, description and other visible tags. +- * +- * @return a AdvancementDisplay object, or null if not set. + * @return the display info -+ */ + */ +- @Nullable +- AdvancementDisplay getDisplay(); + @org.jetbrains.annotations.Nullable + io.papermc.paper.advancement.AdvancementDisplay getDisplay(); + @@ -205,13 +209,10 @@ index 17527c2f7bd5b8a5528388a53f2472bc1869c7f3..3f6b9e59c2ea38031ca74962e02d710f + * completes the advancement. Will return the same as + * {@link io.papermc.paper.advancement.AdvancementDisplay#displayName()} when an + * {@link io.papermc.paper.advancement.AdvancementDisplay} is present. - * -- * @return a AdvancementDisplay object, or null if not set. ++ * + * @return the display name + * @see io.papermc.paper.advancement.AdvancementDisplay#displayName() - */ -- @Nullable -- AdvancementDisplay getDisplay(); ++ */ + @NotNull net.kyori.adventure.text.Component displayName(); + + /** diff --git a/patches/api/0323-Add-critical-damage-API.patch b/patches/api/0323-Add-critical-damage-API.patch index 3a9d1f8070..b8f225d5da 100644 --- a/patches/api/0323-Add-critical-damage-API.patch +++ b/patches/api/0323-Add-critical-damage-API.patch @@ -8,7 +8,7 @@ diff --git a/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.jav index 869bad7405ec7fa67728e90d8b9f2e11b542611f..7ce8f1a26c1b33dd0eb6e6435952fd73abf49879 100644 --- a/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java +++ b/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java -@@ -11,15 +11,40 @@ import org.jetbrains.annotations.NotNull; +@@ -11,16 +11,41 @@ import org.jetbrains.annotations.NotNull; public class EntityDamageByEntityEvent extends EntityDamageEvent { private final Entity damager; @@ -32,8 +32,8 @@ index 869bad7405ec7fa67728e90d8b9f2e11b542611f..7ce8f1a26c1b33dd0eb6e6435952fd73 this.damager = damager; + // Paper start - add critical damage API + this.critical = critical; -+ } -+ + } + + /** + * Shows this damage instance was critical. + * The damage instance can be critical if the attacking player met the respective conditions. @@ -44,8 +44,9 @@ index 869bad7405ec7fa67728e90d8b9f2e11b542611f..7ce8f1a26c1b33dd0eb6e6435952fd73 + */ + public boolean isCritical() { + return this.critical; - } ++ } + // Paper end - ++ /** * Returns the entity that damaged the defender. + * diff --git a/patches/api/0406-Improve-PortalEvents.patch b/patches/api/0406-Improve-PortalEvents.patch index f7f53b19fc..8c5aa2655d 100644 --- a/patches/api/0406-Improve-PortalEvents.patch +++ b/patches/api/0406-Improve-PortalEvents.patch @@ -8,7 +8,7 @@ diff --git a/src/main/java/org/bukkit/event/entity/EntityPortalEvent.java b/src/ index 67fb9d93e808e907fa980f3004d415ae5d0a53fc..97e36c7f6e09276fbae20eaeee0965566332ca46 100644 --- a/src/main/java/org/bukkit/event/entity/EntityPortalEvent.java +++ b/src/main/java/org/bukkit/event/entity/EntityPortalEvent.java -@@ -15,15 +15,58 @@ import org.jetbrains.annotations.Nullable; +@@ -15,16 +15,59 @@ import org.jetbrains.annotations.Nullable; public class EntityPortalEvent extends EntityTeleportEvent { private static final HandlerList handlers = new HandlerList(); private int searchRadius = 128; @@ -23,8 +23,8 @@ index 67fb9d93e808e907fa980f3004d415ae5d0a53fc..97e36c7f6e09276fbae20eaeee096556 super(entity, from, to); this.searchRadius = searchRadius; + this.type = org.bukkit.PortalType.CUSTOM; // Paper -+ } -+ + } + + // Paper start + public EntityPortalEvent(@NotNull Entity entity, @NotNull Location from, @Nullable Location to, int searchRadius, final @NotNull org.bukkit.PortalType portalType) { + super(entity, from, to); @@ -63,11 +63,12 @@ index 67fb9d93e808e907fa980f3004d415ae5d0a53fc..97e36c7f6e09276fbae20eaeee096556 + @Override + public void setTo(@Nullable final Location to) { + super.setTo(to); - } ++ } + // Paper end - ++ /** * Set the Block radius to search in for available portals. + * diff --git a/src/main/java/org/bukkit/event/player/PlayerPortalEvent.java b/src/main/java/org/bukkit/event/player/PlayerPortalEvent.java index 57eeeafae84f83a939925820e827769749ff27ec..929a997671de8202efb9da97fbf9b4a0bf7c37e8 100644 --- a/src/main/java/org/bukkit/event/player/PlayerPortalEvent.java diff --git a/patches/server/0009-MC-Utils.patch b/patches/server/0009-MC-Utils.patch index cd3303b7f0..fe1c0f306b 100644 --- a/patches/server/0009-MC-Utils.patch +++ b/patches/server/0009-MC-Utils.patch @@ -7674,12 +7674,12 @@ index d2026d218405a40a6949c5f491c04704811b72b5..629178347039893fb9de710810fe8112 + public ChunkAccess getChunkIfLoadedImmediately(int x, int z) { + throw new UnsupportedOperationException("Not supported yet."); + } -+ + + @Override + public BlockState getBlockStateIfLoaded(BlockPos blockposition) { + throw new UnsupportedOperationException("Not supported yet."); + } - ++ + @Override + public FluidState getFluidIfLoaded(BlockPos blockposition) { + throw new UnsupportedOperationException("Not supported yet."); diff --git a/patches/server/0010-Adventure.patch b/patches/server/0010-Adventure.patch index 9195ff5f72..8c51cf6e6d 100644 --- a/patches/server/0010-Adventure.patch +++ b/patches/server/0010-Adventure.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park +From: Riley Park Date: Fri, 29 Jan 2021 17:54:03 +0100 Subject: [PATCH] Adventure @@ -2322,13 +2322,14 @@ index 000fd11480d783eab80a93fedde48f66e6b1298b..b3b6121dcfb6451d177431d51fa8a3e0 - @Deprecated - public void disconnect(Component reason) { - this.disconnect(CraftChatMessage.fromComponent(reason)); -+ public void disconnect(String s) { +- } +- // CraftBukkit end +- + public void disconnect(String s) { + // Paper start + this.disconnect(net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(s)); - } -- // CraftBukkit end - -- public void disconnect(String s) { ++ } ++ + public void disconnect(final Component reason) { + this.disconnect(PaperAdventure.asAdventure(reason)); + } @@ -2809,13 +2810,13 @@ index 059ba63319f6ca04750a7d6b095e6179cae68b4f..cb2dc6db887856c5f60d127f5999a078 } + // Paper start -+ @Override + @Override + public net.kyori.adventure.text.Component shutdownMessage() { + String msg = getShutdownMessage(); + return msg != null ? net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(msg) : null; + } + // Paper end - @Override ++ @Override + @Deprecated // Paper public String getShutdownMessage() { return this.configuration.getString("settings.shutdown-message"); @@ -2892,12 +2893,12 @@ index 059ba63319f6ca04750a7d6b095e6179cae68b4f..cb2dc6db887856c5f60d127f5999a078 } + // Paper start -+ @Override + @Override + public Merchant createMerchant(net.kyori.adventure.text.Component title) { + return new org.bukkit.craftbukkit.inventory.CraftMerchantCustom(title == null ? InventoryType.MERCHANT.defaultTitle() : title); + } + // Paper end - @Override ++ @Override + @Deprecated // Paper public Merchant createMerchant(String title) { return new CraftMerchantCustom(title == null ? InventoryType.MERCHANT.getDefaultTitle() : title); @@ -2963,7 +2964,7 @@ index 3b9e42adb657d0feb99de4b55dc0c628e9cd5afd..253f965e52cd488af88d55cdd09f1bad // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 7fc066ee281662192aad826840573e4181f5ceff..6569c9db3fa026ee4fbfaceac0e4f6a15c1fbe16 100644 +index fe726771b76cabcb58bf624969490d9595965082..e16a458a708080ff5321362cba440fa465dba7d6 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -20,6 +20,12 @@ public class Main { @@ -3949,7 +3950,7 @@ index b7f54a7d90a2a34e641f152eb8f5c3c62033e511..2d04443a9efd6e4b5eb1e360a727d849 @Override public int getLineWidth() { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index f9499aa8fc5443b54617c8e84011af5d0325bd45..2c3518ea974be5fce424093e9b710c853fd52a7a 100644 +index 5e02ea662a1307b2718811bab98ed0d6d17edd87..54a9a630ca1aa3cabc9aa29ba7d9e516c0f88a00 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -820,9 +820,9 @@ public class CraftEventFactory { diff --git a/patches/server/0011-Paper-command.patch b/patches/server/0011-Paper-command.patch index f7cf98532c..908f57d0d5 100644 --- a/patches/server/0011-Paper-command.patch +++ b/patches/server/0011-Paper-command.patch @@ -1,8 +1,9 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Zach Brown +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 29 Feb 2016 21:02:09 -0600 Subject: [PATCH] Paper command +Co-authored-by: Zach Brown diff --git a/src/main/java/io/papermc/paper/command/CommandUtil.java b/src/main/java/io/papermc/paper/command/CommandUtil.java new file mode 100644 diff --git a/patches/server/0016-Starlight.patch b/patches/server/0016-Starlight.patch index da5f1b8108..1741b5b0a1 100644 --- a/patches/server/0016-Starlight.patch +++ b/patches/server/0016-Starlight.patch @@ -4545,13 +4545,13 @@ index 5b238e41ffa3e374b52ee955cb39087571c6ffc2..275b7f7dd36a2073a3eb9f89f4c83283 + this.hasSkyLight = hasBlockLight; // Nice variable name. + this.theLightEngine = new ca.spottedleaf.starlight.common.light.StarLightInterface(chunkProvider, this.hasSkyLight, this.hasBlockLight, this); + // Paper end - replace light engine impl -+ } -+ + } + + // Paper start - replace light engine impl + protected final ChunkAccess getChunk(final int chunkX, final int chunkZ) { + return ((ServerLevel)this.theLightEngine.getWorld()).getChunkSource().getChunkAtImmediately(chunkX, chunkZ); - } - ++ } ++ + protected long relightCounter; + + public int relight(java.util.Set chunks_param, @@ -5167,13 +5167,13 @@ index aa4f2dc63dd79e6c3d7594d2fd63fa0091df5f53..bca8084f7e76d036378705aa802217cc + } else if (flag1) { + skyNibbles[y - minSection] = new ca.spottedleaf.starlight.common.light.SWMRNibbleArray(null, sectionData.getInt(SKYLIGHT_STATE_TAG)); + // Paper end - rewrite the light engine -+ } + } + + // Paper start - rewrite the light engine + } catch (Exception ex) { + LOGGER.warn("Failed to load light data for chunk " + chunkPos + " in world '" + world.getWorld().getName() + "', light will be regenerated", ex); + flag = false; - } ++ } + // Paper end - rewrite light engine } } diff --git a/patches/server/0018-Rewrite-chunk-system.patch b/patches/server/0018-Rewrite-chunk-system.patch index 723e84af55..028e662121 100644 --- a/patches/server/0018-Rewrite-chunk-system.patch +++ b/patches/server/0018-Rewrite-chunk-system.patch @@ -13176,16 +13176,6 @@ index 30e330cc3a2f51e4ec9555671e3eeb7bb14bdfa3..214e0657035f82e5266de06e31975d6b - entityplayer.connection.send(packet); - }); - } -- -- public CompletableFuture> getOrScheduleFuture(ChunkStatus targetStatus, ChunkMap chunkStorage) { -- int i = targetStatus.getIndex(); -- CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); -- -- if (completablefuture != null) { -- Either either = (Either) completablefuture.getNow(ChunkHolder.NOT_DONE_YET); -- -- if (either == null) { -- String s = "value in future for status: " + targetStatus + " was incorrectly set to null at chunk: " + this.pos; + // Paper start - per player view distance + // there can be potential desync with player's last mapped section and the view distance map, so use the + // view distance map here. @@ -13195,6 +13185,16 @@ index 30e330cc3a2f51e4ec9555671e3eeb7bb14bdfa3..214e0657035f82e5266de06e31975d6b + return; + } +- public CompletableFuture> getOrScheduleFuture(ChunkStatus targetStatus, ChunkMap chunkStorage) { +- int i = targetStatus.getIndex(); +- CompletableFuture> completablefuture = (CompletableFuture) this.futures.get(i); +- +- if (completablefuture != null) { +- Either either = (Either) completablefuture.getNow(ChunkHolder.NOT_DONE_YET); +- +- if (either == null) { +- String s = "value in future for status: " + targetStatus + " was incorrectly set to null at chunk: " + this.pos; +- - throw chunkStorage.debugFuturesAndCreateReportedException(new IllegalStateException("null value previously set for chunk status"), s); + Object[] backingSet = players.getBackingSet(); + for (int i = 0, len = backingSet.length; i < len; ++i) { @@ -13258,8 +13258,9 @@ index 30e330cc3a2f51e4ec9555671e3eeb7bb14bdfa3..214e0657035f82e5266de06e31975d6b public final int getTicketLevel() { // Paper - final for inline - return this.ticketLevel; -- } -- ++ return this.newChunkHolder.getTicketLevel(); // Paper - rewrite chunk system + } + - public int getQueueLevel() { - return this.queueLevel; - } @@ -13285,9 +13286,8 @@ index 30e330cc3a2f51e4ec9555671e3eeb7bb14bdfa3..214e0657035f82e5266de06e31975d6b - completablefuture1.complete(null); // CraftBukkit - decompile error - }); - }); -+ return this.newChunkHolder.getTicketLevel(); // Paper - rewrite chunk system - } - +- } +- - private void demoteFullChunk(ChunkMap playerchunkmap, ChunkHolder.FullChunkStatus playerchunk_state) { - this.pendingFullStateConfirmation.cancel(false); - playerchunkmap.onFullChunkStatusChange(this.pos, playerchunk_state); @@ -13823,15 +13823,16 @@ index 578849f64de38dc75cdefeb243422c4c89a5c69c..9246ce9f654ad4db6155b026778a83d4 - } finally { - super.close(); - } +- + throw new UnsupportedOperationException("Use ServerChunkCache#close"); // Paper - rewrite chunk system -+ } + } + // Paper start - rewrite chunk system + protected void saveIncrementally() { + this.level.chunkTaskScheduler.chunkHolderManager.autoSave(); // Paper - rewrite chunk system - } ++ } + // Paper end - - rewrite chunk system - ++ protected void saveAllChunks(boolean flush) { - if (flush) { - List list = (List) io.papermc.paper.chunk.system.ChunkSystem.getVisibleChunkHolders(this.level).stream().filter(ChunkHolder::wasAccessibleSinceLastSave).peek(ChunkHolder::refreshAccessibility).collect(Collectors.toList()); // Paper @@ -14491,21 +14492,25 @@ index 578849f64de38dc75cdefeb243422c4c89a5c69c..9246ce9f654ad4db6155b026778a83d4 - Set set = this.playerMap.getPlayers(chunkPos.toLong()); - Builder builder = ImmutableList.builder(); - Iterator iterator = set.iterator(); +- +- while (iterator.hasNext()) { +- ServerPlayer entityplayer = (ServerPlayer) iterator.next(); +- SectionPos sectionposition = entityplayer.getLastSectionPos(); +- +- if (onlyOnWatchDistanceEdge && ChunkMap.isChunkOnRangeBorder(chunkPos.x, chunkPos.z, sectionposition.x(), sectionposition.z(), this.viewDistance) || !onlyOnWatchDistanceEdge && ChunkMap.isChunkInRange(chunkPos.x, chunkPos.z, sectionposition.x(), sectionposition.z(), this.viewDistance)) { +- builder.add(entityplayer); +- } + // Paper start - per player view distance + // there can be potential desync with player's last mapped section and the view distance map, so use the + // view distance map here. + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet players = this.playerChunkManager.broadcastMap.getObjectsInRange(chunkPos); + if (players == null) { + return java.util.Collections.emptyList(); -+ } + } -- while (iterator.hasNext()) { -- ServerPlayer entityplayer = (ServerPlayer) iterator.next(); -- SectionPos sectionposition = entityplayer.getLastSectionPos(); +- return builder.build(); + List ret = new java.util.ArrayList<>(players.size()); - -- if (onlyOnWatchDistanceEdge && ChunkMap.isChunkOnRangeBorder(chunkPos.x, chunkPos.z, sectionposition.x(), sectionposition.z(), this.viewDistance) || !onlyOnWatchDistanceEdge && ChunkMap.isChunkInRange(chunkPos.x, chunkPos.z, sectionposition.x(), sectionposition.z(), this.viewDistance)) { -- builder.add(entityplayer); ++ + Object[] backingSet = players.getBackingSet(); + for (int i = 0, len = backingSet.length; i < len; ++i) { + if (!(backingSet[i] instanceof ServerPlayer player)) { @@ -14513,11 +14518,10 @@ index 578849f64de38dc75cdefeb243422c4c89a5c69c..9246ce9f654ad4db6155b026778a83d4 + } + if (!this.playerChunkManager.isChunkSent(player, chunkPos.x, chunkPos.z, onlyOnWatchDistanceEdge)) { + continue; - } ++ } + ret.add(player); - } - -- return builder.build(); ++ } ++ + return ret; + // Paper end - per player view distance } @@ -14883,7 +14887,8 @@ index d38ad1b1eee92a6dbd2b79b4fcdb8959cdb4007d..ffa1e457decf8502c3283352bf5be94d - private void dumpTickets(String path) { - try { - FileOutputStream fileoutputstream = new FileOutputStream(new File(path)); -- ++ // Paper - rewrite chunk system + - try { - ObjectIterator objectiterator = this.tickets.long2ObjectEntrySet().iterator(); - @@ -14904,8 +14909,7 @@ index d38ad1b1eee92a6dbd2b79b4fcdb8959cdb4007d..ffa1e457decf8502c3283352bf5be94d - } catch (Throwable throwable1) { - throwable.addSuppressed(throwable1); - } -+ // Paper - rewrite chunk system - +- - throw throwable; - } - @@ -15125,29 +15129,23 @@ index 28c8a3ba1caddf0ea334a6ef43cae25f982743e4..80d108ae7faf3fdcb024931e93032215 - ChunkHolder.FullChunkStatus oldChunkState = ChunkHolder.getFullChunkStatus(playerchunk.oldTicketLevel); - ChunkHolder.FullChunkStatus currentChunkState = ChunkHolder.getFullChunkStatus(playerchunk.getTicketLevel()); - currentlyUnloading = (oldChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER) && !currentChunkState.isOrAfter(ChunkHolder.FullChunkStatus.BORDER)); -- } ++ boolean needsFullScheduling = leastStatus == ChunkStatus.FULL && (chunkHolder == null || !chunkHolder.getChunkStatus().isOrAfter(ChunkHolder.FullChunkStatus.BORDER)); ++ ++ if ((chunkHolder == null || chunkHolder.getTicketLevel() > minLevel || needsFullScheduling) && !create) { ++ return ChunkHolder.UNLOADED_CHUNK_FUTURE; + } - if (create && !currentlyUnloading) { - // CraftBukkit end - this.distanceManager.addTicket(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair); - if (this.chunkAbsent(playerchunk, l)) { - ProfilerFiller gameprofilerfiller = this.level.getProfiler(); -- + - gameprofilerfiller.push("chunkLoad"); - this.runDistanceManagerUpdates(); - playerchunk = this.getVisibleChunkIfPresent(k); - gameprofilerfiller.pop(); - if (this.chunkAbsent(playerchunk, l)) { - throw (IllegalStateException) Util.pauseInIde(new IllegalStateException("No chunk holder after ticket has been added")); -- } -- } -+ boolean needsFullScheduling = leastStatus == ChunkStatus.FULL && (chunkHolder == null || !chunkHolder.getChunkStatus().isOrAfter(ChunkHolder.FullChunkStatus.BORDER)); -+ -+ if ((chunkHolder == null || chunkHolder.getTicketLevel() > minLevel || needsFullScheduling) && !create) { -+ return ChunkHolder.UNLOADED_CHUNK_FUTURE; - } - -- return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(leastStatus, this.chunkMap); -- } + io.papermc.paper.chunk.system.scheduling.NewChunkHolder.ChunkCompletion chunkCompletion = chunkHolder == null ? null : chunkHolder.getLastChunkCompletion(); + if (needsFullScheduling || chunkCompletion == null || !chunkCompletion.genStatus().isOrAfter(leastStatus)) { + // schedule @@ -15157,11 +15155,10 @@ index 28c8a3ba1caddf0ea334a6ef43cae25f982743e4..80d108ae7faf3fdcb024931e93032215 + ret.complete(Either.right(ChunkHolder.ChunkLoadingFailure.UNLOADED)); + } else { + ret.complete(Either.left(chunk)); -+ } + } +- } + }; - -- private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { -- return holder == null || holder.oldTicketLevel > maxLevel; // CraftBukkit using oldTicketLevel for isLoaded checks ++ + this.level.chunkTaskScheduler.scheduleChunkLoad( + chunkX, chunkZ, leastStatus, true, + isUrgent ? ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.BLOCKING : ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor.Priority.NORMAL, @@ -15172,12 +15169,17 @@ index 28c8a3ba1caddf0ea334a6ef43cae25f982743e4..80d108ae7faf3fdcb024931e93032215 + } else { + // can return now + return CompletableFuture.completedFuture(Either.left(chunkCompletion.chunk())); -+ } + } +- +- return this.chunkAbsent(playerchunk, l) ? ChunkHolder.UNLOADED_CHUNK_FUTURE : playerchunk.getOrScheduleFuture(leastStatus, this.chunkMap); + // Paper end - rewrite chunk system } +- private boolean chunkAbsent(@Nullable ChunkHolder holder, int maxLevel) { +- return holder == null || holder.oldTicketLevel > maxLevel; // CraftBukkit using oldTicketLevel for isLoaded checks +- } + // Paper - rewrite chunk system -+ + @Override public boolean hasChunk(int x, int z) { - ChunkHolder playerchunk = this.getVisibleChunkIfPresent((new ChunkPos(x, z)).toLong()); @@ -16532,7 +16534,21 @@ index 69f55f7207b8c03ca886947c57c9d13a8e8eb576..0517c0932b79db1a0e27673654ae8bb5 - if (result.size() >= limit) { - return AbortableIterationConsumer.Continuation.ABORT; - } -- } ++ // Paper start - optimise this call ++ //TODO use limit ++ if (filter instanceof net.minecraft.world.entity.EntityType entityTypeTest) { ++ ((ServerLevel) this).getEntityLookup().getEntities(entityTypeTest, box, result, predicate); ++ } else { ++ Predicate test = (obj) -> { ++ return filter.tryCast(obj) != null; ++ }; ++ predicate = predicate == null ? test : test.and((Predicate) predicate); ++ Class base; ++ if (filter == null || (base = filter.getBaseClass()) == null || base == Entity.class) { ++ ((ServerLevel) this).getEntityLookup().getEntities((Entity) null, box, (List) result, (Predicate)predicate); ++ } else { ++ ((ServerLevel) this).getEntityLookup().getEntities(base, null, box, (List) result, (Predicate)predicate); // Paper - optimise this call + } - - if (entity instanceof EnderDragon) { - EnderDragon entityenderdragon = (EnderDragon) entity; @@ -16550,21 +16566,7 @@ index 69f55f7207b8c03ca886947c57c9d13a8e8eb576..0517c0932b79db1a0e27673654ae8bb5 - } - } - } -+ // Paper start - optimise this call -+ //TODO use limit -+ if (filter instanceof net.minecraft.world.entity.EntityType entityTypeTest) { -+ ((ServerLevel) this).getEntityLookup().getEntities(entityTypeTest, box, result, predicate); -+ } else { -+ Predicate test = (obj) -> { -+ return filter.tryCast(obj) != null; -+ }; -+ predicate = predicate == null ? test : test.and((Predicate) predicate); -+ Class base; -+ if (filter == null || (base = filter.getBaseClass()) == null || base == Entity.class) { -+ ((ServerLevel) this).getEntityLookup().getEntities((Entity) null, box, (List) result, (Predicate)predicate); -+ } else { -+ ((ServerLevel) this).getEntityLookup().getEntities(base, null, box, (List) result, (Predicate)predicate); // Paper - optimise this call - } +- } - - return AbortableIterationConsumer.Continuation.CONTINUE; - }); @@ -16966,15 +16968,15 @@ index bca8084f7e76d036378705aa802217cc1bfdbc7d..f9dd2d9312297a727344d43150c5cab7 } else { ProtoChunk protochunk1 = (ProtoChunk) object1; -@@ -362,9 +388,41 @@ public class ChunkSerializer { +@@ -362,10 +388,42 @@ public class ChunkSerializer { protochunk1.setCarvingMask(worldgenstage_features, new CarvingMask(nbttagcompound4.getLongArray(s1), ((ChunkAccess) object1).getMinBuildHeight())); } - return protochunk1; + return new InProgressChunkHolder(protochunk1, tasksToExecuteOnMain); // Paper - Async chunk loading -+ } -+ } -+ + } + } + + // Paper start - async chunk save for unload + public record AsyncSaveData( + Tag blockTickList, // non-null if we had to go to the server's tick list @@ -16996,7 +16998,7 @@ index bca8084f7e76d036378705aa802217cc1bfdbc7d..f9dd2d9312297a727344d43150c5cab7 + if (blockEntityNbt != null) { + blockEntitiesSerialized.add(blockEntityNbt); + } - } ++ } + + return new AsyncSaveData( + tickLists.get(BLOCK_TICKS_TAG), @@ -17004,11 +17006,12 @@ index bca8084f7e76d036378705aa802217cc1bfdbc7d..f9dd2d9312297a727344d43150c5cab7 + blockEntitiesSerialized, + world.getGameTime() + ); - } ++ } + // Paper end - ++ private static void logErrors(ChunkPos chunkPos, int y, String message) { ChunkSerializer.LOGGER.error("Recoverable errors when loading section [" + chunkPos.x + ", " + y + ", " + chunkPos.z + "]: " + message); + } @@ -381,6 +439,11 @@ public class ChunkSerializer { // CraftBukkit end @@ -17148,11 +17151,11 @@ index ba267f3082607669282a61f013991e1c391a3f09..0747d2d411a85a26bfea08cc1dd29df6 + } catch (Throwable thr) { + return CompletableFuture.failedFuture(thr); + } -+ } + } + @Nullable + public CompoundTag readSync(ChunkPos chunkPos) throws IOException { + return this.regionFileCache.read(chunkPos); - } ++ } + // Paper end - async chunk io - public void write(ChunkPos chunkPos, CompoundTag nbt) { @@ -17239,17 +17242,17 @@ index 98b3909b536f11eda9c481ffd74066ad0cdb0ebc..0ec0be22f7292d57c40da6f1f4575bde - } - }, this.entityDeserializerQueue::tell); + throw new UnsupportedOperationException(); // Paper - rewrite chunk system - copy out read logic into readEntities -+ } -+ + } + +- private static ChunkPos readChunkPos(CompoundTag chunkNbt) { + // Paper start - rewrite chunk system + public static List readEntities(ServerLevel level, CompoundTag compoundTag) { + ListTag listTag = compoundTag.getList("Entities", 10); + List list = EntityType.loadEntitiesRecursive(listTag, level).collect(ImmutableList.toImmutableList()); + return list; - } ++ } + // Paper end - rewrite chunk system - -- private static ChunkPos readChunkPos(CompoundTag chunkNbt) { ++ + public static ChunkPos readChunkPos(CompoundTag chunkNbt) { // Paper - public int[] is = chunkNbt.getIntArray("Position"); return new ChunkPos(is[0], is[1]); @@ -17291,6 +17294,10 @@ index 98b3909b536f11eda9c481ffd74066ad0cdb0ebc..0ec0be22f7292d57c40da6f1f4575bde } } +- @Override +- public void flush(boolean sync) { +- this.worker.synchronize(sync).join(); +- this.entityDeserializerQueue.runAll(); + // Paper start - rewrite chunk system + public static void copyEntities(final CompoundTag from, final CompoundTag into) { + if (from == null) { @@ -17304,8 +17311,9 @@ index 98b3909b536f11eda9c481ffd74066ad0cdb0ebc..0ec0be22f7292d57c40da6f1f4575bde + final ListTag entitiesInto = into.getList("Entities", net.minecraft.nbt.Tag.TAG_COMPOUND); + into.put("Entities", entitiesInto); // this is in case into doesn't have any entities + entitiesInto.addAll(0, entitiesFrom.copy()); // need to copy, this is coming from the save thread -+ } -+ + } + +- private CompoundTag upgradeChunkTag(CompoundTag chunkNbt) { + public static CompoundTag saveEntityChunk(List entities, ChunkPos chunkPos, ServerLevel level) { + return saveEntityChunk0(entities, chunkPos, level, false); + } @@ -17331,14 +17339,11 @@ index 98b3909b536f11eda9c481ffd74066ad0cdb0ebc..0ec0be22f7292d57c40da6f1f4575bde + } + // Paper end - rewrite chunk system + - @Override - public void flush(boolean sync) { -- this.worker.synchronize(sync).join(); -- this.entityDeserializerQueue.runAll(); ++ @Override ++ public void flush(boolean sync) { + throw new UnsupportedOperationException(); // Paper - rewrite chunk system - } - -- private CompoundTag upgradeChunkTag(CompoundTag chunkNbt) { ++ } ++ + public static CompoundTag upgradeChunkTag(CompoundTag chunkNbt) { // Paper - public and static int i = NbtUtils.getDataVersion(chunkNbt, -1); return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY_CHUNK, chunkNbt, i, net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion()); // Paper - route to new converter system @@ -17996,7 +18001,7 @@ index 253f965e52cd488af88d55cdd09f1bad0ddbeb56..30137f60a3796cf845e8fd7bd3c291be // Spigot start private final org.bukkit.World.Spigot spigot = new org.bukkit.World.Spigot() diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 12e7a0a24fe2aa6e7af97ad7d50d81e5c7b26663..d60dc99e2b926847f42a32e9d093a31556d179d8 100644 +index 7c9f1b998ea5447d6ff29cdbb9e3cee0ba1c7c99..7b57298ee6c9422fa10dde9cf9441ea10b3443e4 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -177,6 +177,81 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0030-Player-affects-spawning-API.patch b/patches/server/0030-Player-affects-spawning-API.patch index 5012bdb12b..8b945d0813 100644 --- a/patches/server/0030-Player-affects-spawning-API.patch +++ b/patches/server/0030-Player-affects-spawning-API.patch @@ -21,7 +21,7 @@ index 5c3b11f738c1ea19981cc878aa6c2323497391a0..6fd874a83a248e6a7d427d18d11fc608 public static Predicate withinDistance(double x, double y, double z, double max) { double d4 = max * max; diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index f74e1788692c3f9b291e6ba5043944a3179b97e1..eee466e718f52329f8200ff830f5f1e44cda3e7e 100644 +index 9feb422045c5c47bbf48a5f75f437e51f19e1595..e06dc3f6c03276afb2ab3e0ec24cba707e09a24e 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java @@ -837,7 +837,7 @@ public abstract class Mob extends LivingEntity implements Targeting { @@ -137,7 +137,7 @@ index be6e3e21ad62da01e5e2dd78e300cbc8efdbeb42..ea98625fe7c00743b8df74a24e6d4b75 for(Player player : this.players()) { if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player)) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index d60dc99e2b926847f42a32e9d093a31556d179d8..aa8f41ac360592a37306e439c85dda81acaaa6dc 100644 +index 7b57298ee6c9422fa10dde9cf9441ea10b3443e4..f9cf8b94890be80e383d1e24671aa8b10f54f1b6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -2187,8 +2187,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -145,13 +145,13 @@ index d60dc99e2b926847f42a32e9d093a31556d179d8..aa8f41ac360592a37306e439c85dda81 public String getLocale() { return this.getHandle().locale; + -+ } -+ + } + + // Paper start + public void setAffectsSpawning(boolean affects) { + this.getHandle().affectsSpawning = affects; - } - ++ } ++ + @Override + public boolean getAffectsSpawning() { + return this.getHandle().affectsSpawning; diff --git a/patches/server/0031-Further-improve-server-tick-loop.patch b/patches/server/0031-Further-improve-server-tick-loop.patch index 2204d80cc2..8168fa8c75 100644 --- a/patches/server/0031-Further-improve-server-tick-loop.patch +++ b/patches/server/0031-Further-improve-server-tick-loop.patch @@ -12,7 +12,7 @@ Previous implementation did not calculate TPS correctly. Switch to a realistic rolling average and factor in std deviation as an extra reporting variable diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 23181f54828410d78cae56fed226bea5de4be5ff..19d7a4da730cf260407d6216b8dbba958ec8f84c 100644 +index 8cd3ad2601df5a604de904304ae3f603a471dfee..846dc9b607f40f1af3b4b7c7bbfe3c0803c0ad39 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -284,7 +284,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) { + sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); @@ -193,10 +196,7 @@ index 4ab81a99f906e3f28e026d0e50b5b943c1bdcfb5..9bede6a26c08ede063c7a38f1149c811 + sender.sendMessage(ChatColor.RED + "Warning: " + ChatColor.GOLD + " Memory usage on modern garbage collectors is not a stable value and it is perfectly normal to see it reach max. Please do not pay it much attention."); + hasShownMemoryWarning = true; + } - } -- sender.sendMessage( sb.substring( 0, sb.length() - 2 ) ); -- sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " -- + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)"); ++ } + // Paper end return true; diff --git a/patches/server/0033-Entity-Origin-API.patch b/patches/server/0033-Entity-Origin-API.patch index 66cb388d44..cf616bf8a6 100644 --- a/patches/server/0033-Entity-Origin-API.patch +++ b/patches/server/0033-Entity-Origin-API.patch @@ -37,12 +37,12 @@ index 969fbf3959733200b1dfb98a8520465e358018c5..3cc8426283f68db0a4cbda6934aa6bfd + private org.bukkit.util.Vector origin; + @javax.annotation.Nullable + private UUID originWorld; -+ + + public void setOrigin(@javax.annotation.Nonnull Location location) { + this.origin = location.toVector(); + this.originWorld = location.getWorld().getUID(); + } - ++ + @javax.annotation.Nullable + public org.bukkit.util.Vector getOriginVector() { + return this.origin != null ? this.origin.clone() : null; diff --git a/patches/server/0069-Handle-Item-Meta-Inconsistencies.patch b/patches/server/0069-Handle-Item-Meta-Inconsistencies.patch index 15b9759073..fb8484ecf5 100644 --- a/patches/server/0069-Handle-Item-Meta-Inconsistencies.patch +++ b/patches/server/0069-Handle-Item-Meta-Inconsistencies.patch @@ -130,7 +130,14 @@ index 1e5ec95e19aca0530c141b6415fe6daca4f2d066..da5e660860a46227c59567f6458a9cf4 - ListTag list = CraftItemStack.getEnchantmentList(this.handle), listCopy; - if (list == null) { - return 0; -- } ++ // Paper start - replace entire method ++ int level = getEnchantmentLevel(ench); ++ if (level > 0) { ++ final ItemMeta itemMeta = this.getItemMeta(); ++ if (itemMeta == null) return 0; ++ itemMeta.removeEnchant(ench); ++ this.setItemMeta(itemMeta); + } - int index = Integer.MIN_VALUE; - int level = Integer.MIN_VALUE; - int size = list.size(); @@ -162,14 +169,7 @@ index 1e5ec95e19aca0530c141b6415fe6daca4f2d066..da5e660860a46227c59567f6458a9cf4 - if (i != index) { - listCopy.add(list.get(i)); - } -+ // Paper start - replace entire method -+ int level = getEnchantmentLevel(ench); -+ if (level > 0) { -+ final ItemMeta itemMeta = this.getItemMeta(); -+ if (itemMeta == null) return 0; -+ itemMeta.removeEnchant(ench); -+ this.setItemMeta(itemMeta); - } +- } - this.handle.getTag().put(ENCHANTMENTS.NBT, listCopy); + // Paper end @@ -184,7 +184,7 @@ index 1e5ec95e19aca0530c141b6415fe6daca4f2d066..da5e660860a46227c59567f6458a9cf4 static Map getEnchantments(net.minecraft.world.item.ItemStack item) { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 78029398774f1060e3522e4613259be894d68c22..9823ddae9edb40be805332ca1ef4325f9c1df14b 100644 +index 69f71bf44bbc66a38a877c660c8dbc493a0a8327..82cfd1354929f415c74132b7e2bbbfabd9f18758 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -6,6 +6,7 @@ import com.google.common.collect.ImmutableList; diff --git a/patches/server/0076-Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch b/patches/server/0076-Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch index b11ae54fff..639ad2fd23 100644 --- a/patches/server/0076-Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch +++ b/patches/server/0076-Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch @@ -103,7 +103,7 @@ index 58048d90a66cf3291a31d7c1f13ae66eac04ed64..8775163c42d639516a533559eaf312ee - int k = pos.getZ(); + return this.getBlockStateFinal(pos.getX(), pos.getY(), pos.getZ()); + } -+ + + @Override + public BlockState getBlockState(final int x, final int y, final int z) { + return this.getBlockStateFinal(x, y, z); @@ -116,7 +116,7 @@ index 58048d90a66cf3291a31d7c1f13ae66eac04ed64..8775163c42d639516a533559eaf312ee + } + // Inlined ChunkSection.getType() and DataPaletteBlock.a(int,int,int) + return this.sections[i].states.get((y & 15) << 8 | (z & 15) << 4 | x & 15); - ++ + } + + public BlockState getBlockState_unused(int i, int j, int k) { diff --git a/patches/server/0083-Add-PlayerUseUnknownEntityEvent.patch b/patches/server/0083-Add-PlayerUseUnknownEntityEvent.patch index 0535488630..561ff802a2 100644 --- a/patches/server/0083-Add-PlayerUseUnknownEntityEvent.patch +++ b/patches/server/0083-Add-PlayerUseUnknownEntityEvent.patch @@ -22,10 +22,10 @@ index a5d57cc862036012d83b090bb1b3ccf4115a88b3..21068f766b75c414d5818073b7dca083 static final ServerboundInteractPacket.Action ATTACK_ACTION = new ServerboundInteractPacket.Action() { @Override diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index f5b8da00f641a401d7ff4641908dd7de55cbe683..76f7ddbbba4be5c31d70ce9af9e041e69ee31662 100644 +index cf905220ac5bbce62e5e061f0dfc96906fc29328..dfff872200195b90c51b05188b4a3c53e799249d 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2534,8 +2534,37 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2534,9 +2534,38 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic }); } } @@ -48,8 +48,8 @@ index f5b8da00f641a401d7ff4641908dd7de55cbe683..76f7ddbbba4be5c31d70ce9af9e041e6 + } + }); + } -+ -+ } + + } + private void callPlayerUseUnknownEntityEvent(ServerboundInteractPacket packet, InteractionHand hand) { + this.cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent( @@ -58,8 +58,9 @@ index f5b8da00f641a401d7ff4641908dd7de55cbe683..76f7ddbbba4be5c31d70ce9af9e041e6 + packet.getActionType() == ServerboundInteractPacket.ActionType.ATTACK, + hand == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND + )); - } ++ } + // Paper end - ++ @Override public void handleClientCommand(ServerboundClientCommandPacket packet) { + PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); diff --git a/patches/server/0129-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server/0129-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch index 04019fdf60..a4848f8a17 100644 --- a/patches/server/0129-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ b/patches/server/0129-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -32,7 +32,7 @@ index 5a79b49e321cba352d8e4189dfbfdd0506ec3e5a..f9488311524bb8ff8a5686763973c9ae + public java.util.UUID sourceEntityId; + public java.util.UUID triggerEntityId; + public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN; -+ + + private void loadPaperNBT(CompoundTag nbttagcompound) { + if (!nbttagcompound.contains("Paper.ExpData", 10)) { // 10 = compound + return; @@ -66,7 +66,7 @@ index 5a79b49e321cba352d8e4189dfbfdd0506ec3e5a..f9488311524bb8ff8a5686763973c9ae + } + nbttagcompound.put("Paper.ExpData", comp); + } - ++ + @io.papermc.paper.annotation.DoNotUse + @Deprecated public ExperienceOrb(Level world, double x, double y, double z, int amount) { @@ -131,7 +131,7 @@ index 5a79b49e321cba352d8e4189dfbfdd0506ec3e5a..f9488311524bb8ff8a5686763973c9ae @Override diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index d0d38e39010ba3398a0b8960bc674c39d9a9ff51..e004dffee9f1efe44c78f9b2e938b98cc4b2b847 100644 +index 46701f9c30c5b85b49311ad15da7e1fe2993c789..08087527293c5137af078fa17b6c0f219eab15d0 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -1716,7 +1716,8 @@ public abstract class LivingEntity extends Entity implements Attackable { diff --git a/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch b/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch index 54d45acd92..c77004f048 100644 --- a/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch +++ b/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch @@ -30,7 +30,7 @@ will have plugins and worlds saving to the disk has a high potential to result in corruption/dataloss. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index e7b8e53a8709babb147a1ee3f375e96638f425a4..24f9d7314ab6c70fec42150e6065a7546c5de828 100644 +index 776f7a27c4e85e713863f8fd0d37fc61e2bb0e49..b248a4ab47728c078dbc922896964e0e893fc255 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -236,6 +236,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop) MinecraftServer.getServer().getPlayerList().players ) - { @@ -130,6 +116,73 @@ index 94d8ba376cd1f024b244654cac9bb62bb19e3060..a142a56a920e153ed84c08cece993f10 - } - // Close the socket so we can rebind with the new process - MinecraftServer.getServer().getConnection().stop(); +- +- // Give time for it to kick in +- try +- { +- Thread.sleep( 100 ); +- } catch ( InterruptedException ex ) +- { +- } +- +- // Actually shutdown +- try +- { +- MinecraftServer.getServer().close(); +- } catch ( Throwable t ) +- { +- } +- +- // This will be done AFTER the server has completely halted +- Thread shutdownHook = new Thread() +- { +- @Override +- public void run() +- { +- try +- { +- String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); +- if ( os.contains( "win" ) ) +- { +- Runtime.getRuntime().exec( "cmd /c start " + restartScript ); +- } else +- { +- Runtime.getRuntime().exec( "sh " + restartScript ); +- } +- } catch ( Exception e ) +- { +- e.printStackTrace(); +- } +- } +- }; +- +- shutdownHook.setDaemon( true ); +- Runtime.getRuntime().addShutdownHook( shutdownHook ); ++ System.out.println( "Attempting to restart with " + SpigotConfig.restartScript ); + } else + { + System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); +- +- // Actually shutdown +- try +- { +- MinecraftServer.getServer().close(); +- } catch ( Throwable t ) +- { +- } + } +- System.exit( 0 ); ++ // Stop the watchdog ++ WatchdogThread.doStop(); ++ ++ shutdownServer( isRestarting ); ++ // Paper end + } catch ( Exception ex ) + { + ex.printStackTrace(); + } + } ++ + // Paper start - sync copied from above with minor changes, async added + private static void shutdownServer(boolean isRestarting) + { @@ -147,23 +200,9 @@ index 94d8ba376cd1f024b244654cac9bb62bb19e3060..a142a56a920e153ed84c08cece993f10 + } catch ( InterruptedException ex ) + { + } - -- // Give time for it to kick in -- try -- { -- Thread.sleep( 100 ); -- } catch ( InterruptedException ex ) -- { -- } ++ + closeSocket(); - -- // Actually shutdown -- try -- { -- MinecraftServer.getServer().close(); -- } catch ( Throwable t ) -- { -- } ++ + // Actually shutdown + try + { @@ -174,9 +213,7 @@ index 94d8ba376cd1f024b244654cac9bb62bb19e3060..a142a56a920e153ed84c08cece993f10 + + // Actually stop the JVM + System.exit( 0 ); - -- // This will be done AFTER the server has completely halted -- Thread shutdownHook = new Thread() ++ + } else + { + // Mark the server to shutdown at the end of the tick @@ -228,63 +265,32 @@ index 94d8ba376cd1f024b244654cac9bb62bb19e3060..a142a56a920e153ed84c08cece993f10 + { + @Override + public void run() - { -- @Override -- public void run() ++ { + try - { -- try ++ { + String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); + if ( os.contains( "win" ) ) - { -- String os = System.getProperty( "os.name" ).toLowerCase(java.util.Locale.ENGLISH); -- if ( os.contains( "win" ) ) -- { -- Runtime.getRuntime().exec( "cmd /c start " + restartScript ); -- } else -- { -- Runtime.getRuntime().exec( "sh " + restartScript ); -- } -- } catch ( Exception e ) ++ { + Runtime.getRuntime().exec( "cmd /c start " + restartScript ); + } else - { -- e.printStackTrace(); ++ { + Runtime.getRuntime().exec( "sh " + restartScript ); - } ++ } + } catch ( Exception e ) + { + e.printStackTrace(); - } -- }; -- -- shutdownHook.setDaemon( true ); -- Runtime.getRuntime().addShutdownHook( shutdownHook ); -- } else -- { -- System.out.println( "Startup script '" + SpigotConfig.restartScript + "' does not exist! Stopping server." ); -- -- // Actually shutdown -- try -- { -- MinecraftServer.getServer().close(); -- } catch ( Throwable t ) -- { - } -- } -- System.exit( 0 ); -- } catch ( Exception ex ) ++ } ++ } + }; + + shutdownHook.setDaemon( true ); + Runtime.getRuntime().addShutdownHook( shutdownHook ); + return true; + } else - { -- ex.printStackTrace(); ++ { + return false; - } - } ++ } ++ } + // Paper end + } diff --git a/patches/server/0136-Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/0136-Use-TerminalConsoleAppender-for-console-improvements.patch index f21944e06d..be01e4e5a8 100644 --- a/patches/server/0136-Use-TerminalConsoleAppender-for-console-improvements.patch +++ b/patches/server/0136-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -262,7 +262,7 @@ index 3aabd7aaad60c157740d12932d0cb071ae259c21..8aaba38c7f4dc17c8536a0049be8bdea @Override public PluginCommand getPluginCommand(String name) { diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 34dc3555dbff9942a3ee39b27da44831f280b5a8..a736afdd6671ad36157d1d0c908b6ccb37f602b6 100644 +index 288b3afe6c7e0c93234f43f864e37d167500dd0e..ebf561bce1b442f2b3a138d4ba0ed252e4ba3207 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -13,7 +13,6 @@ import java.util.logging.Logger; @@ -397,8 +397,9 @@ index 0b4c62387c1093652ac15b64a8703249de4cf088..b996fde481cebbbcce80a6c267591136 if (offers == null) { - return cursor; + return; // Paper - Method returns void -+ } -+ + } +- candidates.addAll(offers); + + // Paper start - JLine update + for (String completion : offers) { + if (completion.isEmpty()) { @@ -406,10 +407,9 @@ index 0b4c62387c1093652ac15b64a8703249de4cf088..b996fde481cebbbcce80a6c267591136 + } + + candidates.add(new Candidate(completion)); - } -- candidates.addAll(offers); ++ } + // Paper end - ++ + // Paper start - JLine handles cursor now + /* final int lastSpace = buffer.lastIndexOf(' '); diff --git a/patches/server/0169-AsyncTabCompleteEvent.patch b/patches/server/0169-AsyncTabCompleteEvent.patch index 544db3c891..f970025162 100644 --- a/patches/server/0169-AsyncTabCompleteEvent.patch +++ b/patches/server/0169-AsyncTabCompleteEvent.patch @@ -49,12 +49,6 @@ index bc72f5380c49c0d389e53d270165d4108a3bb901..ec1aa8d5fbfdafc35948a04f4d8d65e8 if (stringreader.canRead() && stringreader.peek() == '/') { stringreader.skip(); } -- -- ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); -- -- this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { -- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer -- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); + final String command = packet.getCommand(); + final com.destroystokyo.paper.event.server.AsyncTabCompleteEvent event = new com.destroystokyo.paper.event.server.AsyncTabCompleteEvent(this.getCraftPlayer(), command, true, null); + event.callEvent(); @@ -62,10 +56,14 @@ index bc72f5380c49c0d389e53d270165d4108a3bb901..ec1aa8d5fbfdafc35948a04f4d8d65e8 + // If the event isn't handled, we can assume that we have no completions, and so we'll ask the server + if (!event.isHandled()) { + if (!event.isCancelled()) { -+ + +- ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); + this.server.scheduleOnMain(() -> { // This needs to be on main + ParseResults parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack()); -+ + +- this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { +- if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer +- this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); + this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> { + if (suggestions.isEmpty()) return; // CraftBukkit - don't send through empty suggestions - prevents [] from showing for plugins with nothing more to offer + this.connection.send(new ClientboundCommandSuggestionsPacket(packet.getId(), suggestions)); diff --git a/patches/server/0184-Player.setPlayerProfile-API.patch b/patches/server/0184-Player.setPlayerProfile-API.patch index 2059d2c9c4..b2cdc45aef 100644 --- a/patches/server/0184-Player.setPlayerProfile-API.patch +++ b/patches/server/0184-Player.setPlayerProfile-API.patch @@ -55,7 +55,7 @@ index e7442952ef1f03969949014492a7ddc6d0796ba5..69a1852905dd4724c30ac8ab88c14251 public Server getServer() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index a1ab7a666e429f0ac9afc1bd8a65866364655b70..2dd0e3272587697b52f75e851f26bb818f25c6aa 100644 +index 39ecd1161b2f2636197eaa157a765cfe5d6f6405..5b2322389c2c2f5277a8891c857ba04f8d347e4d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -82,6 +82,7 @@ import net.minecraft.world.entity.ai.attributes.Attributes; @@ -127,11 +127,11 @@ index a1ab7a666e429f0ac9afc1bd8a65866364655b70..2dd0e3272587697b52f75e851f26bb81 + bukkitPlayer.unregisterEntity(self); + } + } -+ -+ // Set the game profile here, we should have unregistered the entity via iterating all player entities above. -+ self.gameProfile = gameProfile; - server.getPluginManager().callEvent(new PlayerShowEntityEvent(this, entity)); ++ // Set the game profile here, we should have unregistered the entity via iterating all player entities above. ++ self.gameProfile = gameProfile; ++ + // Re-register the game profile for all players + for (ServerPlayer player : players) { + CraftPlayer bukkitPlayer = player.getBukkitEntity(); diff --git a/patches/server/0255-Improve-death-events.patch b/patches/server/0255-Improve-death-events.patch index dccd479d40..f39017892c 100644 --- a/patches/server/0255-Improve-death-events.patch +++ b/patches/server/0255-Improve-death-events.patch @@ -70,7 +70,7 @@ index dad0368c8b55be018167bd8b113a80b7508647f1..77a74d41679e88d748d903295ac4f455 } } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index d29519bd75e6e5a97b06aae86c485b49c4415fb8..73cefc7ec582cb0fbfcff32cb9311f34ec2f31f0 100644 +index 7c0e1963383a1a2862930cf77844e5c8c80e70e3..4c1992bcffd629ef53f14c5a0146eab2ddcb563c 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -258,6 +258,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -119,8 +119,13 @@ index d29519bd75e6e5a97b06aae86c485b49c4415fb8..73cefc7ec582cb0fbfcff32cb9311f34 + // Paper - moved into if below if (this.level instanceof ServerLevel) { - if (entity == null || entity.wasKilled((ServerLevel) this.level, this)) { +- this.gameEvent(GameEvent.ENTITY_DIE); +- this.dropAllDeathLoot(damageSource); +- this.createWitherRose(entityliving); +- } + // Paper - move below into if for onKill -+ + +- this.level.broadcastEntityEvent(this, (byte) 3); + // Paper start + org.bukkit.event.entity.EntityDeathEvent deathEvent = this.dropAllDeathLoot(damageSource); + if (deathEvent == null || !deathEvent.isCancelled()) { @@ -148,15 +153,11 @@ index d29519bd75e6e5a97b06aae86c485b49c4415fb8..73cefc7ec582cb0fbfcff32cb9311f34 + if (entity != null) { + entity.wasKilled((ServerLevel) this.level, this); + } - this.gameEvent(GameEvent.ENTITY_DIE); -- this.dropAllDeathLoot(damageSource); -- this.createWitherRose(entityliving); ++ this.gameEvent(GameEvent.ENTITY_DIE); + } else { + this.dead = false; + this.setHealth((float) deathEvent.getReviveHealth()); - } -- -- this.level.broadcastEntityEvent(this, (byte) 3); ++ } + // Paper end + this.createWitherRose(entityliving); } @@ -220,7 +221,7 @@ index d29519bd75e6e5a97b06aae86c485b49c4415fb8..73cefc7ec582cb0fbfcff32cb9311f34 // CraftBukkit start public int getExpReward() { diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java -index e818687adf432e7ff47c8442ed2ea32d41c06b64..60d833bf8b7dcee046da9712a2dc809b05a31b42 100644 +index 984a33d5e1f790a9c78ba57f2dc21fb072a44b3d..dbf442e9686e59723ed0456f97e472cc663f8cc7 100644 --- a/src/main/java/net/minecraft/world/entity/Mob.java +++ b/src/main/java/net/minecraft/world/entity/Mob.java @@ -1065,7 +1065,13 @@ public abstract class Mob extends LivingEntity implements Targeting { @@ -352,7 +353,7 @@ index e38cbdff34479673f1640c46d727f1a807a609c7..dbb4bfb3d1f1ce2e435ca531be36ea44 this.gameEvent(GameEvent.ENTITY_DIE); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 2d704af9491bec382e00a40fde36c6e01c8484f2..e3239cfb4237163389313f88496ad5e69b891c86 100644 +index 6b1b1b49b1b070dab106e9712d66c3916f0a7797..3a4a1f32409d7dddd30a643017da9bc6f6694187 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -2262,7 +2262,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -372,7 +373,7 @@ index 2d704af9491bec382e00a40fde36c6e01c8484f2..e3239cfb4237163389313f88496ad5e6 public void injectScaledMaxHealth(Collection collection, boolean force) { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index c24e84e07f3f0d93da079ddf73e0e67b7d58fe8b..bdd4572489cd12ea19560fe82006e3fe4db29b50 100644 +index ea385119db05699e355411e779f4464067f923f1..ea83f115d96302731ee7576b682bee95259422de 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -806,9 +806,16 @@ public class CraftEventFactory { diff --git a/patches/server/0259-Prevent-chunk-loading-from-Fluid-Flowing.patch b/patches/server/0259-Prevent-chunk-loading-from-Fluid-Flowing.patch index 261d06e792..b182635d6d 100644 --- a/patches/server/0259-Prevent-chunk-loading-from-Fluid-Flowing.patch +++ b/patches/server/0259-Prevent-chunk-loading-from-Fluid-Flowing.patch @@ -58,15 +58,14 @@ index f809a19afdfdb7df439e907531f54b2df1baf08c..00516a230073391b31795ec5af2aa7aa short short0 = FlowingFluid.getCacheKey(pos, blockposition1); - Pair pair = (Pair) short2objectmap.computeIfAbsent(short0, (short1) -> { - BlockState iblockdata1 = world.getBlockState(blockposition1); -- -- return Pair.of(iblockdata1, iblockdata1.getFluidState()); -- }); + // Paper start + Pair pair = (Pair) short2objectmap.get(short0); + if (pair == null) { + BlockState iblockdatax = world.getBlockStateIfLoaded(blockposition1); + if (iblockdatax == null) continue; -+ + +- return Pair.of(iblockdata1, iblockdata1.getFluidState()); +- }); + pair = Pair.of(iblockdatax, iblockdatax.getFluidState()); + short2objectmap.put(short0, pair); + } diff --git a/patches/server/0273-Add-more-Witch-API.patch b/patches/server/0273-Add-more-Witch-API.patch index a470414cc9..3f836289e0 100644 --- a/patches/server/0273-Add-more-Witch-API.patch +++ b/patches/server/0273-Add-more-Witch-API.patch @@ -39,9 +39,9 @@ index abbb077281eb8fc7961cf97ff23bb9822f2727f0..096546d7a97f031060bda7545aa620d5 - if (!this.isSilent()) { - this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); - } -- -- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); +- AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); +- - attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING); - attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); } diff --git a/patches/server/0301-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/0301-Optimize-Network-Manager-and-add-advanced-packet-sup.patch index f7ccd1df96..ca1dd6295c 100644 --- a/patches/server/0301-Optimize-Network-Manager-and-add-advanced-packet-sup.patch +++ b/patches/server/0301-Optimize-Network-Manager-and-add-advanced-packet-sup.patch @@ -107,21 +107,22 @@ index 62ee5e32ac0f5d244fa55f9fe45d34cf4d2becaa..184f36a137ed5e5cd20797e131801bc2 public void send(Packet packet, @Nullable PacketSendListener callbacks) { - if (this.isConnected()) { - this.flushQueue(); +- this.sendPacket(packet, callbacks); +- } else { +- this.queue.add(new Connection.PacketHolder(packet, callbacks)); + // Paper start - handle oversized packets better + boolean connected = this.isConnected(); + if (!connected && !preparing) { + return; // Do nothing -+ } + } + packet.onPacketDispatch(getPlayer()); + if (connected && (InnerUtil.canSendImmediate(this, packet) || ( + io.papermc.paper.util.MCUtil.isMainThread() && packet.isReady() && this.queue.isEmpty() && + (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty()) + ))) { - this.sendPacket(packet, callbacks); -- } else { -- this.queue.add(new Connection.PacketHolder(packet, callbacks)); ++ this.sendPacket(packet, callbacks); + return; - } ++ } + // write the packets to the queue, then flush - antixray hooks there already + java.util.List extraPackets = InnerUtil.buildExtraPackets(packet); + boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty(); @@ -184,6 +185,10 @@ index 62ee5e32ac0f5d244fa55f9fe45d34cf4d2becaa..184f36a137ed5e5cd20797e131801bc2 } - private void flushQueue() { +- try { // Paper - add pending task queue +- if (this.channel != null && this.channel.isOpen()) { +- Queue queue = this.queue; +- + // Paper start - rewrite this to be safer if ran off main thread + private boolean flushQueue() { // void -> boolean + if (!isConnected()) { @@ -193,16 +198,20 @@ index 62ee5e32ac0f5d244fa55f9fe45d34cf4d2becaa..184f36a137ed5e5cd20797e131801bc2 + return processQueue(); + } else if (isPending) { + // Should only happen during login/status stages -+ synchronized (this.queue) { + synchronized (this.queue) { +- Connection.PacketHolder networkmanager_queuedpacket; +- +- while ((networkmanager_queuedpacket = (Connection.PacketHolder) this.queue.poll()) != null) { +- this.sendPacket(networkmanager_queuedpacket.packet, networkmanager_queuedpacket.listener); +- } +- + return this.processQueue(); -+ } -+ } + } + } + return false; + } + private boolean processQueue() { - try { // Paper - add pending task queue -- if (this.channel != null && this.channel.isOpen()) { -- Queue queue = this.queue; ++ try { // Paper - add pending task queue + if (this.queue.isEmpty()) return true; + // If we are on main, we are safe here in that nothing else should be processing queue off main anymore + // But if we are not on main due to login/status, the parent is synchronized on packetQueue @@ -214,17 +223,13 @@ index 62ee5e32ac0f5d244fa55f9fe45d34cf4d2becaa..184f36a137ed5e5cd20797e131801bc2 + if (queued == null) { + return true; + } - -- synchronized (this.queue) { -- Connection.PacketHolder networkmanager_queuedpacket; ++ + // Paper start - checking isConsumed flag and skipping packet sending + if (queued.isConsumed()) { + continue; + } + // Paper end - checking isConsumed flag and skipping packet sending - -- while ((networkmanager_queuedpacket = (Connection.PacketHolder) this.queue.poll()) != null) { -- this.sendPacket(networkmanager_queuedpacket.packet, networkmanager_queuedpacket.listener); ++ + Packet packet = queued.packet; + if (!packet.isReady()) { + return false; @@ -232,10 +237,9 @@ index 62ee5e32ac0f5d244fa55f9fe45d34cf4d2becaa..184f36a137ed5e5cd20797e131801bc2 + iterator.remove(); + if (queued.tryMarkConsumed()) { // Paper - try to mark isConsumed flag for de-duplicating packet + this.sendPacket(packet, queued.listener); - } -- - } - } ++ } ++ } ++ } + return true; } finally { // Paper start - add pending task queue Runnable r; diff --git a/patches/server/0316-Configurable-Keep-Spawn-Loaded-range-per-world.patch b/patches/server/0316-Configurable-Keep-Spawn-Loaded-range-per-world.patch index 42e4e59213..baa4080537 100644 --- a/patches/server/0316-Configurable-Keep-Spawn-Loaded-range-per-world.patch +++ b/patches/server/0316-Configurable-Keep-Spawn-Loaded-range-per-world.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Configurable Keep Spawn Loaded range per world This lets you disable it for some worlds and lower it for others. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 9d2186655ae03022ddeaf078028570ef9118fb06..fe8c0ba8864afd582c5e1c9d310cff99ef4dbff6 100644 +index cbac51a99885f963feede3563b6b2714a4096022..f62cbd8eddee7ea6997797271ce37d31b8dd3aaa 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -739,31 +739,34 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { + this.setUnhappyCounter(this.getUnhappyCounter() - 1); -+ } + } + if (this.isEffectiveAi()) { + if (level.spigotConfig.tickInactiveVillagers) { + this.customServerAiStep(); + } else { + this.mobTick(true); + } - } ++ } + maybeDecayGossip(); + // Paper end + @@ -569,12 +569,16 @@ index 08bf9f85fe02a3f89640a2f3ae23089a119a394a..f158fc8a151272428a33dc5f6e174287 - public static boolean checkEntityImmunities(Entity entity) + public static int checkEntityImmunities(Entity entity) // Paper - return # of ticks to get immunity { +- // quick checks. +- if ( entity.wasTouchingWater || entity.remainingFireTicks > 0 ) +- { +- return true; + // Paper start + SpigotWorldConfig config = entity.level.spigotConfig; + int inactiveWakeUpImmunity = checkInactiveWakeup(entity); + if (inactiveWakeUpImmunity > -1) { + return inactiveWakeUpImmunity; -+ } + } + if (entity.remainingFireTicks > 0) { + return 2; + } @@ -583,18 +587,16 @@ index 08bf9f85fe02a3f89640a2f3ae23089a119a394a..f158fc8a151272428a33dc5f6e174287 + } + long inactiveFor = MinecraftServer.currentTick - entity.activatedTick; + // Paper end - // quick checks. -- if ( entity.wasTouchingWater || entity.remainingFireTicks > 0 ) ++ // quick checks. + if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByFluid()) ) // Paper - { -- return true; ++ { + return 100; // Paper + } + // Paper start + if ( !entity.isOnGround() || entity.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D ) + { + return 100; - } ++ } + // Paper end if ( !( entity instanceof AbstractArrow ) ) { @@ -624,7 +626,8 @@ index 08bf9f85fe02a3f89640a2f3ae23089a119a394a..f158fc8a151272428a33dc5f6e174287 { - return true; + return 20; // Paper -+ } + } +- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) + // Paper start + if (entity instanceof Bee) { + Bee bee = (Bee)entity; @@ -652,8 +655,7 @@ index 08bf9f85fe02a3f89640a2f3ae23089a119a394a..f158fc8a151272428a33dc5f6e174287 + return config.villagersWorkImmunityFor; + } + } - } -- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) ++ } + if ( entity instanceof Llama && ( (Llama) entity ).inCaravan() ) { - return true; @@ -677,11 +679,11 @@ index 08bf9f85fe02a3f89640a2f3ae23089a119a394a..f158fc8a151272428a33dc5f6e174287 if (entity instanceof Creeper && ((Creeper) entity).isIgnited()) { // isExplosive - return true; + return 20; // Paper -+ } + } + // Paper start + if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) { + return 0; - } ++ } + if (entity instanceof Pillager) { + Pillager pillager = (Pillager) entity; + // TODO:? diff --git a/patches/server/0343-Anti-Xray.patch b/patches/server/0343-Anti-Xray.patch index 37c6097afd..ae1500005f 100644 --- a/patches/server/0343-Anti-Xray.patch +++ b/patches/server/0343-Anti-Xray.patch @@ -1367,7 +1367,7 @@ index cd82985b0aa821dccc0484f328407381d58ec81f..34804dc42c7a18108126c14c1b5f3d5a this.strategy = paletteProvider; this.registry = idList; this.data = this.createOrReuseData((PalettedContainer.Data)null, 0); -@@ -92,11 +131,33 @@ public class PalettedContainer implements PaletteResize, PalettedContainer +@@ -92,12 +131,34 @@ public class PalettedContainer implements PaletteResize, PalettedContainer @Override public int onResize(int newBits, T object) { PalettedContainer.Data data = this.data; @@ -1388,8 +1388,8 @@ index cd82985b0aa821dccc0484f328407381d58ec81f..34804dc42c7a18108126c14c1b5f3d5a + this.addPresetValues(); + return object == null ? -1 : data2.palette.idFor(object); + // Paper end -+ } -+ + } + + // Paper start - Anti-Xray - Add preset values + private void addPresetValues() { + if (this.presetValues != null && this.data.configuration().factory() != PalettedContainer.Strategy.GLOBAL_PALETTE_FACTORY) { @@ -1397,11 +1397,12 @@ index cd82985b0aa821dccc0484f328407381d58ec81f..34804dc42c7a18108126c14c1b5f3d5a + this.data.palette.idFor(presetValue); + } + } - } ++ } + // Paper end - ++ public T getAndSet(int x, int y, int z, T value) { this.acquire(); + @@ -166,25 +227,36 @@ public class PalettedContainer implements PaletteResize, PalettedContainer data.palette.read(buf); buf.readLongArray(data.storage.getRaw()); @@ -1414,10 +1415,10 @@ index cd82985b0aa821dccc0484f328407381d58ec81f..34804dc42c7a18108126c14c1b5f3d5a } + // Paper start - Anti-Xray - Add chunk packet info -+ @Override -+ @Deprecated @io.papermc.paper.annotation.DoNotUse public void write(FriendlyByteBuf buf) { this.write(buf, null, 0); } @Override - public void write(FriendlyByteBuf buf) { ++ @Deprecated @io.papermc.paper.annotation.DoNotUse public void write(FriendlyByteBuf buf) { this.write(buf, null, 0); } ++ @Override + public void write(FriendlyByteBuf buf, @Nullable com.destroystokyo.paper.antixray.ChunkPacketInfo chunkPacketInfo, int bottomBlockY) { this.acquire(); diff --git a/patches/server/0366-Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/0366-Pillager-patrol-spawn-settings-and-per-player-option.patch index 87975fb3cb..7d052fc8c8 100644 --- a/patches/server/0366-Pillager-patrol-spawn-settings-and-per-player-option.patch +++ b/patches/server/0366-Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -44,7 +44,7 @@ index e5918fa3be107ac3a2fc8831fd78733a7506730a..a908652f1ebb426d265ef614746f70cd + // Random player selection moved up for per player spawning and configuration + int j = world.players().size(); + if (j < 1) { - return 0; ++ return 0; + } + + net.minecraft.server.level.ServerPlayer entityhuman = world.players().get(randomsource.nextInt(j)); @@ -56,16 +56,16 @@ index e5918fa3be107ac3a2fc8831fd78733a7506730a..a908652f1ebb426d265ef614746f70cd + if (world.paperConfig().entities.behavior.pillagerPatrols.spawnDelay.perPlayer) { + --entityhuman.patrolSpawnDelay; + patrolSpawnDelay = entityhuman.patrolSpawnDelay; - } else { -- this.nextTick += 12000 + randomsource.nextInt(1200); -- long i = world.getDayTime() / 24000L; ++ } else { + this.nextTick--; + patrolSpawnDelay = this.nextTick; + } + + if (patrolSpawnDelay > 0) { -+ return 0; -+ } else { + return 0; + } else { +- this.nextTick += 12000 + randomsource.nextInt(1200); +- long i = world.getDayTime() / 24000L; + long days; + if (world.paperConfig().entities.behavior.pillagerPatrols.start.perPlayer) { + days = entityhuman.getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.PLAY_TIME)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang diff --git a/patches/server/0374-Optimize-GoalSelector-Goal.Flag-Set-operations.patch b/patches/server/0374-Optimize-GoalSelector-Goal.Flag-Set-operations.patch index 70dff6f0dc..a07de75eb9 100644 --- a/patches/server/0374-Optimize-GoalSelector-Goal.Flag-Set-operations.patch +++ b/patches/server/0374-Optimize-GoalSelector-Goal.Flag-Set-operations.patch @@ -74,26 +74,27 @@ index e5995d0db5dcfba59a873ff439601894fdacd556..b738ee2d3801fadfd09313f05ae24593 - this.availableGoals.removeIf((wrappedGoal) -> { - return wrappedGoal.getGoal() == goal; - }); -- } -- -- private static boolean goalContainsAnyFlags(WrappedGoal goal, EnumSet controls) { -- for(Goal.Flag flag : goal.getFlags()) { -- if (controls.contains(flag)) { -- return true; + // Paper start - remove streams from pathfindergoalselector + for (java.util.Iterator iterator = this.availableGoals.iterator(); iterator.hasNext();) { + WrappedGoal goalWrapped = iterator.next(); + if (goalWrapped.getGoal() != goal) { + continue; - } ++ } + if (goalWrapped.isRunning()) { + goalWrapped.stop(); + } + iterator.remove(); - } ++ } + // Paper end - remove streams from pathfindergoalselector -+ } + } +- private static boolean goalContainsAnyFlags(WrappedGoal goal, EnumSet controls) { +- for(Goal.Flag flag : goal.getFlags()) { +- if (controls.contains(flag)) { +- return true; +- } +- } +- - return false; + private static boolean goalContainsAnyFlags(WrappedGoal goal, com.destroystokyo.paper.util.set.OptimizedSmallEnumSet controls) { + return goal.getFlags().hasCommonElements(controls); // Paper diff --git a/patches/server/0375-Improved-Watchdog-Support.patch b/patches/server/0375-Improved-Watchdog-Support.patch index 09a4fddb2c..67ad90d931 100644 --- a/patches/server/0375-Improved-Watchdog-Support.patch +++ b/patches/server/0375-Improved-Watchdog-Support.patch @@ -318,7 +318,7 @@ index 39defceb694875322b3433a3ad4bb16256413ea8..86f19b7ed15c2029c5483f21b44895d8 final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ()); net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 8b03be6babe3052ab351061c0c206c84e26ef705..7f85bc8e8a666a32e392fa57418bf0d479e758d0 100644 +index 7a0adf528be779241759d1efd818b0e57454a258..d7a98afeadc090281fdb24b27619536f318c2383 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -178,6 +178,36 @@ public class Main { @@ -358,7 +358,7 @@ index 8b03be6babe3052ab351061c0c206c84e26ef705..7f85bc8e8a666a32e392fa57418bf0d4 try { options = parser.parse(args); } catch (joptsimple.OptionException ex) { -@@ -273,8 +303,64 @@ public class Main { +@@ -273,9 +303,65 @@ public class Main { } catch (Throwable t) { t.printStackTrace(); } @@ -405,9 +405,9 @@ index 8b03be6babe3052ab351061c0c206c84e26ef705..7f85bc8e8a666a32e392fa57418bf0d4 + tryPreloadClass(net.minecraft.world.level.lighting.LayerLightEventListener.class.getName()); + tryPreloadClass(net.minecraft.util.ExceptionCollector.class.getName()); + // Paper end -+ } -+ } -+ + } + } + + // Paper start + private static void tryPreloadClass(String className) { + tryPreloadClass(className, true); @@ -417,12 +417,13 @@ index 8b03be6babe3052ab351061c0c206c84e26ef705..7f85bc8e8a666a32e392fa57418bf0d4 + Class.forName(className); + } catch (ClassNotFoundException e) { + if (printError) System.err.println("An expected class " + className + " was not found for preloading: " + e.getMessage()); - } - } ++ } ++ } + // Paper end - ++ private static List asList(String... params) { return Arrays.asList(params); + } diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java index b4a19d80bbf71591f25729fd0e98590350cb31d0..e948ec5a573b22645664eb53bc3e9932246544e4 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java diff --git a/patches/server/0411-Optimize-anyPlayerCloseEnoughForSpawning-to-use-dist.patch b/patches/server/0411-Optimize-anyPlayerCloseEnoughForSpawning-to-use-dist.patch index 832016ceb0..02e1d99f3b 100644 --- a/patches/server/0411-Optimize-anyPlayerCloseEnoughForSpawning-to-use-dist.patch +++ b/patches/server/0411-Optimize-anyPlayerCloseEnoughForSpawning-to-use-dist.patch @@ -136,17 +136,17 @@ index 1c638f65d33e5890a7a32bf7e89d484ae2afc093..4b7c39595302a738e6d4a1749473ef9c - int chunkRange = level.spigotConfig.mobSpawnRange; - chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange; - chunkRange = (chunkRange > 8) ? 8 : chunkRange; -- -- final int finalChunkRange = chunkRange; // Paper for lambda below -- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event -- double blockRange = 16384.0D; // Paper -- // Spigot end -- long i = chunkcoordintpair.toLong(); + // Paper start - optimise anyPlayerCloseEnoughForSpawning + final boolean anyPlayerCloseEnoughForSpawning(ChunkPos chunkcoordintpair, boolean reducedRange) { + return this.anyPlayerCloseEnoughForSpawning(this.getUpdatingChunkIfPresent(chunkcoordintpair.toLong()), chunkcoordintpair, reducedRange); + } +- final int finalChunkRange = chunkRange; // Paper for lambda below +- //double blockRange = (reducedRange) ? Math.pow(chunkRange << 4, 2) : 16384.0D; // Paper - use from event +- double blockRange = 16384.0D; // Paper +- // Spigot end +- long i = chunkcoordintpair.toLong(); +- - if (!this.distanceManager.hasPlayersNearby(i)) { + final boolean anyPlayerCloseEnoughForSpawning(ChunkHolder playerchunk, ChunkPos chunkcoordintpair, boolean reducedRange) { + // this function is so hot that removing the map lookup call can have an order of magnitude impact on its performance @@ -158,18 +158,11 @@ index 1c638f65d33e5890a7a32bf7e89d484ae2afc093..4b7c39595302a738e6d4a1749473ef9c - Iterator iterator = this.playerMap.getPlayers(i).iterator(); - - ServerPlayer entityplayer; -+ } -+ Object[] backingSet = playersInRange.getBackingSet(); - +- - do { - if (!iterator.hasNext()) { - return false; -+ if (reducedRange) { -+ for (int i = 0, len = backingSet.length; i < len; ++i) { -+ Object raw = backingSet[i]; -+ if (!(raw instanceof ServerPlayer player)) { -+ continue; - } +- } - - entityplayer = (ServerPlayer) iterator.next(); - // Paper start - add PlayerNaturallySpawnCreaturesEvent @@ -179,14 +172,24 @@ index 1c638f65d33e5890a7a32bf7e89d484ae2afc093..4b7c39595302a738e6d4a1749473ef9c - event = entityplayer.playerNaturallySpawnedEvent; - if (event == null || event.isCancelled()) return false; - blockRange = (double) ((event.getSpawnRadius() << 4) * (event.getSpawnRadius() << 4)); -+ // don't check spectator and whatnot, already handled by mob spawn map update -+ if (euclideanDistanceSquared(chunkcoordintpair, player) < player.lastEntitySpawnRadiusSquared) { -+ return true; // in range - } +- } - // Paper end - } while (!this.playerIsCloseEnoughForSpawning(entityplayer, chunkcoordintpair, blockRange)); // Spigot - - return true; + } ++ Object[] backingSet = playersInRange.getBackingSet(); ++ ++ if (reducedRange) { ++ for (int i = 0, len = backingSet.length; i < len; ++i) { ++ Object raw = backingSet[i]; ++ if (!(raw instanceof ServerPlayer player)) { ++ continue; ++ } ++ // don't check spectator and whatnot, already handled by mob spawn map update ++ if (euclideanDistanceSquared(chunkcoordintpair, player) < player.lastEntitySpawnRadiusSquared) { ++ return true; // in range ++ } + } + } else { + final double range = (DistanceManager.MOB_SPAWN_RANGE * 16) * (DistanceManager.MOB_SPAWN_RANGE * 16); @@ -201,7 +204,7 @@ index 1c638f65d33e5890a7a32bf7e89d484ae2afc093..4b7c39595302a738e6d4a1749473ef9c + return true; // in range + } + } - } ++ } + // no players in range + return false; + // Paper end - optimise anyPlayerCloseEnoughForSpawning diff --git a/patches/server/0431-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server/0431-Add-Plugin-Tickets-to-API-Chunk-Methods.patch index 19edfeafb8..7d53f27e28 100644 --- a/patches/server/0431-Add-Plugin-Tickets-to-API-Chunk-Methods.patch +++ b/patches/server/0431-Add-Plugin-Tickets-to-API-Chunk-Methods.patch @@ -22,7 +22,7 @@ wants it to collect even faster, they can restore that setting back to 1 instead Not adding it to .getType() though to keep behavior consistent with vanilla for performance reasons. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 82b594729e595bfd7011334a27bdd3e427d2f903..2f978b0c5721b0cf145d324e6c7551d8f0c1eccf 100644 +index 5b29bdd8c39bcdec81ed58b8e06ec6b6940363ab..fb98133b733b86596272609533d311633cbf9231 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -369,7 +369,7 @@ public final class CraftServer implements Server { @@ -47,7 +47,7 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/jav index efa01ad6ac0757da033f2bdf7729717239e474f2..977004b4b5a294c4eab2995777df6fb1faff4625 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -281,8 +281,21 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -281,9 +281,22 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public Chunk getChunkAt(int x, int z) { @@ -60,16 +60,17 @@ index efa01ad6ac0757da033f2bdf7729717239e474f2..977004b4b5a294c4eab2995777df6fb1 + } + return chunk.bukkitChunk; + // Paper end -+ } -+ + } + + // Paper start + private void addTicket(int x, int z) { + io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> world.getChunkSource().addRegionTicket(TicketType.PLUGIN, new ChunkPos(x, z), 0, Unit.INSTANCE)); // Paper - } ++ } + // Paper end - ++ @Override public Chunk getChunkAt(Block block) { + Preconditions.checkArgument(block != null, "null block"); @@ -349,7 +362,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { public boolean unloadChunkRequest(int x, int z) { org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot diff --git a/patches/server/0433-Stop-copy-on-write-operations-for-updating-light-dat.patch b/patches/server/0433-Stop-copy-on-write-operations-for-updating-light-dat.patch index c13f70aec1..336281d839 100644 --- a/patches/server/0433-Stop-copy-on-write-operations-for-updating-light-dat.patch +++ b/patches/server/0433-Stop-copy-on-write-operations-for-updating-light-dat.patch @@ -271,13 +271,12 @@ index 59d2af9f883541518c203302257f03dbe957aa0b..e6c857c8b4e4e65e3cf6a75ce6d844ff protected static final class SkyDataLayerStorageMap extends DataLayerStorageMap { int currentLowestY; - final Long2IntOpenHashMap topSections; -- ++ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data + - public SkyDataLayerStorageMap(Long2ObjectOpenHashMap arrays, Long2IntOpenHashMap columnToTopSection, int minSectionY) { - super(arrays); - this.topSections = columnToTopSection; - columnToTopSection.defaultReturnValue(minSectionY); -+ private final com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int otherData; // Paper - avoid copying light data -+ + // Paper start - avoid copying light data + public SkyDataLayerStorageMap(com.destroystokyo.paper.util.map.QueuedChangesMapLong2Object arrays, com.destroystokyo.paper.util.map.QueuedChangesMapLong2Int columnToTopSection, int minSectionY, boolean isVisible) { + super(arrays, isVisible); diff --git a/patches/server/0484-Fix-for-large-move-vectors-crashing-server.patch b/patches/server/0484-Fix-for-large-move-vectors-crashing-server.patch index 4b010dd3cf..7ce22dca0f 100644 --- a/patches/server/0484-Fix-for-large-move-vectors-crashing-server.patch +++ b/patches/server/0484-Fix-for-large-move-vectors-crashing-server.patch @@ -27,14 +27,13 @@ index ed16292b121aeaee5ad439176af57841281e293d..459403f9c8a784c3911d5ba163a2c90e double d8 = d5 - this.vehicleFirstGoodZ; double d9 = entity.getDeltaMovement().lengthSqr(); - double d10 = d6 * d6 + d7 * d7 + d8 * d8; -- + // Paper start - fix large move vectors killing the server + double currDeltaX = toX - fromX; + double currDeltaY = toY - fromY; + double currDeltaZ = toZ - fromZ; + double d10 = Math.max(d6 * d6 + d7 * d7 + d8 * d8, (currDeltaX * currDeltaX + currDeltaY * currDeltaY + currDeltaZ * currDeltaZ) - 1); + // Paper end - fix large move vectors killing the server -+ + + // Paper start - fix large move vectors killing the server + double otherFieldX = d3 - this.vehicleLastGoodX; + double otherFieldY = d4 - this.vehicleLastGoodY - 1.0E-6D; diff --git a/patches/server/0559-add-DragonEggFormEvent.patch b/patches/server/0559-add-DragonEggFormEvent.patch index 7e39c25a22..c617bc6250 100644 --- a/patches/server/0559-add-DragonEggFormEvent.patch +++ b/patches/server/0559-add-DragonEggFormEvent.patch @@ -25,10 +25,10 @@ index 1ee1b757b90ae0d080aa57f4186228a6f4279c1f..abd13cefd3d8409e1ef8ea70d92877f7 + //this.level.setBlockAndUpdate(this.level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, EndPodiumFeature.END_PODIUM_LOCATION), Blocks.DRAGON_EGG.defaultBlockState()); + } else { + eggEvent.setCancelled(true); -+ } + } + if (eggEvent.callEvent()) { + eggEvent.getNewState().update(true); - } ++ } + // Paper end - DragonEggFormEvent this.previouslyKilled = true; diff --git a/patches/server/0563-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server/0563-Allow-adding-items-to-BlockDropItemEvent.patch index 2c52dce1b8..606f504c05 100644 --- a/patches/server/0563-Allow-adding-items-to-BlockDropItemEvent.patch +++ b/patches/server/0563-Allow-adding-items-to-BlockDropItemEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Allow adding items to BlockDropItemEvent diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index d347b109f046ad633cb2b361fbe47e67595843f5..d39a4e21fa2da3fec535ca62028f1c5ac92e8c96 100644 +index 15b4be18064137d21565434adae97883fb0a8d6a..451fee716b07c8daadcffc9b87973a56641e8198 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -399,13 +399,30 @@ public class CraftEventFactory { @@ -31,13 +31,13 @@ index d347b109f046ad633cb2b361fbe47e67595843f5..d39a4e21fa2da3fec535ca62028f1c5a + Entity item = ((org.bukkit.craftbukkit.entity.CraftItem) bukkit).getHandle(); + item.level.addFreshEntity(item); + } -+ } + } + } else { + for (Item bukkit : list) { + if (bukkit.isValid()) { + bukkit.remove(); + } - } ++ } + // Paper end } } diff --git a/patches/server/0613-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/server/0613-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch index a0f6decc09..4ee9a0b68d 100644 --- a/patches/server/0613-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch +++ b/patches/server/0613-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch @@ -26,7 +26,7 @@ index 98a3f6388712fab9012210241b84def3aca712e2..f2094c52196b45adfd51d8aebcc4c46b if (flag) { ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); -@@ -228,7 +234,20 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo +@@ -228,8 +234,21 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo public void readAdditionalSaveData(CompoundTag nbt) { super.readAdditionalSaveData(nbt); this.reassessWeaponGoal(); @@ -35,18 +35,19 @@ index 98a3f6388712fab9012210241b84def3aca712e2..f2094c52196b45adfd51d8aebcc4c46b + this.shouldBurnInDay = nbt.getBoolean("Paper.ShouldBurnInDay"); + } + // Paper end -+ } -+ + } + + // Paper start + @Override + public void addAdditionalSaveData(CompoundTag nbt) { + super.addAdditionalSaveData(nbt); + nbt.putBoolean("Paper.ShouldBurnInDay", this.shouldBurnInDay); - } ++ } + // Paper end - ++ @Override public void setItemSlot(EquipmentSlot slot, ItemStack stack) { + super.setItemSlot(slot, stack); diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java index 0ada1ba6774e3d0514afb946fd0f104004cc020d..97fb1d2110a51498f6419841081b500b3f190370 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java diff --git a/patches/server/0616-Add-environment-variable-to-disable-server-gui.patch b/patches/server/0616-Add-environment-variable-to-disable-server-gui.patch index 33967006f9..f3894d0d5e 100644 --- a/patches/server/0616-Add-environment-variable-to-disable-server-gui.patch +++ b/patches/server/0616-Add-environment-variable-to-disable-server-gui.patch @@ -1,5 +1,5 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Riley Park +From: Riley Park Date: Mon, 17 May 2021 00:34:55 -0700 Subject: [PATCH] Add environment variable to disable server gui diff --git a/patches/server/0629-Add-PlayerKickEvent-causes.patch b/patches/server/0629-Add-PlayerKickEvent-causes.patch index 44a0dd042a..34e4efddd2 100644 --- a/patches/server/0629-Add-PlayerKickEvent-causes.patch +++ b/patches/server/0629-Add-PlayerKickEvent-causes.patch @@ -36,7 +36,7 @@ index b5f54ee82905e3e6ab5bfde35ab625f5feeb1393..c0a80824a0307ea673805015119cc834 public boolean shouldDisconnect() { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index b9ef06e2ba2e9842a0b4d66976b703918f585752..4c61e7c5e38f6d1e4e1301a5d65b57c19a3b3a58 100644 +index 1874354a04a1e7ad86f2c438c7526da94b9b9e6a..abd2ca040779e651ba01cbb6426b8c997303ccf3 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -2151,7 +2151,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoopbuilder(); + for (Advancement advancement : this.handle.getChildren()) { + children.add(advancement.bukkit); - } ++ } + return children.build(); + } - -- return new CraftAdvancementDisplay(this.handle.getDisplay()); ++ + @Override + public org.bukkit.advancement.Advancement getRoot() { + Advancement advancement = this.handle; @@ -173,7 +175,7 @@ index c47cae84f3b6970247d78382f48ae8ddbc202b59..1435251a4fb721b800e6a1f07b50c5f7 + advancement = advancement.getParent(); + } + return advancement.bukkit; - } ++ } + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementDisplay.java diff --git a/patches/server/0693-Fix-GameProfileCache-concurrency.patch b/patches/server/0693-Fix-GameProfileCache-concurrency.patch index 8c22da1dde..82ab6b35cb 100644 --- a/patches/server/0693-Fix-GameProfileCache-concurrency.patch +++ b/patches/server/0693-Fix-GameProfileCache-concurrency.patch @@ -105,15 +105,15 @@ index 2456edc11b29a92b1648937cd3dd6a9a05706803..b48650c38751a925b83fb4c19ac02f87 jsonarray.add(GameProfileCache.writeGameProfile(usercache_usercacheentry, dateformat)); }); String s = this.gson.toJson(jsonarray); -@@ -332,8 +349,19 @@ public class GameProfileCache { +@@ -332,9 +349,20 @@ public class GameProfileCache { } private Stream getTopMRUProfiles(int limit) { - return ImmutableList.copyOf(this.profilesByUUID.values()).stream().sorted(Comparator.comparing(GameProfileCache.GameProfileInfo::getLastAccess).reversed()).limit((long) limit); + // Paper start - allow better concurrency + return this.listTopMRUProfiles(limit).stream(); -+ } -+ + } + + private List listTopMRUProfiles(int limit) { + try { + this.stateLock.lock(); @@ -121,8 +121,9 @@ index 2456edc11b29a92b1648937cd3dd6a9a05706803..b48650c38751a925b83fb4c19ac02f87 + } finally { + this.stateLock.unlock(); + } - } ++ } + // Paper end - ++ private static JsonElement writeGameProfile(GameProfileCache.GameProfileInfo entry, DateFormat dateFormat) { JsonObject jsonobject = new JsonObject(); + diff --git a/patches/server/0699-Optimise-chunk-tick-iteration.patch b/patches/server/0699-Optimise-chunk-tick-iteration.patch index 27fbd41bbe..ac6f821d60 100644 --- a/patches/server/0699-Optimise-chunk-tick-iteration.patch +++ b/patches/server/0699-Optimise-chunk-tick-iteration.patch @@ -170,13 +170,13 @@ index d1652c237b2b272f0dfe80f774cff16056f39046..b768767b92bf7691a6e57627c69818a1 } + // Paper start - optimise chunk tick iteration + } -+ } + } + + } finally { + if (iterator1 instanceof io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.Iterator safeIterator) { + safeIterator.finishedIterating(); + } - } ++ } + // Paper end - optimise chunk tick iteration this.level.timings.chunkTicks.stopTiming(); // Paper gameprofilerfiller.popPush("customSpawners"); @@ -186,15 +186,15 @@ index d1652c237b2b272f0dfe80f774cff16056f39046..b768767b92bf7691a6e57627c69818a1 } // Paper - timings } - -- gameprofilerfiller.popPush("broadcast"); ++ gameprofilerfiller.pop(); ++ // Paper start - use set of chunks requiring updates, rather than iterating every single one loaded + gameprofilerfiller.popPush("broadcast"); - list.forEach((chunkproviderserver_a1) -> { - this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing - chunkproviderserver_a1.holder.broadcastChanges(chunkproviderserver_a1.chunk); - this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing - }); - gameprofilerfiller.pop(); -+ // Paper start - use set of chunks requiring updates, rather than iterating every single one loaded -+ gameprofilerfiller.popPush("broadcast"); +- gameprofilerfiller.pop(); + this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing + if (!this.chunkMap.needsChangeBroadcasting.isEmpty()) { + ReferenceOpenHashSet copy = this.chunkMap.needsChangeBroadcasting.clone(); diff --git a/patches/server/0701-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch b/patches/server/0701-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch index c61fd4b9a9..9b964553cf 100644 --- a/patches/server/0701-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch +++ b/patches/server/0701-Attempt-to-recalculate-regionfile-header-if-it-is-co.patch @@ -10,7 +10,7 @@ hoping that at least then we don't swap chunks, and maybe recover them all. diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index 9981bbfd846a5380b99f0d894b121db554d03028..f7c7c351d99890adfa25e0a1368229e5cba37f98 100644 +index f0f38f1a7603cd06aba6adefd370d40b97f2e5b8..34a1976699571608ae19e20dc1b6020759dad909 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java @@ -70,6 +70,18 @@ import net.minecraft.world.ticks.ProtoChunkTicks; @@ -42,7 +42,7 @@ index 9981bbfd846a5380b99f0d894b121db554d03028..f7c7c351d99890adfa25e0a1368229e5 nbttagcompound.putString("Status", chunk.getStatus().getName()); BlendingData blendingdata = chunk.getBlendingData(); diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -index 10603eebf36caca7870e9cf087e99d529550ad3e..2b7c41a176f354001bc9f2e1a08a4e3d1dc547b3 100644 +index e9b13e4f70d9a556e6a7d022a952085051c1819d..71abf1c82ee4f5530bd29b3a97dec9fdb7705779 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java @@ -41,7 +41,7 @@ public class ChunkStorage implements AutoCloseable { @@ -509,7 +509,7 @@ index cda87a66fe80bf910f629c64e36c1fecbad81d77..9bae47f99336c377beb72c4b50b7f01c } else { - this.usedSectors.force(i1, j1); + //this.usedSectors.force(i1, j1); // Paper - move this down so we can check if it fails to allocate -+ } + } + // Paper start - recalculate header on header corruption + if (offset < 2 || sectorLength <= 0 || ((long)offset * 4096L) > regionFileSize) { + if (canRecalcHeader) { @@ -532,7 +532,7 @@ index cda87a66fe80bf910f629c64e36c1fecbad81d77..9bae47f99336c377beb72c4b50b7f01c + boolean failedToAllocate = !this.usedSectors.tryAllocate(offset, sectorLength); + if (failedToAllocate) { + LOGGER.error("Overlapping allocation by local chunk (" + (headerLocation & 31) + "," + (headerLocation >>> 5) + ") in regionfile " + this.regionFile.toAbsolutePath()); - } ++ } + if (failedToAllocate & !canRecalcHeader) { + // location = chunkX | (chunkZ << 5); + LOGGER.error("Detected invalid header for regionfile " + this.regionFile.toAbsolutePath() + diff --git a/patches/server/0716-Optimise-BlockSoil-nearby-water-lookup.patch b/patches/server/0716-Optimise-BlockSoil-nearby-water-lookup.patch index 4d0f364a33..38e5222da1 100644 --- a/patches/server/0716-Optimise-BlockSoil-nearby-water-lookup.patch +++ b/patches/server/0716-Optimise-BlockSoil-nearby-water-lookup.patch @@ -15,17 +15,16 @@ index e0aa9a57d6a5993d7333b7685b6fa1b50bc11ea0..34d744837e599633a3c2c0b72f253bb0 private static boolean isNearWater(LevelReader world, BlockPos pos) { - Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 1, 4)).iterator(); -- ++ // Paper start - remove abstract block iteration ++ int xOff = pos.getX(); ++ int yOff = pos.getY(); ++ int zOff = pos.getZ(); + - BlockPos blockposition1; - - do { - if (!iterator.hasNext()) { - return false; -+ // Paper start - remove abstract block iteration -+ int xOff = pos.getX(); -+ int yOff = pos.getY(); -+ int zOff = pos.getZ(); -+ + for (int dz = -4; dz <= 4; ++dz) { + int z = dz + zOff; + for (int dx = -4; dx <= 4; ++dx) { diff --git a/patches/server/0717-Optimise-random-block-ticking.patch b/patches/server/0717-Optimise-random-block-ticking.patch index 7b9486017d..001fb88c4d 100644 --- a/patches/server/0717-Optimise-random-block-ticking.patch +++ b/patches/server/0717-Optimise-random-block-ticking.patch @@ -173,7 +173,14 @@ index 1f683d734b9e272c8f4c48d922f3dcd12d0ffd1a..9523f6acd2c86892b390e14aaab628b4 if (randomTickSpeed > 0) { - LevelChunkSection[] achunksection = chunk.getSections(); - int j1 = achunksection.length; -- ++ LevelChunkSection[] sections = chunk.getSections(); ++ int minSection = io.papermc.paper.util.WorldUtil.getMinSection(this); ++ for (int sectionIndex = 0; sectionIndex < sections.length; ++sectionIndex) { ++ LevelChunkSection section = sections[sectionIndex]; ++ if (section == null || section.tickingList.size() == 0) { ++ continue; ++ } + - for (int k1 = 0; k1 < j1; ++k1) { - LevelChunkSection chunksection = achunksection[k1]; - @@ -185,40 +192,35 @@ index 1f683d734b9e272c8f4c48d922f3dcd12d0ffd1a..9523f6acd2c86892b390e14aaab628b4 - - gameprofilerfiller.push("randomTick"); - BlockState iblockdata3 = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - l1, blockposition2.getZ() - k); -+ LevelChunkSection[] sections = chunk.getSections(); -+ int minSection = io.papermc.paper.util.WorldUtil.getMinSection(this); -+ for (int sectionIndex = 0; sectionIndex < sections.length; ++sectionIndex) { -+ LevelChunkSection section = sections[sectionIndex]; -+ if (section == null || section.tickingList.size() == 0) { -+ continue; -+ } - +- - if (iblockdata3.isRandomlyTicking()) { - iblockdata3.randomTick(this, blockposition2, this.random); - } +- +- FluidState fluid = iblockdata3.getFluidState(); +- +- if (fluid.isRandomlyTicking()) { +- fluid.randomTick(this, blockposition2, this.random); +- } +- +- gameprofilerfiller.pop(); + int yPos = (sectionIndex + minSection) << 4; + for (int a = 0; a < randomTickSpeed; ++a) { + int tickingBlocks = section.tickingList.size(); + int index = this.randomTickRandom.nextInt(16 * 16 * 16); + if (index >= tickingBlocks) { + continue; -+ } - -- FluidState fluid = iblockdata3.getFluidState(); + } ++ + long raw = section.tickingList.getRaw(index); + int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw); + int randomX = location & 15; + int randomY = ((location >>> (4 + 4)) & 255) | yPos; + int randomZ = (location >>> 4) & 15; - -- if (fluid.isRandomlyTicking()) { -- fluid.randomTick(this, blockposition2, this.random); -- } ++ + BlockPos blockposition2 = blockposition.set(j + randomX, randomY, k + randomZ); + BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw); - -- gameprofilerfiller.pop(); -- } ++ + iblockdata.randomTick(this, blockposition2, this.randomTickRandom); + // We drop the fluid tick since LAVA is ALREADY TICKED by the above method (See LiquidBlock). + // TODO CHECK ON UPDATE (ping the Canadian) @@ -377,7 +379,14 @@ index 8c8445af8a2fe684fdbb468f8d8605d44a803758..c7e2796e136ee8fb7d7e438a7fc59826 public void recalcBlockCounts() { - class a implements PalettedContainer.CountConsumer { -- ++ // Paper start - unfuck this ++ this.tickingList.clear(); ++ this.nonEmptyBlockCount = 0; ++ this.tickingBlockCount = 0; ++ this.tickingFluidCount = 0; ++ this.states.forEachLocation((BlockState iblockdata, int i) -> { ++ FluidState fluid = iblockdata.getFluidState(); + - public int nonEmptyBlockCount; - public int tickingBlockCount; - public int tickingFluidCount; @@ -392,38 +401,31 @@ index 8c8445af8a2fe684fdbb468f8d8605d44a803758..c7e2796e136ee8fb7d7e438a7fc59826 - if (iblockdata.isRandomlyTicking()) { - this.tickingBlockCount += i; - } -+ // Paper start - unfuck this -+ this.tickingList.clear(); -+ this.nonEmptyBlockCount = 0; -+ this.tickingBlockCount = 0; -+ this.tickingFluidCount = 0; -+ this.states.forEachLocation((BlockState iblockdata, int i) -> { -+ FluidState fluid = iblockdata.getFluidState(); -+ + if (!iblockdata.isAir()) { + this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); + if (iblockdata.isRandomlyTicking()) { + this.tickingBlockCount = (short)(this.tickingBlockCount + 1); + this.tickingList.add(i, iblockdata); } -+ } - +- - if (!fluid.isEmpty()) { - this.nonEmptyBlockCount += i; - if (fluid.isRandomlyTicking()) { - this.tickingFluidCount += i; - } -+ if (!fluid.isEmpty()) { -+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); -+ if (fluid.isRandomlyTicking()) { -+ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); - } +- } - } - } - a a0 = new a(); -- ++ if (!fluid.isEmpty()) { ++ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); ++ if (fluid.isRandomlyTicking()) { ++ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); ++ } ++ } + - this.states.count(a0); - this.nonEmptyBlockCount = (short) a0.nonEmptyBlockCount; - this.tickingBlockCount = (short) a0.tickingBlockCount; diff --git a/patches/server/0738-Fix-upstreams-block-state-factories.patch b/patches/server/0738-Fix-upstreams-block-state-factories.patch index b6a1321bfd..f518b74909 100644 --- a/patches/server/0738-Fix-upstreams-block-state-factories.patch +++ b/patches/server/0738-Fix-upstreams-block-state-factories.patch @@ -328,21 +328,21 @@ index cf76ca2ebead64d194ce03ee024085d32d02077a..1caa329567b50a962c54bb00c79cc98e private static > void register( - Material blockType, -- Class blockStateType, -- BiFunction blockStateConstructor, -- BiFunction tileEntityConstructor -- ) { -- CraftBlockStates.register(Collections.singletonList(blockType), blockStateType, blockStateConstructor, tileEntityConstructor); -- } -- -- private static > void register( -- List blockTypes, + net.minecraft.world.level.block.entity.BlockEntityType blockEntityType, // Paper Class blockStateType, - BiFunction blockStateConstructor, - BiFunction tileEntityConstructor + BiFunction blockStateConstructor // Paper ) { +- CraftBlockStates.register(Collections.singletonList(blockType), blockStateType, blockStateConstructor, tileEntityConstructor); +- } +- +- private static > void register( +- List blockTypes, +- Class blockStateType, +- BiFunction blockStateConstructor, +- BiFunction tileEntityConstructor +- ) { - BlockStateFactory factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, tileEntityConstructor); - for (Material blockType : blockTypes) { - CraftBlockStates.register(blockType, factory); diff --git a/patches/server/0747-Always-parse-protochunk-light-sources-unless-it-is-m.patch b/patches/server/0747-Always-parse-protochunk-light-sources-unless-it-is-m.patch index ce70afbbc9..5aa52fec7b 100644 --- a/patches/server/0747-Always-parse-protochunk-light-sources-unless-it-is-m.patch +++ b/patches/server/0747-Always-parse-protochunk-light-sources-unless-it-is-m.patch @@ -8,7 +8,7 @@ Chunks not marked as lit will always go through the light engine, so they should always have their block sources parsed. diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java -index f7c7c351d99890adfa25e0a1368229e5cba37f98..887378de7a0673e929a6dcfb30c87a097d12a402 100644 +index 34a1976699571608ae19e20dc1b6020759dad909..0ec80b83a99bfdb1f985045d98a81905a8a5a3ac 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java @@ -327,16 +327,33 @@ public class ChunkSerializer { @@ -21,10 +21,14 @@ index f7c7c351d99890adfa25e0a1368229e5cba37f98..887378de7a0673e929a6dcfb30c87a09 + // Paper start - let's make sure the implementation isn't as slow as possible + int offX = chunkPos.x << 4; + int offZ = chunkPos.z << 4; -+ + +- while (iterator.hasNext()) { +- BlockPos blockposition = (BlockPos) iterator.next(); + int minChunkSection = io.papermc.paper.util.WorldUtil.getMinSection(world); + int maxChunkSection = io.papermc.paper.util.WorldUtil.getMaxSection(world); -+ + +- if (((ChunkAccess) object1).getBlockState(blockposition).getLightEmission() != 0) { +- protochunk.addLight(blockposition); + LevelChunkSection[] sections = achunksection; + for (int sectionY = minChunkSection; sectionY <= maxChunkSection; ++sectionY) { + LevelChunkSection section = sections[sectionY - minChunkSection]; @@ -33,16 +37,12 @@ index f7c7c351d99890adfa25e0a1368229e5cba37f98..887378de7a0673e929a6dcfb30c87a09 + continue; + } + int offY = sectionY << 4; - -- while (iterator.hasNext()) { -- BlockPos blockposition = (BlockPos) iterator.next(); ++ + for (int index = 0; index < (16 * 16 * 16); ++index) { + if (section.states.get(index).getLightEmission() <= 0) { + continue; + } - -- if (((ChunkAccess) object1).getBlockState(blockposition).getLightEmission() != 0) { -- protochunk.addLight(blockposition); ++ + // index = x | (z << 4) | (y << 8) + protochunk.addLight(new BlockPos(offX | (index & 15), offY | (index >>> 8), offZ | ((index >>> 4) & 15))); } diff --git a/patches/server/0757-Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch b/patches/server/0757-Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch index 03f118416a..cbf4934d51 100644 --- a/patches/server/0757-Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch +++ b/patches/server/0757-Highly-optimise-single-and-multi-AABB-VoxelShapes-an.patch @@ -24,7 +24,7 @@ index be668387f65a633c6ac497fca632a4767a1bf3a2..e08f4e39db4ee3fed62e37364d17dcc5 + // Paper start - optimise collisions + static final UnsafeList TEMP_COLLISION_LIST = new UnsafeList<>(1024); + static boolean tempCollisionListInUse; -+ + + public static UnsafeList getTempCollisionList() { + if (!Bukkit.isPrimaryThread() || tempCollisionListInUse) { + return new UnsafeList<>(16); @@ -40,7 +40,7 @@ index be668387f65a633c6ac497fca632a4767a1bf3a2..e08f4e39db4ee3fed62e37364d17dcc5 + ((UnsafeList)list).setSize(0); + tempCollisionListInUse = false; + } - ++ + static final UnsafeList TEMP_GET_ENTITIES_LIST = new UnsafeList<>(1024); + static boolean tempGetEntitiesListInUse; + @@ -1277,29 +1277,26 @@ index 73d475788e23d371c79908c792d8d4dd0ba770ab..182e443e4cd114edeb0c0c6be5dda76d - boolean flag1 = movement.y != vec3d1.y; - boolean flag2 = movement.z != vec3d1.z; - boolean flag3 = this.onGround || flag1 && movement.y < 0.0D; -- -- if (this.maxUpStep() > 0.0F && flag3 && (flag || flag2)) { -- Vec3 vec3d2 = Entity.collideBoundingBox(this, new Vec3(movement.x, (double) this.maxUpStep(), movement.z), axisalignedbb, this.level, list); -- Vec3 vec3d3 = Entity.collideBoundingBox(this, new Vec3(0.0D, (double) this.maxUpStep(), 0.0D), axisalignedbb.expandTowards(movement.x, 0.0D, movement.z), this.level, list); -- -- if (vec3d3.y < (double) this.maxUpStep()) { -- Vec3 vec3d4 = Entity.collideBoundingBox(this, new Vec3(movement.x, 0.0D, movement.z), axisalignedbb.move(vec3d3), this.level, list).add(vec3d3); -- -- if (vec3d4.horizontalDistanceSqr() > vec3d2.horizontalDistanceSqr()) { -- vec3d2 = vec3d4; + // Paper start - optimise collisions + // This is a copy of vanilla's except that it uses strictly AABB math + if (movement.x == 0.0 && movement.y == 0.0 && movement.z == 0.0) { + return movement; + } -+ + +- if (this.maxUpStep() > 0.0F && flag3 && (flag || flag2)) { +- Vec3 vec3d2 = Entity.collideBoundingBox(this, new Vec3(movement.x, (double) this.maxUpStep(), movement.z), axisalignedbb, this.level, list); +- Vec3 vec3d3 = Entity.collideBoundingBox(this, new Vec3(0.0D, (double) this.maxUpStep(), 0.0D), axisalignedbb.expandTowards(movement.x, 0.0D, movement.z), this.level, list); + final Level world = this.level; + final AABB currBoundingBox = this.getBoundingBox(); -+ + +- if (vec3d3.y < (double) this.maxUpStep()) { +- Vec3 vec3d4 = Entity.collideBoundingBox(this, new Vec3(movement.x, 0.0D, movement.z), axisalignedbb.move(vec3d3), this.level, list).add(vec3d3); + if (io.papermc.paper.util.CollisionUtil.isEmpty(currBoundingBox)) { + return movement; + } -+ + +- if (vec3d4.horizontalDistanceSqr() > vec3d2.horizontalDistanceSqr()) { +- vec3d2 = vec3d4; + final List potentialCollisions = io.papermc.paper.util.CachedLists.getTempCollisionList(); + try { + final double stepHeight = (double)this.maxUpStep(); @@ -1326,15 +1323,16 @@ index 73d475788e23d371c79908c792d8d4dd0ba770ab..182e443e4cd114edeb0c0c6be5dda76d - if (vec3d2.horizontalDistanceSqr() > vec3d1.horizontalDistanceSqr()) { - return vec3d2.add(Entity.collideBoundingBox(this, new Vec3(0.0D, -vec3d2.y + movement.y, 0.0D), axisalignedbb.move(vec3d2), this.level, list)); +- } +- } + io.papermc.paper.util.CollisionUtil.getCollisions(world, this, collisionBox, potentialCollisions, false, this.level.paperConfig().chunks.preventMovingIntoUnloadedChunks, + false, false, null, null); -+ -+ if (io.papermc.paper.util.CollisionUtil.isCollidingWithBorderEdge(world.getWorldBorder(), collisionBox)) { -+ io.papermc.paper.util.CollisionUtil.addBoxesToIfIntersects(world.getWorldBorder().getCollisionShape(), collisionBox, potentialCollisions); - } -- } - return vec3d1; ++ if (io.papermc.paper.util.CollisionUtil.isCollidingWithBorderEdge(world.getWorldBorder(), collisionBox)) { ++ io.papermc.paper.util.CollisionUtil.addBoxesToIfIntersects(world.getWorldBorder().getCollisionShape(), collisionBox, potentialCollisions); ++ } ++ + final Vec3 limitedMoveVector = io.papermc.paper.util.CollisionUtil.performCollisions(movement, currBoundingBox, potentialCollisions); + + if (stepHeight > 0.0 diff --git a/patches/server/0793-Implement-regenerateChunk.patch b/patches/server/0793-Implement-regenerateChunk.patch index ff7e10a3f1..dcc076bdc3 100644 --- a/patches/server/0793-Implement-regenerateChunk.patch +++ b/patches/server/0793-Implement-regenerateChunk.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Implement regenerateChunk Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com> diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 5086fcbbd908f5759653ce44b8524345b479d2b8..e52008c574d1f8738c02848c98aee12dd5fb30ab 100644 +index 8fcc553b6f1bf62fb9febb46402940039c37606a..eeeaaf379c7273c276e1faac5d6c55730d5b51bc 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -138,6 +138,7 @@ import org.bukkit.util.Vector; @@ -25,10 +25,6 @@ index 5086fcbbd908f5759653ce44b8524345b479d2b8..e52008c574d1f8738c02848c98aee12d - /* - if (!unloadChunk0(x, z, false)) { - return false; -- } -- -- final long chunkKey = ChunkCoordIntPair.pair(x, z); -- world.getChunkProvider().unloadQueue.remove(chunkKey); + // Paper start - implement regenerateChunk method + final ServerLevel serverLevel = this.world; + final net.minecraft.server.level.ServerChunkCache serverChunkCache = serverLevel.getChunkSource(); @@ -37,8 +33,10 @@ index 5086fcbbd908f5759653ce44b8524345b479d2b8..e52008c574d1f8738c02848c98aee12d + for (final BlockPos blockPos : BlockPos.betweenClosed(chunkPos.getMinBlockX(), serverLevel.getMinBuildHeight(), chunkPos.getMinBlockZ(), chunkPos.getMaxBlockX(), serverLevel.getMaxBuildHeight() - 1, chunkPos.getMaxBlockZ())) { + levelChunk.removeBlockEntity(blockPos); + serverLevel.setBlock(blockPos, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState(), 16); -+ } -+ + } + +- final long chunkKey = ChunkCoordIntPair.pair(x, z); +- world.getChunkProvider().unloadQueue.remove(chunkKey); + for (final ChunkStatus chunkStatus : REGEN_CHUNK_STATUSES) { + final List list = new ArrayList<>(); + final int range = Math.max(1, chunkStatus.getRange()); diff --git a/patches/server/0864-More-Teleport-API.patch b/patches/server/0864-More-Teleport-API.patch index 3065b33e38..eb25b06533 100644 --- a/patches/server/0864-More-Teleport-API.patch +++ b/patches/server/0864-More-Teleport-API.patch @@ -55,14 +55,14 @@ index 7df1eebce5b62214943e55314e9ec98f056fa330..2aee8aacd50431c18ff28af678348ec2 + if (flagSet.contains(io.papermc.paper.entity.TeleportFlag.EntityState.RETAIN_PASSENGERS) && this.entity.isVehicle() && location.getWorld() != this.getWorld()) { + return false; + } -+ + +- if (this.entity.isVehicle() || this.entity.isRemoved()) { + // Don't allow to teleport between worlds if remaining on vehicle + if (!dismount && this.entity.isPassenger() && location.getWorld() != this.getWorld()) { + return false; + } + // Paper end - -- if (this.entity.isVehicle() || this.entity.isRemoved()) { ++ + if ((!ignorePassengers && this.entity.isVehicle()) || this.entity.isRemoved()) { // Paper - Teleport passenger API return false; } @@ -74,7 +74,7 @@ index 7df1eebce5b62214943e55314e9ec98f056fa330..2aee8aacd50431c18ff28af678348ec2 // Let the server handle cross world teleports if (location.getWorld() != null && !location.getWorld().equals(this.getWorld())) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 8e16fc9263cfd43bb85d368b0a6f36624a6ebf91..0a32183038420823811d8a5ae5eadeef73304296 100644 +index 89d9c6c1e1b9cee8a20a657ab47dd5620e7f395f..ad7d009188f2c54926cdee589c7d92e7e6a967f4 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1231,13 +1231,100 @@ public class CraftPlayer extends CraftHumanEntity implements Player { diff --git a/patches/server/0881-Stop-large-look-changes-from-crashing-the-server.patch b/patches/server/0881-Stop-large-look-changes-from-crashing-the-server.patch index e445b904ed..e0405187f0 100644 --- a/patches/server/0881-Stop-large-look-changes-from-crashing-the-server.patch +++ b/patches/server/0881-Stop-large-look-changes-from-crashing-the-server.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Stop large look changes from crashing the server Co-authored-by: Jaren Knodel diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 4e27d0e537a0d813ab81d3bc6524ad038047a0a1..590a14cd045baa892119505df1063b18c6f1fd71 100644 +index 6b1c5b51693b8ae9ece498d4711b4493d0f5543a..80970c877b9e729fc88451745a490f0b80a7c1b6 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -2996,37 +2996,15 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -16,17 +16,18 @@ index 4e27d0e537a0d813ab81d3bc6524ad038047a0a1..590a14cd045baa892119505df1063b18 - while (this.getYRot() - this.yRotO < -180.0F) { - this.yRotO -= 360.0F; - } -- ++ // Paper start - stop large pitch and yaw changes from crashing the server ++ this.yRotO += Math.round((this.getYRot() - this.yRotO) / 360.0F) * 360.0F; + - while (this.getYRot() - this.yRotO >= 180.0F) { - this.yRotO += 360.0F; - } -+ // Paper start - stop large pitch and yaw changes from crashing the server -+ this.yRotO += Math.round((this.getYRot() - this.yRotO) / 360.0F) * 360.0F; ++ this.yBodyRotO += Math.round((this.yBodyRot - this.yBodyRotO) / 360.0F) * 360.0F; - while (this.yBodyRot - this.yBodyRotO < -180.0F) { - this.yBodyRotO -= 360.0F; - } -+ this.yBodyRotO += Math.round((this.yBodyRot - this.yBodyRotO) / 360.0F) * 360.0F; ++ this.xRotO += Math.round((this.getXRot() - this.xRotO) / 360.0F) * 360.0F; - while (this.yBodyRot - this.yBodyRotO >= 180.0F) { - this.yBodyRotO += 360.0F; @@ -35,8 +36,7 @@ index 4e27d0e537a0d813ab81d3bc6524ad038047a0a1..590a14cd045baa892119505df1063b18 - while (this.getXRot() - this.xRotO < -180.0F) { - this.xRotO -= 360.0F; - } -+ this.xRotO += Math.round((this.getXRot() - this.xRotO) / 360.0F) * 360.0F; - +- - while (this.getXRot() - this.xRotO >= 180.0F) { - this.xRotO += 360.0F; - } diff --git a/patches/server/0968-Optimize-Hoppers.patch b/patches/server/0968-Optimize-Hoppers.patch index f78bc2e9f1..1116f8be1f 100644 --- a/patches/server/0968-Optimize-Hoppers.patch +++ b/patches/server/0968-Optimize-Hoppers.patch @@ -13,7 +13,7 @@ Subject: [PATCH] Optimize Hoppers * Remove Streams from Item Suck In and restore restore 1.12 AABB checks which is simpler and no voxel allocations (was doing TWO Item Suck ins) diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 081871412e92ce909ad9c51a8d18ede53596c049..e67c4a7aaa11f5c67f926f92e0a174af526c2ec3 100644 +index 2e2cc6647a4c5acc8495b1c7ad6df3a49c94ac6d..4450d825a5474da211f0e83f845d8c7129fa08aa 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1524,6 +1524,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop