using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using Revitalize.Framework.Utilities.Serialization.ContractResolvers; using StardewValley; using StardewValley.Objects; namespace Revitalize.Framework.Utilities { /// /// Handles serialization of all objects in existence. /// /// TODO: Make JConvert that has same settings to implement a toJSon string obj /// public class Serializer { private JsonSerializer serializer; /// /// All files to be cleaned up after loading. /// private Dictionary> filesToDelete = new Dictionary>(); public List itemsToRemove = new List(); private JsonSerializerSettings settings; /// /// Constructor. /// public Serializer() { this.serializer = new JsonSerializer(); this.serializer.Formatting = Formatting.Indented; this.serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; this.serializer.NullValueHandling = NullValueHandling.Include; this.serializer.ContractResolver = new NetFieldContract(); this.addConverter(new Framework.Utilities.Serialization.Converters.RectangleConverter()); this.addConverter(new Framework.Utilities.Serialization.Converters.Texture2DConverter()); this.addConverter(new Framework.Utilities.Serialization.Converters.ItemCoverter()); //this.addConverter(new Framework.Utilities.Serialization.Converters.NetFieldConverter()); //this.addConverter(new Framework.Utilities.Serialization.Converters.Vector2Converter()); this.gatherAllFilesForCleanup(); this.settings = new JsonSerializerSettings(); foreach(JsonConverter converter in this.serializer.Converters) { this.settings.Converters.Add(converter); } this.settings.Formatting = Formatting.Indented; this.settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; this.settings.NullValueHandling = NullValueHandling.Include; this.settings.ContractResolver = new NetFieldContract(); } /// /// Process all the save data for objects to be deleted by this mod. /// private void gatherAllFilesForCleanup() { if (!Directory.Exists(Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData"))) Directory.CreateDirectory(Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData")); this.filesToDelete.Clear(); string[] directories = Directory.GetDirectories(Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData")); foreach (string playerData in directories) { string objectPath = Path.Combine(playerData, "SavedObjectInformation"); string[] objectFiles = Directory.GetFiles(objectPath); foreach (string file in objectFiles) { string playerName = new DirectoryInfo(objectPath).Parent.Name; if (this.filesToDelete.ContainsKey(playerName)){ this.filesToDelete[playerName].Add(file); //Revitalize.ModCore.log("Added File: " + file); } else { this.filesToDelete.Add(playerName, new List()); //Revitalize.ModCore.log("Added Player Key: " + playerName); this.filesToDelete[playerName].Add(file); //Revitalize.ModCore.log("Added File: " + file); } } } } /// /// Called after load to deal with internal file cleanUp /// public void afterLoad() { this.deleteAllUnusedFiles(); this.removeNullObjects(); } public void returnToTitle() { this.gatherAllFilesForCleanup(); } private void removeNullObjects() { List removalList = new List(); foreach(Item I in Game1.player.Items) { if (I == null) continue; if (I.DisplayName.Contains("Revitalize.Framework") && (I is Chest)) { removalList.Add(I); } } foreach(Item I in removalList) { Game1.player.Items.Remove(I); } } /// /// Removes the file from all files that will be deleted. /// /// /// private void removeFileFromDeletion(string playerDirectory, string fileName) { if (this.filesToDelete.ContainsKey(playerDirectory)) { //Revitalize.ModCore.log("Removing from deletion: " + fileName); this.filesToDelete[playerDirectory].Remove(fileName); } else { //Revitalize.ModCore.log("Found key: " + playerDirectory); //Revitalize.ModCore.log("Found file: " + fileName); } } /// /// Deletes unused object data. /// private void deleteAllUnusedFiles() { foreach(KeyValuePair> pair in this.filesToDelete) { foreach (string file in pair.Value) { File.Delete(file); } } } /// /// Adds a new converter to the json serializer. /// /// The type of json converter to add to the Serializer. public void addConverter(JsonConverter converter) { this.serializer.Converters.Add(converter); } /// /// Deserializes an object from a .json file. /// /// The type of object to deserialize into. /// The path to the file. /// An object of specified type T. public T Deserialize(string p) { string json = ""; foreach (string line in File.ReadLines(p)) { json += line; } using (StreamReader sw = new StreamReader(p)) using (JsonReader reader = new JsonTextReader(sw)) { var obj = this.serializer.Deserialize(reader); return obj; } } /// /// Deserializes an object from a .json file. /// /// The type of object to deserialize into. /// The path to the file. /// An object of specified type T. public object Deserialize(string p,Type T) { string json = ""; foreach (string line in File.ReadLines(p)) { json += line; } using (StreamReader sw = new StreamReader(p)) using (JsonReader reader = new JsonTextReader(sw)) { object obj = this.serializer.Deserialize(reader,T); return obj; } } /// /// Serializes an object to a .json file. /// /// /// public void Serialize(string path, object o) { using (StreamWriter sw = new StreamWriter(path)) using (JsonWriter writer = new JsonTextWriter(sw)) { this.serializer.Serialize(writer, o); } } /// /// Serialize a data structure into an file. /// /// /// public void SerializeGUID(string fileName,object obj) { string path = Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData", Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID, "SavedObjectInformation", fileName + ".json"); Directory.CreateDirectory(Path.GetDirectoryName(path)); this.Serialize(path, obj); } /// /// Deserialze a file into it's proper data structure. /// /// The type of data structure to deserialze to. /// The name of the file to deserialize from. /// A data structure object deserialize from a json string in a file. public object DeserializeGUID(string fileName,Type T) { string path=Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData", Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID, "SavedObjectInformation", fileName + ".json"); this.removeFileFromDeletion((Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID), path); return this.Deserialize(path, T); } /// /// Deserialze a file into it's proper data structure. /// /// The type of data structure to deserialze to. /// The name of the file to deserialize from. /// A data structure object deserialize from a json string in a file. public T DeserializeGUID(string fileName) { string path = Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData", Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID, "SavedObjectInformation", fileName + ".json"); this.removeFileFromDeletion((Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID),path); if (File.Exists(path)) { return this.Deserialize(path); } else { return default(T); } } /// /// Converts objects to json form. /// /// /// public string ToJSONString(object o) { return JsonConvert.SerializeObject(o, this.settings); } /// /// Converts from json form to objects. /// /// /// /// public T DeserializeFromJSONString(string info) { return JsonConvert.DeserializeObject(info,this.settings); } /// /// Converts from json form to objects. /// /// /// /// public object DeserializeFromJSONString(string info, Type T) { return JsonConvert.DeserializeObject(info, T, this.settings); } public T DeserializeContentFile(string pathToFile) { if (File.Exists(pathToFile)) { return this.Deserialize(pathToFile); } else { return default(T); } } public void SerializeContentFile(string fileName, object obj,string extensionFolder) { string path = Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "Content", extensionFolder,fileName+ ".json"); Directory.CreateDirectory(Path.GetDirectoryName(path)); if (File.Exists(path)) return; this.Serialize(path, obj); } } }