2019-01-09 20:03:27 +08:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Text;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Newtonsoft.Json;
|
2019-09-01 09:23:47 +08:00
|
|
|
using PyTK.CustomElementHandler;
|
2019-08-22 11:17:27 +08:00
|
|
|
using Revitalize.Framework.Objects;
|
2019-08-27 07:34:03 +08:00
|
|
|
using Revitalize.Framework.Objects.Furniture;
|
2019-01-11 03:09:51 +08:00
|
|
|
using Revitalize.Framework.Utilities.Serialization.ContractResolvers;
|
2019-08-28 10:27:34 +08:00
|
|
|
using Revitalize.Framework.Utilities.Serialization.Converters;
|
2019-01-11 15:24:55 +08:00
|
|
|
using StardewValley;
|
2019-01-13 03:25:45 +08:00
|
|
|
using StardewValley.Objects;
|
2019-01-09 20:03:27 +08:00
|
|
|
|
|
|
|
namespace Revitalize.Framework.Utilities
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// Handles serialization of all objects in existence.
|
|
|
|
/// </summary>
|
|
|
|
public class Serializer
|
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
/// <summary>
|
|
|
|
/// The actual json serializer.
|
|
|
|
/// </summary>
|
2019-01-09 20:03:27 +08:00
|
|
|
private JsonSerializer serializer;
|
|
|
|
|
2019-01-13 02:40:47 +08:00
|
|
|
/// <summary>
|
|
|
|
/// All files to be cleaned up after loading.
|
|
|
|
/// </summary>
|
|
|
|
private Dictionary<string, List<string>> filesToDelete = new Dictionary<string, List<string>>();
|
|
|
|
|
2019-08-23 04:43:11 +08:00
|
|
|
/// <summary>
|
|
|
|
/// The items to remove for deletion.
|
|
|
|
/// </summary>
|
|
|
|
private List<Item> itemsToRemove = new List<Item>();
|
2019-01-13 02:40:47 +08:00
|
|
|
|
2019-08-23 04:43:11 +08:00
|
|
|
/// <summary>
|
|
|
|
/// The settings used by the seralizer
|
|
|
|
/// </summary>
|
2019-01-14 06:46:31 +08:00
|
|
|
private JsonSerializerSettings settings;
|
2019-01-13 02:40:47 +08:00
|
|
|
|
2019-08-28 10:27:34 +08:00
|
|
|
|
|
|
|
public static NetFieldConverter NetFieldConverter;
|
2019-01-09 20:03:27 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Constructor.
|
|
|
|
/// </summary>
|
|
|
|
public Serializer()
|
|
|
|
{
|
|
|
|
this.serializer = new JsonSerializer();
|
|
|
|
this.serializer.Formatting = Formatting.Indented;
|
|
|
|
this.serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
|
|
|
this.serializer.NullValueHandling = NullValueHandling.Include;
|
|
|
|
|
2019-08-27 07:34:03 +08:00
|
|
|
this.serializer.ContractResolver = new NetFieldContract();
|
2019-08-28 10:27:34 +08:00
|
|
|
NetFieldConverter = new NetFieldConverter();
|
2019-01-11 03:09:51 +08:00
|
|
|
|
2019-01-09 20:03:27 +08:00
|
|
|
this.addConverter(new Framework.Utilities.Serialization.Converters.RectangleConverter());
|
|
|
|
this.addConverter(new Framework.Utilities.Serialization.Converters.Texture2DConverter());
|
2019-01-11 10:15:31 +08:00
|
|
|
this.addConverter(new Framework.Utilities.Serialization.Converters.ItemCoverter());
|
2019-08-28 10:27:34 +08:00
|
|
|
this.addConverter(NetFieldConverter);
|
2019-08-22 10:06:17 +08:00
|
|
|
//this.addConverter(new Framework.Utilities.Serialization.Converters.CustomObjectDataConverter());
|
2019-01-11 05:37:35 +08:00
|
|
|
//this.addConverter(new Framework.Utilities.Serialization.Converters.NetFieldConverter());
|
2019-01-09 20:03:27 +08:00
|
|
|
//this.addConverter(new Framework.Utilities.Serialization.Converters.Vector2Converter());
|
2019-01-13 02:40:47 +08:00
|
|
|
|
2019-08-22 10:06:17 +08:00
|
|
|
//this.gatherAllFilesForCleanup();
|
2019-01-13 02:40:47 +08:00
|
|
|
|
2019-01-14 06:46:31 +08:00
|
|
|
this.settings = new JsonSerializerSettings();
|
2019-08-23 04:43:11 +08:00
|
|
|
foreach (JsonConverter converter in this.serializer.Converters)
|
2019-01-14 06:46:31 +08:00
|
|
|
{
|
|
|
|
this.settings.Converters.Add(converter);
|
|
|
|
}
|
|
|
|
this.settings.Formatting = Formatting.Indented;
|
|
|
|
this.settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
|
|
|
|
this.settings.NullValueHandling = NullValueHandling.Include;
|
2019-08-27 07:34:03 +08:00
|
|
|
this.settings.ContractResolver = new NetFieldContract();
|
2019-01-13 02:40:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Process all the save data for objects to be deleted by this mod.
|
|
|
|
/// </summary>
|
|
|
|
private void gatherAllFilesForCleanup()
|
|
|
|
{
|
2019-05-16 03:42:48 +08:00
|
|
|
if (!Directory.Exists(Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData"))) Directory.CreateDirectory(Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData"));
|
2019-01-13 03:25:45 +08:00
|
|
|
this.filesToDelete.Clear();
|
2019-01-13 02:40:47 +08:00
|
|
|
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;
|
2019-08-23 04:43:11 +08:00
|
|
|
if (this.filesToDelete.ContainsKey(playerName))
|
|
|
|
{
|
2019-01-13 02:40:47 +08:00
|
|
|
this.filesToDelete[playerName].Add(file);
|
|
|
|
//Revitalize.ModCore.log("Added File: " + file);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.filesToDelete.Add(playerName, new List<string>());
|
|
|
|
//Revitalize.ModCore.log("Added Player Key: " + playerName);
|
|
|
|
this.filesToDelete[playerName].Add(file);
|
|
|
|
//Revitalize.ModCore.log("Added File: " + file);
|
|
|
|
}
|
2019-08-23 04:43:11 +08:00
|
|
|
|
2019-01-13 02:40:47 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-22 10:06:17 +08:00
|
|
|
private void deleteFilesBeforeSave()
|
|
|
|
{
|
|
|
|
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 (playerName != this.getUniqueCharacterString()) return;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
File.Delete(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-13 02:40:47 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Called after load to deal with internal file cleanUp
|
|
|
|
/// </summary>
|
|
|
|
public void afterLoad()
|
|
|
|
{
|
2019-09-22 17:32:59 +08:00
|
|
|
ModCore.log("WHAT");
|
2019-05-16 03:42:48 +08:00
|
|
|
this.deleteAllUnusedFiles();
|
2019-08-22 11:17:27 +08:00
|
|
|
//this.removeNullObjects();
|
2019-08-27 07:34:03 +08:00
|
|
|
this.restoreModObjects();
|
2019-08-22 11:17:27 +08:00
|
|
|
}
|
|
|
|
|
2019-08-23 04:43:11 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Restore mod objects to inventories and world after load.
|
|
|
|
/// </summary>
|
2019-08-22 11:17:27 +08:00
|
|
|
public void restoreModObjects()
|
|
|
|
{
|
2019-09-23 02:12:07 +08:00
|
|
|
//ModCore.log("Restore all mod objects!");
|
2019-08-23 04:43:11 +08:00
|
|
|
//Replace all items in the world.
|
2019-08-28 15:31:14 +08:00
|
|
|
List<CustomObject> objsToRestore = new List<CustomObject>();
|
2019-08-22 11:17:27 +08:00
|
|
|
foreach (var v in ModCore.ObjectGroups)
|
|
|
|
{
|
|
|
|
foreach (var obj in v.Value.objects.Values)
|
|
|
|
{
|
2019-08-28 15:31:14 +08:00
|
|
|
//(obj as CustomObject).replaceAfterLoad();
|
|
|
|
objsToRestore.Add(obj as CustomObject);
|
2019-08-22 11:17:27 +08:00
|
|
|
}
|
|
|
|
}
|
2019-08-28 15:31:14 +08:00
|
|
|
foreach(CustomObject o in objsToRestore)
|
|
|
|
{
|
|
|
|
(o as CustomObject).replaceAfterLoad();
|
|
|
|
}
|
|
|
|
|
2019-08-23 04:43:11 +08:00
|
|
|
//Replace all held items or items in inventories.
|
|
|
|
foreach (GameLocation loc in LocationUtilities.GetAllLocations())
|
2019-08-22 11:17:27 +08:00
|
|
|
{
|
2019-09-23 02:12:07 +08:00
|
|
|
//ModCore.log("Looking at location: " + loc);
|
2019-08-22 11:17:27 +08:00
|
|
|
foreach (StardewValley.Object c in loc.Objects.Values)
|
|
|
|
{
|
|
|
|
if (c is Chest)
|
|
|
|
{
|
|
|
|
List<Item> toRemove = new List<Item>();
|
|
|
|
List<Item> toAdd = new List<Item>();
|
|
|
|
foreach (Item o in (c as Chest).items)
|
|
|
|
{
|
|
|
|
if (o == null) continue;
|
|
|
|
if (o is Chest && o.Name != "Chest")
|
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
Item I = this.GetItemFromChestName(o.Name);
|
2019-08-23 07:30:22 +08:00
|
|
|
ModCore.log("Found a custom item in a chest!");
|
2019-08-22 11:17:27 +08:00
|
|
|
toAdd.Add(I);
|
|
|
|
toRemove.Add(o);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach (Item i in toRemove)
|
|
|
|
{
|
|
|
|
(c as Chest).items.Remove(i);
|
|
|
|
}
|
|
|
|
foreach (Item I in toAdd)
|
|
|
|
{
|
|
|
|
(c as Chest).items.Add(I);
|
|
|
|
}
|
|
|
|
}
|
2019-09-22 17:32:59 +08:00
|
|
|
else if(c is Chest && c.Name != "Chest")
|
|
|
|
{
|
|
|
|
loc.objects[c.TileLocation] = (StardewValley.Object)this.GetItemFromChestName(c.Name);
|
|
|
|
ModCore.log("Found a custom item that is a chest!");
|
|
|
|
}
|
2019-08-23 04:43:11 +08:00
|
|
|
else if (c is CustomObject)
|
2019-08-22 11:17:27 +08:00
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
if ((c as CustomObject).info.inventory == null) continue;
|
|
|
|
List<Item> toRemove = new List<Item>();
|
|
|
|
List<Item> toAdd = new List<Item>();
|
|
|
|
foreach (Item o in (c as CustomObject).info.inventory.items)
|
2019-08-22 11:17:27 +08:00
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
if (o == null) continue;
|
2019-08-22 11:17:27 +08:00
|
|
|
if (o is Chest && o.Name != "Chest")
|
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
Item I = this.GetItemFromChestName(o.Name);
|
|
|
|
toAdd.Add(I);
|
|
|
|
toRemove.Add(o);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach (Item i in toRemove)
|
|
|
|
{
|
|
|
|
(c as Chest).items.Remove(i);
|
|
|
|
}
|
|
|
|
foreach (Item I in toAdd)
|
|
|
|
{
|
|
|
|
(c as Chest).items.Add(I);
|
|
|
|
}
|
|
|
|
if (c.heldObject.Value != null)
|
|
|
|
{
|
|
|
|
if (c.heldObject.Value is Chest && c.heldObject.Value.Name != "Chest")
|
|
|
|
{
|
|
|
|
ModCore.log("Found a custom object as a held object!");
|
|
|
|
Item I = this.GetItemFromChestName(c.heldObject.Value.Name);
|
|
|
|
c.heldObject.Value = (StardewValley.Object)I;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (c is StardewValley.Object)
|
|
|
|
{
|
|
|
|
if (c.heldObject.Value != null)
|
|
|
|
{
|
|
|
|
if (c.heldObject.Value is Chest && c.heldObject.Value.Name != "Chest")
|
|
|
|
{
|
|
|
|
ModCore.log("Found a custom object as a held object!");
|
|
|
|
Item I = this.GetItemFromChestName(c.heldObject.Value.Name);
|
|
|
|
c.heldObject.Value = (StardewValley.Object)I;
|
2019-08-22 11:17:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
List<Item> toAdd2 = new List<Item>();
|
|
|
|
List<Item> toRemove2 = new List<Item>();
|
|
|
|
foreach (Item I in Game1.player.Items)
|
|
|
|
{
|
|
|
|
if (I == null) continue;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (I is Chest && I.Name != "Chest")
|
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
Item ret = this.GetItemFromChestName(I.Name);
|
2019-08-22 11:17:27 +08:00
|
|
|
toAdd2.Add(ret);
|
|
|
|
toRemove2.Add(I);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach (Item i in toRemove2)
|
|
|
|
{
|
|
|
|
Game1.player.Items.Remove(i);
|
|
|
|
}
|
|
|
|
foreach (Item I in toAdd2)
|
|
|
|
{
|
|
|
|
Game1.player.addItemToInventory(I);
|
|
|
|
}
|
2019-01-13 03:25:45 +08:00
|
|
|
}
|
2019-08-27 07:34:03 +08:00
|
|
|
|
2019-08-23 04:43:11 +08:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets an Item recreated from PYTK's chest replacement objects.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="JsonName"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
public Item GetItemFromChestName(string JsonName)
|
|
|
|
{
|
|
|
|
//ModCore.log("Found a custom object in a chest!");
|
|
|
|
string jsonString = JsonName;
|
2019-08-28 10:42:05 +08:00
|
|
|
//ModCore.log(JsonName);
|
2019-08-28 10:27:34 +08:00
|
|
|
string dataSplit= jsonString.Split(new string[] { "<" }, StringSplitOptions.None)[1];
|
|
|
|
string backUpGUID = dataSplit.Split('|')[0];
|
|
|
|
string[] guidArr = jsonString.Split(new string[] { "|" }, StringSplitOptions.None);
|
|
|
|
|
|
|
|
foreach(string s in guidArr)
|
|
|
|
{
|
2019-08-28 10:42:05 +08:00
|
|
|
//ModCore.log(s);
|
2019-08-28 10:27:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
string guidName = guidArr[guidArr.Length - 1];
|
|
|
|
guidName = guidName.Substring(5);
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Guid g = Guid.Parse(guidName);
|
|
|
|
}
|
|
|
|
catch (Exception err)
|
|
|
|
{
|
|
|
|
Guid d = Guid.Parse(backUpGUID);
|
|
|
|
guidName = backUpGUID;
|
|
|
|
}
|
2019-08-28 10:42:05 +08:00
|
|
|
//ModCore.log("THE GUID IS:"+ guidName);
|
2019-08-28 10:27:34 +08:00
|
|
|
|
2019-08-23 04:43:11 +08:00
|
|
|
//ModCore.log(jsonString);
|
|
|
|
string type = jsonString.Split('|')[2];
|
|
|
|
Item I = (Item)ModCore.Serializer.DeserializeGUID(guidName, Type.GetType(type));
|
|
|
|
|
2019-08-27 07:34:03 +08:00
|
|
|
if (I is MultiTiledObject)
|
|
|
|
{
|
|
|
|
(I as MultiTiledObject).recreate();
|
|
|
|
}
|
2019-08-23 04:43:11 +08:00
|
|
|
return I;
|
|
|
|
}
|
|
|
|
|
2019-09-01 09:23:47 +08:00
|
|
|
public Item DeserializeFromFarmhandInventory(string JsonName)
|
|
|
|
{
|
|
|
|
//ModCore.log("Found a custom object in a chest!");
|
|
|
|
string jsonString = JsonName;
|
|
|
|
//ModCore.log(JsonName);
|
|
|
|
string dataSplit = jsonString.Split(new string[] { "<" }, StringSplitOptions.None)[2];
|
|
|
|
string backUpGUID = dataSplit.Split('|')[0];
|
|
|
|
string[] guidArr = jsonString.Split(new string[] { "|" }, StringSplitOptions.None);
|
|
|
|
|
|
|
|
string infoStr = jsonString.Split(new string[] { "<" }, StringSplitOptions.None)[0];
|
|
|
|
string guidStr= jsonString.Split(new string[] { "<" }, StringSplitOptions.None)[1];
|
|
|
|
|
|
|
|
CustomObjectData pyTkData = ModCore.Serializer.DeserializeFromJSONString<CustomObjectData>(dataSplit);
|
|
|
|
Type t = Type.GetType(pyTkData.type);
|
|
|
|
string id = pyTkData.id;
|
|
|
|
//Need Item info
|
|
|
|
|
|
|
|
string guidName = backUpGUID;
|
|
|
|
string infoSplit = infoStr.Split('|')[3];
|
|
|
|
infoSplit = infoSplit.Substring(3);
|
|
|
|
BasicItemInformation info = ModCore.Serializer.DeserializeFromJSONString<BasicItemInformation>(infoSplit);
|
|
|
|
|
|
|
|
CustomObject clone = (CustomObject)ModCore.ObjectManager.getItemByIDAndType(id, t);
|
|
|
|
if (clone != null)
|
|
|
|
{
|
|
|
|
clone.info = info;
|
|
|
|
ModCore.log("Guid is????:"+guidStr);
|
|
|
|
clone.guid = Guid.Parse(guidStr);
|
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2019-01-13 03:25:45 +08:00
|
|
|
public void returnToTitle()
|
|
|
|
{
|
2019-08-22 10:06:17 +08:00
|
|
|
//this.gatherAllFilesForCleanup();
|
2019-01-13 03:25:45 +08:00
|
|
|
}
|
|
|
|
|
2019-08-23 04:43:11 +08:00
|
|
|
|
|
|
|
|
|
|
|
[Obsolete]
|
2019-01-13 03:25:45 +08:00
|
|
|
private void removeNullObjects()
|
|
|
|
{
|
|
|
|
List<Item> removalList = new List<Item>();
|
2019-08-23 04:43:11 +08:00
|
|
|
foreach (Item I in Game1.player.Items)
|
2019-01-13 03:25:45 +08:00
|
|
|
{
|
|
|
|
if (I == null) continue;
|
|
|
|
if (I.DisplayName.Contains("Revitalize.Framework") && (I is Chest))
|
|
|
|
{
|
|
|
|
removalList.Add(I);
|
|
|
|
}
|
2019-08-23 04:43:11 +08:00
|
|
|
|
2019-01-13 03:25:45 +08:00
|
|
|
}
|
2019-08-23 04:43:11 +08:00
|
|
|
foreach (Item I in removalList)
|
2019-01-13 03:25:45 +08:00
|
|
|
{
|
2019-05-16 03:42:48 +08:00
|
|
|
Game1.player.Items.Remove(I);
|
2019-01-13 03:25:45 +08:00
|
|
|
}
|
2019-01-13 02:40:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Removes the file from all files that will be deleted.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="playerDirectory"></param>
|
|
|
|
/// <param name="fileName"></param>
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Deletes unused object data.
|
|
|
|
/// </summary>
|
|
|
|
private void deleteAllUnusedFiles()
|
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
foreach (KeyValuePair<string, List<string>> pair in this.filesToDelete)
|
2019-01-13 02:40:47 +08:00
|
|
|
{
|
|
|
|
foreach (string file in pair.Value)
|
|
|
|
{
|
|
|
|
File.Delete(file);
|
|
|
|
}
|
|
|
|
}
|
2019-01-09 20:03:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Adds a new converter to the json serializer.
|
|
|
|
/// </summary>
|
2019-01-13 02:40:47 +08:00
|
|
|
/// <param name="converter">The type of json converter to add to the Serializer.</param>
|
2019-01-09 20:03:27 +08:00
|
|
|
public void addConverter(JsonConverter converter)
|
|
|
|
{
|
|
|
|
this.serializer.Converters.Add(converter);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Deserializes an object from a .json file.
|
|
|
|
/// </summary>
|
2019-01-13 02:40:47 +08:00
|
|
|
/// <typeparam name="T">The type of object to deserialize into.</typeparam>
|
|
|
|
/// <param name="p">The path to the file.</param>
|
|
|
|
/// <returns>An object of specified type T.</returns>
|
2019-01-09 20:03:27 +08:00
|
|
|
public T Deserialize<T>(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))
|
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
|
|
|
|
var obj = this.serializer.Deserialize<T>(reader);
|
2019-01-09 20:03:27 +08:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-13 02:40:47 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Deserializes an object from a .json file.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="T">The type of object to deserialize into.</typeparam>
|
|
|
|
/// <param name="p">The path to the file.</param>
|
|
|
|
/// <returns>An object of specified type T.</returns>
|
2019-08-23 04:43:11 +08:00
|
|
|
public object Deserialize(string p, Type T)
|
2019-01-11 10:32:35 +08:00
|
|
|
{
|
|
|
|
string json = "";
|
|
|
|
foreach (string line in File.ReadLines(p))
|
|
|
|
{
|
|
|
|
json += line;
|
|
|
|
}
|
|
|
|
using (StreamReader sw = new StreamReader(p))
|
|
|
|
using (JsonReader reader = new JsonTextReader(sw))
|
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
object obj = this.serializer.Deserialize(reader, T);
|
2019-01-11 10:32:35 +08:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-09 20:03:27 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Serializes an object to a .json file.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="path"></param>
|
|
|
|
/// <param name="o"></param>
|
|
|
|
public void Serialize(string path, object o)
|
|
|
|
{
|
|
|
|
using (StreamWriter sw = new StreamWriter(path))
|
|
|
|
using (JsonWriter writer = new JsonTextWriter(sw))
|
|
|
|
{
|
|
|
|
this.serializer.Serialize(writer, o);
|
|
|
|
}
|
|
|
|
}
|
2019-01-11 15:24:55 +08:00
|
|
|
|
2019-01-13 02:40:47 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Serialize a data structure into an file.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="fileName"></param>
|
|
|
|
/// <param name="obj"></param>
|
2019-08-23 04:43:11 +08:00
|
|
|
public void SerializeGUID(string fileName, object obj)
|
2019-01-11 15:24:55 +08:00
|
|
|
{
|
2019-05-16 03:42:48 +08:00
|
|
|
string path = Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData", Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID, "SavedObjectInformation", fileName + ".json");
|
2019-01-11 15:24:55 +08:00
|
|
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
2019-05-16 03:42:48 +08:00
|
|
|
this.Serialize(path, obj);
|
2019-01-11 15:24:55 +08:00
|
|
|
}
|
|
|
|
|
2019-01-13 02:40:47 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Deserialze a file into it's proper data structure.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="T">The type of data structure to deserialze to.</typeparam>
|
|
|
|
/// <param name="fileName">The name of the file to deserialize from.</param>
|
|
|
|
/// <returns>A data structure object deserialize from a json string in a file.</returns>
|
2019-08-23 04:43:11 +08:00
|
|
|
public object DeserializeGUID(string fileName, Type T)
|
2019-01-11 15:24:55 +08:00
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
string path = Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData", Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID, "SavedObjectInformation", fileName + ".json");
|
2019-05-16 03:42:48 +08:00
|
|
|
this.removeFileFromDeletion((Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID), path);
|
|
|
|
return this.Deserialize(path, T);
|
2019-01-11 15:24:55 +08:00
|
|
|
}
|
|
|
|
|
2019-01-13 02:40:47 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Deserialze a file into it's proper data structure.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="T">The type of data structure to deserialze to.</typeparam>
|
|
|
|
/// <param name="fileName">The name of the file to deserialize from.</param>
|
|
|
|
/// <returns>A data structure object deserialize from a json string in a file.</returns>
|
2019-01-11 15:24:55 +08:00
|
|
|
public T DeserializeGUID<T>(string fileName)
|
|
|
|
{
|
2019-05-16 03:42:48 +08:00
|
|
|
string path = Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "SaveData", Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID, "SavedObjectInformation", fileName + ".json");
|
2019-08-22 10:06:17 +08:00
|
|
|
//this.removeFileFromDeletion((Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID),path);
|
2019-01-13 02:40:47 +08:00
|
|
|
if (File.Exists(path))
|
|
|
|
{
|
2019-08-22 10:06:17 +08:00
|
|
|
//ModCore.log("Deseralizing file:" + path);
|
2019-05-16 03:42:48 +08:00
|
|
|
return this.Deserialize<T>(path);
|
2019-01-13 02:40:47 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-08-22 10:06:17 +08:00
|
|
|
throw new Exception("Can't deserialize file. Default returned. " + path);
|
2019-01-13 02:40:47 +08:00
|
|
|
}
|
2019-01-11 15:24:55 +08:00
|
|
|
}
|
2019-01-13 02:40:47 +08:00
|
|
|
|
2019-01-14 06:46:31 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Converts objects to json form.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="o"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
public string ToJSONString(object o)
|
|
|
|
{
|
|
|
|
return JsonConvert.SerializeObject(o, this.settings);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Converts from json form to objects.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="T"></typeparam>
|
|
|
|
/// <param name="info"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
public T DeserializeFromJSONString<T>(string info)
|
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
return JsonConvert.DeserializeObject<T>(info, this.settings);
|
2019-01-14 06:46:31 +08:00
|
|
|
}
|
2019-01-13 02:40:47 +08:00
|
|
|
|
2019-01-14 06:46:31 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Converts from json form to objects.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="info"></param>
|
|
|
|
/// <param name="T"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
public object DeserializeFromJSONString(string info, Type T)
|
|
|
|
{
|
|
|
|
return JsonConvert.DeserializeObject(info, T, this.settings);
|
|
|
|
}
|
2019-01-13 02:40:47 +08:00
|
|
|
|
2019-05-16 03:42:48 +08:00
|
|
|
|
2019-08-23 04:43:11 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Deserailizes a content file for the mod.
|
|
|
|
/// </summary>
|
|
|
|
/// <typeparam name="T"></typeparam>
|
|
|
|
/// <param name="pathToFile"></param>
|
|
|
|
/// <returns></returns>
|
2019-05-16 03:42:48 +08:00
|
|
|
public T DeserializeContentFile<T>(string pathToFile)
|
|
|
|
{
|
|
|
|
if (File.Exists(pathToFile))
|
|
|
|
{
|
|
|
|
|
|
|
|
return this.Deserialize<T>(pathToFile);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return default(T);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-17 05:35:40 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Serializes a content file if it doesn't already exist. If it does exist this does nothing as to not override the content file.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="fileName">The name to name the file. So a file named MyFile would be a MyFile.json</param>
|
|
|
|
/// <param name="obj">The actual to serialize.</param>
|
|
|
|
/// <param name="extensionFolder">The sub folder path inside of the Content folder for this mod.</param>
|
2019-08-23 04:43:11 +08:00
|
|
|
public void SerializeContentFile(string fileName, object obj, string extensionFolder)
|
2019-05-16 03:42:48 +08:00
|
|
|
{
|
2019-08-23 04:43:11 +08:00
|
|
|
string path = Path.Combine(Revitalize.ModCore.ModHelper.DirectoryPath, "Content", extensionFolder, fileName + ".json");
|
2019-05-16 03:42:48 +08:00
|
|
|
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
|
|
|
if (File.Exists(path)) return;
|
|
|
|
this.Serialize(path, obj);
|
|
|
|
}
|
|
|
|
|
2019-08-23 04:43:11 +08:00
|
|
|
/// <summary>
|
|
|
|
/// Deletes all .json saved objects before saving.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="o"></param>
|
|
|
|
/// <param name="sender"></param>
|
2019-08-22 10:06:17 +08:00
|
|
|
public void DayEnding_CleanUpFilesForDeletion(object o, StardewModdingAPI.Events.DayEndingEventArgs sender)
|
|
|
|
{
|
|
|
|
//ModCore.log("Day ending now delete files!");
|
|
|
|
this.deleteFilesBeforeSave();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the unique character path string.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns></returns>
|
|
|
|
public string getUniqueCharacterString()
|
|
|
|
{
|
|
|
|
return Game1.player.Name + "_" + Game1.player.UniqueMultiplayerID;
|
|
|
|
}
|
2019-05-16 13:27:38 +08:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// https://stackoverflow.com/questions/2742276/how-do-i-check-if-a-type-is-a-subtype-or-the-type-of-an-object
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="potentialBase"></param>
|
|
|
|
/// <param name="potentialDescendant"></param>
|
|
|
|
/// <returns></returns>
|
|
|
|
public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
|
|
|
|
{
|
|
|
|
return potentialDescendant.IsSubclassOf(potentialBase)
|
|
|
|
|| potentialDescendant == potentialBase;
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool IsSubclass(Type potentialBase, Type potentialDescendant)
|
|
|
|
{
|
|
|
|
return potentialDescendant.IsSubclassOf(potentialBase);
|
|
|
|
}
|
2019-01-09 20:03:27 +08:00
|
|
|
}
|
|
|
|
}
|