Merge pull request #25 from FrankHeijden/feature/multi-management
Add initial multi plugin management
This commit is contained in:
commit
bb5c642f31
66 changed files with 2531 additions and 1107 deletions
|
|
@ -4,7 +4,7 @@ version = rootProject.version
|
||||||
archivesBaseName = rootProject.name + '-Bukkit'
|
archivesBaseName = rootProject.name + '-Bukkit'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.github.FrankHeijden.cloud:cloud-paper:fea4605277'
|
implementation "com.github.FrankHeijden.cloud:cloud-paper:${rootProject.cloudVersion}"
|
||||||
implementation 'org.bstats:bstats-bukkit:2.2.1'
|
implementation 'org.bstats:bstats-bukkit:2.2.1'
|
||||||
implementation project(":Common")
|
implementation project(":Common")
|
||||||
compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT'
|
compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT'
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package net.frankheijden.serverutils.bukkit;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import net.frankheijden.serverutils.bukkit.entities.BukkitPlugin;
|
import net.frankheijden.serverutils.bukkit.entities.BukkitPlugin;
|
||||||
import net.frankheijden.serverutils.bukkit.managers.BukkitPluginManager;
|
import net.frankheijden.serverutils.bukkit.managers.BukkitPluginManager;
|
||||||
import net.frankheijden.serverutils.bukkit.reflection.RCraftServer;
|
import net.frankheijden.serverutils.bukkit.reflection.RCraftServer;
|
||||||
|
|
@ -65,14 +66,14 @@ public class ServerUtils extends JavaPlugin {
|
||||||
String commandString = StringUtils.join(":", split, 1);
|
String commandString = StringUtils.join(":", split, 1);
|
||||||
PluginCommand pluginCommand = Bukkit.getPluginCommand(commandString);
|
PluginCommand pluginCommand = Bukkit.getPluginCommand(commandString);
|
||||||
|
|
||||||
Plugin plugin = getPlugin().getPluginManager().getPlugin(split[0]);
|
Optional<Plugin> pluginOptional = getPlugin().getPluginManager().getPlugin(split[0]);
|
||||||
if (plugin == null) {
|
if (!pluginOptional.isPresent()) {
|
||||||
getLogger().warning("Unknown plugin '" + split[0] + "' in disabled-commands!");
|
getLogger().warning("Unknown plugin '" + split[0] + "' in disabled-commands!");
|
||||||
continue;
|
continue;
|
||||||
} else if (pluginCommand == null) {
|
} else if (pluginCommand == null) {
|
||||||
getLogger().warning("Unknown command '" + commandString + "' in disabled-commands!");
|
getLogger().warning("Unknown command '" + commandString + "' in disabled-commands!");
|
||||||
continue;
|
continue;
|
||||||
} else if (!plugin.getName().equalsIgnoreCase(pluginCommand.getPlugin().getName())) {
|
} else if (pluginOptional.get().getName().equalsIgnoreCase(pluginCommand.getPlugin().getName())) {
|
||||||
// No output here, plugin didn't match!
|
// No output here, plugin didn't match!
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package net.frankheijden.serverutils.bukkit.commands;
|
||||||
import cloud.commandframework.CommandManager;
|
import cloud.commandframework.CommandManager;
|
||||||
import cloud.commandframework.arguments.CommandArgument;
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
import cloud.commandframework.context.CommandContext;
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -18,7 +19,8 @@ import net.frankheijden.serverutils.bukkit.reflection.RDedicatedServer;
|
||||||
import net.frankheijden.serverutils.bukkit.utils.ReloadHandler;
|
import net.frankheijden.serverutils.bukkit.utils.ReloadHandler;
|
||||||
import net.frankheijden.serverutils.bukkit.utils.VersionReloadHandler;
|
import net.frankheijden.serverutils.bukkit.utils.VersionReloadHandler;
|
||||||
import net.frankheijden.serverutils.common.commands.CommandServerUtils;
|
import net.frankheijden.serverutils.common.commands.CommandServerUtils;
|
||||||
import net.frankheijden.serverutils.common.entities.Result;
|
import net.frankheijden.serverutils.common.commands.arguments.PluginsArgument;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
||||||
import net.frankheijden.serverutils.common.utils.FormatBuilder;
|
import net.frankheijden.serverutils.common.utils.FormatBuilder;
|
||||||
import net.frankheijden.serverutils.common.utils.ForwardFilter;
|
import net.frankheijden.serverutils.common.utils.ForwardFilter;
|
||||||
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
||||||
|
|
@ -46,7 +48,7 @@ public class BukkitCommandServerUtils extends CommandServerUtils<BukkitPlugin, P
|
||||||
}
|
}
|
||||||
|
|
||||||
public BukkitCommandServerUtils(BukkitPlugin plugin) {
|
public BukkitCommandServerUtils(BukkitPlugin plugin) {
|
||||||
super(plugin);
|
super(plugin, Plugin[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -72,10 +74,14 @@ public class BukkitCommandServerUtils extends CommandServerUtils<BukkitPlugin, P
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
manager.command(buildSubcommand(builder, "enableplugin")
|
manager.command(buildSubcommand(builder, "enableplugin")
|
||||||
.argument(getArgument("plugin"))
|
.argument(getArgument("plugins"))
|
||||||
.handler(this::handleEnablePlugin));
|
.handler(this::handleEnablePlugin));
|
||||||
manager.command(buildSubcommand(builder, "disableplugin")
|
manager.command(buildSubcommand(builder, "disableplugin")
|
||||||
.argument(getArgument("plugin"))
|
.argument(new PluginsArgument<>(
|
||||||
|
true,
|
||||||
|
"plugins",
|
||||||
|
new PluginsArgument.PluginsParser<>(plugin, arrayCreator, getRawPath("disableplugin"))
|
||||||
|
))
|
||||||
.handler(this::handleDisablePlugin));
|
.handler(this::handleDisablePlugin));
|
||||||
manager.command(buildSubcommand(builder, "reloadconfig")
|
manager.command(buildSubcommand(builder, "reloadconfig")
|
||||||
.argument(getArgument("config"))
|
.argument(getArgument("config"))
|
||||||
|
|
@ -84,18 +90,22 @@ public class BukkitCommandServerUtils extends CommandServerUtils<BukkitPlugin, P
|
||||||
|
|
||||||
private void handleEnablePlugin(CommandContext<BukkitCommandSender> context) {
|
private void handleEnablePlugin(CommandContext<BukkitCommandSender> context) {
|
||||||
BukkitCommandSender sender = context.getSender();
|
BukkitCommandSender sender = context.getSender();
|
||||||
String pluginName = context.get("plugin");
|
List<Plugin> plugins = Arrays.asList(context.get("plugins"));
|
||||||
|
|
||||||
Result result = plugin.getPluginManager().enablePlugin(pluginName);
|
PluginResults<Plugin> result = plugin.getPluginManager().enablePlugins(plugins);
|
||||||
result.sendTo(sender, "enabl", pluginName);
|
result.sendTo(sender, "enabl");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleDisablePlugin(CommandContext<BukkitCommandSender> context) {
|
private void handleDisablePlugin(CommandContext<BukkitCommandSender> context) {
|
||||||
BukkitCommandSender sender = context.getSender();
|
BukkitCommandSender sender = context.getSender();
|
||||||
String pluginName = context.get("plugin");
|
List<Plugin> plugins = Arrays.asList(context.get("plugins"));
|
||||||
|
|
||||||
Result result = plugin.getPluginManager().disablePlugin(pluginName);
|
if (checkDependingPlugins(context, sender, plugins, "disableplugin")) {
|
||||||
result.sendTo(sender, "disabl", pluginName);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginResults<Plugin> result = plugin.getPluginManager().disablePlugins(plugins);
|
||||||
|
result.sendTo(sender, "disabl");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleReloadConfig(CommandContext<BukkitCommandSender> context) {
|
private void handleReloadConfig(CommandContext<BukkitCommandSender> context) {
|
||||||
|
|
@ -148,12 +158,11 @@ public class BukkitCommandServerUtils extends CommandServerUtils<BukkitPlugin, P
|
||||||
protected FormatBuilder createPluginInfo(
|
protected FormatBuilder createPluginInfo(
|
||||||
FormatBuilder builder,
|
FormatBuilder builder,
|
||||||
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
|
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
|
||||||
String pluginName
|
Plugin bukkitPlugin
|
||||||
) {
|
) {
|
||||||
Plugin plugin = Bukkit.getPluginManager().getPlugin(pluginName);
|
PluginDescriptionFile description = bukkitPlugin.getDescription();
|
||||||
PluginDescriptionFile description = plugin.getDescription();
|
|
||||||
|
|
||||||
builder.add("Name", plugin.getName())
|
builder.add("Name", bukkitPlugin.getName())
|
||||||
.add("Full Name", description.getFullName())
|
.add("Full Name", description.getFullName())
|
||||||
.add("Version", description.getVersion())
|
.add("Version", description.getVersion())
|
||||||
.add("Website", description.getWebsite())
|
.add("Website", description.getWebsite())
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
package net.frankheijden.serverutils.bukkit.entities;
|
|
||||||
|
|
||||||
import net.frankheijden.serverutils.common.entities.LoadResult;
|
|
||||||
import net.frankheijden.serverutils.common.entities.Result;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
public class BukkitLoadResult extends LoadResult<Plugin> {
|
|
||||||
|
|
||||||
private BukkitLoadResult(Plugin obj, Result result) {
|
|
||||||
super(obj, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BukkitLoadResult(Plugin obj) {
|
|
||||||
this(obj, Result.SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BukkitLoadResult(Result result) {
|
|
||||||
this(null, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package net.frankheijden.serverutils.bukkit.entities;
|
package net.frankheijden.serverutils.bukkit.entities;
|
||||||
|
|
||||||
|
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
|
||||||
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
import cloud.commandframework.execution.CommandExecutionCoordinator;
|
||||||
import cloud.commandframework.paper.PaperCommandManager;
|
import cloud.commandframework.paper.PaperCommandManager;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -16,12 +17,7 @@ import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
public class BukkitPlugin extends ServerUtilsPlugin<
|
public class BukkitPlugin extends ServerUtilsPlugin<Plugin, BukkitTask, BukkitCommandSender, CommandSender, BukkitPluginDescription> {
|
||||||
Plugin,
|
|
||||||
BukkitTask,
|
|
||||||
BukkitCommandSender,
|
|
||||||
CommandSender
|
|
||||||
> {
|
|
||||||
|
|
||||||
private final ServerUtils plugin;
|
private final ServerUtils plugin;
|
||||||
private final BukkitPluginManager pluginManager;
|
private final BukkitPluginManager pluginManager;
|
||||||
|
|
@ -45,8 +41,9 @@ public class BukkitPlugin extends ServerUtilsPlugin<
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PaperCommandManager<BukkitCommandSender> newCommandManager() {
|
protected PaperCommandManager<BukkitCommandSender> newCommandManager() {
|
||||||
|
PaperCommandManager<BukkitCommandSender> commandManager;
|
||||||
try {
|
try {
|
||||||
return new PaperCommandManager<>(
|
commandManager = new PaperCommandManager<>(
|
||||||
plugin,
|
plugin,
|
||||||
CommandExecutionCoordinator.simpleCoordinator(),
|
CommandExecutionCoordinator.simpleCoordinator(),
|
||||||
chatProvider::get,
|
chatProvider::get,
|
||||||
|
|
@ -55,6 +52,17 @@ public class BukkitPlugin extends ServerUtilsPlugin<
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (commandManager.queryCapability(CloudBukkitCapabilities.BRIGADIER)) {
|
||||||
|
commandManager.registerBrigadier();
|
||||||
|
handleBrigadier(commandManager.brigadierManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandManager.queryCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
|
||||||
|
commandManager.registerAsynchronousCompletions();
|
||||||
|
}
|
||||||
|
|
||||||
|
return commandManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package net.frankheijden.serverutils.bukkit.entities;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
||||||
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
|
|
||||||
|
public class BukkitPluginDescription implements ServerUtilsPluginDescription {
|
||||||
|
|
||||||
|
private final PluginDescriptionFile descriptionFile;
|
||||||
|
private final File file;
|
||||||
|
private final String author;
|
||||||
|
private final Set<String> dependencies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new BukkitPluginDescription.
|
||||||
|
*/
|
||||||
|
public BukkitPluginDescription(PluginDescriptionFile descriptionFile, File file) {
|
||||||
|
this.descriptionFile = descriptionFile;
|
||||||
|
this.file = file;
|
||||||
|
this.author = String.join(", ", this.descriptionFile.getAuthors());
|
||||||
|
this.dependencies = new HashSet<>(descriptionFile.getDepend());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return this.descriptionFile.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.descriptionFile.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVersion() {
|
||||||
|
return this.descriptionFile.getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthor() {
|
||||||
|
return this.author;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFile() {
|
||||||
|
return this.file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getDependencies() {
|
||||||
|
return this.dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginDescriptionFile getDescriptionFile() {
|
||||||
|
return descriptionFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,10 +9,11 @@ import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import net.frankheijden.serverutils.bukkit.entities.BukkitLoadResult;
|
import net.frankheijden.serverutils.bukkit.entities.BukkitPluginDescription;
|
||||||
import net.frankheijden.serverutils.bukkit.events.BukkitPluginDisableEvent;
|
import net.frankheijden.serverutils.bukkit.events.BukkitPluginDisableEvent;
|
||||||
import net.frankheijden.serverutils.bukkit.events.BukkitPluginEnableEvent;
|
import net.frankheijden.serverutils.bukkit.events.BukkitPluginEnableEvent;
|
||||||
import net.frankheijden.serverutils.bukkit.events.BukkitPluginLoadEvent;
|
import net.frankheijden.serverutils.bukkit.events.BukkitPluginLoadEvent;
|
||||||
|
|
@ -24,8 +25,10 @@ import net.frankheijden.serverutils.bukkit.reflection.RJavaPlugin;
|
||||||
import net.frankheijden.serverutils.bukkit.reflection.RJavaPluginLoader;
|
import net.frankheijden.serverutils.bukkit.reflection.RJavaPluginLoader;
|
||||||
import net.frankheijden.serverutils.bukkit.reflection.RPluginClassLoader;
|
import net.frankheijden.serverutils.bukkit.reflection.RPluginClassLoader;
|
||||||
import net.frankheijden.serverutils.bukkit.reflection.RSimplePluginManager;
|
import net.frankheijden.serverutils.bukkit.reflection.RSimplePluginManager;
|
||||||
import net.frankheijden.serverutils.common.entities.CloseableResult;
|
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResults;
|
||||||
import net.frankheijden.serverutils.common.entities.Result;
|
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.Result;
|
||||||
|
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
|
||||||
import net.frankheijden.serverutils.common.events.PluginEvent;
|
import net.frankheijden.serverutils.common.events.PluginEvent;
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
@ -35,11 +38,11 @@ import org.bukkit.command.PluginIdentifiableCommand;
|
||||||
import org.bukkit.plugin.InvalidDescriptionException;
|
import org.bukkit.plugin.InvalidDescriptionException;
|
||||||
import org.bukkit.plugin.InvalidPluginException;
|
import org.bukkit.plugin.InvalidPluginException;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
|
||||||
import org.bukkit.plugin.PluginLoader;
|
import org.bukkit.plugin.PluginLoader;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.UnknownDependencyException;
|
import org.bukkit.plugin.UnknownDependencyException;
|
||||||
|
|
||||||
public class BukkitPluginManager implements AbstractPluginManager<Plugin> {
|
public class BukkitPluginManager extends AbstractPluginManager<Plugin, BukkitPluginDescription> {
|
||||||
|
|
||||||
private static BukkitPluginManager instance;
|
private static BukkitPluginManager instance;
|
||||||
|
|
||||||
|
|
@ -51,122 +54,105 @@ public class BukkitPluginManager implements AbstractPluginManager<Plugin> {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the specified file as a plugin.
|
|
||||||
* @param jarFile The name of the file in the plugins/ folder.
|
|
||||||
* @return The result of the loading procedure.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public BukkitLoadResult loadPlugin(String jarFile) {
|
public PluginResults<Plugin> loadPluginDescriptions(List<BukkitPluginDescription> descriptions) {
|
||||||
return loadPlugin(new File(getPluginsFolder(), jarFile));
|
PluginResults<Plugin> pluginResults = new PluginResults<>();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
for (BukkitPluginDescription description : descriptions) {
|
||||||
* Loads the specified file as a plugin.
|
String pluginId = description.getId();
|
||||||
* @param file The file to be loaded.
|
|
||||||
* @return The result of the loading procedure.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BukkitLoadResult loadPlugin(File file) {
|
|
||||||
if (!file.exists()) return new BukkitLoadResult(Result.NOT_EXISTS);
|
|
||||||
|
|
||||||
Plugin loadedPlugin = getLoadedPlugin(file);
|
|
||||||
if (loadedPlugin != null) return new BukkitLoadResult(Result.ALREADY_LOADED);
|
|
||||||
|
|
||||||
Plugin plugin;
|
Plugin plugin;
|
||||||
try {
|
try {
|
||||||
plugin = Bukkit.getPluginManager().loadPlugin(file);
|
plugin = Bukkit.getPluginManager().loadPlugin(description.getFile());
|
||||||
} catch (InvalidDescriptionException ex) {
|
} catch (InvalidDescriptionException ex) {
|
||||||
return new BukkitLoadResult(Result.INVALID_DESCRIPTION);
|
return pluginResults.addResult(pluginId, Result.INVALID_DESCRIPTION);
|
||||||
} catch (UnknownDependencyException ex) {
|
} catch (UnknownDependencyException ex) {
|
||||||
return new BukkitLoadResult(Result.UNKNOWN_DEPENDENCY.arg(ex.getMessage()));
|
return pluginResults.addResult(pluginId, Result.UNKNOWN_DEPENDENCY.arg(ex.getMessage()));
|
||||||
} catch (InvalidPluginException ex) {
|
} catch (InvalidPluginException ex) {
|
||||||
if (ex.getCause() instanceof IllegalArgumentException) {
|
if (ex.getCause() instanceof IllegalArgumentException) {
|
||||||
IllegalArgumentException e = (IllegalArgumentException) ex.getCause();
|
IllegalArgumentException e = (IllegalArgumentException) ex.getCause();
|
||||||
if (e.getMessage().equalsIgnoreCase("Plugin already initialized!")) {
|
if (e.getMessage().equalsIgnoreCase("Plugin already initialized!")) {
|
||||||
return new BukkitLoadResult(Result.ALREADY_ENABLED);
|
return pluginResults.addResult(pluginId, Result.ALREADY_ENABLED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
return new BukkitLoadResult(Result.ERROR);
|
return pluginResults.addResult(pluginId, Result.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugin == null) return new BukkitLoadResult(Result.INVALID_PLUGIN);
|
if (plugin == null) return pluginResults.addResult(pluginId, Result.INVALID_PLUGIN);
|
||||||
Bukkit.getPluginManager().callEvent(new BukkitPluginLoadEvent(plugin, PluginEvent.Stage.PRE));
|
Bukkit.getPluginManager().callEvent(new BukkitPluginLoadEvent(plugin, PluginEvent.Stage.PRE));
|
||||||
plugin.onLoad();
|
plugin.onLoad();
|
||||||
Bukkit.getPluginManager().callEvent(new BukkitPluginLoadEvent(plugin, PluginEvent.Stage.POST));
|
Bukkit.getPluginManager().callEvent(new BukkitPluginLoadEvent(plugin, PluginEvent.Stage.POST));
|
||||||
return new BukkitLoadResult(plugin);
|
pluginResults.addResult(pluginId, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return pluginResults;
|
||||||
* Disables the specified plugin by name and cleans all commands and recipes of the plugin.
|
|
||||||
* @param pluginName The plugin to disable.
|
|
||||||
* @return The result of the disable call.
|
|
||||||
*/
|
|
||||||
public Result disablePlugin(String pluginName) {
|
|
||||||
return disablePlugin(Bukkit.getPluginManager().getPlugin(pluginName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables the specified plugin and cleans all commands and recipes of the plugin.
|
|
||||||
* @param plugin The plugin to disable.
|
|
||||||
* @return The result of the disable call.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Result disablePlugin(Plugin plugin) {
|
public PluginResults<Plugin> disableOrderedPlugins(List<Plugin> plugins) {
|
||||||
if (plugin == null) return Result.NOT_ENABLED;
|
PluginResults<Plugin> disableResults = new PluginResults<>();
|
||||||
if (!plugin.isEnabled()) return Result.ALREADY_DISABLED;
|
|
||||||
|
for (Plugin plugin : plugins) {
|
||||||
|
String pluginId = getPluginId(plugin);
|
||||||
|
if (!isPluginEnabled(pluginId)) return disableResults.addResult(pluginId, Result.ALREADY_DISABLED);
|
||||||
|
|
||||||
Bukkit.getPluginManager().callEvent(new BukkitPluginDisableEvent(plugin, PluginEvent.Stage.PRE));
|
Bukkit.getPluginManager().callEvent(new BukkitPluginDisableEvent(plugin, PluginEvent.Stage.PRE));
|
||||||
try {
|
try {
|
||||||
Bukkit.getPluginManager().disablePlugin(plugin);
|
Bukkit.getPluginManager().disablePlugin(plugin);
|
||||||
RCraftingManager.removeRecipesFor(plugin);
|
RCraftingManager.removeRecipesFor(plugin);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
return Result.ERROR;
|
return disableResults.addResult(pluginId, Result.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
unregisterCommands(plugin);
|
unregisterCommands(plugin);
|
||||||
Bukkit.getPluginManager().callEvent(new BukkitPluginDisableEvent(plugin, PluginEvent.Stage.POST));
|
Bukkit.getPluginManager().callEvent(new BukkitPluginDisableEvent(plugin, PluginEvent.Stage.POST));
|
||||||
return Result.SUCCESS;
|
|
||||||
|
disableResults.addResult(pluginId, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return disableResults;
|
||||||
* Unloads the specified plugin by name and cleans all traces within bukkit.
|
|
||||||
* @param pluginName The plugin to unload.
|
|
||||||
* @return The result of the unload.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public CloseableResult unloadPlugin(String pluginName) {
|
|
||||||
return unloadPlugin(Bukkit.getPluginManager().getPlugin(pluginName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Unloads the specified plugin and cleans all traces within bukkit.
|
|
||||||
* @param plugin The plugin to unload.
|
|
||||||
* @return The result of the unload.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public CloseableResult unloadPlugin(Plugin plugin) {
|
public CloseablePluginResults<Plugin> unloadOrderedPlugins(List<Plugin> plugins) {
|
||||||
if (plugin == null) return new CloseableResult(Result.NOT_EXISTS);
|
CloseablePluginResults<Plugin> unloadResults = new CloseablePluginResults<>();
|
||||||
|
|
||||||
|
for (Plugin plugin : plugins) {
|
||||||
|
String pluginId = getPluginId(plugin);
|
||||||
Bukkit.getPluginManager().callEvent(new BukkitPluginUnloadEvent(plugin, PluginEvent.Stage.PRE));
|
Bukkit.getPluginManager().callEvent(new BukkitPluginUnloadEvent(plugin, PluginEvent.Stage.PRE));
|
||||||
|
|
||||||
|
RCraftingManager.removeRecipesFor(plugin);
|
||||||
|
unregisterCommands(plugin);
|
||||||
|
|
||||||
List<Closeable> closeables = new ArrayList<>();
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
RSimplePluginManager.getPlugins(Bukkit.getPluginManager()).remove(plugin);
|
RSimplePluginManager.getPlugins(Bukkit.getPluginManager()).remove(plugin);
|
||||||
RSimplePluginManager.removeLookupName(Bukkit.getPluginManager(), plugin.getName());
|
RSimplePluginManager.removeLookupName(Bukkit.getPluginManager(), pluginId);
|
||||||
|
|
||||||
ClassLoader loader = RJavaPlugin.getClassLoader(plugin);
|
ClassLoader classLoader = plugin.getClass().getClassLoader();
|
||||||
RPluginClassLoader.clearClassLoader(loader);
|
RPluginClassLoader.clearClassLoader(classLoader);
|
||||||
addIfInstance(closeables, (Closeable) () -> {
|
|
||||||
Map<String, Class<?>> classes = RPluginClassLoader.getClasses(loader);
|
PluginLoader loader = RPluginClassLoader.getLoader(classLoader);
|
||||||
RJavaPluginLoader.removeClasses(getPluginLoader(getPluginFile(plugin)), classes.keySet());
|
Map<String, Class<?>> classes = RPluginClassLoader.getClasses(classLoader);
|
||||||
});
|
RJavaPluginLoader.removeClasses(loader, classes.keySet());
|
||||||
addIfInstance(closeables, loader);
|
|
||||||
addIfInstance(closeables, RJavaPlugin.clearJavaPlugin(plugin));
|
RJavaPlugin.clearJavaPlugin(plugin);
|
||||||
|
|
||||||
|
addIfInstance(closeables, RPluginClassLoader.getLibraryLoader(classLoader));
|
||||||
|
addIfInstance(closeables, classLoader);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
return new CloseableResult(Result.ERROR);
|
return unloadResults.addResult(pluginId, Result.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bukkit.getPluginManager().callEvent(new BukkitPluginUnloadEvent(plugin, PluginEvent.Stage.POST));
|
Bukkit.getPluginManager().callEvent(new BukkitPluginUnloadEvent(plugin, PluginEvent.Stage.POST));
|
||||||
return new CloseableResult(closeables);
|
|
||||||
|
unloadResults.addResult(pluginId, plugin, closeables);
|
||||||
|
}
|
||||||
|
|
||||||
|
return unloadResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addIfInstance(List<Closeable> list, Object obj) {
|
private static void addIfInstance(List<Closeable> list, Object obj) {
|
||||||
|
|
@ -175,68 +161,29 @@ public class BukkitPluginManager implements AbstractPluginManager<Plugin> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Enables the specified plugin by name.
|
protected PluginResults<Plugin> enableOrderedPlugins(List<Plugin> plugins) {
|
||||||
* @param pluginName The plugin to enable.
|
PluginResults<Plugin> enableResults = new PluginResults<>();
|
||||||
* @return The result of the enabling.
|
PluginManager bukkitPluginManager = Bukkit.getPluginManager();
|
||||||
*/
|
for (Plugin plugin : plugins) {
|
||||||
public Result enablePlugin(String pluginName) {
|
String pluginId = getPluginId(plugin);
|
||||||
return enablePlugin(Bukkit.getPluginManager().getPlugin(pluginName));
|
bukkitPluginManager.callEvent(new BukkitPluginEnableEvent(plugin, PluginEvent.Stage.PRE));
|
||||||
|
bukkitPluginManager.enablePlugin(plugin);
|
||||||
|
|
||||||
|
if (!bukkitPluginManager.isPluginEnabled(plugin.getName())) {
|
||||||
|
return enableResults.addResult(pluginId, Result.ERROR);
|
||||||
|
}
|
||||||
|
bukkitPluginManager.callEvent(new BukkitPluginEnableEvent(plugin, PluginEvent.Stage.POST));
|
||||||
|
enableResults.addResult(pluginId, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables the specified plugin.
|
|
||||||
* @param plugin The plugin to enable.
|
|
||||||
* @return The result of the enabling.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Result enablePlugin(Plugin plugin) {
|
|
||||||
if (plugin == null) return Result.NOT_EXISTS;
|
|
||||||
if (Bukkit.getPluginManager().isPluginEnabled(plugin.getName())) return Result.ALREADY_ENABLED;
|
|
||||||
|
|
||||||
Bukkit.getPluginManager().callEvent(new BukkitPluginEnableEvent(plugin, PluginEvent.Stage.PRE));
|
|
||||||
Bukkit.getPluginManager().enablePlugin(plugin);
|
|
||||||
RCraftServer.syncCommands();
|
RCraftServer.syncCommands();
|
||||||
|
return enableResults;
|
||||||
if (!Bukkit.getPluginManager().isPluginEnabled(plugin.getName())) return Result.ERROR;
|
|
||||||
Bukkit.getPluginManager().callEvent(new BukkitPluginEnableEvent(plugin, PluginEvent.Stage.POST));
|
|
||||||
return Result.SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reloads the specified plugin by name.
|
|
||||||
* @param pluginName The plugin to reload.
|
|
||||||
* @return The result of the reload.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Result reloadPlugin(String pluginName) {
|
public boolean isPluginEnabled(String pluginId) {
|
||||||
Plugin plugin = Bukkit.getPluginManager().getPlugin(pluginName);
|
return Bukkit.getPluginManager().isPluginEnabled(pluginId);
|
||||||
if (plugin == null) return Result.NOT_EXISTS;
|
|
||||||
return reloadPlugin(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reloads the specified plugin.
|
|
||||||
* @param plugin The plugin to reload.
|
|
||||||
* @return The result of the reload.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Result reloadPlugin(Plugin plugin) {
|
|
||||||
Result disableResult = disablePlugin(plugin);
|
|
||||||
if (disableResult != Result.SUCCESS && disableResult != Result.ALREADY_DISABLED) {
|
|
||||||
return disableResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseableResult result = unloadPlugin(plugin);
|
|
||||||
if (result.getResult() != Result.SUCCESS) return result.getResult();
|
|
||||||
result.tryClose();
|
|
||||||
|
|
||||||
File pluginFile = getPluginFile(plugin.getName());
|
|
||||||
if (pluginFile == null) return Result.FILE_DELETED;
|
|
||||||
|
|
||||||
BukkitLoadResult loadResult = loadPlugin(pluginFile);
|
|
||||||
if (!loadResult.isSuccess()) return loadResult.getResult();
|
|
||||||
return enablePlugin(loadResult.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -366,45 +313,30 @@ public class BukkitPluginManager implements AbstractPluginManager<Plugin> {
|
||||||
* @param file The file.
|
* @param file The file.
|
||||||
* @return The appropiate PluginLoader.
|
* @return The appropiate PluginLoader.
|
||||||
*/
|
*/
|
||||||
public static PluginLoader getPluginLoader(File file) {
|
public static Optional<PluginLoader> getPluginLoader(File file) {
|
||||||
Map<Pattern, PluginLoader> fileAssociations = getFileAssociations();
|
Map<Pattern, PluginLoader> fileAssociations = getFileAssociations();
|
||||||
if (fileAssociations == null) return null;
|
if (fileAssociations != null) {
|
||||||
|
for (Map.Entry<Pattern, PluginLoader> entry : fileAssociations.entrySet()) {
|
||||||
for (Pattern filter : fileAssociations.keySet()) {
|
Matcher match = entry.getKey().matcher(file.getName());
|
||||||
Matcher match = filter.matcher(file.getName());
|
|
||||||
if (match.find()) {
|
if (match.find()) {
|
||||||
return fileAssociations.get(filter);
|
return Optional.ofNullable(entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
}
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Retrieves a loaded plugin associated to a jar file.
|
public Optional<BukkitPluginDescription> getPluginDescription(File file) throws InvalidPluginDescriptionException {
|
||||||
* @param file The jar file.
|
if (!file.exists()) return Optional.empty();
|
||||||
* @return The already loaded plugin, or null if none.
|
|
||||||
*/
|
Optional<PluginLoader> loader = getPluginLoader(file);
|
||||||
public static Plugin getLoadedPlugin(File file) {
|
if (!loader.isPresent()) throw new InvalidPluginDescriptionException("Plugin loader is not present!");
|
||||||
PluginDescriptionFile descriptionFile;
|
|
||||||
try {
|
try {
|
||||||
descriptionFile = getPluginDescription(file);
|
return Optional.of(new BukkitPluginDescription(loader.get().getPluginDescription(file), file));
|
||||||
} catch (InvalidDescriptionException ex) {
|
} catch (InvalidDescriptionException ex) {
|
||||||
return null;
|
throw new InvalidPluginDescriptionException(ex);
|
||||||
}
|
}
|
||||||
if (descriptionFile == null) return null;
|
|
||||||
return Bukkit.getPluginManager().getPlugin(descriptionFile.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the PluginDescriptionFile of a jar file.
|
|
||||||
* @param file The jar file.
|
|
||||||
* @return The PluginDescriptionFile.
|
|
||||||
* @throws InvalidDescriptionException Iff the PluginDescriptionFile is invalid.
|
|
||||||
*/
|
|
||||||
public static PluginDescriptionFile getPluginDescription(File file) throws InvalidDescriptionException {
|
|
||||||
PluginLoader loader = getPluginLoader(file);
|
|
||||||
if (loader == null) return null;
|
|
||||||
return loader.getPluginDescription(file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -412,29 +344,14 @@ public class BukkitPluginManager implements AbstractPluginManager<Plugin> {
|
||||||
return RJavaPlugin.getFile(plugin);
|
return RJavaPlugin.getFile(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to retrieve the plugin file by plugin name.
|
|
||||||
* @param pluginName The plugin name.
|
|
||||||
* @return The file, or null if invalid or not found.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public File getPluginFile(String pluginName) {
|
public Optional<Plugin> getPlugin(String pluginName) {
|
||||||
for (File file : getPluginJars()) {
|
return Optional.ofNullable(Bukkit.getPluginManager().getPlugin(pluginName));
|
||||||
PluginDescriptionFile descriptionFile;
|
|
||||||
try {
|
|
||||||
descriptionFile = getPluginDescription(file);
|
|
||||||
} catch (InvalidDescriptionException ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (descriptionFile == null) return null;
|
|
||||||
if (descriptionFile.getName().equals(pluginName)) return file;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Plugin getPlugin(String pluginName) {
|
public BukkitPluginDescription getLoadedPluginDescription(Plugin plugin) {
|
||||||
return Bukkit.getPluginManager().getPlugin(pluginName);
|
return new BukkitPluginDescription(plugin.getDescription(), getPluginFile(plugin));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -455,7 +372,7 @@ public class BukkitPluginManager implements AbstractPluginManager<Plugin> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPluginName(Plugin plugin) {
|
public String getPluginId(Plugin plugin) {
|
||||||
return plugin.getName();
|
return plugin.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,6 @@ public class RJavaPlugin {
|
||||||
public static Closeable clearJavaPlugin(Object instance) {
|
public static Closeable clearJavaPlugin(Object instance) {
|
||||||
reflection.set(instance, "loader", null);
|
reflection.set(instance, "loader", null);
|
||||||
reflection.set(instance, "classLoader", null);
|
reflection.set(instance, "classLoader", null);
|
||||||
Class<?> clazz = reflection.invoke(instance, "getClass");
|
|
||||||
if (clazz != null && clazz.getClassLoader() instanceof Closeable) {
|
|
||||||
return (Closeable) clazz.getClassLoader();
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
package net.frankheijden.serverutils.bukkit.reflection;
|
package net.frankheijden.serverutils.bukkit.reflection;
|
||||||
|
|
||||||
import dev.frankheijden.minecraftreflection.MinecraftReflection;
|
import dev.frankheijden.minecraftreflection.MinecraftReflection;
|
||||||
|
import dev.frankheijden.minecraftreflection.exceptions.MinecraftReflectionException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
import dev.frankheijden.minecraftreflection.exceptions.MinecraftReflectionException;
|
|
||||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
import org.bukkit.plugin.java.JavaPluginLoader;
|
||||||
|
|
||||||
public class RJavaPluginLoader {
|
public class RJavaPluginLoader {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package net.frankheijden.serverutils.bukkit.reflection;
|
package net.frankheijden.serverutils.bukkit.reflection;
|
||||||
|
|
||||||
import dev.frankheijden.minecraftreflection.MinecraftReflection;
|
import dev.frankheijden.minecraftreflection.MinecraftReflection;
|
||||||
|
import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.bukkit.plugin.PluginLoader;
|
||||||
|
|
||||||
public class RPluginClassLoader {
|
public class RPluginClassLoader {
|
||||||
|
|
||||||
|
|
@ -23,12 +25,23 @@ public class RPluginClassLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PluginLoader getLoader(ClassLoader loader) {
|
||||||
|
if (loader == null) return null;
|
||||||
|
return reflection.get(loader, "loader");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClassLoader getLibraryLoader(ClassLoader loader) {
|
||||||
|
if (loader == null && MinecraftReflectionVersion.MINOR <= 16) return null;
|
||||||
|
return reflection.get(loader, "libraryLoader");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the plugin fields from the specified PluginClassLoader.
|
* Clears the plugin fields from the specified PluginClassLoader.
|
||||||
* @param pluginLoader The plugin loader instance.
|
* @param pluginLoader The plugin loader instance.
|
||||||
*/
|
*/
|
||||||
public static void clearPluginClassLoader(Object pluginLoader) {
|
public static void clearPluginClassLoader(Object pluginLoader) {
|
||||||
if (pluginLoader == null) return;
|
if (pluginLoader == null) return;
|
||||||
|
|
||||||
reflection.set(pluginLoader, "plugin", null);
|
reflection.set(pluginLoader, "plugin", null);
|
||||||
reflection.set(pluginLoader, "pluginInit", null);
|
reflection.set(pluginLoader, "pluginInit", null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
"ep"
|
"ep"
|
||||||
],
|
],
|
||||||
"permission": "serverutils.enableplugin",
|
"permission": "serverutils.enableplugin",
|
||||||
"description": "Enables the specified plugin.",
|
"description": "Enables the specified plugin(s).",
|
||||||
"display-in-help": true
|
"display-in-help": true
|
||||||
},
|
},
|
||||||
"disableplugin": {
|
"disableplugin": {
|
||||||
|
|
@ -17,8 +17,17 @@
|
||||||
"dp"
|
"dp"
|
||||||
],
|
],
|
||||||
"permission": "serverutils.disableplugin",
|
"permission": "serverutils.disableplugin",
|
||||||
"description": "Disables the specified plugin.",
|
"description": "Disables the specified plugin(s).",
|
||||||
"display-in-help": true
|
"display-in-help": true,
|
||||||
|
"flags": {
|
||||||
|
"force": {
|
||||||
|
"main": "force",
|
||||||
|
"aliases": ["f"],
|
||||||
|
"permission": "serverutils.disableplugin",
|
||||||
|
"description": "Force disables the specified plugin(s).",
|
||||||
|
"display-in-help": false
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"reloadconfig": {
|
"reloadconfig": {
|
||||||
"main": "reloadconfig",
|
"main": "reloadconfig",
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.github.FrankHeijden.cloud:cloud-bungee:fea4605277'
|
implementation "com.github.FrankHeijden.cloud:cloud-bungee:${rootProject.cloudVersion}"
|
||||||
implementation 'org.bstats:bstats-bungeecord:2.2.1'
|
implementation 'org.bstats:bstats-bungeecord:2.2.1'
|
||||||
implementation project(":Common")
|
implementation project(":Common")
|
||||||
compileOnly 'net.md-5:bungeecord-api:1.17-R0.1-SNAPSHOT'
|
compileOnly 'net.md-5:bungeecord-api:1.17-R0.1-SNAPSHOT'
|
||||||
|
|
|
||||||
|
|
@ -19,17 +19,16 @@ import net.md_5.bungee.api.plugin.PluginManager;
|
||||||
public class BungeeCommandServerUtils extends CommandServerUtils<BungeePlugin, Plugin, BungeeCommandSender> {
|
public class BungeeCommandServerUtils extends CommandServerUtils<BungeePlugin, Plugin, BungeeCommandSender> {
|
||||||
|
|
||||||
public BungeeCommandServerUtils(BungeePlugin plugin) {
|
public BungeeCommandServerUtils(BungeePlugin plugin) {
|
||||||
super(plugin);
|
super(plugin, Plugin[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FormatBuilder createPluginInfo(
|
protected FormatBuilder createPluginInfo(
|
||||||
FormatBuilder builder,
|
FormatBuilder builder,
|
||||||
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
|
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
|
||||||
String pluginName
|
Plugin bungeePlugin
|
||||||
) {
|
) {
|
||||||
Plugin container = plugin.getPluginManager().getPlugin(pluginName);
|
PluginDescription desc = bungeePlugin.getDescription();
|
||||||
PluginDescription desc = container.getDescription();
|
|
||||||
|
|
||||||
return builder
|
return builder
|
||||||
.add("Name", desc.getName())
|
.add("Name", desc.getName())
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,12 +15,7 @@ import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.api.scheduler.ScheduledTask;
|
import net.md_5.bungee.api.scheduler.ScheduledTask;
|
||||||
|
|
||||||
public class BungeePlugin extends ServerUtilsPlugin<
|
public class BungeePlugin extends ServerUtilsPlugin<Plugin, ScheduledTask, BungeeCommandSender, CommandSender, BungeePluginDescription> {
|
||||||
Plugin,
|
|
||||||
ScheduledTask,
|
|
||||||
BungeeCommandSender,
|
|
||||||
CommandSender
|
|
||||||
> {
|
|
||||||
|
|
||||||
private final ServerUtils plugin;
|
private final ServerUtils plugin;
|
||||||
private final BungeePluginManager pluginManager;
|
private final BungeePluginManager pluginManager;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
package net.frankheijden.serverutils.bungee.entities;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
||||||
|
import net.md_5.bungee.api.plugin.PluginDescription;
|
||||||
|
|
||||||
|
public class BungeePluginDescription implements ServerUtilsPluginDescription {
|
||||||
|
|
||||||
|
private final PluginDescription description;
|
||||||
|
private final File file;
|
||||||
|
private final Set<String> dependencies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new BungeePluginDescription.
|
||||||
|
*/
|
||||||
|
public BungeePluginDescription(PluginDescription description) {
|
||||||
|
this.description = description;
|
||||||
|
this.file = description.getFile();
|
||||||
|
this.dependencies = new HashSet<>(description.getDepends());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return this.description.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.description.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVersion() {
|
||||||
|
return this.description.getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthor() {
|
||||||
|
return this.description.getAuthor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFile() {
|
||||||
|
return this.file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getDependencies() {
|
||||||
|
return this.dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginDescription getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,38 +1,42 @@
|
||||||
package net.frankheijden.serverutils.bungee.managers;
|
package net.frankheijden.serverutils.bungee.managers;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import net.frankheijden.serverutils.bungee.entities.BungeeLoadResult;
|
import net.frankheijden.serverutils.bungee.entities.BungeePluginDescription;
|
||||||
import net.frankheijden.serverutils.bungee.events.BungeePluginDisableEvent;
|
import net.frankheijden.serverutils.bungee.events.BungeePluginDisableEvent;
|
||||||
import net.frankheijden.serverutils.bungee.events.BungeePluginEnableEvent;
|
import net.frankheijden.serverutils.bungee.events.BungeePluginEnableEvent;
|
||||||
import net.frankheijden.serverutils.bungee.events.BungeePluginLoadEvent;
|
import net.frankheijden.serverutils.bungee.events.BungeePluginLoadEvent;
|
||||||
import net.frankheijden.serverutils.bungee.events.BungeePluginUnloadEvent;
|
import net.frankheijden.serverutils.bungee.events.BungeePluginUnloadEvent;
|
||||||
import net.frankheijden.serverutils.bungee.reflection.RLibraryLoader;
|
|
||||||
import net.frankheijden.serverutils.bungee.reflection.RPluginClassLoader;
|
import net.frankheijden.serverutils.bungee.reflection.RPluginClassLoader;
|
||||||
import net.frankheijden.serverutils.bungee.reflection.RPluginManager;
|
import net.frankheijden.serverutils.bungee.reflection.RPluginManager;
|
||||||
import net.frankheijden.serverutils.common.entities.CloseableResult;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
||||||
import net.frankheijden.serverutils.common.entities.Result;
|
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResults;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.Result;
|
||||||
import net.frankheijden.serverutils.common.events.PluginEvent;
|
import net.frankheijden.serverutils.common.events.PluginEvent;
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.api.plugin.PluginDescription;
|
import net.md_5.bungee.api.plugin.PluginDescription;
|
||||||
|
import net.md_5.bungee.api.plugin.PluginManager;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
public class BungeePluginManager implements AbstractPluginManager<Plugin> {
|
public class BungeePluginManager extends AbstractPluginManager<Plugin, BungeePluginDescription> {
|
||||||
|
|
||||||
private static final ProxyServer proxy = ProxyServer.getInstance();
|
private static final ProxyServer proxy = ProxyServer.getInstance();
|
||||||
|
|
||||||
|
|
@ -65,128 +69,114 @@ public class BungeePluginManager implements AbstractPluginManager<Plugin> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BungeeLoadResult loadPlugin(String pluginFile) {
|
public PluginResults<Plugin> loadPluginDescriptions(List<BungeePluginDescription> descriptions) {
|
||||||
File file = getPluginFileExact(pluginFile);
|
PluginResults<Plugin> loadResults = new PluginResults<>();
|
||||||
if (!file.exists()) return new BungeeLoadResult(Result.NOT_EXISTS);
|
|
||||||
return loadPlugin(file);
|
PluginManager proxyPluginManager = proxy.getPluginManager();
|
||||||
|
Map<String, PluginDescription> toLoad = RPluginManager.getToLoad(proxyPluginManager);
|
||||||
|
if (toLoad == null) toLoad = new HashMap<>(descriptions.size());
|
||||||
|
|
||||||
|
for (BungeePluginDescription description : descriptions) {
|
||||||
|
PluginDescription desc = description.getDescription();
|
||||||
|
toLoad.put(desc.getName(), desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
RPluginManager.setToLoad(proxyPluginManager, toLoad);
|
||||||
|
proxyPluginManager.loadPlugins();
|
||||||
|
|
||||||
|
for (BungeePluginDescription description : descriptions) {
|
||||||
|
Optional<Plugin> pluginOptional = getPlugin(description.getId());
|
||||||
|
if (!pluginOptional.isPresent()) return loadResults.addResult(description.getId(), Result.ERROR);
|
||||||
|
|
||||||
|
Plugin plugin = pluginOptional.get();
|
||||||
|
proxyPluginManager.callEvent(new BungeePluginLoadEvent(plugin, PluginEvent.Stage.PRE));
|
||||||
|
proxyPluginManager.callEvent(new BungeePluginLoadEvent(plugin, PluginEvent.Stage.POST));
|
||||||
|
loadResults.addResult(description.getId(), plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BungeeLoadResult loadPlugin(File file) {
|
public PluginResults<Plugin> enableOrderedPlugins(List<Plugin> plugins) {
|
||||||
PluginDescription desc;
|
PluginResults<Plugin> enableResults = new PluginResults<>();
|
||||||
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 {
|
for (Plugin plugin : plugins) {
|
||||||
Object libraryLoader = RPluginManager.getLibraryLoader(proxy.getPluginManager());
|
ServerUtilsPluginDescription description = getLoadedPluginDescription(plugin);
|
||||||
ClassLoader classLoader = RLibraryLoader.createLoader(libraryLoader, desc);
|
String pluginId = description.getId();
|
||||||
URLClassLoader loader = (URLClassLoader) RPluginClassLoader.newInstance(
|
|
||||||
proxy,
|
|
||||||
desc,
|
|
||||||
desc.getFile(),
|
|
||||||
classLoader
|
|
||||||
);
|
|
||||||
|
|
||||||
Class<?> main = loader.loadClass(desc.getMain());
|
|
||||||
Plugin plugin = (Plugin) main.getDeclaredConstructor().newInstance();
|
|
||||||
|
|
||||||
RPluginManager.getPlugins(proxy.getPluginManager()).put(desc.getName(), plugin);
|
|
||||||
proxy.getPluginManager().callEvent(new BungeePluginLoadEvent(plugin, PluginEvent.Stage.PRE));
|
|
||||||
plugin.onLoad();
|
|
||||||
proxy.getLogger().log(Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[] {
|
|
||||||
desc.getName(), desc.getVersion(), desc.getAuthor()
|
|
||||||
});
|
|
||||||
proxy.getPluginManager().callEvent(new BungeePluginLoadEvent(plugin, PluginEvent.Stage.POST));
|
|
||||||
return new BungeeLoadResult(plugin);
|
|
||||||
} catch (Throwable th) {
|
|
||||||
proxy.getLogger().log(Level.WARNING, "Error loading plugin " + desc.getName(), th);
|
|
||||||
return new BungeeLoadResult(Result.ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Result enablePlugin(Plugin plugin) {
|
|
||||||
PluginDescription desc = plugin.getDescription();
|
|
||||||
String name = desc.getName();
|
|
||||||
proxy.getPluginManager().callEvent(new BungeePluginEnableEvent(plugin, PluginEvent.Stage.PRE));
|
proxy.getPluginManager().callEvent(new BungeePluginEnableEvent(plugin, PluginEvent.Stage.PRE));
|
||||||
try {
|
try {
|
||||||
plugin.onEnable();
|
plugin.onEnable();
|
||||||
Object[] args = new Object[] { name, desc.getVersion(), desc.getAuthor() };
|
} catch (Throwable th) {
|
||||||
|
proxy.getLogger().log(Level.WARNING, "Exception encountered when loading plugin: " + pluginId, th);
|
||||||
|
return enableResults.addResult(pluginId, Result.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] args = new Object[] { description.getId(), description.getVersion(), description.getAuthor() };
|
||||||
proxy.getLogger().log(Level.INFO, "Enabled plugin {0} version {1} by {2}", args);
|
proxy.getLogger().log(Level.INFO, "Enabled plugin {0} version {1} by {2}", args);
|
||||||
proxy.getPluginManager().callEvent(new BungeePluginEnableEvent(plugin, PluginEvent.Stage.POST));
|
proxy.getPluginManager().callEvent(new BungeePluginEnableEvent(plugin, PluginEvent.Stage.POST));
|
||||||
return Result.SUCCESS;
|
enableResults.addResult(pluginId, plugin);
|
||||||
} catch (Throwable th) {
|
|
||||||
proxy.getLogger().log(Level.WARNING, "Exception encountered when loading plugin: " + name, th);
|
|
||||||
return Result.ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return enableResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result disablePlugin(Plugin plugin) {
|
public boolean isPluginEnabled(String pluginId) {
|
||||||
PluginDescription desc = plugin.getDescription();
|
return false; // Not supported on BungeeCord.
|
||||||
String name = desc.getName();
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PluginResults<Plugin> disableOrderedPlugins(List<Plugin> plugins) {
|
||||||
|
PluginResults<Plugin> disableResults = new PluginResults<>();
|
||||||
|
|
||||||
|
for (Plugin plugin : plugins) {
|
||||||
|
String pluginId = getPluginId(plugin);
|
||||||
proxy.getPluginManager().callEvent(new BungeePluginDisableEvent(plugin, PluginEvent.Stage.PRE));
|
proxy.getPluginManager().callEvent(new BungeePluginDisableEvent(plugin, PluginEvent.Stage.PRE));
|
||||||
try {
|
try {
|
||||||
plugin.onDisable();
|
plugin.onDisable();
|
||||||
proxy.getPluginManager().callEvent(new BungeePluginDisableEvent(plugin, PluginEvent.Stage.POST));
|
|
||||||
return Result.SUCCESS;
|
|
||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
proxy.getLogger().log(Level.WARNING, "Exception encountered when disabling plugin: " + name, th);
|
proxy.getLogger().log(Level.WARNING, "Exception encountered when disabling plugin: " + pluginId, th);
|
||||||
return Result.ERROR;
|
return disableResults.addResult(pluginId, Result.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proxy.getPluginManager().callEvent(new BungeePluginDisableEvent(plugin, PluginEvent.Stage.POST));
|
||||||
|
disableResults.addResult(pluginId, plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return disableResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result reloadPlugin(String pluginName) {
|
public CloseablePluginResults<Plugin> unloadOrderedPlugins(List<Plugin> plugins) {
|
||||||
Plugin plugin = proxy.getPluginManager().getPlugin(pluginName);
|
CloseablePluginResults<Plugin> unloadResults = new CloseablePluginResults<>();
|
||||||
if (plugin == null) return Result.NOT_ENABLED;
|
|
||||||
return reloadPlugin(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
for (Plugin plugin : plugins) {
|
||||||
public Result reloadPlugin(Plugin plugin) {
|
String pluginId = getPluginId(plugin);
|
||||||
CloseableResult result = unloadPlugin(plugin);
|
|
||||||
if (result.getResult() != Result.SUCCESS) return result.getResult();
|
|
||||||
result.tryClose();
|
|
||||||
|
|
||||||
File file = getPluginFile(plugin.getDescription().getName());
|
|
||||||
if (file == null) return Result.FILE_DELETED;
|
|
||||||
|
|
||||||
BungeeLoadResult loadResult = loadPlugin(file);
|
|
||||||
if (!loadResult.isSuccess()) return loadResult.getResult();
|
|
||||||
|
|
||||||
return enablePlugin(loadResult.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CloseableResult unloadPlugin(String pluginName) {
|
|
||||||
Plugin plugin = proxy.getPluginManager().getPlugin(pluginName);
|
|
||||||
if (plugin == null) return new CloseableResult(Result.NOT_ENABLED);
|
|
||||||
return unloadPlugin(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CloseableResult unloadPlugin(Plugin plugin) {
|
|
||||||
proxy.getPluginManager().callEvent(new BungeePluginUnloadEvent(plugin, PluginEvent.Stage.PRE));
|
proxy.getPluginManager().callEvent(new BungeePluginUnloadEvent(plugin, PluginEvent.Stage.PRE));
|
||||||
plugin.onDisable();
|
plugin.onDisable();
|
||||||
proxy.getPluginManager().unregisterCommands(plugin);
|
proxy.getPluginManager().unregisterCommands(plugin);
|
||||||
proxy.getPluginManager().unregisterListeners(plugin);
|
proxy.getPluginManager().unregisterListeners(plugin);
|
||||||
proxy.getScheduler().cancel(plugin);
|
proxy.getScheduler().cancel(plugin);
|
||||||
|
plugin.getExecutorService().shutdown();
|
||||||
|
|
||||||
List<Closeable> closeables = new ArrayList<>();
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
RPluginManager.clearPlugin(proxy.getPluginManager(), plugin);
|
RPluginManager.clearPlugin(proxy.getPluginManager(), plugin);
|
||||||
addIfInstance(closeables, RPluginClassLoader.getPluginClassLoader(plugin));
|
addIfInstance(closeables, RPluginClassLoader.removePluginClassLoader(plugin));
|
||||||
addIfInstance(closeables, plugin.getClass().getClassLoader());
|
addIfInstance(closeables, plugin.getClass().getClassLoader());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
return new CloseableResult(Result.ERROR);
|
return unloadResults.addResult(pluginId, Result.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy.getPluginManager().callEvent(new BungeePluginUnloadEvent(plugin, PluginEvent.Stage.POST));
|
proxy.getPluginManager().callEvent(new BungeePluginUnloadEvent(plugin, PluginEvent.Stage.POST));
|
||||||
return new CloseableResult(closeables);
|
unloadResults.addResult(pluginId, plugin, closeables);
|
||||||
|
}
|
||||||
|
|
||||||
|
return unloadResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addIfInstance(List<Closeable> list, Object obj) {
|
private static void addIfInstance(List<Closeable> list, Object obj) {
|
||||||
|
|
@ -195,38 +185,31 @@ public class BungeePluginManager implements AbstractPluginManager<Plugin> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File getPluginFileExact(String fileName) {
|
|
||||||
return new File(proxy.getPluginsFolder(), fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the File of a plugin associated with a name.
|
|
||||||
* @param pluginName The plugin name to search for.
|
|
||||||
* @return The File if the plugin exists with that name.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public File getPluginFile(String pluginName) {
|
public Optional<File> getPluginFile(String pluginId) {
|
||||||
for (File file : getPluginJars()) {
|
for (File file : getPluginJars()) {
|
||||||
PluginDescription desc;
|
BungeePluginDescription description;
|
||||||
try {
|
try {
|
||||||
desc = getPluginDescription(file);
|
Optional<BungeePluginDescription> descriptionOptional = getPluginDescription(file);
|
||||||
|
if (!descriptionOptional.isPresent()) continue;
|
||||||
|
description = descriptionOptional.get();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc.getName().equals(pluginName)) return file;
|
if (description.getId().equals(pluginId)) return Optional.of(file);
|
||||||
}
|
}
|
||||||
return null;
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getPluginFile(Plugin plugin) {
|
public Optional<Plugin> getPlugin(String pluginName) {
|
||||||
return plugin.getFile();
|
return Optional.ofNullable(proxy.getPluginManager().getPlugin(pluginName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Plugin getPlugin(String pluginName) {
|
public BungeePluginDescription getLoadedPluginDescription(Plugin plugin) {
|
||||||
return proxy.getPluginManager().getPlugin(pluginName);
|
return new BungeePluginDescription(plugin.getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -241,38 +224,33 @@ public class BungeePluginManager implements AbstractPluginManager<Plugin> {
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Retrieves the PluginDescription of a (plugin's) File.
|
public Optional<BungeePluginDescription> getPluginDescription(File file) throws InvalidPluginDescriptionException {
|
||||||
* @param file The file.
|
|
||||||
* @return The PluginDescription.
|
|
||||||
* @throws Exception Iff and I/O exception occurred, or notNullChecks failed.
|
|
||||||
*/
|
|
||||||
public static PluginDescription getPluginDescription(File file) throws Exception {
|
|
||||||
try (JarFile jar = new JarFile(file)) {
|
try (JarFile jar = new JarFile(file)) {
|
||||||
JarEntry entry = getPluginDescriptionEntry(jar);
|
JarEntry entry = jar.getJarEntry("bungee.yml");
|
||||||
Preconditions.checkNotNull(entry, "Plugin must have a plugin.yml or bungee.yml");
|
if (entry == null) {
|
||||||
|
entry = jar.getJarEntry("plugin.yml");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry == null) {
|
||||||
|
throw new InvalidPluginDescriptionException("Plugin must have a plugin.yml or bungee.yml");
|
||||||
|
}
|
||||||
|
|
||||||
try (InputStream in = jar.getInputStream(entry)) {
|
try (InputStream in = jar.getInputStream(entry)) {
|
||||||
Yaml yaml = RPluginManager.getYaml(proxy.getPluginManager());
|
Yaml yaml = RPluginManager.getYaml(proxy.getPluginManager());
|
||||||
PluginDescription desc = yaml.loadAs(in, PluginDescription.class);
|
PluginDescription description = yaml.loadAs(in, PluginDescription.class);
|
||||||
Preconditions.checkNotNull(desc.getName(), "Plugin from %s has no name", file);
|
if (description.getName() == null) {
|
||||||
Preconditions.checkNotNull(desc.getMain(), "Plugin from %s has no main", file);
|
throw new InvalidPluginDescriptionException("Plugin from " + file + " has no name");
|
||||||
|
} else if (description.getMain() == null) {
|
||||||
desc.setFile(file);
|
throw new InvalidPluginDescriptionException("Plugin from " + file + " has no main");
|
||||||
return desc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
description.setFile(file);
|
||||||
* Retrieves the JarEntry which contains the Description file of the JarFile.
|
return Optional.of(new BungeePluginDescription(description));
|
||||||
* @param jar The JarFile.
|
}
|
||||||
* @return The description JarEntry.
|
} catch (IOException ex) {
|
||||||
*/
|
throw new InvalidPluginDescriptionException(ex);
|
||||||
public static JarEntry getPluginDescriptionEntry(JarFile jar) {
|
}
|
||||||
JarEntry entry = jar.getJarEntry("bungee.yml");
|
|
||||||
if (entry == null) return jar.getJarEntry("plugin.yml");
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -298,11 +276,6 @@ public class BungeePluginManager implements AbstractPluginManager<Plugin> {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getPluginName(Plugin plugin) {
|
|
||||||
return plugin.getDataFolder().getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the plugins sorted by their names.
|
* Retrieves the plugins sorted by their names.
|
||||||
* @param modules Whether or not to include `module` plugins
|
* @param modules Whether or not to include `module` plugins
|
||||||
|
|
@ -310,7 +283,7 @@ public class BungeePluginManager implements AbstractPluginManager<Plugin> {
|
||||||
*/
|
*/
|
||||||
public List<Plugin> getPluginsSorted(boolean modules) {
|
public List<Plugin> getPluginsSorted(boolean modules) {
|
||||||
List<Plugin> plugins = getPlugins(modules);
|
List<Plugin> plugins = getPlugins(modules);
|
||||||
plugins.sort(Comparator.comparing(this::getPluginName));
|
plugins.sort(Comparator.comparing(this::getPluginId));
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
package net.frankheijden.serverutils.bungee.reflection;
|
|
||||||
|
|
||||||
import dev.frankheijden.minecraftreflection.MinecraftReflection;
|
|
||||||
import net.md_5.bungee.api.plugin.PluginDescription;
|
|
||||||
|
|
||||||
public class RLibraryLoader {
|
|
||||||
|
|
||||||
private static final MinecraftReflection reflection = MinecraftReflection
|
|
||||||
.of("net.md_5.bungee.api.plugin.LibraryLoader");
|
|
||||||
|
|
||||||
private RLibraryLoader() {}
|
|
||||||
|
|
||||||
public static ClassLoader createLoader(Object instance, PluginDescription desc) {
|
|
||||||
return instance == null ? null : reflection.invoke(instance, "createLoader", desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
package net.frankheijden.serverutils.bungee.reflection;
|
package net.frankheijden.serverutils.bungee.reflection;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import dev.frankheijden.minecraftreflection.ClassObject;
|
|
||||||
import dev.frankheijden.minecraftreflection.MinecraftReflection;
|
import dev.frankheijden.minecraftreflection.MinecraftReflection;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.api.plugin.PluginDescription;
|
|
||||||
|
|
||||||
public class RPluginClassLoader {
|
public class RPluginClassLoader {
|
||||||
|
|
||||||
|
|
@ -16,23 +12,9 @@ public class RPluginClassLoader {
|
||||||
private RPluginClassLoader() {}
|
private RPluginClassLoader() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of a PluginClassLoader from given parameters.
|
* Removes the PluginClassLoader of a specific plugin.
|
||||||
*/
|
*/
|
||||||
public static Object newInstance(ProxyServer proxy, PluginDescription desc, File file, ClassLoader classLoader) {
|
public static Object removePluginClassLoader(Plugin plugin) {
|
||||||
return reflection.newInstance(
|
|
||||||
ClassObject.of(ProxyServer.class, proxy),
|
|
||||||
ClassObject.of(PluginDescription.class, desc),
|
|
||||||
ClassObject.of(File.class, file),
|
|
||||||
ClassObject.of(ClassLoader.class, classLoader)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the PluginClassLoader of a specific plugin.
|
|
||||||
* @param plugin The plugin to lookup the PluginClassLoader for.
|
|
||||||
* @return The PluginClassLoader.
|
|
||||||
*/
|
|
||||||
public static Object getPluginClassLoader(Plugin plugin) {
|
|
||||||
Set<Object> allLoaders = reflection.get(null, "allLoaders");
|
Set<Object> allLoaders = reflection.get(null, "allLoaders");
|
||||||
if (allLoaders == null) return null;
|
if (allLoaders == null) return null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import dev.frankheijden.minecraftreflection.MinecraftReflection;
|
||||||
import net.frankheijden.serverutils.common.utils.MapUtils;
|
import net.frankheijden.serverutils.common.utils.MapUtils;
|
||||||
import net.md_5.bungee.api.plugin.Command;
|
import net.md_5.bungee.api.plugin.Command;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
import net.md_5.bungee.api.plugin.PluginDescription;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
public class RPluginManager {
|
public class RPluginManager {
|
||||||
|
|
@ -26,10 +27,6 @@ public class RPluginManager {
|
||||||
MapUtils.remove(reflection.get(instance, "toLoad"), pluginName);
|
MapUtils.remove(reflection.get(instance, "toLoad"), pluginName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, Plugin> getPlugins(Object instance) {
|
|
||||||
return reflection.get(instance, "plugins");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Yaml getYaml(Object instance) {
|
public static Yaml getYaml(Object instance) {
|
||||||
return reflection.get(instance, "yaml");
|
return reflection.get(instance, "yaml");
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +35,14 @@ public class RPluginManager {
|
||||||
return reflection.get(instance, "commandMap");
|
return reflection.get(instance, "commandMap");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Map<String, PluginDescription> getToLoad(Object pluginManager) {
|
||||||
|
return reflection.get(pluginManager, "toLoad");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setToLoad(Object pluginManager, Map<String, PluginDescription> toLoad) {
|
||||||
|
reflection.set(pluginManager, "toLoad", toLoad);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the registered plugin of the command.
|
* Retrieves the registered plugin of the command.
|
||||||
* @param instance The PluginManager instance.
|
* @param instance The PluginManager instance.
|
||||||
|
|
@ -53,8 +58,4 @@ public class RPluginManager {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object getLibraryLoader(Object instance) {
|
|
||||||
return reflection.get(instance, "libraryLoader");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
group = rootProject.group + '.common'
|
group = rootProject.group + '.common'
|
||||||
String dependencyDir = group + '.dependencies'
|
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
archivesBaseName = rootProject.name + '-Common'
|
archivesBaseName = rootProject.name + '-Common'
|
||||||
|
|
||||||
|
|
@ -12,7 +11,6 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.google.code.gson:gson:2.8.6'
|
|
||||||
compileOnly 'com.github.FrankHeijden:ServerUtilsUpdater:v1.0.0'
|
compileOnly 'com.github.FrankHeijden:ServerUtilsUpdater:v1.0.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,5 +23,4 @@ shadowJar {
|
||||||
exclude 'net/frankheijden/serverutilsupdater/**'
|
exclude 'net/frankheijden/serverutilsupdater/**'
|
||||||
exclude 'plugin.yml'
|
exclude 'plugin.yml'
|
||||||
exclude 'bungee.yml'
|
exclude 'bungee.yml'
|
||||||
relocate 'com.google.gson', dependencyDir + '.gson'
|
|
||||||
}
|
}
|
||||||
|
|
@ -3,13 +3,15 @@ package net.frankheijden.serverutils.common;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import net.frankheijden.serverutils.common.entities.CloseableResult;
|
import java.util.Optional;
|
||||||
import net.frankheijden.serverutils.common.entities.Result;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResult;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.PluginResult;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
import net.frankheijden.serverutils.common.tasks.UpdateCheckerTask;
|
import net.frankheijden.serverutils.common.tasks.UpdateCheckerTask;
|
||||||
|
|
||||||
public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S>, P, T, C extends ServerCommandSender<S>, S> {
|
public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S, D>, P, T, C extends ServerCommandSender<S>, S, D extends ServerUtilsPluginDescription> {
|
||||||
|
|
||||||
public static final int BSTATS_METRICS_ID = 7790;
|
public static final int BSTATS_METRICS_ID = 7790;
|
||||||
public static final String VERSION = "{version}";
|
public static final String VERSION = "{version}";
|
||||||
|
|
@ -25,7 +27,14 @@ public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S>, P, T, C ext
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <U extends ServerUtilsPlugin<P, T, C, S>, P, T, C extends ServerCommandSender<S>, S> void init(
|
public static <
|
||||||
|
U extends ServerUtilsPlugin<P, T, C, S, D>,
|
||||||
|
P,
|
||||||
|
T,
|
||||||
|
C extends ServerCommandSender<S>,
|
||||||
|
S,
|
||||||
|
D extends ServerUtilsPluginDescription
|
||||||
|
> void init(
|
||||||
Object platformPlugin,
|
Object platformPlugin,
|
||||||
U plugin
|
U plugin
|
||||||
) {
|
) {
|
||||||
|
|
@ -42,30 +51,31 @@ public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S>, P, T, C ext
|
||||||
/**
|
/**
|
||||||
* Unloads the ServerUtilsUpdater and deletes the file.
|
* Unloads the ServerUtilsUpdater and deletes the file.
|
||||||
*/
|
*/
|
||||||
public static <U extends ServerUtilsPlugin<P, T, C, S>, P, T, C extends ServerCommandSender<S>, S>
|
public static <P> void unloadServerUtilsUpdater() {
|
||||||
void unloadServerUtilsUpdater() {
|
ServerUtilsPlugin<P, ?, ?, ?, ?> plugin = getPlugin();
|
||||||
U plugin = getPlugin();
|
|
||||||
plugin.getTaskManager().runTaskLater(() -> {
|
plugin.getTaskManager().runTaskLater(() -> {
|
||||||
String updaterName = plugin.getPlatform() == ServerUtilsPlugin.Platform.VELOCITY
|
String updaterName = plugin.getPlatform() == ServerUtilsPlugin.Platform.VELOCITY
|
||||||
? "serverutilsupdater"
|
? "serverutilsupdater"
|
||||||
: "ServerUtilsUpdater";
|
: "ServerUtilsUpdater";
|
||||||
P updaterPlugin = plugin.getPluginManager().getPlugin(updaterName);
|
Optional<P> updaterPluginOptional = plugin.getPluginManager().getPlugin(updaterName);
|
||||||
if (updaterPlugin == null) return;
|
if (!updaterPluginOptional.isPresent()) return;
|
||||||
|
P updaterPlugin = updaterPluginOptional.get();
|
||||||
|
|
||||||
@SuppressWarnings("VariableDeclarationUsageDistance")
|
@SuppressWarnings("VariableDeclarationUsageDistance")
|
||||||
File file = plugin.getPluginManager().getPluginFile(updaterPlugin);
|
File file = plugin.getPluginManager().getPluginFile(updaterPlugin);
|
||||||
Result result = plugin.getPluginManager().disablePlugin(updaterPlugin);
|
PluginResult<P> disableResult = plugin.getPluginManager().disablePlugin(updaterPlugin);
|
||||||
if (result != Result.SUCCESS) {
|
if (!disableResult.isSuccess()) {
|
||||||
result.sendTo(plugin.getChatProvider().getConsoleSender(), "disabl", updaterName);
|
disableResult.getResult().sendTo(plugin.getChatProvider().getConsoleSender(), "disabl", updaterName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseableResult closeableResult = plugin.getPluginManager().unloadPlugin(updaterName);
|
CloseablePluginResult<P> unloadResult = plugin.getPluginManager().unloadPlugin(disableResult.getPlugin());
|
||||||
if (closeableResult.getResult() != Result.SUCCESS) {
|
if (!unloadResult.isSuccess()) {
|
||||||
closeableResult.getResult().sendTo(plugin.getChatProvider().getConsoleSender(), "unload", updaterName);
|
unloadResult.getResult().sendTo(plugin.getChatProvider().getConsoleSender(), "unload", updaterName);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
closeableResult.tryClose();
|
unloadResult.tryClose();
|
||||||
|
|
||||||
if (Files.exists(file.toPath())) {
|
if (Files.exists(file.toPath())) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -82,8 +92,14 @@ public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S>, P, T, C ext
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <U extends ServerUtilsPlugin<P, T, C, S>, P, T, C extends ServerCommandSender<S>, S>
|
public static <
|
||||||
U getPlugin() {
|
U extends ServerUtilsPlugin<P, T, C, S, D>,
|
||||||
|
P,
|
||||||
|
T,
|
||||||
|
C extends ServerCommandSender<S>,
|
||||||
|
S,
|
||||||
|
D extends ServerUtilsPluginDescription
|
||||||
|
> U getPlugin() {
|
||||||
return (U) instance.plugin;
|
return (U) instance.plugin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
||||||
import net.frankheijden.serverutils.common.utils.ListFormat;
|
import net.frankheijden.serverutils.common.utils.ListFormat;
|
||||||
|
|
||||||
public abstract class CommandPlugins<U extends ServerUtilsPlugin<P, ?, C, ?>, P, C extends ServerCommandSender<?>>
|
public abstract class CommandPlugins<U extends ServerUtilsPlugin<P, ?, C, ?, ?>, P, C extends ServerCommandSender<?>>
|
||||||
extends ServerUtilsCommand<U, C> {
|
extends ServerUtilsCommand<U, C> {
|
||||||
|
|
||||||
protected CommandPlugins(U plugin) {
|
protected CommandPlugins(U plugin) {
|
||||||
|
|
|
||||||
|
|
@ -4,38 +4,46 @@ import cloud.commandframework.Command;
|
||||||
import cloud.commandframework.CommandManager;
|
import cloud.commandframework.CommandManager;
|
||||||
import cloud.commandframework.arguments.CommandArgument;
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
import cloud.commandframework.context.CommandContext;
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
|
import net.frankheijden.serverutils.common.commands.arguments.JarFilesArgument;
|
||||||
|
import net.frankheijden.serverutils.common.commands.arguments.PluginArgument;
|
||||||
|
import net.frankheijden.serverutils.common.commands.arguments.PluginsArgument;
|
||||||
|
import net.frankheijden.serverutils.common.config.MessagesResource;
|
||||||
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
|
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
|
||||||
import net.frankheijden.serverutils.common.entities.AbstractResult;
|
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResults;
|
||||||
import net.frankheijden.serverutils.common.entities.CloseableResult;
|
import net.frankheijden.serverutils.common.entities.results.PluginResult;
|
||||||
import net.frankheijden.serverutils.common.entities.LoadResult;
|
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
||||||
import net.frankheijden.serverutils.common.entities.Result;
|
import net.frankheijden.serverutils.common.entities.results.Result;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.WatchResult;
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
||||||
import net.frankheijden.serverutils.common.utils.FormatBuilder;
|
import net.frankheijden.serverutils.common.utils.FormatBuilder;
|
||||||
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
import net.frankheijden.serverutils.common.utils.ListBuilder;
|
||||||
import net.frankheijden.serverutils.common.utils.ListFormat;
|
import net.frankheijden.serverutils.common.utils.ListFormat;
|
||||||
|
|
||||||
public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?>, P, C extends ServerCommandSender<?>>
|
public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?, ?>, P, C extends ServerCommandSender<?>>
|
||||||
extends ServerUtilsCommand<U, C> {
|
extends ServerUtilsCommand<U, C> {
|
||||||
|
|
||||||
protected CommandServerUtils(U plugin) {
|
protected final IntFunction<P[]> arrayCreator;
|
||||||
|
|
||||||
|
protected CommandServerUtils(U plugin, IntFunction<P[]> arrayCreator) {
|
||||||
super(plugin, "serverutils");
|
super(plugin, "serverutils");
|
||||||
|
this.arrayCreator = arrayCreator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(CommandManager<C> manager, Command.Builder<C> builder) {
|
public void register(CommandManager<C> manager, Command.Builder<C> builder) {
|
||||||
addArgument(CommandArgument.<C, String>ofType(String.class, "jarFile")
|
addArgument(new JarFilesArgument<>(true, "jarFiles", plugin));
|
||||||
.manager(manager)
|
addArgument(new PluginsArgument<>(true, "plugins", new PluginsArgument.PluginsParser<>(plugin, arrayCreator)));
|
||||||
.withSuggestionsProvider((context, s) -> plugin.getPluginManager().getPluginFileNames())
|
addArgument(new PluginArgument<>(true, "plugin", plugin));
|
||||||
.build());
|
|
||||||
addArgument(CommandArgument.<C, String>ofType(String.class, "plugin")
|
|
||||||
.manager(manager)
|
|
||||||
.withSuggestionsProvider((context, s) -> plugin.getPluginManager().getPluginNames())
|
|
||||||
.build());
|
|
||||||
addArgument(CommandArgument.<C, String>ofType(String.class, "command")
|
addArgument(CommandArgument.<C, String>ofType(String.class, "command")
|
||||||
.manager(manager)
|
.manager(manager)
|
||||||
.withSuggestionsProvider((context, s) -> new ArrayList<>(plugin.getPluginManager().getCommands()))
|
.withSuggestionsProvider((context, s) -> new ArrayList<>(plugin.getPluginManager().getCommands()))
|
||||||
|
|
@ -48,16 +56,28 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?>
|
||||||
manager.command(buildSubcommand(builder, "reload")
|
manager.command(buildSubcommand(builder, "reload")
|
||||||
.handler(this::handleReload));
|
.handler(this::handleReload));
|
||||||
manager.command(buildSubcommand(builder, "loadplugin")
|
manager.command(buildSubcommand(builder, "loadplugin")
|
||||||
.argument(getArgument("jarFile"))
|
.argument(getArgument("jarFiles"))
|
||||||
.handler(this::handleLoadPlugin));
|
.handler(this::handleLoadPlugin));
|
||||||
manager.command(buildSubcommand(builder, "unloadplugin")
|
manager.command(buildSubcommand(builder, "unloadplugin")
|
||||||
.argument(getArgument("plugin"))
|
.argument(new PluginsArgument<>(
|
||||||
|
true,
|
||||||
|
"plugins",
|
||||||
|
new PluginsArgument.PluginsParser<>(plugin, arrayCreator, getRawPath("unloadplugin"))
|
||||||
|
))
|
||||||
.handler(this::handleUnloadPlugin));
|
.handler(this::handleUnloadPlugin));
|
||||||
manager.command(buildSubcommand(builder, "reloadplugin")
|
manager.command(buildSubcommand(builder, "reloadplugin")
|
||||||
.argument(getArgument("plugin"))
|
.argument(new PluginsArgument<>(
|
||||||
|
true,
|
||||||
|
"plugins",
|
||||||
|
new PluginsArgument.PluginsParser<>(plugin, arrayCreator, getRawPath("reloadplugin"))
|
||||||
|
))
|
||||||
.handler(this::handleReloadPlugin));
|
.handler(this::handleReloadPlugin));
|
||||||
manager.command(buildSubcommand(builder, "watchplugin")
|
manager.command(buildSubcommand(builder, "watchplugin")
|
||||||
.argument(getArgument("plugin"))
|
.argument(new PluginsArgument<>(
|
||||||
|
true,
|
||||||
|
"plugins",
|
||||||
|
new PluginsArgument.PluginsParser<>(plugin, arrayCreator, getRawPath("watchplugin"))
|
||||||
|
))
|
||||||
.handler(this::handleWatchPlugin));
|
.handler(this::handleWatchPlugin));
|
||||||
manager.command(buildSubcommand(builder, "unwatchplugin")
|
manager.command(buildSubcommand(builder, "unwatchplugin")
|
||||||
.argument(getArgument("plugin"))
|
.argument(getArgument("plugin"))
|
||||||
|
|
@ -146,69 +166,130 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?>
|
||||||
|
|
||||||
private void handleLoadPlugin(CommandContext<C> context) {
|
private void handleLoadPlugin(CommandContext<C> context) {
|
||||||
C sender = context.getSender();
|
C sender = context.getSender();
|
||||||
String jarFile = context.get("jarFile");
|
List<File> jarFiles = Arrays.asList(context.get("jarFiles"));
|
||||||
|
|
||||||
AbstractPluginManager<P> pluginManager = plugin.getPluginManager();
|
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
|
||||||
LoadResult<P> loadResult = pluginManager.loadPlugin(jarFile);
|
PluginResults<P> loadResults = pluginManager.loadPlugins(jarFiles);
|
||||||
if (!loadResult.isSuccess()) {
|
if (!loadResults.isSuccess()) {
|
||||||
loadResult.getResult().sendTo(sender, "load", jarFile);
|
PluginResult<P> failedResult = loadResults.last();
|
||||||
|
failedResult.getResult().sendTo(sender, "load", failedResult.getPluginId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
P loadedPlugin = loadResult.get();
|
PluginResults<P> enableResults = pluginManager.enablePlugins(loadResults.getPlugins());
|
||||||
Result result = pluginManager.enablePlugin(loadedPlugin);
|
enableResults.sendTo(sender, "load");
|
||||||
result.sendTo(sender, "load", pluginManager.getPluginName(loadedPlugin));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleUnloadPlugin(CommandContext<C> context) {
|
private void handleUnloadPlugin(CommandContext<C> context) {
|
||||||
C sender = context.getSender();
|
C sender = context.getSender();
|
||||||
String pluginName = context.get("plugin");
|
List<P> plugins = Arrays.asList(context.get("plugins"));
|
||||||
|
|
||||||
CloseableResult result = plugin.getPluginManager().unloadPlugin(pluginName);
|
if (checkDependingPlugins(context, sender, plugins, "unloadplugin")) {
|
||||||
result.getResult().sendTo(sender, "unload", pluginName);
|
return;
|
||||||
result.tryClose();
|
}
|
||||||
|
|
||||||
|
PluginResults<P> disableResults = plugin.getPluginManager().disablePlugins(plugins);
|
||||||
|
for (PluginResult<P> disableResult : disableResults.getResults()) {
|
||||||
|
if (!disableResult.isSuccess() && disableResult.getResult() != Result.ALREADY_DISABLED) {
|
||||||
|
disableResult.getResult().sendTo(sender, "disabl", disableResult.getPluginId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseablePluginResults<P> unloadResults = plugin.getPluginManager().unloadPlugins(plugins);
|
||||||
|
unloadResults.tryClose();
|
||||||
|
unloadResults.sendTo(sender, "unload");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleReloadPlugin(CommandContext<C> context) {
|
private void handleReloadPlugin(CommandContext<C> context) {
|
||||||
C sender = context.getSender();
|
C sender = context.getSender();
|
||||||
String pluginName = context.get("plugin");
|
List<P> plugins = Arrays.asList(context.get("plugins"));
|
||||||
|
|
||||||
Result result = plugin.getPluginManager().reloadPlugin(pluginName);
|
if (checkDependingPlugins(context, sender, plugins, "reloadplugin")) {
|
||||||
result.sendTo(sender, "reload", pluginName);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginResults<P> reloadResult = plugin.getPluginManager().reloadPlugins(plugins);
|
||||||
|
reloadResult.sendTo(sender, "reload");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean checkDependingPlugins(CommandContext<C> context, C sender, List<P> plugins, String subcommand) {
|
||||||
|
if (context.flags().contains("force")) return false;
|
||||||
|
|
||||||
|
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
|
||||||
|
MessagesResource messages = plugin.getMessagesResource();
|
||||||
|
|
||||||
|
boolean hasDependingPlugins = false;
|
||||||
|
for (P plugin : plugins) {
|
||||||
|
String pluginId = pluginManager.getPluginId(plugin);
|
||||||
|
|
||||||
|
List<P> dependingPlugins = pluginManager.getPluginsDependingOn(pluginId);
|
||||||
|
if (!dependingPlugins.isEmpty()) {
|
||||||
|
String prefixString = messages.getMessage(
|
||||||
|
"serverutils.depending_plugins.prefix",
|
||||||
|
"%what%", pluginId
|
||||||
|
);
|
||||||
|
|
||||||
|
String dependingPluginsString = ListBuilder.create(dependingPlugins)
|
||||||
|
.format(p -> messages.getMessage(
|
||||||
|
"serverutils.depending_plugins.format",
|
||||||
|
"%plugin%", pluginManager.getPluginId(p)
|
||||||
|
))
|
||||||
|
.seperator(messages.getMessage("serverutils.depending_plugins.separator"))
|
||||||
|
.lastSeperator(messages.getMessage("serverutils.depending_plugins.last_separator"))
|
||||||
|
.toString();
|
||||||
|
messages.sendRawMessage(sender, prefixString + dependingPluginsString);
|
||||||
|
hasDependingPlugins = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasDependingPlugins) {
|
||||||
|
String flagPath = getRawPath(subcommand) + ".flags.force";
|
||||||
|
String forceFlag = plugin.getCommandsResource().getAllFlagAliases(flagPath).stream()
|
||||||
|
.min(Comparator.comparingInt(String::length))
|
||||||
|
.orElse("-f");
|
||||||
|
|
||||||
|
messages.sendMessage(sender,
|
||||||
|
"serverutils.depending_plugins.override",
|
||||||
|
"%command%", context.getRawInputJoined() + " " + forceFlag
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasDependingPlugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleWatchPlugin(CommandContext<C> context) {
|
private void handleWatchPlugin(CommandContext<C> context) {
|
||||||
C sender = context.getSender();
|
C sender = context.getSender();
|
||||||
String pluginName = context.get("plugin");
|
List<P> plugins = Arrays.asList(context.get("plugins"));
|
||||||
|
|
||||||
AbstractResult result = plugin.getPluginManager().watchPlugin(sender, pluginName);
|
if (checkDependingPlugins(context, sender, plugins, "watchplugin")) {
|
||||||
result.sendTo(sender, "watch", pluginName);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WatchResult result = plugin.getWatchManager().watchPlugins(sender, plugins);
|
||||||
|
result.sendTo(sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleUnwatchPlugin(CommandContext<C> context) {
|
private void handleUnwatchPlugin(CommandContext<C> context) {
|
||||||
C sender = context.getSender();
|
C sender = context.getSender();
|
||||||
String pluginName = context.get("plugin");
|
P pluginArg = context.get("plugin");
|
||||||
|
|
||||||
AbstractResult result = plugin.getPluginManager().unwatchPlugin(pluginName);
|
String pluginId = plugin.getPluginManager().getPluginId(pluginArg);
|
||||||
result.sendTo(sender, "unwatch", pluginName);
|
WatchResult result = plugin.getWatchManager().unwatchPluginsAssociatedWith(pluginId);
|
||||||
|
result.sendTo(sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handlePluginInfo(CommandContext<C> context) {
|
private void handlePluginInfo(CommandContext<C> context) {
|
||||||
C sender = context.getSender();
|
C sender = context.getSender();
|
||||||
String pluginName = context.get("plugin");
|
P pluginArg = context.get("plugin");
|
||||||
|
|
||||||
if (this.plugin.getPluginManager().getPlugin(pluginName) == null) {
|
createInfo(sender, "plugininfo", pluginArg, this::createPluginInfo);
|
||||||
Result.NOT_EXISTS.sendTo(sender, "fetch", pluginName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
createInfo(sender, "plugininfo", pluginName, this::createPluginInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract FormatBuilder createPluginInfo(
|
protected abstract FormatBuilder createPluginInfo(
|
||||||
FormatBuilder builder,
|
FormatBuilder builder,
|
||||||
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
|
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
|
||||||
String pluginName
|
P pluginArg
|
||||||
);
|
);
|
||||||
|
|
||||||
private void handleCommandInfo(CommandContext<C> context) {
|
private void handleCommandInfo(CommandContext<C> context) {
|
||||||
|
|
@ -229,7 +310,7 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?>
|
||||||
String commandName
|
String commandName
|
||||||
);
|
);
|
||||||
|
|
||||||
private void createInfo(C sender, String command, String item, InfoCreator creator) {
|
private <T> void createInfo(C sender, String command, T item, InfoCreator<T> creator) {
|
||||||
String messagePrefix = "serverutils." + command;
|
String messagePrefix = "serverutils." + command;
|
||||||
String format = plugin.getMessagesResource().getMessage(messagePrefix + ".format");
|
String format = plugin.getMessagesResource().getMessage(messagePrefix + ".format");
|
||||||
String listFormatString = plugin.getMessagesResource().getMessage(messagePrefix + ".list_format");
|
String listFormatString = plugin.getMessagesResource().getMessage(messagePrefix + ".list_format");
|
||||||
|
|
@ -256,12 +337,12 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?>
|
||||||
plugin.getMessagesResource().sendMessage(sender, messagePrefix + ".footer");
|
plugin.getMessagesResource().sendMessage(sender, messagePrefix + ".footer");
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface InfoCreator {
|
private interface InfoCreator<T> {
|
||||||
|
|
||||||
FormatBuilder createInfo(
|
FormatBuilder createInfo(
|
||||||
FormatBuilder builder,
|
FormatBuilder builder,
|
||||||
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
|
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
|
||||||
String item
|
T item
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,15 @@ import cloud.commandframework.arguments.CommandArgument;
|
||||||
import cloud.commandframework.arguments.flags.CommandFlag;
|
import cloud.commandframework.arguments.flags.CommandFlag;
|
||||||
import cloud.commandframework.permission.CommandPermission;
|
import cloud.commandframework.permission.CommandPermission;
|
||||||
import cloud.commandframework.permission.Permission;
|
import cloud.commandframework.permission.Permission;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
|
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
|
||||||
public abstract class ServerUtilsCommand<U extends ServerUtilsPlugin<?, ?, C, ?>, C extends ServerCommandSender<?>> {
|
public abstract class ServerUtilsCommand<U extends ServerUtilsPlugin<?, ?, C, ?, ?>, C extends ServerCommandSender<?>> {
|
||||||
|
|
||||||
protected final U plugin;
|
protected final U plugin;
|
||||||
protected final String commandName;
|
protected final String commandName;
|
||||||
|
|
@ -58,9 +60,14 @@ public abstract class ServerUtilsCommand<U extends ServerUtilsPlugin<?, ?, C, ?>
|
||||||
*/
|
*/
|
||||||
public Command.Builder<C> buildSubcommand(Command.Builder<C> builder, String subcommandName) {
|
public Command.Builder<C> buildSubcommand(Command.Builder<C> builder, String subcommandName) {
|
||||||
CommandElement subcommand = parseSubcommand(subcommandName);
|
CommandElement subcommand = parseSubcommand(subcommandName);
|
||||||
return builder
|
|
||||||
|
builder = builder
|
||||||
.literal(subcommand.getMain(), subcommand.getDescription(), subcommand.getAliases())
|
.literal(subcommand.getMain(), subcommand.getDescription(), subcommand.getAliases())
|
||||||
.permission(subcommand.getPermission());
|
.permission(subcommand.getPermission());
|
||||||
|
for (CommandElement flagElement : subcommand.getFlags()) {
|
||||||
|
builder = builder.flag(createFlag(flagElement));
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -76,7 +83,16 @@ public abstract class ServerUtilsCommand<U extends ServerUtilsPlugin<?, ?, C, ?>
|
||||||
.map(this::applyPrefix)
|
.map(this::applyPrefix)
|
||||||
.toArray(String[]::new);
|
.toArray(String[]::new);
|
||||||
|
|
||||||
return new CommandElement(main, description, permission, displayInHelp, aliases);
|
List<CommandElement> flags = new ArrayList<>();
|
||||||
|
Object flagsObject = elementConfig.get("flags");
|
||||||
|
if (flagsObject instanceof ServerUtilsConfig) {
|
||||||
|
ServerUtilsConfig flagsConfig = ((ServerUtilsConfig) flagsObject);
|
||||||
|
for (String flagName : flagsConfig.getKeys()) {
|
||||||
|
flags.add(parseElement((ServerUtilsConfig) flagsConfig.get(flagName)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommandElement(main, description, permission, displayInHelp, aliases, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -86,15 +102,25 @@ public abstract class ServerUtilsCommand<U extends ServerUtilsPlugin<?, ?, C, ?>
|
||||||
return parseElement((ServerUtilsConfig) commandConfig.get("subcommands." + subcommandName));
|
return parseElement((ServerUtilsConfig) commandConfig.get("subcommands." + subcommandName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRawPath(String subcommandName) {
|
||||||
|
return "commands." + commandName + ".subcommands." + subcommandName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a flag from the config.
|
* Parses a flag from the config.
|
||||||
*/
|
*/
|
||||||
public CommandFlag<Void> parseFlag(String flagName) {
|
public CommandFlag<Void> parseFlag(String flagName) {
|
||||||
CommandElement flag = parseElement((ServerUtilsConfig) commandConfig.get("flags." + flagName));
|
return createFlag(parseElement((ServerUtilsConfig) commandConfig.get("flags." + flagName)));
|
||||||
return CommandFlag.newBuilder(flag.getMain())
|
}
|
||||||
.withAliases(flag.getAliases())
|
|
||||||
.withPermission(flag.getPermission())
|
/**
|
||||||
.withDescription(flag.getDescription())
|
* Creates a flag from a CommandElement.
|
||||||
|
*/
|
||||||
|
public CommandFlag<Void> createFlag(CommandElement flagElement) {
|
||||||
|
return CommandFlag.newBuilder(flagElement.getMain())
|
||||||
|
.withAliases(flagElement.getAliases())
|
||||||
|
.withPermission(flagElement.getPermission())
|
||||||
|
.withDescription(flagElement.getDescription())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,19 +150,22 @@ public abstract class ServerUtilsCommand<U extends ServerUtilsPlugin<?, ?, C, ?>
|
||||||
private final CommandPermission permission;
|
private final CommandPermission permission;
|
||||||
private final boolean displayInHelp;
|
private final boolean displayInHelp;
|
||||||
private final String[] aliases;
|
private final String[] aliases;
|
||||||
|
private final List<CommandElement> flags;
|
||||||
|
|
||||||
public CommandElement(
|
public CommandElement(
|
||||||
String main,
|
String main,
|
||||||
ArgumentDescription description,
|
ArgumentDescription description,
|
||||||
CommandPermission permission,
|
CommandPermission permission,
|
||||||
boolean displayInHelp,
|
boolean displayInHelp,
|
||||||
String... aliases
|
String[] aliases,
|
||||||
|
List<CommandElement> flags
|
||||||
) {
|
) {
|
||||||
this.main = main;
|
this.main = main;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.permission = permission;
|
this.permission = permission;
|
||||||
this.displayInHelp = displayInHelp;
|
this.displayInHelp = displayInHelp;
|
||||||
this.aliases = aliases;
|
this.aliases = aliases;
|
||||||
|
this.flags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMain() {
|
public String getMain() {
|
||||||
|
|
@ -158,5 +187,9 @@ public abstract class ServerUtilsCommand<U extends ServerUtilsPlugin<?, ?, C, ?>
|
||||||
public String[] getAliases() {
|
public String[] getAliases() {
|
||||||
return aliases;
|
return aliases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<CommandElement> getFlags() {
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
package net.frankheijden.serverutils.common.commands.arguments;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||||
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
|
||||||
|
public class JarFilesArgument<C extends ServerCommandSender<?>> extends CommandArgument<C, File[]> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Jar Files argument.
|
||||||
|
*/
|
||||||
|
public JarFilesArgument(boolean required, String name, ServerUtilsPlugin<?, ?, C, ?, ?> plugin) {
|
||||||
|
super(
|
||||||
|
required,
|
||||||
|
name,
|
||||||
|
new JarFilesParser<>(plugin),
|
||||||
|
"",
|
||||||
|
new TypeToken<File[]>() {},
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class JarFilesParser<C extends ServerCommandSender<?>> implements ArgumentParser<C, File[]> {
|
||||||
|
|
||||||
|
private final ServerUtilsPlugin<?, ?, C, ?, ?> plugin;
|
||||||
|
|
||||||
|
public JarFilesParser(ServerUtilsPlugin<?, ?, C, ?, ?> plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArgumentParseResult<File[]> parse(CommandContext<C> context, Queue<String> inputQueue) {
|
||||||
|
if (inputQueue.isEmpty()) {
|
||||||
|
return ArgumentParseResult.failure(new NoInputProvidedException(JarFilesParser.class, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> pluginFiles = new HashSet<>(plugin.getPluginManager().getPluginFileNames());
|
||||||
|
File[] files = new File[inputQueue.size()];
|
||||||
|
for (int i = 0; i < files.length; i++) {
|
||||||
|
if (!pluginFiles.contains(inputQueue.peek())) {
|
||||||
|
return ArgumentParseResult.failure(new IllegalArgumentException(
|
||||||
|
"Plugin '" + inputQueue.peek() + "' does not exist!"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
files[i] = new File(plugin.getPluginManager().getPluginsFolder(), inputQueue.remove());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ArgumentParseResult.success(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> suggestions(CommandContext<C> context, String input) {
|
||||||
|
return plugin.getPluginManager().getPluginFileNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isContextFree() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package net.frankheijden.serverutils.common.commands.arguments;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||||
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Queue;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
|
||||||
|
public class PluginArgument<C extends ServerCommandSender<?>, P> extends CommandArgument<C, P> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Plugin argument.
|
||||||
|
*/
|
||||||
|
public PluginArgument(boolean required, String name, ServerUtilsPlugin<P, ?, C, ?, ?> plugin) {
|
||||||
|
super(
|
||||||
|
required,
|
||||||
|
name,
|
||||||
|
new PluginParser<>(plugin),
|
||||||
|
"",
|
||||||
|
new TypeToken<P>() {},
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class PluginParser<C extends ServerCommandSender<?>, P> implements ArgumentParser<C, P> {
|
||||||
|
|
||||||
|
private final ServerUtilsPlugin<P, ?, C, ?, ?> plugin;
|
||||||
|
|
||||||
|
public PluginParser(ServerUtilsPlugin<P, ?, C, ?, ?> plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArgumentParseResult<P> parse(CommandContext<C> context, Queue<String> inputQueue) {
|
||||||
|
if (inputQueue.isEmpty()) {
|
||||||
|
return ArgumentParseResult.failure(new NoInputProvidedException(PluginParser.class, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<P> pluginOptional = plugin.getPluginManager().getPlugin(inputQueue.peek());
|
||||||
|
if (!pluginOptional.isPresent()) {
|
||||||
|
return ArgumentParseResult.failure(new IllegalArgumentException(
|
||||||
|
"Plugin '" + inputQueue.peek() + "' does not exist!"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
inputQueue.remove();
|
||||||
|
return ArgumentParseResult.success(pluginOptional.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> suggestions(CommandContext<C> context, String input) {
|
||||||
|
return plugin.getPluginManager().getPluginNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isContextFree() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
package net.frankheijden.serverutils.common.commands.arguments;
|
||||||
|
|
||||||
|
import cloud.commandframework.arguments.CommandArgument;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||||
|
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||||
|
import cloud.commandframework.context.CommandContext;
|
||||||
|
import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
|
||||||
|
public class PluginsArgument<C extends ServerCommandSender<?>, P> extends CommandArgument<C, P[]> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Plugins argument.
|
||||||
|
*/
|
||||||
|
public PluginsArgument(
|
||||||
|
boolean required,
|
||||||
|
String name,
|
||||||
|
PluginsParser<C, P> parser
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
required,
|
||||||
|
name,
|
||||||
|
parser,
|
||||||
|
"",
|
||||||
|
new TypeToken<P[]>() {},
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class PluginsParser<C extends ServerCommandSender<?>, P> implements ArgumentParser<C, P[]> {
|
||||||
|
|
||||||
|
private final ServerUtilsPlugin<P, ?, C, ?, ?> plugin;
|
||||||
|
private final IntFunction<P[]> arrayCreator;
|
||||||
|
private final String commandConfigPath;
|
||||||
|
|
||||||
|
public PluginsParser(ServerUtilsPlugin<P, ?, C, ?, ?> plugin, IntFunction<P[]> arrayCreator) {
|
||||||
|
this(plugin, arrayCreator, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new PluginsParser.
|
||||||
|
*/
|
||||||
|
public PluginsParser(
|
||||||
|
ServerUtilsPlugin<P, ?, C, ?, ?> plugin,
|
||||||
|
IntFunction<P[]> arrayCreator,
|
||||||
|
String commandConfigPath
|
||||||
|
) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.arrayCreator = arrayCreator;
|
||||||
|
this.commandConfigPath = commandConfigPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArgumentParseResult<P[]> parse(CommandContext<C> context, Queue<String> inputQueue) {
|
||||||
|
if (inputQueue.isEmpty()) {
|
||||||
|
return ArgumentParseResult.failure(new NoInputProvidedException(PluginsParser.class, context));
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<String> flags = plugin.getCommandsResource().getAllFlagAliases(commandConfigPath + ".flags.force");
|
||||||
|
|
||||||
|
int queueSize = inputQueue.size();
|
||||||
|
List<P> plugins = new ArrayList<>(queueSize);
|
||||||
|
for (int i = 0; i < queueSize; i++) {
|
||||||
|
if (flags.contains(inputQueue.peek())) continue;
|
||||||
|
|
||||||
|
Optional<P> pluginOptional = plugin.getPluginManager().getPlugin(inputQueue.peek());
|
||||||
|
if (!pluginOptional.isPresent()) {
|
||||||
|
return ArgumentParseResult.failure(new IllegalArgumentException(
|
||||||
|
"Plugin '" + inputQueue.peek() + "' does not exist!"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
inputQueue.remove();
|
||||||
|
plugins.add(pluginOptional.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ArgumentParseResult.success(plugins.stream().toArray(arrayCreator));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> suggestions(CommandContext<C> context, String input) {
|
||||||
|
return plugin.getPluginManager().getPluginNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isContextFree() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package net.frankheijden.serverutils.common.commands.brigadier;
|
||||||
|
|
||||||
|
import cloud.commandframework.brigadier.CloudBrigadierManager;
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import net.frankheijden.serverutils.common.commands.arguments.JarFilesArgument;
|
||||||
|
import net.frankheijden.serverutils.common.commands.arguments.PluginsArgument;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
|
||||||
|
public class BrigadierHandler<C extends ServerCommandSender<?>, P> {
|
||||||
|
|
||||||
|
private final CloudBrigadierManager<C, ?> brigadierManager;
|
||||||
|
|
||||||
|
public BrigadierHandler(CloudBrigadierManager<C, ?> brigadierManager) {
|
||||||
|
this.brigadierManager = brigadierManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers types with the cloud brigadier manager.
|
||||||
|
*/
|
||||||
|
public void registerTypes() {
|
||||||
|
brigadierManager.registerMapping(
|
||||||
|
new TypeToken<JarFilesArgument.JarFilesParser<C>>() {},
|
||||||
|
builder -> builder
|
||||||
|
.cloudSuggestions()
|
||||||
|
.toConstant(StringArgumentType.greedyString())
|
||||||
|
);
|
||||||
|
brigadierManager.registerMapping(
|
||||||
|
new TypeToken<PluginsArgument.PluginsParser<C, P>>() {},
|
||||||
|
builder -> builder
|
||||||
|
.cloudSuggestions()
|
||||||
|
.toConstant(StringArgumentType.greedyString())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
package net.frankheijden.serverutils.common.config;
|
package net.frankheijden.serverutils.common.config;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -9,10 +12,30 @@ public class CommandsResource extends ServerUtilsResource {
|
||||||
|
|
||||||
private static final String COMMANDS_RESOURCE = "commands";
|
private static final String COMMANDS_RESOURCE = "commands";
|
||||||
|
|
||||||
public CommandsResource(ServerUtilsPlugin<?, ?, ?, ?> plugin) {
|
public CommandsResource(ServerUtilsPlugin<?, ?, ?, ?, ?> plugin) {
|
||||||
super(plugin, COMMANDS_RESOURCE);
|
super(plugin, COMMANDS_RESOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all flag aliases for the given flag path.
|
||||||
|
*/
|
||||||
|
public Set<String> getAllFlagAliases(String path) {
|
||||||
|
Object flagObject = getConfig().get(path);
|
||||||
|
if (flagObject instanceof ServerUtilsConfig) {
|
||||||
|
ServerUtilsConfig flagConfig = (ServerUtilsConfig) flagObject;
|
||||||
|
|
||||||
|
Set<String> flagAliases = new HashSet<>();
|
||||||
|
flagAliases.add("--" + flagConfig.getString("main"));
|
||||||
|
for (String alias : flagConfig.getStringList("aliases")) {
|
||||||
|
flagAliases.add("-" + alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
return flagAliases;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void migrate(int currentConfigVersion) {
|
public void migrate(int currentConfigVersion) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ public class ConfigResource extends ServerUtilsResource {
|
||||||
|
|
||||||
private static final String CONFIG_RESOURCE = "config";
|
private static final String CONFIG_RESOURCE = "config";
|
||||||
|
|
||||||
public ConfigResource(ServerUtilsPlugin<?, ?, ?, ?> plugin) {
|
public ConfigResource(ServerUtilsPlugin<?, ?, ?, ?, ?> plugin) {
|
||||||
super(plugin, CONFIG_RESOURCE);
|
super(plugin, CONFIG_RESOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ public class MessagesResource extends ServerUtilsResource {
|
||||||
|
|
||||||
public static final String MESSAGES_RESOURCE = "messages";
|
public static final String MESSAGES_RESOURCE = "messages";
|
||||||
|
|
||||||
public MessagesResource(ServerUtilsPlugin<?, ?, ?, ?> plugin) {
|
public MessagesResource(ServerUtilsPlugin<?, ?, ?, ?, ?> plugin) {
|
||||||
super(plugin, MESSAGES_RESOURCE);
|
super(plugin, MESSAGES_RESOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@ import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
|
||||||
public abstract class ServerUtilsResource {
|
public abstract class ServerUtilsResource {
|
||||||
|
|
||||||
protected final ServerUtilsPlugin<?, ?, ?, ?> plugin;
|
protected final ServerUtilsPlugin<?, ?, ?, ?, ?> plugin;
|
||||||
protected final ServerUtilsConfig config;
|
protected final ServerUtilsConfig config;
|
||||||
protected final JsonConfig defaultConfig;
|
protected final JsonConfig defaultConfig;
|
||||||
|
|
||||||
protected ServerUtilsResource(
|
protected ServerUtilsResource(
|
||||||
ServerUtilsPlugin<?, ?, ?, ?> plugin,
|
ServerUtilsPlugin<?, ?, ?, ?, ?> plugin,
|
||||||
ServerUtilsConfig config,
|
ServerUtilsConfig config,
|
||||||
JsonConfig defaultConfig
|
JsonConfig defaultConfig
|
||||||
) {
|
) {
|
||||||
|
|
@ -19,7 +19,7 @@ public abstract class ServerUtilsResource {
|
||||||
this.defaultConfig = defaultConfig;
|
this.defaultConfig = defaultConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ServerUtilsResource(ServerUtilsPlugin<?, ?, ?, ?> plugin, String resourceName) {
|
protected ServerUtilsResource(ServerUtilsPlugin<?, ?, ?, ?, ?> plugin, String resourceName) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.defaultConfig = JsonConfig.load(plugin.getResourceProvider(), plugin.getPlatform(), resourceName);
|
this.defaultConfig = JsonConfig.load(plugin.getResourceProvider(), plugin.getPlatform(), resourceName);
|
||||||
this.config = ServerUtilsConfig.init(
|
this.config = ServerUtilsConfig.init(
|
||||||
|
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
package net.frankheijden.serverutils.common.entities;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A result which should be closed when done.
|
|
||||||
*/
|
|
||||||
public class CloseableResult implements Closeable {
|
|
||||||
|
|
||||||
private Result result;
|
|
||||||
private final List<Closeable> closeables;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new closable result.
|
|
||||||
* Used for unloading / reloading a plugin.
|
|
||||||
* NB: The closable needs to be closed to fully ensure that the old plugin doesn't work anymore!
|
|
||||||
* @param result The result of the procedure
|
|
||||||
* @param closeables The list of closable's of the procedure.
|
|
||||||
*/
|
|
||||||
public CloseableResult(Result result, List<Closeable> closeables) {
|
|
||||||
this.result = result;
|
|
||||||
this.closeables = closeables;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new closable result with no closable instance.
|
|
||||||
* @param result The result of the procedure
|
|
||||||
*/
|
|
||||||
public CloseableResult(Result result) {
|
|
||||||
this(result, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new closable result with a closable instance and success result.
|
|
||||||
* @param closeable The closable of the procedure.
|
|
||||||
*/
|
|
||||||
public CloseableResult(Closeable closeable) {
|
|
||||||
this(Result.SUCCESS, Collections.singletonList(closeable));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new closable result with a closable instance and success result.
|
|
||||||
* @param closeables The list of closable's of the procedure.
|
|
||||||
*/
|
|
||||||
public CloseableResult(List<Closeable> closeables) {
|
|
||||||
this(Result.SUCCESS, closeables);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the result.
|
|
||||||
* @return The result.
|
|
||||||
*/
|
|
||||||
public Result getResult() {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the result of this instance.
|
|
||||||
* @param result The result to set.
|
|
||||||
* @return The current instance.
|
|
||||||
*/
|
|
||||||
public CloseableResult set(Result result) {
|
|
||||||
this.result = result;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to close the closable, essentially wrapping it with try-catch.
|
|
||||||
*/
|
|
||||||
public void tryClose() {
|
|
||||||
if (closeables == null) return;
|
|
||||||
try {
|
|
||||||
close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the closable.
|
|
||||||
* @throws IOException Iff an I/O error occurred.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
for (Closeable closeable : closeables) {
|
|
||||||
closeable.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
package net.frankheijden.serverutils.common.entities;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A result which contains a loaded object from a load operation.
|
|
||||||
* @param <T> The loaded object type
|
|
||||||
*/
|
|
||||||
public class LoadResult<T> {
|
|
||||||
|
|
||||||
private final T obj;
|
|
||||||
private final Result result;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new LoadResult with an object and a result.
|
|
||||||
* @param obj The object of the load operation.
|
|
||||||
* @param result The result of the load operation.
|
|
||||||
*/
|
|
||||||
public LoadResult(T obj, Result result) {
|
|
||||||
this.obj = obj;
|
|
||||||
this.result = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new LoadResult with an object and a success result.
|
|
||||||
* @param obj The object of the load operation.
|
|
||||||
*/
|
|
||||||
public LoadResult(T obj) {
|
|
||||||
this(obj, Result.SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new LoadResult without a loaded object, just a result.
|
|
||||||
* @param result The result of the load operation.
|
|
||||||
*/
|
|
||||||
public LoadResult(Result result) {
|
|
||||||
this(null, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the loaded object.
|
|
||||||
* @return The loaded object.
|
|
||||||
*/
|
|
||||||
public T get() {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The result of the LoadResult.
|
|
||||||
* @return The result.
|
|
||||||
*/
|
|
||||||
public Result getResult() {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the result is a success.
|
|
||||||
* @return Whether there is success or not.
|
|
||||||
*/
|
|
||||||
public boolean isSuccess() {
|
|
||||||
return obj != null && result == Result.SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,6 +2,7 @@ package net.frankheijden.serverutils.common.entities;
|
||||||
|
|
||||||
import cloud.commandframework.Command;
|
import cloud.commandframework.Command;
|
||||||
import cloud.commandframework.CommandManager;
|
import cloud.commandframework.CommandManager;
|
||||||
|
import cloud.commandframework.brigadier.CloudBrigadierManager;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|
@ -9,19 +10,22 @@ import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
||||||
|
import net.frankheijden.serverutils.common.commands.brigadier.BrigadierHandler;
|
||||||
import net.frankheijden.serverutils.common.config.CommandsResource;
|
import net.frankheijden.serverutils.common.config.CommandsResource;
|
||||||
import net.frankheijden.serverutils.common.config.ConfigResource;
|
import net.frankheijden.serverutils.common.config.ConfigResource;
|
||||||
import net.frankheijden.serverutils.common.config.MessagesResource;
|
import net.frankheijden.serverutils.common.config.MessagesResource;
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractTaskManager;
|
import net.frankheijden.serverutils.common.managers.AbstractTaskManager;
|
||||||
import net.frankheijden.serverutils.common.managers.UpdateManager;
|
import net.frankheijden.serverutils.common.managers.UpdateManager;
|
||||||
|
import net.frankheijden.serverutils.common.managers.WatchManager;
|
||||||
import net.frankheijden.serverutils.common.providers.ChatProvider;
|
import net.frankheijden.serverutils.common.providers.ChatProvider;
|
||||||
import net.frankheijden.serverutils.common.providers.ResourceProvider;
|
import net.frankheijden.serverutils.common.providers.ResourceProvider;
|
||||||
import net.frankheijden.serverutils.common.utils.FileUtils;
|
import net.frankheijden.serverutils.common.utils.FileUtils;
|
||||||
|
|
||||||
public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>, S> {
|
public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>, S, D extends ServerUtilsPluginDescription> {
|
||||||
|
|
||||||
private final UpdateManager updateManager = new UpdateManager();
|
private final UpdateManager updateManager = new UpdateManager();
|
||||||
|
private final WatchManager<P, T> watchManager = new WatchManager<>(this);
|
||||||
private CommandsResource commandsResource;
|
private CommandsResource commandsResource;
|
||||||
private ConfigResource configResource;
|
private ConfigResource configResource;
|
||||||
private MessagesResource messagesResource;
|
private MessagesResource messagesResource;
|
||||||
|
|
@ -43,7 +47,7 @@ public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>,
|
||||||
return messagesResource;
|
return messagesResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract AbstractPluginManager<P> getPluginManager();
|
public abstract AbstractPluginManager<P, D> getPluginManager();
|
||||||
|
|
||||||
public abstract AbstractTaskManager<T> getTaskManager();
|
public abstract AbstractTaskManager<T> getTaskManager();
|
||||||
|
|
||||||
|
|
@ -55,6 +59,10 @@ public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>,
|
||||||
return updateManager;
|
return updateManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WatchManager<P, T> getWatchManager() {
|
||||||
|
return watchManager;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Logger getLogger();
|
public abstract Logger getLogger();
|
||||||
|
|
||||||
public abstract File getDataFolder();
|
public abstract File getDataFolder();
|
||||||
|
|
@ -91,6 +99,11 @@ public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>,
|
||||||
|
|
||||||
protected abstract CommandManager<C> newCommandManager();
|
protected abstract CommandManager<C> newCommandManager();
|
||||||
|
|
||||||
|
protected void handleBrigadier(CloudBrigadierManager<C, ?> brigadierManager) {
|
||||||
|
BrigadierHandler<C, P> handler = new BrigadierHandler<>(brigadierManager);
|
||||||
|
handler.registerTypes();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables the plugin.
|
* Enables the plugin.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package net.frankheijden.serverutils.common.entities;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface ServerUtilsPluginDescription {
|
||||||
|
|
||||||
|
String getId();
|
||||||
|
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
String getVersion();
|
||||||
|
|
||||||
|
String getAuthor();
|
||||||
|
|
||||||
|
File getFile();
|
||||||
|
|
||||||
|
Set<String> getDependencies();
|
||||||
|
}
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
package net.frankheijden.serverutils.common.entities;
|
|
||||||
|
|
||||||
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
|
||||||
|
|
||||||
public enum WatchResult implements AbstractResult {
|
|
||||||
|
|
||||||
START,
|
|
||||||
CHANGE,
|
|
||||||
NOT_WATCHING,
|
|
||||||
STOPPED;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the associated message of the result
|
|
||||||
* and sends it to a CommandSender.
|
|
||||||
* @param sender The receiver.
|
|
||||||
* @param action The action which let to the result.
|
|
||||||
* @param what An associated variable.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void sendTo(ServerCommandSender<?> sender, String action, String what) {
|
|
||||||
ServerUtilsApp.getPlugin().getMessagesResource().sendMessage(
|
|
||||||
sender,
|
|
||||||
"serverutils.watcher." + this.name().toLowerCase(),
|
|
||||||
"%what%", what
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package net.frankheijden.serverutils.common.entities.exceptions;
|
||||||
|
|
||||||
|
public class InvalidPluginDescriptionException extends RuntimeException {
|
||||||
|
|
||||||
|
public InvalidPluginDescriptionException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidPluginDescriptionException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidPluginDescriptionException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
package net.frankheijden.serverutils.common.entities;
|
package net.frankheijden.serverutils.common.entities.results;
|
||||||
|
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
|
||||||
public interface AbstractResult {
|
public interface AbstractResult {
|
||||||
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package net.frankheijden.serverutils.common.entities.results;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CloseablePluginResult<T> extends PluginResult<T> implements Closeable {
|
||||||
|
|
||||||
|
private final List<Closeable> closeables;
|
||||||
|
|
||||||
|
public CloseablePluginResult(String pluginId, Result result) {
|
||||||
|
super(pluginId, result);
|
||||||
|
this.closeables = Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CloseablePluginResult(String pluginId, T plugin, Result result, List<Closeable> closeables) {
|
||||||
|
super(pluginId, plugin, result);
|
||||||
|
this.closeables = closeables;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to close the closable, essentially wrapping it with try-catch.
|
||||||
|
*/
|
||||||
|
public void tryClose() {
|
||||||
|
if (closeables == null) return;
|
||||||
|
try {
|
||||||
|
close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the closable.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
for (Closeable closeable : closeables) {
|
||||||
|
closeable.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
package net.frankheijden.serverutils.common.entities.results;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CloseablePluginResults<T> extends PluginResults<T> implements Closeable {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CloseablePluginResults<T> addResult(PluginResult<T> pluginResult) {
|
||||||
|
if (!(pluginResult instanceof CloseablePluginResult)) {
|
||||||
|
throw new IllegalArgumentException("Not an instance of CloseablePluginResult: " + pluginResult);
|
||||||
|
}
|
||||||
|
results.add(pluginResult);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CloseablePluginResults<T> addResult(String pluginId, Result result) {
|
||||||
|
super.addResult(pluginId, result);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CloseablePluginResults<T> addResult(String pluginId, T plugin) {
|
||||||
|
super.addResult(pluginId, plugin);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CloseablePluginResults<T> addResult(String pluginId, T plugin, Result result) {
|
||||||
|
super.addResult(pluginId, plugin, result);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CloseablePluginResults<T> addResult(String pluginId, T plugin, List<Closeable> closeables) {
|
||||||
|
return addResult(new CloseablePluginResult<>(pluginId, plugin, Result.SUCCESS, closeables));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CloseablePluginResult<T> first() {
|
||||||
|
PluginResult<T> pluginResult = super.first();
|
||||||
|
if (!(pluginResult instanceof CloseablePluginResult)) {
|
||||||
|
throw new IllegalArgumentException("Not an instance of CloseablePluginResult: " + pluginResult);
|
||||||
|
}
|
||||||
|
return (CloseablePluginResult<T>) pluginResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CloseablePluginResult<T> last() {
|
||||||
|
PluginResult<T> pluginResult = super.last();
|
||||||
|
if (!(pluginResult instanceof CloseablePluginResult)) {
|
||||||
|
throw new IllegalArgumentException("Not an instance of CloseablePluginResult: " + pluginResult);
|
||||||
|
}
|
||||||
|
return (CloseablePluginResult<T>) pluginResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to close the {@link CloseablePluginResult}'s enclosed.
|
||||||
|
*/
|
||||||
|
public void tryClose() {
|
||||||
|
try {
|
||||||
|
close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
for (PluginResult<T> pluginResult : this) {
|
||||||
|
if (pluginResult instanceof CloseablePluginResult) {
|
||||||
|
((CloseablePluginResult<T>) pluginResult).close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package net.frankheijden.serverutils.common.entities.results;
|
||||||
|
|
||||||
|
public class PluginResult<T> {
|
||||||
|
|
||||||
|
private final String pluginId;
|
||||||
|
private final T plugin;
|
||||||
|
private final Result result;
|
||||||
|
|
||||||
|
public PluginResult(String pluginId, Result result) {
|
||||||
|
this(pluginId, null, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new PluginResult.
|
||||||
|
*/
|
||||||
|
public PluginResult(String pluginId, T plugin, Result result) {
|
||||||
|
this.pluginId = pluginId;
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPluginId() {
|
||||||
|
return pluginId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getPlugin() {
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return plugin != null && result == Result.SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
package net.frankheijden.serverutils.common.entities.results;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
|
||||||
|
public class PluginResults<T> implements Iterable<PluginResult<T>> {
|
||||||
|
|
||||||
|
protected final List<PluginResult<T>> results;
|
||||||
|
|
||||||
|
public PluginResults() {
|
||||||
|
this.results = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginResults<T> addResult(String pluginId, Result result) {
|
||||||
|
addResult(pluginId, null, result);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginResults<T> addResult(String pluginId, T plugin) {
|
||||||
|
addResult(pluginId, plugin, Result.SUCCESS);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PluginResults<T> addResult(String pluginId, T plugin, Result result) {
|
||||||
|
addResult(new PluginResult<>(pluginId, plugin, result));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginResults<T> addResult(PluginResult<T> pluginResult) {
|
||||||
|
this.results.add(pluginResult);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return results.stream().allMatch(PluginResult::isSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PluginResult<T>> getResults() {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an array of all plugins.
|
||||||
|
* @throws IllegalArgumentException Iff a result was not successful (check {@link PluginResults#isSuccess()} first!)
|
||||||
|
*/
|
||||||
|
public List<T> getPlugins() {
|
||||||
|
List<T> plugins = new ArrayList<>(results.size());
|
||||||
|
for (PluginResult<T> result : results) {
|
||||||
|
if (!result.isSuccess()) throw new IllegalArgumentException(
|
||||||
|
"Result after handling plugin '" + result.getPluginId() + "' was not successful!"
|
||||||
|
);
|
||||||
|
plugins.add(result.getPlugin());
|
||||||
|
}
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginResult<T> first() {
|
||||||
|
return results.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginResult<T> last() {
|
||||||
|
return results.get(results.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the results to given receiver.
|
||||||
|
*/
|
||||||
|
public void sendTo(ServerCommandSender<?> sender, String action) {
|
||||||
|
for (PluginResult<T> result : results) {
|
||||||
|
result.getResult().sendTo(sender, action, result.getPluginId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<PluginResult<T>> iterator() {
|
||||||
|
return results.iterator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package net.frankheijden.serverutils.common.entities;
|
package net.frankheijden.serverutils.common.entities.results;
|
||||||
|
|
||||||
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enum containing possible results.
|
* An enum containing possible results.
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package net.frankheijden.serverutils.common.entities.results;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
||||||
|
import net.frankheijden.serverutils.common.config.MessagesResource;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
|
||||||
|
public enum WatchResult implements AbstractResult {
|
||||||
|
|
||||||
|
START,
|
||||||
|
CHANGE,
|
||||||
|
ALREADY_WATCHING,
|
||||||
|
NOT_WATCHING,
|
||||||
|
FILE_DELETED,
|
||||||
|
DELETED_FILE_IS_CREATED,
|
||||||
|
STOPPED;
|
||||||
|
|
||||||
|
private List<String> args = null;
|
||||||
|
|
||||||
|
public WatchResult arg(String arg) {
|
||||||
|
return args(Collections.singletonList(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
public WatchResult args(List<String> args) {
|
||||||
|
this.args = args;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendTo(ServerCommandSender<?> sender, String action, String what) {
|
||||||
|
arg(what);
|
||||||
|
sendTo(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the result(s) to the console and specified sender.
|
||||||
|
*/
|
||||||
|
public void sendTo(ServerCommandSender<?> sender) {
|
||||||
|
String path = "serverutils.watchplugin." + this.name().toLowerCase();
|
||||||
|
List<String[]> sendArguments = new ArrayList<>();
|
||||||
|
if (args == null || args.isEmpty()) {
|
||||||
|
sendArguments.add(new String[0]);
|
||||||
|
} else {
|
||||||
|
for (String what : args) {
|
||||||
|
sendArguments.add(new String[] { "%what%", what });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessagesResource messages = ServerUtilsApp.getPlugin().getMessagesResource();
|
||||||
|
ServerCommandSender<?> console = ServerUtilsApp.getPlugin().getChatProvider().getConsoleSender();
|
||||||
|
for (String[] replacements : sendArguments) {
|
||||||
|
messages.sendMessage(sender, path, replacements);
|
||||||
|
if (sender.isPlayer()) {
|
||||||
|
messages.sendMessage(console, path, replacements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@ import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
import net.frankheijden.serverutils.common.tasks.UpdateCheckerTask;
|
import net.frankheijden.serverutils.common.tasks.UpdateCheckerTask;
|
||||||
|
|
||||||
public abstract class PlayerListener<U extends ServerUtilsPlugin<P, ?, C, ?>, P, C extends ServerCommandSender<?>>
|
public abstract class PlayerListener<U extends ServerUtilsPlugin<P, ?, C, ?, ?>, P, C extends ServerCommandSender<?>>
|
||||||
extends ServerUtilsListener<U, C> {
|
extends ServerUtilsListener<U, C> {
|
||||||
|
|
||||||
protected PlayerListener(U plugin) {
|
protected PlayerListener(U plugin) {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package net.frankheijden.serverutils.common.listeners;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
|
||||||
public abstract class ServerUtilsListener<U extends ServerUtilsPlugin<?, ?, C, ?>, C extends ServerCommandSender<?>> {
|
public abstract class ServerUtilsListener<U extends ServerUtilsPlugin<?, ?, C, ?, ?>, C extends ServerCommandSender<?>> {
|
||||||
|
|
||||||
protected final U plugin;
|
protected final U plugin;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,292 @@
|
||||||
package net.frankheijden.serverutils.common.managers;
|
package net.frankheijden.serverutils.common.managers;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
import java.util.ArrayList;
|
||||||
import net.frankheijden.serverutils.common.entities.AbstractResult;
|
import java.util.Collection;
|
||||||
import net.frankheijden.serverutils.common.entities.CloseableResult;
|
import java.util.Collections;
|
||||||
import net.frankheijden.serverutils.common.entities.LoadResult;
|
import java.util.HashMap;
|
||||||
import net.frankheijden.serverutils.common.entities.Result;
|
import java.util.HashSet;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
import java.util.List;
|
||||||
import net.frankheijden.serverutils.common.entities.WatchResult;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResult;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResults;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.PluginResult;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.Result;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
||||||
|
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
|
||||||
import net.frankheijden.serverutils.common.providers.PluginProvider;
|
import net.frankheijden.serverutils.common.providers.PluginProvider;
|
||||||
import net.frankheijden.serverutils.common.tasks.PluginWatcherTask;
|
import net.frankheijden.serverutils.common.utils.DependencyUtils;
|
||||||
|
|
||||||
public interface AbstractPluginManager<P> extends PluginProvider<P> {
|
public abstract class AbstractPluginManager<P, D extends ServerUtilsPluginDescription> implements PluginProvider<P, D> {
|
||||||
|
|
||||||
LoadResult<P> loadPlugin(String pluginFile);
|
|
||||||
|
|
||||||
LoadResult<P> loadPlugin(File file);
|
|
||||||
|
|
||||||
Result enablePlugin(P plugin);
|
|
||||||
|
|
||||||
Result disablePlugin(P plugin);
|
|
||||||
|
|
||||||
Result reloadPlugin(String pluginName);
|
|
||||||
|
|
||||||
Result reloadPlugin(P plugin);
|
|
||||||
|
|
||||||
CloseableResult unloadPlugin(String pluginName);
|
|
||||||
|
|
||||||
CloseableResult unloadPlugin(P plugin);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts watching the specified plugin for changes.
|
* Loads the given plugin by their jar file.
|
||||||
* Reloads the plugin if a change is detected.
|
|
||||||
* @param pluginName The plugin to watch.
|
|
||||||
* @return The result of the action.
|
|
||||||
*/
|
*/
|
||||||
default AbstractResult watchPlugin(ServerCommandSender<?> sender, String pluginName) {
|
public PluginResult<P> loadPlugin(String pluginFile) {
|
||||||
if (getPlugin(pluginName) == null) return Result.NOT_EXISTS;
|
File file = new File(getPluginsFolder(), pluginFile);
|
||||||
ServerUtilsApp.getPlugin().getTaskManager()
|
if (!file.exists()) return new PluginResult<>(pluginFile, Result.NOT_EXISTS);
|
||||||
.runTaskAsynchronously(pluginName, new PluginWatcherTask(sender, pluginName));
|
return loadPlugin(file);
|
||||||
return WatchResult.START;
|
}
|
||||||
|
|
||||||
|
public PluginResult<P> loadPlugin(File file) {
|
||||||
|
return loadPlugins(Collections.singletonList(file)).first();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops watching the plugin for changes.
|
* Loads a list of files as plugins.
|
||||||
* @param pluginName The plugin to stop watching.
|
|
||||||
* @return The result of the action.
|
|
||||||
*/
|
*/
|
||||||
default AbstractResult unwatchPlugin(String pluginName) {
|
public PluginResults<P> loadPlugins(List<File> files) {
|
||||||
if (ServerUtilsApp.getPlugin().getTaskManager().cancelTask(pluginName)) return WatchResult.STOPPED;
|
List<D> descriptions = new ArrayList<>(files.size());
|
||||||
return WatchResult.NOT_WATCHING;
|
|
||||||
|
for (File file : files) {
|
||||||
|
D description;
|
||||||
|
try {
|
||||||
|
Optional<D> descriptionOptional = getPluginDescription(file);
|
||||||
|
if (!descriptionOptional.isPresent()) {
|
||||||
|
return new PluginResults<P>().addResult(file.getName(), Result.NOT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
description = descriptionOptional.get();
|
||||||
|
} catch (InvalidPluginDescriptionException ex) {
|
||||||
|
return new PluginResults<P>().addResult(file.getName(), Result.INVALID_DESCRIPTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getPlugin(description.getId()).isPresent()) {
|
||||||
|
return new PluginResults<P>().addResult(description.getId(), Result.ALREADY_LOADED);
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptions.add(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<D> orderedDescriptions;
|
||||||
|
try {
|
||||||
|
orderedDescriptions = determineLoadOrder(descriptions);
|
||||||
|
} catch (IllegalStateException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (File file : files) {
|
||||||
|
sb.append(", ").append(file.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PluginResults<P>().addResult(sb.substring(2), Result.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadPluginDescriptions(orderedDescriptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract PluginResults<P> loadPluginDescriptions(List<D> descriptions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables the given plugin by name.
|
||||||
|
*/
|
||||||
|
public PluginResult<P> enablePlugin(String pluginId) {
|
||||||
|
return getPlugin(pluginId)
|
||||||
|
.map(this::enablePlugin)
|
||||||
|
.orElse(new PluginResult<>(pluginId, Result.NOT_EXISTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginResult<P> enablePlugin(P plugin) {
|
||||||
|
return enablePlugins(Collections.singletonList(plugin)).first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables a list of plugins.
|
||||||
|
*/
|
||||||
|
public PluginResults<P> enablePlugins(List<P> plugins) {
|
||||||
|
for (P plugin : plugins) {
|
||||||
|
String pluginId = getPluginId(plugin);
|
||||||
|
if (isPluginEnabled(pluginId)) {
|
||||||
|
return new PluginResults<P>().addResult(pluginId, Result.ALREADY_ENABLED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enableOrderedPlugins(determineLoadOrder(plugins));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract PluginResults<P> enableOrderedPlugins(List<P> plugins);
|
||||||
|
|
||||||
|
public boolean isPluginEnabled(P plugin) {
|
||||||
|
return isPluginEnabled(getPluginId(plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean isPluginEnabled(String pluginId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables the given plugin by name.
|
||||||
|
*/
|
||||||
|
public PluginResult<P> disablePlugin(String pluginId) {
|
||||||
|
return getPlugin(pluginId)
|
||||||
|
.map(this::disablePlugin)
|
||||||
|
.orElse(new PluginResult<>(pluginId, Result.NOT_EXISTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginResult<P> disablePlugin(P plugin) {
|
||||||
|
return disablePlugins(Collections.singletonList(plugin)).first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables a list of plugins.
|
||||||
|
*/
|
||||||
|
public PluginResults<P> disablePlugins(List<P> plugins) {
|
||||||
|
for (P plugin : plugins) {
|
||||||
|
if (!isPluginEnabled(plugin)) {
|
||||||
|
return new PluginResults<P>().addResult(getPluginId(plugin), Result.ALREADY_DISABLED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<P> orderedPlugins;
|
||||||
|
try {
|
||||||
|
orderedPlugins = determineLoadOrder(plugins);
|
||||||
|
} catch (IllegalStateException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (P plugin : plugins) {
|
||||||
|
sb.append(", ").append(getPluginId(plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PluginResults<P>().addResult(sb.substring(2), Result.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.reverse(orderedPlugins);
|
||||||
|
return disableOrderedPlugins(orderedPlugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract PluginResults<P> disableOrderedPlugins(List<P> plugins);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads the given plugin by name.
|
||||||
|
*/
|
||||||
|
public PluginResult<P> reloadPlugin(String pluginId) {
|
||||||
|
return getPlugin(pluginId)
|
||||||
|
.map(this::reloadPlugin)
|
||||||
|
.orElse(new PluginResult<>(pluginId, Result.NOT_EXISTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginResult<P> reloadPlugin(P plugin) {
|
||||||
|
return reloadPlugins(Collections.singletonList(plugin)).first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads the given plugins.
|
||||||
|
*/
|
||||||
|
public PluginResults<P> reloadPlugins(List<P> plugins) {
|
||||||
|
PluginResults<P> disableResults = disablePlugins(plugins);
|
||||||
|
for (PluginResult<P> disableResult : disableResults.getResults()) {
|
||||||
|
if (!disableResult.isSuccess() && disableResult.getResult() != Result.ALREADY_DISABLED) {
|
||||||
|
return disableResults;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> pluginIds = new ArrayList<>(plugins.size());
|
||||||
|
for (P plugin : plugins) {
|
||||||
|
pluginIds.add(getPluginId(plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseablePluginResults<P> unloadResults = unloadPlugins(plugins);
|
||||||
|
if (!unloadResults.isSuccess()) return unloadResults;
|
||||||
|
unloadResults.tryClose();
|
||||||
|
|
||||||
|
List<File> pluginFiles = new ArrayList<>(plugins.size());
|
||||||
|
for (String pluginId : pluginIds) {
|
||||||
|
Optional<File> pluginFile = getPluginFile(pluginId);
|
||||||
|
if (!pluginFile.isPresent()) return new PluginResults<P>().addResult(pluginId, Result.FILE_DELETED);
|
||||||
|
pluginFiles.add(pluginFile.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginResults<P> loadResults = loadPlugins(pluginFiles);
|
||||||
|
if (!loadResults.isSuccess()) return loadResults;
|
||||||
|
|
||||||
|
List<P> loadedPlugins = new ArrayList<>(pluginIds.size());
|
||||||
|
for (PluginResult<P> loadResult : loadResults) {
|
||||||
|
loadedPlugins.add(loadResult.getPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
return enablePlugins(loadedPlugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unloads the given plugin by name.
|
||||||
|
*/
|
||||||
|
public CloseablePluginResult<P> unloadPlugin(String pluginId) {
|
||||||
|
return getPlugin(pluginId)
|
||||||
|
.map(this::unloadPlugin)
|
||||||
|
.orElse(new CloseablePluginResult<>(pluginId, Result.NOT_EXISTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CloseablePluginResult<P> unloadPlugin(P plugin) {
|
||||||
|
return unloadPlugins(Collections.singletonList(plugin)).first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unloads a list of plugins.
|
||||||
|
*/
|
||||||
|
public CloseablePluginResults<P> unloadPlugins(List<P> plugins) {
|
||||||
|
List<P> orderedPlugins;
|
||||||
|
try {
|
||||||
|
orderedPlugins = determineLoadOrder(plugins);
|
||||||
|
} catch (IllegalStateException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (P plugin : plugins) {
|
||||||
|
sb.append(", ").append(getPluginId(plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CloseablePluginResults<P>().addResult(sb.substring(2), Result.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.reverse(orderedPlugins);
|
||||||
|
return unloadOrderedPlugins(orderedPlugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract CloseablePluginResults<P> unloadOrderedPlugins(List<P> plugins);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the load order of a list of plugins.
|
||||||
|
*/
|
||||||
|
public List<P> determineLoadOrder(List<P> plugins) throws IllegalStateException {
|
||||||
|
Map<D, P> descriptionMap = new HashMap<>(plugins.size());
|
||||||
|
for (P plugin : plugins) {
|
||||||
|
descriptionMap.put(getLoadedPluginDescription(plugin), plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<P> orderedPlugins = new ArrayList<>(plugins.size());
|
||||||
|
for (D description : determineLoadOrder(descriptionMap.keySet())) {
|
||||||
|
orderedPlugins.add(descriptionMap.get(description));
|
||||||
|
}
|
||||||
|
return orderedPlugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the load order for a given collection of descriptions.
|
||||||
|
* @throws IllegalStateException Iff circular dependency
|
||||||
|
*/
|
||||||
|
public List<D> determineLoadOrder(Collection<? extends D> descriptions) throws IllegalStateException {
|
||||||
|
Map<String, D> pluginIdToDescriptionMap = new HashMap<>();
|
||||||
|
for (D description : descriptions) {
|
||||||
|
pluginIdToDescriptionMap.put(description.getId(), description);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<D, Set<D>> dependencyMap = new HashMap<>(descriptions.size());
|
||||||
|
for (D description : descriptions) {
|
||||||
|
Set<String> dependencyStrings = description.getDependencies();
|
||||||
|
Set<D> dependencies = new HashSet<>();
|
||||||
|
|
||||||
|
for (String dependencyString : dependencyStrings) {
|
||||||
|
D dependency = pluginIdToDescriptionMap.get(dependencyString);
|
||||||
|
if (dependency != null) {
|
||||||
|
dependencies.add(dependency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyMap.put(description, dependencies);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DependencyUtils.determineOrder(dependencyMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package net.frankheijden.serverutils.common.managers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.WatchResult;
|
||||||
|
import net.frankheijden.serverutils.common.tasks.PluginWatcherTask;
|
||||||
|
|
||||||
|
public class WatchManager<P, T> {
|
||||||
|
|
||||||
|
private final ServerUtilsPlugin<P, T, ?, ?, ?> plugin;
|
||||||
|
private final Map<String, WatchTask> watchTasks;
|
||||||
|
|
||||||
|
public WatchManager(ServerUtilsPlugin<P, T, ?, ?, ?> plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.watchTasks = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts watching the specified plugin and reloads it when a change is detected.
|
||||||
|
*/
|
||||||
|
public WatchResult watchPlugins(ServerCommandSender<?> sender, List<P> plugins) {
|
||||||
|
List<String> pluginIds = new ArrayList<>(plugins.size());
|
||||||
|
for (P watchPlugin : plugins) {
|
||||||
|
String pluginId = plugin.getPluginManager().getPluginId(watchPlugin);
|
||||||
|
if (watchTasks.containsKey(pluginId)) {
|
||||||
|
return WatchResult.ALREADY_WATCHING.arg(pluginId);
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginIds.add(plugin.getPluginManager().getPluginId(watchPlugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID key = UUID.randomUUID();
|
||||||
|
plugin.getTaskManager().runTaskAsynchronously(
|
||||||
|
key.toString(),
|
||||||
|
new PluginWatcherTask<>(plugin, sender, plugins)
|
||||||
|
);
|
||||||
|
|
||||||
|
WatchTask watchTask = new WatchTask(key, pluginIds);
|
||||||
|
for (String pluginId : pluginIds) {
|
||||||
|
watchTasks.put(pluginId, watchTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
return WatchResult.START.args(pluginIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops watching plugins for changes.
|
||||||
|
*/
|
||||||
|
public WatchResult unwatchPluginsAssociatedWith(String pluginId) {
|
||||||
|
WatchTask task = watchTasks.get(pluginId);
|
||||||
|
if (task != null && plugin.getTaskManager().cancelTask(task.key.toString())) {
|
||||||
|
task.pluginIds.forEach(watchTasks::remove);
|
||||||
|
return WatchResult.STOPPED.args(task.pluginIds);
|
||||||
|
}
|
||||||
|
return WatchResult.NOT_WATCHING.arg(pluginId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class WatchTask {
|
||||||
|
|
||||||
|
private final UUID key;
|
||||||
|
private final List<String> pluginIds;
|
||||||
|
|
||||||
|
private WatchTask(UUID key, List<String> pluginIds) {
|
||||||
|
this.key = key;
|
||||||
|
this.pluginIds = pluginIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,18 @@
|
||||||
package net.frankheijden.serverutils.common.providers;
|
package net.frankheijden.serverutils.common.providers;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
||||||
|
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
|
||||||
|
|
||||||
public interface PluginProvider<P> {
|
public interface PluginProvider<P, D extends ServerUtilsPluginDescription> {
|
||||||
|
|
||||||
default File getPluginsFolder() {
|
default File getPluginsFolder() {
|
||||||
return ServerUtilsApp.getPlugin().getDataFolder().getParentFile();
|
return ServerUtilsApp.getPlugin().getDataFolder().getParentFile();
|
||||||
|
|
@ -16,13 +20,59 @@ public interface PluginProvider<P> {
|
||||||
|
|
||||||
List<P> getPlugins();
|
List<P> getPlugins();
|
||||||
|
|
||||||
String getPluginName(P plugin);
|
default String getPluginId(P plugin) {
|
||||||
|
return getLoadedPluginDescription(plugin).getId();
|
||||||
|
}
|
||||||
|
|
||||||
File getPluginFile(P plugin);
|
default File getPluginFile(P plugin) {
|
||||||
|
return getLoadedPluginDescription(plugin).getFile();
|
||||||
|
}
|
||||||
|
|
||||||
File getPluginFile(String pluginName);
|
/**
|
||||||
|
* Attempts to find the file for a given plugin id.
|
||||||
|
*/
|
||||||
|
default Optional<File> getPluginFile(String pluginId) {
|
||||||
|
for (File file : getPluginJars()) {
|
||||||
|
Optional<D> pluginDescriptionOptional;
|
||||||
|
try {
|
||||||
|
pluginDescriptionOptional = getPluginDescription(file);
|
||||||
|
} catch (InvalidPluginDescriptionException ex) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
P getPlugin(String pluginName);
|
if (pluginDescriptionOptional.isPresent() && pluginDescriptionOptional.get().getId().equals(pluginId)) {
|
||||||
|
return Optional.of(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves plugins which depend on the given plugin.
|
||||||
|
*/
|
||||||
|
default List<P> getPluginsDependingOn(String pluginId) {
|
||||||
|
List<P> plugins = new ArrayList<>();
|
||||||
|
|
||||||
|
for (P loadedPlugin : getPlugins()) {
|
||||||
|
ServerUtilsPluginDescription description = getLoadedPluginDescription(loadedPlugin);
|
||||||
|
if (description.getDependencies().contains(pluginId)) {
|
||||||
|
plugins.add(loadedPlugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<P> getPlugin(String pluginId);
|
||||||
|
|
||||||
|
D getLoadedPluginDescription(P plugin);
|
||||||
|
|
||||||
|
default Optional<D> getPluginDescription(String pluginId) throws InvalidPluginDescriptionException {
|
||||||
|
Optional<File> fileOptional = getPluginFile(pluginId);
|
||||||
|
return fileOptional.flatMap(this::getPluginDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<D> getPluginDescription(File file) throws InvalidPluginDescriptionException;
|
||||||
|
|
||||||
Object getInstance(P plugin);
|
Object getInstance(P plugin);
|
||||||
|
|
||||||
|
|
@ -34,7 +84,7 @@ public interface PluginProvider<P> {
|
||||||
*/
|
*/
|
||||||
default List<P> getPluginsSorted() {
|
default List<P> getPluginsSorted() {
|
||||||
List<P> plugins = getPlugins();
|
List<P> plugins = getPlugins();
|
||||||
plugins.sort(Comparator.comparing(this::getPluginName));
|
plugins.sort(Comparator.comparing(this::getPluginId));
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +94,7 @@ public interface PluginProvider<P> {
|
||||||
*/
|
*/
|
||||||
default List<String> getPluginNames() {
|
default List<String> getPluginNames() {
|
||||||
return getPlugins().stream()
|
return getPlugins().stream()
|
||||||
.map(this::getPluginName)
|
.map(this::getPluginId)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,34 @@
|
||||||
package net.frankheijden.serverutils.common.tasks;
|
package net.frankheijden.serverutils.common.tasks;
|
||||||
|
|
||||||
import com.sun.nio.file.SensitivityWatchEventModifier;
|
import com.sun.nio.file.SensitivityWatchEventModifier;
|
||||||
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
|
||||||
import net.frankheijden.serverutils.common.entities.AbstractTask;
|
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
|
||||||
import net.frankheijden.serverutils.common.entities.WatchResult;
|
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractTaskManager;
|
|
||||||
import net.frankheijden.serverutils.common.providers.ChatProvider;
|
|
||||||
import net.frankheijden.serverutils.common.utils.FileUtils;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.ClosedWatchServiceException;
|
import java.nio.file.ClosedWatchServiceException;
|
||||||
import java.nio.file.FileSystems;
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardWatchEventKinds;
|
import java.nio.file.StandardWatchEventKinds;
|
||||||
import java.nio.file.WatchEvent;
|
import java.nio.file.WatchEvent;
|
||||||
import java.nio.file.WatchKey;
|
import java.nio.file.WatchKey;
|
||||||
import java.nio.file.WatchService;
|
import java.nio.file.WatchService;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import net.frankheijden.serverutils.common.entities.AbstractTask;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
||||||
|
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.PluginResult;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.WatchResult;
|
||||||
|
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
||||||
|
import net.frankheijden.serverutils.common.utils.FileUtils;
|
||||||
|
|
||||||
public class PluginWatcherTask extends AbstractTask {
|
public class PluginWatcherTask<P, T> extends AbstractTask {
|
||||||
|
|
||||||
private static final WatchEvent.Kind<?>[] EVENTS = new WatchEvent.Kind[]{
|
private static final WatchEvent.Kind<?>[] EVENTS = new WatchEvent.Kind[]{
|
||||||
StandardWatchEventKinds.ENTRY_CREATE,
|
StandardWatchEventKinds.ENTRY_CREATE,
|
||||||
|
|
@ -28,32 +36,33 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
StandardWatchEventKinds.ENTRY_DELETE
|
StandardWatchEventKinds.ENTRY_DELETE
|
||||||
};
|
};
|
||||||
|
|
||||||
private final ServerUtilsPlugin<?, ?, ?, ?> plugin = ServerUtilsApp.getPlugin();
|
private final ServerUtilsPlugin<P, T, ?, ?, ?> plugin;
|
||||||
private final AbstractPluginManager<?> pluginManager = plugin.getPluginManager();
|
|
||||||
private final ChatProvider<?, ?> chatProvider = plugin.getChatProvider();
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private final AbstractTaskManager taskManager = plugin.getTaskManager();
|
|
||||||
|
|
||||||
private final ServerCommandSender<?> sender;
|
private final ServerCommandSender<?> sender;
|
||||||
private final String pluginName;
|
private final Map<String, WatchEntry> fileNameToWatchEntryMap;
|
||||||
private final AtomicBoolean run;
|
private final Map<String, WatchEntry> pluginIdToWatchEntryMap;
|
||||||
private File file;
|
|
||||||
private String hash;
|
|
||||||
private long hashTimestamp = 0;
|
|
||||||
|
|
||||||
|
private final AtomicBoolean run = new AtomicBoolean(true);
|
||||||
private WatchService watchService;
|
private WatchService watchService;
|
||||||
private Object task = null;
|
private T task = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new PluginWatcherTask for the specified plugin.
|
* Constructs a new PluginWatcherTask for the specified plugin.
|
||||||
*
|
|
||||||
* @param pluginName The name of the plugin.
|
|
||||||
*/
|
*/
|
||||||
public PluginWatcherTask(ServerCommandSender<?> sender, String pluginName) {
|
public PluginWatcherTask(ServerUtilsPlugin<P, T, ?, ?, ?> plugin, ServerCommandSender<?> sender, List<P> plugins) {
|
||||||
|
this.plugin = plugin;
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
this.pluginName = pluginName;
|
this.fileNameToWatchEntryMap = new HashMap<>();
|
||||||
this.file = pluginManager.getPluginFile(pluginName);
|
this.pluginIdToWatchEntryMap = new HashMap<>();
|
||||||
this.run = new AtomicBoolean(true);
|
|
||||||
|
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
|
||||||
|
for (P watchPlugin : plugins) {
|
||||||
|
File file = pluginManager.getPluginFile(watchPlugin);
|
||||||
|
|
||||||
|
WatchEntry entry = new WatchEntry(pluginManager.getPluginId(watchPlugin));
|
||||||
|
entry.update(file);
|
||||||
|
|
||||||
|
this.fileNameToWatchEntryMap.put(file.getName(), entry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -61,34 +70,21 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
|
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
|
||||||
this.watchService = watchService;
|
this.watchService = watchService;
|
||||||
|
|
||||||
File folder = pluginManager.getPluginsFolder();
|
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
|
||||||
folder.toPath().register(watchService, EVENTS, SensitivityWatchEventModifier.HIGH);
|
Path basePath = pluginManager.getPluginsFolder().toPath();
|
||||||
|
basePath.register(watchService, EVENTS, SensitivityWatchEventModifier.HIGH);
|
||||||
|
|
||||||
while (run.get()) {
|
while (run.get()) {
|
||||||
WatchKey key = watchService.take();
|
WatchKey key = watchService.take();
|
||||||
for (WatchEvent<?> event : key.pollEvents()) {
|
for (WatchEvent<?> event : key.pollEvents()) {
|
||||||
if (file.getName().equals(event.context().toString())) {
|
Path path = basePath.resolve((Path) event.context());
|
||||||
if (task != null) {
|
|
||||||
taskManager.cancelTask(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
String previousHash = hash;
|
if (!Files.isDirectory(path)) {
|
||||||
long previousHashTimestamp = hashTimestamp;
|
handleWatchEvent(path);
|
||||||
|
|
||||||
hash = FileUtils.getHash(file.toPath());
|
|
||||||
hashTimestamp = System.currentTimeMillis();
|
|
||||||
task = ServerUtilsApp.getPlugin().getTaskManager().runTaskLater(() -> {
|
|
||||||
if (hash.equals(previousHash) || previousHashTimestamp < hashTimestamp - 1000L) {
|
|
||||||
send(WatchResult.CHANGE);
|
|
||||||
|
|
||||||
pluginManager.reloadPlugin(pluginName);
|
|
||||||
file = pluginManager.getPluginFile(pluginName);
|
|
||||||
}
|
|
||||||
}, 10L);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file == null || !key.reset()) {
|
if ((fileNameToWatchEntryMap.isEmpty() && pluginIdToWatchEntryMap.isEmpty()) || !key.reset()) {
|
||||||
send(WatchResult.STOPPED);
|
send(WatchResult.STOPPED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -102,10 +98,93 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleWatchEvent(Path path) {
|
||||||
|
String fileName = path.getFileName().toString();
|
||||||
|
WatchEntry entry = fileNameToWatchEntryMap.get(fileName);
|
||||||
|
|
||||||
|
if (entry == null && Files.exists(path)) {
|
||||||
|
Optional<? extends ServerUtilsPluginDescription> descriptionOptional;
|
||||||
|
try {
|
||||||
|
descriptionOptional = plugin.getPluginManager().getPluginDescription(path.toFile());
|
||||||
|
} catch (InvalidPluginDescriptionException ignored) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (descriptionOptional.isPresent()) {
|
||||||
|
ServerUtilsPluginDescription description = descriptionOptional.get();
|
||||||
|
WatchEntry foundEntry = pluginIdToWatchEntryMap.remove(description.getId());
|
||||||
|
if (foundEntry != null) {
|
||||||
|
send(WatchResult.DELETED_FILE_IS_CREATED.arg(foundEntry.pluginId));
|
||||||
|
fileNameToWatchEntryMap.put(fileName, foundEntry);
|
||||||
|
|
||||||
|
if (pluginIdToWatchEntryMap.isEmpty()) {
|
||||||
|
entry = foundEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry != null) {
|
||||||
|
checkWatchEntry(entry, fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkWatchEntry(WatchEntry entry, String fileName) {
|
||||||
|
if (task != null) {
|
||||||
|
plugin.getTaskManager().cancelTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
|
||||||
|
Optional<File> fileOptional = pluginManager.getPluginFile(entry.pluginId);
|
||||||
|
if (!fileOptional.isPresent()) {
|
||||||
|
send(WatchResult.FILE_DELETED.arg(entry.pluginId));
|
||||||
|
|
||||||
|
fileNameToWatchEntryMap.remove(fileName);
|
||||||
|
pluginIdToWatchEntryMap.put(entry.pluginId, entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String previousHash = entry.hash;
|
||||||
|
long previousTimestamp = entry.timestamp;
|
||||||
|
entry.update(fileOptional.get());
|
||||||
|
|
||||||
|
task = plugin.getTaskManager().runTaskLater(() -> {
|
||||||
|
if (entry.hash.equals(previousHash) || previousTimestamp < entry.timestamp - 1000L) {
|
||||||
|
send(WatchResult.CHANGE);
|
||||||
|
|
||||||
|
List<P> plugins = new ArrayList<>(fileNameToWatchEntryMap.size());
|
||||||
|
Map<String, WatchEntry> retainedWatchEntries = new HashMap<>();
|
||||||
|
for (WatchEntry oldEntry : fileNameToWatchEntryMap.values()) {
|
||||||
|
Optional<P> pluginOptional = pluginManager.getPlugin(oldEntry.pluginId);
|
||||||
|
if (!pluginOptional.isPresent()) continue;
|
||||||
|
|
||||||
|
plugins.add(pluginOptional.get());
|
||||||
|
retainedWatchEntries.put(oldEntry.pluginId, oldEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
fileNameToWatchEntryMap.clear();
|
||||||
|
|
||||||
|
PluginResults<P> reloadResults = pluginManager.reloadPlugins(plugins);
|
||||||
|
reloadResults.sendTo(sender, "reload");
|
||||||
|
|
||||||
|
for (PluginResult<P> reloadResult : reloadResults) {
|
||||||
|
if (!reloadResult.isSuccess()) continue;
|
||||||
|
|
||||||
|
P reloadedPlugin = reloadResult.getPlugin();
|
||||||
|
String pluginId = pluginManager.getPluginId(reloadedPlugin);
|
||||||
|
|
||||||
|
WatchEntry retainedEntry = retainedWatchEntries.get(pluginId);
|
||||||
|
String pluginFileName = pluginManager.getPluginFile(reloadedPlugin).getName();
|
||||||
|
fileNameToWatchEntryMap.put(pluginFileName, retainedEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 10L);
|
||||||
|
}
|
||||||
|
|
||||||
private void send(WatchResult result) {
|
private void send(WatchResult result) {
|
||||||
result.sendTo(sender, null, pluginName);
|
result.sendTo(sender);
|
||||||
if (sender.isPlayer()) {
|
if (sender.isPlayer()) {
|
||||||
result.sendTo(chatProvider.getConsoleSender(), null, pluginName);
|
result.sendTo(plugin.getChatProvider().getConsoleSender());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,4 +197,20 @@ public class PluginWatcherTask extends AbstractTask {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class WatchEntry {
|
||||||
|
|
||||||
|
private final String pluginId;
|
||||||
|
private String hash = null;
|
||||||
|
private long timestamp = 0L;
|
||||||
|
|
||||||
|
public WatchEntry(String pluginId) {
|
||||||
|
this.pluginId = pluginId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(File file) {
|
||||||
|
this.hash = FileUtils.getHash(file.toPath());
|
||||||
|
this.timestamp = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ import java.net.UnknownHostException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
import net.frankheijden.serverutils.common.ServerUtilsApp;
|
||||||
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
|
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
|
||||||
import net.frankheijden.serverutils.common.entities.LoadResult;
|
import net.frankheijden.serverutils.common.entities.results.PluginResult;
|
||||||
import net.frankheijden.serverutils.common.entities.Result;
|
import net.frankheijden.serverutils.common.entities.results.Result;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
|
||||||
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
|
||||||
import net.frankheijden.serverutils.common.entities.http.GitHubAsset;
|
import net.frankheijden.serverutils.common.entities.http.GitHubAsset;
|
||||||
|
|
@ -22,7 +22,7 @@ import net.frankheijden.serverutils.common.utils.GitHubUtils;
|
||||||
import net.frankheijden.serverutils.common.utils.VersionUtils;
|
import net.frankheijden.serverutils.common.utils.VersionUtils;
|
||||||
import net.frankheijden.serverutilsupdater.common.Updater;
|
import net.frankheijden.serverutilsupdater.common.Updater;
|
||||||
|
|
||||||
public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?>, P> implements Runnable {
|
public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> implements Runnable {
|
||||||
|
|
||||||
private final U plugin;
|
private final U plugin;
|
||||||
private final ServerCommandSender<?> sender;
|
private final ServerCommandSender<?> sender;
|
||||||
|
|
@ -60,7 +60,7 @@ public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?>, P> imple
|
||||||
* Checks for updates if enabled per config for the specific action.
|
* Checks for updates if enabled per config for the specific action.
|
||||||
* Action must be 'login' or 'boot'.
|
* Action must be 'login' or 'boot'.
|
||||||
*/
|
*/
|
||||||
public static <U extends ServerUtilsPlugin<P, ?, ?, ?>, P> void tryStart(
|
public static <U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> void tryStart(
|
||||||
U plugin,
|
U plugin,
|
||||||
ServerCommandSender<?> sender,
|
ServerCommandSender<?> sender,
|
||||||
String action
|
String action
|
||||||
|
|
@ -75,7 +75,7 @@ public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?>, P> imple
|
||||||
* Checks for updates and downloads/installs if configured.
|
* Checks for updates and downloads/installs if configured.
|
||||||
* Action must be 'login' or 'boot'.
|
* Action must be 'login' or 'boot'.
|
||||||
*/
|
*/
|
||||||
public static <U extends ServerUtilsPlugin<P, ?, ?, ?>, P> void start(
|
public static <U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> void start(
|
||||||
U plugin,
|
U plugin,
|
||||||
ServerCommandSender<?> sender,
|
ServerCommandSender<?> sender,
|
||||||
String action
|
String action
|
||||||
|
|
@ -241,21 +241,19 @@ public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?>, P> imple
|
||||||
|
|
||||||
private void tryReloadPlugin(File pluginFile, File updaterFile) {
|
private void tryReloadPlugin(File pluginFile, File updaterFile) {
|
||||||
plugin.getTaskManager().runTask(() -> {
|
plugin.getTaskManager().runTask(() -> {
|
||||||
LoadResult<P> loadResult = plugin.getPluginManager().loadPlugin(updaterFile);
|
PluginResult<P> loadResult = plugin.getPluginManager().loadPlugin(updaterFile);
|
||||||
if (!loadResult.isSuccess()) {
|
if (!loadResult.isSuccess()) {
|
||||||
plugin.getLogger().log(Level.INFO, UPDATER_LOAD_ERROR,
|
plugin.getLogger().log(Level.INFO, UPDATER_LOAD_ERROR, loadResult.getResult().name());
|
||||||
loadResult.getResult().name());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
P updaterPlugin = loadResult.get();
|
PluginResult<P> enableResult = plugin.getPluginManager().enablePlugin(loadResult.getPlugin());
|
||||||
Result result = plugin.getPluginManager().enablePlugin(updaterPlugin);
|
if (!enableResult.isSuccess() && enableResult.getResult() != Result.ALREADY_ENABLED) {
|
||||||
if (result != Result.SUCCESS && result != Result.ALREADY_ENABLED) {
|
plugin.getLogger().log(Level.INFO, UPDATER_ENABLE_ERROR, enableResult.getResult().name());
|
||||||
plugin.getLogger().log(Level.INFO, UPDATER_ENABLE_ERROR, result.name());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Updater updater = (Updater) plugin.getPluginManager().getInstance(updaterPlugin);
|
Updater updater = (Updater) plugin.getPluginManager().getInstance(enableResult.getPlugin());
|
||||||
updater.update(pluginFile);
|
updater.update(pluginFile);
|
||||||
updaterFile.delete();
|
updaterFile.delete();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
package net.frankheijden.serverutils.common.utils;
|
||||||
|
|
||||||
|
import com.google.common.graph.Graph;
|
||||||
|
import com.google.common.graph.GraphBuilder;
|
||||||
|
import com.google.common.graph.MutableGraph;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class DependencyUtils {
|
||||||
|
|
||||||
|
private DependencyUtils() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the topological order of a dependency map.
|
||||||
|
* Adapted from https://github.com/VelocityPowered/Velocity.
|
||||||
|
* @throws IllegalStateException Iff circular dependency.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
|
public static <T> List<T> determineOrder(Map<T, Set<T>> dependencyMap) throws IllegalStateException {
|
||||||
|
MutableGraph<T> dependencyGraph = GraphBuilder.directed().allowsSelfLoops(true).build();
|
||||||
|
for (T node : dependencyMap.keySet()) {
|
||||||
|
dependencyGraph.addNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<T, Set<T>> entry : dependencyMap.entrySet()) {
|
||||||
|
for (T dependency : entry.getValue()) {
|
||||||
|
dependencyGraph.putEdge(entry.getKey(), dependency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<T> orderedList = new ArrayList<>(dependencyMap.size());
|
||||||
|
Map<T, Mark> marks = new HashMap<>(dependencyMap.size());
|
||||||
|
|
||||||
|
for (T node : dependencyGraph.nodes()) {
|
||||||
|
visitNode(dependencyGraph, node, marks, orderedList, new LinkedList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
return orderedList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
|
private static <T> void visitNode(
|
||||||
|
Graph<T> dependencyGraph,
|
||||||
|
T node,
|
||||||
|
Map<T, Mark> marks,
|
||||||
|
List<T> orderedList,
|
||||||
|
Deque<T> currentIteration
|
||||||
|
) throws IllegalStateException {
|
||||||
|
Mark mark = marks.getOrDefault(node, Mark.NOT_VISITED);
|
||||||
|
if (mark == Mark.PERMANENT) {
|
||||||
|
return;
|
||||||
|
} else if (mark == Mark.TEMPORARY) {
|
||||||
|
currentIteration.addLast(node);
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (T currentNode : currentIteration) {
|
||||||
|
sb.append(" -> ").append(currentNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Circular dependency detected: " + sb.substring(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIteration.addLast(node);
|
||||||
|
marks.put(node, Mark.TEMPORARY);
|
||||||
|
|
||||||
|
for (T successorNode : dependencyGraph.successors(node)) {
|
||||||
|
visitNode(dependencyGraph, successorNode, marks, orderedList, currentIteration);
|
||||||
|
}
|
||||||
|
|
||||||
|
marks.put(node, Mark.PERMANENT);
|
||||||
|
currentIteration.removeLast();
|
||||||
|
orderedList.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Mark {
|
||||||
|
NOT_VISITED,
|
||||||
|
TEMPORARY,
|
||||||
|
PERMANENT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -41,29 +41,56 @@
|
||||||
"main": "loadplugin",
|
"main": "loadplugin",
|
||||||
"aliases": ["lp"],
|
"aliases": ["lp"],
|
||||||
"permission": "serverutils.loadplugin",
|
"permission": "serverutils.loadplugin",
|
||||||
"description": "Loads the specified jar file as a plugin.",
|
"description": "Loads the specified jar file(s).",
|
||||||
"display-in-help": true
|
"display-in-help": true
|
||||||
},
|
},
|
||||||
"unloadplugin": {
|
"unloadplugin": {
|
||||||
"main": "unloadplugin",
|
"main": "unloadplugin",
|
||||||
"aliases": ["up"],
|
"aliases": ["up"],
|
||||||
"permission": "serverutils.unloadplugin",
|
"permission": "serverutils.unloadplugin",
|
||||||
"description": "Disables and unloads the specified plugin.",
|
"description": "Disables and unloads the specified plugin(s).",
|
||||||
"display-in-help": true
|
"display-in-help": true,
|
||||||
|
"flags": {
|
||||||
|
"force": {
|
||||||
|
"main": "force",
|
||||||
|
"aliases": ["f"],
|
||||||
|
"permission": "serverutils.unloadplugin",
|
||||||
|
"description": "Force disable and unload the specified plugin(s).",
|
||||||
|
"display-in-help": false
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"reloadplugin": {
|
"reloadplugin": {
|
||||||
"main": "reloadplugin",
|
"main": "reloadplugin",
|
||||||
"aliases": ["rp"],
|
"aliases": ["rp"],
|
||||||
"permission": "serverutils.reloadplugin",
|
"permission": "serverutils.reloadplugin",
|
||||||
"description": "Reloads the specified plugin.",
|
"description": "Reloads the specified plugin(s).",
|
||||||
"display-in-help": true
|
"display-in-help": true,
|
||||||
|
"flags": {
|
||||||
|
"force": {
|
||||||
|
"main": "force",
|
||||||
|
"aliases": ["f"],
|
||||||
|
"permission": "serverutils.reloadplugin",
|
||||||
|
"description": "Force reloads the specified plugin(s).",
|
||||||
|
"display-in-help": false
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"watchplugin": {
|
"watchplugin": {
|
||||||
"main": "watchplugin",
|
"main": "watchplugin",
|
||||||
"aliases": ["wp"],
|
"aliases": ["wp"],
|
||||||
"permission": "serverutils.watchplugin",
|
"permission": "serverutils.watchplugin",
|
||||||
"description": "Watches the specified plugin for changes.",
|
"description": "Watches the specified plugin(s) for changes.",
|
||||||
"display-in-help": true
|
"display-in-help": true,
|
||||||
|
"flags": {
|
||||||
|
"force": {
|
||||||
|
"main": "force",
|
||||||
|
"aliases": ["f"],
|
||||||
|
"permission": "serverutils.watchplugin",
|
||||||
|
"description": "Force watches the specified plugin(s) for changes.",
|
||||||
|
"display-in-help": false
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"unwatchplugin": {
|
"unwatchplugin": {
|
||||||
"main": "unwatchplugin",
|
"main": "unwatchplugin",
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,21 @@
|
||||||
"invalid_description": "&cAn error occurred while %action%ing &4%what%&c, plugin doesn't have a valid description!",
|
"invalid_description": "&cAn error occurred while %action%ing &4%what%&c, plugin doesn't have a valid description!",
|
||||||
"invalid_plugin": "&cAn error occurred while %action%ing &4%what%&c, plugin is invalid!",
|
"invalid_plugin": "&cAn error occurred while %action%ing &4%what%&c, plugin is invalid!",
|
||||||
"unknown_dependency": "&cAn error occurred while %action%ing &4%what%&c, plugin has a dependeny which is not loaded: &4%arg%",
|
"unknown_dependency": "&cAn error occurred while %action%ing &4%what%&c, plugin has a dependeny which is not loaded: &4%arg%",
|
||||||
"watcher": {
|
"depending_plugins": {
|
||||||
|
"prefix": "&cPlugin &4%what%&c has depending plugins: ",
|
||||||
|
"format": "&4%plugin%",
|
||||||
|
"separator": "&c, ",
|
||||||
|
"last_separator": " &cand ",
|
||||||
|
"override": "&cUse \"&4/%command%&c\" to force command execution."
|
||||||
|
},
|
||||||
|
"watchplugin": {
|
||||||
"start": "&3Started watching &b%what%&3!",
|
"start": "&3Started watching &b%what%&3!",
|
||||||
"change": "&3Change detected for plugin &b%what%&3, reloading now...",
|
"change": "&3Changes detected, reloading plugins now...",
|
||||||
"stopped": "&3Stopped watching &b%what%&3!",
|
"stopped": "&3Stopped watching &b%what%&3!",
|
||||||
"not_watching": "&cWe aren't watching that plugin!"
|
"file_deleted": "&cPlugin file &4%what%&c has been deleted! Waiting for plugin to show up...",
|
||||||
|
"deleted_file_is_created": "&3Plugin file &b%what%&3 has shown up again!",
|
||||||
|
"already_watching": "&cYou are already watching &4%what%&c!",
|
||||||
|
"not_watching": "&cYou are not watching &4%what%&c!"
|
||||||
},
|
},
|
||||||
"update": {
|
"update": {
|
||||||
"available": "&8&m------------=&r&8[ &b&lServerUtils Update&r &8]&m=--------------\n &3Current version: &b%old%\n &3New version: &b%new%\n &3Release info: &b%info%\n&8&m-------------------------------------------------",
|
"available": "&8&m------------=&r&8[ &b&lServerUtils Update&r &8]&m=--------------\n &3Current version: &b%old%\n &3New version: &b%new%\n &3Release info: &b%info%\n&8&m-------------------------------------------------",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
package net.frankheijden.serverutils.common.utils;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||||
|
import static org.junit.jupiter.params.provider.Arguments.of;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
class DependencyUtilsTest {
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "dependencyMap = {0}, expected = {1}")
|
||||||
|
@MethodSource("dependencyGenerator")
|
||||||
|
void determineOrderDependencies(
|
||||||
|
Map<String, Set<String>> dependencyMap,
|
||||||
|
List<String> expected
|
||||||
|
) {
|
||||||
|
assertThat(DependencyUtils.determineOrder(dependencyMap)).isEqualTo(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "dependencyMap = {0}")
|
||||||
|
@MethodSource("circularDependencyGenerator")
|
||||||
|
void determineOrderCircularDependencies(
|
||||||
|
Map<String, Set<String>> dependencyMap
|
||||||
|
) {
|
||||||
|
assertThatIllegalStateException().isThrownBy(() -> DependencyUtils.determineOrder(dependencyMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream<Arguments> dependencyGenerator() {
|
||||||
|
return Stream.of(
|
||||||
|
of(
|
||||||
|
mapOf(
|
||||||
|
new Pair<>("B", asSet("A"))
|
||||||
|
),
|
||||||
|
asList("A", "B")
|
||||||
|
),
|
||||||
|
of(
|
||||||
|
mapOf(
|
||||||
|
new Pair<>("B", asSet("A")),
|
||||||
|
new Pair<>("C", asSet("A", "B"))
|
||||||
|
),
|
||||||
|
asList("A", "B", "C")
|
||||||
|
),
|
||||||
|
of(
|
||||||
|
mapOf(
|
||||||
|
new Pair<>("A", asSet("B")),
|
||||||
|
new Pair<>("B", asSet("C", "D")),
|
||||||
|
new Pair<>("C", asSet()),
|
||||||
|
new Pair<>("D", asSet("C", "E")),
|
||||||
|
new Pair<>("E", asSet("F")),
|
||||||
|
new Pair<>("F", asSet("C"))
|
||||||
|
),
|
||||||
|
asList("C", "F", "E", "D", "B", "A")
|
||||||
|
),
|
||||||
|
of(
|
||||||
|
mapOf(
|
||||||
|
new Pair<>("A", asSet()),
|
||||||
|
new Pair<>("B", asSet()),
|
||||||
|
new Pair<>("C", asSet()),
|
||||||
|
new Pair<>("D", asSet("C"))
|
||||||
|
),
|
||||||
|
asList("A", "B", "C", "D")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream<Arguments> circularDependencyGenerator() {
|
||||||
|
return Stream.of(
|
||||||
|
of(
|
||||||
|
mapOf(
|
||||||
|
new Pair<>("A", asSet("A"))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
of(
|
||||||
|
mapOf(
|
||||||
|
new Pair<>("A", asSet("B")),
|
||||||
|
new Pair<>("B", asSet("A"))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
of(
|
||||||
|
mapOf(
|
||||||
|
new Pair<>("B", asSet("A")),
|
||||||
|
new Pair<>("C", asSet("A", "B")),
|
||||||
|
new Pair<>("A", asSet("C"))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
of(
|
||||||
|
mapOf(
|
||||||
|
new Pair<>("A", asSet("B")),
|
||||||
|
new Pair<>("B", asSet("C")),
|
||||||
|
new Pair<>("C", asSet("D")),
|
||||||
|
new Pair<>("D", asSet("A"))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> Set<T> asSet(T... elements) {
|
||||||
|
return new HashSet<>(asList(elements));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <K, V> Map<K, V> mapOf(Pair<K, V>... pairs) {
|
||||||
|
Map<K, V> map = new HashMap<>();
|
||||||
|
for (Pair<K, V> pair : pairs) {
|
||||||
|
map.put(pair.first, pair.second);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class Pair<A, B> {
|
||||||
|
private final A first;
|
||||||
|
private final B second;
|
||||||
|
|
||||||
|
private Pair(A first, B second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,7 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.github.FrankHeijden.cloud:cloud-velocity:fea4605277'
|
implementation "com.github.FrankHeijden.cloud:cloud-velocity:${rootProject.cloudVersion}"
|
||||||
implementation 'org.bstats:bstats-velocity:2.2.1'
|
implementation 'org.bstats:bstats-velocity:2.2.1'
|
||||||
implementation project(":Common")
|
implementation project(":Common")
|
||||||
compileOnly 'com.velocitypowered:velocity-api:3.0.0'
|
compileOnly 'com.velocitypowered:velocity-api:3.0.0'
|
||||||
|
|
|
||||||
|
|
@ -21,16 +21,15 @@ public class VelocityCommandServerUtils
|
||||||
extends CommandServerUtils<VelocityPlugin, PluginContainer, VelocityCommandSender> {
|
extends CommandServerUtils<VelocityPlugin, PluginContainer, VelocityCommandSender> {
|
||||||
|
|
||||||
public VelocityCommandServerUtils(VelocityPlugin plugin) {
|
public VelocityCommandServerUtils(VelocityPlugin plugin) {
|
||||||
super(plugin);
|
super(plugin, PluginContainer[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FormatBuilder createPluginInfo(
|
protected FormatBuilder createPluginInfo(
|
||||||
FormatBuilder builder,
|
FormatBuilder builder,
|
||||||
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
|
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
|
||||||
String pluginName
|
PluginContainer container
|
||||||
) {
|
) {
|
||||||
PluginContainer container = plugin.getPluginManager().getPlugin(pluginName);
|
|
||||||
PluginDescription desc = container.getDescription();
|
PluginDescription desc = container.getDescription();
|
||||||
|
|
||||||
return builder
|
return builder
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
package net.frankheijden.serverutils.velocity.entities;
|
|
||||||
|
|
||||||
import com.velocitypowered.api.plugin.PluginContainer;
|
|
||||||
import net.frankheijden.serverutils.common.entities.LoadResult;
|
|
||||||
import net.frankheijden.serverutils.common.entities.Result;
|
|
||||||
|
|
||||||
public class VelocityLoadResult extends LoadResult<PluginContainer> {
|
|
||||||
|
|
||||||
public VelocityLoadResult(PluginContainer obj, Result result) {
|
|
||||||
super(obj, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public VelocityLoadResult(PluginContainer obj) {
|
|
||||||
super(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public VelocityLoadResult(Result result) {
|
|
||||||
super(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,12 +15,7 @@ import net.frankheijden.serverutils.velocity.listeners.VelocityPlayerListener;
|
||||||
import net.frankheijden.serverutils.velocity.managers.VelocityPluginManager;
|
import net.frankheijden.serverutils.velocity.managers.VelocityPluginManager;
|
||||||
import net.frankheijden.serverutils.velocity.managers.VelocityTaskManager;
|
import net.frankheijden.serverutils.velocity.managers.VelocityTaskManager;
|
||||||
|
|
||||||
public class VelocityPlugin extends ServerUtilsPlugin<
|
public class VelocityPlugin extends ServerUtilsPlugin<PluginContainer, ScheduledTask, VelocityCommandSender, CommandSource, VelocityPluginDescription> {
|
||||||
PluginContainer,
|
|
||||||
ScheduledTask,
|
|
||||||
VelocityCommandSender,
|
|
||||||
CommandSource
|
|
||||||
> {
|
|
||||||
|
|
||||||
private final ServerUtils plugin;
|
private final ServerUtils plugin;
|
||||||
private final VelocityPluginManager pluginManager;
|
private final VelocityPluginManager pluginManager;
|
||||||
|
|
@ -46,13 +41,15 @@ public class VelocityPlugin extends ServerUtilsPlugin<
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected VelocityCommandManager<VelocityCommandSender> newCommandManager() {
|
protected VelocityCommandManager<VelocityCommandSender> newCommandManager() {
|
||||||
return new VelocityCommandManager<>(
|
VelocityCommandManager<VelocityCommandSender> commandManager = new VelocityCommandManager<>(
|
||||||
plugin.getPluginContainer(),
|
plugin.getPluginContainer(),
|
||||||
plugin.getProxy(),
|
plugin.getProxy(),
|
||||||
AsynchronousCommandExecutionCoordinator.<VelocityCommandSender>newBuilder().build(),
|
AsynchronousCommandExecutionCoordinator.<VelocityCommandSender>newBuilder().build(),
|
||||||
chatProvider::get,
|
chatProvider::get,
|
||||||
VelocityCommandSender::getSource
|
VelocityCommandSender::getSource
|
||||||
);
|
);
|
||||||
|
handleBrigadier(commandManager.brigadierManager());
|
||||||
|
return commandManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
package net.frankheijden.serverutils.velocity.entities;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.plugin.PluginDescription;
|
||||||
|
import com.velocitypowered.api.plugin.meta.PluginDependency;
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
|
||||||
|
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
|
||||||
|
|
||||||
|
public class VelocityPluginDescription implements ServerUtilsPluginDescription {
|
||||||
|
|
||||||
|
private final PluginDescription description;
|
||||||
|
private final File file;
|
||||||
|
private final String author;
|
||||||
|
private final Set<String> dependencies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new BungeePluginDescription.
|
||||||
|
*/
|
||||||
|
public VelocityPluginDescription(PluginDescription description) {
|
||||||
|
this.description = description;
|
||||||
|
|
||||||
|
Optional<Path> sourceOptional = description.getSource();
|
||||||
|
if (!sourceOptional.isPresent()) throw new InvalidPluginDescriptionException("Source path is null");
|
||||||
|
|
||||||
|
this.file = sourceOptional.get().toFile();
|
||||||
|
this.author = String.join(", ", description.getAuthors());
|
||||||
|
this.dependencies = description.getDependencies().stream()
|
||||||
|
.map(PluginDependency::getId)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return this.description.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return this.description.getName().orElse("<UNKNOWN>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getVersion() {
|
||||||
|
return this.description.getVersion().orElse("<UNKNOWN>");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAuthor() {
|
||||||
|
return this.author;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getFile() {
|
||||||
|
return this.file;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getDependencies() {
|
||||||
|
return this.dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginDescription getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,11 +26,13 @@ import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import net.frankheijden.serverutils.common.entities.CloseableResult;
|
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
|
||||||
import net.frankheijden.serverutils.common.entities.Result;
|
import net.frankheijden.serverutils.common.entities.results.CloseablePluginResults;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.PluginResults;
|
||||||
|
import net.frankheijden.serverutils.common.entities.results.Result;
|
||||||
import net.frankheijden.serverutils.common.events.PluginEvent;
|
import net.frankheijden.serverutils.common.events.PluginEvent;
|
||||||
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
|
||||||
import net.frankheijden.serverutils.velocity.entities.VelocityLoadResult;
|
import net.frankheijden.serverutils.velocity.entities.VelocityPluginDescription;
|
||||||
import net.frankheijden.serverutils.velocity.events.VelocityPluginDisableEvent;
|
import net.frankheijden.serverutils.velocity.events.VelocityPluginDisableEvent;
|
||||||
import net.frankheijden.serverutils.velocity.events.VelocityPluginEnableEvent;
|
import net.frankheijden.serverutils.velocity.events.VelocityPluginEnableEvent;
|
||||||
import net.frankheijden.serverutils.velocity.events.VelocityPluginLoadEvent;
|
import net.frankheijden.serverutils.velocity.events.VelocityPluginLoadEvent;
|
||||||
|
|
@ -44,7 +46,7 @@ import net.frankheijden.serverutils.velocity.reflection.RVelocityPluginManager;
|
||||||
import net.frankheijden.serverutils.velocity.reflection.RVelocityScheduler;
|
import net.frankheijden.serverutils.velocity.reflection.RVelocityScheduler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
public class VelocityPluginManager implements AbstractPluginManager<PluginContainer> {
|
public class VelocityPluginManager extends AbstractPluginManager<PluginContainer, VelocityPluginDescription> {
|
||||||
|
|
||||||
private static VelocityPluginManager instance;
|
private static VelocityPluginManager instance;
|
||||||
private final ProxyServer proxy;
|
private final ProxyServer proxy;
|
||||||
|
|
@ -66,26 +68,33 @@ public class VelocityPluginManager implements AbstractPluginManager<PluginContai
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VelocityLoadResult loadPlugin(String pluginFile) {
|
public PluginResults<PluginContainer> loadPluginDescriptions(List<VelocityPluginDescription> descriptions) {
|
||||||
return loadPlugin(new File(getPluginsFolder(), pluginFile));
|
PluginResults<PluginContainer> loadResults = new PluginResults<>();
|
||||||
|
|
||||||
|
for (VelocityPluginDescription description : descriptions) {
|
||||||
|
Path source = description.getFile().toPath();
|
||||||
|
Path baseDirectory = source.getParent();
|
||||||
|
|
||||||
|
Object javaPluginLoader = RJavaPluginLoader.newInstance(proxy, baseDirectory);
|
||||||
|
PluginDescription candidate = RJavaPluginLoader.loadPluginDescription(javaPluginLoader, source);
|
||||||
|
|
||||||
|
dependencyCheck:
|
||||||
|
for (PluginDependency dependency : candidate.getDependencies()) {
|
||||||
|
String pluginId = dependency.getId();
|
||||||
|
for (VelocityPluginDescription desc : descriptions) {
|
||||||
|
if (desc.getId().equals(pluginId)) continue dependencyCheck;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public VelocityLoadResult loadPlugin(File file) {
|
|
||||||
if (!file.exists() || file.isDirectory()) return new VelocityLoadResult(Result.NOT_EXISTS);
|
|
||||||
|
|
||||||
Object javaPluginLoader = RJavaPluginLoader.newInstance(proxy, file.toPath().getParent());
|
|
||||||
PluginDescription candidate = RJavaPluginLoader.loadPluginDescription(javaPluginLoader, file.toPath());
|
|
||||||
if (proxy.getPluginManager().isLoaded(candidate.getId())) return new VelocityLoadResult(Result.ALREADY_LOADED);
|
|
||||||
|
|
||||||
for (PluginDependency dependency : candidate.getDependencies()) {
|
|
||||||
if (!dependency.isOptional() && !proxy.getPluginManager().isLoaded(dependency.getId())) {
|
if (!dependency.isOptional() && !proxy.getPluginManager().isLoaded(dependency.getId())) {
|
||||||
logger.error(
|
logger.error(
|
||||||
"Can't load plugin {} due to missing dependency {}",
|
"Can't load plugin {} due to missing dependency {}",
|
||||||
candidate.getId(),
|
candidate.getId(),
|
||||||
dependency.getId()
|
dependency.getId()
|
||||||
);
|
);
|
||||||
return new VelocityLoadResult(Result.UNKNOWN_DEPENDENCY.arg(dependency.getId()));
|
return loadResults.addResult(
|
||||||
|
description.getId(),
|
||||||
|
Result.UNKNOWN_DEPENDENCY.arg(dependency.getId())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,13 +103,23 @@ public class VelocityPluginManager implements AbstractPluginManager<PluginContai
|
||||||
proxy.getEventManager().fire(new VelocityPluginLoadEvent(container, PluginEvent.Stage.PRE));
|
proxy.getEventManager().fire(new VelocityPluginLoadEvent(container, PluginEvent.Stage.PRE));
|
||||||
proxy.getEventManager().fire(new VelocityPluginLoadEvent(container, PluginEvent.Stage.POST));
|
proxy.getEventManager().fire(new VelocityPluginLoadEvent(container, PluginEvent.Stage.POST));
|
||||||
|
|
||||||
return new VelocityLoadResult(container);
|
loadResults.addResult(description.getId(), container);
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result enablePlugin(PluginContainer container) {
|
public PluginResults<PluginContainer> enableOrderedPlugins(List<PluginContainer> containers) {
|
||||||
|
PluginResults<PluginContainer> enableResults = new PluginResults<>();
|
||||||
|
|
||||||
|
List<Object> pluginInstances = new ArrayList<>(containers.size());
|
||||||
|
for (PluginContainer container : containers) {
|
||||||
|
String pluginId = container.getDescription().getId();
|
||||||
proxy.getEventManager().fire(new VelocityPluginEnableEvent(container, PluginEvent.Stage.PRE));
|
proxy.getEventManager().fire(new VelocityPluginEnableEvent(container, PluginEvent.Stage.PRE));
|
||||||
if (proxy.getPluginManager().isLoaded(container.getDescription().getId())) return Result.ALREADY_ENABLED;
|
if (isPluginEnabled(pluginId)) {
|
||||||
|
return enableResults.addResult(pluginId, Result.ALREADY_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
Object javaPluginLoader = RJavaPluginLoader.newInstance(
|
Object javaPluginLoader = RJavaPluginLoader.newInstance(
|
||||||
proxy,
|
proxy,
|
||||||
|
|
@ -121,10 +140,12 @@ public class VelocityPluginManager implements AbstractPluginManager<PluginContai
|
||||||
.annotatedWith(Names.named(container.getDescription().getId()))
|
.annotatedWith(Names.named(container.getDescription().getId()))
|
||||||
.toInstance(container);
|
.toInstance(container);
|
||||||
}
|
}
|
||||||
|
for (PluginContainer container : containers) {
|
||||||
bind(PluginContainer.class)
|
bind(PluginContainer.class)
|
||||||
.annotatedWith(Names.named(realPlugin.getId()))
|
.annotatedWith(Names.named(container.getDescription().getId()))
|
||||||
.toInstance(container);
|
.toInstance(container);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -134,7 +155,7 @@ public class VelocityPluginManager implements AbstractPluginManager<PluginContai
|
||||||
String.format("Can't create plugin %s", container.getDescription().getId()),
|
String.format("Can't create plugin %s", container.getDescription().getId()),
|
||||||
ex
|
ex
|
||||||
);
|
);
|
||||||
return Result.ERROR;
|
return enableResults.addResult(pluginId, Result.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
|
|
@ -145,12 +166,18 @@ public class VelocityPluginManager implements AbstractPluginManager<PluginContai
|
||||||
);
|
);
|
||||||
|
|
||||||
RVelocityPluginManager.registerPlugin(proxy.getPluginManager(), container);
|
RVelocityPluginManager.registerPlugin(proxy.getPluginManager(), container);
|
||||||
container.getInstance().ifPresent(pluginInstance -> {
|
Optional<?> instanceOptional = container.getInstance();
|
||||||
|
if (instanceOptional.isPresent()) {
|
||||||
|
Object pluginInstance = instanceOptional.get();
|
||||||
RVelocityEventManager.registerInternally(proxy.getEventManager(), container, pluginInstance);
|
RVelocityEventManager.registerInternally(proxy.getEventManager(), container, pluginInstance);
|
||||||
RVelocityEventManager.fireForPlugin(
|
pluginInstances.add(pluginInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RVelocityEventManager.fireForPlugins(
|
||||||
proxy.getEventManager(),
|
proxy.getEventManager(),
|
||||||
new ProxyInitializeEvent(),
|
new ProxyInitializeEvent(),
|
||||||
pluginInstance
|
pluginInstances
|
||||||
).join();
|
).join();
|
||||||
|
|
||||||
ConsoleCommandSource console = proxy.getConsoleCommandSource();
|
ConsoleCommandSource console = proxy.getConsoleCommandSource();
|
||||||
|
|
@ -158,10 +185,10 @@ public class VelocityPluginManager implements AbstractPluginManager<PluginContai
|
||||||
console,
|
console,
|
||||||
s -> PermissionFunction.ALWAYS_TRUE
|
s -> PermissionFunction.ALWAYS_TRUE
|
||||||
);
|
);
|
||||||
PermissionFunction permissionFunction = RVelocityEventManager.fireForPlugin(
|
PermissionFunction permissionFunction = RVelocityEventManager.fireForPlugins(
|
||||||
proxy.getEventManager(),
|
proxy.getEventManager(),
|
||||||
event,
|
event,
|
||||||
pluginInstance
|
pluginInstances
|
||||||
).join().createFunction(console);
|
).join().createFunction(console);
|
||||||
|
|
||||||
if (permissionFunction == null) {
|
if (permissionFunction == null) {
|
||||||
|
|
@ -175,70 +202,70 @@ public class VelocityPluginManager implements AbstractPluginManager<PluginContai
|
||||||
}
|
}
|
||||||
|
|
||||||
RVelocityConsole.setPermissionFunction(console, permissionFunction);
|
RVelocityConsole.setPermissionFunction(console, permissionFunction);
|
||||||
});
|
|
||||||
|
|
||||||
|
for (PluginContainer container : containers) {
|
||||||
proxy.getEventManager().fire(new VelocityPluginEnableEvent(container, PluginEvent.Stage.POST));
|
proxy.getEventManager().fire(new VelocityPluginEnableEvent(container, PluginEvent.Stage.POST));
|
||||||
return Result.SUCCESS;
|
enableResults.addResult(container.getDescription().getId(), container);
|
||||||
|
}
|
||||||
|
|
||||||
|
return enableResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result disablePlugin(PluginContainer container) {
|
public boolean isPluginEnabled(String pluginId) {
|
||||||
proxy.getEventManager().fire(new VelocityPluginDisableEvent(container, PluginEvent.Stage.PRE));
|
return proxy.getPluginManager().isLoaded(pluginId);
|
||||||
Object pluginInstance = container.getInstance().orElse(null);
|
}
|
||||||
if (pluginInstance == null) return Result.NOT_EXISTS;
|
|
||||||
|
|
||||||
RVelocityEventManager.fireForPlugin(
|
@Override
|
||||||
|
public PluginResults<PluginContainer> disableOrderedPlugins(List<PluginContainer> containers) {
|
||||||
|
PluginResults<PluginContainer> disableResults = new PluginResults<>();
|
||||||
|
|
||||||
|
List<Object> pluginInstances = new ArrayList<>(containers.size());
|
||||||
|
for (PluginContainer container : containers) {
|
||||||
|
proxy.getEventManager().fire(new VelocityPluginDisableEvent(container, PluginEvent.Stage.PRE));
|
||||||
|
String pluginId = getPluginId(container);
|
||||||
|
Object pluginInstance = container.getInstance().orElse(null);
|
||||||
|
if (pluginInstance == null) {
|
||||||
|
return disableResults.addResult(pluginId, Result.ALREADY_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginInstances.add(pluginInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
RVelocityEventManager.fireForPlugins(
|
||||||
proxy.getEventManager(),
|
proxy.getEventManager(),
|
||||||
pluginInstance,
|
new ProxyShutdownEvent(),
|
||||||
new ProxyShutdownEvent()
|
pluginInstances
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for (PluginContainer container : containers) {
|
||||||
proxy.getEventManager().fire(new VelocityPluginDisableEvent(container, PluginEvent.Stage.POST));
|
proxy.getEventManager().fire(new VelocityPluginDisableEvent(container, PluginEvent.Stage.POST));
|
||||||
return Result.SUCCESS;
|
disableResults.addResult(getPluginId(container), container);
|
||||||
|
}
|
||||||
|
|
||||||
|
return disableResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result reloadPlugin(String pluginName) {
|
public CloseablePluginResults<PluginContainer> unloadOrderedPlugins(List<PluginContainer> containers) {
|
||||||
Optional<PluginContainer> pluginOptional = proxy.getPluginManager().getPlugin(pluginName);
|
CloseablePluginResults<PluginContainer> unloadResults = new CloseablePluginResults<>();
|
||||||
if (!pluginOptional.isPresent()) return Result.NOT_EXISTS;
|
|
||||||
return reloadPlugin(pluginOptional.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
for (PluginContainer container : containers) {
|
||||||
public Result reloadPlugin(PluginContainer plugin) {
|
|
||||||
CloseableResult result = unloadPlugin(plugin);
|
|
||||||
if (result.getResult() != Result.SUCCESS) return result.getResult();
|
|
||||||
result.tryClose();
|
|
||||||
|
|
||||||
File file = getPluginFile(plugin.getDescription().getId());
|
|
||||||
if (file == null) return Result.FILE_DELETED;
|
|
||||||
|
|
||||||
VelocityLoadResult loadResult = loadPlugin(file);
|
|
||||||
if (!loadResult.isSuccess()) return loadResult.getResult();
|
|
||||||
|
|
||||||
return enablePlugin(loadResult.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CloseableResult unloadPlugin(String pluginName) {
|
|
||||||
Optional<PluginContainer> pluginOptional = proxy.getPluginManager().getPlugin(pluginName);
|
|
||||||
if (!pluginOptional.isPresent()) return new CloseableResult(Result.NOT_EXISTS);
|
|
||||||
return unloadPlugin(pluginOptional.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CloseableResult unloadPlugin(PluginContainer container) {
|
|
||||||
proxy.getEventManager().fire(new VelocityPluginUnloadEvent(container, PluginEvent.Stage.PRE));
|
proxy.getEventManager().fire(new VelocityPluginUnloadEvent(container, PluginEvent.Stage.PRE));
|
||||||
|
String pluginId = getPluginId(container);
|
||||||
Optional<?> pluginInstanceOptional = container.getInstance();
|
Optional<?> pluginInstanceOptional = container.getInstance();
|
||||||
if (!pluginInstanceOptional.isPresent()) return new CloseableResult(Result.INVALID_PLUGIN);
|
if (!pluginInstanceOptional.isPresent()) {
|
||||||
|
return unloadResults.addResult(pluginId, Result.INVALID_PLUGIN);
|
||||||
|
}
|
||||||
|
|
||||||
Object pluginInstance = pluginInstanceOptional.get();
|
Object pluginInstance = pluginInstanceOptional.get();
|
||||||
|
|
||||||
proxy.getEventManager().unregisterListeners(pluginInstance);
|
proxy.getEventManager().unregisterListeners(pluginInstance);
|
||||||
for (ScheduledTask task : RVelocityScheduler.getTasksByPlugin(proxy.getScheduler()).removeAll(pluginInstance)) {
|
for (ScheduledTask task : RVelocityScheduler.getTasksByPlugin(proxy.getScheduler())
|
||||||
|
.removeAll(pluginInstance)) {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
String pluginId = container.getDescription().getId();
|
|
||||||
for (String alias : pluginCommandManager.getPluginCommands().removeAll(pluginId)) {
|
for (String alias : pluginCommandManager.getPluginCommands().removeAll(pluginId)) {
|
||||||
proxy.getCommandManager().unregister(alias);
|
proxy.getCommandManager().unregister(alias);
|
||||||
}
|
}
|
||||||
|
|
@ -254,7 +281,10 @@ public class VelocityPluginManager implements AbstractPluginManager<PluginContai
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy.getEventManager().fire(new VelocityPluginUnloadEvent(container, PluginEvent.Stage.POST));
|
proxy.getEventManager().fire(new VelocityPluginUnloadEvent(container, PluginEvent.Stage.POST));
|
||||||
return new CloseableResult(closeables);
|
unloadResults.addResult(pluginId, container, closeables);
|
||||||
|
}
|
||||||
|
|
||||||
|
return unloadResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -263,7 +293,7 @@ public class VelocityPluginManager implements AbstractPluginManager<PluginContai
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPluginName(PluginContainer plugin) {
|
public String getPluginId(PluginContainer plugin) {
|
||||||
return plugin.getDescription().getId();
|
return plugin.getDescription().getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,22 +305,43 @@ public class VelocityPluginManager implements AbstractPluginManager<PluginContai
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getPluginFile(String pluginName) {
|
public Optional<File> getPluginFile(String pluginName) {
|
||||||
Object javaPluginLoader = RJavaPluginLoader.newInstance(instance.proxy, getPluginsFolder().toPath());
|
Object javaPluginLoader = RJavaPluginLoader.newInstance(instance.proxy, getPluginsFolder().toPath());
|
||||||
|
|
||||||
for (File file : getPluginJars()) {
|
for (File file : getPluginJars()) {
|
||||||
PluginDescription desc = RJavaPluginLoader.loadPluginDescription(javaPluginLoader, file.toPath());
|
PluginDescription desc = RJavaPluginLoader.loadPluginDescription(javaPluginLoader, file.toPath());
|
||||||
|
|
||||||
if (desc.getId().equals(pluginName)) {
|
if (desc.getId().equals(pluginName)) {
|
||||||
return file;
|
return Optional.of(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PluginContainer getPlugin(String pluginName) {
|
public Optional<PluginContainer> getPlugin(String pluginName) {
|
||||||
return proxy.getPluginManager().getPlugin(pluginName).orElse(null);
|
return proxy.getPluginManager().getPlugin(pluginName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VelocityPluginDescription getLoadedPluginDescription(PluginContainer plugin) {
|
||||||
|
return new VelocityPluginDescription(plugin.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<VelocityPluginDescription> getPluginDescription(
|
||||||
|
File file
|
||||||
|
) throws InvalidPluginDescriptionException {
|
||||||
|
Path source = file.toPath();
|
||||||
|
Path baseDirectory = source.getParent();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object javaPluginLoader = RJavaPluginLoader.newInstance(proxy, baseDirectory);
|
||||||
|
PluginDescription candidate = RJavaPluginLoader.loadPluginDescription(javaPluginLoader, source);
|
||||||
|
return Optional.of(new VelocityPluginDescription(candidate));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new InvalidPluginDescriptionException(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import dev.frankheijden.minecraftreflection.MinecraftReflection;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class RVelocityEventManager {
|
public class RVelocityEventManager {
|
||||||
|
|
@ -27,9 +28,14 @@ public class RVelocityEventManager {
|
||||||
* Retrieves the registrations from a plugin for a specific event.
|
* Retrieves the registrations from a plugin for a specific event.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static List<Object> getRegistrationsByPlugin(EventManager manager, Object plugin, Class<?> eventClass) {
|
public static List<Object> getRegistrationsByPlugins(
|
||||||
|
EventManager manager,
|
||||||
|
List<Object> plugins,
|
||||||
|
Class<?> eventClass
|
||||||
|
) {
|
||||||
return (List<Object>) getHandlersByType(manager).get(eventClass).stream()
|
return (List<Object>) getHandlersByType(manager).get(eventClass).stream()
|
||||||
.filter(r -> RHandlerRegistration.getPlugin(r).getInstance().orElse(null) == plugin)
|
.filter(r -> plugins.contains(RHandlerRegistration.getPlugin(r).getInstance().orElse(null)))
|
||||||
|
.sorted(reflection.get(manager, "handlerComparator"))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,26 +54,27 @@ public class RVelocityEventManager {
|
||||||
/**
|
/**
|
||||||
* Fires an event specifically for one plugin.
|
* Fires an event specifically for one plugin.
|
||||||
*/
|
*/
|
||||||
public static <E> CompletableFuture<E> fireForPlugin(
|
public static <E> CompletableFuture<E> fireForPlugins(
|
||||||
EventManager manager,
|
EventManager manager,
|
||||||
E event,
|
E event,
|
||||||
Object plugin
|
List<Object> pluginInstances
|
||||||
) {
|
) {
|
||||||
List<Object> registrations = getRegistrationsByPlugin(manager, plugin, event.getClass());
|
List<Object> registrations = getRegistrationsByPlugins(manager, pluginInstances, event.getClass());
|
||||||
CompletableFuture<E> future = new CompletableFuture<>();
|
CompletableFuture<E> future = new CompletableFuture<>();
|
||||||
|
|
||||||
Object registrationsEmptyArray = Array.newInstance(RHandlerRegistration.reflection.getClazz(), 0);
|
Object registrationsEmptyArray = Array.newInstance(RHandlerRegistration.reflection.getClazz(), 0);
|
||||||
Class<?> registrationsArrayClass = registrationsEmptyArray.getClass();
|
Class<?> registrationsArrayClass = registrationsEmptyArray.getClass();
|
||||||
|
|
||||||
reflection.invoke(
|
ExecutorService executor = reflection.invoke(manager, "getAsyncExecutor");
|
||||||
|
executor.execute(() -> reflection.invoke(
|
||||||
manager,
|
manager,
|
||||||
"fire",
|
"fire",
|
||||||
ClassObject.of(CompletableFuture.class, future),
|
ClassObject.of(CompletableFuture.class, future),
|
||||||
ClassObject.of(Object.class, event),
|
ClassObject.of(Object.class, event),
|
||||||
ClassObject.of(int.class, 0),
|
ClassObject.of(int.class, 0),
|
||||||
ClassObject.of(boolean.class, false),
|
ClassObject.of(boolean.class, true),
|
||||||
ClassObject.of(registrationsArrayClass, registrations.toArray((Object[]) registrationsEmptyArray))
|
ClassObject.of(registrationsArrayClass, registrations.toArray((Object[]) registrationsEmptyArray))
|
||||||
);
|
));
|
||||||
|
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
37
build.gradle
37
build.gradle
|
|
@ -7,6 +7,12 @@ group = 'net.frankheijden.serverutils'
|
||||||
String dependencyDir = group + '.dependencies'
|
String dependencyDir = group + '.dependencies'
|
||||||
version = '2.5.6'
|
version = '2.5.6'
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
ext {
|
||||||
|
cloudVersion = '62e3bc97ef'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
|
|
@ -19,14 +25,19 @@ subprojects {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url 'https://jitpack.io' }
|
maven { url 'https://jitpack.io' }
|
||||||
maven { url 'https://repo.aikar.co/content/groups/aikar/' }
|
|
||||||
maven { url 'https://repo.incendo.org/content/repositories/snapshots' }
|
maven { url 'https://repo.incendo.org/content/repositories/snapshots' }
|
||||||
maven { url 'https://papermc.io/repo/repository/maven-public/' }
|
maven { url 'https://papermc.io/repo/repository/maven-public/' }
|
||||||
|
maven { url 'https://libraries.minecraft.net' }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.github.FrankHeijden.cloud:cloud-core:fea4605277'
|
implementation "com.github.FrankHeijden.cloud:cloud-core:${rootProject.cloudVersion}"
|
||||||
|
implementation "com.github.FrankHeijden.cloud:cloud-brigadier:${rootProject.cloudVersion}"
|
||||||
implementation 'com.github.FrankHeijden:MinecraftReflection:1.0.0'
|
implementation 'com.github.FrankHeijden:MinecraftReflection:1.0.0'
|
||||||
|
implementation 'com.google.guava:guava:30.1.1-jre'
|
||||||
|
implementation 'com.google.code.gson:gson:2.8.6'
|
||||||
|
implementation 'me.lucko:commodore:1.10'
|
||||||
|
compileOnly 'com.mojang:brigadier:1.0.17'
|
||||||
|
|
||||||
testCompile 'org.assertj:assertj-core:3.18.1'
|
testCompile 'org.assertj:assertj-core:3.18.1'
|
||||||
testCompile 'org.junit.jupiter:junit-jupiter-api:5.7.0'
|
testCompile 'org.junit.jupiter:junit-jupiter-api:5.7.0'
|
||||||
|
|
@ -55,6 +66,28 @@ subprojects {
|
||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
exclude 'com/mojang/**'
|
exclude 'com/mojang/**'
|
||||||
|
exclude 'javax/annotation/**'
|
||||||
|
exclude 'org/checkerframework/**'
|
||||||
|
exclude 'com/google/errorprone/**'
|
||||||
|
exclude 'com/google/j2objc/**'
|
||||||
|
exclude 'com/google/thirdparty/**'
|
||||||
|
exclude 'com/google/common/annotations/**'
|
||||||
|
exclude 'com/google/common/base/**'
|
||||||
|
exclude 'com/google/common/cache/**'
|
||||||
|
exclude 'com/google/common/collect/**'
|
||||||
|
exclude 'com/google/common/escape/**'
|
||||||
|
exclude 'com/google/common/eventbus/**'
|
||||||
|
exclude 'com/google/common/hash/**'
|
||||||
|
exclude 'com/google/common/html/**'
|
||||||
|
exclude 'com/google/common/io/**'
|
||||||
|
exclude 'com/google/common/math/**'
|
||||||
|
exclude 'com/google/common/net/**'
|
||||||
|
exclude 'com/google/common/primitives/**'
|
||||||
|
exclude 'com/google/common/reflect/**'
|
||||||
|
exclude 'com/google/common/util/**'
|
||||||
|
exclude 'com/google/common/xml/**'
|
||||||
|
relocate 'com.google.gson', dependencyDir + '.gson'
|
||||||
|
relocate 'com.google.common.graph', dependencyDir + '.common.graph'
|
||||||
relocate 'dev.frankheijden.minecraftreflection', dependencyDir + '.minecraftreflection'
|
relocate 'dev.frankheijden.minecraftreflection', dependencyDir + '.minecraftreflection'
|
||||||
relocate 'cloud.commandframework', dependencyDir + '.cloud'
|
relocate 'cloud.commandframework', dependencyDir + '.cloud'
|
||||||
relocate 'io.leangen.geantyref', dependencyDir + '.typetoken'
|
relocate 'io.leangen.geantyref', dependencyDir + '.typetoken'
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
<property name="fileExtensions" value="java"/>
|
<property name="fileExtensions" value="java"/>
|
||||||
<!-- changed from 100 to 120, loosen a bit -->
|
<!-- changed from 100 to 120, loosen a bit -->
|
||||||
<property name="max" value="120"/>
|
<property name="max" value="120"/>
|
||||||
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://|^[ ]*(public )?(static )?(final )?(abstract )?class.*"/>
|
||||||
</module>
|
</module>
|
||||||
|
|
||||||
<module name="TreeWalker">
|
<module name="TreeWalker">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue