mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-15 05:41:51 +08:00
Use plugin classloader for thread context when initializing system
This allows ServiceLoader to find slf4j-nop provider for Jetty preventing SLF4J "No provider" error Affects issues: - Fixed #2438
This commit is contained in:
parent
a82bcbff0d
commit
b0be4f296d
@ -90,7 +90,7 @@ subprojects {
|
|||||||
mysqlVersion = "8.0.26"
|
mysqlVersion = "8.0.26"
|
||||||
sqliteVersion = "3.36.0.3"
|
sqliteVersion = "3.36.0.3"
|
||||||
hikariVersion = "5.0.1"
|
hikariVersion = "5.0.1"
|
||||||
slf4jVersion = "1.7.36"
|
slf4jVersion = "2.0.0-alpha7"
|
||||||
geoIpVersion = "3.0.1"
|
geoIpVersion = "3.0.1"
|
||||||
gsonVersion = "2.9.0"
|
gsonVersion = "2.9.0"
|
||||||
dependencyDownloadVersion = "1.2.1"
|
dependencyDownloadVersion = "1.2.1"
|
||||||
|
@ -23,5 +23,4 @@ shadowJar {
|
|||||||
configurations = [project.configurations.shadow]
|
configurations = [project.configurations.shadow]
|
||||||
|
|
||||||
relocate 'org.bstats', 'net.playeranalytics.bstats.utilities.metrics'
|
relocate 'org.bstats', 'net.playeranalytics.bstats.utilities.metrics'
|
||||||
relocate 'org.slf4j', 'plan.org.slf4j'
|
|
||||||
}
|
}
|
@ -25,6 +25,7 @@ import com.djrapitops.plan.gathering.ServerShutdownSave;
|
|||||||
import com.djrapitops.plan.settings.locale.Locale;
|
import com.djrapitops.plan.settings.locale.Locale;
|
||||||
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
||||||
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
||||||
|
import com.djrapitops.plan.utilities.java.ThreadContextClassLoaderSwap;
|
||||||
import net.playeranalytics.plugin.BukkitPlatformLayer;
|
import net.playeranalytics.plugin.BukkitPlatformLayer;
|
||||||
import net.playeranalytics.plugin.PlatformAbstractionLayer;
|
import net.playeranalytics.plugin.PlatformAbstractionLayer;
|
||||||
import net.playeranalytics.plugin.scheduling.RunnableFactory;
|
import net.playeranalytics.plugin.scheduling.RunnableFactory;
|
||||||
@ -71,7 +72,7 @@ public class Plan extends JavaPlugin implements PlanPlugin {
|
|||||||
.server(getServer())
|
.server(getServer())
|
||||||
.build();
|
.build();
|
||||||
try {
|
try {
|
||||||
system = component.system();
|
system = ThreadContextClassLoaderSwap.performOperation(getClass().getClassLoader(), component::system);
|
||||||
serverShutdownSave = component.serverShutdownSave();
|
serverShutdownSave = component.serverShutdownSave();
|
||||||
locale = system.getLocaleSystem().getLocale();
|
locale = system.getLocaleSystem().getLocale();
|
||||||
system.enable();
|
system.enable();
|
||||||
@ -175,37 +176,37 @@ public class Plan extends JavaPlugin implements PlanPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Deprecated due to use of APF Config
|
* @deprecated Deprecated due to use of custom Config
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated(since = "Config.java (2018)")
|
||||||
public void reloadConfig() {
|
public void reloadConfig() {
|
||||||
throw new IllegalStateException("This method should be used on this plugin. Use onReload() instead");
|
throw new IllegalStateException("This method should be used on this plugin. Use onReload() instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Deprecated due to use of APF Config
|
* @deprecated Deprecated due to use of custom Config
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated(since = "Config.java (2018)")
|
||||||
public FileConfiguration getConfig() {
|
public FileConfiguration getConfig() {
|
||||||
throw new IllegalStateException("This method should be used on this plugin. Use getMainConfig() instead");
|
throw new IllegalStateException("This method should be used on this plugin. Use getMainConfig() instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Deprecated due to use of APF Config
|
* @deprecated Deprecated due to use of custom Config
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated(since = "Config.java (2018)")
|
||||||
public void saveConfig() {
|
public void saveConfig() {
|
||||||
throw new IllegalStateException("This method should be used on this plugin. Use getMainConfig().save() instead");
|
throw new IllegalStateException("This method should be used on this plugin. Use getMainConfig().save() instead");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Deprecated due to use of APF Config
|
* @deprecated Deprecated due to use of custom Config
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated(since = "Config.java (2018)")
|
||||||
public void saveDefaultConfig() {
|
public void saveDefaultConfig() {
|
||||||
throw new IllegalStateException("This method should be used on this plugin.");
|
throw new IllegalStateException("This method should be used on this plugin.");
|
||||||
}
|
}
|
||||||
|
@ -17,5 +17,4 @@ dependencies {
|
|||||||
shadowJar {
|
shadowJar {
|
||||||
configurations = [project.configurations.shadow]
|
configurations = [project.configurations.shadow]
|
||||||
relocate 'org.bstats', 'net.playeranalytics.bstats.utilities.metrics'
|
relocate 'org.bstats', 'net.playeranalytics.bstats.utilities.metrics'
|
||||||
relocate 'org.slf4j', 'plan.org.slf4j'
|
|
||||||
}
|
}
|
@ -23,6 +23,7 @@ import com.djrapitops.plan.exceptions.EnableException;
|
|||||||
import com.djrapitops.plan.settings.locale.Locale;
|
import com.djrapitops.plan.settings.locale.Locale;
|
||||||
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
||||||
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
||||||
|
import com.djrapitops.plan.utilities.java.ThreadContextClassLoaderSwap;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.playeranalytics.plugin.BungeePlatformLayer;
|
import net.playeranalytics.plugin.BungeePlatformLayer;
|
||||||
import net.playeranalytics.plugin.PlatformAbstractionLayer;
|
import net.playeranalytics.plugin.PlatformAbstractionLayer;
|
||||||
@ -61,7 +62,7 @@ public class PlanBungee extends Plugin implements PlanPlugin {
|
|||||||
.abstractionLayer(abstractionLayer)
|
.abstractionLayer(abstractionLayer)
|
||||||
.build();
|
.build();
|
||||||
try {
|
try {
|
||||||
system = component.system();
|
system = ThreadContextClassLoaderSwap.performOperation(getClass().getClassLoader(), component::system);
|
||||||
locale = system.getLocaleSystem().getLocale();
|
locale = system.getLocaleSystem().getLocale();
|
||||||
system.enable();
|
system.enable();
|
||||||
|
|
||||||
|
@ -170,6 +170,4 @@ processResources {
|
|||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
configurations = [project.configurations.shadow]
|
configurations = [project.configurations.shadow]
|
||||||
|
|
||||||
relocate 'org.slf4j', 'plan.org.slf4j'
|
|
||||||
}
|
}
|
||||||
|
@ -152,6 +152,7 @@ public class PlanSystem implements SubSystem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables only the systems that are required for {@link com.djrapitops.plan.commands.PlanCommand}.
|
* Enables only the systems that are required for {@link com.djrapitops.plan.commands.PlanCommand}.
|
||||||
|
*
|
||||||
* @see #enableOtherThanCommands()
|
* @see #enableOtherThanCommands()
|
||||||
*/
|
*/
|
||||||
public void enableForCommands() {
|
public void enableForCommands() {
|
||||||
|
@ -20,6 +20,7 @@ import com.djrapitops.plan.delivery.webserver.ResponseResolver;
|
|||||||
import com.djrapitops.plan.delivery.webserver.configuration.WebserverConfiguration;
|
import com.djrapitops.plan.delivery.webserver.configuration.WebserverConfiguration;
|
||||||
import com.djrapitops.plan.delivery.webserver.configuration.WebserverLogMessages;
|
import com.djrapitops.plan.delivery.webserver.configuration.WebserverLogMessages;
|
||||||
import com.djrapitops.plan.exceptions.EnableException;
|
import com.djrapitops.plan.exceptions.EnableException;
|
||||||
|
import com.djrapitops.plan.utilities.java.ThreadContextClassLoaderSwap;
|
||||||
import net.playeranalytics.plugin.server.PluginLogger;
|
import net.playeranalytics.plugin.server.PluginLogger;
|
||||||
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
|
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
|
||||||
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
|
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
|
||||||
@ -129,24 +130,19 @@ public class JettyWebserver implements WebServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ALPNServerConnectionFactory getAlpnServerConnectionFactory(String protocol) {
|
private ALPNServerConnectionFactory getAlpnServerConnectionFactory(String protocol) {
|
||||||
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
ClassLoader pluginClassLoader = getClass().getClassLoader();
|
||||||
try {
|
return ThreadContextClassLoaderSwap.performOperation(pluginClassLoader, () -> {
|
||||||
ClassLoader pluginClassLoader = getClass().getClassLoader();
|
try {
|
||||||
// Jetty uses Thread context classloader, so we need to change to plugin classloader where the ALPNProcessor is.
|
Class.forName("org.eclipse.jetty.alpn.java.server.JDK9ServerALPNProcessor");
|
||||||
Thread.currentThread().setContextClassLoader(pluginClassLoader);
|
// ALPN is protocol upgrade protocol required for upgrading http 1.1 connections to 2
|
||||||
|
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory("h2", "h2c", "http/1.1");
|
||||||
Class.forName("org.eclipse.jetty.alpn.java.server.JDK9ServerALPNProcessor");
|
alpn.setDefaultProtocol(protocol);
|
||||||
// ALPN is protocol upgrade protocol required for upgrading http 1.1 connections to 2
|
return alpn;
|
||||||
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory("h2", "h2c", "http/1.1");
|
} catch (ClassNotFoundException ignored) {
|
||||||
alpn.setDefaultProtocol(protocol);
|
logger.warn("JDK9ServerALPNProcessor not found. ALPN is not available.");
|
||||||
|
return null;
|
||||||
return alpn;
|
}
|
||||||
} catch (ClassNotFoundException ignored) {
|
});
|
||||||
logger.warn("JDK9ServerALPNProcessor not found. ALPN is not available.");
|
|
||||||
return null;
|
|
||||||
} finally {
|
|
||||||
Thread.currentThread().setContextClassLoader(contextClassLoader);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<SslContextFactory.Server> getSslContextFactory() {
|
private Optional<SslContextFactory.Server> getSslContextFactory() {
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Player Analytics (Plan).
|
||||||
|
*
|
||||||
|
* Plan is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Plan is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.djrapitops.plan.utilities.java;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class ThreadContextClassLoaderSwap {
|
||||||
|
|
||||||
|
private ThreadContextClassLoaderSwap() {
|
||||||
|
/* static method utility class */
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void performOperation(ClassLoader usingClassLoader, Runnable operation) {
|
||||||
|
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
// Jetty uses Thread context classloader, so we need to change to plugin classloader where the ALPNProcessor is.
|
||||||
|
Thread.currentThread().setContextClassLoader(usingClassLoader);
|
||||||
|
|
||||||
|
operation.run();
|
||||||
|
} finally {
|
||||||
|
Thread.currentThread().setContextClassLoader(contextClassLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T performOperation(ClassLoader usingClassLoader, Supplier<T> operation) {
|
||||||
|
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
// Jetty uses Thread context classloader, so we need to change to plugin classloader where the ALPNProcessor is.
|
||||||
|
Thread.currentThread().setContextClassLoader(usingClassLoader);
|
||||||
|
|
||||||
|
return operation.get();
|
||||||
|
} finally {
|
||||||
|
Thread.currentThread().setContextClassLoader(contextClassLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -50,6 +50,8 @@ shadowJar {
|
|||||||
exclude "**/*.svg"
|
exclude "**/*.svg"
|
||||||
exclude "**/*.psd"
|
exclude "**/*.psd"
|
||||||
exclude "**/*.map"
|
exclude "**/*.map"
|
||||||
|
exclude "LICENSE*.txt"
|
||||||
|
exclude "jetty-dir.css"
|
||||||
|
|
||||||
exclude "**/module-info.class"
|
exclude "**/module-info.class"
|
||||||
exclude "module-info.class"
|
exclude "module-info.class"
|
||||||
|
@ -25,6 +25,7 @@ import com.djrapitops.plan.gathering.ServerShutdownSave;
|
|||||||
import com.djrapitops.plan.settings.locale.Locale;
|
import com.djrapitops.plan.settings.locale.Locale;
|
||||||
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
||||||
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
||||||
|
import com.djrapitops.plan.utilities.java.ThreadContextClassLoaderSwap;
|
||||||
import net.fabricmc.api.DedicatedServerModInitializer;
|
import net.fabricmc.api.DedicatedServerModInitializer;
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
@ -93,7 +94,7 @@ public class PlanFabric implements PlanPlugin, DedicatedServerModInitializer {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
system = component.system();
|
system = ThreadContextClassLoaderSwap.performOperation(getClass().getClassLoader(), component::system);
|
||||||
serverShutdownSave = component.serverShutdownSave();
|
serverShutdownSave = component.serverShutdownSave();
|
||||||
locale = system.getLocaleSystem().getLocale();
|
locale = system.getLocaleSystem().getLocale();
|
||||||
system.enable();
|
system.enable();
|
||||||
|
@ -19,5 +19,4 @@ dependencies {
|
|||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
configurations = [project.configurations.shadow]
|
configurations = [project.configurations.shadow]
|
||||||
relocate 'org.slf4j', 'plan.org.slf4j'
|
|
||||||
}
|
}
|
@ -28,6 +28,7 @@ import com.djrapitops.plan.gathering.ServerShutdownSave;
|
|||||||
import com.djrapitops.plan.settings.locale.Locale;
|
import com.djrapitops.plan.settings.locale.Locale;
|
||||||
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
||||||
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
||||||
|
import com.djrapitops.plan.utilities.java.ThreadContextClassLoaderSwap;
|
||||||
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
import com.djrapitops.plan.utilities.logging.ErrorContext;
|
||||||
import net.playeranalytics.plugin.NukkitPlatformLayer;
|
import net.playeranalytics.plugin.NukkitPlatformLayer;
|
||||||
import net.playeranalytics.plugin.PlatformAbstractionLayer;
|
import net.playeranalytics.plugin.PlatformAbstractionLayer;
|
||||||
@ -75,7 +76,7 @@ public class PlanNukkit extends PluginBase implements PlanPlugin {
|
|||||||
.abstractionLayer(abstractionLayer)
|
.abstractionLayer(abstractionLayer)
|
||||||
.build();
|
.build();
|
||||||
try {
|
try {
|
||||||
system = component.system();
|
system = ThreadContextClassLoaderSwap.performOperation(getClass().getClassLoader(), component::system);
|
||||||
serverShutdownSave = component.serverShutdownSave();
|
serverShutdownSave = component.serverShutdownSave();
|
||||||
locale = system.getLocaleSystem().getLocale();
|
locale = system.getLocaleSystem().getLocale();
|
||||||
system.enable();
|
system.enable();
|
||||||
|
@ -31,6 +31,8 @@ shadowJar {
|
|||||||
exclude "**/*.svg"
|
exclude "**/*.svg"
|
||||||
exclude "**/*.psd"
|
exclude "**/*.psd"
|
||||||
exclude "**/*.map"
|
exclude "**/*.map"
|
||||||
|
exclude "LICENSE*.txt"
|
||||||
|
exclude "jetty-dir.css"
|
||||||
|
|
||||||
exclude "**/module-info.class"
|
exclude "**/module-info.class"
|
||||||
exclude "module-info.class"
|
exclude "module-info.class"
|
||||||
@ -56,6 +58,12 @@ shadowJar {
|
|||||||
exclude "jakarta/xml/**/*"
|
exclude "jakarta/xml/**/*"
|
||||||
exclude "javassist/**/*"
|
exclude "javassist/**/*"
|
||||||
|
|
||||||
|
relocate('org.slf4j', 'plan.org.slf4j') {
|
||||||
|
exclude 'com.djrapitops.plan.PlanVelocity'
|
||||||
|
exclude 'net.playeranalytics.plugin.VelocityPlatformLayer'
|
||||||
|
exclude 'net.playeranalytics.plugin.server.VelocityPluginLogger'
|
||||||
|
}
|
||||||
|
|
||||||
relocate('org.apache', 'plan.org.apache') {
|
relocate('org.apache', 'plan.org.apache') {
|
||||||
exclude 'org/apache/logging/**'
|
exclude 'org/apache/logging/**'
|
||||||
exclude 'org/apache/maven/**' // This needs to be unrelocated for Sponge
|
exclude 'org/apache/maven/**' // This needs to be unrelocated for Sponge
|
||||||
|
@ -24,6 +24,7 @@ import com.djrapitops.plan.gathering.ServerShutdownSave;
|
|||||||
import com.djrapitops.plan.settings.locale.Locale;
|
import com.djrapitops.plan.settings.locale.Locale;
|
||||||
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
||||||
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
||||||
|
import com.djrapitops.plan.utilities.java.ThreadContextClassLoaderSwap;
|
||||||
import net.playeranalytics.plugin.PlatformAbstractionLayer;
|
import net.playeranalytics.plugin.PlatformAbstractionLayer;
|
||||||
import net.playeranalytics.plugin.SpongePlatformLayer;
|
import net.playeranalytics.plugin.SpongePlatformLayer;
|
||||||
import net.playeranalytics.plugin.scheduling.RunnableFactory;
|
import net.playeranalytics.plugin.scheduling.RunnableFactory;
|
||||||
@ -104,7 +105,7 @@ public class PlanSponge implements PlanPlugin {
|
|||||||
|
|
||||||
catchStartupErrors(() -> {
|
catchStartupErrors(() -> {
|
||||||
component = makeComponent();
|
component = makeComponent();
|
||||||
system = component.system();
|
system = ThreadContextClassLoaderSwap.performOperation(getClass().getClassLoader(), component::system);
|
||||||
system.enableForCommands();
|
system.enableForCommands();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -120,7 +121,7 @@ public class PlanSponge implements PlanPlugin {
|
|||||||
if (!firstBoot) {
|
if (!firstBoot) {
|
||||||
// Reinitialize component & system
|
// Reinitialize component & system
|
||||||
component = makeComponent();
|
component = makeComponent();
|
||||||
system = component.system();
|
system = ThreadContextClassLoaderSwap.performOperation(getClass().getClassLoader(), component::system);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverShutdownSave = component.serverShutdownSave();
|
serverShutdownSave = component.serverShutdownSave();
|
||||||
|
@ -23,6 +23,7 @@ import com.djrapitops.plan.exceptions.EnableException;
|
|||||||
import com.djrapitops.plan.settings.locale.Locale;
|
import com.djrapitops.plan.settings.locale.Locale;
|
||||||
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
import com.djrapitops.plan.settings.locale.lang.PluginLang;
|
||||||
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
import com.djrapitops.plan.settings.theme.PlanColorScheme;
|
||||||
|
import com.djrapitops.plan.utilities.java.ThreadContextClassLoaderSwap;
|
||||||
import com.velocitypowered.api.command.CommandManager;
|
import com.velocitypowered.api.command.CommandManager;
|
||||||
import com.velocitypowered.api.event.Subscribe;
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||||
@ -106,7 +107,7 @@ public class PlanVelocity implements PlanPlugin {
|
|||||||
.abstractionLayer(abstractionLayer)
|
.abstractionLayer(abstractionLayer)
|
||||||
.build();
|
.build();
|
||||||
try {
|
try {
|
||||||
system = component.system();
|
system = ThreadContextClassLoaderSwap.performOperation(getClass().getClassLoader(), component::system);
|
||||||
locale = system.getLocaleSystem().getLocale();
|
locale = system.getLocaleSystem().getLocale();
|
||||||
system.enable();
|
system.enable();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user