Paper Plugins
This commit is contained in:
@@ -146,4 +146,14 @@ public interface UnsafeValues {
|
||||
|
||||
@ApiStatus.Internal
|
||||
Biome getCustomBiome();
|
||||
|
||||
// Paper start
|
||||
@Deprecated(forRemoval = true)
|
||||
boolean isSupportedApiVersion(String apiVersion);
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
static boolean isLegacyPlugin(org.bukkit.plugin.Plugin plugin) {
|
||||
return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion());
|
||||
}
|
||||
// Paper end
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public final class PluginCommand extends Command implements PluginIdentifiableCo
|
||||
private CommandExecutor executor;
|
||||
private TabCompleter completer;
|
||||
|
||||
protected PluginCommand(@NotNull String name, @NotNull Plugin owner) {
|
||||
PluginCommand(@NotNull String name, @NotNull Plugin owner) {
|
||||
super(name);
|
||||
this.executor = owner;
|
||||
this.owningPlugin = owner;
|
||||
|
||||
@@ -35,7 +35,7 @@ public class SimpleCommandMap implements CommandMap {
|
||||
private void setDefaultCommands() {
|
||||
register("bukkit", new VersionCommand("version"));
|
||||
register("bukkit", new ReloadCommand("reload"));
|
||||
register("bukkit", new PluginsCommand("plugins"));
|
||||
//register("bukkit", new PluginsCommand("plugins")); // Paper
|
||||
register("bukkit", new TimingsCommand("timings"));
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Deprecated(forRemoval = true) // Paper
|
||||
public class PluginsCommand extends BukkitCommand {
|
||||
public PluginsCommand(@NotNull String name) {
|
||||
super(name);
|
||||
|
||||
@@ -30,10 +30,21 @@ public interface Plugin extends TabExecutor {
|
||||
* Returns the plugin.yaml file containing the details for this plugin
|
||||
*
|
||||
* @return Contents of the plugin.yaml file
|
||||
* @deprecated May be inaccurate due to different plugin implementations.
|
||||
* @see Plugin#getPluginMeta()
|
||||
*/
|
||||
@Deprecated // Paper
|
||||
@NotNull
|
||||
public PluginDescriptionFile getDescription();
|
||||
|
||||
// Paper start
|
||||
/**
|
||||
* Gets the plugin meta for this plugin.
|
||||
* @return configuration
|
||||
*/
|
||||
@NotNull
|
||||
io.papermc.paper.plugin.configuration.PluginMeta getPluginMeta();
|
||||
// Paper end
|
||||
/**
|
||||
* Gets a {@link FileConfiguration} for this plugin, read through
|
||||
* "config.yml"
|
||||
@@ -94,6 +105,7 @@ public interface Plugin extends TabExecutor {
|
||||
*
|
||||
* @return PluginLoader that controls this plugin
|
||||
*/
|
||||
@Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future
|
||||
@NotNull
|
||||
public PluginLoader getPluginLoader();
|
||||
|
||||
|
||||
@@ -31,6 +31,6 @@ public abstract class PluginBase implements Plugin {
|
||||
@Override
|
||||
@NotNull
|
||||
public final String getName() {
|
||||
return getDescription().getName();
|
||||
return getPluginMeta().getName(); // Paper
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ import org.yaml.snakeyaml.representer.Representer;
|
||||
* inferno.burningdeaths: true
|
||||
*</pre></blockquote>
|
||||
*/
|
||||
public final class PluginDescriptionFile {
|
||||
public final class PluginDescriptionFile implements io.papermc.paper.plugin.configuration.PluginMeta { // Paper
|
||||
private static final Pattern VALID_NAME = Pattern.compile("^[A-Za-z0-9 _.-]+$");
|
||||
private static final ThreadLocal<Yaml> YAML = new ThreadLocal<Yaml>() {
|
||||
@Override
|
||||
@@ -260,6 +260,70 @@ public final class PluginDescriptionFile {
|
||||
private Set<PluginAwareness> awareness = ImmutableSet.of();
|
||||
private String apiVersion = null;
|
||||
private List<String> libraries = ImmutableList.of();
|
||||
// Paper start - oh my goddddd
|
||||
/**
|
||||
* Don't use this.
|
||||
*/
|
||||
@org.jetbrains.annotations.ApiStatus.Internal
|
||||
public PluginDescriptionFile(String rawName, String name, List<String> provides, String main, String classLoaderOf, List<String> depend, List<String> softDepend, List<String> loadBefore, String version, Map<String, Map<String, Object>> commands, String description, List<String> authors, List<String> contributors, String website, String prefix, PluginLoadOrder order, List<Permission> permissions, PermissionDefault defaultPerm, Set<PluginAwareness> awareness, String apiVersion, List<String> libraries) {
|
||||
this.rawName = rawName;
|
||||
this.name = name;
|
||||
this.provides = provides;
|
||||
this.main = main;
|
||||
this.classLoaderOf = classLoaderOf;
|
||||
this.depend = depend;
|
||||
this.softDepend = softDepend;
|
||||
this.loadBefore = loadBefore;
|
||||
this.version = version;
|
||||
this.commands = commands;
|
||||
this.description = description;
|
||||
this.authors = authors;
|
||||
this.contributors = contributors;
|
||||
this.website = website;
|
||||
this.prefix = prefix;
|
||||
this.order = order;
|
||||
this.permissions = permissions;
|
||||
this.defaultPerm = defaultPerm;
|
||||
this.awareness = awareness;
|
||||
this.apiVersion = apiVersion;
|
||||
this.libraries = libraries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getMainClass() {
|
||||
return this.main;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PluginLoadOrder getLoadOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getLoggerPrefix() {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> getPluginDependencies() {
|
||||
return this.depend;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> getPluginSoftDependencies() {
|
||||
return this.softDepend;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> getLoadBeforePlugins() {
|
||||
return this.loadBefore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<String> getProvidedPlugins() {
|
||||
return this.provides;
|
||||
}
|
||||
// Paper end
|
||||
|
||||
public PluginDescriptionFile(@NotNull final InputStream stream) throws InvalidDescriptionException {
|
||||
loadMap(asMap(YAML.get().load(stream)));
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
* Represents a plugin loader, which handles direct access to specific types
|
||||
* of plugins
|
||||
*/
|
||||
@Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future
|
||||
public interface PluginLoader {
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* Handles all plugin management from the Server
|
||||
*/
|
||||
public interface PluginManager {
|
||||
public interface PluginManager extends io.papermc.paper.plugin.PermissionManager { // Paper
|
||||
|
||||
/**
|
||||
* Registers the specified plugin loader
|
||||
@@ -23,6 +23,7 @@ public interface PluginManager {
|
||||
* @throws IllegalArgumentException Thrown when the given Class is not a
|
||||
* valid PluginLoader
|
||||
*/
|
||||
@Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future
|
||||
public void registerInterface(@NotNull Class<? extends PluginLoader> loader) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
@@ -312,4 +313,17 @@ public interface PluginManager {
|
||||
* @return True if event timings are to be used
|
||||
*/
|
||||
public boolean useTimings();
|
||||
|
||||
// Paper start
|
||||
@org.jetbrains.annotations.ApiStatus.Internal
|
||||
boolean isTransitiveDependency(io.papermc.paper.plugin.configuration.PluginMeta pluginMeta, io.papermc.paper.plugin.configuration.PluginMeta dependencyConfig);
|
||||
|
||||
/**
|
||||
* Sets the permission manager to be used for this server.
|
||||
*
|
||||
* @param permissionManager permission manager
|
||||
*/
|
||||
@org.jetbrains.annotations.ApiStatus.Experimental
|
||||
void overridePermissionManager(@NotNull Plugin plugin, @Nullable io.papermc.paper.plugin.PermissionManager permissionManager);
|
||||
// Paper end
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* Handles all plugin management from the Server
|
||||
*/
|
||||
@Deprecated(forRemoval = true) // Paper - This implementation may be replaced in a future version of Paper.
|
||||
// Plugins may still reflect into this class to modify permission logic for the time being.
|
||||
public final class SimplePluginManager implements PluginManager {
|
||||
private final Server server;
|
||||
private final Map<Pattern, PluginLoader> fileAssociations = new HashMap<Pattern, PluginLoader>();
|
||||
@@ -52,10 +54,13 @@ public final class SimplePluginManager implements PluginManager {
|
||||
private MutableGraph<String> dependencyGraph = GraphBuilder.directed().build();
|
||||
private File updateDirectory;
|
||||
private final SimpleCommandMap commandMap;
|
||||
private final Map<String, Permission> permissions = new HashMap<String, Permission>();
|
||||
private final Map<Boolean, Set<Permission>> defaultPerms = new LinkedHashMap<Boolean, Set<Permission>>();
|
||||
private final Map<String, Map<Permissible, Boolean>> permSubs = new HashMap<String, Map<Permissible, Boolean>>();
|
||||
private final Map<Boolean, Map<Permissible, Boolean>> defSubs = new HashMap<Boolean, Map<Permissible, Boolean>>();
|
||||
// Paper start
|
||||
public final Map<String, Permission> permissions = new HashMap<String, Permission>();
|
||||
public final Map<Boolean, Set<Permission>> defaultPerms = new LinkedHashMap<Boolean, Set<Permission>>();
|
||||
public final Map<String, Map<Permissible, Boolean>> permSubs = new HashMap<String, Map<Permissible, Boolean>>();
|
||||
public final Map<Boolean, Map<Permissible, Boolean>> defSubs = new HashMap<Boolean, Map<Permissible, Boolean>>();
|
||||
public PluginManager paperPluginManager;
|
||||
// Paper end
|
||||
private boolean useTimings = false;
|
||||
|
||||
public SimplePluginManager(@NotNull Server instance, @NotNull SimpleCommandMap commandMap) {
|
||||
@@ -112,6 +117,11 @@ public final class SimplePluginManager implements PluginManager {
|
||||
@Override
|
||||
@NotNull
|
||||
public Plugin[] loadPlugins(@NotNull File directory) {
|
||||
if (true) {
|
||||
List<Plugin> pluginList = new ArrayList<>();
|
||||
java.util.Collections.addAll(pluginList, this.paperPluginManager.loadPlugins(directory));
|
||||
return pluginList.toArray(new Plugin[0]);
|
||||
}
|
||||
Preconditions.checkArgument(directory != null, "Directory cannot be null");
|
||||
Preconditions.checkArgument(directory.isDirectory(), "Directory must be a directory");
|
||||
|
||||
@@ -130,6 +140,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
*/
|
||||
@NotNull
|
||||
public Plugin[] loadPlugins(@NotNull File[] files) {
|
||||
// TODO Replace with Paper plugin loader
|
||||
Preconditions.checkArgument(files != null, "File list cannot be null");
|
||||
|
||||
List<Plugin> result = new ArrayList<Plugin>();
|
||||
@@ -390,6 +401,15 @@ public final class SimplePluginManager implements PluginManager {
|
||||
@Nullable
|
||||
public synchronized Plugin loadPlugin(@NotNull File file) throws InvalidPluginException, UnknownDependencyException {
|
||||
Preconditions.checkArgument(file != null, "File cannot be null");
|
||||
// Paper start
|
||||
if (true) {
|
||||
try {
|
||||
return this.paperPluginManager.loadPlugin(file);
|
||||
} catch (org.bukkit.plugin.InvalidDescriptionException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Paper end
|
||||
|
||||
checkUpdate(file);
|
||||
|
||||
@@ -440,12 +460,14 @@ public final class SimplePluginManager implements PluginManager {
|
||||
@Override
|
||||
@Nullable
|
||||
public synchronized Plugin getPlugin(@NotNull String name) {
|
||||
if (true) {return this.paperPluginManager.getPlugin(name);} // Paper
|
||||
return lookupNames.get(name.replace(' ', '_'));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public synchronized Plugin[] getPlugins() {
|
||||
if (true) {return this.paperPluginManager.getPlugins();} // Paper
|
||||
return plugins.toArray(new Plugin[plugins.size()]);
|
||||
}
|
||||
|
||||
@@ -459,6 +481,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
*/
|
||||
@Override
|
||||
public boolean isPluginEnabled(@NotNull String name) {
|
||||
if (true) {return this.paperPluginManager.isPluginEnabled(name);} // Paper
|
||||
Plugin plugin = getPlugin(name);
|
||||
|
||||
return isPluginEnabled(plugin);
|
||||
@@ -472,6 +495,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
*/
|
||||
@Override
|
||||
public boolean isPluginEnabled(@Nullable Plugin plugin) {
|
||||
if (true) {return this.paperPluginManager.isPluginEnabled(plugin);} // Paper
|
||||
if ((plugin != null) && (plugins.contains(plugin))) {
|
||||
return plugin.isEnabled();
|
||||
} else {
|
||||
@@ -481,6 +505,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public void enablePlugin(@NotNull final Plugin plugin) {
|
||||
if (true) {this.paperPluginManager.enablePlugin(plugin); return;} // Paper
|
||||
if (!plugin.isEnabled()) {
|
||||
List<Command> pluginCommands = PluginCommandYamlParser.parse(plugin);
|
||||
|
||||
@@ -500,6 +525,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public void disablePlugins() {
|
||||
if (true) {this.paperPluginManager.disablePlugins(); return;} // Paper
|
||||
Plugin[] plugins = getPlugins();
|
||||
for (int i = plugins.length - 1; i >= 0; i--) {
|
||||
disablePlugin(plugins[i]);
|
||||
@@ -508,6 +534,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public void disablePlugin(@NotNull final Plugin plugin) {
|
||||
if (true) {this.paperPluginManager.disablePlugin(plugin); return;} // Paper
|
||||
if (plugin.isEnabled()) {
|
||||
try {
|
||||
plugin.getPluginLoader().disablePlugin(plugin);
|
||||
@@ -552,6 +579,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public void clearPlugins() {
|
||||
if (true) {this.paperPluginManager.clearPlugins(); return;} // Paper
|
||||
synchronized (this) {
|
||||
disablePlugins();
|
||||
plugins.clear();
|
||||
@@ -572,6 +600,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
*/
|
||||
@Override
|
||||
public void callEvent(@NotNull Event event) {
|
||||
if (true) {this.paperPluginManager.callEvent(event); return;} // Paper
|
||||
if (event.isAsynchronous()) {
|
||||
if (Thread.holdsLock(this)) {
|
||||
throw new IllegalStateException(event.getEventName() + " cannot be triggered asynchronously from inside synchronized code.");
|
||||
@@ -620,6 +649,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public void registerEvents(@NotNull Listener listener, @NotNull Plugin plugin) {
|
||||
if (true) {this.paperPluginManager.registerEvents(listener, plugin); return;} // Paper
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalPluginAccessException("Plugin attempted to register " + listener + " while not enabled");
|
||||
}
|
||||
@@ -653,6 +683,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
Preconditions.checkArgument(priority != null, "Priority cannot be null");
|
||||
Preconditions.checkArgument(executor != null, "Executor cannot be null");
|
||||
Preconditions.checkArgument(plugin != null, "Plugin cannot be null");
|
||||
if (true) {this.paperPluginManager.registerEvent(event, listener, priority, executor, plugin, ignoreCancelled); return;} // Paper
|
||||
|
||||
if (!plugin.isEnabled()) {
|
||||
throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled");
|
||||
@@ -700,16 +731,19 @@ public final class SimplePluginManager implements PluginManager {
|
||||
@Override
|
||||
@Nullable
|
||||
public Permission getPermission(@NotNull String name) {
|
||||
if (true) {return this.paperPluginManager.getPermission(name);} // Paper
|
||||
return permissions.get(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPermission(@NotNull Permission perm) {
|
||||
if (true) {this.paperPluginManager.addPermission(perm); return;} // Paper
|
||||
addPermission(perm, true);
|
||||
}
|
||||
|
||||
@Deprecated(since = "1.12")
|
||||
public void addPermission(@NotNull Permission perm, boolean dirty) {
|
||||
if (true) {this.paperPluginManager.addPermission(perm); return;} // Paper - This just has a performance implication, use the better api to avoid this.
|
||||
String name = perm.getName().toLowerCase(Locale.ROOT);
|
||||
|
||||
if (permissions.containsKey(name)) {
|
||||
@@ -723,21 +757,25 @@ public final class SimplePluginManager implements PluginManager {
|
||||
@Override
|
||||
@NotNull
|
||||
public Set<Permission> getDefaultPermissions(boolean op) {
|
||||
if (true) {return this.paperPluginManager.getDefaultPermissions(op);} // Paper
|
||||
return ImmutableSet.copyOf(defaultPerms.get(op));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePermission(@NotNull Permission perm) {
|
||||
if (true) {this.paperPluginManager.removePermission(perm); return;} // Paper
|
||||
removePermission(perm.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePermission(@NotNull String name) {
|
||||
if (true) {this.paperPluginManager.removePermission(name); return;} // Paper
|
||||
permissions.remove(name.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recalculatePermissionDefaults(@NotNull Permission perm) {
|
||||
if (true) {this.paperPluginManager.recalculatePermissionDefaults(perm); return;} // Paper
|
||||
if (perm != null && permissions.containsKey(perm.getName().toLowerCase(Locale.ROOT))) {
|
||||
defaultPerms.get(true).remove(perm);
|
||||
defaultPerms.get(false).remove(perm);
|
||||
@@ -777,6 +815,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public void subscribeToPermission(@NotNull String permission, @NotNull Permissible permissible) {
|
||||
if (true) {this.paperPluginManager.subscribeToPermission(permission, permissible); return;} // Paper
|
||||
String name = permission.toLowerCase(Locale.ROOT);
|
||||
Map<Permissible, Boolean> map = permSubs.get(name);
|
||||
|
||||
@@ -790,6 +829,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public void unsubscribeFromPermission(@NotNull String permission, @NotNull Permissible permissible) {
|
||||
if (true) {this.paperPluginManager.unsubscribeFromPermission(permission, permissible); return;} // Paper
|
||||
String name = permission.toLowerCase(Locale.ROOT);
|
||||
Map<Permissible, Boolean> map = permSubs.get(name);
|
||||
|
||||
@@ -805,6 +845,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
@Override
|
||||
@NotNull
|
||||
public Set<Permissible> getPermissionSubscriptions(@NotNull String permission) {
|
||||
if (true) {return this.paperPluginManager.getPermissionSubscriptions(permission);} // Paper
|
||||
String name = permission.toLowerCase(Locale.ROOT);
|
||||
Map<Permissible, Boolean> map = permSubs.get(name);
|
||||
|
||||
@@ -817,6 +858,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public void subscribeToDefaultPerms(boolean op, @NotNull Permissible permissible) {
|
||||
if (true) {this.paperPluginManager.subscribeToDefaultPerms(op, permissible); return;} // Paper
|
||||
Map<Permissible, Boolean> map = defSubs.get(op);
|
||||
|
||||
if (map == null) {
|
||||
@@ -829,6 +871,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public void unsubscribeFromDefaultPerms(boolean op, @NotNull Permissible permissible) {
|
||||
if (true) {this.paperPluginManager.unsubscribeFromDefaultPerms(op, permissible); return;} // Paper
|
||||
Map<Permissible, Boolean> map = defSubs.get(op);
|
||||
|
||||
if (map != null) {
|
||||
@@ -843,6 +886,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
@Override
|
||||
@NotNull
|
||||
public Set<Permissible> getDefaultPermSubscriptions(boolean op) {
|
||||
if (true) {return this.paperPluginManager.getDefaultPermSubscriptions(op);} // Paper
|
||||
Map<Permissible, Boolean> map = defSubs.get(op);
|
||||
|
||||
if (map == null) {
|
||||
@@ -855,6 +899,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
@Override
|
||||
@NotNull
|
||||
public Set<Permission> getPermissions() {
|
||||
if (true) {return this.paperPluginManager.getPermissions();} // Paper
|
||||
return new HashSet<Permission>(permissions.values());
|
||||
}
|
||||
|
||||
@@ -878,6 +923,7 @@ public final class SimplePluginManager implements PluginManager {
|
||||
|
||||
@Override
|
||||
public boolean useTimings() {
|
||||
if (true) {return this.paperPluginManager.useTimings();} // Paper
|
||||
return useTimings;
|
||||
}
|
||||
|
||||
@@ -889,4 +935,28 @@ public final class SimplePluginManager implements PluginManager {
|
||||
public void useTimings(boolean use) {
|
||||
useTimings = use;
|
||||
}
|
||||
|
||||
// Paper start
|
||||
public void clearPermissions() {
|
||||
if (true) {this.paperPluginManager.clearPermissions(); return;} // Paper
|
||||
permissions.clear();
|
||||
defaultPerms.get(true).clear();
|
||||
defaultPerms.get(false).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransitiveDependency(io.papermc.paper.plugin.configuration.PluginMeta pluginMeta, io.papermc.paper.plugin.configuration.PluginMeta dependencyConfig) {
|
||||
return this.paperPluginManager.isTransitiveDependency(pluginMeta, dependencyConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void overridePermissionManager(@NotNull Plugin plugin, @Nullable io.papermc.paper.plugin.PermissionManager permissionManager) {
|
||||
this.paperPluginManager.overridePermissionManager(plugin, permissionManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPermissions(@NotNull List<Permission> perm) {
|
||||
this.paperPluginManager.addPermissions(perm);
|
||||
}
|
||||
// Paper end
|
||||
}
|
||||
|
||||
@@ -43,4 +43,16 @@ public class UnknownDependencyException extends RuntimeException {
|
||||
public UnknownDependencyException() {
|
||||
|
||||
}
|
||||
// Paper start
|
||||
/**
|
||||
* Create a new {@link UnknownDependencyException} with a message informing
|
||||
* about which dependencies are missing for what plugin.
|
||||
*
|
||||
* @param missingDependencies missing dependencies
|
||||
* @param pluginName plugin which is missing said dependencies
|
||||
*/
|
||||
public UnknownDependencyException(final @org.jetbrains.annotations.NotNull java.util.Collection<String> missingDependencies, final @org.jetbrains.annotations.NotNull String pluginName) {
|
||||
this("Unknown/missing dependency plugins: [" + String.join(", ", missingDependencies) + "]. Please download and install these plugins to run '" + pluginName + "'.");
|
||||
}
|
||||
// Paper end
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
private Server server = null;
|
||||
private File file = null;
|
||||
private PluginDescriptionFile description = null;
|
||||
private io.papermc.paper.plugin.configuration.PluginMeta pluginMeta = null; // Paper
|
||||
private File dataFolder = null;
|
||||
private ClassLoader classLoader = null;
|
||||
private boolean naggable = true;
|
||||
@@ -49,13 +50,16 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
private PluginLogger logger = null;
|
||||
|
||||
public JavaPlugin() {
|
||||
final ClassLoader classLoader = this.getClass().getClassLoader();
|
||||
if (!(classLoader instanceof PluginClassLoader)) {
|
||||
throw new IllegalStateException("JavaPlugin requires " + PluginClassLoader.class.getName());
|
||||
// Paper start
|
||||
if (this.getClass().getClassLoader() instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader) {
|
||||
configuredPluginClassLoader.init(this);
|
||||
} else {
|
||||
throw new IllegalStateException("JavaPlugin requires to be created by a valid classloader.");
|
||||
}
|
||||
((PluginClassLoader) classLoader).initialize(this);
|
||||
// Paper end
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true) // Paper
|
||||
protected JavaPlugin(@NotNull final JavaPluginLoader loader, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file) {
|
||||
final ClassLoader classLoader = this.getClass().getClassLoader();
|
||||
if (classLoader instanceof PluginClassLoader) {
|
||||
@@ -80,9 +84,12 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
* Gets the associated PluginLoader responsible for this plugin
|
||||
*
|
||||
* @return PluginLoader that controls this plugin
|
||||
* @deprecated Plugin loading now occurs at a point which makes it impossible to expose this
|
||||
* behavior. This instance will only throw unsupported operation exceptions.
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
@Deprecated(forRemoval = true) // Paper
|
||||
public final PluginLoader getPluginLoader() {
|
||||
return loader;
|
||||
}
|
||||
@@ -123,13 +130,20 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
* Returns the plugin.yaml file containing the details for this plugin
|
||||
*
|
||||
* @return Contents of the plugin.yaml file
|
||||
* @deprecated No longer applicable to all types of plugins
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
@Deprecated
|
||||
public final PluginDescriptionFile getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public final io.papermc.paper.plugin.configuration.PluginMeta getPluginMeta() {
|
||||
return this.pluginMeta;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FileConfiguration getConfig() {
|
||||
@@ -259,7 +273,8 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
*
|
||||
* @param enabled true if enabled, otherwise false
|
||||
*/
|
||||
protected final void setEnabled(final boolean enabled) {
|
||||
@org.jetbrains.annotations.ApiStatus.Internal // Paper
|
||||
public final void setEnabled(final boolean enabled) { // Paper
|
||||
if (isEnabled != enabled) {
|
||||
isEnabled = enabled;
|
||||
|
||||
@@ -271,9 +286,18 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final void init(@NotNull PluginLoader loader, @NotNull Server server, @NotNull PluginDescriptionFile description, @NotNull File dataFolder, @NotNull File file, @NotNull ClassLoader classLoader) {
|
||||
this.loader = loader;
|
||||
// Paper start
|
||||
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 = DummyPluginLoaderImplHolder.INSTANCE; // Paper
|
||||
this.server = server;
|
||||
this.file = file;
|
||||
this.description = description;
|
||||
@@ -281,6 +305,7 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
this.classLoader = classLoader;
|
||||
this.configFile = new File(dataFolder, "config.yml");
|
||||
this.logger = new PluginLogger(this);
|
||||
this.pluginMeta = configuration; // Paper
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -397,10 +422,10 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
throw new IllegalArgumentException(clazz + " does not extend " + JavaPlugin.class);
|
||||
}
|
||||
final ClassLoader cl = clazz.getClassLoader();
|
||||
if (!(cl instanceof PluginClassLoader)) {
|
||||
throw new IllegalArgumentException(clazz + " is not initialized by " + PluginClassLoader.class);
|
||||
if (!(cl instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader)) { // Paper
|
||||
throw new IllegalArgumentException(clazz + " is not initialized by a " + io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader.class); // Paper
|
||||
}
|
||||
JavaPlugin plugin = ((PluginClassLoader) cl).plugin;
|
||||
JavaPlugin plugin = configuredPluginClassLoader.getPlugin(); // Paper
|
||||
if (plugin == null) {
|
||||
throw new IllegalStateException("Cannot get plugin for " + clazz + " from a static initializer");
|
||||
}
|
||||
@@ -423,10 +448,10 @@ public abstract class JavaPlugin extends PluginBase {
|
||||
public static JavaPlugin getProvidingPlugin(@NotNull Class<?> clazz) {
|
||||
Preconditions.checkArgument(clazz != null, "Null class cannot have a plugin");
|
||||
final ClassLoader cl = clazz.getClassLoader();
|
||||
if (!(cl instanceof PluginClassLoader)) {
|
||||
throw new IllegalArgumentException(clazz + " is not provided by " + PluginClassLoader.class);
|
||||
if (!(cl instanceof io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader configuredPluginClassLoader)) { // Paper
|
||||
throw new IllegalArgumentException(clazz + " is not provided by a " + io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader.class); // Paper
|
||||
}
|
||||
JavaPlugin plugin = ((PluginClassLoader) cl).plugin;
|
||||
JavaPlugin plugin = configuredPluginClassLoader.getPlugin(); // Paper
|
||||
if (plugin == null) {
|
||||
throw new IllegalStateException("Cannot get plugin for " + clazz + " from a static initializer");
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.yaml.snakeyaml.error.YAMLException;
|
||||
/**
|
||||
* Represents a Java plugin loader, allowing plugins in the form of .jar
|
||||
*/
|
||||
@Deprecated(forRemoval = true) // Paper - The PluginLoader system will not function in the near future. This implementation will be moved.
|
||||
public final class JavaPluginLoader implements PluginLoader {
|
||||
final Server server;
|
||||
private final Pattern[] fileFilters = new Pattern[]{Pattern.compile("\\.jar$")};
|
||||
@@ -79,6 +80,7 @@ public final class JavaPluginLoader implements PluginLoader {
|
||||
@Override
|
||||
@NotNull
|
||||
public Plugin loadPlugin(@NotNull final File file) throws InvalidPluginException {
|
||||
if (true) throw new UnsupportedOperationException(); // Paper
|
||||
Preconditions.checkArgument(file != null, "File cannot be null");
|
||||
|
||||
if (!file.exists()) {
|
||||
@@ -142,7 +144,7 @@ public final class JavaPluginLoader implements PluginLoader {
|
||||
|
||||
final PluginClassLoader loader;
|
||||
try {
|
||||
loader = new PluginClassLoader(this, getClass().getClassLoader(), description, dataFolder, file, (libraryLoader != null) ? libraryLoader.createLoader(description) : null);
|
||||
loader = new PluginClassLoader(getClass().getClassLoader(), description, dataFolder, file, (libraryLoader != null) ? libraryLoader.createLoader(description) : null, null, null); // Paper
|
||||
} catch (InvalidPluginException ex) {
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
|
||||
@@ -36,7 +36,10 @@ import org.eclipse.aether.transport.http.HttpTransporterFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class LibraryLoader
|
||||
// Paper start
|
||||
@org.jetbrains.annotations.ApiStatus.Internal
|
||||
public class LibraryLoader
|
||||
// Paper end
|
||||
{
|
||||
|
||||
private final Logger logger;
|
||||
@@ -55,6 +58,7 @@ class LibraryLoader
|
||||
this.repository = locator.getService( RepositorySystem.class );
|
||||
this.session = MavenRepositorySystemUtils.newSession();
|
||||
|
||||
session.setSystemProperties(System.getProperties()); // Paper - paper plugins, backport system properties fix for transitive dependency parsing, see #10116
|
||||
session.setChecksumPolicy( RepositoryPolicy.CHECKSUM_POLICY_FAIL );
|
||||
session.setLocalRepositoryManager( repository.newLocalRepositoryManager( session, new LocalRepository( "libraries" ) ) );
|
||||
session.setTransferListener( new AbstractTransferListener()
|
||||
@@ -84,7 +88,7 @@ class LibraryLoader
|
||||
}
|
||||
logger.log( Level.INFO, "[{0}] Loading {1} libraries... please wait", new Object[]
|
||||
{
|
||||
desc.getName(), desc.getLibraries().size()
|
||||
java.util.Objects.requireNonNullElseGet(desc.getPrefix(), desc::getName), desc.getLibraries().size() // Paper - use configured log prefix
|
||||
} );
|
||||
|
||||
List<Dependency> dependencies = new ArrayList<>();
|
||||
@@ -122,7 +126,7 @@ class LibraryLoader
|
||||
jarFiles.add( url );
|
||||
logger.log( Level.INFO, "[{0}] Loaded library {1}", new Object[]
|
||||
{
|
||||
desc.getName(), file
|
||||
java.util.Objects.requireNonNullElseGet(desc.getPrefix(), desc::getName), file // Paper - use configured log prefix
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* A ClassLoader for plugins, to allow shared classes across multiple plugins
|
||||
*/
|
||||
final class PluginClassLoader extends URLClassLoader {
|
||||
@org.jetbrains.annotations.ApiStatus.Internal // Paper
|
||||
public final class PluginClassLoader extends URLClassLoader implements io.papermc.paper.plugin.provider.classloader.ConfiguredPluginClassLoader { // Paper
|
||||
private final JavaPluginLoader loader;
|
||||
private final Map<String, Class<?>> classes = new ConcurrentHashMap<String, Class<?>>();
|
||||
private final PluginDescriptionFile description;
|
||||
@@ -45,24 +46,32 @@ final class PluginClassLoader extends URLClassLoader {
|
||||
private JavaPlugin pluginInit;
|
||||
private IllegalStateException pluginState;
|
||||
private final Set<String> seenIllegalAccess = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
private java.util.logging.Logger logger; // Paper - add field
|
||||
private io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup classLoaderGroup; // Paper
|
||||
public io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext; // Paper
|
||||
|
||||
static {
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
}
|
||||
|
||||
PluginClassLoader(@NotNull final JavaPluginLoader loader, @Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader) throws IOException, InvalidPluginException, MalformedURLException {
|
||||
@org.jetbrains.annotations.ApiStatus.Internal // Paper
|
||||
public PluginClassLoader(@Nullable final ClassLoader parent, @NotNull final PluginDescriptionFile description, @NotNull final File dataFolder, @NotNull final File file, @Nullable ClassLoader libraryLoader, JarFile jarFile, io.papermc.paper.plugin.provider.entrypoint.DependencyContext dependencyContext) throws IOException, InvalidPluginException, MalformedURLException { // Paper - use JarFile provided by SpigotPluginProvider
|
||||
super(new URL[] {file.toURI().toURL()}, parent);
|
||||
Preconditions.checkArgument(loader != null, "Loader cannot be null");
|
||||
this.loader = null; // Paper - pass null into loader field
|
||||
|
||||
this.loader = loader;
|
||||
this.description = description;
|
||||
this.dataFolder = dataFolder;
|
||||
this.file = file;
|
||||
this.jar = new JarFile(file);
|
||||
this.jar = jarFile; // Paper - use JarFile provided by SpigotPluginProvider
|
||||
this.manifest = jar.getManifest();
|
||||
this.url = file.toURI().toURL();
|
||||
this.libraryLoader = libraryLoader;
|
||||
|
||||
// Paper start
|
||||
this.dependencyContext = dependencyContext;
|
||||
this.classLoaderGroup = io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage.instance().registerSpigotGroup(this);
|
||||
// Paper end
|
||||
|
||||
Class<?> jarClass;
|
||||
try {
|
||||
jarClass = Class.forName(description.getMain(), true, this);
|
||||
@@ -107,6 +116,27 @@ final class PluginClassLoader extends URLClassLoader {
|
||||
return findResources(name);
|
||||
}
|
||||
|
||||
// Paper start
|
||||
@Override
|
||||
public Class<?> loadClass(@NotNull String name, boolean resolve, boolean checkGlobal, boolean checkLibraries) throws ClassNotFoundException {
|
||||
return this.loadClass0(name, resolve, checkGlobal, checkLibraries);
|
||||
}
|
||||
@Override
|
||||
public io.papermc.paper.plugin.configuration.PluginMeta getConfiguration() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(JavaPlugin plugin) {
|
||||
this.initialize(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaPlugin getPlugin() {
|
||||
return this.plugin;
|
||||
}
|
||||
// Paper end
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
return loadClass0(name, resolve, true, true);
|
||||
@@ -132,26 +162,11 @@ final class PluginClassLoader extends URLClassLoader {
|
||||
|
||||
if (checkGlobal) {
|
||||
// This ignores the libraries of other plugins, unless they are transitive dependencies.
|
||||
Class<?> result = loader.getClassByName(name, resolve, description);
|
||||
Class<?> result = this.classLoaderGroup.getClassByName(name, resolve, this); // Paper
|
||||
|
||||
if (result != null) {
|
||||
// If the class was loaded from a library instead of a PluginClassLoader, we can assume that its associated plugin is a transitive dependency and can therefore skip this check.
|
||||
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)) {
|
||||
|
||||
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()});
|
||||
}
|
||||
}
|
||||
}
|
||||
// Paper - Totally delete the illegal access logic, we are never going to enforce it anyways here.
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -180,7 +195,7 @@ final class PluginClassLoader extends URLClassLoader {
|
||||
throw new ClassNotFoundException(name, ex);
|
||||
}
|
||||
|
||||
classBytes = loader.server.getUnsafe().processClass(description, path, classBytes);
|
||||
classBytes = org.bukkit.Bukkit.getServer().getUnsafe().processClass(description, path, classBytes); // Paper
|
||||
|
||||
int dot = name.lastIndexOf('.');
|
||||
if (dot != -1) {
|
||||
@@ -210,8 +225,8 @@ final class PluginClassLoader extends URLClassLoader {
|
||||
result = super.findClass(name);
|
||||
}
|
||||
|
||||
loader.setClass(name, result);
|
||||
classes.put(name, result);
|
||||
this.setClass(name, result); // Paper
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -220,6 +235,12 @@ final class PluginClassLoader extends URLClassLoader {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
// Paper start
|
||||
Collection<Class<?>> classes = getClasses();
|
||||
for (Class<?> clazz : classes) {
|
||||
removeClass(clazz);
|
||||
}
|
||||
// Paper end
|
||||
super.close();
|
||||
} finally {
|
||||
jar.close();
|
||||
@@ -231,7 +252,7 @@ final class PluginClassLoader extends URLClassLoader {
|
||||
return classes.values();
|
||||
}
|
||||
|
||||
synchronized void initialize(@NotNull JavaPlugin javaPlugin) {
|
||||
public synchronized void initialize(@NotNull JavaPlugin javaPlugin) { // Paper
|
||||
Preconditions.checkArgument(javaPlugin != null, "Initializing plugin cannot be null");
|
||||
Preconditions.checkArgument(javaPlugin.getClass().getClassLoader() == this, "Cannot initialize plugin outside of this class loader");
|
||||
if (this.plugin != null || this.pluginInit != null) {
|
||||
@@ -241,6 +262,38 @@ final class PluginClassLoader extends URLClassLoader {
|
||||
pluginState = new IllegalStateException("Initial initialization");
|
||||
this.pluginInit = javaPlugin;
|
||||
|
||||
javaPlugin.init(loader, loader.server, description, dataFolder, file, this);
|
||||
javaPlugin.init(null, org.bukkit.Bukkit.getServer(), description, dataFolder, file, this); // Paper
|
||||
}
|
||||
|
||||
// Paper start
|
||||
@Override
|
||||
public String toString() {
|
||||
JavaPlugin currPlugin = plugin != null ? plugin : pluginInit;
|
||||
return "PluginClassLoader{" +
|
||||
"plugin=" + currPlugin +
|
||||
", pluginEnabled=" + (currPlugin == null ? "uninitialized" : currPlugin.isEnabled()) +
|
||||
", url=" + file +
|
||||
'}';
|
||||
}
|
||||
|
||||
void setClass(@NotNull final String name, @NotNull final Class<?> clazz) {
|
||||
if (org.bukkit.configuration.serialization.ConfigurationSerializable.class.isAssignableFrom(clazz)) {
|
||||
Class<? extends org.bukkit.configuration.serialization.ConfigurationSerializable> serializable = clazz.asSubclass(org.bukkit.configuration.serialization.ConfigurationSerializable.class);
|
||||
org.bukkit.configuration.serialization.ConfigurationSerialization.registerClass(serializable);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeClass(@NotNull Class<?> clazz) {
|
||||
if (org.bukkit.configuration.serialization.ConfigurationSerializable.class.isAssignableFrom(clazz)) {
|
||||
Class<? extends org.bukkit.configuration.serialization.ConfigurationSerializable> serializable = clazz.asSubclass(org.bukkit.configuration.serialization.ConfigurationSerializable.class);
|
||||
org.bukkit.configuration.serialization.ConfigurationSerialization.unregisterClass(serializable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup getGroup() {
|
||||
return this.classLoaderGroup;
|
||||
}
|
||||
|
||||
// Paper end
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user