1
0
mirror of https://github.com/lucko/LuckPerms.git synced 2025-09-01 18:32:33 +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

@@ -4,24 +4,17 @@ plugins {
dependencies {
compile project(':common')
compileOnly project(':common:loader-utils')
compileOnly 'net.md-5:bungeecord-api:1.15-SNAPSHOT'
compileOnly 'me.lucko:adventure-platform-bungeecord:4.0.0' // re: this artifact - see note in common/build.gradle
compileOnly 'com.imaginarycode.minecraft:RedisBungee:0.4'
}
processResources {
from(sourceSets.main.resources.srcDirs) {
expand 'pluginVersion': project.ext.fullVersion
include 'plugin.yml'
}
}
shadowJar {
archiveName = "LuckPerms-Bungee-${project.ext.fullVersion}.jar"
archiveName = 'luckperms-bungee.jarinjar'
dependencies {
include(dependency('net.luckperms:.*'))
include(dependency('me.lucko.luckperms:.*'))
}

View File

@@ -0,0 +1,29 @@
plugins {
id 'com.github.johnrengelman.shadow'
}
dependencies {
compileOnly 'net.md-5:bungeecord-api:1.15-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-Bungee-${project.ext.fullVersion}.jar"
from {
project(':bungee').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.bungee.loader;
import me.lucko.luckperms.common.loader.JarInJarClassLoader;
import me.lucko.luckperms.common.loader.LoaderBootstrap;
import net.md_5.bungee.api.plugin.Plugin;
public class BungeeLoaderPlugin extends Plugin {
private static final String JAR_NAME = "luckperms-bungee.jarinjar";
private static final String BOOTSTRAP_CLASS = "me.lucko.luckperms.bungee.LPBungeeBootstrap";
private final LoaderBootstrap plugin;
public BungeeLoaderPlugin() {
JarInJarClassLoader loader = new JarInJarClassLoader(getClass().getClassLoader(), JAR_NAME);
this.plugin = loader.instantiatePlugin(BOOTSTRAP_CLASS, Plugin.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

@@ -2,5 +2,5 @@ name: LuckPerms
version: ${pluginVersion}
description: A permissions plugin
author: Luck
main: me.lucko.luckperms.bungee.LPBungeeBootstrap
main: me.lucko.luckperms.bungee.loader.BungeeLoaderPlugin
softDepends: ["RedisBungee"]

View File

@@ -73,7 +73,7 @@ public class BungeeCommandExecutor extends Command implements TabExecutor {
public void register() {
ProxyServer proxy = this.plugin.getBootstrap().getProxy();
proxy.getPluginManager().registerCommand(this.plugin.getBootstrap(), this);
proxy.getPluginManager().registerCommand(this.plugin.getLoader(), this);
// don't allow players to execute the slash aliases - these are just for the console.
proxy.getDisabledCommands().addAll(Arrays.asList(SLASH_ALIASES));

View File

@@ -45,7 +45,7 @@ public class BungeeSchedulerAdapter implements SchedulerAdapter {
public BungeeSchedulerAdapter(LPBungeeBootstrap bootstrap) {
this.bootstrap = bootstrap;
this.executor = r -> bootstrap.getProxy().getScheduler().runAsync(bootstrap, r);
this.executor = r -> bootstrap.getProxy().getScheduler().runAsync(bootstrap.getLoader(), r);
}
@Override
@@ -60,14 +60,14 @@ public class BungeeSchedulerAdapter implements SchedulerAdapter {
@Override
public SchedulerTask asyncLater(Runnable task, long delay, TimeUnit unit) {
ScheduledTask t = this.bootstrap.getProxy().getScheduler().schedule(this.bootstrap, task, delay, unit);
ScheduledTask t = this.bootstrap.getProxy().getScheduler().schedule(this.bootstrap.getLoader(), task, delay, unit);
this.tasks.add(t);
return t::cancel;
}
@Override
public SchedulerTask asyncRepeating(Runnable task, long interval, TimeUnit unit) {
ScheduledTask t = this.bootstrap.getProxy().getScheduler().schedule(this.bootstrap, task, interval, interval, unit);
ScheduledTask t = this.bootstrap.getProxy().getScheduler().schedule(this.bootstrap.getLoader(), task, interval, interval, unit);
this.tasks.add(t);
return t::cancel;
}

View File

@@ -42,7 +42,7 @@ public class BungeeSenderFactory extends SenderFactory<LPBungeePlugin, CommandSe
public BungeeSenderFactory(LPBungeePlugin plugin) {
super(plugin);
this.audiences = BungeeAudiences.create(plugin.getBootstrap());
this.audiences = BungeeAudiences.create(plugin.getLoader());
}
@Override

View File

@@ -26,21 +26,22 @@
package me.lucko.luckperms.bungee;
import me.lucko.luckperms.bungee.util.RedisBungeeUtil;
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;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
import net.luckperms.api.platform.Platform;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginDescription;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.time.Instant;
@@ -50,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 BungeeCord.
*/
public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
public class LPBungeeBootstrap implements LuckPermsBootstrap, LoaderBootstrap {
private final Plugin loader;
/**
* The plugin logger
@@ -67,9 +70,9 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
private final SchedulerAdapter schedulerAdapter;
/**
* The plugin classloader
* The plugin class path appender
*/
private final PluginClassLoader classLoader;
private final ClassPathAppender classPathAppender;
/**
* The plugin instance
@@ -88,14 +91,24 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
// if the plugin has been loaded on an incompatible version
private boolean incompatibleVersion = false;
public LPBungeeBootstrap() {
public LPBungeeBootstrap(Plugin loader) {
this.loader = loader;
this.schedulerAdapter = new BungeeSchedulerAdapter(this);
this.classLoader = new ReflectionClassLoader(this);
this.classPathAppender = new JarInJarClassPathAppender(getClass().getClassLoader());
this.plugin = new LPBungeePlugin(this);
}
// provide adapters
public Plugin getLoader() {
return this.loader;
}
public ProxyServer getProxy() {
return this.loader.getProxy();
}
@Override
public PluginLogger getPluginLogger() {
if (this.logger == null) {
@@ -110,15 +123,15 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
}
@Override
public PluginClassLoader getPluginClassLoader() {
return this.classLoader;
public ClassPathAppender getClassPathAppender() {
return this.classPathAppender;
}
// lifecycle
@Override
public void onLoad() {
this.logger = new JavaPluginLogger(getLogger());
this.logger = new JavaPluginLogger(this.loader.getLogger());
if (checkIncompatibleVersion()) {
this.incompatibleVersion = true;
@@ -135,16 +148,17 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
@Override
public void onEnable() {
if (this.incompatibleVersion) {
getLogger().severe("----------------------------------------------------------------------");
getLogger().severe("Your proxy version is not compatible with this build of LuckPerms. :(");
getLogger().severe("");
getLogger().severe("This is most likely because you are using an old/outdated version of BungeeCord.");
getLogger().severe("If you need 1.7 support, replace your BungeeCord.jar file with the latest build of");
getLogger().severe("'Travertine' from here:");
getLogger().severe("==> https://papermc.io/downloads#Travertine");
getLogger().severe("");
getLogger().severe("The proxy will now shutdown.");
getLogger().severe("----------------------------------------------------------------------");
Logger logger = this.loader.getLogger();
logger.severe("----------------------------------------------------------------------");
logger.severe("Your proxy version is not compatible with this build of LuckPerms. :(");
logger.severe("");
logger.severe("This is most likely because you are using an old/outdated version of BungeeCord.");
logger.severe("If you need 1.7 support, replace your BungeeCord.jar file with the latest build of");
logger.severe("'Travertine' from here:");
logger.severe("==> https://papermc.io/downloads#Travertine");
logger.severe("");
logger.severe("The proxy will now shutdown.");
logger.severe("----------------------------------------------------------------------");
getProxy().stop();
return;
}
@@ -180,7 +194,7 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
@Override
public String getVersion() {
return getDescription().getVersion();
return this.loader.getDescription().getVersion();
}
@Override
@@ -207,12 +221,7 @@ public class LPBungeeBootstrap extends Plugin implements LuckPermsBootstrap {
@Override
public Path getDataDirectory() {
return getDataFolder().toPath().toAbsolutePath();
}
@Override
public InputStream getResourceStream(String path) {
return getResourceAsStream(path);
return this.loader.getDataFolder().toPath().toAbsolutePath();
}
@Override

View File

@@ -51,11 +51,8 @@ import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.query.QueryOptions;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -84,6 +81,10 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin {
return this.bootstrap;
}
public Plugin getLoader() {
return this.bootstrap.getLoader();
}
@Override
protected void setupSenderFactory() {
this.senderFactory = new BungeeSenderFactory(this);
@@ -99,14 +100,14 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin {
@Override
protected ConfigurationAdapter provideConfigurationAdapter() {
return new BungeeConfigAdapter(this, resolveConfig());
return new BungeeConfigAdapter(this, resolveConfig("config.yml").toFile());
}
@Override
protected void registerPlatformListeners() {
this.connectionListener = new BungeeConnectionListener(this);
this.bootstrap.getProxy().getPluginManager().registerListener(this.bootstrap, this.connectionListener);
this.bootstrap.getProxy().getPluginManager().registerListener(this.bootstrap, new BungeePermissionCheckListener(this));
this.bootstrap.getProxy().getPluginManager().registerListener(this.bootstrap.getLoader(), this.connectionListener);
this.bootstrap.getProxy().getPluginManager().registerListener(this.bootstrap.getLoader(), new BungeePermissionCheckListener(this));
}
@Override
@@ -141,7 +142,7 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin {
this.contextManager = new BungeeContextManager(this);
BungeePlayerCalculator playerCalculator = new BungeePlayerCalculator(this);
this.bootstrap.getProxy().getPluginManager().registerListener(this.bootstrap, playerCalculator);
this.bootstrap.getProxy().getPluginManager().registerListener(this.bootstrap.getLoader(), playerCalculator);
this.contextManager.registerCalculator(playerCalculator);
if (this.bootstrap.getProxy().getPluginManager().getPlugin("RedisBungee") != null) {
@@ -175,21 +176,6 @@ public class LPBungeePlugin extends AbstractLuckPermsPlugin {
}
private File resolveConfig() {
File configFile = new File(this.bootstrap.getDataFolder(), "config.yml");
if (!configFile.exists()) {
this.bootstrap.getDataFolder().mkdirs();
try (InputStream is = this.bootstrap.getResourceAsStream("config.yml")) {
Files.copy(is, configFile.toPath());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return configFile;
}
@Override
public Optional<QueryOptions> getQueryOptionsForUser(User user) {
return this.bootstrap.getPlayer(user.getUniqueId()).map(player -> this.contextManager.getQueryOptions(player));

View File

@@ -76,7 +76,7 @@ public class BungeeConnectionListener extends AbstractConnectionListener impleme
/* registers the plugins intent to modify this events state going forward.
this will prevent the event from completing until we're finished handling. */
e.registerIntent(this.plugin.getBootstrap());
e.registerIntent(this.plugin.getLoader());
this.plugin.getBootstrap().getScheduler().executeAsync(() -> {
/* Actually process the login for the connection.
@@ -106,7 +106,7 @@ public class BungeeConnectionListener extends AbstractConnectionListener impleme
}
// finally, complete our intent to modify state, so the proxy can continue handling the connection.
e.completeIntent(this.plugin.getBootstrap());
e.completeIntent(this.plugin.getLoader());
});
}
@@ -134,7 +134,7 @@ public class BungeeConnectionListener extends AbstractConnectionListener impleme
e.getPlayer().disconnect(BungeeComponentSerializer.get().serialize(reason));
} else {
// just send a message
this.plugin.getBootstrap().getProxy().getScheduler().schedule(this.plugin.getBootstrap(), () -> {
this.plugin.getBootstrap().getProxy().getScheduler().schedule(this.plugin.getLoader(), () -> {
if (!player.isConnected()) {
return;
}

View File

@@ -59,7 +59,7 @@ public class PluginMessageMessenger implements Messenger, Listener {
public void init() {
ProxyServer proxy = this.plugin.getBootstrap().getProxy();
proxy.getPluginManager().registerListener(this.plugin.getBootstrap(), this);
proxy.getPluginManager().registerListener(this.plugin.getLoader(), this);
proxy.registerChannel(CHANNEL);
}

View File

@@ -58,7 +58,7 @@ public class RedisBungeeMessenger implements Messenger, Listener {
this.redisBungee = RedisBungee.getApi();
this.redisBungee.registerPubSubChannels(CHANNEL);
this.plugin.getBootstrap().getProxy().getPluginManager().registerListener(this.plugin.getBootstrap(), this);
this.plugin.getBootstrap().getProxy().getPluginManager().registerListener(this.plugin.getLoader(), this);
}
@Override