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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 790 additions and 339 deletions

View File

@ -3,7 +3,7 @@ plugins {
}
dependencies {
compile project(path: ':bukkit', configuration: 'shadow')
compile project(path: ':bukkit:loader', configuration: 'shadow')
compile 'com.google.code.gson:gson:2.7'
compile 'com.google.guava:guava:19.0'
}
@ -12,7 +12,6 @@ shadowJar {
archiveName = "LuckPerms-Bukkit-Legacy-${project.ext.fullVersion}.jar"
dependencies {
include(dependency('net.luckperms:.*'))
include(dependency('me.lucko.luckperms:.*'))
include(dependency('com.google.guava:guava:.*'))
include(dependency('com.google.code.gson:gson:.*'))

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);

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

View File

@ -11,6 +11,8 @@ dependencies {
compile project(':api')
compile 'org.checkerframework:checker-qual:3.8.0'
compileOnly project(':common:loader-utils')
compileOnly 'org.slf4j:slf4j-api:1.7.30'
compileOnly 'org.apache.logging.log4j:log4j-api:2.14.0'

View File

@ -0,0 +1 @@
// nothing special to do here (yet)!

View File

@ -0,0 +1,140 @@
/*
* 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.common.loader;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
/**
* Classloader that can load a jar from within another jar file.
*
* <p>The "loader" jar contains the loading code & public API classes,
* and is class-loaded by the platform.</p>
*
* <p>The inner "plugin" jar contains the plugin itself, and is class-loaded
* by the loading code & this classloader.</p>
*/
public class JarInJarClassLoader extends URLClassLoader {
static {
ClassLoader.registerAsParallelCapable();
}
/**
* Creates a new jar-in-jar class loader.
*
* @param loaderClassLoader the loader plugin's classloader (setup and created by the platform)
* @param jarResourcePath the path to the jar-in-jar resource within the loader jar
* @throws LoadingException if something unexpectedly bad happens
*/
public JarInJarClassLoader(ClassLoader loaderClassLoader, String jarResourcePath) throws LoadingException {
super(new URL[]{extractJar(loaderClassLoader, jarResourcePath)}, loaderClassLoader);
}
public void addJarToClasspath(URL url) {
addURL(url);
}
/**
* Creates a new plugin instance.
*
* @param bootstrapClass the name of the bootstrap plugin class
* @param loaderPluginType the type of the loader plugin, the only parameter of the bootstrap
* plugin constructor
* @param loaderPlugin the loader plugin instance
* @param <T> the type of the loader plugin
* @return the instantiated bootstrap plugin
*/
public <T> LoaderBootstrap instantiatePlugin(String bootstrapClass, Class<T> loaderPluginType, T loaderPlugin) throws LoadingException {
Class<? extends LoaderBootstrap> plugin;
try {
plugin = loadClass(bootstrapClass).asSubclass(LoaderBootstrap.class);
} catch (ReflectiveOperationException e) {
throw new LoadingException("Unable to load bootstrap class", e);
}
Constructor<? extends LoaderBootstrap> constructor;
try {
constructor = plugin.getConstructor(loaderPluginType);
} catch (ReflectiveOperationException e) {
throw new LoadingException("Unable to get bootstrap constructor", e);
}
try {
return constructor.newInstance(loaderPlugin);
} catch (ReflectiveOperationException e) {
throw new LoadingException("Unable to create bootstrap plugin instance", e);
}
}
/**
* Extracts the "jar-in-jar" from the loader plugin into a temporary file,
* then returns a URL that can be used by the {@link JarInJarClassLoader}.
*
* @param loaderClassLoader the classloader for the "host" loader plugin
* @param jarResourcePath the inner jar resource path
* @return a URL to the extracted file
*/
private static URL extractJar(ClassLoader loaderClassLoader, String jarResourcePath) throws LoadingException {
// get the jar-in-jar resource
URL jarInJar = loaderClassLoader.getResource(jarResourcePath);
if (jarInJar == null) {
throw new LoadingException("Could not locate jar-in-jar");
}
// create a temporary file
// on posix systems by default this is only read/writable by the process owner
Path path;
try {
path = Files.createTempFile("luckperms-jarinjar", ".jar.tmp");
} catch (IOException e) {
throw new LoadingException("Unable to create a temporary file", e);
}
// mark that the file should be deleted on exit
path.toFile().deleteOnExit();
// copy the jar-in-jar to the temporary file path
try (InputStream in = jarInJar.openStream()) {
Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new LoadingException("Unable to copy jar-in-jar to temporary path", e);
}
try {
return path.toUri().toURL();
} catch (MalformedURLException e) {
throw new LoadingException("Unable to get URL from path", e);
}
}
}

View File

@ -0,0 +1,39 @@
/*
* 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.common.loader;
/**
* Minimal bootstrap plugin, called by the loader plugin.
*/
public interface LoaderBootstrap {
void onLoad();
void onEnable();
void onDisable();
}

View File

@ -0,0 +1,41 @@
/*
* 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.common.loader;
/**
* Runtime exception used if there is a problem during loading
*/
public class LoadingException extends RuntimeException {
public LoadingException(String message) {
super(message);
}
public LoadingException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -150,7 +150,7 @@ public class DependencyManager {
this.loaded.put(dependency, file);
if (this.registry.shouldAutoLoad(dependency)) {
this.plugin.getBootstrap().getPluginClassLoader().addJarToClasspath(file);
this.plugin.getBootstrap().getClassPathAppender().addJarToClasspath(file);
}
}

View File

@ -136,7 +136,7 @@ public class SimpleExtensionManager implements ExtensionManager, AutoCloseable {
throw new IllegalArgumentException("class is null");
}
this.plugin.getBootstrap().getPluginClassLoader().addJarToClasspath(path);
this.plugin.getBootstrap().getClassPathAppender().addJarToClasspath(path);
Class<? extends Extension> extensionClass;
try {

View File

@ -60,6 +60,10 @@ import net.luckperms.api.LuckPerms;
import okhttp3.OkHttpClient;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
@ -265,6 +269,24 @@ public abstract class AbstractLuckPermsPlugin implements LuckPermsPlugin {
);
}
protected Path resolveConfig(String fileName) {
Path configFile = getBootstrap().getDataDirectory().resolve(fileName);
if (!Files.exists(configFile)) {
try {
Files.createDirectories(configFile.getParent());
} catch (IOException e) {
// ignore
}
try (InputStream is = getBootstrap().getResourceStream(fileName)) {
Files.copy(is, configFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return configFile;
}
protected abstract void setupSenderFactory();
protected abstract ConfigurationAdapter provideConfigurationAdapter();
protected abstract void registerPlatformListeners();

View File

@ -25,7 +25,7 @@
package me.lucko.luckperms.common.plugin.bootstrap;
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
@ -66,11 +66,11 @@ public interface LuckPermsBootstrap {
SchedulerAdapter getScheduler();
/**
* Gets a {@link PluginClassLoader} for this instance
* Gets a {@link ClassPathAppender} for this bootstrap plugin
*
* @return a classloader
* @return a class path appender
*/
PluginClassLoader getPluginClassLoader();
ClassPathAppender getClassPathAppender();
/**
* Returns a countdown latch which {@link CountDownLatch#countDown() counts down}
@ -159,7 +159,9 @@ public interface LuckPermsBootstrap {
* @param path the path of the file
* @return the file as an input stream
*/
InputStream getResourceStream(String path);
default InputStream getResourceStream(String path) {
return getClass().getClassLoader().getResourceAsStream(path);
}
/**
* Gets a player object linked to this User. The returned object must be the same type

View File

@ -23,14 +23,14 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.dependencies.classloader;
package me.lucko.luckperms.common.plugin.classpath;
import java.nio.file.Path;
/**
* Represents the plugins classloader
* Interface which allows access to add URLs to the plugin classpath at runtime.
*/
public interface PluginClassLoader {
public interface ClassPathAppender {
void addJarToClasspath(Path file);

View File

@ -0,0 +1,51 @@
/*
* 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.common.plugin.classpath;
import me.lucko.luckperms.common.loader.JarInJarClassLoader;
import java.net.MalformedURLException;
import java.nio.file.Path;
public class JarInJarClassPathAppender implements ClassPathAppender {
private final JarInJarClassLoader classLoader;
public JarInJarClassPathAppender(ClassLoader classLoader) {
if (!(classLoader instanceof JarInJarClassLoader)) {
throw new IllegalArgumentException("Loader is not a JarInJarClassLoader: " + classLoader.getClass().getName());
}
this.classLoader = (JarInJarClassLoader) classLoader;
}
@Override
public void addJarToClasspath(Path file) {
try {
this.classLoader.addJarToClasspath(file.toUri().toURL());
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -23,19 +23,18 @@
* SOFTWARE.
*/
package me.lucko.luckperms.common.dependencies.classloader;
package me.lucko.luckperms.common.plugin.classpath;
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
public class ReflectionClassLoader implements PluginClassLoader {
@Deprecated // TODO: no longer works on Java 16 - Sponge needs to switch to JarInJar or find an API to add to classpath at runtime
public class ReflectionClassPathAppender implements ClassPathAppender {
private static final Method ADD_URL_METHOD;
static {
@ -58,7 +57,7 @@ public class ReflectionClassLoader implements PluginClassLoader {
private final URLClassLoader classLoader;
public ReflectionClassLoader(LuckPermsBootstrap bootstrap) throws IllegalStateException {
public ReflectionClassPathAppender(LuckPermsBootstrap bootstrap) throws IllegalStateException {
ClassLoader classLoader = bootstrap.getClass().getClassLoader();
if (classLoader instanceof URLClassLoader) {
this.classLoader = (URLClassLoader) classLoader;
@ -71,7 +70,7 @@ public class ReflectionClassLoader implements PluginClassLoader {
public void addJarToClasspath(Path file) {
try {
ADD_URL_METHOD.invoke(this.classLoader, file.toUri().toURL());
} catch (IllegalAccessException | InvocationTargetException | MalformedURLException e) {
} catch (ReflectiveOperationException | MalformedURLException e) {
throw new RuntimeException(e);
}
}
@ -92,7 +91,7 @@ public class ReflectionClassLoader implements PluginClassLoader {
Method addOpensMethod = moduleClass.getMethod("addOpens", String.class, moduleClass);
Object urlClassLoaderModule = getModuleMethod.invoke(URLClassLoader.class);
Object thisModule = getModuleMethod.invoke(ReflectionClassLoader.class);
Object thisModule = getModuleMethod.invoke(ReflectionClassPathAppender.class);
addOpensMethod.invoke(urlClassLoaderModule, URLClassLoader.class.getPackage().getName(), thisModule);
}

View File

@ -25,14 +25,14 @@
package me.lucko.luckperms.fabric;
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
import net.fabricmc.loader.launch.common.FabricLauncherBase;
import java.net.MalformedURLException;
import java.nio.file.Path;
public class FabricClassLoader implements PluginClassLoader {
public class FabricClassPathAppender implements ClassPathAppender {
@Override
public void addJarToClasspath(Path file) {

View File

@ -27,8 +27,8 @@ package me.lucko.luckperms.fabric;
import com.mojang.authlib.GameProfile;
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
import me.lucko.luckperms.common.plugin.logging.Log4jPluginLogger;
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
@ -76,9 +76,9 @@ public final class LPFabricBootstrap implements LuckPermsBootstrap, DedicatedSer
private final SchedulerAdapter schedulerAdapter;
/**
* The plugin class loader.
* The plugin class path appender
*/
private final PluginClassLoader classLoader;
private final ClassPathAppender classPathAppender;
/**
* The plugin instance
@ -102,7 +102,7 @@ public final class LPFabricBootstrap implements LuckPermsBootstrap, DedicatedSer
public LPFabricBootstrap() {
this.logger = new Log4jPluginLogger(LogManager.getLogger(MODID));
this.schedulerAdapter = new FabricSchedulerAdapter(this);
this.classLoader = new FabricClassLoader();
this.classPathAppender = new FabricClassPathAppender();
this.plugin = new LPFabricPlugin(this);
}
@ -119,8 +119,8 @@ public final class LPFabricBootstrap implements LuckPermsBootstrap, DedicatedSer
}
@Override
public PluginClassLoader getPluginClassLoader() {
return this.classLoader;
public ClassPathAppender getClassPathAppender() {
return this.classPathAppender;
}
// lifecycle

View File

@ -41,7 +41,6 @@ import me.lucko.luckperms.common.sender.DummySender;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
import me.lucko.luckperms.common.util.MoreFiles;
import me.lucko.luckperms.fabric.context.FabricContextManager;
import me.lucko.luckperms.fabric.context.FabricPlayerCalculator;
import me.lucko.luckperms.fabric.listeners.FabricConnectionListener;
@ -55,10 +54,6 @@ import net.luckperms.api.LuckPerms;
import net.luckperms.api.query.QueryOptions;
import net.minecraft.server.MinecraftServer;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -112,20 +107,7 @@ public class LPFabricPlugin extends AbstractLuckPermsPlugin {
@Override
protected ConfigurationAdapter provideConfigurationAdapter() {
Path configPath = this.getBootstrap().getConfigDirectory().resolve("luckperms.conf");
if (!Files.exists(configPath)) {
try {
MoreFiles.createDirectoriesIfNotExists(this.bootstrap.getConfigDirectory());
try (InputStream is = this.getBootstrap().getResourceStream("luckperms.conf")) {
Files.copy(is, configPath);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return new FabricConfigAdapter(this, configPath);
return new FabricConfigAdapter(this, resolveConfig("luckperms.conf"));
}
@Override

View File

@ -9,22 +9,15 @@ repositories {
dependencies {
compile project(':common')
compileOnly project(':common:loader-utils')
compileOnly 'cn.nukkit:nukkit:1.0-SNAPSHOT'
}
processResources {
from(sourceSets.main.resources.srcDirs) {
expand 'pluginVersion': project.ext.fullVersion
include 'plugin.yml'
}
}
shadowJar {
archiveName = "LuckPerms-Nukkit-${project.ext.fullVersion}.jar"
archiveName = 'luckperms-nukkit.jarinjar'
dependencies {
include(dependency('net.luckperms:.*'))
include(dependency('me.lucko.luckperms:.*'))
}

View File

@ -0,0 +1,34 @@
plugins {
id 'com.github.johnrengelman.shadow'
}
repositories {
mavenLocal()
maven { url 'https://repo.nukkitx.com/main/' }
}
dependencies {
compileOnly 'cn.nukkit:nukkit:1.0-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-Nukkit-${project.ext.fullVersion}.jar"
from {
project(':nukkit').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.nukkit.loader;
import me.lucko.luckperms.common.loader.JarInJarClassLoader;
import me.lucko.luckperms.common.loader.LoaderBootstrap;
import cn.nukkit.plugin.PluginBase;
public class NukkitLoaderPlugin extends PluginBase {
private static final String JAR_NAME = "luckperms-nukkit.jarinjar";
private static final String BOOTSTRAP_CLASS = "me.lucko.luckperms.nukkit.LPNukkitBootstrap";
private final LoaderBootstrap plugin;
public NukkitLoaderPlugin() {
JarInJarClassLoader loader = new JarInJarClassLoader(getClass().getClassLoader(), JAR_NAME);
this.plugin = loader.instantiatePlugin(BOOTSTRAP_CLASS, PluginBase.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

@ -5,7 +5,7 @@ description: A permissions plugin
author: Luck
website: https://luckperms.net
main: me.lucko.luckperms.nukkit.LPNukkitBootstrap
main: me.lucko.luckperms.nukkit.loader.NukkitLoaderPlugin
load: STARTUP
commands:

View File

@ -25,17 +25,18 @@
package me.lucko.luckperms.nukkit;
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.PluginLogger;
import net.luckperms.api.platform.Platform;
import cn.nukkit.Player;
import cn.nukkit.Server;
import cn.nukkit.plugin.PluginBase;
import java.io.InputStream;
import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
@ -48,7 +49,8 @@ import java.util.concurrent.CountDownLatch;
/**
* Bootstrap plugin for LuckPerms running on Nukkit.
*/
public class LPNukkitBootstrap extends PluginBase implements LuckPermsBootstrap {
public class LPNukkitBootstrap implements LuckPermsBootstrap, LoaderBootstrap {
private final PluginBase loader;
/**
* The plugin logger
@ -61,9 +63,9 @@ public class LPNukkitBootstrap extends PluginBase implements LuckPermsBootstrap
private final NukkitSchedulerAdapter schedulerAdapter;
/**
* The plugin classloader
* The plugin class path appender
*/
private final PluginClassLoader classLoader;
private final ClassPathAppender classPathAppender;
/**
* The plugin instance
@ -79,14 +81,24 @@ public class LPNukkitBootstrap extends PluginBase implements LuckPermsBootstrap
private final CountDownLatch loadLatch = new CountDownLatch(1);
private final CountDownLatch enableLatch = new CountDownLatch(1);
public LPNukkitBootstrap() {
public LPNukkitBootstrap(PluginBase loader) {
this.loader = loader;
this.schedulerAdapter = new NukkitSchedulerAdapter(this);
this.classLoader = new ReflectionClassLoader(this);
this.classPathAppender = new JarInJarClassPathAppender(getClass().getClassLoader());
this.plugin = new LPNukkitPlugin(this);
}
// provide adapters
public PluginBase getLoader() {
return this.loader;
}
public Server getServer() {
return this.loader.getServer();
}
@Override
public PluginLogger getPluginLogger() {
if (this.logger == null) {
@ -101,15 +113,15 @@ public class LPNukkitBootstrap extends PluginBase implements LuckPermsBootstrap
}
@Override
public PluginClassLoader getPluginClassLoader() {
return this.classLoader;
public ClassPathAppender getClassPathAppender() {
return this.classPathAppender;
}
// lifecycle
@Override
public void onLoad() {
this.logger = new NukkitPluginLogger(getLogger());
this.logger = new NukkitPluginLogger(this.loader.getLogger());
try {
this.plugin.load();
@ -147,7 +159,7 @@ public class LPNukkitBootstrap extends PluginBase implements LuckPermsBootstrap
@Override
public String getVersion() {
return getDescription().getVersion();
return this.loader.getDescription().getVersion();
}
@Override
@ -174,12 +186,7 @@ public class LPNukkitBootstrap extends PluginBase 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

@ -64,12 +64,11 @@ import net.luckperms.api.query.QueryOptions;
import cn.nukkit.Player;
import cn.nukkit.command.PluginCommand;
import cn.nukkit.permission.Permission;
import cn.nukkit.plugin.PluginBase;
import cn.nukkit.plugin.PluginManager;
import cn.nukkit.plugin.service.ServicePriority;
import cn.nukkit.utils.Config;
import java.io.File;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
@ -100,6 +99,10 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
return this.bootstrap;
}
public PluginBase getLoader() {
return this.bootstrap.getLoader();
}
@Override
protected void setupSenderFactory() {
this.senderFactory = new NukkitSenderFactory(this);
@ -107,14 +110,14 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
@Override
protected ConfigurationAdapter provideConfigurationAdapter() {
return new NukkitConfigAdapter(this, resolveConfig());
return new NukkitConfigAdapter(this, resolveConfig("config.yml").toFile());
}
@Override
protected void registerPlatformListeners() {
this.connectionListener = new NukkitConnectionListener(this);
this.bootstrap.getServer().getPluginManager().registerEvents(this.connectionListener, this.bootstrap);
this.bootstrap.getServer().getPluginManager().registerEvents(new NukkitPlatformListener(this), this.bootstrap);
this.bootstrap.getServer().getPluginManager().registerEvents(this.connectionListener, this.bootstrap.getLoader());
this.bootstrap.getServer().getPluginManager().registerEvents(new NukkitPlatformListener(this), this.bootstrap.getLoader());
}
@Override
@ -146,7 +149,7 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
this.contextManager = new NukkitContextManager(this);
NukkitPlayerCalculator playerCalculator = new NukkitPlayerCalculator(this);
this.bootstrap.getServer().getPluginManager().registerEvents(playerCalculator, this.bootstrap);
this.bootstrap.getServer().getPluginManager().registerEvents(playerCalculator, this.bootstrap.getLoader());
this.contextManager.registerCalculator(playerCalculator);
}
@ -165,7 +168,7 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
// schedule another injection after all plugins have loaded
// the entire pluginmanager instance is replaced by some plugins :(
this.bootstrap.getServer().getScheduler().scheduleDelayedTask(this.bootstrap, injector, 1, true);
this.bootstrap.getServer().getScheduler().scheduleDelayedTask(this.bootstrap.getLoader(), injector, 1, true);
}
}
@ -176,7 +179,7 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
@Override
protected void registerApiOnPlatform(LuckPerms api) {
this.bootstrap.getServer().getServiceManager().register(LuckPerms.class, api, this.bootstrap, ServicePriority.NORMAL);
this.bootstrap.getServer().getServiceManager().register(LuckPerms.class, api, this.bootstrap.getLoader(), ServicePriority.NORMAL);
}
@Override
@ -262,33 +265,6 @@ public class LPNukkitPlugin extends AbstractLuckPermsPlugin {
new PermissibleMonitoringInjector(this, PermissibleMonitoringInjector.Mode.UNINJECT).run();
}
public void refreshAutoOp(Player player) {
if (!getConfiguration().get(ConfigKeys.AUTO_OP)) {
return;
}
User user = getUserManager().getIfLoaded(player.getUniqueId());
boolean value;
if (user != null) {
Map<String, Boolean> permData = user.getCachedData().getPermissionData(this.contextManager.getQueryOptions(player)).getPermissionMap();
value = permData.getOrDefault("luckperms.autoop", false);
} else {
value = false;
}
player.setOp(value);
}
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;
}
@Override
public Optional<QueryOptions> getQueryOptionsForUser(User user) {
return this.bootstrap.getPlayer(user.getUniqueId()).map(player -> this.contextManager.getQueryOptions(player));

View File

@ -52,7 +52,7 @@ public class NukkitCommandExecutor extends CommandManager implements CommandExec
public void register() {
this.command.setExecutor(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 NukkitEventBus extends AbstractEventBus<Plugin> implements Listener
// register listener
LPNukkitBootstrap 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 NukkitSchedulerAdapter extends AbstractJavaScheduler implements Sch
private final Executor sync;
public NukkitSchedulerAdapter(LPNukkitBootstrap bootstrap) {
this.sync = r -> bootstrap.getServer().getScheduler().scheduleTask(bootstrap, r, false);
this.sync = r -> bootstrap.getServer().getScheduler().scheduleTask(bootstrap.getLoader(), r, false);
}
@Override

View File

@ -316,7 +316,7 @@ public class LuckPermsPermissionAttachment extends PermissionAttachment {
@Override
public 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

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

View File

@ -13,11 +13,15 @@ rootProject.name = 'luckperms'
include (
'api',
'common',
'common:loader-utils',
'bukkit',
'bukkit:loader',
'bukkit-legacy',
'bungee',
'bungee:loader',
'fabric',
'nukkit',
'nukkit:loader',
'sponge', 'sponge:sponge-service', 'sponge:sponge-service-api6', 'sponge:sponge-service-api7',
'velocity'
)

View File

@ -63,13 +63,3 @@ shadowJar {
artifacts {
archives shadowJar
}
// Only used occasionally for deployment - not needed for normal builds.
/*
apply plugin: 'signing'
signing {
useGpgCmd()
sign configurations.archives
}
*/

View File

@ -27,9 +27,9 @@ package me.lucko.luckperms.sponge;
import com.google.inject.Inject;
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
import me.lucko.luckperms.common.dependencies.classloader.ReflectionClassLoader;
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
import me.lucko.luckperms.common.plugin.classpath.ReflectionClassPathAppender;
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
import me.lucko.luckperms.common.plugin.logging.Slf4jPluginLogger;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
@ -56,7 +56,6 @@ import org.spongepowered.api.scheduler.SpongeExecutorService;
import org.spongepowered.api.scheduler.SynchronousExecutor;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
@ -95,9 +94,9 @@ public class LPSpongeBootstrap 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
@ -142,7 +141,7 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap {
this.logger = new Slf4jPluginLogger(logger);
this.spongeScheduler = Sponge.getScheduler();
this.schedulerAdapter = new SpongeSchedulerAdapter(this, this.spongeScheduler, syncExecutor, asyncExecutor);
this.classLoader = new ReflectionClassLoader(this);
this.classPathAppender = new ReflectionClassPathAppender(this);
this.plugin = new LPSpongePlugin(this);
}
@ -159,8 +158,8 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap {
}
@Override
public PluginClassLoader getPluginClassLoader() {
return this.classLoader;
public ClassPathAppender getClassPathAppender() {
return this.classPathAppender;
}
// lifecycle
@ -266,11 +265,6 @@ public class LPSpongeBootstrap implements LuckPermsBootstrap {
return this.configDirectory.toAbsolutePath();
}
@Override
public InputStream getResourceStream(String path) {
return getClass().getClassLoader().getResourceAsStream(path);
}
@Override
public Optional<Player> getPlayer(UUID uniqueId) {
return getServer().flatMap(s -> s.getPlayer(uniqueId));

View File

@ -41,7 +41,6 @@ import me.lucko.luckperms.common.sender.DummySender;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
import me.lucko.luckperms.common.util.MoreFiles;
import me.lucko.luckperms.sponge.calculator.SpongeCalculatorFactory;
import me.lucko.luckperms.sponge.commands.SpongeParentCommand;
import me.lucko.luckperms.sponge.context.SpongeContextManager;
@ -67,10 +66,6 @@ import net.luckperms.api.query.QueryOptions;
import org.spongepowered.api.service.permission.PermissionDescription;
import org.spongepowered.api.service.permission.PermissionService;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@ -123,7 +118,7 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin {
@Override
protected ConfigurationAdapter provideConfigurationAdapter() {
return new SpongeConfigAdapter(this, resolveConfig());
return new SpongeConfigAdapter(this, resolveConfig("luckperms.conf"));
}
@Override
@ -236,22 +231,6 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin {
this.service.invalidateAllCaches();
}
private Path resolveConfig() {
Path path = this.bootstrap.getConfigDirectory().resolve("luckperms.conf");
if (!Files.exists(path)) {
try {
MoreFiles.createDirectoriesIfNotExists(this.bootstrap.getConfigDirectory());
try (InputStream is = getClass().getClassLoader().getResourceAsStream("luckperms.conf")) {
Files.copy(is, path);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return path;
}
@Override
public Optional<QueryOptions> getQueryOptionsForUser(User user) {
return this.bootstrap.getPlayer(user.getUniqueId()).map(player -> this.contextManager.getQueryOptions(player));
@ -273,7 +252,7 @@ public class LPSpongePlugin extends AbstractLuckPermsPlugin {
return new DummySender(this, Sender.CONSOLE_UUID, Sender.CONSOLE_NAME) {
@Override
public void sendMessage(Component message) {
LPSpongePlugin.this.bootstrap.getPluginLogger().info(LegacyComponentSerializer.legacySection().serialize(TranslationManager.render(message)));
LPSpongePlugin.this.getLogger().info(LegacyComponentSerializer.legacySection().serialize(TranslationManager.render(message)));
}
};
}

View File

@ -35,8 +35,8 @@ import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
import me.lucko.luckperms.common.plugin.bootstrap.LuckPermsBootstrap;
import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
import me.lucko.luckperms.common.plugin.logging.PluginLogger;
import me.lucko.luckperms.common.plugin.logging.Slf4jPluginLogger;
import me.lucko.luckperms.common.plugin.scheduler.SchedulerAdapter;
@ -45,7 +45,6 @@ import net.luckperms.api.platform.Platform;
import org.slf4j.Logger;
import java.io.InputStream;
import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
@ -79,9 +78,9 @@ public class LPVelocityBootstrap 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
@ -108,7 +107,7 @@ public class LPVelocityBootstrap implements LuckPermsBootstrap {
public LPVelocityBootstrap(Logger logger) {
this.logger = new Slf4jPluginLogger(logger);
this.schedulerAdapter = new VelocitySchedulerAdapter(this);
this.classLoader = new VelocityClassLoader(this);
this.classPathAppender = new VelocityClassPathAppender(this);
this.plugin = new LPVelocityPlugin(this);
}
@ -125,8 +124,8 @@ public class LPVelocityBootstrap implements LuckPermsBootstrap {
}
@Override
public PluginClassLoader getPluginClassLoader() {
return this.classLoader;
public ClassPathAppender getClassPathAppender() {
return this.classPathAppender;
}
// lifecycle
@ -202,11 +201,6 @@ public class LPVelocityBootstrap implements LuckPermsBootstrap {
return this.configDirectory.toAbsolutePath();
}
@Override
public InputStream getResourceStream(String path) {
return getClass().getClassLoader().getResourceAsStream(path);
}
@Override
public Optional<Player> getPlayer(UUID uniqueId) {
return this.proxy.getPlayer(uniqueId);

View File

@ -41,7 +41,6 @@ import me.lucko.luckperms.common.plugin.util.AbstractConnectionListener;
import me.lucko.luckperms.common.sender.Sender;
import me.lucko.luckperms.common.tasks.CacheHousekeepingTask;
import me.lucko.luckperms.common.tasks.ExpireTemporaryTask;
import me.lucko.luckperms.common.util.MoreFiles;
import me.lucko.luckperms.velocity.calculator.VelocityCalculatorFactory;
import me.lucko.luckperms.velocity.context.VelocityContextManager;
import me.lucko.luckperms.velocity.context.VelocityPlayerCalculator;
@ -52,10 +51,6 @@ import me.lucko.luckperms.velocity.messaging.VelocityMessagingFactory;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.query.QueryOptions;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -101,7 +96,7 @@ public class LPVelocityPlugin extends AbstractLuckPermsPlugin {
@Override
protected ConfigurationAdapter provideConfigurationAdapter() {
return new VelocityConfigAdapter(this, resolveConfig());
return new VelocityConfigAdapter(this, resolveConfig("config.yml"));
}
@Override
@ -169,22 +164,6 @@ public class LPVelocityPlugin extends AbstractLuckPermsPlugin {
}
private Path resolveConfig() {
Path path = this.bootstrap.getConfigDirectory().resolve("config.yml");
if (!Files.exists(path)) {
try {
MoreFiles.createDirectoriesIfNotExists(this.bootstrap.getConfigDirectory());
try (InputStream is = getClass().getClassLoader().getResourceAsStream("config.yml")) {
Files.copy(is, path);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return path;
}
@Override
public Optional<QueryOptions> getQueryOptionsForUser(User user) {
return this.bootstrap.getPlayer(user.getUniqueId()).map(player -> this.contextManager.getQueryOptions(player));

View File

@ -25,14 +25,14 @@
package me.lucko.luckperms.velocity;
import me.lucko.luckperms.common.dependencies.classloader.PluginClassLoader;
import me.lucko.luckperms.common.plugin.classpath.ClassPathAppender;
import java.nio.file.Path;
public class VelocityClassLoader implements PluginClassLoader {
public class VelocityClassPathAppender implements ClassPathAppender {
private final LPVelocityBootstrap bootstrap;
public VelocityClassLoader(LPVelocityBootstrap bootstrap) {
public VelocityClassPathAppender(LPVelocityBootstrap bootstrap) {
this.bootstrap = bootstrap;
}