diff --git a/patches/api/0305-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/api/0305-Add-command-line-option-to-load-extra-plugin-jars-no.patch
index 53c0f4aab0..378170796e 100644
--- a/patches/api/0305-Add-command-line-option-to-load-extra-plugin-jars-no.patch
+++ b/patches/api/0305-Add-command-line-option-to-load-extra-plugin-jars-no.patch
@@ -6,19 +6,59 @@ Subject: [PATCH] Add command line option to load extra plugin jars not in the
ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar
+diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
+index 5ec72f013c6c94a6590e78e87d2f97e57176c6a1..3a31dedebc3f89326ead64fbd0aad556d1650802 100644
+--- a/src/main/java/org/bukkit/Bukkit.java
++++ b/src/main/java/org/bukkit/Bukkit.java
+@@ -2053,6 +2053,20 @@ public final class Bukkit {
+ return server.getCurrentTick();
+ }
+
++ /**
++ * Returns the de facto plugins directory, generally used for storing plugin jars to be loaded,
++ * as well as their {@link org.bukkit.plugin.Plugin#getDataFolder() data folders}.
++ *
++ *
Plugins should use {@link org.bukkit.plugin.Plugin#getDataFolder()} rather than traversing this
++ * directory manually when determining the location in which to store their data and configuration files.
++ *
++ * @return plugins directory
++ */
++ @NotNull
++ public static File getPluginsFolder() {
++ return server.getPluginsFolder();
++ }
++
+ /**
+ * Checks if the server is in the process of being shutdown.
+ *
+diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
+index 1db87711dd9b67bcba42e731c8c1a81502abf56c..c34cfba8f9ed7e9dbd0b6b8ffef9fba46abff046 100644
+--- a/src/main/java/org/bukkit/Server.java
++++ b/src/main/java/org/bukkit/Server.java
+@@ -1804,6 +1804,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
+ */
+ int getCurrentTick();
+
++ /**
++ * Returns the de facto plugins directory, generally used for storing plugin jars to be loaded,
++ * as well as their {@link org.bukkit.plugin.Plugin#getDataFolder() data folders}.
++ *
++ * Plugins should use {@link org.bukkit.plugin.Plugin#getDataFolder()} rather than traversing this
++ * directory manually when determining the location in which to store their data and configuration files.
++ *
++ * @return plugins directory
++ */
++ @NotNull
++ File getPluginsFolder();
++
+ /**
+ * Checks if the server is in the process of being shutdown.
+ *
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec014722978 100644
+index 20b4ef7a94e00d9264b8ecc126ce5853b584ea8c..0d9d729a18b5388b06ab0a3749e55f91f838be88 100644
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-@@ -60,6 +60,7 @@ public final class SimplePluginManager implements PluginManager {
- private final Map> permSubs = new HashMap>();
- private final Map> defSubs = new HashMap>();
- private boolean useTimings = false;
-+ private File pluginsDirectory; public @Nullable File pluginsDirectory() { return this.pluginsDirectory; } // Paper
-
- public SimplePluginManager(@NotNull Server instance, @NotNull SimpleCommandMap commandMap) {
- server = instance;
-@@ -115,6 +116,13 @@ public final class SimplePluginManager implements PluginManager {
+@@ -115,6 +115,12 @@ public final class SimplePluginManager implements PluginManager {
@Override
@NotNull
public Plugin[] loadPlugins(@NotNull File directory) {
@@ -27,12 +67,11 @@ index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec0
+ }
+ @NotNull
+ public Plugin[] loadPlugins(final @NotNull File directory, final @NotNull List extraPluginJars) {
-+ this.pluginsDirectory = directory;
+ // Paper end
Validate.notNull(directory, "Directory cannot be null");
Validate.isTrue(directory.isDirectory(), "Directory must be a directory");
-@@ -132,7 +140,11 @@ public final class SimplePluginManager implements PluginManager {
+@@ -132,7 +138,11 @@ public final class SimplePluginManager implements PluginManager {
Map> softDependencies = new HashMap>();
// This is where it figures out all possible plugins
@@ -45,7 +84,7 @@ index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec0
PluginLoader loader = null;
for (Pattern filter : filters) {
Matcher match = filter.matcher(file.getName());
-@@ -148,14 +160,14 @@ public final class SimplePluginManager implements PluginManager {
+@@ -148,14 +158,14 @@ public final class SimplePluginManager implements PluginManager {
description = loader.getPluginDescription(file);
String name = description.getName();
if (name.equalsIgnoreCase("bukkit") || name.equalsIgnoreCase("minecraft") || name.equalsIgnoreCase("mojang")) {
@@ -63,7 +102,7 @@ index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec0
continue;
}
-@@ -166,7 +178,7 @@ public final class SimplePluginManager implements PluginManager {
+@@ -166,7 +176,7 @@ public final class SimplePluginManager implements PluginManager {
description.getName(),
file.getPath(),
replacedFile.getPath(),
@@ -72,7 +111,7 @@ index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec0
));
}
-@@ -187,7 +199,7 @@ public final class SimplePluginManager implements PluginManager {
+@@ -187,7 +197,7 @@ public final class SimplePluginManager implements PluginManager {
file.getPath(),
provided,
pluginFile.getPath(),
@@ -81,7 +120,7 @@ index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec0
));
} else {
String replacedPlugin = pluginsProvided.put(provided, description.getName());
-@@ -269,7 +281,7 @@ public final class SimplePluginManager implements PluginManager {
+@@ -269,7 +279,7 @@ public final class SimplePluginManager implements PluginManager {
server.getLogger().log(
Level.SEVERE,
@@ -90,7 +129,7 @@ index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec0
new UnknownDependencyException("Unknown dependency " + dependency + ". Please download and install " + dependency + " to run this plugin."));
break;
}
-@@ -308,11 +320,11 @@ public final class SimplePluginManager implements PluginManager {
+@@ -308,11 +318,11 @@ public final class SimplePluginManager implements PluginManager {
loadedPlugins.add(loadedPlugin.getName());
loadedPlugins.addAll(loadedPlugin.getDescription().getProvides());
} else {
@@ -104,7 +143,7 @@ index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec0
}
}
}
-@@ -339,11 +351,11 @@ public final class SimplePluginManager implements PluginManager {
+@@ -339,11 +349,11 @@ public final class SimplePluginManager implements PluginManager {
loadedPlugins.add(loadedPlugin.getName());
loadedPlugins.addAll(loadedPlugin.getDescription().getProvides());
} else {
@@ -118,7 +157,7 @@ index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec0
}
}
}
-@@ -356,7 +368,7 @@ public final class SimplePluginManager implements PluginManager {
+@@ -356,7 +366,7 @@ public final class SimplePluginManager implements PluginManager {
while (failedPluginIterator.hasNext()) {
File file = failedPluginIterator.next();
failedPluginIterator.remove();
@@ -128,7 +167,7 @@ index 49e5d49eb09bb966e47d6a03ac08a527c963b43d..f988705a3cd3943b2f6f952b4f8b5ec0
}
}
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
-index 31793f46e5623729dfb4048e901f274082f57826..d3812d8cd195017841ee08ffbc53a5748fcc74ec 100644
+index 80236a0934861902db7f15571d0d9b4902e70045..d2712f45dbcf26fabe8463d99f378bf422c66970 100644
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
@@ -94,7 +94,7 @@ public final class JavaPluginLoader implements PluginLoader {
@@ -136,7 +175,7 @@ index 31793f46e5623729dfb4048e901f274082f57826..d3812d8cd195017841ee08ffbc53a574
}
- final File parentFile = file.getParentFile();
-+ final File parentFile = ((SimplePluginManager) this.server.getPluginManager()).pluginsDirectory(); // Paper
++ final File parentFile = this.server.getPluginsFolder(); // Paper
final File dataFolder = new File(parentFile, description.getName());
@SuppressWarnings("deprecation")
final File oldDataFolder = new File(parentFile, description.getRawName());
diff --git a/patches/api/0306-List-all-missing-hard-depends-not-just-first.patch b/patches/api/0306-List-all-missing-hard-depends-not-just-first.patch
index 4d1ba6ef20..995528e860 100644
--- a/patches/api/0306-List-all-missing-hard-depends-not-just-first.patch
+++ b/patches/api/0306-List-all-missing-hard-depends-not-just-first.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] List all missing hard depends not just first
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-index f988705a3cd3943b2f6f952b4f8b5ec014722978..0e25119564dfa9cb12f3c5dc5f653d7f2c147a9d 100644
+index 0d9d729a18b5388b06ab0a3749e55f91f838be88..c57a59d337a41c083e88e36637d839db027b9289 100644
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-@@ -264,6 +264,7 @@ public final class SimplePluginManager implements PluginManager {
+@@ -262,6 +262,7 @@ public final class SimplePluginManager implements PluginManager {
if (dependencies.containsKey(plugin)) {
Iterator dependencyIterator = dependencies.get(plugin).iterator();
@@ -16,7 +16,7 @@ index f988705a3cd3943b2f6f952b4f8b5ec014722978..0e25119564dfa9cb12f3c5dc5f653d7f
while (dependencyIterator.hasNext()) {
String dependency = dependencyIterator.next();
-@@ -274,6 +275,12 @@ public final class SimplePluginManager implements PluginManager {
+@@ -272,6 +273,12 @@ public final class SimplePluginManager implements PluginManager {
// We have a dependency not found
} else if (!plugins.containsKey(dependency) && !pluginsProvided.containsKey(dependency)) {
@@ -29,7 +29,7 @@ index f988705a3cd3943b2f6f952b4f8b5ec014722978..0e25119564dfa9cb12f3c5dc5f653d7f
missingDependency = false;
pluginIterator.remove();
softDependencies.remove(plugin);
-@@ -282,9 +289,7 @@ public final class SimplePluginManager implements PluginManager {
+@@ -280,9 +287,7 @@ public final class SimplePluginManager implements PluginManager {
server.getLogger().log(
Level.SEVERE,
"Could not load '" + entry.getValue().getPath() + "' in folder '" + entry.getValue().getParentFile().getPath() + "'", // Paper
@@ -65,7 +65,7 @@ index a80251eff75430863b37db1c131e22593f3fcd5e..7b2e607a21f1173d98ee845818814111
* Constructs a new UnknownDependencyException based on the given
* Exception
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
-index d3812d8cd195017841ee08ffbc53a5748fcc74ec..b622cedeeee017f042bcf92485d81832030a8030 100644
+index d2712f45dbcf26fabe8463d99f378bf422c66970..c8b11793c6a3baabc1c9566e0463ab1d6e293827 100644
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
@@ -132,13 +132,19 @@ public final class JavaPluginLoader implements PluginLoader {
diff --git a/patches/api/0334-Fix-plugin-provides-load-order.patch b/patches/api/0334-Fix-plugin-provides-load-order.patch
index b504c8d697..83c8568dff 100644
--- a/patches/api/0334-Fix-plugin-provides-load-order.patch
+++ b/patches/api/0334-Fix-plugin-provides-load-order.patch
@@ -6,10 +6,10 @@ Subject: [PATCH] Fix plugin provides load order
Fixes https://hub.spigotmc.org/jira/browse/SPIGOT-6740
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-index 0e25119564dfa9cb12f3c5dc5f653d7f2c147a9d..98fb7241d9902cd2ffc703e6c5eb2771307779f8 100644
+index c57a59d337a41c083e88e36637d839db027b9289..1366496271c4c7f72d1e5f990e51775b1c371f99 100644
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-@@ -283,6 +283,7 @@ public final class SimplePluginManager implements PluginManager {
+@@ -281,6 +281,7 @@ public final class SimplePluginManager implements PluginManager {
// Paper end
missingDependency = false;
pluginIterator.remove();
@@ -17,7 +17,7 @@ index 0e25119564dfa9cb12f3c5dc5f653d7f2c147a9d..98fb7241d9902cd2ffc703e6c5eb2771
softDependencies.remove(plugin);
dependencies.remove(plugin);
-@@ -316,6 +317,7 @@ public final class SimplePluginManager implements PluginManager {
+@@ -314,6 +315,7 @@ public final class SimplePluginManager implements PluginManager {
// We're clear to load, no more soft or hard dependencies left
File file = plugins.get(plugin);
pluginIterator.remove();
diff --git a/patches/server/0682-Add-command-line-option-to-load-extra-plugin-jars-no.patch b/patches/server/0682-Add-command-line-option-to-load-extra-plugin-jars-no.patch
index d4c446601c..5966712d5a 100644
--- a/patches/server/0682-Add-command-line-option-to-load-extra-plugin-jars-no.patch
+++ b/patches/server/0682-Add-command-line-option-to-load-extra-plugin-jars-no.patch
@@ -7,12 +7,15 @@ Subject: [PATCH] Add command line option to load extra plugin jars not in the
ex: java -jar paperclip.jar nogui -add-plugin=/path/to/plugin.jar -add-plugin=/path/to/another/plugin_jar.jar
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
-index ea902f8d525684e0e8f82bc5017bcf748f106e40..b80930a5e3812c1b02f11ff9c592ee8a39b08456 100644
+index ea902f8d525684e0e8f82bc5017bcf748f106e40..8ba95157e0273c412314a506d4f6e24b0784147b 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
-@@ -409,8 +409,13 @@ public final class CraftServer implements Server {
+@@ -407,10 +407,15 @@ public final class CraftServer implements Server {
+ public void loadPlugins() {
+ this.pluginManager.registerInterface(JavaPluginLoader.class);
- File pluginFolder = (File) console.options.valueOf("plugins");
+- File pluginFolder = (File) console.options.valueOf("plugins");
++ File pluginFolder = this.getPluginsFolder(); // Paper
- if (pluginFolder.exists()) {
- Plugin[] plugins = this.pluginManager.loadPlugins(pluginFolder);
@@ -26,19 +29,36 @@ index ea902f8d525684e0e8f82bc5017bcf748f106e40..b80930a5e3812c1b02f11ff9c592ee8a
for (Plugin plugin : plugins) {
try {
String message = String.format("Loading %s", plugin.getDescription().getFullName());
-@@ -425,6 +430,18 @@ public final class CraftServer implements Server {
+@@ -425,6 +430,35 @@ public final class CraftServer implements Server {
}
}
+ // Paper start
++ @Override
++ public File getPluginsFolder() {
++ return (File) this.console.options.valueOf("plugins");
++ }
++
+ private List extraPluginJars() {
+ @SuppressWarnings("unchecked")
+ final List jars = (List) this.console.options.valuesOf("add-plugin");
-+ return jars.stream()
-+ .filter(File::exists)
-+ .filter(File::isFile)
-+ .filter(file -> file.getName().endsWith(".jar"))
-+ .collect(java.util.stream.Collectors.toList());
++ final List list = new ArrayList<>();
++ for (final File file : jars) {
++ if (!file.exists()) {
++ MinecraftServer.LOGGER.warn("File '{}' specified through 'add-plugin' argument does not exist, cannot load a plugin from it!", file.getAbsolutePath());
++ continue;
++ }
++ if (!file.isFile()) {
++ MinecraftServer.LOGGER.warn("File '{}' specified through 'add-plugin' argument is not a file, cannot load a plugin from it!", file.getAbsolutePath());
++ continue;
++ }
++ if (!file.getName().endsWith(".jar")) {
++ MinecraftServer.LOGGER.warn("File '{}' specified through 'add-plugin' argument is not a jar file, cannot load a plugin from it!", file.getAbsolutePath());
++ continue;
++ }
++ list.add(file);
++ }
++ return list;
+ }
+ // Paper end
+
diff --git a/patches/server/0683-Fix-and-optimise-world-force-upgrading.patch b/patches/server/0683-Fix-and-optimise-world-force-upgrading.patch
index f35b278639..1b2d426e71 100644
--- a/patches/server/0683-Fix-and-optimise-world-force-upgrading.patch
+++ b/patches/server/0683-Fix-and-optimise-world-force-upgrading.patch
@@ -265,7 +265,7 @@ index cf0a74b8a1c31d4bc493eb09a69ee2bd94cb6485..cfd43069ee2b6f79afb12e10d223f6bf
Main.LOGGER.info("Forcing world upgrade! {}", session.getLevelId()); // CraftBukkit
WorldUpgrader worldupgrader = new WorldUpgrader(session, dataFixer, worlds, eraseCache);
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
-index 33dcb39428c3bd24daa600c2b486954466d81eef..1f6d59d1a95fcc8f93685a9ed6bb1d9419aafb95 100644
+index 84afe36963178aa0319e219244ddbe6f0b91260b..be6b19b587ae2bbc708d712fc4327e4c56b7197c 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -563,13 +563,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata));
-@@ -1211,6 +1204,14 @@ public final class CraftServer implements Server {
+@@ -1228,6 +1221,14 @@ public final class CraftServer implements Server {
}
}