From 27dece2cf445147c5e2848f9ec26f38a101f50fc Mon Sep 17 00:00:00 2001 From: Gormogon Date: Sun, 29 May 2016 18:23:01 -0400 Subject: Attempt to migrate to new directory structure. --- src/StardewModdingAPI/Config.cs | 176 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 src/StardewModdingAPI/Config.cs (limited to 'src/StardewModdingAPI/Config.cs') diff --git a/src/StardewModdingAPI/Config.cs b/src/StardewModdingAPI/Config.cs new file mode 100644 index 00000000..c5b7beca --- /dev/null +++ b/src/StardewModdingAPI/Config.cs @@ -0,0 +1,176 @@ +/* + Copyright 2016 Zoey (Zoryn) +*/ + +using System; +using System.IO; +using System.Linq; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace StardewModdingAPI +{ + public class Config + { + [JsonIgnore] + public virtual string ConfigLocation { get; protected internal set; } + + [JsonIgnore] + public virtual string ConfigDir => Path.GetDirectoryName(ConfigLocation); + + public virtual Config Instance() where T : Config => Activator.CreateInstance(); + + /// + /// Loads the config from the json blob on disk, updating and re-writing to the disk if needed. + /// + /// + /// + public virtual T LoadConfig() where T : Config + { + if (string.IsNullOrEmpty(ConfigLocation)) + { + Log.AsyncR("A config tried to load without specifying a location on the disk."); + return null; + } + + T ret = null; + + if (!File.Exists(ConfigLocation)) + { + //no config exists, generate default values + var c = GenerateDefaultConfig(); + c.ConfigLocation = ConfigLocation; + ret = c; + } + else + { + try + { + //try to load the config from a json blob on disk + var c = JsonConvert.DeserializeObject(File.ReadAllText(ConfigLocation), new JsonSerializerSettings {ContractResolver = new JsonResolver()}); + + c.ConfigLocation = ConfigLocation; + + //update the config with default values if needed + ret = c.UpdateConfig(); + + c = null; + } + catch (Exception ex) + { + Log.AsyncR($"Invalid JSON ({GetType().Name}): {ConfigLocation} \n{ex}"); + return GenerateDefaultConfig(); + } + } + + ret.WriteConfig(); + return ret; + } + + /// + /// MUST be implemented in inheriting class! + /// + public virtual T GenerateDefaultConfig() where T : Config + { + return null; + } + + /// + /// Merges a default-value config with the user-config on disk. + /// + /// + /// + public virtual T UpdateConfig() where T : Config + { + try + { + //default config + var b = JObject.FromObject(Instance().GenerateDefaultConfig(), new JsonSerializer {ContractResolver = new JsonResolver()}); + + //user config + var u = JObject.FromObject(this, new JsonSerializer {ContractResolver = new JsonResolver()}); + + //overwrite default values with user values + b.Merge(u, new JsonMergeSettings {MergeArrayHandling = MergeArrayHandling.Replace}); + + //cast json object to config + var c = b.ToObject(); + + //re-write the location on disk to the object + c.ConfigLocation = ConfigLocation; + + return c; + } + catch (Exception ex) + { + Log.AsyncR("An error occured when updating a config: " + ex); + return this as T; + } + } + } + + public static class ConfigExtensions + { + /// + /// Initializes an instance of any class that inherits from Config. + /// This method performs the loading, saving, and merging of the config on the disk and in memory at a default state. + /// This method should not be used to re-load or to re-save a config. + /// NOTE: You MUST set your config EQUAL to the return of this method! + /// + /// + /// + /// + /// + public static T InitializeConfig(this T baseConfig, string configLocation) where T : Config + { + if (baseConfig == null) + { + baseConfig = Activator.CreateInstance(); + /* + Log.AsyncR("A config tried to initialize whilst being null."); + return null; + */ + } + + if (string.IsNullOrEmpty(configLocation)) + { + Log.AsyncR("A config tried to initialize without specifying a location on the disk."); + return null; + } + + baseConfig.ConfigLocation = configLocation; + var c = baseConfig.LoadConfig(); + + return c; + } + + /// + /// Writes a config to a json blob on the disk specified in the config's properties. + /// + public static void WriteConfig(this T baseConfig) where T : Config + { + if (string.IsNullOrEmpty(baseConfig?.ConfigLocation) || string.IsNullOrEmpty(baseConfig.ConfigDir)) + { + Log.AsyncR("A config attempted to save when it itself or it's location were null."); + return; + } + + var s = JsonConvert.SerializeObject(baseConfig, typeof(T), Formatting.Indented, new JsonSerializerSettings {ContractResolver = new JsonResolver()}); + + if (!Directory.Exists(baseConfig.ConfigDir)) + Directory.CreateDirectory(baseConfig.ConfigDir); + + if (!File.Exists(baseConfig.ConfigLocation) || !File.ReadAllText(baseConfig.ConfigLocation).SequenceEqual(s)) + File.WriteAllText(baseConfig.ConfigLocation, s); + } + + /// + /// Re-reads the json blob on the disk and merges its values with a default config. + /// NOTE: You MUST set your config EQUAL to the return of this method! + /// + public static T ReloadConfig(this T baseConfig) where T : Config + { + return baseConfig.LoadConfig(); + } + } +} \ No newline at end of file -- cgit