diff --git a/patches/api/0008-Paper-Plugins.patch b/patches/api/0008-Paper-Plugins.patch
index 4c6ce22600..d73b50e2ac 100644
--- a/patches/api/0008-Paper-Plugins.patch
+++ b/patches/api/0008-Paper-Plugins.patch
@@ -1218,72 +1218,6 @@ index 0000000000000000000000000000000000000000..44d630c3eb2670c36134b9907519dc98
 +    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<Class<? extends Event>, Set<RegisteredListener>> 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
@@ -1901,7 +1835,7 @@ index a80251eff75430863b37db1c131e22593f3fcd5e..310c4041963a3f1e0a26e39a6da12a9b
 +    // 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
+index 669a70faa95d0d6525a731d73499ed6fb0b48320..6175b04327b12e74140a0885f7326546dfaf269a 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 {
@@ -1977,7 +1911,7 @@ index 669a70faa95d0d6525a731d73499ed6fb0b48320..a5636b1f223dd37420a4acbccf28f719
          if (isEnabled != enabled) {
              isEnabled = enabled;
  
-@@ -268,9 +283,14 @@ public abstract class JavaPlugin extends PluginBase {
+@@ -268,9 +283,18 @@ public abstract class JavaPlugin extends PluginBase {
          }
      }
  
@@ -1985,17 +1919,21 @@ index 669a70faa95d0d6525a731d73499ed6fb0b48320..a5636b1f223dd37420a4acbccf28f719
 -    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
++    private static class DummyPluginLoaderImplHolder {
++        private static final PluginLoader INSTANCE =  net.kyori.adventure.util.Services.service(PluginLoader.class)
++            .orElseThrow();
++    }
 +    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.loader = DummyPluginLoaderImplHolder.INSTANCE; // Paper
          this.server = server;
          this.file = file;
          this.description = description;
-@@ -278,6 +298,7 @@ public abstract class JavaPlugin extends PluginBase {
+@@ -278,6 +302,7 @@ public abstract class JavaPlugin extends PluginBase {
          this.classLoader = classLoader;
          this.configFile = new File(dataFolder, "config.yml");
          this.logger = new PluginLogger(this);
@@ -2049,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..e721c58eafee2180d4ba1a73002cf850355a366e 100644
+index 2f74ec96ece706de23156ebabfe493211bc05391..2c3d2f60d3f2f55a1a90791d37521c61f96ab4b3 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;
@@ -2134,7 +2072,7 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..e721c58eafee2180d4ba1a73002cf850
  
              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 {
+@@ -128,14 +153,14 @@ final class PluginClassLoader extends URLClassLoader {
  
                      if (provider != description
                              && !seenIllegalAccess.contains(provider.getName())
@@ -2143,6 +2081,14 @@ index 2f74ec96ece706de23156ebabfe493211bc05391..e721c58eafee2180d4ba1a73002cf850
  
                          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 {
                      throw new ClassNotFoundException(name, ex);
                  }
diff --git a/patches/api/0070-Handle-plugin-prefixes-in-implementation-logging-con.patch b/patches/api/0070-Handle-plugin-prefixes-in-implementation-logging-con.patch
index 692bbf51ef..bdc3a0e82f 100644
--- a/patches/api/0070-Handle-plugin-prefixes-in-implementation-logging-con.patch
+++ b/patches/api/0070-Handle-plugin-prefixes-in-implementation-logging-con.patch
@@ -17,7 +17,7 @@ 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 a5636b1f223dd37420a4acbccf28f7198a7eee98..accac9527b1c267b75774532b85f28c868b06c28 100644
+index 6175b04327b12e74140a0885f7326546dfaf269a..79df67daf2fe8193fd83dd6a7bfc78b3f6e524c2 100644
 --- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
 +++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
 @@ -44,7 +44,7 @@ public abstract class JavaPlugin extends PluginBase {
@@ -29,7 +29,7 @@ index a5636b1f223dd37420a4acbccf28f7198a7eee98..accac9527b1c267b75774532b85f28c8
  
      public JavaPlugin() {
          // Paper start
-@@ -297,8 +297,8 @@ public abstract class JavaPlugin extends PluginBase {
+@@ -301,8 +301,8 @@ public abstract class JavaPlugin extends PluginBase {
          this.dataFolder = dataFolder;
          this.classLoader = classLoader;
          this.configFile = new File(dataFolder, "config.yml");
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 eadb0c1fc9..d35399c155 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
@@ -67,7 +67,7 @@ index 0000000000000000000000000000000000000000..087ee57fe5485bc760fadd45a176d4d9
 +
 +}
 diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
-index accac9527b1c267b75774532b85f28c868b06c28..a536c47fb5f05cad046c2f3374c69f4f83f7f32c 100644
+index 79df67daf2fe8193fd83dd6a7bfc78b3f6e524c2..0e4cedc005466c600ff6b9d500febf338b12a842 100644
 --- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
 +++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java
 @@ -44,7 +44,7 @@ public abstract class JavaPlugin extends PluginBase {
@@ -79,7 +79,7 @@ index accac9527b1c267b75774532b85f28c868b06c28..a536c47fb5f05cad046c2f3374c69f4f
  
      public JavaPlugin() {
          // Paper start
-@@ -298,7 +298,11 @@ public abstract class JavaPlugin extends PluginBase {
+@@ -302,7 +302,11 @@ public abstract class JavaPlugin extends PluginBase {
          this.classLoader = classLoader;
          this.configFile = new File(dataFolder, "config.yml");
          this.pluginMeta = configuration; // Paper
@@ -93,7 +93,7 @@ index accac9527b1c267b75774532b85f28c868b06c28..a536c47fb5f05cad046c2f3374c69f4f
  
      /**
 diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
-index 39c9253d03bae99f8b5b19d22295f6172606d57b..a657654079c40a0fee6f70c7d72df24b3827b911 100644
+index c5f49ba2d0cc5cdf127670ea2be59f1b174dc94b..1c6542bb9ce13781c8f3b84330b5ef5aa52d0348 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
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
index 62749287b8..ab80103802 100644
--- 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
@@ -6,16 +6,16 @@ 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 4cb4e28c9b0dfdac45c4129fb0325e6afe5cb131..4b3380a42b4be54ef4df806c5db0d3a1be5909a6 100644
+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
-                             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
                          }
 +                        // Paper start
 +                        if (Boolean.getBoolean("Paper.printStacktraceOnBadPluginClassAccess")) {
-+                            (plugin != null ? plugin.getLogger() : loader.server.getLogger()).log(Level.WARNING, "Stacktrace", new Exception());
++                            (plugin != null ? plugin.getLogger() : org.bukkit.Bukkit.getLogger()).log(Level.WARNING, "Stacktrace", new Exception());
 +                        }
 +                        // Paper end
                      }
diff --git a/patches/server/0013-Paper-Plugins.patch b/patches/server/0013-Paper-Plugins.patch
index 701ff50329..dbe2760025 100644
--- a/patches/server/0013-Paper-Plugins.patch
+++ b/patches/server/0013-Paper-Plugins.patch
@@ -457,13 +457,14 @@ index 0000000000000000000000000000000000000000..254854646b748e5bb47657625315ced5
 +}
 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..85fa762d7d3476510886a7cc7b3bc79acfce4425
+index 0000000000000000000000000000000000000000..9926eb59b83abffffb578356f148f045edc027cb
 --- /dev/null
 +++ b/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java
-@@ -0,0 +1,78 @@
+@@ -0,0 +1,88 @@
 +package io.papermc.paper.plugin;
 +
 +import com.mojang.logging.LogUtils;
++import io.papermc.paper.configuration.PaperConfigurations;
 +import joptsimple.OptionSet;
 +import org.bukkit.configuration.file.YamlConfiguration;
 +import org.jetbrains.annotations.NotNull;
@@ -482,45 +483,54 @@ index 0000000000000000000000000000000000000000..85fa762d7d3476510886a7cc7b3bc79a
 +    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();
-+
-+        String updateDirectory = YamlConfiguration.loadConfiguration(configFileLocationBukkit).getString("settings.update-folder", "update");
-+        if (updateDirectory.isBlank()) {
-+            this.updateDirectory = null;
-+        } else {
-+            Path resolvedUpdateDirectory = this.pluginDirectory.resolve(updateDirectory);
-+            if (!Files.isDirectory(resolvedUpdateDirectory)) {
-+                this.updateDirectory = null;
-+                return;
-+            }
-+
-+            boolean isSameFile = true;
-+            try {
-+                isSameFile = Files.isSameFile(resolvedUpdateDirectory, this.pluginDirectory);
-+            } catch (IOException e) {
-+                LOGGER.error("Misconfigured update directory!");
-+                LOGGER.error("Failed to compare update/plugin directory", e);
-+            }
-+
-+            if (isSameFile) {
-+                LOGGER.error("Misconfigured update directory!");
-+                LOGGER.error(("Your configured update directory (%s) in bukkit.yml is pointing to the same location as the plugin directory (%s). " +
-+                    "Disabling auto updating functionality.").formatted(resolvedUpdateDirectory, this.pluginDirectory));
-+
-+                this.updateDirectory = null;
-+            } else {
-+                this.updateDirectory = resolvedUpdateDirectory;
-+            }
-+
-+        }
-+
++    PluginInitializerManager(final Path pluginDirectory, final Path updateDirectory) {
++        this.pluginDirectory = pluginDirectory;
++        this.updateDirectory = updateDirectory;
 +    }
 +
-+    public static PluginInitializerManager init(OptionSet optionSet) {
-+        impl = new PluginInitializerManager(optionSet);
++    private static PluginInitializerManager parse(@NotNull final OptionSet minecraftOptionSet) throws Exception {
++        // We have to load the bukkit configuration inorder to get the update folder location.
++        final File configFileLocationBukkit = (File) minecraftOptionSet.valueOf("bukkit-settings");
++
++        final Path pluginDirectory = ((File) minecraftOptionSet.valueOf("plugins")).toPath();
++
++        final YamlConfiguration configuration = PaperConfigurations.loadLegacyConfigFile(configFileLocationBukkit);
++
++        final String updateDirectoryName = configuration.getString("settings.update-folder", "update");
++        if (updateDirectoryName.isBlank()) {
++            return new PluginInitializerManager(pluginDirectory, null);
++        }
++
++        final Path resolvedUpdateDirectory = pluginDirectory.resolve(updateDirectoryName);
++        if (!Files.isDirectory(resolvedUpdateDirectory)) {
++            LOGGER.error("Misconfigured update directory!");
++            LOGGER.error(("Your configured update directory (%s) in bukkit.yml is pointing to a non-directory path. " +
++                "Disabling auto updating functionality.").formatted(resolvedUpdateDirectory));
++            return new PluginInitializerManager(pluginDirectory, null);
++        }
++
++        boolean isSameFile;
++        try {
++            isSameFile = Files.isSameFile(resolvedUpdateDirectory, pluginDirectory);
++        } catch (final IOException e) {
++            LOGGER.error("Misconfigured update directory!");
++            LOGGER.error("Failed to compare update/plugin directory", e);
++            return new PluginInitializerManager(pluginDirectory, null);
++        }
++
++        if (isSameFile) {
++            LOGGER.error("Misconfigured update directory!");
++            LOGGER.error(("Your configured update directory (%s) in bukkit.yml is pointing to the same location as the plugin directory (%s). " +
++                "Disabling auto updating functionality.").formatted(resolvedUpdateDirectory, pluginDirectory));
++
++            return new PluginInitializerManager(pluginDirectory, null);
++        }
++
++        return new PluginInitializerManager(pluginDirectory, resolvedUpdateDirectory);
++    }
++
++    public static PluginInitializerManager init(final OptionSet optionSet) throws Exception {
++        impl = parse(optionSet);
 +        return impl;
 +    }
 +
@@ -2033,7 +2043,7 @@ 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..8bc11d7e9341a31382c1b055565cc8d5fd3203ea
+index 0000000000000000000000000000000000000000..c337852883f38f6c2d8d5afbed0c848b047701d9
 --- /dev/null
 +++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/LegacyPluginLoadingStrategy.java
 @@ -0,0 +1,260 @@
@@ -2069,8 +2079,8 @@ index 0000000000000000000000000000000000000000..8bc11d7e9341a31382c1b055565cc8d5
 +    }
 +
 +    @Override
-+    public List<T> loadProviders(List<PluginProvider<T>> providers) {
-+        List<T> javapluginsLoaded = new ArrayList<>();
++    public List<ProviderPair<T>> loadProviders(List<PluginProvider<T>> providers) {
++        List<ProviderPair<T>> javapluginsLoaded = new ArrayList<>();
 +        MutableGraph<String> dependencyGraph = GraphBuilder.directed().build();
 +        GraphDependencyContext dependencyContext = new GraphDependencyContext(dependencyGraph);
 +
@@ -2240,7 +2250,7 @@ index 0000000000000000000000000000000000000000..8bc11d7e9341a31382c1b055565cc8d5
 +                        if (this.configuration.load(file, loadedPlugin)) {
 +                            loadedPlugins.add(file.getMeta().getName());
 +                            loadedPlugins.addAll(file.getMeta().getProvidedPlugins());
-+                            javapluginsLoaded.add(loadedPlugin);
++                            javapluginsLoaded.add(new ProviderPair<>(file, loadedPlugin));
 +                        }
 +
 +                    } catch (Exception ex) {
@@ -2271,7 +2281,7 @@ index 0000000000000000000000000000000000000000..8bc11d7e9341a31382c1b055565cc8d5
 +                            if (this.configuration.load(file, loadedPlugin)) {
 +                                loadedPlugins.add(file.getMeta().getName());
 +                                loadedPlugins.addAll(file.getMeta().getProvidedPlugins());
-+                                javapluginsLoaded.add(loadedPlugin);
++                                javapluginsLoaded.add(new ProviderPair<>(file, loadedPlugin));
 +                            }
 +                            break;
 +                        } catch (Exception ex) {
@@ -2299,7 +2309,7 @@ index 0000000000000000000000000000000000000000..8bc11d7e9341a31382c1b055565cc8d5
 +}
 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
+index 0000000000000000000000000000000000000000..30e56289cccc09456b3421f7960d8647b6610639
 --- /dev/null
 +++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ModernPluginLoadingStrategy.java
 @@ -0,0 +1,143 @@
@@ -2332,7 +2342,7 @@ index 0000000000000000000000000000000000000000..a0363af157131a2b42c00028a260e9c3
 +    }
 +
 +    @Override
-+    public List<T> loadProviders(List<PluginProvider<T>> pluginProviders) {
++    public List<ProviderPair<T>> loadProviders(List<PluginProvider<T>> pluginProviders) {
 +        MutableGraph<String> dependencyGraph = GraphBuilder.directed().build();
 +        Map<String, PluginProviderEntry<T>> providerMap = new HashMap<>();
 +        List<PluginProvider<T>> validatedProviders = new ArrayList<>();
@@ -2408,7 +2418,7 @@ index 0000000000000000000000000000000000000000..a0363af157131a2b42c00028a260e9c3
 +        }
 +
 +        GraphDependencyContext graphDependencyContext = new GraphDependencyContext(dependencyGraph);
-+        List<T> loadedPlugins = new ArrayList<>();
++        List<ProviderPair<T>> 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<PluginProvider<T>>, but we would have to check if each dependency exists there... just
@@ -2426,7 +2436,7 @@ index 0000000000000000000000000000000000000000..a0363af157131a2b42c00028a260e9c3
 +
 +                T instance = retrievedProvider.createInstance();
 +                if (this.configuration.load(retrievedProvider, instance)) {
-+                    loadedPlugins.add(instance);
++                    loadedPlugins.add(new ProviderPair<>(retrievedProvider, instance));
 +                }
 +            } catch (Exception ex) {
 +                LOGGER.error("Could not load plugin '%s' in folder '%s'".formatted(retrievedProvider.getFileName(), retrievedProvider.getParentSource()), ex); // Paper
@@ -2505,10 +2515,10 @@ index 0000000000000000000000000000000000000000..5e18616160014d70df2b539d7e65bb00
 +}
 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
+index 0000000000000000000000000000000000000000..dee83e821dcc9baf3a3e5ca8325b03ed2d5eb81c
 --- /dev/null
 +++ b/src/main/java/io/papermc/paper/plugin/entrypoint/strategy/ProviderLoadingStrategy.java
-@@ -0,0 +1,16 @@
+@@ -0,0 +1,20 @@
 +package io.papermc.paper.plugin.entrypoint.strategy;
 +
 +import io.papermc.paper.plugin.provider.PluginProvider;
@@ -2523,7 +2533,11 @@ index 0000000000000000000000000000000000000000..e8d5ce5f137a960e353c6722e1f20f9b
 + */
 +public interface ProviderLoadingStrategy<P> {
 +
-+    List<P> loadProviders(List<PluginProvider<P>> providers);
++    List<ProviderPair<P>> loadProviders(List<PluginProvider<P>> providers);
++
++    record ProviderPair<P>(PluginProvider<P> provider, P provided) {
++
++    }
 +}
 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
@@ -2594,7 +2608,7 @@ index 0000000000000000000000000000000000000000..0720af0d48b39ca46e7d3aba08d7b359
 +}
 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
+index 0000000000000000000000000000000000000000..f38ecd7f65dc24e4a3f0bc675e3730287ac353f1
 --- /dev/null
 +++ b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java
 @@ -0,0 +1,64 @@
@@ -2656,7 +2670,7 @@ index 0000000000000000000000000000000000000000..d49dd7d17ce7ac17efb19b33de163015
 +        }
 +
 +        try {
-+            return new PaperPluginClassLoader(logger, source, jarFile, configuration, this.getClass().getClassLoader(), new URLClassLoader(urls));
++            return new PaperPluginClassLoader(logger, source, jarFile, configuration, this.getClass().getClassLoader(), new URLClassLoader(urls, getClass().getClassLoader()));
 +        } catch (IOException exception) {
 +            throw new RuntimeException(exception);
 +        }
@@ -2689,9 +2703,72 @@ index 0000000000000000000000000000000000000000..5fcce65009f715d46dd3013f1f92ec83
 +        return this.paths;
 +    }
 +}
+diff --git a/src/main/java/io/papermc/paper/plugin/manager/DummyBukkitPluginLoader.java b/src/main/java/io/papermc/paper/plugin/manager/DummyBukkitPluginLoader.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..ea37ace14849ef4589a4f97287e6dcd64351370f
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/plugin/manager/DummyBukkitPluginLoader.java
+@@ -0,0 +1,57 @@
++package io.papermc.paper.plugin.manager;
++
++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.
++ */
++@ApiStatus.Internal
++public class DummyBukkitPluginLoader 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<Class<? extends Event>, Set<RegisteredListener>> createRegisteredListeners(@NotNull Listener listener, @NotNull Plugin plugin) {
++        return PaperPluginManagerImpl.getInstance().paperEventManager.createRegisteredListeners(listener, plugin);
++    }
++
++    @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/manager/MultiRuntimePluginProviderStorage.java b/src/main/java/io/papermc/paper/plugin/manager/MultiRuntimePluginProviderStorage.java
 new file mode 100644
-index 0000000000000000000000000000000000000000..a47c0c1dedf5f8cd7006b170639676429c17d74d
+index 0000000000000000000000000000000000000000..b532e35505d5fffd4c525109f273012e2652f777
 --- /dev/null
 +++ b/src/main/java/io/papermc/paper/plugin/manager/MultiRuntimePluginProviderStorage.java
 @@ -0,0 +1,49 @@
@@ -2729,8 +2806,8 @@ index 0000000000000000000000000000000000000000..a47c0c1dedf5f8cd7006b17063967642
 +    }
 +
 +    @Override
-+    public void processProvided(JavaPlugin provided) {
-+        super.processProvided(provided);
++    public void processProvided(PluginProvider<JavaPlugin> provider, JavaPlugin provided) {
++        super.processProvided(provider, provided);
 +        this.provided.add(provided);
 +    }
 +
@@ -3512,7 +3589,7 @@ index 0000000000000000000000000000000000000000..c0e896343c22badd97c774c4ed1daa4e
 +}
 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
+index 0000000000000000000000000000000000000000..dab211c458311869c61779305580a1c7da830f71
 --- /dev/null
 +++ b/src/main/java/io/papermc/paper/plugin/manager/PaperPluginManagerImpl.java
 @@ -0,0 +1,241 @@
@@ -3548,9 +3625,9 @@ index 0000000000000000000000000000000000000000..cdc3f6c5c845fe00478c41a22d39d7b3
 +
 +public class PaperPluginManagerImpl implements PluginManager, DependencyContext {
 +
-+    private final PaperPluginInstanceManager instanceManager;
-+    private final PaperEventManager paperEventManager;
-+    private PermissionManager permissionManager;
++    final PaperPluginInstanceManager instanceManager;
++    final PaperEventManager paperEventManager;
++    PermissionManager permissionManager;
 +
 +    public PaperPluginManagerImpl(Server server, CommandMap commandMap, @Nullable SimplePluginManager permissionManager) {
 +        this.instanceManager = new PaperPluginInstanceManager(this, commandMap, server);
@@ -3812,7 +3889,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..ebc01cbffdc55ca9664897ff10ef14ad6c5ab726
+index 0000000000000000000000000000000000000000..194f1439e322cb6b3433a72f80a8a4c7624b20d5
 --- /dev/null
 +++ b/src/main/java/io/papermc/paper/plugin/manager/SingularRuntimePluginProviderStorage.java
 @@ -0,0 +1,80 @@
@@ -3882,8 +3959,8 @@ index 0000000000000000000000000000000000000000..ebc01cbffdc55ca9664897ff10ef14ad
 +    }
 +
 +    @Override
-+    public void processProvided(JavaPlugin provided) {
-+        super.processProvided(provided);
++    public void processProvided(PluginProvider<JavaPlugin> provider, JavaPlugin provided) {
++        super.processProvided(provider, provided);
 +        this.singleLoaded = provided;
 +    }
 +
@@ -5720,10 +5797,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..b049691292fb9d53ac598cb333fa408b043e7bc5
+index 0000000000000000000000000000000000000000..8b47e585c85e54a71e34aa57d61c1b2b8c9edfdf
 --- /dev/null
 +++ b/src/main/java/io/papermc/paper/plugin/storage/ServerPluginProviderStorage.java
-@@ -0,0 +1,82 @@
+@@ -0,0 +1,85 @@
 +package io.papermc.paper.plugin.storage;
 +
 +import com.mojang.logging.LogUtils;
@@ -5761,18 +5838,9 @@ index 0000000000000000000000000000000000000000..b049691292fb9d53ac598cb333fa408b
 +
 +            @Override
 +            public boolean load(PluginProvider<JavaPlugin> 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;
-+                }
++                // Add it to the map here, we have to run the actual loading logic later.
++                PaperPluginManagerImpl.getInstance().loadPlugin(provided);
++                return true;
 +            }
 +
 +            @Override
@@ -5801,6 +5869,18 @@ index 0000000000000000000000000000000000000000..b049691292fb9d53ac598cb333fa408b
 +        pluginProviders.removeIf((provider) -> (provider instanceof PaperPluginParent.PaperServerPluginProvider pluginProvider && pluginProvider.shouldSkipCreation()));
 +    }
 +
++    // We need to call the load methods AFTER all plugins are constructed
++    @Override
++    public void processProvided(PluginProvider<JavaPlugin> provider, JavaPlugin provided) {
++        try {
++            provided.getLogger().info(String.format("Loading server plugin %s", provided.getPluginMeta().getDisplayName()));
++            provided.onLoad();
++        } catch (Throwable ex) {
++            // Don't mark that provider as ERRORED, as this apparently still needs to run the onEnable logic.
++            provided.getSLF4JLogger().error("Error initializing plugin '%s' in folder '%s' (Is it up to date?)".formatted(provider.getFileName(), provider.getParentSource()), ex);
++        }
++    }
++
 +    @Override
 +    public String toString() {
 +        return "PLUGIN:" + super.toString();
@@ -5808,7 +5888,7 @@ index 0000000000000000000000000000000000000000..b049691292fb9d53ac598cb333fa408b
 +}
 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
+index 0000000000000000000000000000000000000000..1c4c344eb65dd90e1d3698908b0d9b46262c9540
 --- /dev/null
 +++ b/src/main/java/io/papermc/paper/plugin/storage/SimpleProviderStorage.java
 @@ -0,0 +1,57 @@
@@ -5841,8 +5921,8 @@ index 0000000000000000000000000000000000000000..ac263f02a9a79fb3db24c4daa16c405f
 +        this.filterLoadingProviders(providerList);
 +
 +        try {
-+            for (T plugin : this.strategy.loadProviders(providerList)) {
-+                this.processProvided(plugin);
++            for (ProviderLoadingStrategy.ProviderPair<T> providerPair : this.strategy.loadProviders(providerList)) {
++                this.processProvided(providerPair.provider(), providerPair.provided());
 +            }
 +        } catch (PluginGraphCycleException exception) {
 +            this.handleCycle(exception);
@@ -5854,7 +5934,7 @@ index 0000000000000000000000000000000000000000..ac263f02a9a79fb3db24c4daa16c405f
 +        return this.providers;
 +    }
 +
-+    public void processProvided(T provided) {}
++    public void processProvided(PluginProvider<T> provider, T provided) {}
 +
 +    // Mutable enter
 +    protected void filterLoadingProviders(List<PluginProvider<T>> providers) {}
@@ -6157,6 +6237,13 @@ index 0000000000000000000000000000000000000000..a22647244037cd92262b3b5a6582f0a1
 +++ 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/main/resources/META-INF/services/org.bukkit.plugin.PluginLoader b/src/main/resources/META-INF/services/org.bukkit.plugin.PluginLoader
+new file mode 100644
+index 0000000000000000000000000000000000000000..4f78bc62d03460463b9694de933e5b73da8df6e3
+--- /dev/null
++++ b/src/main/resources/META-INF/services/org.bukkit.plugin.PluginLoader
+@@ -0,0 +1 @@
++io.papermc.paper.plugin.manager.DummyBukkitPluginLoader
 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