feat: Migrate to configurate

This commit is contained in:
Adrian3d04 2022-08-05 23:46:51 +00:00
parent 638be7d180
commit 6063375180
13 changed files with 218 additions and 168 deletions

View File

@ -7,8 +7,7 @@ repositories {
}
dependencies {
compileOnly("space.arim.dazzleconf:dazzleconf-core:1.3.0-M1")
compileOnly("space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.3.0-M1")
compileOnly("org.spongepowered:configurate-hocon:4.1.2")
compileOnly("org.slf4j:slf4j-api:1.7.36")
compileOnly("net.byteflux:libby-core:1.1.5")
}
@ -16,6 +15,6 @@ dependencies {
tasks {
shadowJar {
relocate("net.byteflux.libby", "me.adrianed.authmevelocity.libs.libby")
relocate("space.arim.dazzleconf", "me.adrianed.authmevelocity.libs.dazzleconf")
relocate("org.spongepowered", "me.adrianed.authmevelocity.libs.sponge")
}
}

View File

@ -0,0 +1,6 @@
package me.adrianed.authmevelocity.common;
public final class Constants {
public static final String CONFIGURATE = "4.1.2";
public static final String GEANTYREF = "1.3.13";
}

View File

@ -14,35 +14,36 @@ public final class LibsManager {
}
public void loadLibraries() {
final String dazzlePackage = new String(new char[] {
's','p','a','c','e','.','a','r','i','m','.','d','a','z','z','l','e','c','o','n','f'});
final Relocation dazzleRelocation
= new Relocation(dazzlePackage, "me.adrianed.authmevelocity.libs.dazzleconf");
final Relocation snakeYamlRelocation
= new Relocation("org.yaml.snakeyaml", "me.adrianed.authmevelocity.libs.snakeyaml");
final Library dazzleConf = Library.builder()
.groupId(dazzlePackage)
.artifactId("dazzleconf-core")
.version("1.3.0-M1")
.relocate(dazzleRelocation)
final Relocation configurateRelocation
= new Relocation("org{}spongepowered", "me.adrianed.authmevelocity.libs.sponge");
final Relocation geantyrefRelocation =
new Relocation("io{}leangen{}geantyref", "me.adrianed.authmevelocity.libs.geantyref");
final Library hocon = Library.builder()
.groupId("org{}spongepowered")
.artifactId("configurate-hocon")
.version(Constants.CONFIGURATE)
.id("configurate-hocon")
.relocate(configurateRelocation)
.relocate(geantyrefRelocation)
.build();
final Library dazzleYaml = Library.builder()
.groupId(dazzlePackage)
.artifactId("dazzleconf-ext-snakeyaml")
.version("1.3.0-M1")
.relocate(dazzleRelocation)
.relocate(snakeYamlRelocation)
final Library confCore = Library.builder()
.groupId("org{}spongepowered")
.artifactId("configurate-core")
.version(Constants.CONFIGURATE)
.id("configurate-core")
.relocate(configurateRelocation)
.relocate(geantyrefRelocation)
.build();
final Library snakeYaml = Library.builder()
.groupId("org.yaml")
.artifactId("snakeyaml")
.version("1.30")
.relocate(dazzleRelocation)
.relocate(snakeYamlRelocation)
final Library geantyref = Library.builder()
.groupId("io{}leangen{}geantyref")
.artifactId("geantyref")
.version(Constants.GEANTYREF)
.id("geantyref")
.relocate(geantyrefRelocation)
.build();
manager.loadLibrary(snakeYaml);
manager.loadLibrary(dazzleConf);
manager.loadLibrary(dazzleYaml);
manager.loadLibrary(confCore);
manager.loadLibrary(hocon);
manager.loadLibrary(geantyref);
}
}

View File

@ -0,0 +1,61 @@
package me.adrianed.authmevelocity.common.configuration;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.spongepowered.configurate.CommentedConfigurationNode;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
public class ConfigurationContainer<C> {
private C config;
private final HoconConfigurationLoader loader;
private final Class<C> clazz;
private final Logger logger;
public ConfigurationContainer(
final C config,
final Class<C> clazz,
final HoconConfigurationLoader loader,
final Logger logger
) {
this.config = config;
this.loader = loader;
this.clazz = clazz;
this.logger = logger;
}
public CompletableFuture<Boolean> reload() {
return this.safeReload();
}
public void setValues(Consumer<C> consumer) {
consumer.accept(this.config);
this.safeReload();
}
public C get() {
return this.config;
}
private final CompletableFuture<Boolean> safeReload() {
return CompletableFuture.supplyAsync(() -> {
C newConfig = null;
try {
final CommentedConfigurationNode node = loader.load();
newConfig = node.get(clazz);
node.set(clazz, config);
loader.save(node);
return true;
} catch (ConfigurateException exception) {
logger.error("Could not load config.conf file", exception);
return false;
} finally {
if (newConfig != null) {
config = newConfig;
}
}
});
}
}

View File

@ -1,65 +1,36 @@
package me.adrianed.authmevelocity.common.configuration;
import java.nio.file.Path;
import org.slf4j.Logger;
import space.arim.dazzleconf.ConfigurationFactory;
import space.arim.dazzleconf.ConfigurationOptions;
import space.arim.dazzleconf.error.ConfigFormatSyntaxException;
import space.arim.dazzleconf.error.InvalidConfigException;
import space.arim.dazzleconf.ext.snakeyaml.CommentMode;
import space.arim.dazzleconf.ext.snakeyaml.SnakeYamlConfigurationFactory;
import space.arim.dazzleconf.ext.snakeyaml.SnakeYamlOptions;
import space.arim.dazzleconf.helper.ConfigurationHelper;
import org.spongepowered.configurate.CommentedConfigurationNode;
import org.spongepowered.configurate.ConfigurateException;
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import org.spongepowered.configurate.objectmapping.meta.Comment;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
public class Loader<C> {
private final ConfigurationHelper<C> configHelper;
private volatile C configData;
private final Logger logger;
public class Loader {
public static <C> ConfigurationContainer<C> loadMainConfig(final Path path, Class<C> clazz, Logger logger){
final HoconConfigurationLoader loader = HoconConfigurationLoader.builder()
.defaultOptions(opts -> opts
.shouldCopyDefaults(true)
.header("AuthMeVelocity | by Glyart & 4drian3d\n")
)
.path(path.resolve("config.conf"))
.build();
private Loader(ConfigurationHelper<C> configHelper, Logger logger) {
this.configHelper = configHelper;
this.logger = logger;
}
public static <C> Loader<C> create(Path configFolder, String fileName, Class<C> configClass, Logger logger) {
SnakeYamlOptions yamlOptions = new SnakeYamlOptions.Builder()
.commentMode(CommentMode.alternativeWriter())
.build();
ConfigurationFactory<C> configFactory = SnakeYamlConfigurationFactory.create(
configClass,
ConfigurationOptions.defaults(),
yamlOptions);
return new Loader<>(new ConfigurationHelper<>(configFolder, fileName, configFactory), logger);
}
public boolean reloadConfig() {
try {
configData = configHelper.reloadConfigData();
return true;
} catch (IOException ex) {
throw new UncheckedIOException(ex);
} catch (ConfigFormatSyntaxException ex) {
configData = configHelper.getFactory().loadDefaults();
logger.error("The yaml syntax in your configuration is invalid. "
+ "Check your YAML syntax with a tool such as https://yaml-online-parser.appspot.com/", ex);
return false;
} catch (InvalidConfigException ex) {
configData = configHelper.getFactory().loadDefaults();
logger.error("One of the values in your configuration is not valid. "
+ "Check to make sure you have specified the right data types.", ex);
return false;
}
}
public C getConfig() {
C configData = this.configData;
if (configData == null) {
throw new IllegalStateException("Configuration has not been loaded yet");
}
return configData;
}
final C config;
try {
final CommentedConfigurationNode node = loader.load();
config = node.get(clazz);
node.set(clazz, config);
loader.save(node);
} catch (ConfigurateException exception){
logger.error("Could not load config.conf file", exception);
return null;
}
return new ConfigurationContainer<>(config, clazz, loader, logger);
}
}

View File

@ -1,66 +1,77 @@
package me.adrianed.authmevelocity.common.configuration;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import org.spongepowered.configurate.objectmapping.meta.Comment;
import java.util.List;
import space.arim.dazzleconf.annote.ConfDefault;
import space.arim.dazzleconf.annote.ConfComments;
public interface ProxyConfiguration {
@ConfDefault.DefaultStrings({
"auth1", "auth2"
})
@ConfComments({
"List of login/registration servers"
})
List<String> authServers();
@ConfDefault.DefaultObject("defaultSendOnLogin")
SendOnLogin sendOnLogin();
@ConfDefault.DefaultObject("defaultCommands")
Commands commands();
@ConfDefault.DefaultObject("defaultEnsureAuth")
EnsureAuthServer ensureAuthServer();
public interface SendOnLogin {
@ConfComments({
"Send logged in players to another server?"
})
@ConfDefault.DefaultBoolean(false)
boolean sendToServerOnLogin();
@ConfComments({
"List of servers to send",
"One of these servers will be chosen at random"
})
@ConfDefault.DefaultStrings({
"lobby1", "lobby2"
})
List<String> teleportServers();
@ConfigSerializable
public class ProxyConfiguration {
@Comment("List of login/registration servers")
private List<String> authServers = List.of("auth1", "auth2");
public List<String> authServers() {
return this.authServers;
}
private SendOnLogin sendOnLogin = new SendOnLogin();
public SendOnLogin sendOnLogin() {
return this.sendOnLogin;
}
public interface Commands {
@ConfComments({
"Sets the commands that users who have not yet logged in can execute"
})
@ConfDefault.DefaultStrings({
"login", "register", "l", "reg", "email", "captcha"
})
List<String> allowedCommands();
@ConfComments({
"Sets the message to send in case a non-logged-in player executes an unauthorized command",
"To deactivate the message, leave it empty"
})
@ConfDefault.DefaultString("<red>You cannot execute commands if you are not logged in yet")
String blockedCommandMessage();
private Commands commands = new Commands();
public Commands commands() {
return this.commands;
}
public interface EnsureAuthServer {
@ConfComments({
"Ensure that the first server to which players connect is an auth server"
})
@ConfDefault.DefaultBoolean(false)
boolean ensureFirstServerIsAuthServer();
private EnsureAuthServer ensureAuthServer = new EnsureAuthServer();
public EnsureAuthServer ensureAuthServer() {
return this.ensureAuthServer;
}
@ConfigSerializable
public static class EnsureAuthServer {
@Comment("Ensure that the first server to which players connect is an auth server")
private boolean ensureAuthServer = false;
public boolean ensureFirstServerIsAuthServer() {
return this.ensureAuthServer;
}
}
@ConfigSerializable
public static class SendOnLogin {
@Comment("Send logged in players to another server?")
private boolean sendOnLogin = false;
public boolean sendToServerOnLogin() {
return this.sendOnLogin;
}
@Comment("""
List of servers to send
One of these servers will be chosen at random
""")
private List<String> teleportServers = List.of("lobby1", "lobby2");
public List<String> teleportServers() {
return this.teleportServers;
}
}
@ConfigSerializable
public static class Commands {
@Comment("Sets the commands that users who have not yet logged in can execute")
private List<String> allowedCommands = List.of("login", "register", "l", "reg", "email", "captcha");
public List<String> allowedCommands() {
return this.allowedCommands;
}
@Comment("""
Sets the message to send in case a non-logged-in player executes an unauthorized command
To deactivate the message, leave it empty
""")
private String blockedMessage = "<red>You cannot execute commands if you are not logged in yet";
public String blockedCommandMessage() {
return this.blockedMessage;
}
}
}

View File

@ -35,7 +35,6 @@ tasks {
shadowJar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
relocate("net.byteflux.libby", "me.adrianed.authmevelocity.libs.libby")
relocate("space.arim.dazzleconf", "me.adrianed.authmevelocity.libs.dazzleconf")
configurations = listOf(project.configurations.shadow.get())
}

View File

@ -28,7 +28,6 @@ tasks {
shadowJar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
relocate("net.byteflux.libby", "me.adrianed.authmevelocity.libs.libby")
relocate("space.arim.dazzleconf", "me.adrianed.authmevelocity.libs.dazzleconf")
configurations = listOf(project.configurations.shadow.get())
}
}

View File

@ -7,6 +7,7 @@ import me.adrianed.authmevelocity.velocity.listener.PluginMessageListener;
import me.adrianed.authmevelocity.velocity.listener.ProxyListener;
import me.adrianed.authmevelocity.api.velocity.AuthMeVelocityAPI;
import me.adrianed.authmevelocity.common.LibsManager;
import me.adrianed.authmevelocity.common.configuration.ConfigurationContainer;
import me.adrianed.authmevelocity.common.configuration.Loader;
import me.adrianed.authmevelocity.common.configuration.ProxyConfiguration;
import com.google.inject.Inject;
@ -58,7 +59,7 @@ public final class AuthMeVelocityPlugin implements AuthMeVelocityAPI {
private final ProxyServer proxy;
private final Logger logger;
private final Path pluginDirectory;
private Loader<ProxyConfiguration> config;
private ConfigurationContainer<ProxyConfiguration> config;
protected final Set<UUID> loggedPlayers = ConcurrentHashMap.newKeySet();
@ -77,7 +78,7 @@ public final class AuthMeVelocityPlugin implements AuthMeVelocityAPI {
logger, pluginDirectory, proxy.getPluginManager(), this));
libraries.loadLibraries();
this.config = Loader.create(pluginDirectory, "config.yml", ProxyConfiguration.class, logger);
this.config = Loader.loadMainConfig(pluginDirectory, ProxyConfiguration.class, logger);
proxy.getChannelRegistrar().register(AUTHMEVELOCITY_CHANNEL);
@ -110,14 +111,14 @@ public final class AuthMeVelocityPlugin implements AuthMeVelocityAPI {
source.sendMessage(MiniMessage.miniMessage().deserialize(
" <gray>--- <aqua>AuthMeVelocity</aqua> ---"));
source.sendMessage(MiniMessage.miniMessage().deserialize(
"<gray>AuthServers: <green>" + config.getConfig().authServers()));
if (config.getConfig().sendOnLogin().sendToServerOnLogin()) {
"<gray>AuthServers: <green>" + config.get().authServers()));
if (config.get().sendOnLogin().sendToServerOnLogin()) {
source.sendMessage(MiniMessage.miniMessage().deserialize(
"<gray>LobbyServers: <green>" + config.getConfig().sendOnLogin().teleportServers()));
"<gray>LobbyServers: <green>" + config.get().sendOnLogin().teleportServers()));
}
}
public Loader<ProxyConfiguration> config() {
public ConfigurationContainer<ProxyConfiguration> config() {
return this.config;
}
@ -153,16 +154,16 @@ public final class AuthMeVelocityPlugin implements AuthMeVelocityAPI {
@Override
public boolean isAuthServer(RegisteredServer server){
return config.getConfig().authServers().contains(server.getServerInfo().getName());
return config.get().authServers().contains(server.getServerInfo().getName());
}
@Override
public boolean isAuthServer(ServerConnection connection){
return config.getConfig().authServers().contains(connection.getServerInfo().getName());
return config.get().authServers().contains(connection.getServerInfo().getName());
}
@Override
public boolean isAuthServer(String server){
return config.getConfig().authServers().contains(server);
return config.get().authServers().contains(server);
}
}

View File

@ -20,14 +20,16 @@ public class AuthmeCommand {
.then(LiteralArgumentBuilder.<CommandSource>literal("reload")
.executes(cmd -> {
CommandSource source = cmd.getSource();
if (plugin.config().reloadConfig()) {
plugin.sendInfoMessage();
source.sendMessage(MiniMessage.miniMessage().deserialize(
"<aqua>AuthmeVelocity <green>has been successfully reloaded"));
} else {
source.sendMessage(MiniMessage.miniMessage().deserialize(
"<dark_red>There was an error while reloading the configuration. <red>Check the server console"));
}
plugin.config().reload().thenAcceptAsync(result -> {
if(result) {
plugin.sendInfoMessage();
source.sendMessage(MiniMessage.miniMessage().deserialize(
"<aqua>AuthmeVelocity <green>has been successfully reloaded"));
} else {
source.sendMessage(MiniMessage.miniMessage().deserialize(
"<dark_red>There was an error while reloading the configuration. <red>Check the server console"));
}
});
return Command.SINGLE_SUCCESS;
})
).build();

View File

@ -32,7 +32,7 @@ public class ConnectListener {
@Subscribe(order = PostOrder.LATE)
public void onInitialServer(PlayerChooseInitialServerEvent event, Continuation continuation){
if(!plugin.config().getConfig().ensureAuthServer().ensureFirstServerIsAuthServer()) {
if(!plugin.config().get().ensureAuthServer().ensureFirstServerIsAuthServer()) {
continuation.resume();
return;
}
@ -79,7 +79,7 @@ public class ConnectListener {
// TODO: Implement #40
private @Nullable RegisteredServer getAvailableServer() {
for(String sv : plugin.config().getConfig().authServers()){
for(String sv : plugin.config().get().authServers()){
Optional<RegisteredServer> opt = proxy.getServer(sv);
if (opt.isPresent()) return opt.get();
}

View File

@ -85,7 +85,7 @@ public class PluginMessageListener {
}
private void createServerConnectionRequest(Player player, ServerConnection connection){
if (!plugin.config().getConfig().sendOnLogin().sendToServerOnLogin()) {
if (!plugin.config().get().sendOnLogin().sendToServerOnLogin()) {
return;
}
@ -115,7 +115,7 @@ public class PluginMessageListener {
}
private String getRandomServer() {
final List<String> serverList = plugin.config().getConfig().sendOnLogin().teleportServers();
final List<String> serverList = plugin.config().get().sendOnLogin().teleportServers();
return serverList.get(rm.nextInt(serverList.size()));
}
}

View File

@ -42,7 +42,7 @@ public final class ProxyListener {
if (plugin.isInAuthServer(player)) {
String command = AuthmeUtils.getFirstArgument(event.getCommand());
if (!plugin.config().getConfig().commands().allowedCommands().contains(command)) {
if (!plugin.config().get().commands().allowedCommands().contains(command)) {
sendBlockedMessage(player);
event.setResult(CommandExecuteEvent.CommandResult.denied());
}
@ -67,7 +67,7 @@ public final class ProxyListener {
}
final String command = event.getPartialMessage();
for (final String allowed : plugin.config().getConfig().commands().allowedCommands()) {
for (final String allowed : plugin.config().get().commands().allowedCommands()) {
if (allowed.startsWith(command)) {
return;
}
@ -77,7 +77,7 @@ public final class ProxyListener {
}
void sendBlockedMessage(Player player){
String blockedMessage = plugin.config().getConfig().commands().blockedCommandMessage();
String blockedMessage = plugin.config().get().commands().blockedCommandMessage();
if (!blockedMessage.isBlank()){
player.sendMessage(MiniMessage.miniMessage().deserialize(blockedMessage));
}