diff --git a/build.gradle.kts b/build.gradle.kts index 0f7fd3dbda..d3c530db0b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -39,7 +39,7 @@ subprojects { events(TestLogEvent.STANDARD_OUT) } minHeapSize = "2g" - maxHeapSize = "2g" + maxHeapSize = "4g" } repositories { diff --git a/patches/api/0003-Test-changes.patch b/patches/api/0003-Test-changes.patch index 5853d992bd..ade12ea30c 100644 --- a/patches/api/0003-Test-changes.patch +++ b/patches/api/0003-Test-changes.patch @@ -143,7 +143,7 @@ index 0000000000000000000000000000000000000000..756acf231b1b076b08046d86992ba7ce + +} diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 4ac3dd977e75cd8464163351d306e037ee32cb48..1a71bb8861150c1add6446aa2fad0f7035dd6873 100644 +index 4ac3dd977e75cd8464163351d306e037ee32cb48..8f35cda0d67ec66646c6096a5bf1c84891b8b0fd 100644 --- a/src/test/java/org/bukkit/AnnotationTest.java +++ b/src/test/java/org/bukkit/AnnotationTest.java @@ -40,7 +40,17 @@ public class AnnotationTest { @@ -229,7 +229,19 @@ index 4ac3dd977e75cd8464163351d306e037ee32cb48..1a71bb8861150c1add6446aa2fad0f70 } private static void collectClasses(@NotNull File from, @NotNull Map to) throws IOException { -@@ -152,7 +193,7 @@ public class AnnotationTest { +@@ -140,6 +181,11 @@ public class AnnotationTest { + // Exceptions are excluded + return false; + } ++ // Paper start ++ if (isInternal(clazz.invisibleAnnotations)) { ++ return false; ++ } ++ // Paper end + + for (String excludedClass : EXCLUDED_CLASSES) { + if (excludedClass.equals(clazz.name)) { +@@ -152,7 +198,7 @@ public class AnnotationTest { private static boolean isMethodIncluded(@NotNull ClassNode clazz, @NotNull MethodNode method, @NotNull Map allClasses) { // Exclude private, synthetic and deprecated methods @@ -238,9 +250,32 @@ index 4ac3dd977e75cd8464163351d306e037ee32cb48..1a71bb8861150c1add6446aa2fad0f70 return false; } -@@ -174,7 +215,7 @@ public class AnnotationTest { +@@ -170,11 +216,30 @@ public class AnnotationTest { + if ("".equals(method.name) && isAnonymous(clazz)) { + return false; + } ++ // Paper start ++ if (isInternal(method.invisibleAnnotations)) { ++ return false; ++ } ++ // Paper end + return true; } ++ // Paper start ++ private static boolean isInternal(List annotations) { ++ if (annotations == null) { ++ return false; ++ } ++ for (AnnotationNode node : annotations) { ++ if (node.desc.equals("Lorg/jetbrains/annotations/ApiStatus$Internal;")) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ // Paper end - private static boolean isWellAnnotated(@Nullable List annotations) { + private static boolean isWellAnnotated(@Nullable List annotations) { // Paper diff --git a/patches/api/0005-Adventure.patch b/patches/api/0005-Adventure.patch index f593875871..ad99c9b606 100644 --- a/patches/api/0005-Adventure.patch +++ b/patches/api/0005-Adventure.patch @@ -1561,20 +1561,19 @@ index ab6b0ec328e94bf65a0dafd0403e5ee3b870296c..c8d37184d8e882a4084a1bfef85faa33 /** diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 80209bb88a0294d4eedc78509533a6257315d856..57ade3963faae3724d9a01eeeb6d02168acb567e 100644 +index 80209bb88a0294d4eedc78509533a6257315d856..caa29be46e8541b69ec47c181eb3320d6515b544 100644 --- a/src/main/java/org/bukkit/command/Command.java +++ b/src/main/java/org/bukkit/command/Command.java -@@ -32,8 +32,7 @@ public abstract class Command { +@@ -32,7 +32,7 @@ public abstract class Command { protected String description; protected String usageMessage; private String permission; - private String permissionMessage; -- public org.spigotmc.CustomTimingsHandler timings; // Spigot + private net.kyori.adventure.text.Component permissionMessage; // Paper + public org.spigotmc.CustomTimingsHandler timings; // Spigot protected Command(@NotNull String name) { - this(name, "", "/" + name, new ArrayList()); -@@ -186,10 +185,10 @@ public abstract class Command { +@@ -186,10 +186,10 @@ public abstract class Command { if (permissionMessage == null) { target.sendMessage(ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is a mistake."); @@ -1589,7 +1588,7 @@ index 80209bb88a0294d4eedc78509533a6257315d856..57ade3963faae3724d9a01eeeb6d0216 } return false; -@@ -317,10 +316,12 @@ public abstract class Command { +@@ -317,10 +317,12 @@ public abstract class Command { * command * * @return Permission check failed message @@ -1603,7 +1602,7 @@ index 80209bb88a0294d4eedc78509533a6257315d856..57ade3963faae3724d9a01eeeb6d0216 } /** -@@ -381,10 +382,12 @@ public abstract class Command { +@@ -381,10 +383,12 @@ public abstract class Command { * @param permissionMessage new permission message, null to indicate * default message, or an empty string to indicate no message * @return this command object, for chaining @@ -1617,7 +1616,7 @@ index 80209bb88a0294d4eedc78509533a6257315d856..57ade3963faae3724d9a01eeeb6d0216 return this; } -@@ -399,13 +402,47 @@ public abstract class Command { +@@ -399,13 +403,47 @@ public abstract class Command { this.usageMessage = (usage == null) ? "" : usage; return this; } @@ -1666,7 +1665,7 @@ index 80209bb88a0294d4eedc78509533a6257315d856..57ade3963faae3724d9a01eeeb6d0216 if (source instanceof BlockCommandSender) { BlockCommandSender blockCommandSender = (BlockCommandSender) source; -@@ -424,7 +461,12 @@ public abstract class Command { +@@ -424,7 +462,12 @@ public abstract class Command { } Set users = Bukkit.getPluginManager().getPermissionSubscriptions(Server.BROADCAST_CHANNEL_ADMINISTRATIVE); @@ -4677,7 +4676,7 @@ index 0db7fe1b9fe5621ceed3f4f046691e359f5949dd..47b10df619ad2520b9bb673e2220f363 /** diff --git a/src/test/java/org/bukkit/AnnotationTest.java b/src/test/java/org/bukkit/AnnotationTest.java -index 1a71bb8861150c1add6446aa2fad0f7035dd6873..8275a5d7e1de39a5171e254f449a42c6defd3445 100644 +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; diff --git a/patches/api/0027-Use-ASM-for-event-executors.patch b/patches/api/0007-Use-ASM-for-event-executors.patch similarity index 90% rename from patches/api/0027-Use-ASM-for-event-executors.patch rename to patches/api/0007-Use-ASM-for-event-executors.patch index a54f62a007..a96b5596a3 100644 --- a/patches/api/0027-Use-ASM-for-event-executors.patch +++ b/patches/api/0007-Use-ASM-for-event-executors.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Use ASM for event executors. Uses method handles for private or static methods. diff --git a/build.gradle.kts b/build.gradle.kts -index c9f9174a085174b96897c013e0ecb79738c2e9e3..9d650b937610d83748b30d724cee97afd715167f 100644 +index 558fa62d87af1103efa703ef9114481cb928cf8d..359e7bd7e3c76cec89d638f940006dc9c944f98b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -39,6 +39,9 @@ dependencies { @@ -368,30 +368,3 @@ index a850f0780de05463fc0d3f9e15ff7f19d88b2aed..9026e108ccd3a88aee1267ee275137be + } + // Paper end } -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 5eb24f38f158d43fb42836b83c108f808c89512e..5d74fab03a15d7099e5dacb780eade4cdc185797 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -291,21 +291,7 @@ public final class JavaPluginLoader implements PluginLoader { - } - } - -- EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Paper -- @Override -- public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException { // Paper -- try { -- if (!eventClass.isAssignableFrom(event.getClass())) { -- return; -- } -- method.invoke(listener, event); -- } catch (InvocationTargetException ex) { -- throw new EventException(ex.getCause()); -- } catch (Throwable t) { -- throw new EventException(t); -- } -- } -- }, plugin, method, eventClass); // Paper -+ EventExecutor executor = new co.aikar.timings.TimedEventExecutor(EventExecutor.create(method, eventClass), plugin, method, eventClass); // Paper // Paper (Yes.) - Use factory method `EventExecutor.create()` - if (false) { // Spigot - RL handles useTimings check now - eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); - } else { diff --git a/patches/api/0008-Paper-Plugins.patch b/patches/api/0008-Paper-Plugins.patch new file mode 100644 index 0000000000..4c6ce22600 --- /dev/null +++ b/patches/api/0008-Paper-Plugins.patch @@ -0,0 +1,2494 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 6 Jul 2022 23:00:36 -0400 +Subject: [PATCH] Paper Plugins + + +diff --git a/build.gradle.kts b/build.gradle.kts +index 359e7bd7e3c76cec89d638f940006dc9c944f98b..f5f217a3a786bf4c95bea74c135289d12205cf7b 100644 +--- a/build.gradle.kts ++++ b/build.gradle.kts +@@ -44,7 +44,7 @@ dependencies { + implementation("org.ow2.asm:asm-commons:9.2") + // Paper end + +- compileOnly("org.apache.maven:maven-resolver-provider:3.8.5") ++ api("org.apache.maven:maven-resolver-provider:3.8.5") // Paper, expose + compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3") + compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.7.3") + compileOnly("com.google.code.findbugs:jsr305:1.3.9") // Paper +diff --git a/src/main/java/io/papermc/paper/plugin/PermissionManager.java b/src/main/java/io/papermc/paper/plugin/PermissionManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..cdbc93b317b3bab47bf6552c29cfbb2c27846933 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/PermissionManager.java +@@ -0,0 +1,171 @@ ++package io.papermc.paper.plugin; ++ ++import org.bukkit.permissions.Permissible; ++import org.bukkit.permissions.Permission; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.List; ++import java.util.Set; ++ ++/** ++ * A permission manager implementation to keep backwards compatibility partially alive with existing plugins that used ++ * the bukkit one before. ++ */ ++@ApiStatus.Experimental ++public interface PermissionManager { ++ ++ /** ++ * Gets a {@link Permission} from its fully qualified name ++ * ++ * @param name Name of the permission ++ * @return Permission, or null if none ++ */ ++ @Nullable ++ Permission getPermission(@NotNull String name); ++ ++ /** ++ * Adds a {@link Permission} to this plugin manager. ++ *

++ * If a permission is already defined with the given name of the new ++ * permission, an exception will be thrown. ++ * ++ * @param perm Permission to add ++ * @throws IllegalArgumentException Thrown when a permission with the same ++ * name already exists ++ */ ++ void addPermission(@NotNull Permission perm); ++ ++ /** ++ * Removes a {@link Permission} registration from this plugin manager. ++ *

++ * If the specified permission does not exist in this plugin manager, ++ * nothing will happen. ++ *

++ * Removing a permission registration will not remove the ++ * permission from any {@link Permissible}s that have it. ++ * ++ * @param perm Permission to remove ++ */ ++ void removePermission(@NotNull Permission perm); ++ ++ /** ++ * Removes a {@link Permission} registration from this plugin manager. ++ *

++ * If the specified permission does not exist in this plugin manager, ++ * nothing will happen. ++ *

++ * Removing a permission registration will not remove the ++ * permission from any {@link Permissible}s that have it. ++ * ++ * @param name Permission to remove ++ */ ++ void removePermission(@NotNull String name); ++ ++ /** ++ * Gets the default permissions for the given op status ++ * ++ * @param op Which set of default permissions to get ++ * @return The default permissions ++ */ ++ @NotNull ++ Set getDefaultPermissions(boolean op); ++ ++ /** ++ * Recalculates the defaults for the given {@link Permission}. ++ *

++ * This will have no effect if the specified permission is not registered ++ * here. ++ * ++ * @param perm Permission to recalculate ++ */ ++ void recalculatePermissionDefaults(@NotNull Permission perm); ++ ++ /** ++ * Subscribes the given Permissible for information about the requested ++ * Permission, by name. ++ *

++ * If the specified Permission changes in any form, the Permissible will ++ * be asked to recalculate. ++ * ++ * @param permission Permission to subscribe to ++ * @param permissible Permissible subscribing ++ */ ++ void subscribeToPermission(@NotNull String permission, @NotNull Permissible permissible); ++ ++ /** ++ * Unsubscribes the given Permissible for information about the requested ++ * Permission, by name. ++ * ++ * @param permission Permission to unsubscribe from ++ * @param permissible Permissible subscribing ++ */ ++ void unsubscribeFromPermission(@NotNull String permission, @NotNull Permissible permissible); ++ ++ /** ++ * Gets a set containing all subscribed {@link Permissible}s to the given ++ * permission, by name ++ * ++ * @param permission Permission to query for ++ * @return Set containing all subscribed permissions ++ */ ++ @NotNull ++ Set getPermissionSubscriptions(@NotNull String permission); ++ ++ /** ++ * Subscribes to the given Default permissions by operator status ++ *

++ * If the specified defaults change in any form, the Permissible will be ++ * asked to recalculate. ++ * ++ * @param op Default list to subscribe to ++ * @param permissible Permissible subscribing ++ */ ++ void subscribeToDefaultPerms(boolean op, @NotNull Permissible permissible); ++ ++ /** ++ * Unsubscribes from the given Default permissions by operator status ++ * ++ * @param op Default list to unsubscribe from ++ * @param permissible Permissible subscribing ++ */ ++ void unsubscribeFromDefaultPerms(boolean op, @NotNull Permissible permissible); ++ ++ /** ++ * Gets a set containing all subscribed {@link Permissible}s to the given ++ * default list, by op status ++ * ++ * @param op Default list to query for ++ * @return Set containing all subscribed permissions ++ */ ++ @NotNull ++ Set getDefaultPermSubscriptions(boolean op); ++ ++ /** ++ * Gets a set of all registered permissions. ++ *

++ * This set is a copy and will not be modified live. ++ * ++ * @return Set containing all current registered permissions ++ */ ++ @NotNull ++ Set getPermissions(); ++ ++ /** ++ * Adds a list of permissions. ++ *

++ * This is meant as an optimization for adding multiple permissions without recalculating each permission. ++ * ++ * @param perm permission ++ */ ++ void addPermissions(@NotNull List perm); ++ ++ /** ++ * Clears the current registered permissinos. ++ *

++ * This is used for reloading. ++ */ ++ void clearPermissions(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrap.java b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ea84b11e8682e73fcd563fec65e76b707546a99e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginBootstrap.java +@@ -0,0 +1,41 @@ ++package io.papermc.paper.plugin.bootstrap; ++ ++import io.papermc.paper.plugin.provider.util.ProviderUtil; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A plugin boostrap is meant for loading certain parts of the plugin before the server is loaded. ++ *

++ * Plugin bootstrapping allows values to be initialized in certain parts of the server that might not be allowed ++ * when the server is running. ++ *

++ * Your bootstrap class will be on the same classloader as your JavaPlugin. ++ *

++ * All calls to Bukkit may throw a NullPointerExceptions or return null unexpectedly. You should only call api methods that are explicitly documented to work in the bootstrapper ++ */ ++@ApiStatus.OverrideOnly ++@ApiStatus.Experimental ++public interface PluginBootstrap { ++ ++ /** ++ * Called by the server, allowing you to bootstrap the plugin with a context that provides things like a logger and your shared plugin configuration file. ++ * ++ * @param context the server provided context ++ */ ++ void bootstrap(@NotNull PluginProviderContext context); ++ ++ /** ++ * Called by the server to instantiate your main class. ++ * Plugins may override this logic to define custom creation logic for said instance, like passing addition ++ * constructor arguments. ++ * ++ * @param context the server created bootstrap object ++ * @return the server requested instance of the plugins main class. ++ */ ++ @NotNull ++ default JavaPlugin createPlugin(@NotNull PluginProviderContext context) { ++ return ProviderUtil.loadClass(context.getConfiguration().getMainClass(), JavaPlugin.class, this.getClass().getClassLoader()); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContext.java b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContext.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a4467fe1ba0dc348eab681900dbcac1770963591 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContext.java +@@ -0,0 +1,53 @@ ++package io.papermc.paper.plugin.bootstrap; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++import java.nio.file.Path; ++import java.util.logging.Logger; ++ ++/** ++ * Represents the context provided to a {@link PluginBootstrap} during both the bootstrapping and plugin ++ * instanciation logic. ++ * A boostrap context may be used to access data or logic usually provided to {@link org.bukkit.plugin.Plugin} instances ++ * like the plugin's configuration or logger during the plugins bootstrap. ++ */ ++@ApiStatus.NonExtendable ++@ApiStatus.Experimental ++public interface PluginProviderContext { ++ ++ /** ++ * Provides the plugin's configuration. ++ * ++ * @return the plugin's configuration ++ */ ++ @NotNull ++ PluginMeta getConfiguration(); ++ ++ /** ++ * Provides the path to the data directory of the plugin. ++ * ++ * @return the previously described path ++ */ ++ @NotNull ++ Path getDataDirectory(); ++ ++ /** ++ * Provides the logger used for this plugin. ++ * ++ * @return the logger instance ++ */ ++ @NotNull ++ Logger getLogger(); ++ ++ /** ++ * Provides the SLF4J logger assigned to this plugin. ++ * ++ * @return SLF4J logger ++ */ ++ @NotNull ++ default org.slf4j.Logger getSLF4JLogger() { ++ return org.slf4j.LoggerFactory.getLogger(this.getLogger().getName()); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/configuration/PluginMeta.java b/src/main/java/io/papermc/paper/plugin/configuration/PluginMeta.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ef393f1f93ca48264fc1b6e3a27787f6a9152e1b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/configuration/PluginMeta.java +@@ -0,0 +1,203 @@ ++package io.papermc.paper.plugin.configuration; ++ ++import org.bukkit.permissions.Permission; ++import org.bukkit.permissions.PermissionDefault; ++import org.bukkit.plugin.PluginLoadOrder; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.List; ++ ++/** ++ * This class acts as an abstraction for a plugin configuration. ++ */ ++@ApiStatus.NonExtendable ++@ApiStatus.Experimental // Subject to change! ++public interface PluginMeta { ++ ++ /** ++ * Provides the name of the plugin. This name uniquely identifies the plugin amongst all loaded plugins on the ++ * server. ++ *

    ++ *
  • Will only contain alphanumeric characters, underscores, hyphens, ++ * and periods: [a-zA-Z0-9_\-\.]. ++ *
  • Typically used for identifying the plugin data folder. ++ *
  • The name also acts as the token referenced in {@link #getPluginDependencies()}, ++ * {@link #getPluginSoftDependencies()}, and {@link #getLoadBeforePlugins()}. ++ *
++ *

++ * In the plugin.yml, this entry is named name. ++ *

++ * Example:

name: MyPlugin
++ * ++ * @return the name of the plugin ++ */ ++ @NotNull ++ String getName(); ++ ++ /** ++ * Returns the display name of the plugin, including the version. ++ * ++ * @return a descriptive name of the plugin and respective version ++ */ ++ @NotNull ++ default String getDisplayName() { ++ return this.getName() + " v" + this.getVersion(); ++ } ++ ++ /** ++ * Provides the fully qualified class name of the main class for the plugin. ++ * A subtype of {@link JavaPlugin} is expected at this location. ++ * ++ * @return the fully qualified class name of the plugin's main class. ++ */ ++ @NotNull ++ String getMainClass(); ++ ++ /** ++ * Returns the phase of the server startup logic that the plugin should be loaded. ++ * ++ * @return the plugin load order ++ * @see PluginLoadOrder for further details regards the available load orders. ++ */ ++ @NotNull ++ PluginLoadOrder getLoadOrder(); ++ ++ /** ++ * Provides the version of this plugin as defined by the plugin. ++ * There is no inherit format defined/enforced for the version of a plugin, however a common approach ++ * might be schematic versioning. ++ * ++ * @return the string representation of the plugin's version ++ */ ++ @NotNull ++ String getVersion(); ++ ++ /** ++ * Provides the prefix that should be used for the plugin logger. ++ * The logger prefix allows plugins to overwrite the usual default of the logger prefix, which is the name of the ++ * plugin. ++ * ++ * @return the specific overwrite of the logger prefix as defined by the plugin. If the plugin did not define a ++ * custom logger prefix, this method will return null ++ */ ++ @Nullable ++ String getLoggerPrefix(); ++ ++ /** ++ * Provides a list of dependencies that are required for this plugin to load. ++ * The list holds the unique identifiers, following the constraints laid out in {@link #getName()}, of the ++ * dependencies. ++ *

++ * If any of the dependencies defined by this list are not installed on the server, this plugin will fail to load. ++ * ++ * @return an immutable list of required dependency names ++ */ ++ @NotNull ++ List getPluginDependencies(); ++ ++ /** ++ * Provides a list of dependencies that are used but not required by this plugin. ++ * The list holds the unique identifiers, following the constraints laid out in {@link #getName()}, of the soft ++ * dependencies. ++ *

++ * If these dependencies are installed on the server, they will be loaded first and supplied as dependencies to this ++ * plugin, however the plugin will load even if these dependencies are not installed. ++ * ++ * @return immutable list of soft dependencies ++ */ ++ @NotNull ++ List getPluginSoftDependencies(); ++ ++ /** ++ * Provides a list of plugins that should be loaded before this plugin is loaded. ++ * The list holds the unique identifiers, following the constraints laid out in {@link #getName()}, of the ++ * plugins that should be loaded before the plugin described by this plugin meta. ++ *

++ * The plugins referenced in the list provided by this method are not considered dependencies of this plugin and ++ * are hence not available to the plugin at runtime. They merely load before this plugin. ++ * ++ * @return immutable list of plugins to load before this plugin ++ */ ++ @NotNull ++ List getLoadBeforePlugins(); ++ ++ /** ++ * Returns the list of plugins/dependencies that this plugin provides. ++ * The list holds the unique identifiers, following the constraints laid out in {@link #getName()}, for each plugin ++ * it provides the expected classes for. ++ * ++ * @return immutable list of provided plugins/dependencies ++ */ ++ @NotNull ++ List getProvidedPlugins(); ++ ++ /** ++ * Provides the list of authors that are credited with creating this plugin. ++ * The author names are in no particular format. ++ * ++ * @return an immutable list of the plugin's authors ++ */ ++ @NotNull ++ List getAuthors(); ++ ++ /** ++ * Provides a list of contributors that contributed to the plugin but are not considered authors. ++ * The names of the contributors are in no particular format. ++ * ++ * @return an immutable list of the plugin's contributors ++ */ ++ @NotNull ++ List getContributors(); ++ ++ /** ++ * Gives a human-friendly description of the functionality the plugin ++ * provides. ++ * ++ * @return description or null if the plugin did not define a human readable description. ++ */ ++ @Nullable ++ String getDescription(); ++ ++ /** ++ * Provides the website for the plugin or the plugin's author. ++ * The defined string value is not guaranteed to be in the form of a url. ++ * ++ * @return a string representation of the website that serves as the main hub for this plugin/its author. ++ */ ++ @Nullable ++ String getWebsite(); ++ ++ /** ++ * Provides the list of permissions that are defined via the plugin meta instance. ++ * ++ * @return an immutable list of permissions ++ */ ++ // TODO: Do we even want this? Why not just use the bootstrapper ++ @NotNull ++ List getPermissions(); ++ ++ /** ++ * Provides the default values that apply to the permissions defined in this plugin meta. ++ * ++ * @return the bukkit permission default container. ++ * @see #getPermissions() ++ */ ++ // TODO: Do we even want this? Why not just use the bootstrapper ++ @NotNull ++ PermissionDefault getPermissionDefault(); ++ ++ /** ++ * Gets the api version that this plugin supports. ++ * Nullable if this version is not specified, and should be ++ * considered legacy (spigot plugins only) ++ * ++ * @return the version string made up of the major and minor version (e.g. 1.18 or 1.19). Minor versions like 1.18.2 ++ * are unified to their major release version (in this example 1.18) ++ */ ++ @Nullable ++ String getAPIVersion(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/configuration/package-info.java b/src/main/java/io/papermc/paper/plugin/configuration/package-info.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ddb3076124365d0d1a5caa32d4dcb1f4314dd7ae +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/configuration/package-info.java +@@ -0,0 +1,8 @@ ++/** ++ * The paper configuration package contains the new java representation of a plugins configuration file. ++ * While most values are described in detail on {@link io.papermc.paper.plugin.configuration.PluginMeta}, a full ++ * entry on the paper contains a full and extensive example of possible configurations of the paper-plugin.yml. ++ * @see Extensive documentation and examples of the paper-plugin.yml ++ * ++ */ ++package io.papermc.paper.plugin.configuration; +diff --git a/src/main/java/io/papermc/paper/plugin/loader/PluginClasspathBuilder.java b/src/main/java/io/papermc/paper/plugin/loader/PluginClasspathBuilder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..28cbc09b7c1ded1f4515969cef4a669adac85703 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/PluginClasspathBuilder.java +@@ -0,0 +1,38 @@ ++package io.papermc.paper.plugin.loader; ++ ++import io.papermc.paper.plugin.bootstrap.PluginProviderContext; ++import io.papermc.paper.plugin.loader.library.ClassPathLibrary; ++import io.papermc.paper.plugin.loader.library.LibraryStore; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A mutable builder that may be used to collect and register all {@link ClassPathLibrary} instances a ++ * {@link PluginLoader} aims to provide to its plugin at runtime. ++ */ ++@ApiStatus.NonExtendable ++@ApiStatus.Experimental ++public interface PluginClasspathBuilder { ++ ++ /** ++ * Adds a new classpath library to this classpath builder. ++ *

++ * As a builder, this method does not invoke {@link ClassPathLibrary#register(LibraryStore)} and ++ * may hence be run without invoking potential IO performed by a {@link ClassPathLibrary} during resolution. ++ *

++ * The paper api provides pre implemented {@link ClassPathLibrary} types that allow easy inclusion of existing ++ * libraries on disk or on remote maven repositories. ++ * ++ * @param classPathLibrary the library instance to add to this builder ++ * @return self ++ * @see io.papermc.paper.plugin.loader.library.impl.JarLibrary ++ * @see io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver ++ */ ++ @NotNull ++ @Contract("_ -> this") ++ PluginClasspathBuilder addLibrary(@NotNull ClassPathLibrary classPathLibrary); ++ ++ @NotNull ++ PluginProviderContext getContext(); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/PluginLoader.java b/src/main/java/io/papermc/paper/plugin/loader/PluginLoader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c9e31f78ff6ff969436c6d99755845786c4d383f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/PluginLoader.java +@@ -0,0 +1,30 @@ ++package io.papermc.paper.plugin.loader; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A plugin loader is responsible for creating certain aspects of a plugin before it is created. ++ *

++ * The goal of the plugin loader is the creation of an expected/dynamic environment for the plugin to load into. ++ * This, as of right now, only applies to creating the expected classpath for the plugin, e.g. supplying external ++ * libraries to the plugin. ++ *

++ * It should be noted that this class will be called from a different classloader, this will cause any static values ++ * set in this class/any other classes loaded not to persist when the plugin loads. ++ */ ++@ApiStatus.OverrideOnly ++@ApiStatus.Experimental ++public interface PluginLoader { ++ ++ /** ++ * Called by the server to allows plugins to configure the runtime classpath that the plugin is run on. ++ * This allows plugin loaders to configure dependencies for the plugin where jars can be downloaded or ++ * provided during runtime. ++ * ++ * @param classpathBuilder a mutable classpath builder that may be used to register custom runtime dependencies ++ * for the plugin the loader was registered for. ++ */ ++ void classloader(@NotNull PluginClasspathBuilder classpathBuilder); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/ClassPathLibrary.java b/src/main/java/io/papermc/paper/plugin/loader/library/ClassPathLibrary.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1347b535d90c2c281c184d0459e7ac59c0350c9f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/ClassPathLibrary.java +@@ -0,0 +1,20 @@ ++package io.papermc.paper.plugin.loader.library; ++ ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * The classpath library interface represents libraries that are capable of registering themselves via ++ * {@link #register(LibraryStore)} on any given {@link LibraryStore}. ++ */ ++public interface ClassPathLibrary { ++ ++ /** ++ * Called to register the library this class path library represents into the passed library store. ++ * This method may either be implemented by the plugins themselves if they need complex logic, or existing ++ * API exposed implementations of this interface may be used. ++ * ++ * @param store the library store instance to register this library into ++ * @throws LibraryLoadingException if library loading failed for this classpath library ++ */ ++ void register(@NotNull LibraryStore store) throws LibraryLoadingException; ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/LibraryLoadingException.java b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryLoadingException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..79ba423a364b50588f3ee87fdc69155cb8e64ad0 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryLoadingException.java +@@ -0,0 +1,15 @@ ++package io.papermc.paper.plugin.loader.library; ++ ++/** ++ * Indicates that an exception has occured while loading a library. ++ */ ++public class LibraryLoadingException extends RuntimeException { ++ ++ public LibraryLoadingException(String s) { ++ super(s); ++ } ++ ++ public LibraryLoadingException(String s, Exception e) { ++ super(s, e); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/LibraryStore.java b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryStore.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0546fa1e9dcd7155086a8650806a8c086b6fc458 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/LibraryStore.java +@@ -0,0 +1,26 @@ ++package io.papermc.paper.plugin.loader.library; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++import java.nio.file.Path; ++ ++/** ++ * Represents a storage that stores library jars. ++ *

++ * The library store api allows plugins to register specific dependencies into their runtime classloader when their ++ * {@link io.papermc.paper.plugin.loader.PluginLoader} is processed. ++ * ++ * @see io.papermc.paper.plugin.loader.PluginLoader ++ */ ++@ApiStatus.Internal ++public interface LibraryStore { ++ ++ /** ++ * Adds the provided library path to this library store. ++ * ++ * @param library path to the libraries jar file on the disk ++ */ ++ void addLibrary(@NotNull Path library); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/impl/JarLibrary.java b/src/main/java/io/papermc/paper/plugin/loader/library/impl/JarLibrary.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3327595d154700890c862a2ced5eff93da4bd634 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/impl/JarLibrary.java +@@ -0,0 +1,45 @@ ++package io.papermc.paper.plugin.loader.library.impl; ++ ++import io.papermc.paper.plugin.loader.library.ClassPathLibrary; ++import io.papermc.paper.plugin.loader.library.LibraryLoadingException; ++import io.papermc.paper.plugin.loader.library.LibraryStore; ++import org.jetbrains.annotations.NotNull; ++ ++import java.nio.file.Files; ++import java.nio.file.Path; ++ ++/** ++ * A simple jar library implementation of the {@link ClassPathLibrary} that allows {@link io.papermc.paper.plugin.loader.PluginLoader}s to ++ * append a jar stored on the local file system into their runtime classloader. ++ *

++ * An example creation of the jar library type may look like this: ++ *

{@code
++ *   final JarLibrary customLibrary = new JarLibrary(Path.of("libs/custom-library-1.24.jar"));
++ * }
++ * resulting in a jar library that provides the jar at {@code libs/custom-library-1.24.jar} to the plugins classloader ++ * at runtime. ++ *

++ * The jar library implementation will error if file exists at the specified path. ++ */ ++public class JarLibrary implements ClassPathLibrary { ++ ++ private final Path path; ++ ++ /** ++ * Creates a new jar library that references the jar file found at the provided path. ++ * ++ * @param path the path, relative to the JVMs start directory. ++ */ ++ public JarLibrary(@NotNull Path path) { ++ this.path = path; ++ } ++ ++ @Override ++ public void register(@NotNull LibraryStore store) throws LibraryLoadingException { ++ if (Files.notExists(this.path)) { ++ throw new LibraryLoadingException("Could not find library at " + this.path); ++ } ++ ++ store.addLibrary(this.path); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e3e902a708a760be167cb1bba8e845c5fa5b9141 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java +@@ -0,0 +1,132 @@ ++package io.papermc.paper.plugin.loader.library.impl; ++ ++import io.papermc.paper.plugin.loader.library.ClassPathLibrary; ++import io.papermc.paper.plugin.loader.library.LibraryLoadingException; ++import io.papermc.paper.plugin.loader.library.LibraryStore; ++import org.apache.maven.repository.internal.MavenRepositorySystemUtils; ++import org.eclipse.aether.DefaultRepositorySystemSession; ++import org.eclipse.aether.RepositorySystem; ++import org.eclipse.aether.collection.CollectRequest; ++import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; ++import org.eclipse.aether.graph.Dependency; ++import org.eclipse.aether.impl.DefaultServiceLocator; ++import org.eclipse.aether.repository.LocalRepository; ++import org.eclipse.aether.repository.RemoteRepository; ++import org.eclipse.aether.repository.RepositoryPolicy; ++import org.eclipse.aether.resolution.ArtifactResult; ++import org.eclipse.aether.resolution.DependencyRequest; ++import org.eclipse.aether.resolution.DependencyResolutionException; ++import org.eclipse.aether.resolution.DependencyResult; ++import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; ++import org.eclipse.aether.spi.connector.transport.TransporterFactory; ++import org.eclipse.aether.transfer.AbstractTransferListener; ++import org.eclipse.aether.transfer.TransferCancelledException; ++import org.eclipse.aether.transfer.TransferEvent; ++import org.eclipse.aether.transport.http.HttpTransporterFactory; ++import org.jetbrains.annotations.NotNull; ++ ++import java.io.File; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++/** ++ * The maven library resolver acts as a resolver for yet to be resolved jar libraries that may be pulled from a ++ * remote maven repository. ++ *

++ * Plugins may create and configure a {@link MavenLibraryResolver} by creating a new one and registering both ++ * a dependency artifact that should be resolved to a library at runtime and the repository it is found in. ++ * An example of this would be the inclusion of the jooq library for typesafe SQL queries: ++ *

{@code
++ * MavenLibraryResolver resolver = new MavenLibraryResolver();
++ * resolver.addDependency(new Dependency(new DefaultArtifact("org.jooq:jooq:3.17.7"), null));
++ * resolver.addRepository(new RemoteRepository.Builder(
++ *     "central", "default", "https://repo1.maven.org/maven2/"
++ * ).build());
++ * }
++ * ++ * Plugins may create and register a {@link MavenLibraryResolver} after configuring it. ++ */ ++public class MavenLibraryResolver implements ClassPathLibrary { ++ ++ private static final Logger logger = Logger.getLogger("MavenLibraryResolver"); ++ ++ private final RepositorySystem repository; ++ private final DefaultRepositorySystemSession session; ++ private final List repositories = new ArrayList<>(); ++ private final List dependencies = new ArrayList<>(); ++ ++ /** ++ * Creates a new maven library resolver instance. ++ *

++ * The created instance will use the servers {@code libraries} folder to cache fetched libraries in. ++ * Notably, the resolver is created without any repository, not even maven central. ++ * It is hence crucial that plugins which aim to use this api register all required repositories before ++ * submitting the {@link MavenLibraryResolver} to the {@link io.papermc.paper.plugin.loader.PluginClasspathBuilder}. ++ */ ++ public MavenLibraryResolver() { ++ DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); ++ locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); ++ locator.addService(TransporterFactory.class, HttpTransporterFactory.class); ++ ++ this.repository = locator.getService(RepositorySystem.class); ++ this.session = MavenRepositorySystemUtils.newSession(); ++ ++ this.session.setChecksumPolicy(RepositoryPolicy.CHECKSUM_POLICY_FAIL); ++ this.session.setLocalRepositoryManager(this.repository.newLocalRepositoryManager(this.session, new LocalRepository("libraries"))); ++ this.session.setTransferListener(new AbstractTransferListener() { ++ @Override ++ public void transferInitiated(@NotNull TransferEvent event) throws TransferCancelledException { ++ logger.log(Level.INFO, "Downloading {0}", event.getResource().getRepositoryUrl() + event.getResource().getResourceName()); ++ } ++ }); ++ this.session.setReadOnly(); ++ } ++ ++ /** ++ * Adds the provided dependency to the library resolver. ++ * The artifact from the first valid repository matching the passed dependency will be chosen. ++ * ++ * @param dependency the definition of the dependency the maven library resolver should resolve when running ++ * @see MavenLibraryResolver#addRepository(RemoteRepository) ++ */ ++ public void addDependency(@NotNull Dependency dependency) { ++ this.dependencies.add(dependency); ++ } ++ ++ /** ++ * Adds the provided repository to the library resolver. ++ * The order in which these are added does matter, as dependency resolving will start at the first added ++ * repository. ++ * ++ * @param remoteRepository the configuration that defines the maven repository this library resolver should fetch ++ * dependencies from ++ */ ++ public void addRepository(@NotNull RemoteRepository remoteRepository) { ++ this.repositories.add(remoteRepository); ++ } ++ ++ /** ++ * Resolves the provided dependencies and adds them to the library store. ++ * ++ * @param store the library store the then resolved and downloaded dependencies are registered into ++ * @throws LibraryLoadingException if resolving a dependency failed ++ */ ++ @Override ++ public void register(@NotNull LibraryStore store) throws LibraryLoadingException { ++ List repos = this.repository.newResolutionRepositories(this.session, this.repositories); ++ ++ DependencyResult result; ++ try { ++ result = this.repository.resolveDependencies(this.session, new DependencyRequest(new CollectRequest((Dependency) null, this.dependencies, repos), null)); ++ } catch (DependencyResolutionException ex) { ++ throw new LibraryLoadingException("Error resolving libraries", ex); ++ } ++ ++ for (ArtifactResult artifact : result.getArtifactResults()) { ++ File file = artifact.getArtifact().getFile(); ++ store.addLibrary(file.toPath()); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/ClassLoaderAccess.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/ClassLoaderAccess.java +new file mode 100644 +index 0000000000000000000000000000000000000000..64e46fdfa4d404cb08c67a456e5990b729296b98 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/ClassLoaderAccess.java +@@ -0,0 +1,34 @@ ++package io.papermc.paper.plugin.provider.classloader; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * The class loader access interface is an internal representation of a class accesses' ability to see types ++ * from other {@link ConfiguredPluginClassLoader}. ++ *

++ * An example of this would be a class loader access representing a plugin. The class loader access in that case would ++ * only return {@code true} on calls for {@link #canAccess(ConfiguredPluginClassLoader)} if the passed class loader ++ * is owned by a direct or transitive dependency of the plugin, preventing the plugin for accidentally discovering and ++ * using class types that are supplied by plugins/libraries the plugin did not actively define as a dependency. ++ */ ++@ApiStatus.Internal ++public interface ClassLoaderAccess { ++ ++ /** ++ * Evaluates if this class loader access is allowed to access types provided by the passed {@link ++ * ConfiguredPluginClassLoader}. ++ *

++ * This interface method does not offer any further contracts on the interface level, as the logic to determine ++ * what class loaders this class loader access is allowed to retrieve types from depends heavily on the type of ++ * access. ++ * Legacy spigot types for example may access any class loader available on the server, while modern paper plugins ++ * are properly limited to their dependency tree. ++ * ++ * @param classLoader the class loader for which access should be evaluated ++ * @return a plain boolean flag, {@code true} indicating that this class loader access is allowed to access types ++ * from the passed configured plugin class loader, {@code false} indicating otherwise. ++ */ ++ boolean canAccess(ConfiguredPluginClassLoader classLoader); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/ConfiguredPluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/ConfiguredPluginClassLoader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a15e7474eb8eb1196f69070b7cf7fd5af6100f68 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/ConfiguredPluginClassLoader.java +@@ -0,0 +1,55 @@ ++package io.papermc.paper.plugin.provider.classloader; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++import java.io.Closeable; ++ ++/** ++ * The configured plugin class loader represents an internal abstraction over the classloaders used by the server ++ * to load and access a plugins classes during runtime. ++ *

++ * It implements {@link Closeable} to define the ability to shutdown and close the classloader that implements this ++ * interface. ++ */ ++@ApiStatus.Internal ++public interface ConfiguredPluginClassLoader extends Closeable { ++ ++ /** ++ * Provides the configuration of the plugin that this plugin classloader provides type access to. ++ * ++ * @return the plugin meta instance, holding all meta information about the plugin instance. ++ */ ++ PluginMeta getConfiguration(); ++ ++ /** ++ * Attempts to load a class from this plugin class loader using the passed fully qualified name. ++ * This lookup logic can be configured through the following parameters to define how wide or how narrow the ++ * class lookup should be. ++ * ++ * @param name the fully qualified name of the class to load ++ * @param resolve whether the class should be resolved if needed or not ++ * @param checkGlobal whether this lookup should check transitive dependencies, including either the legacy spigot ++ * global class loader or the paper {@link PluginClassLoaderGroup} ++ * @param checkLibraries whether the defined libraries should be checked for the class or not ++ * @return the class found at the fully qualified class name passed under the passed restrictions ++ * @throws ClassNotFoundException if the class could not be found considering the passed restrictions ++ * @see ClassLoader#loadClass(String) ++ * @see Class#forName(String, boolean, ClassLoader) ++ */ ++ Class loadClass(@NotNull String name, ++ boolean resolve, ++ boolean checkGlobal, ++ boolean checkLibraries) throws ClassNotFoundException; ++ ++ /** ++ * Initializes both this configured plugin class loader and the java plugin passed to link to each other. ++ * This logic is to be called exactly once when the initial setup between the class loader and the instantiated ++ * {@link JavaPlugin} is loaded. ++ * ++ * @param plugin the {@link JavaPlugin} that should be interlinked with this class loader. ++ */ ++ void init(JavaPlugin plugin); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorage.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fefc87d5ffd36b848a7adb326a3a741e9edb28df +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorage.java +@@ -0,0 +1,92 @@ ++package io.papermc.paper.plugin.provider.classloader; ++ ++import org.bukkit.plugin.java.PluginClassLoader; ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * The plugin classloader storage is an internal type that is used to manage existing classloaders on the server. ++ *

++ * The paper classloader storage is also responsible for storing added {@link ConfiguredPluginClassLoader}s into ++ * {@link PluginClassLoaderGroup}s, via {@link #registerOpenGroup(ConfiguredPluginClassLoader)}, ++ * {@link #registerSpigotGroup(PluginClassLoader)} and {@link ++ * #registerAccessBackedGroup(ConfiguredPluginClassLoader, ClassLoaderAccess)}. ++ *

++ * Groups are differentiated into the global group or plugin owned groups. ++ *

    ++ *
  • The global group holds all registered class loaders and merely exists to maintain backwards compatibility with ++ * spigots legacy classloader handling.
  • ++ *
  • The plugin groups only contains the classloaders that each plugin has access to and hence serves to properly ++ * separates unrelated classloaders.
  • ++ *
++ */ ++@ApiStatus.Internal ++public interface PaperClassLoaderStorage { ++ ++ /** ++ * Access to the shared instance of the {@link PaperClassLoaderStorageAccess}. ++ * ++ * @return the singleton instance of the {@link PaperClassLoaderStorage} used throughout the server ++ */ ++ static PaperClassLoaderStorage instance() { ++ return PaperClassLoaderStorageAccess.INSTANCE; ++ } ++ ++ /** ++ * Registers a legacy spigot {@link PluginClassLoader} into the loader storage, creating a group wrapping ++ * the single plugin class loader with transitive access to the global group. ++ * ++ * @param pluginClassLoader the legacy spigot plugin class loader to register ++ * @return the group the plugin class loader was placed into ++ */ ++ PluginClassLoaderGroup registerSpigotGroup(PluginClassLoader pluginClassLoader); ++ ++ /** ++ * Registers a paper configured plugin classloader into a new open group, with full access to the global ++ * plugin class loader group. ++ *

++ * This method hence allows the configured plugin class loader to access all other class loaders registered in this ++ * storage. ++ * ++ * @param classLoader the configured plugin class loader to register ++ * @return the group the plugin class loader was placed into ++ */ ++ PluginClassLoaderGroup registerOpenGroup(ConfiguredPluginClassLoader classLoader); ++ ++ /** ++ * Registers a paper configured classloader into a new, access backed group. ++ * The access backed classloader group, different from an open group, only has access to the classloaders ++ * the passed {@link ClassLoaderAccess} grants access to. ++ * ++ * @param classLoader the configured plugin class loader to register ++ * @param access the class loader access that defines what other classloaders the passed plugin class loader ++ * should be granted access to. ++ * @return the group the plugin class loader was placed into. ++ */ ++ PluginClassLoaderGroup registerAccessBackedGroup(ConfiguredPluginClassLoader classLoader, ClassLoaderAccess access); ++ ++ /** ++ * Unregisters a configured class loader from this storage. ++ * This removes the passed class loaders from any group it may have been a part of, including the global group. ++ *

++ * Note: this method is highly discouraged from being used, as mutation of the classloaders at runtime ++ * is not encouraged ++ * ++ * @param configuredPluginClassLoader the class loader to remove from this storage. ++ */ ++ void unregisterClassloader(ConfiguredPluginClassLoader configuredPluginClassLoader); ++ ++ /** ++ * Registers a configured plugin class loader directly into the global group without adding it to ++ * any existing groups. ++ *

++ * Note: this method unsafely injects the plugin classloader directly into the global group, which bypasses the ++ * group structure paper's plugin API introduced. This method should hence be used with caution. ++ * ++ * @param pluginLoader the configured plugin classloader instance that should be registered directly into the global ++ * group. ++ * @return a simple boolean flag, {@code true} if the classloader was registered or {@code false} if the classloader ++ * was already part of the global group. ++ */ ++ boolean registerUnsafePlugin(ConfiguredPluginClassLoader pluginLoader); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorageAccess.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorageAccess.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2c0e5ba6f8eba7a632180491843071b8a8558e56 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/PaperClassLoaderStorageAccess.java +@@ -0,0 +1,17 @@ ++package io.papermc.paper.plugin.provider.classloader; ++ ++import net.kyori.adventure.util.Services; ++ ++/** ++ * The paper classloader storage access acts as the holder for the server provided implementation of the ++ * {@link PaperClassLoaderStorage} interface. ++ */ ++class PaperClassLoaderStorageAccess { ++ ++ /** ++ * The shared instance of the {@link PaperClassLoaderStorage}, supplied through the {@link java.util.ServiceLoader} ++ * by the server. ++ */ ++ static final PaperClassLoaderStorage INSTANCE = Services.service(PaperClassLoaderStorage.class).orElseThrow(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/classloader/PluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/provider/classloader/PluginClassLoaderGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..885151cb932d9b8c09a7887edc879e154225f416 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/classloader/PluginClassLoaderGroup.java +@@ -0,0 +1,65 @@ ++package io.papermc.paper.plugin.provider.classloader; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * A plugin classloader group represents a group of classloaders that a plugins classloader may access. ++ *

++ * An example of this would be a classloader group that holds all direct and transitive dependencies a plugin declared, ++ * allowing a plugins classloader to access classes included in these dependencies via this group. ++ */ ++@ApiStatus.Internal ++public interface PluginClassLoaderGroup { ++ ++ /** ++ * Attempts to find/load a class from this plugin class loader group using the passed fully qualified name ++ * in any of the classloaders that are part of this group. ++ *

++ * The lookup order across the contained loaders is not defined on the API level and depends purely on the ++ * implementation. ++ * ++ * @param name the fully qualified name of the class to load ++ * @param resolve whether the class should be resolved if needed or not ++ * @param requester plugin classloader that is requesting the class from this loader group ++ * @return the class found at the fully qualified class name passed. If the class could not be found, {@code null} ++ * will be returned. ++ * @see ConfiguredPluginClassLoader#loadClass(String, boolean, boolean, boolean) ++ */ ++ @Nullable ++ Class getClassByName(String name, boolean resolve, ConfiguredPluginClassLoader requester); ++ ++ /** ++ * Removes a configured plugin classloader from this class loader group. ++ * If the classloader is not currently in the list, this method will simply do nothing. ++ * ++ * @param configuredPluginClassLoader the plugin classloader to remove from the group ++ */ ++ @Contract(mutates = "this") ++ void remove(ConfiguredPluginClassLoader configuredPluginClassLoader); ++ ++ /** ++ * Adds the passed plugin classloader to this group, allowing this group to use it during ++ * {@link #getClassByName(String, boolean, ConfiguredPluginClassLoader)} lookups. ++ *

++ * This method does not query the {@link ClassLoaderAccess} (exposed via {@link #getAccess()}) to ensure ++ * if this group has access to the class loader passed. ++ * ++ * @param configuredPluginClassLoader the plugin classloader to add to this group. ++ */ ++ @Contract(mutates = "this") ++ void add(ConfiguredPluginClassLoader configuredPluginClassLoader); ++ ++ /** ++ * Provides the class loader access that guards and defines the content of this classloader group. ++ * While not guaranteed contractually (see {@link #add(ConfiguredPluginClassLoader)}), the access generally is ++ * responsible for defining which {@link ConfiguredPluginClassLoader}s should be part of this group and which ones ++ * should not. ++ * ++ * @return the classloader access governing which classloaders should be part of this group and which ones should ++ * not. ++ */ ++ ClassLoaderAccess getAccess(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/entrypoint/DependencyContext.java b/src/main/java/io/papermc/paper/plugin/provider/entrypoint/DependencyContext.java +new file mode 100644 +index 0000000000000000000000000000000000000000..44d630c3eb2670c36134b9907519dc986b3761b4 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/entrypoint/DependencyContext.java +@@ -0,0 +1,48 @@ ++package io.papermc.paper.plugin.provider.entrypoint; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * A dependency context is a read-only abstraction of a type/concept that can resolve dependencies between plugins. ++ *

++ * This may for example be the server wide plugin manager itself, capable of validating if a dependency exists between ++ * two {@link PluginMeta} instances, however the implementation is not limited to such a concrete use-case. ++ */ ++@ApiStatus.Internal ++public interface DependencyContext { ++ ++ /** ++ * Computes if the passed {@link PluginMeta} defined the passed dependency as a transitive dependency. ++ * A transitive dependency, as implied by its name, may not have been configured directly by the passed plugin ++ * but could also simply be a dependency of a dependency. ++ *

++ * A simple example of this method would be ++ *

{@code
++     * dependencyContext.isTransitiveDependency(pluginMetaA, pluginMetaC);
++     * }
++ * which would return {@code true} if {@code pluginMetaA} directly or indirectly depends on {@code pluginMetaC}. ++ * ++ * @param plugin the plugin meta this computation should consider the requester of the dependency status for the ++ * passed potential dependency. ++ * @param depend the potential transitive dependency of the {@code plugin} parameter. ++ * @return a simple boolean flag indicating if {@code plugin} considers {@code depend} as a transitive dependency. ++ */ ++ boolean isTransitiveDependency(@NotNull PluginMeta plugin, @NotNull PluginMeta depend); ++ ++ /** ++ * Computes if this dependency context is aware of a dependency that provides/matches the passed identifier. ++ *

++ * A dependency in this methods context is any dependable artefact. It does not matter if anything actually depends ++ * on said artefact, its mere existence as a potential dependency is enough for this method to consider it a ++ * dependency. If this dependency context is hence aware of an artefact with the matching identifier, this ++ * method returns {@code true}. ++ * ++ * @param pluginIdentifier the unique identifier of the dependency with which to probe this dependency context. ++ * @return a plain boolean flag indicating if this dependency context is aware of a potential dependency with the ++ * passed identifier. ++ */ ++ boolean hasDependency(@NotNull String pluginIdentifier); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/util/DummyBukkitPluginLoader.java b/src/main/java/io/papermc/paper/plugin/provider/util/DummyBukkitPluginLoader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c912ee020937f1ce16481c108e332e45acba5ff9 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/util/DummyBukkitPluginLoader.java +@@ -0,0 +1,60 @@ ++package io.papermc.paper.plugin.provider.util; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.event.Listener; ++import org.bukkit.plugin.InvalidDescriptionException; ++import org.bukkit.plugin.InvalidPluginException; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.PluginLoader; ++import org.bukkit.plugin.RegisteredListener; ++import org.bukkit.plugin.UnknownDependencyException; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++import java.io.File; ++import java.util.Map; ++import java.util.Set; ++import java.util.regex.Pattern; ++ ++/** ++ * A purely internal type that implements the now deprecated {@link PluginLoader} after the implementation ++ * of papers new plugin system. ++ * ++ * @param plugin the loaded plugin that should be wrapped by this NOOP implementation ++ */ ++@ApiStatus.Internal ++public record DummyBukkitPluginLoader(Plugin plugin) implements PluginLoader { ++ ++ ++ @Override ++ public @NotNull Plugin loadPlugin(@NotNull File file) throws InvalidPluginException, UnknownDependencyException { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull PluginDescriptionFile getPluginDescription(@NotNull File file) throws InvalidDescriptionException { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull Pattern[] getPluginFileFilters() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public @NotNull Map, Set> createRegisteredListeners(@NotNull Listener listener, @NotNull Plugin plugin) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public void enablePlugin(@NotNull Plugin plugin) { ++ Bukkit.getPluginManager().enablePlugin(plugin); ++ } ++ ++ @Override ++ public void disablePlugin(@NotNull Plugin plugin) { ++ Bukkit.getPluginManager().disablePlugin(plugin); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/util/ProviderUtil.java b/src/main/java/io/papermc/paper/plugin/provider/util/ProviderUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6bf3d212a6156ad9ab0e82d1ca0a04f83f6e4b83 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/util/ProviderUtil.java +@@ -0,0 +1,78 @@ ++package io.papermc.paper.plugin.provider.util; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++/** ++ * An internal utility type that holds logic for loading a provider-like type from a classloaders. ++ * Provides, at least in the context of this utility, define themselves as implementations of a specific parent ++ * interface/type, e.g. {@link org.bukkit.plugin.java.JavaPlugin} and implement a no-args constructor. ++ */ ++@ApiStatus.Internal ++public class ProviderUtil { ++ ++ /** ++ * Loads the class found at the provided fully qualified class name from the passed classloader, creates a new ++ * instance of it using the no-args constructor, that should exist as per this method contract, and casts it to the ++ * provided parent type. ++ * ++ * @param clazz the fully qualified name of the class to load ++ * @param classType the parent type that the created object found at the {@code clazz} name should be cast to ++ * @param loader the loader from which the class should be loaded ++ * @param the generic type of the parent class the created object will be cast to ++ * @return the object instantiated from the class found at the provided FQN, cast to the parent type ++ */ ++ @NotNull ++ public static T loadClass(@NotNull String clazz, @NotNull Class classType, @NotNull ClassLoader loader) { ++ return loadClass(clazz, classType, loader, null); ++ } ++ ++ /** ++ * Loads the class found at the provided fully qualified class name from the passed classloader, creates a new ++ * instance of it using the no-args constructor, that should exist as per this method contract, and casts it to the ++ * provided parent type. ++ * ++ * @param clazz the fully qualified name of the class to load ++ * @param classType the parent type that the created object found at the {@code clazz} name should be cast to ++ * @param loader the loader from which the class should be loaded ++ * @param onError a runnable that is executed before any unknown exception is raised through a sneaky throw. ++ * @param the generic type of the parent class the created object will be cast to ++ * @return the object instantiated from the class found at the provided fully qualified class name, cast to the ++ * parent type ++ */ ++ @NotNull ++ public static T loadClass(@NotNull String clazz, @NotNull Class classType, @NotNull ClassLoader loader, @Nullable Runnable onError) { ++ try { ++ T clazzInstance; ++ ++ try { ++ Class jarClass = Class.forName(clazz, true, loader); ++ ++ Class pluginClass; ++ try { ++ pluginClass = jarClass.asSubclass(classType); ++ } catch (ClassCastException ex) { ++ throw new ClassCastException("class '%s' does not extend '%s'".formatted(clazz, classType)); ++ } ++ ++ clazzInstance = pluginClass.getDeclaredConstructor().newInstance(); ++ } catch (IllegalAccessException exception) { ++ throw new RuntimeException("No public constructor"); ++ } catch (InstantiationException exception) { ++ throw new RuntimeException("Abnormal class instantiation", exception); ++ } ++ ++ return clazzInstance; ++ } catch (Throwable e) { ++ if (onError != null) { ++ onError.run(); ++ } ++ SneakyThrow.sneaky(e); ++ } ++ ++ throw new AssertionError(); // Shouldn't happen ++ } ++ ++} +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 876072a6c91bd02c9c7de53556419b8e1ac48f27..dc9a4f12d9f05a3ae7c9f1c7648123e4b3dfd115 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -96,4 +96,14 @@ public interface UnsafeValues { + String getTranslationKey(EntityType entityType); + + String getTranslationKey(ItemStack itemStack); ++ ++ // Paper start ++ @Deprecated(forRemoval = true) ++ boolean isSupportedApiVersion(String apiVersion); ++ ++ @Deprecated(forRemoval = true) ++ static boolean isLegacyPlugin(org.bukkit.plugin.Plugin plugin) { ++ return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/command/PluginCommand.java b/src/main/java/org/bukkit/command/PluginCommand.java +index 1dbbc244309043b18c1d71707c4fb066c0d0e02d..551c5af6a7bfa2268cbc63be8e70d129bccaa912 100644 +--- a/src/main/java/org/bukkit/command/PluginCommand.java ++++ b/src/main/java/org/bukkit/command/PluginCommand.java +@@ -14,7 +14,7 @@ public final class PluginCommand extends Command implements PluginIdentifiableCo + private CommandExecutor executor; + private TabCompleter completer; + +- protected PluginCommand(@NotNull String name, @NotNull Plugin owner) { ++ PluginCommand(@NotNull String name, @NotNull Plugin owner) { + super(name); + this.executor = owner; + this.owningPlugin = owner; +diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java +index e195e74c48c69047aa825b75fad95419c505b41f..53f28c9e6843991486a576d41b6641c170589807 100644 +--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java ++++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java +@@ -34,7 +34,7 @@ public class SimpleCommandMap implements CommandMap { + private void setDefaultCommands() { + register("bukkit", new VersionCommand("version")); + register("bukkit", new ReloadCommand("reload")); +- register("bukkit", new PluginsCommand("plugins")); ++ //register("bukkit", new PluginsCommand("plugins")); // Paper + register("bukkit", new TimingsCommand("timings")); + } + +diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java +index b37938745f916b5f0111b07b1a1c97527f026e9d..8c76716249e44ed8bf6be94c1f5c7b6d9bb35be2 100644 +--- a/src/main/java/org/bukkit/plugin/Plugin.java ++++ b/src/main/java/org/bukkit/plugin/Plugin.java +@@ -30,10 +30,21 @@ public interface Plugin extends TabExecutor { + * Returns the plugin.yaml file containing the details for this plugin + * + * @return Contents of the plugin.yaml file ++ * @deprecated May be inaccurate due to different plugin implementations. ++ * @see Plugin#getPluginMeta() + */ ++ @Deprecated // Paper + @NotNull + public PluginDescriptionFile getDescription(); + ++ // Paper start ++ /** ++ * Gets the plugin meta for this plugin. ++ * @return configuration ++ */ ++ @NotNull ++ io.papermc.paper.plugin.configuration.PluginMeta getPluginMeta(); ++ // Paper end + /** + * Gets a {@link FileConfiguration} for this plugin, read through + * "config.yml" +@@ -94,6 +105,7 @@ public interface Plugin extends TabExecutor { + * + * @return PluginLoader that controls this plugin + */ ++ @Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future + @NotNull + public PluginLoader getPluginLoader(); + +diff --git a/src/main/java/org/bukkit/plugin/PluginBase.java b/src/main/java/org/bukkit/plugin/PluginBase.java +index 94f8ceb965cecb5669a84a0ec61c0f706c2a2673..e773db6da357ad210eb24d4c389af2dc84ce450a 100644 +--- a/src/main/java/org/bukkit/plugin/PluginBase.java ++++ b/src/main/java/org/bukkit/plugin/PluginBase.java +@@ -31,6 +31,6 @@ public abstract class PluginBase implements Plugin { + @Override + @NotNull + public final String getName() { +- return getDescription().getName(); ++ return getPluginMeta().getName(); // Paper + } + } +diff --git a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java +index 0c9f4d1e9104fa6951114c1f9ec954dfcc749196..f1ae66989afaa433bf2896e0bfe2cea472f774d8 100644 +--- a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java ++++ b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java +@@ -194,7 +194,7 @@ import org.yaml.snakeyaml.nodes.Tag; + * inferno.burningdeaths: true + * + */ +-public final class PluginDescriptionFile { ++public final class PluginDescriptionFile implements io.papermc.paper.plugin.configuration.PluginMeta { // Paper + private static final Pattern VALID_NAME = Pattern.compile("^[A-Za-z0-9 _.-]+$"); + private static final ThreadLocal YAML = new ThreadLocal() { + @Override +@@ -254,6 +254,70 @@ public final class PluginDescriptionFile { + private Set awareness = ImmutableSet.of(); + private String apiVersion = null; + private List libraries = ImmutableList.of(); ++ // Paper start - oh my goddddd ++ /** ++ * Don't use this. ++ */ ++ @org.jetbrains.annotations.ApiStatus.Internal ++ public PluginDescriptionFile(String rawName, String name, List provides, String main, String classLoaderOf, List depend, List softDepend, List loadBefore, String version, Map> commands, String description, List authors, List contributors, String website, String prefix, PluginLoadOrder order, List permissions, PermissionDefault defaultPerm, Set awareness, String apiVersion, List libraries) { ++ this.rawName = rawName; ++ this.name = name; ++ this.provides = provides; ++ this.main = main; ++ this.classLoaderOf = classLoaderOf; ++ this.depend = depend; ++ this.softDepend = softDepend; ++ this.loadBefore = loadBefore; ++ this.version = version; ++ this.commands = commands; ++ this.description = description; ++ this.authors = authors; ++ this.contributors = contributors; ++ this.website = website; ++ this.prefix = prefix; ++ this.order = order; ++ this.permissions = permissions; ++ this.defaultPerm = defaultPerm; ++ this.awareness = awareness; ++ this.apiVersion = apiVersion; ++ this.libraries = libraries; ++ } ++ ++ @Override ++ public @NotNull String getMainClass() { ++ return this.main; ++ } ++ ++ @Override ++ public @NotNull PluginLoadOrder getLoadOrder() { ++ return this.order; ++ } ++ ++ @Override ++ public @Nullable String getLoggerPrefix() { ++ return this.prefix; ++ } ++ ++ @Override ++ public @NotNull List getPluginDependencies() { ++ return this.depend; ++ } ++ ++ @Override ++ public @NotNull List getPluginSoftDependencies() { ++ return this.softDepend; ++ } ++ ++ @Override ++ public @NotNull List getLoadBeforePlugins() { ++ return this.loadBefore; ++ } ++ ++ @Override ++ public @NotNull List getProvidedPlugins() { ++ return this.provides; ++ } ++ // Paper end + + public PluginDescriptionFile(@NotNull final InputStream stream) throws InvalidDescriptionException { + loadMap(asMap(YAML.get().load(stream))); +diff --git a/src/main/java/org/bukkit/plugin/PluginLoader.java b/src/main/java/org/bukkit/plugin/PluginLoader.java +index a88733f1cd1ddb5d85ab1b0e6af4fd5b80bbc1c6..cb530369e667c426c842da356c31304bb5c3ecfa 100644 +--- a/src/main/java/org/bukkit/plugin/PluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/PluginLoader.java +@@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull; + * Represents a plugin loader, which handles direct access to specific types + * of plugins + */ ++@Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future + public interface PluginLoader { + + /** +diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java +index 41e26451fe12d8e6e0ef73c85731b24b4e3f200c..03213fde8315384ec56c16031cfc606ade2e8091 100644 +--- a/src/main/java/org/bukkit/plugin/PluginManager.java ++++ b/src/main/java/org/bukkit/plugin/PluginManager.java +@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Handles all plugin management from the Server + */ +-public interface PluginManager { ++public interface PluginManager extends io.papermc.paper.plugin.PermissionManager { // Paper + + /** + * Registers the specified plugin loader +@@ -23,6 +23,7 @@ public interface PluginManager { + * @throws IllegalArgumentException Thrown when the given Class is not a + * valid PluginLoader + */ ++ @Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future + public void registerInterface(@NotNull Class loader) throws IllegalArgumentException; + + /** +@@ -303,4 +304,17 @@ public interface PluginManager { + * @return True if event timings are to be used + */ + public boolean useTimings(); ++ ++ // Paper start ++ @org.jetbrains.annotations.ApiStatus.Internal ++ boolean isTransitiveDependency(io.papermc.paper.plugin.configuration.PluginMeta pluginMeta, io.papermc.paper.plugin.configuration.PluginMeta dependencyConfig); ++ ++ /** ++ * Sets the permission manager to be used for this server. ++ * ++ * @param permissionManager permission manager ++ */ ++ @org.jetbrains.annotations.ApiStatus.Experimental ++ void overridePermissionManager(@NotNull Plugin plugin, @Nullable io.papermc.paper.plugin.PermissionManager permissionManager); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index a69c5d5cad6168aeaae41e8adc319dc8c976b1e2..f64a90241ce7f73e111e6b5ac6ff87cd93583c0e 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -43,6 +43,8 @@ import org.jetbrains.annotations.Nullable; + /** + * Handles all plugin management from the Server + */ ++@Deprecated(forRemoval = true) // Paper - This implementation may be replaced in a future version of Paper. ++// Plugins may still reflect into this class to modify permission logic for the time being. + public final class SimplePluginManager implements PluginManager { + private final Server server; + private final Map fileAssociations = new HashMap(); +@@ -51,10 +53,13 @@ public final class SimplePluginManager implements PluginManager { + private MutableGraph dependencyGraph = GraphBuilder.directed().build(); + private File updateDirectory; + private final SimpleCommandMap commandMap; +- private final Map permissions = new HashMap(); +- private final Map> defaultPerms = new LinkedHashMap>(); +- private final Map> permSubs = new HashMap>(); +- private final Map> defSubs = new HashMap>(); ++ // Paper start ++ public final Map permissions = new HashMap(); ++ public final Map> defaultPerms = new LinkedHashMap>(); ++ public final Map> permSubs = new HashMap>(); ++ public final Map> defSubs = new HashMap>(); ++ public PluginManager paperPluginManager; ++ // Paper end + private boolean useTimings = false; + + public SimplePluginManager(@NotNull Server instance, @NotNull SimpleCommandMap commandMap) { +@@ -111,6 +116,11 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Plugin[] loadPlugins(@NotNull File directory) { ++ if (true) { ++ List pluginList = new ArrayList<>(); ++ java.util.Collections.addAll(pluginList, this.paperPluginManager.loadPlugins(directory)); ++ return pluginList.toArray(new Plugin[0]); ++ } + Preconditions.checkArgument(directory != null, "Directory cannot be null"); + Preconditions.checkArgument(directory.isDirectory(), "Directory must be a directory"); + +@@ -378,6 +388,15 @@ public final class SimplePluginManager implements PluginManager { + @Nullable + public synchronized Plugin loadPlugin(@NotNull File file) throws InvalidPluginException, UnknownDependencyException { + Preconditions.checkArgument(file != null, "File cannot be null"); ++ // Paper start ++ if (true) { ++ try { ++ return this.paperPluginManager.loadPlugin(file); ++ } catch (org.bukkit.plugin.InvalidDescriptionException ignored) { ++ return null; ++ } ++ } ++ // Paper end + + checkUpdate(file); + +@@ -428,12 +447,14 @@ public final class SimplePluginManager implements PluginManager { + @Override + @Nullable + public synchronized Plugin getPlugin(@NotNull String name) { ++ if (true) {return this.paperPluginManager.getPlugin(name);} // Paper + return lookupNames.get(name.replace(' ', '_')); + } + + @Override + @NotNull + public synchronized Plugin[] getPlugins() { ++ if (true) {return this.paperPluginManager.getPlugins();} // Paper + return plugins.toArray(new Plugin[plugins.size()]); + } + +@@ -447,6 +468,7 @@ public final class SimplePluginManager implements PluginManager { + */ + @Override + public boolean isPluginEnabled(@NotNull String name) { ++ if (true) {return this.paperPluginManager.isPluginEnabled(name);} // Paper + Plugin plugin = getPlugin(name); + + return isPluginEnabled(plugin); +@@ -460,6 +482,7 @@ public final class SimplePluginManager implements PluginManager { + */ + @Override + public boolean isPluginEnabled(@Nullable Plugin plugin) { ++ if (true) {return this.paperPluginManager.isPluginEnabled(plugin);} // Paper + if ((plugin != null) && (plugins.contains(plugin))) { + return plugin.isEnabled(); + } else { +@@ -469,6 +492,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void enablePlugin(@NotNull final Plugin plugin) { ++ if (true) {this.paperPluginManager.enablePlugin(plugin); return;} // Paper + if (!plugin.isEnabled()) { + List pluginCommands = PluginCommandYamlParser.parse(plugin); + +@@ -488,6 +512,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void disablePlugins() { ++ if (true) {this.paperPluginManager.disablePlugins(); return;} // Paper + Plugin[] plugins = getPlugins(); + for (int i = plugins.length - 1; i >= 0; i--) { + disablePlugin(plugins[i]); +@@ -496,6 +521,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void disablePlugin(@NotNull final Plugin plugin) { ++ if (true) {this.paperPluginManager.disablePlugin(plugin); return;} // Paper + if (plugin.isEnabled()) { + try { + plugin.getPluginLoader().disablePlugin(plugin); +@@ -540,6 +566,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void clearPlugins() { ++ if (true) {this.paperPluginManager.clearPlugins(); return;} // Paper + synchronized (this) { + disablePlugins(); + plugins.clear(); +@@ -560,6 +587,7 @@ public final class SimplePluginManager implements PluginManager { + */ + @Override + public void callEvent(@NotNull Event event) { ++ if (true) {this.paperPluginManager.callEvent(event); return;} // Paper + if (event.isAsynchronous()) { + if (Thread.holdsLock(this)) { + throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); +@@ -608,6 +636,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void registerEvents(@NotNull Listener listener, @NotNull Plugin plugin) { ++ if (true) {this.paperPluginManager.registerEvents(listener, plugin); return;} // Paper + if (!plugin.isEnabled()) { + throw new IllegalPluginAccessException("Plugin attempted to register " + listener + " while not enabled"); + } +@@ -641,6 +670,7 @@ public final class SimplePluginManager implements PluginManager { + Preconditions.checkArgument(priority != null, "Priority cannot be null"); + Preconditions.checkArgument(executor != null, "Executor cannot be null"); + Preconditions.checkArgument(plugin != null, "Plugin cannot be null"); ++ if (true) {this.paperPluginManager.registerEvent(event, listener, priority, executor, plugin); return;} // Paper + + if (!plugin.isEnabled()) { + throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled"); +@@ -688,16 +718,19 @@ public final class SimplePluginManager implements PluginManager { + @Override + @Nullable + public Permission getPermission(@NotNull String name) { ++ if (true) {return this.paperPluginManager.getPermission(name);} // Paper + return permissions.get(name.toLowerCase(java.util.Locale.ENGLISH)); + } + + @Override + public void addPermission(@NotNull Permission perm) { ++ if (true) {this.paperPluginManager.addPermission(perm); return;} // Paper + addPermission(perm, true); + } + + @Deprecated + public void addPermission(@NotNull Permission perm, boolean dirty) { ++ if (true) {this.paperPluginManager.addPermission(perm); return;} // Paper - This just has a performance implication, use the better api to avoid this. + String name = perm.getName().toLowerCase(java.util.Locale.ENGLISH); + + if (permissions.containsKey(name)) { +@@ -711,21 +744,25 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Set getDefaultPermissions(boolean op) { ++ if (true) {return this.paperPluginManager.getDefaultPermissions(op);} // Paper + return ImmutableSet.copyOf(defaultPerms.get(op)); + } + + @Override + public void removePermission(@NotNull Permission perm) { ++ if (true) {this.paperPluginManager.removePermission(perm); return;} // Paper + removePermission(perm.getName()); + } + + @Override + public void removePermission(@NotNull String name) { ++ if (true) {this.paperPluginManager.removePermission(name); return;} // Paper + permissions.remove(name.toLowerCase(java.util.Locale.ENGLISH)); + } + + @Override + public void recalculatePermissionDefaults(@NotNull Permission perm) { ++ if (true) {this.paperPluginManager.recalculatePermissionDefaults(perm); return;} // Paper + if (perm != null && permissions.containsKey(perm.getName().toLowerCase(java.util.Locale.ENGLISH))) { + defaultPerms.get(true).remove(perm); + defaultPerms.get(false).remove(perm); +@@ -765,6 +802,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void subscribeToPermission(@NotNull String permission, @NotNull Permissible permissible) { ++ if (true) {this.paperPluginManager.subscribeToPermission(permission, permissible); return;} // Paper + String name = permission.toLowerCase(java.util.Locale.ENGLISH); + Map map = permSubs.get(name); + +@@ -778,6 +816,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void unsubscribeFromPermission(@NotNull String permission, @NotNull Permissible permissible) { ++ if (true) {this.paperPluginManager.unsubscribeFromPermission(permission, permissible); return;} // Paper + String name = permission.toLowerCase(java.util.Locale.ENGLISH); + Map map = permSubs.get(name); + +@@ -793,6 +832,7 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Set getPermissionSubscriptions(@NotNull String permission) { ++ if (true) {return this.paperPluginManager.getPermissionSubscriptions(permission);} // Paper + String name = permission.toLowerCase(java.util.Locale.ENGLISH); + Map map = permSubs.get(name); + +@@ -805,6 +845,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void subscribeToDefaultPerms(boolean op, @NotNull Permissible permissible) { ++ if (true) {this.paperPluginManager.subscribeToDefaultPerms(op, permissible); return;} // Paper + Map map = defSubs.get(op); + + if (map == null) { +@@ -817,6 +858,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public void unsubscribeFromDefaultPerms(boolean op, @NotNull Permissible permissible) { ++ if (true) {this.paperPluginManager.unsubscribeFromDefaultPerms(op, permissible); return;} // Paper + Map map = defSubs.get(op); + + if (map != null) { +@@ -831,6 +873,7 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Set getDefaultPermSubscriptions(boolean op) { ++ if (true) {return this.paperPluginManager.getDefaultPermSubscriptions(op);} // Paper + Map map = defSubs.get(op); + + if (map == null) { +@@ -843,6 +886,7 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Set getPermissions() { ++ if (true) {return this.paperPluginManager.getPermissions();} // Paper + return new HashSet(permissions.values()); + } + +@@ -866,6 +910,7 @@ public final class SimplePluginManager implements PluginManager { + + @Override + public boolean useTimings() { ++ if (true) {return this.paperPluginManager.useTimings();} // Paper + return useTimings; + } + +@@ -877,4 +922,28 @@ public final class SimplePluginManager implements PluginManager { + public void useTimings(boolean use) { + useTimings = use; + } ++ ++ // Paper start ++ public void clearPermissions() { ++ if (true) {this.paperPluginManager.clearPermissions(); return;} // Paper ++ permissions.clear(); ++ defaultPerms.get(true).clear(); ++ defaultPerms.get(false).clear(); ++ } ++ ++ @Override ++ public boolean isTransitiveDependency(io.papermc.paper.plugin.configuration.PluginMeta pluginMeta, io.papermc.paper.plugin.configuration.PluginMeta dependencyConfig) { ++ return this.paperPluginManager.isTransitiveDependency(pluginMeta, dependencyConfig); ++ } ++ ++ @Override ++ public void overridePermissionManager(@NotNull Plugin plugin, @Nullable io.papermc.paper.plugin.PermissionManager permissionManager) { ++ this.paperPluginManager.overridePermissionManager(plugin, permissionManager); ++ } ++ ++ @Override ++ public void addPermissions(@NotNull List perm) { ++ this.paperPluginManager.addPermissions(perm); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/plugin/UnknownDependencyException.java b/src/main/java/org/bukkit/plugin/UnknownDependencyException.java +index a80251eff75430863b37db1c131e22593f3fcd5e..310c4041963a3f1e0a26e39a6da12a9bfdb51edc 100644 +--- a/src/main/java/org/bukkit/plugin/UnknownDependencyException.java ++++ b/src/main/java/org/bukkit/plugin/UnknownDependencyException.java +@@ -43,4 +43,16 @@ public class UnknownDependencyException extends RuntimeException { + public UnknownDependencyException() { + + } ++ // Paper start ++ /** ++ * Create a new {@link UnknownDependencyException} with a message informing ++ * about which dependencies are missing for what plugin. ++ * ++ * @param missingDependencies missing dependencies ++ * @param pluginName plugin which is missing said dependencies ++ */ ++ public UnknownDependencyException(final @org.jetbrains.annotations.NotNull java.util.Collection missingDependencies, final @org.jetbrains.annotations.NotNull String pluginName) { ++ this("Unknown/missing dependency plugins: [" + String.join(", ", missingDependencies) + "]. Please download and install these plugins to run '" + pluginName + "'."); ++ } ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +index 669a70faa95d0d6525a731d73499ed6fb0b48320..a5636b1f223dd37420a4acbccf28f7198a7eee98 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +@@ -38,6 +38,7 @@ public abstract class JavaPlugin extends PluginBase { + private Server server = null; + private File file = null; + private PluginDescriptionFile description = null; ++ private io.papermc.paper.plugin.configuration.PluginMeta pluginMeta = null; // Paper + private File dataFolder = null; + private ClassLoader classLoader = null; + private boolean naggable = true; +@@ -46,13 +47,16 @@ public abstract class JavaPlugin extends PluginBase { + private PluginLogger logger = null; + + public JavaPlugin() { +- final ClassLoader classLoader = this.getClass().getClassLoader(); +- if (!(classLoader instanceof PluginClassLoader)) { +- throw new IllegalStateException("JavaPlugin requires " + PluginClassLoader.class.getName()); ++ // Paper start ++ if (this.getClass().getClassLoader() instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ configuredPluginClassLoader.init(this); ++ } else { ++ throw new IllegalStateException("JavaPlugin requires to be created by a valid classloader."); + } +- ((PluginClassLoader) classLoader).initialize(this); ++ // Paper end + } + ++ @Deprecated(forRemoval = true) // Paper + protected JavaPlugin(@NotNull final JavaPluginLoader loader, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file) { + final ClassLoader classLoader = this.getClass().getClassLoader(); + if (classLoader instanceof PluginClassLoader) { +@@ -77,9 +81,12 @@ public abstract class JavaPlugin extends PluginBase { + * Gets the associated PluginLoader responsible for this plugin + * + * @return PluginLoader that controls this plugin ++ * @deprecated Plugin loading now occurs at a point which makes it impossible to expose this ++ * behavior. This instance will only throw unsupported operation exceptions. + */ + @NotNull + @Override ++ @Deprecated(forRemoval = true) // Paper + public final PluginLoader getPluginLoader() { + return loader; + } +@@ -120,13 +127,20 @@ public abstract class JavaPlugin extends PluginBase { + * Returns the plugin.yaml file containing the details for this plugin + * + * @return Contents of the plugin.yaml file ++ * @deprecated No longer applicable to all types of plugins + */ + @NotNull + @Override ++ @Deprecated + public final PluginDescriptionFile getDescription() { + return description; + } + ++ @Nullable ++ public final io.papermc.paper.plugin.configuration.PluginMeta getPluginMeta() { ++ return this.pluginMeta; ++ } ++ + @NotNull + @Override + public FileConfiguration getConfig() { +@@ -256,7 +270,8 @@ public abstract class JavaPlugin extends PluginBase { + * + * @param enabled true if enabled, otherwise false + */ +- protected final void setEnabled(final boolean enabled) { ++ @org.jetbrains.annotations.ApiStatus.Internal // Paper ++ public final void setEnabled(final boolean enabled) { // Paper + if (isEnabled != enabled) { + isEnabled = enabled; + +@@ -268,9 +283,14 @@ public abstract class JavaPlugin extends PluginBase { + } + } + +- +- final void init(@NotNull PluginLoader loader, @NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader) { +- this.loader = loader; ++ // Paper start ++ public final void init(@NotNull PluginLoader loader, @NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader) { ++ init(server, description, dataFolder, file, classLoader, description); ++ this.pluginMeta = description; ++ } ++ public final void init(@NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader, @Nullable io.papermc.paper.plugin.configuration.PluginMeta configuration) { ++ // Paper end ++ this.loader = new io.papermc.paper.plugin.provider.util.DummyBukkitPluginLoader(this); + this.server = server; + this.file = file; + this.description = description; +@@ -278,6 +298,7 @@ public abstract class JavaPlugin extends PluginBase { + this.classLoader = classLoader; + this.configFile = new File(dataFolder, "config.yml"); + this.logger = new PluginLogger(this); ++ this.pluginMeta = configuration; // Paper + } + + /** +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 047c0304fd617cec990f80815b43916c6ef5a94c..d0ad072c832b8fc8a1cfdcafdd42c724531a2e29 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -49,6 +49,7 @@ import org.yaml.snakeyaml.error.YAMLException; + /** + * Represents a Java plugin loader, allowing plugins in the form of .jar + */ ++@Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future. This implementation will be moved. + public final class JavaPluginLoader implements PluginLoader { + final Server server; + private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; +@@ -79,6 +80,7 @@ public final class JavaPluginLoader implements PluginLoader { + @Override + @NotNull + public Plugin loadPlugin(@NotNull final File file) throws InvalidPluginException { ++ if (true) throw new UnsupportedOperationException(); // Paper + Preconditions.checkArgument(file != null, "File cannot be null"); + + if (!file.exists()) { +@@ -142,7 +144,7 @@ public final class JavaPluginLoader implements PluginLoader { + + final PluginClassLoader loader; + try { +- loader = new PluginClassLoader(this, getClass().getClassLoader(), description, dataFolder, file, (libraryLoader != null) ? libraryLoader.createLoader(description) : null); ++ loader = new PluginClassLoader(getClass().getClassLoader(), description, dataFolder, file, (libraryLoader != null) ? libraryLoader.createLoader(description) : null, null); // Paper + } catch (InvalidPluginException ex) { + throw ex; + } catch (Throwable ex) { +diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +index 6d634b0ea813ccb19f1562a7d0e5a59cea4eab21..f9e67e20133d349e43d126dbb48b34d4d9aceb4c 100644 +--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +@@ -36,7 +36,10 @@ import org.eclipse.aether.transport.http.HttpTransporterFactory; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + +-class LibraryLoader ++// Paper start ++@org.jetbrains.annotations.ApiStatus.Internal ++public class LibraryLoader ++// Paper end + { + + private final Logger logger; +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index 2f74ec96ece706de23156ebabfe493211bc05391..e721c58eafee2180d4ba1a73002cf850355a366e 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -29,7 +29,8 @@ import org.jetbrains.annotations.Nullable; + /** + * A ClassLoader for plugins, to allow shared classes across multiple plugins + */ +-final class PluginClassLoader extends URLClassLoader { ++@org.jetbrains.annotations.ApiStatus.Internal // Paper ++public final class PluginClassLoader extends URLClassLoader implements io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader { // Paper + private final JavaPluginLoader loader; + private final Map> classes = new ConcurrentHashMap>(); + private final PluginDescriptionFile description; +@@ -39,20 +40,23 @@ final class PluginClassLoader extends URLClassLoader { + private final Manifest manifest; + private final URL url; + private final ClassLoader libraryLoader; +- final JavaPlugin plugin; ++ public final JavaPlugin plugin; // Paper + private JavaPlugin pluginInit; + private IllegalStateException pluginState; + private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); ++ private java.util.logging.Logger logger; // Paper - add field ++ private io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup classLoaderGroup; // Paper ++ public io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext; // Paper + + static { + ClassLoader.registerAsParallelCapable(); + } + +- PluginClassLoader(@NotNull final JavaPluginLoader loader, @Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader) throws IOException, InvalidPluginException, MalformedURLException { ++ @org.jetbrains.annotations.ApiStatus.Internal // Paper ++ public PluginClassLoader(@Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader, io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext) throws IOException, InvalidPluginException, MalformedURLException { // Paper + super(new URL[] {file.toURI().toURL()}, parent); +- Preconditions.checkArgument(loader != null, "Loader cannot be null"); ++ this.loader = null; // Paper - pass null into loader field + +- this.loader = loader; + this.description = description; + this.dataFolder = dataFolder; + this.file = file; +@@ -61,6 +65,11 @@ final class PluginClassLoader extends URLClassLoader { + this.url = file.toURI().toURL(); + this.libraryLoader = libraryLoader; + ++ ++ // Paper start ++ this.classLoaderGroup = io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage.instance().registerSpigotGroup(this); // Paper ++ this.dependencyContext = dependencyContext; ++ // Paper end + try { + Class jarClass; + try { +@@ -94,6 +103,22 @@ final class PluginClassLoader extends URLClassLoader { + return findResources(name); + } + ++ // Paper start ++ @Override ++ public Class loadClass(@NotNull String name, boolean resolve, boolean checkGlobal, boolean checkLibraries) throws ClassNotFoundException { ++ return this.loadClass0(name, resolve, checkGlobal, checkLibraries); ++ } ++ @Override ++ public io.papermc.paper.plugin.configuration.PluginMeta getConfiguration() { ++ return this.description; ++ } ++ ++ @Override ++ public void init(JavaPlugin plugin) { ++ this.initialize(plugin); ++ } ++ // Paper end ++ + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + return loadClass0(name, resolve, true, true); +@@ -119,7 +144,7 @@ final class PluginClassLoader extends URLClassLoader { + + if (checkGlobal) { + // This ignores the libraries of other plugins, unless they are transitive dependencies. +- Class result = loader.getClassByName(name, resolve, description); ++ Class result = this.classLoaderGroup.getClassByName(name, resolve, this); // Paper + + if (result != null) { + // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. +@@ -128,7 +153,7 @@ final class PluginClassLoader extends URLClassLoader { + + if (provider != description + && !seenIllegalAccess.contains(provider.getName()) +- && !((SimplePluginManager) loader.server.getPluginManager()).isTransitiveDepend(description, provider)) { ++ && !this.dependencyContext.isTransitiveDependency(description, provider)) { // Paper + + seenIllegalAccess.add(provider.getName()); + if (plugin != null) { +@@ -167,7 +192,7 @@ final class PluginClassLoader extends URLClassLoader { + throw new ClassNotFoundException(name, ex); + } + +- classBytes = loader.server.getUnsafe().processClass(description, path, classBytes); ++ classBytes = org.bukkit.Bukkit.getServer().getUnsafe().processClass(description, path, classBytes); // Paper + + int dot = name.lastIndexOf('.'); + if (dot != -1) { +@@ -197,8 +222,8 @@ final class PluginClassLoader extends URLClassLoader { + result = super.findClass(name); + } + +- loader.setClass(name, result); + classes.put(name, result); ++ this.setClass(name, result); // Paper + } + + return result; +@@ -207,6 +232,12 @@ final class PluginClassLoader extends URLClassLoader { + @Override + public void close() throws IOException { + try { ++ // Paper start ++ Collection> classes = getClasses(); ++ for (Class clazz : classes) { ++ removeClass(clazz); ++ } ++ // Paper end + super.close(); + } finally { + jar.close(); +@@ -218,7 +249,7 @@ final class PluginClassLoader extends URLClassLoader { + return classes.values(); + } + +- synchronized void initialize(@NotNull JavaPlugin javaPlugin) { ++ public synchronized void initialize(@NotNull JavaPlugin javaPlugin) { // Paper + Preconditions.checkArgument(javaPlugin != null, "Initializing plugin cannot be null"); + Preconditions.checkArgument(javaPlugin.getClass().getClassLoader() == this, "Cannot initialize plugin outside of this class loader"); + if (this.plugin != null || this.pluginInit != null) { +@@ -228,6 +259,32 @@ final class PluginClassLoader extends URLClassLoader { + pluginState = new IllegalStateException("Initial initialization"); + this.pluginInit = javaPlugin; + +- javaPlugin.init(loader, loader.server, description, dataFolder, file, this); ++ javaPlugin.init(null, org.bukkit.Bukkit.getServer(), description, dataFolder, file, this); // Paper ++ } ++ ++ // Paper start ++ @Override ++ public String toString() { ++ JavaPlugin currPlugin = plugin != null ? plugin : pluginInit; ++ return "PluginClassLoader{" + ++ "plugin=" + currPlugin + ++ ", pluginEnabled=" + (currPlugin == null ? "uninitialized" : currPlugin.isEnabled()) + ++ ", url=" + file + ++ '}'; ++ } ++ ++ void setClass(@NotNull final String name, @NotNull final Class clazz) { ++ if (org.bukkit.configuration.serialization.ConfigurationSerializable.class.isAssignableFrom(clazz)) { ++ Class serializable = clazz.asSubclass(org.bukkit.configuration.serialization.ConfigurationSerializable.class); ++ org.bukkit.configuration.serialization.ConfigurationSerialization.registerClass(serializable); ++ } ++ } ++ ++ private void removeClass(@NotNull Class clazz) { ++ if (org.bukkit.configuration.serialization.ConfigurationSerializable.class.isAssignableFrom(clazz)) { ++ Class serializable = clazz.asSubclass(org.bukkit.configuration.serialization.ConfigurationSerializable.class); ++ org.bukkit.configuration.serialization.ConfigurationSerialization.unregisterClass(serializable); ++ } + } ++ // Paper end + } +diff --git a/src/test/java/io/papermc/paper/testing/TestServer.java b/src/test/java/io/papermc/paper/testing/TestServer.java +index 756acf231b1b076b08046d86992ba7ce7f62a94f..52d27d977b9df0bdf02b33ed0aaa3b4db0a04cb4 100644 +--- a/src/test/java/io/papermc/paper/testing/TestServer.java ++++ b/src/test/java/io/papermc/paper/testing/TestServer.java +@@ -36,9 +36,6 @@ public final class TestServer { + + when(dummyServer.getTag(anyString(), any(NamespacedKey.class), any())).thenAnswer(ignored -> new EmptyTag()); + +- final PluginManager pluginManager = new SimplePluginManager(dummyServer, new SimpleCommandMap(dummyServer)); +- when(dummyServer.getPluginManager()).thenReturn(pluginManager); +- + when(dummyServer.getRegistry(any())).thenAnswer(ignored -> new EmptyRegistry()); + when(dummyServer.getScoreboardCriteria(anyString())).thenReturn(null); + +diff --git a/src/test/java/org/bukkit/event/SyntheticEventTest.java b/src/test/java/org/bukkit/event/SyntheticEventTest.java +deleted file mode 100644 +index 09886568ae6167141b463b6262565fa212af3385..0000000000000000000000000000000000000000 +--- a/src/test/java/org/bukkit/event/SyntheticEventTest.java ++++ /dev/null +@@ -1,48 +0,0 @@ +-package org.bukkit.event; +- +-import org.bukkit.plugin.PluginLoader; +-import org.bukkit.plugin.SimplePluginManager; +-import org.bukkit.plugin.TestPlugin; +-import org.bukkit.plugin.java.JavaPluginLoader; +-import org.junit.Assert; +-import org.junit.Test; +- +-public class SyntheticEventTest { +- @SuppressWarnings("deprecation") +- @Test +- public void test() { +- io.papermc.paper.testing.TestServer.setup(); // Paper +- final JavaPluginLoader loader = new JavaPluginLoader(org.bukkit.Bukkit.getServer()); // Paper +- TestPlugin plugin = new TestPlugin(getClass().getName()) { +- @Override +- public PluginLoader getPluginLoader() { +- return loader; +- } +- }; +- SimplePluginManager pluginManager = new SimplePluginManager(org.bukkit.Bukkit.getServer(), null); // Paper +- +- TestEvent event = new TestEvent(false); +- Impl impl = new Impl(); +- +- pluginManager.registerEvents(impl, plugin); +- pluginManager.callEvent(event); +- +- Assert.assertEquals(1, impl.callCount); +- } +- +- public abstract static class Base implements Listener { +- int callCount = 0; +- +- public void accept(E evt) { +- callCount++; +- } +- } +- +- public static class Impl extends Base { +- @Override +- @EventHandler +- public void accept(TestEvent evt) { +- super.accept(evt); +- } +- } +-} +diff --git a/src/test/java/org/bukkit/plugin/PluginManagerTest.java b/src/test/java/org/bukkit/plugin/PluginManagerTest.java +deleted file mode 100644 +index c46ed2acb82db814d660459b705dd49e6d44240f..0000000000000000000000000000000000000000 +--- a/src/test/java/org/bukkit/plugin/PluginManagerTest.java ++++ /dev/null +@@ -1,183 +0,0 @@ +-package org.bukkit.plugin; +- +-import static org.hamcrest.Matchers.*; +-import static org.junit.Assert.*; +-import org.bukkit.event.Event; +-import org.bukkit.event.TestEvent; +-import org.bukkit.permissions.Permission; +-import org.junit.After; +-import org.junit.Test; +- +-public class PluginManagerTest { +- private class MutableObject { +- volatile Object value = null; +- } +- +- private static final PluginManager pm = org.bukkit.Bukkit.getServer().getPluginManager(); // Paper +- +- private final MutableObject store = new MutableObject(); +- +- @Test +- public void testAsyncSameThread() { +- final Event event = new TestEvent(true); +- try { +- pm.callEvent(event); +- } catch (IllegalStateException ex) { +- assertThat(event.getEventName() + " cannot be triggered asynchronously from primary server thread.", is(ex.getMessage())); +- return; +- } +- throw new IllegalStateException("No exception thrown"); +- } +- +- @Test +- public void testSyncSameThread() { +- final Event event = new TestEvent(false); +- pm.callEvent(event); +- } +- +- @Test +- public void testAsyncLocked() throws InterruptedException { +- final Event event = new TestEvent(true); +- Thread secondThread = new Thread( +- new Runnable() { +- @Override +- public void run() { +- try { +- synchronized (pm) { +- pm.callEvent(event); +- } +- } catch (Throwable ex) { +- store.value = ex; +- } +- } +- } +- ); +- secondThread.start(); +- secondThread.join(); +- assertThat(store.value, is(instanceOf(IllegalStateException.class))); +- assertThat(event.getEventName() + " cannot be triggered asynchronously from inside synchronized code.", is(((Throwable) store.value).getMessage())); +- } +- +- @Test +- public void testAsyncUnlocked() throws InterruptedException { +- final Event event = new TestEvent(true); +- Thread secondThread = new Thread( +- new Runnable() { +- @Override +- public void run() { +- try { +- pm.callEvent(event); +- } catch (Throwable ex) { +- store.value = ex; +- } +- } +- } +- ); +- secondThread.start(); +- secondThread.join(); +- if (store.value != null) { +- throw new RuntimeException((Throwable) store.value); +- } +- } +- +- @Test +- public void testSyncUnlocked() throws InterruptedException { +- final Event event = new TestEvent(false); +- Thread secondThread = new Thread( +- new Runnable() { +- @Override +- public void run() { +- try { +- pm.callEvent(event); +- } catch (Throwable ex) { +- store.value = ex; +- assertThat(event.getEventName() + " cannot be triggered asynchronously from another thread.", is(ex.getMessage())); +- return; +- } +- } +- } +- ); +- secondThread.start(); +- secondThread.join(); +- if (store.value == null) { +- throw new IllegalStateException("No exception thrown"); +- } +- } +- +- @Test +- public void testSyncLocked() throws InterruptedException { +- final Event event = new TestEvent(false); +- Thread secondThread = new Thread( +- new Runnable() { +- @Override +- public void run() { +- try { +- synchronized (pm) { +- pm.callEvent(event); +- } +- } catch (Throwable ex) { +- store.value = ex; +- assertThat(event.getEventName() + " cannot be triggered asynchronously from another thread.", is(ex.getMessage())); +- return; +- } +- } +- } +- ); +- secondThread.start(); +- secondThread.join(); +- if (store.value == null) { +- throw new IllegalStateException("No exception thrown"); +- } +- } +- +- @Test +- public void testRemovePermissionByNameLower() { +- this.testRemovePermissionByName("lower"); +- } +- +- @Test +- public void testRemovePermissionByNameUpper() { +- this.testRemovePermissionByName("UPPER"); +- } +- +- @Test +- public void testRemovePermissionByNameCamel() { +- this.testRemovePermissionByName("CaMeL"); +- } +- +- public void testRemovePermissionByPermissionLower() { +- this.testRemovePermissionByPermission("lower"); +- } +- +- @Test +- public void testRemovePermissionByPermissionUpper() { +- this.testRemovePermissionByPermission("UPPER"); +- } +- +- @Test +- public void testRemovePermissionByPermissionCamel() { +- this.testRemovePermissionByPermission("CaMeL"); +- } +- +- private void testRemovePermissionByName(final String name) { +- final Permission perm = new Permission(name); +- pm.addPermission(perm); +- assertThat("Permission \"" + name + "\" was not added", pm.getPermission(name), is(perm)); +- pm.removePermission(name); +- assertThat("Permission \"" + name + "\" was not removed", pm.getPermission(name), is(nullValue())); +- } +- +- private void testRemovePermissionByPermission(final String name) { +- final Permission perm = new Permission(name); +- pm.addPermission(perm); +- assertThat("Permission \"" + name + "\" was not added", pm.getPermission(name), is(perm)); +- pm.removePermission(perm); +- assertThat("Permission \"" + name + "\" was not removed", pm.getPermission(name), is(nullValue())); +- } +- +- @After +- public void tearDown() { +- pm.clearPlugins(); +- assertThat(pm.getPermissions(), is(empty())); +- } +-} +diff --git a/src/test/java/org/bukkit/plugin/TestPlugin.java b/src/test/java/org/bukkit/plugin/TestPlugin.java +index a8be3e23e3e280ad301d9530de50028515612966..43b58e920e739bb949ac0673e9ef73ba7b500dc9 100644 +--- a/src/test/java/org/bukkit/plugin/TestPlugin.java ++++ b/src/test/java/org/bukkit/plugin/TestPlugin.java +@@ -32,6 +32,12 @@ public class TestPlugin extends PluginBase { + public PluginDescriptionFile getDescription() { + return new PluginDescriptionFile(pluginName, "1.0", "test.test"); + } ++ // Paper start ++ @Override ++ public io.papermc.paper.plugin.configuration.PluginMeta getPluginMeta() { ++ return getDescription(); ++ } ++ // Paper end + + @Override + public FileConfiguration getConfig() { diff --git a/patches/api/0007-Add-Position.patch b/patches/api/0009-Add-Position.patch similarity index 100% rename from patches/api/0007-Add-Position.patch rename to patches/api/0009-Add-Position.patch diff --git a/patches/api/0009-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/api/0009-Add-command-line-option-to-load-extra-plugin-jars-no.patch deleted file mode 100644 index aab62144b6..0000000000 --- a/patches/api/0009-Add-command-line-option-to-load-extra-plugin-jars-no.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> -Date: Tue, 18 May 2021 14:42:26 -0700 -Subject: [PATCH] Add command line option to load extra plugin jars not in the - plugins folder - -ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index e24589a4cb42b0163e4a1455b8b11d7130b5cd41..71a09ed2b9863d2d339967f41ab6373ec27429d3 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -76,6 +76,20 @@ public final class Bukkit { - return server; - } - -+ /** -+ * Returns the de facto plugins directory, generally used for storing plugin jars to be loaded, -+ * as well as their {@link org.bukkit.plugin.Plugin#getDataFolder() data folders}. -+ * -+ *

Plugins should use {@link org.bukkit.plugin.Plugin#getDataFolder()} rather than traversing this -+ * directory manually when determining the location in which to store their data and configuration files.

-+ * -+ * @return plugins directory -+ */ -+ @NotNull -+ public static File getPluginsFolder() { -+ return server.getPluginsFolder(); -+ } -+ - /** - * Attempts to set the {@link Server} singleton. - *

-diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index ac087402c90dad4b3c499fcf8507e50e9099cea5..a4f8035b40eebff8afe01788781128b04247f28c 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -61,6 +61,18 @@ import org.jetbrains.annotations.Nullable; - */ - public interface Server extends PluginMessageRecipient, net.kyori.adventure.audience.ForwardingAudience { // Paper - -+ /** -+ * Returns the de facto plugins directory, generally used for storing plugin jars to be loaded, -+ * as well as their {@link org.bukkit.plugin.Plugin#getDataFolder() data folders}. -+ * -+ *

Plugins should use {@link org.bukkit.plugin.Plugin#getDataFolder()} rather than traversing this -+ * directory manually when determining the location in which to store their data and configuration files.

-+ * -+ * @return plugins directory -+ */ -+ @NotNull -+ File getPluginsFolder(); -+ - /** - * Used for all administrative messages, such as an operator using a - * command. -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 763b3e9ea24b14c54abf94048931f29228c76df5..1bfa9fcb1b803eecfe33156f81ee88d2922ca88a 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -111,6 +111,12 @@ public final class SimplePluginManager implements PluginManager { - @Override - @NotNull - public Plugin[] loadPlugins(@NotNull File directory) { -+ // Paper start - extra jars -+ return this.loadPlugins(directory, java.util.Collections.emptyList()); -+ } -+ @NotNull -+ public Plugin[] loadPlugins(final @NotNull File directory, final @NotNull List extraPluginJars) { -+ // Paper end - Preconditions.checkArgument(directory != null, "Directory cannot be null"); - Preconditions.checkArgument(directory.isDirectory(), "Directory must be a directory"); - -@@ -128,7 +134,11 @@ public final class SimplePluginManager implements PluginManager { - Map> softDependencies = new HashMap>(); - - // This is where it figures out all possible plugins -- for (File file : directory.listFiles()) { -+ // Paper start - extra jars -+ final List pluginJars = new ArrayList<>(java.util.Arrays.asList(directory.listFiles())); -+ pluginJars.addAll(extraPluginJars); -+ for (File file : pluginJars) { -+ // Paper end - PluginLoader loader = null; - for (Pattern filter : filters) { - Matcher match = filter.matcher(file.getName()); -@@ -144,14 +154,14 @@ public final class SimplePluginManager implements PluginManager { - description = loader.getPluginDescription(file); - String name = description.getName(); - if (name.equalsIgnoreCase("bukkit") || name.equalsIgnoreCase("minecraft") || name.equalsIgnoreCase("mojang")) { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': Restricted Name"); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "': Restricted Name"); // Paper - continue; - } else if (description.rawName.indexOf(' ') != -1) { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': uses the space-character (0x20) in its name"); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "': uses the space-character (0x20) in its name"); // Paper - continue; - } - } catch (InvalidDescriptionException ex) { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'", ex); // Paper - continue; - } - -@@ -162,7 +172,7 @@ public final class SimplePluginManager implements PluginManager { - description.getName(), - file.getPath(), - replacedFile.getPath(), -- directory.getPath() -+ file.getParentFile().getPath() // Paper - )); - } - -@@ -183,7 +193,7 @@ public final class SimplePluginManager implements PluginManager { - file.getPath(), - provided, - pluginFile.getPath(), -- directory.getPath() -+ file.getParentFile().getPath() // Paper - )); - } else { - String replacedPlugin = pluginsProvided.put(provided, description.getName()); -@@ -265,7 +275,7 @@ public final class SimplePluginManager implements PluginManager { - - server.getLogger().log( - Level.SEVERE, -- "Could not load '" + entry.getValue().getPath() + "' in folder '" + directory.getPath() + "'", -+ "Could not load '" + entry.getValue().getPath() + "' in folder '" + entry.getValue().getParentFile().getPath() + "'", // Paper - new UnknownDependencyException("Unknown dependency " + dependency + ". Please download and install " + dependency + " to run this plugin.")); - break; - } -@@ -304,11 +314,11 @@ public final class SimplePluginManager implements PluginManager { - loadedPlugins.add(loadedPlugin.getName()); - loadedPlugins.addAll(loadedPlugin.getDescription().getProvides()); - } else { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'"); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'"); // Paper - } - continue; - } catch (InvalidPluginException ex) { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'", ex); // Paper - } - } - } -@@ -335,11 +345,11 @@ public final class SimplePluginManager implements PluginManager { - loadedPlugins.add(loadedPlugin.getName()); - loadedPlugins.addAll(loadedPlugin.getDescription().getProvides()); - } else { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'"); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'"); // Paper - } - break; - } catch (InvalidPluginException ex) { -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "'", ex); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "'", ex); // Paper - } - } - } -@@ -352,7 +362,7 @@ public final class SimplePluginManager implements PluginManager { - while (failedPluginIterator.hasNext()) { - File file = failedPluginIterator.next(); - failedPluginIterator.remove(); -- server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': circular dependency detected"); -+ server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + file.getParentFile().getPath() + "': circular dependency detected"); // Paper - } - } - } -diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 5c1b8b05d8a5408bb4830942c74ebfe400ab5a32..333c47a1f7e9d7ddf91aad5ec15163427f7b8039 100644 ---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -91,7 +91,7 @@ public final class JavaPluginLoader implements PluginLoader { - throw new InvalidPluginException(ex); - } - -- final File parentFile = file.getParentFile(); -+ final File parentFile = this.server.getPluginsFolder(); // Paper - final File dataFolder = new File(parentFile, description.getName()); - @SuppressWarnings("deprecation") - final File oldDataFolder = new File(parentFile, description.getRawName()); diff --git a/patches/api/0008-Timings-v2.patch b/patches/api/0010-Timings-v2.patch similarity index 98% rename from patches/api/0008-Timings-v2.patch rename to patches/api/0010-Timings-v2.patch index 5b6f5bf932..3d19a7239d 100644 --- a/patches/api/0008-Timings-v2.patch +++ b/patches/api/0010-Timings-v2.patch @@ -2834,7 +2834,7 @@ index 892e03189957b0072827be4fd485dd98352334e8..ac087402c90dad4b3c499fcf8507e50e * Sends the component to the player * diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 876072a6c91bd02c9c7de53556419b8e1ac48f27..33c005a11e1ee241c1146e2cc291d523b1dd744e 100644 +index dc9a4f12d9f05a3ae7c9f1c7648123e4b3dfd115..daf3ac72cae4d19c0273058dc6a1e1afe9a47f77 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java @@ -33,6 +33,7 @@ public interface UnsafeValues { @@ -2845,10 +2845,10 @@ index 876072a6c91bd02c9c7de53556419b8e1ac48f27..33c005a11e1ee241c1146e2cc291d523 Material toLegacy(Material material); Material fromLegacy(Material material); -@@ -96,4 +97,12 @@ public interface UnsafeValues { - String getTranslationKey(EntityType entityType); - - String getTranslationKey(ItemStack itemStack); +@@ -106,4 +107,12 @@ public interface UnsafeValues { + return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); + } + // Paper end + + // Paper start + /** @@ -2886,19 +2886,20 @@ index 0000000000000000000000000000000000000000..f9a00aecca5ec41b460bf41dfe1c6969 + } +} diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java -index 57ade3963faae3724d9a01eeeb6d02168acb567e..6fd341482d5250ad814e870360e40b52427f799a 100644 +index caa29be46e8541b69ec47c181eb3320d6515b544..6fd341482d5250ad814e870360e40b52427f799a 100644 --- a/src/main/java/org/bukkit/command/Command.java +++ b/src/main/java/org/bukkit/command/Command.java -@@ -33,6 +33,8 @@ public abstract class Command { +@@ -33,7 +33,8 @@ public abstract class Command { protected String usageMessage; private String permission; private net.kyori.adventure.text.Component permissionMessage; // Paper +- public org.spigotmc.CustomTimingsHandler timings; // Spigot + public co.aikar.timings.Timing timings; // Paper + @NotNull public String getTimingName() {return getName();} // Paper protected Command(@NotNull String name) { this(name, "", "/" + name, new ArrayList()); -@@ -46,7 +48,6 @@ public abstract class Command { +@@ -47,7 +48,6 @@ public abstract class Command { this.usageMessage = (usageMessage == null) ? "/" + name : usageMessage; this.aliases = aliases; this.activeAliases = new ArrayList(aliases); @@ -2906,7 +2907,7 @@ index 57ade3963faae3724d9a01eeeb6d02168acb567e..6fd341482d5250ad814e870360e40b52 } /** -@@ -244,7 +245,6 @@ public abstract class Command { +@@ -245,7 +245,6 @@ public abstract class Command { } this.nextLabel = name; if (!isRegistered()) { @@ -3079,7 +3080,7 @@ index 0000000000000000000000000000000000000000..9d263ab3afb938c215c0b64d9171345f + +} diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index e195e74c48c69047aa825b75fad95419c505b41f..f99d71301ceaa3af07ff0525f7d657ac6253d0e6 100644 +index 53f28c9e6843991486a576d41b6641c170589807..4205649948a9e2a72f64c3f007112245abac6d50 100644 --- a/src/main/java/org/bukkit/command/SimpleCommandMap.java +++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java @@ -15,7 +15,6 @@ import org.bukkit.command.defaults.BukkitCommand; @@ -3093,7 +3094,7 @@ index e195e74c48c69047aa825b75fad95419c505b41f..f99d71301ceaa3af07ff0525f7d657ac @@ -35,7 +34,7 @@ public class SimpleCommandMap implements CommandMap { register("bukkit", new VersionCommand("version")); register("bukkit", new ReloadCommand("reload")); - register("bukkit", new PluginsCommand("plugins")); + //register("bukkit", new PluginsCommand("plugins")); // Paper - register("bukkit", new TimingsCommand("timings")); + register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Paper } @@ -3410,10 +3411,10 @@ index 4053c086a9ef9aa071402818672643bd800851d6..705644a2e0d209ef717470da07d34faf @NotNull diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index a69c5d5cad6168aeaae41e8adc319dc8c976b1e2..763b3e9ea24b14c54abf94048931f29228c76df5 100644 +index f64a90241ce7f73e111e6b5ac6ff87cd93583c0e..f13dcbe448111b24b36105d25527ba87ccc9334e 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -358,7 +358,6 @@ public final class SimplePluginManager implements PluginManager { +@@ -368,7 +368,6 @@ public final class SimplePluginManager implements PluginManager { } } @@ -3421,7 +3422,7 @@ index a69c5d5cad6168aeaae41e8adc319dc8c976b1e2..763b3e9ea24b14c54abf94048931f292 return result.toArray(new Plugin[result.size()]); } -@@ -397,9 +396,9 @@ public final class SimplePluginManager implements PluginManager { +@@ -416,9 +415,9 @@ public final class SimplePluginManager implements PluginManager { if (result != null) { plugins.add(result); @@ -3433,16 +3434,16 @@ index a69c5d5cad6168aeaae41e8adc319dc8c976b1e2..763b3e9ea24b14c54abf94048931f292 } } -@@ -428,7 +427,7 @@ public final class SimplePluginManager implements PluginManager { - @Override +@@ -448,7 +447,7 @@ public final class SimplePluginManager implements PluginManager { @Nullable public synchronized Plugin getPlugin(@NotNull String name) { + if (true) {return this.paperPluginManager.getPlugin(name);} // Paper - return lookupNames.get(name.replace(' ', '_')); + return lookupNames.get(name.replace(' ', '_').toLowerCase(java.util.Locale.ENGLISH)); // Paper } @Override -@@ -646,7 +645,8 @@ public final class SimplePluginManager implements PluginManager { +@@ -676,7 +675,8 @@ public final class SimplePluginManager implements PluginManager { throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled"); } @@ -3452,28 +3453,29 @@ index a69c5d5cad6168aeaae41e8adc319dc8c976b1e2..763b3e9ea24b14c54abf94048931f292 getEventListeners(event).register(new TimedRegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); } else { getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); -@@ -866,7 +866,7 @@ public final class SimplePluginManager implements PluginManager { - +@@ -911,7 +911,7 @@ public final class SimplePluginManager implements PluginManager { @Override public boolean useTimings() { + if (true) {return this.paperPluginManager.useTimings();} // Paper - return useTimings; + return co.aikar.timings.Timings.isTimingsEnabled(); // Spigot } /** -@@ -875,6 +875,6 @@ public final class SimplePluginManager implements PluginManager { +@@ -920,7 +920,7 @@ public final class SimplePluginManager implements PluginManager { * @param use True if per event timing code should be used */ public void useTimings(boolean use) { - useTimings = use; + co.aikar.timings.Timings.setTimingsEnabled(use); // Paper } - } + + // Paper start diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 047c0304fd617cec990f80815b43916c6ef5a94c..5c1b8b05d8a5408bb4830942c74ebfe400ab5a32 100644 +index d0ad072c832b8fc8a1cfdcafdd42c724531a2e29..02062284dbc1a6c923ceffa5e4d6a3be8c7429d3 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -54,7 +54,6 @@ public final class JavaPluginLoader implements PluginLoader { +@@ -55,7 +55,6 @@ public final class JavaPluginLoader implements PluginLoader { private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; private final List loaders = new CopyOnWriteArrayList(); private final LibraryLoader libraryLoader; @@ -3481,7 +3483,7 @@ index 047c0304fd617cec990f80815b43916c6ef5a94c..5c1b8b05d8a5408bb4830942c74ebfe4 /** * This class was not meant to be constructed explicitly -@@ -292,27 +291,21 @@ public final class JavaPluginLoader implements PluginLoader { +@@ -294,27 +293,21 @@ public final class JavaPluginLoader implements PluginLoader { } } @@ -3513,15 +3515,13 @@ index 047c0304fd617cec990f80815b43916c6ef5a94c..5c1b8b05d8a5408bb4830942c74ebfe4 eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); } else { diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 2f74ec96ece706de23156ebabfe493211bc05391..6148b69af39344f758b05a28c7c572befa9b8f3f 100644 +index e721c58eafee2180d4ba1a73002cf850355a366e..39c9253d03bae99f8b5b19d22295f6172606d57b 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -29,7 +29,8 @@ import org.jetbrains.annotations.Nullable; - /** - * A ClassLoader for plugins, to allow shared classes across multiple plugins +@@ -31,6 +31,7 @@ import org.jetbrains.annotations.Nullable; */ --final class PluginClassLoader extends URLClassLoader { -+public final class PluginClassLoader extends URLClassLoader { // Spigot + @org.jetbrains.annotations.ApiStatus.Internal // Paper + public final class PluginClassLoader extends URLClassLoader implements io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader { // Paper + public JavaPlugin getPlugin() { return plugin; } // Spigot private final JavaPluginLoader loader; private final Map> classes = new ConcurrentHashMap>(); diff --git a/patches/api/0011-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/api/0011-Add-command-line-option-to-load-extra-plugin-jars-no.patch new file mode 100644 index 0000000000..c3bb33b35f --- /dev/null +++ b/patches/api/0011-Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -0,0 +1,96 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Tue, 18 May 2021 14:42:26 -0700 +Subject: [PATCH] Add command line option to load extra plugin jars not in the + plugins folder + +ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index e24589a4cb42b0163e4a1455b8b11d7130b5cd41..71a09ed2b9863d2d339967f41ab6373ec27429d3 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -76,6 +76,20 @@ public final class Bukkit { + return server; + } + ++ /** ++ * Returns the de facto plugins directory, generally used for storing plugin jars to be loaded, ++ * as well as their {@link org.bukkit.plugin.Plugin#getDataFolder() data folders}. ++ * ++ *

Plugins should use {@link org.bukkit.plugin.Plugin#getDataFolder()} rather than traversing this ++ * directory manually when determining the location in which to store their data and configuration files.

++ * ++ * @return plugins directory ++ */ ++ @NotNull ++ public static File getPluginsFolder() { ++ return server.getPluginsFolder(); ++ } ++ + /** + * Attempts to set the {@link Server} singleton. + *

+diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index ac087402c90dad4b3c499fcf8507e50e9099cea5..a4f8035b40eebff8afe01788781128b04247f28c 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -61,6 +61,18 @@ import org.jetbrains.annotations.Nullable; + */ + public interface Server extends PluginMessageRecipient, net.kyori.adventure.audience.ForwardingAudience { // Paper + ++ /** ++ * Returns the de facto plugins directory, generally used for storing plugin jars to be loaded, ++ * as well as their {@link org.bukkit.plugin.Plugin#getDataFolder() data folders}. ++ * ++ *

Plugins should use {@link org.bukkit.plugin.Plugin#getDataFolder()} rather than traversing this ++ * directory manually when determining the location in which to store their data and configuration files.

++ * ++ * @return plugins directory ++ */ ++ @NotNull ++ File getPluginsFolder(); ++ + /** + * Used for all administrative messages, such as an operator using a + * command. +diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +index f13dcbe448111b24b36105d25527ba87ccc9334e..3fcb73a0fc2daaeb76dd4c6757afce52c5b3118b 100644 +--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java ++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java +@@ -116,9 +116,22 @@ public final class SimplePluginManager implements PluginManager { + @Override + @NotNull + public Plugin[] loadPlugins(@NotNull File directory) { ++ // Paper start - extra jars ++ return this.loadPlugins(directory, java.util.Collections.emptyList()); ++ } ++ @NotNull ++ public Plugin[] loadPlugins(final @NotNull File directory, final @NotNull List extraPluginJars) { ++ // Paper end + if (true) { + List pluginList = new ArrayList<>(); + java.util.Collections.addAll(pluginList, this.paperPluginManager.loadPlugins(directory)); ++ for (File file : extraPluginJars) { ++ try { ++ pluginList.add(this.paperPluginManager.loadPlugin(file)); ++ } catch (Exception e) { ++ this.server.getLogger().log(Level.SEVERE, "Plugin loading error!", e); ++ } ++ } + return pluginList.toArray(new Plugin[0]); + } + Preconditions.checkArgument(directory != null, "Directory cannot be null"); +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 02062284dbc1a6c923ceffa5e4d6a3be8c7429d3..88d852c1a729ffd5951da803da424b31591c9f9a 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -93,7 +93,7 @@ public final class JavaPluginLoader implements PluginLoader { + throw new InvalidPluginException(ex); + } + +- final File parentFile = file.getParentFile(); ++ final File parentFile = this.server.getPluginsFolder(); // Paper + final File dataFolder = new File(parentFile, description.getName()); + @SuppressWarnings("deprecation") + final File oldDataFolder = new File(parentFile, description.getRawName()); diff --git a/patches/api/0010-Player-affects-spawning-API.patch b/patches/api/0012-Player-affects-spawning-API.patch similarity index 100% rename from patches/api/0010-Player-affects-spawning-API.patch rename to patches/api/0012-Player-affects-spawning-API.patch diff --git a/patches/api/0011-Add-getTPS-method.patch b/patches/api/0013-Add-getTPS-method.patch similarity index 100% rename from patches/api/0011-Add-getTPS-method.patch rename to patches/api/0013-Add-getTPS-method.patch diff --git a/patches/api/0012-Version-Command-2.0.patch b/patches/api/0014-Version-Command-2.0.patch similarity index 98% rename from patches/api/0012-Version-Command-2.0.patch rename to patches/api/0014-Version-Command-2.0.patch index 802400840a..9a83efca80 100644 --- a/patches/api/0012-Version-Command-2.0.patch +++ b/patches/api/0014-Version-Command-2.0.patch @@ -56,10 +56,10 @@ index 0000000000000000000000000000000000000000..a736d7bcdc5861a01b66ba36158db1c7 + } +} diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 33c005a11e1ee241c1146e2cc291d523b1dd744e..5183d3b1893fdcad9a475b747cb34df5653774fd 100644 +index daf3ac72cae4d19c0273058dc6a1e1afe9a47f77..24fad8e59a3a5a174d24505cedda2a3fd52115b1 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -104,5 +104,12 @@ public interface UnsafeValues { +@@ -114,5 +114,12 @@ public interface UnsafeValues { * @return name */ String getTimingsServerName(); diff --git a/patches/api/0013-Entity-Origin-API.patch b/patches/api/0015-Entity-Origin-API.patch similarity index 100% rename from patches/api/0013-Entity-Origin-API.patch rename to patches/api/0015-Entity-Origin-API.patch diff --git a/patches/api/0014-Add-PlayerLocaleChangeEvent.patch b/patches/api/0016-Add-PlayerLocaleChangeEvent.patch similarity index 100% rename from patches/api/0014-Add-PlayerLocaleChangeEvent.patch rename to patches/api/0016-Add-PlayerLocaleChangeEvent.patch diff --git a/patches/api/0015-Add-view-distance-API.patch b/patches/api/0017-Add-view-distance-API.patch similarity index 100% rename from patches/api/0015-Add-view-distance-API.patch rename to patches/api/0017-Add-view-distance-API.patch diff --git a/patches/api/0016-Add-BeaconEffectEvent.patch b/patches/api/0018-Add-BeaconEffectEvent.patch similarity index 100% rename from patches/api/0016-Add-BeaconEffectEvent.patch rename to patches/api/0018-Add-BeaconEffectEvent.patch diff --git a/patches/api/0017-Add-PlayerInitialSpawnEvent.patch b/patches/api/0019-Add-PlayerInitialSpawnEvent.patch similarity index 100% rename from patches/api/0017-Add-PlayerInitialSpawnEvent.patch rename to patches/api/0019-Add-PlayerInitialSpawnEvent.patch diff --git a/patches/api/0019-Expose-server-CommandMap.patch b/patches/api/0020-Expose-server-CommandMap.patch similarity index 100% rename from patches/api/0019-Expose-server-CommandMap.patch rename to patches/api/0020-Expose-server-CommandMap.patch diff --git a/patches/api/0020-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/patches/api/0021-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch similarity index 100% rename from patches/api/0020-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch rename to patches/api/0021-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch diff --git a/patches/api/0021-Add-exception-reporting-event.patch b/patches/api/0022-Add-exception-reporting-event.patch similarity index 97% rename from patches/api/0021-Add-exception-reporting-event.patch rename to patches/api/0022-Add-exception-reporting-event.patch index fb5e83667b..bed957377c 100644 --- a/patches/api/0021-Add-exception-reporting-event.patch +++ b/patches/api/0022-Add-exception-reporting-event.patch @@ -462,7 +462,7 @@ index 0000000000000000000000000000000000000000..5582999fe94c7a3dac655044ccc6d078 + } +} diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index f99d71301ceaa3af07ff0525f7d657ac6253d0e6..2e23c124311b38aaea64dd274c33afcd52edcf43 100644 +index 4205649948a9e2a72f64c3f007112245abac6d50..b3b32ce429edbf1ed040354dbe28ab86f0d24201 100644 --- a/src/main/java/org/bukkit/command/SimpleCommandMap.java +++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java @@ -155,11 +155,14 @@ public class SimpleCommandMap implements CommandMap { @@ -493,10 +493,10 @@ index f99d71301ceaa3af07ff0525f7d657ac6253d0e6..2e23c124311b38aaea64dd274c33afcd } diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 1bfa9fcb1b803eecfe33156f81ee88d2922ca88a..b535ab89b5a04371bac41720d28b4af8b18f1c20 100644 +index 5a25e44c6ddeec5ad5fdd8c4a1f30dba5546cbe6..d1d5bf23529434730df7be8ae463d2e32c9fcf5f 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -488,7 +488,8 @@ public final class SimplePluginManager implements PluginManager { +@@ -515,7 +515,8 @@ public final class SimplePluginManager implements PluginManager { try { plugin.getPluginLoader().enablePlugin(plugin); } catch (Throwable ex) { @@ -506,7 +506,7 @@ index 1bfa9fcb1b803eecfe33156f81ee88d2922ca88a..b535ab89b5a04371bac41720d28b4af8 } HandlerList.bakeAll(); -@@ -509,32 +510,37 @@ public final class SimplePluginManager implements PluginManager { +@@ -538,32 +539,37 @@ public final class SimplePluginManager implements PluginManager { try { plugin.getPluginLoader().disablePlugin(plugin); } catch (Throwable ex) { @@ -549,7 +549,7 @@ index 1bfa9fcb1b803eecfe33156f81ee88d2922ca88a..b535ab89b5a04371bac41720d28b4af8 } try { -@@ -547,6 +553,13 @@ public final class SimplePluginManager implements PluginManager { +@@ -576,6 +582,13 @@ public final class SimplePluginManager implements PluginManager { } } @@ -562,8 +562,8 @@ index 1bfa9fcb1b803eecfe33156f81ee88d2922ca88a..b535ab89b5a04371bac41720d28b4af8 + @Override public void clearPlugins() { - synchronized (this) { -@@ -610,7 +623,13 @@ public final class SimplePluginManager implements PluginManager { + if (true) {this.paperPluginManager.clearPlugins(); return;} // Paper +@@ -641,7 +654,13 @@ public final class SimplePluginManager implements PluginManager { )); } } catch (Throwable ex) { diff --git a/patches/api/0022-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/patches/api/0023-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch similarity index 100% rename from patches/api/0022-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch rename to patches/api/0023-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch diff --git a/patches/api/0023-Fix-ServerListPingEvent-flagging-as-Async.patch b/patches/api/0024-Fix-ServerListPingEvent-flagging-as-Async.patch similarity index 100% rename from patches/api/0023-Fix-ServerListPingEvent-flagging-as-Async.patch rename to patches/api/0024-Fix-ServerListPingEvent-flagging-as-Async.patch diff --git a/patches/api/0024-Player-Tab-List-and-Title-APIs.patch b/patches/api/0025-Player-Tab-List-and-Title-APIs.patch similarity index 100% rename from patches/api/0024-Player-Tab-List-and-Title-APIs.patch rename to patches/api/0025-Player-Tab-List-and-Title-APIs.patch diff --git a/patches/api/0025-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/api/0026-Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 100% rename from patches/api/0025-Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to patches/api/0026-Add-methods-for-working-with-arrows-stuck-in-living-.patch diff --git a/patches/api/0026-Complete-resource-pack-API.patch b/patches/api/0027-Complete-resource-pack-API.patch similarity index 100% rename from patches/api/0026-Complete-resource-pack-API.patch rename to patches/api/0027-Complete-resource-pack-API.patch diff --git a/patches/api/0030-Add-command-to-reload-permissions.yml-and-require-co.patch b/patches/api/0030-Add-command-to-reload-permissions.yml-and-require-co.patch index 9f6ec05cf3..595ab58607 100644 --- a/patches/api/0030-Add-command-to-reload-permissions.yml-and-require-co.patch +++ b/patches/api/0030-Add-command-to-reload-permissions.yml-and-require-co.patch @@ -84,21 +84,3 @@ index 50cc311be7904cc8fc6070a21c8e4de3a489fd20..5fa9d648bc780e874f658597f1a24715 + return java.util.Collections.singletonList("permissions"); // Paper } } -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index b535ab89b5a04371bac41720d28b4af8b18f1c20..77caec9f974077ed6580d3cbbc20feb1199feb11 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -906,4 +906,13 @@ public final class SimplePluginManager implements PluginManager { - public void useTimings(boolean use) { - co.aikar.timings.Timings.setTimingsEnabled(use); // Paper - } -+ -+ // Paper start -+ public void clearPermissions() { -+ permissions.clear(); -+ defaultPerms.get(true).clear(); -+ defaultPerms.get(false).clear(); -+ } -+ // Paper end -+ - } diff --git a/patches/api/0043-Allow-Reloading-of-Command-Aliases.patch b/patches/api/0043-Allow-Reloading-of-Command-Aliases.patch index 5be01c94c3..66c1e8846b 100644 --- a/patches/api/0043-Allow-Reloading-of-Command-Aliases.patch +++ b/patches/api/0043-Allow-Reloading-of-Command-Aliases.patch @@ -56,7 +56,7 @@ index bd2c7a6964722412148fae39e1b4951fc0002b9b..864c263bbd4dd6dd7c37a74b39b1a40a + // Paper end } diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index 2e23c124311b38aaea64dd274c33afcd52edcf43..950a2d0b3b583c6b9a703190874bbc4df2783ab7 100644 +index b3b32ce429edbf1ed040354dbe28ab86f0d24201..1424060c0a162020d4a680e0a592224561067b16 100644 --- a/src/main/java/org/bukkit/command/SimpleCommandMap.java +++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java @@ -293,4 +293,11 @@ public class SimpleCommandMap implements CommandMap { diff --git a/patches/api/0051-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/api/0051-Provide-E-TE-Chunk-count-stat-methods.patch index d90b03ed52..cfa57eedb2 100644 --- a/patches/api/0051-Provide-E-TE-Chunk-count-stat-methods.patch +++ b/patches/api/0051-Provide-E-TE-Chunk-count-stat-methods.patch @@ -7,7 +7,7 @@ Provides counts without the ineffeciency of using .getEntities().size() which creates copy of the collections. diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 75a87b221cc0f6334c5283130a7b2bfdf4eedd03..e6c9942f7820f2b8750c1bb0825c8bdbc6f4b99e 100644 +index 8a6a548314eef8d486be908e38e3a4562f26bdb4..749d3de7dad480965be536938733d72bdfc2995b 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -45,6 +45,33 @@ import org.jetbrains.annotations.Nullable; diff --git a/patches/api/0068-LivingEntity-setKiller.patch b/patches/api/0067-LivingEntity-setKiller.patch similarity index 90% rename from patches/api/0068-LivingEntity-setKiller.patch rename to patches/api/0067-LivingEntity-setKiller.patch index e5800f86d8..e117b6ac51 100644 --- a/patches/api/0068-LivingEntity-setKiller.patch +++ b/patches/api/0067-LivingEntity-setKiller.patch @@ -5,7 +5,7 @@ Subject: [PATCH] LivingEntity#setKiller diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 069711e792f92c2afa9dc661a2b14c55ffa54114..3489c719089e5cc0cc4710e8a06417c02dd76767 100644 +index 9977bb3cb5a66c84db816f8e4597db1c053f77c8..ccd8f36c8450bab9f609bb220b5270394960580e 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -295,6 +295,15 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0069-ProfileWhitelistVerifyEvent.patch b/patches/api/0068-ProfileWhitelistVerifyEvent.patch similarity index 100% rename from patches/api/0069-ProfileWhitelistVerifyEvent.patch rename to patches/api/0068-ProfileWhitelistVerifyEvent.patch diff --git a/patches/api/0070-Allow-plugins-to-use-SLF4J-for-logging.patch b/patches/api/0069-Allow-plugins-to-use-SLF4J-for-logging.patch similarity index 88% rename from patches/api/0070-Allow-plugins-to-use-SLF4J-for-logging.patch rename to patches/api/0069-Allow-plugins-to-use-SLF4J-for-logging.patch index 2fbad5cbc1..4254e0f90a 100644 --- a/patches/api/0070-Allow-plugins-to-use-SLF4J-for-logging.patch +++ b/patches/api/0069-Allow-plugins-to-use-SLF4J-for-logging.patch @@ -14,7 +14,7 @@ it without having to shade it in the plugin and going through several layers of logging abstraction. diff --git a/build.gradle.kts b/build.gradle.kts -index 9d650b937610d83748b30d724cee97afd715167f..3c4dd6ebc2289c44c2f5723e7920aadffdc51884 100644 +index f5f217a3a786bf4c95bea74c135289d12205cf7b..56333098150995cd36793de75a998b628e82881d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -39,6 +39,8 @@ dependencies { @@ -27,10 +27,10 @@ index 9d650b937610d83748b30d724cee97afd715167f..3c4dd6ebc2289c44c2f5723e7920aadf implementation("org.ow2.asm:asm:9.2") implementation("org.ow2.asm:asm-commons:9.2") diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java -index b37938745f916b5f0111b07b1a1c97527f026e9d..08aef59d8443038771704d9587e31f299e587307 100644 +index 8c76716249e44ed8bf6be94c1f5c7b6d9bb35be2..4eb639fbb46a0848be207149ea433455550fae1c 100644 --- a/src/main/java/org/bukkit/plugin/Plugin.java +++ b/src/main/java/org/bukkit/plugin/Plugin.java -@@ -186,6 +186,22 @@ public interface Plugin extends TabExecutor { +@@ -198,6 +198,22 @@ public interface Plugin extends TabExecutor { } // Paper end diff --git a/patches/api/0071-Handle-plugin-prefixes-in-implementation-logging-con.patch b/patches/api/0070-Handle-plugin-prefixes-in-implementation-logging-con.patch similarity index 79% rename from patches/api/0071-Handle-plugin-prefixes-in-implementation-logging-con.patch rename to patches/api/0070-Handle-plugin-prefixes-in-implementation-logging-con.patch index e8b752d9a7..692bbf51ef 100644 --- a/patches/api/0071-Handle-plugin-prefixes-in-implementation-logging-con.patch +++ b/patches/api/0070-Handle-plugin-prefixes-in-implementation-logging-con.patch @@ -17,10 +17,10 @@ The implementation should handle plugin prefixes by displaying logger names when appropriate. diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -index 669a70faa95d0d6525a731d73499ed6fb0b48320..1ff0e0ef1aebec5bbb0a8a09af11d07b2a3220e8 100644 +index a5636b1f223dd37420a4acbccf28f7198a7eee98..accac9527b1c267b75774532b85f28c868b06c28 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -@@ -43,7 +43,7 @@ public abstract class JavaPlugin extends PluginBase { +@@ -44,7 +44,7 @@ public abstract class JavaPlugin extends PluginBase { private boolean naggable = true; private FileConfiguration newConfig = null; private File configFile = null; @@ -28,14 +28,14 @@ index 669a70faa95d0d6525a731d73499ed6fb0b48320..1ff0e0ef1aebec5bbb0a8a09af11d07b + private Logger logger = null; // Paper - PluginLogger -> Logger public JavaPlugin() { - final ClassLoader classLoader = this.getClass().getClassLoader(); -@@ -277,7 +277,8 @@ public abstract class JavaPlugin extends PluginBase { + // Paper start +@@ -297,8 +297,8 @@ public abstract class JavaPlugin extends PluginBase { this.dataFolder = dataFolder; this.classLoader = classLoader; this.configFile = new File(dataFolder, "config.yml"); - this.logger = new PluginLogger(this); -+ // Paper - Handle plugin prefix in implementation -+ this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); + this.pluginMeta = configuration; // Paper ++ this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); // Paper - Handle plugin prefix in implementation } /** diff --git a/patches/api/0072-Add-PlayerJumpEvent.patch b/patches/api/0071-Add-PlayerJumpEvent.patch similarity index 100% rename from patches/api/0072-Add-PlayerJumpEvent.patch rename to patches/api/0071-Add-PlayerJumpEvent.patch diff --git a/patches/api/0073-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/patches/api/0072-Add-workaround-for-plugins-modifying-the-parent-of-t.patch similarity index 65% rename from patches/api/0073-Add-workaround-for-plugins-modifying-the-parent-of-t.patch rename to patches/api/0072-Add-workaround-for-plugins-modifying-the-parent-of-t.patch index 4b8543b4f9..eadb0c1fc9 100644 --- a/patches/api/0073-Add-workaround-for-plugins-modifying-the-parent-of-t.patch +++ b/patches/api/0072-Add-workaround-for-plugins-modifying-the-parent-of-t.patch @@ -14,12 +14,13 @@ parent of the plugin logger to avoid this. diff --git a/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java new file mode 100644 -index 0000000000000000000000000000000000000000..76f2cb9cd99cad2a9484eab2becd8c36f1dd91b3 +index 0000000000000000000000000000000000000000..087ee57fe5485bc760fadd45a176d4d90a18f9f8 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/utils/PaperPluginLogger.java -@@ -0,0 +1,41 @@ +@@ -0,0 +1,48 @@ +package com.destroystokyo.paper.utils; + ++import io.papermc.paper.plugin.configuration.PluginMeta; +import org.bukkit.plugin.PluginDescriptionFile; + +import java.util.logging.Level; @@ -32,20 +33,26 @@ index 0000000000000000000000000000000000000000..76f2cb9cd99cad2a9484eab2becd8c36 + */ +public class PaperPluginLogger extends Logger { + ++ @Deprecated(forRemoval = true) + @NotNull + public static Logger getLogger(@NotNull PluginDescriptionFile description) { -+ Logger logger = new PaperPluginLogger(description); ++ return getLogger((PluginMeta) description); ++ } ++ ++ @NotNull ++ public static Logger getLogger(@NotNull PluginMeta meta) { ++ Logger logger = new PaperPluginLogger(meta); + if (!LogManager.getLogManager().addLogger(logger)) { + // Disable this if it's going to happen across reloads anyways... + //logger.log(Level.WARNING, "Could not insert plugin logger - one was already found: {}", LogManager.getLogManager().getLogger(this.getName())); -+ logger = LogManager.getLogManager().getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); ++ logger = LogManager.getLogManager().getLogger(meta.getLoggerPrefix() != null ? meta.getLoggerPrefix() : meta.getName()); + } + + return logger; + } + -+ private PaperPluginLogger(@NotNull PluginDescriptionFile description) { -+ super(description.getPrefix() != null ? description.getPrefix() : description.getName(), null); ++ private PaperPluginLogger(@NotNull PluginMeta meta) { ++ super(meta.getLoggerPrefix() != null ? meta.getLoggerPrefix() : meta.getName(), null); + } + + @Override @@ -60,24 +67,23 @@ index 0000000000000000000000000000000000000000..76f2cb9cd99cad2a9484eab2becd8c36 + +} diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -index 1ff0e0ef1aebec5bbb0a8a09af11d07b2a3220e8..3bea5dd67ad0393160ccede4ac99a3c7baa1803b 100644 +index accac9527b1c267b75774532b85f28c868b06c28..a536c47fb5f05cad046c2f3374c69f4f83f7f32c 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java -@@ -43,7 +43,7 @@ public abstract class JavaPlugin extends PluginBase { +@@ -44,7 +44,7 @@ public abstract class JavaPlugin extends PluginBase { private boolean naggable = true; private FileConfiguration newConfig = null; private File configFile = null; - private Logger logger = null; // Paper - PluginLogger -> Logger -+ Logger logger = null; // Paper - PluginLogger -> Logger, package-private ++ public Logger logger = null; // Paper - PluginLogger -> Logger, public public JavaPlugin() { - final ClassLoader classLoader = this.getClass().getClassLoader(); -@@ -277,8 +277,11 @@ public abstract class JavaPlugin extends PluginBase { - this.dataFolder = dataFolder; + // Paper start +@@ -298,7 +298,11 @@ public abstract class JavaPlugin extends PluginBase { this.classLoader = classLoader; this.configFile = new File(dataFolder, "config.yml"); -- // Paper - Handle plugin prefix in implementation -- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); + this.pluginMeta = configuration; // Paper +- this.logger = Logger.getLogger(description.getPrefix() != null ? description.getPrefix() : description.getName()); // Paper - Handle plugin prefix in implementation + // Paper start + if (this.logger == null) { + this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(this.description); @@ -87,31 +93,23 @@ index 1ff0e0ef1aebec5bbb0a8a09af11d07b2a3220e8..3bea5dd67ad0393160ccede4ac99a3c7 /** diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 6148b69af39344f758b05a28c7c572befa9b8f3f..0db641f5d5e1293b236ad0d2e3a156802ffed839 100644 +index 39c9253d03bae99f8b5b19d22295f6172606d57b..a657654079c40a0fee6f70c7d72df24b3827b911 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -44,6 +44,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - private JavaPlugin pluginInit; - private IllegalStateException pluginState; - private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); -+ private java.util.logging.Logger logger; // Paper - add field - - static { - ClassLoader.registerAsParallelCapable(); -@@ -62,6 +63,8 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot +@@ -66,7 +66,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm this.url = file.toURI().toURL(); this.libraryLoader = libraryLoader; +- + this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early -+ - try { - Class jarClass; - try { -@@ -229,6 +232,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot + // Paper start + this.classLoaderGroup = io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage.instance().registerSpigotGroup(this); // Paper + this.dependencyContext = dependencyContext; +@@ -260,6 +260,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm pluginState = new IllegalStateException("Initial initialization"); this.pluginInit = javaPlugin; + javaPlugin.logger = this.logger; // Paper - set logger - javaPlugin.init(loader, loader.server, description, dataFolder, file, this); + javaPlugin.init(null, org.bukkit.Bukkit.getServer(), description, dataFolder, file, this); // Paper } - } + diff --git a/patches/api/0074-Add-PlayerArmorChangeEvent.patch b/patches/api/0073-Add-PlayerArmorChangeEvent.patch similarity index 100% rename from patches/api/0074-Add-PlayerArmorChangeEvent.patch rename to patches/api/0073-Add-PlayerArmorChangeEvent.patch diff --git a/patches/api/0075-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/api/0074-API-to-get-a-BlockState-without-a-snapshot.patch similarity index 100% rename from patches/api/0075-API-to-get-a-BlockState-without-a-snapshot.patch rename to patches/api/0074-API-to-get-a-BlockState-without-a-snapshot.patch diff --git a/patches/api/0076-AsyncTabCompleteEvent.patch b/patches/api/0075-AsyncTabCompleteEvent.patch similarity index 99% rename from patches/api/0076-AsyncTabCompleteEvent.patch rename to patches/api/0075-AsyncTabCompleteEvent.patch index 205825a521..ebb7553005 100644 --- a/patches/api/0076-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 8275a5d7e1de39a5171e254f449a42c6defd3445..4bca64b2a44ae032730575ecba39f9737a5a1ec7 100644 +index 9825db30d42701aad5d9970bbb989fbff0142fb1..2cb81e6d253d70388da15c9d07b630277d486c70 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/0077-Expose-client-protocol-version-and-virtual-host.patch b/patches/api/0076-Expose-client-protocol-version-and-virtual-host.patch similarity index 96% rename from patches/api/0077-Expose-client-protocol-version-and-virtual-host.patch rename to patches/api/0076-Expose-client-protocol-version-and-virtual-host.patch index 1acdee557a..b8c4f58271 100644 --- a/patches/api/0077-Expose-client-protocol-version-and-virtual-host.patch +++ b/patches/api/0076-Expose-client-protocol-version-and-virtual-host.patch @@ -57,7 +57,7 @@ index 0000000000000000000000000000000000000000..7b2af1bd72dfbcf4e962a982940fc49b + +} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 50faa513411cdb611ae228f0c07a7dfe15807b85..1f29ed50c981fa262790a070722bbe9fecac5b02 100644 +index e15a9525b989abee62ca2d8ec924ee492118abb2..7efa33336a6f6309cf11677185fd11a7c0757bb3 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -41,7 +41,7 @@ import org.jetbrains.annotations.Nullable; diff --git a/patches/api/0078-Display-warning-on-deprecated-recipe-API.patch b/patches/api/0077-Display-warning-on-deprecated-recipe-API.patch similarity index 100% rename from patches/api/0078-Display-warning-on-deprecated-recipe-API.patch rename to patches/api/0077-Display-warning-on-deprecated-recipe-API.patch diff --git a/patches/api/0079-PlayerPickupExperienceEvent.patch b/patches/api/0078-PlayerPickupExperienceEvent.patch similarity index 100% rename from patches/api/0079-PlayerPickupExperienceEvent.patch rename to patches/api/0078-PlayerPickupExperienceEvent.patch diff --git a/patches/api/0080-ExperienceOrbMergeEvent.patch b/patches/api/0079-ExperienceOrbMergeEvent.patch similarity index 100% rename from patches/api/0080-ExperienceOrbMergeEvent.patch rename to patches/api/0079-ExperienceOrbMergeEvent.patch diff --git a/patches/api/0081-Ability-to-apply-mending-to-XP-API.patch b/patches/api/0080-Ability-to-apply-mending-to-XP-API.patch similarity index 100% rename from patches/api/0081-Ability-to-apply-mending-to-XP-API.patch rename to patches/api/0080-Ability-to-apply-mending-to-XP-API.patch diff --git a/patches/api/0082-PreCreatureSpawnEvent.patch b/patches/api/0081-PreCreatureSpawnEvent.patch similarity index 98% rename from patches/api/0082-PreCreatureSpawnEvent.patch rename to patches/api/0081-PreCreatureSpawnEvent.patch index abc126ec41..f00514bf0f 100644 --- a/patches/api/0082-PreCreatureSpawnEvent.patch +++ b/patches/api/0081-PreCreatureSpawnEvent.patch @@ -16,7 +16,7 @@ See: https://github.com/PaperMC/Paper/issues/917 diff --git a/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..3ad231aa3206c8cfd5ec995249584cebab5d11f3 +index 0000000000000000000000000000000000000000..02e421b0bb4ce3529ef1c4d34ec8a0c0345cce57 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/event/entity/PreCreatureSpawnEvent.java @@ -0,0 +1,105 @@ diff --git a/patches/api/0083-PlayerNaturallySpawnCreaturesEvent.patch b/patches/api/0082-PlayerNaturallySpawnCreaturesEvent.patch similarity index 100% rename from patches/api/0083-PlayerNaturallySpawnCreaturesEvent.patch rename to patches/api/0082-PlayerNaturallySpawnCreaturesEvent.patch diff --git a/patches/api/0084-Add-setPlayerProfile-API-for-Skulls.patch b/patches/api/0083-Add-setPlayerProfile-API-for-Skulls.patch similarity index 100% rename from patches/api/0084-Add-setPlayerProfile-API-for-Skulls.patch rename to patches/api/0083-Add-setPlayerProfile-API-for-Skulls.patch diff --git a/patches/api/0085-Fill-Profile-Property-Events.patch b/patches/api/0084-Fill-Profile-Property-Events.patch similarity index 100% rename from patches/api/0085-Fill-Profile-Property-Events.patch rename to patches/api/0084-Fill-Profile-Property-Events.patch diff --git a/patches/api/0086-PlayerAdvancementCriterionGrantEvent.patch b/patches/api/0085-PlayerAdvancementCriterionGrantEvent.patch similarity index 100% rename from patches/api/0086-PlayerAdvancementCriterionGrantEvent.patch rename to patches/api/0085-PlayerAdvancementCriterionGrantEvent.patch diff --git a/patches/api/0087-Add-ArmorStand-Item-Meta.patch b/patches/api/0086-Add-ArmorStand-Item-Meta.patch similarity index 100% rename from patches/api/0087-Add-ArmorStand-Item-Meta.patch rename to patches/api/0086-Add-ArmorStand-Item-Meta.patch diff --git a/patches/api/0088-Optimize-Hoppers.patch b/patches/api/0087-Optimize-Hoppers.patch similarity index 100% rename from patches/api/0088-Optimize-Hoppers.patch rename to patches/api/0087-Optimize-Hoppers.patch diff --git a/patches/api/0089-Tameable-getOwnerUniqueId-API.patch b/patches/api/0088-Tameable-getOwnerUniqueId-API.patch similarity index 100% rename from patches/api/0089-Tameable-getOwnerUniqueId-API.patch rename to patches/api/0088-Tameable-getOwnerUniqueId-API.patch diff --git a/patches/api/0090-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/api/0089-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 100% rename from patches/api/0090-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to patches/api/0089-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch diff --git a/patches/api/0091-Add-extended-PaperServerListPingEvent.patch b/patches/api/0090-Add-extended-PaperServerListPingEvent.patch similarity index 100% rename from patches/api/0091-Add-extended-PaperServerListPingEvent.patch rename to patches/api/0090-Add-extended-PaperServerListPingEvent.patch diff --git a/patches/api/0092-Player.setPlayerProfile-API.patch b/patches/api/0091-Player.setPlayerProfile-API.patch similarity index 100% rename from patches/api/0092-Player.setPlayerProfile-API.patch rename to patches/api/0091-Player.setPlayerProfile-API.patch diff --git a/patches/api/0093-getPlayerUniqueId-API.patch b/patches/api/0092-getPlayerUniqueId-API.patch similarity index 100% rename from patches/api/0093-getPlayerUniqueId-API.patch rename to patches/api/0092-getPlayerUniqueId-API.patch diff --git a/patches/api/0094-Add-legacy-ping-support-to-PaperServerListPingEvent.patch b/patches/api/0093-Add-legacy-ping-support-to-PaperServerListPingEvent.patch similarity index 100% rename from patches/api/0094-Add-legacy-ping-support-to-PaperServerListPingEvent.patch rename to patches/api/0093-Add-legacy-ping-support-to-PaperServerListPingEvent.patch diff --git a/patches/api/0095-Add-openSign-method-to-HumanEntity.patch b/patches/api/0094-Add-openSign-method-to-HumanEntity.patch similarity index 100% rename from patches/api/0095-Add-openSign-method-to-HumanEntity.patch rename to patches/api/0094-Add-openSign-method-to-HumanEntity.patch diff --git a/patches/api/0096-Add-Ban-Methods-to-Player-Objects.patch b/patches/api/0095-Add-Ban-Methods-to-Player-Objects.patch similarity index 100% rename from patches/api/0096-Add-Ban-Methods-to-Player-Objects.patch rename to patches/api/0095-Add-Ban-Methods-to-Player-Objects.patch diff --git a/patches/api/0097-EndermanEscapeEvent.patch b/patches/api/0096-EndermanEscapeEvent.patch similarity index 100% rename from patches/api/0097-EndermanEscapeEvent.patch rename to patches/api/0096-EndermanEscapeEvent.patch diff --git a/patches/api/0098-Enderman.teleportRandomly.patch b/patches/api/0097-Enderman.teleportRandomly.patch similarity index 100% rename from patches/api/0098-Enderman.teleportRandomly.patch rename to patches/api/0097-Enderman.teleportRandomly.patch diff --git a/patches/api/0099-Additional-world.getNearbyEntities-API-s.patch b/patches/api/0098-Additional-world.getNearbyEntities-API-s.patch similarity index 99% rename from patches/api/0099-Additional-world.getNearbyEntities-API-s.patch rename to patches/api/0098-Additional-world.getNearbyEntities-API-s.patch index 3659b5a65e..750f260d01 100644 --- a/patches/api/0099-Additional-world.getNearbyEntities-API-s.patch +++ b/patches/api/0098-Additional-world.getNearbyEntities-API-s.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Additional world.getNearbyEntities API's Provides more methods to get nearby entities, and filter by types and predicates diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index e6c9942f7820f2b8750c1bb0825c8bdbc6f4b99e..3539e63993cc21f9eecda9046b759cebdfec80ff 100644 +index 749d3de7dad480965be536938733d72bdfc2995b..dad7de7246741d6f3f2a444cf0b88f396302a8af 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -1,6 +1,9 @@ diff --git a/patches/api/0100-Location.isChunkLoaded-API.patch b/patches/api/0099-Location.isChunkLoaded-API.patch similarity index 100% rename from patches/api/0100-Location.isChunkLoaded-API.patch rename to patches/api/0099-Location.isChunkLoaded-API.patch diff --git a/patches/api/0101-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/api/0100-Expand-World.spawnParticle-API-and-add-Builder.patch similarity index 100% rename from patches/api/0101-Expand-World.spawnParticle-API-and-add-Builder.patch rename to patches/api/0100-Expand-World.spawnParticle-API-and-add-Builder.patch diff --git a/patches/api/0102-EndermanAttackPlayerEvent.patch b/patches/api/0101-EndermanAttackPlayerEvent.patch similarity index 100% rename from patches/api/0102-EndermanAttackPlayerEvent.patch rename to patches/api/0101-EndermanAttackPlayerEvent.patch diff --git a/patches/api/0104-WitchConsumePotionEvent.patch b/patches/api/0102-WitchConsumePotionEvent.patch similarity index 100% rename from patches/api/0104-WitchConsumePotionEvent.patch rename to patches/api/0102-WitchConsumePotionEvent.patch diff --git a/patches/api/0105-WitchThrowPotionEvent.patch b/patches/api/0103-WitchThrowPotionEvent.patch similarity index 100% rename from patches/api/0105-WitchThrowPotionEvent.patch rename to patches/api/0103-WitchThrowPotionEvent.patch diff --git a/patches/api/0106-Location.toBlockLocation-toCenterLocation.patch b/patches/api/0104-Location.toBlockLocation-toCenterLocation.patch similarity index 100% rename from patches/api/0106-Location.toBlockLocation-toCenterLocation.patch rename to patches/api/0104-Location.toBlockLocation-toCenterLocation.patch diff --git a/patches/api/0107-PotionEffect-clone-methods.patch b/patches/api/0105-PotionEffect-clone-methods.patch similarity index 100% rename from patches/api/0107-PotionEffect-clone-methods.patch rename to patches/api/0105-PotionEffect-clone-methods.patch diff --git a/patches/api/0108-WitchReadyPotionEvent.patch b/patches/api/0106-WitchReadyPotionEvent.patch similarity index 100% rename from patches/api/0108-WitchReadyPotionEvent.patch rename to patches/api/0106-WitchReadyPotionEvent.patch diff --git a/patches/api/0109-ItemStack-getMaxItemUseDuration.patch b/patches/api/0107-ItemStack-getMaxItemUseDuration.patch similarity index 100% rename from patches/api/0109-ItemStack-getMaxItemUseDuration.patch rename to patches/api/0107-ItemStack-getMaxItemUseDuration.patch diff --git a/patches/api/0110-Add-EntityTeleportEndGatewayEvent.patch b/patches/api/0108-Add-EntityTeleportEndGatewayEvent.patch similarity index 100% rename from patches/api/0110-Add-EntityTeleportEndGatewayEvent.patch rename to patches/api/0108-Add-EntityTeleportEndGatewayEvent.patch diff --git a/patches/api/0111-Make-shield-blocking-delay-configurable.patch b/patches/api/0109-Make-shield-blocking-delay-configurable.patch similarity index 91% rename from patches/api/0111-Make-shield-blocking-delay-configurable.patch rename to patches/api/0109-Make-shield-blocking-delay-configurable.patch index 96405d00ae..42c5c4e0cb 100644 --- a/patches/api/0111-Make-shield-blocking-delay-configurable.patch +++ b/patches/api/0109-Make-shield-blocking-delay-configurable.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Make shield blocking delay configurable diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 3489c719089e5cc0cc4710e8a06417c02dd76767..81d89daf9691b5338b53bb7b0749ad802f5d026f 100644 +index ccd8f36c8450bab9f609bb220b5270394960580e..2bfeebe26f32d2e931dc483714d30430deeb9b04 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -731,5 +731,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0112-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch b/patches/api/0110-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch similarity index 100% rename from patches/api/0112-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch rename to patches/api/0110-EntityShootBowEvent-consumeArrow-and-getArrowItem-AP.patch diff --git a/patches/api/0113-Add-getNearbyXXX-methods-to-Location.patch b/patches/api/0111-Add-getNearbyXXX-methods-to-Location.patch similarity index 100% rename from patches/api/0113-Add-getNearbyXXX-methods-to-Location.patch rename to patches/api/0111-Add-getNearbyXXX-methods-to-Location.patch diff --git a/patches/api/0114-PlayerReadyArrowEvent.patch b/patches/api/0112-PlayerReadyArrowEvent.patch similarity index 100% rename from patches/api/0114-PlayerReadyArrowEvent.patch rename to patches/api/0112-PlayerReadyArrowEvent.patch diff --git a/patches/api/0115-Add-EntityKnockbackByEntityEvent-and-EntityPushedByE.patch b/patches/api/0113-Add-EntityKnockbackByEntityEvent-and-EntityPushedByE.patch similarity index 100% rename from patches/api/0115-Add-EntityKnockbackByEntityEvent-and-EntityPushedByE.patch rename to patches/api/0113-Add-EntityKnockbackByEntityEvent-and-EntityPushedByE.patch diff --git a/patches/api/0116-Expand-Explosions-API.patch b/patches/api/0114-Expand-Explosions-API.patch similarity index 98% rename from patches/api/0116-Expand-Explosions-API.patch rename to patches/api/0114-Expand-Explosions-API.patch index eefb112a52..f578a00aa5 100644 --- a/patches/api/0116-Expand-Explosions-API.patch +++ b/patches/api/0114-Expand-Explosions-API.patch @@ -106,7 +106,7 @@ index 6693e3d8dc2519facb12db981a6b6325faa095bf..5a6b33c6d9a68affdbd02c13fdb0854e * Returns a list of entities within a bounding box centered around a Location. * diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 8b48ce606523528f4322296b61a64bd12067387c..fd50f3a12863d1bc65d1880c939389f7b5d2c53c 100644 +index ae102dddda30ff0e15f70bdb17385c8d9d4b9a08..adf743334f4e69ebca8045df70800f67bcd7d98f 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -1424,6 +1424,88 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient diff --git a/patches/api/0117-ItemStack-API-additions-for-quantity-flags-lore.patch b/patches/api/0115-ItemStack-API-additions-for-quantity-flags-lore.patch similarity index 100% rename from patches/api/0117-ItemStack-API-additions-for-quantity-flags-lore.patch rename to patches/api/0115-ItemStack-API-additions-for-quantity-flags-lore.patch diff --git a/patches/api/0118-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/api/0116-LivingEntity-Hand-Raised-Item-Use-API.patch similarity index 96% rename from patches/api/0118-LivingEntity-Hand-Raised-Item-Use-API.patch rename to patches/api/0116-LivingEntity-Hand-Raised-Item-Use-API.patch index 95412562b4..719617eb8e 100644 --- a/patches/api/0118-LivingEntity-Hand-Raised-Item-Use-API.patch +++ b/patches/api/0116-LivingEntity-Hand-Raised-Item-Use-API.patch @@ -20,7 +20,7 @@ index 9715a9d36187e2eecfeab1a05087d27c28b8690e..12068d14af5731494a839b87b67ed3cc public ItemStack getItemInUse(); diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 81d89daf9691b5338b53bb7b0749ad802f5d026f..8241a89ac92845a2a8c2398dbeb76529abebd37c 100644 +index 2bfeebe26f32d2e931dc483714d30430deeb9b04..17e5d2e2acdae23d8ea3b3b1a89f62e8be7b81a8 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -745,5 +745,42 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0119-RangedEntity-API.patch b/patches/api/0117-RangedEntity-API.patch similarity index 100% rename from patches/api/0119-RangedEntity-API.patch rename to patches/api/0117-RangedEntity-API.patch diff --git a/patches/api/0120-Add-World.getEntity-UUID-API.patch b/patches/api/0118-Add-World.getEntity-UUID-API.patch similarity index 91% rename from patches/api/0120-Add-World.getEntity-UUID-API.patch rename to patches/api/0118-Add-World.getEntity-UUID-API.patch index 7a8b323bb4..759dc7c245 100644 --- a/patches/api/0120-Add-World.getEntity-UUID-API.patch +++ b/patches/api/0118-Add-World.getEntity-UUID-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add World.getEntity(UUID) API diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index fd50f3a12863d1bc65d1880c939389f7b5d2c53c..c58c9c7791eff28ba8f847f5bc60e0db757ababd 100644 +index adf743334f4e69ebca8045df70800f67bcd7d98f..e0caac06b7f5459faefbbd5a6a3486dbb6bfa9ba 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -944,6 +944,17 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient diff --git a/patches/api/0121-InventoryCloseEvent-Reason-API.patch b/patches/api/0119-InventoryCloseEvent-Reason-API.patch similarity index 100% rename from patches/api/0121-InventoryCloseEvent-Reason-API.patch rename to patches/api/0119-InventoryCloseEvent-Reason-API.patch diff --git a/patches/api/0122-Allow-setting-the-vex-s-summoner.patch b/patches/api/0120-Allow-setting-the-vex-s-summoner.patch similarity index 100% rename from patches/api/0122-Allow-setting-the-vex-s-summoner.patch rename to patches/api/0120-Allow-setting-the-vex-s-summoner.patch diff --git a/patches/api/0123-Entity-getChunk-API.patch b/patches/api/0121-Entity-getChunk-API.patch similarity index 100% rename from patches/api/0123-Entity-getChunk-API.patch rename to patches/api/0121-Entity-getChunk-API.patch diff --git a/patches/api/0125-EnderDragon-Events.patch b/patches/api/0122-EnderDragon-Events.patch similarity index 100% rename from patches/api/0125-EnderDragon-Events.patch rename to patches/api/0122-EnderDragon-Events.patch diff --git a/patches/api/0126-PlayerElytraBoostEvent.patch b/patches/api/0123-PlayerElytraBoostEvent.patch similarity index 100% rename from patches/api/0126-PlayerElytraBoostEvent.patch rename to patches/api/0123-PlayerElytraBoostEvent.patch diff --git a/patches/api/0127-PlayerLaunchProjectileEvent.patch b/patches/api/0124-PlayerLaunchProjectileEvent.patch similarity index 100% rename from patches/api/0127-PlayerLaunchProjectileEvent.patch rename to patches/api/0124-PlayerLaunchProjectileEvent.patch diff --git a/patches/api/0128-EntityTransformedEvent.patch b/patches/api/0125-EntityTransformedEvent.patch similarity index 100% rename from patches/api/0128-EntityTransformedEvent.patch rename to patches/api/0125-EntityTransformedEvent.patch diff --git a/patches/api/0129-Allow-disabling-armour-stand-ticking.patch b/patches/api/0126-Allow-disabling-armour-stand-ticking.patch similarity index 100% rename from patches/api/0129-Allow-disabling-armour-stand-ticking.patch rename to patches/api/0126-Allow-disabling-armour-stand-ticking.patch diff --git a/patches/api/0130-SkeletonHorse-Additions.patch b/patches/api/0127-SkeletonHorse-Additions.patch similarity index 100% rename from patches/api/0130-SkeletonHorse-Additions.patch rename to patches/api/0127-SkeletonHorse-Additions.patch diff --git a/patches/api/0131-Expand-Location-Manipulation-API.patch b/patches/api/0128-Expand-Location-Manipulation-API.patch similarity index 100% rename from patches/api/0131-Expand-Location-Manipulation-API.patch rename to patches/api/0128-Expand-Location-Manipulation-API.patch diff --git a/patches/api/0132-Expand-ArmorStand-API.patch b/patches/api/0129-Expand-ArmorStand-API.patch similarity index 100% rename from patches/api/0132-Expand-ArmorStand-API.patch rename to patches/api/0129-Expand-ArmorStand-API.patch diff --git a/patches/api/0133-AnvilDamageEvent.patch b/patches/api/0130-AnvilDamageEvent.patch similarity index 100% rename from patches/api/0133-AnvilDamageEvent.patch rename to patches/api/0130-AnvilDamageEvent.patch diff --git a/patches/api/0135-Add-TNTPrimeEvent.patch b/patches/api/0131-Add-TNTPrimeEvent.patch similarity index 100% rename from patches/api/0135-Add-TNTPrimeEvent.patch rename to patches/api/0131-Add-TNTPrimeEvent.patch diff --git a/patches/api/0136-Provide-Chunk-Coordinates-as-a-Long-API.patch b/patches/api/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch similarity index 100% rename from patches/api/0136-Provide-Chunk-Coordinates-as-a-Long-API.patch rename to patches/api/0132-Provide-Chunk-Coordinates-as-a-Long-API.patch diff --git a/patches/api/0137-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch b/patches/api/0133-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch similarity index 100% rename from patches/api/0137-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch rename to patches/api/0133-Ability-to-get-Tile-Entities-from-a-chunk-without-sn.patch diff --git a/patches/api/0138-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch b/patches/api/0134-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch similarity index 100% rename from patches/api/0138-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch rename to patches/api/0134-Don-t-use-snapshots-for-Timings-Tile-Entity-reports.patch diff --git a/patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch b/patches/api/0135-Allow-Blocks-to-be-accessed-via-a-long-key.patch similarity index 100% rename from patches/api/0139-Allow-Blocks-to-be-accessed-via-a-long-key.patch rename to patches/api/0135-Allow-Blocks-to-be-accessed-via-a-long-key.patch diff --git a/patches/api/0140-Slime-Pathfinder-Events.patch b/patches/api/0136-Slime-Pathfinder-Events.patch similarity index 100% rename from patches/api/0140-Slime-Pathfinder-Events.patch rename to patches/api/0136-Slime-Pathfinder-Events.patch diff --git a/patches/api/0141-Add-PhantomPreSpawnEvent.patch b/patches/api/0137-Add-PhantomPreSpawnEvent.patch similarity index 100% rename from patches/api/0141-Add-PhantomPreSpawnEvent.patch rename to patches/api/0137-Add-PhantomPreSpawnEvent.patch diff --git a/patches/api/0142-Add-More-Creeper-API.patch b/patches/api/0138-Add-More-Creeper-API.patch similarity index 100% rename from patches/api/0142-Add-More-Creeper-API.patch rename to patches/api/0138-Add-More-Creeper-API.patch diff --git a/patches/api/0143-Inventory-removeItemAnySlot.patch b/patches/api/0139-Inventory-removeItemAnySlot.patch similarity index 100% rename from patches/api/0143-Inventory-removeItemAnySlot.patch rename to patches/api/0139-Inventory-removeItemAnySlot.patch diff --git a/patches/api/0144-isChunkGenerated-API.patch b/patches/api/0140-isChunkGenerated-API.patch similarity index 96% rename from patches/api/0144-isChunkGenerated-API.patch rename to patches/api/0140-isChunkGenerated-API.patch index 0704b7f0db..510a040e7e 100644 --- a/patches/api/0144-isChunkGenerated-API.patch +++ b/patches/api/0140-isChunkGenerated-API.patch @@ -34,7 +34,7 @@ index 16a604b6315daff228c827fe02b1234cca3e884d..20978b269a7757a561d6b872cc77898b /** * Sets the position of this Location and returns itself diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 25e38f0f4fe36193dcc968ef7619bc8c0e705fb2..44b758d70b96a0ba857e1090af91893313945096 100644 +index 00651d5486f1de886df7a4a01aaf272ceb0fa82a..8075ff77eddb971a0a73dad3c9b809131b5db343 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -260,6 +260,17 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient diff --git a/patches/api/0145-Add-source-block-constructor-and-getChangedBlockData.patch b/patches/api/0141-Add-source-block-constructor-and-getChangedBlockData.patch similarity index 100% rename from patches/api/0145-Add-source-block-constructor-and-getChangedBlockData.patch rename to patches/api/0141-Add-source-block-constructor-and-getChangedBlockData.patch diff --git a/patches/api/0146-Async-Chunks-API.patch b/patches/api/0142-Async-Chunks-API.patch similarity index 99% rename from patches/api/0146-Async-Chunks-API.patch rename to patches/api/0142-Async-Chunks-API.patch index f42bce4b89..e81a733023 100644 --- a/patches/api/0146-Async-Chunks-API.patch +++ b/patches/api/0142-Async-Chunks-API.patch @@ -8,7 +8,7 @@ Adds API's to load or generate chunks asynchronously. Also adds utility methods to Entity to teleport asynchronously. diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 44b758d70b96a0ba857e1090af91893313945096..d7f0117a8776a5bd0c6ec6c05d2c56c3b8e08de8 100644 +index 8075ff77eddb971a0a73dad3c9b809131b5db343..12c1731cd3e7138b30a509bf1c6de937b70cf27d 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -969,6 +969,482 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient diff --git a/patches/api/0147-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/api/0143-Add-ray-tracing-methods-to-LivingEntity.patch similarity index 98% rename from patches/api/0147-Add-ray-tracing-methods-to-LivingEntity.patch rename to patches/api/0143-Add-ray-tracing-methods-to-LivingEntity.patch index e1aaccea32..b2299ab712 100644 --- a/patches/api/0147-Add-ray-tracing-methods-to-LivingEntity.patch +++ b/patches/api/0143-Add-ray-tracing-methods-to-LivingEntity.patch @@ -78,7 +78,7 @@ index 0000000000000000000000000000000000000000..c896d172519a8552a132031cb956378d + } +} diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index c80e75b72ac863db19e3d234e349876dd8797924..c29846df0469535870e1743eee25325a4f092a6d 100644 +index 17e5d2e2acdae23d8ea3b3b1a89f62e8be7b81a8..8cccec99cdb028e86b71b3984f4f94201fd9a390 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -83,6 +83,98 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0148-Expose-attack-cooldown-methods-for-Player.patch b/patches/api/0144-Expose-attack-cooldown-methods-for-Player.patch similarity index 100% rename from patches/api/0148-Expose-attack-cooldown-methods-for-Player.patch rename to patches/api/0144-Expose-attack-cooldown-methods-for-Player.patch diff --git a/patches/api/0149-Improve-death-events.patch b/patches/api/0145-Improve-death-events.patch similarity index 98% rename from patches/api/0149-Improve-death-events.patch rename to patches/api/0145-Improve-death-events.patch index 7cad311ede..4c756a68c6 100644 --- a/patches/api/0149-Improve-death-events.patch +++ b/patches/api/0145-Improve-death-events.patch @@ -180,7 +180,7 @@ index a5984ab06cce95d30e70511e125f69339b574c04..e19a3df9aa2204b44c0b029bda141ae6 + // Paper end } diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java -index 7941c60b0e1840785ba2b250071591bd75bc6e35..a871eddf73f918c0e3d2554ef8d9cfd0f830fcaa 100644 +index 1f1df82c9bcf18bad1187e3f24ede1901d91c06f..3b43954b428f2e5e9a718bf6d34116f25c90269f 100644 --- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java @@ -63,6 +63,17 @@ public class PlayerDeathEvent extends EntityDeathEvent { diff --git a/patches/api/0150-Add-Git-information-to-version-command-on-startup.patch b/patches/api/0146-Add-Git-information-to-version-command-on-startup.patch similarity index 100% rename from patches/api/0150-Add-Git-information-to-version-command-on-startup.patch rename to patches/api/0146-Add-Git-information-to-version-command-on-startup.patch diff --git a/patches/api/0151-Mob-Pathfinding-API.patch b/patches/api/0147-Mob-Pathfinding-API.patch similarity index 100% rename from patches/api/0151-Mob-Pathfinding-API.patch rename to patches/api/0147-Mob-Pathfinding-API.patch diff --git a/patches/api/0152-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/patches/api/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch similarity index 100% rename from patches/api/0152-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch rename to patches/api/0148-Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch diff --git a/patches/api/0153-Performance-Concurrency-Improvements-to-Permissions.patch b/patches/api/0149-Performance-Concurrency-Improvements-to-Permissions.patch similarity index 100% rename from patches/api/0153-Performance-Concurrency-Improvements-to-Permissions.patch rename to patches/api/0149-Performance-Concurrency-Improvements-to-Permissions.patch diff --git a/patches/api/0154-Add-ItemStackRecipeChoice-Draft-API.patch b/patches/api/0150-Add-ItemStackRecipeChoice-Draft-API.patch similarity index 100% rename from patches/api/0154-Add-ItemStackRecipeChoice-Draft-API.patch rename to patches/api/0150-Add-ItemStackRecipeChoice-Draft-API.patch diff --git a/patches/api/0155-Implement-furnace-cook-speed-multiplier-API.patch b/patches/api/0151-Implement-furnace-cook-speed-multiplier-API.patch similarity index 100% rename from patches/api/0155-Implement-furnace-cook-speed-multiplier-API.patch rename to patches/api/0151-Implement-furnace-cook-speed-multiplier-API.patch diff --git a/patches/api/0156-Material-API-additions.patch b/patches/api/0152-Material-API-additions.patch similarity index 100% rename from patches/api/0156-Material-API-additions.patch rename to patches/api/0152-Material-API-additions.patch diff --git a/patches/api/0157-Add-Material-Tags.patch b/patches/api/0153-Add-Material-Tags.patch similarity index 100% rename from patches/api/0157-Add-Material-Tags.patch rename to patches/api/0153-Add-Material-Tags.patch diff --git a/patches/api/0158-PreSpawnerSpawnEvent.patch b/patches/api/0154-PreSpawnerSpawnEvent.patch similarity index 100% rename from patches/api/0158-PreSpawnerSpawnEvent.patch rename to patches/api/0154-PreSpawnerSpawnEvent.patch diff --git a/patches/api/0159-Add-LivingEntity-getTargetEntity.patch b/patches/api/0155-Add-LivingEntity-getTargetEntity.patch similarity index 98% rename from patches/api/0159-Add-LivingEntity-getTargetEntity.patch rename to patches/api/0155-Add-LivingEntity-getTargetEntity.patch index 9d07ef98d1..323e4aa5ca 100644 --- a/patches/api/0159-Add-LivingEntity-getTargetEntity.patch +++ b/patches/api/0155-Add-LivingEntity-getTargetEntity.patch @@ -51,7 +51,7 @@ index 0000000000000000000000000000000000000000..af8765b213390cf75fe02a6eb68aecf7 + } +} diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 70c0512a5875533c9b8ce7a1b21cc799772c5ef4..98484c748db12dbdcdbe456befa30ad87864420b 100644 +index 8cccec99cdb028e86b71b3984f4f94201fd9a390..94fad96f8fd57314c571b6396f44cd9d91254cfc 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -173,6 +173,77 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0160-Add-sun-related-API.patch b/patches/api/0156-Add-sun-related-API.patch similarity index 94% rename from patches/api/0160-Add-sun-related-API.patch rename to patches/api/0156-Add-sun-related-API.patch index 714a4b24ea..0efa61418f 100644 --- a/patches/api/0160-Add-sun-related-API.patch +++ b/patches/api/0156-Add-sun-related-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add sun related API diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index d7f0117a8776a5bd0c6ec6c05d2c56c3b8e08de8..24a14005cb9c2fe7e97ba0fbd948c0c1110c52ce 100644 +index 12c1731cd3e7138b30a509bf1c6de937b70cf27d..0ece998826c8e5d5a02a4a348172274b82bb2086 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -1796,6 +1796,16 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient diff --git a/patches/api/0161-Turtle-API.patch b/patches/api/0157-Turtle-API.patch similarity index 100% rename from patches/api/0161-Turtle-API.patch rename to patches/api/0157-Turtle-API.patch diff --git a/patches/api/0162-Add-spectator-target-events.patch b/patches/api/0158-Add-spectator-target-events.patch similarity index 100% rename from patches/api/0162-Add-spectator-target-events.patch rename to patches/api/0158-Add-spectator-target-events.patch diff --git a/patches/api/0163-Add-more-Witch-API.patch b/patches/api/0159-Add-more-Witch-API.patch similarity index 100% rename from patches/api/0163-Add-more-Witch-API.patch rename to patches/api/0159-Add-more-Witch-API.patch diff --git a/patches/api/0164-Make-the-default-permission-message-configurable.patch b/patches/api/0160-Make-the-default-permission-message-configurable.patch similarity index 100% rename from patches/api/0164-Make-the-default-permission-message-configurable.patch rename to patches/api/0160-Make-the-default-permission-message-configurable.patch diff --git a/patches/api/0165-Support-cancellation-supression-of-EntityDismount-Ve.patch b/patches/api/0161-Support-cancellation-supression-of-EntityDismount-Ve.patch similarity index 100% rename from patches/api/0165-Support-cancellation-supression-of-EntityDismount-Ve.patch rename to patches/api/0161-Support-cancellation-supression-of-EntityDismount-Ve.patch diff --git a/patches/api/0166-Add-more-Zombie-API.patch b/patches/api/0162-Add-more-Zombie-API.patch similarity index 100% rename from patches/api/0166-Add-more-Zombie-API.patch rename to patches/api/0162-Add-more-Zombie-API.patch diff --git a/patches/api/0167-Change-the-reserved-channel-check-to-be-sensible.patch b/patches/api/0163-Change-the-reserved-channel-check-to-be-sensible.patch similarity index 100% rename from patches/api/0167-Change-the-reserved-channel-check-to-be-sensible.patch rename to patches/api/0163-Change-the-reserved-channel-check-to-be-sensible.patch diff --git a/patches/api/0168-Add-PlayerConnectionCloseEvent.patch b/patches/api/0164-Add-PlayerConnectionCloseEvent.patch similarity index 100% rename from patches/api/0168-Add-PlayerConnectionCloseEvent.patch rename to patches/api/0164-Add-PlayerConnectionCloseEvent.patch diff --git a/patches/api/0169-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch b/patches/api/0165-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch similarity index 96% rename from patches/api/0169-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch rename to patches/api/0165-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch index ad97b59cd4..79029fc972 100644 --- a/patches/api/0169-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch +++ b/patches/api/0165-Add-APIs-to-replace-OfflinePlayer-getLastPlayed.patch @@ -16,7 +16,7 @@ intent to remove) and replace it with two new methods, clearly named and documented as to their purpose. diff --git a/src/main/java/org/bukkit/OfflinePlayer.java b/src/main/java/org/bukkit/OfflinePlayer.java -index 93f86bb30725dff5dbfcccf15012ffd1cee237bf..a7d1f1e701f23e851f735584a30bedadb0d8b9bd 100644 +index b39ed4eb2e7d9e40805e201d77973877481db8fd..69b50eee42e8c52063033705bd23a5ef5231ed83 100644 --- a/src/main/java/org/bukkit/OfflinePlayer.java +++ b/src/main/java/org/bukkit/OfflinePlayer.java @@ -160,7 +160,9 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio diff --git a/patches/api/0170-Add-ItemStack-Recipe-API-helper-methods.patch b/patches/api/0166-Add-ItemStack-Recipe-API-helper-methods.patch similarity index 100% rename from patches/api/0170-Add-ItemStack-Recipe-API-helper-methods.patch rename to patches/api/0166-Add-ItemStack-Recipe-API-helper-methods.patch diff --git a/patches/api/0171-BlockDestroyEvent.patch b/patches/api/0167-BlockDestroyEvent.patch similarity index 100% rename from patches/api/0171-BlockDestroyEvent.patch rename to patches/api/0167-BlockDestroyEvent.patch diff --git a/patches/api/0172-Add-WhitelistToggleEvent.patch b/patches/api/0168-Add-WhitelistToggleEvent.patch similarity index 100% rename from patches/api/0172-Add-WhitelistToggleEvent.patch rename to patches/api/0168-Add-WhitelistToggleEvent.patch diff --git a/patches/api/0173-Add-GS4-Query-event.patch b/patches/api/0169-Add-GS4-Query-event.patch similarity index 100% rename from patches/api/0173-Add-GS4-Query-event.patch rename to patches/api/0169-Add-GS4-Query-event.patch diff --git a/patches/api/0174-Add-PlayerPostRespawnEvent.patch b/patches/api/0170-Add-PlayerPostRespawnEvent.patch similarity index 100% rename from patches/api/0174-Add-PlayerPostRespawnEvent.patch rename to patches/api/0170-Add-PlayerPostRespawnEvent.patch diff --git a/patches/api/0175-Entity-getEntitySpawnReason.patch b/patches/api/0171-Entity-getEntitySpawnReason.patch similarity index 100% rename from patches/api/0175-Entity-getEntitySpawnReason.patch rename to patches/api/0171-Entity-getEntitySpawnReason.patch diff --git a/patches/api/0176-Fix-Spigot-annotation-mistakes.patch b/patches/api/0172-Fix-Spigot-annotation-mistakes.patch similarity index 100% rename from patches/api/0176-Fix-Spigot-annotation-mistakes.patch rename to patches/api/0172-Fix-Spigot-annotation-mistakes.patch diff --git a/patches/api/0177-Server-Tick-Events.patch b/patches/api/0173-Server-Tick-Events.patch similarity index 100% rename from patches/api/0177-Server-Tick-Events.patch rename to patches/api/0173-Server-Tick-Events.patch diff --git a/patches/api/0178-PlayerDeathEvent-getItemsToKeep.patch b/patches/api/0174-PlayerDeathEvent-getItemsToKeep.patch similarity index 100% rename from patches/api/0178-PlayerDeathEvent-getItemsToKeep.patch rename to patches/api/0174-PlayerDeathEvent-getItemsToKeep.patch diff --git a/patches/api/0179-Add-Heightmap-API.patch b/patches/api/0175-Add-Heightmap-API.patch similarity index 99% rename from patches/api/0179-Add-Heightmap-API.patch rename to patches/api/0175-Add-Heightmap-API.patch index ff70e17363..4c029e4fc2 100644 --- a/patches/api/0179-Add-Heightmap-API.patch +++ b/patches/api/0175-Add-Heightmap-API.patch @@ -103,7 +103,7 @@ index 2b9a117804a8ca54b47e51e23359bd6e01087641..6bbf8468bc47e82b0aeb164e49cdb73d * Creates explosion at this location with given power * diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 891b25c84f6cc86ac3ccf61eca1d4398f31ba6b5..79b1015c56aab88ee8bf70cef0a2ab05c910d991 100644 +index f57e59dd5db687fb4feb13e8283e4ff327c3e8c4..30d5ed45df901a4931a35cc62aec08818307ec99 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -167,6 +167,87 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient diff --git a/patches/api/0180-Mob-Spawner-API-Enhancements.patch b/patches/api/0176-Mob-Spawner-API-Enhancements.patch similarity index 100% rename from patches/api/0180-Mob-Spawner-API-Enhancements.patch rename to patches/api/0176-Mob-Spawner-API-Enhancements.patch diff --git a/patches/api/0181-Add-BlockSoundGroup-interface.patch b/patches/api/0177-Add-BlockSoundGroup-interface.patch similarity index 100% rename from patches/api/0181-Add-BlockSoundGroup-interface.patch rename to patches/api/0177-Add-BlockSoundGroup-interface.patch diff --git a/patches/api/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch b/patches/api/0178-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch similarity index 100% rename from patches/api/0182-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch rename to patches/api/0178-Amend-PlayerInteractAtEntityEvent-javadoc-for-ArmorS.patch diff --git a/patches/api/0183-Increase-custom-payload-channel-message-size.patch b/patches/api/0179-Increase-custom-payload-channel-message-size.patch similarity index 100% rename from patches/api/0183-Increase-custom-payload-channel-message-size.patch rename to patches/api/0179-Increase-custom-payload-channel-message-size.patch diff --git a/patches/api/0184-Expose-the-internal-current-tick.patch b/patches/api/0180-Expose-the-internal-current-tick.patch similarity index 100% rename from patches/api/0184-Expose-the-internal-current-tick.patch rename to patches/api/0180-Expose-the-internal-current-tick.patch diff --git a/patches/api/0185-Improve-Block-breakNaturally-API.patch b/patches/api/0181-Improve-Block-breakNaturally-API.patch similarity index 100% rename from patches/api/0185-Improve-Block-breakNaturally-API.patch rename to patches/api/0181-Improve-Block-breakNaturally-API.patch diff --git a/patches/api/0186-PlayerDeathEvent-shouldDropExperience.patch b/patches/api/0182-PlayerDeathEvent-shouldDropExperience.patch similarity index 100% rename from patches/api/0186-PlayerDeathEvent-shouldDropExperience.patch rename to patches/api/0182-PlayerDeathEvent-shouldDropExperience.patch diff --git a/patches/api/0187-Add-ThrownEggHatchEvent.patch b/patches/api/0183-Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/api/0187-Add-ThrownEggHatchEvent.patch rename to patches/api/0183-Add-ThrownEggHatchEvent.patch diff --git a/patches/api/0188-Entity-Jump-API.patch b/patches/api/0184-Entity-Jump-API.patch similarity index 96% rename from patches/api/0188-Entity-Jump-API.patch rename to patches/api/0184-Entity-Jump-API.patch index bdc4a33969..56fdb9b0f4 100644 --- a/patches/api/0188-Entity-Jump-API.patch +++ b/patches/api/0184-Entity-Jump-API.patch @@ -57,7 +57,7 @@ index 0000000000000000000000000000000000000000..f0067c2e953d18e1a33536980071ba3f + } +} diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index affe38b8c04f71ff6ef60dced1a5e829324429af..eacb21bea254a104cc0ef2288e2f9886dc09d888 100644 +index 94fad96f8fd57314c571b6396f44cd9d91254cfc..f76090f1f7ae7e3c026896b82e6379e5c2fd26fe 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -945,5 +945,25 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0189-add-hand-to-BlockMultiPlaceEvent.patch b/patches/api/0185-add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/api/0189-add-hand-to-BlockMultiPlaceEvent.patch rename to patches/api/0185-add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/api/0190-Add-tick-times-API.patch b/patches/api/0186-Add-tick-times-API.patch similarity index 100% rename from patches/api/0190-Add-tick-times-API.patch rename to patches/api/0186-Add-tick-times-API.patch diff --git a/patches/api/0191-Expose-MinecraftServer-isRunning.patch b/patches/api/0187-Expose-MinecraftServer-isRunning.patch similarity index 100% rename from patches/api/0191-Expose-MinecraftServer-isRunning.patch rename to patches/api/0187-Expose-MinecraftServer-isRunning.patch diff --git a/patches/api/0192-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/api/0188-Add-Raw-Byte-ItemStack-Serialization.patch similarity index 88% rename from patches/api/0192-Add-Raw-Byte-ItemStack-Serialization.patch rename to patches/api/0188-Add-Raw-Byte-ItemStack-Serialization.patch index d2e64b3c1a..a97f91708d 100644 --- a/patches/api/0192-Add-Raw-Byte-ItemStack-Serialization.patch +++ b/patches/api/0188-Add-Raw-Byte-ItemStack-Serialization.patch @@ -6,12 +6,12 @@ Subject: [PATCH] Add Raw Byte ItemStack Serialization Serializes using NBT which is safer for server data migrations than bukkits format. diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 4af059f9b32d2a0913e6d88c6a93e101018e88a2..bdc68e164a8d25a068bc51c04ba17b65a558ba78 100644 +index 24fad8e59a3a5a174d24505cedda2a3fd52115b1..ee9ed5f0e2936c740903784b01b9e2fff75b92f8 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -117,5 +117,9 @@ public interface UnsafeValues { - static boolean isLegacyPlugin(org.bukkit.plugin.Plugin plugin) { - return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); +@@ -121,5 +121,9 @@ public interface UnsafeValues { + default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { + return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); } + + byte[] serializeItem(ItemStack item); diff --git a/patches/api/0195-Add-Player-Client-Options-API.patch b/patches/api/0189-Add-Player-Client-Options-API.patch similarity index 100% rename from patches/api/0195-Add-Player-Client-Options-API.patch rename to patches/api/0189-Add-Player-Client-Options-API.patch diff --git a/patches/api/0196-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/api/0190-Add-PlayerAttackEntityCooldownResetEvent.patch similarity index 100% rename from patches/api/0196-Add-PlayerAttackEntityCooldownResetEvent.patch rename to patches/api/0190-Add-PlayerAttackEntityCooldownResetEvent.patch diff --git a/patches/api/0197-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch b/patches/api/0191-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch similarity index 100% rename from patches/api/0197-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch rename to patches/api/0191-Fix-Potion-toItemStack-swapping-the-extended-and-upg.patch diff --git a/patches/api/0198-Add-item-slot-convenience-methods.patch b/patches/api/0192-Add-item-slot-convenience-methods.patch similarity index 100% rename from patches/api/0198-Add-item-slot-convenience-methods.patch rename to patches/api/0192-Add-item-slot-convenience-methods.patch diff --git a/patches/api/0199-Villager-Restocks-API.patch b/patches/api/0193-Villager-Restocks-API.patch similarity index 100% rename from patches/api/0199-Villager-Restocks-API.patch rename to patches/api/0193-Villager-Restocks-API.patch diff --git a/patches/api/0200-Expose-game-version.patch b/patches/api/0194-Expose-game-version.patch similarity index 100% rename from patches/api/0200-Expose-game-version.patch rename to patches/api/0194-Expose-game-version.patch diff --git a/patches/api/0201-Add-Mob-Goal-API.patch b/patches/api/0195-Add-Mob-Goal-API.patch similarity index 100% rename from patches/api/0201-Add-Mob-Goal-API.patch rename to patches/api/0195-Add-Mob-Goal-API.patch diff --git a/patches/api/0202-Add-villager-reputation-API.patch b/patches/api/0196-Add-villager-reputation-API.patch similarity index 100% rename from patches/api/0202-Add-villager-reputation-API.patch rename to patches/api/0196-Add-villager-reputation-API.patch diff --git a/patches/api/0203-Spawn-Reason-API.patch b/patches/api/0197-Spawn-Reason-API.patch similarity index 100% rename from patches/api/0203-Spawn-Reason-API.patch rename to patches/api/0197-Spawn-Reason-API.patch diff --git a/patches/api/0204-Potential-bed-API.patch b/patches/api/0198-Potential-bed-API.patch similarity index 100% rename from patches/api/0204-Potential-bed-API.patch rename to patches/api/0198-Potential-bed-API.patch diff --git a/patches/api/0207-Inventory-getHolder-method-without-block-snapshot.patch b/patches/api/0199-Inventory-getHolder-method-without-block-snapshot.patch similarity index 100% rename from patches/api/0207-Inventory-getHolder-method-without-block-snapshot.patch rename to patches/api/0199-Inventory-getHolder-method-without-block-snapshot.patch diff --git a/patches/api/0208-Improve-Arrow-API.patch b/patches/api/0200-Improve-Arrow-API.patch similarity index 100% rename from patches/api/0208-Improve-Arrow-API.patch rename to patches/api/0200-Improve-Arrow-API.patch diff --git a/patches/api/0209-Add-and-implement-PlayerRecipeBookClickEvent.patch b/patches/api/0201-Add-and-implement-PlayerRecipeBookClickEvent.patch similarity index 100% rename from patches/api/0209-Add-and-implement-PlayerRecipeBookClickEvent.patch rename to patches/api/0201-Add-and-implement-PlayerRecipeBookClickEvent.patch diff --git a/patches/api/0210-Support-components-in-ItemMeta.patch b/patches/api/0202-Support-components-in-ItemMeta.patch similarity index 100% rename from patches/api/0210-Support-components-in-ItemMeta.patch rename to patches/api/0202-Support-components-in-ItemMeta.patch diff --git a/patches/api/0211-added-2-new-TargetReasons-for-1.16-mob-behavior.patch b/patches/api/0203-added-2-new-TargetReasons-for-1.16-mob-behavior.patch similarity index 100% rename from patches/api/0211-added-2-new-TargetReasons-for-1.16-mob-behavior.patch rename to patches/api/0203-added-2-new-TargetReasons-for-1.16-mob-behavior.patch diff --git a/patches/api/0212-Add-entity-liquid-API.patch b/patches/api/0204-Add-entity-liquid-API.patch similarity index 100% rename from patches/api/0212-Add-entity-liquid-API.patch rename to patches/api/0204-Add-entity-liquid-API.patch diff --git a/patches/api/0213-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch b/patches/api/0205-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch similarity index 100% rename from patches/api/0213-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch rename to patches/api/0205-Add-PrepareResultEvent-PrepareGrindstoneEvent.patch diff --git a/patches/api/0214-Brand-support.patch b/patches/api/0206-Brand-support.patch similarity index 100% rename from patches/api/0214-Brand-support.patch rename to patches/api/0206-Brand-support.patch diff --git a/patches/api/0215-Support-hex-colors-in-getLastColors.patch b/patches/api/0207-Support-hex-colors-in-getLastColors.patch similarity index 100% rename from patches/api/0215-Support-hex-colors-in-getLastColors.patch rename to patches/api/0207-Support-hex-colors-in-getLastColors.patch diff --git a/patches/api/0216-Add-setMaxPlayers-API.patch b/patches/api/0208-Add-setMaxPlayers-API.patch similarity index 100% rename from patches/api/0216-Add-setMaxPlayers-API.patch rename to patches/api/0208-Add-setMaxPlayers-API.patch diff --git a/patches/api/0217-Add-BellRingEvent.patch b/patches/api/0209-Add-BellRingEvent.patch similarity index 100% rename from patches/api/0217-Add-BellRingEvent.patch rename to patches/api/0209-Add-BellRingEvent.patch diff --git a/patches/api/0218-Add-moon-phase-API.patch b/patches/api/0210-Add-moon-phase-API.patch similarity index 100% rename from patches/api/0218-Add-moon-phase-API.patch rename to patches/api/0210-Add-moon-phase-API.patch diff --git a/patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch b/patches/api/0211-Add-playPickupItemAnimation-to-LivingEntity.patch similarity index 93% rename from patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch rename to patches/api/0211-Add-playPickupItemAnimation-to-LivingEntity.patch index 1f64398a6b..92490d42d5 100644 --- a/patches/api/0219-Add-playPickupItemAnimation-to-LivingEntity.patch +++ b/patches/api/0211-Add-playPickupItemAnimation-to-LivingEntity.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add playPickupItemAnimation to LivingEntity diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index eacb21bea254a104cc0ef2288e2f9886dc09d888..1e510a40f48fdf1337cdd0cc8ec8bc378dab94da 100644 +index f76090f1f7ae7e3c026896b82e6379e5c2fd26fe..76fdfa7b00cb905163567a204a727cf047d9261a 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -965,5 +965,28 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0220-Add-more-Evoker-API.patch b/patches/api/0212-Add-more-Evoker-API.patch similarity index 100% rename from patches/api/0220-Add-more-Evoker-API.patch rename to patches/api/0212-Add-more-Evoker-API.patch diff --git a/patches/api/0221-Add-methods-to-get-translation-keys.patch b/patches/api/0213-Add-methods-to-get-translation-keys.patch similarity index 100% rename from patches/api/0221-Add-methods-to-get-translation-keys.patch rename to patches/api/0213-Add-methods-to-get-translation-keys.patch diff --git a/patches/api/0222-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/api/0214-Create-HoverEvent-from-ItemStack-Entity.patch similarity index 100% rename from patches/api/0222-Create-HoverEvent-from-ItemStack-Entity.patch rename to patches/api/0214-Create-HoverEvent-from-ItemStack-Entity.patch diff --git a/patches/api/0223-Add-additional-open-container-api-to-HumanEntity.patch b/patches/api/0215-Add-additional-open-container-api-to-HumanEntity.patch similarity index 100% rename from patches/api/0223-Add-additional-open-container-api-to-HumanEntity.patch rename to patches/api/0215-Add-additional-open-container-api-to-HumanEntity.patch diff --git a/patches/api/0224-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/api/0216-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch similarity index 84% rename from patches/api/0224-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch rename to patches/api/0216-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch index 7653717c83..cc17c319f5 100644 --- a/patches/api/0224-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ b/patches/api/0216-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index bdc68e164a8d25a068bc51c04ba17b65a558ba78..7a6c22b9845798580635a938c28adf01908e04a0 100644 +index ee9ed5f0e2936c740903784b01b9e2fff75b92f8..1f89a3c1c3b73a939c2653102fc1dc8b630672a8 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -121,5 +121,12 @@ public interface UnsafeValues { +@@ -125,5 +125,12 @@ public interface UnsafeValues { byte[] serializeItem(ItemStack item); ItemStack deserializeItem(byte[] data); diff --git a/patches/api/0225-Entity-isTicking.patch b/patches/api/0217-Entity-isTicking.patch similarity index 100% rename from patches/api/0225-Entity-isTicking.patch rename to patches/api/0217-Entity-isTicking.patch diff --git a/patches/api/0226-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch b/patches/api/0218-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch similarity index 100% rename from patches/api/0226-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch rename to patches/api/0218-Clarify-the-Javadocs-for-Entity.getEntitySpawnReason.patch diff --git a/patches/api/0227-Villager-resetOffers.patch b/patches/api/0219-Villager-resetOffers.patch similarity index 100% rename from patches/api/0227-Villager-resetOffers.patch rename to patches/api/0219-Villager-resetOffers.patch diff --git a/patches/api/0228-Player-elytra-boost-API.patch b/patches/api/0220-Player-elytra-boost-API.patch similarity index 100% rename from patches/api/0228-Player-elytra-boost-API.patch rename to patches/api/0220-Player-elytra-boost-API.patch diff --git a/patches/api/0229-Add-getOfflinePlayerIfCached-String.patch b/patches/api/0221-Add-getOfflinePlayerIfCached-String.patch similarity index 100% rename from patches/api/0229-Add-getOfflinePlayerIfCached-String.patch rename to patches/api/0221-Add-getOfflinePlayerIfCached-String.patch diff --git a/patches/api/0230-Add-ignore-discounts-API.patch b/patches/api/0222-Add-ignore-discounts-API.patch similarity index 100% rename from patches/api/0230-Add-ignore-discounts-API.patch rename to patches/api/0222-Add-ignore-discounts-API.patch diff --git a/patches/api/0231-Item-no-age-no-player-pickup.patch b/patches/api/0223-Item-no-age-no-player-pickup.patch similarity index 100% rename from patches/api/0231-Item-no-age-no-player-pickup.patch rename to patches/api/0223-Item-no-age-no-player-pickup.patch diff --git a/patches/api/0232-Beacon-API-custom-effect-ranges.patch b/patches/api/0224-Beacon-API-custom-effect-ranges.patch similarity index 100% rename from patches/api/0232-Beacon-API-custom-effect-ranges.patch rename to patches/api/0224-Beacon-API-custom-effect-ranges.patch diff --git a/patches/api/0233-Add-API-for-quit-reason.patch b/patches/api/0225-Add-API-for-quit-reason.patch similarity index 100% rename from patches/api/0233-Add-API-for-quit-reason.patch rename to patches/api/0225-Add-API-for-quit-reason.patch diff --git a/patches/api/0234-Add-Destroy-Speed-API.patch b/patches/api/0226-Add-Destroy-Speed-API.patch similarity index 100% rename from patches/api/0234-Add-Destroy-Speed-API.patch rename to patches/api/0226-Add-Destroy-Speed-API.patch diff --git a/patches/api/0235-Add-LivingEntity-clearActiveItem.patch b/patches/api/0227-Add-LivingEntity-clearActiveItem.patch similarity index 90% rename from patches/api/0235-Add-LivingEntity-clearActiveItem.patch rename to patches/api/0227-Add-LivingEntity-clearActiveItem.patch index 0faf1aa181..cb7332dea2 100644 --- a/patches/api/0235-Add-LivingEntity-clearActiveItem.patch +++ b/patches/api/0227-Add-LivingEntity-clearActiveItem.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add LivingEntity#clearActiveItem diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 1e510a40f48fdf1337cdd0cc8ec8bc378dab94da..194159adbab5e6ee86a07a9a67a3ca40e103f535 100644 +index 76fdfa7b00cb905163567a204a727cf047d9261a..b09c9eb92c069f76e0fba4a08ed0a5c66ced3a40 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -916,6 +916,13 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0236-Add-PlayerItemCooldownEvent.patch b/patches/api/0228-Add-PlayerItemCooldownEvent.patch similarity index 100% rename from patches/api/0236-Add-PlayerItemCooldownEvent.patch rename to patches/api/0228-Add-PlayerItemCooldownEvent.patch diff --git a/patches/api/0237-More-lightning-API.patch b/patches/api/0229-More-lightning-API.patch similarity index 100% rename from patches/api/0237-More-lightning-API.patch rename to patches/api/0229-More-lightning-API.patch diff --git a/patches/api/0238-Add-PlayerShearBlockEvent.patch b/patches/api/0230-Add-PlayerShearBlockEvent.patch similarity index 100% rename from patches/api/0238-Add-PlayerShearBlockEvent.patch rename to patches/api/0230-Add-PlayerShearBlockEvent.patch diff --git a/patches/api/0239-Enable-multi-release-plugin-jars.patch b/patches/api/0231-Enable-multi-release-plugin-jars.patch similarity index 82% rename from patches/api/0239-Enable-multi-release-plugin-jars.patch rename to patches/api/0231-Enable-multi-release-plugin-jars.patch index 40eb489f1d..cedc39b349 100644 --- a/patches/api/0239-Enable-multi-release-plugin-jars.patch +++ b/patches/api/0231-Enable-multi-release-plugin-jars.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Enable multi-release plugin jars diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index fc5dc3b2f73e76976748eb013b39cae931072143..e39492e2544c39c5457f079a6baadf0b4074dd7e 100644 +index a657654079c40a0fee6f70c7d72df24b3827b911..ef60a8a7e20e27fee6f96fe1398ec9aee9352aec 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -58,7 +58,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot +@@ -61,7 +61,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm this.description = description; this.dataFolder = dataFolder; this.file = file; diff --git a/patches/api/0240-Player-Chunk-Load-Unload-Events.patch b/patches/api/0232-Player-Chunk-Load-Unload-Events.patch similarity index 100% rename from patches/api/0240-Player-Chunk-Load-Unload-Events.patch rename to patches/api/0232-Player-Chunk-Load-Unload-Events.patch diff --git a/patches/api/0241-Expose-LivingEntity-hurt-direction.patch b/patches/api/0233-Expose-LivingEntity-hurt-direction.patch similarity index 90% rename from patches/api/0241-Expose-LivingEntity-hurt-direction.patch rename to patches/api/0233-Expose-LivingEntity-hurt-direction.patch index e1cf74262c..92baefbb10 100644 --- a/patches/api/0241-Expose-LivingEntity-hurt-direction.patch +++ b/patches/api/0233-Expose-LivingEntity-hurt-direction.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Expose LivingEntity hurt direction diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 194159adbab5e6ee86a07a9a67a3ca40e103f535..53a8d79788f2d9d4b46e6aece1d76863dd5fb727 100644 +index b09c9eb92c069f76e0fba4a08ed0a5c66ced3a40..cc61e030f1bdb4d1ef52a0a1ae4983f95d2460fd 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -995,5 +995,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0242-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/api/0234-Add-OBSTRUCTED-reason-to-BedEnterResult.patch similarity index 100% rename from patches/api/0242-Add-OBSTRUCTED-reason-to-BedEnterResult.patch rename to patches/api/0234-Add-OBSTRUCTED-reason-to-BedEnterResult.patch diff --git a/patches/api/0243-Added-PlayerTradeEvent.patch b/patches/api/0235-Added-PlayerTradeEvent.patch similarity index 100% rename from patches/api/0243-Added-PlayerTradeEvent.patch rename to patches/api/0235-Added-PlayerTradeEvent.patch diff --git a/patches/api/0244-Add-TargetHitEvent-API.patch b/patches/api/0236-Add-TargetHitEvent-API.patch similarity index 100% rename from patches/api/0244-Add-TargetHitEvent-API.patch rename to patches/api/0236-Add-TargetHitEvent-API.patch diff --git a/patches/api/0245-Additional-Block-Material-API-s.patch b/patches/api/0237-Additional-Block-Material-API-s.patch similarity index 100% rename from patches/api/0245-Additional-Block-Material-API-s.patch rename to patches/api/0237-Additional-Block-Material-API-s.patch diff --git a/patches/api/0246-Add-API-to-get-Material-from-Boats-and-Minecarts.patch b/patches/api/0238-Add-API-to-get-Material-from-Boats-and-Minecarts.patch similarity index 100% rename from patches/api/0246-Add-API-to-get-Material-from-Boats-and-Minecarts.patch rename to patches/api/0238-Add-API-to-get-Material-from-Boats-and-Minecarts.patch diff --git a/patches/api/0247-Add-PlayerFlowerPotManipulateEvent.patch b/patches/api/0239-Add-PlayerFlowerPotManipulateEvent.patch similarity index 100% rename from patches/api/0247-Add-PlayerFlowerPotManipulateEvent.patch rename to patches/api/0239-Add-PlayerFlowerPotManipulateEvent.patch diff --git a/patches/api/0248-Zombie-API-breaking-doors.patch b/patches/api/0240-Zombie-API-breaking-doors.patch similarity index 100% rename from patches/api/0248-Zombie-API-breaking-doors.patch rename to patches/api/0240-Zombie-API-breaking-doors.patch diff --git a/patches/api/0249-Add-EntityLoadCrossbowEvent.patch b/patches/api/0241-Add-EntityLoadCrossbowEvent.patch similarity index 100% rename from patches/api/0249-Add-EntityLoadCrossbowEvent.patch rename to patches/api/0241-Add-EntityLoadCrossbowEvent.patch diff --git a/patches/api/0250-Added-WorldGameRuleChangeEvent.patch b/patches/api/0242-Added-WorldGameRuleChangeEvent.patch similarity index 100% rename from patches/api/0250-Added-WorldGameRuleChangeEvent.patch rename to patches/api/0242-Added-WorldGameRuleChangeEvent.patch diff --git a/patches/api/0251-Added-ServerResourcesReloadedEvent.patch b/patches/api/0243-Added-ServerResourcesReloadedEvent.patch similarity index 100% rename from patches/api/0251-Added-ServerResourcesReloadedEvent.patch rename to patches/api/0243-Added-ServerResourcesReloadedEvent.patch diff --git a/patches/api/0252-Add-BlockFailedDispenseEvent.patch b/patches/api/0244-Add-BlockFailedDispenseEvent.patch similarity index 100% rename from patches/api/0252-Add-BlockFailedDispenseEvent.patch rename to patches/api/0244-Add-BlockFailedDispenseEvent.patch diff --git a/patches/api/0253-Added-PlayerLecternPageChangeEvent.patch b/patches/api/0245-Added-PlayerLecternPageChangeEvent.patch similarity index 100% rename from patches/api/0253-Added-PlayerLecternPageChangeEvent.patch rename to patches/api/0245-Added-PlayerLecternPageChangeEvent.patch diff --git a/patches/api/0254-Added-PlayerLoomPatternSelectEvent.patch b/patches/api/0246-Added-PlayerLoomPatternSelectEvent.patch similarity index 100% rename from patches/api/0254-Added-PlayerLoomPatternSelectEvent.patch rename to patches/api/0246-Added-PlayerLoomPatternSelectEvent.patch diff --git a/patches/api/0255-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch b/patches/api/0247-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch similarity index 100% rename from patches/api/0255-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch rename to patches/api/0247-Add-API-to-get-exact-interaction-point-in-PlayerInte.patch diff --git a/patches/api/0256-Add-sendOpLevel-API.patch b/patches/api/0248-Add-sendOpLevel-API.patch similarity index 100% rename from patches/api/0256-Add-sendOpLevel-API.patch rename to patches/api/0248-Add-sendOpLevel-API.patch diff --git a/patches/api/0257-Add-PaperRegistry.patch b/patches/api/0249-Add-PaperRegistry.patch similarity index 96% rename from patches/api/0257-Add-PaperRegistry.patch rename to patches/api/0249-Add-PaperRegistry.patch index d4857c45ed..c4c2b84949 100644 --- a/patches/api/0257-Add-PaperRegistry.patch +++ b/patches/api/0249-Add-PaperRegistry.patch @@ -91,10 +91,10 @@ index 0000000000000000000000000000000000000000..f29e76a6b66ddfec12ddf8db6dcb2df6 + } +} diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 7a6c22b9845798580635a938c28adf01908e04a0..1b6fe8fadcf4860cd3411c0433bc775de3a870ad 100644 +index 1f89a3c1c3b73a939c2653102fc1dc8b630672a8..e5e91f4b4492fa1e709d81f313aac80761ab9e07 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -128,5 +128,15 @@ public interface UnsafeValues { +@@ -132,5 +132,15 @@ public interface UnsafeValues { * Use this when sending custom packets, so that there are no collisions on the client or server. */ public int nextEntityId(); diff --git a/patches/api/0258-Add-StructuresLocateEvent.patch b/patches/api/0250-Add-StructuresLocateEvent.patch similarity index 100% rename from patches/api/0258-Add-StructuresLocateEvent.patch rename to patches/api/0250-Add-StructuresLocateEvent.patch diff --git a/patches/api/0259-Return-chat-component-with-empty-text-instead-of-thr.patch b/patches/api/0251-Return-chat-component-with-empty-text-instead-of-thr.patch similarity index 100% rename from patches/api/0259-Return-chat-component-with-empty-text-instead-of-thr.patch rename to patches/api/0251-Return-chat-component-with-empty-text-instead-of-thr.patch diff --git a/patches/api/0260-Add-BlockPreDispenseEvent.patch b/patches/api/0252-Add-BlockPreDispenseEvent.patch similarity index 100% rename from patches/api/0260-Add-BlockPreDispenseEvent.patch rename to patches/api/0252-Add-BlockPreDispenseEvent.patch diff --git a/patches/api/0261-Added-missing-vanilla-tags.patch b/patches/api/0253-Added-missing-vanilla-tags.patch similarity index 100% rename from patches/api/0261-Added-missing-vanilla-tags.patch rename to patches/api/0253-Added-missing-vanilla-tags.patch diff --git a/patches/api/0262-Added-PlayerChangeBeaconEffectEvent.patch b/patches/api/0254-Added-PlayerChangeBeaconEffectEvent.patch similarity index 100% rename from patches/api/0262-Added-PlayerChangeBeaconEffectEvent.patch rename to patches/api/0254-Added-PlayerChangeBeaconEffectEvent.patch diff --git a/patches/api/0263-Added-PlayerStonecutterRecipeSelectEvent.patch b/patches/api/0255-Added-PlayerStonecutterRecipeSelectEvent.patch similarity index 100% rename from patches/api/0263-Added-PlayerStonecutterRecipeSelectEvent.patch rename to patches/api/0255-Added-PlayerStonecutterRecipeSelectEvent.patch diff --git a/patches/api/0264-Add-dropLeash-variable-to-EntityUnleashEvent.patch b/patches/api/0256-Add-dropLeash-variable-to-EntityUnleashEvent.patch similarity index 100% rename from patches/api/0264-Add-dropLeash-variable-to-EntityUnleashEvent.patch rename to patches/api/0256-Add-dropLeash-variable-to-EntityUnleashEvent.patch diff --git a/patches/api/0265-add-DragonEggFormEvent.patch b/patches/api/0257-add-DragonEggFormEvent.patch similarity index 100% rename from patches/api/0265-add-DragonEggFormEvent.patch rename to patches/api/0257-add-DragonEggFormEvent.patch diff --git a/patches/api/0266-EntityMoveEvent.patch b/patches/api/0258-EntityMoveEvent.patch similarity index 100% rename from patches/api/0266-EntityMoveEvent.patch rename to patches/api/0258-EntityMoveEvent.patch diff --git a/patches/api/0267-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/api/0259-Allow-adding-items-to-BlockDropItemEvent.patch similarity index 100% rename from patches/api/0267-Allow-adding-items-to-BlockDropItemEvent.patch rename to patches/api/0259-Allow-adding-items-to-BlockDropItemEvent.patch diff --git a/patches/api/0268-Add-getMainThreadExecutor-to-BukkitScheduler.patch b/patches/api/0260-Add-getMainThreadExecutor-to-BukkitScheduler.patch similarity index 100% rename from patches/api/0268-Add-getMainThreadExecutor-to-BukkitScheduler.patch rename to patches/api/0260-Add-getMainThreadExecutor-to-BukkitScheduler.patch diff --git a/patches/api/0269-living-entity-allow-attribute-registration.patch b/patches/api/0261-living-entity-allow-attribute-registration.patch similarity index 100% rename from patches/api/0269-living-entity-allow-attribute-registration.patch rename to patches/api/0261-living-entity-allow-attribute-registration.patch diff --git a/patches/api/0270-Add-missing-effects.patch b/patches/api/0262-Add-missing-effects.patch similarity index 100% rename from patches/api/0270-Add-missing-effects.patch rename to patches/api/0262-Add-missing-effects.patch diff --git a/patches/api/0271-Expose-Tracked-Players.patch b/patches/api/0263-Expose-Tracked-Players.patch similarity index 100% rename from patches/api/0271-Expose-Tracked-Players.patch rename to patches/api/0263-Expose-Tracked-Players.patch diff --git a/patches/api/0272-Cache-the-result-of-Material-isBlock.patch b/patches/api/0264-Cache-the-result-of-Material-isBlock.patch similarity index 100% rename from patches/api/0272-Cache-the-result-of-Material-isBlock.patch rename to patches/api/0264-Cache-the-result-of-Material-isBlock.patch diff --git a/patches/api/0273-Add-worldborder-events.patch b/patches/api/0265-Add-worldborder-events.patch similarity index 100% rename from patches/api/0273-Add-worldborder-events.patch rename to patches/api/0265-Add-worldborder-events.patch diff --git a/patches/api/0274-added-PlayerNameEntityEvent.patch b/patches/api/0266-added-PlayerNameEntityEvent.patch similarity index 100% rename from patches/api/0274-added-PlayerNameEntityEvent.patch rename to patches/api/0266-added-PlayerNameEntityEvent.patch diff --git a/patches/api/0275-Add-recipe-to-cook-events.patch b/patches/api/0267-Add-recipe-to-cook-events.patch similarity index 100% rename from patches/api/0275-Add-recipe-to-cook-events.patch rename to patches/api/0267-Add-recipe-to-cook-events.patch diff --git a/patches/api/0276-Add-Block-isValidTool.patch b/patches/api/0268-Add-Block-isValidTool.patch similarity index 100% rename from patches/api/0276-Add-Block-isValidTool.patch rename to patches/api/0268-Add-Block-isValidTool.patch diff --git a/patches/api/0277-Expand-world-key-API.patch b/patches/api/0269-Expand-world-key-API.patch similarity index 97% rename from patches/api/0277-Expand-world-key-API.patch rename to patches/api/0269-Expand-world-key-API.patch index ea1cc66c9b..e78eb2a0e5 100644 --- a/patches/api/0277-Expand-world-key-API.patch +++ b/patches/api/0269-Expand-world-key-API.patch @@ -78,10 +78,10 @@ index 02b898d441c42771903d5839c3cde544b1a25778..1a3b4f20c7126caf8a34040028f73508 * Create a new virtual {@link WorldBorder}. *

diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 1b6fe8fadcf4860cd3411c0433bc775de3a870ad..027bbfe33011f26914852750b6f0a7200818dc95 100644 +index e5e91f4b4492fa1e709d81f313aac80761ab9e07..3545313f1c592e29d0bb5d055fc4e5c71c8a6fca 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -138,5 +138,10 @@ public interface UnsafeValues { +@@ -142,5 +142,10 @@ public interface UnsafeValues { * @throws IllegalArgumentException if there isn't a registry for that type */ @org.jetbrains.annotations.NotNull Registry registryFor(Class classOfT); diff --git a/patches/api/0278-Item-Rarity-API.patch b/patches/api/0270-Item-Rarity-API.patch similarity index 96% rename from patches/api/0278-Item-Rarity-API.patch rename to patches/api/0270-Item-Rarity-API.patch index 22b88307e4..2558d2aed0 100644 --- a/patches/api/0278-Item-Rarity-API.patch +++ b/patches/api/0270-Item-Rarity-API.patch @@ -61,10 +61,10 @@ index 7e447f8be7dc9768df487e1f7f4b9aafedb33e2d..eb8aa093148eea3b2fcafe06e8f1277e /** diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 027bbfe33011f26914852750b6f0a7200818dc95..2768aee1ec52037c32a7873a3018e659604175ce 100644 +index 3545313f1c592e29d0bb5d055fc4e5c71c8a6fca..aa6d4e0ea2a1e2b96cc94d5a1d2223caecfea7a4 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -143,5 +143,22 @@ public interface UnsafeValues { +@@ -147,5 +147,22 @@ public interface UnsafeValues { * Just don't use it. */ @org.jetbrains.annotations.NotNull String getMainLevelName(); diff --git a/patches/api/0279-Expose-protocol-version.patch b/patches/api/0271-Expose-protocol-version.patch similarity index 82% rename from patches/api/0279-Expose-protocol-version.patch rename to patches/api/0271-Expose-protocol-version.patch index 36702be6d1..fc59754077 100644 --- a/patches/api/0279-Expose-protocol-version.patch +++ b/patches/api/0271-Expose-protocol-version.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose protocol version diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 2768aee1ec52037c32a7873a3018e659604175ce..c63de60fd3c6b5c2cf3b5b01288d8309d9e6d02b 100644 +index aa6d4e0ea2a1e2b96cc94d5a1d2223caecfea7a4..c876f95989d5bb64e745f8f62b4874422156d49c 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -160,5 +160,12 @@ public interface UnsafeValues { +@@ -164,5 +164,12 @@ public interface UnsafeValues { * @return the itemstack rarity */ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack); diff --git a/patches/api/0280-add-isDeeplySleeping-to-HumanEntity.patch b/patches/api/0272-add-isDeeplySleeping-to-HumanEntity.patch similarity index 100% rename from patches/api/0280-add-isDeeplySleeping-to-HumanEntity.patch rename to patches/api/0272-add-isDeeplySleeping-to-HumanEntity.patch diff --git a/patches/api/0281-add-consumeFuel-to-FurnaceBurnEvent.patch b/patches/api/0273-add-consumeFuel-to-FurnaceBurnEvent.patch similarity index 100% rename from patches/api/0281-add-consumeFuel-to-FurnaceBurnEvent.patch rename to patches/api/0273-add-consumeFuel-to-FurnaceBurnEvent.patch diff --git a/patches/api/0282-add-get-set-drop-chance-to-EntityEquipment.patch b/patches/api/0274-add-get-set-drop-chance-to-EntityEquipment.patch similarity index 100% rename from patches/api/0282-add-get-set-drop-chance-to-EntityEquipment.patch rename to patches/api/0274-add-get-set-drop-chance-to-EntityEquipment.patch diff --git a/patches/api/0283-Added-PlayerDeepSleepEvent.patch b/patches/api/0275-Added-PlayerDeepSleepEvent.patch similarity index 100% rename from patches/api/0283-Added-PlayerDeepSleepEvent.patch rename to patches/api/0275-Added-PlayerDeepSleepEvent.patch diff --git a/patches/api/0284-More-World-API.patch b/patches/api/0276-More-World-API.patch similarity index 100% rename from patches/api/0284-More-World-API.patch rename to patches/api/0276-More-World-API.patch diff --git a/patches/api/0285-Added-PlayerBedFailEnterEvent.patch b/patches/api/0277-Added-PlayerBedFailEnterEvent.patch similarity index 100% rename from patches/api/0285-Added-PlayerBedFailEnterEvent.patch rename to patches/api/0277-Added-PlayerBedFailEnterEvent.patch diff --git a/patches/api/0286-Introduce-beacon-activation-deactivation-events.patch b/patches/api/0278-Introduce-beacon-activation-deactivation-events.patch similarity index 100% rename from patches/api/0286-Introduce-beacon-activation-deactivation-events.patch rename to patches/api/0278-Introduce-beacon-activation-deactivation-events.patch diff --git a/patches/api/0287-PlayerMoveEvent-Improvements.patch b/patches/api/0279-PlayerMoveEvent-Improvements.patch similarity index 100% rename from patches/api/0287-PlayerMoveEvent-Improvements.patch rename to patches/api/0279-PlayerMoveEvent-Improvements.patch diff --git a/patches/api/0288-add-RespawnFlags-to-PlayerRespawnEvent.patch b/patches/api/0280-add-RespawnFlags-to-PlayerRespawnEvent.patch similarity index 100% rename from patches/api/0288-add-RespawnFlags-to-PlayerRespawnEvent.patch rename to patches/api/0280-add-RespawnFlags-to-PlayerRespawnEvent.patch diff --git a/patches/api/0289-Add-more-WanderingTrader-API.patch b/patches/api/0281-Add-more-WanderingTrader-API.patch similarity index 100% rename from patches/api/0289-Add-more-WanderingTrader-API.patch rename to patches/api/0281-Add-more-WanderingTrader-API.patch diff --git a/patches/api/0290-Add-EntityBlockStorage-clearEntities.patch b/patches/api/0282-Add-EntityBlockStorage-clearEntities.patch similarity index 100% rename from patches/api/0290-Add-EntityBlockStorage-clearEntities.patch rename to patches/api/0282-Add-EntityBlockStorage-clearEntities.patch diff --git a/patches/api/0291-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch b/patches/api/0283-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch similarity index 100% rename from patches/api/0291-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch rename to patches/api/0283-Add-Adventure-message-to-PlayerAdvancementDoneEvent.patch diff --git a/patches/api/0292-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch b/patches/api/0284-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/api/0292-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch rename to patches/api/0284-Add-raw-address-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/api/0293-Inventory-close.patch b/patches/api/0285-Inventory-close.patch similarity index 100% rename from patches/api/0293-Inventory-close.patch rename to patches/api/0285-Inventory-close.patch diff --git a/patches/api/0294-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch b/patches/api/0286-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch similarity index 100% rename from patches/api/0294-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch rename to patches/api/0286-Add-a-should-burn-in-sunlight-API-for-Phantoms-and-S.patch diff --git a/patches/api/0295-Add-basic-Datapack-API.patch b/patches/api/0287-Add-basic-Datapack-API.patch similarity index 100% rename from patches/api/0295-Add-basic-Datapack-API.patch rename to patches/api/0287-Add-basic-Datapack-API.patch diff --git a/patches/api/0296-additions-to-PlayerGameModeChangeEvent.patch b/patches/api/0288-additions-to-PlayerGameModeChangeEvent.patch similarity index 100% rename from patches/api/0296-additions-to-PlayerGameModeChangeEvent.patch rename to patches/api/0288-additions-to-PlayerGameModeChangeEvent.patch diff --git a/patches/api/0297-ItemStack-repair-check-API.patch b/patches/api/0289-ItemStack-repair-check-API.patch similarity index 94% rename from patches/api/0297-ItemStack-repair-check-API.patch rename to patches/api/0289-ItemStack-repair-check-API.patch index d9dee9799f..6e16f41651 100644 --- a/patches/api/0297-ItemStack-repair-check-API.patch +++ b/patches/api/0289-ItemStack-repair-check-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] ItemStack repair check API diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index c63de60fd3c6b5c2cf3b5b01288d8309d9e6d02b..ee20f8cd7c260540f4fa9235343841ddd6e72eba 100644 +index c876f95989d5bb64e745f8f62b4874422156d49c..52e0bee77f10965932c67333e7d22cbbcdc08048 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -161,6 +161,16 @@ public interface UnsafeValues { +@@ -165,6 +165,16 @@ public interface UnsafeValues { */ public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack); diff --git a/patches/api/0298-More-Enchantment-API.patch b/patches/api/0290-More-Enchantment-API.patch similarity index 100% rename from patches/api/0298-More-Enchantment-API.patch rename to patches/api/0290-More-Enchantment-API.patch diff --git a/patches/api/0300-Add-Mob-lookAt-API.patch b/patches/api/0291-Add-Mob-lookAt-API.patch similarity index 100% rename from patches/api/0300-Add-Mob-lookAt-API.patch rename to patches/api/0291-Add-Mob-lookAt-API.patch diff --git a/patches/api/0301-ItemStack-editMeta.patch b/patches/api/0292-ItemStack-editMeta.patch similarity index 100% rename from patches/api/0301-ItemStack-editMeta.patch rename to patches/api/0292-ItemStack-editMeta.patch diff --git a/patches/api/0302-Add-EntityInsideBlockEvent.patch b/patches/api/0293-Add-EntityInsideBlockEvent.patch similarity index 100% rename from patches/api/0302-Add-EntityInsideBlockEvent.patch rename to patches/api/0293-Add-EntityInsideBlockEvent.patch diff --git a/patches/api/0303-Attributes-API-for-item-defaults.patch b/patches/api/0294-Attributes-API-for-item-defaults.patch similarity index 94% rename from patches/api/0303-Attributes-API-for-item-defaults.patch rename to patches/api/0294-Attributes-API-for-item-defaults.patch index cf9f6bf7b3..804d636cec 100644 --- a/patches/api/0303-Attributes-API-for-item-defaults.patch +++ b/patches/api/0294-Attributes-API-for-item-defaults.patch @@ -31,10 +31,10 @@ index eb8aa093148eea3b2fcafe06e8f1277ebbe2f275..9c6291531d3081bf601364815fdd0a9b /** diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index ee20f8cd7c260540f4fa9235343841ddd6e72eba..dc1dc789c6f8eebc026ca990ed44fa7c6cb88f19 100644 +index 52e0bee77f10965932c67333e7d22cbbcdc08048..3388f31c2f287c8dcf4bfd157a04d9383cbe41e3 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -171,6 +171,18 @@ public interface UnsafeValues { +@@ -175,6 +175,18 @@ public interface UnsafeValues { */ public boolean isValidRepairItemStack(@org.jetbrains.annotations.NotNull ItemStack itemToBeRepaired, @org.jetbrains.annotations.NotNull ItemStack repairMaterial); diff --git a/patches/api/0304-Add-cause-to-Weather-ThunderChangeEvents.patch b/patches/api/0295-Add-cause-to-Weather-ThunderChangeEvents.patch similarity index 100% rename from patches/api/0304-Add-cause-to-Weather-ThunderChangeEvents.patch rename to patches/api/0295-Add-cause-to-Weather-ThunderChangeEvents.patch diff --git a/patches/api/0305-More-Lidded-Block-API.patch b/patches/api/0296-More-Lidded-Block-API.patch similarity index 100% rename from patches/api/0305-More-Lidded-Block-API.patch rename to patches/api/0296-More-Lidded-Block-API.patch diff --git a/patches/api/0306-Add-PlayerKickEvent-causes.patch b/patches/api/0297-Add-PlayerKickEvent-causes.patch similarity index 97% rename from patches/api/0306-Add-PlayerKickEvent-causes.patch rename to patches/api/0297-Add-PlayerKickEvent-causes.patch index 8c11c37695..a216a1fe7d 100644 --- a/patches/api/0306-Add-PlayerKickEvent-causes.patch +++ b/patches/api/0297-Add-PlayerKickEvent-causes.patch @@ -5,7 +5,7 @@ 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 9bae45ea3097e328594dcaefac87c55d2c27498d..19d23f2995322e1710741b58e5c7bc2f3880fc0d 100644 +index c3db4783a05020cf91e2fd314dddf22d1ccfc02b..ba45de407168f34511af34bcd1a0e209ddfe2374 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -252,6 +252,14 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/api/0307-Add-PufferFishStateChangeEvent.patch b/patches/api/0298-Add-PufferFishStateChangeEvent.patch similarity index 100% rename from patches/api/0307-Add-PufferFishStateChangeEvent.patch rename to patches/api/0298-Add-PufferFishStateChangeEvent.patch diff --git a/patches/api/0308-Add-BellRevealRaiderEvent.patch b/patches/api/0299-Add-BellRevealRaiderEvent.patch similarity index 100% rename from patches/api/0308-Add-BellRevealRaiderEvent.patch rename to patches/api/0299-Add-BellRevealRaiderEvent.patch diff --git a/patches/api/0309-Add-ElderGuardianAppearanceEvent.patch b/patches/api/0300-Add-ElderGuardianAppearanceEvent.patch similarity index 100% rename from patches/api/0309-Add-ElderGuardianAppearanceEvent.patch rename to patches/api/0300-Add-ElderGuardianAppearanceEvent.patch diff --git a/patches/api/0310-Add-more-line-of-sight-methods.patch b/patches/api/0301-Add-more-line-of-sight-methods.patch similarity index 95% rename from patches/api/0310-Add-more-line-of-sight-methods.patch rename to patches/api/0301-Add-more-line-of-sight-methods.patch index c25014dd74..6c81b3e7cf 100644 --- a/patches/api/0310-Add-more-line-of-sight-methods.patch +++ b/patches/api/0301-Add-more-line-of-sight-methods.patch @@ -23,7 +23,7 @@ index aa534b1a9a1fb84a2fbd4b372f313bb4b63325fa..43b53c21af01e0f496c8aaacff82dfdf // Paper end } diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 53a8d79788f2d9d4b46e6aece1d76863dd5fb727..a38606c07d681b210124949001c9439835d6d3c9 100644 +index cc61e030f1bdb4d1ef52a0a1ae4983f95d2460fd..9ab91154c74b5a3001cf4d5df1b4ae1e26508b60 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -546,6 +546,19 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0311-Add-WaterBottleSplashEvent.patch b/patches/api/0302-Add-WaterBottleSplashEvent.patch similarity index 100% rename from patches/api/0311-Add-WaterBottleSplashEvent.patch rename to patches/api/0302-Add-WaterBottleSplashEvent.patch diff --git a/patches/api/0312-Add-more-LimitedRegion-API.patch b/patches/api/0303-Add-more-LimitedRegion-API.patch similarity index 100% rename from patches/api/0312-Add-more-LimitedRegion-API.patch rename to patches/api/0303-Add-more-LimitedRegion-API.patch diff --git a/patches/api/0313-Missing-Entity-Behavior-API.patch b/patches/api/0304-Missing-Entity-Behavior-API.patch similarity index 100% rename from patches/api/0313-Missing-Entity-Behavior-API.patch rename to patches/api/0304-Missing-Entity-Behavior-API.patch diff --git a/patches/api/0314-Adds-PlayerArmSwingEvent.patch b/patches/api/0305-Adds-PlayerArmSwingEvent.patch similarity index 100% rename from patches/api/0314-Adds-PlayerArmSwingEvent.patch rename to patches/api/0305-Adds-PlayerArmSwingEvent.patch diff --git a/patches/api/0315-Add-PlayerSignCommandPreprocessEvent.patch b/patches/api/0306-Add-PlayerSignCommandPreprocessEvent.patch similarity index 100% rename from patches/api/0315-Add-PlayerSignCommandPreprocessEvent.patch rename to patches/api/0306-Add-PlayerSignCommandPreprocessEvent.patch diff --git a/patches/api/0316-fix-empty-array-elements-in-command-arguments.patch b/patches/api/0307-fix-empty-array-elements-in-command-arguments.patch similarity index 93% rename from patches/api/0316-fix-empty-array-elements-in-command-arguments.patch rename to patches/api/0307-fix-empty-array-elements-in-command-arguments.patch index b6512f8f29..4b66990211 100644 --- a/patches/api/0316-fix-empty-array-elements-in-command-arguments.patch +++ b/patches/api/0307-fix-empty-array-elements-in-command-arguments.patch @@ -9,7 +9,7 @@ Adjacent spaces sent by players are removed in PlayerConnection, so this change But it does affect the console, command blocks, Bukkit.dispatchCommand, etc. diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java -index 950a2d0b3b583c6b9a703190874bbc4df2783ab7..b8623575b1c1b565560c2dd6438190716845a652 100644 +index 1424060c0a162020d4a680e0a592224561067b16..ac9a28922f8a556944a4c3649d74c32c622f0cb0 100644 --- a/src/main/java/org/bukkit/command/SimpleCommandMap.java +++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java @@ -130,7 +130,7 @@ public class SimpleCommandMap implements CommandMap { diff --git a/patches/api/0317-Stinger-API.patch b/patches/api/0308-Stinger-API.patch similarity index 100% rename from patches/api/0317-Stinger-API.patch rename to patches/api/0308-Stinger-API.patch diff --git a/patches/api/0309-Rewrite-LogEvents-to-contain-the-source-jars-in-stac.patch b/patches/api/0309-Rewrite-LogEvents-to-contain-the-source-jars-in-stac.patch new file mode 100644 index 0000000000..69d7c509c4 --- /dev/null +++ b/patches/api/0309-Rewrite-LogEvents-to-contain-the-source-jars-in-stac.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: SirYwell +Date: Sat, 10 Jul 2021 11:11:43 +0200 +Subject: [PATCH] Rewrite LogEvents to contain the source jars in stack traces + + +diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +index ef60a8a7e20e27fee6f96fe1398ec9aee9352aec..87c90128ada98fcb31ff106333ffabb35972a107 100644 +--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +@@ -55,7 +55,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm + + @org.jetbrains.annotations.ApiStatus.Internal // Paper + public PluginClassLoader(@Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader, io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext) throws IOException, InvalidPluginException, MalformedURLException { // Paper +- super(new URL[] {file.toURI().toURL()}, parent); ++ super(file.getName(), new URL[] {file.toURI().toURL()}, parent); + this.loader = null; // Paper - pass null into loader field + + this.description = description; diff --git a/patches/api/0319-Add-PlayerSetSpawnEvent.patch b/patches/api/0310-Add-PlayerSetSpawnEvent.patch similarity index 100% rename from patches/api/0319-Add-PlayerSetSpawnEvent.patch rename to patches/api/0310-Add-PlayerSetSpawnEvent.patch diff --git a/patches/api/0320-Added-EntityDamageItemEvent.patch b/patches/api/0311-Added-EntityDamageItemEvent.patch similarity index 100% rename from patches/api/0320-Added-EntityDamageItemEvent.patch rename to patches/api/0311-Added-EntityDamageItemEvent.patch diff --git a/patches/api/0321-Make-EntityUnleashEvent-cancellable.patch b/patches/api/0312-Make-EntityUnleashEvent-cancellable.patch similarity index 100% rename from patches/api/0321-Make-EntityUnleashEvent-cancellable.patch rename to patches/api/0312-Make-EntityUnleashEvent-cancellable.patch diff --git a/patches/api/0322-Change-EnderEye-target-without-changing-other-things.patch b/patches/api/0313-Change-EnderEye-target-without-changing-other-things.patch similarity index 100% rename from patches/api/0322-Change-EnderEye-target-without-changing-other-things.patch rename to patches/api/0313-Change-EnderEye-target-without-changing-other-things.patch diff --git a/patches/api/0323-Add-BlockBreakBlockEvent.patch b/patches/api/0314-Add-BlockBreakBlockEvent.patch similarity index 100% rename from patches/api/0323-Add-BlockBreakBlockEvent.patch rename to patches/api/0314-Add-BlockBreakBlockEvent.patch diff --git a/patches/api/0324-Add-helpers-for-left-right-click-to-Action.patch b/patches/api/0315-Add-helpers-for-left-right-click-to-Action.patch similarity index 100% rename from patches/api/0324-Add-helpers-for-left-right-click-to-Action.patch rename to patches/api/0315-Add-helpers-for-left-right-click-to-Action.patch diff --git a/patches/api/0325-Option-to-prevent-NBT-copy-in-smithing-recipes.patch b/patches/api/0316-Option-to-prevent-NBT-copy-in-smithing-recipes.patch similarity index 100% rename from patches/api/0325-Option-to-prevent-NBT-copy-in-smithing-recipes.patch rename to patches/api/0316-Option-to-prevent-NBT-copy-in-smithing-recipes.patch diff --git a/patches/api/0326-More-CommandBlock-API.patch b/patches/api/0317-More-CommandBlock-API.patch similarity index 100% rename from patches/api/0326-More-CommandBlock-API.patch rename to patches/api/0317-More-CommandBlock-API.patch diff --git a/patches/api/0328-Add-missing-team-sidebar-display-slots.patch b/patches/api/0318-Add-missing-team-sidebar-display-slots.patch similarity index 100% rename from patches/api/0328-Add-missing-team-sidebar-display-slots.patch rename to patches/api/0318-Add-missing-team-sidebar-display-slots.patch diff --git a/patches/api/0318-Rewrite-LogEvents-to-contain-the-source-jars-in-stac.patch b/patches/api/0318-Rewrite-LogEvents-to-contain-the-source-jars-in-stac.patch deleted file mode 100644 index a9319418e4..0000000000 --- a/patches/api/0318-Rewrite-LogEvents-to-contain-the-source-jars-in-stac.patch +++ /dev/null @@ -1,19 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: SirYwell -Date: Sat, 10 Jul 2021 11:11:43 +0200 -Subject: [PATCH] Rewrite LogEvents to contain the source jars in stack traces - - -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index e39492e2544c39c5457f079a6baadf0b4074dd7e..345394132df70593800127d34a38f8f8a4dafe00 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -51,7 +51,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - } - - PluginClassLoader(@NotNull final JavaPluginLoader loader, @Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader) throws IOException, InvalidPluginException, MalformedURLException { -- super(new URL[] {file.toURI().toURL()}, parent); -+ super(file.getName(), new URL[] {file.toURI().toURL()}, parent); // Paper - rewrite LogEvents to contain source jar info - Preconditions.checkArgument(loader != null, "Loader cannot be null"); - - this.loader = loader; diff --git a/patches/api/0329-add-back-EntityPortalExitEvent.patch b/patches/api/0319-add-back-EntityPortalExitEvent.patch similarity index 100% rename from patches/api/0329-add-back-EntityPortalExitEvent.patch rename to patches/api/0319-add-back-EntityPortalExitEvent.patch diff --git a/patches/api/0330-Add-methods-to-find-targets-for-lightning-strikes.patch b/patches/api/0320-Add-methods-to-find-targets-for-lightning-strikes.patch similarity index 95% rename from patches/api/0330-Add-methods-to-find-targets-for-lightning-strikes.patch rename to patches/api/0320-Add-methods-to-find-targets-for-lightning-strikes.patch index bce5db5143..d0652f734d 100644 --- a/patches/api/0330-Add-methods-to-find-targets-for-lightning-strikes.patch +++ b/patches/api/0320-Add-methods-to-find-targets-for-lightning-strikes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add methods to find targets for lightning strikes diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 82eb04abe67e05f1bb6fd2a0350d5b2574a01d4b..43d12399e807abd4c95ffec8c025373b6d344a36 100644 +index 6da379edbf35321f7265606228695f40a9ea6977..2955302b08b30570e4a561e3b076d10d80f2f2b3 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -749,6 +749,37 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient diff --git a/patches/api/0331-Get-entity-default-attributes.patch b/patches/api/0321-Get-entity-default-attributes.patch similarity index 94% rename from patches/api/0331-Get-entity-default-attributes.patch rename to patches/api/0321-Get-entity-default-attributes.patch index 502c1f8c5a..0d8ae058a8 100644 --- a/patches/api/0331-Get-entity-default-attributes.patch +++ b/patches/api/0321-Get-entity-default-attributes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Get entity default attributes diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index dc1dc789c6f8eebc026ca990ed44fa7c6cb88f19..edcf0ca00aaf9d9ad26eb7fb04075fba101169fd 100644 +index 3388f31c2f287c8dcf4bfd157a04d9383cbe41e3..393e0e9bacb30cdae4154ec2573e000a82cc89e7 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -189,5 +189,22 @@ public interface UnsafeValues { +@@ -193,5 +193,22 @@ public interface UnsafeValues { * @return the server's protocol version */ int getProtocolVersion(); diff --git a/patches/api/0332-Left-handed-API.patch b/patches/api/0322-Left-handed-API.patch similarity index 100% rename from patches/api/0332-Left-handed-API.patch rename to patches/api/0322-Left-handed-API.patch diff --git a/patches/api/0333-Add-more-advancement-API.patch b/patches/api/0323-Add-more-advancement-API.patch similarity index 98% rename from patches/api/0333-Add-more-advancement-API.patch rename to patches/api/0323-Add-more-advancement-API.patch index 1dcfad9c82..2fd6d7a372 100644 --- a/patches/api/0333-Add-more-advancement-API.patch +++ b/patches/api/0323-Add-more-advancement-API.patch @@ -256,7 +256,7 @@ index 0ff86a39025a94ca128364a45bf171728cb81027..aec6be7e121da3eb8a464b6934da29ab /** diff --git a/src/main/java/org/bukkit/advancement/AdvancementDisplayType.java b/src/main/java/org/bukkit/advancement/AdvancementDisplayType.java -index d6640a9ebb30195abf4570dfd30a320fa4636995..f6e1a6c1bb7b99a391dec73c9707840214988fc6 100644 +index de767efb9f55448df061e166c66a2cf3439d57ec..06d8b72dd54becc13f40bd6e505115405462cd73 100644 --- a/src/main/java/org/bukkit/advancement/AdvancementDisplayType.java +++ b/src/main/java/org/bukkit/advancement/AdvancementDisplayType.java @@ -8,7 +8,9 @@ import org.jetbrains.annotations.NotNull; diff --git a/patches/api/0334-Add-ItemFactory-getSpawnEgg-API.patch b/patches/api/0324-Add-ItemFactory-getSpawnEgg-API.patch similarity index 100% rename from patches/api/0334-Add-ItemFactory-getSpawnEgg-API.patch rename to patches/api/0324-Add-ItemFactory-getSpawnEgg-API.patch diff --git a/patches/api/0335-Add-critical-damage-API.patch b/patches/api/0325-Add-critical-damage-API.patch similarity index 100% rename from patches/api/0335-Add-critical-damage-API.patch rename to patches/api/0325-Add-critical-damage-API.patch diff --git a/patches/api/0336-Fix-issues-with-mob-conversion.patch b/patches/api/0326-Fix-issues-with-mob-conversion.patch similarity index 100% rename from patches/api/0336-Fix-issues-with-mob-conversion.patch rename to patches/api/0326-Fix-issues-with-mob-conversion.patch diff --git a/patches/api/0337-Add-isCollidable-methods-to-various-places.patch b/patches/api/0327-Add-isCollidable-methods-to-various-places.patch similarity index 95% rename from patches/api/0337-Add-isCollidable-methods-to-various-places.patch rename to patches/api/0327-Add-isCollidable-methods-to-various-places.patch index dbc60870ba..5923e618bf 100644 --- a/patches/api/0337-Add-isCollidable-methods-to-various-places.patch +++ b/patches/api/0327-Add-isCollidable-methods-to-various-places.patch @@ -26,10 +26,10 @@ index 9c6291531d3081bf601364815fdd0a9b801eee50..33371518fc8c5d97625f3d528ba8fee2 /** diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index edcf0ca00aaf9d9ad26eb7fb04075fba101169fd..4b0b1afcf3f8fa8929311dae47df91d0b7dd6fdc 100644 +index 393e0e9bacb30cdae4154ec2573e000a82cc89e7..aa5fff8704fa002af0cffb09049311edaef19339 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -206,5 +206,14 @@ public interface UnsafeValues { +@@ -210,5 +210,14 @@ public interface UnsafeValues { * @throws IllegalArgumentException if the entity does not exist of have default attributes (use {@link #hasDefaultEntityAttributes(NamespacedKey)} first) */ @org.jetbrains.annotations.NotNull org.bukkit.attribute.Attributable getDefaultEntityAttributes(@org.jetbrains.annotations.NotNull NamespacedKey entityKey); diff --git a/patches/api/0338-Goat-ram-API.patch b/patches/api/0328-Goat-ram-API.patch similarity index 100% rename from patches/api/0338-Goat-ram-API.patch rename to patches/api/0328-Goat-ram-API.patch diff --git a/patches/api/0339-Add-API-for-resetting-a-single-score.patch b/patches/api/0329-Add-API-for-resetting-a-single-score.patch similarity index 100% rename from patches/api/0339-Add-API-for-resetting-a-single-score.patch rename to patches/api/0329-Add-API-for-resetting-a-single-score.patch diff --git a/patches/api/0340-Add-Raw-Byte-Entity-Serialization.patch b/patches/api/0330-Add-Raw-Byte-Entity-Serialization.patch similarity index 94% rename from patches/api/0340-Add-Raw-Byte-Entity-Serialization.patch rename to patches/api/0330-Add-Raw-Byte-Entity-Serialization.patch index 9be43fece0..5afcb9c166 100644 --- a/patches/api/0340-Add-Raw-Byte-Entity-Serialization.patch +++ b/patches/api/0330-Add-Raw-Byte-Entity-Serialization.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add Raw Byte Entity Serialization diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 4b0b1afcf3f8fa8929311dae47df91d0b7dd6fdc..dda436f61b174bf1bd94033a09468626f099ee3a 100644 +index aa5fff8704fa002af0cffb09049311edaef19339..80314e6dabadcd290841c792f3a5fafecd6ea036 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -122,6 +122,14 @@ public interface UnsafeValues { +@@ -126,6 +126,14 @@ public interface UnsafeValues { ItemStack deserializeItem(byte[] data); diff --git a/patches/api/0341-Add-PlayerItemFrameChangeEvent.patch b/patches/api/0331-Add-PlayerItemFrameChangeEvent.patch similarity index 100% rename from patches/api/0341-Add-PlayerItemFrameChangeEvent.patch rename to patches/api/0331-Add-PlayerItemFrameChangeEvent.patch diff --git a/patches/api/0342-Add-player-health-update-API.patch b/patches/api/0332-Add-player-health-update-API.patch similarity index 100% rename from patches/api/0342-Add-player-health-update-API.patch rename to patches/api/0332-Add-player-health-update-API.patch diff --git a/patches/api/0343-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/api/0333-Allow-delegation-to-vanilla-chunk-gen.patch similarity index 100% rename from patches/api/0343-Allow-delegation-to-vanilla-chunk-gen.patch rename to patches/api/0333-Allow-delegation-to-vanilla-chunk-gen.patch diff --git a/patches/api/0344-Add-more-Campfire-API.patch b/patches/api/0334-Add-more-Campfire-API.patch similarity index 100% rename from patches/api/0344-Add-more-Campfire-API.patch rename to patches/api/0334-Add-more-Campfire-API.patch diff --git a/patches/api/0345-Move-VehicleCollisionEvent-HandlerList-up.patch b/patches/api/0335-Move-VehicleCollisionEvent-HandlerList-up.patch similarity index 100% rename from patches/api/0345-Move-VehicleCollisionEvent-HandlerList-up.patch rename to patches/api/0335-Move-VehicleCollisionEvent-HandlerList-up.patch diff --git a/patches/api/0346-Improve-scoreboard-entries.patch b/patches/api/0336-Improve-scoreboard-entries.patch similarity index 100% rename from patches/api/0346-Improve-scoreboard-entries.patch rename to patches/api/0336-Improve-scoreboard-entries.patch diff --git a/patches/api/0347-Entity-powdered-snow-API.patch b/patches/api/0337-Entity-powdered-snow-API.patch similarity index 100% rename from patches/api/0347-Entity-powdered-snow-API.patch rename to patches/api/0337-Entity-powdered-snow-API.patch diff --git a/patches/api/0348-Add-API-for-item-entity-health.patch b/patches/api/0338-Add-API-for-item-entity-health.patch similarity index 100% rename from patches/api/0348-Add-API-for-item-entity-health.patch rename to patches/api/0338-Add-API-for-item-entity-health.patch diff --git a/patches/api/0349-Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch b/patches/api/0339-Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch similarity index 100% rename from patches/api/0349-Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch rename to patches/api/0339-Expose-isFuel-and-canSmelt-methods-to-FurnaceInvento.patch diff --git a/patches/api/0350-Bucketable-API.patch b/patches/api/0340-Bucketable-API.patch similarity index 100% rename from patches/api/0350-Bucketable-API.patch rename to patches/api/0340-Bucketable-API.patch diff --git a/patches/api/0351-System-prop-for-default-config-comment-parsing.patch b/patches/api/0341-System-prop-for-default-config-comment-parsing.patch similarity index 100% rename from patches/api/0351-System-prop-for-default-config-comment-parsing.patch rename to patches/api/0341-System-prop-for-default-config-comment-parsing.patch diff --git a/patches/api/0352-Expose-vanilla-BiomeProvider-from-WorldInfo.patch b/patches/api/0342-Expose-vanilla-BiomeProvider-from-WorldInfo.patch similarity index 100% rename from patches/api/0352-Expose-vanilla-BiomeProvider-from-WorldInfo.patch rename to patches/api/0342-Expose-vanilla-BiomeProvider-from-WorldInfo.patch diff --git a/patches/api/0353-Add-new-overload-to-PersistentDataContainer-has.patch b/patches/api/0343-Add-new-overload-to-PersistentDataContainer-has.patch similarity index 100% rename from patches/api/0353-Add-new-overload-to-PersistentDataContainer-has.patch rename to patches/api/0343-Add-new-overload-to-PersistentDataContainer-has.patch diff --git a/patches/api/0354-Multiple-Entries-with-Scoreboards.patch b/patches/api/0344-Multiple-Entries-with-Scoreboards.patch similarity index 100% rename from patches/api/0354-Multiple-Entries-with-Scoreboards.patch rename to patches/api/0344-Multiple-Entries-with-Scoreboards.patch diff --git a/patches/api/0355-Added-getHostname-to-AsyncPlayerPreLoginEvent.patch b/patches/api/0345-Added-getHostname-to-AsyncPlayerPreLoginEvent.patch similarity index 100% rename from patches/api/0355-Added-getHostname-to-AsyncPlayerPreLoginEvent.patch rename to patches/api/0345-Added-getHostname-to-AsyncPlayerPreLoginEvent.patch diff --git a/patches/api/0356-Warn-on-strange-EventHandler-return-types.patch b/patches/api/0346-Warn-on-strange-EventHandler-return-types.patch similarity index 100% rename from patches/api/0356-Warn-on-strange-EventHandler-return-types.patch rename to patches/api/0346-Warn-on-strange-EventHandler-return-types.patch diff --git a/patches/api/0357-Multi-Block-Change-API.patch b/patches/api/0347-Multi-Block-Change-API.patch similarity index 100% rename from patches/api/0357-Multi-Block-Change-API.patch rename to patches/api/0347-Multi-Block-Change-API.patch diff --git a/patches/api/0358-Fix-NotePlayEvent.patch b/patches/api/0348-Fix-NotePlayEvent.patch similarity index 100% rename from patches/api/0358-Fix-NotePlayEvent.patch rename to patches/api/0348-Fix-NotePlayEvent.patch diff --git a/patches/api/0359-Freeze-Tick-Lock-API.patch b/patches/api/0349-Freeze-Tick-Lock-API.patch similarity index 100% rename from patches/api/0359-Freeze-Tick-Lock-API.patch rename to patches/api/0349-Freeze-Tick-Lock-API.patch diff --git a/patches/api/0360-Dolphin-API.patch b/patches/api/0350-Dolphin-API.patch similarity index 100% rename from patches/api/0360-Dolphin-API.patch rename to patches/api/0350-Dolphin-API.patch diff --git a/patches/api/0361-More-PotionEffectType-API.patch b/patches/api/0351-More-PotionEffectType-API.patch similarity index 100% rename from patches/api/0361-More-PotionEffectType-API.patch rename to patches/api/0351-More-PotionEffectType-API.patch diff --git a/patches/api/0362-API-for-creating-command-sender-which-forwards-feedb.patch b/patches/api/0352-API-for-creating-command-sender-which-forwards-feedb.patch similarity index 100% rename from patches/api/0362-API-for-creating-command-sender-which-forwards-feedb.patch rename to patches/api/0352-API-for-creating-command-sender-which-forwards-feedb.patch diff --git a/patches/api/0363-Implement-regenerateChunk.patch b/patches/api/0353-Implement-regenerateChunk.patch similarity index 91% rename from patches/api/0363-Implement-regenerateChunk.patch rename to patches/api/0353-Implement-regenerateChunk.patch index 4cc4dda624..fc4adbf415 100644 --- a/patches/api/0363-Implement-regenerateChunk.patch +++ b/patches/api/0353-Implement-regenerateChunk.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Implement regenerateChunk diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java -index 43d12399e807abd4c95ffec8c025373b6d344a36..9e71e519cda72a1e2a01474f238b97015ec5115e 100644 +index 2955302b08b30570e4a561e3b076d10d80f2f2b3..aa04d7df70d99402c91e920fd693d7d4fb655786 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -498,8 +498,8 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient diff --git a/patches/api/0365-Add-GameEvent-tags.patch b/patches/api/0354-Add-GameEvent-tags.patch similarity index 100% rename from patches/api/0365-Add-GameEvent-tags.patch rename to patches/api/0354-Add-GameEvent-tags.patch diff --git a/patches/api/0366-Furnace-RecipesUsed-API.patch b/patches/api/0355-Furnace-RecipesUsed-API.patch similarity index 100% rename from patches/api/0366-Furnace-RecipesUsed-API.patch rename to patches/api/0355-Furnace-RecipesUsed-API.patch diff --git a/patches/api/0367-Configurable-sculk-sensor-listener-range.patch b/patches/api/0356-Configurable-sculk-sensor-listener-range.patch similarity index 100% rename from patches/api/0367-Configurable-sculk-sensor-listener-range.patch rename to patches/api/0356-Configurable-sculk-sensor-listener-range.patch diff --git a/patches/api/0368-Add-missing-block-data-mins-and-maxes.patch b/patches/api/0357-Add-missing-block-data-mins-and-maxes.patch similarity index 100% rename from patches/api/0368-Add-missing-block-data-mins-and-maxes.patch rename to patches/api/0357-Add-missing-block-data-mins-and-maxes.patch diff --git a/patches/api/0369-Custom-Potion-Mixes.patch b/patches/api/0358-Custom-Potion-Mixes.patch similarity index 100% rename from patches/api/0369-Custom-Potion-Mixes.patch rename to patches/api/0358-Custom-Potion-Mixes.patch diff --git a/patches/api/0370-Expose-furnace-minecart-push-values.patch b/patches/api/0359-Expose-furnace-minecart-push-values.patch similarity index 100% rename from patches/api/0370-Expose-furnace-minecart-push-values.patch rename to patches/api/0359-Expose-furnace-minecart-push-values.patch diff --git a/patches/api/0371-More-Projectile-API.patch b/patches/api/0360-More-Projectile-API.patch similarity index 100% rename from patches/api/0371-More-Projectile-API.patch rename to patches/api/0360-More-Projectile-API.patch diff --git a/patches/api/0372-Add-getComputedBiome-API.patch b/patches/api/0361-Add-getComputedBiome-API.patch similarity index 100% rename from patches/api/0372-Add-getComputedBiome-API.patch rename to patches/api/0361-Add-getComputedBiome-API.patch diff --git a/patches/api/0373-Add-enchantWithLevels-API.patch b/patches/api/0362-Add-enchantWithLevels-API.patch similarity index 100% rename from patches/api/0373-Add-enchantWithLevels-API.patch rename to patches/api/0362-Add-enchantWithLevels-API.patch diff --git a/patches/api/0374-Add-TameableDeathMessageEvent.patch b/patches/api/0363-Add-TameableDeathMessageEvent.patch similarity index 100% rename from patches/api/0374-Add-TameableDeathMessageEvent.patch rename to patches/api/0363-Add-TameableDeathMessageEvent.patch diff --git a/patches/api/0375-Allow-to-change-the-podium-of-the-EnderDragon.patch b/patches/api/0364-Allow-to-change-the-podium-of-the-EnderDragon.patch similarity index 100% rename from patches/api/0375-Allow-to-change-the-podium-of-the-EnderDragon.patch rename to patches/api/0364-Allow-to-change-the-podium-of-the-EnderDragon.patch diff --git a/patches/api/0376-Add-pre-unbreaking-amount-to-PlayerItemDamageEvent.patch b/patches/api/0365-Add-pre-unbreaking-amount-to-PlayerItemDamageEvent.patch similarity index 100% rename from patches/api/0376-Add-pre-unbreaking-amount-to-PlayerItemDamageEvent.patch rename to patches/api/0365-Add-pre-unbreaking-amount-to-PlayerItemDamageEvent.patch diff --git a/patches/api/0378-WorldCreator-keepSpawnLoaded.patch b/patches/api/0366-WorldCreator-keepSpawnLoaded.patch similarity index 100% rename from patches/api/0378-WorldCreator-keepSpawnLoaded.patch rename to patches/api/0366-WorldCreator-keepSpawnLoaded.patch diff --git a/patches/api/0379-Add-EntityDyeEvent-and-CollarColorable-interface.patch b/patches/api/0367-Add-EntityDyeEvent-and-CollarColorable-interface.patch similarity index 100% rename from patches/api/0379-Add-EntityDyeEvent-and-CollarColorable-interface.patch rename to patches/api/0367-Add-EntityDyeEvent-and-CollarColorable-interface.patch diff --git a/patches/api/0380-Add-PlayerStopUsingItemEvent.patch b/patches/api/0368-Add-PlayerStopUsingItemEvent.patch similarity index 100% rename from patches/api/0380-Add-PlayerStopUsingItemEvent.patch rename to patches/api/0368-Add-PlayerStopUsingItemEvent.patch diff --git a/patches/api/0381-FallingBlock-auto-expire-setting.patch b/patches/api/0369-FallingBlock-auto-expire-setting.patch similarity index 100% rename from patches/api/0381-FallingBlock-auto-expire-setting.patch rename to patches/api/0369-FallingBlock-auto-expire-setting.patch diff --git a/patches/api/0382-Keyed-Cat-Type.patch b/patches/api/0370-Keyed-Cat-Type.patch similarity index 100% rename from patches/api/0382-Keyed-Cat-Type.patch rename to patches/api/0370-Keyed-Cat-Type.patch diff --git a/patches/api/0383-Add-method-isTickingWorlds-to-Bukkit.patch b/patches/api/0371-Add-method-isTickingWorlds-to-Bukkit.patch similarity index 100% rename from patches/api/0383-Add-method-isTickingWorlds-to-Bukkit.patch rename to patches/api/0371-Add-method-isTickingWorlds-to-Bukkit.patch diff --git a/patches/api/0384-Add-WardenAngerChangeEvent.patch b/patches/api/0372-Add-WardenAngerChangeEvent.patch similarity index 100% rename from patches/api/0384-Add-WardenAngerChangeEvent.patch rename to patches/api/0372-Add-WardenAngerChangeEvent.patch diff --git a/patches/api/0385-Nameable-Banner-API.patch b/patches/api/0373-Nameable-Banner-API.patch similarity index 100% rename from patches/api/0385-Nameable-Banner-API.patch rename to patches/api/0373-Nameable-Banner-API.patch diff --git a/patches/api/0386-Add-Player-getFishHook.patch b/patches/api/0374-Add-Player-getFishHook.patch similarity index 100% rename from patches/api/0386-Add-Player-getFishHook.patch rename to patches/api/0374-Add-Player-getFishHook.patch diff --git a/patches/api/0387-More-Teleport-API.patch b/patches/api/0375-More-Teleport-API.patch similarity index 100% rename from patches/api/0387-More-Teleport-API.patch rename to patches/api/0375-More-Teleport-API.patch diff --git a/patches/api/0388-Add-EntityPortalReadyEvent.patch b/patches/api/0376-Add-EntityPortalReadyEvent.patch similarity index 100% rename from patches/api/0388-Add-EntityPortalReadyEvent.patch rename to patches/api/0376-Add-EntityPortalReadyEvent.patch diff --git a/patches/api/0389-Custom-Chat-Completion-Suggestions-API.patch b/patches/api/0377-Custom-Chat-Completion-Suggestions-API.patch similarity index 100% rename from patches/api/0389-Custom-Chat-Completion-Suggestions-API.patch rename to patches/api/0377-Custom-Chat-Completion-Suggestions-API.patch diff --git a/patches/api/0390-Collision-API.patch b/patches/api/0378-Collision-API.patch similarity index 100% rename from patches/api/0390-Collision-API.patch rename to patches/api/0378-Collision-API.patch diff --git a/patches/api/0391-Block-Ticking-API.patch b/patches/api/0379-Block-Ticking-API.patch similarity index 100% rename from patches/api/0391-Block-Ticking-API.patch rename to patches/api/0379-Block-Ticking-API.patch diff --git a/patches/api/0392-Add-NamespacedKey-biome-methods.patch b/patches/api/0380-Add-NamespacedKey-biome-methods.patch similarity index 92% rename from patches/api/0392-Add-NamespacedKey-biome-methods.patch rename to patches/api/0380-Add-NamespacedKey-biome-methods.patch index aa346d768f..72e349941b 100644 --- a/patches/api/0392-Add-NamespacedKey-biome-methods.patch +++ b/patches/api/0380-Add-NamespacedKey-biome-methods.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add NamespacedKey biome methods Co-authored-by: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index dda436f61b174bf1bd94033a09468626f099ee3a..0f4a642a851eace1f3694b9bc0027c2ffdff3695 100644 +index 80314e6dabadcd290841c792f3a5fafecd6ea036..7cf5223d3f66783e05767e16000bf51925064d66 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -223,5 +223,32 @@ public interface UnsafeValues { +@@ -227,5 +227,32 @@ public interface UnsafeValues { * @throws IllegalArgumentException if {@link Material#isBlock()} is false */ boolean isCollidable(@org.jetbrains.annotations.NotNull Material material); diff --git a/patches/api/0393-Add-custom-destroyerIdentity-to-sendBlockDamage.patch b/patches/api/0381-Add-custom-destroyerIdentity-to-sendBlockDamage.patch similarity index 100% rename from patches/api/0393-Add-custom-destroyerIdentity-to-sendBlockDamage.patch rename to patches/api/0381-Add-custom-destroyerIdentity-to-sendBlockDamage.patch diff --git a/patches/api/0394-Also-load-resources-from-LibraryLoader.patch b/patches/api/0382-Also-load-resources-from-LibraryLoader.patch similarity index 81% rename from patches/api/0394-Also-load-resources-from-LibraryLoader.patch rename to patches/api/0382-Also-load-resources-from-LibraryLoader.patch index 9843c45af2..8aa2155fce 100644 --- a/patches/api/0394-Also-load-resources-from-LibraryLoader.patch +++ b/patches/api/0382-Also-load-resources-from-LibraryLoader.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Also load resources from LibraryLoader diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 345394132df70593800127d34a38f8f8a4dafe00..f7cfe6c0d9d52ed72d0d45baaaf856c15769c668 100644 +index 87c90128ada98fcb31ff106333ffabb35972a107..4cb4e28c9b0dfdac45c4129fb0325e6afe5cb131 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -90,14 +90,35 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot +@@ -96,14 +96,35 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm @Override public URL getResource(String name) { @@ -43,6 +43,6 @@ index 345394132df70593800127d34a38f8f8a4dafe00..f7cfe6c0d9d52ed72d0d45baaaf856c1 + } + // Paper end + + // Paper start @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - return loadClass0(name, resolve, true, true); + public Class loadClass(@NotNull String name, boolean resolve, boolean checkGlobal, boolean checkLibraries) throws ClassNotFoundException { diff --git a/patches/api/0395-Added-byte-array-serialization-deserialization-for-P.patch b/patches/api/0383-Added-byte-array-serialization-deserialization-for-P.patch similarity index 100% rename from patches/api/0395-Added-byte-array-serialization-deserialization-for-P.patch rename to patches/api/0383-Added-byte-array-serialization-deserialization-for-P.patch diff --git a/patches/api/0396-Add-a-consumer-parameter-to-ProjectileSource-launchP.patch b/patches/api/0384-Add-a-consumer-parameter-to-ProjectileSource-launchP.patch similarity index 100% rename from patches/api/0396-Add-a-consumer-parameter-to-ProjectileSource-launchP.patch rename to patches/api/0384-Add-a-consumer-parameter-to-ProjectileSource-launchP.patch diff --git a/patches/api/0397-Expose-codepoint-limit-in-YamlConfigOptions-and-incr.patch b/patches/api/0385-Expose-codepoint-limit-in-YamlConfigOptions-and-incr.patch similarity index 100% rename from patches/api/0397-Expose-codepoint-limit-in-YamlConfigOptions-and-incr.patch rename to patches/api/0385-Expose-codepoint-limit-in-YamlConfigOptions-and-incr.patch diff --git a/patches/api/0398-Add-system-property-to-print-stacktrace-on-bad-plugi.patch b/patches/api/0386-Add-system-property-to-print-stacktrace-on-bad-plugi.patch similarity index 86% rename from patches/api/0398-Add-system-property-to-print-stacktrace-on-bad-plugi.patch rename to patches/api/0386-Add-system-property-to-print-stacktrace-on-bad-plugi.patch index 48e74889cc..62749287b8 100644 --- a/patches/api/0398-Add-system-property-to-print-stacktrace-on-bad-plugi.patch +++ b/patches/api/0386-Add-system-property-to-print-stacktrace-on-bad-plugi.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add system property to print stacktrace on bad plugin class diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index f7cfe6c0d9d52ed72d0d45baaaf856c15769c668..cb3c25ef46b279ffdde87f47f729eb8aa7549c1c 100644 +index 4cb4e28c9b0dfdac45c4129fb0325e6afe5cb131..4b3380a42b4be54ef4df806c5db0d3a1be5909a6 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -162,6 +162,11 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot +@@ -184,6 +184,11 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm // In case the bad access occurs on construction loader.server.getLogger().log(Level.WARNING, "[{0}] Loaded class {1} from {2} which is not a depend or softdepend of this plugin.", new Object[]{description.getName(), name, provider.getFullName()}); } diff --git a/patches/api/0399-Add-getDrops-to-BlockState.patch b/patches/api/0387-Add-getDrops-to-BlockState.patch similarity index 100% rename from patches/api/0399-Add-getDrops-to-BlockState.patch rename to patches/api/0387-Add-getDrops-to-BlockState.patch diff --git a/patches/api/0400-Add-PlayerInventorySlotChangeEvent.patch b/patches/api/0388-Add-PlayerInventorySlotChangeEvent.patch similarity index 100% rename from patches/api/0400-Add-PlayerInventorySlotChangeEvent.patch rename to patches/api/0388-Add-PlayerInventorySlotChangeEvent.patch diff --git a/patches/api/0401-Elder-Guardian-appearance-API.patch b/patches/api/0389-Elder-Guardian-appearance-API.patch similarity index 100% rename from patches/api/0401-Elder-Guardian-appearance-API.patch rename to patches/api/0389-Elder-Guardian-appearance-API.patch diff --git a/patches/api/0402-Allow-changing-bed-s-occupied-property.patch b/patches/api/0390-Allow-changing-bed-s-occupied-property.patch similarity index 100% rename from patches/api/0402-Allow-changing-bed-s-occupied-property.patch rename to patches/api/0390-Allow-changing-bed-s-occupied-property.patch diff --git a/patches/api/0403-Add-EquipmentSlot-convenience-methods.patch b/patches/api/0391-Add-EquipmentSlot-convenience-methods.patch similarity index 100% rename from patches/api/0403-Add-EquipmentSlot-convenience-methods.patch rename to patches/api/0391-Add-EquipmentSlot-convenience-methods.patch diff --git a/patches/api/0404-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch b/patches/api/0392-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch similarity index 93% rename from patches/api/0404-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch rename to patches/api/0392-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch index 9d36e8b247..cb116f6d63 100644 --- a/patches/api/0404-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch +++ b/patches/api/0392-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add LivingEntity#swingHand(EquipmentSlot) convenience method diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 6512d2bf94adfc32046ddae25a7c2906db7b1441..15c803ad038585bf3c37e4504d53177d31850acf 100644 +index 27187efdbcf1cf20a53175f1177c16dc40acab3c..aa2c3c4648844908b2699f6f220393f98836ed5d 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -1052,5 +1052,23 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0405-Add-entity-knockback-API.patch b/patches/api/0393-Add-entity-knockback-API.patch similarity index 92% rename from patches/api/0405-Add-entity-knockback-API.patch rename to patches/api/0393-Add-entity-knockback-API.patch index 0af97e0b29..4f7f54130d 100644 --- a/patches/api/0405-Add-entity-knockback-API.patch +++ b/patches/api/0393-Add-entity-knockback-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add entity knockback API diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index 15c803ad038585bf3c37e4504d53177d31850acf..b18a833019c81b8e46535a1b4c42ba3987a97c90 100644 +index aa2c3c4648844908b2699f6f220393f98836ed5d..f5a4160afb75549dd56a237cf99ec733efef9b4c 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -1070,5 +1070,17 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource diff --git a/patches/api/0406-Added-EntityToggleSitEvent.patch b/patches/api/0394-Added-EntityToggleSitEvent.patch similarity index 100% rename from patches/api/0406-Added-EntityToggleSitEvent.patch rename to patches/api/0394-Added-EntityToggleSitEvent.patch diff --git a/patches/api/0407-Add-Moving-Piston-API.patch b/patches/api/0395-Add-Moving-Piston-API.patch similarity index 100% rename from patches/api/0407-Add-Moving-Piston-API.patch rename to patches/api/0395-Add-Moving-Piston-API.patch diff --git a/patches/api/0408-Add-PrePlayerAttackEntityEvent.patch b/patches/api/0396-Add-PrePlayerAttackEntityEvent.patch similarity index 100% rename from patches/api/0408-Add-PrePlayerAttackEntityEvent.patch rename to patches/api/0396-Add-PrePlayerAttackEntityEvent.patch diff --git a/patches/api/0409-Add-Player-Warden-Warning-API.patch b/patches/api/0397-Add-Player-Warden-Warning-API.patch similarity index 100% rename from patches/api/0409-Add-Player-Warden-Warning-API.patch rename to patches/api/0397-Add-Player-Warden-Warning-API.patch diff --git a/patches/api/0410-More-vanilla-friendly-methods-to-update-trades.patch b/patches/api/0398-More-vanilla-friendly-methods-to-update-trades.patch similarity index 100% rename from patches/api/0410-More-vanilla-friendly-methods-to-update-trades.patch rename to patches/api/0398-More-vanilla-friendly-methods-to-update-trades.patch diff --git a/patches/api/0411-Add-paper-dumplisteners-command.patch b/patches/api/0399-Add-paper-dumplisteners-command.patch similarity index 100% rename from patches/api/0411-Add-paper-dumplisteners-command.patch rename to patches/api/0399-Add-paper-dumplisteners-command.patch diff --git a/patches/api/0412-ItemStack-damage-API.patch b/patches/api/0400-ItemStack-damage-API.patch similarity index 100% rename from patches/api/0412-ItemStack-damage-API.patch rename to patches/api/0400-ItemStack-damage-API.patch diff --git a/patches/api/0413-Add-Tick-TemporalUnit.patch b/patches/api/0401-Add-Tick-TemporalUnit.patch similarity index 100% rename from patches/api/0413-Add-Tick-TemporalUnit.patch rename to patches/api/0401-Add-Tick-TemporalUnit.patch diff --git a/patches/api/0414-Friction-API.patch b/patches/api/0402-Friction-API.patch similarity index 96% rename from patches/api/0414-Friction-API.patch rename to patches/api/0402-Friction-API.patch index 8cff02f9c4..b2370553c0 100644 --- a/patches/api/0414-Friction-API.patch +++ b/patches/api/0402-Friction-API.patch @@ -59,7 +59,7 @@ index d0bef15785493b512ff0f7414c1d58d38fead581..58017fce436cdbda255f7172fbdadb72 /** * Gets the item stack associated with this item drop. diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java -index f6cbada38ca48638e5ad0bd99d0b6ea65f6b02de..97336be470a9d545d93f78e683a793f328013ad8 100644 +index 285b4028eb45439c052d6a2e9001a8c0bfacd49a..6555397148b84dba7a87cae505544b65452f1742 100644 --- a/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/src/main/java/org/bukkit/entity/LivingEntity.java @@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; diff --git a/patches/api/0415-Player-Entity-Tracking-Events.patch b/patches/api/0403-Player-Entity-Tracking-Events.patch similarity index 100% rename from patches/api/0415-Player-Entity-Tracking-Events.patch rename to patches/api/0403-Player-Entity-Tracking-Events.patch diff --git a/patches/api/0416-Add-missing-Fluid-type.patch b/patches/api/0404-Add-missing-Fluid-type.patch similarity index 100% rename from patches/api/0416-Add-missing-Fluid-type.patch rename to patches/api/0404-Add-missing-Fluid-type.patch diff --git a/patches/api/0418-Mark-experimental-api-as-such.patch b/patches/api/0405-Mark-experimental-api-as-such.patch similarity index 100% rename from patches/api/0418-Mark-experimental-api-as-such.patch rename to patches/api/0405-Mark-experimental-api-as-such.patch diff --git a/patches/api/0419-fix-Instruments.patch b/patches/api/0406-fix-Instruments.patch similarity index 98% rename from patches/api/0419-fix-Instruments.patch rename to patches/api/0406-fix-Instruments.patch index 701943942f..199e7067e4 100644 --- a/patches/api/0419-fix-Instruments.patch +++ b/patches/api/0406-fix-Instruments.patch @@ -105,7 +105,7 @@ index de976be7132d05506fde7a839cac3954b0dd8da4..27dafd1850d3b984a6af155f5c08ee54 public static Instrument getByType(final byte type) { return BY_DATA.get(type); diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 1e27b9de47f111b9c000243214e22890e323f7fc..19995314b01f19c312efa2a4584ccfba2d700c52 100644 +index 3a450af12df6c71e91eab34237dcbf870708f3c6..4d7089da20e0667fd7e67ef4da073d938e7b9a67 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -393,9 +393,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/api/0420-Add-BlockLockCheckEvent.patch b/patches/api/0407-Add-BlockLockCheckEvent.patch similarity index 100% rename from patches/api/0420-Add-BlockLockCheckEvent.patch rename to patches/api/0407-Add-BlockLockCheckEvent.patch diff --git a/patches/api/0421-Add-Sneaking-API-for-Entities.patch b/patches/api/0408-Add-Sneaking-API-for-Entities.patch similarity index 95% rename from patches/api/0421-Add-Sneaking-API-for-Entities.patch rename to patches/api/0408-Add-Sneaking-API-for-Entities.patch index 5e878c634d..601c064327 100644 --- a/patches/api/0421-Add-Sneaking-API-for-Entities.patch +++ b/patches/api/0408-Add-Sneaking-API-for-Entities.patch @@ -35,7 +35,7 @@ index 33a6b7a27dc91552799c07a7aad9b3df31ad13f7..cdbc7329cf5f67d66e31eb31e83b9e79 * Get the category of spawn to which this entity belongs. * diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 19995314b01f19c312efa2a4584ccfba2d700c52..9f762cf670bf5db9138e468e72e57781d8d22f54 100644 +index 4d7089da20e0667fd7e67ef4da073d938e7b9a67..b27d7414f34f1d49c56dbc33d6d23bc822adf721 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -296,6 +296,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/api/0422-Improve-PortalEvents.patch b/patches/api/0409-Improve-PortalEvents.patch similarity index 100% rename from patches/api/0422-Improve-PortalEvents.patch rename to patches/api/0409-Improve-PortalEvents.patch diff --git a/patches/api/0423-Add-exploded-block-state-to-BlockExplodeEvent.patch b/patches/api/0410-Add-exploded-block-state-to-BlockExplodeEvent.patch similarity index 100% rename from patches/api/0423-Add-exploded-block-state-to-BlockExplodeEvent.patch rename to patches/api/0410-Add-exploded-block-state-to-BlockExplodeEvent.patch diff --git a/patches/api/0424-Flying-Fall-Damage-API.patch b/patches/api/0411-Flying-Fall-Damage-API.patch similarity index 100% rename from patches/api/0424-Flying-Fall-Damage-API.patch rename to patches/api/0411-Flying-Fall-Damage-API.patch diff --git a/patches/api/0425-Expose-pre-collision-moving-velocity-to-VehicleBlock.patch b/patches/api/0412-Expose-pre-collision-moving-velocity-to-VehicleBlock.patch similarity index 100% rename from patches/api/0425-Expose-pre-collision-moving-velocity-to-VehicleBlock.patch rename to patches/api/0412-Expose-pre-collision-moving-velocity-to-VehicleBlock.patch diff --git a/patches/api/0426-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch b/patches/api/0413-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch similarity index 100% rename from patches/api/0426-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch rename to patches/api/0413-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch diff --git a/patches/api/0427-Add-Player-sendEquipmentChange-Map-API.patch b/patches/api/0414-Add-Player-sendEquipmentChange-Map-API.patch similarity index 100% rename from patches/api/0427-Add-Player-sendEquipmentChange-Map-API.patch rename to patches/api/0414-Add-Player-sendEquipmentChange-Map-API.patch diff --git a/patches/api/0428-Win-Screen-API.patch b/patches/api/0415-Win-Screen-API.patch similarity index 100% rename from patches/api/0428-Win-Screen-API.patch rename to patches/api/0415-Win-Screen-API.patch diff --git a/patches/api/0429-Add-Entity-Body-Yaw-API.patch b/patches/api/0416-Add-Entity-Body-Yaw-API.patch similarity index 100% rename from patches/api/0429-Add-Entity-Body-Yaw-API.patch rename to patches/api/0416-Add-Entity-Body-Yaw-API.patch diff --git a/patches/api/0430-Add-missing-isFuel-Material-entries.patch b/patches/api/0417-Add-missing-isFuel-Material-entries.patch similarity index 100% rename from patches/api/0430-Add-missing-isFuel-Material-entries.patch rename to patches/api/0417-Add-missing-isFuel-Material-entries.patch diff --git a/patches/api/0431-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch b/patches/api/0418-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch similarity index 100% rename from patches/api/0431-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch rename to patches/api/0418-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch diff --git a/patches/api/0018-Automatically-disable-plugins-that-fail-to-load.patch b/patches/removed/1.19.3-paper-plugins/api/0019-Automatically-disable-plugins-that-fail-to-load.patch similarity index 86% rename from patches/api/0018-Automatically-disable-plugins-that-fail-to-load.patch rename to patches/removed/1.19.3-paper-plugins/api/0019-Automatically-disable-plugins-that-fail-to-load.patch index 61b71bb093..51fb196a9b 100644 --- a/patches/api/0018-Automatically-disable-plugins-that-fail-to-load.patch +++ b/patches/removed/1.19.3-paper-plugins/api/0019-Automatically-disable-plugins-that-fail-to-load.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Automatically disable plugins that fail to load diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 333c47a1f7e9d7ddf91aad5ec15163427f7b8039..5eb24f38f158d43fb42836b83c108f808c89512e 100644 +index 88d852c1a729ffd5951da803da424b31591c9f9a..c95833aaeda48bbdad6e8f67f98e1070171db7de 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -335,6 +335,10 @@ public final class JavaPluginLoader implements PluginLoader { +@@ -337,6 +337,10 @@ public final class JavaPluginLoader implements PluginLoader { jPlugin.setEnabled(true); } catch (Throwable ex) { server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); diff --git a/patches/api/0067-Make-plugins-list-alphabetical.patch b/patches/removed/1.19.3-paper-plugins/api/0068-Make-plugins-list-alphabetical.patch similarity index 100% rename from patches/api/0067-Make-plugins-list-alphabetical.patch rename to patches/removed/1.19.3-paper-plugins/api/0068-Make-plugins-list-alphabetical.patch diff --git a/patches/api/0103-Close-Plugin-Class-Loaders-on-Disable.patch b/patches/removed/1.19.3-paper-plugins/api/0104-Close-Plugin-Class-Loaders-on-Disable.patch similarity index 84% rename from patches/api/0103-Close-Plugin-Class-Loaders-on-Disable.patch rename to patches/removed/1.19.3-paper-plugins/api/0104-Close-Plugin-Class-Loaders-on-Disable.patch index 834dc85486..cecc785a80 100644 --- a/patches/api/0103-Close-Plugin-Class-Loaders-on-Disable.patch +++ b/patches/removed/1.19.3-paper-plugins/api/0104-Close-Plugin-Class-Loaders-on-Disable.patch @@ -13,10 +13,10 @@ PluginClassLoader fails to disable, as upstream decided to ignore the exception. diff --git a/src/main/java/org/bukkit/plugin/PluginLoader.java b/src/main/java/org/bukkit/plugin/PluginLoader.java -index a88733f1cd1ddb5d85ab1b0e6af4fd5b80bbc1c6..256e440e699942e3c9da4205bb964bdc10ec92c4 100644 +index cb530369e667c426c842da356c31304bb5c3ecfa..a11515b81575fc42c771a218a81fea8f05d2289d 100644 --- a/src/main/java/org/bukkit/plugin/PluginLoader.java +++ b/src/main/java/org/bukkit/plugin/PluginLoader.java -@@ -77,4 +77,21 @@ public interface PluginLoader { +@@ -78,4 +78,21 @@ public interface PluginLoader { * @param plugin Plugin to disable */ public void disablePlugin(@NotNull Plugin plugin); @@ -39,10 +39,10 @@ index a88733f1cd1ddb5d85ab1b0e6af4fd5b80bbc1c6..256e440e699942e3c9da4205bb964bdc + // Paper end - close Classloader on disable } diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java -index 41e26451fe12d8e6e0ef73c85731b24b4e3f200c..0d1b20f2b5580ea5505ccc2f003925dbcee67199 100644 +index 03213fde8315384ec56c16031cfc606ade2e8091..94fef99525a3613dcc313a0d0b03e47a91d4117b 100644 --- a/src/main/java/org/bukkit/plugin/PluginManager.java +++ b/src/main/java/org/bukkit/plugin/PluginManager.java -@@ -161,6 +161,22 @@ public interface PluginManager { +@@ -162,6 +162,22 @@ public interface PluginManager extends io.papermc.paper.plugin.PermissionManager */ public void disablePlugin(@NotNull Plugin plugin); @@ -66,10 +66,10 @@ index 41e26451fe12d8e6e0ef73c85731b24b4e3f200c..0d1b20f2b5580ea5505ccc2f003925db * Gets a {@link Permission} from its fully qualified name * diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 77caec9f974077ed6580d3cbbc20feb1199feb11..9f32b57464352c08617f6adec144111b8fcad50c 100644 +index 2b8308989fce7f8a16907f8711b362e671fdbfb6..f96164a2bc4e042bdd7c6045a9b392ad4e4dbea7 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -504,6 +504,21 @@ public final class SimplePluginManager implements PluginManager { +@@ -532,6 +532,21 @@ public final class SimplePluginManager implements PluginManager { } } @@ -90,12 +90,12 @@ index 77caec9f974077ed6580d3cbbc20feb1199feb11..9f32b57464352c08617f6adec144111b + @Override public void disablePlugin(@NotNull final Plugin plugin) { - if (plugin.isEnabled()) { + if (true) {this.paperPluginManager.disablePlugin(plugin); return;} // Paper diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 5d74fab03a15d7099e5dacb780eade4cdc185797..032ed2aba7d47144d241d616ba27489ce22d6fea 100644 +index ac1c884e950ce13e9e7b3a7be1378808012fafc4..e0423adf45bf5855c23259257863f67cec1c3d54 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -366,6 +366,7 @@ public final class JavaPluginLoader implements PluginLoader { +@@ -368,6 +368,7 @@ public final class JavaPluginLoader implements PluginLoader { loader.close(); } catch (IOException ex) { // diff --git a/patches/api/0124-Add-an-asterisk-to-legacy-API-plugins.patch b/patches/removed/1.19.3-paper-plugins/api/0125-Add-an-asterisk-to-legacy-API-plugins.patch similarity index 95% rename from patches/api/0124-Add-an-asterisk-to-legacy-API-plugins.patch rename to patches/removed/1.19.3-paper-plugins/api/0125-Add-an-asterisk-to-legacy-API-plugins.patch index 7279975212..1dfa20b766 100644 --- a/patches/api/0124-Add-an-asterisk-to-legacy-API-plugins.patch +++ b/patches/removed/1.19.3-paper-plugins/api/0125-Add-an-asterisk-to-legacy-API-plugins.patch @@ -45,10 +45,10 @@ index 4de959bbd1270d7d6ea8e5e69521bcca6abe2138..1aa58c59e1e8738bbdc77752885ff3b1 if (plugin.getDescription().getProvides().size() > 0) { pluginList.append(" (").append(String.join(", ", plugin.getDescription().getProvides())).append(")"); diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 032ed2aba7d47144d241d616ba27489ce22d6fea..e98934d32b8dac88b3c3fd14ea5d726872212807 100644 +index e0423adf45bf5855c23259257863f67cec1c3d54..c0b9ed3a1e28c51d0195c53ec3d301dcdf58046f 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -306,7 +306,14 @@ public final class JavaPluginLoader implements PluginLoader { +@@ -308,7 +308,14 @@ public final class JavaPluginLoader implements PluginLoader { Preconditions.checkArgument(plugin instanceof JavaPlugin, "Plugin is not associated with this PluginLoader"); if (!plugin.isEnabled()) { diff --git a/patches/api/0134-Remove-deadlock-risk-in-firing-async-events.patch b/patches/removed/1.19.3-paper-plugins/api/0134-Remove-deadlock-risk-in-firing-async-events.patch similarity index 100% rename from patches/api/0134-Remove-deadlock-risk-in-firing-async-events.patch rename to patches/removed/1.19.3-paper-plugins/api/0134-Remove-deadlock-risk-in-firing-async-events.patch diff --git a/patches/api/0193-Disable-Sync-Events-firing-Async-errors-during-shutd.patch b/patches/removed/1.19.3-paper-plugins/api/0193-Disable-Sync-Events-firing-Async-errors-during-shutd.patch similarity index 100% rename from patches/api/0193-Disable-Sync-Events-firing-Async-errors-during-shutd.patch rename to patches/removed/1.19.3-paper-plugins/api/0193-Disable-Sync-Events-firing-Async-errors-during-shutd.patch diff --git a/patches/api/0194-Make-JavaPluginLoader-thread-safe.patch b/patches/removed/1.19.3-paper-plugins/api/0193-Make-JavaPluginLoader-thread-safe.patch similarity index 91% rename from patches/api/0194-Make-JavaPluginLoader-thread-safe.patch rename to patches/removed/1.19.3-paper-plugins/api/0193-Make-JavaPluginLoader-thread-safe.patch index 9afcec1657..80e221872b 100644 --- a/patches/api/0194-Make-JavaPluginLoader-thread-safe.patch +++ b/patches/removed/1.19.3-paper-plugins/api/0193-Make-JavaPluginLoader-thread-safe.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make JavaPluginLoader thread-safe diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index e98934d32b8dac88b3c3fd14ea5d726872212807..cf809eda2a3feb6abccf7286068280f430452135 100644 +index c0b9ed3a1e28c51d0195c53ec3d301dcdf58046f..e40224667f2abe48d709112f038904672fa8faf5 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -52,6 +52,8 @@ import org.yaml.snakeyaml.error.YAMLException; +@@ -53,6 +53,8 @@ import org.yaml.snakeyaml.error.YAMLException; public final class JavaPluginLoader implements PluginLoader { final Server server; private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; @@ -17,7 +17,7 @@ index e98934d32b8dac88b3c3fd14ea5d726872212807..cf809eda2a3feb6abccf7286068280f4 private final List loaders = new CopyOnWriteArrayList(); private final LibraryLoader libraryLoader; -@@ -201,12 +203,33 @@ public final class JavaPluginLoader implements PluginLoader { +@@ -203,12 +205,33 @@ public final class JavaPluginLoader implements PluginLoader { @Nullable Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description) { diff --git a/patches/api/0205-Prioritise-own-classes-where-possible.patch b/patches/removed/1.19.3-paper-plugins/api/0204-Prioritise-own-classes-where-possible.patch similarity index 79% rename from patches/api/0205-Prioritise-own-classes-where-possible.patch rename to patches/removed/1.19.3-paper-plugins/api/0204-Prioritise-own-classes-where-possible.patch index 948e2f95fa..a2ad52282f 100644 --- a/patches/api/0205-Prioritise-own-classes-where-possible.patch +++ b/patches/removed/1.19.3-paper-plugins/api/0204-Prioritise-own-classes-where-possible.patch @@ -25,18 +25,18 @@ The patch in general terms just loads the class in the plugin's jar before it starts looking elsewhere for it. diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index cf809eda2a3feb6abccf7286068280f430452135..4b54af83ef8fd18696d2d21ed52b61f13bff7988 100644 +index e40224667f2abe48d709112f038904672fa8faf5..84ae5b84a75baca4e12221e300006bb209f8671e 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -@@ -51,6 +51,7 @@ import org.yaml.snakeyaml.error.YAMLException; - */ +@@ -52,6 +52,7 @@ import org.yaml.snakeyaml.error.YAMLException; + @Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future. This implementation will be moved. public final class JavaPluginLoader implements PluginLoader { final Server server; + private static final boolean DISABLE_CLASS_PRIORITIZATION = Boolean.getBoolean("Paper.DisableClassPrioritization"); // Paper private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")}; private final Map classLoadLock = new java.util.HashMap(); // Paper private final Map classLoadLockCount = new java.util.HashMap(); // Paper -@@ -203,6 +204,11 @@ public final class JavaPluginLoader implements PluginLoader { +@@ -205,6 +206,11 @@ public final class JavaPluginLoader implements PluginLoader { @Nullable Class getClassByName(final String name, boolean resolve, PluginDescriptionFile description) { @@ -48,7 +48,7 @@ index cf809eda2a3feb6abccf7286068280f430452135..4b54af83ef8fd18696d2d21ed52b61f1 // Paper start - make MT safe java.util.concurrent.locks.ReentrantReadWriteLock lock; synchronized (classLoadLock) { -@@ -210,6 +216,13 @@ public final class JavaPluginLoader implements PluginLoader { +@@ -212,6 +218,13 @@ public final class JavaPluginLoader implements PluginLoader { classLoadLockCount.compute(name, (x, prev) -> prev != null ? prev + 1 : 1); } lock.writeLock().lock();try { @@ -63,10 +63,10 @@ index cf809eda2a3feb6abccf7286068280f430452135..4b54af83ef8fd18696d2d21ed52b61f1 for (PluginClassLoader loader : loaders) { try { diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index 0db641f5d5e1293b236ad0d2e3a156802ffed839..064c758b19bc8c9a4e94769dd205a1bdcc972a89 100644 +index ac62ad546dacfefd686bb824f60f4523631f7abc..3306c2e81ac66d649e3988aa1c142fb9fb7236fc 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -33,7 +33,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot +@@ -33,7 +33,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm public JavaPlugin getPlugin() { return plugin; } // Spigot private final JavaPluginLoader loader; private final Map> classes = new ConcurrentHashMap>(); @@ -75,12 +75,3 @@ index 0db641f5d5e1293b236ad0d2e3a156802ffed839..064c758b19bc8c9a4e94769dd205a1bd private final File dataFolder; private final File file; private final JarFile jar; -@@ -123,7 +123,7 @@ public final class PluginClassLoader extends URLClassLoader { // Spigot - - if (checkGlobal) { - // This ignores the libraries of other plugins, unless they are transitive dependencies. -- Class result = loader.getClassByName(name, resolve, description); -+ Class result = loader.getClassByName(name, resolve, description, this); // Paper - prioritize self - - if (result != null) { - // If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check. diff --git a/patches/api/0206-Provide-a-useful-PluginClassLoader-toString.patch b/patches/removed/1.19.3-paper-plugins/api/0206-Provide-a-useful-PluginClassLoader-toString.patch similarity index 100% rename from patches/api/0206-Provide-a-useful-PluginClassLoader-toString.patch rename to patches/removed/1.19.3-paper-plugins/api/0206-Provide-a-useful-PluginClassLoader-toString.patch diff --git a/patches/api/0299-List-all-missing-hard-depends-not-just-first.patch b/patches/removed/1.19.3-paper-plugins/api/0299-List-all-missing-hard-depends-not-just-first.patch similarity index 100% rename from patches/api/0299-List-all-missing-hard-depends-not-just-first.patch rename to patches/removed/1.19.3-paper-plugins/api/0299-List-all-missing-hard-depends-not-just-first.patch diff --git a/patches/api/0327-Fix-plugin-provides-load-order.patch b/patches/removed/1.19.3-paper-plugins/api/0318-Fix-plugin-provides-load-order.patch similarity index 79% rename from patches/api/0327-Fix-plugin-provides-load-order.patch rename to patches/removed/1.19.3-paper-plugins/api/0318-Fix-plugin-provides-load-order.patch index 74b275da11..948a872c64 100644 --- a/patches/api/0327-Fix-plugin-provides-load-order.patch +++ b/patches/removed/1.19.3-paper-plugins/api/0318-Fix-plugin-provides-load-order.patch @@ -6,18 +6,18 @@ Subject: [PATCH] Fix plugin provides load order Fixes https://hub.spigotmc.org/jira/browse/SPIGOT-6740 diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 60988665eb358d5566e9de61aec841db3f79722c..d1c1df75c011d8b4e10342c864aeb206e5cac23f 100644 +index 2b8308989fce7f8a16907f8711b362e671fdbfb6..758faf990ba96cbcd0203e9184bcad234b4cb728 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -277,6 +277,7 @@ public final class SimplePluginManager implements PluginManager { - // Paper end +@@ -283,6 +283,7 @@ public final class SimplePluginManager implements PluginManager { + } else if (!plugins.containsKey(dependency) && !pluginsProvided.containsKey(dependency)) { missingDependency = false; pluginIterator.remove(); + pluginsProvided.values().removeIf(s -> s.equals(plugin)); // Paper - remove provided plugins softDependencies.remove(plugin); dependencies.remove(plugin); -@@ -310,6 +311,7 @@ public final class SimplePluginManager implements PluginManager { +@@ -318,6 +319,7 @@ public final class SimplePluginManager implements PluginManager { // We're clear to load, no more soft or hard dependencies left File file = plugins.get(plugin); pluginIterator.remove(); diff --git a/patches/api/0364-Don-t-load-plugins-prefixed-with-a-dot.patch b/patches/removed/1.19.3-paper-plugins/api/0364-Don-t-load-plugins-prefixed-with-a-dot.patch similarity index 100% rename from patches/api/0364-Don-t-load-plugins-prefixed-with-a-dot.patch rename to patches/removed/1.19.3-paper-plugins/api/0364-Don-t-load-plugins-prefixed-with-a-dot.patch diff --git a/patches/api/0377-Update-Folder-Uses-Plugin-Name.patch b/patches/removed/1.19.3-paper-plugins/api/0367-Update-Folder-Uses-Plugin-Name.patch similarity index 89% rename from patches/api/0377-Update-Folder-Uses-Plugin-Name.patch rename to patches/removed/1.19.3-paper-plugins/api/0367-Update-Folder-Uses-Plugin-Name.patch index a5c98762cf..823069413c 100644 --- a/patches/api/0377-Update-Folder-Uses-Plugin-Name.patch +++ b/patches/removed/1.19.3-paper-plugins/api/0367-Update-Folder-Uses-Plugin-Name.patch @@ -5,19 +5,19 @@ Subject: [PATCH] Update Folder Uses Plugin Name diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 94646b37c77fcb18fc4030306c431684e7e9a5cc..9db611841b73fed8dc8a71f4d7fdef95af3cf89d 100644 +index 758faf990ba96cbcd0203e9184bcad234b4cb728..fb19ab3bd929045b4d3e227ed961a24b16b8b2bd 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -396,7 +396,7 @@ public final class SimplePluginManager implements PluginManager { - public synchronized Plugin loadPlugin(@NotNull File file) throws InvalidPluginException, UnknownDependencyException { - Preconditions.checkArgument(file != null, "File cannot be null"); +@@ -412,7 +412,7 @@ public final class SimplePluginManager implements PluginManager { + } + // Paper end - checkUpdate(file); + file = checkUpdate(file); // Paper - update the reference in case checkUpdate renamed it Set filters = fileAssociations.keySet(); Plugin result = null; -@@ -423,16 +423,61 @@ public final class SimplePluginManager implements PluginManager { +@@ -439,16 +439,61 @@ public final class SimplePluginManager implements PluginManager { return result; } @@ -32,7 +32,7 @@ index 94646b37c77fcb18fc4030306c431684e7e9a5cc..9db611841b73fed8dc8a71f4d7fdef95 if (updateDirectory == null || !updateDirectory.isDirectory()) { - return; + return file; -+ } + } + PluginLoader pluginLoader = getPluginLoader(file); + try { + String pluginName = pluginLoader.getPluginDescription(file).getName(); @@ -59,7 +59,7 @@ index 94646b37c77fcb18fc4030306c431684e7e9a5cc..9db611841b73fed8dc8a71f4d7fdef95 + updateFile.delete(); + return newName; + } - } ++ } + catch (InvalidDescriptionException e) { + throw new InvalidPluginException(e); + } diff --git a/patches/api/0417-Future-API-Plans.patch b/patches/removed/1.19.3-paper-plugins/api/0413-Future-API-Plans.patch similarity index 67% rename from patches/api/0417-Future-API-Plans.patch rename to patches/removed/1.19.3-paper-plugins/api/0413-Future-API-Plans.patch index 9209318a74..7afa310be8 100644 --- a/patches/api/0417-Future-API-Plans.patch +++ b/patches/removed/1.19.3-paper-plugins/api/0413-Future-API-Plans.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Future API Plans diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java -index 08aef59d8443038771704d9587e31f299e587307..cdf496598839380e073d7ccd89af473e9a702f00 100644 +index 8245de7dbf63a01336b8e291b0a3dd5e71ccd349..4eb639fbb46a0848be207149ea433455550fae1c 100644 --- a/src/main/java/org/bukkit/plugin/Plugin.java +++ b/src/main/java/org/bukkit/plugin/Plugin.java -@@ -94,6 +94,7 @@ public interface Plugin extends TabExecutor { +@@ -105,6 +105,7 @@ public interface Plugin extends TabExecutor { * * @return PluginLoader that controls this plugin */ @@ -29,10 +29,10 @@ index 256e440e699942e3c9da4205bb964bdc10ec92c4..a11515b81575fc42c771a218a81fea8f /** diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java -index 0d1b20f2b5580ea5505ccc2f003925dbcee67199..efc04803a1eab01053a1f003d6feb2b712165d69 100644 +index e3460b19f3d2c27d7a9c3477467739221211f1d4..94fef99525a3613dcc313a0d0b03e47a91d4117b 100644 --- a/src/main/java/org/bukkit/plugin/PluginManager.java +++ b/src/main/java/org/bukkit/plugin/PluginManager.java -@@ -23,6 +23,7 @@ public interface PluginManager { +@@ -23,6 +23,7 @@ public interface PluginManager extends io.papermc.paper.plugin.PermissionManager * @throws IllegalArgumentException Thrown when the given Class is not a * valid PluginLoader */ @@ -40,21 +40,8 @@ index 0d1b20f2b5580ea5505ccc2f003925dbcee67199..efc04803a1eab01053a1f003d6feb2b7 public void registerInterface(@NotNull Class loader) throws IllegalArgumentException; /** -diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -index 9db611841b73fed8dc8a71f4d7fdef95af3cf89d..b012ce40d82389c29d1b841ff685425ac10a7f9e 100644 ---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java -+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java -@@ -43,6 +43,8 @@ import org.jetbrains.annotations.Nullable; - /** - * Handles all plugin management from the Server - */ -+@Deprecated(forRemoval = true) // Paper - This implementation may be replaced in a future version of Paper. -+// Plugins may still reflect into this class to modify permission logic for the time being. - public final class SimplePluginManager implements PluginManager { - private final Server server; - private final Map fileAssociations = new HashMap(); diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java -index 8ff78fad47f6086aa289e32590f4fbec24b3d500..7e5149a21b6747f64425a277c142e69f0ef43b3f 100644 +index d104aa3c45bd65b3c6a521ef1ed249fb4e9de053..84ae5b84a75baca4e12221e300006bb209f8671e 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java @@ -49,6 +49,7 @@ import org.yaml.snakeyaml.error.YAMLException; diff --git a/patches/server/0222-Add-CraftMagicNumbers.isSupportedApiVersion.patch b/patches/removed/1.19.3-paper-plugins/server/0223-Add-CraftMagicNumbers.isSupportedApiVersion.patch similarity index 100% rename from patches/server/0222-Add-CraftMagicNumbers.isSupportedApiVersion.patch rename to patches/removed/1.19.3-paper-plugins/server/0223-Add-CraftMagicNumbers.isSupportedApiVersion.patch diff --git a/patches/server/0013-Paper-Plugins.patch b/patches/server/0013-Paper-Plugins.patch new file mode 100644 index 0000000000..ef5d353ddd --- /dev/null +++ b/patches/server/0013-Paper-Plugins.patch @@ -0,0 +1,6780 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> +Date: Wed, 6 Jul 2022 23:00:31 -0400 +Subject: [PATCH] Paper Plugins + + +diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java +index b3a58bf4b654e336826dc04da9e2f80ff8b9a9a7..156334e3876d966fedc91d18da29f562395ab182 100644 +--- a/src/main/java/io/papermc/paper/command/PaperCommand.java ++++ b/src/main/java/io/papermc/paper/command/PaperCommand.java +@@ -4,6 +4,7 @@ import io.papermc.paper.command.subcommands.EntityCommand; + import io.papermc.paper.command.subcommands.HeapDumpCommand; + import io.papermc.paper.command.subcommands.ReloadCommand; + import io.papermc.paper.command.subcommands.VersionCommand; ++import io.papermc.paper.command.subcommands.DumpPluginsCommand; + import it.unimi.dsi.fastutil.Pair; + import java.util.ArrayList; + import java.util.Arrays; +@@ -40,6 +41,7 @@ public final class PaperCommand extends Command { + commands.put(Set.of("entity"), new EntityCommand()); + commands.put(Set.of("reload"), new ReloadCommand()); + commands.put(Set.of("version"), new VersionCommand()); ++ commands.put(Set.of("dumpplugins"), new DumpPluginsCommand()); + + return commands.entrySet().stream() + .flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue()))) +diff --git a/src/main/java/io/papermc/paper/command/PaperCommands.java b/src/main/java/io/papermc/paper/command/PaperCommands.java +index 6a00f3d38da8107825ab1d405f337fd077b09f72..d44d0074446c1c54e87dc8078dff7fef1d92f343 100644 +--- a/src/main/java/io/papermc/paper/command/PaperCommands.java ++++ b/src/main/java/io/papermc/paper/command/PaperCommands.java +@@ -23,5 +23,6 @@ public final class PaperCommands { + COMMANDS.forEach((s, command) -> { + server.server.getCommandMap().register(s, "Paper", command); + }); ++ server.server.getCommandMap().register("bukkit", new PaperPluginsCommand()); + } + } +diff --git a/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..72096a66a4046633de73a12f5a043ac6dff169b1 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/command/PaperPluginsCommand.java +@@ -0,0 +1,207 @@ ++package io.papermc.paper.command; ++ ++import com.google.common.collect.Lists; ++import io.leangen.geantyref.GenericTypeReflector; ++import io.leangen.geantyref.TypeToken; ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.entrypoint.Entrypoint; ++import io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.ProviderStatus; ++import io.papermc.paper.plugin.provider.ProviderStatusHolder; ++import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent; ++import io.papermc.paper.plugin.provider.type.spigot.SpigotPluginProvider; ++import net.kyori.adventure.text.Component; ++import net.kyori.adventure.text.JoinConfiguration; ++import net.kyori.adventure.text.TextComponent; ++import net.kyori.adventure.text.event.ClickEvent; ++import net.kyori.adventure.text.format.NamedTextColor; ++import net.kyori.adventure.text.format.TextColor; ++import org.bukkit.Bukkit; ++import org.bukkit.command.CommandSender; ++import org.bukkit.command.defaults.BukkitCommand; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.NotNull; ++ ++import java.lang.reflect.Type; ++import java.util.ArrayList; ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.List; ++import java.util.TreeMap; ++ ++public class PaperPluginsCommand extends BukkitCommand { ++ ++ private static final TextColor INFO_COLOR = TextColor.color(52, 159, 218); ++ ++ // TODO: LINK? ++ private static final Component SERVER_PLUGIN_INFO = Component.text("ℹ What is a server plugin?", INFO_COLOR) ++ .append(asPlainComponents(""" ++ Server plugins can add new behavior to your server! ++ You can find new plugins on Paper's plugin repository, Hangar. ++ ++ ++ """)); ++ ++ private static final Component SERVER_INITIALIZER_INFO = Component.text("ℹ What is a server initializer?", INFO_COLOR) ++ .append(asPlainComponents(""" ++ Server initializers are ran before your server ++ starts and are provided by paper plugins. ++ """)); ++ ++ private static final Component LEGACY_PLUGIN_INFO = Component.text("ℹ What is a legacy plugin?", INFO_COLOR) ++ .append(asPlainComponents(""" ++ A legacy plugin is a plugin that was made on ++ very old unsupported versions of the game. ++ ++ It is encouraged that you replace this plugin, ++ as they might not work in the future and may cause ++ performance issues. ++ """)); ++ ++ private static final Component LEGACY_PLUGIN_STAR = Component.text('*', TextColor.color(255, 212, 42)).hoverEvent(LEGACY_PLUGIN_INFO); ++ private static final Component INFO_ICON_START = Component.text("ℹ ", INFO_COLOR); ++ private static final Component PAPER_HEADER = Component.text("Paper Plugins:", TextColor.color(2, 136, 209)); ++ private static final Component BUKKIT_HEADER = Component.text("Bukkit Plugins:", TextColor.color(237, 129, 6)); ++ private static final Component PLUGIN_TICK = Component.text("- ", NamedTextColor.DARK_GRAY); ++ private static final Component PLUGIN_TICK_EMPTY = Component.text(" "); ++ ++ private static final Type JAVA_PLUGIN_PROVIDER_TYPE = new TypeToken>() {}.getType(); ++ ++ public PaperPluginsCommand() { ++ super("plugins"); ++ this.description = "Gets a list of plugins running on the server"; ++ this.usageMessage = "/plugins"; ++ this.setPermission("bukkit.command.plugins"); ++ this.setAliases(Arrays.asList("pl")); ++ } ++ ++ private static List formatProviders(TreeMap> plugins) { ++ List components = new ArrayList<>(plugins.size()); ++ for (PluginProvider entry : plugins.values()) { ++ components.add(formatProvider(entry)); ++ } ++ ++ boolean isFirst = true; ++ List formattedSublists = new ArrayList<>(); ++ /* ++ Split up the plugin list for each 10 plugins to get size down ++ ++ Plugin List: ++ - Plugin 1, Plugin 2, .... Plugin 10, ++ Plugin 11, Plugin 12 ... Plugin 20, ++ */ ++ for (List componentSublist : Lists.partition(components, 10)) { ++ Component component = Component.space(); ++ if (isFirst) { ++ component = component.append(PLUGIN_TICK); ++ isFirst = false; ++ } else { ++ component = PLUGIN_TICK_EMPTY; ++ //formattedSublists.add(Component.empty()); // Add an empty line, the auto chat wrapping and this makes it quite jarring. ++ } ++ ++ formattedSublists.add(component.append(Component.join(JoinConfiguration.commas(true), componentSublist))); ++ } ++ ++ return formattedSublists; ++ } ++ ++ private static Component formatProvider(PluginProvider provider) { ++ TextComponent.Builder builder = Component.text(); ++ if (provider instanceof SpigotPluginProvider spigotPluginProvider && CraftMagicNumbers.isLegacy(spigotPluginProvider.getMeta())) { ++ builder.append(LEGACY_PLUGIN_STAR); ++ } ++ ++ String name = provider.getMeta().getName(); ++ Component pluginName = Component.text(name, fromStatus(provider)) ++ .clickEvent(ClickEvent.runCommand("/version " + name)); ++ ++ builder.append(pluginName); ++ ++ return builder.build(); ++ } ++ ++ private static Component asPlainComponents(String strings) { ++ net.kyori.adventure.text.TextComponent.Builder builder = Component.text(); ++ for (String string : strings.split("\n")) { ++ builder.append(Component.newline()); ++ builder.append(Component.text(string, NamedTextColor.WHITE)); ++ } ++ ++ return builder.build(); ++ } ++ ++ private static TextColor fromStatus(PluginProvider provider) { ++ if (provider instanceof ProviderStatusHolder statusHolder && statusHolder.getLastProvidedStatus() != null) { ++ ProviderStatus status = statusHolder.getLastProvidedStatus(); ++ ++ // Handle enabled/disabled game plugins ++ if (status == ProviderStatus.INITIALIZED && GenericTypeReflector.isSuperType(JAVA_PLUGIN_PROVIDER_TYPE, provider.getClass())) { ++ Plugin plugin = Bukkit.getPluginManager().getPlugin(provider.getMeta().getName()); ++ // Plugin doesn't exist? Could be due to it being removed. ++ if (plugin == null) { ++ return NamedTextColor.RED; ++ } ++ ++ return plugin.isEnabled() ? NamedTextColor.GREEN : NamedTextColor.RED; ++ } ++ ++ return switch (status) { ++ case INITIALIZED -> NamedTextColor.GREEN; ++ case ERRORED -> NamedTextColor.RED; ++ }; ++ } else if (provider instanceof PaperPluginParent.PaperServerPluginProvider serverPluginProvider && serverPluginProvider.shouldSkipCreation()) { ++ // Paper plugins will be skipped if their provider is skipped due to their initializer failing. ++ // Show them as red ++ return NamedTextColor.RED; ++ } else { ++ // Separated for future logic choice, but this indicated a provider that failed to load due to ++ // dependency issues or what not. ++ return NamedTextColor.RED; ++ } ++ } ++ ++ @Override ++ public boolean execute(@NotNull CommandSender sender, @NotNull String currentAlias, @NotNull String[] args) { ++ if (!this.testPermission(sender)) return true; ++ ++ TreeMap> paperPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); ++ TreeMap> spigotPlugins = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); ++ ++ ++ for (PluginProvider provider : LaunchEntryPointHandler.INSTANCE.get(Entrypoint.PLUGIN).getRegisteredProviders()) { ++ PluginMeta configuration = provider.getMeta(); ++ ++ if (provider instanceof SpigotPluginProvider) { ++ spigotPlugins.put(configuration.getDisplayName(), provider); ++ } else if (provider instanceof PaperPluginParent.PaperServerPluginProvider) { ++ paperPlugins.put(configuration.getDisplayName(), provider); ++ } ++ } ++ ++ Component infoMessage = Component.text("Server Plugins (%s):".formatted(paperPlugins.size() + spigotPlugins.size()), NamedTextColor.WHITE); ++ //.append(INFO_ICON_START.hoverEvent(SERVER_PLUGIN_INFO)); TODO: Add docs ++ ++ sender.sendMessage(infoMessage); ++ sender.sendMessage(PAPER_HEADER); ++ for (Component component : formatProviders(paperPlugins)) { ++ sender.sendMessage(component); ++ } ++ sender.sendMessage(BUKKIT_HEADER); ++ for (Component component : formatProviders(spigotPlugins)) { ++ sender.sendMessage(component); ++ } ++ ++ return true; ++ } ++ ++ @NotNull ++ @Override ++ public List tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { ++ return Collections.emptyList(); ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java b/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java +new file mode 100644 +index 0000000000000000000000000000000000000000..254854646b748e5bb47657625315ced51b22887f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java +@@ -0,0 +1,201 @@ ++package io.papermc.paper.command.subcommands; ++ ++import com.google.gson.JsonArray; ++import com.google.gson.JsonElement; ++import com.google.gson.JsonObject; ++import com.google.gson.JsonPrimitive; ++import com.google.gson.internal.Streams; ++import com.google.gson.stream.JsonWriter; ++import io.papermc.paper.command.PaperSubcommand; ++import io.papermc.paper.plugin.entrypoint.Entrypoint; ++import io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler; ++import io.papermc.paper.plugin.entrypoint.classloader.group.LockingClassLoaderGroup; ++import io.papermc.paper.plugin.entrypoint.classloader.group.PaperPluginClassLoaderStorage; ++import io.papermc.paper.plugin.entrypoint.classloader.group.SimpleListPluginClassLoaderGroup; ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++import io.papermc.paper.plugin.entrypoint.strategy.ModernPluginLoadingStrategy; ++import io.papermc.paper.plugin.entrypoint.strategy.ProviderConfiguration; ++import io.papermc.paper.plugin.manager.PaperPluginManagerImpl; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; ++import io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage; ++import io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup; ++import io.papermc.paper.plugin.storage.ConfiguredProviderStorage; ++import io.papermc.paper.plugin.storage.ProviderStorage; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.command.CommandSender; ++import org.bukkit.plugin.Plugin; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.framework.qual.DefaultQualifier; ++ ++import java.io.PrintStream; ++import java.io.StringWriter; ++import java.nio.charset.StandardCharsets; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.time.LocalDateTime; ++import java.time.format.DateTimeFormatter; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++ ++import static net.kyori.adventure.text.Component.text; ++import static net.kyori.adventure.text.format.NamedTextColor.GREEN; ++import static net.kyori.adventure.text.format.NamedTextColor.RED; ++ ++@DefaultQualifier(NonNull.class) ++public final class DumpPluginsCommand implements PaperSubcommand { ++ @Override ++ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { ++ this.dumpPlugins(sender, args); ++ return true; ++ } ++ ++ private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss"); ++ ++ private void dumpPlugins(final CommandSender sender, final String[] args) { ++ Path parent = Path.of("debug"); ++ Path path = parent.resolve("plugin-info" + FORMATTER.format(LocalDateTime.now()) + ".txt"); ++ try { ++ Files.createDirectories(parent); ++ Files.createFile(path); ++ sender.sendMessage(text("Writing plugin information to " + path, GREEN)); ++ ++ final JsonObject data = this.writeDebug(); ++ ++ StringWriter stringWriter = new StringWriter(); ++ JsonWriter jsonWriter = new JsonWriter(stringWriter); ++ jsonWriter.setIndent(" "); ++ jsonWriter.setLenient(false); ++ Streams.write(data, jsonWriter); ++ ++ try (PrintStream out = new PrintStream(Files.newOutputStream(path), false, StandardCharsets.UTF_8)) { ++ out.print(stringWriter); ++ } ++ sender.sendMessage(text("Successfully written plugin debug information!", GREEN)); ++ } catch (Throwable e) { ++ sender.sendMessage(text("Failed to write plugin information! See the console for more info.", RED)); ++ MinecraftServer.LOGGER.warn("Error occurred while dumping plugin info", e); ++ } ++ } ++ ++ private JsonObject writeDebug() { ++ JsonObject root = new JsonObject(); ++ if (ConfiguredProviderStorage.LEGACY_PLUGIN_LOADING) { ++ root.addProperty("legacy-loading-strategy", true); ++ } ++ ++ this.writeProviders(root); ++ this.writePlugins(root); ++ this.writeClassloaders(root); ++ ++ return root; ++ } ++ ++ private void writeProviders(JsonObject root) { ++ JsonObject rootProviders = new JsonObject(); ++ root.add("providers", rootProviders); ++ ++ for (Map.Entry, ProviderStorage> entry : LaunchEntryPointHandler.INSTANCE.getStorage().entrySet()) { ++ JsonObject entrypoint = new JsonObject(); ++ ++ JsonArray providers = new JsonArray(); ++ entrypoint.add("providers", providers); ++ ++ List> pluginProviders = new ArrayList<>(); ++ for (PluginProvider provider : entry.getValue().getRegisteredProviders()) { ++ JsonObject providerObj = new JsonObject(); ++ providerObj.addProperty("name", provider.getMeta().getName()); ++ providerObj.addProperty("version", provider.getMeta().getVersion()); ++ providerObj.addProperty("dependencies", provider.getMeta().getPluginDependencies().toString()); ++ providerObj.addProperty("soft-dependencies", provider.getMeta().getPluginSoftDependencies().toString()); ++ providerObj.addProperty("load-before", provider.getMeta().getLoadBeforePlugins().toString()); ++ ++ ++ providers.add(providerObj); ++ pluginProviders.add((PluginProvider) provider); ++ } ++ ++ JsonArray loadOrder = new JsonArray(); ++ entrypoint.add("load-order", loadOrder); ++ ++ ModernPluginLoadingStrategy modernPluginLoadingStrategy = new ModernPluginLoadingStrategy<>(new ProviderConfiguration<>() { ++ @Override ++ public void applyContext(PluginProvider provider, DependencyContext dependencyContext) { ++ } ++ ++ @Override ++ public boolean load(PluginProvider provider, Object provided) { ++ loadOrder.add(provider.getMeta().getName()); ++ return false; ++ } ++ ++ @Override ++ public List requiredDependencies(PluginProvider provider) { ++ return provider.getMeta().getPluginDependencies(); ++ } ++ ++ @Override ++ public List optionalDependencies(PluginProvider provider) { ++ return provider.getMeta().getPluginSoftDependencies(); ++ } ++ ++ @Override ++ public List loadBeforeDependencies(PluginProvider provider) { ++ return provider.getMeta().getLoadBeforePlugins(); ++ } ++ }); ++ modernPluginLoadingStrategy.loadProviders(pluginProviders); ++ ++ rootProviders.add(entry.getKey().getDebugName(), entrypoint); ++ } ++ } ++ ++ private void writePlugins(JsonObject root) { ++ JsonArray rootPlugins = new JsonArray(); ++ root.add("plugins", rootPlugins); ++ ++ for (Plugin plugin : PaperPluginManagerImpl.getInstance().getPlugins()) { ++ rootPlugins.add(plugin.toString()); ++ } ++ } ++ ++ private void writeClassloaders(JsonObject root) { ++ JsonObject classLoadersRoot = new JsonObject(); ++ root.add("classloaders", classLoadersRoot); ++ ++ PaperPluginClassLoaderStorage storage = (PaperPluginClassLoaderStorage) PaperClassLoaderStorage.instance(); ++ classLoadersRoot.addProperty("global", storage.getGlobalGroup().toString()); ++ classLoadersRoot.addProperty("dependency_graph", PaperPluginManagerImpl.getInstance().getInstanceManagerGraph().toString()); ++ ++ JsonArray array = new JsonArray(); ++ classLoadersRoot.add("children", array); ++ for (PluginClassLoaderGroup group : storage.getGroups()) { ++ array.add(this.writeClassloader(group)); ++ } ++ } ++ ++ private JsonObject writeClassloader(PluginClassLoaderGroup group) { ++ JsonObject classLoadersRoot = new JsonObject(); ++ if (group instanceof SimpleListPluginClassLoaderGroup listGroup) { ++ JsonArray array = new JsonArray(); ++ classLoadersRoot.addProperty("main", listGroup.toString()); ++ classLoadersRoot.add("children", array); ++ for (ConfiguredPluginClassLoader innerGroup : listGroup.getClassLoaders()) { ++ array.add(this.writeClassloader(innerGroup)); ++ } ++ ++ } else if (group instanceof LockingClassLoaderGroup locking) { ++ // Unwrap ++ return this.writeClassloader(locking.getParent()); ++ } else { ++ classLoadersRoot.addProperty("raw", group.toString()); ++ } ++ ++ return classLoadersRoot; ++ } ++ ++ private JsonElement writeClassloader(ConfiguredPluginClassLoader innerGroup) { ++ return new JsonPrimitive(innerGroup.toString()); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java b/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..39e503f52684e928c61c6d27bf61727a4721739c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java +@@ -0,0 +1,45 @@ ++package io.papermc.paper.plugin; ++ ++import com.mojang.logging.LogUtils; ++import joptsimple.OptionSet; ++import org.bukkit.configuration.file.YamlConfiguration; ++import org.jetbrains.annotations.NotNull; ++import org.slf4j.Logger; ++ ++import java.io.File; ++import java.nio.file.Path; ++ ++public class PluginInitializerManager { ++ ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ private static PluginInitializerManager impl; ++ private final Path pluginDirectory; ++ private final Path updateDirectory; ++ ++ PluginInitializerManager(@NotNull OptionSet minecraftOptionSet) { ++ // We have to load the bukkit configuration inorder to get the update folder location. ++ File configFileLocationBukkit = (File) minecraftOptionSet.valueOf("bukkit-settings"); ++ this.pluginDirectory = ((File) minecraftOptionSet.valueOf("plugins")).toPath(); ++ this.updateDirectory = this.pluginDirectory.resolve(YamlConfiguration.loadConfiguration(configFileLocationBukkit).getString("settings.update-folder", "update")); ++ } ++ ++ public static PluginInitializerManager init(OptionSet optionSet) { ++ impl = new PluginInitializerManager(optionSet); ++ return impl; ++ } ++ ++ public static PluginInitializerManager instance() { ++ return impl; ++ } ++ ++ @NotNull ++ public Path pluginDirectoryPath() { ++ return pluginDirectory; ++ } ++ ++ @NotNull ++ public Path pluginUpdatePath() { ++ return updateDirectory; ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContextImpl.java b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContextImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8249a7024537fccd99735b92abb1368e6647b5ae +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/bootstrap/PluginProviderContextImpl.java +@@ -0,0 +1,40 @@ ++package io.papermc.paper.plugin.bootstrap; ++ ++import io.papermc.paper.plugin.PluginInitializerManager; ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import org.jetbrains.annotations.NotNull; ++ ++import java.nio.file.Path; ++import java.util.logging.Logger; ++ ++public record PluginProviderContextImpl(PluginMeta config, Path dataFolder, ++ Logger logger) implements PluginProviderContext { ++ ++ public static PluginProviderContextImpl of(PluginMeta config, Logger logger) { ++ Path dataFolder = PluginInitializerManager.instance().pluginDirectoryPath().resolve(config.getDisplayName()); ++ ++ return new PluginProviderContextImpl(config, dataFolder, logger); ++ } ++ ++ public static PluginProviderContextImpl of(PluginProvider provider, Path pluginFolder) { ++ Path dataFolder = pluginFolder.resolve(provider.getMeta().getDisplayName()); ++ ++ return new PluginProviderContextImpl(provider.getMeta(), dataFolder, provider.getLogger()); ++ } ++ ++ @Override ++ public @NotNull PluginMeta getConfiguration() { ++ return this.config; ++ } ++ ++ @Override ++ public @NotNull Path getDataDirectory() { ++ return this.dataFolder; ++ } ++ ++ @Override ++ public @NotNull Logger getLogger() { ++ return this.logger; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/Entrypoint.java b/src/main/java/io/papermc/paper/plugin/entrypoint/Entrypoint.java +new file mode 100644 +index 0000000000000000000000000000000000000000..125008ac7db8b9f3fb57c49f8e4facc4ad4bb136 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/Entrypoint.java +@@ -0,0 +1,25 @@ ++package io.papermc.paper.plugin.entrypoint; ++ ++import io.papermc.paper.plugin.bootstrap.PluginBootstrap; ++import org.bukkit.plugin.java.JavaPlugin; ++ ++/** ++ * Used to mark a certain place that {@link EntrypointHandler} will register {@link io.papermc.paper.plugin.provider.PluginProvider} under. ++ * Used for loading only certain providers at a certain time. ++ * @param provider type ++ */ ++public final class Entrypoint { ++ ++ public static final Entrypoint BOOTSTRAPPER = new Entrypoint<>("bootstrapper"); ++ public static final Entrypoint PLUGIN = new Entrypoint<>("plugin"); ++ ++ private final String debugName; ++ ++ private Entrypoint(String debugName) { ++ this.debugName = debugName; ++ } ++ ++ public String getDebugName() { ++ return debugName; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/EntrypointHandler.java b/src/main/java/io/papermc/paper/plugin/entrypoint/EntrypointHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b38e1e0f3d3055086f51bb191fd4b60ecf32d016 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/EntrypointHandler.java +@@ -0,0 +1,14 @@ ++package io.papermc.paper.plugin.entrypoint; ++ ++import io.papermc.paper.plugin.provider.PluginProvider; ++ ++/** ++ * Represents a register that will register providers at a certain {@link Entrypoint}, ++ * where then when the given {@link Entrypoint} is registered those will be loaded. ++ */ ++public interface EntrypointHandler { ++ ++ void register(Entrypoint entrypoint, PluginProvider provider); ++ ++ void enter(Entrypoint entrypoint); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/LaunchEntryPointHandler.java b/src/main/java/io/papermc/paper/plugin/entrypoint/LaunchEntryPointHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..61a67971a41527c0e3b614bf48d2bc8eabd443b5 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/LaunchEntryPointHandler.java +@@ -0,0 +1,60 @@ ++package io.papermc.paper.plugin.entrypoint; ++ ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.storage.BootstrapProviderStorage; ++import io.papermc.paper.plugin.storage.ProviderStorage; ++import io.papermc.paper.plugin.storage.ServerPluginProviderStorage; ++import org.jetbrains.annotations.ApiStatus; ++ ++import java.util.HashMap; ++import java.util.Map; ++ ++/** ++ * Used by the server to register/load plugin bootstrappers and plugins. ++ */ ++public class LaunchEntryPointHandler implements EntrypointHandler { ++ ++ public static final LaunchEntryPointHandler INSTANCE = new LaunchEntryPointHandler(); ++ private final Map, ProviderStorage> storage = new HashMap<>(); ++ ++ LaunchEntryPointHandler() { ++ this.storage.put(Entrypoint.BOOTSTRAPPER, new BootstrapProviderStorage()); ++ this.storage.put(Entrypoint.PLUGIN, new ServerPluginProviderStorage()); ++ } ++ ++ // Utility ++ public static void enterBootstrappers() { ++ LaunchEntryPointHandler.INSTANCE.enter(Entrypoint.BOOTSTRAPPER); ++ } ++ ++ @Override ++ public void enter(Entrypoint entrypoint) { ++ ProviderStorage storage = this.storage.get(entrypoint); ++ if (storage == null) { ++ throw new IllegalArgumentException("No storage registered for entrypoint %s.".formatted(entrypoint)); ++ } ++ ++ storage.enter(); ++ } ++ ++ @Override ++ public void register(Entrypoint entrypoint, PluginProvider provider) { ++ ProviderStorage storage = this.get(entrypoint); ++ if (storage == null) { ++ throw new IllegalArgumentException("No storage registered for entrypoint %s.".formatted(entrypoint)); ++ } ++ ++ storage.register(provider); ++ } ++ ++ @SuppressWarnings("unchecked") ++ public ProviderStorage get(Entrypoint entrypoint) { ++ return (ProviderStorage) this.storage.get(entrypoint); ++ } ++ ++ // Debug only ++ @ApiStatus.Internal ++ public Map, ProviderStorage> getStorage() { ++ return storage; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/ClassloaderBytecodeModifier.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/ClassloaderBytecodeModifier.java +new file mode 100644 +index 0000000000000000000000000000000000000000..93b5196a960f3efbe0d28f5527ea2752426213ce +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/ClassloaderBytecodeModifier.java +@@ -0,0 +1,22 @@ ++package io.papermc.paper.plugin.entrypoint.classloader; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import net.kyori.adventure.util.Services; ++import org.jetbrains.annotations.ApiStatus; ++ ++@ApiStatus.Internal ++public interface ClassloaderBytecodeModifier { ++ ++ static ClassloaderBytecodeModifier bytecodeModifier() { ++ return Provider.INSTANCE; ++ } ++ ++ byte[] modify(PluginMeta config, byte[] bytecode); ++ ++ class Provider { ++ ++ private static final ClassloaderBytecodeModifier INSTANCE = Services.service(ClassloaderBytecodeModifier.class).orElseThrow(); ++ ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperClassloaderBytecodeModifier.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperClassloaderBytecodeModifier.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f9a2c55a354c877749db3f92956de802ae575788 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperClassloaderBytecodeModifier.java +@@ -0,0 +1,12 @@ ++package io.papermc.paper.plugin.entrypoint.classloader; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++ ++// Stub, implement in future. ++public class PaperClassloaderBytecodeModifier implements ClassloaderBytecodeModifier { ++ ++ @Override ++ public byte[] modify(PluginMeta configuration, byte[] bytecode) { ++ return bytecode; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f1a2d25079c841daff19f41f2b24fb8e97d2c7d3 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperPluginClassLoader.java +@@ -0,0 +1,193 @@ ++package io.papermc.paper.plugin.entrypoint.classloader; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; ++import io.papermc.paper.plugin.entrypoint.classloader.group.PaperPluginClassLoaderStorage; ++import io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage; ++import io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup; ++import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; ++import org.bukkit.Bukkit; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.io.File; ++import java.io.IOException; ++import java.net.URL; ++import java.nio.file.Path; ++import java.util.ArrayList; ++import java.util.Collections; ++import java.util.Enumeration; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import java.util.concurrent.ConcurrentHashMap; ++import java.util.jar.JarFile; ++import java.util.logging.Logger; ++ ++/** ++ * This is similar to a {@link org.bukkit.plugin.java.PluginClassLoader} but is completely kept hidden from the api. ++ * This is only used with Paper plugins. ++ * ++ * @see PaperPluginClassLoaderStorage ++ */ ++public class PaperPluginClassLoader extends PaperSimplePluginClassLoader implements ConfiguredPluginClassLoader { ++ ++ static { ++ registerAsParallelCapable(); ++ } ++ ++ private final ClassLoader libraryLoader; ++ private final Set seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>()); ++ private final Logger logger; ++ @Nullable ++ private JavaPlugin loadedJavaPlugin; ++ @Nullable ++ private PluginClassLoaderGroup group; ++ ++ public PaperPluginClassLoader(Logger logger, Path source, JarFile file, PaperPluginMeta configuration, ClassLoader parentLoader, ClassLoader libraryLoader) throws IOException { ++ super(source, file, configuration, parentLoader); ++ this.libraryLoader = libraryLoader; ++ ++ this.logger = logger; ++ if (this.configuration.hasOpenClassloader()) { ++ this.group = PaperClassLoaderStorage.instance().registerOpenGroup(this); ++ } ++ } ++ ++ public void refreshClassloaderDependencyTree(DependencyContext dependencyContext) { ++ if (this.configuration.hasOpenClassloader()) { ++ return; ++ } ++ if (this.group != null) { ++ // We need to unregister the classloader inorder to allow for dependencies ++ // to be recalculated ++ PaperClassLoaderStorage.instance().unregisterClassloader(this); ++ } ++ ++ this.group = PaperClassLoaderStorage.instance().registerAccessBackedGroup(this, (classLoader) -> { ++ return dependencyContext.isTransitiveDependency(PaperPluginClassLoader.this.configuration, classLoader.getConfiguration()); ++ }); ++ } ++ ++ @Override ++ public URL getResource(String name) { ++ URL resource = findResource(name); ++ if (resource == null && this.libraryLoader != null) { ++ return this.libraryLoader.getResource(name); ++ } ++ return resource; ++ } ++ ++ @Override ++ public Enumeration getResources(String name) throws IOException { ++ List resources = new ArrayList<>(); ++ this.addEnumeration(resources, this.findResources(name)); ++ if (this.libraryLoader != null) { ++ addEnumeration(resources, this.libraryLoader.getResources(name)); ++ } ++ return Collections.enumeration(resources); ++ } ++ ++ private void addEnumeration(List list, Enumeration enumeration) { ++ while (enumeration.hasMoreElements()) { ++ list.add(enumeration.nextElement()); ++ } ++ } ++ ++ @Override ++ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { ++ return this.loadClass(name, resolve, true, true); ++ } ++ ++ @Override ++ public PluginMeta getConfiguration() { ++ return this.configuration; ++ } ++ ++ @Override ++ public Class loadClass(@NotNull String name, boolean resolve, boolean checkGroup, boolean checkLibraries) throws ClassNotFoundException { ++ try { ++ Class result = super.loadClass(name, resolve); ++ ++ // SPIGOT-6749: Library classes will appear in the above, but we don't want to return them to other plugins ++ if (checkGroup || result.getClassLoader() == this) { ++ return result; ++ } ++ } catch (ClassNotFoundException ignored) { ++ } ++ ++ if (checkLibraries) { ++ try { ++ return this.libraryLoader.loadClass(name); ++ } catch (ClassNotFoundException ignored) { ++ } ++ } ++ ++ if (checkGroup) { ++ // This ignores the libraries of other plugins, unless they are transitive dependencies. ++ if (this.group == null) { ++ throw new IllegalStateException("Tried to resolve class while group was not yet initialized"); ++ } ++ ++ Class clazz = this.group.getClassByName(name, resolve, this); ++ if (clazz != null) { ++ return clazz; ++ } ++ } ++ ++ throw new ClassNotFoundException(name); ++ } ++ ++ @Override ++ public void init(JavaPlugin plugin) { ++ PluginMeta config = this.configuration; ++ PluginDescriptionFile pluginDescriptionFile = new PluginDescriptionFile( ++ config.getName(), ++ config.getDisplayName(), ++ config.getProvidedPlugins(), ++ config.getMainClass(), ++ "", // Classloader load order api ++ List.of(), // Dependencies ++ List.of(), // Soft Depends ++ List.of(), // Load Before ++ config.getVersion(), ++ Map.of(), // Commands, we use a separate system ++ config.getDescription(), ++ config.getAuthors(), ++ config.getContributors(), ++ config.getWebsite(), ++ config.getLoggerPrefix(), ++ config.getLoadOrder(), ++ config.getPermissions(), ++ config.getPermissionDefault(), ++ Set.of(), // Aware api ++ config.getAPIVersion(), ++ List.of() // Libraries ++ ); ++ ++ File dataFolder = new File(Bukkit.getPluginsFolder(), pluginDescriptionFile.getName()); ++ ++ plugin.init(Bukkit.getServer(), pluginDescriptionFile, dataFolder, this.source.toFile(), this, config); ++ plugin.logger = this.logger; ++ ++ this.loadedJavaPlugin = plugin; ++ } ++ ++ @Nullable ++ public JavaPlugin getLoadedJavaPlugin() { ++ return this.loadedJavaPlugin; ++ } ++ ++ @Override ++ public String toString() { ++ return "PaperPluginClassLoader{" + ++ "libraryLoader=" + this.libraryLoader + ++ ", seenIllegalAccess=" + this.seenIllegalAccess + ++ ", loadedJavaPlugin=" + this.loadedJavaPlugin + ++ ", group=" + this.group + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6688f2af4a32c2f79785f162e2eac0330d439ac1 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperSimplePluginClassLoader.java +@@ -0,0 +1,116 @@ ++package io.papermc.paper.plugin.entrypoint.classloader; ++ ++import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; ++import io.papermc.paper.plugin.util.NamespaceChecker; ++import org.jetbrains.annotations.ApiStatus; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.net.URL; ++import java.net.URLClassLoader; ++import java.nio.file.Path; ++import java.security.CodeSigner; ++import java.security.CodeSource; ++import java.util.Enumeration; ++import java.util.jar.JarEntry; ++import java.util.jar.JarFile; ++import java.util.jar.Manifest; ++ ++/** ++ * Represents a simple classloader used for paper plugin bootstrappers. ++ */ ++@ApiStatus.Internal ++public class PaperSimplePluginClassLoader extends URLClassLoader { ++ ++ static { ++ ClassLoader.registerAsParallelCapable(); ++ } ++ ++ protected final PaperPluginMeta configuration; ++ protected final Path source; ++ protected final Manifest jarManifest; ++ protected final URL jarUrl; ++ protected final JarFile jar; ++ ++ public PaperSimplePluginClassLoader(Path source, JarFile file, PaperPluginMeta configuration, ClassLoader parentLoader) throws IOException { ++ super(source.getFileName().toString(), new URL[]{source.toUri().toURL()}, parentLoader); ++ ++ this.source = source; ++ this.jarManifest = file.getManifest(); ++ this.jarUrl = source.toUri().toURL(); ++ this.configuration = configuration; ++ this.jar = file; ++ } ++ ++ @Override ++ public URL getResource(String name) { ++ return this.findResource(name); ++ } ++ ++ @Override ++ public Enumeration getResources(String name) throws IOException { ++ return this.findResources(name); ++ } ++ ++ // Bytecode modification supported loader ++ @Override ++ protected Class findClass(String name) throws ClassNotFoundException { ++ NamespaceChecker.validateNameSpaceForClassloading(name); ++ ++ // See UrlClassLoader#findClass(String) ++ String path = name.replace('.', '/').concat(".class"); ++ JarEntry entry = this.jar.getJarEntry(path); ++ if (entry == null) { ++ throw new ClassNotFoundException(); ++ } ++ ++ // See URLClassLoader#defineClass(String, Resource) ++ byte[] classBytes; ++ ++ try (InputStream is = this.jar.getInputStream(entry)) { ++ classBytes = is.readAllBytes(); ++ } catch (IOException ex) { ++ throw new ClassNotFoundException(name, ex); ++ } ++ ++ classBytes = ClassloaderBytecodeModifier.bytecodeModifier().modify(this.configuration, classBytes); ++ ++ int dot = name.lastIndexOf('.'); ++ if (dot != -1) { ++ String pkgName = name.substring(0, dot); ++ // Get defined package does not correctly handle sealed packages. ++ if (this.getDefinedPackage(pkgName) == null) { ++ try { ++ if (this.jarManifest != null) { ++ this.definePackage(pkgName, this.jarManifest, this.jarUrl); ++ } else { ++ this.definePackage(pkgName, null, null, null, null, null, null, null); ++ } ++ } catch (IllegalArgumentException ex) { ++ // parallel-capable class loaders: re-verify in case of a ++ // race condition ++ if (this.getDefinedPackage(pkgName) == null) { ++ // Should never happen ++ throw new IllegalStateException("Cannot find package " + pkgName); ++ } ++ } ++ } ++ } ++ ++ CodeSigner[] signers = entry.getCodeSigners(); ++ CodeSource source = new CodeSource(this.jarUrl, signers); ++ ++ return this.defineClass(name, classBytes, 0, classBytes.length, source); ++ } ++ ++ @Override ++ public String toString() { ++ return "PaperSimplePluginClassLoader{" + ++ "configuration=" + this.configuration + ++ ", source=" + this.source + ++ ", jarManifest=" + this.jarManifest + ++ ", jarUrl=" + this.jarUrl + ++ ", jar=" + this.jar + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/DependencyBasedPluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/DependencyBasedPluginClassLoaderGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..eaf5c794cbe8d6138c9d60eaae20f5fc7711f541 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/DependencyBasedPluginClassLoaderGroup.java +@@ -0,0 +1,47 @@ ++package io.papermc.paper.plugin.entrypoint.classloader.group; ++ ++import io.papermc.paper.plugin.provider.classloader.ClassLoaderAccess; ++import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; ++import org.jetbrains.annotations.ApiStatus; ++ ++import java.util.ArrayList; ++ ++@ApiStatus.Internal ++public class DependencyBasedPluginClassLoaderGroup extends SimpleListPluginClassLoaderGroup { ++ ++ private final GlobalPluginClassLoaderGroup globalPluginClassLoaderGroup; ++ private final ClassLoaderAccess access; ++ ++ public DependencyBasedPluginClassLoaderGroup(GlobalPluginClassLoaderGroup globalPluginClassLoaderGroup, ClassLoaderAccess access) { ++ super(new ArrayList<>()); ++ this.access = access; ++ this.globalPluginClassLoaderGroup = globalPluginClassLoaderGroup; ++ } ++ ++ /** ++ * This will refresh the dependencies of the current classloader. ++ */ ++ public void populateDependencies() { ++ this.classloaders.clear(); ++ for (ConfiguredPluginClassLoader configuredPluginClassLoader : this.globalPluginClassLoaderGroup.getClassLoaders()) { ++ if (this.access.canAccess(configuredPluginClassLoader)) { ++ this.classloaders.add(configuredPluginClassLoader); ++ } ++ } ++ ++ } ++ ++ @Override ++ public ClassLoaderAccess getAccess() { ++ return this.access; ++ } ++ ++ @Override ++ public String toString() { ++ return "DependencyBasedPluginClassLoaderGroup{" + ++ "globalPluginClassLoaderGroup=" + this.globalPluginClassLoaderGroup + ++ ", access=" + this.access + ++ ", classloaders=" + this.classloaders + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/GlobalPluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/GlobalPluginClassLoaderGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2b7eef787f83e5a32896cb30c215406b6f652786 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/GlobalPluginClassLoaderGroup.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.plugin.entrypoint.classloader.group; ++ ++import io.papermc.paper.plugin.provider.classloader.ClassLoaderAccess; ++import org.jetbrains.annotations.ApiStatus; ++ ++@ApiStatus.Internal ++public class GlobalPluginClassLoaderGroup extends SimpleListPluginClassLoaderGroup { ++ ++ @Override ++ public ClassLoaderAccess getAccess() { ++ return (v) -> true; ++ } ++ ++ @Override ++ public String toString() { ++ return super.toString(); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/LockingClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/LockingClassLoaderGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..aae50ebba6ba1579b75af5370c8b020d2a927b2c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/LockingClassLoaderGroup.java +@@ -0,0 +1,76 @@ ++package io.papermc.paper.plugin.entrypoint.classloader.group; ++ ++import io.papermc.paper.plugin.provider.classloader.ClassLoaderAccess; ++import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; ++import io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.HashMap; ++import java.util.Map; ++import java.util.concurrent.atomic.AtomicInteger; ++import java.util.concurrent.locks.ReentrantReadWriteLock; ++ ++@ApiStatus.Internal ++public class LockingClassLoaderGroup implements PluginClassLoaderGroup { ++ ++ private final PluginClassLoaderGroup parent; ++ private final Map classLoadLock = new HashMap<>(); ++ ++ public LockingClassLoaderGroup(PluginClassLoaderGroup parent) { ++ this.parent = parent; ++ } ++ ++ @Override ++ public @Nullable Class getClassByName(String name, boolean resolve, ConfiguredPluginClassLoader requester) { ++ // make MT safe ++ ClassLockEntry lock; ++ synchronized (this.classLoadLock) { ++ lock = this.classLoadLock.computeIfAbsent(name, (x) -> new ClassLockEntry(new AtomicInteger(0), new java.util.concurrent.locks.ReentrantReadWriteLock())); ++ lock.count.incrementAndGet(); ++ } ++ lock.reentrantReadWriteLock.writeLock().lock(); ++ try { ++ return parent.getClassByName(name, resolve, requester); ++ } finally { ++ synchronized (this.classLoadLock) { ++ lock.reentrantReadWriteLock.writeLock().unlock(); ++ if (lock.count.get() == 1) { ++ this.classLoadLock.remove(name); ++ } else { ++ lock.count.decrementAndGet(); ++ } ++ } ++ } ++ } ++ ++ @Override ++ public void remove(ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ this.parent.remove(configuredPluginClassLoader); ++ } ++ ++ @Override ++ public void add(ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ this.parent.add(configuredPluginClassLoader); ++ } ++ ++ @Override ++ public ClassLoaderAccess getAccess() { ++ return this.parent.getAccess(); ++ } ++ ++ public PluginClassLoaderGroup getParent() { ++ return parent; ++ } ++ ++ record ClassLockEntry(AtomicInteger count, ReentrantReadWriteLock reentrantReadWriteLock) { ++ } ++ ++ @Override ++ public String toString() { ++ return "LockingClassLoaderGroup{" + ++ "parent=" + this.parent + ++ ", classLoadLock=" + this.classLoadLock + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/PaperPluginClassLoaderStorage.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/PaperPluginClassLoaderStorage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2c906e2c7d972b221a41acd614e00d0fbc1227c6 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/PaperPluginClassLoaderStorage.java +@@ -0,0 +1,93 @@ ++package io.papermc.paper.plugin.entrypoint.classloader.group; ++ ++import io.papermc.paper.plugin.provider.classloader.ClassLoaderAccess; ++import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; ++import io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage; ++import io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup; ++import org.bukkit.Bukkit; ++import org.bukkit.plugin.java.PluginClassLoader; ++import org.jetbrains.annotations.ApiStatus; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.concurrent.CopyOnWriteArrayList; ++ ++/** ++ * This is used for connecting multiple classloaders. ++ */ ++public final class PaperPluginClassLoaderStorage implements PaperClassLoaderStorage { ++ ++ private final GlobalPluginClassLoaderGroup globalGroup = new GlobalPluginClassLoaderGroup(); ++ private final List groups = new CopyOnWriteArrayList<>(); ++ ++ public PaperPluginClassLoaderStorage() { ++ this.groups.add(this.globalGroup); ++ } ++ ++ @Override ++ public PluginClassLoaderGroup registerSpigotGroup(PluginClassLoader pluginClassLoader) { ++ return this.registerGroup(pluginClassLoader, new SpigotPluginClassLoaderGroup(this.globalGroup, (library) -> { ++ return Bukkit.getServer().getPluginManager().isTransitiveDependency(pluginClassLoader.getConfiguration(), library.getConfiguration()); ++ })); ++ } ++ ++ @Override ++ public PluginClassLoaderGroup registerOpenGroup(ConfiguredPluginClassLoader classLoader) { ++ return this.registerGroup(classLoader, this.globalGroup); ++ } ++ ++ @Override ++ public PluginClassLoaderGroup registerAccessBackedGroup(ConfiguredPluginClassLoader classLoader, ClassLoaderAccess access) { ++ List allowedLoaders = new ArrayList<>(); ++ for (ConfiguredPluginClassLoader configuredPluginClassLoader : this.globalGroup.getClassLoaders()) { ++ if (access.canAccess(configuredPluginClassLoader)) { ++ allowedLoaders.add(configuredPluginClassLoader); ++ } ++ } ++ ++ return this.registerGroup(classLoader, new StaticPluginClassLoaderGroup(allowedLoaders, access)); ++ } ++ ++ private PluginClassLoaderGroup registerGroup(ConfiguredPluginClassLoader classLoader, PluginClassLoaderGroup group) { ++ // Now add this classloader to any groups that allows it (includes global) ++ for (PluginClassLoaderGroup loaderGroup : this.groups) { ++ if (loaderGroup.getAccess().canAccess(classLoader)) { ++ loaderGroup.add(classLoader); ++ } ++ } ++ ++ group = new LockingClassLoaderGroup(group); ++ this.groups.add(group); ++ return group; ++ } ++ ++ @Override ++ public void unregisterClassloader(ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ this.globalGroup.remove(configuredPluginClassLoader); ++ for (PluginClassLoaderGroup group : this.groups) { ++ group.remove(configuredPluginClassLoader); ++ } ++ } ++ ++ @Override ++ public boolean registerUnsafePlugin(ConfiguredPluginClassLoader pluginLoader) { ++ if (this.globalGroup.getClassLoaders().contains(pluginLoader)) { ++ return false; ++ } else { ++ this.globalGroup.getClassLoaders().add(pluginLoader); ++ return true; ++ } ++ } ++ ++ // Debug only ++ @ApiStatus.Internal ++ public GlobalPluginClassLoaderGroup getGlobalGroup() { ++ return this.globalGroup; ++ } ++ ++ // Debug only ++ @ApiStatus.Internal ++ public List getGroups() { ++ return this.groups; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SimpleListPluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SimpleListPluginClassLoaderGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..23b6cb297f46c9c2b2944a3ab4031c31414620ad +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SimpleListPluginClassLoaderGroup.java +@@ -0,0 +1,69 @@ ++package io.papermc.paper.plugin.entrypoint.classloader.group; ++ ++import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; ++import io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.List; ++import java.util.concurrent.CopyOnWriteArrayList; ++ ++@ApiStatus.Internal ++public abstract class SimpleListPluginClassLoaderGroup implements PluginClassLoaderGroup { ++ ++ private static final boolean DISABLE_CLASS_PRIORITIZATION = Boolean.getBoolean("Paper.DisableClassPrioritization"); ++ ++ protected final List classloaders; ++ ++ protected SimpleListPluginClassLoaderGroup() { ++ this(new CopyOnWriteArrayList<>()); ++ } ++ ++ protected SimpleListPluginClassLoaderGroup(List classloaders) { ++ this.classloaders = classloaders; ++ } ++ ++ @Override ++ public @Nullable Class getClassByName(String name, boolean resolve, ConfiguredPluginClassLoader requester) { ++ if (!DISABLE_CLASS_PRIORITIZATION) { ++ try { ++ return this.lookupClass(name, false, requester); // First check the requester ++ } catch (ClassNotFoundException ignored) { ++ } ++ } ++ ++ for (ConfiguredPluginClassLoader loader : this.classloaders) { ++ try { ++ return this.lookupClass(name, resolve, loader); ++ } catch (ClassNotFoundException ignored) { ++ } ++ } ++ ++ return null; ++ } ++ ++ protected Class lookupClass(String name, boolean resolve, ConfiguredPluginClassLoader current) throws ClassNotFoundException { ++ return current.loadClass(name, resolve, false, true); ++ } ++ ++ @Override ++ public void remove(ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ this.classloaders.remove(configuredPluginClassLoader); ++ } ++ ++ @Override ++ public void add(ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ this.classloaders.add(configuredPluginClassLoader); ++ } ++ ++ public List getClassLoaders() { ++ return classloaders; ++ } ++ ++ @Override ++ public String toString() { ++ return "SimpleListPluginClassLoaderGroup{" + ++ "classloaders=" + this.classloaders + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SingletonPluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SingletonPluginClassLoaderGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..3b670bd6b35ae7f56488a9b50df54709a0b28901 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SingletonPluginClassLoaderGroup.java +@@ -0,0 +1,60 @@ ++package io.papermc.paper.plugin.entrypoint.classloader.group; ++ ++import io.papermc.paper.plugin.provider.classloader.ClassLoaderAccess; ++import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; ++import io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Nullable; ++ ++@ApiStatus.Internal ++public class SingletonPluginClassLoaderGroup implements PluginClassLoaderGroup { ++ ++ private final ConfiguredPluginClassLoader configuredPluginClassLoader; ++ private final Access access; ++ ++ public SingletonPluginClassLoaderGroup(ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ this.configuredPluginClassLoader = configuredPluginClassLoader; ++ this.access = new Access(); ++ } ++ ++ @Override ++ public @Nullable Class getClassByName(String name, boolean resolve, ConfiguredPluginClassLoader requester) { ++ try { ++ return this.configuredPluginClassLoader.loadClass(name, resolve, false, true); ++ } catch (ClassNotFoundException ignored) { ++ } ++ ++ return null; ++ } ++ ++ @Override ++ public void remove(ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ } ++ ++ @Override ++ public void add(ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ } ++ ++ @Override ++ public ClassLoaderAccess getAccess() { ++ return this.access; ++ } ++ ++ @ApiStatus.Internal ++ private class Access implements ClassLoaderAccess { ++ ++ @Override ++ public boolean canAccess(ConfiguredPluginClassLoader classLoader) { ++ return SingletonPluginClassLoaderGroup.this.configuredPluginClassLoader == classLoader; ++ } ++ ++ } ++ ++ @Override ++ public String toString() { ++ return "SingletonPluginClassLoaderGroup{" + ++ "configuredPluginClassLoader=" + this.configuredPluginClassLoader + ++ ", access=" + this.access + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SpigotPluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SpigotPluginClassLoaderGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5d26367524389388be163ae3120c1d2bf55cfef7 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/SpigotPluginClassLoaderGroup.java +@@ -0,0 +1,49 @@ ++package io.papermc.paper.plugin.entrypoint.classloader.group; ++ ++import io.papermc.paper.plugin.provider.classloader.ClassLoaderAccess; ++import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; ++import org.jetbrains.annotations.ApiStatus; ++ ++import java.util.function.Predicate; ++ ++/** ++ * Spigot classloaders have the ability to see everything. ++ * However, libraries are ONLY shared depending on their dependencies. ++ */ ++@ApiStatus.Internal ++public class SpigotPluginClassLoaderGroup extends SimpleListPluginClassLoaderGroup { ++ ++ private final Predicate libraryClassloaderPredicate; ++ ++ public SpigotPluginClassLoaderGroup(GlobalPluginClassLoaderGroup globalPluginClassLoaderGroup, Predicate libraryClassloaderPredicate) { ++ super(globalPluginClassLoaderGroup.getClassLoaders()); ++ this.libraryClassloaderPredicate = libraryClassloaderPredicate; ++ } ++ ++ // Mirrors global list ++ @Override ++ public void add(ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ } ++ ++ @Override ++ public void remove(ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ } ++ ++ @Override ++ protected Class lookupClass(String name, boolean resolve, ConfiguredPluginClassLoader current) throws ClassNotFoundException { ++ return current.loadClass(name, resolve, false, this.libraryClassloaderPredicate.test(current)); ++ } ++ ++ @Override ++ public ClassLoaderAccess getAccess() { ++ return v -> true; ++ } ++ ++ @Override ++ public String toString() { ++ return "SpigotPluginClassLoaderGroup{" + ++ "libraryClassloaderPredicate=" + this.libraryClassloaderPredicate + ++ ", classloaders=" + this.classloaders + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/StaticPluginClassLoaderGroup.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/StaticPluginClassLoaderGroup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7f7085b06271adf8a37485f4c9c9b8af605dd27d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/group/StaticPluginClassLoaderGroup.java +@@ -0,0 +1,31 @@ ++package io.papermc.paper.plugin.entrypoint.classloader.group; ++ ++import io.papermc.paper.plugin.provider.classloader.ClassLoaderAccess; ++import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; ++import org.jetbrains.annotations.ApiStatus; ++ ++import java.util.List; ++ ++@ApiStatus.Internal ++public class StaticPluginClassLoaderGroup extends SimpleListPluginClassLoaderGroup { ++ ++ private final ClassLoaderAccess access; ++ ++ public StaticPluginClassLoaderGroup(List classloaders, ClassLoaderAccess access) { ++ super(classloaders); ++ this.access = access; ++ } ++ ++ @Override ++ public ClassLoaderAccess getAccess() { ++ return this.access; ++ } ++ ++ @Override ++ public String toString() { ++ return "StaticPluginClassLoaderGroup{" + ++ "access=" + this.access + ++ ", classloaders=" + this.classloaders + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/dependency/DependencyContextHolder.java b/src/main/java/io/papermc/paper/plugin/entrypoint/dependency/DependencyContextHolder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f43295fdeaa587cf30c35a1d545167071d58ce4b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/dependency/DependencyContextHolder.java +@@ -0,0 +1,9 @@ ++package io.papermc.paper.plugin.entrypoint.dependency; ++ ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++ ++public interface DependencyContextHolder { ++ ++ void setContext(DependencyContext context); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/dependency/DependencyUtil.java b/src/main/java/io/papermc/paper/plugin/entrypoint/dependency/DependencyUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1af3c3434eb1f3b00857b17a07f42e51086c1e2b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/dependency/DependencyUtil.java +@@ -0,0 +1,45 @@ ++package io.papermc.paper.plugin.entrypoint.dependency; ++ ++import com.google.common.graph.MutableGraph; ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++@SuppressWarnings("UnstableApiUsage") ++public class DependencyUtil { ++ ++ @NotNull ++ public static MutableGraph buildDependencyGraph(@NotNull MutableGraph dependencyGraph, @NotNull PluginMeta configuration) { ++ List dependencies = new ArrayList<>(); ++ dependencies.addAll(configuration.getPluginDependencies()); ++ dependencies.addAll(configuration.getPluginSoftDependencies()); ++ ++ return buildDependencyGraph(dependencyGraph, configuration.getName(), dependencies, configuration.getLoadBeforePlugins()); ++ } ++ ++ @NotNull ++ public static MutableGraph buildDependencyGraph(@NotNull MutableGraph dependencyGraph, String identifier, @NotNull Iterable depends, @NotNull Iterable loadBefore) { ++ for (String dependency : depends) { ++ dependencyGraph.putEdge(identifier, dependency); ++ } ++ ++ for (String loadBeforeTarget : loadBefore) { ++ dependencyGraph.putEdge(loadBeforeTarget, identifier); ++ } ++ ++ dependencyGraph.addNode(identifier); // Make sure dependencies at least have a node ++ return dependencyGraph; ++ } ++ ++ // This adds a provided plugin to another plugin, basically making it seem like a "dependency" ++ // in order to have plugins that need the provided plugin to load after the specified plugin name ++ @NotNull ++ public static MutableGraph addProvidedPlugin(@NotNull MutableGraph dependencyGraph, @NotNull String pluginName, @NotNull String providedName) { ++ dependencyGraph.putEdge(pluginName, providedName); ++ ++ return dependencyGraph; ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/dependency/GraphDependencyContext.java b/src/main/java/io/papermc/paper/plugin/entrypoint/dependency/GraphDependencyContext.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6f201a8131ca9631ac4af62c75e6f2e889cb5eae +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/dependency/GraphDependencyContext.java +@@ -0,0 +1,43 @@ ++package io.papermc.paper.plugin.entrypoint.dependency; ++ ++import com.google.common.graph.Graph; ++import com.google.common.graph.Graphs; ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++ ++import java.util.Set; ++ ++@SuppressWarnings("UnstableApiUsage") ++public class GraphDependencyContext implements DependencyContext { ++ ++ private final Graph dependencyGraph; ++ ++ public GraphDependencyContext(Graph dependencyGraph) { ++ this.dependencyGraph = dependencyGraph; ++ } ++ ++ @Override ++ public boolean isTransitiveDependency(PluginMeta plugin, PluginMeta depend) { ++ String pluginIdentifier = plugin.getName(); ++ ++ if (this.dependencyGraph.nodes().contains(pluginIdentifier)) { ++ Set reachableNodes = Graphs.reachableNodes(this.dependencyGraph, pluginIdentifier); ++ if (reachableNodes.contains(depend.getName())) { ++ return true; ++ } ++ for (String provided : depend.getProvidedPlugins()) { ++ if (reachableNodes.contains(provided)) { ++ return true; ++ } ++ } ++ } ++ ++ return false; ++ } ++ ++ @Override ++ public boolean hasDependency(String pluginIdentifier) { ++ return this.dependencyGraph.nodes().contains(pluginIdentifier); ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/JohnsonSimpleCycles.java b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/JohnsonSimpleCycles.java +new file mode 100644 +index 0000000000000000000000000000000000000000..22189a1c42459c00d3e8bdeb980d15a69b720805 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/JohnsonSimpleCycles.java +@@ -0,0 +1,350 @@ ++/* ++ * (C) Copyright 2013-2021, by Nikolay Ognyanov and Contributors. ++ * ++ * JGraphT : a free Java graph-theory library ++ * ++ * See the CONTRIBUTORS.md file distributed with this work for additional ++ * information regarding copyright ownership. ++ * ++ * This program and the accompanying materials are made available under the ++ * terms of the Eclipse Public License 2.0 which is available at ++ * http://www.eclipse.org/legal/epl-2.0, or the ++ * GNU Lesser General Public License v2.1 or later ++ * which is available at ++ * http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html. ++ * ++ * SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later ++ */ ++ ++// MODIFICATIONS: ++// - Modified to use a guava graph directly ++ ++package io.papermc.paper.plugin.entrypoint.strategy; ++ ++import com.google.common.base.Preconditions; ++import com.google.common.graph.Graph; ++import com.google.common.graph.GraphBuilder; ++import com.google.common.graph.MutableGraph; ++import com.mojang.datafixers.util.Pair; ++ ++import java.util.ArrayDeque; ++import java.util.ArrayList; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import java.util.function.Consumer; ++ ++/** ++ * Find all simple cycles of a directed graph using the Johnson's algorithm. ++ * ++ *

++ * See:
++ * D.B.Johnson, Finding all the elementary circuits of a directed graph, SIAM J. Comput., 4 (1975), ++ * pp. 77-84. ++ * ++ * @param the vertex type. ++ * ++ * @author Nikolay Ognyanov ++ */ ++public class JohnsonSimpleCycles ++{ ++ // The graph. ++ private Graph graph; ++ ++ // The main state of the algorithm. ++ private Consumer> cycleConsumer = null; ++ private V[] iToV = null; ++ private Map vToI = null; ++ private Set blocked = null; ++ private Map> bSets = null; ++ private ArrayDeque stack = null; ++ ++ // The state of the embedded Tarjan SCC algorithm. ++ private List> foundSCCs = null; ++ private int index = 0; ++ private Map vIndex = null; ++ private Map vLowlink = null; ++ private ArrayDeque path = null; ++ private Set pathSet = null; ++ ++ /** ++ * Create a simple cycle finder for the specified graph. ++ * ++ * @param graph - the DirectedGraph in which to find cycles. ++ * ++ * @throws IllegalArgumentException if the graph argument is ++ * null. ++ */ ++ public JohnsonSimpleCycles(Graph graph) ++ { ++ Preconditions.checkState(graph.isDirected(), "Graph must be directed"); ++ this.graph = graph; ++ } ++ ++ /** ++ * Find the simple cycles of the graph. ++ * ++ * @return The list of all simple cycles. Possibly empty but never null. ++ */ ++ public List> findSimpleCycles() ++ { ++ List> result = new ArrayList<>(); ++ findSimpleCycles(result::add); ++ return result; ++ } ++ ++ /** ++ * Find the simple cycles of the graph. ++ * ++ * @param consumer Consumer that will be called with each cycle found. ++ */ ++ public void findSimpleCycles(Consumer> consumer) ++ { ++ if (graph == null) { ++ throw new IllegalArgumentException("Null graph."); ++ } ++ initState(consumer); ++ ++ int startIndex = 0; ++ int size = graph.nodes().size(); ++ while (startIndex < size) { ++ Pair, Integer> minSCCGResult = findMinSCSG(startIndex); ++ if (minSCCGResult != null) { ++ startIndex = minSCCGResult.getSecond(); ++ Graph scg = minSCCGResult.getFirst(); ++ V startV = toV(startIndex); ++ for (V v : scg.successors(startV)) { ++ blocked.remove(v); ++ getBSet(v).clear(); ++ } ++ findCyclesInSCG(startIndex, startIndex, scg); ++ startIndex++; ++ } else { ++ break; ++ } ++ } ++ ++ clearState(); ++ } ++ ++ private Pair, Integer> findMinSCSG(int startIndex) ++ { ++ /* ++ * Per Johnson : "adjacency structure of strong component $K$ with least vertex in subgraph ++ * of $G$ induced by $(s, s + 1, n)$". Or in contemporary terms: the strongly connected ++ * component of the subgraph induced by $(v_1, \dotso ,v_n)$ which contains the minimum ++ * (among those SCCs) vertex index. We return that index together with the graph. ++ */ ++ initMinSCGState(); ++ ++ List> foundSCCs = findSCCS(startIndex); ++ ++ // find the SCC with the minimum index ++ int minIndexFound = Integer.MAX_VALUE; ++ Set minSCC = null; ++ for (Set scc : foundSCCs) { ++ for (V v : scc) { ++ int t = toI(v); ++ if (t < minIndexFound) { ++ minIndexFound = t; ++ minSCC = scc; ++ } ++ } ++ } ++ if (minSCC == null) { ++ return null; ++ } ++ ++ // build a graph for the SCC found ++ MutableGraph dependencyGraph = GraphBuilder.directed().allowsSelfLoops(true).build(); ++ ++ for (V v : minSCC) { ++ for (V w : minSCC) { ++ if (graph.hasEdgeConnecting(v, w)) { ++ dependencyGraph.putEdge(v, w); ++ } ++ } ++ } ++ ++ Pair, Integer> result = Pair.of(dependencyGraph, minIndexFound); ++ clearMinSCCState(); ++ return result; ++ } ++ ++ private List> findSCCS(int startIndex) ++ { ++ // Find SCCs in the subgraph induced ++ // by vertices startIndex and beyond. ++ // A call to StrongConnectivityAlgorithm ++ // would be too expensive because of the ++ // need to materialize the subgraph. ++ // So - do a local search by the Tarjan's ++ // algorithm and pretend that vertices ++ // with an index smaller than startIndex ++ // do not exist. ++ for (V v : graph.nodes()) { ++ int vI = toI(v); ++ if (vI < startIndex) { ++ continue; ++ } ++ if (!vIndex.containsKey(v)) { ++ getSCCs(startIndex, vI); ++ } ++ } ++ List> result = foundSCCs; ++ foundSCCs = null; ++ return result; ++ } ++ ++ private void getSCCs(int startIndex, int vertexIndex) ++ { ++ V vertex = toV(vertexIndex); ++ vIndex.put(vertex, index); ++ vLowlink.put(vertex, index); ++ index++; ++ path.push(vertex); ++ pathSet.add(vertex); ++ ++ Set edges = graph.successors(vertex); ++ for (V successor : edges) { ++ int successorIndex = toI(successor); ++ if (successorIndex < startIndex) { ++ continue; ++ } ++ if (!vIndex.containsKey(successor)) { ++ getSCCs(startIndex, successorIndex); ++ vLowlink.put(vertex, Math.min(vLowlink.get(vertex), vLowlink.get(successor))); ++ } else if (pathSet.contains(successor)) { ++ vLowlink.put(vertex, Math.min(vLowlink.get(vertex), vIndex.get(successor))); ++ } ++ } ++ if (vLowlink.get(vertex).equals(vIndex.get(vertex))) { ++ Set result = new HashSet<>(); ++ V temp; ++ do { ++ temp = path.pop(); ++ pathSet.remove(temp); ++ result.add(temp); ++ } while (!vertex.equals(temp)); ++ if (result.size() == 1) { ++ V v = result.iterator().next(); ++ if (graph.edges().contains(vertex)) { ++ foundSCCs.add(result); ++ } ++ } else { ++ foundSCCs.add(result); ++ } ++ } ++ } ++ ++ private boolean findCyclesInSCG(int startIndex, int vertexIndex, Graph scg) ++ { ++ /* ++ * Find cycles in a strongly connected graph per Johnson. ++ */ ++ boolean foundCycle = false; ++ V vertex = toV(vertexIndex); ++ stack.push(vertex); ++ blocked.add(vertex); ++ ++ for (V successor : scg.successors(vertex)) { ++ int successorIndex = toI(successor); ++ if (successorIndex == startIndex) { ++ List cycle = new ArrayList<>(stack.size()); ++ stack.descendingIterator().forEachRemaining(cycle::add); ++ cycleConsumer.accept(cycle); ++ foundCycle = true; ++ } else if (!blocked.contains(successor)) { ++ boolean gotCycle = findCyclesInSCG(startIndex, successorIndex, scg); ++ foundCycle = foundCycle || gotCycle; ++ } ++ } ++ if (foundCycle) { ++ unblock(vertex); ++ } else { ++ for (V w : scg.successors(vertex)) { ++ Set bSet = getBSet(w); ++ bSet.add(vertex); ++ } ++ } ++ stack.pop(); ++ return foundCycle; ++ } ++ ++ private void unblock(V vertex) ++ { ++ blocked.remove(vertex); ++ Set bSet = getBSet(vertex); ++ while (bSet.size() > 0) { ++ V w = bSet.iterator().next(); ++ bSet.remove(w); ++ if (blocked.contains(w)) { ++ unblock(w); ++ } ++ } ++ } ++ ++ @SuppressWarnings("unchecked") ++ private void initState(Consumer> consumer) ++ { ++ cycleConsumer = consumer; ++ iToV = (V[]) graph.nodes().toArray(); ++ vToI = new HashMap<>(); ++ blocked = new HashSet<>(); ++ bSets = new HashMap<>(); ++ stack = new ArrayDeque<>(); ++ ++ for (int i = 0; i < iToV.length; i++) { ++ vToI.put(iToV[i], i); ++ } ++ } ++ ++ private void clearState() ++ { ++ cycleConsumer = null; ++ iToV = null; ++ vToI = null; ++ blocked = null; ++ bSets = null; ++ stack = null; ++ } ++ ++ private void initMinSCGState() ++ { ++ index = 0; ++ foundSCCs = new ArrayList<>(); ++ vIndex = new HashMap<>(); ++ vLowlink = new HashMap<>(); ++ path = new ArrayDeque<>(); ++ pathSet = new HashSet<>(); ++ } ++ ++ private void clearMinSCCState() ++ { ++ index = 0; ++ foundSCCs = null; ++ vIndex = null; ++ vLowlink = null; ++ path = null; ++ pathSet = null; ++ } ++ ++ private Integer toI(V vertex) ++ { ++ return vToI.get(vertex); ++ } ++ ++ private V toV(Integer i) ++ { ++ return iToV[i]; ++ } ++ ++ private Set getBSet(V v) ++ { ++ // B sets typically not all needed, ++ // so instantiate lazily. ++ return bSets.computeIfAbsent(v, k -> new HashSet<>()); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/LegacyPluginLoadingStrategy.java b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/LegacyPluginLoadingStrategy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8bc11d7e9341a31382c1b055565cc8d5fd3203ea +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/LegacyPluginLoadingStrategy.java +@@ -0,0 +1,260 @@ ++package io.papermc.paper.plugin.entrypoint.strategy; ++ ++import com.google.common.graph.GraphBuilder; ++import com.google.common.graph.MutableGraph; ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.entrypoint.dependency.GraphDependencyContext; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import org.bukkit.plugin.UnknownDependencyException; ++ ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.Iterator; ++import java.util.LinkedList; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++@SuppressWarnings("UnstableApiUsage") ++public class LegacyPluginLoadingStrategy implements ProviderLoadingStrategy { ++ ++ private static final Logger LOGGER = Logger.getLogger("LegacyPluginLoadingStrategy"); ++ private final ProviderConfiguration configuration; ++ ++ public LegacyPluginLoadingStrategy(ProviderConfiguration onLoad) { ++ this.configuration = onLoad; ++ } ++ ++ @Override ++ public List loadProviders(List> providers) { ++ List javapluginsLoaded = new ArrayList<>(); ++ MutableGraph dependencyGraph = GraphBuilder.directed().build(); ++ GraphDependencyContext dependencyContext = new GraphDependencyContext(dependencyGraph); ++ ++ Map> providersToLoad = new HashMap<>(); ++ Set loadedPlugins = new HashSet<>(); ++ Map pluginsProvided = new HashMap<>(); ++ Map> dependencies = new HashMap<>(); ++ Map> softDependencies = new HashMap<>(); ++ ++ for (PluginProvider provider : providers) { ++ PluginMeta configuration = provider.getMeta(); ++ ++ PluginProvider replacedProvider = providersToLoad.put(configuration.getName(), provider); ++ if (replacedProvider != null) { ++ LOGGER.severe(String.format( ++ "Ambiguous plugin name `%s' for files `%s' and `%s' in `%s'", ++ configuration.getName(), ++ provider.getSource(), ++ replacedProvider.getSource(), ++ replacedProvider.getParentSource() ++ )); ++ } ++ ++ String removedProvided = pluginsProvided.remove(configuration.getName()); ++ if (removedProvided != null) { ++ LOGGER.warning(String.format( ++ "Ambiguous plugin name `%s'. It is also provided by `%s'", ++ configuration.getName(), ++ removedProvided ++ )); ++ } ++ ++ for (String provided : configuration.getProvidedPlugins()) { ++ PluginProvider pluginProvider = providersToLoad.get(provided); ++ ++ if (pluginProvider != null) { ++ LOGGER.warning(String.format( ++ "`%s provides `%s' while this is also the name of `%s' in `%s'", ++ provider.getSource(), ++ provided, ++ pluginProvider.getSource(), ++ provider.getParentSource() ++ )); ++ } else { ++ String replacedPlugin = pluginsProvided.put(provided, configuration.getName()); ++ if (replacedPlugin != null) { ++ LOGGER.warning(String.format( ++ "`%s' is provided by both `%s' and `%s'", ++ provided, ++ configuration.getName(), ++ replacedPlugin ++ )); ++ } ++ } ++ } ++ ++ Collection softDependencySet = this.configuration.optionalDependencies(provider); ++ if (softDependencySet != null && !softDependencySet.isEmpty()) { ++ if (softDependencies.containsKey(configuration.getName())) { ++ // Duplicates do not matter, they will be removed together if applicable ++ softDependencies.get(configuration.getName()).addAll(softDependencySet); ++ } else { ++ softDependencies.put(configuration.getName(), new LinkedList(softDependencySet)); ++ } ++ ++ for (String depend : softDependencySet) { ++ dependencyGraph.putEdge(configuration.getName(), depend); ++ } ++ } ++ ++ Collection dependencySet = this.configuration.requiredDependencies(provider); ++ if (dependencySet != null && !dependencySet.isEmpty()) { ++ dependencies.put(configuration.getName(), new LinkedList(dependencySet)); ++ ++ for (String depend : dependencySet) { ++ dependencyGraph.putEdge(configuration.getName(), depend); ++ } ++ } ++ ++ Collection loadBeforeSet = this.configuration.loadBeforeDependencies(provider); ++ if (loadBeforeSet != null && !loadBeforeSet.isEmpty()) { ++ for (String loadBeforeTarget : loadBeforeSet) { ++ if (softDependencies.containsKey(loadBeforeTarget)) { ++ softDependencies.get(loadBeforeTarget).add(configuration.getName()); ++ } else { ++ // softDependencies is never iterated, so 'ghost' plugins aren't an issue ++ Collection shortSoftDependency = new LinkedList(); ++ shortSoftDependency.add(configuration.getName()); ++ softDependencies.put(loadBeforeTarget, shortSoftDependency); ++ } ++ ++ dependencyGraph.putEdge(loadBeforeTarget, configuration.getName()); ++ } ++ } ++ } ++ ++ while (!providersToLoad.isEmpty()) { ++ boolean missingDependency = true; ++ Iterator>> providerIterator = providersToLoad.entrySet().iterator(); ++ ++ while (providerIterator.hasNext()) { ++ Map.Entry> entry = providerIterator.next(); ++ String providerIdentifier = entry.getKey(); ++ ++ if (dependencies.containsKey(providerIdentifier)) { ++ Iterator dependencyIterator = dependencies.get(providerIdentifier).iterator(); ++ final Set missingHardDependencies = new HashSet<>(dependencies.get(providerIdentifier).size()); // Paper - list all missing hard depends ++ ++ while (dependencyIterator.hasNext()) { ++ String dependency = dependencyIterator.next(); ++ ++ // Dependency loaded ++ if (loadedPlugins.contains(dependency)) { ++ dependencyIterator.remove(); ++ ++ // We have a dependency not found ++ } else if (!providersToLoad.containsKey(dependency) && !pluginsProvided.containsKey(dependency)) { ++ // Paper start ++ missingHardDependencies.add(dependency); ++ } ++ } ++ if (!missingHardDependencies.isEmpty()) { ++ // Paper end ++ missingDependency = false; ++ providerIterator.remove(); ++ pluginsProvided.values().removeIf(s -> s.equals(providerIdentifier)); // Paper - remove provided plugins ++ softDependencies.remove(providerIdentifier); ++ dependencies.remove(providerIdentifier); ++ ++ LOGGER.log( ++ Level.SEVERE, ++ "Could not load '" + entry.getValue().getSource() + "' in folder '" + entry.getValue().getParentSource() + "'", // Paper ++ new UnknownDependencyException(missingHardDependencies, providerIdentifier)); // Paper ++ } ++ ++ if (dependencies.containsKey(providerIdentifier) && dependencies.get(providerIdentifier).isEmpty()) { ++ dependencies.remove(providerIdentifier); ++ } ++ } ++ if (softDependencies.containsKey(providerIdentifier)) { ++ Iterator softDependencyIterator = softDependencies.get(providerIdentifier).iterator(); ++ ++ while (softDependencyIterator.hasNext()) { ++ String softDependency = softDependencyIterator.next(); ++ ++ // Soft depend is no longer around ++ if (!providersToLoad.containsKey(softDependency) && !pluginsProvided.containsKey(softDependency)) { ++ softDependencyIterator.remove(); ++ } ++ } ++ ++ if (softDependencies.get(providerIdentifier).isEmpty()) { ++ softDependencies.remove(providerIdentifier); ++ } ++ } ++ if (!(dependencies.containsKey(providerIdentifier) || softDependencies.containsKey(providerIdentifier)) && providersToLoad.containsKey(providerIdentifier)) { ++ // We're clear to load, no more soft or hard dependencies left ++ PluginProvider file = providersToLoad.get(providerIdentifier); ++ providerIterator.remove(); ++ pluginsProvided.values().removeIf(s -> s.equals(providerIdentifier)); // Paper - remove provided plugins ++ missingDependency = false; ++ ++ try { ++ this.configuration.applyContext(file, dependencyContext); ++ T loadedPlugin = file.createInstance(); ++ ++ if (this.configuration.load(file, loadedPlugin)) { ++ loadedPlugins.add(file.getMeta().getName()); ++ loadedPlugins.addAll(file.getMeta().getProvidedPlugins()); ++ javapluginsLoaded.add(loadedPlugin); ++ } ++ ++ } catch (Exception ex) { ++ LOGGER.log(Level.SEVERE, "Could not load '" + file.getSource() + "' in folder '" + file.getParentSource() + "'", ex); // Paper ++ } ++ } ++ } ++ ++ if (missingDependency) { ++ // We now iterate over plugins until something loads ++ // This loop will ignore soft dependencies ++ providerIterator = providersToLoad.entrySet().iterator(); ++ ++ while (providerIterator.hasNext()) { ++ Map.Entry> entry = providerIterator.next(); ++ String plugin = entry.getKey(); ++ ++ if (!dependencies.containsKey(plugin)) { ++ softDependencies.remove(plugin); ++ missingDependency = false; ++ PluginProvider file = entry.getValue(); ++ providerIterator.remove(); ++ ++ try { ++ this.configuration.applyContext(file, dependencyContext); ++ T loadedPlugin = file.createInstance(); ++ ++ if (this.configuration.load(file, loadedPlugin)) { ++ loadedPlugins.add(file.getMeta().getName()); ++ loadedPlugins.addAll(file.getMeta().getProvidedPlugins()); ++ javapluginsLoaded.add(loadedPlugin); ++ } ++ break; ++ } catch (Exception ex) { ++ LOGGER.log(Level.SEVERE, "Could not load '" + file.getSource() + "' in folder '" + file.getParentSource() + "'", ex); // Paper ++ } ++ } ++ } ++ // We have no plugins left without a depend ++ if (missingDependency) { ++ softDependencies.clear(); ++ dependencies.clear(); ++ Iterator> failedPluginIterator = providersToLoad.values().iterator(); ++ ++ while (failedPluginIterator.hasNext()) { ++ PluginProvider file = failedPluginIterator.next(); ++ failedPluginIterator.remove(); ++ LOGGER.log(Level.SEVERE, "Could not load '" + file.getSource() + "' in folder '" + file.getParentSource() + "': circular dependency detected"); // Paper ++ } ++ } ++ } ++ } ++ ++ return javapluginsLoaded; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ModernPluginLoadingStrategy.java b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ModernPluginLoadingStrategy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a0363af157131a2b42c00028a260e9c3d3c543de +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ModernPluginLoadingStrategy.java +@@ -0,0 +1,143 @@ ++package io.papermc.paper.plugin.entrypoint.strategy; ++ ++import com.google.common.collect.Lists; ++import com.google.common.graph.GraphBuilder; ++import com.google.common.graph.MutableGraph; ++import com.mojang.logging.LogUtils; ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.entrypoint.dependency.DependencyUtil; ++import io.papermc.paper.plugin.entrypoint.dependency.GraphDependencyContext; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import org.bukkit.plugin.UnknownDependencyException; ++import org.slf4j.Logger; ++ ++import java.util.ArrayList; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++ ++@SuppressWarnings("UnstableApiUsage") ++public class ModernPluginLoadingStrategy implements ProviderLoadingStrategy { ++ ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ private final ProviderConfiguration configuration; ++ ++ public ModernPluginLoadingStrategy(ProviderConfiguration onLoad) { ++ this.configuration = onLoad; ++ } ++ ++ @Override ++ public List loadProviders(List> pluginProviders) { ++ MutableGraph dependencyGraph = GraphBuilder.directed().build(); ++ Map> providerMap = new HashMap<>(); ++ List> validatedProviders = new ArrayList<>(); ++ ++ // Populate provider map ++ for (PluginProvider provider : pluginProviders) { ++ PluginMeta providerConfig = provider.getMeta(); ++ PluginProviderEntry entry = new PluginProviderEntry<>(provider); ++ ++ PluginProviderEntry replacedProvider = providerMap.put(providerConfig.getName(), entry); ++ if (replacedProvider != null) { ++ LOGGER.error(String.format( ++ "Ambiguous plugin name '%s' for files '%s' and '%s' in '%s'", ++ providerConfig.getName(), ++ provider.getSource(), ++ replacedProvider.provider.getSource(), ++ replacedProvider.provider.getParentSource() ++ )); ++ } ++ ++ for (String extra : providerConfig.getProvidedPlugins()) { ++ PluginProviderEntry replacedExtraProvider = providerMap.putIfAbsent(extra, entry); ++ if (replacedExtraProvider != null) { ++ LOGGER.warn(String.format( ++ "`%s' is provided by both `%s' and `%s'", ++ extra, ++ providerConfig.getName(), ++ replacedExtraProvider.provider.getMeta().getName() ++ )); ++ } ++ } ++ } ++ ++ // Validate providers, ensuring all of them have valid dependencies. Removing those who are invalid ++ for (PluginProvider provider : pluginProviders) { ++ PluginMeta configuration = provider.getMeta(); ++ ++ // Populate missing dependencies to capture if there are multiple missing ones. ++ List missingDependencies = new ArrayList<>(); ++ for (String hardDependency : this.configuration.requiredDependencies(provider)) { ++ if (!providerMap.containsKey(hardDependency)) { ++ missingDependencies.add(hardDependency); ++ } ++ } ++ ++ if (missingDependencies.isEmpty()) { ++ validatedProviders.add(provider); ++ } else { ++ LOGGER.error("Could not load '%s' in '%s'".formatted(provider.getSource(), provider.getParentSource()), new UnknownDependencyException(missingDependencies, configuration.getName())); // Paper ++ // Because the validator is invalid, remove it from the provider map ++ providerMap.remove(configuration.getName()); ++ } ++ } ++ ++ for (PluginProvider validated : validatedProviders) { ++ PluginMeta configuration = validated.getMeta(); ++ ++ // Build a validated provider's dependencies into the graph ++ DependencyUtil.buildDependencyGraph(dependencyGraph, configuration); ++ ++ // Add the provided plugins to the graph as well ++ for (String provides : configuration.getProvidedPlugins()) { ++ DependencyUtil.addProvidedPlugin(dependencyGraph, configuration.getName(), provides); ++ } ++ } ++ ++ // Reverse the topographic search to let us see which providers we can load first. ++ List reversedTopographicSort; ++ try { ++ reversedTopographicSort = Lists.reverse(TopographicGraphSorter.sortGraph(dependencyGraph)); ++ } catch (TopographicGraphSorter.GraphCycleException exception) { ++ throw new PluginGraphCycleException(new JohnsonSimpleCycles<>(dependencyGraph).findSimpleCycles()); ++ } ++ ++ GraphDependencyContext graphDependencyContext = new GraphDependencyContext(dependencyGraph); ++ List loadedPlugins = new ArrayList<>(); ++ for (String providerIdentifier : reversedTopographicSort) { ++ // It's possible that this will be null because the above dependencies for soft/load before aren't validated if they exist. ++ // The graph could be MutableGraph>, but we would have to check if each dependency exists there... just ++ // nicer to do it here TBH. ++ PluginProviderEntry retrievedProviderEntry = providerMap.get(providerIdentifier); ++ if (retrievedProviderEntry == null || retrievedProviderEntry.provided) { ++ // OR if this was already provided (most likely from a plugin that already "provides" that dependency) ++ // This won't matter since the provided plugin is loaded as a dependency, meaning it should have been loaded correctly anyways ++ continue; // Skip provider that doesn't exist.... ++ } ++ retrievedProviderEntry.provided = true; ++ PluginProvider retrievedProvider = retrievedProviderEntry.provider; ++ try { ++ this.configuration.applyContext(retrievedProvider, graphDependencyContext); ++ ++ T instance = retrievedProvider.createInstance(); ++ if (this.configuration.load(retrievedProvider, instance)) { ++ loadedPlugins.add(instance); ++ } ++ } catch (Exception ex) { ++ LOGGER.error("Could not load plugin '%s' in folder '%s'".formatted(retrievedProvider.getFileName(), retrievedProvider.getParentSource()), ex); // Paper ++ } ++ } ++ ++ return loadedPlugins; ++ } ++ ++ private static class PluginProviderEntry { ++ ++ private final PluginProvider provider; ++ private boolean provided; ++ ++ private PluginProviderEntry(PluginProvider provider) { ++ this.provider = provider; ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/PluginGraphCycleException.java b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/PluginGraphCycleException.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2ea978ac957849260e7ca69c9ff56588d0ccc41b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/PluginGraphCycleException.java +@@ -0,0 +1,19 @@ ++package io.papermc.paper.plugin.entrypoint.strategy; ++ ++import java.util.List; ++ ++/** ++ * Indicates a dependency cycle within a provider loading sequence. ++ */ ++public class PluginGraphCycleException extends RuntimeException { ++ ++ private final List> cycles; ++ ++ public PluginGraphCycleException(List> cycles) { ++ this.cycles = cycles; ++ } ++ ++ public List> getCycles() { ++ return this.cycles; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderConfiguration.java b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5e18616160014d70df2b539d7e65bb003ac7a4b7 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderConfiguration.java +@@ -0,0 +1,26 @@ ++package io.papermc.paper.plugin.entrypoint.strategy; ++ ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++ ++import java.util.List; ++ ++/** ++ * Used to share code with the modern and legacy plugin load strategy. ++ * ++ * @param ++ */ ++public interface ProviderConfiguration { ++ ++ void applyContext(PluginProvider provider, DependencyContext dependencyContext); ++ ++ boolean load(PluginProvider provider, T provided); ++ ++ List requiredDependencies(PluginProvider provider); ++ ++ List optionalDependencies(PluginProvider provider); ++ ++ List loadBeforeDependencies(PluginProvider provider); ++ ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderLoadingStrategy.java b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderLoadingStrategy.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e8d5ce5f137a960e353c6722e1f20f9b342d4ba5 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderLoadingStrategy.java +@@ -0,0 +1,16 @@ ++package io.papermc.paper.plugin.entrypoint.strategy; ++ ++import io.papermc.paper.plugin.provider.PluginProvider; ++ ++import java.util.List; ++ ++/** ++ * Used by a {@link io.papermc.paper.plugin.storage.SimpleProviderStorage} to load plugin providers in a certain order. ++ *

++ * Returns providers loaded. ++ * @param

provider type ++ */ ++public interface ProviderLoadingStrategy

{ ++ ++ List

loadProviders(List> providers); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/TopographicGraphSorter.java b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/TopographicGraphSorter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0720af0d48b39ca46e7d3aba08d7b359ed053461 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/TopographicGraphSorter.java +@@ -0,0 +1,61 @@ ++package io.papermc.paper.plugin.entrypoint.strategy; ++ ++import com.google.common.graph.Graph; ++ ++import java.util.ArrayDeque; ++import java.util.ArrayList; ++import java.util.Deque; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++ ++public class TopographicGraphSorter { ++ ++ // Topographically sort dependencies ++ public static List sortGraph(Graph graph) throws PluginGraphCycleException { ++ List sorted = new ArrayList<>(); ++ Deque roots = new ArrayDeque<>(); ++ Map nonRoots = new HashMap<>(); ++ ++ for (N node : graph.nodes()) { ++ // Is a node being referred to by any other nodes? ++ int degree = graph.inDegree(node); ++ if (degree == 0) { ++ // Is a root ++ roots.add(node); ++ } else { ++ // Isn't a root, the number represents how many nodes connect to it. ++ nonRoots.put(node, degree); ++ } ++ } ++ ++ // Pick from nodes that aren't referred to anywhere else ++ while (!roots.isEmpty()) { ++ N next = roots.remove(); ++ ++ for (N successor : graph.successors(next)) { ++ // Traverse through, moving down a degree ++ int newInDegree = nonRoots.get(successor) - 1; ++ ++ if (newInDegree == 0) { ++ nonRoots.remove(successor); ++ roots.add(successor); ++ } else { ++ nonRoots.put(successor, newInDegree); ++ } ++ ++ } ++ sorted.add(next); ++ } ++ ++ if (!nonRoots.isEmpty()) { ++ throw new GraphCycleException(); ++ } ++ ++ return sorted; ++ } ++ ++ public static class GraphCycleException extends RuntimeException { ++ ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d49dd7d17ce7ac17efb19b33de163015787213f7 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java +@@ -0,0 +1,64 @@ ++package io.papermc.paper.plugin.loader; ++ ++import io.papermc.paper.plugin.bootstrap.PluginProviderContext; ++import io.papermc.paper.plugin.loader.library.ClassPathLibrary; ++import io.papermc.paper.plugin.loader.library.PaperLibraryStore; ++import io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader; ++import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; ++import org.jetbrains.annotations.NotNull; ++ ++import java.io.IOException; ++import java.net.MalformedURLException; ++import java.net.URL; ++import java.net.URLClassLoader; ++import java.nio.file.Path; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.jar.JarFile; ++import java.util.logging.Logger; ++ ++public class PaperClasspathBuilder implements PluginClasspathBuilder { ++ ++ private final List libraries = new ArrayList<>(); ++ ++ private final PluginProviderContext context; ++ ++ public PaperClasspathBuilder(PluginProviderContext context) { ++ this.context = context; ++ } ++ ++ @Override ++ public @NotNull PluginProviderContext getContext() { ++ return this.context; ++ } ++ ++ @Override ++ public @NotNull PluginClasspathBuilder addLibrary(@NotNull ClassPathLibrary classPathLibrary) { ++ this.libraries.add(classPathLibrary); ++ return this; ++ } ++ ++ public PaperPluginClassLoader buildClassLoader(Logger logger, Path source, JarFile jarFile, PaperPluginMeta configuration) { ++ PaperLibraryStore paperLibraryStore = new PaperLibraryStore(); ++ for (ClassPathLibrary library : this.libraries) { ++ library.register(paperLibraryStore); ++ } ++ ++ List paths = paperLibraryStore.getPaths(); ++ URL[] urls = new URL[paths.size()]; ++ for (int i = 0; i < paths.size(); i++) { ++ Path path = paperLibraryStore.getPaths().get(i); ++ try { ++ urls[i] = path.toUri().toURL(); ++ } catch (MalformedURLException e) { ++ throw new AssertionError(e); ++ } ++ } ++ ++ try { ++ return new PaperPluginClassLoader(logger, source, jarFile, configuration, this.getClass().getClassLoader(), new URLClassLoader(urls)); ++ } catch (IOException exception) { ++ throw new RuntimeException(exception); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/loader/library/PaperLibraryStore.java b/src/main/java/io/papermc/paper/plugin/loader/library/PaperLibraryStore.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5fcce65009f715d46dd3013f1f92ec8393d66e15 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/loader/library/PaperLibraryStore.java +@@ -0,0 +1,21 @@ ++package io.papermc.paper.plugin.loader.library; ++ ++import org.jetbrains.annotations.NotNull; ++ ++import java.nio.file.Path; ++import java.util.ArrayList; ++import java.util.List; ++ ++public class PaperLibraryStore implements LibraryStore { ++ ++ private final List paths = new ArrayList<>(); ++ ++ @Override ++ public void addLibrary(@NotNull Path library) { ++ this.paths.add(library); ++ } ++ ++ public List getPaths() { ++ return this.paths; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/manager/MultiRuntimePluginProviderStorage.java b/src/main/java/io/papermc/paper/plugin/manager/MultiRuntimePluginProviderStorage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a47c0c1dedf5f8cd7006b170639676429c17d74d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/manager/MultiRuntimePluginProviderStorage.java +@@ -0,0 +1,49 @@ ++package io.papermc.paper.plugin.manager; ++ ++import com.mojang.logging.LogUtils; ++import io.papermc.paper.plugin.entrypoint.Entrypoint; ++import io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent; ++import io.papermc.paper.plugin.storage.ServerPluginProviderStorage; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.slf4j.Logger; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++public class MultiRuntimePluginProviderStorage extends ServerPluginProviderStorage { ++ ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ private final List provided = new ArrayList<>(); ++ ++ @Override ++ public void register(PluginProvider provider) { ++ if (provider instanceof PaperPluginParent.PaperServerPluginProvider) { ++ LOGGER.warn("Skipping loading of paper plugin requested from SimplePluginManager."); ++ return; ++ } ++ super.register(provider); ++ /* ++ Register the provider into the server entrypoint, this allows it to show in /plugins correctly. Generally it might be better in the future to make a separate storage, ++ as putting it into the entrypoint handlers doesn't make much sense. ++ */ ++ LaunchEntryPointHandler.INSTANCE.register(Entrypoint.PLUGIN, provider); ++ } ++ ++ @Override ++ public void processProvided(JavaPlugin provided) { ++ super.processProvided(provided); ++ this.provided.add(provided); ++ } ++ ++ @Override ++ public boolean exitOnCycleDependencies() { ++ return false; ++ } ++ ++ public List getLoaded() { ++ return this.provided; ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/manager/NormalPaperPermissionManager.java b/src/main/java/io/papermc/paper/plugin/manager/NormalPaperPermissionManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6f6aaab295018017565ba27d6958a1f5c7b69bc8 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/manager/NormalPaperPermissionManager.java +@@ -0,0 +1,43 @@ ++package io.papermc.paper.plugin.manager; ++ ++import org.bukkit.permissions.Permissible; ++import org.bukkit.permissions.Permission; ++ ++import java.util.HashMap; ++import java.util.LinkedHashMap; ++import java.util.LinkedHashSet; ++import java.util.Map; ++import java.util.Set; ++ ++class NormalPaperPermissionManager extends PaperPermissionManager { ++ ++ private final Map permissions = new HashMap<>(); ++ private final Map> defaultPerms = new LinkedHashMap<>(); ++ private final Map> permSubs = new HashMap<>(); ++ private final Map> defSubs = new HashMap<>(); ++ ++ public NormalPaperPermissionManager() { ++ this.defaultPerms().put(true, new LinkedHashSet<>()); ++ this.defaultPerms().put(false, new LinkedHashSet<>()); ++ } ++ ++ @Override ++ public Map permissions() { ++ return this.permissions; ++ } ++ ++ @Override ++ public Map> defaultPerms() { ++ return this.defaultPerms; ++ } ++ ++ @Override ++ public Map> permSubs() { ++ return this.permSubs; ++ } ++ ++ @Override ++ public Map> defSubs() { ++ return this.defSubs; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7ce9ebba8ce304d1f3f21d4f15ee5f3560d7700b +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/manager/PaperEventManager.java +@@ -0,0 +1,194 @@ ++package io.papermc.paper.plugin.manager; ++ ++import co.aikar.timings.TimedEventExecutor; ++import com.destroystokyo.paper.event.server.ServerExceptionEvent; ++import com.destroystokyo.paper.exception.ServerEventException; ++import com.google.common.collect.Sets; ++import org.bukkit.Server; ++import org.bukkit.Warning; ++import org.bukkit.event.Event; ++import org.bukkit.event.EventHandler; ++import org.bukkit.event.EventPriority; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.Listener; ++import org.bukkit.plugin.AuthorNagException; ++import org.bukkit.plugin.EventExecutor; ++import org.bukkit.plugin.IllegalPluginAccessException; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.RegisteredListener; ++import org.jetbrains.annotations.NotNull; ++ ++import java.lang.reflect.Method; ++import java.util.Arrays; ++import java.util.HashMap; ++import java.util.HashSet; ++import java.util.Map; ++import java.util.Set; ++import java.util.logging.Level; ++ ++class PaperEventManager { ++ ++ private final Server server; ++ ++ public PaperEventManager(Server server) { ++ this.server = server; ++ } ++ ++ // SimplePluginManager ++ public void callEvent(@NotNull Event event) { ++ if (event.isAsynchronous() && this.server.isPrimaryThread()) { ++ throw new IllegalStateException(event.getEventName() + " may only be triggered asynchronously."); ++ } else if (!event.isAsynchronous() && !this.server.isPrimaryThread() && !this.server.isStopping()) { ++ throw new IllegalStateException(event.getEventName() + " may only be triggered synchronously."); ++ } ++ ++ HandlerList handlers = event.getHandlers(); ++ RegisteredListener[] listeners = handlers.getRegisteredListeners(); ++ ++ for (RegisteredListener registration : listeners) { ++ if (!registration.getPlugin().isEnabled()) { ++ continue; ++ } ++ ++ try { ++ registration.callEvent(event); ++ } catch (AuthorNagException ex) { ++ Plugin plugin = registration.getPlugin(); ++ ++ if (plugin.isNaggable()) { ++ plugin.setNaggable(false); ++ ++ this.server.getLogger().log(Level.SEVERE, String.format( ++ "Nag author(s): '%s' of '%s' about the following: %s", ++ plugin.getPluginMeta().getAuthors(), ++ plugin.getPluginMeta().getDisplayName(), ++ ex.getMessage() ++ )); ++ } ++ } catch (Throwable ex) { ++ String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getPluginMeta().getDisplayName(); ++ this.server.getLogger().log(Level.SEVERE, msg, ex); ++ if (!(event instanceof ServerExceptionEvent)) { // We don't want to cause an endless event loop ++ this.callEvent(new ServerExceptionEvent(new ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event))); ++ } ++ } ++ } ++ } ++ ++ public void registerEvents(@NotNull Listener listener, @NotNull Plugin plugin) { ++ if (!plugin.isEnabled()) { ++ throw new IllegalPluginAccessException("Plugin attempted to register " + listener + " while not enabled"); ++ } ++ ++ for (Map.Entry, Set> entry : this.createRegisteredListeners(listener, plugin).entrySet()) { ++ this.getEventListeners(this.getRegistrationClass(entry.getKey())).registerAll(entry.getValue()); ++ } ++ ++ } ++ ++ public void registerEvent(@NotNull Class event, @NotNull Listener listener, @NotNull EventPriority priority, @NotNull EventExecutor executor, @NotNull Plugin plugin) { ++ this.registerEvent(event, listener, priority, executor, plugin, false); ++ } ++ ++ public void registerEvent(@NotNull Class event, @NotNull Listener listener, @NotNull EventPriority priority, @NotNull EventExecutor executor, @NotNull Plugin plugin, boolean ignoreCancelled) { ++ if (!plugin.isEnabled()) { ++ throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled"); ++ } ++ ++ executor = new TimedEventExecutor(executor, plugin, null, event); ++ this.getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled)); ++ } ++ ++ @NotNull ++ private HandlerList getEventListeners(@NotNull Class type) { ++ try { ++ Method method = this.getRegistrationClass(type).getDeclaredMethod("getHandlerList"); ++ method.setAccessible(true); ++ return (HandlerList) method.invoke(null); ++ } catch (Exception e) { ++ throw new IllegalPluginAccessException(e.toString()); ++ } ++ } ++ ++ @NotNull ++ private Class getRegistrationClass(@NotNull Class clazz) { ++ try { ++ clazz.getDeclaredMethod("getHandlerList"); ++ return clazz; ++ } catch (NoSuchMethodException e) { ++ if (clazz.getSuperclass() != null ++ && !clazz.getSuperclass().equals(Event.class) ++ && Event.class.isAssignableFrom(clazz.getSuperclass())) { ++ return this.getRegistrationClass(clazz.getSuperclass().asSubclass(Event.class)); ++ } else { ++ throw new IllegalPluginAccessException("Unable to find handler list for event " + clazz.getName() + ". Static getHandlerList method required!"); ++ } ++ } ++ } ++ ++ // JavaPluginLoader ++ @NotNull ++ public Map, Set> createRegisteredListeners(@NotNull Listener listener, @NotNull final Plugin plugin) { ++ Map, Set> ret = new HashMap<>(); ++ ++ Set methods; ++ try { ++ Class listenerClazz = listener.getClass(); ++ methods = Sets.union( ++ Set.of(listenerClazz.getMethods()), ++ Set.of(listenerClazz.getDeclaredMethods()) ++ ); ++ } catch (NoClassDefFoundError e) { ++ plugin.getLogger().severe("Failed to register events for " + listener.getClass() + " because " + e.getMessage() + " does not exist."); ++ return ret; ++ } ++ ++ for (final Method method : methods) { ++ final EventHandler eh = method.getAnnotation(EventHandler.class); ++ if (eh == null) continue; ++ // Do not register bridge or synthetic methods to avoid event duplication ++ // Fixes SPIGOT-893 ++ if (method.isBridge() || method.isSynthetic()) { ++ continue; ++ } ++ final Class checkClass; ++ if (method.getParameterTypes().length != 1 || !Event.class.isAssignableFrom(checkClass = method.getParameterTypes()[0])) { ++ plugin.getLogger().severe(plugin.getPluginMeta().getDisplayName() + " attempted to register an invalid EventHandler method signature \"" + method.toGenericString() + "\" in " + listener.getClass()); ++ continue; ++ } ++ final Class eventClass = checkClass.asSubclass(Event.class); ++ method.setAccessible(true); ++ Set eventSet = ret.computeIfAbsent(eventClass, k -> new HashSet<>()); ++ ++ for (Class clazz = eventClass; Event.class.isAssignableFrom(clazz); clazz = clazz.getSuperclass()) { ++ // This loop checks for extending deprecated events ++ if (clazz.getAnnotation(Deprecated.class) != null) { ++ Warning warning = clazz.getAnnotation(Warning.class); ++ Warning.WarningState warningState = this.server.getWarningState(); ++ if (!warningState.printFor(warning)) { ++ break; ++ } ++ plugin.getLogger().log( ++ Level.WARNING, ++ String.format( ++ "\"%s\" has registered a listener for %s on method \"%s\", but the event is Deprecated. \"%s\"; please notify the authors %s.", ++ plugin.getPluginMeta().getDisplayName(), ++ clazz.getName(), ++ method.toGenericString(), ++ (warning != null && warning.reason().length() != 0) ? warning.reason() : "Server performance will be affected", ++ Arrays.toString(plugin.getPluginMeta().getAuthors().toArray())), ++ warningState == Warning.WarningState.ON ? new AuthorNagException(null) : null); ++ break; ++ } ++ } ++ ++ EventExecutor executor = new TimedEventExecutor(EventExecutor.create(method, eventClass), plugin, method, eventClass); ++ eventSet.add(new RegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); ++ } ++ return ret; ++ } ++ ++ public void clearEvents() { ++ HandlerList.unregisterAll(); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperPermissionManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperPermissionManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..92a69677f21b2c1c035119d8e5a6af63fa19b801 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/manager/PaperPermissionManager.java +@@ -0,0 +1,201 @@ ++package io.papermc.paper.plugin.manager; ++ ++import com.google.common.collect.ImmutableSet; ++import io.papermc.paper.plugin.PermissionManager; ++import org.bukkit.permissions.Permissible; ++import org.bukkit.permissions.Permission; ++import org.bukkit.permissions.PermissionDefault; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.HashSet; ++import java.util.List; ++import java.util.Locale; ++import java.util.Map; ++import java.util.Set; ++import java.util.WeakHashMap; ++ ++/** ++ * See ++ * {@link StupidSPMPermissionManagerWrapper} ++ */ ++abstract class PaperPermissionManager implements PermissionManager { ++ ++ public abstract Map permissions(); ++ ++ public abstract Map> defaultPerms(); ++ ++ public abstract Map> permSubs(); ++ ++ public abstract Map> defSubs(); ++ ++ @Override ++ @Nullable ++ public Permission getPermission(@NotNull String name) { ++ return this.permissions().get(name.toLowerCase(java.util.Locale.ENGLISH)); ++ } ++ ++ @Override ++ public void addPermission(@NotNull Permission perm) { ++ this.addPermission(perm, true); ++ } ++ ++ @Override ++ public void addPermissions(@NotNull List permissions) { ++ for (Permission permission : permissions) { ++ this.addPermission(permission, false); ++ } ++ this.dirtyPermissibles(); ++ } ++ ++ // Allow suppressing permission default calculations ++ private void addPermission(@NotNull Permission perm, boolean dirty) { ++ String name = perm.getName().toLowerCase(java.util.Locale.ENGLISH); ++ ++ if (this.permissions().containsKey(name)) { ++ throw new IllegalArgumentException("The permission " + name + " is already defined!"); ++ } ++ ++ this.permissions().put(name, perm); ++ this.calculatePermissionDefault(perm, dirty); ++ } ++ ++ @Override ++ @NotNull ++ public Set getDefaultPermissions(boolean op) { ++ return ImmutableSet.copyOf(this.defaultPerms().get(op)); ++ } ++ ++ ++ @Override ++ public void removePermission(@NotNull Permission perm) { ++ this.removePermission(perm.getName()); ++ } ++ ++ ++ @Override ++ public void removePermission(@NotNull String name) { ++ this.permissions().remove(name.toLowerCase(java.util.Locale.ENGLISH)); ++ } ++ ++ @Override ++ public void recalculatePermissionDefaults(@NotNull Permission perm) { ++ // we need a null check here because some plugins for some unknown reason pass null into this? ++ if (perm != null && this.permissions().containsKey(perm.getName().toLowerCase(Locale.ENGLISH))) { ++ this.defaultPerms().get(true).remove(perm); ++ this.defaultPerms().get(false).remove(perm); ++ ++ this.calculatePermissionDefault(perm, true); ++ } ++ } ++ ++ private void calculatePermissionDefault(@NotNull Permission perm, boolean dirty) { ++ if ((perm.getDefault() == PermissionDefault.OP) || (perm.getDefault() == PermissionDefault.TRUE)) { ++ this.defaultPerms().get(true).add(perm); ++ if (dirty) { ++ this.dirtyPermissibles(true); ++ } ++ } ++ if ((perm.getDefault() == PermissionDefault.NOT_OP) || (perm.getDefault() == PermissionDefault.TRUE)) { ++ this.defaultPerms().get(false).add(perm); ++ if (dirty) { ++ this.dirtyPermissibles(false); ++ } ++ } ++ } ++ ++ ++ @Override ++ public void subscribeToPermission(@NotNull String permission, @NotNull Permissible permissible) { ++ String name = permission.toLowerCase(java.util.Locale.ENGLISH); ++ Map map = this.permSubs().computeIfAbsent(name, k -> new WeakHashMap<>()); ++ ++ map.put(permissible, true); ++ } ++ ++ @Override ++ public void unsubscribeFromPermission(@NotNull String permission, @NotNull Permissible permissible) { ++ String name = permission.toLowerCase(java.util.Locale.ENGLISH); ++ Map map = this.permSubs().get(name); ++ ++ if (map != null) { ++ map.remove(permissible); ++ ++ if (map.isEmpty()) { ++ this.permSubs().remove(name); ++ } ++ } ++ } ++ ++ @Override ++ @NotNull ++ public Set getPermissionSubscriptions(@NotNull String permission) { ++ String name = permission.toLowerCase(java.util.Locale.ENGLISH); ++ Map map = this.permSubs().get(name); ++ ++ if (map == null) { ++ return ImmutableSet.of(); ++ } else { ++ return ImmutableSet.copyOf(map.keySet()); ++ } ++ } ++ ++ @Override ++ public void subscribeToDefaultPerms(boolean op, @NotNull Permissible permissible) { ++ Map map = this.defSubs().computeIfAbsent(op, k -> new WeakHashMap<>()); ++ ++ map.put(permissible, true); ++ } ++ ++ @Override ++ public void unsubscribeFromDefaultPerms(boolean op, @NotNull Permissible permissible) { ++ Map map = this.defSubs().get(op); ++ ++ if (map != null) { ++ map.remove(permissible); ++ ++ if (map.isEmpty()) { ++ this.defSubs().remove(op); ++ } ++ } ++ } ++ ++ @Override ++ @NotNull ++ public Set getDefaultPermSubscriptions(boolean op) { ++ Map map = this.defSubs().get(op); ++ ++ if (map == null) { ++ return ImmutableSet.of(); ++ } else { ++ return ImmutableSet.copyOf(map.keySet()); ++ } ++ } ++ ++ @Override ++ @NotNull ++ public Set getPermissions() { ++ return new HashSet<>(this.permissions().values()); ++ } ++ ++ @Override ++ public void clearPermissions() { ++ this.permissions().clear(); ++ this.defaultPerms().get(true).clear(); ++ this.defaultPerms().get(false).clear(); ++ } ++ ++ ++ void dirtyPermissibles(boolean op) { ++ Set permissibles = this.getDefaultPermSubscriptions(op); ++ ++ for (Permissible p : permissibles) { ++ p.recalculatePermissions(); ++ } ++ } ++ ++ void dirtyPermissibles() { ++ this.dirtyPermissibles(true); ++ this.dirtyPermissibles(false); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c0e896343c22badd97c774c4ed1daa4e274f5d44 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginInstanceManager.java +@@ -0,0 +1,304 @@ ++package io.papermc.paper.plugin.manager; ++ ++import com.google.common.base.Preconditions; ++import com.google.common.graph.GraphBuilder; ++import com.google.common.graph.MutableGraph; ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.entrypoint.Entrypoint; ++import io.papermc.paper.plugin.entrypoint.dependency.DependencyUtil; ++import io.papermc.paper.plugin.entrypoint.dependency.GraphDependencyContext; ++import io.papermc.paper.plugin.entrypoint.strategy.PluginGraphCycleException; ++import io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader; ++import io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage; ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++import io.papermc.paper.plugin.provider.source.DirectoryProviderSource; ++import io.papermc.paper.plugin.provider.source.FileProviderSource; ++import org.bukkit.Bukkit; ++import org.bukkit.Server; ++import org.bukkit.World; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandMap; ++import org.bukkit.command.PluginCommandYamlParser; ++import org.bukkit.craftbukkit.util.CraftMagicNumbers; ++import org.bukkit.event.HandlerList; ++import org.bukkit.event.server.PluginDisableEvent; ++import org.bukkit.event.server.PluginEnableEvent; ++import org.bukkit.plugin.InvalidDescriptionException; ++import org.bukkit.plugin.InvalidPluginException; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.PluginManager; ++import org.bukkit.plugin.UnknownDependencyException; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.spongepowered.configurate.serialize.SerializationException; ++ ++import java.io.IOException; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.util.ArrayList; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.logging.Level; ++ ++@SuppressWarnings("UnstableApiUsage") ++class PaperPluginInstanceManager { ++ ++ private static final FileProviderSource FILE_PROVIDER_SOURCE = new FileProviderSource("File '%s'"::formatted); ++ private static final DirectoryProviderSource DIRECTORY_PROVIDER_SOURCE = new DirectoryProviderSource(); ++ ++ private final List plugins = new ArrayList<>(); ++ private final Map lookupNames = new HashMap<>(); ++ ++ private final PluginManager pluginManager; ++ private final CommandMap commandMap; ++ private final Server server; ++ ++ private final MutableGraph dependencyGraph = GraphBuilder.directed().build(); ++ private final DependencyContext context = new GraphDependencyContext(this.dependencyGraph); ++ ++ public PaperPluginInstanceManager(PluginManager pluginManager, CommandMap commandMap, Server server) { ++ this.commandMap = commandMap; ++ this.server = server; ++ this.pluginManager = pluginManager; ++ } ++ ++ public @Nullable Plugin getPlugin(@NotNull String name) { ++ return this.lookupNames.get(name.replace(' ', '_').toLowerCase(java.util.Locale.ENGLISH)); // Paper ++ } ++ ++ public @NotNull Plugin[] getPlugins() { ++ return this.plugins.toArray(new Plugin[0]); ++ } ++ ++ public boolean isPluginEnabled(@NotNull String name) { ++ Plugin plugin = this.getPlugin(name); ++ ++ return this.isPluginEnabled(plugin); ++ } ++ ++ public synchronized boolean isPluginEnabled(@Nullable Plugin plugin) { ++ if ((plugin != null) && (this.plugins.contains(plugin))) { ++ return plugin.isEnabled(); ++ } else { ++ return false; ++ } ++ } ++ ++ public void loadPlugin(Plugin provided) { ++ PluginMeta configuration = provided.getPluginMeta(); ++ ++ this.plugins.add(provided); ++ this.lookupNames.put(configuration.getName().toLowerCase(java.util.Locale.ENGLISH), provided); ++ for (String providedPlugin : configuration.getProvidedPlugins()) { ++ this.lookupNames.putIfAbsent(providedPlugin.toLowerCase(java.util.Locale.ENGLISH), provided); ++ } ++ ++ DependencyUtil.buildDependencyGraph(this.dependencyGraph, configuration); ++ } ++ ++ // InvalidDescriptionException is never used, because the old JavaPluginLoader would wrap the exception. ++ public @Nullable Plugin loadPlugin(@NotNull Path path) throws InvalidPluginException, UnknownDependencyException { ++ RuntimePluginEntrypointHandler runtimePluginEntrypointHandler = new RuntimePluginEntrypointHandler<>(new SingularRuntimePluginProviderStorage()); ++ ++ try { ++ FILE_PROVIDER_SOURCE.registerProviders(runtimePluginEntrypointHandler, path); ++ } catch (IllegalArgumentException exception) { ++ return null; // Return null when the plugin file is not valid / plugin type is unknown ++ } catch (PluginGraphCycleException exception) { ++ throw new InvalidPluginException("Cannot import plugin that causes cyclic dependencies!"); ++ } catch (SerializationException | ++ InvalidDescriptionException ex) { // The spigot implementation wraps it in an invalid plugin exception ++ throw new InvalidPluginException(ex); ++ } catch (Exception e) { ++ throw new InvalidPluginException(e); ++ } ++ ++ try { ++ runtimePluginEntrypointHandler.enter(Entrypoint.PLUGIN); ++ } catch (Throwable e) { ++ throw new InvalidPluginException(e); ++ } ++ ++ return runtimePluginEntrypointHandler.getPluginProviderStorage().getSingleLoaded() ++ .orElseThrow(() -> new InvalidPluginException("Plugin didn't load any plugin providers?")); ++ } ++ ++ // The behavior of this is that all errors are logged instead of being thrown ++ public @NotNull Plugin[] loadPlugins(@NotNull Path directory) { ++ Preconditions.checkArgument(Files.isDirectory(directory), "Directory must be a directory"); // Avoid creating a directory if it doesn't exist ++ ++ RuntimePluginEntrypointHandler runtimePluginEntrypointHandler = new RuntimePluginEntrypointHandler<>(new MultiRuntimePluginProviderStorage()); ++ try { ++ DIRECTORY_PROVIDER_SOURCE.registerProviders(runtimePluginEntrypointHandler, directory); ++ runtimePluginEntrypointHandler.enter(Entrypoint.PLUGIN); ++ } catch (Exception e) { ++ // This should never happen, any errors that occur in this provider should instead be logged. ++ this.server.getLogger().log(Level.SEVERE, "Unknown error occurred while loading plugins through PluginManager.", e); ++ } ++ ++ return runtimePluginEntrypointHandler.getPluginProviderStorage().getLoaded().toArray(new JavaPlugin[0]); ++ } ++ ++ // Plugins are disabled in order like this inorder to "rougly" prevent ++ // their dependencies unloading first. But, eh. ++ public void disablePlugins() { ++ Plugin[] plugins = this.getPlugins(); ++ for (int i = plugins.length - 1; i >= 0; i--) { ++ this.disablePlugin(plugins[i]); ++ } ++ } ++ ++ public void clearPlugins() { ++ synchronized (this) { ++ this.disablePlugins(); ++ this.plugins.clear(); ++ this.lookupNames.clear(); ++ } ++ } ++ ++ public synchronized void enablePlugin(@NotNull Plugin plugin) { ++ if (plugin.isEnabled()) { ++ return; ++ } ++ ++ if (plugin.getPluginMeta() instanceof PluginDescriptionFile) { ++ List bukkitCommands = PluginCommandYamlParser.parse(plugin); ++ ++ if (!bukkitCommands.isEmpty()) { ++ this.commandMap.registerAll(plugin.getPluginMeta().getName(), bukkitCommands); ++ } ++ } ++ ++ try { ++ String enableMsg = "Enabling " + plugin.getPluginMeta().getDisplayName(); ++ if (plugin.getPluginMeta() instanceof PluginDescriptionFile descriptionFile && CraftMagicNumbers.isLegacy(descriptionFile)) { ++ enableMsg += "*"; ++ } ++ plugin.getLogger().info(enableMsg); ++ ++ JavaPlugin jPlugin = (JavaPlugin) plugin; ++ ++ if (jPlugin.getClass().getClassLoader() instanceof ConfiguredPluginClassLoader classLoader) { // Paper ++ if (PaperClassLoaderStorage.instance().registerUnsafePlugin(classLoader)) { ++ this.server.getLogger().log(Level.WARNING, "Enabled plugin with unregistered ConfiguredPluginClassLoader " + plugin.getPluginMeta().getDisplayName()); ++ } ++ } // Paper ++ ++ try { ++ jPlugin.setEnabled(true); ++ } catch (Throwable ex) { ++ this.server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getPluginMeta().getDisplayName() + " (Is it up to date?)", ex); ++ // Paper start - Disable plugins that fail to load ++ this.server.getPluginManager().disablePlugin(jPlugin); ++ return; ++ // Paper end ++ } ++ ++ // Perhaps abort here, rather than continue going, but as it stands, ++ // an abort is not possible the way it's currently written ++ this.server.getPluginManager().callEvent(new PluginEnableEvent(plugin)); ++ } catch (Throwable ex) { ++ this.handlePluginException("Error occurred (in the plugin loader) while enabling " ++ + plugin.getPluginMeta().getDisplayName() + " (Is it up to date?)", ex, plugin); ++ } ++ ++ HandlerList.bakeAll(); ++ } ++ ++ public synchronized void disablePlugin(@NotNull Plugin plugin) { ++ if (!(plugin instanceof JavaPlugin javaPlugin)) { ++ throw new IllegalArgumentException("Only expects java plugins."); ++ } ++ if (!plugin.isEnabled()) { ++ return; ++ } ++ ++ String pluginName = plugin.getPluginMeta().getDisplayName(); ++ ++ try { ++ plugin.getLogger().info("Disabling %s".formatted(pluginName)); ++ ++ this.server.getPluginManager().callEvent(new PluginDisableEvent(plugin)); ++ ++ javaPlugin.setEnabled(false); ++ ++ ClassLoader classLoader = plugin.getClass().getClassLoader(); ++ if (classLoader instanceof ConfiguredPluginClassLoader configuredPluginClassLoader) { ++ try { ++ configuredPluginClassLoader.close(); ++ } catch (IOException ex) { ++ this.server.getLogger().log(Level.WARNING, "Error closing the classloader for '" + pluginName + "'", ex); // Paper - log exception ++ } ++ // Remove from the classloader pool inorder to prevent plugins from trying ++ // to access classes ++ PaperClassLoaderStorage.instance().unregisterClassloader(configuredPluginClassLoader); ++ } ++ ++ } catch (Throwable ex) { ++ this.handlePluginException("Error occurred (in the plugin loader) while disabling " ++ + pluginName + " (Is it up to date?)", ex, plugin); // Paper ++ } ++ ++ try { ++ this.server.getScheduler().cancelTasks(plugin); ++ } catch (Throwable ex) { ++ this.handlePluginException("Error occurred (in the plugin loader) while cancelling tasks for " ++ + pluginName + " (Is it up to date?)", ex, plugin); // Paper ++ } ++ ++ try { ++ this.server.getServicesManager().unregisterAll(plugin); ++ } catch (Throwable ex) { ++ this.handlePluginException("Error occurred (in the plugin loader) while unregistering services for " ++ + pluginName + " (Is it up to date?)", ex, plugin); // Paper ++ } ++ ++ try { ++ HandlerList.unregisterAll(plugin); ++ } catch (Throwable ex) { ++ this.handlePluginException("Error occurred (in the plugin loader) while unregistering events for " ++ + pluginName + " (Is it up to date?)", ex, plugin); // Paper ++ } ++ ++ try { ++ this.server.getMessenger().unregisterIncomingPluginChannel(plugin); ++ this.server.getMessenger().unregisterOutgoingPluginChannel(plugin); ++ } catch (Throwable ex) { ++ this.handlePluginException("Error occurred (in the plugin loader) while unregistering plugin channels for " ++ + pluginName + " (Is it up to date?)", ex, plugin); // Paper ++ } ++ ++ try { ++ for (World world : this.server.getWorlds()) { ++ world.removePluginChunkTickets(plugin); ++ } ++ } catch (Throwable ex) { ++ this.handlePluginException("Error occurred (in the plugin loader) while removing chunk tickets for " + pluginName + " (Is it up to date?)", ex, plugin); // Paper ++ } ++ ++ } ++ ++ // TODO: Implement event part in future patch (paper patch move up, this patch is lower) ++ private void handlePluginException(String msg, Throwable ex, Plugin plugin) { ++ Bukkit.getServer().getLogger().log(Level.SEVERE, msg, ex); ++ this.pluginManager.callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin))); ++ } ++ ++ public boolean isTransitiveDepend(@NotNull PluginMeta plugin, @NotNull PluginMeta depend) { ++ return this.context.isTransitiveDependency(plugin, depend); ++ } ++ ++ public boolean hasDependency(String pluginIdentifier) { ++ return this.getPlugin(pluginIdentifier) != null; ++ } ++ ++ // Debug only ++ @ApiStatus.Internal ++ public MutableGraph getDependencyGraph() { ++ return this.dependencyGraph; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/manager/PaperPluginManagerImpl.java b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginManagerImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..cdc3f6c5c845fe00478c41a22d39d7b348673559 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginManagerImpl.java +@@ -0,0 +1,241 @@ ++package io.papermc.paper.plugin.manager; ++ ++import com.google.common.graph.MutableGraph; ++import io.papermc.paper.plugin.PermissionManager; ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++import org.bukkit.Bukkit; ++import org.bukkit.Server; ++import org.bukkit.command.CommandMap; ++import org.bukkit.craftbukkit.CraftServer; ++import org.bukkit.event.Event; ++import org.bukkit.event.EventPriority; ++import org.bukkit.event.Listener; ++import org.bukkit.permissions.Permissible; ++import org.bukkit.permissions.Permission; ++import org.bukkit.plugin.EventExecutor; ++import org.bukkit.plugin.InvalidDescriptionException; ++import org.bukkit.plugin.InvalidPluginException; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.PluginLoader; ++import org.bukkit.plugin.PluginManager; ++import org.bukkit.plugin.SimplePluginManager; ++import org.bukkit.plugin.UnknownDependencyException; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.io.File; ++import java.util.List; ++import java.util.Set; ++ ++public class PaperPluginManagerImpl implements PluginManager, DependencyContext { ++ ++ private final PaperPluginInstanceManager instanceManager; ++ private final PaperEventManager paperEventManager; ++ private PermissionManager permissionManager; ++ ++ public PaperPluginManagerImpl(Server server, CommandMap commandMap, @Nullable SimplePluginManager permissionManager) { ++ this.instanceManager = new PaperPluginInstanceManager(this, commandMap, server); ++ this.paperEventManager = new PaperEventManager(server); ++ ++ if (permissionManager == null) { ++ this.permissionManager = new NormalPaperPermissionManager(); ++ } else { ++ this.permissionManager = new StupidSPMPermissionManagerWrapper(permissionManager); // TODO: See comment when SimplePermissionManager is removed ++ } ++ } ++ ++ // REMOVE THIS WHEN SimplePluginManager is removed. ++ // Just cast and use Bukkit.getServer().getPluginManager() ++ public static PaperPluginManagerImpl getInstance() { ++ return ((CraftServer) (Bukkit.getServer())).paperPluginManager; ++ } ++ ++ // Plugin Manipulation ++ ++ @Override ++ public @Nullable Plugin getPlugin(@NotNull String name) { ++ return this.instanceManager.getPlugin(name); ++ } ++ ++ @Override ++ public @NotNull Plugin[] getPlugins() { ++ return this.instanceManager.getPlugins(); ++ } ++ ++ @Override ++ public boolean isPluginEnabled(@NotNull String name) { ++ return this.instanceManager.isPluginEnabled(name); ++ } ++ ++ @Override ++ public boolean isPluginEnabled(@Nullable Plugin plugin) { ++ return this.instanceManager.isPluginEnabled(plugin); ++ } ++ ++ public void loadPlugin(Plugin plugin) { ++ this.instanceManager.loadPlugin(plugin); ++ } ++ ++ @Override ++ public @Nullable Plugin loadPlugin(@NotNull File file) throws InvalidPluginException, InvalidDescriptionException, UnknownDependencyException { ++ return this.instanceManager.loadPlugin(file.toPath()); ++ } ++ ++ @Override ++ public @NotNull Plugin[] loadPlugins(@NotNull File directory) { ++ return this.instanceManager.loadPlugins(directory.toPath()); ++ } ++ ++ @Override ++ public void disablePlugins() { ++ this.instanceManager.disablePlugins(); ++ } ++ ++ @Override ++ public synchronized void clearPlugins() { ++ this.instanceManager.clearPlugins(); ++ this.permissionManager.clearPermissions(); ++ this.paperEventManager.clearEvents(); ++ } ++ ++ @Override ++ public void enablePlugin(@NotNull Plugin plugin) { ++ this.instanceManager.enablePlugin(plugin); ++ } ++ ++ @Override ++ public void disablePlugin(@NotNull Plugin plugin) { ++ this.instanceManager.disablePlugin(plugin); ++ } ++ ++ @Override ++ public boolean isTransitiveDependency(PluginMeta pluginMeta, PluginMeta dependencyConfig) { ++ return this.instanceManager.isTransitiveDepend(pluginMeta, dependencyConfig); ++ } ++ ++ @Override ++ public boolean hasDependency(String pluginIdentifier) { ++ return this.instanceManager.hasDependency(pluginIdentifier); ++ } ++ ++ // Event manipulation ++ ++ @Override ++ public void callEvent(@NotNull Event event) throws IllegalStateException { ++ this.paperEventManager.callEvent(event); ++ } ++ ++ @Override ++ public void registerEvents(@NotNull Listener listener, @NotNull Plugin plugin) { ++ this.paperEventManager.registerEvents(listener, plugin); ++ } ++ ++ @Override ++ public void registerEvent(@NotNull Class event, @NotNull Listener listener, @NotNull EventPriority priority, @NotNull EventExecutor executor, @NotNull Plugin plugin) { ++ this.paperEventManager.registerEvent(event, listener, priority, executor, plugin); ++ } ++ ++ @Override ++ public void registerEvent(@NotNull Class event, @NotNull Listener listener, @NotNull EventPriority priority, @NotNull EventExecutor executor, @NotNull Plugin plugin, boolean ignoreCancelled) { ++ this.paperEventManager.registerEvent(event, listener, priority, executor, plugin, ignoreCancelled); ++ } ++ ++ // Permission manipulation ++ ++ @Override ++ public @Nullable Permission getPermission(@NotNull String name) { ++ return this.permissionManager.getPermission(name); ++ } ++ ++ @Override ++ public void addPermission(@NotNull Permission perm) { ++ this.permissionManager.addPermission(perm); ++ } ++ ++ @Override ++ public void removePermission(@NotNull Permission perm) { ++ this.permissionManager.removePermission(perm); ++ } ++ ++ @Override ++ public void removePermission(@NotNull String name) { ++ this.permissionManager.removePermission(name); ++ } ++ ++ @Override ++ public @NotNull Set getDefaultPermissions(boolean op) { ++ return this.permissionManager.getDefaultPermissions(op); ++ } ++ ++ @Override ++ public void recalculatePermissionDefaults(@NotNull Permission perm) { ++ this.permissionManager.recalculatePermissionDefaults(perm); ++ } ++ ++ @Override ++ public void subscribeToPermission(@NotNull String permission, @NotNull Permissible permissible) { ++ this.permissionManager.subscribeToPermission(permission, permissible); ++ } ++ ++ @Override ++ public void unsubscribeFromPermission(@NotNull String permission, @NotNull Permissible permissible) { ++ this.permissionManager.unsubscribeFromPermission(permission, permissible); ++ } ++ ++ @Override ++ public @NotNull Set getPermissionSubscriptions(@NotNull String permission) { ++ return this.permissionManager.getPermissionSubscriptions(permission); ++ } ++ ++ @Override ++ public void subscribeToDefaultPerms(boolean op, @NotNull Permissible permissible) { ++ this.permissionManager.subscribeToDefaultPerms(op, permissible); ++ } ++ ++ @Override ++ public void unsubscribeFromDefaultPerms(boolean op, @NotNull Permissible permissible) { ++ this.permissionManager.unsubscribeFromDefaultPerms(op, permissible); ++ } ++ ++ @Override ++ public @NotNull Set getDefaultPermSubscriptions(boolean op) { ++ return this.permissionManager.getDefaultPermSubscriptions(op); ++ } ++ ++ @Override ++ public @NotNull Set getPermissions() { ++ return this.permissionManager.getPermissions(); ++ } ++ ++ @Override ++ public void addPermissions(@NotNull List perm) { ++ this.permissionManager.addPermissions(perm); ++ } ++ ++ @Override ++ public void clearPermissions() { ++ this.permissionManager.clearPermissions(); ++ } ++ ++ @Override ++ public void overridePermissionManager(@NotNull Plugin plugin, @Nullable PermissionManager permissionManager) { ++ this.permissionManager = permissionManager; ++ } ++ ++ // Etc ++ ++ @Override ++ public boolean useTimings() { ++ return co.aikar.timings.Timings.isTimingsEnabled(); ++ } ++ ++ @Override ++ public void registerInterface(@NotNull Class loader) throws IllegalArgumentException { ++ throw new UnsupportedOperationException(); ++ } ++ ++ public MutableGraph getInstanceManagerGraph() { ++ return instanceManager.getDependencyGraph(); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/manager/RuntimePluginEntrypointHandler.java b/src/main/java/io/papermc/paper/plugin/manager/RuntimePluginEntrypointHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5d50d1d312388e979c0e1cd53a6bf5977ca6e549 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/manager/RuntimePluginEntrypointHandler.java +@@ -0,0 +1,47 @@ ++package io.papermc.paper.plugin.manager; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import io.papermc.paper.plugin.entrypoint.Entrypoint; ++import io.papermc.paper.plugin.entrypoint.EntrypointHandler; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.storage.ProviderStorage; ++import org.bukkit.plugin.InvalidPluginException; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Used for loading plugins during runtime, only supporting providers that are plugins. ++ * This is only used for the plugin manager, as it only allows plugins to be ++ * registered to a provider storage. ++ */ ++class RuntimePluginEntrypointHandler> implements EntrypointHandler { ++ ++ private final T providerStorage; ++ ++ RuntimePluginEntrypointHandler(T providerStorage) { ++ this.providerStorage = providerStorage; ++ } ++ ++ @Override ++ public void register(Entrypoint entrypoint, PluginProvider provider) { ++ if (!entrypoint.equals(Entrypoint.PLUGIN)) { ++ SneakyThrow.sneaky(new InvalidPluginException("Plugin cannot register entrypoints other than PLUGIN during runtime. Tried registering %s!".formatted(entrypoint))); ++ // We have to throw an invalid plugin exception for legacy reasons ++ } ++ ++ this.providerStorage.register((PluginProvider) provider); ++ } ++ ++ @Override ++ public void enter(Entrypoint entrypoint) { ++ if (entrypoint != Entrypoint.PLUGIN) { ++ throw new IllegalArgumentException("Only plugin entrypoint supported"); ++ } ++ this.providerStorage.enter(); ++ } ++ ++ @NotNull ++ public T getPluginProviderStorage() { ++ return this.providerStorage; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/manager/SingularRuntimePluginProviderStorage.java b/src/main/java/io/papermc/paper/plugin/manager/SingularRuntimePluginProviderStorage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ebc01cbffdc55ca9664897ff10ef14ad6c5ab726 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/manager/SingularRuntimePluginProviderStorage.java +@@ -0,0 +1,80 @@ ++package io.papermc.paper.plugin.manager; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import io.papermc.paper.plugin.entrypoint.Entrypoint; ++import io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent; ++import io.papermc.paper.plugin.storage.ServerPluginProviderStorage; ++import org.bukkit.plugin.InvalidPluginException; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.UnknownDependencyException; ++import org.bukkit.plugin.java.JavaPlugin; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Optional; ++ ++/** ++ * Used for registering a single plugin provider. ++ * This has special behavior in that some errors are thrown instead of logged. ++ */ ++class SingularRuntimePluginProviderStorage extends ServerPluginProviderStorage { ++ ++ private PluginProvider lastProvider; ++ private JavaPlugin singleLoaded; ++ ++ @Override ++ public void register(PluginProvider provider) { ++ super.register(provider); ++ if (this.lastProvider != null) { ++ SneakyThrow.sneaky(new InvalidPluginException("Plugin registered two JavaPlugins")); ++ } ++ if (provider instanceof PaperPluginParent.PaperServerPluginProvider) { ++ throw new IllegalStateException("Cannot register paper plugins during runtime!"); ++ } ++ this.lastProvider = provider; ++ // Register the provider into the server entrypoint, this allows it to show in /plugins correctly. ++ // Generally it might be better in the future to make a separate storage, as putting it into the entrypoint handlers doesn't make much sense. ++ LaunchEntryPointHandler.INSTANCE.register(Entrypoint.PLUGIN, provider); ++ } ++ ++ @Override ++ public void enter() { ++ PluginProvider provider = this.lastProvider; ++ if (provider == null) { ++ return; ++ } ++ ++ // Manually validate dependencies, LEGACY BEHAVIOR. ++ // Normally it is logged, but manually adding one plugin will cause it to actually throw exceptions. ++ PluginDescriptionFile descriptionFile = (PluginDescriptionFile) provider.getMeta(); ++ List missingDependencies = new ArrayList<>(); ++ for (String dependency : descriptionFile.getDepend()) { ++ if (!PaperPluginManagerImpl.getInstance().isPluginEnabled(dependency)) { ++ missingDependencies.add(dependency); ++ } ++ } ++ if (!missingDependencies.isEmpty()) { ++ throw new UnknownDependencyException(missingDependencies, provider.getFileName().toString()); ++ } ++ ++ // Go through normal plugin loading logic ++ super.enter(); ++ } ++ ++ @Override ++ public void processProvided(JavaPlugin provided) { ++ super.processProvided(provided); ++ this.singleLoaded = provided; ++ } ++ ++ @Override ++ public boolean exitOnCycleDependencies() { ++ return false; ++ } ++ ++ public Optional getSingleLoaded() { ++ return Optional.ofNullable(this.singleLoaded); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/manager/StupidSPMPermissionManagerWrapper.java b/src/main/java/io/papermc/paper/plugin/manager/StupidSPMPermissionManagerWrapper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ea8cf22c35242eb9f3914b95df00e20504aef5c1 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/manager/StupidSPMPermissionManagerWrapper.java +@@ -0,0 +1,42 @@ ++package io.papermc.paper.plugin.manager; ++ ++import org.bukkit.permissions.Permissible; ++import org.bukkit.permissions.Permission; ++import org.bukkit.plugin.SimplePluginManager; ++ ++import java.util.Map; ++import java.util.Set; ++ ++/* ++This is actually so cursed I hate it. ++We need to wrap these in fields as people override the fields, so we need to access them lazily at all times. ++// TODO: When SimplePluginManager is GONE remove this and cleanup the PaperPermissionManager to use actual fields. ++ */ ++class StupidSPMPermissionManagerWrapper extends PaperPermissionManager { ++ ++ private final SimplePluginManager simplePluginManager; ++ ++ public StupidSPMPermissionManagerWrapper(SimplePluginManager simplePluginManager) { ++ this.simplePluginManager = simplePluginManager; ++ } ++ ++ @Override ++ public Map permissions() { ++ return this.simplePluginManager.permissions; ++ } ++ ++ @Override ++ public Map> defaultPerms() { ++ return this.simplePluginManager.defaultPerms; ++ } ++ ++ @Override ++ public Map> permSubs() { ++ return this.simplePluginManager.permSubs; ++ } ++ ++ @Override ++ public Map> defSubs() { ++ return this.simplePluginManager.defSubs; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/PluginProvider.java b/src/main/java/io/papermc/paper/plugin/provider/PluginProvider.java +new file mode 100644 +index 0000000000000000000000000000000000000000..11b6cb377c9b04b63b6359918eef214ba3032d96 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/PluginProvider.java +@@ -0,0 +1,47 @@ ++package io.papermc.paper.plugin.provider; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++import java.nio.file.Path; ++import java.util.jar.JarFile; ++import java.util.logging.Logger; ++ ++/** ++ * PluginProviders are created by a {@link io.papermc.paper.plugin.provider.source.ProviderSource}, ++ * which is loaded into an {@link io.papermc.paper.plugin.entrypoint.EntrypointHandler}. ++ *

++ * A PluginProvider is responsible for providing part of a plugin, whether it's a Bootstrapper or Server Plugin. ++ * The point of this class is to be able to create the actual instance later, as at the time this is created the server ++ * may be missing some key parts. For example, the Bukkit singleton will not be initialized yet, therefor we need to ++ * have a PluginServerProvider load the server plugin later. ++ *

++ * Plugin providers are currently not exposed in any way of the api. It is preferred that this stays this way, ++ * as providers are only needed for initialization. ++ * ++ * @param provider type ++ */ ++@ApiStatus.Internal ++public interface PluginProvider { ++ ++ @NotNull ++ Path getSource(); ++ ++ default Path getFileName() { ++ return this.getSource().getFileName(); ++ } ++ ++ default Path getParentSource() { ++ return this.getSource().getParent(); ++ } ++ ++ JarFile file(); ++ ++ T createInstance(); ++ ++ PluginMeta getMeta(); ++ ++ Logger getLogger(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/ProviderStatus.java b/src/main/java/io/papermc/paper/plugin/provider/ProviderStatus.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6154e864b0ff01cb70acaaeee5ca8c9f4a90a90e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/ProviderStatus.java +@@ -0,0 +1,13 @@ ++package io.papermc.paper.plugin.provider; ++ ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * This is used for the /plugins command, where it will look in the {@link io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler} and ++ * use the provider statuses to determine the color. ++ */ ++@ApiStatus.Internal ++public enum ProviderStatus { ++ INITIALIZED, ++ ERRORED, ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/ProviderStatusHolder.java b/src/main/java/io/papermc/paper/plugin/provider/ProviderStatusHolder.java +new file mode 100644 +index 0000000000000000000000000000000000000000..17284d0f61c459dff765c0adae4ad2c641e054c1 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/ProviderStatusHolder.java +@@ -0,0 +1,11 @@ ++package io.papermc.paper.plugin.provider; ++ ++/** ++ * This is used to mark that a plugin provider is able to hold a status for the /plugins command. ++ */ ++public interface ProviderStatusHolder { ++ ++ ProviderStatus getLastProvidedStatus(); ++ ++ void setStatus(ProviderStatus status); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/FlattenedResolver.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/FlattenedResolver.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6ba3bcc468c0a60c76d6d0f0243bda661c737f2f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/FlattenedResolver.java +@@ -0,0 +1,29 @@ ++package io.papermc.paper.plugin.provider.configuration; ++ ++import org.checkerframework.checker.nullness.qual.Nullable; ++import org.spongepowered.configurate.objectmapping.meta.NodeResolver; ++ ++import java.lang.annotation.ElementType; ++import java.lang.annotation.Retention; ++import java.lang.annotation.RetentionPolicy; ++import java.lang.annotation.Target; ++import java.lang.reflect.AnnotatedElement; ++ ++@Retention(RetentionPolicy.RUNTIME) ++@Target(ElementType.FIELD) ++public @interface FlattenedResolver { ++ ++ final class Factory implements NodeResolver.Factory { ++ ++ @Override ++ public @Nullable NodeResolver make(String name, AnnotatedElement element) { ++ if (element.isAnnotationPresent(FlattenedResolver.class)) { ++ return (node) -> node; ++ } else { ++ return null; ++ } ++ } ++ } ++ ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java +new file mode 100644 +index 0000000000000000000000000000000000000000..622a6c5fdfcb6d8cc12054f3de81c73c9af2389f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java +@@ -0,0 +1,213 @@ ++package io.papermc.paper.plugin.provider.configuration; ++ ++import com.google.common.collect.ImmutableList; ++import io.leangen.geantyref.TypeToken; ++import io.papermc.paper.configuration.constraint.Constraint; ++import io.papermc.paper.configuration.serializer.ComponentSerializer; ++import io.papermc.paper.configuration.serializer.EnumValueSerializer; ++import io.papermc.paper.configuration.serializer.collections.MapSerializer; ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.provider.configuration.serializer.ImmutableListSerializer; ++import io.papermc.paper.plugin.provider.configuration.serializer.PermissionConfigurationSerializer; ++import io.papermc.paper.plugin.provider.configuration.serializer.constraints.PluginConfigConstraints; ++import io.papermc.paper.plugin.provider.configuration.type.DependencyConfiguration; ++import io.papermc.paper.plugin.provider.configuration.type.PermissionConfiguration; ++import org.bukkit.permissions.Permission; ++import org.bukkit.permissions.PermissionDefault; ++import org.bukkit.plugin.PluginLoadOrder; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import org.spongepowered.configurate.CommentedConfigurationNode; ++import org.spongepowered.configurate.ConfigurateException; ++import org.spongepowered.configurate.loader.HeaderMode; ++import org.spongepowered.configurate.objectmapping.ConfigSerializable; ++import org.spongepowered.configurate.objectmapping.ObjectMapper; ++import org.spongepowered.configurate.objectmapping.meta.Required; ++import org.spongepowered.configurate.yaml.NodeStyle; ++import org.spongepowered.configurate.yaml.YamlConfigurationLoader; ++ ++import java.io.BufferedReader; ++import java.util.List; ++ ++@SuppressWarnings({"CanBeFinal", "FieldCanBeLocal", "FieldMayBeFinal", "NotNullFieldNotInitialized", "InnerClassMayBeStatic"}) ++@ConfigSerializable ++public class PaperPluginMeta implements PluginMeta { ++ ++ @PluginConfigConstraints.PluginName ++ @Required ++ private String name; ++ @Required ++ @PluginConfigConstraints.PluginNameSpace ++ private String main; ++ @PluginConfigConstraints.PluginNameSpace ++ private String bootstrapper; ++ @PluginConfigConstraints.PluginNameSpace ++ private String loader; ++ private List dependencies = List.of(); ++ private List loadBefore = List.of(); ++ private List provides = List.of(); ++ private boolean hasOpenClassloader = false; ++ @Required ++ private String version; ++ private String description; ++ private List authors = List.of(); ++ private List contributors = List.of(); ++ private String website; ++ private String prefix; ++ private PluginLoadOrder load = PluginLoadOrder.POSTWORLD; ++ @FlattenedResolver ++ private PermissionConfiguration permissionConfiguration = new PermissionConfiguration(PermissionDefault.OP, List.of()); ++ @Required ++ @PluginConfigConstraints.PluginVersion ++ private String apiVersion; ++ ++ private transient String displayName; ++ ++ public PaperPluginMeta() { ++ } ++ ++ public static PaperPluginMeta create(BufferedReader reader) throws ConfigurateException { ++ YamlConfigurationLoader loader = YamlConfigurationLoader.builder() ++ .indent(2) ++ .nodeStyle(NodeStyle.BLOCK) ++ .headerMode(HeaderMode.NONE) ++ .source(() -> reader) ++ .defaultOptions((options) -> { ++ ++ return options.serializers((serializers) -> { ++ serializers ++ .register(new EnumValueSerializer()) ++ .register(MapSerializer.TYPE, new MapSerializer(false)) ++ .register(new TypeToken<>() { ++ }, new ImmutableListSerializer()) ++ .register(PermissionConfiguration.class, PermissionConfigurationSerializer.SERIALIZER) ++ .register(new ComponentSerializer()) ++ .registerAnnotatedObjects( ++ ObjectMapper.factoryBuilder() ++ .addConstraint(Constraint.class, new Constraint.Factory()) ++ .addConstraint(PluginConfigConstraints.PluginName.class, String.class, new PluginConfigConstraints.PluginName.Factory()) ++ .addConstraint(PluginConfigConstraints.PluginVersion.class, String.class, new PluginConfigConstraints.PluginVersion.Factory()) ++ .addConstraint(PluginConfigConstraints.PluginNameSpace.class, String.class, new PluginConfigConstraints.PluginNameSpace.Factory()) ++ .addNodeResolver(new FlattenedResolver.Factory()) ++ .build() ++ ); ++ ++ }); ++ }) ++ .build(); ++ CommentedConfigurationNode node = loader.load(); ++ PaperPluginMeta pluginConfiguration = node.require(PaperPluginMeta.class); ++ ++ if (!node.node("author").virtual()) { ++ pluginConfiguration.authors = ImmutableList.builder() ++ .addAll(pluginConfiguration.authors) ++ .add(node.node("author").getString()) ++ .build(); ++ } ++ ++ pluginConfiguration.displayName = pluginConfiguration.name.replace('_', ' '); ++ ++ return pluginConfiguration; ++ } ++ ++ @Override ++ public @NotNull String getName() { ++ return this.name; ++ } ++ ++ @Override ++ public @NotNull String getMainClass() { ++ return this.main; ++ } ++ ++ @Override ++ public @NotNull String getVersion() { ++ return this.version; ++ } ++ ++ @Override ++ public @NotNull String getDisplayName() { ++ return this.displayName; ++ } ++ ++ @Override ++ public @Nullable String getLoggerPrefix() { ++ return this.prefix; ++ } ++ ++ @Override ++ public @NotNull List getPluginDependencies() { ++ return this.dependencies.stream().filter((dependency) -> dependency.required() && !dependency.bootstrap()).map(DependencyConfiguration::name).toList(); ++ } ++ ++ @Override ++ public @NotNull List getPluginSoftDependencies() { ++ return this.dependencies.stream().filter((dependency) -> !dependency.required() && !dependency.bootstrap()).map(DependencyConfiguration::name).toList(); ++ } ++ ++ @Override ++ public @NotNull List getLoadBeforePlugins() { ++ return this.loadBefore; ++ } ++ ++ @Override ++ public @NotNull PluginLoadOrder getLoadOrder() { ++ return this.load; ++ } ++ ++ @Override ++ public @NotNull String getDescription() { ++ return this.description; ++ } ++ ++ @Override ++ public @NotNull List getAuthors() { ++ return this.authors; ++ } ++ ++ @Override ++ public @NotNull List getContributors() { ++ return this.contributors; ++ } ++ ++ @Override ++ public String getWebsite() { ++ return this.website; ++ } ++ ++ @Override ++ public @NotNull List getPermissions() { ++ return this.permissionConfiguration.permissions(); ++ } ++ ++ @Override ++ public @NotNull PermissionDefault getPermissionDefault() { ++ return this.permissionConfiguration.defaultPerm(); ++ } ++ ++ @Override ++ public @NotNull String getAPIVersion() { ++ return this.apiVersion; ++ } ++ ++ @Override ++ public @NotNull List getProvidedPlugins() { ++ return this.provides; ++ } ++ ++ public String getBootstrapper() { ++ return this.bootstrapper; ++ } ++ ++ public String getLoader() { ++ return this.loader; ++ } ++ ++ public boolean hasOpenClassloader() { ++ return this.hasOpenClassloader; ++ } ++ ++ public List getDependencies() { ++ return dependencies; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/ImmutableCollectionSerializer.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/ImmutableCollectionSerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f0cdb1bab30faaa438aa3e6de6125ade3fae98c2 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/ImmutableCollectionSerializer.java +@@ -0,0 +1,90 @@ ++package io.papermc.paper.plugin.provider.configuration.serializer; ++ ++import com.google.common.collect.ImmutableCollection; ++import org.checkerframework.checker.nullness.qual.Nullable; ++import org.spongepowered.configurate.ConfigurationNode; ++import org.spongepowered.configurate.ConfigurationOptions; ++import org.spongepowered.configurate.serialize.SerializationException; ++import org.spongepowered.configurate.serialize.TypeSerializer; ++import org.spongepowered.configurate.util.CheckedConsumer; ++ ++import java.lang.reflect.Type; ++import java.util.Collection; ++import java.util.Collections; ++import java.util.List; ++ ++@SuppressWarnings("unchecked") ++public abstract class ImmutableCollectionSerializer, T extends Collection> implements TypeSerializer { ++ ++ protected ImmutableCollectionSerializer() { ++ } ++ ++ @Override ++ public final T deserialize(final Type type, final ConfigurationNode node) throws SerializationException { ++ final Type entryType = this.elementType(type); ++ final @Nullable TypeSerializer entrySerial = node.options().serializers().get(entryType); ++ if (entrySerial == null) { ++ throw new SerializationException(node, entryType, "No applicable type serializer for type"); ++ } ++ ++ if (node.isList()) { ++ final List values = node.childrenList(); ++ final B builder = this.createNew(values.size()); ++ for (ConfigurationNode value : values) { ++ try { ++ this.deserializeSingle(builder, entrySerial.deserialize(entryType, value)); ++ } catch (final SerializationException ex) { ++ ex.initPath(value::path); ++ throw ex; ++ } ++ } ++ return (T) builder.build(); ++ } else { ++ final @Nullable Object unwrappedVal = node.raw(); ++ if (unwrappedVal != null) { ++ final B builder = this.createNew(1); ++ this.deserializeSingle(builder, entrySerial.deserialize(entryType, node)); ++ return (T) builder.build(); ++ } ++ } ++ return this.emptyValue(type, null); ++ } ++ ++ @SuppressWarnings({"unchecked", "rawtypes"}) ++ @Override ++ public final void serialize(final Type type, final @Nullable T obj, final ConfigurationNode node) throws SerializationException { ++ final Type entryType = this.elementType(type); ++ final @Nullable TypeSerializer entrySerial = node.options().serializers().get(entryType); ++ if (entrySerial == null) { ++ throw new SerializationException(node, entryType, "No applicable type serializer for type"); ++ } ++ ++ node.raw(Collections.emptyList()); ++ if (obj != null) { ++ this.forEachElement(obj, el -> { ++ final ConfigurationNode child = node.appendListNode(); ++ try { ++ entrySerial.serialize(entryType, el, child); ++ } catch (final SerializationException ex) { ++ ex.initPath(child::path); ++ throw ex; ++ } ++ }); ++ } ++ } ++ ++ @SuppressWarnings({"unchecked"}) ++ @Override ++ public @Nullable T emptyValue(final Type specificType, final ConfigurationOptions options) { ++ return (T) this.createNew(0).build(); ++ } ++ ++ protected abstract Type elementType(Type containerType) throws SerializationException; ++ ++ protected abstract B createNew(int size); ++ ++ protected abstract void forEachElement(T collection, CheckedConsumer action) throws SerializationException; ++ ++ protected abstract void deserializeSingle(B builder, @Nullable Object deserialized) throws SerializationException; ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/ImmutableListSerializer.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/ImmutableListSerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7757d7df70e39a6fe4d92d02b6f905a22f80dbf3 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/ImmutableListSerializer.java +@@ -0,0 +1,43 @@ ++package io.papermc.paper.plugin.provider.configuration.serializer; ++ ++import com.google.common.collect.ImmutableList; ++import org.checkerframework.checker.nullness.qual.Nullable; ++import org.spongepowered.configurate.serialize.SerializationException; ++import org.spongepowered.configurate.util.CheckedConsumer; ++ ++import java.lang.reflect.ParameterizedType; ++import java.lang.reflect.Type; ++import java.util.List; ++ ++public class ImmutableListSerializer extends ImmutableCollectionSerializer, List> { ++ ++ @Override ++ protected Type elementType(Type containerType) throws SerializationException { ++ if (!(containerType instanceof ParameterizedType)) { ++ throw new SerializationException(containerType, "Raw types are not supported for collections"); ++ } ++ return ((ParameterizedType) containerType).getActualTypeArguments()[0]; ++ } ++ ++ @Override ++ protected ImmutableList.Builder createNew(int size) { ++ return ImmutableList.builderWithExpectedSize(size); ++ } ++ ++ @Override ++ protected void forEachElement(List collection, CheckedConsumer action) throws SerializationException { ++ for (Object obj : collection) { ++ action.accept(obj); ++ } ++ } ++ ++ @SuppressWarnings({"unchecked", "rawtypes"}) ++ @Override ++ protected void deserializeSingle(ImmutableList.Builder builder, @Nullable Object deserialized) throws SerializationException { ++ if (deserialized == null) { ++ return; ++ } ++ ++ ((ImmutableList.Builder) builder).add(deserialized); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/PermissionConfigurationSerializer.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/PermissionConfigurationSerializer.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d1088e4b7fa5f8e689f23b150b83645ce1ae5a0e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/PermissionConfigurationSerializer.java +@@ -0,0 +1,56 @@ ++package io.papermc.paper.plugin.provider.configuration.serializer; ++ ++import io.papermc.paper.plugin.provider.configuration.type.PermissionConfiguration; ++import org.bukkit.permissions.Permission; ++import org.bukkit.permissions.PermissionDefault; ++import org.spongepowered.configurate.ConfigurationNode; ++import org.spongepowered.configurate.serialize.SerializationException; ++import org.spongepowered.configurate.serialize.TypeSerializer; ++ ++import java.lang.reflect.Type; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; ++ ++public class PermissionConfigurationSerializer { ++ ++ public static final Serializer SERIALIZER = new Serializer(); ++ ++ private static final class Serializer implements TypeSerializer { ++ private Serializer() { ++ super(); ++ } ++ ++ @Override ++ public PermissionConfiguration deserialize(Type type, ConfigurationNode node) throws SerializationException { ++ Map map = (Map) node.node("permissions").raw(); ++ ++ PermissionDefault permissionDefault; ++ ConfigurationNode permNode = node.node("defaultPerm"); ++ if (permNode.virtual()) { ++ permissionDefault = PermissionDefault.OP; ++ } else { ++ permissionDefault = PermissionDefault.getByName(permNode.getString()); ++ } ++ ++ List result = new ArrayList<>(); ++ if (map != null) { ++ for (Map.Entry entry : map.entrySet()) { ++ try { ++ result.add(Permission.loadPermission(entry.getKey().toString(), (Map) entry.getValue(), permissionDefault, result)); ++ } catch (Throwable ex) { ++ throw new SerializationException(null, "Error loading permission %s".formatted(entry.getKey()), ex); ++ } ++ } ++ } ++ ++ return new PermissionConfiguration(permissionDefault, List.copyOf(result)); ++ } ++ ++ @Override ++ public void serialize(Type type, @org.checkerframework.checker.nullness.qual.Nullable PermissionConfiguration obj, ConfigurationNode node) throws SerializationException { ++ ++ } ++ ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/constraints/PluginConfigConstraints.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/constraints/PluginConfigConstraints.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a0109a388188b0808900405d334a40318ab16ec1 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/serializer/constraints/PluginConfigConstraints.java +@@ -0,0 +1,86 @@ ++package io.papermc.paper.plugin.provider.configuration.serializer.constraints; ++ ++import io.papermc.paper.plugin.util.NamespaceChecker; ++import org.spongepowered.configurate.objectmapping.meta.Constraint; ++import org.spongepowered.configurate.serialize.SerializationException; ++ ++import java.lang.annotation.Documented; ++import java.lang.annotation.ElementType; ++import java.lang.annotation.Retention; ++import java.lang.annotation.RetentionPolicy; ++import java.lang.annotation.Target; ++import java.lang.reflect.Type; ++import java.util.Locale; ++import java.util.Set; ++import java.util.regex.Pattern; ++ ++public final class PluginConfigConstraints { ++ ++ public static final Set RESERVED_KEYS = Set.of("bukkit", "minecraft", "mojang", "spigot", "paper"); ++ public static final Set VALID_PAPER_VERSIONS = Set.of("1.19"); ++ ++ @Documented ++ @Retention(RetentionPolicy.RUNTIME) ++ @Target(ElementType.FIELD) ++ public @interface PluginName { ++ ++ final class Factory implements Constraint.Factory { ++ ++ private static final Pattern VALID_NAME = Pattern.compile("^[A-Za-z\\d _.-]+$"); ++ ++ @Override ++ public Constraint make(PluginName data, Type type) { ++ return value -> { ++ if (value != null) { ++ if (RESERVED_KEYS.contains(value.toLowerCase(Locale.ROOT))) { ++ throw new SerializationException("Restricted name, cannot use '%s' as a plugin name.".formatted(data)); ++ } else if (value.indexOf(' ') != -1) { ++ // For legacy reasons, the space condition has a separate exception message. ++ throw new SerializationException("Restricted name, cannot use 0x20 (space character) in a plugin name."); ++ } ++ ++ if (!VALID_NAME.matcher(value).matches()) { ++ throw new SerializationException("name '" + value + "' contains invalid characters."); ++ } ++ } ++ }; ++ } ++ } ++ } ++ ++ @Documented ++ @Retention(RetentionPolicy.RUNTIME) ++ @Target(ElementType.FIELD) ++ public @interface PluginNameSpace { ++ ++ final class Factory implements Constraint.Factory { ++ ++ @Override ++ public Constraint make(PluginNameSpace data, Type type) { ++ return value -> { ++ if (value != null && !NamespaceChecker.isValidNameSpace(value)) { ++ throw new SerializationException("provided class '%s' is in an invalid namespace.".formatted(value)); ++ } ++ }; ++ } ++ } ++ } ++ ++ @Documented ++ @Retention(RetentionPolicy.RUNTIME) ++ @Target(ElementType.FIELD) ++ public @interface PluginVersion { ++ ++ final class Factory implements Constraint.Factory { ++ ++ @Override ++ public Constraint make(PluginVersion data, Type type) { ++ return value -> { ++ if (value != null && !VALID_PAPER_VERSIONS.contains(value)) { ++ throw new SerializationException("Provided plugin's version (%s) is not supported on this version.".formatted(value)); ++ } ++ }; ++ } ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/type/DependencyConfiguration.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/type/DependencyConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..071bff3f988a4391be424bdf7e98a6c35e6cac67 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/type/DependencyConfiguration.java +@@ -0,0 +1,12 @@ ++package io.papermc.paper.plugin.provider.configuration.type; ++ ++import org.spongepowered.configurate.objectmapping.ConfigSerializable; ++import org.spongepowered.configurate.objectmapping.meta.Required; ++ ++@ConfigSerializable ++public record DependencyConfiguration( ++ @Required String name, ++ boolean required, ++ boolean bootstrap ++) { ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/type/PermissionConfiguration.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/type/PermissionConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a180612a1ec395202dbae1ca5b97ec01382097e4 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/type/PermissionConfiguration.java +@@ -0,0 +1,14 @@ ++package io.papermc.paper.plugin.provider.configuration.type; ++ ++import org.bukkit.permissions.Permission; ++import org.bukkit.permissions.PermissionDefault; ++import org.spongepowered.configurate.objectmapping.ConfigSerializable; ++ ++import java.util.List; ++ ++// Record components used for deserialization!!!! ++@ConfigSerializable ++public record PermissionConfiguration( ++ PermissionDefault defaultPerm, ++ List permissions) { ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/source/DirectoryProviderSource.java b/src/main/java/io/papermc/paper/plugin/provider/source/DirectoryProviderSource.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1822e076601db51c8a7954036853bee1fb8e3704 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/source/DirectoryProviderSource.java +@@ -0,0 +1,40 @@ ++package io.papermc.paper.plugin.provider.source; ++ ++import com.mojang.logging.LogUtils; ++import io.papermc.paper.plugin.entrypoint.EntrypointHandler; ++import org.slf4j.Logger; ++ ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.util.logging.Level; ++ ++/** ++ * Loads all plugin providers in the given directory. ++ */ ++public class DirectoryProviderSource extends FileProviderSource { ++ ++ public static final DirectoryProviderSource INSTANCE = new DirectoryProviderSource(); ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ ++ public DirectoryProviderSource() { ++ super("Directory '%s'"::formatted); ++ } ++ ++ @Override ++ public void registerProviders(EntrypointHandler entrypointHandler, Path context) throws Exception { ++ // Sym link happy, create file if missing. ++ if (!Files.isDirectory(context)) { ++ Files.createDirectories(context); ++ } ++ ++ Files.walk(context, 1).filter(Files::isRegularFile).forEach((path) -> { ++ try { ++ super.registerProviders(entrypointHandler, path); ++ } catch (IllegalArgumentException ignored) { ++ // Ignore initial argument exceptions ++ } catch (Exception e) { ++ LOGGER.error("Error loading plugin: " + e.getMessage(), e); ++ } ++ }); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java b/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java +new file mode 100644 +index 0000000000000000000000000000000000000000..cfc34bbb32d5cf19dbb100003a4aae620696d446 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/source/FileProviderSource.java +@@ -0,0 +1,154 @@ ++package io.papermc.paper.plugin.provider.source; ++ ++import io.papermc.paper.plugin.PluginInitializerManager; ++import io.papermc.paper.plugin.entrypoint.EntrypointHandler; ++import io.papermc.paper.plugin.provider.type.PluginFileType; ++import org.bukkit.plugin.InvalidPluginException; ++import org.jetbrains.annotations.Nullable; ++ ++import java.io.File; ++import java.io.IOException; ++import java.nio.file.FileVisitResult; ++import java.nio.file.FileVisitor; ++import java.nio.file.Files; ++import java.nio.file.Path; ++import java.nio.file.StandardCopyOption; ++import java.nio.file.attribute.BasicFileAttributes; ++import java.util.Set; ++import java.util.function.Function; ++import java.util.jar.JarFile; ++ ++/** ++ * Loads a plugin provider at the given plugin jar file path. ++ */ ++public class FileProviderSource implements ProviderSource { ++ ++ private final Function contextChecker; ++ ++ public FileProviderSource(Function contextChecker) { ++ this.contextChecker = contextChecker; ++ } ++ ++ @Override ++ public void registerProviders(EntrypointHandler entrypointHandler, Path context) throws Exception { ++ String source = this.contextChecker.apply(context); ++ ++ if (Files.notExists(context)) { ++ throw new IllegalArgumentException(source + " does not exist, cannot load a plugin from it!"); ++ } ++ ++ if (!Files.isRegularFile(context)) { ++ throw new IllegalArgumentException(source + " is not a file, cannot load a plugin from it!"); ++ } ++ ++ if (!context.getFileName().toString().endsWith(".jar")) { ++ throw new IllegalArgumentException(source + " is not a jar file, cannot load a plugin from it!"); ++ } ++ ++ try { ++ this.checkUpdate(context); ++ ++ JarFile file = new JarFile(context.toFile()); ++ PluginFileType type = PluginFileType.guessType(file); ++ if (type == null) { ++ throw new IllegalArgumentException(source + " is not a valid plugin file, cannot load a plugin from it!"); ++ } ++ ++ type.register(entrypointHandler, file, context); ++ } catch (Exception exception) { ++ throw new RuntimeException(source + " failed to load!", exception); ++ } ++ } ++ ++ /** ++ * Replaces a plugin with a plugin of the same plugin name in the update folder. ++ * ++ * @param file ++ */ ++ private Path checkUpdate(Path file) throws Exception { ++ PluginInitializerManager pluginSystem = PluginInitializerManager.instance(); ++ if (!Files.isDirectory(pluginSystem.pluginUpdatePath())) { ++ return file; ++ } ++ ++ try { ++ String pluginName = this.getPluginName(file); ++ UpdateFileVisitor visitor = new UpdateFileVisitor(pluginName); ++ Files.walkFileTree(pluginSystem.pluginUpdatePath(), Set.of(), 1, visitor); ++ if (visitor.getValidPlugin() != null) { ++ Path updateLocation = visitor.getValidPlugin(); ++ ++ try { ++ Files.copy(updateLocation, file, StandardCopyOption.REPLACE_EXISTING); ++ } catch (IOException exception) { ++ throw new RuntimeException("Could not copy '" + updateLocation + "' to '" + file + "' in update plugin process", exception); ++ } ++ ++ // Idk what this is about, TODO ++ File newName = new File(file.toFile().getParentFile(), updateLocation.toFile().getName()); ++ file.toFile().renameTo(newName); ++ updateLocation.toFile().delete(); ++ } ++ } catch (Exception e) { ++ throw new InvalidPluginException(e); ++ } ++ return file; ++ } ++ ++ private String getPluginName(Path path) throws Exception { ++ JarFile file = new JarFile(path.toFile()); ++ PluginFileType type = PluginFileType.guessType(file); ++ if (type == null) { ++ throw new IllegalArgumentException(path + " is not a valid plugin file, cannot load a plugin from it!"); ++ } ++ ++ return type.getConfig(file).getName(); ++ } ++ ++ private class UpdateFileVisitor implements FileVisitor { ++ ++ private final String targetName; ++ @Nullable ++ private Path validPlugin; ++ ++ private UpdateFileVisitor(String targetName) { ++ this.targetName = targetName; ++ } ++ ++ @Override ++ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { ++ return FileVisitResult.CONTINUE; ++ } ++ ++ @Override ++ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { ++ try { ++ String updatePluginName = FileProviderSource.this.getPluginName(file); ++ if (this.targetName.equals(updatePluginName)) { ++ this.validPlugin = file; ++ return FileVisitResult.TERMINATE; ++ } ++ } catch (Exception e) { ++ // We failed to load this data for some reason, so, we'll skip over this ++ } ++ ++ ++ return FileVisitResult.CONTINUE; ++ } ++ ++ @Override ++ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { ++ return FileVisitResult.CONTINUE; ++ } ++ ++ @Override ++ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { ++ return FileVisitResult.CONTINUE; ++ } ++ ++ @Nullable ++ public Path getValidPlugin() { ++ return validPlugin; ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/source/PluginFlagProviderSource.java b/src/main/java/io/papermc/paper/plugin/provider/source/PluginFlagProviderSource.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e62b476ddbce2bdc66061c116aa0228622f6fd16 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/source/PluginFlagProviderSource.java +@@ -0,0 +1,29 @@ ++package io.papermc.paper.plugin.provider.source; ++ ++import com.mojang.logging.LogUtils; ++import io.papermc.paper.plugin.entrypoint.EntrypointHandler; ++import org.slf4j.Logger; ++ ++import java.io.File; ++import java.util.List; ++ ++/** ++ * Registers providers at the provided files in the add-plugin argument. ++ */ ++public class PluginFlagProviderSource implements ProviderSource> { ++ ++ public static final PluginFlagProviderSource INSTANCE = new PluginFlagProviderSource(); ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ private final FileProviderSource providerSource = new FileProviderSource("File '%s' specified through 'add-plugin' argument"::formatted); ++ ++ @Override ++ public void registerProviders(EntrypointHandler entrypointHandler, List context) { ++ for (File file : context) { ++ try { ++ this.providerSource.registerProviders(entrypointHandler, file.toPath()); ++ } catch (Exception e) { ++ LOGGER.error("Error loading plugin: " + e.getMessage(), e); ++ } ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/source/ProviderSource.java b/src/main/java/io/papermc/paper/plugin/provider/source/ProviderSource.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6d247819ee842eb054a74711a0e5805ac8f0498e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/source/ProviderSource.java +@@ -0,0 +1,14 @@ ++package io.papermc.paper.plugin.provider.source; ++ ++import io.papermc.paper.plugin.entrypoint.EntrypointHandler; ++ ++/** ++ * A provider source is responsible for giving PluginTypes an EntrypointHandler for ++ * registering providers at. ++ * ++ * @param context ++ */ ++public interface ProviderSource { ++ ++ void registerProviders(EntrypointHandler entrypointHandler, C context) throws Throwable; ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java b/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java +new file mode 100644 +index 0000000000000000000000000000000000000000..22c25dc6fdfd336f5074fa52c3a4e8128d433ccc +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/PluginFileType.java +@@ -0,0 +1,77 @@ ++package io.papermc.paper.plugin.provider.type; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.entrypoint.Entrypoint; ++import io.papermc.paper.plugin.entrypoint.EntrypointHandler; ++import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; ++import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent; ++import io.papermc.paper.plugin.provider.type.spigot.SpigotPluginProvider; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.jetbrains.annotations.Nullable; ++ ++import java.nio.file.Path; ++import java.util.List; ++import java.util.jar.JarEntry; ++import java.util.jar.JarFile; ++ ++/** ++ * This is where spigot/paper plugins are registered. ++ * This will get the jar and find a certain config file, create an object ++ * then registering it into a {@link EntrypointHandler} at a certain {@link Entrypoint}. ++ */ ++public abstract class PluginFileType { ++ ++ public static final PluginFileType PAPER = new PluginFileType<>("paper-plugin.yml", PaperPluginParent.FACTORY) { ++ @Override ++ protected void register(EntrypointHandler entrypointHandler, PaperPluginParent parent) { ++ PaperPluginParent.PaperBootstrapProvider bootstrapPluginProvider = null; ++ if (parent.shouldCreateBootstrap()) { ++ bootstrapPluginProvider = parent.createBootstrapProvider(); ++ entrypointHandler.register(Entrypoint.BOOTSTRAPPER, bootstrapPluginProvider); ++ } ++ ++ entrypointHandler.register(Entrypoint.PLUGIN, parent.createPluginProvider(bootstrapPluginProvider)); ++ } ++ }; ++ public static final PluginFileType SPIGOT = new PluginFileType<>("plugin.yml", SpigotPluginProvider.FACTORY) { ++ @Override ++ protected void register(EntrypointHandler entrypointHandler, SpigotPluginProvider provider) { ++ entrypointHandler.register(Entrypoint.PLUGIN, provider); ++ } ++ }; ++ ++ private static final List> VALUES = List.of(PAPER, SPIGOT); ++ ++ private final String config; ++ private final PluginTypeFactory factory; ++ ++ PluginFileType(String config, PluginTypeFactory factory) { ++ this.config = config; ++ this.factory = factory; ++ } ++ ++ @Nullable ++ public static PluginFileType guessType(JarFile file) { ++ for (PluginFileType type : VALUES) { ++ JarEntry entry = file.getJarEntry(type.config); ++ if (entry != null) { ++ return type; ++ } ++ } ++ ++ return null; ++ } ++ ++ public T register(EntrypointHandler entrypointHandler, JarFile file, Path context) throws Exception { ++ C config = this.getConfig(file); ++ T provider = this.factory.build(file, config, context); ++ this.register(entrypointHandler, provider); ++ return provider; ++ } ++ ++ public C getConfig(JarFile file) throws Exception { ++ return this.factory.create(file, file.getJarEntry(this.config)); ++ } ++ ++ protected abstract void register(EntrypointHandler entrypointHandler, T provider); ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/PluginTypeFactory.java b/src/main/java/io/papermc/paper/plugin/provider/type/PluginTypeFactory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..32f230d66f6953520b59ccbf3079c5a6242ca92c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/PluginTypeFactory.java +@@ -0,0 +1,21 @@ ++package io.papermc.paper.plugin.provider.type; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++ ++import java.nio.file.Path; ++import java.util.jar.JarEntry; ++import java.util.jar.JarFile; ++ ++/** ++ * A plugin type factory is responsible for building an object ++ * and config for a certain plugin type. ++ * ++ * @param plugin provider type (may not be a plugin provider) ++ * @param config type ++ */ ++public interface PluginTypeFactory { ++ ++ T build(JarFile file, C configuration, Path source) throws Exception; ++ ++ C create(JarFile file, JarEntry config) throws Exception; ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..46ee1b7f4b4c509932c68a4152e1d8445811d3b8 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java +@@ -0,0 +1,226 @@ ++package io.papermc.paper.plugin.provider.type.paper; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import io.papermc.paper.plugin.bootstrap.PluginProviderContext; ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++import io.papermc.paper.plugin.entrypoint.dependency.DependencyContextHolder; ++import io.papermc.paper.plugin.bootstrap.PluginBootstrap; ++import io.papermc.paper.plugin.bootstrap.PluginProviderContextImpl; ++import io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.ProviderStatus; ++import io.papermc.paper.plugin.provider.ProviderStatusHolder; ++import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; ++import io.papermc.paper.plugin.provider.type.PluginTypeFactory; ++import io.papermc.paper.plugin.provider.util.ProviderUtil; ++import org.bukkit.Bukkit; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.NotNull; ++ ++import java.nio.file.Path; ++import java.util.jar.JarFile; ++import java.util.logging.Logger; ++ ++public class PaperPluginParent { ++ ++ public static final PluginTypeFactory FACTORY = new PaperPluginProviderFactory(); ++ private final Path path; ++ private final JarFile jarFile; ++ private final PaperPluginMeta description; ++ private final PaperPluginClassLoader classLoader; ++ private final PluginProviderContext context; ++ private final Logger logger; ++ ++ public PaperPluginParent(Path path, JarFile jarFile, PaperPluginMeta description, PaperPluginClassLoader classLoader, PluginProviderContext context) { ++ this.path = path; ++ this.jarFile = jarFile; ++ this.description = description; ++ this.classLoader = classLoader; ++ this.context = context; ++ this.logger = context.getLogger(); ++ } ++ ++ public boolean shouldCreateBootstrap() { ++ return this.description.getBootstrapper() != null; ++ } ++ ++ public PaperBootstrapProvider createBootstrapProvider() { ++ return new PaperBootstrapProvider(); ++ } ++ ++ public PaperServerPluginProvider createPluginProvider(PaperBootstrapProvider provider) { ++ return new PaperServerPluginProvider(provider); ++ } ++ ++ public class PaperBootstrapProvider implements PluginProvider, ProviderStatusHolder, DependencyContextHolder { ++ ++ private ProviderStatus status; ++ private PluginBootstrap lastProvided; ++ ++ @Override ++ public @NotNull Path getSource() { ++ return PaperPluginParent.this.path; ++ } ++ ++ @Override ++ public JarFile file() { ++ return PaperPluginParent.this.jarFile; ++ } ++ ++ @Override ++ public PluginBootstrap createInstance() { ++ PluginBootstrap bootstrap = ProviderUtil.loadClass(PaperPluginParent.this.description.getBootstrapper(), ++ PluginBootstrap.class, PaperPluginParent.this.classLoader, () -> this.status = ProviderStatus.ERRORED); ++ this.status = ProviderStatus.INITIALIZED; ++ this.lastProvided = bootstrap; ++ return bootstrap; ++ } ++ ++ @Override ++ public PaperPluginMeta getMeta() { ++ return PaperPluginParent.this.description; ++ } ++ ++ @Override ++ public Logger getLogger() { ++ return PaperPluginParent.this.logger; ++ } ++ ++ @Override ++ public ProviderStatus getLastProvidedStatus() { ++ return this.status; ++ } ++ ++ @Override ++ public void setStatus(ProviderStatus status) { ++ this.status = status; ++ } ++ ++ public PluginBootstrap getLastProvided() { ++ return this.lastProvided; ++ } ++ ++ @Override ++ public void setContext(DependencyContext context) { ++ PaperPluginParent.this.classLoader.refreshClassloaderDependencyTree(context); ++ } ++ ++ @Override ++ public String toString() { ++ return "PaperBootstrapProvider{" + ++ "parent=" + PaperPluginParent.this + ++ "status=" + status + ++ ", lastProvided=" + lastProvided + ++ '}'; ++ } ++ } ++ ++ public class PaperServerPluginProvider implements PluginProvider, ProviderStatusHolder, DependencyContextHolder { ++ ++ private final PaperBootstrapProvider bootstrapProvider; ++ ++ private ProviderStatus status; ++ ++ PaperServerPluginProvider(PaperBootstrapProvider bootstrapProvider) { ++ this.bootstrapProvider = bootstrapProvider; ++ } ++ ++ @Override ++ public @NotNull Path getSource() { ++ return PaperPluginParent.this.path; ++ } ++ ++ @Override ++ public JarFile file() { ++ return PaperPluginParent.this.jarFile; ++ } ++ ++ @Override ++ public JavaPlugin createInstance() { ++ PluginBootstrap bootstrap = null; ++ if (this.bootstrapProvider != null && this.bootstrapProvider.getLastProvided() != null) { ++ bootstrap = this.bootstrapProvider.getLastProvided(); ++ } ++ ++ try { ++ JavaPlugin plugin; ++ if (bootstrap == null) { ++ plugin = ProviderUtil.loadClass(PaperPluginParent.this.description.getMainClass(), JavaPlugin.class, PaperPluginParent.this.classLoader); ++ } else { ++ plugin = bootstrap.createPlugin(PaperPluginParent.this.context); ++ } ++ ++ // Don't allow plugins to load plugins other than the one defined in main. This restriction might not be necessary. ++ if (!plugin.getClass().isAssignableFrom(Class.forName(PaperPluginParent.this.description.getMainClass(), true, plugin.getClass().getClassLoader()))) { ++ throw new IllegalArgumentException("Plugin provided must be the same type as main defined in plugin configuration!"); ++ } ++ ++ this.status = ProviderStatus.INITIALIZED; ++ return plugin; ++ } catch (Throwable throwable) { ++ this.status = ProviderStatus.ERRORED; ++ SneakyThrow.sneaky(throwable); ++ } ++ ++ throw new AssertionError(); // Impossible ++ } ++ ++ @Override ++ public PaperPluginMeta getMeta() { ++ return PaperPluginParent.this.description; ++ } ++ ++ @Override ++ public Logger getLogger() { ++ return PaperPluginParent.this.logger; ++ } ++ ++ @Override ++ public ProviderStatus getLastProvidedStatus() { ++ return this.status; ++ } ++ ++ @Override ++ public void setStatus(ProviderStatus status) { ++ this.status = status; ++ } ++ ++ public boolean shouldSkipCreation() { ++ if (this.bootstrapProvider == null) { ++ return false; ++ } ++ ++ return this.bootstrapProvider.getLastProvidedStatus() == ProviderStatus.ERRORED; ++ } ++ ++ /* ++ The plugin has to reuse the classloader in order to share the bootstrapper. ++ However, a plugin may have totally separate dependencies during bootstrapping. ++ This is a bit yuck, but in general we have to treat bootstrapping and normal game as connected. ++ */ ++ @Override ++ public void setContext(DependencyContext context) { ++ PaperPluginParent.this.classLoader.refreshClassloaderDependencyTree(context); ++ } ++ ++ @Override ++ public String toString() { ++ return "PaperServerPluginProvider{" + ++ "parent=" + PaperPluginParent.this + ++ "bootstrapProvider=" + bootstrapProvider + ++ ", status=" + status + ++ '}'; ++ } ++ } ++ ++ ++ @Override ++ public String toString() { ++ return "PaperPluginParent{" + ++ "path=" + path + ++ ", jarFile=" + jarFile + ++ ", description=" + description + ++ ", classLoader=" + classLoader + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginProviderFactory.java b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginProviderFactory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..db343a2f482ac375078610f0875692861f412ee2 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginProviderFactory.java +@@ -0,0 +1,54 @@ ++package io.papermc.paper.plugin.provider.type.paper; ++ ++import com.destroystokyo.paper.utils.PaperPluginLogger; ++import io.papermc.paper.plugin.bootstrap.PluginProviderContext; ++import io.papermc.paper.plugin.bootstrap.PluginProviderContextImpl; ++import io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader; ++import io.papermc.paper.plugin.entrypoint.classloader.PaperSimplePluginClassLoader; ++import io.papermc.paper.plugin.loader.PaperClasspathBuilder; ++import io.papermc.paper.plugin.loader.PluginLoader; ++import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; ++import io.papermc.paper.plugin.provider.type.PluginTypeFactory; ++import io.papermc.paper.plugin.provider.util.ProviderUtil; ++ ++import java.io.BufferedReader; ++import java.io.IOException; ++import java.io.InputStreamReader; ++import java.nio.file.Path; ++import java.util.jar.JarEntry; ++import java.util.jar.JarFile; ++import java.util.logging.Logger; ++ ++class PaperPluginProviderFactory implements PluginTypeFactory { ++ ++ @Override ++ public PaperPluginParent build(JarFile file, PaperPluginMeta configuration, Path source) throws Exception { ++ Logger logger = PaperPluginLogger.getLogger(configuration); ++ PluginProviderContext context = PluginProviderContextImpl.of(configuration, logger); ++ ++ PaperClasspathBuilder builder = new PaperClasspathBuilder(context); ++ ++ if (configuration.getLoader() != null) { ++ try ( ++ PaperSimplePluginClassLoader simplePluginClassLoader = new PaperSimplePluginClassLoader(source, file, configuration, this.getClass().getClassLoader()) ++ ) { ++ PluginLoader loader = ProviderUtil.loadClass(configuration.getLoader(), PluginLoader.class, simplePluginClassLoader); ++ loader.classloader(builder); ++ } catch (IOException e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++ PaperPluginClassLoader classLoader = builder.buildClassLoader(logger, source, file, configuration); ++ return new PaperPluginParent(source, file, configuration, classLoader, context); ++ } ++ ++ @Override ++ public PaperPluginMeta create(JarFile file, JarEntry config) throws Exception { ++ PaperPluginMeta configuration; ++ try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(file.getInputStream(config)))) { ++ configuration = PaperPluginMeta.create(bufferedReader); ++ } ++ return configuration; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java +new file mode 100644 +index 0000000000000000000000000000000000000000..309c3dc492cbf469768d6a712485a0e42e73f947 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java +@@ -0,0 +1,172 @@ ++package io.papermc.paper.plugin.provider.type.spigot; ++ ++import com.destroystokyo.paper.util.SneakyThrow; ++import com.destroystokyo.paper.utils.PaperPluginLogger; ++import io.papermc.paper.plugin.manager.PaperPluginManagerImpl; ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++import io.papermc.paper.plugin.entrypoint.dependency.DependencyContextHolder; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.ProviderStatus; ++import io.papermc.paper.plugin.provider.ProviderStatusHolder; ++import io.papermc.paper.plugin.provider.type.PluginTypeFactory; ++import org.bukkit.Bukkit; ++import org.bukkit.Server; ++import org.bukkit.plugin.InvalidPluginException; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.UnknownDependencyException; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.bukkit.plugin.java.LibraryLoader; ++import org.bukkit.plugin.java.PluginClassLoader; ++import org.jetbrains.annotations.NotNull; ++ ++import java.io.File; ++import java.nio.file.Path; ++import java.util.HashSet; ++import java.util.Set; ++import java.util.jar.JarFile; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++public class SpigotPluginProvider implements PluginProvider, ProviderStatusHolder, DependencyContextHolder { ++ ++ public static final PluginTypeFactory FACTORY = new SpigotPluginProviderFactory(); ++ private static final LibraryLoader LIBRARY_LOADER = new LibraryLoader(Logger.getLogger("SpigotLibraryLoader")); ++ private final Path path; ++ private final PluginDescriptionFile description; ++ private final JarFile jarFile; ++ private final Logger logger; ++ private ProviderStatus status; ++ private DependencyContext dependencyContext; ++ ++ SpigotPluginProvider(Path path, JarFile file, PluginDescriptionFile description) { ++ this.path = path; ++ this.jarFile = file; ++ this.description = description; ++ this.logger = PaperPluginLogger.getLogger(description); ++ } ++ ++ @Override ++ public @NotNull Path getSource() { ++ return this.path; ++ } ++ ++ @Override ++ public JarFile file() { ++ return this.jarFile; ++ } ++ ++ @Override ++ public JavaPlugin createInstance() { ++ Server server = Bukkit.getServer(); ++ try { ++ ++ final File parentFile = server.getPluginsFolder(); // Paper ++ final File dataFolder = new File(parentFile, this.description.getName()); ++ @SuppressWarnings("deprecation") final File oldDataFolder = new File(parentFile, this.description.getRawName()); ++ ++ // Found old data folder ++ if (dataFolder.equals(oldDataFolder)) { ++ // They are equal -- nothing needs to be done! ++ } else if (dataFolder.isDirectory() && oldDataFolder.isDirectory()) { ++ server.getLogger().warning(String.format( ++ "While loading %s (%s) found old-data folder: `%s' next to the new one `%s'", ++ this.description.getFullName(), ++ this.path, ++ oldDataFolder, ++ dataFolder ++ )); ++ } else if (oldDataFolder.isDirectory() && !dataFolder.exists()) { ++ if (!oldDataFolder.renameTo(dataFolder)) { ++ throw new InvalidPluginException("Unable to rename old data folder: `" + oldDataFolder + "' to: `" + dataFolder + "'"); ++ } ++ server.getLogger().log(Level.INFO, String.format( ++ "While loading %s (%s) renamed data folder: `%s' to `%s'", ++ this.description.getFullName(), ++ this.path, ++ oldDataFolder, ++ dataFolder ++ )); ++ } ++ ++ if (dataFolder.exists() && !dataFolder.isDirectory()) { ++ throw new InvalidPluginException(String.format( ++ "Projected datafolder: `%s' for %s (%s) exists and is not a directory", ++ dataFolder, ++ this.description.getFullName(), ++ this.path ++ )); ++ } ++ ++ Set missingHardDependencies = new HashSet<>(this.description.getDepend().size()); // Paper - list all missing hard depends ++ for (final String pluginName : this.description.getDepend()) { ++ if (!this.dependencyContext.hasDependency(pluginName)) { ++ missingHardDependencies.add(pluginName); // Paper - list all missing hard depends ++ } ++ } ++ // Paper start - list all missing hard depends ++ if (!missingHardDependencies.isEmpty()) { ++ throw new UnknownDependencyException(missingHardDependencies, this.description.getFullName()); ++ } ++ // Paper end ++ ++ server.getUnsafe().checkSupported(this.description); ++ ++ final PluginClassLoader loader; ++ try { ++ loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description), this.dependencyContext); // Paper ++ } catch (InvalidPluginException ex) { ++ throw ex; ++ } catch (Throwable ex) { ++ throw new InvalidPluginException(ex); ++ } ++ ++ // Override dependency context. ++ // We must provide a temporary context in order to properly handle dependencies on the plugin classloader constructor. ++ loader.dependencyContext = PaperPluginManagerImpl.getInstance(); ++ ++ this.status = ProviderStatus.INITIALIZED; ++ return loader.plugin; ++ } catch (Throwable ex) { ++ this.status = ProviderStatus.ERRORED; ++ SneakyThrow.sneaky(ex); ++ } ++ ++ throw new AssertionError(); // Shouldn't happen ++ } ++ ++ @Override ++ public PluginDescriptionFile getMeta() { ++ return this.description; ++ } ++ ++ @Override ++ public Logger getLogger() { ++ return this.logger; ++ } ++ ++ @Override ++ public ProviderStatus getLastProvidedStatus() { ++ return this.status; ++ } ++ ++ @Override ++ public void setStatus(ProviderStatus status) { ++ this.status = status; ++ } ++ ++ @Override ++ public void setContext(DependencyContext context) { ++ this.dependencyContext = context; ++ } ++ ++ @Override ++ public String toString() { ++ return "SpigotPluginProvider{" + ++ "path=" + path + ++ ", description=" + description + ++ ", jarFile=" + jarFile + ++ ", status=" + status + ++ ", dependencyContext=" + dependencyContext + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java +new file mode 100644 +index 0000000000000000000000000000000000000000..14ed05945ba5bfeb2b539d4786278b0e04130404 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java +@@ -0,0 +1,45 @@ ++package io.papermc.paper.plugin.provider.type.spigot; ++ ++import io.papermc.paper.plugin.provider.configuration.serializer.constraints.PluginConfigConstraints; ++import io.papermc.paper.plugin.provider.type.PluginTypeFactory; ++import org.bukkit.plugin.InvalidDescriptionException; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.yaml.snakeyaml.error.YAMLException; ++ ++import java.io.IOException; ++import java.io.InputStream; ++import java.nio.file.Path; ++import java.util.Locale; ++import java.util.jar.JarEntry; ++import java.util.jar.JarFile; ++ ++class SpigotPluginProviderFactory implements PluginTypeFactory { ++ ++ @Override ++ public SpigotPluginProvider build(JarFile file, PluginDescriptionFile configuration, Path source) throws Exception { ++ // Copied from SimplePluginManager#loadPlugins ++ // Spigot doesn't validate the name when the config is created, and instead when the plugin is loaded. ++ // Paper plugin configuration will do these checks in config serializer instead of when this is created. ++ String name = configuration.getRawName(); ++ if (PluginConfigConstraints.RESERVED_KEYS.contains(name.toLowerCase(Locale.ROOT))) { ++ throw new InvalidDescriptionException("Restricted name, cannot use %s as a plugin name.".formatted(name)); ++ } else if (name.indexOf(' ') != -1) { ++ throw new InvalidDescriptionException("Restricted name, cannot use 0x20 (space character) in a plugin name."); ++ } ++ ++ return new SpigotPluginProvider(source, file, configuration); ++ } ++ ++ @Override ++ public PluginDescriptionFile create(JarFile file, JarEntry config) throws Exception { ++ PluginDescriptionFile descriptionFile; ++ try (InputStream inputStream = file.getInputStream(config)) { ++ descriptionFile = new PluginDescriptionFile(inputStream); ++ } catch (IOException | YAMLException ex) { ++ throw new InvalidDescriptionException(ex); ++ } ++ ++ return descriptionFile; ++ } ++} ++ +diff --git a/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java b/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7af995b941ce83265a93cdc6b5a2de8ad27e4db6 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java +@@ -0,0 +1,113 @@ ++package io.papermc.paper.plugin.storage; ++ ++import com.mojang.logging.LogUtils; ++import io.papermc.paper.plugin.PluginInitializerManager; ++import io.papermc.paper.plugin.bootstrap.PluginBootstrap; ++import io.papermc.paper.plugin.bootstrap.PluginProviderContext; ++import io.papermc.paper.plugin.bootstrap.PluginProviderContextImpl; ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++import io.papermc.paper.plugin.entrypoint.dependency.DependencyContextHolder; ++import io.papermc.paper.plugin.entrypoint.strategy.ModernPluginLoadingStrategy; ++import io.papermc.paper.plugin.entrypoint.strategy.PluginGraphCycleException; ++import io.papermc.paper.plugin.entrypoint.strategy.ProviderConfiguration; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.ProviderStatus; ++import io.papermc.paper.plugin.provider.ProviderStatusHolder; ++import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; ++import io.papermc.paper.plugin.provider.configuration.type.DependencyConfiguration; ++import org.slf4j.Logger; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++public class BootstrapProviderStorage extends SimpleProviderStorage { ++ ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ ++ public BootstrapProviderStorage() { ++ super(new ModernPluginLoadingStrategy<>(new ProviderConfiguration<>() { ++ @Override ++ public void applyContext(PluginProvider provider, DependencyContext dependencyContext) { ++ if (provider instanceof DependencyContextHolder contextHolder) { ++ contextHolder.setContext(dependencyContext); ++ } ++ } ++ ++ @Override ++ public boolean load(PluginProvider provider, PluginBootstrap provided) { ++ try { ++ PluginProviderContext context = PluginProviderContextImpl.of(provider, PluginInitializerManager.instance().pluginDirectoryPath()); ++ provided.bootstrap(context); ++ return true; ++ } catch (Exception e) { ++ LOGGER.error("Failed to run bootstrapper for %s. This plugin will not be loaded.".formatted(provider.getSource()), e); ++ if (provider instanceof ProviderStatusHolder statusHolder) { ++ statusHolder.setStatus(ProviderStatus.ERRORED); ++ } ++ return false; ++ } ++ } ++ ++ @Override ++ public List requiredDependencies(PluginProvider provider) { ++ List dependencies = new ArrayList<>(); ++ if (provider.getMeta() instanceof PaperPluginMeta paperPluginMeta) { ++ for (DependencyConfiguration configuration : paperPluginMeta.getDependencies()) { ++ if (configuration.required() && configuration.bootstrap()) { ++ dependencies.add(configuration.name()); ++ } ++ } ++ ++ return dependencies; ++ } ++ ++ throw new IllegalStateException(); ++ } ++ ++ @Override ++ public List optionalDependencies(PluginProvider provider) { ++ List dependencies = new ArrayList<>(); ++ if (provider.getMeta() instanceof PaperPluginMeta paperPluginMeta) { ++ for (DependencyConfiguration configuration : paperPluginMeta.getDependencies()) { ++ if (!configuration.required() && configuration.bootstrap()) { ++ dependencies.add(configuration.name()); ++ } ++ } ++ ++ return dependencies; ++ } ++ ++ throw new IllegalStateException(); ++ } ++ ++ @Override ++ public List loadBeforeDependencies(PluginProvider provider) { ++ return provider.getMeta().getLoadBeforePlugins(); ++ } ++ })); ++ } ++ ++ @Override ++ protected void handleCycle(PluginGraphCycleException exception) { ++ List logMessages = new ArrayList<>(); ++ for (List list : exception.getCycles()) { ++ // CoolPlugin depends on Dependency depends on CoolPlugin... ++ logMessages.add(String.join(" depends on ", list) + " depends on " + list.get(0) + "..."); ++ } ++ ++ LOGGER.error("Circular dependencies detected!"); ++ LOGGER.error("You have a plugin that is depending on a plugin which refers back to that plugin. Your server will shut down until these are resolved, or the strategy is changed."); ++ LOGGER.error("Circular dependencies:"); ++ for (String message : logMessages) { ++ LOGGER.error(message); ++ } ++ LOGGER.error("If you would like to still load these plugins, acknowledging that there may be unexpected plugin loading issues, run the server with -Dpaper.useLegacyPluginLoading=true"); ++ ++ System.exit(-1); ++ } ++ ++ @Override ++ public String toString() { ++ return "BOOTSTRAP:" + super.toString(); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/storage/ConfiguredProviderStorage.java b/src/main/java/io/papermc/paper/plugin/storage/ConfiguredProviderStorage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..93575a996933b4923e3bdc7dd88ffeb736c42e69 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/storage/ConfiguredProviderStorage.java +@@ -0,0 +1,49 @@ ++package io.papermc.paper.plugin.storage; ++ ++import io.papermc.paper.plugin.entrypoint.strategy.LegacyPluginLoadingStrategy; ++import io.papermc.paper.plugin.entrypoint.strategy.ModernPluginLoadingStrategy; ++import io.papermc.paper.plugin.entrypoint.strategy.PluginGraphCycleException; ++import io.papermc.paper.plugin.entrypoint.strategy.ProviderConfiguration; ++ ++import java.util.ArrayList; ++import java.util.List; ++import java.util.logging.Level; ++import java.util.logging.Logger; ++ ++public abstract class ConfiguredProviderStorage extends SimpleProviderStorage { ++ ++ private static final Logger LOGGER = Logger.getLogger("ConfiguredOrderedProviderStorage"); ++ public static final boolean LEGACY_PLUGIN_LOADING = Boolean.getBoolean("paper.useLegacyPluginLoading"); ++ ++ protected ConfiguredProviderStorage(ProviderConfiguration onLoad) { ++ // This doesn't work with reloading. ++ // Should we care? ++ super(LEGACY_PLUGIN_LOADING ? new LegacyPluginLoadingStrategy<>(onLoad) : new ModernPluginLoadingStrategy<>(onLoad)); ++ } ++ ++ @Override ++ protected void handleCycle(PluginGraphCycleException exception) { ++ List logMessages = new ArrayList<>(); ++ for (List list : exception.getCycles()) { ++ // CoolPlugin depends on Dependency depends on CoolPlugin... ++ logMessages.add(String.join(" depends on ", list) + " depends on " + list.get(0) + "..."); ++ } ++ ++ LOGGER.log(Level.SEVERE, "Circular dependencies detected!"); ++ LOGGER.log(Level.SEVERE, "You have a plugin that is depending on a plugin which refers back to that plugin. Your server will shut down until these are resolved, or the strategy is changed."); ++ LOGGER.log(Level.SEVERE, "Circular dependencies:"); ++ for (String message : logMessages) { ++ LOGGER.log(Level.SEVERE, message); ++ } ++ LOGGER.log(Level.SEVERE, "If you would like to still load these plugins, acknowledging that there may be unexpected plugin loading issues, run the server with -Dpaper.useLegacyPluginLoading=true"); ++ ++ if (this.exitOnCycleDependencies()) { ++ System.exit(-1); ++ } ++ } ++ ++ public boolean exitOnCycleDependencies() { ++ return true; ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/storage/ProviderStorage.java b/src/main/java/io/papermc/paper/plugin/storage/ProviderStorage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..374e7d3d69fc8603ecf54999f173123d3a9fbf6e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/storage/ProviderStorage.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.plugin.storage; ++ ++import io.papermc.paper.plugin.provider.PluginProvider; ++ ++/** ++ * A provider storage is meant to be a singleton that stores providers. ++ * ++ * @param provider type ++ */ ++public interface ProviderStorage { ++ ++ void register(PluginProvider provider); ++ ++ void enter(); ++ ++ Iterable> getRegisteredProviders(); ++ ++} +diff --git a/src/main/java/io/papermc/paper/plugin/storage/ServerPluginProviderStorage.java b/src/main/java/io/papermc/paper/plugin/storage/ServerPluginProviderStorage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b049691292fb9d53ac598cb333fa408b043e7bc5 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/storage/ServerPluginProviderStorage.java +@@ -0,0 +1,82 @@ ++package io.papermc.paper.plugin.storage; ++ ++import com.mojang.logging.LogUtils; ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++import io.papermc.paper.plugin.entrypoint.dependency.DependencyContextHolder; ++import io.papermc.paper.plugin.entrypoint.strategy.ProviderConfiguration; ++import io.papermc.paper.plugin.manager.PaperPluginManagerImpl; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.ProviderStatus; ++import io.papermc.paper.plugin.provider.ProviderStatusHolder; ++import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.slf4j.Logger; ++ ++import java.util.List; ++ ++public class ServerPluginProviderStorage extends ConfiguredProviderStorage { ++ ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ ++ public ServerPluginProviderStorage() { ++ super(new ProviderConfiguration<>() { ++ @Override ++ public void applyContext(PluginProvider provider, DependencyContext dependencyContext) { ++ Plugin alreadyLoadedPlugin = PaperPluginManagerImpl.getInstance().getPlugin(provider.getMeta().getName()); ++ if (alreadyLoadedPlugin != null) { ++ throw new IllegalStateException("Provider " + provider + " attempted to add duplicate plugin identifier " + alreadyLoadedPlugin + " THIS WILL CREATE BUGS!!!"); ++ } ++ ++ if (provider instanceof DependencyContextHolder contextHolder) { ++ contextHolder.setContext(dependencyContext); ++ } ++ } ++ ++ @Override ++ public boolean load(PluginProvider provider, JavaPlugin provided) { ++ try { ++ provided.getLogger().info(String.format("Loading server plugin %s", provided.getPluginMeta().getDisplayName())); ++ PaperPluginManagerImpl.getInstance().loadPlugin(provided); // We have to add it to the map before the plugin is loaded ++ provided.onLoad(); ++ return true; ++ } catch (Throwable ex) { ++ if (provider instanceof ProviderStatusHolder statusHolder) { ++ statusHolder.setStatus(ProviderStatus.ERRORED); ++ } ++ LOGGER.error("Could not load server plugin '%s' in folder '%s' (Is it up to date?)".formatted(provider.getFileName(), provider.getParentSource()), ex); ++ return false; ++ } ++ } ++ ++ @Override ++ public List requiredDependencies(PluginProvider provider) { ++ return provider.getMeta().getPluginDependencies(); ++ } ++ ++ @Override ++ public List optionalDependencies(PluginProvider provider) { ++ return provider.getMeta().getPluginSoftDependencies(); ++ } ++ ++ @Override ++ public List loadBeforeDependencies(PluginProvider provider) { ++ return provider.getMeta().getLoadBeforePlugins(); ++ } ++ }); ++ } ++ ++ @Override ++ protected void filterLoadingProviders(List> pluginProviders) { ++ /* ++ Have to do this to prevent loading plugin providers that have failed initializers. ++ This is a hack and a better solution here would be to store failed plugin providers elsewhere. ++ */ ++ pluginProviders.removeIf((provider) -> (provider instanceof PaperPluginParent.PaperServerPluginProvider pluginProvider && pluginProvider.shouldSkipCreation())); ++ } ++ ++ @Override ++ public String toString() { ++ return "PLUGIN:" + super.toString(); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/storage/SimpleProviderStorage.java b/src/main/java/io/papermc/paper/plugin/storage/SimpleProviderStorage.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ac263f02a9a79fb3db24c4daa16c405f9b0f7459 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/storage/SimpleProviderStorage.java +@@ -0,0 +1,57 @@ ++package io.papermc.paper.plugin.storage; ++ ++import io.papermc.paper.plugin.entrypoint.strategy.PluginGraphCycleException; ++import io.papermc.paper.plugin.entrypoint.strategy.ProviderLoadingStrategy; ++import io.papermc.paper.plugin.provider.PluginProvider; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++public abstract class SimpleProviderStorage implements ProviderStorage { ++ ++ protected final List> providers = new ArrayList<>(); ++ protected ProviderLoadingStrategy strategy; ++ ++ protected SimpleProviderStorage(ProviderLoadingStrategy strategy) { ++ this.strategy = strategy; ++ } ++ ++ @Override ++ public void register(PluginProvider provider) { ++ this.providers.add(provider); ++ } ++ ++ @Override ++ public void enter() { ++ List> providerList = new ArrayList<>(this.providers); ++ this.filterLoadingProviders(providerList); ++ ++ try { ++ for (T plugin : this.strategy.loadProviders(providerList)) { ++ this.processProvided(plugin); ++ } ++ } catch (PluginGraphCycleException exception) { ++ this.handleCycle(exception); ++ } ++ } ++ ++ @Override ++ public Iterable> getRegisteredProviders() { ++ return this.providers; ++ } ++ ++ public void processProvided(T provided) {} ++ ++ // Mutable enter ++ protected void filterLoadingProviders(List> providers) {} ++ ++ protected abstract void handleCycle(PluginGraphCycleException exception); ++ ++ @Override ++ public String toString() { ++ return "SimpleProviderStorage{" + ++ "providers=" + this.providers + ++ ", strategy=" + this.strategy + ++ '}'; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/storage/package-info.java b/src/main/java/io/papermc/paper/plugin/storage/package-info.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c1114675137e862ac9682b635bfdbfbc1d7c6e67 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/storage/package-info.java +@@ -0,0 +1,5 @@ ++/** ++ * Classes in this package are supposed to connect components of {@link io.papermc.paper.plugin.entrypoint} and {@link io.papermc.paper.plugin.provider} packages. ++ * @see io.papermc.paper.plugin.entrypoint.Entrypoint ++ */ ++package io.papermc.paper.plugin.storage; +diff --git a/src/main/java/io/papermc/paper/plugin/util/EntrypointUtil.java b/src/main/java/io/papermc/paper/plugin/util/EntrypointUtil.java +new file mode 100644 +index 0000000000000000000000000000000000000000..98518351e616e536315cd89790b327d3bad33d0e +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/util/EntrypointUtil.java +@@ -0,0 +1,19 @@ ++package io.papermc.paper.plugin.util; ++ ++import com.mojang.logging.LogUtils; ++import io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler; ++import io.papermc.paper.plugin.provider.source.ProviderSource; ++import org.slf4j.Logger; ++ ++public class EntrypointUtil { ++ ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ ++ public static void registerProvidersFromSource(ProviderSource source, C context) { ++ try { ++ source.registerProviders(LaunchEntryPointHandler.INSTANCE, context); ++ } catch (Throwable e) { ++ LOGGER.error(e.getMessage(), e); ++ } ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/util/NamespaceChecker.java b/src/main/java/io/papermc/paper/plugin/util/NamespaceChecker.java +new file mode 100644 +index 0000000000000000000000000000000000000000..fd55fd1d6518ebd1bc2513dd331f072018fd4782 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/util/NamespaceChecker.java +@@ -0,0 +1,37 @@ ++package io.papermc.paper.plugin.util; ++ ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++ ++@ApiStatus.Internal ++public class NamespaceChecker { ++ ++ private static final String[] QUICK_INVALID_NAMESPACES = { ++ "net.minecraft.", ++ "org.bukkit.", ++ "io.papermc.paper.", ++ "com.destroystokoyo.paper." ++ }; ++ ++ /** ++ * Used for a variety of namespaces that shouldn't be resolved and should instead be moved to ++ * other classloaders. We can assume this because only plugins should be using this classloader. ++ * ++ * @param name namespace ++ */ ++ public static void validateNameSpaceForClassloading(@NotNull String name) throws ClassNotFoundException { ++ if (!isValidNameSpace(name)) { ++ throw new ClassNotFoundException(name); ++ } ++ } ++ ++ public static boolean isValidNameSpace(@NotNull String name) { ++ for (String string : QUICK_INVALID_NAMESPACES) { ++ if (name.startsWith(string)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/util/StackWalkerUtil.java b/src/main/java/io/papermc/paper/util/StackWalkerUtil.java +index f7114d5b8f2f93f62883e24da29afaf9f74ee1a6..00e78a495575abb9496b1849822605b613afe3b4 100644 +--- a/src/main/java/io/papermc/paper/util/StackWalkerUtil.java ++++ b/src/main/java/io/papermc/paper/util/StackWalkerUtil.java +@@ -1,9 +1,11 @@ + package io.papermc.paper.util; + ++import io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader; + import org.bukkit.plugin.java.JavaPlugin; + import org.bukkit.plugin.java.PluginClassLoader; + import org.jetbrains.annotations.Nullable; + ++import java.util.Objects; + import java.util.Optional; + + public class StackWalkerUtil { +@@ -12,11 +14,20 @@ public class StackWalkerUtil { + public static JavaPlugin getFirstPluginCaller() { + Optional foundFrame = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) + .walk(stream -> stream +- .filter(frame -> frame.getDeclaringClass().getClassLoader() instanceof PluginClassLoader) + .map((frame) -> { +- PluginClassLoader classLoader = (PluginClassLoader) frame.getDeclaringClass().getClassLoader(); +- return classLoader.getPlugin(); ++ ClassLoader classLoader = frame.getDeclaringClass().getClassLoader(); ++ JavaPlugin plugin; ++ if (classLoader instanceof PaperPluginClassLoader pluginClassLoader) { ++ plugin = pluginClassLoader.getLoadedJavaPlugin(); ++ } else if (classLoader instanceof PluginClassLoader spigotClassloader) { ++ plugin = spigotClassloader.getPlugin(); ++ } else { ++ plugin = null; ++ } ++ ++ return plugin; + }) ++ .filter(Objects::nonNull) + .findFirst()); + + return foundFrame.orElse(null); +diff --git a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java +index 5b8ecf5b0165ed2cd4397cdee958e97c2e8f18d5..ad802eb211f05f646159d7fc53f8a9427b46cb89 100644 +--- a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java ++++ b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java +@@ -310,7 +310,13 @@ public class BuiltInRegistries { + } + + public static void bootStrap() { ++ // Paper start ++ bootStrap(() -> {}); ++ } ++ public static void bootStrap(Runnable runnable) { ++ // Paper end + createContents(); ++ runnable.run(); // Paper + freeze(); + validate(REGISTRY); + } +diff --git a/src/main/java/net/minecraft/server/Bootstrap.java b/src/main/java/net/minecraft/server/Bootstrap.java +index b5aa358638b9d0638dfe47f7ebac04cca1dd80b9..e43096e69a00f9ea96badd7c966443cfcf3e7b95 100644 +--- a/src/main/java/net/minecraft/server/Bootstrap.java ++++ b/src/main/java/net/minecraft/server/Bootstrap.java +@@ -69,7 +69,11 @@ public class Bootstrap { + EntitySelectorOptions.bootStrap(); + DispenseItemBehavior.bootStrap(); + CauldronInteraction.bootStrap(); +- BuiltInRegistries.bootStrap(); ++ // Paper start ++ BuiltInRegistries.bootStrap(() -> { ++ io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enterBootstrappers(); // Paper - Entrypoint for bootstrapping ++ }); ++ // Paper end + Bootstrap.wrapStreams(); + } + // CraftBukkit start - easier than fixing the decompile +diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java +index b7399e29094c66c88a6f4c0e996a906bcaa3b4ca..abf4c54eec6881d6e05893983f83f9eb4b249634 100644 +--- a/src/main/java/net/minecraft/server/Main.java ++++ b/src/main/java/net/minecraft/server/Main.java +@@ -110,6 +110,17 @@ public class Main { + JvmProfiler.INSTANCE.start(Environment.SERVER); + } + ++ // Paper start ++ ++ // We have to load the bukkit configuration inorder to get the update folder location. ++ io.papermc.paper.plugin.PluginInitializerManager pluginSystem = io.papermc.paper.plugin.PluginInitializerManager.init(optionset); ++ // Register the default plugin directory ++ io.papermc.paper.plugin.util.EntrypointUtil.registerProvidersFromSource(io.papermc.paper.plugin.provider.source.DirectoryProviderSource.INSTANCE, pluginSystem.pluginDirectoryPath()); ++ @SuppressWarnings("unchecked") ++ java.util.List files = (java.util.List) optionset.valuesOf("add-plugin"); ++ // Register plugins from the flag ++ io.papermc.paper.plugin.util.EntrypointUtil.registerProvidersFromSource(io.papermc.paper.plugin.provider.source.PluginFlagProviderSource.INSTANCE, files); ++ // Paper end + Bootstrap.bootStrap(); + Bootstrap.validate(); + Util.startTimerHackThread(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 26ca07b5e302cc4cc02e06f5d07f6d9eb541275e..17a6290969a63be85fa780e2cad4ce63790379b1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -268,7 +268,8 @@ public final class CraftServer implements Server { + private final CraftCommandMap commandMap = new CraftCommandMap(this); + private final SimpleHelpMap helpMap = new SimpleHelpMap(this); + private final StandardMessenger messenger = new StandardMessenger(); +- private final SimplePluginManager pluginManager = new SimplePluginManager(this, this.commandMap); ++ private final SimplePluginManager pluginManager = new SimplePluginManager(this, commandMap); ++ public final io.papermc.paper.plugin.manager.PaperPluginManagerImpl paperPluginManager = new io.papermc.paper.plugin.manager.PaperPluginManagerImpl(this, this.commandMap, pluginManager); {this.pluginManager.paperPluginManager = this.paperPluginManager;} // Paper + private final StructureManager structureManager; + protected final DedicatedServer console; + protected final DedicatedPlayerList playerList; +@@ -416,24 +417,7 @@ public final class CraftServer implements Server { + } + + public void loadPlugins() { +- this.pluginManager.registerInterface(JavaPluginLoader.class); +- +- File pluginFolder = (File) console.options.valueOf("plugins"); +- +- if (pluginFolder.exists()) { +- Plugin[] plugins = this.pluginManager.loadPlugins(pluginFolder); +- for (Plugin plugin : plugins) { +- try { +- String message = String.format("Loading %s", plugin.getDescription().getFullName()); +- plugin.getLogger().info(message); +- plugin.onLoad(); +- } catch (Throwable ex) { +- Logger.getLogger(CraftServer.class.getName()).log(Level.SEVERE, ex.getMessage() + " initializing " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex); +- } +- } +- } else { +- pluginFolder.mkdir(); +- } ++ io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.INSTANCE.enter(io.papermc.paper.plugin.entrypoint.Entrypoint.PLUGIN); // Paper - replace implementation + } + + public void enablePlugins(PluginLoadOrder type) { +@@ -522,15 +506,17 @@ public final class CraftServer implements Server { + private void enablePlugin(Plugin plugin) { + try { + List perms = plugin.getDescription().getPermissions(); +- ++ List permsToLoad = new ArrayList<>(); // Paper + for (Permission perm : perms) { +- try { +- this.pluginManager.addPermission(perm, false); +- } catch (IllegalArgumentException ex) { +- this.getLogger().log(Level.WARNING, "Plugin " + plugin.getDescription().getFullName() + " tried to register permission '" + perm.getName() + "' but it's already registered", ex); ++ // Paper start ++ if (this.paperPluginManager.getPermission(perm.getName()) == null) { ++ permsToLoad.add(perm); ++ } else { ++ this.getLogger().log(Level.WARNING, "Plugin " + plugin.getDescription().getFullName() + " tried to register permission '" + perm.getName() + "' but it's already registered"); ++ // Paper end + } + } +- this.pluginManager.dirtyPermissibles(); ++ this.paperPluginManager.addPermissions(permsToLoad); // Paper + + this.pluginManager.enablePlugin(plugin); + } catch (Throwable ex) { +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java +index 909b2c98e7a9117d2f737245e4661792ffafb744..d96399e9bf1a58db5a4a22e58abb99e7660e0694 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java +@@ -42,6 +42,12 @@ public class MinecraftInternalPlugin extends PluginBase { + public PluginDescriptionFile getDescription() { + return pdf; + } ++ // Paper start ++ @Override ++ public io.papermc.paper.plugin.configuration.PluginMeta getPluginMeta() { ++ return pdf; ++ } ++ // Paper end + + @Override + public FileConfiguration getConfig() { +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +index 750f4b3930278c291f10015c7a8a8df57d04a286..3d2303dbd06a12968302cb100e36be9de28700f0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +@@ -436,6 +436,12 @@ public final class CraftMagicNumbers implements UnsafeValues { + net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); + return nmsItemStack.getItem().getDescriptionId(nmsItemStack); + } ++ // Paper start ++ @Override ++ public boolean isSupportedApiVersion(String apiVersion) { ++ return apiVersion != null && SUPPORTED_API.contains(apiVersion); ++ } ++ // Paper end + + /** + * This helper class represents the different NBT Tags. +diff --git a/src/main/resources/META-INF/services/io.papermc.paper.plugin.entrypoint.classloader.ClassloaderBytecodeModifier b/src/main/resources/META-INF/services/io.papermc.paper.plugin.entrypoint.classloader.ClassloaderBytecodeModifier +new file mode 100644 +index 0000000000000000000000000000000000000000..20dbe2775951bfcdb85c5d679ac86c77a93e0847 +--- /dev/null ++++ b/src/main/resources/META-INF/services/io.papermc.paper.plugin.entrypoint.classloader.ClassloaderBytecodeModifier +@@ -0,0 +1 @@ ++io.papermc.paper.plugin.entrypoint.classloader.PaperClassloaderBytecodeModifier +diff --git a/src/main/resources/META-INF/services/io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage b/src/main/resources/META-INF/services/io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage +new file mode 100644 +index 0000000000000000000000000000000000000000..a22647244037cd92262b3b5a6582f0a11172fdc8 +--- /dev/null ++++ b/src/main/resources/META-INF/services/io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage +@@ -0,0 +1 @@ ++io.papermc.paper.plugin.entrypoint.classloader.group.PaperPluginClassLoaderStorage +diff --git a/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java b/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java +new file mode 100644 +index 0000000000000000000000000000000000000000..1d14f530ef888102e47eeeaf0d1a6076e51871c4 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/plugin/PaperTestPlugin.java +@@ -0,0 +1,146 @@ ++package io.papermc.paper.plugin; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import org.bukkit.Server; ++import org.bukkit.command.Command; ++import org.bukkit.command.CommandSender; ++import org.bukkit.configuration.file.FileConfiguration; ++import org.bukkit.generator.BiomeProvider; ++import org.bukkit.generator.ChunkGenerator; ++import org.bukkit.plugin.PluginBase; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.PluginLoader; ++import org.bukkit.plugin.PluginLogger; ++ ++import java.io.File; ++import java.io.InputStream; ++import java.util.List; ++ ++public class PaperTestPlugin extends PluginBase { ++ private final String pluginName; ++ private boolean enabled = true; ++ private final PluginMeta configuration; ++ ++ public PaperTestPlugin(String pluginName) { ++ this.pluginName = pluginName; ++ this.configuration = new TestPluginMeta(pluginName); ++ } ++ ++ public PaperTestPlugin(PluginMeta configuration) { ++ this.configuration = configuration; ++ this.pluginName = configuration.getName(); ++ } ++ ++ @Override ++ public File getDataFolder() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginDescriptionFile getDescription() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginMeta getPluginMeta() { ++ return this.configuration; ++ } ++ ++ @Override ++ public FileConfiguration getConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public InputStream getResource(String filename) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveDefaultConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void saveResource(String resourcePath, boolean replace) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void reloadConfig() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginLogger getLogger() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public PluginLoader getPluginLoader() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public Server getServer() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean isEnabled() { ++ return enabled; ++ } ++ ++ public void setEnabled(boolean enabled) { ++ this.enabled = enabled; ++ } ++ ++ @Override ++ public void onDisable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void onLoad() { ++ } ++ ++ @Override ++ public void onEnable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean isNaggable() { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public void setNaggable(boolean canNag) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public BiomeProvider getDefaultBiomeProvider(String worldName, String id) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++ ++ @Override ++ public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { ++ throw new UnsupportedOperationException("Not supported."); ++ } ++} +diff --git a/src/test/java/io/papermc/paper/plugin/PluginDependencyLoadingTest.java b/src/test/java/io/papermc/paper/plugin/PluginDependencyLoadingTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7665967dc1849dde750c6d24298e76c2c74f8443 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/plugin/PluginDependencyLoadingTest.java +@@ -0,0 +1,159 @@ ++package io.papermc.paper.plugin; ++ ++import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; ++import io.papermc.paper.plugin.entrypoint.strategy.ModernPluginLoadingStrategy; ++import io.papermc.paper.plugin.entrypoint.strategy.ProviderConfiguration; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import org.junit.Assert; ++import org.junit.Before; ++import org.junit.Test; ++ ++import java.util.ArrayList; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.concurrent.atomic.AtomicInteger; ++ ++public class PluginDependencyLoadingTest { ++ ++ private static List> REGISTERED_PROVIDERS = new ArrayList<>(); ++ private static Map LOAD_ORDER = new HashMap<>(); ++ ++ static { ++ setup(); ++ } ++ ++ private static TestJavaPluginProvider setup(String identifier, String[] hard, String[] soft, String[] before) { ++ TestPluginMeta configuration = new TestPluginMeta(identifier); ++ configuration.setHardDependencies(List.of(hard)); ++ configuration.setSoftDependencies(List.of(soft)); ++ configuration.setLoadBefore(List.of(before)); ++ ++ TestJavaPluginProvider provider = new TestJavaPluginProvider(configuration); ++ REGISTERED_PROVIDERS.add(provider); ++ return provider; ++ } ++ ++ /** ++ * Obfuscated plugin names, this uses a real dependency tree... ++ */ ++ private static void setup() { ++ setup("RedAir", new String[]{}, new String[]{"NightShovel", "EmeraldFire"}, new String[]{"GreenShovel", "IronSpork", "BrightBlueShovel", "WireDoor"}); ++ setup("BigGrass", new String[]{}, new String[]{"IronEarth", "RedAir"}, new String[]{"BlueFire"}); ++ setup("BlueFire", new String[]{}, new String[]{}, new String[]{}); ++ setup("BigPaper", new String[]{}, new String[]{"BlueFire"}, new String[]{}); ++ setup("EmeraldSpork", new String[]{}, new String[]{}, new String[]{"GoldPaper", "YellowSnow"}); ++ setup("GreenShovel", new String[]{}, new String[]{}, new String[]{}); ++ setup("BrightBlueGrass", new String[]{"BigPaper"}, new String[]{"DarkSpork"}, new String[]{}); ++ setup("GoldPaper", new String[]{}, new String[]{"BlueFire"}, new String[]{}); ++ setup("GreenGlass", new String[]{}, new String[]{}, new String[]{}); ++ setup("GoldNeptune", new String[]{}, new String[]{"GreenShovel", "GoldNeptuneVersioning"}, new String[]{}); ++ setup("RedPaper", new String[]{}, new String[]{"GoldPaper", "GoldFire", "EmeraldGrass", "BlueFire", "CopperSpork", "YellowDoor", "OrangeClam", "BlueSponge", "GoldNeptune", "BrightBlueGrass", "DarkSpoon", "BigShovel", "GreenGlass", "IronGlass"}, new String[]{"IronPaper", "YellowFire"}); ++ setup("YellowGrass", new String[]{}, new String[]{"RedAir"}, new String[]{}); ++ setup("WireFire", new String[]{}, new String[]{"RedPaper", "WireGrass", "YellowSpork", "NightAir"}, new String[]{}); ++ setup("OrangeNeptune", new String[]{}, new String[]{}, new String[]{}); ++ setup("BigSpoon", new String[]{"YellowGrass", "GreenShovel"}, new String[]{"RedAir", "GoldNeptune", "BrightBlueGrass", "LightDoor", "LightSpork", "LightEarth", "NightDoor", "OrangeSpoon", "GoldSponge", "GoldDoor", "DarkPaper", "RedPaper", "GreenGlass", "IronGlass", "NightGlass", "BigGrass", "BlueFire", "YellowSpoon", "DiamondGrass", "DiamondShovel", "DarkSnow", "EmeraldGlass", "EmeraldSpoon", "LightFire", "WireGrass", "RedEarth", "WireFire"}, new String[]{}); ++ setup("CopperSnow", new String[]{}, new String[]{"RedSnow", "OrangeFire", "WireAir", "GreenGlass", "NightSpork", "EmeraldPaper"}, new String[]{"BlueGrass"}); ++ setup("BrightBluePaper", new String[]{}, new String[]{"GoldEarth", "BrightBlueSpoon", "CopperGlass", "LightSporkChat", "DarkAir", "LightEarth", "DiamondDoor", "YellowShovel", "BlueAir", "DarkShovel", "GoldPaper", "BlueFire", "GreenGlass", "YellowSpork", "BigGrass", "OrangePaper", "DarkPaper"}, new String[]{"WireShovel"}); ++ setup("LightSponge", new String[]{}, new String[]{}, new String[]{}); ++ setup("OrangeShovel", new String[]{}, new String[]{}, new String[]{}); ++ setup("GoldGrass", new String[]{}, new String[]{"GreenGlass", "BlueFire"}, new String[]{}); ++ setup("IronSponge", new String[]{}, new String[]{"DiamondEarth"}, new String[]{}); ++ setup("EmeraldSnow", new String[]{}, new String[]{}, new String[]{}); ++ setup("BlueSpoon", new String[]{"BigGrass"}, new String[]{"GreenGlass", "GoldPaper", "GreenShovel", "YellowClam"}, new String[]{}); ++ setup("BigSpork", new String[]{}, new String[]{"BigPaper"}, new String[]{}); ++ setup("BluePaper", new String[]{}, new String[]{"BigClam", "RedSpoon", "GreenFire", "WireSnow", "OrangeSnow", "BlueFire", "BrightBlueGrass", "YellowSpork", "GreenGlass"}, new String[]{}); ++ setup("OrangeSpork", new String[]{}, new String[]{}, new String[]{}); ++ setup("DiamondNeptune", new String[]{}, new String[]{"GreenGlass", "GreenShovel", "YellowNeptune"}, new String[]{}); ++ setup("BigFire", new String[]{}, new String[]{"BlueFire", "BrightBlueDoor", "GreenGlass"}, new String[]{}); ++ setup("NightNeptune", new String[]{}, new String[]{"BlueFire", "DarkGlass", "GoldPaper", "YellowNeptune", "BlueShovel"}, new String[]{}); ++ setup("YellowEarth", new String[]{"RedAir"}, new String[]{}, new String[]{}); ++ setup("DiamondClam", new String[]{}, new String[]{}, new String[]{}); ++ setup("CopperAir", new String[]{}, new String[]{"BigPaper"}, new String[]{}); ++ setup("NightSpoon", new String[]{"OrangeNeptune"}, new String[]{"BlueFire", "GreenGlass", "RedSpork", "GoldPaper", "BigShovel", "YellowSponge", "EmeraldSpork"}, new String[]{}); ++ setup("GreenClam", new String[]{}, new String[]{"GreenShovel", "BrightBlueEarth", "BigSpoon", "RedPaper", "BlueFire", "GreenGlass", "WireFire", "GreenSnow"}, new String[]{}); ++ setup("YellowPaper", new String[]{}, new String[]{}, new String[]{}); ++ setup("WireGlass", new String[]{"YellowGrass"}, new String[]{"YellowGlass", "BigSpoon", "CopperSnow", "GreenGlass", "BlueEarth"}, new String[]{}); ++ setup("BlueSpork", new String[]{}, new String[]{"BrightBlueGrass"}, new String[]{}); ++ setup("CopperShovel", new String[]{}, new String[]{"GreenGlass"}, new String[]{}); ++ setup("RedClam", new String[]{}, new String[]{}, new String[]{}); ++ setup("EmeraldClam", new String[]{}, new String[]{"BlueFire"}, new String[]{}); ++ setup("DarkClam", new String[]{}, new String[]{"GoldAir", "LightGlass"}, new String[]{}); ++ setup("WireSpoon", new String[]{}, new String[]{"GoldPaper", "LightSnow"}, new String[]{}); ++ setup("CopperNeptune", new String[]{}, new String[]{"GreenGlass", "BigGrass"}, new String[]{}); ++ setup("RedNeptune", new String[]{}, new String[]{}, new String[]{}); ++ setup("GreenAir", new String[]{}, new String[]{}, new String[]{}); ++ setup("RedFire", new String[]{"BrightBlueGrass", "BigPaper"}, new String[]{"BlueFire", "GreenGlass", "BigGrass"}, new String[]{}); ++ } ++ ++ @Before ++ public void loadProviders() { ++ AtomicInteger currentLoad = new AtomicInteger(); ++ ModernPluginLoadingStrategy modernPluginLoadingStrategy = new ModernPluginLoadingStrategy<>(new ProviderConfiguration<>() { ++ @Override ++ public void applyContext(PluginProvider provider, DependencyContext dependencyContext) { ++ } ++ ++ @Override ++ public boolean load(PluginProvider provider, PaperTestPlugin provided) { ++ LOAD_ORDER.put(provider.getMeta().getName(), currentLoad.getAndIncrement()); ++ return false; ++ } ++ ++ @Override ++ public List requiredDependencies(PluginProvider provider) { ++ return provider.getMeta().getPluginDependencies(); ++ } ++ ++ @Override ++ public List optionalDependencies(PluginProvider provider) { ++ return provider.getMeta().getPluginSoftDependencies(); ++ } ++ ++ @Override ++ public List loadBeforeDependencies(PluginProvider provider) { ++ return provider.getMeta().getLoadBeforePlugins(); ++ } ++ }); ++ ++ modernPluginLoadingStrategy.loadProviders(REGISTERED_PROVIDERS); ++ } ++ ++ @Test ++ public void testDependencies() { ++ for (PluginProvider provider : REGISTERED_PROVIDERS) { ++ TestPluginMeta pluginMeta = (TestPluginMeta) provider.getMeta(); ++ String identifier = pluginMeta.getName(); ++ Assert.assertTrue("Provider wasn't loaded! (%s)".formatted(identifier), LOAD_ORDER.containsKey(identifier)); ++ ++ int index = LOAD_ORDER.get(identifier); ++ ++ // Hard dependencies should be loaded BEFORE ++ for (String hardDependency : pluginMeta.getPluginDependencies()) { ++ Assert.assertTrue("Plugin (%s) is missing hard dependency (%s)".formatted(identifier, hardDependency), LOAD_ORDER.containsKey(hardDependency)); ++ ++ int dependencyIndex = LOAD_ORDER.get(hardDependency); ++ Assert.assertTrue("Plugin (%s) was not loaded BEFORE soft dependency. (%s)".formatted(identifier, hardDependency), index > dependencyIndex); ++ } ++ ++ for (String softDependency : pluginMeta.getPluginSoftDependencies()) { ++ if (!LOAD_ORDER.containsKey(softDependency)) { ++ continue; ++ } ++ ++ int dependencyIndex = LOAD_ORDER.get(softDependency); ++ ++ Assert.assertTrue("Plugin (%s) was not loaded BEFORE soft dependency. (%s)".formatted(identifier, softDependency), index > dependencyIndex); ++ } ++ ++ for (String loadBefore : pluginMeta.getLoadBeforePlugins()) { ++ if (!LOAD_ORDER.containsKey(loadBefore)) { ++ continue; ++ } ++ ++ int dependencyIndex = LOAD_ORDER.get(loadBefore); ++ Assert.assertTrue("Plugin (%s) was NOT loaded BEFORE loadbefore dependency. (%s)".formatted(identifier, loadBefore), index < dependencyIndex); ++ } ++ } ++ } ++} +diff --git a/src/test/java/io/papermc/paper/plugin/PluginLoadingTest.java b/src/test/java/io/papermc/paper/plugin/PluginLoadingTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 +diff --git a/src/test/java/io/papermc/paper/plugin/PluginManagerTest.java b/src/test/java/io/papermc/paper/plugin/PluginManagerTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..726eba26470e62b0e94a91418512e242464800ae +--- /dev/null ++++ b/src/test/java/io/papermc/paper/plugin/PluginManagerTest.java +@@ -0,0 +1,75 @@ ++package io.papermc.paper.plugin; ++ ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.permissions.Permission; ++import org.bukkit.plugin.PluginManager; ++import org.bukkit.support.AbstractTestingBase; ++import org.junit.After; ++import org.junit.Test; ++ ++import static org.hamcrest.MatcherAssert.assertThat; ++import static org.hamcrest.Matchers.*; ++ ++public class PluginManagerTest extends AbstractTestingBase { ++ ++ private static final PluginManager pm = Bukkit.getPluginManager(); ++ ++ @Test ++ public void testSyncSameThread() { ++ final Event event = new TestEvent(false); ++ pm.callEvent(event); ++ } ++ ++ @Test ++ public void testRemovePermissionByNameLower() { ++ this.testRemovePermissionByName("lower"); ++ } ++ ++ @Test ++ public void testRemovePermissionByNameUpper() { ++ this.testRemovePermissionByName("UPPER"); ++ } ++ ++ @Test ++ public void testRemovePermissionByNameCamel() { ++ this.testRemovePermissionByName("CaMeL"); ++ } ++ ++ @Test ++ public void testRemovePermissionByPermissionLower() { ++ this.testRemovePermissionByPermission("lower"); ++ } ++ ++ @Test ++ public void testRemovePermissionByPermissionUpper() { ++ this.testRemovePermissionByPermission("UPPER"); ++ } ++ ++ @Test ++ public void testRemovePermissionByPermissionCamel() { ++ this.testRemovePermissionByPermission("CaMeL"); ++ } ++ ++ private void testRemovePermissionByName(final String name) { ++ final Permission perm = new Permission(name); ++ pm.addPermission(perm); ++ assertThat("Permission \"" + name + "\" was not added", pm.getPermission(name), is(perm)); ++ pm.removePermission(name); ++ assertThat("Permission \"" + name + "\" was not removed", pm.getPermission(name), is(nullValue())); ++ } ++ ++ private void testRemovePermissionByPermission(final String name) { ++ final Permission perm = new Permission(name); ++ pm.addPermission(perm); ++ assertThat("Permission \"" + name + "\" was not added", pm.getPermission(name), is(perm)); ++ pm.removePermission(perm); ++ assertThat("Permission \"" + name + "\" was not removed", pm.getPermission(name), is(nullValue())); ++ } ++ ++ @After ++ public void tearDown() { ++ pm.clearPlugins(); ++ assertThat(pm.getPermissions(), is(empty())); ++ } ++} +diff --git a/src/test/java/io/papermc/paper/plugin/SyntheticEventTest.java b/src/test/java/io/papermc/paper/plugin/SyntheticEventTest.java +new file mode 100644 +index 0000000000000000000000000000000000000000..51c08740edffd152c8e2b6d3676ff7f1ce6090c6 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/plugin/SyntheticEventTest.java +@@ -0,0 +1,42 @@ ++package io.papermc.paper.plugin; ++ ++import io.papermc.paper.plugin.manager.PaperPluginManagerImpl; ++import org.bukkit.Bukkit; ++import org.bukkit.event.Event; ++import org.bukkit.event.EventHandler; ++import org.bukkit.event.Listener; ++import org.junit.Assert; ++import org.junit.Test; ++ ++public class SyntheticEventTest { ++ ++ @Test ++ public void test() { ++ PaperTestPlugin paperTestPlugin = new PaperTestPlugin("synthetictest"); ++ PaperPluginManagerImpl paperPluginManager = new PaperPluginManagerImpl(Bukkit.getServer(), null, null); ++ ++ TestEvent event = new TestEvent(false); ++ Impl impl = new Impl(); ++ ++ paperPluginManager.registerEvents(impl, paperTestPlugin); ++ paperPluginManager.callEvent(event); ++ ++ Assert.assertEquals(1, impl.callCount); ++ } ++ ++ public abstract static class Base implements Listener { ++ int callCount = 0; ++ ++ public void accept(E evt) { ++ callCount++; ++ } ++ } ++ ++ public static class Impl extends Base { ++ @Override ++ @EventHandler ++ public void accept(TestEvent evt) { ++ super.accept(evt); ++ } ++ } ++} +diff --git a/src/test/java/io/papermc/paper/plugin/TestEvent.java b/src/test/java/io/papermc/paper/plugin/TestEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..04903794a8ee4dd73162ae240862ff6dc4cb4e24 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/plugin/TestEvent.java +@@ -0,0 +1,22 @@ ++package io.papermc.paper.plugin; ++ ++ ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++ ++public class TestEvent extends Event { ++ private static final HandlerList handlers = new HandlerList(); ++ ++ public TestEvent(boolean async) { ++ super(async); ++ } ++ ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/test/java/io/papermc/paper/plugin/TestJavaPluginProvider.java b/src/test/java/io/papermc/paper/plugin/TestJavaPluginProvider.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8837b131dedc41e7d0d58ccf3d1e251168c5b9b8 +--- /dev/null ++++ b/src/test/java/io/papermc/paper/plugin/TestJavaPluginProvider.java +@@ -0,0 +1,42 @@ ++package io.papermc.paper.plugin; ++ ++import io.papermc.paper.plugin.provider.PluginProvider; ++import org.jetbrains.annotations.NotNull; ++ ++import java.nio.file.Path; ++import java.util.jar.JarFile; ++import java.util.logging.Logger; ++ ++public class TestJavaPluginProvider implements PluginProvider { ++ ++ private final TestPluginMeta testPluginConfiguration; ++ ++ public TestJavaPluginProvider(TestPluginMeta testPluginConfiguration) { ++ this.testPluginConfiguration = testPluginConfiguration; ++ } ++ ++ @Override ++ public @NotNull Path getSource() { ++ return Path.of("dummy"); ++ } ++ ++ @Override ++ public JarFile file() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public PaperTestPlugin createInstance() { ++ return new PaperTestPlugin(this.testPluginConfiguration); ++ } ++ ++ @Override ++ public TestPluginMeta getMeta() { ++ return this.testPluginConfiguration; ++ } ++ ++ @Override ++ public Logger getLogger() { ++ return Logger.getLogger("TestPlugin"); ++ } ++} +diff --git a/src/test/java/io/papermc/paper/plugin/TestPluginMeta.java b/src/test/java/io/papermc/paper/plugin/TestPluginMeta.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ba271c35eb2804f94cfc893bf94affb9ae13d3ba +--- /dev/null ++++ b/src/test/java/io/papermc/paper/plugin/TestPluginMeta.java +@@ -0,0 +1,114 @@ ++package io.papermc.paper.plugin; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import org.bukkit.permissions.Permission; ++import org.bukkit.permissions.PermissionDefault; ++import org.bukkit.plugin.PluginLoadOrder; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++ ++import java.util.List; ++ ++public class TestPluginMeta implements PluginMeta { ++ ++ private final String identifier; ++ private List hardDependencies = List.of(); ++ private List softDependencies = List.of(); ++ private List loadBefore = List.of(); ++ ++ public TestPluginMeta(String identifier) { ++ this.identifier = identifier; ++ } ++ ++ @Override ++ public @NotNull String getName() { ++ return this.identifier; ++ } ++ ++ @Override ++ public @NotNull String getMainClass() { ++ return "null"; ++ } ++ ++ @Override ++ public @NotNull PluginLoadOrder getLoadOrder() { ++ return PluginLoadOrder.POSTWORLD; ++ } ++ ++ @Override ++ public @NotNull String getVersion() { ++ return "1.0"; ++ } ++ ++ @Override ++ public @Nullable String getLoggerPrefix() { ++ return this.identifier; ++ } ++ ++ public void setHardDependencies(List hardDependencies) { ++ this.hardDependencies = hardDependencies; ++ } ++ ++ @Override ++ public @NotNull List getPluginDependencies() { ++ return this.hardDependencies; ++ } ++ ++ public void setSoftDependencies(List softDependencies) { ++ this.softDependencies = softDependencies; ++ } ++ ++ @Override ++ public @NotNull List getPluginSoftDependencies() { ++ return this.softDependencies; ++ } ++ ++ public void setLoadBefore(List loadBefore) { ++ this.loadBefore = loadBefore; ++ } ++ ++ @Override ++ public @NotNull List getLoadBeforePlugins() { ++ return this.loadBefore; ++ } ++ ++ @Override ++ public @NotNull List getProvidedPlugins() { ++ return List.of(); ++ } ++ ++ @Override ++ public @NotNull List getAuthors() { ++ return List.of(); ++ } ++ ++ @Override ++ public @NotNull List getContributors() { ++ return List.of(); ++ } ++ ++ @Override ++ public @Nullable String getDescription() { ++ return "null"; ++ } ++ ++ @Override ++ public @Nullable String getWebsite() { ++ return "null"; ++ } ++ ++ @Override ++ public @NotNull List getPermissions() { ++ return List.of(); ++ } ++ ++ @Override ++ public @NotNull PermissionDefault getPermissionDefault() { ++ return PermissionDefault.TRUE; ++ } ++ ++ @Override ++ public @NotNull String getAPIVersion() { ++ return "null"; ++ } ++} +diff --git a/src/test/java/io/papermc/paper/testing/DummyServer.java b/src/test/java/io/papermc/paper/testing/DummyServer.java +index 286790061c9d81c872108ef63e1a1aba2fbec809..53ac8df47a2c9a84c751955fd4fbb352a3ded16b 100644 +--- a/src/test/java/io/papermc/paper/testing/DummyServer.java ++++ b/src/test/java/io/papermc/paper/testing/DummyServer.java +@@ -57,7 +57,7 @@ public final class DummyServer { + return new LazyRegistry(() -> CraftRegistry.createRegistry(invocation.getArgument(0, Class.class), AbstractTestingBase.REGISTRY_CUSTOM)); + }); + +- final PluginManager pluginManager = new SimplePluginManager(dummyServer, new SimpleCommandMap(dummyServer)); ++ final PluginManager pluginManager = new io.papermc.paper.plugin.manager.PaperPluginManagerImpl(dummyServer, new SimpleCommandMap(dummyServer), null); + when(dummyServer.getPluginManager()).thenReturn(pluginManager); + + Bukkit.setServer(dummyServer); diff --git a/patches/server/0013-Timings-v2.patch b/patches/server/0014-Timings-v2.patch similarity index 99% rename from patches/server/0013-Timings-v2.patch rename to patches/server/0014-Timings-v2.patch index 5d8af4d353..2729c186aa 100644 --- a/patches/server/0013-Timings-v2.patch +++ b/patches/server/0014-Timings-v2.patch @@ -1620,10 +1620,10 @@ index cf496b430bf3d7aab0b8e86c11e015583c1411a7..6fdd5c92ab069896e3921faa042cbdb3 }; } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 26ca07b5e302cc4cc02e06f5d07f6d9eb541275e..c684460c91ad41ba9741616c25dae5c3efede704 100644 +index 17a6290969a63be85fa780e2cad4ce63790379b1..83e0038b3c281c176463d33bacbcc1ca283e41dc 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2406,12 +2406,31 @@ public final class CraftServer implements Server { +@@ -2392,12 +2392,31 @@ public final class CraftServer implements Server { private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() { @@ -2021,7 +2021,7 @@ index e52ef47b783785dc214746b678e7b549aea9a274..3d90b3426873a3528af14f7f1ab0adae this.value = value; } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 750f4b3930278c291f10015c7a8a8df57d04a286..702ab12f93e422b1ba9d544084fa7712e776c751 100644 +index 3d2303dbd06a12968302cb100e36be9de28700f0..8324787573510df3e23e6833f06aa1618336b7bb 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -222,6 +222,12 @@ public final class CraftMagicNumbers implements UnsafeValues { @@ -2037,9 +2037,9 @@ index 750f4b3930278c291f10015c7a8a8df57d04a286..702ab12f93e422b1ba9d544084fa7712 public static byte toLegacyData(BlockState data) { return CraftLegacy.toLegacyData(data); -@@ -437,6 +443,13 @@ public final class CraftMagicNumbers implements UnsafeValues { - return nmsItemStack.getItem().getDescriptionId(nmsItemStack); +@@ -443,6 +449,13 @@ public final class CraftMagicNumbers implements UnsafeValues { } + // Paper end + // Paper start + @Override diff --git a/patches/server/0014-Rewrite-dataconverter-system.patch b/patches/server/0015-Rewrite-dataconverter-system.patch similarity index 100% rename from patches/server/0014-Rewrite-dataconverter-system.patch rename to patches/server/0015-Rewrite-dataconverter-system.patch diff --git a/patches/server/0015-Starlight.patch b/patches/server/0016-Starlight.patch similarity index 99% rename from patches/server/0015-Starlight.patch rename to patches/server/0016-Starlight.patch index 17217a833f..4eb2645ff7 100644 --- a/patches/server/0015-Starlight.patch +++ b/patches/server/0016-Starlight.patch @@ -4331,7 +4331,7 @@ index 0000000000000000000000000000000000000000..dd995e25ae620ae36cd5eecb2fe10ad0 + +} diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java -index b3a58bf4b654e336826dc04da9e2f80ff8b9a9a7..c9a2ac696f7cefc8b0715f53db3fc541f26b62f6 100644 +index 156334e3876d966fedc91d18da29f562395ab182..268b243f76b632fc8eea08bba4657a5100b5dfc7 100644 --- a/src/main/java/io/papermc/paper/command/PaperCommand.java +++ b/src/main/java/io/papermc/paper/command/PaperCommand.java @@ -1,6 +1,7 @@ @@ -4342,10 +4342,10 @@ index b3a58bf4b654e336826dc04da9e2f80ff8b9a9a7..c9a2ac696f7cefc8b0715f53db3fc541 import io.papermc.paper.command.subcommands.HeapDumpCommand; import io.papermc.paper.command.subcommands.ReloadCommand; import io.papermc.paper.command.subcommands.VersionCommand; -@@ -40,6 +41,7 @@ public final class PaperCommand extends Command { - commands.put(Set.of("entity"), new EntityCommand()); +@@ -42,6 +43,7 @@ public final class PaperCommand extends Command { commands.put(Set.of("reload"), new ReloadCommand()); commands.put(Set.of("version"), new VersionCommand()); + commands.put(Set.of("dumpplugins"), new DumpPluginsCommand()); + commands.put(Set.of("fixlight"), new FixLightCommand()); return commands.entrySet().stream() diff --git a/patches/server/0016-Add-TickThread.patch b/patches/server/0017-Add-TickThread.patch similarity index 100% rename from patches/server/0016-Add-TickThread.patch rename to patches/server/0017-Add-TickThread.patch diff --git a/patches/server/0017-Rewrite-chunk-system.patch b/patches/server/0018-Rewrite-chunk-system.patch similarity index 99% rename from patches/server/0017-Rewrite-chunk-system.patch rename to patches/server/0018-Rewrite-chunk-system.patch index 25a16b2889..4711d56525 100644 --- a/patches/server/0017-Rewrite-chunk-system.patch +++ b/patches/server/0018-Rewrite-chunk-system.patch @@ -11555,7 +11555,7 @@ index 0000000000000000000000000000000000000000..b4c56bf12dc8dd17452210ece4fd6741 + protected abstract void raisePriorityScheduled(final PrioritisedExecutor.Priority priority); +} diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java -index c9a2ac696f7cefc8b0715f53db3fc541f26b62f6..1e9105cf5ab2ff0ee847fafd00b41e1bd47f1d9e 100644 +index 268b243f76b632fc8eea08bba4657a5100b5dfc7..e202af893c7ec22bfc0b8dbeb8e1551db685d1d3 100644 --- a/src/main/java/io/papermc/paper/command/PaperCommand.java +++ b/src/main/java/io/papermc/paper/command/PaperCommand.java @@ -1,5 +1,6 @@ @@ -11565,9 +11565,9 @@ index c9a2ac696f7cefc8b0715f53db3fc541f26b62f6..1e9105cf5ab2ff0ee847fafd00b41e1b import io.papermc.paper.command.subcommands.EntityCommand; import io.papermc.paper.command.subcommands.FixLightCommand; import io.papermc.paper.command.subcommands.HeapDumpCommand; -@@ -42,6 +43,7 @@ public final class PaperCommand extends Command { - commands.put(Set.of("reload"), new ReloadCommand()); +@@ -44,6 +45,7 @@ public final class PaperCommand extends Command { commands.put(Set.of("version"), new VersionCommand()); + commands.put(Set.of("dumpplugins"), new DumpPluginsCommand()); commands.put(Set.of("fixlight"), new FixLightCommand()); + commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand()); @@ -12718,10 +12718,10 @@ index a5e438a834826161c52ca9db57d234d9ff80a591..b8bc1b9b8e8a33df90a963f9f9769292 @Override diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index b7399e29094c66c88a6f4c0e996a906bcaa3b4ca..e600563a9d2ddbfa37c106481decb13e67f71524 100644 +index abf4c54eec6881d6e05893983f83f9eb4b249634..8d61e388bbdfd6097f914fc5f122fdf7f9b9ffe2 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -259,6 +259,7 @@ public class Main { +@@ -270,6 +270,7 @@ public class Main { convertable_conversionsession.saveDataTag(iregistrycustom_dimension, savedata); */ @@ -17854,10 +17854,10 @@ index 738d3ce38a42ff8cd53eec042ef8bc74f2b8d059..a895c81ea6af0822c8371ae93cfe4b72 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c684460c91ad41ba9741616c25dae5c3efede704..720a078acfe770dba76413a8cfa4ef15616ae292 100644 +index 83e0038b3c281c176463d33bacbcc1ca283e41dc..4b8178514bea3f53e1aeec266caa2ed19eb895b0 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1142,7 +1142,7 @@ public final class CraftServer implements Server { +@@ -1128,7 +1128,7 @@ public final class CraftServer implements Server { this.console.addLevel(internal); this.getServer().prepareLevels(internal.getChunkSource().chunkMap.progressListener, internal); @@ -17866,7 +17866,7 @@ index c684460c91ad41ba9741616c25dae5c3efede704..720a078acfe770dba76413a8cfa4ef15 this.pluginManager.callEvent(new WorldLoadEvent(internal.getWorld())); return internal.getWorld(); -@@ -1186,7 +1186,7 @@ public final class CraftServer implements Server { +@@ -1172,7 +1172,7 @@ public final class CraftServer implements Server { } handle.getChunkSource().close(save); @@ -17875,7 +17875,7 @@ index c684460c91ad41ba9741616c25dae5c3efede704..720a078acfe770dba76413a8cfa4ef15 handle.convertable.close(); } catch (Exception ex) { this.getLogger().log(Level.SEVERE, null, ex); -@@ -2001,7 +2001,7 @@ public final class CraftServer implements Server { +@@ -1987,7 +1987,7 @@ public final class CraftServer implements Server { @Override public boolean isPrimaryThread() { diff --git a/patches/server/0018-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server/0019-Add-command-line-option-to-load-extra-plugin-jars-no.patch similarity index 74% rename from patches/server/0018-Add-command-line-option-to-load-extra-plugin-jars-no.patch rename to patches/server/0019-Add-command-line-option-to-load-extra-plugin-jars-no.patch index 4783e6fd0d..a49cc4a0cb 100644 --- a/patches/server/0018-Add-command-line-option-to-load-extra-plugin-jars-no.patch +++ b/patches/server/0019-Add-command-line-option-to-load-extra-plugin-jars-no.patch @@ -7,30 +7,11 @@ Subject: [PATCH] Add command line option to load extra plugin jars not in the ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 720a078acfe770dba76413a8cfa4ef15616ae292..82b267898f98b7e6c808a2377951106769a4a763 100644 +index 4b8178514bea3f53e1aeec266caa2ed19eb895b0..d061919b93f131cb4d8132951775b044766edaf1 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -418,10 +418,15 @@ public final class CraftServer implements Server { - public void loadPlugins() { - this.pluginManager.registerInterface(JavaPluginLoader.class); - -- File pluginFolder = (File) console.options.valueOf("plugins"); -+ File pluginFolder = this.getPluginsFolder(); // Paper - -- if (pluginFolder.exists()) { -- Plugin[] plugins = this.pluginManager.loadPlugins(pluginFolder); -+ // Paper start -+ if (true || pluginFolder.exists()) { -+ if (!pluginFolder.exists()) { -+ pluginFolder.mkdirs(); -+ } -+ Plugin[] plugins = this.pluginManager.loadPlugins(pluginFolder, this.extraPluginJars()); -+ // Paper end - for (Plugin plugin : plugins) { - try { - String message = String.format("Loading %s", plugin.getDescription().getFullName()); -@@ -436,6 +441,35 @@ public final class CraftServer implements Server { - } +@@ -420,6 +420,35 @@ public final class CraftServer implements Server { + io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.INSTANCE.enter(io.papermc.paper.plugin.entrypoint.Entrypoint.PLUGIN); // Paper - replace implementation } + // Paper start diff --git a/patches/server/0019-Configurable-cactus-bamboo-and-reed-growth-heights.patch b/patches/server/0020-Configurable-cactus-bamboo-and-reed-growth-heights.patch similarity index 100% rename from patches/server/0019-Configurable-cactus-bamboo-and-reed-growth-heights.patch rename to patches/server/0020-Configurable-cactus-bamboo-and-reed-growth-heights.patch diff --git a/patches/server/0020-Configurable-baby-zombie-movement-speed.patch b/patches/server/0021-Configurable-baby-zombie-movement-speed.patch similarity index 100% rename from patches/server/0020-Configurable-baby-zombie-movement-speed.patch rename to patches/server/0021-Configurable-baby-zombie-movement-speed.patch diff --git a/patches/server/0021-Configurable-fishing-time-ranges.patch b/patches/server/0022-Configurable-fishing-time-ranges.patch similarity index 100% rename from patches/server/0021-Configurable-fishing-time-ranges.patch rename to patches/server/0022-Configurable-fishing-time-ranges.patch diff --git a/patches/server/0022-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch b/patches/server/0023-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch similarity index 100% rename from patches/server/0022-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch rename to patches/server/0023-Allow-nerfed-mobs-to-jump-and-take-water-damage.patch diff --git a/patches/server/0023-Add-configurable-despawn-distances-for-living-entiti.patch b/patches/server/0024-Add-configurable-despawn-distances-for-living-entiti.patch similarity index 100% rename from patches/server/0023-Add-configurable-despawn-distances-for-living-entiti.patch rename to patches/server/0024-Add-configurable-despawn-distances-for-living-entiti.patch diff --git a/patches/server/0024-Allow-for-toggling-of-spawn-chunks.patch b/patches/server/0025-Allow-for-toggling-of-spawn-chunks.patch similarity index 100% rename from patches/server/0024-Allow-for-toggling-of-spawn-chunks.patch rename to patches/server/0025-Allow-for-toggling-of-spawn-chunks.patch diff --git a/patches/server/0025-Drop-falling-block-and-tnt-entities-at-the-specified.patch b/patches/server/0026-Drop-falling-block-and-tnt-entities-at-the-specified.patch similarity index 100% rename from patches/server/0025-Drop-falling-block-and-tnt-entities-at-the-specified.patch rename to patches/server/0026-Drop-falling-block-and-tnt-entities-at-the-specified.patch diff --git a/patches/server/0026-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch b/patches/server/0027-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch similarity index 98% rename from patches/server/0026-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch rename to patches/server/0027-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch index e111c858bf..abb5332603 100644 --- a/patches/server/0026-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch +++ b/patches/server/0027-Show-Paper-in-client-crashes-server-lists-and-Mojang.patch @@ -19,7 +19,7 @@ index e9f4ffec4b659f3300daa0138f6e955a8d97786d..e2e66fd4bd34e0ceaab350214a50ddbb public SystemReport fillSystemReport(SystemReport details) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 82b267898f98b7e6c808a2377951106769a4a763..e609a52750fe6ca178ce2933510d000a11438270 100644 +index d061919b93f131cb4d8132951775b044766edaf1..ea16abd65ff909ad4644f7a98fd29d9c3c9f7ac7 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -259,7 +259,7 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; diff --git a/patches/server/0027-Implement-Paper-VersionChecker.patch b/patches/server/0028-Implement-Paper-VersionChecker.patch similarity index 97% rename from patches/server/0027-Implement-Paper-VersionChecker.patch rename to patches/server/0028-Implement-Paper-VersionChecker.patch index b8c3cd87f4..701eb0a55b 100644 --- a/patches/server/0027-Implement-Paper-VersionChecker.patch +++ b/patches/server/0028-Implement-Paper-VersionChecker.patch @@ -140,10 +140,10 @@ index 0000000000000000000000000000000000000000..351159bbdb0c8045f4983f54dee34430 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 702ab12f93e422b1ba9d544084fa7712e776c751..cbb161e3daa0250ae2e12e3cec972708fccaeadc 100644 +index 8324787573510df3e23e6833f06aa1618336b7bb..0ee761fa0d42fd90e82f3284ee756ddd60c6178d 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -448,6 +448,11 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -454,6 +454,11 @@ public final class CraftMagicNumbers implements UnsafeValues { public String getTimingsServerName() { return io.papermc.paper.configuration.GlobalConfiguration.get().timings.serverName; } diff --git a/patches/server/0028-Add-version-history-to-version-command.patch b/patches/server/0029-Add-version-history-to-version-command.patch similarity index 100% rename from patches/server/0028-Add-version-history-to-version-command.patch rename to patches/server/0029-Add-version-history-to-version-command.patch diff --git a/patches/server/0029-Player-affects-spawning-API.patch b/patches/server/0030-Player-affects-spawning-API.patch similarity index 100% rename from patches/server/0029-Player-affects-spawning-API.patch rename to patches/server/0030-Player-affects-spawning-API.patch diff --git a/patches/server/0030-Further-improve-server-tick-loop.patch b/patches/server/0031-Further-improve-server-tick-loop.patch similarity index 98% rename from patches/server/0030-Further-improve-server-tick-loop.patch rename to patches/server/0031-Further-improve-server-tick-loop.patch index 9f1bc03008..70439a74c2 100644 --- a/patches/server/0030-Further-improve-server-tick-loop.patch +++ b/patches/server/0031-Further-improve-server-tick-loop.patch @@ -145,10 +145,10 @@ index e2e66fd4bd34e0ceaab350214a50ddbb1dc76184..ac81428f19e2d445f315000d34173c2d this.startMetricsRecordingTick(); this.profiler.push("tick"); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e609a52750fe6ca178ce2933510d000a11438270..ecc94c04ba83aff8f232467aef2def69065a1c1e 100644 +index ea16abd65ff909ad4644f7a98fd29d9c3c9f7ac7..710b06caa91d09f6e3d55f76162e60f41d0037e2 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2436,6 +2436,17 @@ public final class CraftServer implements Server { +@@ -2417,6 +2417,17 @@ public final class CraftServer implements Server { return CraftMagicNumbers.INSTANCE; } diff --git a/patches/server/0031-Only-refresh-abilities-if-needed.patch b/patches/server/0032-Only-refresh-abilities-if-needed.patch similarity index 100% rename from patches/server/0031-Only-refresh-abilities-if-needed.patch rename to patches/server/0032-Only-refresh-abilities-if-needed.patch diff --git a/patches/server/0032-Entity-Origin-API.patch b/patches/server/0033-Entity-Origin-API.patch similarity index 100% rename from patches/server/0032-Entity-Origin-API.patch rename to patches/server/0033-Entity-Origin-API.patch diff --git a/patches/server/0033-Prevent-tile-entity-and-entity-crashes.patch b/patches/server/0034-Prevent-tile-entity-and-entity-crashes.patch similarity index 100% rename from patches/server/0033-Prevent-tile-entity-and-entity-crashes.patch rename to patches/server/0034-Prevent-tile-entity-and-entity-crashes.patch diff --git a/patches/server/0034-Configurable-top-of-nether-void-damage.patch b/patches/server/0035-Configurable-top-of-nether-void-damage.patch similarity index 100% rename from patches/server/0034-Configurable-top-of-nether-void-damage.patch rename to patches/server/0035-Configurable-top-of-nether-void-damage.patch diff --git a/patches/server/0035-Check-online-mode-before-converting-and-renaming-pla.patch b/patches/server/0036-Check-online-mode-before-converting-and-renaming-pla.patch similarity index 100% rename from patches/server/0035-Check-online-mode-before-converting-and-renaming-pla.patch rename to patches/server/0036-Check-online-mode-before-converting-and-renaming-pla.patch diff --git a/patches/server/0036-Always-tick-falling-blocks.patch b/patches/server/0037-Always-tick-falling-blocks.patch similarity index 100% rename from patches/server/0036-Always-tick-falling-blocks.patch rename to patches/server/0037-Always-tick-falling-blocks.patch diff --git a/patches/server/0037-Configurable-end-credits.patch b/patches/server/0038-Configurable-end-credits.patch similarity index 100% rename from patches/server/0037-Configurable-end-credits.patch rename to patches/server/0038-Configurable-end-credits.patch diff --git a/patches/server/0038-Fix-lag-from-explosions-processing-dead-entities.patch b/patches/server/0039-Fix-lag-from-explosions-processing-dead-entities.patch similarity index 100% rename from patches/server/0038-Fix-lag-from-explosions-processing-dead-entities.patch rename to patches/server/0039-Fix-lag-from-explosions-processing-dead-entities.patch diff --git a/patches/server/0039-Optimize-explosions.patch b/patches/server/0040-Optimize-explosions.patch similarity index 100% rename from patches/server/0039-Optimize-explosions.patch rename to patches/server/0040-Optimize-explosions.patch diff --git a/patches/server/0040-Disable-explosion-knockback.patch b/patches/server/0041-Disable-explosion-knockback.patch similarity index 100% rename from patches/server/0040-Disable-explosion-knockback.patch rename to patches/server/0041-Disable-explosion-knockback.patch diff --git a/patches/server/0041-Disable-thunder.patch b/patches/server/0042-Disable-thunder.patch similarity index 100% rename from patches/server/0041-Disable-thunder.patch rename to patches/server/0042-Disable-thunder.patch diff --git a/patches/server/0042-Disable-ice-and-snow.patch b/patches/server/0043-Disable-ice-and-snow.patch similarity index 100% rename from patches/server/0042-Disable-ice-and-snow.patch rename to patches/server/0043-Disable-ice-and-snow.patch diff --git a/patches/server/0043-Configurable-mob-spawner-tick-rate.patch b/patches/server/0044-Configurable-mob-spawner-tick-rate.patch similarity index 100% rename from patches/server/0043-Configurable-mob-spawner-tick-rate.patch rename to patches/server/0044-Configurable-mob-spawner-tick-rate.patch diff --git a/patches/server/0044-Implement-PlayerLocaleChangeEvent.patch b/patches/server/0045-Implement-PlayerLocaleChangeEvent.patch similarity index 100% rename from patches/server/0044-Implement-PlayerLocaleChangeEvent.patch rename to patches/server/0045-Implement-PlayerLocaleChangeEvent.patch diff --git a/patches/server/0045-Add-BeaconEffectEvent.patch b/patches/server/0046-Add-BeaconEffectEvent.patch similarity index 100% rename from patches/server/0045-Add-BeaconEffectEvent.patch rename to patches/server/0046-Add-BeaconEffectEvent.patch diff --git a/patches/server/0046-Configurable-container-update-tick-rate.patch b/patches/server/0047-Configurable-container-update-tick-rate.patch similarity index 100% rename from patches/server/0046-Configurable-container-update-tick-rate.patch rename to patches/server/0047-Configurable-container-update-tick-rate.patch diff --git a/patches/server/0047-Use-UserCache-for-player-heads.patch b/patches/server/0048-Use-UserCache-for-player-heads.patch similarity index 100% rename from patches/server/0047-Use-UserCache-for-player-heads.patch rename to patches/server/0048-Use-UserCache-for-player-heads.patch diff --git a/patches/server/0048-Disable-spigot-tick-limiters.patch b/patches/server/0049-Disable-spigot-tick-limiters.patch similarity index 100% rename from patches/server/0048-Disable-spigot-tick-limiters.patch rename to patches/server/0049-Disable-spigot-tick-limiters.patch diff --git a/patches/server/0049-Add-PlayerInitialSpawnEvent.patch b/patches/server/0050-Add-PlayerInitialSpawnEvent.patch similarity index 100% rename from patches/server/0049-Add-PlayerInitialSpawnEvent.patch rename to patches/server/0050-Add-PlayerInitialSpawnEvent.patch diff --git a/patches/server/0050-Configurable-Disabling-Cat-Chest-Detection.patch b/patches/server/0051-Configurable-Disabling-Cat-Chest-Detection.patch similarity index 100% rename from patches/server/0050-Configurable-Disabling-Cat-Chest-Detection.patch rename to patches/server/0051-Configurable-Disabling-Cat-Chest-Detection.patch diff --git a/patches/server/0051-Ensure-commands-are-not-ran-async.patch b/patches/server/0052-Ensure-commands-are-not-ran-async.patch similarity index 98% rename from patches/server/0051-Ensure-commands-are-not-ran-async.patch rename to patches/server/0052-Ensure-commands-are-not-ran-async.patch index bb4cabe4eb..060ec86489 100644 --- a/patches/server/0051-Ensure-commands-are-not-ran-async.patch +++ b/patches/server/0052-Ensure-commands-are-not-ran-async.patch @@ -74,10 +74,10 @@ index 8ef64f5192500f87f514c42432c0d5c8361145a7..f9f18e263d29421bdc83993a6fd55f47 if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index ecc94c04ba83aff8f232467aef2def69065a1c1e..21479b83bbf8a3fd83d2c28626c70b7ee6e5da83 100644 +index 710b06caa91d09f6e3d55f76162e60f41d0037e2..6654764b00e2b1ff15d54aa94d16474660bc3f47 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -876,6 +876,28 @@ public final class CraftServer implements Server { +@@ -857,6 +857,28 @@ public final class CraftServer implements Server { Validate.notNull(commandLine, "CommandLine cannot be null"); org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot diff --git a/patches/server/0052-All-chunks-are-slime-spawn-chunks-toggle.patch b/patches/server/0053-All-chunks-are-slime-spawn-chunks-toggle.patch similarity index 100% rename from patches/server/0052-All-chunks-are-slime-spawn-chunks-toggle.patch rename to patches/server/0053-All-chunks-are-slime-spawn-chunks-toggle.patch diff --git a/patches/server/0053-Expose-server-CommandMap.patch b/patches/server/0054-Expose-server-CommandMap.patch similarity index 78% rename from patches/server/0053-Expose-server-CommandMap.patch rename to patches/server/0054-Expose-server-CommandMap.patch index 0efe24c9a6..263fb6029b 100644 --- a/patches/server/0053-Expose-server-CommandMap.patch +++ b/patches/server/0054-Expose-server-CommandMap.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose server CommandMap diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 21479b83bbf8a3fd83d2c28626c70b7ee6e5da83..af723e317878e024abac59be8c1cc0a228a45980 100644 +index 6654764b00e2b1ff15d54aa94d16474660bc3f47..44cd9d5bccdc751dc9fb72a39f12e74a99133783 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2010,6 +2010,7 @@ public final class CraftServer implements Server { +@@ -1991,6 +1991,7 @@ public final class CraftServer implements Server { return this.helpMap; } diff --git a/patches/server/0054-Be-a-bit-more-informative-in-maxHealth-exception.patch b/patches/server/0055-Be-a-bit-more-informative-in-maxHealth-exception.patch similarity index 100% rename from patches/server/0054-Be-a-bit-more-informative-in-maxHealth-exception.patch rename to patches/server/0055-Be-a-bit-more-informative-in-maxHealth-exception.patch diff --git a/patches/server/0055-Player-Tab-List-and-Title-APIs.patch b/patches/server/0056-Player-Tab-List-and-Title-APIs.patch similarity index 100% rename from patches/server/0055-Player-Tab-List-and-Title-APIs.patch rename to patches/server/0056-Player-Tab-List-and-Title-APIs.patch diff --git a/patches/server/0056-Add-configurable-portal-search-radius.patch b/patches/server/0057-Add-configurable-portal-search-radius.patch similarity index 100% rename from patches/server/0056-Add-configurable-portal-search-radius.patch rename to patches/server/0057-Add-configurable-portal-search-radius.patch diff --git a/patches/server/0057-Add-velocity-warnings.patch b/patches/server/0058-Add-velocity-warnings.patch similarity index 96% rename from patches/server/0057-Add-velocity-warnings.patch rename to patches/server/0058-Add-velocity-warnings.patch index 7315eb6708..488501294c 100644 --- a/patches/server/0057-Add-velocity-warnings.patch +++ b/patches/server/0058-Add-velocity-warnings.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add velocity warnings diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index af723e317878e024abac59be8c1cc0a228a45980..d55bc1b83bd3ae99533b41c941d762f130f51c94 100644 +index 44cd9d5bccdc751dc9fb72a39f12e74a99133783..a290b298e24e8c4be08e7c720c10c9a83115eebf 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -293,6 +293,7 @@ public final class CraftServer implements Server { +@@ -294,6 +294,7 @@ public final class CraftServer implements Server { public boolean ignoreVanillaPermissions = false; private final List playerView; public int reloadCount; diff --git a/patches/server/0058-Configurable-inter-world-teleportation-safety.patch b/patches/server/0059-Configurable-inter-world-teleportation-safety.patch similarity index 100% rename from patches/server/0058-Configurable-inter-world-teleportation-safety.patch rename to patches/server/0059-Configurable-inter-world-teleportation-safety.patch diff --git a/patches/server/0059-Add-exception-reporting-event.patch b/patches/server/0060-Add-exception-reporting-event.patch similarity index 100% rename from patches/server/0059-Add-exception-reporting-event.patch rename to patches/server/0060-Add-exception-reporting-event.patch diff --git a/patches/server/0060-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch b/patches/server/0061-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch similarity index 100% rename from patches/server/0060-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch rename to patches/server/0061-Don-t-nest-if-we-don-t-need-to-when-cerealising-text.patch diff --git a/patches/server/0061-Disable-Scoreboards-for-non-players-by-default.patch b/patches/server/0062-Disable-Scoreboards-for-non-players-by-default.patch similarity index 100% rename from patches/server/0061-Disable-Scoreboards-for-non-players-by-default.patch rename to patches/server/0062-Disable-Scoreboards-for-non-players-by-default.patch diff --git a/patches/server/0062-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/patches/server/0063-Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 100% rename from patches/server/0062-Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to patches/server/0063-Add-methods-for-working-with-arrows-stuck-in-living-.patch diff --git a/patches/server/0063-Chunk-Save-Reattempt.patch b/patches/server/0064-Chunk-Save-Reattempt.patch similarity index 100% rename from patches/server/0063-Chunk-Save-Reattempt.patch rename to patches/server/0064-Chunk-Save-Reattempt.patch diff --git a/patches/server/0064-Complete-resource-pack-API.patch b/patches/server/0065-Complete-resource-pack-API.patch similarity index 100% rename from patches/server/0064-Complete-resource-pack-API.patch rename to patches/server/0065-Complete-resource-pack-API.patch diff --git a/patches/server/0065-Default-loading-permissions.yml-before-plugins.patch b/patches/server/0066-Default-loading-permissions.yml-before-plugins.patch similarity index 89% rename from patches/server/0065-Default-loading-permissions.yml-before-plugins.patch rename to patches/server/0066-Default-loading-permissions.yml-before-plugins.patch index bf475d5464..bca8836919 100644 --- a/patches/server/0065-Default-loading-permissions.yml-before-plugins.patch +++ b/patches/server/0066-Default-loading-permissions.yml-before-plugins.patch @@ -16,10 +16,10 @@ modify that. Under the previous logic, plugins were unable (cleanly) override pe A config option has been added for those who depend on the previous behavior, but I don't expect that. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index d55bc1b83bd3ae99533b41c941d762f130f51c94..bf752e456f44a8be2344678b657b8d0869b75c23 100644 +index a290b298e24e8c4be08e7c720c10c9a83115eebf..2b0defa81e3a250119d8f4337bf75ee17b57b08e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -475,6 +475,7 @@ public final class CraftServer implements Server { +@@ -454,6 +454,7 @@ public final class CraftServer implements Server { if (type == PluginLoadOrder.STARTUP) { this.helpMap.clear(); this.helpMap.initializeGeneralTopics(); @@ -27,7 +27,7 @@ index d55bc1b83bd3ae99533b41c941d762f130f51c94..bf752e456f44a8be2344678b657b8d08 } Plugin[] plugins = this.pluginManager.getPlugins(); -@@ -494,7 +495,7 @@ public final class CraftServer implements Server { +@@ -473,7 +474,7 @@ public final class CraftServer implements Server { this.commandMap.registerServerAliases(); DefaultPermissions.registerCorePermissions(); CraftDefaultPermissions.registerCorePermissions(); diff --git a/patches/server/0066-Allow-Reloading-of-Custom-Permissions.patch b/patches/server/0067-Allow-Reloading-of-Custom-Permissions.patch similarity index 90% rename from patches/server/0066-Allow-Reloading-of-Custom-Permissions.patch rename to patches/server/0067-Allow-Reloading-of-Custom-Permissions.patch index 5d9756be65..a48e9a9573 100644 --- a/patches/server/0066-Allow-Reloading-of-Custom-Permissions.patch +++ b/patches/server/0067-Allow-Reloading-of-Custom-Permissions.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Allow Reloading of Custom Permissions https://github.com/PaperMC/Paper/issues/49 diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index bf752e456f44a8be2344678b657b8d0869b75c23..93e98d43f71d376b28e566244bd650d22645e194 100644 +index 2b0defa81e3a250119d8f4337bf75ee17b57b08e..81982d554c53732621a01c14b565a03e2c623c28 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2564,5 +2564,23 @@ public final class CraftServer implements Server { +@@ -2545,5 +2545,23 @@ public final class CraftServer implements Server { } return this.adventure$audiences; } diff --git a/patches/server/0067-Remove-Metadata-on-reload.patch b/patches/server/0068-Remove-Metadata-on-reload.patch similarity index 88% rename from patches/server/0067-Remove-Metadata-on-reload.patch rename to patches/server/0068-Remove-Metadata-on-reload.patch index 523367c700..71aeeaa8e9 100644 --- a/patches/server/0067-Remove-Metadata-on-reload.patch +++ b/patches/server/0068-Remove-Metadata-on-reload.patch @@ -7,10 +7,10 @@ Metadata is not meant to persist reload as things break badly with non primitive This will remove metadata on reload so it does not crash everything if a plugin uses it. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 93e98d43f71d376b28e566244bd650d22645e194..c46ebebb2b47e07962d8b4a69777161e6428dd6b 100644 +index 81982d554c53732621a01c14b565a03e2c623c28..620cce68ec6407d0777d3f6de4d7de308331df8a 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -963,8 +963,16 @@ public final class CraftServer implements Server { +@@ -944,8 +944,16 @@ public final class CraftServer implements Server { world.spigotConfig.init(); // Spigot } diff --git a/patches/server/0068-Handle-Item-Meta-Inconsistencies.patch b/patches/server/0069-Handle-Item-Meta-Inconsistencies.patch similarity index 100% rename from patches/server/0068-Handle-Item-Meta-Inconsistencies.patch rename to patches/server/0069-Handle-Item-Meta-Inconsistencies.patch diff --git a/patches/server/0069-Configurable-Non-Player-Arrow-Despawn-Rate.patch b/patches/server/0070-Configurable-Non-Player-Arrow-Despawn-Rate.patch similarity index 100% rename from patches/server/0069-Configurable-Non-Player-Arrow-Despawn-Rate.patch rename to patches/server/0070-Configurable-Non-Player-Arrow-Despawn-Rate.patch diff --git a/patches/server/0070-Add-World-Util-Methods.patch b/patches/server/0071-Add-World-Util-Methods.patch similarity index 100% rename from patches/server/0070-Add-World-Util-Methods.patch rename to patches/server/0071-Add-World-Util-Methods.patch diff --git a/patches/server/0071-Custom-replacement-for-eaten-items.patch b/patches/server/0072-Custom-replacement-for-eaten-items.patch similarity index 100% rename from patches/server/0071-Custom-replacement-for-eaten-items.patch rename to patches/server/0072-Custom-replacement-for-eaten-items.patch diff --git a/patches/server/0072-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/patches/server/0073-handle-NaN-health-absorb-values-and-repair-bad-data.patch similarity index 100% rename from patches/server/0072-handle-NaN-health-absorb-values-and-repair-bad-data.patch rename to patches/server/0073-handle-NaN-health-absorb-values-and-repair-bad-data.patch diff --git a/patches/server/0073-Use-a-Shared-Random-for-Entities.patch b/patches/server/0074-Use-a-Shared-Random-for-Entities.patch similarity index 100% rename from patches/server/0073-Use-a-Shared-Random-for-Entities.patch rename to patches/server/0074-Use-a-Shared-Random-for-Entities.patch diff --git a/patches/server/0074-Configurable-spawn-chances-for-skeleton-horses.patch b/patches/server/0075-Configurable-spawn-chances-for-skeleton-horses.patch similarity index 100% rename from patches/server/0074-Configurable-spawn-chances-for-skeleton-horses.patch rename to patches/server/0075-Configurable-spawn-chances-for-skeleton-horses.patch diff --git a/patches/server/0075-Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch b/patches/server/0076-Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch similarity index 100% rename from patches/server/0075-Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch rename to patches/server/0076-Optimize-isInWorldBounds-and-getBlockState-for-inlin.patch diff --git a/patches/server/0076-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch b/patches/server/0077-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch similarity index 100% rename from patches/server/0076-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch rename to patches/server/0077-Only-process-BlockPhysicsEvent-if-a-plugin-has-a-lis.patch diff --git a/patches/server/0077-Entity-AddTo-RemoveFrom-World-Events.patch b/patches/server/0078-Entity-AddTo-RemoveFrom-World-Events.patch similarity index 100% rename from patches/server/0077-Entity-AddTo-RemoveFrom-World-Events.patch rename to patches/server/0078-Entity-AddTo-RemoveFrom-World-Events.patch diff --git a/patches/server/0078-Configurable-Chunk-Inhabited-Time.patch b/patches/server/0079-Configurable-Chunk-Inhabited-Time.patch similarity index 100% rename from patches/server/0078-Configurable-Chunk-Inhabited-Time.patch rename to patches/server/0079-Configurable-Chunk-Inhabited-Time.patch diff --git a/patches/server/0079-EntityPathfindEvent.patch b/patches/server/0080-EntityPathfindEvent.patch similarity index 100% rename from patches/server/0079-EntityPathfindEvent.patch rename to patches/server/0080-EntityPathfindEvent.patch diff --git a/patches/server/0080-Sanitise-RegionFileCache-and-make-configurable.patch b/patches/server/0081-Sanitise-RegionFileCache-and-make-configurable.patch similarity index 100% rename from patches/server/0080-Sanitise-RegionFileCache-and-make-configurable.patch rename to patches/server/0081-Sanitise-RegionFileCache-and-make-configurable.patch diff --git a/patches/server/0081-Do-not-load-chunks-for-Pathfinding.patch b/patches/server/0082-Do-not-load-chunks-for-Pathfinding.patch similarity index 100% rename from patches/server/0081-Do-not-load-chunks-for-Pathfinding.patch rename to patches/server/0082-Do-not-load-chunks-for-Pathfinding.patch diff --git a/patches/server/0082-Add-PlayerUseUnknownEntityEvent.patch b/patches/server/0083-Add-PlayerUseUnknownEntityEvent.patch similarity index 100% rename from patches/server/0082-Add-PlayerUseUnknownEntityEvent.patch rename to patches/server/0083-Add-PlayerUseUnknownEntityEvent.patch diff --git a/patches/server/0083-Configurable-Grass-Spread-Tick-Rate.patch b/patches/server/0084-Configurable-Grass-Spread-Tick-Rate.patch similarity index 100% rename from patches/server/0083-Configurable-Grass-Spread-Tick-Rate.patch rename to patches/server/0084-Configurable-Grass-Spread-Tick-Rate.patch diff --git a/patches/server/0084-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch b/patches/server/0085-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch similarity index 100% rename from patches/server/0084-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch rename to patches/server/0085-Fix-Cancelling-BlockPlaceEvent-triggering-physics.patch diff --git a/patches/server/0085-Optimize-DataBits.patch b/patches/server/0086-Optimize-DataBits.patch similarity index 100% rename from patches/server/0085-Optimize-DataBits.patch rename to patches/server/0086-Optimize-DataBits.patch diff --git a/patches/server/0086-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch b/patches/server/0087-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch similarity index 100% rename from patches/server/0086-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch rename to patches/server/0087-Option-to-use-vanilla-per-world-scoreboard-coloring-.patch diff --git a/patches/server/0087-Configurable-Player-Collision.patch b/patches/server/0088-Configurable-Player-Collision.patch similarity index 100% rename from patches/server/0087-Configurable-Player-Collision.patch rename to patches/server/0088-Configurable-Player-Collision.patch diff --git a/patches/server/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch b/patches/server/0089-Add-handshake-event-to-allow-plugins-to-handle-clien.patch similarity index 100% rename from patches/server/0088-Add-handshake-event-to-allow-plugins-to-handle-clien.patch rename to patches/server/0089-Add-handshake-event-to-allow-plugins-to-handle-clien.patch diff --git a/patches/server/0089-Configurable-RCON-IP-address.patch b/patches/server/0090-Configurable-RCON-IP-address.patch similarity index 100% rename from patches/server/0089-Configurable-RCON-IP-address.patch rename to patches/server/0090-Configurable-RCON-IP-address.patch diff --git a/patches/server/0090-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/server/0091-EntityRegainHealthEvent-isFastRegen-API.patch similarity index 100% rename from patches/server/0090-EntityRegainHealthEvent-isFastRegen-API.patch rename to patches/server/0091-EntityRegainHealthEvent-isFastRegen-API.patch diff --git a/patches/server/0091-Add-ability-to-configure-frosted_ice-properties.patch b/patches/server/0092-Add-ability-to-configure-frosted_ice-properties.patch similarity index 100% rename from patches/server/0091-Add-ability-to-configure-frosted_ice-properties.patch rename to patches/server/0092-Add-ability-to-configure-frosted_ice-properties.patch diff --git a/patches/server/0092-remove-null-possibility-for-getServer-singleton.patch b/patches/server/0093-remove-null-possibility-for-getServer-singleton.patch similarity index 100% rename from patches/server/0092-remove-null-possibility-for-getServer-singleton.patch rename to patches/server/0093-remove-null-possibility-for-getServer-singleton.patch diff --git a/patches/server/0093-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/patches/server/0094-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch similarity index 100% rename from patches/server/0093-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch rename to patches/server/0094-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch diff --git a/patches/server/0094-LootTable-API-Replenishable-Lootables-Feature.patch b/patches/server/0095-LootTable-API-Replenishable-Lootables-Feature.patch similarity index 100% rename from patches/server/0094-LootTable-API-Replenishable-Lootables-Feature.patch rename to patches/server/0095-LootTable-API-Replenishable-Lootables-Feature.patch diff --git a/patches/server/0095-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch b/patches/server/0096-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch similarity index 100% rename from patches/server/0095-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch rename to patches/server/0096-Don-t-save-empty-scoreboard-teams-to-scoreboard.dat.patch diff --git a/patches/server/0096-System-property-for-disabling-watchdoge.patch b/patches/server/0097-System-property-for-disabling-watchdoge.patch similarity index 100% rename from patches/server/0096-System-property-for-disabling-watchdoge.patch rename to patches/server/0097-System-property-for-disabling-watchdoge.patch diff --git a/patches/server/0097-Async-GameProfileCache-saving.patch b/patches/server/0098-Async-GameProfileCache-saving.patch similarity index 100% rename from patches/server/0097-Async-GameProfileCache-saving.patch rename to patches/server/0098-Async-GameProfileCache-saving.patch diff --git a/patches/server/0098-Optional-TNT-doesn-t-move-in-water.patch b/patches/server/0099-Optional-TNT-doesn-t-move-in-water.patch similarity index 100% rename from patches/server/0098-Optional-TNT-doesn-t-move-in-water.patch rename to patches/server/0099-Optional-TNT-doesn-t-move-in-water.patch diff --git a/patches/server/0099-Faster-redstone-torch-rapid-clock-removal.patch b/patches/server/0100-Faster-redstone-torch-rapid-clock-removal.patch similarity index 100% rename from patches/server/0099-Faster-redstone-torch-rapid-clock-removal.patch rename to patches/server/0100-Faster-redstone-torch-rapid-clock-removal.patch diff --git a/patches/server/0100-Add-server-name-parameter.patch b/patches/server/0101-Add-server-name-parameter.patch similarity index 100% rename from patches/server/0100-Add-server-name-parameter.patch rename to patches/server/0101-Add-server-name-parameter.patch diff --git a/patches/server/0101-Only-send-global-sounds-to-same-world-if-limiting-ra.patch b/patches/server/0102-Only-send-global-sounds-to-same-world-if-limiting-ra.patch similarity index 100% rename from patches/server/0101-Only-send-global-sounds-to-same-world-if-limiting-ra.patch rename to patches/server/0102-Only-send-global-sounds-to-same-world-if-limiting-ra.patch diff --git a/patches/server/0102-Fix-Old-Sign-Conversion.patch b/patches/server/0103-Fix-Old-Sign-Conversion.patch similarity index 100% rename from patches/server/0102-Fix-Old-Sign-Conversion.patch rename to patches/server/0103-Fix-Old-Sign-Conversion.patch diff --git a/patches/server/0103-Avoid-blocking-on-Network-Manager-creation.patch b/patches/server/0104-Avoid-blocking-on-Network-Manager-creation.patch similarity index 100% rename from patches/server/0103-Avoid-blocking-on-Network-Manager-creation.patch rename to patches/server/0104-Avoid-blocking-on-Network-Manager-creation.patch diff --git a/patches/server/0104-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/patches/server/0105-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch similarity index 100% rename from patches/server/0104-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch rename to patches/server/0105-Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch diff --git a/patches/server/0105-Add-setting-for-proxy-online-mode-status.patch b/patches/server/0106-Add-setting-for-proxy-online-mode-status.patch similarity index 95% rename from patches/server/0105-Add-setting-for-proxy-online-mode-status.patch rename to patches/server/0106-Add-setting-for-proxy-online-mode-status.patch index f822ac4e07..ed58b6232d 100644 --- a/patches/server/0105-Add-setting-for-proxy-online-mode-status.patch +++ b/patches/server/0106-Add-setting-for-proxy-online-mode-status.patch @@ -43,10 +43,10 @@ index da98f074ccd5a40c635824112c97fd174c393cb1..6599f874d9f97e9ef4862039ecad7277 } else { String[] astring1 = astring; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c46ebebb2b47e07962d8b4a69777161e6428dd6b..34dd9d9b772413888b48310ff7791e3cffefd1a8 100644 +index 620cce68ec6407d0777d3f6de4d7de308331df8a..7a4b9f0e26608d984a1e1483b5a549fa4214604f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1733,7 +1733,7 @@ public final class CraftServer implements Server { +@@ -1714,7 +1714,7 @@ public final class CraftServer implements Server { // Spigot Start GameProfile profile = null; // Only fetch an online UUID in online mode diff --git a/patches/server/0106-Optimise-BlockState-s-hashCode-equals.patch b/patches/server/0107-Optimise-BlockState-s-hashCode-equals.patch similarity index 100% rename from patches/server/0106-Optimise-BlockState-s-hashCode-equals.patch rename to patches/server/0107-Optimise-BlockState-s-hashCode-equals.patch diff --git a/patches/server/0107-Configurable-packet-in-spam-threshold.patch b/patches/server/0108-Configurable-packet-in-spam-threshold.patch similarity index 100% rename from patches/server/0107-Configurable-packet-in-spam-threshold.patch rename to patches/server/0108-Configurable-packet-in-spam-threshold.patch diff --git a/patches/server/0108-Configurable-flying-kick-messages.patch b/patches/server/0109-Configurable-flying-kick-messages.patch similarity index 100% rename from patches/server/0108-Configurable-flying-kick-messages.patch rename to patches/server/0109-Configurable-flying-kick-messages.patch diff --git a/patches/server/0109-Add-EntityZapEvent.patch b/patches/server/0110-Add-EntityZapEvent.patch similarity index 100% rename from patches/server/0109-Add-EntityZapEvent.patch rename to patches/server/0110-Add-EntityZapEvent.patch diff --git a/patches/server/0110-Filter-bad-tile-entity-nbt-data-from-falling-blocks.patch b/patches/server/0111-Filter-bad-tile-entity-nbt-data-from-falling-blocks.patch similarity index 100% rename from patches/server/0110-Filter-bad-tile-entity-nbt-data-from-falling-blocks.patch rename to patches/server/0111-Filter-bad-tile-entity-nbt-data-from-falling-blocks.patch diff --git a/patches/server/0111-Cache-user-authenticator-threads.patch b/patches/server/0112-Cache-user-authenticator-threads.patch similarity index 100% rename from patches/server/0111-Cache-user-authenticator-threads.patch rename to patches/server/0112-Cache-user-authenticator-threads.patch diff --git a/patches/server/0112-Allow-Reloading-of-Command-Aliases.patch b/patches/server/0113-Allow-Reloading-of-Command-Aliases.patch similarity index 90% rename from patches/server/0112-Allow-Reloading-of-Command-Aliases.patch rename to patches/server/0113-Allow-Reloading-of-Command-Aliases.patch index 5dabe23aa2..ed07bd7106 100644 --- a/patches/server/0112-Allow-Reloading-of-Command-Aliases.patch +++ b/patches/server/0113-Allow-Reloading-of-Command-Aliases.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Allow Reloading of Command Aliases Reload the aliases stored in commands.yml diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 34dd9d9b772413888b48310ff7791e3cffefd1a8..5cda3f24048fc734d727fd4ea07c676203b88f89 100644 +index 7a4b9f0e26608d984a1e1483b5a549fa4214604f..b1f7b5fe81fa179a6689422c4d3de5e2c8339552 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2590,5 +2590,24 @@ public final class CraftServer implements Server { +@@ -2571,5 +2571,24 @@ public final class CraftServer implements Server { DefaultPermissions.registerCorePermissions(); CraftDefaultPermissions.registerCorePermissions(); } diff --git a/patches/server/0113-Add-source-to-PlayerExpChangeEvent.patch b/patches/server/0114-Add-source-to-PlayerExpChangeEvent.patch similarity index 100% rename from patches/server/0113-Add-source-to-PlayerExpChangeEvent.patch rename to patches/server/0114-Add-source-to-PlayerExpChangeEvent.patch diff --git a/patches/server/0114-Add-ProjectileCollideEvent.patch b/patches/server/0115-Add-ProjectileCollideEvent.patch similarity index 100% rename from patches/server/0114-Add-ProjectileCollideEvent.patch rename to patches/server/0115-Add-ProjectileCollideEvent.patch diff --git a/patches/server/0115-Prevent-Pathfinding-out-of-World-Border.patch b/patches/server/0116-Prevent-Pathfinding-out-of-World-Border.patch similarity index 100% rename from patches/server/0115-Prevent-Pathfinding-out-of-World-Border.patch rename to patches/server/0116-Prevent-Pathfinding-out-of-World-Border.patch diff --git a/patches/server/0116-Optimize-World.isLoaded-BlockPosition-Z.patch b/patches/server/0117-Optimize-World.isLoaded-BlockPosition-Z.patch similarity index 100% rename from patches/server/0116-Optimize-World.isLoaded-BlockPosition-Z.patch rename to patches/server/0117-Optimize-World.isLoaded-BlockPosition-Z.patch diff --git a/patches/server/0117-Bound-Treasure-Maps-to-World-Border.patch b/patches/server/0118-Bound-Treasure-Maps-to-World-Border.patch similarity index 100% rename from patches/server/0117-Bound-Treasure-Maps-to-World-Border.patch rename to patches/server/0118-Bound-Treasure-Maps-to-World-Border.patch diff --git a/patches/server/0118-Configurable-Cartographer-Treasure-Maps.patch b/patches/server/0119-Configurable-Cartographer-Treasure-Maps.patch similarity index 100% rename from patches/server/0118-Configurable-Cartographer-Treasure-Maps.patch rename to patches/server/0119-Configurable-Cartographer-Treasure-Maps.patch diff --git a/patches/server/0119-Optimize-ItemStack.isEmpty.patch b/patches/server/0120-Optimize-ItemStack.isEmpty.patch similarity index 100% rename from patches/server/0119-Optimize-ItemStack.isEmpty.patch rename to patches/server/0120-Optimize-ItemStack.isEmpty.patch diff --git a/patches/server/0120-Add-API-methods-to-control-if-armour-stands-can-move.patch b/patches/server/0121-Add-API-methods-to-control-if-armour-stands-can-move.patch similarity index 100% rename from patches/server/0120-Add-API-methods-to-control-if-armour-stands-can-move.patch rename to patches/server/0121-Add-API-methods-to-control-if-armour-stands-can-move.patch diff --git a/patches/server/0121-String-based-Action-Bar-API.patch b/patches/server/0122-String-based-Action-Bar-API.patch similarity index 100% rename from patches/server/0121-String-based-Action-Bar-API.patch rename to patches/server/0122-String-based-Action-Bar-API.patch diff --git a/patches/server/0122-Properly-fix-item-duplication-bug.patch b/patches/server/0123-Properly-fix-item-duplication-bug.patch similarity index 100% rename from patches/server/0122-Properly-fix-item-duplication-bug.patch rename to patches/server/0123-Properly-fix-item-duplication-bug.patch diff --git a/patches/server/0123-Firework-API-s.patch b/patches/server/0124-Firework-API-s.patch similarity index 100% rename from patches/server/0123-Firework-API-s.patch rename to patches/server/0124-Firework-API-s.patch diff --git a/patches/server/0124-PlayerTeleportEndGatewayEvent.patch b/patches/server/0125-PlayerTeleportEndGatewayEvent.patch similarity index 100% rename from patches/server/0124-PlayerTeleportEndGatewayEvent.patch rename to patches/server/0125-PlayerTeleportEndGatewayEvent.patch diff --git a/patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch b/patches/server/0126-Provide-E-TE-Chunk-count-stat-methods.patch similarity index 100% rename from patches/server/0125-Provide-E-TE-Chunk-count-stat-methods.patch rename to patches/server/0126-Provide-E-TE-Chunk-count-stat-methods.patch diff --git a/patches/server/0126-Enforce-Sync-Player-Saves.patch b/patches/server/0127-Enforce-Sync-Player-Saves.patch similarity index 100% rename from patches/server/0126-Enforce-Sync-Player-Saves.patch rename to patches/server/0127-Enforce-Sync-Player-Saves.patch diff --git a/patches/server/0127-Don-t-allow-entities-to-ride-themselves-572.patch b/patches/server/0128-Don-t-allow-entities-to-ride-themselves-572.patch similarity index 100% rename from patches/server/0127-Don-t-allow-entities-to-ride-themselves-572.patch rename to patches/server/0128-Don-t-allow-entities-to-ride-themselves-572.patch diff --git a/patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server/0129-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch similarity index 100% rename from patches/server/0128-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch rename to patches/server/0129-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch diff --git a/patches/server/0129-Cap-Entity-Collisions.patch b/patches/server/0130-Cap-Entity-Collisions.patch similarity index 100% rename from patches/server/0129-Cap-Entity-Collisions.patch rename to patches/server/0130-Cap-Entity-Collisions.patch diff --git a/patches/server/0130-Remove-CraftScheduler-Async-Task-Debugger.patch b/patches/server/0131-Remove-CraftScheduler-Async-Task-Debugger.patch similarity index 100% rename from patches/server/0130-Remove-CraftScheduler-Async-Task-Debugger.patch rename to patches/server/0131-Remove-CraftScheduler-Async-Task-Debugger.patch diff --git a/patches/server/0131-Do-not-let-armorstands-drown.patch b/patches/server/0132-Do-not-let-armorstands-drown.patch similarity index 100% rename from patches/server/0131-Do-not-let-armorstands-drown.patch rename to patches/server/0132-Do-not-let-armorstands-drown.patch diff --git a/patches/server/0132-Properly-handle-async-calls-to-restart-the-server.patch b/patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch similarity index 100% rename from patches/server/0132-Properly-handle-async-calls-to-restart-the-server.patch rename to patches/server/0133-Properly-handle-async-calls-to-restart-the-server.patch diff --git a/patches/server/0133-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/patches/server/0134-Add-option-to-make-parrots-stay-on-shoulders-despite.patch similarity index 100% rename from patches/server/0133-Add-option-to-make-parrots-stay-on-shoulders-despite.patch rename to patches/server/0134-Add-option-to-make-parrots-stay-on-shoulders-despite.patch diff --git a/patches/server/0134-Add-configuration-option-to-prevent-player-names-fro.patch b/patches/server/0135-Add-configuration-option-to-prevent-player-names-fro.patch similarity index 83% rename from patches/server/0134-Add-configuration-option-to-prevent-player-names-fro.patch rename to patches/server/0135-Add-configuration-option-to-prevent-player-names-fro.patch index 16726b815c..60d9853c8d 100644 --- a/patches/server/0134-Add-configuration-option-to-prevent-player-names-fro.patch +++ b/patches/server/0135-Add-configuration-option-to-prevent-player-names-fro.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add configuration option to prevent player names from being diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 5cda3f24048fc734d727fd4ea07c676203b88f89..5e4bd49319c20461d5828489d0379601e0398005 100644 +index b1f7b5fe81fa179a6689422c4d3de5e2c8339552..6a0f2a8a12a4072d235c3d036ad253ba4a66fa6e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2609,5 +2609,10 @@ public final class CraftServer implements Server { +@@ -2590,5 +2590,10 @@ public final class CraftServer implements Server { commandMap.registerServerAliases(); return true; } diff --git a/patches/server/0135-Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/0136-Use-TerminalConsoleAppender-for-console-improvements.patch similarity index 99% rename from patches/server/0135-Use-TerminalConsoleAppender-for-console-improvements.patch rename to patches/server/0136-Use-TerminalConsoleAppender-for-console-improvements.patch index f166db6091..4cbee2372e 100644 --- a/patches/server/0135-Use-TerminalConsoleAppender-for-console-improvements.patch +++ b/patches/server/0136-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -236,7 +236,7 @@ index e6a47361db762bd4b54e28d3665a4aee72f91c19..30a017c54c334f0a8463186367c97c2c this.bans = new UserBanList(PlayerList.USERBANLIST_FILE); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 5e4bd49319c20461d5828489d0379601e0398005..bc2bbddde33738db0e46f0dbe39fe62c6d34126b 100644 +index 6a0f2a8a12a4072d235c3d036ad253ba4a66fa6e..95e64a7f0ab010798571b0b6a86dfad43003af62 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -48,7 +48,6 @@ import java.util.logging.Level; @@ -247,7 +247,7 @@ index 5e4bd49319c20461d5828489d0379601e0398005..bc2bbddde33738db0e46f0dbe39fe62c import net.minecraft.advancements.Advancement; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -@@ -1303,9 +1302,13 @@ public final class CraftServer implements Server { +@@ -1284,9 +1283,13 @@ public final class CraftServer implements Server { return this.logger; } diff --git a/patches/server/0136-provide-a-configurable-option-to-disable-creeper-lin.patch b/patches/server/0137-provide-a-configurable-option-to-disable-creeper-lin.patch similarity index 100% rename from patches/server/0136-provide-a-configurable-option-to-disable-creeper-lin.patch rename to patches/server/0137-provide-a-configurable-option-to-disable-creeper-lin.patch diff --git a/patches/server/0137-Item-canEntityPickup.patch b/patches/server/0138-Item-canEntityPickup.patch similarity index 100% rename from patches/server/0137-Item-canEntityPickup.patch rename to patches/server/0138-Item-canEntityPickup.patch diff --git a/patches/server/0138-PlayerPickupItemEvent-setFlyAtPlayer.patch b/patches/server/0139-PlayerPickupItemEvent-setFlyAtPlayer.patch similarity index 100% rename from patches/server/0138-PlayerPickupItemEvent-setFlyAtPlayer.patch rename to patches/server/0139-PlayerPickupItemEvent-setFlyAtPlayer.patch diff --git a/patches/server/0139-PlayerAttemptPickupItemEvent.patch b/patches/server/0140-PlayerAttemptPickupItemEvent.patch similarity index 100% rename from patches/server/0139-PlayerAttemptPickupItemEvent.patch rename to patches/server/0140-PlayerAttemptPickupItemEvent.patch diff --git a/patches/server/0140-Do-not-submit-profile-lookups-to-worldgen-threads.patch b/patches/server/0141-Do-not-submit-profile-lookups-to-worldgen-threads.patch similarity index 100% rename from patches/server/0140-Do-not-submit-profile-lookups-to-worldgen-threads.patch rename to patches/server/0141-Do-not-submit-profile-lookups-to-worldgen-threads.patch diff --git a/patches/server/0141-Add-UnknownCommandEvent.patch b/patches/server/0142-Add-UnknownCommandEvent.patch similarity index 96% rename from patches/server/0141-Add-UnknownCommandEvent.patch rename to patches/server/0142-Add-UnknownCommandEvent.patch index 583d76ce66..48b0b77034 100644 --- a/patches/server/0141-Add-UnknownCommandEvent.patch +++ b/patches/server/0142-Add-UnknownCommandEvent.patch @@ -83,10 +83,10 @@ index 9eaa7ad424252ea2e033d6041a14bf1ef7dd9fde..4cf76403098cc8565199b29757a29c80 b1 = 0; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index bc2bbddde33738db0e46f0dbe39fe62c6d34126b..d2f40cafd9a0a7a4c8e00647defa98d1ae678284 100644 +index 95e64a7f0ab010798571b0b6a86dfad43003af62..e17507dfbf9dc9634a0839a045c741bd38ab45ad 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -533,6 +533,7 @@ public final class CraftServer implements Server { +@@ -512,6 +512,7 @@ public final class CraftServer implements Server { if (command instanceof VanillaCommandWrapper) { LiteralCommandNode node = (LiteralCommandNode) ((VanillaCommandWrapper) command).vanillaCommand; @@ -94,7 +94,7 @@ index bc2bbddde33738db0e46f0dbe39fe62c6d34126b..d2f40cafd9a0a7a4c8e00647defa98d1 if (!node.getLiteral().equals(label)) { LiteralCommandNode clone = new LiteralCommandNode(label, node.getCommand(), node.getRequirement(), node.getRedirect(), node.getRedirectModifier(), node.isFork()); -@@ -905,7 +906,13 @@ public final class CraftServer implements Server { +@@ -886,7 +887,13 @@ public final class CraftServer implements Server { // Spigot start if (!org.spigotmc.SpigotConfig.unknownCommandMessage.isEmpty()) { diff --git a/patches/server/0142-Basic-PlayerProfile-API.patch b/patches/server/0143-Basic-PlayerProfile-API.patch similarity index 98% rename from patches/server/0142-Basic-PlayerProfile-API.patch rename to patches/server/0143-Basic-PlayerProfile-API.patch index 0b78ac510b..c2e9ac174c 100644 --- a/patches/server/0142-Basic-PlayerProfile-API.patch +++ b/patches/server/0143-Basic-PlayerProfile-API.patch @@ -596,10 +596,10 @@ index cf3e083c2ada3275a52c303de16a62576696e83f..b19850ae31f6c796cb3491dd5070d28e * Calculates distance between 2 entities * @param e1 diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index e600563a9d2ddbfa37c106481decb13e67f71524..7c1ad1e39c3b3dfd476133ef4d938187b7a11f09 100644 +index 8d61e388bbdfd6097f914fc5f122fdf7f9b9ffe2..c364ff90ea72ba45bc453ea78ca08c1c3fbf35dd 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -158,7 +158,7 @@ public class Main { +@@ -169,7 +169,7 @@ public class Main { } File file = (File) optionset.valueOf("universe"); // CraftBukkit @@ -631,7 +631,7 @@ index 4038bb76339d43f18770624bd7fecc79b8d7f2a9..2456edc11b29a92b1648937cd3dd6a9a String s1 = name.toLowerCase(Locale.ROOT); GameProfileCache.GameProfileInfo usercache_usercacheentry = (GameProfileCache.GameProfileInfo) this.profilesByName.get(s1); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index d2f40cafd9a0a7a4c8e00647defa98d1ae678284..a8f760ac25e42de33523727a56c7a2045cd284a6 100644 +index e17507dfbf9dc9634a0839a045c741bd38ab45ad..dce99265f1a3ef2b54bab3f3bad431f3f8dde888 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -257,6 +257,9 @@ import org.yaml.snakeyaml.error.MarkedYAMLException; @@ -644,7 +644,7 @@ index d2f40cafd9a0a7a4c8e00647defa98d1ae678284..a8f760ac25e42de33523727a56c7a204 public final class CraftServer implements Server { private final String serverName = "Paper"; // Paper private final String serverVersion; -@@ -297,6 +300,7 @@ public final class CraftServer implements Server { +@@ -298,6 +301,7 @@ public final class CraftServer implements Server { static { ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); ConfigurationSerialization.registerClass(CraftPlayerProfile.class); @@ -652,7 +652,7 @@ index d2f40cafd9a0a7a4c8e00647defa98d1ae678284..a8f760ac25e42de33523727a56c7a204 CraftItemFactory.instance(); } -@@ -2624,5 +2628,37 @@ public final class CraftServer implements Server { +@@ -2605,5 +2609,37 @@ public final class CraftServer implements Server { public boolean suggestPlayerNamesWhenNullTabCompletions() { return io.papermc.paper.configuration.GlobalConfiguration.get().commands.suggestPlayerNamesWhenNullTabCompletions; } diff --git a/patches/server/0143-Shoulder-Entities-Release-API.patch b/patches/server/0144-Shoulder-Entities-Release-API.patch similarity index 100% rename from patches/server/0143-Shoulder-Entities-Release-API.patch rename to patches/server/0144-Shoulder-Entities-Release-API.patch diff --git a/patches/server/0144-Profile-Lookup-Events.patch b/patches/server/0145-Profile-Lookup-Events.patch similarity index 100% rename from patches/server/0144-Profile-Lookup-Events.patch rename to patches/server/0145-Profile-Lookup-Events.patch diff --git a/patches/server/0145-Block-player-logins-during-server-shutdown.patch b/patches/server/0146-Block-player-logins-during-server-shutdown.patch similarity index 100% rename from patches/server/0145-Block-player-logins-during-server-shutdown.patch rename to patches/server/0146-Block-player-logins-during-server-shutdown.patch diff --git a/patches/server/0146-Entity-fromMobSpawner.patch b/patches/server/0147-Entity-fromMobSpawner.patch similarity index 100% rename from patches/server/0146-Entity-fromMobSpawner.patch rename to patches/server/0147-Entity-fromMobSpawner.patch diff --git a/patches/server/0147-Improve-the-Saddle-API-for-Horses.patch b/patches/server/0148-Improve-the-Saddle-API-for-Horses.patch similarity index 100% rename from patches/server/0147-Improve-the-Saddle-API-for-Horses.patch rename to patches/server/0148-Improve-the-Saddle-API-for-Horses.patch diff --git a/patches/server/0148-Implement-ensureServerConversions-API.patch b/patches/server/0149-Implement-ensureServerConversions-API.patch similarity index 100% rename from patches/server/0148-Implement-ensureServerConversions-API.patch rename to patches/server/0149-Implement-ensureServerConversions-API.patch diff --git a/patches/server/0149-Implement-getI18NDisplayName.patch b/patches/server/0150-Implement-getI18NDisplayName.patch similarity index 100% rename from patches/server/0149-Implement-getI18NDisplayName.patch rename to patches/server/0150-Implement-getI18NDisplayName.patch diff --git a/patches/server/0150-ProfileWhitelistVerifyEvent.patch b/patches/server/0151-ProfileWhitelistVerifyEvent.patch similarity index 100% rename from patches/server/0150-ProfileWhitelistVerifyEvent.patch rename to patches/server/0151-ProfileWhitelistVerifyEvent.patch diff --git a/patches/server/0151-Fix-this-stupid-bullshit.patch b/patches/server/0152-Fix-this-stupid-bullshit.patch similarity index 96% rename from patches/server/0151-Fix-this-stupid-bullshit.patch rename to patches/server/0152-Fix-this-stupid-bullshit.patch index da40a6458f..c198fc05b3 100644 --- a/patches/server/0151-Fix-this-stupid-bullshit.patch +++ b/patches/server/0152-Fix-this-stupid-bullshit.patch @@ -9,7 +9,7 @@ modified in order to prevent merge conflicts when Spigot changes/disables the wa and to provide some level of hint without being disruptive. diff --git a/src/main/java/net/minecraft/server/Bootstrap.java b/src/main/java/net/minecraft/server/Bootstrap.java -index b5aa358638b9d0638dfe47f7ebac04cca1dd80b9..0d3a8f576c037886ccdd6068ce953c4ce010ae2f 100644 +index e43096e69a00f9ea96badd7c966443cfcf3e7b95..ac2b7b5161eaaca3620268ae865d6f2a80227fde 100644 --- a/src/main/java/net/minecraft/server/Bootstrap.java +++ b/src/main/java/net/minecraft/server/Bootstrap.java @@ -40,7 +40,7 @@ public class Bootstrap { diff --git a/patches/server/0152-LivingEntity-setKiller.patch b/patches/server/0153-LivingEntity-setKiller.patch similarity index 100% rename from patches/server/0152-LivingEntity-setKiller.patch rename to patches/server/0153-LivingEntity-setKiller.patch diff --git a/patches/server/0153-Ocelot-despawns-should-honor-nametags-and-leash.patch b/patches/server/0154-Ocelot-despawns-should-honor-nametags-and-leash.patch similarity index 100% rename from patches/server/0153-Ocelot-despawns-should-honor-nametags-and-leash.patch rename to patches/server/0154-Ocelot-despawns-should-honor-nametags-and-leash.patch diff --git a/patches/server/0154-Reset-spawner-timer-when-spawner-event-is-cancelled.patch b/patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch similarity index 100% rename from patches/server/0154-Reset-spawner-timer-when-spawner-event-is-cancelled.patch rename to patches/server/0155-Reset-spawner-timer-when-spawner-event-is-cancelled.patch diff --git a/patches/server/0155-Allow-specifying-a-custom-authentication-servers-dow.patch b/patches/server/0156-Allow-specifying-a-custom-authentication-servers-dow.patch similarity index 100% rename from patches/server/0155-Allow-specifying-a-custom-authentication-servers-dow.patch rename to patches/server/0156-Allow-specifying-a-custom-authentication-servers-dow.patch diff --git a/patches/server/0156-Handle-plugin-prefixes-using-Log4J-configuration.patch b/patches/server/0157-Handle-plugin-prefixes-using-Log4J-configuration.patch similarity index 100% rename from patches/server/0156-Handle-plugin-prefixes-using-Log4J-configuration.patch rename to patches/server/0157-Handle-plugin-prefixes-using-Log4J-configuration.patch diff --git a/patches/server/0157-Improve-Log4J-Configuration-Plugin-Loggers.patch b/patches/server/0158-Improve-Log4J-Configuration-Plugin-Loggers.patch similarity index 100% rename from patches/server/0157-Improve-Log4J-Configuration-Plugin-Loggers.patch rename to patches/server/0158-Improve-Log4J-Configuration-Plugin-Loggers.patch diff --git a/patches/server/0158-Add-PlayerJumpEvent.patch b/patches/server/0159-Add-PlayerJumpEvent.patch similarity index 100% rename from patches/server/0158-Add-PlayerJumpEvent.patch rename to patches/server/0159-Add-PlayerJumpEvent.patch diff --git a/patches/server/0159-handle-ServerboundKeepAlivePacket-async.patch b/patches/server/0160-handle-ServerboundKeepAlivePacket-async.patch similarity index 100% rename from patches/server/0159-handle-ServerboundKeepAlivePacket-async.patch rename to patches/server/0160-handle-ServerboundKeepAlivePacket-async.patch diff --git a/patches/server/0160-Expose-client-protocol-version-and-virtual-host.patch b/patches/server/0161-Expose-client-protocol-version-and-virtual-host.patch similarity index 100% rename from patches/server/0160-Expose-client-protocol-version-and-virtual-host.patch rename to patches/server/0161-Expose-client-protocol-version-and-virtual-host.patch diff --git a/patches/server/0161-revert-serverside-behavior-of-keepalives.patch b/patches/server/0162-revert-serverside-behavior-of-keepalives.patch similarity index 100% rename from patches/server/0161-revert-serverside-behavior-of-keepalives.patch rename to patches/server/0162-revert-serverside-behavior-of-keepalives.patch diff --git a/patches/server/0162-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/patches/server/0163-Send-attack-SoundEffects-only-to-players-who-can-see.patch similarity index 100% rename from patches/server/0162-Send-attack-SoundEffects-only-to-players-who-can-see.patch rename to patches/server/0163-Send-attack-SoundEffects-only-to-players-who-can-see.patch diff --git a/patches/server/0163-Add-PlayerArmorChangeEvent.patch b/patches/server/0164-Add-PlayerArmorChangeEvent.patch similarity index 100% rename from patches/server/0163-Add-PlayerArmorChangeEvent.patch rename to patches/server/0164-Add-PlayerArmorChangeEvent.patch diff --git a/patches/server/0164-Prevent-logins-from-being-processed-when-the-player-.patch b/patches/server/0165-Prevent-logins-from-being-processed-when-the-player-.patch similarity index 100% rename from patches/server/0164-Prevent-logins-from-being-processed-when-the-player-.patch rename to patches/server/0165-Prevent-logins-from-being-processed-when-the-player-.patch diff --git a/patches/server/0165-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/patches/server/0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch similarity index 100% rename from patches/server/0165-Fix-MC-117075-TE-Unload-Lag-Spike.patch rename to patches/server/0166-Fix-MC-117075-TE-Unload-Lag-Spike.patch diff --git a/patches/server/0166-use-CB-BlockState-implementations-for-captured-block.patch b/patches/server/0167-use-CB-BlockState-implementations-for-captured-block.patch similarity index 100% rename from patches/server/0166-use-CB-BlockState-implementations-for-captured-block.patch rename to patches/server/0167-use-CB-BlockState-implementations-for-captured-block.patch diff --git a/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch b/patches/server/0168-API-to-get-a-BlockState-without-a-snapshot.patch similarity index 98% rename from patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch rename to patches/server/0168-API-to-get-a-BlockState-without-a-snapshot.patch index 53edd2717b..9d98e1c68d 100644 --- a/patches/server/0167-API-to-get-a-BlockState-without-a-snapshot.patch +++ b/patches/server/0168-API-to-get-a-BlockState-without-a-snapshot.patch @@ -51,7 +51,7 @@ index b701a1344db066b9368841f2377ee493514bf282..5768ff2c3e15c038d132c7ad391332fb return null; } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 14e1c7c40761b1bd8123b4b351d5d77d7c1c52c2..13da02b84d7e748d61fdf5db01d92a8d8cd5c799 100644 +index 0e96f8d01b0499a4d4a8e9e11c2d94f54022bb6b..0951e0836ef16c99505c884ea80e5bd23873b7e6 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -331,6 +331,13 @@ public class CraftBlock implements Block { diff --git a/patches/server/0168-AsyncTabCompleteEvent.patch b/patches/server/0169-AsyncTabCompleteEvent.patch similarity index 98% rename from patches/server/0168-AsyncTabCompleteEvent.patch rename to patches/server/0169-AsyncTabCompleteEvent.patch index 49f6a03bac..aeb19e57b5 100644 --- a/patches/server/0168-AsyncTabCompleteEvent.patch +++ b/patches/server/0169-AsyncTabCompleteEvent.patch @@ -91,10 +91,10 @@ index 66436cd5b6b14914919a1eb612ca133ee4ffef05..43748cb2ee5840ee82d5ab6337a72c86 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index a8f760ac25e42de33523727a56c7a2045cd284a6..25343a382c7ef8e79f74e276b28fd2fc73c66e27 100644 +index dce99265f1a3ef2b54bab3f3bad431f3f8dde888..87b29d0965b460706385aa4e28931f5ddd4a33a7 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2114,7 +2114,7 @@ public final class CraftServer implements Server { +@@ -2095,7 +2095,7 @@ public final class CraftServer implements Server { offers = this.tabCompleteChat(player, message); } diff --git a/patches/server/0169-PlayerPickupExperienceEvent.patch b/patches/server/0170-PlayerPickupExperienceEvent.patch similarity index 100% rename from patches/server/0169-PlayerPickupExperienceEvent.patch rename to patches/server/0170-PlayerPickupExperienceEvent.patch diff --git a/patches/server/0170-Ability-to-apply-mending-to-XP-API.patch b/patches/server/0171-Ability-to-apply-mending-to-XP-API.patch similarity index 100% rename from patches/server/0170-Ability-to-apply-mending-to-XP-API.patch rename to patches/server/0171-Ability-to-apply-mending-to-XP-API.patch diff --git a/patches/server/0171-PlayerNaturallySpawnCreaturesEvent.patch b/patches/server/0172-PlayerNaturallySpawnCreaturesEvent.patch similarity index 100% rename from patches/server/0171-PlayerNaturallySpawnCreaturesEvent.patch rename to patches/server/0172-PlayerNaturallySpawnCreaturesEvent.patch diff --git a/patches/server/0172-Add-setPlayerProfile-API-for-Skulls.patch b/patches/server/0173-Add-setPlayerProfile-API-for-Skulls.patch similarity index 100% rename from patches/server/0172-Add-setPlayerProfile-API-for-Skulls.patch rename to patches/server/0173-Add-setPlayerProfile-API-for-Skulls.patch diff --git a/patches/server/0173-PreCreatureSpawnEvent.patch b/patches/server/0174-PreCreatureSpawnEvent.patch similarity index 100% rename from patches/server/0173-PreCreatureSpawnEvent.patch rename to patches/server/0174-PreCreatureSpawnEvent.patch diff --git a/patches/server/0174-Fill-Profile-Property-Events.patch b/patches/server/0175-Fill-Profile-Property-Events.patch similarity index 100% rename from patches/server/0174-Fill-Profile-Property-Events.patch rename to patches/server/0175-Fill-Profile-Property-Events.patch diff --git a/patches/server/0175-PlayerAdvancementCriterionGrantEvent.patch b/patches/server/0176-PlayerAdvancementCriterionGrantEvent.patch similarity index 100% rename from patches/server/0175-PlayerAdvancementCriterionGrantEvent.patch rename to patches/server/0176-PlayerAdvancementCriterionGrantEvent.patch diff --git a/patches/server/0176-Add-ArmorStand-Item-Meta.patch b/patches/server/0177-Add-ArmorStand-Item-Meta.patch similarity index 100% rename from patches/server/0176-Add-ArmorStand-Item-Meta.patch rename to patches/server/0177-Add-ArmorStand-Item-Meta.patch diff --git a/patches/server/0177-Extend-Player-Interact-cancellation.patch b/patches/server/0178-Extend-Player-Interact-cancellation.patch similarity index 100% rename from patches/server/0177-Extend-Player-Interact-cancellation.patch rename to patches/server/0178-Extend-Player-Interact-cancellation.patch diff --git a/patches/server/0178-Tameable-getOwnerUniqueId-API.patch b/patches/server/0179-Tameable-getOwnerUniqueId-API.patch similarity index 100% rename from patches/server/0178-Tameable-getOwnerUniqueId-API.patch rename to patches/server/0179-Tameable-getOwnerUniqueId-API.patch diff --git a/patches/server/0179-Toggleable-player-crits-helps-mitigate-hacked-client.patch b/patches/server/0180-Toggleable-player-crits-helps-mitigate-hacked-client.patch similarity index 100% rename from patches/server/0179-Toggleable-player-crits-helps-mitigate-hacked-client.patch rename to patches/server/0180-Toggleable-player-crits-helps-mitigate-hacked-client.patch diff --git a/patches/server/0180-Disable-Explicit-Network-Manager-Flushing.patch b/patches/server/0181-Disable-Explicit-Network-Manager-Flushing.patch similarity index 100% rename from patches/server/0180-Disable-Explicit-Network-Manager-Flushing.patch rename to patches/server/0181-Disable-Explicit-Network-Manager-Flushing.patch diff --git a/patches/server/0181-Implement-extended-PaperServerListPingEvent.patch b/patches/server/0182-Implement-extended-PaperServerListPingEvent.patch similarity index 100% rename from patches/server/0181-Implement-extended-PaperServerListPingEvent.patch rename to patches/server/0182-Implement-extended-PaperServerListPingEvent.patch diff --git a/patches/server/0182-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch b/patches/server/0183-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch similarity index 100% rename from patches/server/0182-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch rename to patches/server/0183-Ability-to-change-PlayerProfile-in-AsyncPreLoginEven.patch diff --git a/patches/server/0183-Player.setPlayerProfile-API.patch b/patches/server/0184-Player.setPlayerProfile-API.patch similarity index 100% rename from patches/server/0183-Player.setPlayerProfile-API.patch rename to patches/server/0184-Player.setPlayerProfile-API.patch diff --git a/patches/server/0184-getPlayerUniqueId-API.patch b/patches/server/0185-getPlayerUniqueId-API.patch similarity index 90% rename from patches/server/0184-getPlayerUniqueId-API.patch rename to patches/server/0185-getPlayerUniqueId-API.patch index 54e7da5f9a..bd42c0e0fb 100644 --- a/patches/server/0184-getPlayerUniqueId-API.patch +++ b/patches/server/0185-getPlayerUniqueId-API.patch @@ -9,10 +9,10 @@ In Offline Mode, will return an Offline UUID This is a more performant way to obtain a UUID for a name than loading an OfflinePlayer diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 25343a382c7ef8e79f74e276b28fd2fc73c66e27..6bb4f1e6fa16c3972781b04218b0d579d2ceee3d 100644 +index 87b29d0965b460706385aa4e28931f5ddd4a33a7..86d8e08b19316bb202b62bd7ac1187eb4827e5c5 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1736,6 +1736,25 @@ public final class CraftServer implements Server { +@@ -1717,6 +1717,25 @@ public final class CraftServer implements Server { return recipients.size(); } diff --git a/patches/server/0185-Improved-Async-Task-Scheduler.patch b/patches/server/0186-Improved-Async-Task-Scheduler.patch similarity index 100% rename from patches/server/0185-Improved-Async-Task-Scheduler.patch rename to patches/server/0186-Improved-Async-Task-Scheduler.patch diff --git a/patches/server/0186-Make-legacy-ping-handler-more-reliable.patch b/patches/server/0187-Make-legacy-ping-handler-more-reliable.patch similarity index 100% rename from patches/server/0186-Make-legacy-ping-handler-more-reliable.patch rename to patches/server/0187-Make-legacy-ping-handler-more-reliable.patch diff --git a/patches/server/0187-Call-PaperServerListPingEvent-for-legacy-pings.patch b/patches/server/0188-Call-PaperServerListPingEvent-for-legacy-pings.patch similarity index 100% rename from patches/server/0187-Call-PaperServerListPingEvent-for-legacy-pings.patch rename to patches/server/0188-Call-PaperServerListPingEvent-for-legacy-pings.patch diff --git a/patches/server/0188-Flag-to-disable-the-channel-limit.patch b/patches/server/0189-Flag-to-disable-the-channel-limit.patch similarity index 100% rename from patches/server/0188-Flag-to-disable-the-channel-limit.patch rename to patches/server/0189-Flag-to-disable-the-channel-limit.patch diff --git a/patches/server/0189-Add-openSign-method-to-HumanEntity.patch b/patches/server/0190-Add-openSign-method-to-HumanEntity.patch similarity index 100% rename from patches/server/0189-Add-openSign-method-to-HumanEntity.patch rename to patches/server/0190-Add-openSign-method-to-HumanEntity.patch diff --git a/patches/server/0190-Configurable-sprint-interruption-on-attack.patch b/patches/server/0191-Configurable-sprint-interruption-on-attack.patch similarity index 100% rename from patches/server/0190-Configurable-sprint-interruption-on-attack.patch rename to patches/server/0191-Configurable-sprint-interruption-on-attack.patch diff --git a/patches/server/0191-Fix-exploit-that-allowed-colored-signs-to-be-created.patch b/patches/server/0192-Fix-exploit-that-allowed-colored-signs-to-be-created.patch similarity index 100% rename from patches/server/0191-Fix-exploit-that-allowed-colored-signs-to-be-created.patch rename to patches/server/0192-Fix-exploit-that-allowed-colored-signs-to-be-created.patch diff --git a/patches/server/0192-EndermanEscapeEvent.patch b/patches/server/0193-EndermanEscapeEvent.patch similarity index 100% rename from patches/server/0192-EndermanEscapeEvent.patch rename to patches/server/0193-EndermanEscapeEvent.patch diff --git a/patches/server/0193-Enderman.teleportRandomly.patch b/patches/server/0194-Enderman.teleportRandomly.patch similarity index 100% rename from patches/server/0193-Enderman.teleportRandomly.patch rename to patches/server/0194-Enderman.teleportRandomly.patch diff --git a/patches/server/0194-Block-Enderpearl-Travel-Exploit.patch b/patches/server/0195-Block-Enderpearl-Travel-Exploit.patch similarity index 100% rename from patches/server/0194-Block-Enderpearl-Travel-Exploit.patch rename to patches/server/0195-Block-Enderpearl-Travel-Exploit.patch diff --git a/patches/server/0195-Expand-World.spawnParticle-API-and-add-Builder.patch b/patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch similarity index 100% rename from patches/server/0195-Expand-World.spawnParticle-API-and-add-Builder.patch rename to patches/server/0196-Expand-World.spawnParticle-API-and-add-Builder.patch diff --git a/patches/server/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch b/patches/server/0197-Prevent-Frosted-Ice-from-loading-holding-chunks.patch similarity index 100% rename from patches/server/0196-Prevent-Frosted-Ice-from-loading-holding-chunks.patch rename to patches/server/0197-Prevent-Frosted-Ice-from-loading-holding-chunks.patch diff --git a/patches/server/0197-EndermanAttackPlayerEvent.patch b/patches/server/0198-EndermanAttackPlayerEvent.patch similarity index 100% rename from patches/server/0197-EndermanAttackPlayerEvent.patch rename to patches/server/0198-EndermanAttackPlayerEvent.patch diff --git a/patches/server/0198-WitchConsumePotionEvent.patch b/patches/server/0199-WitchConsumePotionEvent.patch similarity index 100% rename from patches/server/0198-WitchConsumePotionEvent.patch rename to patches/server/0199-WitchConsumePotionEvent.patch diff --git a/patches/server/0199-WitchThrowPotionEvent.patch b/patches/server/0200-WitchThrowPotionEvent.patch similarity index 100% rename from patches/server/0199-WitchThrowPotionEvent.patch rename to patches/server/0200-WitchThrowPotionEvent.patch diff --git a/patches/server/0200-Allow-spawning-Item-entities-with-World.spawnEntity.patch b/patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch similarity index 100% rename from patches/server/0200-Allow-spawning-Item-entities-with-World.spawnEntity.patch rename to patches/server/0201-Allow-spawning-Item-entities-with-World.spawnEntity.patch diff --git a/patches/server/0201-WitchReadyPotionEvent.patch b/patches/server/0202-WitchReadyPotionEvent.patch similarity index 100% rename from patches/server/0201-WitchReadyPotionEvent.patch rename to patches/server/0202-WitchReadyPotionEvent.patch diff --git a/patches/server/0202-ItemStack-getMaxItemUseDuration.patch b/patches/server/0203-ItemStack-getMaxItemUseDuration.patch similarity index 100% rename from patches/server/0202-ItemStack-getMaxItemUseDuration.patch rename to patches/server/0203-ItemStack-getMaxItemUseDuration.patch diff --git a/patches/server/0203-Implement-EntityTeleportEndGatewayEvent.patch b/patches/server/0204-Implement-EntityTeleportEndGatewayEvent.patch similarity index 100% rename from patches/server/0203-Implement-EntityTeleportEndGatewayEvent.patch rename to patches/server/0204-Implement-EntityTeleportEndGatewayEvent.patch diff --git a/patches/server/0204-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch b/patches/server/0205-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch similarity index 100% rename from patches/server/0204-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch rename to patches/server/0205-Unset-Ignited-flag-on-cancel-of-Explosion-Event.patch diff --git a/patches/server/0205-Fix-CraftEntity-hashCode.patch b/patches/server/0206-Fix-CraftEntity-hashCode.patch similarity index 100% rename from patches/server/0205-Fix-CraftEntity-hashCode.patch rename to patches/server/0206-Fix-CraftEntity-hashCode.patch diff --git a/patches/server/0206-Configurable-Alternative-LootPool-Luck-Formula.patch b/patches/server/0207-Configurable-Alternative-LootPool-Luck-Formula.patch similarity index 100% rename from patches/server/0206-Configurable-Alternative-LootPool-Luck-Formula.patch rename to patches/server/0207-Configurable-Alternative-LootPool-Luck-Formula.patch diff --git a/patches/server/0207-Print-Error-details-when-failing-to-save-player-data.patch b/patches/server/0208-Print-Error-details-when-failing-to-save-player-data.patch similarity index 100% rename from patches/server/0207-Print-Error-details-when-failing-to-save-player-data.patch rename to patches/server/0208-Print-Error-details-when-failing-to-save-player-data.patch diff --git a/patches/server/0208-Make-shield-blocking-delay-configurable.patch b/patches/server/0209-Make-shield-blocking-delay-configurable.patch similarity index 100% rename from patches/server/0208-Make-shield-blocking-delay-configurable.patch rename to patches/server/0209-Make-shield-blocking-delay-configurable.patch diff --git a/patches/server/0209-Improve-EntityShootBowEvent.patch b/patches/server/0210-Improve-EntityShootBowEvent.patch similarity index 100% rename from patches/server/0209-Improve-EntityShootBowEvent.patch rename to patches/server/0210-Improve-EntityShootBowEvent.patch diff --git a/patches/server/0210-PlayerReadyArrowEvent.patch b/patches/server/0211-PlayerReadyArrowEvent.patch similarity index 100% rename from patches/server/0210-PlayerReadyArrowEvent.patch rename to patches/server/0211-PlayerReadyArrowEvent.patch diff --git a/patches/server/0211-Implement-EntityKnockbackByEntityEvent-and-EntityPus.patch b/patches/server/0212-Implement-EntityKnockbackByEntityEvent-and-EntityPus.patch similarity index 100% rename from patches/server/0211-Implement-EntityKnockbackByEntityEvent-and-EntityPus.patch rename to patches/server/0212-Implement-EntityKnockbackByEntityEvent-and-EntityPus.patch diff --git a/patches/server/0212-Expand-Explosions-API.patch b/patches/server/0213-Expand-Explosions-API.patch similarity index 100% rename from patches/server/0212-Expand-Explosions-API.patch rename to patches/server/0213-Expand-Explosions-API.patch diff --git a/patches/server/0213-LivingEntity-Hand-Raised-Item-Use-API.patch b/patches/server/0214-LivingEntity-Hand-Raised-Item-Use-API.patch similarity index 100% rename from patches/server/0213-LivingEntity-Hand-Raised-Item-Use-API.patch rename to patches/server/0214-LivingEntity-Hand-Raised-Item-Use-API.patch diff --git a/patches/server/0214-RangedEntity-API.patch b/patches/server/0215-RangedEntity-API.patch similarity index 100% rename from patches/server/0214-RangedEntity-API.patch rename to patches/server/0215-RangedEntity-API.patch diff --git a/patches/server/0215-Add-config-to-disable-ender-dragon-legacy-check.patch b/patches/server/0216-Add-config-to-disable-ender-dragon-legacy-check.patch similarity index 100% rename from patches/server/0215-Add-config-to-disable-ender-dragon-legacy-check.patch rename to patches/server/0216-Add-config-to-disable-ender-dragon-legacy-check.patch diff --git a/patches/server/0216-Implement-World.getEntity-UUID-API.patch b/patches/server/0217-Implement-World.getEntity-UUID-API.patch similarity index 100% rename from patches/server/0216-Implement-World.getEntity-UUID-API.patch rename to patches/server/0217-Implement-World.getEntity-UUID-API.patch diff --git a/patches/server/0217-InventoryCloseEvent-Reason-API.patch b/patches/server/0218-InventoryCloseEvent-Reason-API.patch similarity index 100% rename from patches/server/0217-InventoryCloseEvent-Reason-API.patch rename to patches/server/0218-InventoryCloseEvent-Reason-API.patch diff --git a/patches/server/0218-Vex-get-setSummoner-API.patch b/patches/server/0219-Vex-get-setSummoner-API.patch similarity index 100% rename from patches/server/0218-Vex-get-setSummoner-API.patch rename to patches/server/0219-Vex-get-setSummoner-API.patch diff --git a/patches/server/0219-Refresh-player-inventory-when-cancelling-PlayerInter.patch b/patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch similarity index 100% rename from patches/server/0219-Refresh-player-inventory-when-cancelling-PlayerInter.patch rename to patches/server/0220-Refresh-player-inventory-when-cancelling-PlayerInter.patch diff --git a/patches/server/0220-Use-AsyncAppender-to-keep-logging-IO-off-main-thread.patch b/patches/server/0221-Use-AsyncAppender-to-keep-logging-IO-off-main-thread.patch similarity index 100% rename from patches/server/0220-Use-AsyncAppender-to-keep-logging-IO-off-main-thread.patch rename to patches/server/0221-Use-AsyncAppender-to-keep-logging-IO-off-main-thread.patch diff --git a/patches/server/0221-add-more-information-to-Entity.toString.patch b/patches/server/0222-add-more-information-to-Entity.toString.patch similarity index 100% rename from patches/server/0221-add-more-information-to-Entity.toString.patch rename to patches/server/0222-add-more-information-to-Entity.toString.patch diff --git a/patches/server/0239-Add-Early-Warning-Feature-to-WatchDog.patch b/patches/server/0239-Add-Early-Warning-Feature-to-WatchDog.patch index 2dd00112d5..66d6dc4bf8 100644 --- a/patches/server/0239-Add-Early-Warning-Feature-to-WatchDog.patch +++ b/patches/server/0239-Add-Early-Warning-Feature-to-WatchDog.patch @@ -33,10 +33,10 @@ index e6826cd0a596f063e8737dcde3c8c6c5b3f71970..1a2607d1b257cea65c82c661a6b3d46c com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6bb4f1e6fa16c3972781b04218b0d579d2ceee3d..f53304465bf5ead9de2e769b7b783f853103980d 100644 +index 86d8e08b19316bb202b62bd7ac1187eb4827e5c5..ccb176c7292aa49780ef21f7a17d97ca7ef53794 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -925,6 +925,7 @@ public final class CraftServer implements Server { +@@ -906,6 +906,7 @@ public final class CraftServer implements Server { @Override public void reload() { @@ -44,7 +44,7 @@ index 6bb4f1e6fa16c3972781b04218b0d579d2ceee3d..f53304465bf5ead9de2e769b7b783f85 this.reloadCount++; this.configuration = YamlConfiguration.loadConfiguration(this.getConfigFile()); this.commandsConfiguration = YamlConfiguration.loadConfiguration(this.getCommandsConfigFile()); -@@ -1013,6 +1014,7 @@ public final class CraftServer implements Server { +@@ -994,6 +995,7 @@ public final class CraftServer implements Server { this.enablePlugins(PluginLoadOrder.STARTUP); this.enablePlugins(PluginLoadOrder.POSTWORLD); this.getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.RELOAD)); diff --git a/patches/server/0284-Make-the-default-permission-message-configurable.patch b/patches/server/0284-Make-the-default-permission-message-configurable.patch index 5411701202..acf8312b31 100644 --- a/patches/server/0284-Make-the-default-permission-message-configurable.patch +++ b/patches/server/0284-Make-the-default-permission-message-configurable.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make the default permission message configurable diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java -index 1e9105cf5ab2ff0ee847fafd00b41e1bd47f1d9e..65ee888280f917ccd11146505b7389513280a863 100644 +index e202af893c7ec22bfc0b8dbeb8e1551db685d1d3..32b84c59722970218a1515e21c6454d0ea4f781d 100644 --- a/src/main/java/io/papermc/paper/command/PaperCommand.java +++ b/src/main/java/io/papermc/paper/command/PaperCommand.java -@@ -78,7 +78,7 @@ public final class PaperCommand extends Command { +@@ -80,7 +80,7 @@ public final class PaperCommand extends Command { if (sender.hasPermission(BASE_PERM + permission) || sender.hasPermission("bukkit.command.paper")) { return true; } @@ -18,10 +18,10 @@ index 1e9105cf5ab2ff0ee847fafd00b41e1bd47f1d9e..65ee888280f917ccd11146505b738951 } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f53304465bf5ead9de2e769b7b783f853103980d..074098d147d6b1a678233a097d17ade524d938cd 100644 +index ccb176c7292aa49780ef21f7a17d97ca7ef53794..ff166f93e511dda7e29f676cb2bd7ea148ff1a9d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2650,6 +2650,16 @@ public final class CraftServer implements Server { +@@ -2631,6 +2631,16 @@ public final class CraftServer implements Server { return io.papermc.paper.configuration.GlobalConfiguration.get().commands.suggestPlayerNamesWhenNullTabCompletions; } diff --git a/patches/server/0318-Expose-the-internal-current-tick.patch b/patches/server/0318-Expose-the-internal-current-tick.patch index d8875d267d..ee9d9442bd 100644 --- a/patches/server/0318-Expose-the-internal-current-tick.patch +++ b/patches/server/0318-Expose-the-internal-current-tick.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose the internal current tick diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 074098d147d6b1a678233a097d17ade524d938cd..edc810d092d069cdfb8a36566c0eab8577a96859 100644 +index ff166f93e511dda7e29f676cb2bd7ea148ff1a9d..3369e749610fca12aa7dc5b514ffbab9ec40e43c 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2691,5 +2691,10 @@ public final class CraftServer implements Server { +@@ -2672,5 +2672,10 @@ public final class CraftServer implements Server { profile.getProperties().putAll(((CraftPlayer)player).getHandle().getGameProfile().getProperties()); return new com.destroystokyo.paper.profile.CraftPlayerProfile(profile); } diff --git a/patches/server/0328-Flat-bedrock-generator-settings.patch b/patches/server/0328-Flat-bedrock-generator-settings.patch index 51f8e1ed9a..f5ea879f80 100644 --- a/patches/server/0328-Flat-bedrock-generator-settings.patch +++ b/patches/server/0328-Flat-bedrock-generator-settings.patch @@ -19,24 +19,6 @@ public net.minecraft.world.level.levelgen.SurfaceSystem getOrCreateRandomFactory Co-authored-by: Noah van der Aa -diff --git a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java -index 5b8ecf5b0165ed2cd4397cdee958e97c2e8f18d5..ad802eb211f05f646159d7fc53f8a9427b46cb89 100644 ---- a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java -+++ b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java -@@ -310,7 +310,13 @@ public class BuiltInRegistries { - } - - public static void bootStrap() { -+ // Paper start -+ bootStrap(() -> {}); -+ } -+ public static void bootStrap(Runnable runnable) { -+ // Paper end - createContents(); -+ runnable.run(); // Paper - freeze(); - validate(REGISTRY); - } diff --git a/src/main/java/net/minecraft/data/worldgen/SurfaceRuleData.java b/src/main/java/net/minecraft/data/worldgen/SurfaceRuleData.java index 06e1774dfbb667aca69bc30c9675ed472cb5728c..1d5bc86516df3781aea894c3afd340421ba51a17 100644 --- a/src/main/java/net/minecraft/data/worldgen/SurfaceRuleData.java @@ -132,22 +114,17 @@ index 06e1774dfbb667aca69bc30c9675ed472cb5728c..1d5bc86516df3781aea894c3afd34042 public static SurfaceRules.RuleSource end() { diff --git a/src/main/java/net/minecraft/server/Bootstrap.java b/src/main/java/net/minecraft/server/Bootstrap.java -index 0d3a8f576c037886ccdd6068ce953c4ce010ae2f..d0ee6523477309bc984869774533ee1941ed0cb0 100644 +index ac2b7b5161eaaca3620268ae865d6f2a80227fde..a1192d1f6b99669f843e8d9a8928ff0e8c030559 100644 --- a/src/main/java/net/minecraft/server/Bootstrap.java +++ b/src/main/java/net/minecraft/server/Bootstrap.java -@@ -69,7 +69,11 @@ public class Bootstrap { - EntitySelectorOptions.bootStrap(); - DispenseItemBehavior.bootStrap(); +@@ -71,6 +71,7 @@ public class Bootstrap { CauldronInteraction.bootStrap(); -- BuiltInRegistries.bootStrap(); -+ // Paper start - register custom flat bedrock -+ BuiltInRegistries.bootStrap(() -> { + // Paper start + BuiltInRegistries.bootStrap(() -> { + net.minecraft.core.Registry.register(net.minecraft.core.registries.BuiltInRegistries.MATERIAL_CONDITION, new net.minecraft.resources.ResourceLocation("paper", "bedrock_condition_source"), net.minecraft.data.worldgen.SurfaceRuleData.PaperBedrockConditionSource.CODEC.codec()); -+ }); -+ // Paper end - Bootstrap.wrapStreams(); - } - // CraftBukkit start - easier than fixing the decompile + io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler.enterBootstrappers(); // Paper - Entrypoint for bootstrapping + }); + // Paper end diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java index cdc87f14e5d6336856c74d5089e50ae5ebad9923..6b84633bf6956406d2e2c5dd32fa358f41ccc890 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java diff --git a/patches/server/0344-Anti-Xray.patch b/patches/server/0344-Anti-Xray.patch index 5c42a89fcc..9e34f06782 100644 --- a/patches/server/0344-Anti-Xray.patch +++ b/patches/server/0344-Anti-Xray.patch @@ -1571,10 +1571,10 @@ index 832c6d92daaa96210a9c7edbd357ca824a60a4a5..0fadc763fb482cf9f3b51ed44427029b public CraftChunk(net.minecraft.world.level.chunk.LevelChunk chunk) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index edc810d092d069cdfb8a36566c0eab8577a96859..78ab2ea2cf1d4676d16986572a40ebb2c6ca7950 100644 +index 3369e749610fca12aa7dc5b514ffbab9ec40e43c..d312d6c543f0e09e40c232032c09caae35c8891a 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2263,7 +2263,7 @@ public final class CraftServer implements Server { +@@ -2244,7 +2244,7 @@ public final class CraftServer implements Server { public ChunkGenerator.ChunkData createChunkData(World world) { Validate.notNull(world, "World cannot be null"); ServerLevel handle = ((CraftWorld) world).getHandle(); diff --git a/patches/server/0350-Improve-Block-breakNaturally-API.patch b/patches/server/0350-Improve-Block-breakNaturally-API.patch index 8dd927a9b1..1c815426c2 100644 --- a/patches/server/0350-Improve-Block-breakNaturally-API.patch +++ b/patches/server/0350-Improve-Block-breakNaturally-API.patch @@ -34,7 +34,7 @@ index 0afadbc8515d448b0ef817f4f0f53b1bb0abde43..64206d94a5bf210116d208f9678618b9 if (world.dimensionType().ultraWarm()) { world.removeBlock(pos, false); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 2e3b675dca8cec906d533141e158e5db6ae87042..3123a8d52236757c3e7ca3b099cc664485cb3c72 100644 +index ee8315595faae22c63c97748d8047038a671263e..ac543a4c6bc21435de3c6721af37fd5f554e403e 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -477,6 +477,18 @@ public class CraftBlock implements Block { diff --git a/patches/server/0352-Add-debug-for-sync-chunk-loads.patch b/patches/server/0352-Add-debug-for-sync-chunk-loads.patch index e1e2010e32..9d9c319a68 100644 --- a/patches/server/0352-Add-debug-for-sync-chunk-loads.patch +++ b/patches/server/0352-Add-debug-for-sync-chunk-loads.patch @@ -194,7 +194,7 @@ index 0000000000000000000000000000000000000000..0bb4aaa546939b67a5d22865190f3047 + } +} diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java -index 65ee888280f917ccd11146505b7389513280a863..04bf08cbe45763f1338390c5ab4b0dcb334bd07a 100644 +index 32b84c59722970218a1515e21c6454d0ea4f781d..8f35943e71911b6d49b4cf210e56f5e11c5753e8 100644 --- a/src/main/java/io/papermc/paper/command/PaperCommand.java +++ b/src/main/java/io/papermc/paper/command/PaperCommand.java @@ -5,6 +5,7 @@ import io.papermc.paper.command.subcommands.EntityCommand; @@ -203,10 +203,10 @@ index 65ee888280f917ccd11146505b7389513280a863..04bf08cbe45763f1338390c5ab4b0dcb import io.papermc.paper.command.subcommands.ReloadCommand; +import io.papermc.paper.command.subcommands.SyncLoadInfoCommand; import io.papermc.paper.command.subcommands.VersionCommand; + import io.papermc.paper.command.subcommands.DumpPluginsCommand; import it.unimi.dsi.fastutil.Pair; - import java.util.ArrayList; -@@ -44,6 +45,7 @@ public final class PaperCommand extends Command { - commands.put(Set.of("version"), new VersionCommand()); +@@ -46,6 +47,7 @@ public final class PaperCommand extends Command { + commands.put(Set.of("dumpplugins"), new DumpPluginsCommand()); commands.put(Set.of("fixlight"), new FixLightCommand()); commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand()); + commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand()); diff --git a/patches/server/0364-Add-tick-times-API-and-mspt-command.patch b/patches/server/0364-Add-tick-times-API-and-mspt-command.patch index 8571925b05..8c31978826 100644 --- a/patches/server/0364-Add-tick-times-API-and-mspt-command.patch +++ b/patches/server/0364-Add-tick-times-API-and-mspt-command.patch @@ -113,7 +113,7 @@ index 0000000000000000000000000000000000000000..8b5293b0c696ef21d0101493ffa41b60 + } +} diff --git a/src/main/java/io/papermc/paper/command/PaperCommands.java b/src/main/java/io/papermc/paper/command/PaperCommands.java -index 6a00f3d38da8107825ab1d405f337fd077b09f72..d31b5ed47cffc61c90c926a0cd2005b72ebddfc5 100644 +index d44d0074446c1c54e87dc8078dff7fef1d92f343..bbb8b1933ef33a3b91f69545f69dd3cfb84b27f5 100644 --- a/src/main/java/io/papermc/paper/command/PaperCommands.java +++ b/src/main/java/io/papermc/paper/command/PaperCommands.java @@ -17,6 +17,7 @@ public final class PaperCommands { @@ -185,10 +185,10 @@ index 023119624c0534bedb248099d0e12c76622a363a..8dcbeeae50afe23aa7e2a083239f0a31 + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 78ab2ea2cf1d4676d16986572a40ebb2c6ca7950..5d638a1876bf79c46052f2572aa4182dca556457 100644 +index d312d6c543f0e09e40c232032c09caae35c8891a..99e0aca5f57516ef09fe0bb57c6b991934bb5cc8 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2513,6 +2513,16 @@ public final class CraftServer implements Server { +@@ -2494,6 +2494,16 @@ public final class CraftServer implements Server { net.minecraft.server.MinecraftServer.getServer().tps15.getAverage() }; } diff --git a/patches/server/0365-Expose-MinecraftServer-isRunning.patch b/patches/server/0365-Expose-MinecraftServer-isRunning.patch index c08b209864..9ca22e4d6a 100644 --- a/patches/server/0365-Expose-MinecraftServer-isRunning.patch +++ b/patches/server/0365-Expose-MinecraftServer-isRunning.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Expose MinecraftServer#isRunning This allows for plugins to detect if the server is actually turning off in onDisable rather than just plugins reloading. diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 5d638a1876bf79c46052f2572aa4182dca556457..047c1c20624926a7a9be7204bd2e3f144a52afa9 100644 +index 99e0aca5f57516ef09fe0bb57c6b991934bb5cc8..dac4dd74f75a9ea5fcd19dc65e958d933ba7560d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2706,5 +2706,10 @@ public final class CraftServer implements Server { +@@ -2687,5 +2687,10 @@ public final class CraftServer implements Server { public int getCurrentTick() { return net.minecraft.server.MinecraftServer.currentTick; } diff --git a/patches/server/0366-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/0366-Add-Raw-Byte-ItemStack-Serialization.patch index 57aeeeb569..f371e21c28 100644 --- a/patches/server/0366-Add-Raw-Byte-ItemStack-Serialization.patch +++ b/patches/server/0366-Add-Raw-Byte-ItemStack-Serialization.patch @@ -6,12 +6,12 @@ Subject: [PATCH] Add Raw Byte ItemStack Serialization Serializes using NBT which is safer for server data migrations than bukkits format. diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 4d74e7755d3812746d9e9014046c5c22f400deec..10c26e104827502cc40488455af3f493f4ddb4f1 100644 +index 0ee761fa0d42fd90e82f3284ee756ddd60c6178d..70c4eb21b3730a6bb7c44671eaaba9a7bc3ee5a3 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -458,6 +458,52 @@ public final class CraftMagicNumbers implements UnsafeValues { - public boolean isSupportedApiVersion(String apiVersion) { - return apiVersion != null && SUPPORTED_API.contains(apiVersion); +@@ -459,6 +459,52 @@ public final class CraftMagicNumbers implements UnsafeValues { + public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { + return new com.destroystokyo.paper.PaperVersionFetcher(); } + + @Override diff --git a/patches/server/0392-Expose-game-version.patch b/patches/server/0392-Expose-game-version.patch index 34dbb816c3..23d67857c3 100644 --- a/patches/server/0392-Expose-game-version.patch +++ b/patches/server/0392-Expose-game-version.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose game version diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 047c1c20624926a7a9be7204bd2e3f144a52afa9..84de99c3872f1e99301824764c047f214ee24a5e 100644 +index dac4dd74f75a9ea5fcd19dc65e958d933ba7560d..422d6b39337c3a774dfddcee877dc8281c5d7774 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -593,6 +593,13 @@ public final class CraftServer implements Server { +@@ -574,6 +574,13 @@ public final class CraftServer implements Server { return this.bukkitVersion; } diff --git a/patches/server/0395-misc-debugging-dumps.patch b/patches/server/0395-misc-debugging-dumps.patch index e76a319bd1..79a6949953 100644 --- a/patches/server/0395-misc-debugging-dumps.patch +++ b/patches/server/0395-misc-debugging-dumps.patch @@ -74,10 +74,10 @@ index 9d3ea20adba300a38a544c3454eff2edd9b4bbb9..3e6ec2cef2b5b058f240dd471d5c7a22 this.connection.send(new ClientboundDisconnectPacket(ichatmutablecomponent)); this.connection.disconnect(ichatmutablecomponent); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 84de99c3872f1e99301824764c047f214ee24a5e..d5ec8667f87936480ecf8d5820e02b07aea1f5fd 100644 +index 422d6b39337c3a774dfddcee877dc8281c5d7774..222095ad4cc055565c1a166d21714f7b1140815f 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1016,6 +1016,7 @@ public final class CraftServer implements Server { +@@ -997,6 +997,7 @@ public final class CraftServer implements Server { plugin.getDescription().getFullName(), "This plugin is not properly shutting down its async tasks when it is being reloaded. This may cause conflicts with the newly loaded version of the plugin" )); diff --git a/patches/server/0398-Implement-Mob-Goal-API.patch b/patches/server/0398-Implement-Mob-Goal-API.patch index bc0a37795d..05001e984f 100644 --- a/patches/server/0398-Implement-Mob-Goal-API.patch +++ b/patches/server/0398-Implement-Mob-Goal-API.patch @@ -791,10 +791,10 @@ index 4379b9948f1eecfe6fd7dea98e298ad5f761019a..3f081183521603824430709886a9cc31 LOOK, JUMP, diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index d5ec8667f87936480ecf8d5820e02b07aea1f5fd..d4820b97bbfdb6f8f810dda66e6671b318bde8e1 100644 +index 222095ad4cc055565c1a166d21714f7b1140815f..52e852c43556d00ecb2fd0971189de64e0268620 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2719,5 +2719,11 @@ public final class CraftServer implements Server { +@@ -2700,5 +2700,11 @@ public final class CraftServer implements Server { public boolean isStopping() { return net.minecraft.server.MinecraftServer.getServer().hasStopped(); } diff --git a/patches/server/0405-Wait-for-Async-Tasks-during-shutdown.patch b/patches/server/0405-Wait-for-Async-Tasks-during-shutdown.patch index 41fe56662d..c7d2e9343c 100644 --- a/patches/server/0405-Wait-for-Async-Tasks-during-shutdown.patch +++ b/patches/server/0405-Wait-for-Async-Tasks-during-shutdown.patch @@ -22,10 +22,10 @@ index 366959f9841eb0ef3669b3b3b069d7670f0ba7e6..93c1a1bf602af1e73202590e78dac833 // CraftBukkit end if (this.getConnection() != null) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index d4820b97bbfdb6f8f810dda66e6671b318bde8e1..ae1a78fcc61d5fe6bfdc41cca508d269ee9d1e39 100644 +index 52e852c43556d00ecb2fd0971189de64e0268620..39e5b52d1495b7a0f5f451543ad0329fab0fe27d 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1025,6 +1025,35 @@ public final class CraftServer implements Server { +@@ -1006,6 +1006,35 @@ public final class CraftServer implements Server { org.spigotmc.WatchdogThread.hasStarted = true; // Paper - Disable watchdog early timeout on reload } diff --git a/patches/server/0428-Fix-Per-World-Difficulty-Remembering-Difficulty.patch b/patches/server/0428-Fix-Per-World-Difficulty-Remembering-Difficulty.patch index 120fb64f23..683319b41c 100644 --- a/patches/server/0428-Fix-Per-World-Difficulty-Remembering-Difficulty.patch +++ b/patches/server/0428-Fix-Per-World-Difficulty-Remembering-Difficulty.patch @@ -102,10 +102,10 @@ index fa06f9be742103e65aa90dfb9d21a93c119bf0c0..d5f879303080dadf0fbd5d15840c2536 } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index ae1a78fcc61d5fe6bfdc41cca508d269ee9d1e39..82c61d3e06f98e828393aba16d40ebc4fe0fd30e 100644 +index 39e5b52d1495b7a0f5f451543ad0329fab0fe27d..76b0423c71875a3e30d6cc613ebdb1cca4b9bbd5 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -965,8 +965,8 @@ public final class CraftServer implements Server { +@@ -946,8 +946,8 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.init((File) console.options.valueOf("spigot-settings")); // Spigot this.console.paperConfigurations.reloadConfigs(this.console); for (ServerLevel world : this.console.getAllLevels()) { diff --git a/patches/server/0429-Paper-dumpitem-command.patch b/patches/server/0429-Paper-dumpitem-command.patch index 1f5d0868be..52da5fa920 100644 --- a/patches/server/0429-Paper-dumpitem-command.patch +++ b/patches/server/0429-Paper-dumpitem-command.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Paper dumpitem command Let's you quickly view the item in your hands NBT data diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java -index 04bf08cbe45763f1338390c5ab4b0dcb334bd07a..a7b78508ef78229835805300e62a306a3f1ddf6d 100644 +index 8f35943e71911b6d49b4cf210e56f5e11c5753e8..312c0e42643355183ea3346a69fe9b5a5624bf1d 100644 --- a/src/main/java/io/papermc/paper/command/PaperCommand.java +++ b/src/main/java/io/papermc/paper/command/PaperCommand.java @@ -1,6 +1,7 @@ @@ -17,7 +17,7 @@ index 04bf08cbe45763f1338390c5ab4b0dcb334bd07a..a7b78508ef78229835805300e62a306a import io.papermc.paper.command.subcommands.EntityCommand; import io.papermc.paper.command.subcommands.FixLightCommand; import io.papermc.paper.command.subcommands.HeapDumpCommand; -@@ -46,6 +47,7 @@ public final class PaperCommand extends Command { +@@ -48,6 +49,7 @@ public final class PaperCommand extends Command { commands.put(Set.of("fixlight"), new FixLightCommand()); commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand()); commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand()); diff --git a/patches/server/0432-Add-Plugin-Tickets-to-API-Chunk-Methods.patch b/patches/server/0432-Add-Plugin-Tickets-to-API-Chunk-Methods.patch index 99025a7358..0627b61c96 100644 --- a/patches/server/0432-Add-Plugin-Tickets-to-API-Chunk-Methods.patch +++ b/patches/server/0432-Add-Plugin-Tickets-to-API-Chunk-Methods.patch @@ -22,10 +22,10 @@ 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 82c61d3e06f98e828393aba16d40ebc4fe0fd30e..4c4a19a359ff6325906f0a47852dcef6ae6acf3e 100644 +index 76b0423c71875a3e30d6cc613ebdb1cca4b9bbd5..796f0f96811534895623a0a3de04ea33f276ce47 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -373,7 +373,7 @@ public final class CraftServer implements Server { +@@ -374,7 +374,7 @@ public final class CraftServer implements Server { this.overrideSpawnLimits(); console.autosavePeriod = this.configuration.getInt("ticks-per.autosave"); this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose")); @@ -34,7 +34,7 @@ index 82c61d3e06f98e828393aba16d40ebc4fe0fd30e..4c4a19a359ff6325906f0a47852dcef6 this.minimumAPI = this.configuration.getString("settings.minimum-api"); this.loadIcon(); -@@ -945,7 +945,7 @@ public final class CraftServer implements Server { +@@ -926,7 +926,7 @@ public final class CraftServer implements Server { this.console.setMotd(config.motd); this.overrideSpawnLimits(); this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose")); diff --git a/patches/server/0450-Thread-Safe-Vanilla-Command-permission-checking.patch b/patches/server/0450-Thread-Safe-Vanilla-Command-permission-checking.patch index aed58b8511..41ee49df99 100644 --- a/patches/server/0450-Thread-Safe-Vanilla-Command-permission-checking.patch +++ b/patches/server/0450-Thread-Safe-Vanilla-Command-permission-checking.patch @@ -26,7 +26,7 @@ index 20a7cdf87f307878d66922aaac0c60cff218e46c..39844531b03eb8a6c70700b4ecbf0ff1 } // CraftBukkit end diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java -index b8f5b5895bf75aa8e08b2b0431ef6fdacd235430..c2af60bdb755034e46b85143826a29c4482d58f5 100644 +index efad6dc30ff2731fdaed9c7f8d974aba8d8a4bcf..24172c3b7b1d2faa13b18bedf89ad051267feb6c 100644 --- a/src/main/java/net/minecraft/commands/CommandSourceStack.java +++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java @@ -61,7 +61,7 @@ public class CommandSourceStack implements SharedSuggestionProvider, com.destroy diff --git a/patches/server/0452-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch b/patches/server/0452-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch index b880f8bef6..4e73a907d9 100644 --- a/patches/server/0452-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch +++ b/patches/server/0452-Fix-SPIGOT-5824-Bukkit-world-container-is-not-used.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix SPIGOT-5824 Bukkit world-container is not used diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 7c1ad1e39c3b3dfd476133ef4d938187b7a11f09..9b1ec0186e7dfa1591532fa887f27fa378fb1d95 100644 +index c364ff90ea72ba45bc453ea78ca08c1c3fbf35dd..66eab856e7aac5eb9e7db9236ad7ca3cc370060b 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -157,8 +157,17 @@ public class Main { +@@ -168,8 +168,17 @@ public class Main { return; } diff --git a/patches/server/0453-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch b/patches/server/0453-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch index 50c2c1fab5..c1f23f7b9b 100644 --- a/patches/server/0453-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch +++ b/patches/server/0453-Fix-SPIGOT-5885-Unable-to-disable-advancements.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix SPIGOT-5885 Unable to disable advancements diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 9b1ec0186e7dfa1591532fa887f27fa378fb1d95..727efbe152dccabf130a6871e3d2582a5a733016 100644 +index 66eab856e7aac5eb9e7db9236ad7ca3cc370060b..7989b5bf002ba0995c32fb77498c7f50b34e6150 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -157,6 +157,7 @@ public class Main { +@@ -168,6 +168,7 @@ public class Main { return; } diff --git a/patches/server/0459-Add-setMaxPlayers-API.patch b/patches/server/0459-Add-setMaxPlayers-API.patch index acecd5b4e7..6408a7ca14 100644 --- a/patches/server/0459-Add-setMaxPlayers-API.patch +++ b/patches/server/0459-Add-setMaxPlayers-API.patch @@ -18,10 +18,10 @@ index 5d6128932e1af0445cf928fac6d6b91226a18de6..fdd7f80fe912d4f75e7c42a2dd971600 private int simulationDistance; private boolean allowCheatsForAllPlayers; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 4c4a19a359ff6325906f0a47852dcef6ae6acf3e..8dbfae0732675759ff2d08f8be3740edbff92bbf 100644 +index 796f0f96811534895623a0a3de04ea33f276ce47..facd84b0a2a6dcde32ca47fc5a1b9058c41c5ec4 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -688,6 +688,13 @@ public final class CraftServer implements Server { +@@ -669,6 +669,13 @@ public final class CraftServer implements Server { return this.playerList.getMaxPlayers(); } diff --git a/patches/server/0480-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server/0480-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch index 17912b6159..4f8b381046 100644 --- a/patches/server/0480-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ b/patches/server/0480-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch @@ -21,10 +21,10 @@ index 873206bb65b2412d3066a0f7e35fe0684e29661a..d170254265a789998be96ce1dcaf71c9 + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 10c26e104827502cc40488455af3f493f4ddb4f1..97de89745a8bd6526a136506c6d17e5056a9d8d9 100644 +index 70c4eb21b3730a6bb7c44671eaaba9a7bc3ee5a3..26e6fab362db3f5880bb5daddd4795465e969c27 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -504,6 +504,11 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -505,6 +505,11 @@ public final class CraftMagicNumbers implements UnsafeValues { Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); return compound; } diff --git a/patches/server/0495-Add-getOfflinePlayerIfCached-String.patch b/patches/server/0495-Add-getOfflinePlayerIfCached-String.patch index 2bfd07abab..ccdacc2684 100644 --- a/patches/server/0495-Add-getOfflinePlayerIfCached-String.patch +++ b/patches/server/0495-Add-getOfflinePlayerIfCached-String.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add getOfflinePlayerIfCached(String) diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 8dbfae0732675759ff2d08f8be3740edbff92bbf..50e9e9f3cc807972b0d2f612dc93d674fd4ae0ee 100644 +index facd84b0a2a6dcde32ca47fc5a1b9058c41c5ec4..fed01c7ed32a0207216fd902976902b223cc3518 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1831,6 +1831,28 @@ public final class CraftServer implements Server { +@@ -1812,6 +1812,28 @@ public final class CraftServer implements Server { return result; } diff --git a/patches/server/0498-Fix-client-lag-on-advancement-loading.patch b/patches/server/0498-Fix-client-lag-on-advancement-loading.patch index fd96d05210..fe628e7903 100644 --- a/patches/server/0498-Fix-client-lag-on-advancement-loading.patch +++ b/patches/server/0498-Fix-client-lag-on-advancement-loading.patch @@ -15,7 +15,7 @@ manually reload the advancement data for all players, which normally takes place as a part of the datapack reloading. diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 97de89745a8bd6526a136506c6d17e5056a9d8d9..4b7afdfea75e1023f68c1f9dbaf2db23010a0c30 100644 +index 15b09e538675791ab19dc7c678208ee93f51f184..14e50807bf4f337a33ea54578fe5fadeb59e3ae4 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -345,7 +345,13 @@ public final class CraftMagicNumbers implements UnsafeValues { diff --git a/patches/server/0525-Additional-Block-Material-API-s.patch b/patches/server/0525-Additional-Block-Material-API-s.patch index 0d852337ea..3a8a041708 100644 --- a/patches/server/0525-Additional-Block-Material-API-s.patch +++ b/patches/server/0525-Additional-Block-Material-API-s.patch @@ -9,7 +9,7 @@ process to do this in the Bukkit API Adds API for buildable, replaceable, burnable too. diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index ac831b22930ad02951186b6326b0c542de4c9881..30b5a78a93405f3a03624ed1331670770aaa3765 100644 +index c3ab1a60f60806e2b91b633bf89389cf434443ce..23a9469ff63f1be7ab0091b2c86a614eaeba9f55 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -465,6 +465,25 @@ public class CraftBlock implements Block { diff --git a/patches/server/0543-Empty-commands-shall-not-be-dispatched.patch b/patches/server/0543-Empty-commands-shall-not-be-dispatched.patch index cb0945d783..e365b45432 100644 --- a/patches/server/0543-Empty-commands-shall-not-be-dispatched.patch +++ b/patches/server/0543-Empty-commands-shall-not-be-dispatched.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Empty commands shall not be dispatched diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index b9614977b902edc59b4f319f5c1051bcb20dc9fc..80ab8903b340881ca45b46caa7f03e605796080d 100644 +index 2f256d0452617c8f2630f0dd8f16025c9b2e0cae..da7503dca8ab4f7234bf296dfacf39e466de700a 100644 --- a/src/main/java/net/minecraft/commands/Commands.java +++ b/src/main/java/net/minecraft/commands/Commands.java @@ -255,6 +255,7 @@ public class Commands { diff --git a/patches/server/0548-Add-PaperRegistry.patch b/patches/server/0548-Add-PaperRegistry.patch index ae05218e82..b5474d9bb7 100644 --- a/patches/server/0548-Add-PaperRegistry.patch +++ b/patches/server/0548-Add-PaperRegistry.patch @@ -205,10 +205,10 @@ index 04137173ca7034b9dff37a68518e8b6fb0330188..9b1bde95e8303e5d4adfe92f09240df8 // Paper start if (Thread.currentThread() != this.serverThread) { diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 4b7afdfea75e1023f68c1f9dbaf2db23010a0c30..c375ad0211ea5f3a1a80944a920d4e394b06f7f6 100644 +index 1caee283ae73943f936eddd822fbe64dc7815fdf..611cf30d17e110ff7b38219053919b52a86dfb19 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -515,6 +515,11 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -516,6 +516,11 @@ public final class CraftMagicNumbers implements UnsafeValues { public int nextEntityId() { return net.minecraft.world.entity.Entity.nextEntityId(); } diff --git a/patches/server/0549-Add-StructuresLocateEvent.patch b/patches/server/0549-Add-StructuresLocateEvent.patch index 5ce8fd2458..92bb68348d 100644 --- a/patches/server/0549-Add-StructuresLocateEvent.patch +++ b/patches/server/0549-Add-StructuresLocateEvent.patch @@ -106,10 +106,10 @@ index b6df6077107759963ee8205dddb90501d5ccb4d6..29032374f0e71a41a2de260d402b6fbf Map>> map = new Object2ObjectArrayMap(); Iterator iterator = structures.iterator(); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6c2ea3e0cf385d6893faf5430b29dbe2589786b0..c05dab188b35a138ce230b92d366083e1ffca604 100644 +index fed01c7ed32a0207216fd902976902b223cc3518..5b48102ad1c9940a5f41ba8084be0804b7536d30 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -317,6 +317,7 @@ public final class CraftServer implements Server { +@@ -318,6 +318,7 @@ public final class CraftServer implements Server { this.structureManager = new CraftStructureManager(console.getStructureManager()); Bukkit.setServer(this); diff --git a/patches/server/0583-Expand-world-key-API.patch b/patches/server/0583-Expand-world-key-API.patch index 9d0cf785a4..4a5675fda5 100644 --- a/patches/server/0583-Expand-world-key-API.patch +++ b/patches/server/0583-Expand-world-key-API.patch @@ -20,10 +20,10 @@ index 3e4ac4020c9f51e634eadd43243d34267bea4b22..ce52ae980309ecddf597e14b759b77ea // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3baf5c5af9a784a0a5b0d67313d4d88aaadc6cfb..b53c2a7f3413c572c4a6d16bd4da225e75ee06ca 100644 +index 5b48102ad1c9940a5f41ba8084be0804b7536d30..8592f56bdaaabc3c263c3ce6cf122c13a6b9f2de 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1158,9 +1158,15 @@ public final class CraftServer implements Server { +@@ -1139,9 +1139,15 @@ public final class CraftServer implements Server { File folder = new File(this.getWorldContainer(), name); World world = this.getWorld(name); @@ -41,7 +41,7 @@ index 3baf5c5af9a784a0a5b0d67313d4d88aaadc6cfb..b53c2a7f3413c572c4a6d16bd4da225e if ((folder.exists()) && (!folder.isDirectory())) { throw new IllegalArgumentException("File exists with the name '" + name + "' and isn't a folder"); -@@ -1249,7 +1255,7 @@ public final class CraftServer implements Server { +@@ -1230,7 +1236,7 @@ public final class CraftServer implements Server { } else if (name.equals(levelName + "_the_end")) { worldKey = net.minecraft.world.level.Level.END; } else { @@ -50,7 +50,7 @@ index 3baf5c5af9a784a0a5b0d67313d4d88aaadc6cfb..b53c2a7f3413c572c4a6d16bd4da225e } ServerLevel internal = (ServerLevel) new ServerLevel(this.console, console.executor, worldSession, worlddata, worldKey, worlddimension, this.getServer().progressListenerFactory.create(11), -@@ -1341,6 +1347,15 @@ public final class CraftServer implements Server { +@@ -1322,6 +1328,15 @@ public final class CraftServer implements Server { return null; } @@ -67,10 +67,10 @@ index 3baf5c5af9a784a0a5b0d67313d4d88aaadc6cfb..b53c2a7f3413c572c4a6d16bd4da225e // Check if a World already exists with the UID. if (this.getWorld(world.getUID()) != null) { diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index c375ad0211ea5f3a1a80944a920d4e394b06f7f6..abb860bb13774c93f2e87d81b0665225672cda5d 100644 +index 611cf30d17e110ff7b38219053919b52a86dfb19..73334710407574124ad289bbd3379dccb3417755 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -520,6 +520,11 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -521,6 +521,11 @@ public final class CraftMagicNumbers implements UnsafeValues { public Registry registryFor(Class classOfT) { return io.papermc.paper.registry.PaperRegistry.getRegistry(classOfT); } diff --git a/patches/server/0585-Item-Rarity-API.patch b/patches/server/0585-Item-Rarity-API.patch index 968bfaf360..fe64a97d4d 100644 --- a/patches/server/0585-Item-Rarity-API.patch +++ b/patches/server/0585-Item-Rarity-API.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Item Rarity API public net.minecraft.world.item.Item rarity diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index abb860bb13774c93f2e87d81b0665225672cda5d..d0d851dff3a42939ca4591fdf7e7afcdc728ff13 100644 +index 73334710407574124ad289bbd3379dccb3417755..f8bf5b0770e1e6b54d50e8063208083ea0b953a9 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -525,6 +525,20 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -526,6 +526,20 @@ public final class CraftMagicNumbers implements UnsafeValues { public String getMainLevelName() { return ((net.minecraft.server.dedicated.DedicatedServer) net.minecraft.server.MinecraftServer.getServer()).getProperties().levelName; } diff --git a/patches/server/0591-Expose-protocol-version.patch b/patches/server/0591-Expose-protocol-version.patch index 6c0b4f54e4..627aa92478 100644 --- a/patches/server/0591-Expose-protocol-version.patch +++ b/patches/server/0591-Expose-protocol-version.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose protocol version diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index d0d851dff3a42939ca4591fdf7e7afcdc728ff13..a61f42ddf4bcd00294a1aa050c9dc50d67379c44 100644 +index f8bf5b0770e1e6b54d50e8063208083ea0b953a9..21648628856e425dd68d44bd81ac17ce4b4bff47 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -539,6 +539,11 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -540,6 +540,11 @@ public final class CraftMagicNumbers implements UnsafeValues { public io.papermc.paper.inventory.ItemRarity getItemStackRarity(org.bukkit.inventory.ItemStack itemStack) { return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; } diff --git a/patches/server/0617-Add-basic-Datapack-API.patch b/patches/server/0617-Add-basic-Datapack-API.patch index 9280d2e7d3..ef076cd5b5 100644 --- a/patches/server/0617-Add-basic-Datapack-API.patch +++ b/patches/server/0617-Add-basic-Datapack-API.patch @@ -92,10 +92,10 @@ index 0000000000000000000000000000000000000000..cf4374493c11057451a62a655514415c + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index b53c2a7f3413c572c4a6d16bd4da225e75ee06ca..c2128d14a49a698100a64ab72be5e566669a1d8d 100644 +index 8592f56bdaaabc3c263c3ce6cf122c13a6b9f2de..86dda69e39f08de98faba44f4ee7725665f8df68 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -295,6 +295,7 @@ public final class CraftServer implements Server { +@@ -296,6 +296,7 @@ public final class CraftServer implements Server { public boolean ignoreVanillaPermissions = false; private final List playerView; public int reloadCount; @@ -103,7 +103,7 @@ index b53c2a7f3413c572c4a6d16bd4da225e75ee06ca..c2128d14a49a698100a64ab72be5e566 public static Exception excessiveVelEx; // Paper - Velocity warnings static { -@@ -382,6 +383,7 @@ public final class CraftServer implements Server { +@@ -383,6 +384,7 @@ public final class CraftServer implements Server { if (this.configuration.getBoolean("settings.use-map-color-cache")) { MapPalette.setMapColorCache(new CraftMapColorCache(this.logger)); } @@ -111,7 +111,7 @@ index b53c2a7f3413c572c4a6d16bd4da225e75ee06ca..c2128d14a49a698100a64ab72be5e566 } public boolean getCommandBlockOverride(String command) { -@@ -2799,5 +2801,11 @@ public final class CraftServer implements Server { +@@ -2780,5 +2782,11 @@ public final class CraftServer implements Server { public com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { return mobGoals; } diff --git a/patches/server/0618-Add-environment-variable-to-disable-server-gui.patch b/patches/server/0618-Add-environment-variable-to-disable-server-gui.patch index 7606f71f2d..35291abf67 100644 --- a/patches/server/0618-Add-environment-variable-to-disable-server-gui.patch +++ b/patches/server/0618-Add-environment-variable-to-disable-server-gui.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add environment variable to disable server gui diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 727efbe152dccabf130a6871e3d2582a5a733016..2dba2853764ca1cff114d3130672fbd596604ea3 100644 +index 7989b5bf002ba0995c32fb77498c7f50b34e6150..814a4823ab55d09172b2b699d303ced8bec21b47 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -281,6 +281,7 @@ public class Main { +@@ -292,6 +292,7 @@ public class Main { */ boolean flag1 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui"); diff --git a/patches/server/0620-ItemStack-repair-check-API.patch b/patches/server/0620-ItemStack-repair-check-API.patch index de9e083c3a..51ef504b30 100644 --- a/patches/server/0620-ItemStack-repair-check-API.patch +++ b/patches/server/0620-ItemStack-repair-check-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] ItemStack repair check API diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index a61f42ddf4bcd00294a1aa050c9dc50d67379c44..7aaa292f6495a9431687617251cae726675f063a 100644 +index 21648628856e425dd68d44bd81ac17ce4b4bff47..12ad9ccac400159af9b6597811fec7d362be5906 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -540,6 +540,14 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -541,6 +541,14 @@ public final class CraftMagicNumbers implements UnsafeValues { return io.papermc.paper.inventory.ItemRarity.values()[getItem(itemStack.getType()).getRarity(CraftItemStack.asNMSCopy(itemStack)).ordinal()]; } diff --git a/patches/server/0623-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0623-Fix-and-optimise-world-force-upgrading.patch index 9b9f2c4c19..680ecdfbe2 100644 --- a/patches/server/0623-Fix-and-optimise-world-force-upgrading.patch +++ b/patches/server/0623-Fix-and-optimise-world-force-upgrading.patch @@ -247,7 +247,7 @@ index 0000000000000000000000000000000000000000..95cac7edae8ac64811fc6a2f6b97dd4a + } +} diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 2dba2853764ca1cff114d3130672fbd596604ea3..6a5698f05a5f839e643e747c21834aacb90feec8 100644 +index 814a4823ab55d09172b2b699d303ced8bec21b47..c98a67de81439f6e5f8e2eedc7b9d8e3ddc5dc5b 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java @@ -15,6 +15,7 @@ import java.nio.file.Paths; @@ -258,7 +258,7 @@ index 2dba2853764ca1cff114d3130672fbd596604ea3..6a5698f05a5f839e643e747c21834aac import joptsimple.NonOptionArgumentSpec; import joptsimple.OptionParser; import joptsimple.OptionSet; -@@ -329,6 +330,15 @@ public class Main { +@@ -340,6 +341,15 @@ public class Main { return new WorldLoader.InitConfig(worldloader_d, Commands.CommandSelection.DEDICATED, serverPropertiesHandler.functionPermissionLevel); } @@ -359,10 +359,10 @@ index b294ef87fb93e7f4651dc04128124f297575860d..65fd57609e45ccd49ebfc1ba80d25243 return this.regionCache.getAndMoveToFirst(ChunkPos.asLong(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c2128d14a49a698100a64ab72be5e566669a1d8d..ad48a589c1e71eed171f9b71fda11f7512f08e3f 100644 +index 86dda69e39f08de98faba44f4ee7725665f8df68..a24769e0be5c0d67b6a6b8441570e20a622e5cbd 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1234,12 +1234,7 @@ public final class CraftServer implements Server { +@@ -1215,12 +1215,7 @@ public final class CraftServer implements Server { worlddata.customDimensions = iregistry; worlddata.checkName(name); worlddata.setModdedInfo(this.console.getServerModName(), this.console.getModdedStatus().shouldReportAsModified()); @@ -376,7 +376,7 @@ index c2128d14a49a698100a64ab72be5e566669a1d8d..ad48a589c1e71eed171f9b71fda11f75 long j = BiomeManager.obfuscateSeed(creator.seed()); List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata)); -@@ -1250,6 +1245,13 @@ public final class CraftServer implements Server { +@@ -1231,6 +1226,13 @@ public final class CraftServer implements Server { biomeProvider = generator.getDefaultBiomeProvider(worldInfo); } diff --git a/patches/server/0627-Attributes-API-for-item-defaults.patch b/patches/server/0627-Attributes-API-for-item-defaults.patch index 0cd0c44b09..bd9c621984 100644 --- a/patches/server/0627-Attributes-API-for-item-defaults.patch +++ b/patches/server/0627-Attributes-API-for-item-defaults.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Attributes API for item defaults diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 7aaa292f6495a9431687617251cae726675f063a..9a5ac0794cca60b6457e15caf797c506719877a3 100644 +index 12ad9ccac400159af9b6597811fec7d362be5906..6c39b620e9909759ab37d659c93e426c9f33ba95 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -548,6 +548,19 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -549,6 +549,19 @@ public final class CraftMagicNumbers implements UnsafeValues { return CraftMagicNumbers.getItem(itemToBeRepaired.getType()).isValidRepairItem(CraftItemStack.asNMSCopy(itemToBeRepaired), CraftItemStack.asNMSCopy(repairMaterial)); } diff --git a/patches/server/0649-Fix-return-value-of-Block-applyBoneMeal-always-being.patch b/patches/server/0649-Fix-return-value-of-Block-applyBoneMeal-always-being.patch index e88c33e4f7..3a42add191 100644 --- a/patches/server/0649-Fix-return-value-of-Block-applyBoneMeal-always-being.patch +++ b/patches/server/0649-Fix-return-value-of-Block-applyBoneMeal-always-being.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Fix return value of Block#applyBoneMeal always being false diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index 974ab329f92f488aba0999cef25e3b8e7e062209..60aa47a78b9d5921dffd1e205c0b69f453a94851 100644 +index e8d96c1e5dde67436fba1bfc6585c3e4a5c1a63c..4cfefcd6dc1ccdc9ecc52c9965fef5a3e339f862 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -583,7 +583,7 @@ public class CraftBlock implements Block { diff --git a/patches/server/0661-Add-System.out-err-catcher.patch b/patches/server/0661-Add-System.out-err-catcher.patch index 91abcbaf67..ddb6ea8472 100644 --- a/patches/server/0661-Add-System.out-err-catcher.patch +++ b/patches/server/0661-Add-System.out-err-catcher.patch @@ -105,10 +105,10 @@ index 0000000000000000000000000000000000000000..76d0d00cd6742991e3f3ec827a75ee87 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e8f7b418b942a6a36e615dbcaf9bb18257c34ee4..caa9885dd942fc5b82ba6b820d89f1b1a7ffda20 100644 +index a24769e0be5c0d67b6a6b8441570e20a622e5cbd..6707c96293e3c734628cbb017ddcf098641d69c2 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -297,6 +297,7 @@ public final class CraftServer implements Server { +@@ -298,6 +298,7 @@ public final class CraftServer implements Server { public int reloadCount; private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper public static Exception excessiveVelEx; // Paper - Velocity warnings diff --git a/patches/server/0684-Get-entity-default-attributes.patch b/patches/server/0684-Get-entity-default-attributes.patch index 90242f825b..564fc23423 100644 --- a/patches/server/0684-Get-entity-default-attributes.patch +++ b/patches/server/0684-Get-entity-default-attributes.patch @@ -81,10 +81,10 @@ index 0000000000000000000000000000000000000000..cf9d28ea97d93cec05c9fb768d59e283 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 9a5ac0794cca60b6457e15caf797c506719877a3..690d2ddff8b0cb31d35f2c3b4a26b6e92ce686da 100644 +index 6c39b620e9909759ab37d659c93e426c9f33ba95..72ce08862419ce5b6da6decb39d8c36adc1eaaf0 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -565,6 +565,18 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -566,6 +566,18 @@ public final class CraftMagicNumbers implements UnsafeValues { public int getProtocolVersion() { return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); } diff --git a/patches/server/0690-Add-isCollidable-methods-to-various-places.patch b/patches/server/0690-Add-isCollidable-methods-to-various-places.patch index 3ec2e6e213..57cf599be2 100644 --- a/patches/server/0690-Add-isCollidable-methods-to-various-places.patch +++ b/patches/server/0690-Add-isCollidable-methods-to-various-places.patch @@ -39,10 +39,10 @@ index 7b9e943b391c061782fccd2b8d705ceec8db50fe..966ac60daebb7bb211ab8096fc0c5f33 + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 690d2ddff8b0cb31d35f2c3b4a26b6e92ce686da..594828d3d395899bbb2c05e34911ad763393461a 100644 +index 72ce08862419ce5b6da6decb39d8c36adc1eaaf0..dea05265776f2b57115f36e8a31ed7720cce2cd0 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -577,6 +577,12 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -578,6 +578,12 @@ public final class CraftMagicNumbers implements UnsafeValues { var supplier = net.minecraft.world.entity.ai.attributes.DefaultAttributes.getSupplier((net.minecraft.world.entity.EntityType) net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.get(CraftNamespacedKey.toMinecraft(bukkitEntityKey))); return new io.papermc.paper.attribute.UnmodifiableAttributeMap(supplier); } diff --git a/patches/server/0693-Add-Raw-Byte-Entity-Serialization.patch b/patches/server/0693-Add-Raw-Byte-Entity-Serialization.patch index 26892ff6c7..2b5211da2b 100644 --- a/patches/server/0693-Add-Raw-Byte-Entity-Serialization.patch +++ b/patches/server/0693-Add-Raw-Byte-Entity-Serialization.patch @@ -45,10 +45,10 @@ index f1ee89047e8cd916c762b91162842e3f981856b3..726a4ae7ab928eda3ae1c1e98f342157 // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 594828d3d395899bbb2c05e34911ad763393461a..34e4d36024900ae174170c0a0f18b8dda8dd52f2 100644 +index dea05265776f2b57115f36e8a31ed7720cce2cd0..109f36e8892cc2e50d88054459321007ea00cf93 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -483,6 +483,29 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -484,6 +484,29 @@ public final class CraftMagicNumbers implements UnsafeValues { return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ITEM_STACK, compound, dataVersion, getDataVersion()))); } diff --git a/patches/server/0694-Vanilla-command-permission-fixes.patch b/patches/server/0694-Vanilla-command-permission-fixes.patch index ef390eac9c..cdd41b284c 100644 --- a/patches/server/0694-Vanilla-command-permission-fixes.patch +++ b/patches/server/0694-Vanilla-command-permission-fixes.patch @@ -33,7 +33,7 @@ index 899008b2980d13f1be6280cd8cb959c53a29bebf..f875507241ac6769545e91cd3285232b private RedirectModifier modifier = null; private boolean forks; diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java -index 4cf954f54c55bb4d7063b8fcdf147c19ff4634d8..e365cc65383d7a9d7abd5a90144a18dca8a00300 100644 +index 7ebe1c200c26c66b293b245d7f470bf4f81f3eea..f2b312367895f121bcf4135c12dfdb354f32dddb 100644 --- a/src/main/java/net/minecraft/commands/Commands.java +++ b/src/main/java/net/minecraft/commands/Commands.java @@ -223,6 +223,13 @@ public class Commands { diff --git a/patches/server/0698-Add-paper-mobcaps-and-paper-playermobcaps.patch b/patches/server/0698-Add-paper-mobcaps-and-paper-playermobcaps.patch index 6aa2e785be..d01b4444b0 100644 --- a/patches/server/0698-Add-paper-mobcaps-and-paper-playermobcaps.patch +++ b/patches/server/0698-Add-paper-mobcaps-and-paper-playermobcaps.patch @@ -10,7 +10,7 @@ Also has a hover text on each mob category listing what entity types are in said category diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java -index a7b78508ef78229835805300e62a306a3f1ddf6d..724592234e2a178a518f6ab7d09c3180780371a7 100644 +index 312c0e42643355183ea3346a69fe9b5a5624bf1d..5c0b02f1ca8f6594f8f94613edba2783087950f2 100644 --- a/src/main/java/io/papermc/paper/command/PaperCommand.java +++ b/src/main/java/io/papermc/paper/command/PaperCommand.java @@ -5,6 +5,7 @@ import io.papermc.paper.command.subcommands.DumpItemCommand; @@ -21,7 +21,7 @@ index a7b78508ef78229835805300e62a306a3f1ddf6d..724592234e2a178a518f6ab7d09c3180 import io.papermc.paper.command.subcommands.ReloadCommand; import io.papermc.paper.command.subcommands.SyncLoadInfoCommand; import io.papermc.paper.command.subcommands.VersionCommand; -@@ -48,6 +49,7 @@ public final class PaperCommand extends Command { +@@ -50,6 +51,7 @@ public final class PaperCommand extends Command { commands.put(Set.of("debug", "chunkinfo", "holderinfo"), new ChunkDebugCommand()); commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand()); commands.put(Set.of("dumpitem"), new DumpItemCommand()); @@ -286,10 +286,10 @@ index bf3fb416d36a19958033cdbf5cc313556fa0201b..0a49769bfa83d0b9c435e3ab4bba8597 // Paper start - add parameters and int ret type spawnCategoryForChunk(group, world, chunk, checker, runner, Integer.MAX_VALUE, null); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e2ce58158a31d5c61961d9c78d3709377e29b42c..1f1178410dba7846a16e9948c184dde10a93a4d7 100644 +index 6707c96293e3c734628cbb017ddcf098641d69c2..ed7c94b31db6f759c5e24bee01ba6d5df266a126 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2185,6 +2185,11 @@ public final class CraftServer implements Server { +@@ -2166,6 +2166,11 @@ public final class CraftServer implements Server { @Override public int getSpawnLimit(SpawnCategory spawnCategory) { diff --git a/patches/server/0759-Allow-delegation-to-vanilla-chunk-gen.patch b/patches/server/0759-Allow-delegation-to-vanilla-chunk-gen.patch index ef435f17da..41f75dfd1f 100644 --- a/patches/server/0759-Allow-delegation-to-vanilla-chunk-gen.patch +++ b/patches/server/0759-Allow-delegation-to-vanilla-chunk-gen.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow delegation to vanilla chunk gen diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 1f1178410dba7846a16e9948c184dde10a93a4d7..8c980c12a4f132a712a0f22fc3585c83182363dc 100644 +index ed7c94b31db6f759c5e24bee01ba6d5df266a126..a47deed87d662e39981abfa03eed23785f4862ff 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2358,6 +2358,90 @@ public final class CraftServer implements Server { +@@ -2339,6 +2339,90 @@ public final class CraftServer implements Server { return new OldCraftChunkData(world.getMinHeight(), world.getMaxHeight(), handle.registryAccess().registryOrThrow(Registries.BIOME), world); // Paper - Anti-Xray - Add parameters } diff --git a/patches/server/0779-Expose-vanilla-BiomeProvider-from-WorldInfo.patch b/patches/server/0779-Expose-vanilla-BiomeProvider-from-WorldInfo.patch index 66489329f2..0dfbdd9499 100644 --- a/patches/server/0779-Expose-vanilla-BiomeProvider-from-WorldInfo.patch +++ b/patches/server/0779-Expose-vanilla-BiomeProvider-from-WorldInfo.patch @@ -18,10 +18,10 @@ index 0868805c78d991c602d8f1d1b5aeb5c790c13384..6986d5475b090bca60b5ae892512fd5e biomeProvider = gen.getDefaultBiomeProvider(worldInfo); } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 8c980c12a4f132a712a0f22fc3585c83182363dc..ef4cc3e55061d71f64ad16b62efcf7b2af99006a 100644 +index a47deed87d662e39981abfa03eed23785f4862ff..aa3387361b9f5b73ed5ecfb12b826f8a17d2623a 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1241,7 +1241,7 @@ public final class CraftServer implements Server { +@@ -1222,7 +1222,7 @@ public final class CraftServer implements Server { List list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata)); LevelStem worlddimension = iregistry.get(actualDimension); diff --git a/patches/server/0794-API-for-creating-command-sender-which-forwards-feedb.patch b/patches/server/0794-API-for-creating-command-sender-which-forwards-feedb.patch index b0e1d7aac3..a35004a1c8 100644 --- a/patches/server/0794-API-for-creating-command-sender-which-forwards-feedb.patch +++ b/patches/server/0794-API-for-creating-command-sender-which-forwards-feedb.patch @@ -122,10 +122,10 @@ index 0000000000000000000000000000000000000000..e3a5f1ec376319bdfda87fa27ae217bf + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index ef4cc3e55061d71f64ad16b62efcf7b2af99006a..87d7ea9b248253f7c9071857578bf4576760a472 100644 +index aa3387361b9f5b73ed5ecfb12b826f8a17d2623a..944f9dec587ed17c737846362f63e947a99bc173 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2019,6 +2019,13 @@ public final class CraftServer implements Server { +@@ -2000,6 +2000,13 @@ public final class CraftServer implements Server { return console.console; } diff --git a/patches/server/0798-Add-missing-Validate-calls-to-CraftServer-getSpawnLi.patch b/patches/server/0798-Add-missing-Validate-calls-to-CraftServer-getSpawnLi.patch index 459d47f878..c05f61b9a8 100644 --- a/patches/server/0798-Add-missing-Validate-calls-to-CraftServer-getSpawnLi.patch +++ b/patches/server/0798-Add-missing-Validate-calls-to-CraftServer-getSpawnLi.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add missing Validate calls to CraftServer#getSpawnLimit Copies appropriate checks from CraftWorld#getSpawnLimit diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 87d7ea9b248253f7c9071857578bf4576760a472..1dc72eac8a6f2f22e497117fff91e585e93b73ea 100644 +index 944f9dec587ed17c737846362f63e947a99bc173..bbeab1eac527d06f867fb6a67c30e93be6642f8b 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2193,6 +2193,8 @@ public final class CraftServer implements Server { +@@ -2174,6 +2174,8 @@ public final class CraftServer implements Server { @Override public int getSpawnLimit(SpawnCategory spawnCategory) { // Paper start diff --git a/patches/server/0799-Add-GameEvent-tags.patch b/patches/server/0799-Add-GameEvent-tags.patch index 2536a6b6fe..3a96665b2b 100644 --- a/patches/server/0799-Add-GameEvent-tags.patch +++ b/patches/server/0799-Add-GameEvent-tags.patch @@ -46,10 +46,10 @@ index 0000000000000000000000000000000000000000..e7d9fd2702a1ce96596580fff8f5ee4f + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 1dc72eac8a6f2f22e497117fff91e585e93b73ea..54cc314a328568fd4fcf007e0476d0fd12f2eb6a 100644 +index bbeab1eac527d06f867fb6a67c30e93be6642f8b..782a0ed5b128912257571a527e9ba5e77204896e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -2604,6 +2604,15 @@ public final class CraftServer implements Server { +@@ -2585,6 +2585,15 @@ public final class CraftServer implements Server { return (org.bukkit.Tag) new CraftEntityTag(BuiltInRegistries.ENTITY_TYPE, entityTagKey); } } @@ -65,7 +65,7 @@ index 1dc72eac8a6f2f22e497117fff91e585e93b73ea..54cc314a328568fd4fcf007e0476d0fd default -> throw new IllegalArgumentException(); } -@@ -2636,6 +2645,13 @@ public final class CraftServer implements Server { +@@ -2617,6 +2626,13 @@ public final class CraftServer implements Server { net.minecraft.core.Registry> entityTags = BuiltInRegistries.ENTITY_TYPE; return entityTags.getTags().map(pair -> (org.bukkit.Tag) new CraftEntityTag(entityTags, pair.getFirst())).collect(ImmutableList.toImmutableList()); } diff --git a/patches/server/0805-Put-world-into-worldlist-before-initing-the-world.patch b/patches/server/0805-Put-world-into-worldlist-before-initing-the-world.patch index e2531c46f5..c27ddabb68 100644 --- a/patches/server/0805-Put-world-into-worldlist-before-initing-the-world.patch +++ b/patches/server/0805-Put-world-into-worldlist-before-initing-the-world.patch @@ -23,10 +23,10 @@ index d2409599c9d9765a2e1dc7418339923049abc416..f42d7d9e11542370489fcc8dc42ea6ec if (worlddata.getCustomBossEvents() != null) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 54cc314a328568fd4fcf007e0476d0fd12f2eb6a..f13a5f6d3a5a72d089545df4f52b2302adcd601f 100644 +index 782a0ed5b128912257571a527e9ba5e77204896e..e1cb7ae143b1d85cbea494e4694d34f0e954f64e 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1270,10 +1270,11 @@ public final class CraftServer implements Server { +@@ -1251,10 +1251,11 @@ public final class CraftServer implements Server { return null; } diff --git a/patches/server/0807-Custom-Potion-Mixes.patch b/patches/server/0807-Custom-Potion-Mixes.patch index 1aa6ab6ef4..2f01d4cdfb 100644 --- a/patches/server/0807-Custom-Potion-Mixes.patch +++ b/patches/server/0807-Custom-Potion-Mixes.patch @@ -164,10 +164,10 @@ index cf2b6487a640a7a613f3b3604ca7b1063b3ff102..0bab2693b91d5bab222c7db8bc6965cc @Override diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index f13a5f6d3a5a72d089545df4f52b2302adcd601f..6974554791c01df7af2b5cda5c18bb6d66da629b 100644 +index e1cb7ae143b1d85cbea494e4694d34f0e954f64e..7936ff9da40a6938268b7020ba751e3724eb1d72 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -298,6 +298,7 @@ public final class CraftServer implements Server { +@@ -299,6 +299,7 @@ public final class CraftServer implements Server { private final io.papermc.paper.datapack.PaperDatapackManager datapackManager; // Paper public static Exception excessiveVelEx; // Paper - Velocity warnings private final io.papermc.paper.logging.SysoutCatcher sysoutCatcher = new io.papermc.paper.logging.SysoutCatcher(); // Paper @@ -175,7 +175,7 @@ index f13a5f6d3a5a72d089545df4f52b2302adcd601f..6974554791c01df7af2b5cda5c18bb6d static { ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); -@@ -325,7 +326,7 @@ public final class CraftServer implements Server { +@@ -326,7 +327,7 @@ public final class CraftServer implements Server { Enchantments.SHARPNESS.getClass(); org.bukkit.enchantments.Enchantment.stopAcceptingRegistrations(); @@ -184,7 +184,7 @@ index f13a5f6d3a5a72d089545df4f52b2302adcd601f..6974554791c01df7af2b5cda5c18bb6d MobEffects.BLINDNESS.getClass(); PotionEffectType.stopAcceptingRegistrations(); // Ugly hack :( -@@ -2925,5 +2926,10 @@ public final class CraftServer implements Server { +@@ -2906,5 +2907,10 @@ public final class CraftServer implements Server { return datapackManager; } diff --git a/patches/server/0818-Fix-saving-in-unloadWorld.patch b/patches/server/0818-Fix-saving-in-unloadWorld.patch index 86058e73eb..30ca37fabf 100644 --- a/patches/server/0818-Fix-saving-in-unloadWorld.patch +++ b/patches/server/0818-Fix-saving-in-unloadWorld.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Fix saving in unloadWorld Change savingDisabled to false to ensure ServerLevel's saving logic gets called when unloadWorld is called with save = true diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 6974554791c01df7af2b5cda5c18bb6d66da629b..bbf2a8a15acc6b8ca7e0fb83246af83e3b2ae934 100644 +index 7936ff9da40a6938268b7020ba751e3724eb1d72..0d8a8a49368401e0c801ee63d99c6910467507b9 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1318,7 +1318,7 @@ public final class CraftServer implements Server { +@@ -1299,7 +1299,7 @@ public final class CraftServer implements Server { try { if (save) { diff --git a/patches/server/0834-WorldCreator-keepSpawnLoaded.patch b/patches/server/0834-WorldCreator-keepSpawnLoaded.patch index 42ccc13388..ffb6800d6c 100644 --- a/patches/server/0834-WorldCreator-keepSpawnLoaded.patch +++ b/patches/server/0834-WorldCreator-keepSpawnLoaded.patch @@ -5,10 +5,10 @@ Subject: [PATCH] WorldCreator#keepSpawnLoaded diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index bbf2a8a15acc6b8ca7e0fb83246af83e3b2ae934..1198b15878550fbb616093e2fd77bd27398e7dcb 100644 +index 0d8a8a49368401e0c801ee63d99c6910467507b9..be087ee023fc124c676fb83f3d0796b2da3b8bc0 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1277,6 +1277,7 @@ public final class CraftServer implements Server { +@@ -1258,6 +1258,7 @@ public final class CraftServer implements Server { internal.setSpawnSettings(true, true); // Paper - move up diff --git a/patches/server/0850-Throw-exception-on-world-create-while-being-ticked.patch b/patches/server/0850-Throw-exception-on-world-create-while-being-ticked.patch index e982452cb8..ce1deb01dd 100644 --- a/patches/server/0850-Throw-exception-on-world-create-while-being-ticked.patch +++ b/patches/server/0850-Throw-exception-on-world-create-while-being-ticked.patch @@ -45,10 +45,10 @@ index a8b3f0e8be414c4ea92cc85c9811ecd42e5ce9c1..0e04083ff0598451c66731b1518b2eb6 this.profiler.popPush("connection"); MinecraftTimings.connectionTimer.startTiming(); // Spigot diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 1198b15878550fbb616093e2fd77bd27398e7dcb..55cfe795d84f8be32966cad41f8dd46064b2a52c 100644 +index be087ee023fc124c676fb83f3d0796b2da3b8bc0..3ce33ca4ce86a915be1cebb26de1eb3ef5d0d4fb 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -870,6 +870,11 @@ public final class CraftServer implements Server { +@@ -851,6 +851,11 @@ public final class CraftServer implements Server { return new ArrayList(this.worlds.values()); } @@ -60,7 +60,7 @@ index 1198b15878550fbb616093e2fd77bd27398e7dcb..55cfe795d84f8be32966cad41f8dd460 public DedicatedPlayerList getHandle() { return this.playerList; } -@@ -1154,6 +1159,7 @@ public final class CraftServer implements Server { +@@ -1135,6 +1140,7 @@ public final class CraftServer implements Server { @Override public World createWorld(WorldCreator creator) { Preconditions.checkState(this.console.getAllLevels().iterator().hasNext(), "Cannot create additional worlds on STARTUP"); @@ -68,7 +68,7 @@ index 1198b15878550fbb616093e2fd77bd27398e7dcb..55cfe795d84f8be32966cad41f8dd460 Validate.notNull(creator, "Creator may not be null"); String name = creator.name(); -@@ -1292,6 +1298,7 @@ public final class CraftServer implements Server { +@@ -1273,6 +1279,7 @@ public final class CraftServer implements Server { @Override public boolean unloadWorld(World world, boolean save) { diff --git a/patches/server/0857-Don-t-broadcast-messages-to-command-blocks.patch b/patches/server/0857-Don-t-broadcast-messages-to-command-blocks.patch index 0f4dba41b8..0fab6586b8 100644 --- a/patches/server/0857-Don-t-broadcast-messages-to-command-blocks.patch +++ b/patches/server/0857-Don-t-broadcast-messages-to-command-blocks.patch @@ -20,10 +20,10 @@ index 7c7e5f3c0f9cd1f16192a8fc8163da9b2d9519d5..888936385196a178ab8b730fd5e4fff4 Date date = new Date(); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 55cfe795d84f8be32966cad41f8dd46064b2a52c..c34343705ea409a0a0614845b7cf3bdda3dcb4ca 100644 +index 3ce33ca4ce86a915be1cebb26de1eb3ef5d0d4fb..9c97e31a00bf226c7298242a6e0d4c0b35a49817 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -1792,7 +1792,7 @@ public final class CraftServer implements Server { +@@ -1773,7 +1773,7 @@ public final class CraftServer implements Server { // Paper end Set recipients = new HashSet<>(); for (Permissible permissible : this.getPluginManager().getPermissionSubscriptions(permission)) { diff --git a/patches/server/0879-Add-Velocity-IP-Forwarding-Support.patch b/patches/server/0879-Add-Velocity-IP-Forwarding-Support.patch index 5c2e7c08d8..57ecf1f666 100644 --- a/patches/server/0879-Add-Velocity-IP-Forwarding-Support.patch +++ b/patches/server/0879-Add-Velocity-IP-Forwarding-Support.patch @@ -213,10 +213,10 @@ index 0bedd9eadbfe1ce290f22d6c648571e25e3ae0e9..093822a5256e8e919350a000239a3e92 } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index c34343705ea409a0a0614845b7cf3bdda3dcb4ca..f1a3d8dae2a61b875e423aebfdfcad2f77d498ff 100644 +index 9c97e31a00bf226c7298242a6e0d4c0b35a49817..621919a4a45caa73a43020fdca24764d95d89fd2 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -799,7 +799,7 @@ public final class CraftServer implements Server { +@@ -780,7 +780,7 @@ public final class CraftServer implements Server { @Override public long getConnectionThrottle() { // Spigot Start - Automatically set connection throttle for bungee configurations diff --git a/patches/server/0881-Add-NamespacedKey-biome-methods.patch b/patches/server/0881-Add-NamespacedKey-biome-methods.patch index 82abc8c239..60d181b0f7 100644 --- a/patches/server/0881-Add-NamespacedKey-biome-methods.patch +++ b/patches/server/0881-Add-NamespacedKey-biome-methods.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add NamespacedKey biome methods Co-authored-by: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 34e4d36024900ae174170c0a0f18b8dda8dd52f2..c51a7f7489a37093e4096b28bfc1031ba6a2b8c2 100644 +index 109f36e8892cc2e50d88054459321007ea00cf93..adde9b49bf043112765734716f01b0d29456e46c 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -606,6 +606,19 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -607,6 +607,19 @@ public final class CraftMagicNumbers implements UnsafeValues { Preconditions.checkArgument(material.isBlock(), material + " is not a block"); return getBlock(material).hasCollision; } diff --git a/patches/server/0908-Detect-headless-JREs.patch b/patches/server/0908-Detect-headless-JREs.patch index 547c655d70..e3c12df9b9 100644 --- a/patches/server/0908-Detect-headless-JREs.patch +++ b/patches/server/0908-Detect-headless-JREs.patch @@ -27,10 +27,10 @@ index 6bd0afddbcc461149dfe9a5c7a86fff6ea13a5f1..148d233f4f5278ff39eacdaa0f4f0e7d + } } diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 6a5698f05a5f839e643e747c21834aacb90feec8..31faf2d6492696f7d0c99a48edbc0d6f15db1209 100644 +index c98a67de81439f6e5f8e2eedc7b9d8e3ddc5dc5b..a821cb33fbc29109aec68f9d6a0eb2efc121ee13 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java -@@ -158,6 +158,18 @@ public class Main { +@@ -169,6 +169,18 @@ public class Main { return; } diff --git a/patches/server/0924-Add-paper-dumplisteners-command.patch b/patches/server/0924-Add-paper-dumplisteners-command.patch index c59dba6293..e3b37840de 100644 --- a/patches/server/0924-Add-paper-dumplisteners-command.patch +++ b/patches/server/0924-Add-paper-dumplisteners-command.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Add /paper dumplisteners command Co-authored-by: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com> diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java -index 724592234e2a178a518f6ab7d09c3180780371a7..92154550b41b2e1d03deb1271b71bb3baa735e0a 100644 +index 5c0b02f1ca8f6594f8f94613edba2783087950f2..f7a92aba7c8b98c44839fd6687dd9b96df893399 100644 --- a/src/main/java/io/papermc/paper/command/PaperCommand.java +++ b/src/main/java/io/papermc/paper/command/PaperCommand.java @@ -2,6 +2,7 @@ package io.papermc.paper.command; @@ -17,7 +17,7 @@ index 724592234e2a178a518f6ab7d09c3180780371a7..92154550b41b2e1d03deb1271b71bb3b import io.papermc.paper.command.subcommands.EntityCommand; import io.papermc.paper.command.subcommands.FixLightCommand; import io.papermc.paper.command.subcommands.HeapDumpCommand; -@@ -50,6 +51,7 @@ public final class PaperCommand extends Command { +@@ -52,6 +53,7 @@ public final class PaperCommand extends Command { commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand()); commands.put(Set.of("dumpitem"), new DumpItemCommand()); commands.put(Set.of("mobcaps", "playermobcaps"), new MobcapsCommand()); diff --git a/patches/server/0961-Temp-fix-for-EntityType.translationKey.patch b/patches/server/0961-Temp-fix-for-EntityType.translationKey.patch index 4ca8168950..3ecdceaee2 100644 --- a/patches/server/0961-Temp-fix-for-EntityType.translationKey.patch +++ b/patches/server/0961-Temp-fix-for-EntityType.translationKey.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Temp fix for EntityType.translationKey() diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index c51a7f7489a37093e4096b28bfc1031ba6a2b8c2..287e8c4c57ea1737460fdaf114e7eed627a25b2d 100644 +index 769efed4ce75231a5557e4723de5dc3121cedf3d..edc1a161cf509040fcaa12826743232f31d95bd7 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -440,7 +440,12 @@ public final class CraftMagicNumbers implements UnsafeValues { diff --git a/test-plugin/build.gradle.kts b/test-plugin/build.gradle.kts index 6bcdb356c5..e86b933408 100644 --- a/test-plugin/build.gradle.kts +++ b/test-plugin/build.gradle.kts @@ -13,7 +13,7 @@ tasks.processResources { "apiversion" to apiVersion, ) inputs.properties(props) - filesMatching("plugin.yml") { + filesMatching("paper-plugin.yml") { expand(props) } } diff --git a/test-plugin/src/main/java/io/papermc/paper/testplugin/TestPlugin.java b/test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java similarity index 88% rename from test-plugin/src/main/java/io/papermc/paper/testplugin/TestPlugin.java rename to test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java index a0c78b9d68..4e68423bb7 100644 --- a/test-plugin/src/main/java/io/papermc/paper/testplugin/TestPlugin.java +++ b/test-plugin/src/main/java/io/papermc/testplugin/TestPlugin.java @@ -1,9 +1,10 @@ -package io.papermc.paper.testplugin; +package io.papermc.testplugin; import org.bukkit.event.Listener; import org.bukkit.plugin.java.JavaPlugin; public final class TestPlugin extends JavaPlugin implements Listener { + @Override public void onEnable() { this.getServer().getPluginManager().registerEvents(this, this); diff --git a/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java b/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java new file mode 100644 index 0000000000..e464dac8ae --- /dev/null +++ b/test-plugin/src/main/java/io/papermc/testplugin/TestPluginBootstrap.java @@ -0,0 +1,13 @@ +package io.papermc.testplugin; + +import io.papermc.paper.plugin.bootstrap.PluginBootstrap; +import io.papermc.paper.plugin.bootstrap.PluginProviderContext; +import org.jetbrains.annotations.NotNull; + +public class TestPluginBootstrap implements PluginBootstrap { + + @Override + public void bootstrap(@NotNull PluginProviderContext context) { + } + +} diff --git a/test-plugin/src/main/java/io/papermc/testplugin/TestPluginLoader.java b/test-plugin/src/main/java/io/papermc/testplugin/TestPluginLoader.java new file mode 100644 index 0000000000..084899a9fe --- /dev/null +++ b/test-plugin/src/main/java/io/papermc/testplugin/TestPluginLoader.java @@ -0,0 +1,11 @@ +package io.papermc.testplugin; + +import io.papermc.paper.plugin.loader.PluginClasspathBuilder; +import io.papermc.paper.plugin.loader.PluginLoader; +import org.jetbrains.annotations.NotNull; + +public class TestPluginLoader implements PluginLoader { + @Override + public void classloader(@NotNull PluginClasspathBuilder classpathBuilder) { + } +} diff --git a/test-plugin/src/main/resources/paper-plugin.yml b/test-plugin/src/main/resources/paper-plugin.yml new file mode 100644 index 0000000000..459345d794 --- /dev/null +++ b/test-plugin/src/main/resources/paper-plugin.yml @@ -0,0 +1,12 @@ +name: Paper-Test-Plugin +version: ${version} +main: io.papermc.testplugin.TestPlugin +description: Paper Test Plugin +author: PaperMC +api-version: ${apiversion} +load: STARTUP +bootstrapper: io.papermc.testplugin.TestPluginBootstrap +loader: io.papermc.testplugin.TestPluginLoader +defaultPerm: FALSE +permissions: +dependencies: diff --git a/test-plugin/src/main/resources/plugin.yml b/test-plugin/src/main/resources/plugin.yml deleted file mode 100644 index 1e6adb9ff6..0000000000 --- a/test-plugin/src/main/resources/plugin.yml +++ /dev/null @@ -1,7 +0,0 @@ -name: Paper-Test-Plugin -version: ${version} -main: io.papermc.paper.testplugin.TestPlugin -description: Paper Test Plugin -author: PaperMC -api-version: ${apiversion} -load: STARTUP