using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using GTFO.API;
using GTFO.API.JSON;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.Runtime;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class;
using Il2CppJsonNet;
using Il2CppJsonNet.Converters;
using Il2CppJsonNet.Linq;
using Il2CppJsonNet.Serialization;
using Il2CppSystem;
using Il2CppSystem.Runtime.InteropServices;
using InjectLib.FieldInjection;
using InjectLib.JsonNETInjection;
using InjectLib.JsonNETInjection.Converter;
using InjectLib.JsonNETInjection.Detours;
using InjectLib.JsonNETInjection.Handler;
using InjectLib.Utils;
using Microsoft.CodeAnalysis;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("InjectLib")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.0+gita4e4542-master.a4e45424fbf6892b19c98a2cbd8b107258b43399")]
[assembly: AssemblyProduct("InjectLib")]
[assembly: AssemblyTitle("InjectLib")]
[assembly: TargetPlatform("Windows7.0")]
[assembly: SupportedOSPlatform("Windows7.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class IsUnmanagedAttribute : Attribute
{
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NativeIntegerAttribute : Attribute
{
public readonly bool[] TransformFlags;
public NativeIntegerAttribute()
{
TransformFlags = new bool[1] { true };
}
public NativeIntegerAttribute(bool[] P_0)
{
TransformFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace InjectLib
{
[BepInPlugin("GTFO.InjectLib", "InjectLib", "1.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
internal class EntryPoint : BasePlugin
{
public override void Load()
{
NativeJsonProcessorStore.Initialize();
}
public override bool Unload()
{
return ((BasePlugin)this).Unload();
}
}
internal static class Logger
{
private static readonly ManualLogSource _Logger;
static Logger()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Expected O, but got Unknown
_Logger = new ManualLogSource("InjectLib");
Logger.Sources.Add((ILogSource)(object)_Logger);
}
private static string Format(object msg)
{
return msg.ToString();
}
public static void Info(BepInExInfoLogInterpolatedStringHandler handler)
{
_Logger.LogInfo(handler);
}
public static void Info(string str)
{
_Logger.LogMessage((object)str);
}
public static void Info(object data)
{
_Logger.LogMessage((object)Format(data));
}
public static void Debug(BepInExDebugLogInterpolatedStringHandler handler)
{
_Logger.LogDebug(handler);
}
public static void Debug(string str)
{
_Logger.LogDebug((object)str);
}
public static void Debug(object data)
{
_Logger.LogDebug((object)Format(data));
}
public static void Error(BepInExErrorLogInterpolatedStringHandler handler)
{
_Logger.LogError(handler);
}
public static void Error(string str)
{
_Logger.LogError((object)str);
}
public static void Error(object data)
{
_Logger.LogError((object)Format(data));
}
public static void Fatal(BepInExFatalLogInterpolatedStringHandler handler)
{
_Logger.LogFatal(handler);
}
public static void Fatal(string str)
{
_Logger.LogFatal((object)str);
}
public static void Fatal(object data)
{
_Logger.LogFatal((object)Format(data));
}
public static void Warn(BepInExWarningLogInterpolatedStringHandler handler)
{
_Logger.LogWarning(handler);
}
public static void Warn(string str)
{
_Logger.LogWarning((object)str);
}
public static void Warn(object data)
{
_Logger.LogWarning((object)Format(data));
}
[Conditional("DEBUG")]
public static void DebugOnly(object data)
{
}
}
[GeneratedCode("VersionInfoGenerator", "2.1.3+git35c0c2a-master")]
[CompilerGenerated]
internal static class VersionInfo
{
public const string RootNamespace = "InjectLib";
public const string Version = "1.1.0";
public const string VersionPrerelease = null;
public const string VersionMetadata = "gita4e4542-master";
public const string SemVer = "1.1.0+gita4e4542-master";
public const string GitRevShort = "a4e4542";
public const string GitRevLong = "a4e45424fbf6892b19c98a2cbd8b107258b43399";
public const string GitBranch = "master";
public const string GitTag = null;
public const int GitCommitsSinceTag = 0;
public const bool GitIsDirty = false;
}
}
namespace InjectLib.Utils
{
internal static class FieldsExtension
{
public static void SetNativeJsonProcessor(this DataSetConverter converter, NativeJsonProcessor processor)
{
FieldInjector<DataSetConverter>.TrySetManagedField(converter, "m_JsonProcessor", processor);
}
public static NativeJsonProcessor GetNativeJsonProcessor(this DataSetConverter converter)
{
FieldInjector<DataSetConverter>.TryGetManagedField<NativeJsonProcessor>(converter, "m_JsonProcessor", out var value);
return value;
}
}
internal static class ObjectCopier
{
public static void CopyProperties<T>(T source, T target) where T : Il2CppObjectBase
{
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
Type propertyType = propertyInfo.PropertyType;
if (!propertyInfo.Name.Contains("_k__BackingField") && !(propertyType == typeof(IntPtr)) && propertyInfo.CanRead && propertyInfo.CanWrite)
{
propertyInfo.SetValue(target, propertyInfo.GetValue(source));
}
}
}
}
}
namespace InjectLib.JsonNETInjection
{
public static class JsonInjector
{
static JsonInjector()
{
FieldInjector<DataSetConverter>.DefineManagedField<NativeJsonProcessor>("m_JsonProcessor");
}
public static void SetConverter<T>(Il2CppJsonReferenceTypeConverter<T> converter) where T : Il2CppObjectBase
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Expected O, but got Unknown
if (converter == null)
{
throw new ArgumentNullException("converter");
}
if (!NativeJsonProcessorStore.Prepare<T>(out var processor))
{
return;
}
if (processor.Converter != null)
{
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(76, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Converter (type: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(typeof(T).FullName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") will be replaced! This would leads to unwanted behaviour!");
}
Logger.Warn(val);
Logger.Warn(" - Suggetion: If your converter does not require to deep-level altering of JSON, consider use Il2CppJsonReferenceTypeHandler instead.");
val = new BepInExWarningLogInterpolatedStringHandler(19, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Previous Owner: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(processor.Converter.GetType().Assembly.FullName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" / ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(processor.Converter.GetType().FullName);
}
Logger.Warn(val);
val = new BepInExWarningLogInterpolatedStringHandler(14, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("New Owner: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(converter.GetType().Assembly.FullName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" / ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(converter.GetType().FullName);
}
Logger.Warn(val);
}
processor.Converter = converter;
}
public static void SetConverter<T>(Il2CppJsonUnmanagedTypeConverter<T> converter) where T : unmanaged
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Expected O, but got Unknown
if (converter == null)
{
throw new ArgumentNullException("converter");
}
if (!NativeJsonProcessorStore.Prepare<T>(out var processor))
{
return;
}
if (processor.Converter != null)
{
bool flag = default(bool);
BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(76, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Converter (type: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(typeof(T).FullName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(") will be replaced! This would leads to unwanted behaviour!");
}
Logger.Warn(val);
Logger.Warn(" - Suggetion: If your converter does not require to deep-level altering of JSON, consider use Il2CppJsonUnmanagedTypeHandler instead.");
val = new BepInExWarningLogInterpolatedStringHandler(22, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" - Previous Owner: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(processor.Converter.GetType().Assembly.FullName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" / ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(processor.Converter.GetType().FullName);
}
Logger.Warn(val);
val = new BepInExWarningLogInterpolatedStringHandler(17, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" - New Owner: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(converter.GetType().Assembly.FullName);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" / ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(converter.GetType().FullName);
}
Logger.Warn(val);
}
processor.Converter = converter;
}
public static void AddHandler<T>(Il2CppJsonReferenceTypeHandler<T> handler) where T : Il2CppObjectBase
{
if (handler == null)
{
throw new ArgumentNullException("handler");
}
if (NativeJsonProcessorStore.Prepare<T>(out var processor))
{
processor.Handlers.Add(handler);
}
}
public static void AddHandler<T>(Il2CppJsonUnmanagedTypeHandler<T> handler) where T : unmanaged
{
if (handler == null)
{
throw new ArgumentNullException("handler");
}
if (NativeJsonProcessorStore.Prepare<T>(out var processor))
{
processor.Handlers.Add(handler);
}
}
}
internal class NativeJsonProcessor
{
public Type Type { get; set; }
public DataSetConverter DummyConverter { get; set; }
public INativeJsonConverter Converter { get; set; }
public IList<INativeJsonHandler> Handlers { get; } = new List<INativeJsonHandler>();
public bool Enabled { get; set; } = true;
public IntPtr ProcessRead(JsonReader reader, IntPtr existingValue, JsonSerializer serializer)
{
JToken jToken = JToken.ReadFrom(reader);
IntPtr pointer;
if (Converter != null)
{
pointer = ((Il2CppObjectBase)Converter.ReadJson(jToken, existingValue, serializer)).Pointer;
}
else
{
SetUsingContractConverter(serializer, use: false);
pointer = ((Il2CppObjectBase)serializer.Deserialize(jToken.CreateReader(), Type)).Pointer;
SetUsingContractConverter(serializer, use: true);
}
Object result = PtrToObject(pointer);
foreach (INativeJsonHandler handler in Handlers)
{
handler.OnRead(in result, in jToken);
}
return pointer;
}
public void ProcessWrite(JsonWriter writer, IntPtr valueToWrite, JsonSerializer serializer)
{
if (Converter != null)
{
Converter.WriteJson(writer, valueToWrite, serializer);
return;
}
SetUsingContractConverter(serializer, use: false);
serializer.Serialize(writer, PtrToObject(valueToWrite));
SetUsingContractConverter(serializer, use: true);
}
private static Object PtrToObject(IntPtr ptr)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
if (ptr == IntPtr.Zero)
{
return null;
}
return new Object(ptr);
}
private void SetUsingContractConverter(JsonSerializer serializer, bool use)
{
JsonContract val = serializer.ContractResolver.ResolveContract(Type);
if (use)
{
val.Converter = (JsonConverter)(object)DummyConverter;
val.InternalConverter = (JsonConverter)(object)DummyConverter;
}
else
{
val.Converter = null;
val.InternalConverter = null;
}
}
}
internal static class NativeJsonProcessorStore
{
private static readonly Dictionary<IntPtr, NativeJsonProcessor> _RegisteredProcessors = new Dictionary<IntPtr, NativeJsonProcessor>();
internal static void Initialize()
{
Detour_JsonConverterTrampoline.Patch();
Detour_NativeConverterLink.Patch();
}
public static bool Prepare<T>(out NativeJsonProcessor processor)
{
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Expected O, but got Unknown
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected O, but got Unknown
Type val = Il2CppType.From(typeof(T));
if (val != (Type)null && ((Il2CppObjectBase)val).Pointer != IntPtr.Zero)
{
if (_RegisteredProcessors.TryGetValue(((Il2CppObjectBase)val).Pointer, out processor))
{
return true;
}
DataSetConverter val2 = new DataSetConverter();
NativeJsonProcessor nativeJsonProcessor2 = (_RegisteredProcessors[((Il2CppObjectBase)val).Pointer] = new NativeJsonProcessor());
processor = nativeJsonProcessor2;
processor.Type = val;
processor.DummyConverter = val2;
val2.SetNativeJsonProcessor(processor);
return true;
}
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Type: '");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(typeof(T).Name);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' is not in il2cpp domain!");
}
Logger.Error(val3);
processor = null;
return false;
}
public static bool TryGetConverterPointer(IntPtr typePtr, out IntPtr converterPtr)
{
if (TryGetProcessor(typePtr, out var processor) && processor.DummyConverter != null)
{
converterPtr = ((Il2CppObjectBase)processor.DummyConverter).Pointer;
return converterPtr != IntPtr.Zero;
}
converterPtr = IntPtr.Zero;
return false;
}
public static bool TryGetProcessor(IntPtr typePtr, out NativeJsonProcessor processor)
{
if (_RegisteredProcessors.TryGetValue(typePtr, out processor) && processor != null && processor.Enabled)
{
return processor != null;
}
processor = null;
return false;
}
}
}
namespace InjectLib.JsonNETInjection.Supports
{
internal interface IBaseConnector
{
NativeJsonProcessor Processor { get; set; }
}
public sealed class InjectLibConnector : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
Type val = Il2CppType.From(typeToConvert, false);
if (val != (Type)null && NativeJsonProcessorStore.TryGetProcessor(((Il2CppObjectBase)val).Pointer, out var _))
{
return true;
}
return false;
}
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
if (!NativeJsonProcessorStore.TryGetProcessor(((Il2CppObjectBase)Il2CppType.From(typeToConvert, false)).Pointer, out var processor))
{
return null;
}
if (typeToConvert.IsAssignableTo(typeof(Il2CppObjectBase)))
{
JsonConverter obj = (JsonConverter)Activator.CreateInstance(typeof(ReferenceTypeConnector<>).MakeGenericType(typeToConvert), BindingFlags.Instance | BindingFlags.Public, null, null, null);
((IBaseConnector)obj).Processor = processor;
return obj;
}
if (typeToConvert.IsValueType)
{
JsonConverter obj2 = (JsonConverter)Activator.CreateInstance(typeof(ValueTypeConnector<>).MakeGenericType(typeToConvert), BindingFlags.Instance | BindingFlags.Public, null, null, null);
((IBaseConnector)obj2).Processor = processor;
return obj2;
}
return null;
}
}
public class InjectLibJSON
{
public static JsonSerializerOptions JsonOptions => new JsonSerializerOptions(JsonSerializer.DefaultSerializerSettingsWithLocalizedText)
{
Converters = { (JsonConverter)new InjectLibConnector() }
};
public static T Deserialize<T>(string json, params JsonConverter[] converters)
{
JsonSerializerOptions jsonOptions = JsonOptions;
if (converters != null)
{
foreach (JsonConverter item in converters)
{
jsonOptions.Converters.Add(item);
}
}
return JsonSerializer.Deserialize<T>(json, jsonOptions);
}
public static object Deserialize(string json, Type type, params JsonConverter[] converters)
{
JsonSerializerOptions jsonOptions = JsonOptions;
if (converters != null)
{
foreach (JsonConverter item in converters)
{
jsonOptions.Converters.Add(item);
}
}
return JsonSerializer.Deserialize(json, type, jsonOptions);
}
public static string Serialize<T>(T obj, params JsonConverter[] converters)
{
JsonSerializerOptions jsonOptions = JsonOptions;
if (converters != null)
{
foreach (JsonConverter item in converters)
{
jsonOptions.Converters.Add(item);
}
}
return JsonSerializer.Serialize(obj, JsonOptions);
}
public static string Serialize(object obj, params JsonConverter[] converters)
{
JsonSerializerOptions jsonOptions = JsonOptions;
if (converters != null)
{
foreach (JsonConverter item in converters)
{
jsonOptions.Converters.Add(item);
}
}
return JsonSerializer.Serialize(obj, JsonOptions);
}
}
internal class ReferenceTypeConnector<T> : JsonConverter<T>, IBaseConnector where T : Il2CppObjectBase
{
public NativeJsonProcessor Processor { get; set; }
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Type val = Il2CppType.From(typeToConvert, false);
JsonNode jsonNode = JsonNode.Parse(ref reader);
return (T)Activator.CreateInstance(typeof(T), ((Il2CppObjectBase)JsonConvert.DeserializeObject(jsonNode.ToJsonString(), val, (JsonSerializerSettings)null)).Pointer);
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, value);
}
}
internal class ValueTypeConnector<T> : JsonConverter<T>, IBaseConnector where T : unmanaged
{
public NativeJsonProcessor Processor { get; set; }
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
Type val = Il2CppType.From(typeToConvert, false);
return ((Il2CppObjectBase)JsonConvert.DeserializeObject(JsonNode.Parse(ref reader).ToJsonString(), val, (JsonSerializerSettings)null)).Unbox<T>();
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, value);
}
}
}
namespace InjectLib.JsonNETInjection.Handler
{
public abstract class Il2CppJsonReferenceTypeHandler<T> : INativeJsonHandler where T : Il2CppObjectBase
{
public abstract void OnRead(in Object result, in JToken jToken);
}
public abstract class Il2CppJsonUnmanagedTypeHandler<T> : INativeJsonHandler where T : unmanaged
{
public abstract void OnRead(in Object result, in JToken jToken);
}
internal interface INativeJsonHandler
{
void OnRead(in Object result, in JToken jToken);
}
}
namespace InjectLib.JsonNETInjection.Detours
{
internal class Detour_JsonConverterTrampoline
{
public unsafe delegate IntPtr GetMatchingConverterDel(IntPtr converters, IntPtr objectType, Il2CppMethodInfo* methodInfo);
public unsafe delegate IntPtr GetConverterDel(IntPtr attributeProvider, Il2CppMethodInfo* methodInfo);
private static INativeDetour _Detour1;
private static INativeDetour _Detour2;
private static GetMatchingConverterDel _Original1;
private static GetConverterDel _Original2;
public unsafe static void Patch()
{
_Detour1 = INativeDetour.CreateAndApply<GetMatchingConverterDel>((IntPtr)(nint)Il2CppAPI.GetIl2CppMethod<JsonSerializer>("GetMatchingConverter", "Newtonsoft.Json.JsonConverter", false, new string[2]
{
"System.Collections.Generic.IList<Newtonsoft.Json.JsonConverter>",
typeof(Type).FullName
}), (GetMatchingConverterDel)Detour1, ref _Original1);
IntPtr nativeClassPointer = Il2CppClassPointerStore.GetNativeClassPointer(typeof(JsonTypeReflector));
string text = "GetJsonConverter";
void** ptr = (void**)IL2CPP.GetIl2CppMethod(nativeClassPointer, false, text, "Newtonsoft.Json.JsonConverter", new string[1] { typeof(object).FullName }).ToPointer();
_Detour2 = INativeDetour.CreateAndApply<GetConverterDel>((IntPtr)(nint)((ptr == null) ? ptr : (*ptr)), (GetConverterDel)Detour2, ref _Original2);
}
private unsafe static IntPtr Detour1(IntPtr converters, IntPtr objectType, Il2CppMethodInfo* methodInfo)
{
if (NativeJsonProcessorStore.TryGetConverterPointer(objectType, out var converterPtr))
{
return converterPtr;
}
return _Original1(converters, objectType, methodInfo);
}
private unsafe static IntPtr Detour2(IntPtr attributeProvider, Il2CppMethodInfo* methodInfo)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
Type val = ((Il2CppObjectBase)new Object(attributeProvider)).TryCast<Type>();
if (val != (Type)null && NativeJsonProcessorStore.TryGetConverterPointer(((Il2CppObjectBase)val).Pointer, out var converterPtr))
{
return converterPtr;
}
return _Original2(attributeProvider, methodInfo);
}
}
internal class Detour_NativeConverterLink
{
public delegate IntPtr ReadJsonDel(IntPtr _this, IntPtr reader, IntPtr objectType, IntPtr existingValue, IntPtr serializer);
public delegate void WriteJsonDel(IntPtr _this, IntPtr writer, IntPtr value, IntPtr serializer);
private static INativeDetour _ReadDetour;
private static INativeDetour _WriteDetour;
private static ReadJsonDel _ReadOriginal;
private static WriteJsonDel _WriteOriginal;
public unsafe static void Patch()
{
void* il2CppMethod = Il2CppAPI.GetIl2CppMethod<DataSetConverter>("ReadJson", "System.Object", false, new string[4] { "Newtonsoft.Json.JsonReader", "System.Type", "System.Object", "Newtonsoft.Json.JsonSerializer" });
void* il2CppMethod2 = Il2CppAPI.GetIl2CppMethod<DataSetConverter>("WriteJson", typeof(void).FullName, false, new string[3] { "Newtonsoft.Json.JsonWriter", "System.Object", "Newtonsoft.Json.JsonSerializer" });
_ReadDetour = INativeDetour.CreateAndApply<ReadJsonDel>((IntPtr)(nint)il2CppMethod, (ReadJsonDel)Detour_Read, ref _ReadOriginal);
_WriteDetour = INativeDetour.CreateAndApply<WriteJsonDel>((IntPtr)(nint)il2CppMethod2, (WriteJsonDel)Detour_Write, ref _WriteOriginal);
}
private static IntPtr Detour_Read(IntPtr _this, IntPtr reader, IntPtr objectType, IntPtr existingValue, IntPtr serializer)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
NativeJsonProcessor nativeJsonProcessor = FieldsExtension.GetNativeJsonProcessor(new DataSetConverter(_this));
if (nativeJsonProcessor != null)
{
JsonReader reader2 = new JsonReader(reader);
JsonSerializer serializer2 = new JsonSerializer(serializer);
return nativeJsonProcessor.ProcessRead(reader2, existingValue, serializer2);
}
return _ReadOriginal(_this, reader, objectType, existingValue, serializer);
}
private static void Detour_Write(IntPtr _this, IntPtr writer, IntPtr value, IntPtr serializer)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
NativeJsonProcessor nativeJsonProcessor = FieldsExtension.GetNativeJsonProcessor(new DataSetConverter(_this));
if (nativeJsonProcessor != null)
{
JsonWriter writer2 = new JsonWriter(writer);
JsonSerializer serializer2 = new JsonSerializer(serializer);
nativeJsonProcessor.ProcessWrite(writer2, value, serializer2);
}
else
{
_WriteOriginal(_this, writer, value, serializer);
}
}
}
}
namespace InjectLib.JsonNETInjection.Converter
{
public abstract class Il2CppJsonReferenceTypeConverter<T> : INativeJsonConverter where T : Il2CppObjectBase
{
public virtual string Name => GetType().Name;
public Object ReadJson(JToken jToken, IntPtr existingValue, JsonSerializer serializer)
{
if (existingValue == IntPtr.Zero)
{
return ((Il2CppObjectBase)Read(jToken, default(T), serializer)).Cast<Object>();
}
T existingValue2 = (T)Activator.CreateInstance(typeof(T), existingValue);
return ((Il2CppObjectBase)Read(jToken, existingValue2, serializer)).Cast<Object>();
}
public void WriteJson(JsonWriter writer, IntPtr valueToWrite, JsonSerializer serializer)
{
if (valueToWrite == IntPtr.Zero)
{
Write(writer, default(T), serializer);
return;
}
T value = (T)Activator.CreateInstance(typeof(T), valueToWrite);
Write(writer, value, serializer);
}
protected abstract T Read(JToken jToken, T existingValue, JsonSerializer serializer);
protected abstract void Write(JsonWriter writer, T value, JsonSerializer serializer);
}
public abstract class Il2CppJsonUnmanagedTypeConverter<T> : INativeJsonConverter where T : unmanaged
{
public virtual string Name => GetType().Name;
public Object ReadJson(JToken jToken, IntPtr existingValue, JsonSerializer serializer)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
if (existingValue == IntPtr.Zero)
{
return ToIl2CppObject(Read(jToken, default(T), serializer));
}
Object val = new Object(existingValue);
return ToIl2CppObject(Read(jToken, ((Il2CppObjectBase)val).Unbox<T>(), serializer));
}
public void WriteJson(JsonWriter writer, IntPtr valueToWrite, JsonSerializer serializer)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
if (valueToWrite == IntPtr.Zero)
{
Write(writer, default(T), serializer);
return;
}
Object val = new Object(valueToWrite);
Write(writer, ((Il2CppObjectBase)val).Unbox<T>(), serializer);
}
protected abstract T Read(JToken jToken, T existingValue, JsonSerializer serializer);
protected abstract void Write(JsonWriter writer, T value, JsonSerializer serializer);
protected abstract Object ToIl2CppObject(T value);
}
internal interface INativeJsonConverter
{
string Name { get; }
Object ReadJson(JToken jToken, IntPtr existingValue, JsonSerializer serializer);
void WriteJson(JsonWriter writer, IntPtr valueToWrite, JsonSerializer serializer);
}
}
namespace InjectLib.FieldInjection
{
public static class FieldInjector<Il2CppType> where Il2CppType : Il2CppObjectBase
{
private static readonly Dictionary<string, InjectedFieldInfo> _OffsetLookup = new Dictionary<string, InjectedFieldInfo>();
public static void DefineValueField<Value>(string fieldName) where Value : unmanaged
{
if (!_OffsetLookup.ContainsKey(fieldName))
{
InjectValueField<Value>(fieldName);
}
}
public static void DefineManagedField<Value>(string fieldName) where Value : class
{
if (!_OffsetLookup.ContainsKey(fieldName))
{
InjectManagedField<Value>(fieldName);
}
}
private unsafe static void InjectManagedField<Value>(string fieldName) where Value : class
{
int num = 8;
INativeClassStruct val = UnityVersionHandler.Wrap((Il2CppClass*)(void*)Il2CppClassPointerStore<Il2CppType>.NativeClassPtr);
val.InstanceSize += (uint)num;
val.ActualSize = val.InstanceSize;
_OffsetLookup[fieldName] = new InjectedFieldInfo
{
FieldOffset = (nint)(val.InstanceSize - num),
FieldSize = num
};
}
public unsafe static bool TryGetManagedField<Value>(Il2CppType obj, string fieldName, out Value value) where Value : class
{
if (obj == null)
{
value = null;
return false;
}
if (((Il2CppObjectBase)obj).Pointer == IntPtr.Zero)
{
value = null;
return false;
}
if (!_OffsetLookup.TryGetValue(fieldName, out var value2))
{
value = null;
return false;
}
if (8 != value2.FieldSize)
{
value = null;
return false;
}
ulong num = *(ulong*)((nint)((Il2CppObjectBase)obj).Pointer + value2.FieldOffset);
if (num == 0L)
{
value = null;
return false;
}
value = ManagedReferenceStore<Il2CppType, Value>.Get(num);
return value != null;
}
public unsafe static bool TrySetManagedField<Value>(Il2CppType obj, string fieldName, Value value) where Value : class
{
if (obj == null)
{
return false;
}
if (((Il2CppObjectBase)obj).Pointer == IntPtr.Zero)
{
return false;
}
if (!_OffsetLookup.TryGetValue(fieldName, out var value2))
{
return false;
}
if (8 != value2.FieldSize)
{
return false;
}
ulong num = *(ulong*)((nint)((Il2CppObjectBase)obj).Pointer + value2.FieldOffset);
if (num == 0L)
{
ulong uniqueKey = ManagedReferenceStore<Il2CppType, Value>.UniqueKey;
ManagedReferenceStore<Il2CppType, Value>.Set(uniqueKey, value);
*(ulong*)((nint)((Il2CppObjectBase)obj).Pointer + value2.FieldOffset) = uniqueKey;
return true;
}
ManagedReferenceStore<Il2CppType, Value>.Set(num, value);
return true;
}
private static int SizeOfUnmanagedType<Value>() where Value : unmanaged
{
if (typeof(Value) == typeof(bool))
{
return 1;
}
return Marshal.SizeOf<Value>();
}
private unsafe static void InjectValueField<Value>(string fieldName) where Value : unmanaged
{
int num = SizeOfUnmanagedType<Value>();
INativeClassStruct val = UnityVersionHandler.Wrap((Il2CppClass*)(void*)Il2CppClassPointerStore<Il2CppType>.NativeClassPtr);
val.InstanceSize += (uint)num;
val.ActualSize = val.InstanceSize;
_OffsetLookup[fieldName] = new InjectedFieldInfo
{
FieldOffset = (nint)(val.InstanceSize - num),
FieldSize = num
};
}
public unsafe static bool TryGetValueField<Value>(Il2CppType obj, string fieldName, out Value value) where Value : unmanaged
{
if (obj == null)
{
value = default(Value);
return false;
}
if (((Il2CppObjectBase)obj).Pointer == IntPtr.Zero)
{
value = default(Value);
return false;
}
if (!_OffsetLookup.TryGetValue(fieldName, out var value2))
{
value = default(Value);
return false;
}
if (SizeOfUnmanagedType<Value>() != value2.FieldSize)
{
value = default(Value);
return false;
}
value = *(Value*)((nint)((Il2CppObjectBase)obj).Pointer + value2.FieldOffset);
return true;
}
public unsafe static bool TrySetValueField<Value>(Il2CppType obj, string fieldName, Value value) where Value : unmanaged
{
if (obj == null)
{
return false;
}
if (((Il2CppObjectBase)obj).Pointer == IntPtr.Zero)
{
return false;
}
if (!_OffsetLookup.TryGetValue(fieldName, out var value2))
{
return false;
}
if (SizeOfUnmanagedType<Value>() != value2.FieldSize)
{
return false;
}
*(Value*)((nint)((Il2CppObjectBase)obj).Pointer + value2.FieldOffset) = value;
return true;
}
}
internal struct InjectedFieldInfo
{
public nint FieldOffset;
public int FieldSize;
}
public static class ManagedReferenceStore<C, T> where C : Il2CppObjectBase where T : class
{
private static readonly Dictionary<ulong, T> _Lookup = new Dictionary<ulong, T>();
private static ulong _Key = 1uL;
public static ulong UniqueKey => _Key++;
public static T Get(ulong key)
{
_Lookup.TryGetValue(key, out var value);
return value;
}
public static void Set(ulong key, T value)
{
_Lookup[key] = value;
}
public static void Remove(ulong key)
{
_Lookup.Remove(key);
}
}
}