diff --git a/Ceciler/Ceciler.Interfaces.dll b/Ceciler/Ceciler.Interfaces.dll
new file mode 100644
index 00000000..9587329c
Binary files /dev/null and b/Ceciler/Ceciler.Interfaces.dll differ
diff --git a/Ceciler/Ceciler.Launcher.deps.json b/Ceciler/Ceciler.Launcher.deps.json
new file mode 100644
index 00000000..2226a9d0
--- /dev/null
+++ b/Ceciler/Ceciler.Launcher.deps.json
@@ -0,0 +1,67 @@
+{
+ "runtimeTarget": {
+ "name": ".NETCoreApp,Version=v9.0",
+ "signature": ""
+ },
+ "compilationOptions": {},
+ "targets": {
+ ".NETCoreApp,Version=v9.0": {
+ "Ceciler.Launcher/1.0.0": {
+ "dependencies": {
+ "Ceciler.Interfaces": "1.0.0",
+ "Mono.Cecil": "0.11.6"
+ },
+ "runtime": {
+ "Ceciler.Launcher.dll": {}
+ }
+ },
+ "Mono.Cecil/0.11.6": {
+ "runtime": {
+ "lib/netstandard2.0/Mono.Cecil.Mdb.dll": {
+ "assemblyVersion": "0.11.6.0",
+ "fileVersion": "0.11.6.0"
+ },
+ "lib/netstandard2.0/Mono.Cecil.Pdb.dll": {
+ "assemblyVersion": "0.11.6.0",
+ "fileVersion": "0.11.6.0"
+ },
+ "lib/netstandard2.0/Mono.Cecil.Rocks.dll": {
+ "assemblyVersion": "0.11.6.0",
+ "fileVersion": "0.11.6.0"
+ },
+ "lib/netstandard2.0/Mono.Cecil.dll": {
+ "assemblyVersion": "0.11.6.0",
+ "fileVersion": "0.11.6.0"
+ }
+ }
+ },
+ "Ceciler.Interfaces/1.0.0": {
+ "runtime": {
+ "Ceciler.Interfaces.dll": {
+ "assemblyVersion": "1.0.0.0",
+ "fileVersion": "1.0.0.0"
+ }
+ }
+ }
+ }
+ },
+ "libraries": {
+ "Ceciler.Launcher/1.0.0": {
+ "type": "project",
+ "serviceable": false,
+ "sha512": ""
+ },
+ "Mono.Cecil/0.11.6": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-f33RkDtZO8VlGXCtmQIviOtxgnUdym9xx/b1p9h91CRGOsJFxCFOFK1FDbVt1OCf1aWwYejUFa2MOQyFWTFjbA==",
+ "path": "mono.cecil/0.11.6",
+ "hashPath": "mono.cecil.0.11.6.nupkg.sha512"
+ },
+ "Ceciler.Interfaces/1.0.0": {
+ "type": "project",
+ "serviceable": false,
+ "sha512": ""
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ceciler/Ceciler.Launcher.dll b/Ceciler/Ceciler.Launcher.dll
new file mode 100644
index 00000000..5aba7686
Binary files /dev/null and b/Ceciler/Ceciler.Launcher.dll differ
diff --git a/Ceciler/Ceciler.Launcher.exe b/Ceciler/Ceciler.Launcher.exe
new file mode 100644
index 00000000..12ae59f8
Binary files /dev/null and b/Ceciler/Ceciler.Launcher.exe differ
diff --git a/Ceciler/Ceciler.Launcher.runtimeconfig.json b/Ceciler/Ceciler.Launcher.runtimeconfig.json
new file mode 100644
index 00000000..233cae7c
--- /dev/null
+++ b/Ceciler/Ceciler.Launcher.runtimeconfig.json
@@ -0,0 +1,13 @@
+{
+ "runtimeOptions": {
+ "tfm": "net9.0",
+ "framework": {
+ "name": "Microsoft.NETCore.App",
+ "version": "9.0.0"
+ },
+ "configProperties": {
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/Ceciler/Mono.Cecil.Mdb.dll b/Ceciler/Mono.Cecil.Mdb.dll
new file mode 100644
index 00000000..55f9ee25
Binary files /dev/null and b/Ceciler/Mono.Cecil.Mdb.dll differ
diff --git a/Ceciler/Mono.Cecil.Pdb.dll b/Ceciler/Mono.Cecil.Pdb.dll
new file mode 100644
index 00000000..0462a8f2
Binary files /dev/null and b/Ceciler/Mono.Cecil.Pdb.dll differ
diff --git a/Ceciler/Mono.Cecil.Rocks.dll b/Ceciler/Mono.Cecil.Rocks.dll
new file mode 100644
index 00000000..561b0d74
Binary files /dev/null and b/Ceciler/Mono.Cecil.Rocks.dll differ
diff --git a/Ceciler/Mono.Cecil.dll b/Ceciler/Mono.Cecil.dll
new file mode 100644
index 00000000..488bd5cb
Binary files /dev/null and b/Ceciler/Mono.Cecil.dll differ
diff --git a/Libraries/SPTarkov.Server.Core/FodyWeavers.xml b/Libraries/SPTarkov.Server.Core/FodyWeavers.xml
deleted file mode 100644
index c6787ffe..00000000
--- a/Libraries/SPTarkov.Server.Core/FodyWeavers.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/Libraries/SPTarkov.Server.Core/FodyWeavers.xsd b/Libraries/SPTarkov.Server.Core/FodyWeavers.xsd
deleted file mode 100644
index 0eeb31cf..00000000
--- a/Libraries/SPTarkov.Server.Core/FodyWeavers.xsd
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
-
-
-
-
- A comma-separated list of error codes that can be safely ignored in assembly verification.
-
-
-
-
- 'false' to turn off automatic generation of the XML Schema file.
-
-
-
-
-
\ No newline at end of file
diff --git a/Libraries/SPTarkov.Server.Core/SPTarkov.Server.Core.csproj b/Libraries/SPTarkov.Server.Core/SPTarkov.Server.Core.csproj
index 07a260d0..6fddc81e 100644
--- a/Libraries/SPTarkov.Server.Core/SPTarkov.Server.Core.csproj
+++ b/Libraries/SPTarkov.Server.Core/SPTarkov.Server.Core.csproj
@@ -22,17 +22,6 @@
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
- all
-
@@ -48,6 +37,10 @@
+
+
+
+
diff --git a/Patches/Ceciler.Virtualizer/Ceciler.Virtualizer.csproj b/Patches/Ceciler.Virtualizer/Ceciler.Virtualizer.csproj
new file mode 100644
index 00000000..e90359ce
--- /dev/null
+++ b/Patches/Ceciler.Virtualizer/Ceciler.Virtualizer.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net9.0
+ enable
+ enable
+
+
+
+
+ ..\..\Ceciler\Ceciler.Interfaces.dll
+
+
+
+
+
+ all
+
+
+
+
diff --git a/Patches/Ceciler.Virtualizer/VirtualizerPatch.cs b/Patches/Ceciler.Virtualizer/VirtualizerPatch.cs
new file mode 100644
index 00000000..8b325c02
--- /dev/null
+++ b/Patches/Ceciler.Virtualizer/VirtualizerPatch.cs
@@ -0,0 +1,78 @@
+using Ceciler.Interfaces;
+using Mono.Cecil;
+
+namespace Ceciler.Virtualizer;
+
+public class VirtualizerPatch : IPatcher
+{
+ public void Patch(ModuleDefinition module)
+ {
+ foreach (var typeDefinition in module.Types)
+ {
+ foreach (var typeDefinitionMethod in typeDefinition.Methods)
+ {
+ if (typeDefinitionMethod == null)
+ {
+ continue;
+ }
+
+ if (typeDefinitionMethod.IsConstructor)
+ {
+ continue;
+ }
+
+
+ if (typeDefinitionMethod.IsFinal && typeDefinitionMethod.IsVirtual)
+ {
+ typeDefinitionMethod.IsFinal = false;
+ continue;
+ }
+
+ if (typeDefinitionMethod.IsFinal)
+ {
+ continue;
+ }
+
+ if (typeDefinitionMethod.IsVirtual)
+ {
+ continue;
+ }
+
+ if (typeDefinitionMethod.IsStatic)
+ {
+ continue;
+ }
+
+ if (typeDefinitionMethod.IsPrivate)
+ {
+ continue;
+ }
+
+ if (MethodIsSerializationCallback(typeDefinitionMethod))
+ {
+ continue;
+ }
+
+ typeDefinitionMethod.IsVirtual = true;
+ typeDefinitionMethod.IsNewSlot = true;
+ }
+ }
+ module.Write();
+ }
+
+ static bool MethodIsSerializationCallback(MethodDefinition method)
+ {
+ return ContainsAttribute(method.CustomAttributes, "OnSerializingAttribute")
+ || ContainsAttribute(method.CustomAttributes, "OnSerializedAttribute")
+ || ContainsAttribute(method.CustomAttributes, "OnDeserializingAttribute")
+ || ContainsAttribute(method.CustomAttributes, "OnDeserializedAttribute");
+ }
+
+ public static bool ContainsAttribute(IEnumerable attributes, string attributeName) =>
+ attributes.Any(attribute => attribute.Constructor.DeclaringType.Name == attributeName);
+
+ public string Name
+ {
+ get { return "Virtualizer"; }
+ }
+}
diff --git a/server-csharp.sln b/server-csharp.sln
index 1ca3dae8..1fd65863 100644
--- a/server-csharp.sln
+++ b/server-csharp.sln
@@ -6,6 +6,9 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPTarkov.Server", "SPTarkov.Server\SPTarkov.Server.csproj", "{1F5ED9C6-8B1F-4776-85AB-B387CBBC5557}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPTarkov.Server.Core", "Libraries\SPTarkov.Server.Core\SPTarkov.Server.Core.csproj", "{AC8643DC-8779-4B4A-BBDA-2D4CC466F765}"
+ ProjectSection(ProjectDependencies) = postProject
+ {20A5EBD3-75D1-4E06-8240-09EEF874017A} = {20A5EBD3-75D1-4E06-8240-09EEF874017A}
+ EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests.csproj", "{6C0681F9-4013-4579-82DA-0A9297984FD3}"
EndProject
@@ -29,6 +32,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPTarkov.Reflection", "Libr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JsonExtensionDataGenerator", "Tools\JsonExtensionDataGenerator\JsonExtensionDataGenerator.csproj", "{6F4670CD-6861-47A8-9A02-2B63AD73A929}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Patches", "Patches", "{9E41CD5A-271C-4294-AAF9-8EB379311416}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ceciler.Virtualizer", "Patches\Ceciler.Virtualizer\Ceciler.Virtualizer.csproj", "{20A5EBD3-75D1-4E06-8240-09EEF874017A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -79,6 +86,10 @@ Global
{6F4670CD-6861-47A8-9A02-2B63AD73A929}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F4670CD-6861-47A8-9A02-2B63AD73A929}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F4670CD-6861-47A8-9A02-2B63AD73A929}.Release|Any CPU.Build.0 = Release|Any CPU
+ {20A5EBD3-75D1-4E06-8240-09EEF874017A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {20A5EBD3-75D1-4E06-8240-09EEF874017A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {20A5EBD3-75D1-4E06-8240-09EEF874017A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {20A5EBD3-75D1-4E06-8240-09EEF874017A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -92,5 +103,6 @@ Global
{C24B1FEB-F8AC-434E-998D-5DA4D1687295} = {587959C2-5AFA-4B77-B327-566610F9A289}
{9073A593-A2F5-471E-9678-B896A7226FD4} = {F084DDFD-89F3-44F9-89C3-5CA11F4CDEEF}
{6F4670CD-6861-47A8-9A02-2B63AD73A929} = {587959C2-5AFA-4B77-B327-566610F9A289}
+ {20A5EBD3-75D1-4E06-8240-09EEF874017A} = {9E41CD5A-271C-4294-AAF9-8EB379311416}
EndGlobalSection
EndGlobal