Initial BungeeCord edition

This commit is contained in:
Frank van der Heijden 2020-07-04 21:30:34 +02:00
parent 4416d55173
commit 23e8e80191
No known key found for this signature in database
GPG key ID: 26DA56488D314D11
75 changed files with 1931 additions and 396 deletions

View file

@ -0,0 +1,65 @@
package net.frankheijden.serverutils.bungee;
import co.aikar.commands.BungeeCommandCompletionContext;
import co.aikar.commands.BungeeCommandManager;
import co.aikar.commands.CommandCompletions;
import net.frankheijden.serverutils.bungee.commands.CommandPlugins;
import net.frankheijden.serverutils.bungee.commands.CommandServerUtils;
import net.frankheijden.serverutils.bungee.entities.BungeePlugin;
import net.frankheijden.serverutils.bungee.entities.BungeeReflection;
import net.frankheijden.serverutils.common.ServerUtilsApp;
import net.frankheijden.serverutils.common.config.Config;
import net.frankheijden.serverutils.common.config.Messenger;
import net.frankheijden.serverutils.common.providers.PluginProvider;
import net.md_5.bungee.api.plugin.Plugin;
import org.bstats.bungeecord.Metrics;
public class ServerUtils extends Plugin {
private static ServerUtils instance;
private static final String CONFIG_RESOURCE = "bungee-config.yml";
private static final String MESSAGES_RESOURCE = "bungee-messages.yml";
private BungeePlugin plugin;
private BungeeCommandManager commandManager;
@Override
public void onEnable() {
super.onEnable();
instance = this;
this.plugin = new BungeePlugin(this);
ServerUtilsApp.init(plugin);
new Metrics(this, ServerUtilsApp.BSTATS_METRICS_ID);
new BungeeReflection();
this.commandManager = new BungeeCommandManager(this);
commandManager.registerCommand(new CommandPlugins());
commandManager.registerCommand(new CommandServerUtils());
PluginProvider<Plugin> provider = plugin.getPluginProvider();
CommandCompletions<BungeeCommandCompletionContext> commandCompletions = commandManager.getCommandCompletions();
commandCompletions.registerAsyncCompletion("plugins", context -> provider.getPluginNames());
commandCompletions.registerAsyncCompletion("pluginJars", context -> provider.getPluginFileNames());
reload();
}
public static ServerUtils getInstance() {
return instance;
}
public BungeePlugin getPlugin() {
return plugin;
}
public BungeeCommandManager getCommandManager() {
return commandManager;
}
public void reload() {
new Config("config.yml", CONFIG_RESOURCE);
new Messenger("messages.yml", MESSAGES_RESOURCE);
}
}

View file

@ -0,0 +1,50 @@
package net.frankheijden.serverutils.bungee.commands;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Default;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import net.frankheijden.serverutils.bungee.ServerUtils;
import net.frankheijden.serverutils.bungee.entities.BungeePluginProvider;
import net.frankheijden.serverutils.bungee.utils.BungeeUtils;
import net.frankheijden.serverutils.common.commands.Plugins;
import net.frankheijden.serverutils.common.config.Messenger;
import net.md_5.bungee.api.CommandSender;
@CommandAlias("bpl|bplugins|bungeepl")
public class CommandPlugins extends BaseCommand {
private static final ServerUtils plugin = ServerUtils.getInstance();
private static final BungeePluginProvider provider = (BungeePluginProvider) plugin.getPlugin().getPluginProvider();
/**
* Sends the plugin list to the sender.
* The `-v` flag will output the plugins with version.
* The `-m` flag will also output modules in the plugin list.
* @param sender The sender of the command.
*/
@Default
@CommandCompletion("-v|-m -v|-m")
@CommandPermission("serverutils.plugins")
@Description("Shows the plugins of this proxy.")
public void onPlugins(CommandSender sender, String... args) {
boolean version = contains(args, "-v");
boolean modules = contains(args, "-m");
Plugins.sendPlugins(BungeeUtils.wrap(sender), provider.getPluginsSorted(modules), pl -> {
String ver = version ? Messenger.getMessage("serverutils.plugins.version",
"%version%", pl.getDescription().getVersion()) : "";
return Messenger.getMessage("serverutils.plugins.format",
"%plugin%", pl.getDescription().getName()) + ver;
});
}
private static boolean contains(String[] arr, String val) {
for (String s : arr) {
if (s.equalsIgnoreCase(val)) return true;
}
return false;
}
}

View file

@ -0,0 +1,255 @@
package net.frankheijden.serverutils.bungee.commands;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.RegisteredCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandCompletion;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Default;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.SetMultimap;
import net.frankheijden.serverutils.bungee.ServerUtils;
import net.frankheijden.serverutils.bungee.entities.BungeeLoadResult;
import net.frankheijden.serverutils.bungee.managers.PluginManager;
import net.frankheijden.serverutils.bungee.reflection.RPluginManager;
import net.frankheijden.serverutils.bungee.utils.BungeeUtils;
import net.frankheijden.serverutils.common.config.Messenger;
import net.frankheijden.serverutils.common.entities.CloseableResult;
import net.frankheijden.serverutils.common.entities.Result;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.utils.FormatBuilder;
import net.frankheijden.serverutils.common.utils.ListBuilder;
import net.frankheijden.serverutils.common.utils.ListFormat;
import net.md_5.bungee.api.CommandSender;
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 java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static net.frankheijden.serverutils.common.config.Messenger.sendMessage;
@CommandAlias("bsu|bserverutils")
public class CommandServerUtils extends BaseCommand {
private static final ProxyServer proxy = ProxyServer.getInstance();
private static final ServerUtils plugin = ServerUtils.getInstance();
private static final Set<String> ALIASES;
static {
ALIASES = new HashSet<>();
ALIASES.add("bserverutils");
ALIASES.add("bplugins");
ALIASES.add("bungeepl");
}
/**
* Shows the help page to the sender.
* @param commandSender The sender of the command.
*/
@Default
@Subcommand("help")
@CommandPermission("serverutils.help")
@Description("Shows a help page with a few commands.")
public void onHelp(CommandSender commandSender) {
ServerCommandSender sender = BungeeUtils.wrap(commandSender);
Messenger.sendMessage(sender, "serverutils.help.header");
FormatBuilder builder = FormatBuilder.create(Messenger.getMessage("serverutils.help.format"))
.orderedKeys("%command%", "%subcommand%", "%help%");
plugin.getCommandManager().getRegisteredRootCommands().stream()
.filter(c -> !ALIASES.contains(c.getCommandName().toLowerCase()))
.forEach(rootCommand -> {
builder.add(rootCommand.getCommandName(), "", rootCommand.getDescription());
rootCommand.getSubCommands().forEach((str, cmd) -> {
if (cmd.getPrefSubCommand().isEmpty()) return;
builder.add(rootCommand.getCommandName(), " " + cmd.getPrefSubCommand(), cmd.getHelpText());
});
});
builder.sendTo(sender);
Messenger.sendMessage(sender, "serverutils.help.footer");
}
/**
* Reloads the configurations of ServerUtils.
* @param sender The sender of the command.
*/
@Subcommand("reload")
@CommandPermission("serverutils.reload")
@Description("Reloads the ServerUtils plugin.")
public void onReload(CommandSender sender) {
plugin.reload();
sendMessage(BungeeUtils.wrap(sender), "serverutils.success",
"%action%", "reload",
"%what%", "ServerUtils Bungee configurations");
}
/**
* Loads the specified plugin on the proxy.
* @param commandSender The sender of the command.
* @param jarFile The filename of the plugin in the plugins/ directory.
*/
@Subcommand("loadplugin")
@CommandCompletion("@pluginJars")
@CommandPermission("serverutils.loadplugin")
@Description("Loads the specified jar file as a plugin.")
public void onLoadPlugin(CommandSender commandSender, String jarFile) {
ServerCommandSender sender = BungeeUtils.wrap(commandSender);
BungeeLoadResult loadResult = PluginManager.loadPlugin(jarFile);
if (!loadResult.isSuccess()) {
loadResult.getResult().sendTo(sender, "load", jarFile);
return;
}
Plugin plugin = loadResult.get();
Result result = PluginManager.enablePlugin(plugin);
result.sendTo(sender, "load", plugin.getDescription().getName());
}
/**
* Unloads the specified plugin from the proxy.
* @param commandSender The sender of the command.
* @param pluginName The plugin name.
*/
@Subcommand("unloadplugin")
@CommandCompletion("@plugins")
@CommandPermission("serverutils.unloadplugin")
@Description("Disables and unloads the specified plugin.")
public void onUnloadPlugin(CommandSender commandSender, String pluginName) {
CloseableResult result = PluginManager.unloadPlugin(pluginName);
result.getResult().sendTo(BungeeUtils.wrap(commandSender), "unload", pluginName);
result.tryClose();
}
/**
* Reloads the specified plugin on the proxy.
* @param sender The sender of the command.
* @param pluginName The plugin name.
*/
@Subcommand("reloadplugin")
@CommandCompletion("@plugins")
@CommandPermission("serverutils.reloadplugin")
@Description("Reloads a specified plugin.")
public void onReloadPlugin(CommandSender sender, String pluginName) {
CloseableResult result = PluginManager.reloadPlugin(pluginName);
result.getResult().sendTo(BungeeUtils.wrap(sender), "reload", pluginName);
result.tryClose();
}
/**
* Shows information about the specified plugin.
* @param commandSender The sender of the command.
* @param pluginName The plugin name.
*/
@Subcommand("plugininfo")
@CommandCompletion("@plugins")
@CommandPermission("serverutils.plugininfo")
@Description("Shows information about the specified plugin.")
public void onPluginInfo(CommandSender commandSender, String pluginName) {
ServerCommandSender sender = BungeeUtils.wrap(commandSender);
Plugin plugin = ProxyServer.getInstance().getPluginManager().getPlugin(pluginName);
if (plugin == null) {
Result.NOT_EXISTS.sendTo(sender, "fetch", pluginName);
return;
}
PluginDescription desc = plugin.getDescription();
String format = Messenger.getMessage("serverutils.plugininfo.format");
String listFormatString = Messenger.getMessage("serverutils.plugininfo.list_format");
String seperator = Messenger.getMessage("serverutils.plugininfo.seperator");
String lastSeperator = Messenger.getMessage("serverutils.plugininfo.last_seperator");
ListFormat<String> listFormat = str -> listFormatString.replace("%value%", str);
Messenger.sendMessage(sender, "serverutils.plugininfo.header");
FormatBuilder builder = FormatBuilder.create(format)
.orderedKeys("%key%", "%value%")
.add("Name", desc.getName())
.add("Version", desc.getVersion())
.add("Author", desc.getAuthor())
.add("Description", desc.getDescription())
.add("Main", desc.getMain())
.add("File", desc.getFile().getName())
.add("Depend", ListBuilder.create(desc.getDepends())
.format(listFormat)
.seperator(seperator)
.lastSeperator(lastSeperator)
.toString())
.add("Soft Depend", ListBuilder.create(desc.getSoftDepends())
.format(listFormat)
.seperator(seperator)
.lastSeperator(lastSeperator)
.toString());
builder.sendTo(sender);
Messenger.sendMessage(sender, "serverutils.plugininfo.footer");
}
/**
* Shows information about a provided command.
* @param commandSender The sender of the command.
* @param command The command to lookup.
*/
@Subcommand("commandinfo")
@CommandCompletion("@commands")
@CommandPermission("serverutils.commandinfo")
@Description("Shows information about the specified command.")
public void onCommandInfo(CommandSender commandSender, String command) {
ServerCommandSender sender = BungeeUtils.wrap(commandSender);
Map<String, Command> commands;
try {
commands = RPluginManager.getCommands(proxy.getPluginManager());
} catch (IllegalAccessException ex) {
ex.printStackTrace();
return;
}
Command cmd = commands.get(command);
if (cmd == null) {
Messenger.sendMessage(sender, "serverutils.commandinfo.not_exists");
return;
}
Plugin plugin;
try {
plugin = RPluginManager.getPlugin(proxy.getPluginManager(), cmd);
} catch (IllegalAccessException ex) {
ex.printStackTrace();
return;
}
if (plugin == null) {
return;
}
String format = Messenger.getMessage("serverutils.commandinfo.format");
String listFormatString = Messenger.getMessage("serverutils.commandinfo.list_format");
String seperator = Messenger.getMessage("serverutils.commandinfo.seperator");
String lastSeperator = Messenger.getMessage("serverutils.commandinfo.last_seperator");
ListFormat<String> listFormat = str -> listFormatString.replace("%value%", str);
Messenger.sendMessage(sender, "serverutils.commandinfo.header");
FormatBuilder builder = FormatBuilder.create(format)
.orderedKeys("%key%", "%value%")
.add("Name", cmd.getName())
.add("Plugin", plugin.getDescription().getName())
.add("Aliases", ListBuilder.create(cmd.getAliases())
.format(listFormat)
.seperator(seperator)
.lastSeperator(lastSeperator)
.toString())
.add("Permission", cmd.getPermission());
builder.sendTo(sender);
Messenger.sendMessage(sender, "serverutils.commandinfo.footer");
}
}

View file

@ -0,0 +1,12 @@
package net.frankheijden.serverutils.bungee.entities;
import net.frankheijden.serverutils.common.providers.ColorProvider;
import net.md_5.bungee.api.ChatColor;
public class BungeeColorProvider implements ColorProvider {
@Override
public String apply(String str) {
return ChatColor.translateAlternateColorCodes('&', str);
}
}

View file

@ -0,0 +1,18 @@
package net.frankheijden.serverutils.bungee.entities;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.md_5.bungee.api.CommandSender;
public class BungeeCommandSender implements ServerCommandSender {
private final CommandSender sender;
public BungeeCommandSender(CommandSender sender) {
this.sender = sender;
}
@Override
public void sendMessage(String message) {
sender.sendMessage(message);
}
}

View file

@ -0,0 +1,20 @@
package net.frankheijden.serverutils.bungee.entities;
import net.frankheijden.serverutils.common.entities.LoadResult;
import net.frankheijden.serverutils.common.entities.Result;
import net.md_5.bungee.api.plugin.Plugin;
public class BungeeLoadResult extends LoadResult<Plugin> {
public BungeeLoadResult(Plugin obj, Result result) {
super(obj, result);
}
public BungeeLoadResult(Plugin obj) {
super(obj);
}
public BungeeLoadResult(Result result) {
super(result);
}
}

View file

@ -0,0 +1,56 @@
package net.frankheijden.serverutils.bungee.entities;
import java.io.File;
import java.util.logging.Logger;
import net.frankheijden.serverutils.bungee.ServerUtils;
import net.frankheijden.serverutils.common.providers.ColorProvider;
import net.frankheijden.serverutils.common.providers.PluginProvider;
import net.frankheijden.serverutils.common.providers.ResourceProvider;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
import net.md_5.bungee.api.plugin.Plugin;
public class BungeePlugin extends ServerUtilsPlugin {
private final ServerUtils plugin;
private final PluginProvider<Plugin> pluginProvider;
private final ResourceProvider resourceProvider;
private final ColorProvider colorProvider;
/**
* Creates a new BungeePlugin instance of ServerUtils.
* @param plugin The ServerUtils plugin.
*/
public BungeePlugin(ServerUtils plugin) {
this.plugin = plugin;
this.pluginProvider = new BungeePluginProvider(plugin);
this.resourceProvider = new BungeeResourceProvider(plugin);
this.colorProvider = new BungeeColorProvider();
}
@Override
@SuppressWarnings("unchecked")
public PluginProvider<Plugin> getPluginProvider() {
return pluginProvider;
}
@Override
public ResourceProvider getResourceProvider() {
return resourceProvider;
}
@Override
public ColorProvider getColorProvider() {
return colorProvider;
}
@Override
public Logger getLogger() {
return plugin.getLogger();
}
@Override
public File getDataFolder() {
return plugin.getDataFolder();
}
}

View file

@ -0,0 +1,51 @@
package net.frankheijden.serverutils.bungee.entities;
import net.frankheijden.serverutils.bungee.ServerUtils;
import net.frankheijden.serverutils.bungee.managers.PluginManager;
import net.frankheijden.serverutils.common.providers.PluginProvider;
import net.md_5.bungee.api.plugin.Plugin;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class BungeePluginProvider extends PluginProvider<Plugin> {
private final ServerUtils plugin;
public BungeePluginProvider(ServerUtils plugin) {
this.plugin = plugin;
}
@Override
public File getPluginsFolder() {
return plugin.getProxy().getPluginsFolder();
}
@Override
public List<Plugin> getPlugins() {
return getPlugins(false);
}
public List<Plugin> getPlugins(boolean modules) {
Collection<Plugin> plugins = plugin.getProxy().getPluginManager().getPlugins();
if (modules) return new ArrayList<>(plugins);
return plugins.stream()
.filter(PluginManager::isPlugin)
.collect(Collectors.toList());
}
@Override
public String getPluginName(Plugin plugin) {
return plugin.getDataFolder().getName();
}
public List<Plugin> getPluginsSorted(boolean modules) {
List<Plugin> plugins = getPlugins(modules);
plugins.sort(Comparator.comparing(this::getPluginName));
return plugins;
}
}

View file

@ -0,0 +1,12 @@
package net.frankheijden.serverutils.bungee.entities;
import net.frankheijden.serverutils.common.reflection.ReflectionUtils;
import net.frankheijden.serverutils.common.reflection.VersionParam;
public class BungeeReflection extends ReflectionUtils {
@Override
public boolean isCompatible(VersionParam param) {
return true;
}
}

View file

@ -0,0 +1,38 @@
package net.frankheijden.serverutils.bungee.entities;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import net.frankheijden.serverutils.bungee.ServerUtils;
import net.frankheijden.serverutils.common.providers.ResourceProvider;
import net.frankheijden.serverutils.common.config.YamlConfig;
public class BungeeResourceProvider implements ResourceProvider {
private final ServerUtils plugin;
public BungeeResourceProvider(ServerUtils plugin) {
this.plugin = plugin;
}
@Override
public InputStream getResource(String resource) {
return plugin.getResourceAsStream(resource);
}
@Override
public YamlConfig load(InputStream is) {
return new BungeeYamlConfig(is);
}
@Override
public YamlConfig load(File file) {
try {
return new BungeeYamlConfig(file);
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
}

View file

@ -0,0 +1,65 @@
package net.frankheijden.serverutils.bungee.entities;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import net.frankheijden.serverutils.common.config.YamlConfig;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
public class BungeeYamlConfig implements YamlConfig {
private static final ConfigurationProvider provider = ConfigurationProvider.getProvider(YamlConfiguration.class);
private final Configuration config;
private File file = null;
public BungeeYamlConfig(File file) throws IOException {
this.config = provider.load(file);
this.file = file;
}
public BungeeYamlConfig(InputStream in) {
this.config = provider.load(in);
}
public BungeeYamlConfig(Configuration config) {
this.config = config;
}
@Override
public Object get(String path) {
Object obj = config.get(path);
if (obj instanceof Configuration) {
return new BungeeYamlConfig((Configuration) obj);
}
return obj;
}
@Override
public void set(String path, Object value) {
config.set(path, value);
}
@Override
public String getString(String path) {
return config.getString(path);
}
@Override
public boolean getBoolean(String path) {
return config.getBoolean(path);
}
@Override
public Collection<? extends String> getKeys() {
return config.getKeys();
}
@Override
public void save() throws IOException {
provider.save(config, file);
}
}

View file

@ -0,0 +1,182 @@
package net.frankheijden.serverutils.bungee.managers;
import com.google.common.base.Preconditions;
import net.frankheijden.serverutils.bungee.ServerUtils;
import net.frankheijden.serverutils.bungee.entities.BungeeLoadResult;
import net.frankheijden.serverutils.bungee.entities.BungeePluginProvider;
import net.frankheijden.serverutils.bungee.reflection.RPluginClassLoader;
import net.frankheijden.serverutils.bungee.reflection.RPluginManager;
import net.frankheijden.serverutils.common.entities.CloseableResult;
import net.frankheijden.serverutils.common.entities.Result;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginDescription;
import org.yaml.snakeyaml.Yaml;
import java.io.Closeable;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
public class PluginManager {
private static final ProxyServer proxy = ProxyServer.getInstance();
private static final ServerUtils plugin = ServerUtils.getInstance();
private static final BungeePluginProvider provider = (BungeePluginProvider) plugin.getPlugin().getPluginProvider();
/**
* Checks whether a loaded plugin is a module.
* @param plugin The plugin to check.
* @return Whether or not it's a module.
*/
public static boolean isModule(Plugin plugin) {
return plugin.getFile().getParent().equalsIgnoreCase("modules");
}
/**
* Checks whether a loaded plugin is an actual plugin and not a module.
* @param plugin The plugin to check.
* @return Whether or not it's a plugin.
*/
public static boolean isPlugin(Plugin plugin) {
return !isModule(plugin);
}
public static BungeeLoadResult loadPlugin(String fileName) {
File file = getPluginFileExact(fileName);
if (!file.exists()) return new BungeeLoadResult(Result.NOT_EXISTS);
return loadPlugin(file);
}
public static BungeeLoadResult loadPlugin(File file) {
PluginDescription desc;
try {
desc = getPluginDescription(file);
} catch (Exception ex) {
proxy.getLogger().log(Level.WARNING, "Could not load plugin from file " + file, ex );
return new BungeeLoadResult(Result.INVALID_DESCRIPTION);
}
try {
URL url = desc.getFile().toURI().toURL();
URLClassLoader loader = (URLClassLoader) RPluginClassLoader.newInstance(proxy, desc, url);
Class<?> main = loader.loadClass(desc.getMain());
Plugin plugin = (Plugin) main.getDeclaredConstructor().newInstance();
RPluginManager.getPlugins(proxy.getPluginManager()).put(desc.getName(), plugin);
plugin.onLoad();
proxy.getLogger().log(Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[] {
desc.getName(), desc.getVersion(), desc.getAuthor()
});
return new BungeeLoadResult(plugin);
} catch (Throwable th) {
proxy.getLogger().log(Level.WARNING, "Error loading plugin " + desc.getName(), th);
return new BungeeLoadResult(Result.ERROR);
}
}
public static Result enablePlugin(Plugin plugin) {
PluginDescription desc = plugin.getDescription();
String name = desc.getName();
try {
plugin.onEnable();
proxy.getLogger().log(Level.INFO, "Enabled plugin {0} version {1} by {2}", new Object[] {
name, desc.getVersion(), desc.getAuthor()
});
return Result.SUCCESS;
} catch (Throwable th) {
proxy.getLogger().log(Level.WARNING, "Exception encountered when loading plugin: " + name, th);
return Result.ERROR;
}
}
public static CloseableResult reloadPlugin(String pluginName) {
Plugin plugin = proxy.getPluginManager().getPlugin(pluginName);
if (plugin == null) return new CloseableResult(Result.NOT_ENABLED);
return reloadPlugin(plugin);
}
public static CloseableResult reloadPlugin(Plugin plugin) {
CloseableResult result = unloadPlugin(plugin);
if (result.getResult() != Result.SUCCESS) return result;
File file = getPluginFile(plugin.getDescription().getName());
if (file == null) return result.set(Result.FILE_DELETED);
BungeeLoadResult loadResult = loadPlugin(file);
if (!loadResult.isSuccess()) return result.set(loadResult.getResult());
return result.set(enablePlugin(loadResult.get()));
}
public static CloseableResult unloadPlugin(String pluginName) {
Plugin plugin = proxy.getPluginManager().getPlugin(pluginName);
if (plugin == null) return new CloseableResult(Result.NOT_ENABLED);
return unloadPlugin(plugin);
}
public static CloseableResult unloadPlugin(Plugin plugin) {
plugin.onDisable();
proxy.getPluginManager().unregisterCommands(plugin);
proxy.getPluginManager().unregisterListeners(plugin);
try {
RPluginManager.clearPlugin(proxy.getPluginManager(), plugin);
} catch (Exception ex) {
ex.printStackTrace();
return new CloseableResult(Result.ERROR);
}
return new CloseableResult(getCloseable(plugin));
}
public static File getPluginFileExact(String fileName) {
return new File(proxy.getPluginsFolder(), fileName);
}
public static File getPluginFile(String pluginName) {
for (File file : provider.getPluginJars()) {
PluginDescription desc;
try {
desc = getPluginDescription(file);
} catch (Exception ex) {
continue;
}
if (desc.getName().equals(pluginName)) return file;
}
return null;
}
public static PluginDescription getPluginDescription(File file) throws Exception {
try (JarFile jar = new JarFile(file)) {
JarEntry entry = getPluginDescriptionEntry(jar);
Preconditions.checkNotNull(entry, "Plugin must have a plugin.yml or bungee.yml");
try (InputStream in = jar.getInputStream(entry)) {
Yaml yaml = RPluginManager.getYaml(proxy.getPluginManager());
PluginDescription desc = yaml.loadAs(in, PluginDescription.class);
Preconditions.checkNotNull(desc.getName(), "Plugin from %s has no name", file);
Preconditions.checkNotNull(desc.getMain(), "Plugin from %s has no main", file);
desc.setFile(file);
return desc;
}
}
}
public static JarEntry getPluginDescriptionEntry(JarFile jar) {
JarEntry entry = jar.getJarEntry("bungee.yml");
if (entry == null) return jar.getJarEntry("plugin.yml");
return entry;
}
public static Closeable getCloseable(Plugin plugin) {
ClassLoader loader = plugin.getClass().getClassLoader();
if (loader instanceof Closeable) return (Closeable) loader;
return null;
}
}

View file

@ -0,0 +1,27 @@
package net.frankheijden.serverutils.bungee.reflection;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.VersionParam.ALL_VERSIONS;
import java.lang.reflect.Field;
import java.util.Map;
public class RPlugin {
private static Class<?> pluginClass;
private static Map<String, Field> fields;
static {
try {
pluginClass = Class.forName("net.md_5.bungee.api.plugin.Plugin");
fields = getAllFields(pluginClass,
fieldOf("plugins", ALL_VERSIONS),
fieldOf("toLoad", ALL_VERSIONS),
fieldOf("commandsByPlugin", ALL_VERSIONS),
fieldOf("listenersByPlugin", ALL_VERSIONS));
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

View file

@ -0,0 +1,36 @@
package net.frankheijden.serverutils.bungee.reflection;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.PluginDescription;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.Map;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.VersionParam.ALL_VERSIONS;
public class RPluginClassLoader {
private static Class<?> loaderClass;
private static Map<String, Field> fields;
private static Constructor<?> constructor;
static {
try {
loaderClass = Class.forName("net.md_5.bungee.api.plugin.PluginClassloader");
constructor = loaderClass.getDeclaredConstructor(ProxyServer.class, PluginDescription.class, URL[].class);
constructor.setAccessible(true);
fields = getAllFields(loaderClass);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static Object newInstance(ProxyServer proxy, PluginDescription desc, URL... urls) throws Exception {
return constructor.newInstance(proxy, desc, urls);
}
}

View file

@ -0,0 +1,74 @@
package net.frankheijden.serverutils.bungee.reflection;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.VersionParam.ALL_VERSIONS;
import java.lang.reflect.Field;
import java.util.Map;
import com.google.common.collect.Multimap;
import net.frankheijden.serverutils.common.utils.MapUtils;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.Plugin;
import org.yaml.snakeyaml.Yaml;
public class RPluginManager {
private static Class<?> pluginManagerClass;
private static Map<String, Field> fields;
static {
try {
pluginManagerClass = Class.forName("net.md_5.bungee.api.plugin.PluginManager");
fields = getAllFields(pluginManagerClass,
fieldOf("yaml", ALL_VERSIONS),
fieldOf("plugins", ALL_VERSIONS),
fieldOf("commandMap", ALL_VERSIONS),
fieldOf("toLoad", ALL_VERSIONS),
fieldOf("commandsByPlugin", ALL_VERSIONS));
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Clears the plugin from the PluginManager.
* @param instance The instance of the PluginManager.
* @param plugin The plugin to clear.
* @throws ReflectiveOperationException Iff a reflection error happened.
*/
@SuppressWarnings("rawtypes")
public static void clearPlugin(Object instance, Plugin plugin) throws ReflectiveOperationException {
String pluginName = plugin.getDescription().getName();
MapUtils.remove((Map) get(fields, instance, "plugins"), pluginName);
MapUtils.remove((Map) get(fields, instance, "toLoad"), pluginName);
}
@SuppressWarnings("unchecked")
public static Map<String, Plugin> getPlugins(Object instance) throws ReflectiveOperationException {
return (Map<String, Plugin>) get(fields, instance, "plugins");
}
public static Yaml getYaml(Object instance) throws IllegalAccessException {
return (Yaml) get(fields, instance, "yaml");
}
@SuppressWarnings("unchecked")
public static Map<String, Command> getCommands(Object instance) throws IllegalAccessException {
return (Map<String, Command>) get(fields, instance, "commandMap");
}
@SuppressWarnings("unchecked")
public static Plugin getPlugin(Object instance, Command cmd) throws IllegalAccessException {
Object obj = get(fields, instance, "commandsByPlugin");
Multimap<Plugin, Command> plugins = (Multimap<Plugin, Command>) obj;
if (plugins == null) return null;
for (Map.Entry<Plugin, Command> entry : plugins.entries()) {
if (entry.getValue().equals(cmd)) return entry.getKey();
}
return null;
}
}

View file

@ -0,0 +1,12 @@
package net.frankheijden.serverutils.bungee.utils;
import net.frankheijden.serverutils.bungee.entities.BungeeCommandSender;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.md_5.bungee.api.CommandSender;
public class BungeeUtils {
public static ServerCommandSender wrap(CommandSender sender) {
return new BungeeCommandSender(sender);
}
}