diff --git a/patches/api/0008-Paper-Plugins.patch b/patches/api/0008-Paper-Plugins.patch index d73b50e2a..85424564d 100644 --- a/patches/api/0008-Paper-Plugins.patch +++ b/patches/api/0008-Paper-Plugins.patch @@ -1942,7 +1942,7 @@ index 669a70faa95d0d6525a731d73499ed6fb0b48320..6175b04327b12e74140a0885f7326546 /** 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 +index 047c0304fd617cec990f80815b43916c6ef5a94c..fa39c93d76ebb9eecce1f4b5203cb361e4778b4f 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; @@ -1966,7 +1966,7 @@ index 047c0304fd617cec990f80815b43916c6ef5a94c..d0ad072c832b8fc8a1cfdcafdd42c724 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 ++ loader = new PluginClassLoader(getClass().getClassLoader(), description, dataFolder, file, (libraryLoader != null) ? libraryLoader.createLoader(description) : null); // Paper } catch (InvalidPluginException ex) { throw ex; } catch (Throwable ex) { @@ -1987,7 +1987,7 @@ index 6d634b0ea813ccb19f1562a7d0e5a59cea4eab21..f9e67e20133d349e43d126dbb48b34d4 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..2c3d2f60d3f2f55a1a90791d37521c61f96ab4b3 100644 +index 2f74ec96ece706de23156ebabfe493211bc05391..f92071617712a0f410475fae291fb85f668e8e8a 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; @@ -2000,7 +2000,7 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61 private final JavaPluginLoader loader; private final Map> classes = new ConcurrentHashMap>(); private final PluginDescriptionFile description; -@@ -39,20 +40,23 @@ final class PluginClassLoader extends URLClassLoader { +@@ -39,20 +40,22 @@ final class PluginClassLoader extends URLClassLoader { private final Manifest manifest; private final URL url; private final ClassLoader libraryLoader; @@ -2011,7 +2011,6 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61 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(); @@ -2019,7 +2018,7 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61 - 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 ++ public PluginClassLoader(@Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader) 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 @@ -2028,19 +2027,18 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61 this.description = description; this.dataFolder = dataFolder; this.file = file; -@@ -61,6 +65,11 @@ final class PluginClassLoader extends URLClassLoader { +@@ -61,6 +64,10 @@ 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 { +@@ -94,6 +101,22 @@ final class PluginClassLoader extends URLClassLoader { return findResources(name); } @@ -2063,7 +2061,7 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61 @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 { +@@ -119,26 +142,11 @@ final class PluginClassLoader extends URLClassLoader { if (checkGlobal) { // This ignores the libraries of other plugins, unless they are transitive dependencies. @@ -2072,24 +2070,27 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61 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,14 +153,14 @@ final class PluginClassLoader extends URLClassLoader { - - if (provider != description - && !seenIllegalAccess.contains(provider.getName()) +- if (result.getClassLoader() instanceof PluginClassLoader) { +- PluginDescriptionFile provider = ((PluginClassLoader) result.getClassLoader()).description; +- +- 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) { - plugin.getLogger().log(Level.WARNING, "Loaded class {0} from {1} which is not a depend or softdepend of this plugin.", new Object[]{name, provider.getFullName()}); - } else { - // In case the bad access occurs on construction +- +- seenIllegalAccess.add(provider.getName()); +- if (plugin != null) { +- plugin.getLogger().log(Level.WARNING, "Loaded class {0} from {1} which is not a depend or softdepend of this plugin.", new Object[]{name, provider.getFullName()}); +- } else { +- // 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()}); -+ org.bukkit.Bukkit.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()}); // Paper - } - } - } -@@ -167,7 +192,7 @@ final class PluginClassLoader extends URLClassLoader { +- } +- } +- } ++ // Paper - Totally delete the illegal access logic, we are never going to enforce it anyways here. + + return result; + } +@@ -167,7 +175,7 @@ final class PluginClassLoader extends URLClassLoader { throw new ClassNotFoundException(name, ex); } @@ -2098,7 +2099,7 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61 int dot = name.lastIndexOf('.'); if (dot != -1) { -@@ -197,8 +222,8 @@ final class PluginClassLoader extends URLClassLoader { +@@ -197,8 +205,8 @@ final class PluginClassLoader extends URLClassLoader { result = super.findClass(name); } @@ -2108,7 +2109,7 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61 } return result; -@@ -207,6 +232,12 @@ final class PluginClassLoader extends URLClassLoader { +@@ -207,6 +215,12 @@ final class PluginClassLoader extends URLClassLoader { @Override public void close() throws IOException { try { @@ -2121,7 +2122,7 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61 super.close(); } finally { jar.close(); -@@ -218,7 +249,7 @@ final class PluginClassLoader extends URLClassLoader { +@@ -218,7 +232,7 @@ final class PluginClassLoader extends URLClassLoader { return classes.values(); } @@ -2130,7 +2131,7 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61 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 { +@@ -228,6 +242,32 @@ final class PluginClassLoader extends URLClassLoader { pluginState = new IllegalStateException("Initial initialization"); this.pluginInit = javaPlugin; diff --git a/patches/api/0072-Add-workaround-for-plugins-modifying-the-parent-of-t.patch b/patches/api/0072-Add-workaround-for-plugins-modifying-the-parent-of-t.patch index d35399c15..6337778a7 100644 --- a/patches/api/0072-Add-workaround-for-plugins-modifying-the-parent-of-t.patch +++ b/patches/api/0072-Add-workaround-for-plugins-modifying-the-parent-of-t.patch @@ -93,10 +93,10 @@ index 79df67daf2fe8193fd83dd6a7bfc78b3f6e524c2..0e4cedc005466c600ff6b9d500febf33 /** diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index c5f49ba2d0cc5cdf127670ea2be59f1b174dc94b..1c6542bb9ce13781c8f3b84330b5ef5aa52d0348 100644 +index 845b3f8a7dedf801d45489e807ab971dcfe2382e..666f182e5cf2f07a2cf6a17b0d28a100b3f0b891 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -66,7 +66,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm +@@ -65,7 +65,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm this.url = file.toURI().toURL(); this.libraryLoader = libraryLoader; @@ -104,8 +104,8 @@ index c5f49ba2d0cc5cdf127670ea2be59f1b174dc94b..1c6542bb9ce13781c8f3b84330b5ef5a + this.logger = com.destroystokyo.paper.utils.PaperPluginLogger.getLogger(description); // Paper - Register logger early // 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 + // Paper end +@@ -243,6 +243,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm pluginState = new IllegalStateException("Initial initialization"); this.pluginInit = javaPlugin; diff --git a/patches/api/0231-Enable-multi-release-plugin-jars.patch b/patches/api/0231-Enable-multi-release-plugin-jars.patch index cedc39b34..8be6660d2 100644 --- a/patches/api/0231-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 a657654079c40a0fee6f70c7d72df24b3827b911..ef60a8a7e20e27fee6f96fe1398ec9aee9352aec 100644 +index 666f182e5cf2f07a2cf6a17b0d28a100b3f0b891..14cdd833bb56186e7cb83e035348f4dc942e4740 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -61,7 +61,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm +@@ -60,7 +60,7 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm this.description = description; this.dataFolder = dataFolder; this.file = file; 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 index 69d7c509c..55a079368 100644 --- 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 @@ -5,13 +5,13 @@ 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 +index 14cdd833bb56186e7cb83e035348f4dc942e4740..9b4b81f70624cd3906c94cbab99aabe7f9a4223e 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 +@@ -54,7 +54,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 + public PluginClassLoader(@Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader) 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 diff --git a/patches/api/0382-Also-load-resources-from-LibraryLoader.patch b/patches/api/0382-Also-load-resources-from-LibraryLoader.patch index 8aa2155fc..c79c85a32 100644 --- a/patches/api/0382-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 87c90128ada98fcb31ff106333ffabb35972a107..4cb4e28c9b0dfdac45c4129fb0325e6afe5cb131 100644 +index 9b4b81f70624cd3906c94cbab99aabe7f9a4223e..4666d29d27e6247422a94e99511a190ce9484f76 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -96,14 +96,35 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm +@@ -94,14 +94,35 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm @Override public URL getResource(String name) { diff --git a/patches/api/0387-Add-getDrops-to-BlockState.patch b/patches/api/0386-Add-getDrops-to-BlockState.patch similarity index 100% rename from patches/api/0387-Add-getDrops-to-BlockState.patch rename to patches/api/0386-Add-getDrops-to-BlockState.patch diff --git a/patches/api/0386-Add-system-property-to-print-stacktrace-on-bad-plugi.patch b/patches/api/0386-Add-system-property-to-print-stacktrace-on-bad-plugi.patch deleted file mode 100644 index ab8010380..000000000 --- a/patches/api/0386-Add-system-property-to-print-stacktrace-on-bad-plugi.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Nassim Jahnke -Date: Sat, 1 Oct 2022 09:44:26 +0200 -Subject: [PATCH] Add system property to print stacktrace on bad plugin class - access - - -diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -index e9fbf5fd2c86150561468f2c061b75004b123952..e0e69b5639eeb424cb55b0be24a7e938e45fbb26 100644 ---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java -@@ -184,6 +184,11 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm - // In case the bad access occurs on construction - org.bukkit.Bukkit.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()}); // Paper - } -+ // Paper start -+ if (Boolean.getBoolean("Paper.printStacktraceOnBadPluginClassAccess")) { -+ (plugin != null ? plugin.getLogger() : org.bukkit.Bukkit.getLogger()).log(Level.WARNING, "Stacktrace", new Exception()); -+ } -+ // Paper end - } - } - diff --git a/patches/api/0388-Add-PlayerInventorySlotChangeEvent.patch b/patches/api/0387-Add-PlayerInventorySlotChangeEvent.patch similarity index 100% rename from patches/api/0388-Add-PlayerInventorySlotChangeEvent.patch rename to patches/api/0387-Add-PlayerInventorySlotChangeEvent.patch diff --git a/patches/api/0389-Elder-Guardian-appearance-API.patch b/patches/api/0388-Elder-Guardian-appearance-API.patch similarity index 100% rename from patches/api/0389-Elder-Guardian-appearance-API.patch rename to patches/api/0388-Elder-Guardian-appearance-API.patch diff --git a/patches/api/0390-Allow-changing-bed-s-occupied-property.patch b/patches/api/0389-Allow-changing-bed-s-occupied-property.patch similarity index 100% rename from patches/api/0390-Allow-changing-bed-s-occupied-property.patch rename to patches/api/0389-Allow-changing-bed-s-occupied-property.patch diff --git a/patches/api/0391-Add-EquipmentSlot-convenience-methods.patch b/patches/api/0390-Add-EquipmentSlot-convenience-methods.patch similarity index 100% rename from patches/api/0391-Add-EquipmentSlot-convenience-methods.patch rename to patches/api/0390-Add-EquipmentSlot-convenience-methods.patch diff --git a/patches/api/0392-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch b/patches/api/0391-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch similarity index 100% rename from patches/api/0392-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch rename to patches/api/0391-Add-LivingEntity-swingHand-EquipmentSlot-convenience.patch diff --git a/patches/api/0393-Add-entity-knockback-API.patch b/patches/api/0392-Add-entity-knockback-API.patch similarity index 100% rename from patches/api/0393-Add-entity-knockback-API.patch rename to patches/api/0392-Add-entity-knockback-API.patch diff --git a/patches/api/0394-Added-EntityToggleSitEvent.patch b/patches/api/0393-Added-EntityToggleSitEvent.patch similarity index 100% rename from patches/api/0394-Added-EntityToggleSitEvent.patch rename to patches/api/0393-Added-EntityToggleSitEvent.patch diff --git a/patches/api/0395-Add-Moving-Piston-API.patch b/patches/api/0394-Add-Moving-Piston-API.patch similarity index 100% rename from patches/api/0395-Add-Moving-Piston-API.patch rename to patches/api/0394-Add-Moving-Piston-API.patch diff --git a/patches/api/0396-Add-PrePlayerAttackEntityEvent.patch b/patches/api/0395-Add-PrePlayerAttackEntityEvent.patch similarity index 100% rename from patches/api/0396-Add-PrePlayerAttackEntityEvent.patch rename to patches/api/0395-Add-PrePlayerAttackEntityEvent.patch diff --git a/patches/api/0397-Add-Player-Warden-Warning-API.patch b/patches/api/0396-Add-Player-Warden-Warning-API.patch similarity index 100% rename from patches/api/0397-Add-Player-Warden-Warning-API.patch rename to patches/api/0396-Add-Player-Warden-Warning-API.patch diff --git a/patches/api/0398-More-vanilla-friendly-methods-to-update-trades.patch b/patches/api/0397-More-vanilla-friendly-methods-to-update-trades.patch similarity index 100% rename from patches/api/0398-More-vanilla-friendly-methods-to-update-trades.patch rename to patches/api/0397-More-vanilla-friendly-methods-to-update-trades.patch diff --git a/patches/api/0399-Add-paper-dumplisteners-command.patch b/patches/api/0398-Add-paper-dumplisteners-command.patch similarity index 100% rename from patches/api/0399-Add-paper-dumplisteners-command.patch rename to patches/api/0398-Add-paper-dumplisteners-command.patch diff --git a/patches/api/0400-ItemStack-damage-API.patch b/patches/api/0399-ItemStack-damage-API.patch similarity index 100% rename from patches/api/0400-ItemStack-damage-API.patch rename to patches/api/0399-ItemStack-damage-API.patch diff --git a/patches/api/0401-Add-Tick-TemporalUnit.patch b/patches/api/0400-Add-Tick-TemporalUnit.patch similarity index 100% rename from patches/api/0401-Add-Tick-TemporalUnit.patch rename to patches/api/0400-Add-Tick-TemporalUnit.patch diff --git a/patches/api/0402-Friction-API.patch b/patches/api/0401-Friction-API.patch similarity index 100% rename from patches/api/0402-Friction-API.patch rename to patches/api/0401-Friction-API.patch diff --git a/patches/api/0403-Player-Entity-Tracking-Events.patch b/patches/api/0402-Player-Entity-Tracking-Events.patch similarity index 100% rename from patches/api/0403-Player-Entity-Tracking-Events.patch rename to patches/api/0402-Player-Entity-Tracking-Events.patch diff --git a/patches/api/0404-Add-missing-Fluid-type.patch b/patches/api/0403-Add-missing-Fluid-type.patch similarity index 100% rename from patches/api/0404-Add-missing-Fluid-type.patch rename to patches/api/0403-Add-missing-Fluid-type.patch diff --git a/patches/api/0405-Mark-experimental-api-as-such.patch b/patches/api/0404-Mark-experimental-api-as-such.patch similarity index 100% rename from patches/api/0405-Mark-experimental-api-as-such.patch rename to patches/api/0404-Mark-experimental-api-as-such.patch diff --git a/patches/api/0406-fix-Instruments.patch b/patches/api/0405-fix-Instruments.patch similarity index 100% rename from patches/api/0406-fix-Instruments.patch rename to patches/api/0405-fix-Instruments.patch diff --git a/patches/api/0407-Add-BlockLockCheckEvent.patch b/patches/api/0406-Add-BlockLockCheckEvent.patch similarity index 100% rename from patches/api/0407-Add-BlockLockCheckEvent.patch rename to patches/api/0406-Add-BlockLockCheckEvent.patch diff --git a/patches/api/0408-Add-Sneaking-API-for-Entities.patch b/patches/api/0407-Add-Sneaking-API-for-Entities.patch similarity index 100% rename from patches/api/0408-Add-Sneaking-API-for-Entities.patch rename to patches/api/0407-Add-Sneaking-API-for-Entities.patch diff --git a/patches/api/0409-Improve-PortalEvents.patch b/patches/api/0408-Improve-PortalEvents.patch similarity index 100% rename from patches/api/0409-Improve-PortalEvents.patch rename to patches/api/0408-Improve-PortalEvents.patch diff --git a/patches/api/0410-Add-exploded-block-state-to-BlockExplodeEvent.patch b/patches/api/0409-Add-exploded-block-state-to-BlockExplodeEvent.patch similarity index 100% rename from patches/api/0410-Add-exploded-block-state-to-BlockExplodeEvent.patch rename to patches/api/0409-Add-exploded-block-state-to-BlockExplodeEvent.patch diff --git a/patches/api/0411-Flying-Fall-Damage-API.patch b/patches/api/0410-Flying-Fall-Damage-API.patch similarity index 100% rename from patches/api/0411-Flying-Fall-Damage-API.patch rename to patches/api/0410-Flying-Fall-Damage-API.patch diff --git a/patches/api/0412-Expose-pre-collision-moving-velocity-to-VehicleBlock.patch b/patches/api/0411-Expose-pre-collision-moving-velocity-to-VehicleBlock.patch similarity index 100% rename from patches/api/0412-Expose-pre-collision-moving-velocity-to-VehicleBlock.patch rename to patches/api/0411-Expose-pre-collision-moving-velocity-to-VehicleBlock.patch diff --git a/patches/api/0413-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch b/patches/api/0412-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch similarity index 100% rename from patches/api/0413-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch rename to patches/api/0412-Replace-ItemFlag.HIDE_POTION_EFFECTS.patch diff --git a/patches/api/0414-Add-Player-sendEquipmentChange-Map-API.patch b/patches/api/0413-Add-Player-sendEquipmentChange-Map-API.patch similarity index 100% rename from patches/api/0414-Add-Player-sendEquipmentChange-Map-API.patch rename to patches/api/0413-Add-Player-sendEquipmentChange-Map-API.patch diff --git a/patches/api/0415-Win-Screen-API.patch b/patches/api/0414-Win-Screen-API.patch similarity index 100% rename from patches/api/0415-Win-Screen-API.patch rename to patches/api/0414-Win-Screen-API.patch diff --git a/patches/api/0416-Add-Entity-Body-Yaw-API.patch b/patches/api/0415-Add-Entity-Body-Yaw-API.patch similarity index 100% rename from patches/api/0416-Add-Entity-Body-Yaw-API.patch rename to patches/api/0415-Add-Entity-Body-Yaw-API.patch diff --git a/patches/api/0417-Add-missing-isFuel-Material-entries.patch b/patches/api/0416-Add-missing-isFuel-Material-entries.patch similarity index 100% rename from patches/api/0417-Add-missing-isFuel-Material-entries.patch rename to patches/api/0416-Add-missing-isFuel-Material-entries.patch diff --git a/patches/api/0418-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch b/patches/api/0417-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch similarity index 100% rename from patches/api/0418-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch rename to patches/api/0417-Fix-HandlerList-for-InventoryBlockStartEvent-subclas.patch diff --git a/patches/server/0013-Paper-Plugins.patch b/patches/server/0013-Paper-Plugins.patch index dbe276002..7cfddd32f 100644 --- a/patches/server/0013-Paper-Plugins.patch +++ b/patches/server/0013-Paper-Plugins.patch @@ -250,10 +250,10 @@ index 0000000000000000000000000000000000000000..72096a66a4046633de73a12f5a043ac6 +} 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 +index 0000000000000000000000000000000000000000..4ecd00b32c7abc15d655dd3c999b6feca332c3a1 --- /dev/null +++ b/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java -@@ -0,0 +1,201 @@ +@@ -0,0 +1,187 @@ +package io.papermc.paper.command.subcommands; + +import com.google.gson.JsonArray; @@ -386,20 +386,6 @@ index 0000000000000000000000000000000000000000..254854646b748e5bb47657625315ced5 + 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); + @@ -1587,18 +1573,22 @@ index 0000000000000000000000000000000000000000..f43295fdeaa587cf30c35a1d54516707 +} 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 +index 0000000000000000000000000000000000000000..b963fae0285d2d87a6f6a4eddf98996a27dabac2 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/entrypoint/dependency/DependencyUtil.java -@@ -0,0 +1,45 @@ +@@ -0,0 +1,70 @@ +package io.papermc.paper.plugin.entrypoint.dependency; + +import com.google.common.graph.MutableGraph; +import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.configuration.LoadOrderConfiguration; ++import org.bukkit.plugin.PluginDescriptionFile; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; ++import java.util.Map; + +@SuppressWarnings("UnstableApiUsage") +public class DependencyUtil { @@ -1609,16 +1599,27 @@ index 0000000000000000000000000000000000000000..1af3c3434eb1f3b00857b17a07f42e51 + dependencies.addAll(configuration.getPluginDependencies()); + dependencies.addAll(configuration.getPluginSoftDependencies()); + -+ return buildDependencyGraph(dependencyGraph, configuration.getName(), dependencies, configuration.getLoadBeforePlugins()); ++ return buildDependencyGraph(dependencyGraph, configuration.getName(), dependencies); + } + + @NotNull -+ public static MutableGraph buildDependencyGraph(@NotNull MutableGraph dependencyGraph, String identifier, @NotNull Iterable depends, @NotNull Iterable loadBefore) { ++ public static MutableGraph buildDependencyGraph(@NotNull MutableGraph dependencyGraph, String identifier, @NotNull Iterable depends) { + for (String dependency : depends) { + dependencyGraph.putEdge(identifier, dependency); + } + -+ for (String loadBeforeTarget : loadBefore) { ++ dependencyGraph.addNode(identifier); // Make sure dependencies at least have a node ++ return dependencyGraph; ++ } ++ ++ @NotNull ++ public static MutableGraph buildLoadGraph(@NotNull MutableGraph dependencyGraph, @NotNull LoadOrderConfiguration configuration) { ++ String identifier = configuration.getMeta().getName(); ++ for (String dependency : configuration.getLoadAfter()) { ++ dependencyGraph.putEdge(identifier, dependency); ++ } ++ ++ for (String loadBeforeTarget : configuration.getLoadBefore()) { + dependencyGraph.putEdge(loadBeforeTarget, identifier); + } + @@ -1635,6 +1636,16 @@ index 0000000000000000000000000000000000000000..1af3c3434eb1f3b00857b17a07f42e51 + return dependencyGraph; + } + ++ public static List validateSimple(PluginMeta meta, Map> toLoad) { ++ List missingDependencies = new ArrayList<>(); ++ for (String hardDependency : meta.getPluginDependencies()) { ++ if (!toLoad.containsKey(hardDependency)) { ++ missingDependencies.add(hardDependency); ++ } ++ } ++ ++ return missingDependencies; ++ } +} 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 @@ -2043,10 +2054,10 @@ index 0000000000000000000000000000000000000000..22189a1c42459c00d3e8bdeb980d15a6 +} 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..c337852883f38f6c2d8d5afbed0c848b047701d9 +index 0000000000000000000000000000000000000000..d116134db072ecea7caeb90310fab9d83534ef48 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/LegacyPluginLoadingStrategy.java -@@ -0,0 +1,260 @@ +@@ -0,0 +1,269 @@ +package io.papermc.paper.plugin.entrypoint.strategy; + +import com.google.common.graph.GraphBuilder; @@ -2054,6 +2065,7 @@ index 0000000000000000000000000000000000000000..c337852883f38f6c2d8d5afbed0c848b +import io.papermc.paper.plugin.configuration.PluginMeta; +import io.papermc.paper.plugin.entrypoint.dependency.GraphDependencyContext; +import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent; +import org.bukkit.plugin.UnknownDependencyException; + +import java.util.ArrayList; @@ -2137,7 +2149,7 @@ index 0000000000000000000000000000000000000000..c337852883f38f6c2d8d5afbed0c848b + } + } + -+ Collection softDependencySet = this.configuration.optionalDependencies(provider); ++ Collection softDependencySet = provider.getMeta().getPluginSoftDependencies(); + if (softDependencySet != null && !softDependencySet.isEmpty()) { + if (softDependencies.containsKey(configuration.getName())) { + // Duplicates do not matter, they will be removed together if applicable @@ -2151,7 +2163,7 @@ index 0000000000000000000000000000000000000000..c337852883f38f6c2d8d5afbed0c848b + } + } + -+ Collection dependencySet = this.configuration.requiredDependencies(provider); ++ Collection dependencySet = provider.getMeta().getPluginDependencies(); + if (dependencySet != null && !dependencySet.isEmpty()) { + dependencies.put(configuration.getName(), new LinkedList(dependencySet)); + @@ -2160,7 +2172,7 @@ index 0000000000000000000000000000000000000000..c337852883f38f6c2d8d5afbed0c848b + } + } + -+ Collection loadBeforeSet = this.configuration.loadBeforeDependencies(provider); ++ Collection loadBeforeSet = provider.getMeta().getPluginSoftDependencies(); + if (loadBeforeSet != null && !loadBeforeSet.isEmpty()) { + for (String loadBeforeTarget : loadBeforeSet) { + if (softDependencies.containsKey(loadBeforeTarget)) { @@ -2246,6 +2258,7 @@ index 0000000000000000000000000000000000000000..c337852883f38f6c2d8d5afbed0c848b + try { + this.configuration.applyContext(file, dependencyContext); + T loadedPlugin = file.createInstance(); ++ this.warnIfPaperPlugin(file); + + if (this.configuration.load(file, loadedPlugin)) { + loadedPlugins.add(file.getMeta().getName()); @@ -2277,6 +2290,7 @@ index 0000000000000000000000000000000000000000..c337852883f38f6c2d8d5afbed0c848b + try { + this.configuration.applyContext(file, dependencyContext); + T loadedPlugin = file.createInstance(); ++ this.warnIfPaperPlugin(file); + + if (this.configuration.load(file, loadedPlugin)) { + loadedPlugins.add(file.getMeta().getName()); @@ -2306,16 +2320,23 @@ index 0000000000000000000000000000000000000000..c337852883f38f6c2d8d5afbed0c848b + + return javapluginsLoaded; + } ++ ++ private void warnIfPaperPlugin(PluginProvider provider) { ++ if (provider instanceof PaperPluginParent.PaperServerPluginProvider) { ++ provider.getLogger().warning("Loading Paper plugin in the legacy plugin loading logic. This is not recommended and may introduce some differences into load order. It's highly recommended you move away from this if you are wanting to use Paper plugins."); ++ } ++ } +} 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..30e56289cccc09456b3421f7960d8647b6610639 +index 0000000000000000000000000000000000000000..f2ef0ac8b498013d232ee56fdafba331c7dcbe27 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ModernPluginLoadingStrategy.java -@@ -0,0 +1,143 @@ +@@ -0,0 +1,148 @@ +package io.papermc.paper.plugin.entrypoint.strategy; + +import com.google.common.collect.Lists; ++import com.google.common.collect.Maps; +import com.google.common.graph.GraphBuilder; +import com.google.common.graph.MutableGraph; +import com.mojang.logging.LogUtils; @@ -2323,6 +2344,7 @@ index 0000000000000000000000000000000000000000..30e56289cccc09456b3421f7960d8647 +import io.papermc.paper.plugin.entrypoint.dependency.DependencyUtil; +import io.papermc.paper.plugin.entrypoint.dependency.GraphDependencyContext; +import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.configuration.LoadOrderConfiguration; +import org.bukkit.plugin.UnknownDependencyException; +import org.slf4j.Logger; + @@ -2343,8 +2365,8 @@ index 0000000000000000000000000000000000000000..30e56289cccc09456b3421f7960d8647 + + @Override + public List> loadProviders(List> pluginProviders) { -+ MutableGraph dependencyGraph = GraphBuilder.directed().build(); + Map> providerMap = new HashMap<>(); ++ Map> providerMapMirror = Maps.transformValues(providerMap, (entry) -> entry.provider); + List> validatedProviders = new ArrayList<>(); + + // Populate provider map @@ -2381,12 +2403,7 @@ index 0000000000000000000000000000000000000000..30e56289cccc09456b3421f7960d8647 + 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); -+ } -+ } ++ List missingDependencies = provider.validateDependencies(providerMapMirror); + + if (missingDependencies.isEmpty()) { + validatedProviders.add(provider); @@ -2397,24 +2414,32 @@ index 0000000000000000000000000000000000000000..30e56289cccc09456b3421f7960d8647 + } + } + ++ MutableGraph loadOrderGraph = GraphBuilder.directed().build(); ++ MutableGraph dependencyGraph = GraphBuilder.directed().build(); + for (PluginProvider validated : validatedProviders) { + PluginMeta configuration = validated.getMeta(); ++ LoadOrderConfiguration loadOrderConfiguration = validated.createConfiguration(providerMapMirror); ++ ++ // Build a validated provider's load order changes ++ DependencyUtil.buildLoadGraph(loadOrderGraph, loadOrderConfiguration); + + // 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); ++ String name = configuration.getName(); ++ DependencyUtil.addProvidedPlugin(loadOrderGraph, name, provides); ++ DependencyUtil.addProvidedPlugin(dependencyGraph, name, provides); + } + } + + // Reverse the topographic search to let us see which providers we can load first. + List reversedTopographicSort; + try { -+ reversedTopographicSort = Lists.reverse(TopographicGraphSorter.sortGraph(dependencyGraph)); ++ reversedTopographicSort = Lists.reverse(TopographicGraphSorter.sortGraph(loadOrderGraph)); + } catch (TopographicGraphSorter.GraphCycleException exception) { -+ throw new PluginGraphCycleException(new JohnsonSimpleCycles<>(dependencyGraph).findSimpleCycles()); ++ throw new PluginGraphCycleException(new JohnsonSimpleCycles<>(loadOrderGraph).findSimpleCycles()); + } + + GraphDependencyContext graphDependencyContext = new GraphDependencyContext(dependencyGraph); @@ -2483,10 +2508,10 @@ index 0000000000000000000000000000000000000000..2ea978ac957849260e7ca69c9ff56588 +} 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 +index 0000000000000000000000000000000000000000..71536981075095ee06234c638c0dfa054e737fb8 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderConfiguration.java -@@ -0,0 +1,26 @@ +@@ -0,0 +1,19 @@ +package io.papermc.paper.plugin.entrypoint.strategy; + +import io.papermc.paper.plugin.provider.PluginProvider; @@ -2505,13 +2530,6 @@ index 0000000000000000000000000000000000000000..5e18616160014d70df2b539d7e65bb00 + + 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 @@ -2768,7 +2786,7 @@ index 0000000000000000000000000000000000000000..ea37ace14849ef4589a4f97287e6dcd6 +} 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..b532e35505d5fffd4c525109f273012e2652f777 +index 0000000000000000000000000000000000000000..365aa894c77b095bfe23bdaab354591df32bcda2 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/manager/MultiRuntimePluginProviderStorage.java @@ -0,0 +1,49 @@ @@ -2812,7 +2830,7 @@ index 0000000000000000000000000000000000000000..b532e35505d5fffd4c525109f273012e + } + + @Override -+ public boolean exitOnCycleDependencies() { ++ public boolean throwOnCycle() { + return false; + } + @@ -3889,7 +3907,7 @@ index 0000000000000000000000000000000000000000..5d50d1d312388e979c0e1cd53a6bf597 +} 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..194f1439e322cb6b3433a72f80a8a4c7624b20d5 +index 0000000000000000000000000000000000000000..3d1b60e0427b1da1965fe81fe02176a70a8d56a2 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/manager/SingularRuntimePluginProviderStorage.java @@ -0,0 +1,80 @@ @@ -3965,7 +3983,7 @@ index 0000000000000000000000000000000000000000..194f1439e322cb6b3433a72f80a8a4c7 + } + + @Override -+ public boolean exitOnCycleDependencies() { ++ public boolean throwOnCycle() { + return false; + } + @@ -4023,17 +4041,20 @@ index 0000000000000000000000000000000000000000..ea8cf22c35242eb9f3914b95df00e205 +} 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 +index 0000000000000000000000000000000000000000..a97ec947bc6cecf9d9183b236263fd4407e5fd7e --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/provider/PluginProvider.java -@@ -0,0 +1,47 @@ +@@ -0,0 +1,55 @@ +package io.papermc.paper.plugin.provider; + +import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.provider.configuration.LoadOrderConfiguration; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +import java.nio.file.Path; ++import java.util.List; ++import java.util.Map; +import java.util.jar.JarFile; +import java.util.logging.Logger; + @@ -4073,6 +4094,11 @@ index 0000000000000000000000000000000000000000..11b6cb377c9b04b63b6359918eef214b + + Logger getLogger(); + ++ LoadOrderConfiguration createConfiguration(@NotNull Map> toLoad); ++ ++ // Returns a list of missing dependencies ++ List validateDependencies(@NotNull Map> toLoad); ++ +} 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 @@ -4145,12 +4171,56 @@ index 0000000000000000000000000000000000000000..6ba3bcc468c0a60c76d6d0f0243bda66 + + +} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/LoadOrderConfiguration.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/LoadOrderConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e3430f535e8e9c3b8b44bf2daece8c47e8b14db7 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/LoadOrderConfiguration.java +@@ -0,0 +1,38 @@ ++package io.papermc.paper.plugin.provider.configuration; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.List; ++ ++/** ++ * This is used for plugins to configure the load order of strategies. ++ */ ++public interface LoadOrderConfiguration { ++ ++ /** ++ * Provides a list of plugins that THIS configuration should load ++ * before. ++ * ++ * @return list of plugins ++ */ ++ @NotNull ++ List getLoadBefore(); ++ ++ /** ++ * Provides a list of plugins that THIS configuration should load ++ * before. ++ * ++ * @return list of plugins ++ */ ++ @NotNull ++ List getLoadAfter(); ++ ++ /** ++ * Gets the responsible plugin provider's meta. ++ * ++ * @return meta ++ */ ++ @NotNull ++ PluginMeta getMeta(); ++} 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 +index 0000000000000000000000000000000000000000..3808f5a9abc9f084cbabfc4cb95394cc37aaf4bb --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/PaperPluginMeta.java -@@ -0,0 +1,213 @@ +@@ -0,0 +1,227 @@ +package io.papermc.paper.plugin.provider.configuration; + +import com.google.common.collect.ImmutableList; @@ -4164,6 +4234,7 @@ index 0000000000000000000000000000000000000000..622a6c5fdfcb6d8cc12054f3de81c73c +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.LoadConfiguration; +import io.papermc.paper.plugin.provider.configuration.type.PermissionConfiguration; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionDefault; @@ -4197,7 +4268,8 @@ index 0000000000000000000000000000000000000000..622a6c5fdfcb6d8cc12054f3de81c73c + @PluginConfigConstraints.PluginNameSpace + private String loader; + private List dependencies = List.of(); -+ private List loadBefore = List.of(); ++ private List loadBefore = List.of(); ++ private List loadAfter = List.of(); + private List provides = List.of(); + private boolean hasOpenClassloader = false; + @Required @@ -4300,6 +4372,18 @@ index 0000000000000000000000000000000000000000..622a6c5fdfcb6d8cc12054f3de81c73c + + @Override + public @NotNull List getLoadBeforePlugins() { ++ return this.loadBefore.stream().filter((dependency) -> !dependency.bootstrap()).map(LoadConfiguration::name).toList(); ++ } ++ ++ public @NotNull List getLoadAfterPlugins() { ++ return this.loadAfter.stream().filter((dependency) -> !dependency.bootstrap()).map(LoadConfiguration::name).toList(); ++ } ++ ++ public List getLoadAfter() { ++ return this.loadAfter; ++ } ++ ++ public List getLoadBefore() { + return this.loadBefore; + } + @@ -4681,6 +4765,23 @@ index 0000000000000000000000000000000000000000..071bff3f988a4391be424bdf7e98a6c3 + boolean bootstrap +) { +} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/configuration/type/LoadConfiguration.java b/src/main/java/io/papermc/paper/plugin/provider/configuration/type/LoadConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4184e4232c59f15ef8bbc98f82f501fc524f37c7 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/configuration/type/LoadConfiguration.java +@@ -0,0 +1,11 @@ ++package io.papermc.paper.plugin.provider.configuration.type; ++ ++import org.spongepowered.configurate.objectmapping.ConfigSerializable; ++import org.spongepowered.configurate.objectmapping.meta.Required; ++ ++@ConfigSerializable ++public record LoadConfiguration( ++ @Required String name, ++ 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 @@ -5074,20 +5175,125 @@ index 0000000000000000000000000000000000000000..32f230d66f6953520b59ccbf3079c5a6 + + C create(JarFile file, JarEntry config) throws Exception; +} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperBootstrapOrderConfiguration.java b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperBootstrapOrderConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..362feffd88e117c0fb93ffeddafe8334275f0d95 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperBootstrapOrderConfiguration.java +@@ -0,0 +1,47 @@ ++package io.papermc.paper.plugin.provider.type.paper; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.provider.configuration.LoadOrderConfiguration; ++import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; ++import io.papermc.paper.plugin.provider.configuration.type.LoadConfiguration; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.ArrayList; ++import java.util.List; ++ ++public class PaperBootstrapOrderConfiguration implements LoadOrderConfiguration { ++ ++ private final PaperPluginMeta paperPluginMeta; ++ private final List loadBefore = new ArrayList<>(); ++ private final List loadAfter = new ArrayList<>(); ++ ++ public PaperBootstrapOrderConfiguration(PaperPluginMeta paperPluginMeta) { ++ this.paperPluginMeta = paperPluginMeta; ++ ++ for (LoadConfiguration configuration : paperPluginMeta.getLoadAfter()) { ++ if (configuration.bootstrap()) { ++ this.loadAfter.add(configuration.name()); ++ } ++ } ++ for (LoadConfiguration configuration : paperPluginMeta.getLoadBefore()) { ++ if (configuration.bootstrap()) { ++ this.loadBefore.add(configuration.name()); ++ } ++ } ++ } ++ ++ @Override ++ public @NotNull List getLoadBefore() { ++ return this.loadBefore; ++ } ++ ++ @Override ++ public @NotNull List getLoadAfter() { ++ return this.loadAfter; ++ } ++ ++ @Override ++ public @NotNull PluginMeta getMeta() { ++ return this.paperPluginMeta; ++ } ++} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperLoadOrderConfiguration.java b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperLoadOrderConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b7e8a5ba375a558e0442aa9facf96954a9bb135f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperLoadOrderConfiguration.java +@@ -0,0 +1,44 @@ ++package io.papermc.paper.plugin.provider.type.paper; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.configuration.LoadOrderConfiguration; ++import io.papermc.paper.plugin.provider.configuration.PaperPluginMeta; ++import io.papermc.paper.plugin.provider.type.spigot.SpigotPluginProvider; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.ArrayList; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Map; ++ ++public class PaperLoadOrderConfiguration implements LoadOrderConfiguration { ++ ++ private final PaperPluginMeta meta; ++ private final List loadBefore; ++ private final List loadAfter; ++ ++ public PaperLoadOrderConfiguration(PaperPluginMeta meta) { ++ this.meta = meta; ++ ++ this.loadBefore = this.meta.getLoadBeforePlugins(); ++ this.loadAfter = this.meta.getLoadAfterPlugins(); ++ } ++ ++ @Override ++ public @NotNull List getLoadBefore() { ++ return this.loadBefore; ++ } ++ ++ @Override ++ public @NotNull List getLoadAfter() { ++ return this.loadAfter; ++ } ++ ++ @Override ++ public @NotNull PluginMeta getMeta() { ++ return this.meta; ++ } ++} 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 +index 0000000000000000000000000000000000000000..a0773c6d24de1f2ce1f0d949cba26b9997b696e6 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/provider/type/paper/PaperPluginParent.java -@@ -0,0 +1,226 @@ +@@ -0,0 +1,258 @@ +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.entrypoint.dependency.DependencyUtil; ++import io.papermc.paper.plugin.provider.configuration.LoadOrderConfiguration; ++import io.papermc.paper.plugin.provider.configuration.type.DependencyConfiguration; +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; @@ -5095,11 +5301,13 @@ index 0000000000000000000000000000000000000000..46ee1b7f4b4c509932c68a4152e1d844 +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.ArrayList; ++import java.util.List; ++import java.util.Map; +import java.util.jar.JarFile; +import java.util.logging.Logger; + @@ -5169,6 +5377,24 @@ index 0000000000000000000000000000000000000000..46ee1b7f4b4c509932c68a4152e1d844 + } + + @Override ++ public LoadOrderConfiguration createConfiguration(@NotNull Map> toLoad) { ++ return new PaperBootstrapOrderConfiguration(PaperPluginParent.this.description); ++ } ++ ++ @Override ++ public List validateDependencies(@NotNull Map> toLoad) { ++ List missingDependencies = new ArrayList<>(); ++ for (DependencyConfiguration configuration : this.getMeta().getDependencies()) { ++ String dependency = configuration.name(); ++ if (configuration.required() && configuration.bootstrap() && !toLoad.containsKey(dependency)) { ++ missingDependencies.add(dependency); ++ } ++ } ++ ++ return missingDependencies; ++ } ++ ++ @Override + public ProviderStatus getLastProvidedStatus() { + return this.status; + } @@ -5258,6 +5484,16 @@ index 0000000000000000000000000000000000000000..46ee1b7f4b4c509932c68a4152e1d844 + } + + @Override ++ public LoadOrderConfiguration createConfiguration(@NotNull Map> toLoad) { ++ return new PaperLoadOrderConfiguration(PaperPluginParent.this.description); ++ } ++ ++ @Override ++ public List validateDependencies(@NotNull Map> toLoad) { ++ return DependencyUtil.validateSimple(this.getMeta(), toLoad); ++ } ++ ++ @Override + public ProviderStatus getLastProvidedStatus() { + return this.status; + } @@ -5366,17 +5602,97 @@ index 0000000000000000000000000000000000000000..db343a2f482ac375078610f087569286 + return configuration; + } +} +diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotLoadOrderConfiguration.java b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotLoadOrderConfiguration.java +new file mode 100644 +index 0000000000000000000000000000000000000000..b2a6544e321fa61c58bdf5684231de1020884fcc +--- /dev/null ++++ b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotLoadOrderConfiguration.java +@@ -0,0 +1,72 @@ ++package io.papermc.paper.plugin.provider.type.spigot; ++ ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.configuration.LoadOrderConfiguration; ++import org.bukkit.plugin.PluginDescriptionFile; ++import org.bukkit.plugin.java.JavaPlugin; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.ArrayList; ++import java.util.HashSet; ++import java.util.Iterator; ++import java.util.List; ++import java.util.Map; ++import java.util.Set; ++ ++public class SpigotLoadOrderConfiguration implements LoadOrderConfiguration { ++ ++ private final PluginDescriptionFile meta; ++ private final List loadBefore; ++ private final List loadAfter; ++ ++ public SpigotLoadOrderConfiguration(SpigotPluginProvider spigotPluginProvider, Map> toLoad) { ++ this.meta = spigotPluginProvider.getMeta(); ++ ++ this.loadBefore = meta.getLoadBeforePlugins(); ++ this.loadAfter = new ArrayList<>(); ++ this.loadAfter.addAll(meta.getDepend()); ++ this.loadAfter.addAll(meta.getSoftDepend()); ++ ++ // First: Remove as load after IF already in loadbefore ++ // Some plugins would put a plugin both in depends and in loadbefore, ++ // so in this case, we just ignore the effects of depend. ++ for (String loadBefore : this.loadBefore) { ++ this.loadAfter.remove(loadBefore); ++ } ++ ++ // Second: Do a basic check to see if any other dependencies refer back to this plugin. ++ Iterator iterators = this.loadAfter.iterator(); ++ while (iterators.hasNext()) { ++ String loadAfter = iterators.next(); ++ PluginProvider provider = toLoad.get(loadAfter); ++ if (provider != null) { ++ PluginMeta configuration = provider.getMeta(); ++ // Does a configuration refer back to this plugin? ++ Set dependencies = new HashSet<>(); ++ dependencies.addAll(configuration.getPluginDependencies()); ++ dependencies.addAll(configuration.getPluginSoftDependencies()); ++ ++ if (configuration.getName().equals(this.meta.getName()) || dependencies.contains(this.meta.getName())) { ++ iterators.remove(); // Let the other config deal with it ++ } ++ } ++ } ++ ++ } ++ ++ @Override ++ public @NotNull List getLoadBefore() { ++ return this.loadBefore; ++ } ++ ++ @Override ++ public @NotNull List getLoadAfter() { ++ return this.loadAfter; ++ } ++ ++ @Override ++ public @NotNull PluginMeta getMeta() { ++ return this.meta; ++ } ++} 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 +index 0000000000000000000000000000000000000000..0da361611bd93bc3299b8559d5c7c2127a8a6f0f --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java -@@ -0,0 +1,172 @@ +@@ -0,0 +1,188 @@ +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.entrypoint.dependency.DependencyUtil; +import io.papermc.paper.plugin.manager.PaperPluginManagerImpl; ++import io.papermc.paper.plugin.provider.configuration.LoadOrderConfiguration; +import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; +import io.papermc.paper.plugin.entrypoint.dependency.DependencyContextHolder; +import io.papermc.paper.plugin.provider.PluginProvider; @@ -5396,6 +5712,8 @@ index 0000000000000000000000000000000000000000..309c3dc492cbf469768d6a712485a0e4 +import java.io.File; +import java.nio.file.Path; +import java.util.HashSet; ++import java.util.List; ++import java.util.Map; +import java.util.Set; +import java.util.jar.JarFile; +import java.util.logging.Level; @@ -5487,7 +5805,7 @@ index 0000000000000000000000000000000000000000..309c3dc492cbf469768d6a712485a0e4 + + final PluginClassLoader loader; + try { -+ loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description), this.dependencyContext); // Paper ++ loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description)); // Paper + } catch (InvalidPluginException ex) { + throw ex; + } catch (Throwable ex) { @@ -5496,7 +5814,9 @@ index 0000000000000000000000000000000000000000..309c3dc492cbf469768d6a712485a0e4 + + // Override dependency context. + // We must provide a temporary context in order to properly handle dependencies on the plugin classloader constructor. -+ loader.dependencyContext = PaperPluginManagerImpl.getInstance(); ++ // EDIT - Only re add if dependency checking is needed for spigot plugins, but not anymore. ++ // loader.dependencyContext = PaperPluginManagerImpl.getInstance(); ++ + + this.status = ProviderStatus.INITIALIZED; + return loader.plugin; @@ -5519,6 +5839,16 @@ index 0000000000000000000000000000000000000000..309c3dc492cbf469768d6a712485a0e4 + } + + @Override ++ public LoadOrderConfiguration createConfiguration(@NotNull Map> toLoad) { ++ return new SpigotLoadOrderConfiguration(this, toLoad); ++ } ++ ++ @Override ++ public List validateDependencies(@NotNull Map> toLoad) { ++ return DependencyUtil.validateSimple(this.getMeta(), toLoad); ++ } ++ ++ @Override + public ProviderStatus getLastProvidedStatus() { + return this.status; + } @@ -5597,10 +5927,10 @@ index 0000000000000000000000000000000000000000..14ed05945ba5bfeb2b539d4786278b0e + 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 +index 0000000000000000000000000000000000000000..e5b70ff297febd936e64055b79f48712d65dbed9 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/storage/BootstrapProviderStorage.java -@@ -0,0 +1,113 @@ +@@ -0,0 +1,57 @@ +package io.papermc.paper.plugin.storage; + +import com.mojang.logging.LogUtils; @@ -5650,92 +5980,28 @@ index 0000000000000000000000000000000000000000..7af995b941ce83265a93cdc6b5a2de8a + 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..eb4a7e1fbd9f0e853ebf965c6b4f9e0e6061ad74 +index 0000000000000000000000000000000000000000..c49fd0d21f5c591fb2076ac87f158bca1a8e12b1 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/storage/ConfiguredProviderStorage.java -@@ -0,0 +1,51 @@ +@@ -0,0 +1,17 @@ +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; -+import java.util.stream.Collectors; -+ +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) { @@ -5744,32 +6010,6 @@ index 0000000000000000000000000000000000000000..eb4a7e1fbd9f0e853ebf965c6b4f9e0e + 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()) { -+ logMessages.add(String.join(" -> ", list) + " -> " + list.get(0)); -+ } -+ -+ LOGGER.log(Level.SEVERE, "Circular dependencies detected! This happens when"); -+ LOGGER.log(Level.SEVERE, " i) plugin A has a plugin B in its (soft)depend list, and plugin B has plugin A in its (soft)depend list, or"); -+ LOGGER.log(Level.SEVERE, " ii) plugin A has plugin B both in its (soft)depend list and its loadbefore list."); -+ LOGGER.log(Level.SEVERE, "Circular dependencies:"); -+ for (String logMessage : logMessages) { -+ LOGGER.log(Level.SEVERE, " " + logMessage); -+ } -+ LOGGER.log(Level.SEVERE, "Please report this to the plugin authors of the first plugin of each loop or join the PaperMC Discord server for further help."); -+ 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()) { -+ throw new IllegalStateException("Circular plugin dependencies from plugins " + exception.getCycles().stream().map(cycle -> cycle.get(0)).collect(Collectors.joining(", "))); -+ } -+ } -+ -+ 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 @@ -5797,10 +6037,10 @@ index 0000000000000000000000000000000000000000..374e7d3d69fc8603ecf54999f173123d +} 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..8b47e585c85e54a71e34aa57d61c1b2b8c9edfdf +index 0000000000000000000000000000000000000000..fbe76a678f45bd3c55f25f2b6a4366efc0521cb8 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/storage/ServerPluginProviderStorage.java -@@ -0,0 +1,85 @@ +@@ -0,0 +1,70 @@ +package io.papermc.paper.plugin.storage; + +import com.mojang.logging.LogUtils; @@ -5842,21 +6082,6 @@ index 0000000000000000000000000000000000000000..8b47e585c85e54a71e34aa57d61c1b2b + PaperPluginManagerImpl.getInstance().loadPlugin(provided); + return true; + } -+ -+ @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(); -+ } + }); + } + @@ -5888,21 +6113,26 @@ index 0000000000000000000000000000000000000000..8b47e585c85e54a71e34aa57d61c1b2b +} 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..1c4c344eb65dd90e1d3698908b0d9b46262c9540 +index 0000000000000000000000000000000000000000..272b1d13a4925c92f39e02fc8360521a6b284727 --- /dev/null +++ b/src/main/java/io/papermc/paper/plugin/storage/SimpleProviderStorage.java -@@ -0,0 +1,57 @@ +@@ -0,0 +1,85 @@ +package io.papermc.paper.plugin.storage; + ++import com.mojang.logging.LogUtils; +import io.papermc.paper.plugin.entrypoint.strategy.PluginGraphCycleException; +import io.papermc.paper.plugin.entrypoint.strategy.ProviderLoadingStrategy; +import io.papermc.paper.plugin.provider.PluginProvider; ++import org.slf4j.Logger; + +import java.util.ArrayList; +import java.util.List; ++import java.util.stream.Collectors; + +public abstract class SimpleProviderStorage implements ProviderStorage { + ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ + protected final List> providers = new ArrayList<>(); + protected ProviderLoadingStrategy strategy; + @@ -5934,12 +6164,35 @@ index 0000000000000000000000000000000000000000..1c4c344eb65dd90e1d3698908b0d9b46 + return this.providers; + } + -+ public void processProvided(PluginProvider provider, T provided) {} ++ public void processProvided(PluginProvider provider, T provided) { ++ } + + // Mutable enter -+ protected void filterLoadingProviders(List> providers) {} ++ protected void filterLoadingProviders(List> providers) { ++ } + -+ protected abstract void handleCycle(PluginGraphCycleException exception); ++ protected void handleCycle(PluginGraphCycleException exception) { ++ List logMessages = new ArrayList<>(); ++ for (List list : exception.getCycles()) { ++ logMessages.add(String.join(" -> ", list) + " -> " + list.get(0)); ++ } ++ ++ LOGGER.error("Circular plugin loading detected!"); ++ LOGGER.error("Circular load order:"); ++ for (String logMessage : logMessages) { ++ LOGGER.error(" " + logMessage); ++ } ++ LOGGER.error("Please report this to the plugin authors of the first plugin of each loop or join the PaperMC Discord server for further help."); ++ 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"); ++ ++ if (this.throwOnCycle()) { ++ throw new IllegalStateException("Circular plugin loading from plugins " + exception.getCycles().stream().map(cycle -> cycle.get(0)).collect(Collectors.joining(", "))); ++ } ++ } ++ ++ public boolean throwOnCycle() { ++ return true; ++ } + + @Override + public String toString() { @@ -6396,12 +6649,12 @@ index 0000000000000000000000000000000000000000..1d14f530ef888102e47eeeaf0d1a6076 + 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 +diff --git a/src/test/java/io/papermc/paper/plugin/PluginLoadOrderTest.java b/src/test/java/io/papermc/paper/plugin/PluginLoadOrderTest.java new file mode 100644 -index 0000000000000000000000000000000000000000..7665967dc1849dde750c6d24298e76c2c74f8443 +index 0000000000000000000000000000000000000000..d137461a3a1896a367c5245a99a9b30afd9f6ad5 --- /dev/null -+++ b/src/test/java/io/papermc/paper/plugin/PluginDependencyLoadingTest.java -@@ -0,0 +1,159 @@ ++++ b/src/test/java/io/papermc/paper/plugin/PluginLoadOrderTest.java +@@ -0,0 +1,146 @@ +package io.papermc.paper.plugin; + +import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; @@ -6418,19 +6671,20 @@ index 0000000000000000000000000000000000000000..7665967dc1849dde750c6d24298e76c2 +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + -+public class PluginDependencyLoadingTest { ++public class PluginLoadOrderTest { + + private static List> REGISTERED_PROVIDERS = new ArrayList<>(); + private static Map LOAD_ORDER = new HashMap<>(); ++ private static final String[] EMPTY = {}; + + static { + setup(); + } + -+ private static TestJavaPluginProvider setup(String identifier, String[] hard, String[] soft, String[] before) { ++ private static TestJavaPluginProvider setup(String identifier, String[] loadAfter, String[] loadAfterSoft, String[] before) { + TestPluginMeta configuration = new TestPluginMeta(identifier); -+ configuration.setHardDependencies(List.of(hard)); -+ configuration.setSoftDependencies(List.of(soft)); ++ configuration.setHardDependencies(List.of(loadAfter)); ++ configuration.setSoftDependencies(List.of(loadAfterSoft)); + configuration.setLoadBefore(List.of(before)); + + TestJavaPluginProvider provider = new TestJavaPluginProvider(configuration); @@ -6442,52 +6696,52 @@ index 0000000000000000000000000000000000000000..7665967dc1849dde750c6d24298e76c2 + * 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[]{}); ++ setup("RedAir", EMPTY, new String[]{"NightShovel", "EmeraldFire"}, new String[]{"GreenShovel", "IronSpork", "BrightBlueShovel", "WireDoor"}); ++ setup("BigGrass", EMPTY, new String[]{"IronEarth", "RedAir"}, new String[]{"BlueFire"}); ++ setup("BlueFire", EMPTY, EMPTY, EMPTY); ++ setup("BigPaper", EMPTY, new String[]{"BlueFire"}, EMPTY); ++ setup("EmeraldSpork", EMPTY, EMPTY, new String[]{"GoldPaper", "YellowSnow"}); ++ setup("GreenShovel", EMPTY, EMPTY, EMPTY); ++ setup("BrightBlueGrass", new String[]{"BigPaper"}, new String[]{"DarkSpork"}, EMPTY); ++ setup("GoldPaper", EMPTY, new String[]{"BlueFire"}, EMPTY); ++ setup("GreenGlass", EMPTY, EMPTY, EMPTY); ++ setup("GoldNeptune", EMPTY, new String[]{"GreenShovel", "GoldNeptuneVersioning"}, EMPTY); ++ setup("RedPaper", EMPTY, new String[]{"GoldPaper", "GoldFire", "EmeraldGrass", "BlueFire", "CopperSpork", "YellowDoor", "OrangeClam", "BlueSponge", "GoldNeptune", "BrightBlueGrass", "DarkSpoon", "BigShovel", "GreenGlass", "IronGlass"}, new String[]{"IronPaper", "YellowFire"}); ++ setup("YellowGrass", EMPTY, new String[]{"RedAir"}, EMPTY); ++ setup("WireFire", EMPTY, new String[]{"RedPaper", "WireGrass", "YellowSpork", "NightAir"}, EMPTY); ++ setup("OrangeNeptune", EMPTY, EMPTY, EMPTY); ++ 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"}, EMPTY); ++ setup("CopperSnow", EMPTY, new String[]{"RedSnow", "OrangeFire", "WireAir", "GreenGlass", "NightSpork", "EmeraldPaper"}, new String[]{"BlueGrass"}); ++ setup("BrightBluePaper", EMPTY, new String[]{"GoldEarth", "BrightBlueSpoon", "CopperGlass", "LightSporkChat", "DarkAir", "LightEarth", "DiamondDoor", "YellowShovel", "BlueAir", "DarkShovel", "GoldPaper", "BlueFire", "GreenGlass", "YellowSpork", "BigGrass", "OrangePaper", "DarkPaper"}, new String[]{"WireShovel"}); ++ setup("LightSponge", EMPTY, EMPTY, EMPTY); ++ setup("OrangeShovel", EMPTY, EMPTY, EMPTY); ++ setup("GoldGrass", EMPTY, new String[]{"GreenGlass", "BlueFire"}, EMPTY); ++ setup("IronSponge", EMPTY, new String[]{"DiamondEarth"}, EMPTY); ++ setup("EmeraldSnow", EMPTY, EMPTY, EMPTY); ++ setup("BlueSpoon", new String[]{"BigGrass"}, new String[]{"GreenGlass", "GoldPaper", "GreenShovel", "YellowClam"}, EMPTY); ++ setup("BigSpork", EMPTY, new String[]{"BigPaper"}, EMPTY); ++ setup("BluePaper", EMPTY, new String[]{"BigClam", "RedSpoon", "GreenFire", "WireSnow", "OrangeSnow", "BlueFire", "BrightBlueGrass", "YellowSpork", "GreenGlass"}, EMPTY); ++ setup("OrangeSpork", EMPTY, EMPTY, EMPTY); ++ setup("DiamondNeptune", EMPTY, new String[]{"GreenGlass", "GreenShovel", "YellowNeptune"}, EMPTY); ++ setup("BigFire", EMPTY, new String[]{"BlueFire", "BrightBlueDoor", "GreenGlass"}, EMPTY); ++ setup("NightNeptune", EMPTY, new String[]{"BlueFire", "DarkGlass", "GoldPaper", "YellowNeptune", "BlueShovel"}, EMPTY); ++ setup("YellowEarth", new String[]{"RedAir"}, EMPTY, EMPTY); ++ setup("DiamondClam", EMPTY, EMPTY, EMPTY); ++ setup("CopperAir", EMPTY, new String[]{"BigPaper"}, EMPTY); ++ setup("NightSpoon", new String[]{"OrangeNeptune"}, new String[]{"BlueFire", "GreenGlass", "RedSpork", "GoldPaper", "BigShovel", "YellowSponge", "EmeraldSpork"}, EMPTY); ++ setup("GreenClam", EMPTY, new String[]{"GreenShovel", "BrightBlueEarth", "BigSpoon", "RedPaper", "BlueFire", "GreenGlass", "WireFire", "GreenSnow"}, EMPTY); ++ setup("YellowPaper", EMPTY, EMPTY, EMPTY); ++ setup("WireGlass", new String[]{"YellowGrass"}, new String[]{"YellowGlass", "BigSpoon", "CopperSnow", "GreenGlass", "BlueEarth"}, EMPTY); ++ setup("BlueSpork", EMPTY, new String[]{"BrightBlueGrass"}, EMPTY); ++ setup("CopperShovel", EMPTY, new String[]{"GreenGlass"}, EMPTY); ++ setup("RedClam", EMPTY, EMPTY, EMPTY); ++ setup("EmeraldClam", EMPTY, new String[]{"BlueFire"}, EMPTY); ++ setup("DarkClam", EMPTY, new String[]{"GoldAir", "LightGlass"}, EMPTY); ++ setup("WireSpoon", EMPTY, new String[]{"GoldPaper", "LightSnow"}, EMPTY); ++ setup("CopperNeptune", EMPTY, new String[]{"GreenGlass", "BigGrass"}, EMPTY); ++ setup("RedNeptune", EMPTY, EMPTY, EMPTY); ++ setup("GreenAir", EMPTY, EMPTY, EMPTY); ++ setup("RedFire", new String[]{"BrightBlueGrass", "BigPaper"}, new String[]{"BlueFire", "GreenGlass", "BigGrass"}, EMPTY); + } + + @Before @@ -6504,20 +6758,6 @@ index 0000000000000000000000000000000000000000..7665967dc1849dde750c6d24298e76c2 + 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); @@ -6561,9 +6801,6 @@ index 0000000000000000000000000000000000000000..7665967dc1849dde750c6d24298e76c2 + } + } +} -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 @@ -6723,16 +6960,22 @@ index 0000000000000000000000000000000000000000..04903794a8ee4dd73162ae240862ff6d +} 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 +index 0000000000000000000000000000000000000000..ea2854172968abea40c39eb05faf76ed1191c353 --- /dev/null +++ b/src/test/java/io/papermc/paper/plugin/TestJavaPluginProvider.java -@@ -0,0 +1,42 @@ +@@ -0,0 +1,76 @@ +package io.papermc.paper.plugin; + ++import io.papermc.paper.plugin.configuration.PluginMeta; ++import io.papermc.paper.plugin.entrypoint.dependency.DependencyUtil; +import io.papermc.paper.plugin.provider.PluginProvider; ++import io.papermc.paper.plugin.provider.configuration.LoadOrderConfiguration; +import org.jetbrains.annotations.NotNull; + +import java.nio.file.Path; ++import java.util.ArrayList; ++import java.util.List; ++import java.util.Map; +import java.util.jar.JarFile; +import java.util.logging.Logger; + @@ -6768,6 +7011,34 @@ index 0000000000000000000000000000000000000000..8837b131dedc41e7d0d58ccf3d1e2511 + public Logger getLogger() { + return Logger.getLogger("TestPlugin"); + } ++ ++ @Override ++ public LoadOrderConfiguration createConfiguration(@NotNull Map> toLoad) { ++ return new LoadOrderConfiguration() { ++ @Override ++ public @NotNull List getLoadBefore() { ++ return TestJavaPluginProvider.this.testPluginConfiguration.getLoadBeforePlugins(); ++ } ++ ++ @Override ++ public @NotNull List getLoadAfter() { ++ List loadAfter = new ArrayList<>(); ++ loadAfter.addAll(TestJavaPluginProvider.this.testPluginConfiguration.getPluginDependencies()); ++ loadAfter.addAll(TestJavaPluginProvider.this.testPluginConfiguration.getPluginSoftDependencies()); ++ return loadAfter; ++ } ++ ++ @Override ++ public @NotNull PluginMeta getMeta() { ++ return TestJavaPluginProvider.this.testPluginConfiguration; ++ } ++ }; ++ } ++ ++ @Override ++ public List validateDependencies(@NotNull Map> toLoad) { ++ return DependencyUtil.validateSimple(this.getMeta(), toLoad); ++ } +} 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