From f87b6156f4d00403c656a8ccb992b3b579553407 Mon Sep 17 00:00:00 2001
From: Chris <2648373+QuiCM@users.noreply.github.com>
Date: Thu, 28 Jan 2021 19:31:09 +1030
Subject: [PATCH] Update config upgrades to be a bit more robust
---
TShockAPI/Configuration/TShockConfig.cs | 2 +-
TShockAPI/FileTools.cs | 38 ++++++++++++++++---------
2 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/TShockAPI/Configuration/TShockConfig.cs b/TShockAPI/Configuration/TShockConfig.cs
index 332b58ba..25b72c31 100644
--- a/TShockAPI/Configuration/TShockConfig.cs
+++ b/TShockAPI/Configuration/TShockConfig.cs
@@ -600,7 +600,7 @@ namespace TShockAPI.Configuration
///
public override TShockSettings ConvertJson(string json, out bool incompleteSettings)
{
- var settings = FileTools.LoadConfigAndCheckForMissingFields(FileTools.AttemptConfigUpgrade(json), out incompleteSettings);
+ var settings = FileTools.LoadConfigAndCheckForMissingFields(json, out incompleteSettings);
Settings = settings;
OnConfigRead?.Invoke(this);
diff --git a/TShockAPI/FileTools.cs b/TShockAPI/FileTools.cs
index 9c52847b..9c983369 100644
--- a/TShockAPI/FileTools.cs
+++ b/TShockAPI/FileTools.cs
@@ -172,16 +172,17 @@ namespace TShockAPI
return true;
}
}
-
+
///
/// Looks for a 'Settings' token in the json object. If one is not found, returns a new json object with all tokens of the previous object added
/// as children to a root 'Settings' token
///
- ///
+ ///
+ ///
///
- internal static JObject AttemptConfigUpgrade(string json)
+ internal static JObject AttemptConfigUpgrade(JObject cfg, out bool requiredUpgrade)
{
- JObject cfg = JObject.Parse(json);
+ requiredUpgrade = false;
if (cfg.SelectToken("Settings") == null)
{
@@ -190,40 +191,51 @@ namespace TShockAPI
{ "Settings", cfg }
};
cfg = newCfg;
+ requiredUpgrade = true;
}
return cfg;
}
- internal static TSettings LoadConfigAndCheckForMissingFields(string json, out bool anyMissingFields) where TSettings : new()
+ internal static TSettings LoadConfigAndCheckForMissingFields(string json, out bool writeConfig) where TSettings : new()
{
- return LoadConfigAndCheckForMissingFields(JObject.Parse(json), out anyMissingFields);
+ //If an empty file is attempting to be loaded as a config, instead use an empty json object. Otherwise Newtonsoft throws an exception here
+ if (string.IsNullOrWhiteSpace(json))
+ {
+ json = "{}";
+ }
+
+ return LoadConfigAndCheckForMissingFields(JObject.Parse(json), out writeConfig);
}
///
- /// Parses a JObject into a TSettings object, also emitting a bool indicating if any of the TSetting's fields were missing from the JObject
+ /// Parses a JObject into a TSettings object, also emitting a bool indicating if the JObject was incomplete
///
/// The type of the config file object
/// The json object to parse
- /// Whether any fields are missing from the config
+ /// Whether the config needs to be written to disk again
/// The config object
- internal static TSettings LoadConfigAndCheckForMissingFields(JObject jObject, out bool anyMissingFields) where TSettings : new()
+ internal static TSettings LoadConfigAndCheckForMissingFields(JObject jObject, out bool writeConfig) where TSettings : new()
{
- anyMissingFields = false;
+ JObject cfg = AttemptConfigUpgrade(jObject, out bool requiredUpgrade);
var configFields = new HashSet(typeof(TSettings).GetFields()
.Where(field => !field.IsStatic)
.Select(field => field.Name));
- var jsonFields = new HashSet(jObject.SelectToken("Settings")
+ var jsonFields = new HashSet(cfg.SelectToken("Settings")
.Children()
.Select(field => field as JProperty)
.Where(field => field != null)
.Select(field => field.Name));
- anyMissingFields = !configFields.SetEquals(jsonFields);
+ bool missingFields = !configFields.SetEquals(jsonFields);
- return jObject.SelectToken("Settings").ToObject();
+
+ //If the config file had to be upgraded or the fields in the given TSettings don't match the config, we'll want the config to be rewritten with the correct data
+ writeConfig = requiredUpgrade || missingFields;
+
+ return cfg.SelectToken("Settings").ToObject();
}
}
}