Initial BungeeCord edition

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

View file

@ -0,0 +1,17 @@
package net.frankheijden.serverutils.common;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
public class ServerUtilsApp {
public static final int BSTATS_METRICS_ID = 7790;
private static ServerUtilsPlugin plugin;
public static void init(ServerUtilsPlugin plugin) {
ServerUtilsApp.plugin = plugin;
}
public static ServerUtilsPlugin getPlugin() {
return plugin;
}
}

View file

@ -0,0 +1,30 @@
package net.frankheijden.serverutils.common.commands;
import java.util.List;
import net.frankheijden.serverutils.common.config.Messenger;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.utils.ListBuilder;
import net.frankheijden.serverutils.common.utils.ListFormat;
public class Plugins {
/**
* Sends a plugin list to the receiver.
* @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.
*/
public static <T> void sendPlugins(ServerCommandSender sender, List<T> plugins, ListFormat<T> pluginFormat) {
Messenger.sendMessage(sender, "serverutils.plugins.header");
String prefix = Messenger.getMessage("serverutils.plugins.prefix",
"%count%", String.valueOf(plugins.size()));
sender.sendMessage(Messenger.color(prefix + ListBuilder.create(plugins)
.seperator(Messenger.getMessage("serverutils.plugins.seperator"))
.lastSeperator(Messenger.getMessage("serverutils.plugins.last_seperator"))
.format(pluginFormat)
.toString()));
Messenger.sendMessage(sender, "serverutils.plugins.footer");
}
}

View file

@ -0,0 +1,15 @@
package net.frankheijden.serverutils.common.config;
public class Config extends YamlResource {
private static Config instance;
public Config(String fileName, String resource) {
super(fileName, resource);
instance = this;
}
public static Config getInstance() {
return instance;
}
}

View file

@ -0,0 +1,67 @@
package net.frankheijden.serverutils.common.config;
import net.frankheijden.serverutils.common.ServerUtilsApp;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
import net.frankheijden.serverutils.common.utils.StringUtils;
public class Messenger extends YamlResource {
private static Messenger instance;
private static final ServerUtilsPlugin plugin = ServerUtilsApp.getPlugin();
public Messenger(String fileName, String resource) {
super(fileName, resource);
instance = this;
}
public static Messenger getInstance() {
return instance;
}
/**
* 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.
*/
public static String getMessage(String path, String... replacements) {
String message = instance.getConfig().getString(path);
if (message != null) {
return StringUtils.apply(message, replacements);
} else {
instance.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 static void sendRawMessage(ServerCommandSender sender, String msg, String... replacements) {
String message = StringUtils.apply(msg, replacements);
if (message != null) {
sender.sendMessage(instance.plugin.getColorProvider().apply(message));
}
}
/**
* 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 static void sendMessage(ServerCommandSender sender, String path, String... replacements) {
String message = getMessage(path, replacements);
if (message != null) {
sender.sendMessage(instance.plugin.getColorProvider().apply(message));
}
}
public static String color(String str) {
return instance.plugin.getColorProvider().apply(str);
}
}

View file

@ -0,0 +1,59 @@
package net.frankheijden.serverutils.common.config;
import java.io.IOException;
import java.util.Collection;
public interface YamlConfig {
Object get(String path);
void set(String path, Object value);
String getString(String path);
boolean getBoolean(String path);
Collection<? extends String> getKeys();
void save() throws IOException;
static void addDefaults(YamlConfig def, YamlConfig conf) {
addDefaults(def, conf, "");
}
/**
* Adds defaults if keys don't exist to the configuration specified.
* @param def The defaults to copy values over from.
* @param conf The configuration to copy the defaults to.
* @param root The current root path of the iteration.
*/
static void addDefaults(YamlConfig def, YamlConfig conf, String root) {
if (def == null) return;
for (String key : def.getKeys()) {
String newKey = (root.isEmpty() ? "" : root + ".") + key;
Object value = def.get(key);
if (value instanceof YamlConfig) {
addDefaults((YamlConfig) value, conf, newKey);
} else if (conf.get(newKey) == null) {
conf.set(newKey, value);
}
}
}
/**
* Initiates a Configuration from a file with associated defaults.
* @param def The default Configuration to be applied.
* @param conf The Configuration where the defaults will be applied to.
* @return The loaded Configuration of the file with defaults.
*/
static YamlConfig init(YamlConfig def, YamlConfig conf) {
YamlConfig.addDefaults(def, conf);
try {
conf.save();
} catch (IOException ex) {
ex.printStackTrace();
}
return conf;
}
}

View file

@ -0,0 +1,32 @@
package net.frankheijden.serverutils.common.config;
import java.io.File;
import java.io.InputStream;
import net.frankheijden.serverutils.common.ServerUtilsApp;
import net.frankheijden.serverutils.common.entities.ServerUtilsPlugin;
import net.frankheijden.serverutils.common.providers.ResourceProvider;
public class YamlResource {
private static final ServerUtilsPlugin plugin = ServerUtilsApp.getPlugin();
private final YamlConfig config;
/**
* Creates a new YamlResource instance.
* Loads the resource from the jar file.
* @param fileName The destination file.
* @param resource The resource from the jar file.
*/
public YamlResource(String fileName, String resource) {
ResourceProvider provider = plugin.getResourceProvider();
InputStream is = provider.getResource(resource);
File file = plugin.copyResourceIfNotExists(fileName, resource);
config = YamlConfig.init(provider.load(is), provider.load(file));
}
public YamlConfig getConfig() {
return config;
}
}

View file

@ -0,0 +1,56 @@
package net.frankheijden.serverutils.common.entities;
import java.io.Closeable;
import java.io.IOException;
public class CloseableResult implements Closeable {
private Result result;
private final Closeable closeable;
/**
* 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 closeable The closable of the procedure.
*/
public CloseableResult(Result result, Closeable closeable) {
this.result = result;
this.closeable = closeable;
}
public CloseableResult(Result result) {
this(result, null);
}
public CloseableResult(Closeable closeable) {
this(Result.SUCCESS, closeable);
}
public Result getResult() {
return result;
}
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 (closeable == null) return;
try {
close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public void close() throws IOException {
closeable.close();
}
}

View file

@ -0,0 +1,32 @@
package net.frankheijden.serverutils.common.entities;
public class LoadResult<T> {
private final T obj;
private final Result result;
public LoadResult(T obj, Result result) {
this.obj = obj;
this.result = result;
}
public LoadResult(T obj) {
this(obj, Result.SUCCESS);
}
public LoadResult(Result result) {
this(null, result);
}
public T get() {
return obj;
}
public Result getResult() {
return result;
}
public boolean isSuccess() {
return obj != null && result == Result.SUCCESS;
}
}

View file

@ -0,0 +1,42 @@
package net.frankheijden.serverutils.common.entities;
import net.frankheijden.serverutils.common.config.Messenger;
public enum Result {
NOT_EXISTS,
NOT_ENABLED,
ALREADY_LOADED,
ALREADY_ENABLED,
ALREADY_DISABLED,
FILE_DELETED,
INVALID_DESCRIPTION,
INVALID_PLUGIN,
UNKNOWN_DEPENDENCY,
ERROR,
SUCCESS;
private String arg;
Result() {
this.arg = "";
}
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.
*/
public void sendTo(ServerCommandSender sender, String action, String what) {
Messenger.sendMessage(sender, "serverutils." + this.name().toLowerCase(),
"%action%", action,
"%what%", what,
"%arg%", arg);
}
}

View file

@ -0,0 +1,6 @@
package net.frankheijden.serverutils.common.entities;
public interface ServerCommandSender {
void sendMessage(String message);
}

View file

@ -0,0 +1,52 @@
package net.frankheijden.serverutils.common.entities;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import net.frankheijden.serverutils.common.providers.ColorProvider;
import net.frankheijden.serverutils.common.providers.PluginProvider;
import net.frankheijden.serverutils.common.providers.ResourceProvider;
import net.frankheijden.serverutils.common.utils.FileUtils;
public abstract class ServerUtilsPlugin {
public abstract <T> PluginProvider<T> getPluginProvider();
public abstract ResourceProvider getResourceProvider();
public abstract ColorProvider getColorProvider();
public abstract Logger getLogger();
public abstract File getDataFolder();
public void createDataFolderIfNotExists() {
if (getDataFolder().exists()) return;
getDataFolder().mkdirs();
}
/**
* Copies a resource from the jar to the specified target file name under the datafolder.
* @param targetName The target file under the datafolder.
* @param resource The resource from the jar file to copy.
* @return The target file.
*/
public File copyResourceIfNotExists(String targetName, String resource) {
createDataFolderIfNotExists();
File file = new File(getDataFolder(), targetName);
if (!file.exists()) {
getLogger().info(String.format("'%s' not found, creating!", targetName));
try {
FileUtils.saveResource(getResourceProvider().getResource(resource), file);
} catch (IOException ex) {
ex.printStackTrace();
}
}
return file;
}
}

View file

@ -0,0 +1,6 @@
package net.frankheijden.serverutils.common.providers;
public interface ColorProvider {
String apply(String str);
}

View file

@ -0,0 +1,48 @@
package net.frankheijden.serverutils.common.providers;
import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public abstract class PluginProvider<T> {
public abstract File getPluginsFolder();
public abstract List<T> getPlugins();
public abstract String getPluginName(T plugin);
public List<T> getPluginsSorted() {
List<T> plugins = getPlugins();
plugins.sort(Comparator.comparing(this::getPluginName));
return plugins;
}
public List<String> getPluginNames() {
return getPlugins().stream()
.map(this::getPluginName)
.collect(Collectors.toList());
}
/**
* Retrieves all files with a jar extension in the plugins/ folder and returns solely their name.
* @return An list of jar file names.
*/
public List<String> getPluginFileNames() {
return Arrays.stream(getPluginJars())
.map(File::getName)
.collect(Collectors.toList());
}
/**
* Retrieves all files with a jar extension in the plugins/ folder.
* @return An array of jar files.
*/
public File[] getPluginJars() {
File parent = getPluginsFolder();
if (parent == null || !parent.exists()) return new File[0];
return parent.listFiles(f -> f.getName().endsWith(".jar"));
}
}

View file

@ -0,0 +1,15 @@
package net.frankheijden.serverutils.common.providers;
import net.frankheijden.serverutils.common.config.YamlConfig;
import java.io.File;
import java.io.InputStream;
public interface ResourceProvider {
InputStream getResource(String resource);
YamlConfig load(InputStream is);
YamlConfig load(File file);
}

View file

@ -14,6 +14,7 @@ import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
public class FileUtils {
@ -80,4 +81,17 @@ public class FileUtils {
return new JsonParser().parse(jsonText);
}
}
/**
* Saves an InputStream to a file.
* @param in The InputStream.
* @param target The target file.
* @return Whether or not file was created / already exists.
* @throws IOException If an I/O exception occurs.
*/
public static boolean saveResource(InputStream in, File target) throws IOException {
if (target.exists()) return false;
Files.copy(in, target.toPath());
return true;
}
}

View file

@ -0,0 +1,59 @@
package net.frankheijden.serverutils.common.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.frankheijden.serverutils.common.config.Messenger;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
public class FormatBuilder {
private final String format;
private final List<String[]> valueList;
private String[] orderedKeys;
private boolean alwaysSend;
private FormatBuilder(String format) {
this.format = format;
this.valueList = new ArrayList<>();
this.orderedKeys = new String[0];
this.alwaysSend = false;
}
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 alwaysSend(boolean alwaysSend) {
this.alwaysSend = alwaysSend;
return this;
}
/**
* Builds the format and sends it to the CommandSender.
* @param sender The receiver of the list.
*/
public void sendTo(ServerCommandSender sender) {
valueList.forEach(values -> {
int length = Math.min(values.length, orderedKeys.length);
String message = format;
for (int i = 0; i < length; i++) {
String value = values[i];
if (value == null && !alwaysSend) return;
message = message.replace(orderedKeys[i], String.valueOf(value));
}
Messenger.sendRawMessage(sender, message);
});
}
}

View file

@ -0,0 +1,54 @@
package net.frankheijden.serverutils.common.utils;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import net.frankheijden.serverutils.common.entities.ServerCommandSender;
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 boolean warnings;
/**
* Creates a filter which forwards all output to the sender.
* @param sender The sender to forward logs to.
*/
public ForwardFilter(ServerCommandSender sender) {
this.warnings = false;
setPredicate(rec -> {
char color = getColor(rec.getLevel());
if (color != INFO_COLOR) warnings = true;
sender.sendMessage('&' + color + format(rec));
return true;
});
}
public boolean hasWarnings() {
return warnings;
}
private static char getColor(Level level) {
if (Level.SEVERE.equals(level)) {
return SEVERE_COLOR;
} else if (Level.WARNING.equals(level)) {
return WARNING_COLOR;
}
return INFO_COLOR;
}
private static String format(LogRecord record) {
String msg = record.getMessage();
Object[] params = record.getParameters();
if (params == null) return msg;
for (int i = 0; i < params.length; i++) {
msg = msg.replace("{" + i + "}", String.valueOf(params[i]));
}
return msg;
}
}

View file

@ -1,5 +1,8 @@
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> {
@ -17,6 +20,14 @@ public class ListBuilder<T> {
return new ListBuilder<>(list);
}
public static <T> ListBuilder<T> create(Collection<T> list) {
return new ListBuilder<>(new ArrayList<>(list));
}
public static <T> ListBuilder<T> create(T... elements) {
return new ListBuilder<>(Arrays.asList(elements));
}
/**
* Creates a pre-defined ListBuilder with type String.
* @param list The collection to be used.

View file

@ -14,6 +14,7 @@ public class MapUtils {
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static void removeKeys(Map map, Predicate<Object> predicate) {
if (map == null) return;
Set<Object> keysToRemove = new HashSet<>();
map.forEach((k, v) -> {
if (predicate.test(k)) {
@ -30,12 +31,24 @@ public class MapUtils {
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static void removeValues(Map map, Predicate<Object> predicate) {
Set<Object> keysToRemove = new HashSet<>();
if (map == null) return;
Set<Object> valuesToRemove = new HashSet<>();
map.forEach((k, v) -> {
if (predicate.test(v)) {
keysToRemove.add(k);
valuesToRemove.add(k);
}
});
keysToRemove.forEach(map::remove);
valuesToRemove.forEach(map::remove);
}
/**
* Removes a key from a map.
* @param map The map instance.
* @param obj The object to remove.
*/
@SuppressWarnings("rawtypes")
public static void remove(Map map, Object obj) {
if (map == null) return;
map.remove(obj);
}
}

View file

@ -0,0 +1,20 @@
package net.frankheijden.serverutils.common.utils;
public class StringUtils {
/**
* Applies placeholders to a message.
* @param message The message.
* @param replacements The replacements of the message. Expects input to be even and in a key-value like format.
* Example: ["%player%", "Player"]
* @return The message with translated placeholders.
*/
public static String apply(String message, String... replacements) {
if (message == null || message.isEmpty()) return null;
message = message.replace("\\n", "\n");
for (int i = 0; i < replacements.length; i++, i++) {
message = message.replace(replacements[i], replacements[i + 1]);
}
return message;
}
}