1
0
mirror of https://github.com/lucko/LuckPerms.git synced 2025-09-08 21:30:55 +02:00

Implement jar-in-jar loader system (#2899)

This fixes an issue that prevented LuckPerms from loading on Java 16
This commit is contained in:
lucko
2021-02-18 12:21:17 +00:00
committed by GitHub
parent cb5f403043
commit 75d8f00400
61 changed files with 790 additions and 339 deletions

View File

@@ -9,6 +9,7 @@ repositories {
dependencies {
compile project(':common')
compileOnly project(':common:loader-utils')
compileOnly 'com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT'
compileOnly 'me.lucko:adventure-platform-bukkit:4.0.0' // re: this artifact - see note in common/build.gradle
@@ -19,18 +20,10 @@ dependencies {
compileOnly 'lilypad.client.connect:api:0.0.1-SNAPSHOT'
}
processResources {
from(sourceSets.main.resources.srcDirs) {
expand 'pluginVersion': project.ext.fullVersion
include 'plugin.yml'
}
}
shadowJar {
archiveName = "LuckPerms-Bukkit-${project.ext.fullVersion}.jar"
archiveName = 'luckperms-bukkit.jarinjar'
dependencies {
include(dependency('net.luckperms:.*'))
include(dependency('me.lucko.luckperms:.*'))
}

View File

@@ -0,0 +1,33 @@
plugins {
id 'com.github.johnrengelman.shadow'
}
repositories {
maven { url 'https://papermc.io/repo/repository/maven-public/' }
}
dependencies {
compileOnly 'com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT'
compile project(':api')
compile project(':common:loader-utils')
}
processResources {
from(sourceSets.main.resources.srcDirs) {
expand 'pluginVersion': project.ext.fullVersion
include 'plugin.yml'
}
}
shadowJar {
archiveName = "LuckPerms-Bukkit-${project.ext.fullVersion}.jar"
from {
project(':bukkit').tasks.shadowJar.archiveFile
}
}
artifacts {
archives shadowJar
}

View File

@@ -0,0 +1,59 @@
/*
* This file is part of LuckPerms, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.luckperms.bukkit.loader;
import me.lucko.luckperms.common.loader.JarInJarClassLoader;
import me.lucko.luckperms.common.loader.LoaderBootstrap;
import org.bukkit.plugin.java.JavaPlugin;
public class BukkitLoaderPlugin extends JavaPlugin {
private static final String JAR_NAME = "luckperms-bukkit.jarinjar";
private static final String BOOTSTRAP_CLASS = "me.lucko.luckperms.bukkit.LPBukkitBootstrap";
private final LoaderBootstrap plugin;
public BukkitLoaderPlugin() {
JarInJarClassLoader loader = new JarInJarClassLoader(getClass().getClassLoader(), JAR_NAME);
this.plugin = loader.instantiatePlugin(BOOTSTRAP_CLASS, JavaPlugin.class, this);
}
@Override
public void onLoad() {
this.plugin.onLoad();
}
@Override
public void onEnable() {
this.plugin.onEnable();
}
@Override
public void onDisable() {
this.plugin.onDisable();
}
}

View File

@@ -3,7 +3,7 @@ version: ${pluginVersion}
description: A permissions plugin
author: Luck
website: https://luckperms.net
main: me.lucko.luckperms.bukkit.LPBukkitBootstrap
main: me.lucko.luckperms.bukkit.loader.BukkitLoaderPlugin
load: STARTUP
# Mark the plugin as 1.13 compatible to avoid CB having to perform quite as much unnecessary

View File

@@ -73,7 +73,7 @@ public class BukkitCommandExecutor extends CommandManager implements TabExecutor
public void register() {
this.command.setExecutor(this);
this.command.setTabCompleter(this);
this.plugin.getBootstrap().getServer().getPluginManager().registerEvents(this, this.plugin.getBootstrap());
this.plugin.getBootstrap().getServer().getPluginManager().registerEvents(this, this.plugin.getLoader());
}
@Override

View File

@@ -39,7 +39,7 @@ public class BukkitEventBus extends AbstractEventBus<Plugin> implements Listener
// register listener
LPBukkitBootstrap bootstrap = plugin.getBootstrap();
bootstrap.getServer().getPluginManager().registerEvents(this, bootstrap);
bootstrap.getServer().getPluginManager().registerEvents(this, bootstrap.getLoader());
}
@Override

View File

@@ -34,7 +34,7 @@ public class BukkitSchedulerAdapter extends AbstractJavaScheduler implements Sch
private final Executor sync;
public BukkitSchedulerAdapter(LPBukkitBootstrap bootstrap) {
this.sync = r -> bootstrap.getServer().getScheduler().scheduleSyncDelayedTask(bootstrap, r);
this.sync = r -> bootstrap.getServer().getScheduler().scheduleSyncDelayedTask(bootstrap.getLoader(), r);
}
@Override

View File

@@ -44,7 +44,7 @@ public class BukkitSenderFactory extends SenderFactory<LPBukkitPlugin, CommandSe
public BukkitSenderFactory(LPBukkitPlugin plugin) {
super(plugin);
this.audiences = BukkitAudiences.create(plugin.getBootstrap());
this.audiences = BukkitAudiences.create(plugin.getLoader());
}
@Override

View File

@@ -26,9 +26,10 @@
package me.lucko.luckperms.bukkit;
import me.lucko.luckperms.bukkit.util.NullSafeConsoleCommandSender;
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
import me.lucko.luckperms.common.loader.LoaderBootstrap;
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
import me.lucko.luckperms.common.plugin.classpath.JarInJarClassPathAppender;
import me.lucko.luckperms.common.plugin.logging.JavaPluginLogger;
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
@@ -41,7 +42,6 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.time.Instant;
@@ -51,11 +51,13 @@ import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Logger;
/**
* Bootstrap plugin for LuckPerms running on Bukkit.
*/
public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap {
public class LPBukkitBootstrap implements LuckPermsBootstrap, LoaderBootstrap {
private final JavaPlugin loader;
/**
* The plugin logger
@@ -68,9 +70,9 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
private final BukkitSchedulerAdapter schedulerAdapter;
/**
* The plugin classloader
* The plugin class path appender
*/
private final PluginClassLoader classLoader;
private final ClassPathAppender classPathAppender;
/**
* A null-safe console instance which delegates to the server logger
@@ -97,16 +99,26 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
// if the plugin has been loaded on an incompatible version
private boolean incompatibleVersion = false;
public LPBukkitBootstrap() {
this.logger = new JavaPluginLogger(getLogger());
public LPBukkitBootstrap(JavaPlugin loader) {
this.loader = loader;
this.logger = new JavaPluginLogger(loader.getLogger());
this.schedulerAdapter = new BukkitSchedulerAdapter(this);
this.classLoader = new ReflectionClassLoader(this);
this.classPathAppender = new JarInJarClassPathAppender(getClass().getClassLoader());
this.console = new NullSafeConsoleCommandSender(getServer());
this.plugin = new LPBukkitPlugin(this);
}
// provide adapters
public JavaPlugin getLoader() {
return this.loader;
}
public Server getServer() {
return this.loader.getServer();
}
@Override
public PluginLogger getPluginLogger() {
return this.logger;
@@ -118,8 +130,8 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
}
@Override
public PluginClassLoader getPluginClassLoader() {
return this.classLoader;
public ClassPathAppender getClassPathAppender() {
return this.classPathAppender;
}
public ConsoleCommandSender getConsole() {
@@ -144,14 +156,15 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
@Override
public void onEnable() {
if (this.incompatibleVersion) {
getLogger().severe("----------------------------------------------------------------------");
getLogger().severe("Your server version is not compatible with this build of LuckPerms. :(");
getLogger().severe("");
getLogger().severe("If your server is running 1.8, please update to 1.8.8 or higher.");
getLogger().severe("If your server is running 1.7.10, please download the Bukkit-Legacy version of LuckPerms from here:");
getLogger().severe("==> https://ci.lucko.me/job/LuckPerms/");
getLogger().severe("----------------------------------------------------------------------");
getServer().getPluginManager().disablePlugin(this);
Logger logger = this.loader.getLogger();
logger.severe("----------------------------------------------------------------------");
logger.severe("Your server version is not compatible with this build of LuckPerms. :(");
logger.severe("");
logger.severe("If your server is running 1.8, please update to 1.8.8 or higher.");
logger.severe("If your server is running 1.7.10, please download the Bukkit-Legacy version of LuckPerms from here:");
logger.severe("==> https://ci.lucko.me/job/LuckPerms/");
logger.severe("----------------------------------------------------------------------");
getServer().getPluginManager().disablePlugin(this.loader);
return;
}
@@ -162,7 +175,7 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
this.plugin.enable();
// schedule a task to update the 'serverStarting' flag
getServer().getScheduler().runTask(this, () -> this.serverStarting = false);
getServer().getScheduler().runTask(this.loader, () -> this.serverStarting = false);
} finally {
this.enableLatch.countDown();
}
@@ -200,7 +213,7 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
@Override
public String getVersion() {
return getDescription().getVersion();
return this.loader.getDescription().getVersion();
}
@Override
@@ -227,12 +240,7 @@ public class LPBukkitBootstrap extends JavaPlugin implements LuckPermsBootstrap
@Override
public Path getDataDirectory() {
return getDataFolder().toPath().toAbsolutePath();
}
@Override
public InputStream getResourceStream(String path) {
return getResource(path);
return this.loader.getDataFolder().toPath().toAbsolutePath();
}
@Override

View File

@@ -73,8 +73,8 @@ import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -109,6 +109,10 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
return this.bootstrap;
}
public JavaPlugin getLoader() {
return this.bootstrap.getLoader();
}
@Override
protected void setupSenderFactory() {
this.senderFactory = new BukkitSenderFactory(this);
@@ -127,14 +131,14 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
@Override
protected ConfigurationAdapter provideConfigurationAdapter() {
return new BukkitConfigAdapter(this, resolveConfig());
return new BukkitConfigAdapter(this, resolveConfig("config.yml").toFile());
}
@Override
protected void registerPlatformListeners() {
this.connectionListener = new BukkitConnectionListener(this);
this.bootstrap.getServer().getPluginManager().registerEvents(this.connectionListener, this.bootstrap);
this.bootstrap.getServer().getPluginManager().registerEvents(new BukkitPlatformListener(this), this.bootstrap);
this.bootstrap.getServer().getPluginManager().registerEvents(this.connectionListener, this.bootstrap.getLoader());
this.bootstrap.getServer().getPluginManager().registerEvents(new BukkitPlatformListener(this), this.bootstrap.getLoader());
}
@Override
@@ -144,7 +148,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
@Override
protected void registerCommands() {
PluginCommand command = this.bootstrap.getCommand("luckperms");
PluginCommand command = this.bootstrap.getLoader().getCommand("luckperms");
if (command == null) {
getLogger().severe("Unable to register /luckperms command with the server");
return;
@@ -187,7 +191,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
this.contextManager = new BukkitContextManager(this);
BukkitPlayerCalculator playerCalculator = new BukkitPlayerCalculator(this);
this.bootstrap.getServer().getPluginManager().registerEvents(playerCalculator, this.bootstrap);
this.bootstrap.getServer().getPluginManager().registerEvents(playerCalculator, this.bootstrap.getLoader());
this.contextManager.registerCalculator(playerCalculator);
}
@@ -206,7 +210,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
// schedule another injection after all plugins have loaded
// the entire pluginmanager instance is replaced by some plugins :(
this.bootstrap.getServer().getScheduler().runTaskLaterAsynchronously(this.bootstrap, injector, 1);
this.bootstrap.getServer().getScheduler().runTaskLaterAsynchronously(this.bootstrap.getLoader(), injector, 1);
}
/*
@@ -221,7 +225,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
* - https://hub.spigotmc.org/jira/browse/SPIGOT-5546
* - https://github.com/PaperMC/Paper/pull/3509
*/
PluginManagerUtil.injectDependency(this.bootstrap.getServer().getPluginManager(), this.bootstrap.getName(), "Vault");
PluginManagerUtil.injectDependency(this.bootstrap.getServer().getPluginManager(), this.bootstrap.getLoader().getName(), "Vault");
// Provide vault support
tryVaultHook(false);
@@ -251,7 +255,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
@Override
protected void registerApiOnPlatform(LuckPerms api) {
this.bootstrap.getServer().getServicesManager().register(LuckPerms.class, api, this.bootstrap, ServicePriority.Normal);
this.bootstrap.getServer().getServicesManager().register(LuckPerms.class, api, this.bootstrap.getLoader(), ServicePriority.Normal);
}
@Override
@@ -276,7 +280,7 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
// remove all operators on startup if they're disabled
if (!getConfiguration().get(ConfigKeys.OPS_ENABLED)) {
this.bootstrap.getServer().getScheduler().runTaskAsynchronously(this.bootstrap, () -> {
this.bootstrap.getServer().getScheduler().runTaskAsynchronously(this.bootstrap.getLoader(), () -> {
for (OfflinePlayer player : this.bootstrap.getServer().getOperators()) {
player.setOp(false);
}
@@ -351,15 +355,6 @@ public class LPBukkitPlugin extends AbstractLuckPermsPlugin {
}
}
private File resolveConfig() {
File configFile = new File(this.bootstrap.getDataFolder(), "config.yml");
if (!configFile.exists()) {
this.bootstrap.getDataFolder().mkdirs();
this.bootstrap.saveResource("config.yml", false);
}
return configFile;
}
private static boolean classExists(String className) {
try {
Class.forName(className);

View File

@@ -44,7 +44,7 @@ public final class LuckPermsBrigadier {
private LuckPermsBrigadier() {}
public static void register(LPBukkitPlugin plugin, Command pluginCommand) throws Exception {
Commodore commodore = CommodoreProvider.getCommodore(plugin.getBootstrap());
Commodore commodore = CommodoreProvider.getCommodore(plugin.getLoader());
try (InputStream is = plugin.getBootstrap().getResourceStream("luckperms.commodore")) {
if (is == null) {
throw new Exception("Brigadier command data missing from jar");

View File

@@ -287,7 +287,7 @@ public class LuckPermsPermissionAttachment extends PermissionAttachment {
@Override
public @NonNull Plugin getPlugin() {
return this.owner != null ? this.owner : this.permissible.getPlugin().getBootstrap();
return this.owner != null ? this.owner : this.permissible.getPlugin().getLoader();
}
@Override

View File

@@ -239,7 +239,7 @@ public class BukkitConnectionListener extends AbstractConnectionListener impleme
// perform unhooking from bukkit objects 1 tick later.
// this allows plugins listening after us on MONITOR to still have intact permissions data
this.plugin.getBootstrap().getServer().getScheduler().runTaskLater(this.plugin.getBootstrap(), () -> {
this.plugin.getBootstrap().getServer().getScheduler().runTaskLater(this.plugin.getLoader(), () -> {
// Remove the custom permissible
try {
PermissibleInjector.uninject(player, true);

View File

@@ -58,14 +58,14 @@ public class PluginMessageMessenger implements Messenger, PluginMessageListener
}
public void init() {
this.plugin.getBootstrap().getServer().getMessenger().registerOutgoingPluginChannel(this.plugin.getBootstrap(), CHANNEL);
this.plugin.getBootstrap().getServer().getMessenger().registerIncomingPluginChannel(this.plugin.getBootstrap(), CHANNEL, this);
this.plugin.getBootstrap().getServer().getMessenger().registerOutgoingPluginChannel(this.plugin.getLoader(), CHANNEL);
this.plugin.getBootstrap().getServer().getMessenger().registerIncomingPluginChannel(this.plugin.getLoader(), CHANNEL, this);
}
@Override
public void close() {
this.plugin.getBootstrap().getServer().getMessenger().unregisterIncomingPluginChannel(this.plugin.getBootstrap(), CHANNEL);
this.plugin.getBootstrap().getServer().getMessenger().unregisterOutgoingPluginChannel(this.plugin.getBootstrap(), CHANNEL);
this.plugin.getBootstrap().getServer().getMessenger().unregisterIncomingPluginChannel(this.plugin.getLoader(), CHANNEL);
this.plugin.getBootstrap().getServer().getMessenger().unregisterOutgoingPluginChannel(this.plugin.getLoader(), CHANNEL);
}
@Override
@@ -83,10 +83,10 @@ public class PluginMessageMessenger implements Messenger, PluginMessageListener
return;
}
p.sendPluginMessage(PluginMessageMessenger.this.plugin.getBootstrap(), CHANNEL, data);
p.sendPluginMessage(PluginMessageMessenger.this.plugin.getLoader(), CHANNEL, data);
cancel();
}
}.runTaskTimer(this.plugin.getBootstrap(), 1L, 100L);
}.runTaskTimer(this.plugin.getLoader(), 1L, 100L);
}
@Override

View File

@@ -61,8 +61,8 @@ public class VaultHookManager {
}
final ServicesManager sm = this.plugin.getBootstrap().getServer().getServicesManager();
sm.register(Permission.class, this.permission, this.plugin.getBootstrap(), ServicePriority.High);
sm.register(Chat.class, this.chat, this.plugin.getBootstrap(), ServicePriority.High);
sm.register(Permission.class, this.permission, this.plugin.getLoader(), ServicePriority.High);
sm.register(Chat.class, this.chat, this.plugin.getLoader(), ServicePriority.High);
} catch (Exception e) {
this.plugin.getLogger().severe("Error occurred whilst hooking into Vault.", e);