From fc02e77294b487fe1c05c78b1cb4fd51032e3e4a Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 18 May 2024 13:03:55 +0200 Subject: [PATCH] PersistentVelocityCore --- build.gradle | 26 ++- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- src/de/steamwar/bungeecore/Arenaserver.java | 1 - src/de/steamwar/bungeecore/Persistent.java | 97 +++++------ src/de/steamwar/bungeecore/Storage.java | 20 +-- src/de/steamwar/bungeecore/Subserver.java | 121 ++++++++------ .../persistent/ModifiedPluginEventBus.java | 58 ------- src/de/steamwar/persistent/PluginUtils.java | 158 +----------------- src/de/steamwar/persistent/Reflection.java | 1 + src/plugin.yml | 4 - 11 files changed, 146 insertions(+), 344 deletions(-) delete mode 100644 src/de/steamwar/persistent/ModifiedPluginEventBus.java delete mode 100644 src/plugin.yml diff --git a/build.gradle b/build.gradle index 533077e..eb1666a 100644 --- a/build.gradle +++ b/build.gradle @@ -21,19 +21,23 @@ plugins { id 'java' id 'application' - id 'com.github.johnrengelman.shadow' version '5.0.0' + id 'com.github.johnrengelman.shadow' version '8.1.1' id 'de.steamwar.gradle' version 'RELEASE' } group 'de.steamwar' version '' -mainClassName = '' - compileJava.options.encoding = 'UTF-8' -sourceCompatibility = 1.11 -targetCompatibility = 1.11 +application { + mainClassName = '' +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} sourceSets { main { @@ -50,6 +54,13 @@ sourceSets { repositories { mavenCentral() + maven { + name = 'papermc' + url = 'https://repo.papermc.io/repository/maven-public/' + } + maven { + url = 'https://repo.fvdh.dev/releases' + } } dependencies { @@ -58,7 +69,10 @@ dependencies { annotationProcessor 'org.projectlombok:lombok:1.18.22' testAnnotationProcessor 'org.projectlombok:lombok:1.18.22' - compileOnly swdep("waterfall") + compileOnly 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT' + annotationProcessor 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT' + compileOnly 'com.velocitypowered:velocity-proxy:3.3.0-SNAPSHOT' + compileOnly 'net.frankheijden.serverutils:ServerUtils:3.5.4' } steamwar { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3cd8500..d951fac 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index f7829bc..54ae9b3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -26,4 +26,4 @@ pluginManagement { } } -rootProject.name = 'PersistentBungeeCore' +rootProject.name = 'PersistentVelocityCore' diff --git a/src/de/steamwar/bungeecore/Arenaserver.java b/src/de/steamwar/bungeecore/Arenaserver.java index 8c1a734..37bd9db 100644 --- a/src/de/steamwar/bungeecore/Arenaserver.java +++ b/src/de/steamwar/bungeecore/Arenaserver.java @@ -15,5 +15,4 @@ public class Arenaserver extends Subserver { this.map = map; this.allowMerge = allowMerge; } - } diff --git a/src/de/steamwar/bungeecore/Persistent.java b/src/de/steamwar/bungeecore/Persistent.java index 9022e04..3d361c1 100644 --- a/src/de/steamwar/bungeecore/Persistent.java +++ b/src/de/steamwar/bungeecore/Persistent.java @@ -19,71 +19,62 @@ package de.steamwar.bungeecore; -import de.steamwar.persistent.Reflection; -import net.md_5.bungee.api.CommandSender; -import de.steamwar.persistent.ModifiedPluginEventBus; +import com.google.inject.Inject; +import com.velocitypowered.api.command.BrigadierCommand; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; +import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; +import com.velocitypowered.api.plugin.Plugin; +import com.velocitypowered.api.proxy.ProxyServer; import de.steamwar.persistent.PluginUtils; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.plugin.Command; -import net.md_5.bungee.api.plugin.Plugin; -import net.md_5.bungee.api.plugin.PluginDescription; -import net.md_5.bungee.api.plugin.PluginManager; -import net.md_5.bungee.event.EventBus; +import lombok.Getter; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; -import java.io.File; -import java.util.Map; -import java.util.logging.Level; +import java.util.logging.Logger; -public class Persistent extends Plugin { +@Plugin(id = "persistentvelocitycore", name = "PersistentVelocityCore", version = "1.0", description = "PersistentVelocityCore", authors = {"SteamWar"}) +public class Persistent { - public static final String PREFIX = "§eSteam§8War» "; + public static final Component PREFIX = Component.text("Steam").color(NamedTextColor.YELLOW) + .append(Component.text("War»").color(NamedTextColor.DARK_GRAY)) + .appendSpace(); - private static final Reflection.FieldAccessor eventBus = Reflection.getField(PluginManager.class, "eventBus", EventBus.class); + @Getter + private static Persistent instance; - @Override - public void onLoad() { - eventBus.set(getProxy().getPluginManager(), new ModifiedPluginEventBus()); + @Inject + public Persistent(ProxyServer proxyServer, Logger logger) { + instance = this; + this.proxyServer = proxyServer; + this.logger = logger; } - @Override - public void onEnable(){ - getProxy().getPluginManager().registerCommand(this, new Command("softreload", "bungeecore.softreload") { - @Override - public void execute(CommandSender sender, String[] args) { - softreload(); - } - }); + @Getter + private final ProxyServer proxyServer; + + @Getter + private final Logger logger; + + @Subscribe + public void onEnable(ProxyInitializeEvent event) { + proxyServer.getCommandManager().register( + new BrigadierCommand( + BrigadierCommand.literalArgumentBuilder("softreload") + .requires(commandSource -> commandSource.hasPermission("bungeecore.softreload")) + .executes(commandContext -> softreload()) + .build() + ) + ); } - @Override - public void onDisable(){ + @Subscribe + public void onDisable(ProxyShutdownEvent event) { Subserver.shutdown(); } - public void softreload() { - Map commandMap = PluginUtils.CommandMap.get(getProxy().getPluginManager()); - Map plugins = PluginUtils.Plugins.get(getProxy().getPluginManager()); - Object libraryLoader = PluginUtils.LibraryLoader.get(getProxy().getPluginManager()); - PluginDescription desc = PluginUtils.loadDescription(getProxy().getPluginManager(), new File(getProxy().getPluginsFolder(), "BungeeCore.jar")); - - getProxy().getScheduler().runAsync(this, () -> { - getProxy().broadcast(TextComponent.fromLegacyText(PREFIX + "§eNetwork update is starting§8.")); - try { - PluginUtils.unloadPlugin(getProxy(), commandMap, plugins, getProxy().getPluginManager().getPlugin("BungeeCore")); - PluginUtils.loadPlugin(plugins, libraryLoader, desc); - } catch (Throwable t) { - getLogger().log(Level.SEVERE, "Errors during softreload", t); - getProxy().broadcast(TextComponent.fromLegacyText(PREFIX + "§cNetwork update failed§8, §cexpect network restart soon§8.")); - return; - } - - getProxy().broadcast(TextComponent.fromLegacyText(PREFIX + "§eNetwork update complete§8.")); - }); + public int softreload() { + PluginUtils.reloadPlugin(); + return 1; } - - @Deprecated - public static void setLobbyServer(String lobbyServer) {} - - @Deprecated - public static void setChatPrefix(String prefix) {} } diff --git a/src/de/steamwar/bungeecore/Storage.java b/src/de/steamwar/bungeecore/Storage.java index fdcc581..2d71849 100644 --- a/src/de/steamwar/bungeecore/Storage.java +++ b/src/de/steamwar/bungeecore/Storage.java @@ -19,9 +19,9 @@ package de.steamwar.bungeecore; -import net.md_5.bungee.api.config.ServerInfo; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.protocol.packet.PlayerListItem; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.player.TabListEntry; +import com.velocitypowered.api.proxy.server.ServerInfo; import java.sql.Timestamp; import java.util.*; @@ -29,23 +29,23 @@ import java.util.*; public class Storage { private Storage(){} - public static final Map> challenges = new HashMap<>(); + public static final Map> challenges = new HashMap<>(); - public static final Map lastChats = new HashMap<>(); + public static final Map lastChats = new HashMap<>(); public static final Map> teamInvitations = new HashMap<>(); // UserID -> List - public static final Map sessions = new HashMap<>(); // Contains session start timestamp + public static final Map sessions = new HashMap<>(); // Contains session start timestamp public static final Map eventServer = new HashMap<>(); // TeamID -> Subserver map - public static final Set fabricPlayers = new HashSet<>(); + public static final Set fabricPlayers = new HashSet<>(); - public static final Map fabricCheckedPlayers = new HashMap<>(); + public static final Map fabricCheckedPlayers = new HashMap<>(); - public static final Map fabricExpectPluginMessage = new HashMap<>(); + public static final Map fabricExpectPluginMessage = new HashMap<>(); public static final Map teamServers = new HashMap<>(); // TeamID -> ServerInfo map - public static final Map> directTabItems = new HashMap<>(); + public static final Map> directTabItems = new HashMap<>(); } diff --git a/src/de/steamwar/bungeecore/Subserver.java b/src/de/steamwar/bungeecore/Subserver.java index d10372f..95ceb87 100644 --- a/src/de/steamwar/bungeecore/Subserver.java +++ b/src/de/steamwar/bungeecore/Subserver.java @@ -19,13 +19,17 @@ package de.steamwar.bungeecore; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.server.RegisteredServer; +import com.velocitypowered.api.proxy.server.ServerInfo; import lombok.Getter; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.config.ServerInfo; -import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.jetbrains.annotations.Blocking; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; import java.io.*; import java.net.InetSocketAddress; @@ -39,17 +43,18 @@ import java.util.function.Predicate; import java.util.logging.Level; import java.util.logging.Logger; +@SuppressWarnings("unused") public class Subserver { - private static final Logger logger = ProxyServer.getInstance().getLogger(); + private static final Logger logger = Persistent.getInstance().getLogger(); @Getter private static final List serverList = new LinkedList<>(); private static final Map infoToServer = new HashMap<>(); - public static Subserver getSubserver(ProxiedPlayer p) { + public static @Nullable Subserver getSubserver(Player p) { synchronized (serverList) { - for(int i = serverList.size()-1; i >= 0; i--){ - if(serverList.get(i).onServer(p)) + for (int i = serverList.size() - 1; i >= 0; i--) { + if (serverList.get(i).onServer(p)) return serverList.get(i); } } @@ -62,7 +67,7 @@ public class Subserver { } } - static void shutdown(){ + static void shutdown() { while (!serverList.isEmpty()) { Subserver server = serverList.get(0); server.stop(); @@ -78,49 +83,51 @@ public class Subserver { @Getter private final ServerInfo server; @Getter + @Nullable + private RegisteredServer registeredServer; + @Getter private final Servertype type; private final Thread thread; @Getter private boolean started; - private final List cachedPlayers = new LinkedList<>(); + private final List cachedPlayers = new LinkedList<>(); @Getter - private final Map tablistNames = new HashMap<>(); + private final Map tablistNames = new HashMap<>(); - protected Subserver(Servertype type, String serverName, int port, ProcessBuilder processBuilder, Runnable shutdownCallback, Consumer failureCallback) { + protected Subserver(Servertype type, String serverName, int port, ProcessBuilder processBuilder, Runnable shutdownCallback, @Nullable Consumer failureCallback) { this.started = false; this.serverName = serverName; this.type = type; this.shutdownCallback = shutdownCallback; - this.failureCallback = failureCallback == null ? this::fatalError : failureCallback; + this.failureCallback = failureCallback == null ? this::fatalError : failureCallback; this.checkpoint = processBuilder.command().contains("criu"); - try{ + try { this.process = processBuilder.start(); - }catch(IOException e){ + } catch (IOException e) { throw new SecurityException("Server could not be started", e); } InetSocketAddress address = new InetSocketAddress("127.0.0.1", port); - this.server = ProxyServer.getInstance().constructServerInfo( - serverName, address, "SteamWar.de - Subserver", false); + this.server = new ServerInfo(serverName, address); this.writer = new PrintWriter(process.getOutputStream(), true); this.thread = new Thread(this::run, "Subserver " + serverName); this.thread.start(); } - @Deprecated - public boolean hasStarted(){ + @Deprecated(forRemoval = true) + public boolean hasStarted() { return started; } - public void sendPlayer(ProxiedPlayer p) { - if(!started){ - p.sendMessage(ChatMessageType.ACTION_BAR, generateBar(0)); + public void sendPlayer(Player p) { + if (!started) { + p.sendActionBar(generateBar(0)); cachedPlayers.add(p); - }else{ - p.connect(server); + } else { + p.createConnectionRequest(registeredServer).connect(); } } @@ -131,38 +138,40 @@ public class Subserver { public void stop() { try { long pid = process.pid(); - if(checkpoint) + if (checkpoint) pid = process.children().findAny().map(ProcessHandle::pid).orElse(pid); Runtime.getRuntime().exec(new String[]{"kill", "-SIGUSR1", Long.toString(pid)}); } catch (IOException e) { - ProxyServer.getInstance().getLogger().log(Level.SEVERE, "Failed to send SIGUSR1 to subserver.", e); + logger.log(Level.SEVERE, "Failed to send SIGUSR1 to subserver.", e); } try { - if(!process.waitFor(1, TimeUnit.MINUTES)) { + if (!process.waitFor(1, TimeUnit.MINUTES)) { logger.log(Level.SEVERE, () -> serverName + " did not stop correctly, forcibly stopping!"); process.destroyForcibly(); } thread.join(); - }catch(InterruptedException e){ + } catch (InterruptedException e) { logger.log(Level.SEVERE, "Subserver stop interrupted!", e); Thread.currentThread().interrupt(); } } - private boolean onServer(ProxiedPlayer p){ - return cachedPlayers.contains(p) || server.getPlayers().contains(p); + private boolean onServer(Player p) { + return cachedPlayers.contains(p) || (registeredServer != null && registeredServer.getPlayersConnected().contains(p)); } private void fatalError(Exception e) { logger.log(Level.SEVERE, e, () -> serverName + " did not run correctly!"); - for(ProxiedPlayer cached : cachedPlayers) - cached.sendMessage(TextComponent.fromLegacy(Persistent.PREFIX + "§cUnexpected error during server startup.")); - for(ProxiedPlayer player : server.getPlayers()) - player.sendMessage(TextComponent.fromLegacy(Persistent.PREFIX + "§cLost connection to server.")); + for (Player cached : cachedPlayers) + cached.sendMessage(Persistent.PREFIX.append(Component.text("Unexpected error during server startup.").color(NamedTextColor.RED))); + if (registeredServer != null) { + for (Player player : registeredServer.getPlayersConnected()) + player.sendMessage(Persistent.PREFIX.append(Component.text("Lost connection to server.").color(NamedTextColor.RED))); + } } private void start(InputStream stream, Predicate test) throws IOException { @@ -172,13 +181,13 @@ public class Subserver { started = test.test(line); } - if(line == null) + if (line == null) throw new IOException(serverName + " did not start correctly!"); } } protected void register() { - if(ProxyServer.getInstance().getServers().containsKey(serverName)) { + if (Persistent.getInstance().getProxyServer().getAllServers().stream().anyMatch(rs -> rs.getServerInfo().getName().equals(serverName))) { SecurityException e = new SecurityException("Server already registered: " + serverName); stop(); failureCallback.accept(e); @@ -186,17 +195,18 @@ public class Subserver { } synchronized (serverList) { - ProxyServer.getInstance().getServers().put(serverName, server); + registeredServer = Persistent.getInstance().getProxyServer().registerServer(server); serverList.add(this); infoToServer.put(server, this); } } protected void unregister() { - synchronized (serverList){ + synchronized (serverList) { infoToServer.remove(server); serverList.remove(this); - ProxyServer.getInstance().getServers().remove(serverName); + Persistent.getInstance().getProxyServer().unregisterServer(server); + registeredServer = null; } } @@ -205,21 +215,21 @@ public class Subserver { Exception ex = null; try { - if(checkpoint) { + if (checkpoint) { start(process.getErrorStream(), line -> line.contains("Restore finished successfully.")); } else { start(process.getInputStream(), line -> { - if(line.contains("Loading libraries, please wait")) + if (line.contains("Loading libraries, please wait")) sendProgress(2); - else if(line.contains("Starting Minecraft server on")) + else if (line.contains("Starting Minecraft server on")) sendProgress(4); - else if(line.contains("Preparing start region")) + else if (line.contains("Preparing start region")) sendProgress(6); return line.contains("Finished mapping loading"); }); } - if(!started) + if (!started) return; sendProgress(8); @@ -227,32 +237,33 @@ public class Subserver { Thread.sleep(300); sendProgress(10); - for(ProxiedPlayer cachedPlayer : cachedPlayers) { + for (Player cachedPlayer : cachedPlayers) { sendPlayer(cachedPlayer); } cachedPlayers.clear(); process.waitFor(); - } catch(IOException e) { + } catch (IOException e) { ex = e; - } catch(InterruptedException e) { + } catch (InterruptedException e) { ex = e; Thread.currentThread().interrupt(); } finally { unregister(); shutdownCallback.run(); - if(ex != null) + if (ex != null) failureCallback.accept(ex); } } - private BaseComponent generateBar(int progress) { - return TextComponent.fromLegacy("§e" + "⬛".repeat(Math.max(0, progress)) + "§8" + "⬛".repeat(Math.max(0, 10 - progress))); + private Component generateBar(int progress) { + return Component.text("⬛".repeat(Math.max(0, progress))).color(NamedTextColor.GOLD) + .append(Component.text("⬛".repeat(Math.max(0, 10 - progress))).color(NamedTextColor.DARK_GRAY)); } private void sendProgress(int progress) { - BaseComponent tc = generateBar(progress); - for(ProxiedPlayer cached : cachedPlayers) - cached.sendMessage(ChatMessageType.ACTION_BAR, tc); + Component tc = generateBar(progress); + for (Player cached : cachedPlayers) + cached.sendActionBar(tc); } } diff --git a/src/de/steamwar/persistent/ModifiedPluginEventBus.java b/src/de/steamwar/persistent/ModifiedPluginEventBus.java deleted file mode 100644 index a34321f..0000000 --- a/src/de/steamwar/persistent/ModifiedPluginEventBus.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2023 SteamWar.de-Serverteam - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package de.steamwar.persistent; - -import net.md_5.bungee.api.event.AsyncEvent; -import net.md_5.bungee.api.plugin.Plugin; -import net.md_5.bungee.event.EventBus; -import net.md_5.bungee.event.EventExceptionHandler; - -import java.util.Collections; -import java.util.Set; -import java.util.WeakHashMap; - -public final class ModifiedPluginEventBus extends EventBus { - - private static final Set> UNCOMPLETED_EVENTS = Collections.newSetFromMap(new WeakHashMap<>()); - private static final Object LOCK = new Object(); - - public static void completeIntents(Plugin plugin) { - synchronized (LOCK) { - UNCOMPLETED_EVENTS.forEach(event -> { - try { - event.completeIntent(plugin); - } catch (Exception error) { - // Ignored - } - }); - } - } - - @Override - public void post(T event, EventExceptionHandler exceptionHandler) { - if (event instanceof AsyncEvent) { - synchronized (LOCK) { - UNCOMPLETED_EVENTS.add((AsyncEvent) event); - } - } - super.post(event, exceptionHandler); - } - -} diff --git a/src/de/steamwar/persistent/PluginUtils.java b/src/de/steamwar/persistent/PluginUtils.java index d86e472..aa801e8 100644 --- a/src/de/steamwar/persistent/PluginUtils.java +++ b/src/de/steamwar/persistent/PluginUtils.java @@ -19,165 +19,13 @@ package de.steamwar.persistent; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.plugin.Command; -import net.md_5.bungee.api.plugin.Plugin; -import net.md_5.bungee.api.plugin.PluginDescription; -import net.md_5.bungee.api.plugin.PluginManager; -import org.yaml.snakeyaml.Yaml; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URLClassLoader; -import java.util.Map; -import java.util.ResourceBundle; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.logging.Handler; -import java.util.logging.Level; +import net.frankheijden.serverutils.velocity.ServerUtils; public final class PluginUtils { - //Adapted from https://github.com/Shevchik/BungeePluginManager/blob/master/src/bungeepluginmanager/PluginUtils.java - - private static final Class LibraryLoaderClass = Reflection.getClass("net.md_5.bungee.api.plugin.LibraryLoader"); - private static final Reflection.MethodInvoker createLoader = Reflection.getTypedMethod(LibraryLoaderClass, "createLoader", ClassLoader.class, PluginDescription.class); - - public static final Reflection.FieldAccessor CommandMap = Reflection.getField(PluginManager.class, "commandMap", Map.class); - public static final Reflection.FieldAccessor Plugins = Reflection.getField(PluginManager.class, "plugins", Map.class); - public static final Reflection.FieldAccessor Yaml = Reflection.getField(PluginManager.class, "yaml", Yaml.class); - public static final Reflection.FieldAccessor LibraryLoader = Reflection.getField(PluginManager.class, "libraryLoader", LibraryLoaderClass); - public static final Reflection.FieldAccessor Service = Reflection.getField(Plugin.class, "service", ExecutorService.class); - - private static final Class PluginClassLoaderClass = Reflection.getClass("net.md_5.bungee.api.plugin.PluginClassloader"); - private static final Reflection.ConstructorInvoker NewPluginClassLoader = Reflection.getConstructor(PluginClassLoaderClass, ProxyServer.class, PluginDescription.class, File.class, ClassLoader.class); - - private static final Reflection.MethodInvoker init = Reflection.getMethod(Plugin.class, "init", ProxyServer.class, PluginDescription.class); - - private static final Set allLoaders = Reflection.getField(PluginClassLoaderClass, "allLoaders", Set.class).get(null); private PluginUtils() {} - public static void unloadPlugin(ProxyServer proxy, Map commandMap, Map plugins, Plugin plugin) { - IllegalStateException error = new IllegalStateException(); - - PluginManager pluginManager = proxy.getPluginManager(); - ClassLoader pluginClassLoader = plugin.getClass().getClassLoader(); - - try { - plugin.onDisable(); - } catch (Exception e) { - proxy.getLogger().log(Level.SEVERE, "Exception on disable", e); - } - - //unregister event handlers - pluginManager.unregisterListeners(plugin); - - //unregister commands - pluginManager.unregisterCommands(plugin); - //remove incorrectly registered plugins - commandMap.entrySet().removeIf(entry -> entry.getValue().getClass().getClassLoader() == pluginClassLoader); - - //cancel scheduled tasks - proxy.getScheduler().cancel(plugin); - - //finish uncompleted intents - ModifiedPluginEventBus.completeIntents(plugin); - - //shutdown internal executor - ExecutorService service = Service.get(plugin); - if(service != null) - service.shutdownNow(); - - //stop all still active threads that belong to a plugin - for(Thread thread : Thread.getAllStackTraces().keySet()) { - if(thread.getClass().getClassLoader() != pluginClassLoader) - continue; - - thread.interrupt(); - try { - thread.join(100); - } catch (InterruptedException t) { - Thread.currentThread().interrupt(); - } - - if (thread.isAlive()) - proxy.getLogger().log(Level.WARNING, () -> "Could not stop thread " + thread.getName() + " of plugin " + plugin.getDescription().getName() + ". Still running"); - } - - //Clear resource bundle cache - ResourceBundle.clearCache(pluginClassLoader); - - //close all log handlers - for (Handler handler : plugin.getLogger().getHandlers()) { - handler.close(); - } - - //cleanup internal listener and command maps from plugin refs - plugins.values().remove(plugin); - - // Remove classloader - allLoaders.remove(pluginClassLoader); - - //close classloader - if (pluginClassLoader instanceof URLClassLoader) { - try { - ((URLClassLoader) pluginClassLoader).close(); - } catch (Exception e) { - proxy.getLogger().log(Level.SEVERE, "Exception while closing the classloader", e); - } - } - - if(error.getSuppressed().length > 0) { - throw error; - } - } - - public static PluginDescription loadDescription(PluginManager pluginManager, File pluginFile) { - PluginDescription desc; - try (JarFile jar = new JarFile(pluginFile)) { - JarEntry pdf = jar.getJarEntry("bungee.yml"); - - if (pdf == null) { - pdf = jar.getJarEntry("plugin.yml"); - } - - try (InputStream in = jar.getInputStream(pdf)) { - //load description - desc = PluginUtils.Yaml.get(pluginManager).loadAs(in, PluginDescription.class); - } - } catch (IOException e) { - throw new IllegalStateException(e); - } - desc.setFile(pluginFile); - - //check depends - Map pluginsMap = PluginUtils.Plugins.get(pluginManager); - for (String dependency : desc.getDepends()) { - if (!pluginsMap.containsKey(dependency)) { - throw new IllegalStateException(dependency +" (required by " + desc.getName() + ") is unavailable"); - } - } - - return desc; - } - - public static void loadPlugin(Map plugins, Object libraryLoader, PluginDescription desc) { - URLClassLoader loader = (URLClassLoader)NewPluginClassLoader.invoke(ProxyServer.getInstance(), desc, desc.getFile(), libraryLoader != null ? createLoader.invoke(libraryLoader, desc) : null); - - Plugin plugin; - try { - Class mainclazz = loader.loadClass(desc.getMain()); - plugin = (Plugin) Reflection.newInstance(mainclazz); - } catch (ClassNotFoundException e) { - throw new IllegalStateException(e); - } - init.invoke(plugin, ProxyServer.getInstance(), desc); - - plugins.put(desc.getName(), plugin); - plugin.onLoad(); - plugin.onEnable(); + public static void reloadPlugin() { + ServerUtils.getInstance().getPlugin().getPluginManager().reloadPlugin("VelocityCore"); } } diff --git a/src/de/steamwar/persistent/Reflection.java b/src/de/steamwar/persistent/Reflection.java index 94f68d9..16e8377 100644 --- a/src/de/steamwar/persistent/Reflection.java +++ b/src/de/steamwar/persistent/Reflection.java @@ -8,6 +8,7 @@ import java.util.Arrays; * * @author Kristian */ +@Deprecated(forRemoval = true, since = "VelocityCore") public final class Reflection { /** * An interface for invoking a specific constructor. diff --git a/src/plugin.yml b/src/plugin.yml deleted file mode 100644 index cda33ce..0000000 --- a/src/plugin.yml +++ /dev/null @@ -1,4 +0,0 @@ -name: PersistentBungeeCore -main: de.steamwar.bungeecore.Persistent -version: 1.0 -author: Lixfel -- 2.39.2