Re-enabled simple multiplayer support on revitalize but there would be a TON to do still to fully support it.

This commit is contained in:
JoshuaNavarro 2019-08-23 14:28:33 -07:00
parent f3f4f4da27
commit 6d2d31ce23
5 changed files with 196 additions and 6 deletions

View File

@ -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<string, Type> AllTypes = new Dictionary<string, Type>();
JsonSerializerSettings settings;
public INetSerializableConverter()
{
this.settings = new JsonSerializerSettings()
{
Converters = new List<JsonConverter>()
{
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();
}
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
/// <param name="objectType">Type of the object.</param>
/// <param name="existingValue">The existing value of object being read.</param>
/// <param name="serializer">The calling serializer.</param>
/// <returns>The object value.</returns>
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<string>();
//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<StardewValley.Tools.Axe>();
return JsonConvert.DeserializeObject<StardewValley.Tools.Axe>(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<Revitalize.Framework.Objects.MultiTiledObject>(jo["Item"].ToString(), this.settings);
// return jo["Item"].Value<Revitalize.Framework.Objects.MultiTiledObject>();
}
else if (t == typeof(Revitalize.Framework.Objects.MultiTiledComponent).FullName.ToString())
{
Revitalize.ModCore.log("DESERIALIZE Multi Tile Component!!!");
return JsonConvert.DeserializeObject<Revitalize.Framework.Objects.MultiTiledComponent>(jo["Item"].ToString(), this.settings);
// return jo["Item"].Value<Revitalize.Framework.Objects.MultiTiledObject>();
}
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);
}
/// <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;
}
}
}

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
using Revitalize.Framework.Utilities.Serialization.ContractResolvers;
using StardewValley; using StardewValley;
namespace Revitalize.Framework.Utilities.Serialization.Converters 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.RectangleConverter(),
new Framework.Utilities.Serialization.Converters.Texture2DConverter(), new Framework.Utilities.Serialization.Converters.Texture2DConverter(),
new INetSerializableConverter()
}, },
ContractResolver = new NetFieldContract(),
Formatting = Formatting.Indented, Formatting = Formatting.Indented,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
NullValueHandling = NullValueHandling.Include NullValueHandling = NullValueHandling.Include
}; };
//this.settings.Converters.Add(this);
} }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{ {
string convertedString = JsonConvert.SerializeObject((Item)value, this.settings); string convertedString = JsonConvert.SerializeObject((Item)value, this.settings);
DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
writer.WriteStartObject(); writer.WriteStartObject();
writer.WritePropertyName("Type"); writer.WritePropertyName("Type");
serializer.Serialize(writer, value.GetType().FullName.ToString()); serializer.Serialize(writer, value.GetType().FullName.ToString());
@ -62,7 +66,18 @@ namespace Revitalize.Framework.Utilities.Serialization.Converters
return null; 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<string>(); string t = jo["Type"].Value<string>();

View File

@ -8,6 +8,7 @@ using Newtonsoft.Json;
using Revitalize.Framework.Objects; using Revitalize.Framework.Objects;
using Revitalize.Framework.Objects.Furniture; using Revitalize.Framework.Objects.Furniture;
using Revitalize.Framework.Utilities.Serialization.ContractResolvers; using Revitalize.Framework.Utilities.Serialization.ContractResolvers;
using Revitalize.Framework.Utilities.Serialization.Converters;
using StardewValley; using StardewValley;
using StardewValley.Objects; using StardewValley.Objects;
@ -18,6 +19,8 @@ namespace Revitalize.Framework.Utilities
/// </summary> /// </summary>
public class Serializer public class Serializer
{ {
/// <summary> /// <summary>
/// The actual json serializer. /// The actual json serializer.
/// </summary> /// </summary>
@ -48,11 +51,12 @@ namespace Revitalize.Framework.Utilities
this.serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; this.serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
this.serializer.NullValueHandling = NullValueHandling.Include; 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.RectangleConverter());
this.addConverter(new Framework.Utilities.Serialization.Converters.Texture2DConverter()); this.addConverter(new Framework.Utilities.Serialization.Converters.Texture2DConverter());
this.addConverter(new Framework.Utilities.Serialization.Converters.ItemCoverter()); 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.CustomObjectDataConverter());
//this.addConverter(new Framework.Utilities.Serialization.Converters.NetFieldConverter()); //this.addConverter(new Framework.Utilities.Serialization.Converters.NetFieldConverter());
//this.addConverter(new Framework.Utilities.Serialization.Converters.Vector2Converter()); //this.addConverter(new Framework.Utilities.Serialization.Converters.Vector2Converter());
@ -67,7 +71,7 @@ namespace Revitalize.Framework.Utilities
this.settings.Formatting = Formatting.Indented; this.settings.Formatting = Formatting.Indented;
this.settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; this.settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
this.settings.NullValueHandling = NullValueHandling.Include; this.settings.NullValueHandling = NullValueHandling.Include;
this.settings.ContractResolver = new NetFieldContract(); //this.settings.ContractResolver = new NetFieldContract();
} }
/// <summary> /// <summary>

View File

@ -23,6 +23,7 @@ using Revitalize.Framework.Objects.Extras;
using Revitalize.Framework.Minigame.SeasideScrambleMinigame; using Revitalize.Framework.Minigame.SeasideScrambleMinigame;
using Revitalize.Framework.Objects.Items.Resources; using Revitalize.Framework.Objects.Items.Resources;
using Revitalize.Framework.Hacks; using Revitalize.Framework.Hacks;
using Netcode;
namespace Revitalize namespace Revitalize
{ {
@ -379,11 +380,12 @@ namespace Revitalize
private void GameLoop_SaveLoaded(object sender, StardewModdingAPI.Events.SaveLoadedEventArgs e) private void GameLoop_SaveLoaded(object sender, StardewModdingAPI.Events.SaveLoadedEventArgs e)
{ {
this.loadContent(); this.loadContent();
/*
if (Game1.IsServer || Game1.IsMultiplayer || Game1.IsClient) if (Game1.IsServer || Game1.IsMultiplayer || Game1.IsClient)
{ {
throw new Exception("Can't run Revitalize in multiplayer due to lack of current support!"); throw new Exception("Can't run Revitalize in multiplayer due to lack of current support!");
} }
*/
Serializer.afterLoad(); Serializer.afterLoad();
ShopHacks.AddOreToClintsShop(); ShopHacks.AddOreToClintsShop();

View File

@ -31,7 +31,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json"> <PackageReference Include="Newtonsoft.Json">
<Version>12.0.1</Version> <Version>12.0.2</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="2.2.0" /> <PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="2.2.0" />
</ItemGroup> </ItemGroup>
@ -151,6 +151,7 @@
<Compile Include="Framework\Utilities\RotationUtilities.cs" /> <Compile Include="Framework\Utilities\RotationUtilities.cs" />
<Compile Include="Framework\Utilities\Serialization\ContractResolvers\NetFieldContract.cs" /> <Compile Include="Framework\Utilities\Serialization\ContractResolvers\NetFieldContract.cs" />
<Compile Include="Framework\Utilities\Serialization\Converters\CustomObjectDataConverter.cs" /> <Compile Include="Framework\Utilities\Serialization\Converters\CustomObjectDataConverter.cs" />
<Compile Include="Framework\Utilities\Serialization\Converters\INetSerializableConverter.cs" />
<Compile Include="Framework\Utilities\Serialization\Converters\ItemCoverter.cs" /> <Compile Include="Framework\Utilities\Serialization\Converters\ItemCoverter.cs" />
<Compile Include="Framework\Utilities\Serialization\Converters\NetFieldConverter.cs" /> <Compile Include="Framework\Utilities\Serialization\Converters\NetFieldConverter.cs" />
<Compile Include="Framework\Utilities\Serialization\Converters\RectangleConverter.cs" /> <Compile Include="Framework\Utilities\Serialization\Converters\RectangleConverter.cs" />