From 6d2d31ce23cc8718235d1acc46b1fd1251f38553 Mon Sep 17 00:00:00 2001 From: JoshuaNavarro Date: Fri, 23 Aug 2019 14:28:33 -0700 Subject: [PATCH] Re-enabled simple multiplayer support on revitalize but there would be a TON to do still to fully support it. --- .../Converters/INetSerializableConverter.cs | 168 ++++++++++++++++++ .../Serialization/Converters/ItemCoverter.cs | 19 +- .../Utilities/Serialization/Serialization.cs | 8 +- GeneralMods/Revitalize/ModCore.cs | 4 +- GeneralMods/Revitalize/Revitalize.csproj | 3 +- 5 files changed, 196 insertions(+), 6 deletions(-) create mode 100644 GeneralMods/Revitalize/Framework/Utilities/Serialization/Converters/INetSerializableConverter.cs diff --git a/GeneralMods/Revitalize/Framework/Utilities/Serialization/Converters/INetSerializableConverter.cs b/GeneralMods/Revitalize/Framework/Utilities/Serialization/Converters/INetSerializableConverter.cs new file mode 100644 index 00000000..80ecec4d --- /dev/null +++ b/GeneralMods/Revitalize/Framework/Utilities/Serialization/Converters/INetSerializableConverter.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Netcode; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; +using Revitalize.Framework.Utilities.Serialization.ContractResolvers; + +namespace Revitalize.Framework.Utilities.Serialization.Converters +{ + public class INetSerializableConverter : Newtonsoft.Json.JsonConverter + { + public static Dictionary AllTypes = new Dictionary(); + + JsonSerializerSettings settings; + public INetSerializableConverter() + { + this.settings = new JsonSerializerSettings() + { + Converters = new List() + { + new Framework.Utilities.Serialization.Converters.RectangleConverter(), + new Framework.Utilities.Serialization.Converters.Texture2DConverter(), + }, + ContractResolver = new NetFieldContract(), + Formatting = Formatting.Indented, + ReferenceLoopHandling = ReferenceLoopHandling.Ignore, + NullValueHandling = NullValueHandling.Include + }; + + this.settings.Converters.Add(this); + } + + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + string convertedString = JsonConvert.SerializeObject((INetSerializable)value, this.settings); + DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; + writer.WriteStartObject(); + writer.WritePropertyName("Type"); + serializer.Serialize(writer, value.GetType().FullName.ToString()); + writer.WritePropertyName("Item"); + serializer.Serialize(writer, convertedString); + + writer.WriteEndObject(); + } + + /// + /// Reads the JSON representation of the object. + /// + /// The to read from. + /// Type of the object. + /// The existing value of object being read. + /// The calling serializer. + /// The object value. + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) + { + return null; + } + JObject jo = null; + + try + { + jo = JObject.Load(reader); + } + catch(Exception err) + { + if (reader.Value == null) return null; + JArray arr= JArray.Parse(reader.Value.ToString()); + jo=JObject.Parse(arr[0].ToString()); + } + + string t = jo["Type"].Value(); + + //See if the type has already been cached and if so return it for deserialization. + if (AllTypes.ContainsKey(t)) + { + + return JsonConvert.DeserializeObject(jo["Item"].ToString(), AllTypes[t], this.settings); + } + + Assembly asm = typeof(StardewValley.Object).Assembly; + Type type = null; + + type = asm.GetType(t); + + if (type == null) + { + asm = typeof(Revitalize.ModCore).Assembly; + type = asm.GetType(t); + } + + if (type == null) + { + foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + asm = assembly; + type = asm.GetType(t); + if (t != null) break; + } + } + + if (type == null) + { + throw new Exception("Unsupported type found when Deserializing Unsure what to do so we can;t deserialize this thing!: " + t); + } + + //Cache the newly found type. + AllTypes.Add(t, type); + + return JsonConvert.DeserializeObject(jo["Item"].ToString(), type, this.settings); + /* + if (t== typeof(StardewValley.Tools.Axe).FullName.ToString()) + { + Revitalize.ModCore.log("DESERIALIZE AXE!!!"); + //return jo["Item"].Value(); + return JsonConvert.DeserializeObject(jo["Item"].ToString(),this.settings); + } + else if (t == typeof(Revitalize.Framework.Objects.MultiTiledObject).FullName.ToString()) + { + + Revitalize.ModCore.log("DESERIALIZE Multi Tile Object!!!"); + return JsonConvert.DeserializeObject(jo["Item"].ToString(), this.settings); + // return jo["Item"].Value(); + } + else if (t == typeof(Revitalize.Framework.Objects.MultiTiledComponent).FullName.ToString()) + { + Revitalize.ModCore.log("DESERIALIZE Multi Tile Component!!!"); + return JsonConvert.DeserializeObject(jo["Item"].ToString(), this.settings); + // return jo["Item"].Value(); + } + else + { + + throw new NotImplementedException("CANT DESERIALIZE: " + t.ToString()); + } + */ + + + } + + public override bool CanWrite => true; + public override bool CanRead => true; + + public override bool CanConvert(Type objectType) + { + return this.IsSameOrSubclass(typeof(INetSerializable), objectType); + } + + /// + /// https://stackoverflow.com/questions/2742276/how-do-i-check-if-a-type-is-a-subtype-or-the-type-of-an-object + /// + /// + /// + /// + public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant) + { + return potentialDescendant.IsSubclassOf(potentialBase) + || potentialDescendant == potentialBase; + } + } +} diff --git a/GeneralMods/Revitalize/Framework/Utilities/Serialization/Converters/ItemCoverter.cs b/GeneralMods/Revitalize/Framework/Utilities/Serialization/Converters/ItemCoverter.cs index 81547b24..f98090fd 100644 --- a/GeneralMods/Revitalize/Framework/Utilities/Serialization/Converters/ItemCoverter.cs +++ b/GeneralMods/Revitalize/Framework/Utilities/Serialization/Converters/ItemCoverter.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; +using Revitalize.Framework.Utilities.Serialization.ContractResolvers; using StardewValley; namespace Revitalize.Framework.Utilities.Serialization.Converters @@ -24,18 +25,21 @@ namespace Revitalize.Framework.Utilities.Serialization.Converters { new Framework.Utilities.Serialization.Converters.RectangleConverter(), new Framework.Utilities.Serialization.Converters.Texture2DConverter(), + new INetSerializableConverter() }, + ContractResolver = new NetFieldContract(), Formatting = Formatting.Indented, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, NullValueHandling = NullValueHandling.Include }; + + //this.settings.Converters.Add(this); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { string convertedString = JsonConvert.SerializeObject((Item)value, this.settings); - DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartObject(); writer.WritePropertyName("Type"); serializer.Serialize(writer, value.GetType().FullName.ToString()); @@ -62,7 +66,18 @@ namespace Revitalize.Framework.Utilities.Serialization.Converters return null; } - JObject jo = JObject.Load(reader); + JObject jo = null; + + try + { + jo = JObject.Load(reader); + } + catch (Exception err) + { + if (reader.Value == null) return null; + JArray arr = JArray.Parse(reader.Value.ToString()); + jo = JObject.Parse(arr[0].ToString()); + } string t = jo["Type"].Value(); diff --git a/GeneralMods/Revitalize/Framework/Utilities/Serialization/Serialization.cs b/GeneralMods/Revitalize/Framework/Utilities/Serialization/Serialization.cs index 7e8b2567..a44d12f0 100644 --- a/GeneralMods/Revitalize/Framework/Utilities/Serialization/Serialization.cs +++ b/GeneralMods/Revitalize/Framework/Utilities/Serialization/Serialization.cs @@ -8,6 +8,7 @@ using Newtonsoft.Json; using Revitalize.Framework.Objects; using Revitalize.Framework.Objects.Furniture; using Revitalize.Framework.Utilities.Serialization.ContractResolvers; +using Revitalize.Framework.Utilities.Serialization.Converters; using StardewValley; using StardewValley.Objects; @@ -18,6 +19,8 @@ namespace Revitalize.Framework.Utilities /// public class Serializer { + + /// /// The actual json serializer. /// @@ -48,11 +51,12 @@ namespace Revitalize.Framework.Utilities this.serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; this.serializer.NullValueHandling = NullValueHandling.Include; - this.serializer.ContractResolver = new NetFieldContract(); + //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 Serialization.Converters.INetSerializableConverter()); //this.addConverter(new Framework.Utilities.Serialization.Converters.CustomObjectDataConverter()); //this.addConverter(new Framework.Utilities.Serialization.Converters.NetFieldConverter()); //this.addConverter(new Framework.Utilities.Serialization.Converters.Vector2Converter()); @@ -67,7 +71,7 @@ namespace Revitalize.Framework.Utilities this.settings.Formatting = Formatting.Indented; this.settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; this.settings.NullValueHandling = NullValueHandling.Include; - this.settings.ContractResolver = new NetFieldContract(); + //this.settings.ContractResolver = new NetFieldContract(); } /// diff --git a/GeneralMods/Revitalize/ModCore.cs b/GeneralMods/Revitalize/ModCore.cs index f09df947..d1299323 100644 --- a/GeneralMods/Revitalize/ModCore.cs +++ b/GeneralMods/Revitalize/ModCore.cs @@ -23,6 +23,7 @@ using Revitalize.Framework.Objects.Extras; using Revitalize.Framework.Minigame.SeasideScrambleMinigame; using Revitalize.Framework.Objects.Items.Resources; using Revitalize.Framework.Hacks; +using Netcode; namespace Revitalize { @@ -379,11 +380,12 @@ namespace Revitalize private void GameLoop_SaveLoaded(object sender, StardewModdingAPI.Events.SaveLoadedEventArgs e) { this.loadContent(); - + /* if (Game1.IsServer || Game1.IsMultiplayer || Game1.IsClient) { throw new Exception("Can't run Revitalize in multiplayer due to lack of current support!"); } + */ Serializer.afterLoad(); ShopHacks.AddOreToClintsShop(); diff --git a/GeneralMods/Revitalize/Revitalize.csproj b/GeneralMods/Revitalize/Revitalize.csproj index a380750a..42b1fbde 100644 --- a/GeneralMods/Revitalize/Revitalize.csproj +++ b/GeneralMods/Revitalize/Revitalize.csproj @@ -31,7 +31,7 @@ - 12.0.1 + 12.0.2 @@ -151,6 +151,7 @@ +