Add MiniMessage

This commit is contained in:
Frank van der Heijden 2021-08-03 02:07:39 +02:00
parent bb5c642f31
commit 083012abfe
No known key found for this signature in database
GPG key ID: B808721C2DD5B5B8
74 changed files with 1328 additions and 1078 deletions

View file

@ -7,11 +7,12 @@ import java.util.Optional;
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.ServerUtilsAudience;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
import net.frankheijden.serverutils.common.tasks.UpdateCheckerTask;
import net.kyori.adventure.text.Component;
public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S, D>, P, T, C extends ServerCommandSender<S>, S, D extends ServerUtilsPluginDescription> {
public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S, D>, P, T, C extends ServerUtilsAudience<S>, S, D extends ServerUtilsPluginDescription> {
public static final int BSTATS_METRICS_ID = 7790;
public static final String VERSION = "{version}";
@ -31,7 +32,7 @@ public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S, D>, P, T, C
U extends ServerUtilsPlugin<P, T, C, S, D>,
P,
T,
C extends ServerCommandSender<S>,
C extends ServerUtilsAudience<S>,
S,
D extends ServerUtilsPluginDescription
> void init(
@ -45,7 +46,7 @@ public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S, D>, P, T, C
* Tries checking for updates if enabled by the config.
*/
public static void tryCheckForUpdates() {
UpdateCheckerTask.tryStart(getPlugin(), getPlugin().getChatProvider().getConsoleSender(), "boot");
UpdateCheckerTask.tryStart(getPlugin(), getPlugin().getChatProvider().getConsoleServerAudience(), "boot");
}
/**
@ -65,13 +66,15 @@ public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S, D>, P, T, C
File file = plugin.getPluginManager().getPluginFile(updaterPlugin);
PluginResult<P> disableResult = plugin.getPluginManager().disablePlugin(updaterPlugin);
if (!disableResult.isSuccess()) {
disableResult.getResult().sendTo(plugin.getChatProvider().getConsoleSender(), "disabl", updaterName);
Component component = disableResult.toComponent(null);
plugin.getChatProvider().getConsoleServerAudience().sendMessage(component);
return;
}
CloseablePluginResult<P> unloadResult = plugin.getPluginManager().unloadPlugin(disableResult.getPlugin());
if (!unloadResult.isSuccess()) {
unloadResult.getResult().sendTo(plugin.getChatProvider().getConsoleSender(), "unload", updaterName);
Component component = unloadResult.toComponent(null);
plugin.getChatProvider().getConsoleServerAudience().sendMessage(component);
return;
}
@ -96,7 +99,7 @@ public class ServerUtilsApp<U extends ServerUtilsPlugin<P, T, C, S, D>, P, T, C
U extends ServerUtilsPlugin<P, T, C, S, D>,
P,
T,
C extends ServerCommandSender<S>,
C extends ServerUtilsAudience<S>,
S,
D extends ServerUtilsPluginDescription
> U getPlugin() {

View file

@ -2,12 +2,15 @@ package net.frankheijden.serverutils.common.commands;
import cloud.commandframework.context.CommandContext;
import java.util.List;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.config.MessageKey;
import net.frankheijden.serverutils.common.config.MessagesResource;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
import net.frankheijden.serverutils.common.utils.ListBuilder;
import net.frankheijden.serverutils.common.utils.ListFormat;
import net.frankheijden.serverutils.common.utils.ListComponentBuilder;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.Template;
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 ServerUtilsAudience<?>>
extends ServerUtilsCommand<U, C> {
protected CommandPlugins(U plugin) {
@ -21,21 +24,22 @@ public abstract class CommandPlugins<U extends ServerUtilsPlugin<P, ?, C, ?, ?>,
* @param sender The receiver of the plugin list.
* @param plugins The plugins to be sent.
* @param pluginFormat The format of the plugins to be sent.
* @param <T> The plugin type.
*/
protected void handlePlugins(C sender, List<P> plugins, ListFormat<P> pluginFormat) {
String prefix = plugin.getMessagesResource().getMessage(
"serverutils.plugins.prefix",
"%count%", String.valueOf(plugins.size())
);
if (prefix == null) prefix = "";
plugin.getMessagesResource().sendMessage(sender, "serverutils.plugins.header");
sender.sendMessage(plugin.getChatProvider().color(prefix + ListBuilder.create(plugins)
.seperator(plugin.getMessagesResource().getMessage("serverutils.plugins.seperator"))
.lastSeperator(plugin.getMessagesResource().getMessage("serverutils.plugins.last_seperator"))
.format(pluginFormat)
.toString()));
plugin.getMessagesResource().sendMessage(sender, "serverutils.plugins.footer");
protected void handlePlugins(C sender, List<P> plugins, ListComponentBuilder.Format<P> pluginFormat) {
MessagesResource messages = plugin.getMessagesResource();
sender.sendMessage(Component.text()
.append(messages.get(MessageKey.PLUGINS_HEADER).toComponent())
.append(Component.newline())
.append(messages.get(MessageKey.PLUGINS_PREFIX).toComponent(
Template.of("count", String.valueOf(plugins.size()))
))
.append(ListComponentBuilder.create(plugins)
.separator(messages.get(MessageKey.PLUGINS_SEPARATOR).toComponent())
.lastSeparator(messages.get(MessageKey.PLUGINS_LAST_SEPARATOR).toComponent())
.format(pluginFormat)
.build())
.append(Component.newline())
.append(messages.get(MessageKey.PLUGININFO_FOOTER).toComponent())
.build());
}
}

View file

@ -15,21 +15,24 @@ 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.MessageKey;
import net.frankheijden.serverutils.common.config.MessagesResource;
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
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.PluginWatchResults;
import net.frankheijden.serverutils.common.entities.results.Result;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
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.utils.FormatBuilder;
import net.frankheijden.serverutils.common.utils.ListBuilder;
import net.frankheijden.serverutils.common.utils.ListFormat;
import net.frankheijden.serverutils.common.utils.ListComponentBuilder;
import net.frankheijden.serverutils.common.utils.KeyValueComponentBuilder;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.minimessage.Template;
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 ServerUtilsAudience<?>>
extends ServerUtilsCommand<U, C> {
protected final IntFunction<P[]> arrayCreator;
@ -92,10 +95,13 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
private void handleHelpCommand(CommandContext<C> context) {
C sender = context.getSender();
plugin.getMessagesResource().sendMessage(sender, "serverutils.help.header");
FormatBuilder builder = FormatBuilder.create(plugin.getMessagesResource().getMessage("serverutils.help.format"))
.orderedKeys("%command%", "%help%");
MessagesResource messages = plugin.getMessagesResource();
TextComponent.Builder builder = Component.text()
.append(messages.get(MessageKey.HELP_HEADER).toComponent())
.append(Component.newline());
MessagesResource.Message helpFormatMessage = messages.get(MessageKey.HELP_FORMAT);
ServerUtilsConfig config = (ServerUtilsConfig) plugin.getCommandsResource().getConfig().get("commands");
for (String commandName : config.getKeys()) {
@ -104,7 +110,10 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
String shortestCommandAlias = determineShortestAlias(commandElement);
if (commandElement.shouldDisplayInHelp()) {
builder.add(shortestCommandAlias, commandElement.getDescription().getDescription());
builder.append(helpFormatMessage.toComponent(
Template.of("command", shortestCommandAlias),
Template.of("help", commandElement.getDescription().getDescription())
)).append(Component.newline());
}
Object subcommandsObject = commandConfig.get("subcommands");
@ -116,10 +125,10 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
CommandElement subcommandElement = parseElement(subcommandConfig);
if (subcommandElement.shouldDisplayInHelp()) {
String shortestSubcommandAlias = determineShortestAlias(subcommandElement);
builder.add(
shortestCommandAlias + ' ' + shortestSubcommandAlias,
subcommandElement.getDescription().getDescription()
);
builder.append(helpFormatMessage.toComponent(
Template.of("command", shortestCommandAlias + ' ' + shortestSubcommandAlias),
Template.of("help", subcommandElement.getDescription().getDescription())
)).append(Component.newline());
}
}
}
@ -134,16 +143,17 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
if (flagElement.shouldDisplayInHelp()) {
String shortestFlagAlias = determineShortestAlias(flagElement);
String flagPrefix = "-" + (flagElement.getMain().equals(shortestFlagAlias) ? "_" : "");
builder.add(
shortestCommandAlias + ' ' + flagPrefix + shortestFlagAlias,
flagElement.getDescription().getDescription()
);
builder.append(helpFormatMessage.toComponent(
Template.of("command", shortestCommandAlias + ' ' + flagPrefix + shortestFlagAlias),
Template.of("help", flagElement.getDescription().getDescription())
)).append(Component.newline());
}
}
}
}
builder.build().forEach(msg -> plugin.getMessagesResource().sendRawMessage(sender, msg));
plugin.getMessagesResource().sendMessage(sender, "serverutils.help.footer");
builder.append(messages.get(MessageKey.HELP_FOOTER).toComponent());
sender.sendMessage(builder.build());
}
private String determineShortestAlias(CommandElement element) {
@ -159,9 +169,7 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
private void handleReload(CommandContext<C> context) {
C sender = context.getSender();
plugin.reload();
plugin.getMessagesResource().sendMessage(sender, "serverutils.success",
"%action%", "reload",
"%what%", "ServerUtils configurations");
plugin.getMessagesResource().get(MessageKey.RELOAD).sendTo(sender);
}
private void handleLoadPlugin(CommandContext<C> context) {
@ -172,12 +180,12 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
PluginResults<P> loadResults = pluginManager.loadPlugins(jarFiles);
if (!loadResults.isSuccess()) {
PluginResult<P> failedResult = loadResults.last();
failedResult.getResult().sendTo(sender, "load", failedResult.getPluginId());
sender.sendMessage(failedResult.toComponent(null));
return;
}
PluginResults<P> enableResults = pluginManager.enablePlugins(loadResults.getPlugins());
enableResults.sendTo(sender, "load");
sender.sendMessage(enableResults.toComponent(MessageKey.LOADPLUGIN));
}
private void handleUnloadPlugin(CommandContext<C> context) {
@ -191,14 +199,14 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
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());
sender.sendMessage(disableResult.toComponent(null));
return;
}
}
CloseablePluginResults<P> unloadResults = plugin.getPluginManager().unloadPlugins(plugins);
unloadResults.tryClose();
unloadResults.sendTo(sender, "unload");
sender.sendMessage(unloadResults.toComponent(MessageKey.UNLOADPLUGIN));
}
private void handleReloadPlugin(CommandContext<C> context) {
@ -209,8 +217,8 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
return;
}
PluginResults<P> reloadResult = plugin.getPluginManager().reloadPlugins(plugins);
reloadResult.sendTo(sender, "reload");
PluginResults<P> reloadResults = plugin.getPluginManager().reloadPlugins(plugins);
sender.sendMessage(reloadResults.toComponent(MessageKey.RELOADPLUGIN));
}
protected boolean checkDependingPlugins(CommandContext<C> context, C sender, List<P> plugins, String subcommand) {
@ -219,26 +227,27 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
MessagesResource messages = plugin.getMessagesResource();
TextComponent.Builder builder = Component.text();
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
);
builder.append(messages.get(MessageKey.DEPENDING_PLUGINS_PREFIX).toComponent(
Template.of("plugin", pluginId)
));
String dependingPluginsString = ListBuilder.create(dependingPlugins)
.format(p -> messages.getMessage(
"serverutils.depending_plugins.format",
"%plugin%", pluginManager.getPluginId(p)
MessagesResource.Message dependingPluginsFormat = messages.get(MessageKey.DEPENDING_PLUGINS_FORMAT);
builder.append(ListComponentBuilder.create(dependingPlugins)
.format(p -> dependingPluginsFormat.toComponent(
Template.of("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);
.separator(messages.get(MessageKey.DEPENDING_PLUGINS_SEPARATOR).toComponent())
.lastSeparator(messages.get(MessageKey.DEPENDING_PLUGINS_LAST_SEPARATOR).toComponent())
.build());
builder.append(Component.newline());
hasDependingPlugins = true;
}
}
@ -249,12 +258,13 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
.min(Comparator.comparingInt(String::length))
.orElse("-f");
messages.sendMessage(sender,
"serverutils.depending_plugins.override",
"%command%", context.getRawInputJoined() + " " + forceFlag
);
builder.append(messages.get(MessageKey.DEPENDING_PLUGINS_OVERRIDE).toComponent(
Template.of("command", context.getRawInputJoined() + " " + forceFlag)
));
}
sender.sendMessage(builder.build());
return hasDependingPlugins;
}
@ -266,8 +276,8 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
return;
}
WatchResult result = plugin.getWatchManager().watchPlugins(sender, plugins);
result.sendTo(sender);
PluginWatchResults watchResults = plugin.getWatchManager().watchPlugins(sender, plugins);
watchResults.sendTo(sender);
}
private void handleUnwatchPlugin(CommandContext<C> context) {
@ -275,8 +285,8 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
P pluginArg = context.get("plugin");
String pluginId = plugin.getPluginManager().getPluginId(pluginArg);
WatchResult result = plugin.getWatchManager().unwatchPluginsAssociatedWith(pluginId);
result.sendTo(sender);
PluginWatchResults watchResults = plugin.getWatchManager().unwatchPluginsAssociatedWith(pluginId);
watchResults.sendTo(sender);
}
private void handlePluginInfo(CommandContext<C> context) {
@ -286,9 +296,9 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
createInfo(sender, "plugininfo", pluginArg, this::createPluginInfo);
}
protected abstract FormatBuilder createPluginInfo(
FormatBuilder builder,
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
protected abstract KeyValueComponentBuilder createPluginInfo(
KeyValueComponentBuilder builder,
Function<Consumer<ListComponentBuilder<String>>, Component> listBuilderFunction,
P pluginArg
);
@ -297,51 +307,54 @@ public abstract class CommandServerUtils<U extends ServerUtilsPlugin<P, ?, C, ?,
String commandName = context.get("command");
if (!plugin.getPluginManager().getCommands().contains(commandName)) {
plugin.getMessagesResource().sendMessage(sender, "serverutils.commandinfo.not_exists");
plugin.getMessagesResource().get(MessageKey.COMMANDINFO_NOT_EXISTS).sendTo(sender);
return;
}
createInfo(sender, "commandinfo", commandName, this::createCommandInfo);
}
protected abstract FormatBuilder createCommandInfo(
FormatBuilder builder,
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
protected abstract KeyValueComponentBuilder createCommandInfo(
KeyValueComponentBuilder builder,
Function<Consumer<ListComponentBuilder<String>>, Component> listBuilderFunction,
String commandName
);
private <T> void createInfo(C sender, String command, T item, InfoCreator<T> creator) {
String messagePrefix = "serverutils." + command;
String format = plugin.getMessagesResource().getMessage(messagePrefix + ".format");
String listFormatString = plugin.getMessagesResource().getMessage(messagePrefix + ".list_format");
String seperator = plugin.getMessagesResource().getMessage(messagePrefix + ".seperator");
String lastSeperator = plugin.getMessagesResource().getMessage(messagePrefix + ".last_seperator");
MessagesResource messages = plugin.getMessagesResource();
ListFormat<String> listFormat = str -> listFormatString.replace("%value%", str);
String messagePrefix = "messages." + command;
MessagesResource.Message formatMessage = messages.get(messagePrefix + ".format");
MessagesResource.Message listFormatMessage = messages.get(messagePrefix + ".list-format");
Component separator = messages.get(messagePrefix + ".list-separator").toComponent();
Component lastSeparator = messages.get(messagePrefix + ".list-last-separator").toComponent();
TextComponent.Builder builder = Component.text()
.append(messages.get(messagePrefix + ".header").toComponent())
.append(Component.newline());
plugin.getMessagesResource().sendMessage(sender, messagePrefix + ".header");
creator.createInfo(
FormatBuilder
.create(format)
.orderedKeys("%key%", "%value%"),
KeyValueComponentBuilder.create(formatMessage, "key", "value"),
listBuilderConsumer -> {
ListBuilder<String> builder = ListBuilder.<String>create()
.format(listFormat)
.seperator(seperator)
.lastSeperator(lastSeperator);
listBuilderConsumer.accept(builder);
return builder.toString();
ListComponentBuilder<String> listBuilder = ListComponentBuilder.<String>create()
.format(str -> listFormatMessage.toComponent(Template.of("value", str)))
.separator(separator)
.lastSeparator(lastSeparator);
listBuilderConsumer.accept(listBuilder);
return listBuilder.build();
},
item
).build().forEach(str -> plugin.getMessagesResource().sendRawMessage(sender, str));
plugin.getMessagesResource().sendMessage(sender, messagePrefix + ".footer");
);
builder.append(messages.get(messagePrefix + ".footer").toComponent());
sender.sendMessage(builder.build());
}
private interface InfoCreator<T> {
FormatBuilder createInfo(
FormatBuilder builder,
Function<Consumer<ListBuilder<String>>, String> listBuilderFunction,
KeyValueComponentBuilder createInfo(
KeyValueComponentBuilder builder,
Function<Consumer<ListComponentBuilder<String>>, Component> listBuilderFunction,
T item
);
}

View file

@ -12,10 +12,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
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 ServerUtilsAudience<?>> {
protected final U plugin;
protected final String commandName;

View file

@ -11,10 +11,10 @@ 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.ServerUtilsAudience;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
public class JarFilesArgument<C extends ServerCommandSender<?>> extends CommandArgument<C, File[]> {
public class JarFilesArgument<C extends ServerUtilsAudience<?>> extends CommandArgument<C, File[]> {
/**
* Constructs a Jar Files argument.
@ -30,7 +30,7 @@ public class JarFilesArgument<C extends ServerCommandSender<?>> extends CommandA
);
}
public static final class JarFilesParser<C extends ServerCommandSender<?>> implements ArgumentParser<C, File[]> {
public static final class JarFilesParser<C extends ServerUtilsAudience<?>> implements ArgumentParser<C, File[]> {
private final ServerUtilsPlugin<?, ?, C, ?, ?> plugin;

View file

@ -9,10 +9,10 @@ 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.ServerUtilsAudience;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
public class PluginArgument<C extends ServerCommandSender<?>, P> extends CommandArgument<C, P> {
public class PluginArgument<C extends ServerUtilsAudience<?>, P> extends CommandArgument<C, P> {
/**
* Constructs a Plugin argument.
@ -28,7 +28,7 @@ public class PluginArgument<C extends ServerCommandSender<?>, P> extends Command
);
}
public static final class PluginParser<C extends ServerCommandSender<?>, P> implements ArgumentParser<C, P> {
public static final class PluginParser<C extends ServerUtilsAudience<?>, P> implements ArgumentParser<C, P> {
private final ServerUtilsPlugin<P, ?, C, ?, ?> plugin;

View file

@ -12,10 +12,10 @@ 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.ServerUtilsAudience;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
public class PluginsArgument<C extends ServerCommandSender<?>, P> extends CommandArgument<C, P[]> {
public class PluginsArgument<C extends ServerUtilsAudience<?>, P> extends CommandArgument<C, P[]> {
/**
* Constructs a Plugins argument.
@ -35,7 +35,7 @@ public class PluginsArgument<C extends ServerCommandSender<?>, P> extends Comman
);
}
public static final class PluginsParser<C extends ServerCommandSender<?>, P> implements ArgumentParser<C, P[]> {
public static final class PluginsParser<C extends ServerUtilsAudience<?>, P> implements ArgumentParser<C, P[]> {
private final ServerUtilsPlugin<P, ?, C, ?, ?> plugin;
private final IntFunction<P[]> arrayCreator;

View file

@ -5,9 +5,9 @@ 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;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
public class BrigadierHandler<C extends ServerCommandSender<?>, P> {
public class BrigadierHandler<C extends ServerUtilsAudience<?>, P> {
private final CloudBrigadierManager<C, ?> brigadierManager;

View file

@ -0,0 +1,7 @@
package net.frankheijden.serverutils.common.config;
public interface ConfigKey {
String getPath();
}

View file

@ -0,0 +1,89 @@
package net.frankheijden.serverutils.common.config;
import java.util.Locale;
public enum MessageKey implements PlaceholderConfigKey {
RELOAD("reload", false),
LOADPLUGIN("loadplugin"),
UNLOADPLUGIN("unloadplugin"),
RELOADPLUGIN("reloadplugin"),
GENERIC_PREFIX("generic.prefix", false),
GENERIC_ERROR("generic.error", false),
GENERIC_NOT_EXISTS("generic.not-exists"),
GENERIC_NOT_ENABLED("generic.not-enabled"),
GENERIC_ALREADY_LOADED("generic.already-loaded"),
GENERIC_ALREADY_ENABLED("generic.already-enabled"),
GENERIC_ALREADY_DISABLED("generic.already-disabled"),
GENERIC_INVALID_PLUGIN("generic.invalid-plugin"),
GENERIC_INVALID_DESCRIPTION("generic.invalid-description"),
GENERIC_UNKNOWN_DEPENDENCY("generic.unknown-dependency"),
GENERIC_FILE_DELETED("generic.file-deleted"),
DEPENDING_PLUGINS_PREFIX("depending-plugins.prefix"),
DEPENDING_PLUGINS_FORMAT("depending-plugins.format"),
DEPENDING_PLUGINS_SEPARATOR("depending-plugins.separator", false),
DEPENDING_PLUGINS_LAST_SEPARATOR("depending-plugins.last-separator", false),
DEPENDING_PLUGINS_OVERRIDE("depending-plugins.override"),
WATCHPLUGIN_START("watchplugin.start"),
WATCHPLUGIN_CHANGE("watchplugin.change", false),
WATCHPLUGIN_STOPPED("watchplugin.stopped"),
WATCHPLUGIN_FILE_DELETED("watchplugin.file-deleted"),
WATCHPLUGIN_DELETED_FILE_IS_CREATED("watchplugin.deleted-file-is-created"),
WATCHPLUGIN_ALREADY_WATCHING("watchplugin.already-watching"),
WATCHPLUGIN_NOT_WATCHING("watchplugin.not-watching"),
UPDATE_AVAILABLE("update.available"),
UPDATE_DOWNLOADING("update.downloading"),
UPDATE_DOWNLOAD_FAILED("update.download-failed"),
UPDATE_DOWNLOAD_SUCCESS("update.download-success", false),
HELP_HEADER("help.header", false),
HELP_FORMAT("help.format"),
HELP_FOOTER("help.footer", false),
PLUGINS_HEADER("plugins.header", false),
PLUGINS_PREFIX("plugins.prefix"),
PLUGINS_FORMAT("plugins.format"),
PLUGINS_FORMAT_DISABLED("plugins.format-disabled"),
PLUGINS_SEPARATOR("plugins.separator", false),
PLUGINS_LAST_SEPARATOR("plugins.last-separator", false),
PLUGINS_VERSION("plugins.version"),
PLUGINS_FOOTER("plugins.footer", false),
PLUGININFO_HEADER("plugininfo.header", false),
PLUGININFO_FORMAT("plugininfo.format"),
PLUGININFO_LIST_FORMAT("plugininfo.list-format"),
PLUGININFO_LIST_SEPARATOR("plugininfo.list-separator", false),
PLUGININFO_LIST_LAST_SEPARATOR("plugininfo.list-last-separator", false),
PLUGININFO_FOOTER("plugininfo.footer", false),
COMMANDINFO_HEADER("commandinfo.header", false),
COMMANDINFO_FORMAT("commandinfo.format"),
COMMANDINFO_LIST_FORMAT("commandinfo.list-format"),
COMMANDINFO_LIST_SEPARATOR("commandinfo.list-separator", false),
COMMANDINFO_LIST_LAST_SEPARATOR("commandinfo.list-last-separator", false),
COMMANDINFO_FOOTER("commandinfo.footer", false),
COMMANDINFO_NOT_EXISTS("commandinfo.not-exists", false),
;
private final String path;
private final boolean hasPlaceholders;
MessageKey(String path) {
this(path, true);
}
MessageKey(String path, boolean hasPlaceholders) {
this.path = path;
this.hasPlaceholders = hasPlaceholders;
}
public static MessageKey fromPath(String path) {
return MessageKey.valueOf(path.replaceAll("\\.|-", "_").toUpperCase(Locale.ENGLISH));
}
@Override
public String getPath() {
return path;
}
@Override
public boolean hasPlaceholders() {
return hasPlaceholders;
}
}

View file

@ -1,56 +1,83 @@
package net.frankheijden.serverutils.common.config;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
import net.frankheijden.serverutils.common.utils.StringUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.minimessage.Template;
public class MessagesResource extends ServerUtilsResource {
public static final String MESSAGES_RESOURCE = "messages";
private final Map<ConfigKey, Message> messageMap;
private final MiniMessage miniMessage;
/**
* Constructs a new MessagesResource.
*/
public MessagesResource(ServerUtilsPlugin<?, ?, ?, ?, ?> plugin) {
super(plugin, MESSAGES_RESOURCE);
this.messageMap = new HashMap<>();
this.miniMessage = MiniMessage.get();
}
public Message get(String path) {
return get(MessageKey.fromPath(path));
}
public Message get(ConfigKey key) {
return messageMap.get(key);
}
/**
* Retrieves a message from the config.
* @param path The yml path to the message.
* @param replacements The replacements to be taken into account.
* @return The config message with translated placeholders.
* Loads message keys and pre-compiles them if possible.
*/
public String getMessage(String path, String... replacements) {
String message = config.getString(path);
if (message != null) {
return StringUtils.apply(message, replacements);
} else {
plugin.getLogger().severe("Missing locale in messages.yml at path '" + path + "'!");
}
return null;
}
/**
* Sends a message to a player with translated placeholders.
* @param sender The receiver.
* @param msg The message to be sent.
* @param replacements The replacements to be taken into account.
*/
public void sendRawMessage(ServerCommandSender<?> sender, String msg, String... replacements) {
String message = StringUtils.apply(msg, replacements);
if (message != null) {
sender.sendMessage(plugin.getChatProvider().color(message));
public void load(Collection<? extends PlaceholderConfigKey> keys) {
for (PlaceholderConfigKey key : keys) {
this.messageMap.put(key, new Message(key));
}
}
/**
* Sends a message from the specified config path to a player with translated placeholders.
* @param sender The receiver.
* @param path The yml path to the message.
* @param replacements The replacements to be taken into account.
*/
public void sendMessage(ServerCommandSender<?> sender, String path, String... replacements) {
String message = getMessage(path, replacements);
if (message != null) {
sender.sendMessage(plugin.getChatProvider().color(message));
public class Message {
private final PlaceholderConfigKey key;
private final String messageString;
private final Component component;
/**
* Constructs a new Message.
*/
public Message(PlaceholderConfigKey key) {
this.key = key;
this.messageString = getConfig().getString("messages." + key.getPath());
this.component = key.hasPlaceholders() ? null : miniMessage.parse(messageString);
}
/**
* Creates a {@link Component}.
*/
public Component toComponent(Template... placeholders) {
if (this.component == null) {
if (placeholders.length == 0) {
throw new IllegalArgumentException("Message '" + key + "' has placeholders"
+ " but none were provided!");
}
return miniMessage.parse(messageString, placeholders);
} else if (placeholders.length != 0) {
throw new IllegalArgumentException("Message '" + key + "' does not have placeholders"
+ " but the following placeholders were provided: " + Arrays.toString(placeholders));
} else {
return this.component;
}
}
public void sendTo(ServerUtilsAudience<?> serverAudience, Template... placeholders) {
serverAudience.sendMessage(toComponent(placeholders));
}
}

View file

@ -0,0 +1,7 @@
package net.frankheijden.serverutils.common.config;
public interface PlaceholderConfigKey extends ConfigKey {
boolean hasPlaceholders();
}

View file

@ -1,31 +0,0 @@
package net.frankheijden.serverutils.common.entities;
/**
* A basic wrapper for a CommandSender.
*/
public interface ServerCommandSender<C> {
/**
* Sends a message to a CommandSender.
* @param message The message to send.
*/
void sendMessage(String message);
/**
* Checks if the CommandSender has a permission.
* @param permission The permission to check.
* @return Whether or not they have the permission.
*/
boolean hasPermission(String permission);
/**
* Whether or not the given instance is a player.
* @return Boolean true or false.
*/
boolean isPlayer();
/**
* Returns the server specific implementation source.
*/
C getSource();
}

View file

@ -0,0 +1,27 @@
package net.frankheijden.serverutils.common.entities;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
public abstract class ServerUtilsAudience<C> {
protected final Audience audience;
protected final C source;
protected ServerUtilsAudience(Audience audience, C source) {
this.audience = audience;
this.source = source;
}
public abstract boolean isPlayer();
public abstract boolean hasPermission(String permission);
public void sendMessage(Component component) {
audience.sendMessage(component);
}
public C getSource() {
return this.source;
}
}

View file

@ -7,28 +7,30 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.logging.Logger;
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.ConfigResource;
import net.frankheijden.serverutils.common.config.MessageKey;
import net.frankheijden.serverutils.common.config.MessagesResource;
import net.frankheijden.serverutils.common.managers.AbstractPluginManager;
import net.frankheijden.serverutils.common.managers.AbstractTaskManager;
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.ResourceProvider;
import net.frankheijden.serverutils.common.providers.ServerUtilsAudienceProvider;
import net.frankheijden.serverutils.common.utils.FileUtils;
public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>, S, D extends ServerUtilsPluginDescription> {
public abstract class ServerUtilsPlugin<P, T, C extends ServerUtilsAudience<S>, S, D extends ServerUtilsPluginDescription> {
private final UpdateManager updateManager = new UpdateManager();
private final WatchManager<P, T> watchManager = new WatchManager<>(this);
private CommandsResource commandsResource;
private ConfigResource configResource;
private MessagesResource messagesResource;
protected MessagesResource messagesResource;
protected CommandManager<C> commandManager;
public abstract Platform getPlatform();
@ -53,7 +55,7 @@ public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>,
public abstract ResourceProvider getResourceProvider();
public abstract ChatProvider<C, S> getChatProvider();
public abstract ServerUtilsAudienceProvider<S> getChatProvider();
public UpdateManager getUpdateManager() {
return updateManager;
@ -143,6 +145,7 @@ public abstract class ServerUtilsPlugin<P, T, C extends ServerCommandSender<S>,
this.commandsResource = new CommandsResource(this);
this.configResource = new ConfigResource(this);
this.messagesResource = new MessagesResource(this);
this.messagesResource.load(Arrays.asList(MessageKey.values()));
this.commandManager = newCommandManager();
reloadPlugin();
}

View file

@ -1,15 +1,9 @@
package net.frankheijden.serverutils.common.entities.results;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.config.ConfigKey;
public interface AbstractResult {
/**
* 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.
*/
void sendTo(ServerCommandSender<?> sender, String action, String what);
ConfigKey getKey();
}

View file

@ -4,6 +4,7 @@ import java.io.Closeable;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import net.kyori.adventure.text.minimessage.Template;
public class CloseablePluginResult<T> extends PluginResult<T> implements Closeable {
@ -14,8 +15,14 @@ public class CloseablePluginResult<T> extends PluginResult<T> implements Closeab
this.closeables = Collections.emptyList();
}
public CloseablePluginResult(String pluginId, T plugin, Result result, List<Closeable> closeables) {
super(pluginId, plugin, result);
public CloseablePluginResult(
String pluginId,
T plugin,
Result result,
List<Closeable> closeables,
Template... templates
) {
super(pluginId, plugin, result, templates);
this.closeables = closeables;
}

View file

@ -3,6 +3,7 @@ package net.frankheijden.serverutils.common.entities.results;
import java.io.Closeable;
import java.io.IOException;
import java.util.List;
import net.kyori.adventure.text.minimessage.Template;
public class CloseablePluginResults<T> extends PluginResults<T> implements Closeable {
@ -16,25 +17,31 @@ public class CloseablePluginResults<T> extends PluginResults<T> implements Close
}
@Override
public CloseablePluginResults<T> addResult(String pluginId, Result result) {
super.addResult(pluginId, result);
public CloseablePluginResults<T> addResult(String pluginId, Result result, Template... templates) {
super.addResult(pluginId, result, templates);
return this;
}
@Override
public CloseablePluginResults<T> addResult(String pluginId, T plugin) {
super.addResult(pluginId, plugin);
public CloseablePluginResults<T> addResult(String pluginId, T plugin, Template... templates) {
super.addResult(pluginId, plugin, templates);
return this;
}
@Override
protected CloseablePluginResults<T> addResult(String pluginId, T plugin, Result result) {
super.addResult(pluginId, plugin, result);
protected CloseablePluginResults<T> addResult(String pluginId, T plugin, Result result, Template... templates
) {
super.addResult(pluginId, plugin, result, templates);
return this;
}
public CloseablePluginResults<T> addResult(String pluginId, T plugin, List<Closeable> closeables) {
return addResult(new CloseablePluginResult<>(pluginId, plugin, Result.SUCCESS, closeables));
public CloseablePluginResults<T> addResult(
String pluginId,
T plugin,
List<Closeable> closeables,
Template... templates
) {
return addResult(new CloseablePluginResult<>(pluginId, plugin, Result.SUCCESS, closeables, templates));
}
@Override

View file

@ -1,10 +1,16 @@
package net.frankheijden.serverutils.common.entities.results;
public class PluginResult<T> {
import net.frankheijden.serverutils.common.ServerUtilsApp;
import net.frankheijden.serverutils.common.config.ConfigKey;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.Template;
public class PluginResult<T> implements AbstractResult {
private final String pluginId;
private final T plugin;
private final Result result;
private final Template[] templates;
public PluginResult(String pluginId, Result result) {
this(pluginId, null, result);
@ -13,10 +19,13 @@ public class PluginResult<T> {
/**
* Constructs a new PluginResult.
*/
public PluginResult(String pluginId, T plugin, Result result) {
public PluginResult(String pluginId, T plugin, Result result, Template... templates) {
this.pluginId = pluginId;
this.plugin = plugin;
this.result = result;
this.templates = new Template[templates.length + 1];
this.templates[0] = Template.of("plugin", pluginId);
System.arraycopy(templates, 0, this.templates, 1, templates.length);
}
public String getPluginId() {
@ -31,7 +40,21 @@ public class PluginResult<T> {
return result;
}
public Template[] getTemplates() {
return templates;
}
public boolean isSuccess() {
return plugin != null && result == Result.SUCCESS;
}
public Component toComponent(ConfigKey successKey) {
ConfigKey key = isSuccess() ? successKey : result.getKey();
return ServerUtilsApp.getPlugin().getMessagesResource().get(key).toComponent(templates);
}
@Override
public ConfigKey getKey() {
return result.getKey();
}
}

View file

@ -3,7 +3,10 @@ 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;
import net.frankheijden.serverutils.common.config.ConfigKey;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.minimessage.Template;
public class PluginResults<T> implements Iterable<PluginResult<T>> {
@ -13,18 +16,18 @@ public class PluginResults<T> implements Iterable<PluginResult<T>> {
this.results = new ArrayList<>();
}
public PluginResults<T> addResult(String pluginId, Result result) {
addResult(pluginId, null, result);
public PluginResults<T> addResult(String pluginId, Result result, Template... templates) {
addResult(pluginId, null, result, templates);
return this;
}
public PluginResults<T> addResult(String pluginId, T plugin) {
addResult(pluginId, plugin, Result.SUCCESS);
public PluginResults<T> addResult(String pluginId, T plugin, Template... templates) {
addResult(pluginId, plugin, Result.SUCCESS, templates);
return this;
}
protected PluginResults<T> addResult(String pluginId, T plugin, Result result) {
addResult(new PluginResult<>(pluginId, plugin, result));
protected PluginResults<T> addResult(String pluginId, T plugin, Result result, Template... templates) {
addResult(new PluginResult<>(pluginId, plugin, result, templates));
return this;
}
@ -65,12 +68,14 @@ public class PluginResults<T> implements Iterable<PluginResult<T>> {
}
/**
* Sends the results to given receiver.
* Creates a {@link Component}.
*/
public void sendTo(ServerCommandSender<?> sender, String action) {
public Component toComponent(ConfigKey successKey) {
TextComponent.Builder builder = Component.text();
for (PluginResult<T> result : results) {
result.getResult().sendTo(sender, action, result.getPluginId());
builder.append(result.toComponent(successKey));
}
return builder.build();
}
@Override

View file

@ -0,0 +1,28 @@
package net.frankheijden.serverutils.common.entities.results;
import net.frankheijden.serverutils.common.config.ConfigKey;
import net.kyori.adventure.text.minimessage.Template;
public class PluginWatchResult implements AbstractResult {
private final WatchResult result;
private final Template[] templates;
public PluginWatchResult(WatchResult result, Template... templates) {
this.result = result;
this.templates = templates;
}
public WatchResult getResult() {
return result;
}
public Template[] getTemplates() {
return templates;
}
@Override
public ConfigKey getKey() {
return null;
}
}

View file

@ -0,0 +1,47 @@
package net.frankheijden.serverutils.common.entities.results;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.frankheijden.serverutils.common.ServerUtilsApp;
import net.frankheijden.serverutils.common.config.MessagesResource;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.minimessage.Template;
public class PluginWatchResults implements Iterable<PluginWatchResult> {
private final List<PluginWatchResult> watchResults;
public PluginWatchResults() {
this.watchResults = new ArrayList<>();
}
public PluginWatchResults add(WatchResult result, Template... templates) {
return add(new PluginWatchResult(result, templates));
}
public PluginWatchResults add(PluginWatchResult watchResult) {
this.watchResults.add(watchResult);
return this;
}
/**
* Sends the result(s) to the given sender.
*/
public void sendTo(ServerUtilsAudience<?> sender) {
MessagesResource messages = ServerUtilsApp.getPlugin().getMessagesResource();
TextComponent.Builder builder = Component.text();
for (PluginWatchResult watchResult : watchResults) {
builder.append(messages.get(watchResult.getKey()).toComponent(watchResult.getTemplates()));
}
sender.sendMessage(builder.build());
}
@Override
public Iterator<PluginWatchResult> iterator() {
return watchResults.iterator();
}
}

View file

@ -1,58 +1,31 @@
package net.frankheijden.serverutils.common.entities.results;
import net.frankheijden.serverutils.common.ServerUtilsApp;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.config.MessageKey;
/**
* An enum containing possible results.
*/
public enum Result implements AbstractResult {
NOT_EXISTS,
NOT_ENABLED,
ALREADY_LOADED,
ALREADY_ENABLED,
ALREADY_DISABLED,
FILE_DELETED,
INVALID_DESCRIPTION,
INVALID_PLUGIN,
UNKNOWN_DEPENDENCY,
ERROR,
SUCCESS;
NOT_EXISTS(MessageKey.GENERIC_NOT_EXISTS),
NOT_ENABLED(MessageKey.GENERIC_NOT_ENABLED),
ALREADY_LOADED(MessageKey.GENERIC_ALREADY_LOADED),
ALREADY_ENABLED(MessageKey.GENERIC_ALREADY_ENABLED),
ALREADY_DISABLED(MessageKey.GENERIC_ALREADY_DISABLED),
FILE_DELETED(MessageKey.GENERIC_FILE_DELETED),
INVALID_DESCRIPTION(MessageKey.GENERIC_INVALID_DESCRIPTION),
INVALID_PLUGIN(MessageKey.GENERIC_INVALID_PLUGIN),
UNKNOWN_DEPENDENCY(MessageKey.GENERIC_UNKNOWN_DEPENDENCY),
ERROR(MessageKey.GENERIC_ERROR),
SUCCESS(null),
;
private String arg;
private final MessageKey key;
/**
* private constructor which initializes a result with an empty argument.
*/
Result() {
this.arg = "";
Result(MessageKey key) {
this.key = key;
}
/**
* Sets the argument of the result's message.
* @param arg The argument
* @return The current instance.
*/
public Result arg(String arg) {
this.arg = arg;
return this;
}
/**
* 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." + this.name().toLowerCase(),
"%action%", action,
"%what%", what,
"%arg%", arg
);
public MessageKey getKey() {
return key;
}
}

View file

@ -1,60 +1,35 @@
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;
import net.frankheijden.serverutils.common.config.ConfigKey;
import net.frankheijden.serverutils.common.config.MessageKey;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.Template;
public enum WatchResult implements AbstractResult {
START(MessageKey.WATCHPLUGIN_START),
CHANGE(MessageKey.WATCHPLUGIN_CHANGE),
ALREADY_WATCHING(MessageKey.WATCHPLUGIN_ALREADY_WATCHING),
NOT_WATCHING(MessageKey.WATCHPLUGIN_NOT_WATCHING),
FILE_DELETED(MessageKey.WATCHPLUGIN_FILE_DELETED),
DELETED_FILE_IS_CREATED(MessageKey.WATCHPLUGIN_DELETED_FILE_IS_CREATED),
STOPPED(MessageKey.WATCHPLUGIN_STOPPED),
;
START,
CHANGE,
ALREADY_WATCHING,
NOT_WATCHING,
FILE_DELETED,
DELETED_FILE_IS_CREATED,
STOPPED;
private final ConfigKey key;
private List<String> args = null;
public WatchResult arg(String arg) {
return args(Collections.singletonList(arg));
WatchResult(ConfigKey key) {
this.key = key;
}
public WatchResult args(List<String> args) {
this.args = args;
return this;
public void sendTo(ServerUtilsAudience<?> sender, Template... templates) {
Component component = ServerUtilsApp.getPlugin().getMessagesResource().get(key).toComponent(templates);
sender.sendMessage(component);
}
@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);
}
}
public ConfigKey getKey() {
return key;
}
}

View file

@ -1,10 +1,10 @@
package net.frankheijden.serverutils.common.listeners;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
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 ServerUtilsAudience<?>>
extends ServerUtilsListener<U, C> {
protected PlayerListener(U plugin) {

View file

@ -1,9 +1,9 @@
package net.frankheijden.serverutils.common.listeners;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
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 ServerUtilsAudience<?>> {
protected final U plugin;

View file

@ -5,10 +5,12 @@ 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.ServerUtilsAudience;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
import net.frankheijden.serverutils.common.entities.results.PluginWatchResults;
import net.frankheijden.serverutils.common.entities.results.WatchResult;
import net.frankheijden.serverutils.common.tasks.PluginWatcherTask;
import net.kyori.adventure.text.minimessage.Template;
public class WatchManager<P, T> {
@ -23,12 +25,12 @@ public class WatchManager<P, T> {
/**
* Starts watching the specified plugin and reloads it when a change is detected.
*/
public WatchResult watchPlugins(ServerCommandSender<?> sender, List<P> plugins) {
public PluginWatchResults watchPlugins(ServerUtilsAudience<?> 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);
return new PluginWatchResults().add(WatchResult.ALREADY_WATCHING, Template.of("plugin", pluginId));
}
pluginIds.add(plugin.getPluginManager().getPluginId(watchPlugin));
@ -45,19 +47,28 @@ public class WatchManager<P, T> {
watchTasks.put(pluginId, watchTask);
}
return WatchResult.START.args(pluginIds);
PluginWatchResults watchResults = new PluginWatchResults();
for (String pluginId : pluginIds) {
watchResults.add(WatchResult.START, Template.of("plugin", pluginId));
}
return watchResults;
}
/**
* Stops watching plugins for changes.
*/
public WatchResult unwatchPluginsAssociatedWith(String pluginId) {
WatchTask task = watchTasks.get(pluginId);
public PluginWatchResults unwatchPluginsAssociatedWith(String associatedPluginId) {
WatchTask task = watchTasks.get(associatedPluginId);
if (task != null && plugin.getTaskManager().cancelTask(task.key.toString())) {
task.pluginIds.forEach(watchTasks::remove);
return WatchResult.STOPPED.args(task.pluginIds);
PluginWatchResults watchResults = new PluginWatchResults();
for (String pluginId : task.pluginIds) {
watchResults.add(WatchResult.START, Template.of("plugin", pluginId));
}
return watchResults;
}
return WatchResult.NOT_WATCHING.arg(pluginId);
return new PluginWatchResults().add(WatchResult.NOT_WATCHING, Template.of("plugin", associatedPluginId));
}
private static final class WatchTask {

View file

@ -1,34 +0,0 @@
package net.frankheijden.serverutils.common.providers;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
/**
* A basic chat provider class.
*/
public interface ChatProvider<C extends ServerCommandSender<T>, T> {
/**
* Retrieves the console sender of a server instance.
* @return The console sender.
*/
C getConsoleSender();
/**
* Converts the given source (specific to impl) to a ServerCommandSender.
*/
C get(T source);
/**
* Colorizes the given string.
* @param str The string to color.
* @return The colored string.
*/
String color(String str);
/**
* Broadcasts a message over a server instance.
* @param permission The permission the receivers need to have.
* @param message The message to broadcast.
*/
void broadcast(String permission, String message);
}

View file

@ -0,0 +1,22 @@
package net.frankheijden.serverutils.common.providers;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
import net.kyori.adventure.text.Component;
public interface ServerUtilsAudienceProvider<S> {
/**
* Retrieves the console ServerAudience.
*/
ServerUtilsAudience<S> getConsoleServerAudience();
/**
* Converts the given source (specific to impl) to an ServerAudience.
*/
ServerUtilsAudience<S> get(S source);
/**
* Broadcasts a message to all with given permission.
*/
void broadcast(Component component, String permission);
}

View file

@ -17,8 +17,9 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import net.frankheijden.serverutils.common.config.MessageKey;
import net.frankheijden.serverutils.common.entities.AbstractTask;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
import net.frankheijden.serverutils.common.entities.ServerUtilsPluginDescription;
import net.frankheijden.serverutils.common.entities.exceptions.InvalidPluginDescriptionException;
@ -27,6 +28,7 @@ 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;
import net.kyori.adventure.text.minimessage.Template;
public class PluginWatcherTask<P, T> extends AbstractTask {
@ -37,7 +39,7 @@ public class PluginWatcherTask<P, T> extends AbstractTask {
};
private final ServerUtilsPlugin<P, T, ?, ?, ?> plugin;
private final ServerCommandSender<?> sender;
private final ServerUtilsAudience<?> sender;
private final Map<String, WatchEntry> fileNameToWatchEntryMap;
private final Map<String, WatchEntry> pluginIdToWatchEntryMap;
@ -48,7 +50,7 @@ public class PluginWatcherTask<P, T> extends AbstractTask {
/**
* Constructs a new PluginWatcherTask for the specified plugin.
*/
public PluginWatcherTask(ServerUtilsPlugin<P, T, ?, ?, ?> plugin, ServerCommandSender<?> sender, List<P> plugins) {
public PluginWatcherTask(ServerUtilsPlugin<P, T, ?, ?, ?> plugin, ServerUtilsAudience<?> sender, List<P> plugins) {
this.plugin = plugin;
this.sender = sender;
this.fileNameToWatchEntryMap = new HashMap<>();
@ -114,7 +116,7 @@ public class PluginWatcherTask<P, T> extends AbstractTask {
ServerUtilsPluginDescription description = descriptionOptional.get();
WatchEntry foundEntry = pluginIdToWatchEntryMap.remove(description.getId());
if (foundEntry != null) {
send(WatchResult.DELETED_FILE_IS_CREATED.arg(foundEntry.pluginId));
send(WatchResult.DELETED_FILE_IS_CREATED, Template.of("plugin", foundEntry.pluginId));
fileNameToWatchEntryMap.put(fileName, foundEntry);
if (pluginIdToWatchEntryMap.isEmpty()) {
@ -137,7 +139,7 @@ public class PluginWatcherTask<P, T> extends AbstractTask {
AbstractPluginManager<P, ?> pluginManager = plugin.getPluginManager();
Optional<File> fileOptional = pluginManager.getPluginFile(entry.pluginId);
if (!fileOptional.isPresent()) {
send(WatchResult.FILE_DELETED.arg(entry.pluginId));
send(WatchResult.FILE_DELETED, Template.of("plugin", entry.pluginId));
fileNameToWatchEntryMap.remove(fileName);
pluginIdToWatchEntryMap.put(entry.pluginId, entry);
@ -165,7 +167,7 @@ public class PluginWatcherTask<P, T> extends AbstractTask {
fileNameToWatchEntryMap.clear();
PluginResults<P> reloadResults = pluginManager.reloadPlugins(plugins);
reloadResults.sendTo(sender, "reload");
sender.sendMessage(reloadResults.toComponent(MessageKey.RELOADPLUGIN));
for (PluginResult<P> reloadResult : reloadResults) {
if (!reloadResult.isSuccess()) continue;
@ -181,10 +183,10 @@ public class PluginWatcherTask<P, T> extends AbstractTask {
}, 10L);
}
private void send(WatchResult result) {
result.sendTo(sender);
private void send(WatchResult result, Template... templates) {
result.sendTo(sender, templates);
if (sender.isPlayer()) {
result.sendTo(plugin.getChatProvider().getConsoleSender());
result.sendTo(plugin.getChatProvider().getConsoleServerAudience(), templates);
}
}

View file

@ -10,10 +10,12 @@ import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.logging.Level;
import net.frankheijden.serverutils.common.ServerUtilsApp;
import net.frankheijden.serverutils.common.config.ConfigKey;
import net.frankheijden.serverutils.common.config.MessageKey;
import net.frankheijden.serverutils.common.config.ServerUtilsConfig;
import net.frankheijden.serverutils.common.entities.results.PluginResult;
import net.frankheijden.serverutils.common.entities.results.Result;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
import net.frankheijden.serverutils.common.entities.http.GitHubAsset;
import net.frankheijden.serverutils.common.entities.http.GitHubResponse;
@ -21,11 +23,13 @@ import net.frankheijden.serverutils.common.managers.UpdateManager;
import net.frankheijden.serverutils.common.utils.GitHubUtils;
import net.frankheijden.serverutils.common.utils.VersionUtils;
import net.frankheijden.serverutilsupdater.common.Updater;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.Template;
public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> implements Runnable {
private final U plugin;
private final ServerCommandSender<?> sender;
private final ServerUtilsAudience<?> sender;
private final boolean download;
private final boolean install;
@ -49,7 +53,7 @@ public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> im
private static final String UPDATER_ENABLE_ERROR = "Failed to enable ServerUtilsUpdater: {0}";
private static final String UP_TO_DATE = "We are up-to-date!";
private UpdateCheckerTask(U plugin, ServerCommandSender<?> sender, boolean download, boolean install) {
private UpdateCheckerTask(U plugin, ServerUtilsAudience<?> sender, boolean download, boolean install) {
this.plugin = plugin;
this.sender = sender;
this.download = download;
@ -62,7 +66,7 @@ public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> im
*/
public static <U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> void tryStart(
U plugin,
ServerCommandSender<?> sender,
ServerUtilsAudience<?> sender,
String action
) {
ServerUtilsConfig config = ServerUtilsApp.getPlugin().getConfigResource().getConfig();
@ -77,7 +81,7 @@ public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> im
*/
public static <U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> void start(
U plugin,
ServerCommandSender<?> sender,
ServerUtilsAudience<?> sender,
String action
) {
ServerUtilsConfig config = ServerUtilsApp.getPlugin().getConfigResource().getConfig();
@ -121,20 +125,24 @@ public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> im
GitHubAsset pluginAsset = GitHubAsset.from(pluginJson);
if (!download || pluginAsset == null) {
if (sender.isPlayer()) {
plugin.getMessagesResource().sendMessage(sender, "serverutils.update.available",
"%old%", ServerUtilsApp.VERSION,
"%new%", githubVersion,
"%info%", body);
Component component = plugin.getMessagesResource().get(MessageKey.UPDATE_AVAILABLE).toComponent(
Template.of("old", ServerUtilsApp.VERSION),
Template.of("new", githubVersion),
Template.of("info", body)
);
sender.sendMessage(component);
}
return;
}
plugin.getLogger().log(Level.INFO, DOWNLOAD_START, pluginAsset.getDownloadUrl());
if (sender.isPlayer()) {
plugin.getMessagesResource().sendMessage(sender, "serverutils.update.downloading",
"%old%", ServerUtilsApp.VERSION,
"%new%", githubVersion,
"%info%", body);
Component component = plugin.getMessagesResource().get(MessageKey.UPDATE_DOWNLOADING).toComponent(
Template.of("old", ServerUtilsApp.VERSION),
Template.of("new", githubVersion),
Template.of("info", body)
);
sender.sendMessage(component);
}
File pluginTarget = new File(plugin.getPluginManager().getPluginsFolder(), pluginAsset.getName());
@ -260,8 +268,8 @@ public class UpdateCheckerTask<U extends ServerUtilsPlugin<P, ?, ?, ?, ?>, P> im
}
private void broadcastDownloadStatus(String githubVersion, boolean isError) {
final String path = "serverutils.update." + (isError ? "failed" : "success");
String message = plugin.getMessagesResource().getMessage(path, "%new%", githubVersion);
plugin.getChatProvider().broadcast("serverutils.notification.update", message);
ConfigKey key = isError ? MessageKey.UPDATE_DOWNLOAD_FAILED : MessageKey.UPDATE_DOWNLOAD_SUCCESS;
Component component = plugin.getMessagesResource().get(key).toComponent(Template.of("new", githubVersion));
plugin.getChatProvider().broadcast(component, "serverutils.notification.update");
}
}

View file

@ -1,63 +0,0 @@
package net.frankheijden.serverutils.common.utils;
import java.util.ArrayList;
import java.util.List;
public class FormatBuilder {
private final String format;
private final List<String[]> valueList;
private String[] orderedKeys;
private boolean skipEmpty;
private FormatBuilder(String format) {
this.format = format;
this.valueList = new ArrayList<>();
this.orderedKeys = new String[0];
this.skipEmpty = true;
}
public static FormatBuilder create(String format) {
return new FormatBuilder(format);
}
public FormatBuilder orderedKeys(String... orderedKeys) {
this.orderedKeys = orderedKeys;
return this;
}
public FormatBuilder add(String... values) {
this.valueList.add(values);
return this;
}
public FormatBuilder skipEmpty(boolean skipEmpty) {
this.skipEmpty = skipEmpty;
return this;
}
/**
* Builds the current FormatBuilder instance into a list of strings.
*/
public List<String> build() {
List<String> strings = new ArrayList<>();
loop:
for (String[] values : valueList) {
String str = format;
for (int i = 0; i < Math.min(values.length, orderedKeys.length); i++) {
String value = values[i];
if ((value == null || value.isEmpty()) && skipEmpty) continue loop;
str = str.replace(orderedKeys[i], String.valueOf(value));
}
strings.add(str);
}
return strings;
}
@Override
public String toString() {
return build().toString();
}
}

View file

@ -2,14 +2,15 @@ package net.frankheijden.serverutils.common.utils;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.providers.ChatProvider;
import net.frankheijden.serverutils.common.entities.ServerUtilsAudience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
public class ForwardFilter extends PredicateFilter {
private static final char INFO_COLOR = 'a';
private static final char WARNING_COLOR = '6';
private static final char SEVERE_COLOR = 'c';
private static final NamedTextColor INFO_COLOR = NamedTextColor.GREEN;
private static final NamedTextColor WARNING_COLOR = NamedTextColor.GOLD;
private static final NamedTextColor SEVERE_COLOR = NamedTextColor.RED;
private boolean warnings;
@ -17,13 +18,13 @@ public class ForwardFilter extends PredicateFilter {
* Creates a filter which forwards all output to the sender.
* @param sender The sender to forward logs to.
*/
public ForwardFilter(ChatProvider chatProvider, ServerCommandSender sender) {
public ForwardFilter(ServerUtilsAudience<?> sender) {
this.warnings = false;
setPredicate(rec -> {
char color = getColor(rec.getLevel());
NamedTextColor color = getColor(rec.getLevel());
if (color != INFO_COLOR) warnings = true;
sender.sendMessage(chatProvider.color("&" + color + format(rec)));
sender.sendMessage(Component.text(format(rec), color));
return true;
});
}
@ -32,7 +33,7 @@ public class ForwardFilter extends PredicateFilter {
return warnings;
}
private static char getColor(Level level) {
private static NamedTextColor getColor(Level level) {
if (Level.SEVERE.equals(level)) {
return SEVERE_COLOR;
} else if (Level.WARNING.equals(level)) {

View file

@ -1,43 +0,0 @@
package net.frankheijden.serverutils.common.utils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Provides basic conversion between the hex format <#FFFFFF> and bukkit hex format &x&F&F&F&F&F&F.
*/
public class HexUtils {
private static final Pattern hexPattern = Pattern.compile("<(#[0-9a-fA-F]{6})>");
private static final char COLOR_CHAR = '&';
/**
* Prefixes each character provided with the color character {@link #COLOR_CHAR}.
* @param color The color to prefix with the color character.
* @return The prefixed color.
*/
public static String convertHexColor(String color) {
StringBuilder sb = new StringBuilder(2 * (color.length() + 1)).append(COLOR_CHAR).append("x");
for (char c : color.toCharArray()) {
sb.append(COLOR_CHAR).append(c);
}
return sb.toString();
}
/**
* Converts the input string to a bukkit readable color string.
* The accepted hex format is `<#FFFFFF>`.
* @param str The input string.
* @return The output converted hex string.
*/
public static String convertHexString(String str) {
StringBuffer sb = new StringBuffer(str.length());
Matcher matcher = hexPattern.matcher(str);
while (matcher.find()) {
String hex = matcher.group();
matcher.appendReplacement(sb, convertHexColor(hex.substring(2, hex.length() - 1)));
}
matcher.appendTail(sb);
return sb.toString();
}
}

View file

@ -0,0 +1,95 @@
package net.frankheijden.serverutils.common.utils;
import java.util.ArrayList;
import java.util.List;
import net.frankheijden.serverutils.common.config.MessagesResource;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.minimessage.Template;
public class KeyValueComponentBuilder {
private final MessagesResource.Message format;
private final List<Template[]> templatesList;
private final String keyPlaceholder;
private final String valuePlaceholder;
private KeyValueComponentBuilder(
MessagesResource.Message format,
String keyPlaceholder,
String valuePlaceholder
) {
this.format = format;
this.templatesList = new ArrayList<>();
this.keyPlaceholder = keyPlaceholder;
this.valuePlaceholder = valuePlaceholder;
}
/**
* Constructs a new KeyValueComponentBuilder.
*/
public static KeyValueComponentBuilder create(
MessagesResource.Message format,
String keyPlaceholder,
String valuePlaceholder
) {
return new KeyValueComponentBuilder(format, keyPlaceholder, valuePlaceholder);
}
/**
* Adds an entry.
*/
public KeyValueComponentBuilder add(String key, String value) {
if (value != null) this.templatesList.add(new Template[]{
Template.of(keyPlaceholder, key),
Template.of(valuePlaceholder, value)
});
return this;
}
/**
* Adds an entry.
*/
public KeyValueComponentBuilder add(String key, Component value) {
if (value != null) this.templatesList.add(new Template[]{
Template.of(keyPlaceholder, key),
Template.of(valuePlaceholder, value)
});
return this;
}
/**
* Adds an entry.
*/
public KeyValueComponentBuilder add(Component key, String value) {
if (value != null) this.templatesList.add(new Template[]{
Template.of(keyPlaceholder, key),
Template.of(valuePlaceholder, value)
});
return this;
}
/**
* Adds an entry.
*/
public KeyValueComponentBuilder add(Component key, Component value) {
if (value != null) this.templatesList.add(new Template[]{
Template.of(keyPlaceholder, key),
Template.of(valuePlaceholder, value)
});
return this;
}
/**
* Builds the current ListMessageBuilder instance into a Component.
*/
public Component build() {
TextComponent.Builder builder = Component.text();
for (Template[] templates : templatesList) {
builder.append(format.toComponent(templates));
}
return builder.build();
}
}

View file

@ -1,80 +0,0 @@
package net.frankheijden.serverutils.common.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class ListBuilder<T> {
private final List<T> list;
private ListFormat<T> formatter;
private String seperator;
private String lastSeperator;
private ListBuilder() {
this.list = new ArrayList<>();
}
public static <T> ListBuilder<T> create(Collection<? extends T> list) {
return new ListBuilder<T>().addAll(list);
}
@SafeVarargs
public static <T> ListBuilder<T> create(T... elements) {
return new ListBuilder<T>().addAll(Arrays.asList(elements));
}
/**
* Creates a pre-defined ListBuilder with type String.
* @param list The collection to be used.
* @return The ListBuilder.
*/
@SuppressWarnings("unchecked")
public static ListBuilder<String> createStrings(List<? extends String> list) {
ListBuilder<String> builder = create((List<String>) list);
builder.format(ListFormat.stringFormat);
return builder;
}
public ListBuilder<T> format(ListFormat<T> formatter) {
this.formatter = formatter;
return this;
}
public ListBuilder<T> seperator(String seperator) {
this.seperator = seperator;
return this;
}
public ListBuilder<T> lastSeperator(String lastSeperator) {
this.lastSeperator = lastSeperator;
return this;
}
public ListBuilder<T> addAll(Collection<? extends T> collection) {
this.list.addAll(collection);
return this;
}
@Override
public String toString() {
if (list.size() == 1) {
return formatter.format(list.iterator().next());
} else {
StringBuilder sb = new StringBuilder();
int i = 1;
for (T t : list) {
sb.append(formatter.format(t));
if (i == list.size() - 1 && lastSeperator != null) {
sb.append(lastSeperator);
} else if (i != list.size() && seperator != null) {
sb.append(seperator);
}
i++;
}
return sb.toString();
}
}
}

View file

@ -0,0 +1,78 @@
package net.frankheijden.serverutils.common.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
public class ListComponentBuilder<T> {
private final List<T> elements;
private Format<T> format;
private Component separator;
private Component lastSeparator;
private ListComponentBuilder() {
this.elements = new ArrayList<>();
}
public static <T> ListComponentBuilder<T> create(Collection<? extends T> list) {
return new ListComponentBuilder<T>().addAll(list);
}
@SafeVarargs
public static <T> ListComponentBuilder<T> create(T... elements) {
return new ListComponentBuilder<T>().addAll(Arrays.asList(elements));
}
public ListComponentBuilder<T> format(Format<T> format) {
this.format = format;
return this;
}
public ListComponentBuilder<T> separator(Component separator) {
this.separator = separator;
return this;
}
public ListComponentBuilder<T> lastSeparator(Component lastSeparator) {
this.lastSeparator = lastSeparator;
return this;
}
public ListComponentBuilder<T> addAll(Collection<? extends T> elements) {
this.elements.addAll(elements);
return this;
}
/**
* Builds the ListComponent.
*/
public Component build() {
if (elements.size() == 1) {
return format.format(elements.iterator().next());
} else {
TextComponent.Builder builder = Component.empty().toBuilder();
int sizeMinusTwo = elements.size() - 2;
for (int i = 0; i < elements.size(); i++) {
builder.append(format.format(elements.get(i)));
if (i == sizeMinusTwo && lastSeparator != null) {
builder.append(lastSeparator);
} else if (i < sizeMinusTwo && separator != null) {
builder.append(separator);
}
}
return builder.build();
}
}
public interface Format<T> {
Component format(T element);
}
}

View file

@ -1,9 +0,0 @@
package net.frankheijden.serverutils.common.utils;
public interface ListFormat<T> {
ListFormat<String> stringFormat = String::toString;
String format(T t);
}

View file

@ -1,71 +1,76 @@
{
"config-version": 2,
"serverutils": {
"success": "&3Successfully %action%ed &b%what%&3!",
"warning": "&3Successfully %action%ed &b%what%&3, but with warnings.",
"error": "&cAn error occurred while %action%ing &4%what%&c, please check the console!",
"not_exists": "&cAn error occurred while %action%ing &4%what%&c, plugin does not exist!",
"not_enabled": "&cAn error occurred while %action%ing &4%what%&c, plugin is not enabled!",
"already_loaded": "&cAn error occurred while %action%ing &4%what%&c, plugin is already loaded!",
"already_enabled": "&cAn error occurred while %action%ing &4%what%&c, plugin is already enabled!",
"already_disabled": "&cAn error occurred while %action%ing &4%what%&c, plugin is already disabled!",
"file_deleted": "&cAccessing the jar file while %action%ing &4%what%&c went wrong, plugin has been deleted!",
"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!",
"unknown_dependency": "&cAn error occurred while %action%ing &4%what%&c, plugin has a dependeny which is not loaded: &4%arg%",
"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."
"messages": {
"generic": {
"prefix": "<aqua><bold>ServerUtils <dark_gray><bold>»<reset> <gray>",
"error": "<red>An error occurred, please check the console!",
"not-exists": "<red>Plugin <dark_red><plugin></dark_red> does not exist!",
"not-enabled": "<red>Plugin <dark_red><plugin></dark_red> is not enabled!",
"already-loaded": "<red>Plugin <dark_red><plugin></dark_red> is already loaded!",
"already-enabled": "<red>Plugin <dark_red><plugin></dark_red> is already enabled!",
"already-disabled": "<red>Plugin <dark_red><plugin></dark_red> is already disabled!",
"invalid-plugin": "<red>Plugin <dark_red><plugin></dark_red> is invalid!",
"invalid-description": "<red>Plugin <dark_red><plugin></dark_red> has an invalid plugin description!",
"unknown-dependency": "<red>Plugin <dark_red><plugin></dark_red> has an unknown dependency: <dark_red><dependency><red>!",
"file-deleted": "<red>File of plugin <dark_red><plugin></dark_red> has been deleted!"
},
"reload": "<dark_aqua>Successfully reloaded <aqua>ServerUtils configurations</aqua>!",
"loadplugin": "<dark_aqua>Successfully loaded <aqua><plugin></aqua>!",
"unloadplugin": "<dark_aqua>Successfully unloaded <aqua><plugin></aqua>!",
"reloadplugin": "<dark_aqua>Successfully reloaded <aqua><plugin></aqua>!",
"depending-plugins": {
"prefix": "<red>Plugin <dark_red><plugin></dark_red> has depending plugins: ",
"format": "<dark_red><plugin>",
"separator": "<red>, ",
"last-separator": " <red>and ",
"override": "<red>Use \"<dark_red>/<command></dark_red>\" to force command execution."
},
"watchplugin": {
"start": "&3Started watching &b%what%&3!",
"change": "&3Changes detected, reloading plugins now...",
"stopped": "&3Stopped watching &b%what%&3!",
"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!"
"start": "<dark_aqua>Started watching <aqua><plugin></aqua>!",
"change": "<dark_aqua>Changes detected, reloading plugins now...",
"stopped": "<dark_aqua>Stopped watching <aqua><plugin></aqua>!",
"file-deleted": "<red>File of plugin <dark_red><plugin></dark_red> has been deleted! Waiting for plugin to show up...",
"deleted-file-is-created": "<dark_aqua>File of plugin <aqua><plugin></aqua> has shown up again!",
"already-watching": "<red>You are already watching <dark_red><plugin></dark_red>!",
"not-watching": "<red>You are not watching <dark_red><plugin></dark_red>!"
},
"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-------------------------------------------------",
"downloading": "&8&m------------=&r&8[ &b&lServerUtils Update&r &8]&m=--------------\n &3A new version of ServerUtils will be downloaded and installed after a restart!\n &3Current version: &b%old%\n &3New version: &b%new%\n &3Release info: &b%info%\n&8&m-------------------------------------------------",
"download_failed": "&cFailed to download version %new% of ServerUtils. Please update manually.",
"download_success": "&3ServerUtils has been downloaded and will be installed on the next restart."
"available": "<dark_gray><strikethrough>------------=<reset><dark_gray>[ <aqua><bold>ServerUtils Update<reset> <dark_gray>]<strikethrough>=--------------\n <dark_aqua>Current version: <aqua><old>\n <dark_aqua>New version: <aqua><new>\n <dark_aqua>Release info: <aqua><info>\n<dark_gray><strikethrough>-------------------------------------------------",
"downloading": "<dark_gray><strikethrough>------------=<reset><dark_gray>[ <aqua><bold>ServerUtils Update<reset> <dark_gray>]<strikethrough>=--------------\n <dark_aqua>A new version of ServerUtils will be downloaded and installed after a restart!\n <dark_aqua>Current version: <aqua><old>\n <dark_aqua>New version: <aqua><new>\n <dark_aqua>Release info: <aqua><info>\n<dark_gray><strikethrough>-------------------------------------------------",
"download-failed": "<red>Failed to download version <new> of ServerUtils. Please update manually.",
"download-success": "<dark_aqua>ServerUtils has been downloaded and will be installed on the next restart."
},
"help": {
"header": "&8&m-------------=&r&8[ &b&lServerUtils Help&r &8]&m=---------------",
"format": "&8/&3%command% &8(&b%help%&8)",
"footer": "&8&m-------------------------------------------------"
"header": "<dark_gray><strikethrough>-------------=<reset><dark_gray>[ <aqua><bold>ServerUtils Help<reset> <dark_gray>]<strikethrough>=---------------",
"format": "<dark_gray>/<dark_aqua><command> <dark_gray>(<aqua><help><dark_gray>)",
"footer": "<dark_gray><strikethrough>-------------------------------------------------"
},
"plugins": {
"header": "&8&m------------=&r&8[ &b&lServerUtils Plugins&r &8]&m=-------------",
"prefix": " &3Plugins &8(&a%count%&8)&b: ",
"format": "&3%plugin%",
"format_disabled": "&c%plugin%",
"seperator": "&b, ",
"last_seperator": " &band ",
"version": " &8(&a%version%&8)",
"footer": "&8&m-------------------------------------------------"
"header": "<dark_gray><strikethrough>------------=<reset><dark_gray>[ <aqua><bold>ServerUtils Plugins<reset> <dark_gray>]<strikethrough>=-------------",
"prefix": " <dark_aqua>Plugins <dark_gray>(<green><count><dark_gray>)<aqua>: ",
"format": "<dark_aqua><plugin>",
"format-disabled": "<red><plugin>",
"separator": "<aqua>, ",
"last-separator": " <aqua>and ",
"version": " <dark_gray>(<green><version><dark_gray>)",
"footer": "<dark_gray><strikethrough>-------------------------------------------------"
},
"plugininfo": {
"header": "&8&m-----------=&r&8[ &b&lServerUtils PluginInfo&r &8]&m=-----------",
"format": " &3%key%&8: &b%value%",
"list_format": "&b%value%",
"seperator": "&8, ",
"last_seperator": " &8and ",
"footer": "&8&m-------------------------------------------------"
"header": "<dark_gray><strikethrough>-----------=<reset><dark_gray>[ <aqua><bold>ServerUtils PluginInfo<reset> <dark_gray>]<strikethrough>=-----------",
"format": " <dark_aqua><key><dark_gray>: <aqua><value>",
"list-format": "<aqua><value>",
"list-separator": "<dark_gray>, ",
"list-last-separator": " <dark_gray>and ",
"footer": "<dark_gray><strikethrough>-------------------------------------------------"
},
"commandinfo": {
"header": "&8&m-----------=&r&8[ &b&lServerUtils CommandInfo&r &8]&m=----------",
"format": " &3%key%&8: &b%value%",
"list_format": "&b%value%",
"seperator": "&8, ",
"last_seperator": " &8and ",
"footer": "&8&m-------------------------------------------------",
"not_exists": "&cThat command is not a valid registered command."
"header": "<dark_gray><strikethrough>-----------=<reset><dark_gray>[ <aqua><bold>ServerUtils CommandInfo<reset> <dark_gray>]<strikethrough>=----------",
"format": " <dark_aqua><key><dark_gray>: <aqua><value>",
"list-format": "<aqua><value>",
"list-separator": "<dark_gray>, ",
"list-last-separator": " <dark_gray>and ",
"footer": "<dark_gray><strikethrough>-------------------------------------------------",
"not-exists": "<red>That command is not a valid registered command."
}
}
}

View file

@ -0,0 +1,25 @@
package net.frankheijden.serverutils.common.config;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import java.util.Arrays;
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 MessageKeyTest {
@ParameterizedTest(name = "key = {0}")
@MethodSource("messageKeyGenerator")
void testMessageKeyConsistency(MessageKey key) {
assertThatCode(() -> MessageKey.fromPath(key.getPath())).doesNotThrowAnyException();
assertThat(MessageKey.fromPath(key.getPath())).isEqualTo(key);
}
private static Stream<Arguments> messageKeyGenerator() {
return Arrays.stream(MessageKey.values())
.map(Arguments::of);
}
}

View file

@ -1,42 +0,0 @@
package net.frankheijden.serverutils.common.utils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.params.provider.Arguments.of;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;
class HexUtilsTest {
@ParameterizedTest(name = "color = {0}, expected = {1}")
@CsvSource({
"0, &x&0",
"10, &x&1&0",
"789344, &x&7&8&9&3&4&4",
})
void convertHexColor(String color, String expected) {
assertThat(HexUtils.convertHexColor(color)).isEqualTo(expected);
}
@ParameterizedTest(name = "hexString = {0}, expected = {1}")
@MethodSource("hexStringGenerator")
void convertHexString(String hexString, String expected) {
assertThat(HexUtils.convertHexString(hexString)).isEqualTo(expected);
}
private static Stream<Arguments> hexStringGenerator() {
return Stream.of(
of("<#FFFFFF>", "&x&F&F&F&F&F&F"),
of("Hey <#FFFFFF>", "Hey &x&F&F&F&F&F&F"),
of("Hey<#FFFFFF>Hey2<#AAAAAA>", "Hey&x&F&F&F&F&F&FHey2&x&A&A&A&A&A&A"),
of("<#FFFFFF><#AAAAAA><#FFFFFF>", "&x&F&F&F&F&F&F&x&A&A&A&A&A&A&x&F&F&F&F&F&F"),
of("<#FFFFFF>#FFFFFF", "&x&F&F&F&F&F&F#FFFFFF"),
of("<#FFFFFF>FFFFFF", "&x&F&F&F&F&F&FFFFFFF"),
of("<<#FFFFFF>>", "<&x&F&F&F&F&F&F>"),
of("<#<#ABCDEF>>", "<#&x&A&B&C&D&E&F>")
);
}
}

View file

@ -5,38 +5,47 @@ import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.List;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.serializer.ComponentSerializer;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.junit.jupiter.api.Test;
class ListBuilderTest {
private final String seperator = ", ";
private final String lastSeperator = " and ";
private static final ComponentSerializer<Component, TextComponent, String> plainTextComponentSerializer
= PlainTextComponentSerializer.plainText();
private final Component separator = Component.text(", ");
private final Component lastSeparator = Component.text(" and ");
@Test
void testToStringOneElement() {
String list = ListBuilder.createStrings(singletonList("Nice"))
.seperator(seperator)
.lastSeperator(lastSeperator)
.toString();
assertEquals("Nice", list);
Component component = ListComponentBuilder.create(singletonList("Nice"))
.format(Component::text)
.separator(separator)
.lastSeparator(lastSeparator)
.build();
assertEquals("Nice", plainTextComponentSerializer.serialize(component));
}
@Test
void testToStringTwoElements() {
String list = ListBuilder.createStrings(asList("Nice", "List"))
.seperator(seperator)
.lastSeperator(lastSeperator)
.toString();
assertEquals("Nice and List", list);
Component component = ListComponentBuilder.create(asList("Nice", "List"))
.format(Component::text)
.separator(separator)
.lastSeparator(lastSeparator)
.build();
assertEquals("Nice and List", plainTextComponentSerializer.serialize(component));
}
@Test
void testToStringMultipleElements() {
String list = ListBuilder.createStrings(asList("Nice", "List", "You", "Having", "There"))
.seperator(seperator)
.lastSeperator(lastSeperator)
.toString();
assertEquals("Nice, List, You, Having and There", list);
Component component = ListComponentBuilder.create(asList("Nice", "List", "You", "Having", "There"))
.format(Component::text)
.separator(separator)
.lastSeparator(lastSeparator)
.build();
assertEquals("Nice, List, You, Having and There", plainTextComponentSerializer.serialize(component));
}
@Test
@ -47,12 +56,12 @@ class ListBuilderTest {
new TestObject("pre3", 4)
);
String list = ListBuilder.create(objects)
.format(obj -> obj.prefix + "-" + obj.value)
.seperator("; ")
.lastSeperator(" and at last ")
.toString();
assertEquals("pre1-2; pre2-3 and at last pre3-4", list);
Component component = ListComponentBuilder.create(objects)
.format(obj -> Component.text(obj.prefix + "-" + obj.value))
.separator(Component.text("; "))
.lastSeparator(Component.text(" and at last "))
.build();
assertEquals("pre1-2; pre2-3 and at last pre3-4", plainTextComponentSerializer.serialize(component));
}
private static class TestObject {