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 { dependencies {
compileOnly("space.arim.dazzleconf:dazzleconf-core:1.3.0-M1") compileOnly("org.spongepowered:configurate-hocon:4.1.2")
compileOnly("space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.3.0-M1")
compileOnly("org.slf4j:slf4j-api:1.7.36") compileOnly("org.slf4j:slf4j-api:1.7.36")
compileOnly("net.byteflux:libby-core:1.1.5") compileOnly("net.byteflux:libby-core:1.1.5")
} }
@ -16,6 +15,6 @@ dependencies {
tasks { tasks {
shadowJar { shadowJar {
relocate("net.byteflux.libby", "me.adrianed.authmevelocity.libs.libby") 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() { public void loadLibraries() {
final String dazzlePackage = new String(new char[] { final Relocation configurateRelocation
's','p','a','c','e','.','a','r','i','m','.','d','a','z','z','l','e','c','o','n','f'}); = new Relocation("org{}spongepowered", "me.adrianed.authmevelocity.libs.sponge");
final Relocation dazzleRelocation final Relocation geantyrefRelocation =
= new Relocation(dazzlePackage, "me.adrianed.authmevelocity.libs.dazzleconf"); new Relocation("io{}leangen{}geantyref", "me.adrianed.authmevelocity.libs.geantyref");
final Relocation snakeYamlRelocation final Library hocon = Library.builder()
= new Relocation("org.yaml.snakeyaml", "me.adrianed.authmevelocity.libs.snakeyaml"); .groupId("org{}spongepowered")
final Library dazzleConf = Library.builder() .artifactId("configurate-hocon")
.groupId(dazzlePackage) .version(Constants.CONFIGURATE)
.artifactId("dazzleconf-core") .id("configurate-hocon")
.version("1.3.0-M1") .relocate(configurateRelocation)
.relocate(dazzleRelocation) .relocate(geantyrefRelocation)
.build(); .build();
final Library dazzleYaml = Library.builder() final Library confCore = Library.builder()
.groupId(dazzlePackage) .groupId("org{}spongepowered")
.artifactId("dazzleconf-ext-snakeyaml") .artifactId("configurate-core")
.version("1.3.0-M1") .version(Constants.CONFIGURATE)
.relocate(dazzleRelocation) .id("configurate-core")
.relocate(snakeYamlRelocation) .relocate(configurateRelocation)
.relocate(geantyrefRelocation)
.build(); .build();
final Library snakeYaml = Library.builder() final Library geantyref = Library.builder()
.groupId("org.yaml") .groupId("io{}leangen{}geantyref")
.artifactId("snakeyaml") .artifactId("geantyref")
.version("1.30") .version(Constants.GEANTYREF)
.relocate(dazzleRelocation) .id("geantyref")
.relocate(snakeYamlRelocation) .relocate(geantyrefRelocation)
.build(); .build();
manager.loadLibrary(snakeYaml); manager.loadLibrary(confCore);
manager.loadLibrary(dazzleConf); manager.loadLibrary(hocon);
manager.loadLibrary(dazzleYaml); 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; package me.adrianed.authmevelocity.common.configuration;
import java.nio.file.Path;
import org.slf4j.Logger; import org.slf4j.Logger;
import space.arim.dazzleconf.ConfigurationFactory; import org.spongepowered.configurate.CommentedConfigurationNode;
import space.arim.dazzleconf.ConfigurationOptions; import org.spongepowered.configurate.ConfigurateException;
import space.arim.dazzleconf.error.ConfigFormatSyntaxException; import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
import space.arim.dazzleconf.error.InvalidConfigException; import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import space.arim.dazzleconf.ext.snakeyaml.CommentMode; import org.spongepowered.configurate.objectmapping.meta.Comment;
import space.arim.dazzleconf.ext.snakeyaml.SnakeYamlConfigurationFactory;
import space.arim.dazzleconf.ext.snakeyaml.SnakeYamlOptions;
import space.arim.dazzleconf.helper.ConfigurationHelper;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Path;
public class Loader<C> { public class Loader {
private final ConfigurationHelper<C> configHelper; public static <C> ConfigurationContainer<C> loadMainConfig(final Path path, Class<C> clazz, Logger logger){
private volatile C configData; final HoconConfigurationLoader loader = HoconConfigurationLoader.builder()
private final Logger logger; .defaultOptions(opts -> opts
.shouldCopyDefaults(true)
private Loader(ConfigurationHelper<C> configHelper, Logger logger) { .header("AuthMeVelocity | by Glyart & 4drian3d\n")
this.configHelper = configHelper; )
this.logger = logger; .path(path.resolve("config.conf"))
}
public static <C> Loader<C> create(Path configFolder, String fileName, Class<C> configClass, Logger logger) {
SnakeYamlOptions yamlOptions = new SnakeYamlOptions.Builder()
.commentMode(CommentMode.alternativeWriter())
.build(); .build();
ConfigurationFactory<C> configFactory = SnakeYamlConfigurationFactory.create(
configClass,
ConfigurationOptions.defaults(),
yamlOptions);
return new Loader<>(new ConfigurationHelper<>(configFolder, fileName, configFactory), logger);
}
public boolean reloadConfig() { final C config;
try { try {
configData = configHelper.reloadConfigData(); final CommentedConfigurationNode node = loader.load();
return true; config = node.get(clazz);
} catch (IOException ex) { node.set(clazz, config);
throw new UncheckedIOException(ex); loader.save(node);
} catch (ConfigFormatSyntaxException ex) { } catch (ConfigurateException exception){
configData = configHelper.getFactory().loadDefaults(); logger.error("Could not load config.conf file", exception);
logger.error("The yaml syntax in your configuration is invalid. " return null;
+ "Check your YAML syntax with a tool such as https://yaml-online-parser.appspot.com/", ex); }
return false; return new ConfigurationContainer<>(config, clazz, loader, logger);
} 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;
} }
} }

View File

@ -1,66 +1,77 @@
package me.adrianed.authmevelocity.common.configuration; package me.adrianed.authmevelocity.common.configuration;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import org.spongepowered.configurate.objectmapping.meta.Comment;
import java.util.List; import java.util.List;
import space.arim.dazzleconf.annote.ConfDefault;
import space.arim.dazzleconf.annote.ConfComments;
public interface ProxyConfiguration { @ConfigSerializable
@ConfDefault.DefaultStrings({ public class ProxyConfiguration {
"auth1", "auth2" @Comment("List of login/registration servers")
}) private List<String> authServers = List.of("auth1", "auth2");
@ConfComments({ public List<String> authServers() {
"List of login/registration servers" return this.authServers;
})
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();
} }
public interface Commands { private SendOnLogin sendOnLogin = new SendOnLogin();
@ConfComments({ public SendOnLogin sendOnLogin() {
"Sets the commands that users who have not yet logged in can execute" return this.sendOnLogin;
})
@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();
} }
public interface EnsureAuthServer { private Commands commands = new Commands();
@ConfComments({ public Commands commands() {
"Ensure that the first server to which players connect is an auth server" return this.commands;
}) }
@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 { shadowJar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
relocate("net.byteflux.libby", "me.adrianed.authmevelocity.libs.libby") relocate("net.byteflux.libby", "me.adrianed.authmevelocity.libs.libby")
relocate("space.arim.dazzleconf", "me.adrianed.authmevelocity.libs.dazzleconf")
configurations = listOf(project.configurations.shadow.get()) configurations = listOf(project.configurations.shadow.get())
} }

View File

@ -28,7 +28,6 @@ tasks {
shadowJar { shadowJar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
relocate("net.byteflux.libby", "me.adrianed.authmevelocity.libs.libby") relocate("net.byteflux.libby", "me.adrianed.authmevelocity.libs.libby")
relocate("space.arim.dazzleconf", "me.adrianed.authmevelocity.libs.dazzleconf")
configurations = listOf(project.configurations.shadow.get()) 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.velocity.listener.ProxyListener;
import me.adrianed.authmevelocity.api.velocity.AuthMeVelocityAPI; import me.adrianed.authmevelocity.api.velocity.AuthMeVelocityAPI;
import me.adrianed.authmevelocity.common.LibsManager; 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.Loader;
import me.adrianed.authmevelocity.common.configuration.ProxyConfiguration; import me.adrianed.authmevelocity.common.configuration.ProxyConfiguration;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -58,7 +59,7 @@ public final class AuthMeVelocityPlugin implements AuthMeVelocityAPI {
private final ProxyServer proxy; private final ProxyServer proxy;
private final Logger logger; private final Logger logger;
private final Path pluginDirectory; private final Path pluginDirectory;
private Loader<ProxyConfiguration> config; private ConfigurationContainer<ProxyConfiguration> config;
protected final Set<UUID> loggedPlayers = ConcurrentHashMap.newKeySet(); protected final Set<UUID> loggedPlayers = ConcurrentHashMap.newKeySet();
@ -77,7 +78,7 @@ public final class AuthMeVelocityPlugin implements AuthMeVelocityAPI {
logger, pluginDirectory, proxy.getPluginManager(), this)); logger, pluginDirectory, proxy.getPluginManager(), this));
libraries.loadLibraries(); 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); proxy.getChannelRegistrar().register(AUTHMEVELOCITY_CHANNEL);
@ -110,14 +111,14 @@ public final class AuthMeVelocityPlugin implements AuthMeVelocityAPI {
source.sendMessage(MiniMessage.miniMessage().deserialize( source.sendMessage(MiniMessage.miniMessage().deserialize(
" <gray>--- <aqua>AuthMeVelocity</aqua> ---")); " <gray>--- <aqua>AuthMeVelocity</aqua> ---"));
source.sendMessage(MiniMessage.miniMessage().deserialize( source.sendMessage(MiniMessage.miniMessage().deserialize(
"<gray>AuthServers: <green>" + config.getConfig().authServers())); "<gray>AuthServers: <green>" + config.get().authServers()));
if (config.getConfig().sendOnLogin().sendToServerOnLogin()) { if (config.get().sendOnLogin().sendToServerOnLogin()) {
source.sendMessage(MiniMessage.miniMessage().deserialize( 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; return this.config;
} }
@ -153,16 +154,16 @@ public final class AuthMeVelocityPlugin implements AuthMeVelocityAPI {
@Override @Override
public boolean isAuthServer(RegisteredServer server){ public boolean isAuthServer(RegisteredServer server){
return config.getConfig().authServers().contains(server.getServerInfo().getName()); return config.get().authServers().contains(server.getServerInfo().getName());
} }
@Override @Override
public boolean isAuthServer(ServerConnection connection){ public boolean isAuthServer(ServerConnection connection){
return config.getConfig().authServers().contains(connection.getServerInfo().getName()); return config.get().authServers().contains(connection.getServerInfo().getName());
} }
@Override @Override
public boolean isAuthServer(String server){ public boolean isAuthServer(String server){
return config.getConfig().authServers().contains(server); return config.get().authServers().contains(server);
} }
} }

View File

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

View File

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

View File

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

View File

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