From 7f4d9329836d7d7fbfb04d1905d8b06cf6a4be83 Mon Sep 17 00:00:00 2001 From: Vinrobot Date: Mon, 7 Aug 2023 18:46:56 +0200 Subject: [PATCH] Load config from file --- .../client/MinecraftEmoteModClient.java | 14 +++++- .../vinrobot/mcemote/MinecraftEmoteMod.java | 19 +++++++ .../mcemote/config/ConfigurationService.java | 11 ++++ .../vinrobot/mcemote/config/TypedGson.java | 30 +++++++++++ .../config/impl/file/FileConfiguration.java | 17 +++++++ .../impl/file/FileConfigurationService.java | 50 +++++++++++++++++++ 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 src/main/java/net/vinrobot/mcemote/config/ConfigurationService.java create mode 100644 src/main/java/net/vinrobot/mcemote/config/TypedGson.java create mode 100644 src/main/java/net/vinrobot/mcemote/config/impl/file/FileConfiguration.java create mode 100644 src/main/java/net/vinrobot/mcemote/config/impl/file/FileConfigurationService.java diff --git a/src/client/java/net/vinrobot/mcemote/client/MinecraftEmoteModClient.java b/src/client/java/net/vinrobot/mcemote/client/MinecraftEmoteModClient.java index 20afbc9..62d659a 100644 --- a/src/client/java/net/vinrobot/mcemote/client/MinecraftEmoteModClient.java +++ b/src/client/java/net/vinrobot/mcemote/client/MinecraftEmoteModClient.java @@ -7,7 +7,7 @@ import net.vinrobot.mcemote.client.providers.IEmoteProvider; import net.vinrobot.mcemote.client.text.EmotesManager; import net.vinrobot.mcemote.config.Configuration; -import net.vinrobot.mcemote.config.impl.ConfigurationImpl; +import net.vinrobot.mcemote.config.ConfigurationService; import webpdecoderjn.WebPLoader; import java.io.IOException; @@ -27,7 +27,7 @@ public void onInitializeClient() { MinecraftEmoteMod.LOGGER.error("Failed to initialize WebPDecoder", e); } - final Configuration config = new ConfigurationImpl(); + final Configuration config = loadConfiguration(MinecraftEmoteMod.getConfigService()); final ServiceLoader serviceLoader = ServiceLoader.load(IEmoteProvider.class); final List providers = ListHelper.sort(serviceLoader); @@ -52,4 +52,14 @@ public void onInitializeClient() { } } } + + private Configuration loadConfiguration(final ConfigurationService service) { + try { + MinecraftEmoteMod.LOGGER.info("Loading config"); + return service.load(); + } catch (final IOException e) { + MinecraftEmoteMod.LOGGER.error("Failed to load config", e); + return service.create(); + } + } } diff --git a/src/main/java/net/vinrobot/mcemote/MinecraftEmoteMod.java b/src/main/java/net/vinrobot/mcemote/MinecraftEmoteMod.java index 325e196..39e3754 100644 --- a/src/main/java/net/vinrobot/mcemote/MinecraftEmoteMod.java +++ b/src/main/java/net/vinrobot/mcemote/MinecraftEmoteMod.java @@ -1,15 +1,30 @@ package net.vinrobot.mcemote; import net.fabricmc.api.ModInitializer; +import net.fabricmc.loader.api.FabricLoader; +import net.vinrobot.mcemote.config.ConfigurationService; +import net.vinrobot.mcemote.config.impl.file.FileConfigurationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.nio.file.Path; + public class MinecraftEmoteMod implements ModInitializer { // This logger is used to write text to the console and the log file. // It is considered best practice to use your mod id as the logger's name. // That way, it's clear which mod wrote info, warnings, and errors. public static final Logger LOGGER = LoggerFactory.getLogger("MCEmote"); + private static ConfigurationService configService; + + public static ConfigurationService getConfigService() { + ConfigurationService ret = configService; + if (ret == null) { + throw new RuntimeException("Configuration service not yet available!"); + } + return ret; + } + @Override public void onInitialize() { // This code runs as soon as Minecraft is in a mod-load-ready state. @@ -17,5 +32,9 @@ public void onInitialize() { // Proceed with mild caution. LOGGER.info("Hello Fabric world!"); + + final Path configDir = FabricLoader.getInstance().getConfigDir(); + final Path configFile = configDir.resolve("mcemote.json"); + configService = new FileConfigurationService(configFile); } } diff --git a/src/main/java/net/vinrobot/mcemote/config/ConfigurationService.java b/src/main/java/net/vinrobot/mcemote/config/ConfigurationService.java new file mode 100644 index 0000000..fd74b60 --- /dev/null +++ b/src/main/java/net/vinrobot/mcemote/config/ConfigurationService.java @@ -0,0 +1,11 @@ +package net.vinrobot.mcemote.config; + +import java.io.IOException; + +public interface ConfigurationService { + Configuration create(); + + Configuration load() throws IOException; + + void save(Configuration config) throws IOException; +} diff --git a/src/main/java/net/vinrobot/mcemote/config/TypedGson.java b/src/main/java/net/vinrobot/mcemote/config/TypedGson.java new file mode 100644 index 0000000..19b10a5 --- /dev/null +++ b/src/main/java/net/vinrobot/mcemote/config/TypedGson.java @@ -0,0 +1,30 @@ +package net.vinrobot.mcemote.config; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; + +import java.io.Reader; + +public class TypedGson { + private static final Gson DEFAULT_GSON = new GsonBuilder().setPrettyPrinting().create(); + + private final Gson gson; + + public TypedGson() { + this(DEFAULT_GSON); + } + + public TypedGson(final Gson gson) { + this.gson = gson; + } + + public void toJson(S serializable, Appendable writer) throws JsonIOException { + this.gson.toJson(serializable, writer); + } + + public T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { + return this.gson.fromJson(json, classOfT); + } +} diff --git a/src/main/java/net/vinrobot/mcemote/config/impl/file/FileConfiguration.java b/src/main/java/net/vinrobot/mcemote/config/impl/file/FileConfiguration.java new file mode 100644 index 0000000..6a815e7 --- /dev/null +++ b/src/main/java/net/vinrobot/mcemote/config/impl/file/FileConfiguration.java @@ -0,0 +1,17 @@ +package net.vinrobot.mcemote.config.impl.file; + +import net.vinrobot.mcemote.config.Configuration; + +import java.util.Optional; + +class FileConfiguration { + public String twitchId; + + public void copyFrom(final Configuration domain) { + this.twitchId = domain.twitchId().get(); + } + + public void copyTo(final Configuration configuration) { + configuration.twitchId().set(Optional.ofNullable(this.twitchId)); + } +} diff --git a/src/main/java/net/vinrobot/mcemote/config/impl/file/FileConfigurationService.java b/src/main/java/net/vinrobot/mcemote/config/impl/file/FileConfigurationService.java new file mode 100644 index 0000000..f50594f --- /dev/null +++ b/src/main/java/net/vinrobot/mcemote/config/impl/file/FileConfigurationService.java @@ -0,0 +1,50 @@ +package net.vinrobot.mcemote.config.impl.file; + +import net.vinrobot.mcemote.config.Configuration; +import net.vinrobot.mcemote.config.ConfigurationService; +import net.vinrobot.mcemote.config.TypedGson; +import net.vinrobot.mcemote.config.impl.ConfigurationImpl; + +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; + +public class FileConfigurationService implements ConfigurationService { + private final TypedGson gson = new TypedGson<>(); + private final Path configFile; + + public FileConfigurationService(final Path configFile) { + this.configFile = configFile; + } + + @Override + public Configuration create() { + return new ConfigurationImpl(); + } + + @Override + public Configuration load() throws IOException { + FileConfiguration fileConfiguration; + try (final Reader reader = Files.newBufferedReader(this.configFile)) { + fileConfiguration = this.gson.fromJson(reader, FileConfiguration.class); + } + + final Configuration config = this.create(); + if (fileConfiguration != null) { + fileConfiguration.copyTo(config); + } + return config; + } + + @Override + public void save(final Configuration configuration) throws IOException { + final FileConfiguration fileConfiguration = new FileConfiguration(); + fileConfiguration.copyFrom(configuration); + + try (final Writer writer = Files.newBufferedWriter(this.configFile)) { + this.gson.toJson(fileConfiguration, writer); + } + } +}