diff --git a/TShockAPI/ConfigFile.cs b/TShockAPI/ConfigFile.cs
index acfeb61a..b65c5402 100644
--- a/TShockAPI/ConfigFile.cs
+++ b/TShockAPI/ConfigFile.cs
@@ -602,14 +602,21 @@ namespace TShockAPI
/// Reads a configuration file from a given path
///
/// string path
- /// ConfigFile object
- public static ConfigFile Read(string path)
+ /// The path to the config file
+ ///
+ /// Whether the config object has any new files in it, meaning that the config file has to be
+ /// overwritten.
+ ///
+ public static ConfigFile Read(string path, out bool anyMissingFields)
{
if (!File.Exists(path))
+ {
+ anyMissingFields = true;
return new ConfigFile();
+ }
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
- return Read(fs);
+ return Read(fs, out anyMissingFields);
}
}
@@ -617,14 +624,17 @@ namespace TShockAPI
/// Reads the configuration file from a stream
///
/// stream
+ ///
+ /// Whether the config object has any new fields in it, meaning that the config file has to be
+ /// overwritten.
+ ///
/// ConfigFile object
- public static ConfigFile Read(Stream stream)
+ public static ConfigFile Read(Stream stream, out bool anyMissingFields)
{
using (var sr = new StreamReader(stream))
{
- var cf = JsonConvert.DeserializeObject(sr.ReadToEnd());
- if (ConfigRead != null)
- ConfigRead(cf);
+ var cf = FileTools.LoadConfigAndCheckForMissingFields(sr.ReadToEnd(), out anyMissingFields);
+ ConfigRead?.Invoke(cf);
return cf;
}
}
diff --git a/TShockAPI/DB/GroupManager.cs b/TShockAPI/DB/GroupManager.cs
index ceb8e433..eae7df43 100644
--- a/TShockAPI/DB/GroupManager.cs
+++ b/TShockAPI/DB/GroupManager.cs
@@ -389,7 +389,7 @@ namespace TShockAPI.DB
}
// Read the config file to prevent the possible loss of any unsaved changes
- TShock.Config = ConfigFile.Read(FileTools.ConfigPath);
+ TShock.Config = ConfigFile.Read(FileTools.ConfigPath, out bool writeConfig);
if (TShock.Config.DefaultGuestGroupName == oldGroup.Name)
{
TShock.Config.DefaultGuestGroupName = newGroup.Name;
@@ -399,7 +399,10 @@ namespace TShockAPI.DB
{
TShock.Config.DefaultRegistrationGroupName = newGroup.Name;
}
- TShock.Config.Write(FileTools.ConfigPath);
+ if (writeConfig)
+ {
+ TShock.Config.Write(FileTools.ConfigPath);
+ }
// We also need to check if any users belong to the old group and automatically apply changes
using (var command = db.CreateCommand())
diff --git a/TShockAPI/FileTools.cs b/TShockAPI/FileTools.cs
index 314c7c5a..7b421213 100644
--- a/TShockAPI/FileTools.cs
+++ b/TShockAPI/FileTools.cs
@@ -16,9 +16,13 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
+using System.Linq;
using TShockAPI.ServerSideCharacters;
namespace TShockAPI
@@ -103,23 +107,26 @@ namespace TShockAPI
CreateIfNot(MotdPath, MotdFormat);
CreateIfNot(WhitelistPath);
+ bool writeConfig = true; // Default to true if the file doesn't exist
if (File.Exists(ConfigPath))
{
- TShock.Config = ConfigFile.Read(ConfigPath);
- // Add all the missing config properties in the json file
+ TShock.Config = ConfigFile.Read(ConfigPath, out writeConfig);
}
- else
+ if (writeConfig)
{
+ // Add all the missing config properties in the json file
TShock.Config.Write(ConfigPath);
}
+ bool writeSSCConfig = true; // Default to true if the file doesn't exist
if (File.Exists(ServerSideCharacterConfigPath))
{
- TShock.ServerSideCharacterConfig = ServerSideConfig.Read(ServerSideCharacterConfigPath);
- // Add all the missing config properties in the json file
+ TShock.ServerSideCharacterConfig =
+ ServerSideConfig.Read(ServerSideCharacterConfigPath, out writeSSCConfig);
}
- else
+ if (writeSSCConfig)
{
+ // Add all the missing config properties in the json file
TShock.ServerSideCharacterConfig = new ServerSideConfig
{
StartingInventory =
@@ -166,5 +173,30 @@ namespace TShockAPI
return true;
}
}
+
+ ///
+ /// Parse some json text and also return whether any fields are missing from the json
+ ///
+ /// The type of the config file object
+ /// The json text to parse
+ /// Whether any fields are missing from the config
+ /// The config object
+ internal static T LoadConfigAndCheckForMissingFields(string json, out bool anyMissingFields)
+ {
+ JObject jObject = JObject.Parse(json);
+
+ anyMissingFields = false;
+ var configFields = new HashSet(typeof(T).GetFields()
+ .Where(field => !field.IsStatic)
+ .Select(field => field.Name));
+ var jsonFields = new HashSet(jObject
+ .Children()
+ .Select(field => field as JProperty)
+ .Where(field => field != null)
+ .Select(field => field.Name));
+ anyMissingFields = !configFields.SetEquals(jsonFields);
+
+ return jObject.ToObject();
+ }
}
-}
\ No newline at end of file
+}
diff --git a/TShockAPI/ServerSideCharacters/ServerSideConfig.cs b/TShockAPI/ServerSideCharacters/ServerSideConfig.cs
index b1c6f6da..701dce11 100644
--- a/TShockAPI/ServerSideCharacters/ServerSideConfig.cs
+++ b/TShockAPI/ServerSideCharacters/ServerSideConfig.cs
@@ -46,13 +46,22 @@ namespace TShockAPI.ServerSideCharacters
[Description("The starting default inventory for new SSC.")]
public List StartingInventory = new List();
- public static ServerSideConfig Read(string path)
+ ///
+ /// Reads a server-side configuration file from a given path
+ ///
+ /// The path to the config file
+ ///
+ /// Whether the config object has any new fields in it, meaning that the config file has to be
+ /// overwritten.
+ ///
+ /// ConfigFile object
+ public static ServerSideConfig Read(string path, out bool anyMissingFields)
{
using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var reader = new StreamReader(fileStream))
{
string txt = reader.ReadToEnd();
- var config = JsonConvert.DeserializeObject(txt);
+ var config = FileTools.LoadConfigAndCheckForMissingFields(txt, out anyMissingFields);
return config;
}
}