diff --git a/Libraries/SPTarkov.Server.Core/Utils/Reference/StaticReferences.cs b/Libraries/SPTarkov.Server.Core/Utils/Reference/StaticReferences.cs new file mode 100644 index 00000000..b8b83cf0 --- /dev/null +++ b/Libraries/SPTarkov.Server.Core/Utils/Reference/StaticReferences.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace SPTarkov.Server.Core.Utils.Reference; + +// This class is used by the JsonExtensionDataPatch, dont remove! +public class StaticReferences +{ + [JsonIgnore] + private Dictionary _reference = new(); + [JsonExtensionData] + public Dictionary Reference + { + get { return _reference; } + } +} diff --git a/Patches/Ceciler.JsonExtensionData/JsonExtensionDataPatch.cs b/Patches/Ceciler.JsonExtensionData/JsonExtensionDataPatch.cs index 9c5c4bd8..fc4337e6 100644 --- a/Patches/Ceciler.JsonExtensionData/JsonExtensionDataPatch.cs +++ b/Patches/Ceciler.JsonExtensionData/JsonExtensionDataPatch.cs @@ -9,53 +9,15 @@ public class JsonExtensionDataPatch : IPatcher { private TypeReference? _dictionaryStringObjectReference; - private MethodReference? _dictionaryStringObjectCtorReference; - private MethodReference? _jsonExtensionDataAttributeReference; - - private MethodReference? _jsonIgnoreAttributeReference; - public void Patch(AssemblyDefinition assembly) { - _dictionaryStringObjectReference ??= assembly.MainModule.ImportReference(typeof(Dictionary)); - _dictionaryStringObjectCtorReference ??= assembly.MainModule.ImportReference( - typeof(Dictionary).GetConstructor(Type.EmptyTypes) - ); + var sptReferenceType = assembly.MainModule.Types.First(t => t.FullName == "SPTarkov.Server.Core.Utils.Reference.StaticReferences"); + var propertyReferenceType = sptReferenceType.Properties.First(p => p.Name == "Reference"); + var fieldReferenceType = sptReferenceType.Fields.First(p => p.Name == "_reference"); + _dictionaryStringObjectReference = propertyReferenceType.PropertyType; - if (_jsonExtensionDataAttributeReference is null) - { - var jsonConstructorReference = assembly - .MainModule.AssemblyResolver.Resolve(AssemblyNameReference.Parse("System.Text.Json")) - .MainModule.GetType("System.Text.Json.Serialization.JsonExtensionDataAttribute") - .Methods.First(m => m.IsConstructor && !m.HasParameters); - - _jsonExtensionDataAttributeReference = assembly.MainModule.ImportReference(jsonConstructorReference); - } - - if (_jsonIgnoreAttributeReference is null) - { - var jsonIgnoreConstructorReference = assembly - .MainModule.AssemblyResolver.Resolve(AssemblyNameReference.Parse("System.Text.Json")) - .MainModule.GetType("System.Text.Json.Serialization.JsonIgnoreAttribute") - .Methods.First(m => m.IsConstructor && !m.HasParameters); - - _jsonIgnoreAttributeReference = assembly.MainModule.ImportReference(jsonIgnoreConstructorReference); - } - var isExternalInitType = assembly.MainModule.ImportReference(typeof(System.Runtime.CompilerServices.IsExternalInit)); - - var compilerGenerated = assembly.MainModule.ImportReference( - assembly.MainModule.ImportReference( - typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute).GetConstructor(Type.EmptyTypes) - ) - ); - - var nullableAttrType = assembly.MainModule.ImportReference(typeof(System.Runtime.CompilerServices.NullableAttribute)); - var attrCtor = assembly.MainModule.ImportReference( - nullableAttrType - .Resolve() - .Methods.First(m => m.IsConstructor && m.Parameters.Count == 1 && m.Parameters[0].ParameterType.Name == "Byte") - ); - var attr = new CustomAttribute(attrCtor); - attr.ConstructorArguments.Add(new CustomAttributeArgument(assembly.MainModule.TypeSystem.Byte, (byte)1)); + // We need to steal from the constructor the IL line 2 (index 1) + var createDictionaryReference = sptReferenceType.GetConstructors().First(c => c.Parameters.Count == 0).Body.Instructions[1]; var processed = new HashSet(); foreach (var typeDefinition in assembly.MainModule.Types) @@ -66,23 +28,23 @@ public class JsonExtensionDataPatch : IPatcher || typeDefinition.IsEnum || IsStaticClass(typeDefinition) || processed.Contains(typeDefinition.FullName) + || typeDefinition.IsAbstract + || typeDefinition.HasGenericParameters ) { continue; } var propertyDefinition = new PropertyDefinition("ExtensionData", PropertyAttributes.None, _dictionaryStringObjectReference); - propertyDefinition.CustomAttributes.Add(new CustomAttribute(_jsonExtensionDataAttributeReference)); - propertyDefinition.CustomAttributes.Add(attr); + propertyDefinition.CustomAttributes.Add(propertyReferenceType.CustomAttributes.First()); // Add backing field var field = new FieldDefinition( - "k__BackingField", + "_extensionData", FieldAttributes.Private | FieldAttributes.InitOnly, _dictionaryStringObjectReference ); - field.CustomAttributes.Add(new CustomAttribute(compilerGenerated)); - field.CustomAttributes.Add(attr); + field.CustomAttributes.Add(fieldReferenceType.CustomAttributes.First()); typeDefinition.Fields.Add(field); // Add getter @@ -92,35 +54,13 @@ public class JsonExtensionDataPatch : IPatcher _dictionaryStringObjectReference ); - get.CustomAttributes.Add(new CustomAttribute(compilerGenerated)); get.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); get.Body.Instructions.Add(Instruction.Create(OpCodes.Ldfld, field)); get.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); propertyDefinition.GetMethod = get; - typeDefinition.Methods.Add(get); - // Add setter - var set = new MethodDefinition( - "set_ExtensionData", - MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, - assembly.MainModule.TypeSystem.Void - ); - - var returnType = set.ReturnType; - var modifiedReturnType = new RequiredModifierType(isExternalInitType, returnType); - set.MethodReturnType.ReturnType = modifiedReturnType; - set.CustomAttributes.Add(new CustomAttribute(compilerGenerated)); - set.Parameters.Add(new ParameterDefinition("value", ParameterAttributes.None, _dictionaryStringObjectReference)); - set.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); - set.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_1)); - set.Body.Instructions.Add(Instruction.Create(OpCodes.Stfld, field)); - set.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); - - propertyDefinition.SetMethod = set; - - typeDefinition.Methods.Add(set); typeDefinition.Properties.Add(propertyDefinition); foreach (var methodDefinition in typeDefinition.GetConstructors().Where(c => !c.IsStatic)) @@ -128,7 +68,7 @@ public class JsonExtensionDataPatch : IPatcher var ilCtor = methodDefinition.Body.GetILProcessor(); var loadArg = ilCtor.Create(OpCodes.Ldarg_0); - var createObj = ilCtor.Create(OpCodes.Newobj, _dictionaryStringObjectCtorReference); + var createObj = createDictionaryReference; var setField = ilCtor.Create(OpCodes.Stfld, field); var first = ilCtor.Body.Instructions.First(); ilCtor.InsertBefore(first, loadArg);